Merge branches 'edac-spr', 'edac-igen6' and 'edac-misc' into edac-updates-for-v5.11
authorBorislav Petkov <bp@suse.de>
Mon, 14 Dec 2020 10:51:46 +0000 (11:51 +0100)
committerBorislav Petkov <bp@suse.de>
Mon, 14 Dec 2020 10:51:46 +0000 (11:51 +0100)
Signed-off-by: Borislav Petkov <bp@suse.de>
2359 files changed:
.mailmap
CREDITS
Documentation/ABI/README
Documentation/ABI/obsolete/sysfs-class-dax
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra
Documentation/ABI/obsolete/sysfs-gpio
Documentation/ABI/removed/devfs
Documentation/ABI/removed/raw1394
Documentation/ABI/removed/sysfs-class-rfkill
Documentation/ABI/removed/video1394
Documentation/ABI/stable/firewire-cdev
Documentation/ABI/stable/sysfs-acpi-pmprofile
Documentation/ABI/stable/sysfs-bus-firewire
Documentation/ABI/stable/sysfs-bus-nvmem
Documentation/ABI/stable/sysfs-bus-usb
Documentation/ABI/stable/sysfs-bus-vmbus
Documentation/ABI/stable/sysfs-bus-w1
Documentation/ABI/stable/sysfs-class-backlight
Documentation/ABI/stable/sysfs-class-infiniband
Documentation/ABI/stable/sysfs-class-rfkill
Documentation/ABI/stable/sysfs-class-tpm
Documentation/ABI/stable/sysfs-devices
Documentation/ABI/stable/sysfs-driver-dma-ioatdma
Documentation/ABI/stable/sysfs-driver-firmware-zynqmp
Documentation/ABI/stable/sysfs-driver-ib_srp
Documentation/ABI/stable/sysfs-driver-speakup
Documentation/ABI/stable/sysfs-firmware-efi-vars
Documentation/ABI/stable/sysfs-firmware-opal-dump
Documentation/ABI/stable/sysfs-firmware-opal-elog
Documentation/ABI/stable/sysfs-hypervisor-xen
Documentation/ABI/stable/vdso
Documentation/ABI/testing/configfs-acpi
Documentation/ABI/testing/configfs-most
Documentation/ABI/testing/configfs-spear-pcie-gadget
Documentation/ABI/testing/configfs-usb-gadget
Documentation/ABI/testing/configfs-usb-gadget-ecm
Documentation/ABI/testing/configfs-usb-gadget-eem
Documentation/ABI/testing/configfs-usb-gadget-hid
Documentation/ABI/testing/configfs-usb-gadget-loopback
Documentation/ABI/testing/configfs-usb-gadget-mass-storage
Documentation/ABI/testing/configfs-usb-gadget-midi
Documentation/ABI/testing/configfs-usb-gadget-printer
Documentation/ABI/testing/configfs-usb-gadget-rndis
Documentation/ABI/testing/configfs-usb-gadget-sourcesink
Documentation/ABI/testing/configfs-usb-gadget-subset
Documentation/ABI/testing/configfs-usb-gadget-uac1
Documentation/ABI/testing/configfs-usb-gadget-uac2
Documentation/ABI/testing/configfs-usb-gadget-uvc
Documentation/ABI/testing/debugfs-cec-error-inj
Documentation/ABI/testing/debugfs-driver-habanalabs
Documentation/ABI/testing/debugfs-ec
Documentation/ABI/testing/debugfs-moxtet
Documentation/ABI/testing/debugfs-pfo-nx-crypto
Documentation/ABI/testing/debugfs-pktcdvd
Documentation/ABI/testing/debugfs-turris-mox-rwtm
Documentation/ABI/testing/debugfs-wilco-ec
Documentation/ABI/testing/dell-smbios-wmi
Documentation/ABI/testing/dev-kmsg
Documentation/ABI/testing/evm
Documentation/ABI/testing/gpio-cdev
Documentation/ABI/testing/ima_policy
Documentation/ABI/testing/procfs-diskstats
Documentation/ABI/testing/procfs-smaps_rollup
Documentation/ABI/testing/pstore
Documentation/ABI/testing/sysfs-block
Documentation/ABI/testing/sysfs-block-device
Documentation/ABI/testing/sysfs-block-rnbd
Documentation/ABI/testing/sysfs-bus-acpi
Documentation/ABI/testing/sysfs-bus-coresight-devices-cti
Documentation/ABI/testing/sysfs-bus-coresight-devices-etb10
Documentation/ABI/testing/sysfs-bus-coresight-devices-etm3x
Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x
Documentation/ABI/testing/sysfs-bus-coresight-devices-stm
Documentation/ABI/testing/sysfs-bus-coresight-devices-tmc
Documentation/ABI/testing/sysfs-bus-css
Documentation/ABI/testing/sysfs-bus-dfl
Documentation/ABI/testing/sysfs-bus-event_source-devices-dfl_fme
Documentation/ABI/testing/sysfs-bus-event_source-devices-format
Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_24x7
Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_gpci
Documentation/ABI/testing/sysfs-bus-fcoe
Documentation/ABI/testing/sysfs-bus-fsl-mc
Documentation/ABI/testing/sysfs-bus-i2c-devices-fsa9480
Documentation/ABI/testing/sysfs-bus-i2c-devices-pca954x
Documentation/ABI/testing/sysfs-bus-i3c
Documentation/ABI/testing/sysfs-bus-iio
Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector
Documentation/ABI/testing/sysfs-bus-iio-adc-hi8435
Documentation/ABI/testing/sysfs-bus-iio-adc-stm32
Documentation/ABI/testing/sysfs-bus-iio-cros-ec
Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32
Documentation/ABI/testing/sysfs-bus-iio-distance-srf08
Documentation/ABI/testing/sysfs-bus-iio-frequency-ad9523
Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4371
Documentation/ABI/testing/sysfs-bus-iio-health-afe440x
Documentation/ABI/testing/sysfs-bus-iio-light-isl29018
Documentation/ABI/testing/sysfs-bus-iio-lptimer-stm32
Documentation/ABI/testing/sysfs-bus-iio-magnetometer-hmc5843
Documentation/ABI/testing/sysfs-bus-iio-temperature-max31856
Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
Documentation/ABI/testing/sysfs-bus-intel_th-devices-gth
Documentation/ABI/testing/sysfs-bus-intel_th-devices-msc
Documentation/ABI/testing/sysfs-bus-most
Documentation/ABI/testing/sysfs-bus-moxtet-devices
Documentation/ABI/testing/sysfs-bus-nfit
Documentation/ABI/testing/sysfs-bus-nvdimm
Documentation/ABI/testing/sysfs-bus-papr-pmem
Documentation/ABI/testing/sysfs-bus-pci
Documentation/ABI/testing/sysfs-bus-pci-devices-aer_stats
Documentation/ABI/testing/sysfs-bus-pci-devices-catpt
Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd
Documentation/ABI/testing/sysfs-bus-rapidio
Documentation/ABI/testing/sysfs-bus-rbd
Documentation/ABI/testing/sysfs-bus-siox
Documentation/ABI/testing/sysfs-bus-thunderbolt
Documentation/ABI/testing/sysfs-bus-usb
Documentation/ABI/testing/sysfs-bus-usb-devices-usbsevseg
Documentation/ABI/testing/sysfs-bus-vfio-mdev
Documentation/ABI/testing/sysfs-c2port
Documentation/ABI/testing/sysfs-class-backlight
Documentation/ABI/testing/sysfs-class-backlight-adp8860
Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870
Documentation/ABI/testing/sysfs-class-backlight-driver-lm3533
Documentation/ABI/testing/sysfs-class-bdi
Documentation/ABI/testing/sysfs-class-chromeos
Documentation/ABI/testing/sysfs-class-cxl
Documentation/ABI/testing/sysfs-class-devfreq
Documentation/ABI/testing/sysfs-class-devlink
Documentation/ABI/testing/sysfs-class-extcon
Documentation/ABI/testing/sysfs-class-fpga-manager
Documentation/ABI/testing/sysfs-class-gnss
Documentation/ABI/testing/sysfs-class-led
Documentation/ABI/testing/sysfs-class-led-driver-el15203000
Documentation/ABI/testing/sysfs-class-led-driver-lm3533
Documentation/ABI/testing/sysfs-class-led-driver-sc27xx [deleted file]
Documentation/ABI/testing/sysfs-class-led-flash
Documentation/ABI/testing/sysfs-class-led-multicolor
Documentation/ABI/testing/sysfs-class-led-trigger-netdev
Documentation/ABI/testing/sysfs-class-led-trigger-pattern
Documentation/ABI/testing/sysfs-class-led-trigger-usbport
Documentation/ABI/testing/sysfs-class-leds-gt683r
Documentation/ABI/testing/sysfs-class-mic
Documentation/ABI/testing/sysfs-class-net
Documentation/ABI/testing/sysfs-class-net-cdc_ncm
Documentation/ABI/testing/sysfs-class-net-phydev
Documentation/ABI/testing/sysfs-class-ocxl
Documentation/ABI/testing/sysfs-class-pktcdvd
Documentation/ABI/testing/sysfs-class-power
Documentation/ABI/testing/sysfs-class-power-mp2629
Documentation/ABI/testing/sysfs-class-power-twl4030
Documentation/ABI/testing/sysfs-class-power-wilco
Documentation/ABI/testing/sysfs-class-rapidio
Documentation/ABI/testing/sysfs-class-rc
Documentation/ABI/testing/sysfs-class-regulator
Documentation/ABI/testing/sysfs-class-remoteproc
Documentation/ABI/testing/sysfs-class-rnbd-client
Documentation/ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration
Documentation/ABI/testing/sysfs-class-rtrs-client
Documentation/ABI/testing/sysfs-class-scsi_host
Documentation/ABI/testing/sysfs-class-typec
Documentation/ABI/testing/sysfs-class-uwb_rc
Documentation/ABI/testing/sysfs-class-watchdog
Documentation/ABI/testing/sysfs-dev
Documentation/ABI/testing/sysfs-devices-mapping
Documentation/ABI/testing/sysfs-devices-memory
Documentation/ABI/testing/sysfs-devices-platform-ACPI-TAD
Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget
Documentation/ABI/testing/sysfs-devices-platform-docg3
Documentation/ABI/testing/sysfs-devices-platform-ipmi
Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb
Documentation/ABI/testing/sysfs-devices-platform-stratix10-rsu
Documentation/ABI/testing/sysfs-devices-system-cpu
Documentation/ABI/testing/sysfs-devices-system-ibm-rtl
Documentation/ABI/testing/sysfs-driver-bd9571mwv-regulator
Documentation/ABI/testing/sysfs-driver-genwqe
Documentation/ABI/testing/sysfs-driver-hid-lenovo
Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
Documentation/ABI/testing/sysfs-driver-hid-ntrig
Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
Documentation/ABI/testing/sysfs-driver-hid-wiimote
Documentation/ABI/testing/sysfs-driver-input-exc3000
Documentation/ABI/testing/sysfs-driver-jz4780-efuse
Documentation/ABI/testing/sysfs-driver-pciback
Documentation/ABI/testing/sysfs-driver-samsung-laptop
Documentation/ABI/testing/sysfs-driver-toshiba_acpi
Documentation/ABI/testing/sysfs-driver-toshiba_haps
Documentation/ABI/testing/sysfs-driver-ufs
Documentation/ABI/testing/sysfs-driver-w1_ds28e17
Documentation/ABI/testing/sysfs-driver-w1_therm
Documentation/ABI/testing/sysfs-driver-wacom
Documentation/ABI/testing/sysfs-firmware-acpi
Documentation/ABI/testing/sysfs-firmware-dmi-entries
Documentation/ABI/testing/sysfs-firmware-efi-esrt
Documentation/ABI/testing/sysfs-firmware-efi-runtime-map
Documentation/ABI/testing/sysfs-firmware-gsmi
Documentation/ABI/testing/sysfs-firmware-memmap
Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg
Documentation/ABI/testing/sysfs-firmware-sfi
Documentation/ABI/testing/sysfs-firmware-sgi_uv
Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm
Documentation/ABI/testing/sysfs-fs-ext4
Documentation/ABI/testing/sysfs-fs-f2fs
Documentation/ABI/testing/sysfs-hypervisor-xen
Documentation/ABI/testing/sysfs-kernel-boot_params
Documentation/ABI/testing/sysfs-kernel-mm-hugepages
Documentation/ABI/testing/sysfs-kernel-mm-ksm
Documentation/ABI/testing/sysfs-kernel-slab
Documentation/ABI/testing/sysfs-module
Documentation/ABI/testing/sysfs-platform-asus-laptop
Documentation/ABI/testing/sysfs-platform-asus-wmi
Documentation/ABI/testing/sysfs-platform-at91
Documentation/ABI/testing/sysfs-platform-dell-laptop
Documentation/ABI/testing/sysfs-platform-dell-smbios
Documentation/ABI/testing/sysfs-platform-dfl-fme
Documentation/ABI/testing/sysfs-platform-dptf
Documentation/ABI/testing/sysfs-platform-eeepc-laptop
Documentation/ABI/testing/sysfs-platform-i2c-demux-pinctrl
Documentation/ABI/testing/sysfs-platform-ideapad-laptop
Documentation/ABI/testing/sysfs-platform-intel-wmi-sbl-fw-update
Documentation/ABI/testing/sysfs-platform-intel-wmi-thunderbolt
Documentation/ABI/testing/sysfs-platform-kim
Documentation/ABI/testing/sysfs-platform-mellanox-bootctl
Documentation/ABI/testing/sysfs-platform-phy-rcar-gen3-usb2
Documentation/ABI/testing/sysfs-platform-renesas_usb3
Documentation/ABI/testing/sysfs-platform-sst-atom
Documentation/ABI/testing/sysfs-platform-usbip-vudc
Documentation/ABI/testing/sysfs-platform-wilco-ec
Documentation/ABI/testing/sysfs-power
Documentation/ABI/testing/sysfs-profiling
Documentation/ABI/testing/sysfs-ptp
Documentation/ABI/testing/sysfs-uevent
Documentation/ABI/testing/sysfs-wusb_cbaf
Documentation/ABI/testing/usb-charger-uevent
Documentation/ABI/testing/usb-uevent
Documentation/Kconfig
Documentation/Makefile
Documentation/admin-guide/LSM/SafeSetID.rst
Documentation/admin-guide/abi-obsolete.rst [new file with mode: 0644]
Documentation/admin-guide/abi-removed.rst [new file with mode: 0644]
Documentation/admin-guide/abi-stable.rst [new file with mode: 0644]
Documentation/admin-guide/abi-testing.rst [new file with mode: 0644]
Documentation/admin-guide/abi.rst [new file with mode: 0644]
Documentation/admin-guide/bootconfig.rst
Documentation/admin-guide/index.rst
Documentation/admin-guide/kernel-parameters.txt
Documentation/admin-guide/pm/cpuidle.rst
Documentation/admin-guide/sysctl/net.rst
Documentation/arm/sunxi.rst
Documentation/arm64/memory-tagging-extension.rst
Documentation/arm64/silicon-errata.rst
Documentation/conf.py
Documentation/dev-tools/kasan.rst
Documentation/dev-tools/kunit/faq.rst
Documentation/dev-tools/kunit/start.rst
Documentation/dev-tools/kunit/style.rst
Documentation/dev-tools/kunit/usage.rst
Documentation/devicetree/bindings/arm/actions.yaml
Documentation/devicetree/bindings/arm/altera.yaml
Documentation/devicetree/bindings/arm/amazon,al.yaml
Documentation/devicetree/bindings/arm/amlogic.yaml
Documentation/devicetree/bindings/arm/arm,integrator.yaml
Documentation/devicetree/bindings/arm/arm,realview.yaml
Documentation/devicetree/bindings/arm/arm,versatile.yaml
Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml
Documentation/devicetree/bindings/arm/atmel-at91.yaml
Documentation/devicetree/bindings/arm/axxia.yaml
Documentation/devicetree/bindings/arm/bcm/bcm2835.yaml
Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351.yaml
Documentation/devicetree/bindings/arm/bcm/brcm,bcm21664.yaml
Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.yaml
Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.yaml
Documentation/devicetree/bindings/arm/bcm/brcm,cygnus.yaml
Documentation/devicetree/bindings/arm/bcm/brcm,hr2.yaml
Documentation/devicetree/bindings/arm/bcm/brcm,ns2.yaml
Documentation/devicetree/bindings/arm/bcm/brcm,nsp.yaml
Documentation/devicetree/bindings/arm/bcm/brcm,stingray.yaml
Documentation/devicetree/bindings/arm/bcm/brcm,vulcan-soc.yaml
Documentation/devicetree/bindings/arm/bitmain.yaml
Documentation/devicetree/bindings/arm/calxeda.yaml
Documentation/devicetree/bindings/arm/digicolor.yaml
Documentation/devicetree/bindings/arm/fsl.yaml
Documentation/devicetree/bindings/arm/hisilicon/hisilicon.yaml
Documentation/devicetree/bindings/arm/intel,keembay.yaml
Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
Documentation/devicetree/bindings/arm/keystone/ti,k3-sci-common.yaml
Documentation/devicetree/bindings/arm/marvell/armada-7k-8k.yaml
Documentation/devicetree/bindings/arm/mediatek.yaml
Documentation/devicetree/bindings/arm/microchip,sparx5.yaml
Documentation/devicetree/bindings/arm/moxart.yaml
Documentation/devicetree/bindings/arm/mrvl/mrvl.yaml
Documentation/devicetree/bindings/arm/mstar/mstar.yaml
Documentation/devicetree/bindings/arm/nxp/lpc32xx.yaml
Documentation/devicetree/bindings/arm/qcom.yaml
Documentation/devicetree/bindings/arm/rda.yaml
Documentation/devicetree/bindings/arm/realtek.yaml
Documentation/devicetree/bindings/arm/renesas.yaml
Documentation/devicetree/bindings/arm/rockchip.yaml
Documentation/devicetree/bindings/arm/samsung/samsung-boards.yaml
Documentation/devicetree/bindings/arm/sirf.yaml
Documentation/devicetree/bindings/arm/socionext/milbeaut.yaml
Documentation/devicetree/bindings/arm/socionext/uniphier.yaml
Documentation/devicetree/bindings/arm/spear.yaml
Documentation/devicetree/bindings/arm/sprd/sprd.yaml
Documentation/devicetree/bindings/arm/sti.yaml
Documentation/devicetree/bindings/arm/stm32/stm32.yaml
Documentation/devicetree/bindings/arm/sunxi.yaml
Documentation/devicetree/bindings/arm/tegra.yaml
Documentation/devicetree/bindings/arm/ti/k3.yaml
Documentation/devicetree/bindings/arm/ti/nspire.yaml
Documentation/devicetree/bindings/arm/ti/ti,davinci.yaml
Documentation/devicetree/bindings/arm/toshiba.yaml
Documentation/devicetree/bindings/arm/ux500.yaml
Documentation/devicetree/bindings/arm/vt8500.yaml
Documentation/devicetree/bindings/arm/xilinx.yaml
Documentation/devicetree/bindings/arm/zte.yaml
Documentation/devicetree/bindings/clock/hi6220-clock.txt
Documentation/devicetree/bindings/clock/imx5-clock.yaml
Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
Documentation/devicetree/bindings/display/bridge/toshiba,tc358775.yaml
Documentation/devicetree/bindings/display/panel/ilitek,ili9881c.yaml
Documentation/devicetree/bindings/display/panel/mantix,mlaf057we51-x.yaml
Documentation/devicetree/bindings/edac/amazon,al-mc-edac.yaml
Documentation/devicetree/bindings/edac/aspeed-sdram-edac.txt
Documentation/devicetree/bindings/eeprom/at25.yaml
Documentation/devicetree/bindings/gpio/kontron,sl28cpld-gpio.yaml
Documentation/devicetree/bindings/i2c/google,cros-ec-i2c-tunnel.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/i2c-cros-ec-tunnel.txt [deleted file]
Documentation/devicetree/bindings/i2c/ingenic,i2c.yaml
Documentation/devicetree/bindings/iio/adc/adi,ad7291.yaml
Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml
Documentation/devicetree/bindings/iio/adc/cosmic,10001-adc.yaml
Documentation/devicetree/bindings/iio/adc/holt,hi8435.yaml
Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml
Documentation/devicetree/bindings/iio/humidity/ti,hdc2010.yaml
Documentation/devicetree/bindings/input/cros-ec-keyb.txt [deleted file]
Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/interrupt-controller/ti,pruss-intc.yaml
Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.yaml
Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.yaml
Documentation/devicetree/bindings/leds/backlight/common.yaml
Documentation/devicetree/bindings/leds/common.yaml
Documentation/devicetree/bindings/leds/leds-class-multicolor.yaml
Documentation/devicetree/bindings/leds/leds-lp50xx.yaml
Documentation/devicetree/bindings/mailbox/mtk-gce.txt
Documentation/devicetree/bindings/mfd/ene-kb3930.yaml
Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
Documentation/devicetree/bindings/mips/ingenic/devices.yaml
Documentation/devicetree/bindings/mips/loongson/devices.yaml
Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml
Documentation/devicetree/bindings/mmc/microchip,dw-sparx5-sdhci.yaml
Documentation/devicetree/bindings/mmc/sdhci-am654.yaml
Documentation/devicetree/bindings/net/can/can-controller.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/net/can/fsl-flexcan.txt [deleted file]
Documentation/devicetree/bindings/net/can/tcan4x5x.txt
Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml
Documentation/devicetree/bindings/net/nfc/nxp-nci.txt
Documentation/devicetree/bindings/net/nfc/pn544.txt
Documentation/devicetree/bindings/net/ti,dp83822.yaml
Documentation/devicetree/bindings/pci/socionext,uniphier-pcie-ep.yaml
Documentation/devicetree/bindings/phy/socionext,uniphier-ahci-phy.yaml
Documentation/devicetree/bindings/phy/ti,omap-usb2.yaml
Documentation/devicetree/bindings/pinctrl/actions,s500-pinctrl.yaml
Documentation/devicetree/bindings/pinctrl/pinctrl-mt8192.yaml
Documentation/devicetree/bindings/pinctrl/qcom,msm8226-pinctrl.yaml
Documentation/devicetree/bindings/pinctrl/toshiba,visconti-pinctrl.yaml
Documentation/devicetree/bindings/power/reset/reboot-mode.yaml
Documentation/devicetree/bindings/power/supply/ingenic,battery.yaml
Documentation/devicetree/bindings/power/supply/summit,smb347-charger.yaml
Documentation/devicetree/bindings/regulator/mps,mp886x.yaml
Documentation/devicetree/bindings/regulator/pfuze100.yaml
Documentation/devicetree/bindings/riscv/sifive-l2-cache.yaml
Documentation/devicetree/bindings/riscv/sifive.yaml
Documentation/devicetree/bindings/rng/imx-rng.yaml
Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml
Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml
Documentation/devicetree/bindings/sound/mchp,spdifrx.yaml
Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml
Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml
Documentation/devicetree/bindings/sound/realtek,rt1015p.yaml
Documentation/devicetree/bindings/sound/rt1015.txt
Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
Documentation/devicetree/bindings/timer/arm,sp804.yaml
Documentation/devicetree/bindings/usb/cdns,usb3.yaml
Documentation/devicetree/bindings/usb/ti,hd3ss3220.yaml
Documentation/devicetree/bindings/w1/fsl-imx-owire.yaml
Documentation/driver-api/media/drivers/vidtv.rst
Documentation/filesystems/api-summary.rst
Documentation/filesystems/debugfs.rst
Documentation/filesystems/ext4/journal.rst
Documentation/filesystems/ext4/super.rst
Documentation/filesystems/journalling.rst
Documentation/firmware-guide/acpi/acpi-lid.rst
Documentation/firmware-guide/acpi/gpio-properties.rst
Documentation/firmware-guide/acpi/method-tracing.rst
Documentation/gpu/amdgpu.rst
Documentation/hwmon/adm1266.rst
Documentation/hwmon/index.rst
Documentation/hwmon/mp2975.rst
Documentation/kbuild/llvm.rst
Documentation/leds/index.rst
Documentation/leds/leds-el15203000.rst [new file with mode: 0644]
Documentation/leds/leds-sc27xx.rst [new file with mode: 0644]
Documentation/locking/lockdep-design.rst
Documentation/misc-devices/index.rst
Documentation/misc-devices/mic/index.rst [deleted file]
Documentation/misc-devices/mic/mic_overview.rst [deleted file]
Documentation/misc-devices/mic/scif_overview.rst [deleted file]
Documentation/networking/devlink/ice.rst
Documentation/networking/j1939.rst
Documentation/networking/netdev-FAQ.rst
Documentation/networking/phy.rst
Documentation/networking/statistics.rst
Documentation/process/stable-kernel-rules.rst
Documentation/sphinx/automarkup.py
Documentation/sphinx/kernel_abi.py [new file with mode: 0644]
Documentation/sphinx/kernellog.py
Documentation/translations/it_IT/process/stable-kernel-rules.rst
Documentation/userspace-api/index.rst
Documentation/virt/kvm/api.rst
Documentation/virt/kvm/cpuid.rst
Documentation/xtensa/mmu.rst
MAINTAINERS
Makefile
arch/Kconfig
arch/alpha/kernel/process.c
arch/arc/include/asm/bitops.h
arch/arc/include/asm/pgtable.h
arch/arc/kernel/head.S
arch/arc/kernel/stacktrace.c
arch/arc/mm/tlb.c
arch/arc/plat-hsdk/platform.c
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/head.S
arch/arm/boot/dts/am437x-l4.dtsi
arch/arm/boot/dts/aspeed-g6.dtsi
arch/arm/boot/dts/dra76x.dtsi
arch/arm/boot/dts/exynos4412-odroid-common.dtsi
arch/arm/boot/dts/imx50-evk.dts
arch/arm/boot/dts/imx6q-prti6q.dts
arch/arm/boot/dts/imx6qdl-udoo.dtsi
arch/arm/boot/dts/mmp2-olpc-xo-1-75.dts
arch/arm/boot/dts/mmp3.dtsi
arch/arm/boot/dts/stm32mp157c-ed1.dts
arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi
arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi
arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi
arch/arm/boot/dts/stm32mp15xx-dkx.dtsi
arch/arm/boot/dts/sun4i-a10.dtsi
arch/arm/boot/dts/sun6i-a31-hummingbird.dts
arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
arch/arm/boot/dts/sun7i-a20-cubietruck.dts
arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts
arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts
arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts
arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts
arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
arch/arm/boot/dts/sun9i-a80-optimus.dts
arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi
arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
arch/arm/configs/imx_v4_v5_defconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/multi_v5_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/include/asm/kprobes.h
arch/arm/include/asm/pgtable-2level.h
arch/arm/include/asm/pgtable-3level.h
arch/arm/kernel/perf_regs.c
arch/arm/kernel/process.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/mach-mvebu/coherency_ll.S
arch/arm/mach-omap1/board-osk.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/cpuidle44xx.c
arch/arm/mm/init.c
arch/arm/probes/kprobes/opt-arm.c
arch/arm64/Kconfig
arch/arm64/Kconfig.platforms
arch/arm64/Makefile
arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h5-cc.dts
arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts
arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dts
arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
arch/arm64/boot/dts/amlogic/meson-axg.dtsi
arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2-plus.dts
arch/arm64/boot/dts/amlogic/meson-gx.dtsi
arch/arm64/boot/dts/broadcom/stingray/stingray-usb.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28.dts
arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
arch/arm64/boot/dts/freescale/imx8mm-beacon-som.dtsi
arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi
arch/arm64/boot/dts/freescale/imx8mm.dtsi
arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts
arch/arm64/boot/dts/freescale/imx8mn-evk.dts
arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi
arch/arm64/boot/dts/freescale/imx8mn.dtsi
arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi
arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts
arch/arm64/boot/dts/marvell/armada-3720-espressobin-v7-emmc.dts
arch/arm64/boot/dts/marvell/armada-3720-espressobin-v7.dts
arch/arm64/boot/dts/marvell/armada-3720-espressobin.dtsi
arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
arch/arm64/boot/dts/nvidia/tegra194-p3668-0000.dtsi
arch/arm64/boot/dts/nvidia/tegra194.dtsi
arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
arch/arm64/boot/dts/nvidia/tegra234-sim-vdk.dts
arch/arm64/boot/dts/qcom/ipq6018.dtsi
arch/arm64/boot/dts/renesas/r8a774e1.dtsi
arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts
arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts
arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi
arch/arm64/boot/dts/rockchip/rk3399.dtsi
arch/arm64/configs/defconfig
arch/arm64/include/asm/brk-imm.h
arch/arm64/include/asm/cache.h
arch/arm64/include/asm/cpucaps.h
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/cputype.h
arch/arm64/include/asm/daifflags.h
arch/arm64/include/asm/debug-monitors.h
arch/arm64/include/asm/exception.h
arch/arm64/include/asm/kprobes.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/probes.h
arch/arm64/include/asm/ptrace.h
arch/arm64/include/asm/sysreg.h
arch/arm64/include/asm/virt.h
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/cpuinfo.c
arch/arm64/kernel/efi-header.S
arch/arm64/kernel/entry-common.c
arch/arm64/kernel/entry.S
arch/arm64/kernel/image-vars.h
arch/arm64/kernel/irq.c
arch/arm64/kernel/kexec_image.c
arch/arm64/kernel/machine_kexec_file.c
arch/arm64/kernel/perf_regs.c
arch/arm64/kernel/probes/kprobes.c
arch/arm64/kernel/process.c
arch/arm64/kernel/proton-pack.c
arch/arm64/kernel/psci.c
arch/arm64/kernel/sdei.c
arch/arm64/kernel/smp.c
arch/arm64/kernel/syscall.c
arch/arm64/kernel/traps.c
arch/arm64/kernel/vdso32/Makefile
arch/arm64/kernel/vmlinux.lds.S
arch/arm64/kvm/arm.c
arch/arm64/kvm/hyp/include/hyp/switch.h
arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
arch/arm64/kvm/hyp/nvhe/host.S
arch/arm64/kvm/hyp/nvhe/hyp-init.S
arch/arm64/kvm/hyp/nvhe/hyp.lds.S
arch/arm64/kvm/hyp/nvhe/switch.c
arch/arm64/kvm/hyp/nvhe/tlb.c
arch/arm64/kvm/hyp/pgtable.c
arch/arm64/kvm/hyp/vhe/switch.c
arch/arm64/kvm/hypercalls.c
arch/arm64/kvm/mmu.c
arch/arm64/kvm/sys_regs.c
arch/arm64/kvm/sys_regs.h
arch/arm64/kvm/vgic/vgic-mmio-v3.c
arch/arm64/lib/memcpy.S
arch/arm64/lib/memmove.S
arch/arm64/lib/memset.S
arch/arm64/mm/fault.c
arch/arm64/mm/mmu.c
arch/csky/kernel/perf_regs.c
arch/csky/kernel/process.c
arch/h8300/kernel/process.c
arch/hexagon/kernel/process.c
arch/ia64/include/asm/sparsemem.h
arch/ia64/kernel/process.c
arch/microblaze/kernel/process.c
arch/mips/alchemy/common/clock.c
arch/mips/include/asm/pgtable-32.h
arch/mips/kernel/idle.c
arch/mips/kernel/setup.c
arch/mips/mm/tlb-r4k.c
arch/nios2/kernel/process.c
arch/openrisc/kernel/process.c
arch/parisc/kernel/process.c
arch/powerpc/Kconfig
arch/powerpc/Makefile
arch/powerpc/include/asm/book3s/32/pgtable.h
arch/powerpc/include/asm/book3s/64/kup-radix.h
arch/powerpc/include/asm/book3s/64/mmu.h
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/include/asm/feature-fixups.h
arch/powerpc/include/asm/kup.h
arch/powerpc/include/asm/mmzone.h
arch/powerpc/include/asm/nohash/32/kup-8xx.h
arch/powerpc/include/asm/nohash/32/mmu-8xx.h
arch/powerpc/include/asm/nohash/32/pgtable.h
arch/powerpc/include/asm/nohash/32/pte-8xx.h
arch/powerpc/include/asm/security_features.h
arch/powerpc/include/asm/setup.h
arch/powerpc/include/asm/sparsemem.h
arch/powerpc/include/asm/topology.h
arch/powerpc/include/asm/uaccess.h
arch/powerpc/kernel/eeh_cache.c
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/head_40x.S
arch/powerpc/kernel/head_8xx.S
arch/powerpc/kernel/head_book3s_32.S
arch/powerpc/kernel/idle.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/syscall_64.c
arch/powerpc/kernel/vmlinux.lds.S
arch/powerpc/kvm/book3s_xive.c
arch/powerpc/kvm/book3s_xive_native.c
arch/powerpc/lib/feature-fixups.c
arch/powerpc/mm/book3s64/hash_native.c
arch/powerpc/mm/book3s64/mmu_context.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/numa.c
arch/powerpc/perf/imc-pmu.c
arch/powerpc/perf/perf_regs.c
arch/powerpc/platforms/powermac/smp.c
arch/powerpc/platforms/powernv/setup.c
arch/powerpc/platforms/powernv/smp.c
arch/powerpc/platforms/pseries/hotplug-cpu.c
arch/powerpc/platforms/pseries/mobility.c
arch/powerpc/platforms/pseries/msi.c
arch/powerpc/platforms/pseries/pseries.h
arch/powerpc/platforms/pseries/setup.c
arch/riscv/include/asm/pgtable-32.h
arch/riscv/include/asm/uaccess.h
arch/riscv/include/asm/vdso/processor.h
arch/riscv/kernel/ftrace.c
arch/riscv/kernel/head.S
arch/riscv/kernel/perf_regs.c
arch/riscv/kernel/process.c
arch/riscv/kernel/setup.c
arch/riscv/kernel/vdso/.gitignore
arch/riscv/kernel/vdso/Makefile
arch/riscv/kernel/vdso/so2s.sh [new file with mode: 0755]
arch/riscv/mm/fault.c
arch/riscv/mm/init.c
arch/s390/configs/debug_defconfig
arch/s390/configs/defconfig
arch/s390/configs/zfcpdump_defconfig
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/sections.h
arch/s390/include/asm/vdso/vdso.h [deleted file]
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/entry.S
arch/s390/kernel/idle.c
arch/s390/kernel/perf_cpum_sf.c
arch/s390/kernel/perf_regs.c
arch/s390/kernel/smp.c
arch/s390/kernel/uv.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/pv.c
arch/s390/lib/delay.c
arch/s390/mm/gmap.c
arch/s390/pci/pci_event.c
arch/s390/pci/pci_irq.c
arch/sh/kernel/idle.c
arch/sparc/kernel/leon_pmc.c
arch/sparc/kernel/process_32.c
arch/sparc/kernel/process_64.c
arch/um/include/asm/pgalloc.h
arch/um/kernel/process.c
arch/um/kernel/skas/clone.c
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/boot/compressed/Makefile
arch/x86/boot/compressed/ident_map_64.c
arch/x86/boot/compressed/mem_encrypt.S
arch/x86/boot/compressed/misc.h
arch/x86/boot/compressed/sev-es.c
arch/x86/crypto/poly1305_glue.c
arch/x86/entry/syscalls/syscall_64.tbl
arch/x86/events/intel/core.c
arch/x86/events/intel/cstate.c
arch/x86/events/intel/ds.c
arch/x86/events/intel/uncore.c
arch/x86/events/intel/uncore.h
arch/x86/events/intel/uncore_snb.c
arch/x86/events/perf_event.h
arch/x86/events/rapl.c
arch/x86/hyperv/hv_apic.c
arch/x86/include/asm/insn.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/mwait.h
arch/x86/include/asm/perf_event.h
arch/x86/include/asm/sparsemem.h
arch/x86/include/asm/uv/uv.h
arch/x86/include/uapi/asm/kvm_para.h
arch/x86/kernel/alternative.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/mce/core.c
arch/x86/kernel/cpu/microcode/intel.c
arch/x86/kernel/cpu/resctrl/core.c
arch/x86/kernel/cpu/resctrl/internal.h
arch/x86/kernel/cpu/resctrl/rdtgroup.c
arch/x86/kernel/dumpstack.c
arch/x86/kernel/head_64.S
arch/x86/kernel/kexec-bzimage64.c
arch/x86/kernel/perf_regs.c
arch/x86/kernel/process.c
arch/x86/kernel/sev-es-shared.c
arch/x86/kernel/sev-es.c
arch/x86/kernel/sev_verify_cbit.S [new file with mode: 0644]
arch/x86/kernel/tboot.c
arch/x86/kernel/traps.c
arch/x86/kernel/unwind_orc.c
arch/x86/kernel/uprobes.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/emulate.c
arch/x86/kvm/irq.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/mmu/spte.c
arch/x86/kvm/mmu/spte.h
arch/x86/kvm/mmu/tdp_mmu.c
arch/x86/kvm/svm/sev.c
arch/x86/kvm/svm/svm.c
arch/x86/kvm/vmx/evmcs.c
arch/x86/kvm/vmx/evmcs.h
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/x86.c
arch/x86/kvm/x86.h
arch/x86/lib/insn-eval.c
arch/x86/lib/memcpy_64.S
arch/x86/lib/memmove_64.S
arch/x86/lib/memset_64.S
arch/x86/mm/mem_encrypt.c
arch/x86/mm/numa.c
arch/x86/platform/efi/efi_64.c
arch/x86/um/stub_segv.c
arch/x86/xen/spinlock.c
arch/xtensa/include/asm/pgtable.h
arch/xtensa/include/asm/uaccess.h
arch/xtensa/mm/cache.c
arch/xtensa/mm/init.c
block/bio.c
block/blk-cgroup.c
block/blk-flush.c
block/blk-merge.c
block/blk-settings.c
block/genhd.c
block/keyslot-manager.c
drivers/Makefile
drivers/accessibility/speakup/main.c
drivers/accessibility/speakup/selection.c
drivers/accessibility/speakup/speakup.h
drivers/accessibility/speakup/spk_ttyio.c
drivers/accessibility/speakup/spk_types.h
drivers/acpi/acpi_video.c
drivers/acpi/apei/apei-base.c
drivers/acpi/arm64/iort.c
drivers/acpi/battery.c
drivers/acpi/button.c
drivers/acpi/dock.c
drivers/acpi/dptf/dptf_pch_fivr.c
drivers/acpi/dptf/dptf_power.c
drivers/acpi/dptf/int340x_thermal.c
drivers/acpi/event.c
drivers/acpi/evged.c
drivers/acpi/fan.c
drivers/acpi/internal.h
drivers/acpi/nfit/core.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_link.c
drivers/acpi/pci_mcfg.c
drivers/acpi/power.c
drivers/acpi/processor_perflib.c
drivers/acpi/sbs.c
drivers/acpi/sbshc.c
drivers/acpi/sbshc.h
drivers/acpi/scan.c
drivers/acpi/video_detect.c
drivers/acpi/wakeup.c
drivers/ata/sata_nv.c
drivers/atm/nicstar.c
drivers/base/core.c
drivers/base/dd.c
drivers/base/power/runtime.c
drivers/block/loop.c
drivers/block/nbd.c
drivers/block/null_blk.h
drivers/block/null_blk_zoned.c
drivers/block/xsysace.c
drivers/bluetooth/btintel.h
drivers/bus/ti-sysc.c
drivers/char/tpm/eventlog/efi.c
drivers/char/tpm/tpm_tis.c
drivers/char/virtio_console.c
drivers/clk/imx/clk-imx8mm.c
drivers/clk/imx/clk-imx8mn.c
drivers/clk/imx/clk-imx8mp.c
drivers/clk/imx/clk-imx8mq.c
drivers/clk/imx/clk.h
drivers/clk/meson/clk-regmap.h
drivers/clk/qcom/clk-regmap.h
drivers/counter/ti-eqep.c
drivers/cpufreq/Kconfig
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_governor.h
drivers/cpufreq/cpufreq_performance.c
drivers/cpufreq/cpufreq_powersave.c
drivers/cpufreq/e_powersaver.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/longhaul.c
drivers/cpufreq/scmi-cpufreq.c
drivers/cpufreq/speedstep-lib.c
drivers/cpufreq/tegra186-cpufreq.c
drivers/cpuidle/cpuidle-tegra.c
drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c
drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c
drivers/crypto/allwinner/sun8i-ce/sun8i-ce-trng.c
drivers/dax/Kconfig
drivers/dma/Kconfig
drivers/dma/Makefile
drivers/dma/dmaengine.c
drivers/dma/idxd/device.c
drivers/dma/idxd/idxd.h
drivers/dma/idxd/init.c
drivers/dma/idxd/registers.h
drivers/dma/idxd/submit.c
drivers/dma/ioat/dca.c
drivers/dma/mic_x100_dma.c [deleted file]
drivers/dma/mic_x100_dma.h [deleted file]
drivers/dma/pl330.c
drivers/dma/ti/k3-udma-private.c
drivers/dma/ti/omap-dma.c
drivers/dma/xilinx/xilinx_dma.c
drivers/edac/Kconfig
drivers/edac/Makefile
drivers/edac/amd64_edac.c
drivers/edac/amd76x_edac.c
drivers/edac/aspeed_edac.c
drivers/edac/e752x_edac.c
drivers/edac/e7xxx_edac.c
drivers/edac/edac_device.h
drivers/edac/edac_mc.c
drivers/edac/i10nm_base.c
drivers/edac/i3000_edac.c
drivers/edac/i3200_edac.c
drivers/edac/i5000_edac.c
drivers/edac/i5400_edac.c
drivers/edac/i82443bxgx_edac.c
drivers/edac/i82860_edac.c
drivers/edac/i82875p_edac.c
drivers/edac/i82975x_edac.c
drivers/edac/ie31200_edac.c
drivers/edac/mv64x60_edac.c [deleted file]
drivers/edac/mv64x60_edac.h [deleted file]
drivers/edac/r82600_edac.c
drivers/edac/skx_base.c
drivers/edac/skx_common.c
drivers/edac/skx_common.h
drivers/edac/synopsys_edac.c
drivers/edac/x38_edac.c
drivers/firmware/arm_scmi/base.c
drivers/firmware/arm_scmi/clock.c
drivers/firmware/arm_scmi/common.h
drivers/firmware/arm_scmi/driver.c
drivers/firmware/arm_scmi/notify.c
drivers/firmware/arm_scmi/perf.c
drivers/firmware/arm_scmi/reset.c
drivers/firmware/arm_scmi/sensors.c
drivers/firmware/arm_scmi/smc.c
drivers/firmware/efi/Kconfig
drivers/firmware/efi/efi.c
drivers/firmware/xilinx/zynqmp.c
drivers/fpga/Kconfig
drivers/gpio/gpio-aspeed.c
drivers/gpio/gpio-dwapb.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-pcie-idio-24.c
drivers/gpio/gpio-sifive.c
drivers/gpio/gpiolib-cdev.h
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
drivers/gpu/drm/amd/amdgpu/cik.c
drivers/gpu/drm/amd/amdgpu/cik_sdma.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/nv.c
drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c
drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
drivers/gpu/drm/amd/amdkfd/kfd_crat.c
drivers/gpu/drm/amd/display/Kconfig
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_factory_dcn30.c
drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c
drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c
drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c
drivers/gpu/drm/amd/display/dc/os_types.h
drivers/gpu/drm/amd/display/include/dal_asic_id.h
drivers/gpu/drm/amd/include/amd_shared.h
drivers/gpu/drm/amd/pm/inc/hwmgr.h
drivers/gpu/drm/amd/pm/inc/smumgr.h
drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.c
drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
drivers/gpu/drm/amd/pm/powerplay/smumgr/smumgr.c
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/bridge/cadence/Kconfig
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
drivers/gpu/drm/drm_dp_helper.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_gem_shmem_helper.c
drivers/gpu/drm/drm_gem_vram_helper.c
drivers/gpu/drm/drm_prime.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/gma500/psb_irq.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_psr.c
drivers/gpu/drm/i915/gem/i915_gem_domain.c
drivers/gpu/drm/i915/gem/i915_gem_object_types.h
drivers/gpu/drm/i915/gem/i915_gem_phys.c
drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h
drivers/gpu/drm/i915/gt/intel_context.c
drivers/gpu/drm/i915/gt/intel_context_types.h
drivers/gpu/drm/i915/gt/intel_engine.h
drivers/gpu/drm/i915/gt/intel_engine_cs.c
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gt/intel_mocs.c
drivers/gpu/drm/i915/gt/intel_rc6.c
drivers/gpu/drm/i915/gt/intel_rps.c
drivers/gpu/drm/i915/gt/intel_timeline.c
drivers/gpu/drm/i915/gt/intel_timeline_types.h
drivers/gpu/drm/i915/gt/intel_workarounds.c
drivers/gpu/drm/i915/gt/shmem_utils.c
drivers/gpu/drm/i915/gvt/display.c
drivers/gpu/drm/i915/gvt/gvt.h
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/i915/gvt/vgpu.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_request.h
drivers/gpu/drm/i915/i915_vma.c
drivers/gpu/drm/i915/intel_memory_region.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/selftests/i915_request.c
drivers/gpu/drm/i915/selftests/intel_memory_region.c
drivers/gpu/drm/i915/selftests/mock_region.c
drivers/gpu/drm/imx/dw_hdmi-imx.c
drivers/gpu/drm/imx/imx-drm-core.c
drivers/gpu/drm/imx/imx-ldb.c
drivers/gpu/drm/imx/imx-tve.c
drivers/gpu/drm/imx/parallel-display.c
drivers/gpu/drm/mcde/mcde_drv.c
drivers/gpu/drm/mediatek/mtk_dpi.c
drivers/gpu/drm/mediatek/mtk_dsi.c
drivers/gpu/drm/mxsfb/mxsfb_kms.c
drivers/gpu/drm/nouveau/dispnv50/core.h
drivers/gpu/drm/nouveau/dispnv50/core507d.c
drivers/gpu/drm/nouveau/dispnv50/core907d.c
drivers/gpu/drm/nouveau/dispnv50/core917d.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/include/nvhw/class/cl507d.h
drivers/gpu/drm/nouveau/include/nvhw/class/cl907d.h
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_dp.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nouveau_svm.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/omapdrm/dss/sdi.c
drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c
drivers/gpu/drm/panel/panel-sony-acx565akm.c
drivers/gpu/drm/panfrost/panfrost_drv.c
drivers/gpu/drm/panfrost/panfrost_gem.c
drivers/gpu/drm/panfrost/panfrost_gem.h
drivers/gpu/drm/panfrost/panfrost_gem_shrinker.c
drivers/gpu/drm/rockchip/rockchip_lvds.c
drivers/gpu/drm/sun4i/sun4i_backend.c
drivers/gpu/drm/sun4i/sun4i_frontend.c
drivers/gpu/drm/sun4i/sun4i_frontend.h
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
drivers/gpu/drm/tegra/drm.c
drivers/gpu/drm/tegra/output.c
drivers/gpu/drm/tegra/sor.c
drivers/gpu/drm/v3d/v3d_gem.c
drivers/gpu/drm/vc4/vc4_bo.c
drivers/gpu/drm/vc4/vc4_drv.c
drivers/gpu/drm/vc4/vc4_drv.h
drivers/gpu/drm/vc4/vc4_gem.c
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/gpu/drm/vc4/vc4_hdmi.h
drivers/gpu/drm/vc4/vc4_hvs.c
drivers/gpu/drm/vc4/vc4_kms.c
drivers/gpu/drm/vc4/vc4_v3d.c
drivers/gpu/ipu-v3/ipu-common.c
drivers/hid/hid-cypress.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-ite.c
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-mcp2221.c
drivers/hid/hid-quirks.c
drivers/hid/hid-sensor-hub.c
drivers/hid/hid-uclogic-core.c
drivers/hid/hid-uclogic-params.c
drivers/hid/i2c-hid/i2c-hid-core.c
drivers/hv/hv.c
drivers/hv/hv_balloon.c
drivers/hwmon/amd_energy.c
drivers/hwmon/applesmc.c
drivers/hwmon/pmbus/max20730.c
drivers/hwmon/pmbus/pmbus_core.c
drivers/hwmon/pwm-fan.c
drivers/hwtracing/coresight/coresight-core.c
drivers/hwtracing/coresight/coresight-cti-sysfs.c
drivers/hwtracing/coresight/coresight-etm-perf.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-designware-slave.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-mlxbf.c
drivers/i2c/busses/i2c-mt65xx.c
drivers/i2c/busses/i2c-qcom-cci.c
drivers/i2c/busses/i2c-qup.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/idle/intel_idle.c
drivers/iio/accel/kxcjk-1013.c
drivers/iio/adc/ingenic-adc.c
drivers/iio/adc/mt6577_auxadc.c
drivers/iio/adc/stm32-adc-core.c
drivers/iio/adc/stm32-adc.c
drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
drivers/iio/light/Kconfig
drivers/infiniband/Kconfig
drivers/infiniband/core/cm.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/uverbs_std_types_device.c
drivers/infiniband/hw/hfi1/chip.c
drivers/infiniband/hw/hfi1/file_ops.c
drivers/infiniband/hw/hfi1/hfi.h
drivers/infiniband/hw/hfi1/mmu_rb.c
drivers/infiniband/hw/hfi1/mmu_rb.h
drivers/infiniband/hw/hfi1/user_exp_rcv.c
drivers/infiniband/hw/hfi1/user_exp_rcv.h
drivers/infiniband/hw/hfi1/user_sdma.c
drivers/infiniband/hw/hfi1/user_sdma.h
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
drivers/infiniband/hw/hns/hns_roce_hw_v2.h
drivers/infiniband/hw/i40iw/i40iw_main.c
drivers/infiniband/hw/i40iw/i40iw_verbs.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mthca/mthca_cq.c
drivers/infiniband/hw/qedr/qedr_iw_cm.c
drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
drivers/infiniband/sw/rdmavt/Kconfig
drivers/infiniband/sw/rdmavt/vt.c
drivers/infiniband/sw/rxe/Kconfig
drivers/infiniband/sw/rxe/rxe_av.c
drivers/infiniband/sw/rxe/rxe_net.c
drivers/infiniband/sw/rxe/rxe_verbs.c
drivers/infiniband/sw/siw/Kconfig
drivers/infiniband/sw/siw/siw_main.c
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/infiniband/ulp/rtrs/rtrs-clt.c
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/infiniband/ulp/srpt/ib_srpt.h
drivers/input/joystick/xpad.c
drivers/input/keyboard/sunkbd.c
drivers/input/misc/adxl34x.c
drivers/input/misc/soc_button_array.c
drivers/input/mouse/elan_i2c.h
drivers/input/mouse/elan_i2c_core.c
drivers/input/mouse/elan_i2c_i2c.c
drivers/input/mouse/elan_i2c_smbus.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/i8042.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/interconnect/core.c
drivers/interconnect/qcom/icc-rpmh.c
drivers/interconnect/qcom/msm8916.c
drivers/interconnect/qcom/msm8974.c
drivers/interconnect/qcom/qcs404.c
drivers/interconnect/qcom/sc7180.c
drivers/interconnect/qcom/sdm845.c
drivers/interconnect/qcom/sm8150.c
drivers/interconnect/qcom/sm8250.c
drivers/iommu/amd/amd_iommu_types.h
drivers/iommu/amd/init.c
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
drivers/iommu/intel/dmar.c
drivers/iommu/intel/iommu.c
drivers/iommu/intel/svm.c
drivers/iommu/iommu.c
drivers/irqchip/Kconfig
drivers/irqchip/irq-bcm2836.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-mst-intc.c
drivers/irqchip/irq-renesas-intc-irqpin.c
drivers/irqchip/irq-sifive-plic.c
drivers/irqchip/irq-sni-exiu.c
drivers/irqchip/irq-stm32-exti.c
drivers/irqchip/irq-ti-sci-inta.c
drivers/md/dm-cache-target.c
drivers/md/dm-integrity.c
drivers/md/dm-table.c
drivers/md/dm-writecache.c
drivers/md/dm.c
drivers/media/platform/Kconfig
drivers/media/platform/marvell-ccic/mmp-driver.c
drivers/media/platform/mtk-vcodec/Makefile
drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
drivers/media/platform/mtk-vcodec/mtk_vcodec_fw.c
drivers/media/platform/mtk-vcodec/mtk_vcodec_fw.h
drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_priv.h [new file with mode: 0644]
drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c [new file with mode: 0644]
drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c [new file with mode: 0644]
drivers/media/platform/qcom/venus/core.h
drivers/media/platform/qcom/venus/pm_helpers.c
drivers/media/platform/qcom/venus/venc.c
drivers/media/platform/qcom/venus/venc_ctrls.c
drivers/media/test-drivers/vidtv/vidtv_bridge.c
drivers/media/test-drivers/vidtv/vidtv_bridge.h
drivers/media/test-drivers/vidtv/vidtv_channel.c
drivers/media/test-drivers/vidtv/vidtv_channel.h
drivers/media/test-drivers/vidtv/vidtv_common.h
drivers/media/test-drivers/vidtv/vidtv_demod.c
drivers/media/test-drivers/vidtv/vidtv_demod.h
drivers/media/test-drivers/vidtv/vidtv_encoder.h
drivers/media/test-drivers/vidtv/vidtv_mux.c
drivers/media/test-drivers/vidtv/vidtv_mux.h
drivers/media/test-drivers/vidtv/vidtv_pes.c
drivers/media/test-drivers/vidtv/vidtv_pes.h
drivers/media/test-drivers/vidtv/vidtv_psi.c
drivers/media/test-drivers/vidtv/vidtv_psi.h
drivers/media/test-drivers/vidtv/vidtv_s302m.c
drivers/media/test-drivers/vidtv/vidtv_s302m.h
drivers/media/test-drivers/vidtv/vidtv_ts.c
drivers/media/test-drivers/vidtv/vidtv_ts.h
drivers/media/test-drivers/vidtv/vidtv_tuner.c
drivers/media/test-drivers/vidtv/vidtv_tuner.h
drivers/message/fusion/mptscsih.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/habanalabs/common/command_buffer.c
drivers/misc/habanalabs/common/device.c
drivers/misc/habanalabs/common/habanalabs.h
drivers/misc/habanalabs/common/hw_queue.c
drivers/misc/habanalabs/common/irq.c
drivers/misc/habanalabs/common/memory.c
drivers/misc/habanalabs/gaudi/gaudi.c
drivers/misc/habanalabs/gaudi/gaudiP.h
drivers/misc/habanalabs/gaudi/gaudi_coresight.c
drivers/misc/habanalabs/goya/goya.c
drivers/misc/habanalabs/goya/goyaP.h
drivers/misc/habanalabs/include/gaudi/gaudi_masks.h
drivers/misc/mei/Kconfig
drivers/misc/mei/Makefile
drivers/misc/mei/client.h
drivers/misc/mei/hw-virtio.c [deleted file]
drivers/misc/mei/hw.h
drivers/misc/mic/Kconfig [deleted file]
drivers/misc/mic/Makefile [deleted file]
drivers/misc/mic/bus/Makefile [deleted file]
drivers/misc/mic/bus/cosm_bus.c [deleted file]
drivers/misc/mic/bus/cosm_bus.h [deleted file]
drivers/misc/mic/bus/mic_bus.c [deleted file]
drivers/misc/mic/bus/scif_bus.c [deleted file]
drivers/misc/mic/bus/scif_bus.h [deleted file]
drivers/misc/mic/bus/vop_bus.c [deleted file]
drivers/misc/mic/bus/vop_bus.h [deleted file]
drivers/misc/mic/card/Makefile [deleted file]
drivers/misc/mic/card/mic_debugfs.c [deleted file]
drivers/misc/mic/card/mic_device.c [deleted file]
drivers/misc/mic/card/mic_device.h [deleted file]
drivers/misc/mic/card/mic_x100.c [deleted file]
drivers/misc/mic/card/mic_x100.h [deleted file]
drivers/misc/mic/common/mic_dev.h [deleted file]
drivers/misc/mic/cosm/Makefile [deleted file]
drivers/misc/mic/cosm/cosm_debugfs.c [deleted file]
drivers/misc/mic/cosm/cosm_main.c [deleted file]
drivers/misc/mic/cosm/cosm_main.h [deleted file]
drivers/misc/mic/cosm/cosm_scif_server.c [deleted file]
drivers/misc/mic/cosm/cosm_sysfs.c [deleted file]
drivers/misc/mic/cosm_client/Makefile [deleted file]
drivers/misc/mic/cosm_client/cosm_scif_client.c [deleted file]
drivers/misc/mic/host/Makefile [deleted file]
drivers/misc/mic/host/mic_boot.c [deleted file]
drivers/misc/mic/host/mic_debugfs.c [deleted file]
drivers/misc/mic/host/mic_device.h [deleted file]
drivers/misc/mic/host/mic_intr.c [deleted file]
drivers/misc/mic/host/mic_intr.h [deleted file]
drivers/misc/mic/host/mic_main.c [deleted file]
drivers/misc/mic/host/mic_smpt.c [deleted file]
drivers/misc/mic/host/mic_smpt.h [deleted file]
drivers/misc/mic/host/mic_x100.c [deleted file]
drivers/misc/mic/host/mic_x100.h [deleted file]
drivers/misc/mic/scif/Makefile [deleted file]
drivers/misc/mic/scif/scif_api.c [deleted file]
drivers/misc/mic/scif/scif_debugfs.c [deleted file]
drivers/misc/mic/scif/scif_dma.c [deleted file]
drivers/misc/mic/scif/scif_epd.c [deleted file]
drivers/misc/mic/scif/scif_epd.h [deleted file]
drivers/misc/mic/scif/scif_fd.c [deleted file]
drivers/misc/mic/scif/scif_fence.c [deleted file]
drivers/misc/mic/scif/scif_main.c [deleted file]
drivers/misc/mic/scif/scif_main.h [deleted file]
drivers/misc/mic/scif/scif_map.h [deleted file]
drivers/misc/mic/scif/scif_mmap.c [deleted file]
drivers/misc/mic/scif/scif_nm.c [deleted file]
drivers/misc/mic/scif/scif_nodeqp.c [deleted file]
drivers/misc/mic/scif/scif_nodeqp.h [deleted file]
drivers/misc/mic/scif/scif_peer_bus.c [deleted file]
drivers/misc/mic/scif/scif_peer_bus.h [deleted file]
drivers/misc/mic/scif/scif_ports.c [deleted file]
drivers/misc/mic/scif/scif_rb.c [deleted file]
drivers/misc/mic/scif/scif_rb.h [deleted file]
drivers/misc/mic/scif/scif_rma.c [deleted file]
drivers/misc/mic/scif/scif_rma.h [deleted file]
drivers/misc/mic/scif/scif_rma_list.c [deleted file]
drivers/misc/mic/scif/scif_rma_list.h [deleted file]
drivers/misc/mic/vop/Makefile [deleted file]
drivers/misc/mic/vop/vop_debugfs.c [deleted file]
drivers/misc/mic/vop/vop_main.c [deleted file]
drivers/misc/mic/vop/vop_main.h [deleted file]
drivers/misc/mic/vop/vop_vringh.c [deleted file]
drivers/mmc/host/renesas_sdhi_core.c
drivers/mmc/host/sdhci-esdhc.h
drivers/mmc/host/sdhci-of-arasan.c
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mmc/host/sdhci-pci-core.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/tmio_mmc_core.c
drivers/mtd/nand/raw/ams-delta.c
drivers/mtd/nand/raw/au1550nd.c
drivers/mtd/nand/raw/cs553x_nand.c
drivers/mtd/nand/raw/davinci_nand.c
drivers/mtd/nand/raw/diskonchip.c
drivers/mtd/nand/raw/fsl_ifc_nand.c
drivers/mtd/nand/raw/fsmc_nand.c
drivers/mtd/nand/raw/gpio.c
drivers/mtd/nand/raw/lpc32xx_mlc.c
drivers/mtd/nand/raw/lpc32xx_slc.c
drivers/mtd/nand/raw/mpc5121_nfc.c
drivers/mtd/nand/raw/mxc_nand.c
drivers/mtd/nand/raw/orion_nand.c
drivers/mtd/nand/raw/pasemi_nand.c
drivers/mtd/nand/raw/plat_nand.c
drivers/mtd/nand/raw/r852.c
drivers/mtd/nand/raw/r852.h
drivers/mtd/nand/raw/sharpsl.c
drivers/mtd/nand/raw/socrates_nand.c
drivers/mtd/nand/raw/stm32_fmc2_nand.c
drivers/mtd/nand/raw/tmio_nand.c
drivers/mtd/nand/raw/txx9ndfmc.c
drivers/mtd/nand/raw/xway_nand.c
drivers/mtd/spi-nor/core.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs_slave.c
drivers/net/can/c_can/c_can.c
drivers/net/can/dev.c
drivers/net/can/flexcan.c
drivers/net/can/kvaser_pciefd.c
drivers/net/can/m_can/Kconfig
drivers/net/can/m_can/m_can.c
drivers/net/can/m_can/m_can.h
drivers/net/can/m_can/m_can_platform.c
drivers/net/can/m_can/tcan4x5x.c
drivers/net/can/peak_canfd/peak_canfd.c
drivers/net/can/rx-offload.c
drivers/net/can/sja1000/sja1000.c
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
drivers/net/can/sun4i_can.c
drivers/net/can/ti_hecc.c
drivers/net/can/usb/gs_usb.c
drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
drivers/net/can/usb/mcba_usb.c
drivers/net/can/usb/peak_usb/pcan_usb_core.c
drivers/net/can/usb/peak_usb/pcan_usb_fd.c
drivers/net/can/xilinx_can.c
drivers/net/dsa/lantiq_gswip.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/devlink.c
drivers/net/dsa/mv88e6xxx/global1.c
drivers/net/dsa/mv88e6xxx/global1.h
drivers/net/dsa/mv88e6xxx/global1_vtu.c
drivers/net/dsa/qca8k.c
drivers/net/ethernet/amazon/ena/ena_eth_com.c
drivers/net/ethernet/amazon/ena/ena_netdev.c
drivers/net/ethernet/aquantia/atlantic/aq_ring.c
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/atheros/atl1e/atl1e_main.c
drivers/net/ethernet/broadcom/Kconfig
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/chelsio/Kconfig
drivers/net/ethernet/chelsio/cxgb3/sge.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/chelsio/cxgb4/t4_tcb.h
drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c
drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.h
drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c
drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_hw.c
drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c
drivers/net/ethernet/faraday/ftgmac100.c
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
drivers/net/ethernet/freescale/dpaa2/Kconfig
drivers/net/ethernet/freescale/enetc/Kconfig
drivers/net/ethernet/freescale/enetc/enetc.c
drivers/net/ethernet/freescale/enetc/enetc_hw.h
drivers/net/ethernet/freescale/enetc/enetc_mdio.c
drivers/net/ethernet/freescale/enetc/enetc_qos.c
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/ucc_geth.c
drivers/net/ethernet/google/gve/gve_adminq.h
drivers/net/ethernet/google/gve/gve_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/ibm/ibmvnic.h
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/intel/i40e/i40e_xsk.c
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/marvell/prestera/Kconfig
drivers/net/ethernet/marvell/prestera/prestera_pci.c
drivers/net/ethernet/mediatek/mtk_star_emac.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/fw.h
drivers/net/ethernet/mellanox/mlx5/core/en/rep/bond.c
drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h
drivers/net/ethernet/mellanox/mlx5/core/lib/vxlan.c
drivers/net/ethernet/mellanox/mlx5/core/lib/vxlan.h
drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
drivers/net/ethernet/mellanox/mlxsw/Kconfig
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
drivers/net/ethernet/microchip/lan743x_main.c
drivers/net/ethernet/microchip/lan743x_main.h
drivers/net/ethernet/pasemi/pasemi_mac.c
drivers/net/ethernet/pensando/ionic/ionic_dev.c
drivers/net/ethernet/pensando/ionic/ionic_dev.h
drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
drivers/net/ethernet/pensando/ionic/ionic_fw.c
drivers/net/ethernet/pensando/ionic/ionic_lif.c
drivers/net/ethernet/pensando/ionic/ionic_main.c
drivers/net/ethernet/pensando/ionic/ionic_stats.h
drivers/net/ethernet/pensando/ionic/ionic_txrx.c
drivers/net/ethernet/pensando/ionic/ionic_txrx.h
drivers/net/ethernet/qlogic/qed/qed_cxt.c
drivers/net/ethernet/qlogic/qed/qed_cxt.h
drivers/net/ethernet/qlogic/qed/qed_iwarp.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/ti/am65-cpts.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/cpsw_ethtool.c
drivers/net/ethernet/ti/cpsw_new.c
drivers/net/ethernet/ti/cpsw_priv.c
drivers/net/geneve.c
drivers/net/gtp.c
drivers/net/ipa/gsi_trans.c
drivers/net/netdevsim/dev.c
drivers/net/netdevsim/health.c
drivers/net/netdevsim/udp_tunnels.c
drivers/net/phy/mscc/mscc_macsec.c
drivers/net/phy/realtek.c
drivers/net/phy/sfp.c
drivers/net/phy/smsc.c
drivers/net/tun.c
drivers/net/usb/cx82310_eth.c
drivers/net/usb/ipheth.c
drivers/net/usb/qmi_wwan.c
drivers/net/vrf.c
drivers/net/vxlan.c
drivers/net/wan/cosa.c
drivers/net/wireless/intel/iwlwifi/fw/api/sta.h
drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h
drivers/net/wireless/intel/iwlwifi/iwl-config.h
drivers/net/wireless/intel/iwlwifi/iwl-csr.h
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/net/wireless/mediatek/mt76/usb.c
drivers/net/wireless/realtek/rtw88/debug.c
drivers/net/wireless/realtek/rtw88/fw.c
drivers/nfc/s3fwrn5/i2c.c
drivers/nvme/host/core.c
drivers/nvme/host/fc.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/host/tcp.c
drivers/nvme/target/core.c
drivers/nvme/target/trace.h
drivers/of/address.c
drivers/of/device.c
drivers/of/of_reserved_mem.c
drivers/opp/core.c
drivers/opp/of.c
drivers/pci/controller/dwc/pcie-designware-host.c
drivers/pci/controller/pci-mvebu.c
drivers/pci/pci.c
drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
drivers/phy/intel/Kconfig
drivers/phy/mediatek/Kconfig
drivers/phy/motorola/phy-cpcap-usb.c
drivers/phy/qualcomm/Kconfig
drivers/phy/qualcomm/phy-qcom-qmp.c
drivers/phy/tegra/xusb.c
drivers/pinctrl/aspeed/pinctrl-aspeed.c
drivers/pinctrl/intel/pinctrl-intel.c
drivers/pinctrl/pinctrl-amd.c
drivers/pinctrl/pinctrl-ingenic.c
drivers/pinctrl/pinctrl-mcp23s08_spi.c
drivers/pinctrl/pinctrl-rockchip.c
drivers/pinctrl/qcom/pinctrl-msm.c
drivers/pinctrl/qcom/pinctrl-sm8250.c
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/intel-vbtn.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/touchscreen_dmi.c
drivers/pnp/core.c
drivers/powercap/intel_rapl_common.c
drivers/powercap/powercap_sys.c
drivers/ptp/ptp_clockmatrix.c
drivers/pwm/pwm-sl28cpld.c
drivers/regulator/core.c
drivers/regulator/pfuze100-regulator.c
drivers/regulator/ti-abb-regulator.c
drivers/s390/block/dasd.c
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/pkey_api.c
drivers/s390/crypto/zcrypt_card.c
drivers/s390/crypto/zcrypt_queue.c
drivers/s390/net/ism_drv.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/scsi/device_handler/scsi_dh_alua.c
drivers/scsi/hisi_sas/hisi_sas_main.c
drivers/scsi/hpsa.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/libiscsi.c
drivers/scsi/mpt3sas/mpt3sas_base.c
drivers/scsi/mpt3sas/mpt3sas_ctl.c
drivers/scsi/qla2xxx/qla_nvme.c
drivers/scsi/qla2xxx/qla_tmpl.c
drivers/scsi/scsi_scan.c
drivers/scsi/storvsc_drv.c
drivers/scsi/ufs/ufshcd.c
drivers/scsi/ufs/ufshcd.h
drivers/soc/fsl/dpio/dpio-driver.c
drivers/soc/ti/ti_sci_pm_domains.c
drivers/spi/spi-bcm-qspi.c
drivers/spi/spi-bcm2835.c
drivers/spi/spi-bcm2835aux.c
drivers/spi/spi-cadence-quadspi.c
drivers/spi/spi-dw-core.c
drivers/spi/spi-fsi.c
drivers/spi/spi-fsl-dspi.c
drivers/spi/spi-fsl-lpspi.c
drivers/spi/spi-imx.c
drivers/spi/spi-npcm-fiu.c
drivers/spi/spi-nxp-fspi.c
drivers/spi/spi.c
drivers/staging/comedi/drivers/cb_pcidas.c
drivers/staging/fieldbus/anybuss/arcx-anybus.c
drivers/staging/media/sunxi/cedrus/cedrus_h264.c
drivers/staging/mt7621-pci/pci-mt7621.c
drivers/staging/octeon/ethernet-mdio.c
drivers/staging/octeon/ethernet-rx.c
drivers/staging/octeon/ethernet.c
drivers/staging/ralink-gdma/Kconfig
drivers/staging/rtl8723bs/os_dep/sdio_intf.c
drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml
drivers/staging/wfx/bh.c
drivers/staging/wfx/data_tx.c
drivers/target/iscsi/iscsi_target.c
drivers/target/target_core_user.c
drivers/tee/amdtee/amdtee_private.h
drivers/tee/amdtee/core.c
drivers/tee/optee/call.c
drivers/tee/tee_core.c
drivers/thermal/ti-soc-thermal/ti-bandgap.c
drivers/thunderbolt/debugfs.c
drivers/thunderbolt/icm.c
drivers/thunderbolt/nhi.c
drivers/thunderbolt/nhi.h
drivers/thunderbolt/tb.h
drivers/thunderbolt/usb4.c
drivers/thunderbolt/xdomain.c
drivers/tty/serial/21285.c
drivers/tty/serial/8250/8250_mtk.c
drivers/tty/serial/Kconfig
drivers/tty/serial/ar933x_uart.c
drivers/tty/serial/fsl_lpuart.c
drivers/tty/serial/imx.c
drivers/tty/serial/serial_txx9.c
drivers/tty/tty_io.c
drivers/tty/tty_jobctrl.c
drivers/tty/vt/keyboard.c
drivers/tty/vt/vt.c
drivers/tty/vt/vt_ioctl.c
drivers/uio/uio.c
drivers/usb/cdns3/core.c
drivers/usb/cdns3/ep0.c
drivers/usb/cdns3/gadget.c
drivers/usb/cdns3/gadget.h
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.h
drivers/usb/core/devio.c
drivers/usb/core/driver.c
drivers/usb/core/generic.c
drivers/usb/core/quirks.c
drivers/usb/core/usb.h
drivers/usb/dwc2/platform.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/ep0.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/f_midi.c
drivers/usb/gadget/legacy/inode.c
drivers/usb/gadget/legacy/raw_gadget.c
drivers/usb/gadget/udc/fsl_udc_core.c
drivers/usb/gadget/udc/goku_udc.c
drivers/usb/host/ehci-tegra.c
drivers/usb/host/fsl-mph-dr-of.c
drivers/usb/host/ohci-omap.c
drivers/usb/host/xhci-histb.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/apple-mfi-fastcharge.c
drivers/usb/mtu3/mtu3_gadget.c
drivers/usb/musb/musb_dsps.c
drivers/usb/serial/ch341.c
drivers/usb/serial/cyberjack.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/option.c
drivers/usb/storage/scsiglue.c
drivers/usb/storage/uas.c
drivers/usb/storage/usb.c
drivers/usb/typec/Kconfig
drivers/usb/typec/mux.c
drivers/usb/typec/stusb160x.c
drivers/usb/typec/tcpm/tcpm.c
drivers/usb/typec/ucsi/psy.c
drivers/usb/typec/ucsi/ucsi.c
drivers/usb/typec/ucsi/ucsi.h
drivers/vdpa/Kconfig
drivers/vdpa/mlx5/core/mr.c
drivers/vdpa/vdpa_sim/vdpa_sim.c
drivers/vfio/fsl-mc/vfio_fsl_mc.c
drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c
drivers/vfio/pci/vfio_pci.c
drivers/vfio/pci/vfio_pci_rdwr.c
drivers/vfio/platform/vfio_platform_common.c
drivers/vfio/vfio_iommu_type1.c
drivers/vhost/scsi.c
drivers/vhost/vdpa.c
drivers/vhost/vhost.c
drivers/vhost/vhost.h
drivers/vhost/vringh.c
drivers/video/fbdev/hyperv_fb.c
drivers/virt/nitro_enclaves/ne_misc_dev.c
drivers/xen/swiotlb-xen.c
fs/9p/vfs_file.c
fs/afs/cell.c
fs/afs/dir.c
fs/afs/dir_edit.c
fs/afs/file.c
fs/afs/inode.c
fs/afs/internal.h
fs/afs/write.c
fs/afs/xattr.c
fs/afs/yfsclient.c
fs/aio.c
fs/binfmt_elf.c
fs/btrfs/backref.c
fs/btrfs/block-group.c
fs/btrfs/block-rsv.c
fs/btrfs/ctree.h
fs/btrfs/dev-replace.c
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/qgroup.c
fs/btrfs/reada.c
fs/btrfs/ref-verify.c
fs/btrfs/relocation.c
fs/btrfs/scrub.c
fs/btrfs/tests/inode-tests.c
fs/btrfs/tree-checker.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/cachefiles/rdwr.c
fs/ceph/caps.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/quota.c
fs/ceph/snap.c
fs/cifs/cifsacl.c
fs/cifs/connect.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h
fs/cifs/transport.c
fs/coredump.c
fs/crypto/inline_crypt.c
fs/crypto/keysetup.c
fs/debugfs/file.c
fs/efivarfs/inode.c
fs/erofs/inode.c
fs/erofs/zdata.c
fs/ext4/dir.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/fast_commit.c
fs/ext4/fast_commit.h
fs/ext4/file.c
fs/ext4/fsmap.c
fs/ext4/fsync.c
fs/ext4/hash.c
fs/ext4/inline.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/namei.c
fs/ext4/super.c
fs/ext4/sysfs.c
fs/gfs2/aops.c
fs/gfs2/bmap.c
fs/gfs2/glock.c
fs/gfs2/glops.c
fs/gfs2/glops.h
fs/gfs2/incore.h
fs/gfs2/inode.c
fs/gfs2/log.c
fs/gfs2/lops.c
fs/gfs2/lops.h
fs/gfs2/ops_fstype.c
fs/gfs2/recovery.c
fs/gfs2/rgrp.c
fs/gfs2/super.c
fs/hfs/btree.h
fs/hfsplus/hfsplus_fs.h
fs/io-wq.c
fs/io_uring.c
fs/iomap/buffered-io.c
fs/isofs/rock.h
fs/jbd2/checkpoint.c
fs/jbd2/commit.c
fs/jbd2/journal.c
fs/jbd2/recovery.c
fs/jbd2/transaction.c
fs/libfs.c
fs/nfs/dir.c
fs/nfs/nfs42xattr.c
fs/nfs/nfs42xdr.c
fs/nfs/nfsroot.c
fs/nfsd/nfs3proc.c
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs4proc.c
fs/notify/fsnotify.c
fs/ocfs2/journal.c
fs/ocfs2/super.c
fs/proc/base.c
fs/proc/cpuinfo.c
fs/proc/generic.c
fs/proc/inode.c
fs/proc/self.c
fs/proc/stat.c
fs/select.c
fs/seq_file.c
fs/super.c
fs/xfs/libxfs/xfs_alloc.c
fs/xfs/libxfs/xfs_attr_leaf.c
fs/xfs/libxfs/xfs_bmap.h
fs/xfs/libxfs/xfs_rmap.c
fs/xfs/scrub/bmap.c
fs/xfs/scrub/btree.c
fs/xfs/scrub/dir.c
fs/xfs/scrub/inode.c
fs/xfs/scrub/refcount.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_iwalk.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_pnfs.c
fs/xfs/xfs_reflink.c
include/asm-generic/barrier.h
include/asm-generic/percpu.h
include/asm-generic/uaccess.h
include/asm-generic/vmlinux.lds.h
include/drm/drm_dp_helper.h
include/drm/drm_edid.h
include/drm/drm_print.h
include/kunit/test.h
include/linux/arm-smccc.h
include/linux/blk-mq.h
include/linux/blkdev.h
include/linux/bootconfig.h
include/linux/can/skb.h
include/linux/compiler-clang.h
include/linux/compiler-gcc.h
include/linux/compiler.h
include/linux/compiler_types.h
include/linux/cpufreq.h
include/linux/debugfs.h
include/linux/dma/ti-cppi5.h
include/linux/edac.h
include/linux/filter.h
include/linux/firmware/xlnx-zynqmp.h
include/linux/fs.h
include/linux/genhd.h
include/linux/intel-iommu.h
include/linux/io_uring.h
include/linux/iomap.h
include/linux/irqdomain.h
include/linux/jbd2.h
include/linux/jhash.h
include/linux/mailbox/zynqmp-ipi-message.h
include/linux/memcontrol.h
include/linux/memory_hotplug.h
include/linux/mic_bus.h [deleted file]
include/linux/mlx5/driver.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mm.h
include/linux/module.h
include/linux/netdevice.h
include/linux/netfilter/nfnetlink.h
include/linux/netfilter_ipv4.h
include/linux/netfilter_ipv6.h
include/linux/numa.h
include/linux/pagemap.h
include/linux/perf_event.h
include/linux/perf_regs.h
include/linux/pgtable.h
include/linux/phy.h
include/linux/platform_data/cros_ec_commands.h
include/linux/platform_data/cros_ec_proto.h
include/linux/platform_data/ti-sysc.h
include/linux/pm_runtime.h
include/linux/refcount.h
include/linux/sched.h
include/linux/scif.h [deleted file]
include/linux/seq_file.h
include/linux/signal.h
include/linux/spi/spi.h
include/linux/swiotlb.h
include/linux/time64.h
include/linux/tty.h
include/linux/usb/composite.h
include/linux/vdpa.h
include/linux/zsmalloc.h
include/net/bonding.h
include/net/cfg80211.h
include/net/inet_ecn.h
include/net/inet_hashtables.h
include/net/ip_tunnels.h
include/net/ipv6_frag.h
include/net/mac80211.h
include/net/neighbour.h
include/net/netfilter/nf_tables_offload.h
include/net/tls.h
include/net/xdp_sock.h
include/net/xsk_buff_pool.h
include/rdma/rdma_cm.h
include/scsi/libiscsi.h
include/sound/control.h
include/sound/core.h
include/sound/pcm.h
include/sound/rt1015.h [new file with mode: 0644]
include/trace/events/afs.h
include/trace/events/ext4.h
include/trace/events/sunrpc.h
include/trace/events/writeback.h
include/uapi/linux/devlink.h
include/uapi/linux/gpio.h
include/uapi/linux/icmpv6.h
include/uapi/linux/mic_common.h [deleted file]
include/uapi/linux/mic_ioctl.h [deleted file]
include/uapi/linux/openvswitch.h
include/uapi/linux/stat.h
include/uapi/linux/vhost.h
include/uapi/linux/vhost_types.h
include/uapi/sound/compress_offload.h
include/video/imx-ipu-v3.h
init/Kconfig
init/main.c
kernel/bpf/Makefile
kernel/bpf/bpf_lsm.c
kernel/bpf/core.c
kernel/bpf/hashtab.c
kernel/bpf/preload/Kconfig
kernel/bpf/verifier.c
kernel/cpu.c
kernel/dma/swiotlb.c
kernel/entry/common.c
kernel/events/core.c
kernel/events/internal.h
kernel/events/ring_buffer.c
kernel/exit.c
kernel/fail_function.c
kernel/fork.c
kernel/futex.c
kernel/hung_task.c
kernel/irq/Kconfig
kernel/irq/irqdomain.c
kernel/kprobes.c
kernel/kthread.c
kernel/locking/lockdep.c
kernel/panic.c
kernel/params.c
kernel/power/process.c
kernel/printk/printk.c
kernel/printk/printk_ringbuffer.c
kernel/ptrace.c
kernel/rcu/tree.c
kernel/rcu/tree_stall.h
kernel/reboot.c
kernel/sched/core.c
kernel/sched/cpufreq_schedutil.c
kernel/sched/deadline.c
kernel/sched/debug.c
kernel/sched/fair.c
kernel/sched/idle.c
kernel/seccomp.c
kernel/signal.c
kernel/stop_machine.c
kernel/time/hrtimer.c
kernel/time/itimer.c
kernel/time/sched_clock.c
kernel/time/timer.c
kernel/trace/Kconfig
kernel/trace/bpf_trace.c
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_events_synth.c
kernel/trace/trace_hwlat.c
kernel/trace/trace_selftest.c
kernel/tracepoint.c
kernel/watchdog.c
lib/Kconfig.debug
lib/crc32test.c
lib/fonts/font_10x18.c
lib/fonts/font_6x10.c
lib/fonts/font_6x11.c
lib/fonts/font_6x8.c
lib/fonts/font_7x14.c
lib/fonts/font_8x16.c
lib/fonts/font_8x8.c
lib/fonts/font_acorn_8x8.c
lib/fonts/font_mini_4x6.c
lib/fonts/font_pearl_8x8.c
lib/fonts/font_sun12x22.c
lib/fonts/font_sun8x16.c
lib/fonts/font_ter16x32.c
lib/scatterlist.c
lib/strncpy_from_user.c
lib/syscall.c
lib/test_kasan.c
lib/zlib_dfltcc/dfltcc_inflate.c
mm/Kconfig
mm/compaction.c
mm/filemap.c
mm/gup.c
mm/huge_memory.c
mm/hugetlb.c
mm/hugetlb_cgroup.c
mm/list_lru.c
mm/madvise.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/memremap.c
mm/migrate.c
mm/mmap.c
mm/page-writeback.c
mm/page_alloc.c
mm/percpu.c
mm/process_vm_access.c
mm/rmap.c
mm/slab.h
mm/slub.c
mm/swapfile.c
mm/truncate.c
mm/vmscan.c
mm/zsmalloc.c
net/atm/lec.c
net/batman-adv/fragmentation.c
net/batman-adv/hard-interface.c
net/batman-adv/log.c
net/bluetooth/msft.c
net/bridge/br_device.c
net/bridge/br_netfilter_hooks.c
net/can/Kconfig
net/can/af_can.c
net/can/isotp.c
net/can/j1939/socket.c
net/can/proc.c
net/core/dev.c
net/core/devlink.c
net/core/gro_cells.c
net/core/neighbour.c
net/core/netpoll.c
net/core/skbuff.c
net/core/skmsg.c
net/dccp/ipv4.c
net/dccp/ipv6.c
net/ethtool/features.c
net/ipv4/arp.c
net/ipv4/fib_frontend.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_diag.c
net/ipv4/inet_hashtables.c
net/ipv4/ip_tunnel.c
net/ipv4/ip_tunnel_core.c
net/ipv4/netfilter.c
net/ipv4/netfilter/iptable_mangle.c
net/ipv4/netfilter/nf_reject_ipv4.c
net/ipv4/route.c
net/ipv4/syncookies.c
net/ipv4/tcp.c
net/ipv4/tcp_bbr.c
net/ipv4/tcp_bpf.c
net/ipv4/tcp_cong.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp_offload.c
net/ipv4/xfrm4_tunnel.c
net/ipv6/addrconf.c
net/ipv6/addrlabel.c
net/ipv6/ah6.c
net/ipv6/icmp.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/ndisc.c
net/ipv6/netfilter.c
net/ipv6/netfilter/ip6table_mangle.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/reassembly.c
net/ipv6/sit.c
net/ipv6/syncookies.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp_offload.c
net/ipv6/xfrm6_tunnel.c
net/iucv/af_iucv.c
net/mac80211/mlme.c
net/mac80211/rc80211_minstrel.c
net/mac80211/rc80211_minstrel.h
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/status.c
net/mac80211/tx.c
net/mptcp/protocol.c
net/mptcp/subflow.c
net/mptcp/token.c
net/ncsi/ncsi-manage.c
net/ncsi/ncsi-netlink.c
net/ncsi/ncsi-netlink.h
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/nf_nat_proto.c
net/netfilter/nf_synproxy_core.c
net/netfilter/nf_tables_api.c
net/netfilter/nf_tables_offload.c
net/netfilter/nfnetlink.c
net/netfilter/nft_chain_route.c
net/netfilter/nft_cmp.c
net/netfilter/nft_meta.c
net/netfilter/nft_payload.c
net/netfilter/utils.c
net/netlabel/netlabel_unlabeled.c
net/openvswitch/actions.c
net/openvswitch/datapath.c
net/openvswitch/flow_netlink.c
net/openvswitch/flow_table.c
net/packet/af_packet.c
net/rds/ib_cm.c
net/rfkill/core.c
net/rose/rose_loopback.c
net/sched/act_mpls.c
net/sched/cls_api.c
net/sched/sch_netem.c
net/sctp/input.c
net/sctp/sm_sideeffect.c
net/sctp/transport.c
net/smc/af_smc.c
net/smc/smc_clc.h
net/smc/smc_core.c
net/smc/smc_ib.c
net/sunrpc/sysctl.c
net/tipc/msg.c
net/tipc/node.c
net/tipc/topsrv.c
net/tls/tls_device.c
net/tls/tls_sw.c
net/vmw_vsock/af_vsock.c
net/vmw_vsock/virtio_transport_common.c
net/wireless/core.c
net/wireless/core.h
net/wireless/nl80211.c
net/wireless/reg.c
net/x25/af_x25.c
net/xdp/xdp_umem.c
net/xdp/xdp_umem.h
net/xdp/xsk.c
net/xdp/xsk_buff_pool.c
net/xfrm/xfrm_interface.c
net/xfrm/xfrm_state.c
samples/bpf/task_fd_query_user.c
samples/bpf/tracex2_user.c
samples/bpf/tracex3_user.c
samples/bpf/xdp_redirect_cpu_user.c
samples/bpf/xdp_rxq_info_user.c
samples/ftrace/ftrace-direct-modify.c
samples/ftrace/ftrace-direct-too.c
samples/ftrace/ftrace-direct.c
samples/mic/mpssd/.gitignore [deleted file]
samples/mic/mpssd/Makefile [deleted file]
samples/mic/mpssd/micctrl [deleted file]
samples/mic/mpssd/mpss [deleted file]
samples/mic/mpssd/mpssd.c [deleted file]
samples/mic/mpssd/mpssd.h [deleted file]
samples/mic/mpssd/sysfs.c [deleted file]
scripts/Makefile.build
scripts/Makefile.extrawarn
scripts/bpf_helpers_doc.py
scripts/get_abi.pl
scripts/kernel-doc
scripts/lld-version.sh [new file with mode: 0755]
scripts/package/builddeb
security/integrity/ima/ima.h
security/selinux/ibpkey.c
sound/core/control.c
sound/core/pcm_dmaengine.c
sound/core/pcm_lib.c
sound/core/pcm_native.c
sound/firewire/fireworks/fireworks_transaction.c
sound/hda/ext/hdac_ext_controller.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_controller.h
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_generic.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/mixart/mixart_core.c
sound/soc/atmel/mchp-spdiftx.c
sound/soc/codecs/cs42l51.c
sound/soc/codecs/rt1015.c
sound/soc/codecs/rt1015.h
sound/soc/codecs/rt5682.c
sound/soc/codecs/wcd9335.c
sound/soc/codecs/wcd934x.c
sound/soc/codecs/wm_adsp.c
sound/soc/codecs/wsa881x.c
sound/soc/intel/Kconfig
sound/soc/intel/atom/Makefile
sound/soc/intel/atom/sst/Makefile
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/intel/boards/kbl_rt5663_max98927.c
sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
sound/soc/intel/catpt/dsp.c
sound/soc/intel/catpt/pcm.c
sound/soc/intel/keembay/kmb_platform.c
sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
sound/soc/qcom/lpass-cpu.c
sound/soc/qcom/lpass-lpaif-reg.h
sound/soc/qcom/lpass-platform.c
sound/soc/qcom/lpass-sc7180.c
sound/soc/qcom/lpass.h
sound/soc/qcom/sdm845.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/sof/loader.c
sound/usb/card.c
sound/usb/mixer_maps.c
sound/usb/mixer_us16x08.c
sound/usb/pcm.c
sound/usb/quirks.c
tools/arch/arm64/include/uapi/asm/kvm.h
tools/arch/s390/include/uapi/asm/sie.h
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/asm/disabled-features.h
tools/arch/x86/include/asm/insn.h
tools/arch/x86/include/asm/msr-index.h
tools/arch/x86/include/asm/required-features.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/arch/x86/include/uapi/asm/svm.h
tools/arch/x86/lib/memcpy_64.S
tools/arch/x86/lib/memset_64.S
tools/bootconfig/main.c
tools/bootconfig/test-bootconfig.sh
tools/bpf/bpftool/btf.c
tools/bpf/bpftool/feature.c
tools/bpf/bpftool/net.c
tools/bpf/bpftool/prog.c
tools/bpf/bpftool/skeleton/profiler.bpf.c
tools/build/feature/test-all.c
tools/include/linux/compiler-gcc.h
tools/include/linux/compiler.h
tools/include/uapi/asm-generic/unistd.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/fscrypt.h
tools/include/uapi/linux/kvm.h
tools/include/uapi/linux/mman.h
tools/include/uapi/linux/mount.h
tools/include/uapi/linux/perf_event.h
tools/include/uapi/linux/prctl.h
tools/include/uapi/linux/vhost.h
tools/lib/bpf/Makefile
tools/lib/bpf/hashmap.h
tools/lib/bpf/libbpf.c
tools/lib/bpf/xsk.c
tools/perf/Makefile.config
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
tools/perf/arch/x86/tests/dwarf-unwind.c
tools/perf/bench/mem-memcpy-x86-64-asm.S
tools/perf/bench/mem-memset-x86-64-asm.S
tools/perf/builtin-diff.c
tools/perf/builtin-inject.c
tools/perf/builtin-lock.c
tools/perf/builtin-trace.c
tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json
tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json
tools/perf/tests/dwarf-unwind.c
tools/perf/tests/shell/test_arm_coresight.sh
tools/perf/ui/browsers/hists.c
tools/perf/util/build-id.c
tools/perf/util/dwarf-aux.c
tools/perf/util/hashmap.c
tools/perf/util/hashmap.h
tools/perf/util/include/linux/linkage.h
tools/perf/util/machine.c
tools/perf/util/probe-finder.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/session.c
tools/perf/util/stat-display.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/synthetic-events.c
tools/power/x86/turbostat/Makefile
tools/power/x86/turbostat/turbostat.8
tools/power/x86/turbostat/turbostat.c
tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
tools/testing/kunit/.gitattributes [deleted file]
tools/testing/kunit/kunit.py
tools/testing/kunit/kunit_kernel.py
tools/testing/kunit/kunit_parser.py
tools/testing/kunit/kunit_tool_test.py
tools/testing/kunit/test_data/test_config_printk_time.log
tools/testing/kunit/test_data/test_interrupted_tap_output.log
tools/testing/kunit/test_data/test_kernel_panic_interrupt.log
tools/testing/kunit/test_data/test_multiple_prefixes.log
tools/testing/kunit/test_data/test_pound_no_prefix.log
tools/testing/kunit/test_data/test_pound_sign.log
tools/testing/scatterlist/linux/mm.h
tools/testing/scatterlist/main.c
tools/testing/selftests/arm64/mte/check_buffer_fill.c
tools/testing/selftests/arm64/mte/check_child_memory.c
tools/testing/selftests/arm64/mte/check_ksm_options.c
tools/testing/selftests/arm64/mte/check_mmap_options.c
tools/testing/selftests/arm64/mte/check_tags_inclusion.c
tools/testing/selftests/arm64/mte/check_user_mem.c
tools/testing/selftests/bpf/prog_tests/map_init.c [new file with mode: 0644]
tools/testing/selftests/bpf/prog_tests/probe_read_user_str.c [new file with mode: 0644]
tools/testing/selftests/bpf/prog_tests/sockopt_multi.c
tools/testing/selftests/bpf/prog_tests/subprogs.c
tools/testing/selftests/bpf/prog_tests/test_global_funcs.c
tools/testing/selftests/bpf/progs/profiler.inc.h
tools/testing/selftests/bpf/progs/test_global_func8.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/test_map_init.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/test_probe_read_user_str.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/test_subprogs_unused.c [new file with mode: 0644]
tools/testing/selftests/clone3/clone3_cap_checkpoint_restore.c
tools/testing/selftests/core/close_range_test.c
tools/testing/selftests/filesystems/binderfs/binderfs_test.c
tools/testing/selftests/filesystems/epoll/epoll_wakeup_test.c
tools/testing/selftests/ftrace/test.d/dynevent/add_remove_kprobe.tc
tools/testing/selftests/ftrace/test.d/dynevent/clear_select_events.tc
tools/testing/selftests/ftrace/test.d/dynevent/generic_clear_event.tc
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-notrace-pid.tc
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-pid.tc
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-stacktrace.tc
tools/testing/selftests/ftrace/test.d/functions
tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc
tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_comm.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_symbol.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_user.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_multiprobe.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc
tools/testing/selftests/ftrace/test.d/kprobe/profile.tc
tools/testing/selftests/kselftest_harness.h
tools/testing/selftests/kvm/.gitignore
tools/testing/selftests/kvm/Makefile
tools/testing/selftests/kvm/aarch64/get-reg-list-sve.c [new file with mode: 0644]
tools/testing/selftests/kvm/aarch64/get-reg-list.c [new file with mode: 0644]
tools/testing/selftests/kvm/clear_dirty_log_test.c [deleted file]
tools/testing/selftests/kvm/demand_paging_test.c
tools/testing/selftests/kvm/dirty_log_perf_test.c [new file with mode: 0644]
tools/testing/selftests/kvm/dirty_log_test.c
tools/testing/selftests/kvm/include/kvm_util.h
tools/testing/selftests/kvm/include/perf_test_util.h [new file with mode: 0644]
tools/testing/selftests/kvm/include/test_util.h
tools/testing/selftests/kvm/include/x86_64/processor.h
tools/testing/selftests/kvm/include/x86_64/vmx.h
tools/testing/selftests/kvm/lib/aarch64/processor.c
tools/testing/selftests/kvm/lib/aarch64/ucall.c
tools/testing/selftests/kvm/lib/kvm_util.c
tools/testing/selftests/kvm/lib/kvm_util_internal.h
tools/testing/selftests/kvm/lib/s390x/processor.c
tools/testing/selftests/kvm/lib/s390x/ucall.c
tools/testing/selftests/kvm/lib/test_util.c
tools/testing/selftests/kvm/lib/x86_64/handlers.S [new file with mode: 0644]
tools/testing/selftests/kvm/lib/x86_64/processor.c
tools/testing/selftests/kvm/lib/x86_64/ucall.c
tools/testing/selftests/kvm/lib/x86_64/vmx.c
tools/testing/selftests/kvm/x86_64/kvm_pv_test.c [new file with mode: 0644]
tools/testing/selftests/kvm/x86_64/vmx_apic_access_test.c [new file with mode: 0644]
tools/testing/selftests/lib.mk
tools/testing/selftests/pidfd/config
tools/testing/selftests/pidfd/pidfd_getfd_test.c
tools/testing/selftests/pidfd/pidfd_open_test.c
tools/testing/selftests/pidfd/pidfd_poll_test.c
tools/testing/selftests/pidfd/pidfd_setns_test.c
tools/testing/selftests/pidfd/pidfd_test.c
tools/testing/selftests/powerpc/include/utils.h
tools/testing/selftests/powerpc/security/.gitignore
tools/testing/selftests/powerpc/security/Makefile
tools/testing/selftests/powerpc/security/entry_flush.c [new file with mode: 0644]
tools/testing/selftests/powerpc/security/flush_utils.c [new file with mode: 0644]
tools/testing/selftests/powerpc/security/flush_utils.h [new file with mode: 0644]
tools/testing/selftests/powerpc/security/rfi_flush.c
tools/testing/selftests/proc/proc-loadavg-001.c
tools/testing/selftests/proc/proc-self-syscall.c
tools/testing/selftests/proc/proc-uptime-002.c
tools/testing/selftests/seccomp/seccomp_bpf.c
tools/testing/selftests/tc-testing/config
tools/testing/selftests/tc-testing/tc-tests/filters/tests.json
tools/testing/selftests/vm/Makefile
tools/testing/selftests/vm/userfaultfd.c
tools/testing/selftests/wireguard/netns.sh
tools/testing/selftests/wireguard/qemu/kernel.config

index 1e14566a3d56c14106f3e2aea1a5b935ffd45eba..225546cc80288a5b3af81251d3e39c8efd3a0926 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -82,7 +82,10 @@ Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@gmail.com>
 Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@imgtec.com>
 Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@mips.com>
 <dev.kurt@vandijck-laurijssen.be> <kurt.van.dijck@eia.be>
-Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+Dmitry Baryshkov <dbaryshkov@gmail.com>
+Dmitry Baryshkov <dbaryshkov@gmail.com> <[dbaryshkov@gmail.com]>
+Dmitry Baryshkov <dbaryshkov@gmail.com> <dmitry_baryshkov@mentor.com>
+Dmitry Baryshkov <dbaryshkov@gmail.com> <dmitry_eremin@mentor.com>
 Dmitry Safonov <0x7f454c46@gmail.com> <dima@arista.com>
 Dmitry Safonov <0x7f454c46@gmail.com> <d.safonov@partner.samsung.com>
 Dmitry Safonov <0x7f454c46@gmail.com> <dsafonov@virtuozzo.com>
@@ -287,6 +290,7 @@ Santosh Shilimkar <ssantosh@kernel.org>
 Sarangdhar Joshi <spjoshi@codeaurora.org>
 Sascha Hauer <s.hauer@pengutronix.de>
 S.ÇaÄŸlar Onur <caglar@pardus.org.tr>
+Sean Christopherson <seanjc@google.com> <sean.j.christopherson@intel.com>
 Sean Nyekjaer <sean@geanix.com> <sean.nyekjaer@prevas.dk>
 Sebastian Reichel <sre@kernel.org> <sebastian.reichel@collabora.co.uk>
 Sebastian Reichel <sre@kernel.org> <sre@debian.org>
@@ -318,6 +322,8 @@ TripleX Chung <xxx.phy@gmail.com> <zhongyu@18mail.cn>
 Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
 Tycho Andersen <tycho@tycho.pizza> <tycho@tycho.ws>
 Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
+Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Uwe Kleine-König <ukleinek@strlen.de>
 Uwe Kleine-König <ukl@pengutronix.de>
 Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
 Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
diff --git a/CREDITS b/CREDITS
index cb02b9923a5261769e0b8f1b92713575c480b3ac..e88d1a783a80f8c36293f5f1fed436afd2735c14 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -98,7 +98,7 @@ N: Erik Andersen
 E: andersen@codepoet.org
 W: https://www.codepoet.org/
 P: 1024D/30D39057 1BC4 2742 E885 E4DE 9301  0C82 5F9B 643E 30D3 9057
-D: Maintainer of ide-cd and Uniform CD-ROM driver, 
+D: Maintainer of ide-cd and Uniform CD-ROM driver,
 D: ATAPI CD-Changer support, Major 2.1.x CD-ROM update.
 S: 352 North 525 East
 S: Springville, Utah 84663
@@ -263,7 +263,7 @@ N: Paul Barton-Davis
 E: pbd@op.net
 D: Driver for WaveFront soundcards (Turtle Beach Maui, Tropez, Tropez+)
 D: Various bugfixes and changes to sound drivers
-S: USA 
+S: USA
 
 N: Carlos Henrique Bauer
 E: chbauer@acm.org
@@ -740,6 +740,11 @@ S: (ask for current address)
 S: Portland, Oregon
 S: USA
 
+N: Jason Cooper
+D: ARM/Marvell SOC co-maintainer
+D: irqchip co-maintainer
+D: MVEBU PCI DRIVER co-maintainer
+
 N: Robin Cornelius
 E: robincornelius@users.sourceforge.net
 D: Ralink rt2x00 WLAN driver
@@ -849,6 +854,12 @@ D: trivial hack to add variable address length routing to Rose.
 D: AX25-HOWTO, HAM-HOWTO, IPX-HOWTO, NET-2-HOWTO
 D: ax25-utils maintainer.
 
+N: Kamil Debski
+E: kamil@wypas.org
+D: Samsung S5P 2D graphics acceleration and Multi Format Codec drivers
+D: Samsung USB2 phy drivers
+D: PWM fan driver
+
 N: Helge Deller
 E: deller@gmx.de
 W: http://www.parisc-linux.org/
@@ -1199,7 +1210,7 @@ N: Daniel J. Frasnelli
 E: dfrasnel@alphalinux.org
 W: http://www.alphalinux.org/
 P: 1024/3EF87611 B9 F1 44 50 D3 E8 C2 80  DA E5 55 AA 56 7C 42 DA
-D: DEC Alpha hacker 
+D: DEC Alpha hacker
 D: Miscellaneous bug squisher
 
 N: Jim Freeman
@@ -1299,7 +1310,7 @@ S: P.O. Box 76, Epping
 S: New South Wales, 2121
 S: Australia
 
-N: Carlos E. Gorges 
+N: Carlos E. Gorges
 E: carlos@techlinux.com.br
 D: fix smp support on cmpci driver
 P: 2048G/EA3C4B19 FF31 33A6 0362 4915 B7EB  E541 17D0 0379 EA3C 4B19
@@ -1340,7 +1351,7 @@ E: wgreathouse@smva.com
 E: wgreathouse@myfavoritei.com
 D: Current Belkin USB Serial Adapter F5U103 hacker
 D: Kernel hacker, embedded systems
-S: 7802 Fitzwater Road   
+S: 7802 Fitzwater Road
 S: Brecksville, OH  44141-1334
 S: USA
 
@@ -1381,7 +1392,7 @@ N: Grant Guenther
 E: grant@torque.net
 W: http://www.torque.net/linux-pp.html
 D: original author of ppa driver for parallel port ZIP drive
-D: original architect of the parallel-port sharing scheme 
+D: original architect of the parallel-port sharing scheme
 D: PARIDE subsystem: drivers for parallel port IDE & ATAPI devices
 S: 44 St. Joseph Street, Suite 506
 S: Toronto, Ontario, M4Y 2W4
@@ -1523,7 +1534,7 @@ N: Benjamin Herrenschmidt
 E: benh@kernel.crashing.org
 D: Various parts of PPC/PPC64 & PowerMac
 S: 312/107 Canberra Avenue
-S: Griffith, ACT 2603 
+S: Griffith, ACT 2603
 S: Australia
 
 N: Andreas Herrmann
@@ -1825,7 +1836,7 @@ S: Hungary
 N: Bernhard Kaindl
 E: bkaindl@netway.at
 E: edv@bartelt.via.at
-D: Author of a menu based configuration tool, kmenu, which 
+D: Author of a menu based configuration tool, kmenu, which
 D: is the predecessor of 'make menuconfig' and 'make xconfig'.
 D: digiboard driver update(modularisation work and 2.1.x upd)
 S: Tallak 95
@@ -1910,6 +1921,15 @@ S: 660 Harvard Ave. #7
 S: Santa Clara, CA 95051
 S: USA
 
+N: Kukjin Kim
+E: kgene@kernel.org
+D: Samsung S3C, S5P and Exynos ARM architectures
+
+N: Sangbeom Kim
+E: sbkim73@samsung.com
+D: Samsung SoC Audio (ASoC) drivers
+D: Samsung PMIC (RTC, regulators, MFD) drivers
+
 N: Russell King
 E: rmk@arm.linux.org.uk
 D: Linux/arm integrator, maintainer & hacker
@@ -2007,7 +2027,7 @@ W: http://www.xos.nl/
 D: IP transparent proxy support
 S: X/OS Experts in Open Systems BV
 S: Kruislaan 419
-S: 1098 VA Amsterdam 
+S: 1098 VA Amsterdam
 S: The Netherlands
 
 N: Goran Koruga
@@ -2079,7 +2099,7 @@ S: Germany
 
 N: Andrzej M. Krzysztofowicz
 E: ankry@mif.pg.gda.pl
-D: Some 8-bit XT disk driver and devfs hacking 
+D: Some 8-bit XT disk driver and devfs hacking
 D: Aladdin 1533/1543(C) chipset IDE
 D: PIIX chipset IDE
 S: ul. Matemblewska 1B/10
@@ -2454,7 +2474,7 @@ E: mge@EZ-Darmstadt.Telekom.de
 D: Logical Volume Manager
 S: Bartningstr. 12
 S: 64289 Darmstadt
-S: Germany 
+S: Germany
 
 N: Mark W. McClelland
 E: mmcclell@bigfoot.com
@@ -2538,7 +2558,7 @@ E: meskes@debian.org
 P: 1024/04B6E8F5 6C 77 33 CA CC D6 22 03  AB AB 15 A3 AE AD 39 7D
 D: Kernel hacker. PostgreSQL hacker. Software watchdog daemon.
 D: Maintainer of several Debian packages
-S: Th.-Heuss-Str. 61 
+S: Th.-Heuss-Str. 61
 S: D-41812 Erkelenz
 S: Germany
 
@@ -2776,7 +2796,7 @@ E: neuffer@goofy.zdv.uni-mainz.de
 W: http://www.i-Connect.Net/~mike/
 D: Developer and maintainer of the EATA-DMA SCSI driver
 D: Co-developer EATA-PIO SCSI driver
-D: /proc/scsi and assorted other snippets 
+D: /proc/scsi and assorted other snippets
 S: Zum Schiersteiner Grund 2
 S: 55127 Mainz
 S: Germany
@@ -2843,6 +2863,10 @@ D: IPX development and support
 N: Venkatesh Pallipadi (Venki)
 D: x86/HPET
 
+N: Kyungmin Park
+E: kyungmin.park@samsung.com
+D: Samsung S5Pv210 and Exynos4210 mobile platforms
+
 N: David Parsons
 E: orc@pell.chi.il.us
 D: improved memory detection code.
@@ -3010,7 +3034,7 @@ D: Embedded PowerPC 4xx/6xx/7xx/74xx support
 S: Chandler, Arizona 85249
 S: USA
 
-N: Frederic Potter 
+N: Frederic Potter
 E: fpotter@cirpack.com
 D: Some PCI kernel support
 
@@ -3443,21 +3467,21 @@ S: Klosterweg 28 / i309
 S: 76131 Karlsruhe
 S: Germany
 
-N: James Simmons 
+N: James Simmons
 E: jsimmons@infradead.org
-E: jsimmons@users.sf.net 
+E: jsimmons@users.sf.net
 D: Frame buffer device maintainer
 D: input layer development
 D: tty/console layer
-D: various mipsel devices 
-S: 115 Carmel Avenue 
+D: various mipsel devices
+S: 115 Carmel Avenue
 S: El Cerrito CA 94530
-S: USA 
+S: USA
 
 N: Jaspreet Singh
 E: jaspreet@sangoma.com
 W: www.sangoma.com
-D: WANPIPE drivers & API Support for Sangoma S508/FT1 cards 
+D: WANPIPE drivers & API Support for Sangoma S508/FT1 cards
 S: Sangoma Technologies Inc.,
 S: 1001 Denison Street
 S: Suite 101
@@ -3481,7 +3505,7 @@ N: Craig Small
 E: csmall@triode.apana.org.au
 E: vk2xlz@gonzo.vk2xlz.ampr.org (packet radio)
 D: Gracilis PackeTwin device driver
-D: RSPF daemon 
+D: RSPF daemon
 S: 10 Stockalls Place
 S: Minto, NSW, 2566
 S: Australia
@@ -3691,7 +3715,7 @@ N: Tsu-Sheng Tsao
 E: tsusheng@scf.usc.edu
 D: IGMP(Internet Group Management Protocol) version 2
 S: 2F 14 ALY 31 LN 166 SEC 1 SHIH-PEI RD
-S: Taipei 
+S: Taipei
 S: Taiwan 112
 S: Republic of China
 S: 24335 Delta Drive
@@ -3852,7 +3876,7 @@ D: Produced the Slackware distribution, updated the SVGAlib
 D: patches for ghostscript, worked on color 'ls', etc.
 S: 301 15th Street S.
 S: Moorhead, Minnesota 56560
-S: USA 
+S: USA
 
 N: Jos Vos
 E: jos@xos.nl
@@ -3860,7 +3884,7 @@ W: http://www.xos.nl/
 D: Various IP firewall updates, ipfwadm
 S: X/OS Experts in Open Systems BV
 S: Kruislaan 419
-S: 1098 VA Amsterdam 
+S: 1098 VA Amsterdam
 S: The Netherlands
 
 N: Jeroen Vreeken
@@ -4098,7 +4122,7 @@ S: People's Repulic of China
 N: Victor Yodaiken
 E: yodaiken@fsmlabs.com
 D: RTLinux (RealTime Linux)
-S: POB 1822 
+S: POB 1822
 S: Socorro NM, 87801
 S: USA
 
@@ -4196,7 +4220,7 @@ D: EISA/sysfs subsystem
 S: France
 
 # Don't add your name here, unless you really _are_ after Marc
-# alphabetically. Leonard used to be very proud of being the 
+# alphabetically. Leonard used to be very proud of being the
 # last entry, and he'll get positively pissed if he can't even
 # be second-to-last.  (and this file really _is_ supposed to be
 # in alphabetic order)
index 3121029dce210f1fbc9d06a711af40546d8788dd..8bac9cb09a6de7a50f596abab38318368e592128 100644 (file)
@@ -32,7 +32,7 @@ The different levels of stability are:
        layout of the files below for details on how to do this.)
 
   obsolete/
-       This directory documents interfaces that are still remaining in
+       This directory documents interfaces that are still remaining in
        the kernel, but are marked to be removed at some later point in
        time.  The description of the interface will document the reason
        why it is obsolete and when it can be expected to be removed.
@@ -58,6 +58,14 @@ Users:               All users of this interface who wish to be notified when
                be changed further.
 
 
+Note:
+   The fields should be use a simple notation, compatible with ReST markup.
+   Also, the file **should not** have a top-level index, like::
+
+       ===
+       foo
+       ===
+
 How things move between levels:
 
 Interfaces in stable may move to obsolete, as long as the proper
index 2cb9fc5e8bd1420e5c82a11109a1867d98a95ba1..0faf1354cd054fd39d69120e5b8eb5b89723af7b 100644 (file)
@@ -8,11 +8,11 @@ Description:  Device DAX is the device-centric analogue of Filesystem
                system.  Device DAX is strict, precise and predictable.
                Specifically this interface:
 
-               1/ Guarantees fault granularity with respect to a given
-               page size (pte, pmd, or pud) set at configuration time.
+               1. Guarantees fault granularity with respect to a given
+                  page size (pte, pmd, or pud) set at configuration time.
 
-               2/ Enforces deterministic behavior by being strict about
-               what fault scenarios are supported.
+               2. Enforces deterministic behavior by being strict about
+                  what fault scenarios are supported.
 
                The /sys/class/dax/ interface enumerates all the
                device-dax instances in the system. The ABI is
index 5d41ebadf15e9250adb9a6d5258e21281b23870d..66545c587a64a8335ffe2cf939943de0e47d6d43 100644 (file)
@@ -7,10 +7,13 @@ Description:  It is possible to switch the cpi setting of the mouse with the
                setting reported by the mouse. This number has to be further
                processed to receive the real dpi value:
 
+               ===== ====
                VALUE DPI
+               ===== ====
                1     400
                2     800
                4     1600
+               ===== ====
 
                This file is readonly.
                Has never been used. If bookkeeping is done, it's done in userland tools.
index e0d4e5e2dd90a4dafb082b23ddec928497794f97..b8b0fd341c17975f1226e7ec424d5d033132be34 100644 (file)
@@ -13,6 +13,8 @@ Description:
   GPIOs are identified as they are inside the kernel, using integers in
   the range 0..INT_MAX.  See Documentation/admin-guide/gpio for more information.
 
+  ::
+
     /sys/class/gpio
        /export ... asks the kernel to export a GPIO to userspace
        /unexport ... to return a GPIO to the kernel
index 0020c49933c45ab0b61cd7e57fa9b4baa672d3c0..24fb35adf27753ea087990f7a421f21188744cfb 100644 (file)
@@ -5,6 +5,7 @@ Description:
        devfs has been unmaintained for a number of years, has unfixable
        races, contains a naming policy within the kernel that is
        against the LSB, and can be replaced by using udev.
+
        The files fs/devfs/*, include/linux/devfs_fs*.h were removed,
        along with the assorted devfs function calls throughout the
        kernel tree.
index ec333e67632266a935daa6e2124744c09caa8d77..9ec7ec4939203e3ba9b9f9a532e5d4b879f2e6b9 100644 (file)
@@ -7,6 +7,7 @@ Description:
        to implement sensible device security policies, and its low level
        of abstraction that required userspace clients to duplicate much
        of the kernel's ieee1394 core functionality.
+
        Replaced by /dev/fw*, i.e. the <linux/firewire-cdev.h> ABI of
        firewire-core.
 
index 9c08c7f98ffb145b1b46fe506b036ae7467cc188..f25174eafd55aecfeb3c3e49e653a0392ed6954e 100644 (file)
@@ -10,4 +10,4 @@ Description:  This file was deprecated because there no longer was a way to
                claim just control over a single rfkill instance.
                This file was scheduled to be removed in 2012, and was removed
                in 2016.
-Values:        0: Kernel handles events
+Values:                0: Kernel handles events
index c39c25aee77b13e6d92e46686000ac2d8978da51..1905d35a66198724489837b440503a5824231f0b 100644 (file)
@@ -8,6 +8,7 @@ Description:
        performance issues in its first generation.  Any video1394 user had
        to use raw1394 + libraw1394 too because video1394 did not provide
        asynchronous I/O for device discovery and configuration.
+
        Replaced by /dev/fw*, i.e. the <linux/firewire-cdev.h> ABI of
        firewire-core.
 
index f72ed653878a619c62720b17c8428ba208842170..261f85b1315497999c17dfeb2ec720114d62c9e0 100644 (file)
@@ -14,13 +14,17 @@ Description:
                Each /dev/fw* is associated with one IEEE 1394 node, which can
                be remote or local nodes.  Operations on a /dev/fw* file have
                different scope:
+
                  - The 1394 node which is associated with the file:
+
                          - Asynchronous request transmission
                          - Get the Configuration ROM
                          - Query node ID
                          - Query maximum speed of the path between this node
                            and local node
+
                  - The 1394 bus (i.e. "card") to which the node is attached to:
+
                          - Isochronous stream transmission and reception
                          - Asynchronous stream transmission and reception
                          - Asynchronous broadcast request transmission
@@ -31,7 +35,9 @@ Description:
                            manager
                          - Query cycle time
                          - Bus reset initiation, bus reset event reception
+
                  - All 1394 buses:
+
                          - Allocation of IEEE 1212 address ranges on the local
                            link layers, reception of inbound requests to such
                            an address range, asynchronous response transmission
@@ -43,6 +49,7 @@ Description:
                userland implement different access permission models, some
                operations are restricted to /dev/fw* files that are associated
                with a local node:
+
                          - Addition of descriptors or directories to the local
                            nodes' Configuration ROM
                          - PHY packet transmission and reception
@@ -55,50 +62,50 @@ Description:
                The following file operations are supported:
 
                open(2)
-               Currently the only useful flags are O_RDWR.
+                   Currently the only useful flags are O_RDWR.
 
                ioctl(2)
-               Initiate various actions.  Some take immediate effect, others
-               are performed asynchronously while or after the ioctl returns.
-               See the inline documentation in <linux/firewire-cdev.h> for
-               descriptions of all ioctls.
+                   Initiate various actions.  Some take immediate effect, others
+                   are performed asynchronously while or after the ioctl returns.
+                   See the inline documentation in <linux/firewire-cdev.h> for
+                   descriptions of all ioctls.
 
                poll(2), select(2), epoll_wait(2) etc.
-               Watch for events to become available to be read.
+                   Watch for events to become available to be read.
 
                read(2)
-               Receive various events.  There are solicited events like
-               outbound asynchronous transaction completion or isochronous
-               buffer completion, and unsolicited events such as bus resets,
-               request reception, or PHY packet reception.  Always use a read
-               buffer which is large enough to receive the largest event that
-               could ever arrive.  See <linux/firewire-cdev.h> for descriptions
-               of all event types and for which ioctls affect reception of
-               events.
+                   Receive various events.  There are solicited events like
+                   outbound asynchronous transaction completion or isochronous
+                   buffer completion, and unsolicited events such as bus resets,
+                   request reception, or PHY packet reception.  Always use a read
+                   buffer which is large enough to receive the largest event that
+                   could ever arrive.  See <linux/firewire-cdev.h> for descriptions
+                   of all event types and for which ioctls affect reception of
+                   events.
 
                mmap(2)
-               Allocate a DMA buffer for isochronous reception or transmission
-               and map it into the process address space.  The arguments should
-               be used as follows:  addr = NULL, length = the desired buffer
-               size, i.e. number of packets times size of largest packet,
-               prot = at least PROT_READ for reception and at least PROT_WRITE
-               for transmission, flags = MAP_SHARED, fd = the handle to the
-               /dev/fw*, offset = 0.
+                   Allocate a DMA buffer for isochronous reception or transmission
+                   and map it into the process address space.  The arguments should
+                   be used as follows:  addr = NULL, length = the desired buffer
+                   size, i.e. number of packets times size of largest packet,
+                   prot = at least PROT_READ for reception and at least PROT_WRITE
+                   for transmission, flags = MAP_SHARED, fd = the handle to the
+                   /dev/fw*, offset = 0.
 
                Isochronous reception works in packet-per-buffer fashion except
                for multichannel reception which works in buffer-fill mode.
 
                munmap(2)
-               Unmap the isochronous I/O buffer from the process address space.
+                   Unmap the isochronous I/O buffer from the process address space.
 
                close(2)
-               Besides stopping and freeing I/O contexts that were associated
-               with the file descriptor, back out any changes to the local
-               nodes' Configuration ROM.  Deallocate isochronous channels and
-               bandwidth at the IRM that were marked for kernel-assisted
-               re- and deallocation.
-
-Users:         libraw1394
-               libdc1394
-               libhinawa
+                   Besides stopping and freeing I/O contexts that were associated
+                   with the file descriptor, back out any changes to the local
+                   nodes' Configuration ROM.  Deallocate isochronous channels and
+                   bandwidth at the IRM that were marked for kernel-assisted
+                   re- and deallocation.
+
+Users:         libraw1394;
+               libdc1394;
+               libhinawa;
                tools like linux-firewire-utils, fwhack, ...
index 964c7a8afb268ae004364b0d71117efa51261dc3..2d6314f0e4e47e0110fc20712bd9dd2757769d41 100644 (file)
@@ -1,22 +1,26 @@
-What:          /sys/firmware/acpi/pm_profile
+What:          /sys/firmware/acpi/pm_profile
 Date:          03-Nov-2011
 KernelVersion: v3.2
 Contact:       linux-acpi@vger.kernel.org
-Description:   The ACPI pm_profile sysfs interface exports the platform
+Description:   The ACPI pm_profile sysfs interface exports the platform
                power management (and performance) requirement expectations
                as provided by BIOS. The integer value is directly passed as
                retrieved from the FADT ACPI table.
-Values:         For possible values see ACPI specification:
+
+Values:                For possible values see ACPI specification:
                5.2.9 Fixed ACPI Description Table (FADT)
                Field: Preferred_PM_Profile
 
                Currently these values are defined by spec:
-               0 Unspecified
-               1 Desktop
-               2 Mobile
-               3 Workstation
-               4 Enterprise Server
-               5 SOHO Server
-               6 Appliance PC
-               7 Performance Server
+
+               == =================
+               0  Unspecified
+               1  Desktop
+               2  Mobile
+               3  Workstation
+               4  Enterprise Server
+               5  SOHO Server
+               6  Appliance PC
+               7  Performance Server
                >7 Reserved
+               == =================
index 41e5a0cd1e3ed334234c4f3e9e3db1e2fa021dfc..9ac9eddb82efa358e21cb6f4f5249547ff057a44 100644 (file)
@@ -47,6 +47,7 @@ Description:
                IEEE 1394 node device attribute.
                Read-only and immutable.
 Values:                1: The sysfs entry represents a local node (a controller card).
+
                0: The sysfs entry represents a remote node.
 
 
@@ -125,7 +126,9 @@ Description:
                Read-only attribute, immutable during the target's lifetime.
                Format, as exposed by firewire-sbp2 since 2.6.22, May 2007:
                Colon-separated hexadecimal string representations of
+
                        u64 EUI-64 : u24 directory_ID : u16 LUN
+
                without 0x prefixes, without whitespace.  The former sbp2 driver
                (removed in 2.6.37 after being superseded by firewire-sbp2) used
                a somewhat shorter format which was not as close to SAM.
index 9ffba8576f7b690e334517a8f8fd647f2441b670..c399323f37de370d561f65a6bebda93c14e5f0c4 100644 (file)
@@ -9,13 +9,14 @@ Description:
                Note: This file is only present if CONFIG_NVMEM_SYSFS
                is enabled
 
-               ex:
-               hexdump /sys/bus/nvmem/devices/qfprom0/nvmem
+               ex::
 
-               0000000 0000 0000 0000 0000 0000 0000 0000 0000
-               *
-               00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
-               0000000 0000 0000 0000 0000 0000 0000 0000 0000
-               ...
-               *
-               0001000
+                 hexdump /sys/bus/nvmem/devices/qfprom0/nvmem
+
+                 0000000 0000 0000 0000 0000 0000 0000 0000 0000
+                 *
+                 00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
+                 0000000 0000 0000 0000 0000 0000 0000 0000 0000
+                 ...
+                 *
+                 0001000
index b832eeff999914b0afa4e4a99d7379e4f852dea8..cad4bc23252066bdbaf89bcbeefd3285bd74858d 100644 (file)
@@ -50,8 +50,10 @@ Description:
 
                Tools can use this file and the connected_duration file to
                compute the percentage of time that a device has been active.
-               For example,
-               echo $((100 * `cat active_duration` / `cat connected_duration`))
+               For example::
+
+                 echo $((100 * `cat active_duration` / `cat connected_duration`))
+
                will give an integer percentage.  Note that this does not
                account for counter wrap.
 Users:
index 8e8d167eca3145c049e44a9d9b8b0bdbe17c6838..c27b7b89477ce7778e3b4af0bcc3a36637bfd489 100644 (file)
@@ -63,13 +63,6 @@ Contact:     Stephen Hemminger <sthemmin@microsoft.com>
 Description:   VCPU (sub)channel is affinitized to
 Users:         tools/hv/lsvmbus and other debugging tools
 
-What:          /sys/bus/vmbus/devices/<UUID>/channels/<N>/cpu
-Date:          September. 2017
-KernelVersion: 4.14
-Contact:       Stephen Hemminger <sthemmin@microsoft.com>
-Description:   VCPU (sub)channel is affinitized to
-Users:         tools/hv/lsvmbus and other debugging tools
-
 What:          /sys/bus/vmbus/devices/<UUID>/channels/<N>/in_mask
 Date:          September. 2017
 KernelVersion: 4.14
index 992dfb183ed0221edd6562544c78dfcd0a2d0d7f..5cd5e872bcaed22a8bca71a8499d792024f7938c 100644 (file)
@@ -6,6 +6,7 @@ Description:    Bus scanning interval, microseconds component.
                control systems are attached/generate presence for as short as
                100 ms - hence the tens-to-hundreds milliseconds scan intervals
                are required.
+
                see Documentation/w1/w1-generic.rst for detailed information.
 Users:         any user space application which wants to know bus scanning
                interval
index 70302f370e7ec1c1d46e4d278f41319e1ce536c1..023fb52645f8bdcd02c22c3faf0f803609a9a2dd 100644 (file)
@@ -4,6 +4,7 @@ KernelVersion:  2.6.12
 Contact:       Richard Purdie <rpurdie@rpsys.net>
 Description:
                Control BACKLIGHT power, values are FB_BLANK_* from fb.h
+
                 - FB_BLANK_UNBLANK (0)   : power on.
                 - FB_BLANK_POWERDOWN (4) : power off
 Users:         HAL
index 87b11f91b42568f5ac3c6153f10c4c020e4cca20..348c4ac803ade36060d45b2354416b61478f5b34 100644 (file)
@@ -8,12 +8,14 @@ Date:         Apr, 2005
 KernelVersion: v2.6.12
 Contact:       linux-rdma@vger.kernel.org
 Description:
+               =============== ===========================================
                node_type:      (RO) Node type (CA, RNIC, usNIC, usNIC UDP,
                                switch or router)
 
                node_guid:      (RO) Node GUID
 
                sys_image_guid: (RO) System image GUID
+               =============== ===========================================
 
 
 What:          /sys/class/infiniband/<device>/node_desc
@@ -47,6 +49,7 @@ KernelVersion:        v2.6.12
 Contact:       linux-rdma@vger.kernel.org
 Description:
 
+               =============== ===============================================
                lid:            (RO) Port LID
 
                rate:           (RO) Port data rate (active width * active
@@ -66,8 +69,9 @@ Description:
 
                cap_mask:       (RO) Port capability mask. 2 bits here are
                                settable- IsCommunicationManagementSupported
-                               (set when CM module is loaded) and IsSM (set via
-                               open of issmN file).
+                               (set when CM module is loaded) and IsSM (set
+                               via open of issmN file).
+               =============== ===============================================
 
 
 What:          /sys/class/infiniband/<device>/ports/<port-num>/link_layer
@@ -103,8 +107,7 @@ Date:               Apr, 2005
 KernelVersion: v2.6.12
 Contact:       linux-rdma@vger.kernel.org
 Description:
-               Errors info:
-               -----------
+               **Errors info**:
 
                symbol_error: (RO) Total number of minor link errors detected on
                one or more physical lanes.
@@ -142,8 +145,7 @@ Description:
                intervention. It can also indicate hardware issues or extremely
                poor link signal integrity
 
-               Data info:
-               ---------
+               **Data info**:
 
                port_xmit_data: (RO) Total number of data octets, divided by 4
                (lanes), transmitted on all VLs. This is 64 bit counter
@@ -176,8 +178,7 @@ Description:
                transmitted on all VLs from the port. This may include multicast
                packets with errors.
 
-               Misc info:
-               ---------
+               **Misc info**:
 
                port_xmit_discards: (RO) Total number of outbound packets
                discarded by the port because the port is down or congested.
@@ -244,9 +245,11 @@ Description:
                two umad devices and two issm devices, while a switch will have
                one device of each type (for switch port 0).
 
+               ======= =====================================
                ibdev:  (RO) Show Infiniband (IB) device name
 
                port:   (RO) Display port number
+               ======= =====================================
 
 
 What:          /sys/class/infiniband_mad/abi_version
@@ -264,10 +267,12 @@ Date:             Sept, 2005
 KernelVersion: v2.6.14
 Contact:       linux-rdma@vger.kernel.org
 Description:
+               =============== ===========================================
                ibdev:          (RO) Display Infiniband (IB) device name
 
                abi_version:    (RO) Show ABI version of IB device specific
                                interfaces.
+               =============== ===========================================
 
 
 What:          /sys/class/infiniband_verbs/abi_version
@@ -289,12 +294,14 @@ Date:             Apr, 2005
 KernelVersion: v2.6.12
 Contact:       linux-rdma@vger.kernel.org
 Description:
+               =============== ================================================
                hw_rev:         (RO) Hardware revision number
 
                hca_type:       (RO) Host Channel Adapter type: MT23108, MT25208
                                (MT23108 compat mode), MT25208 or MT25204
 
                board_id:       (RO) Manufacturing board ID
+               =============== ================================================
 
 
 sysfs interface for Mellanox ConnectX HCA IB driver (mlx4)
@@ -307,11 +314,13 @@ Date:             Sep, 2007
 KernelVersion: v2.6.24
 Contact:       linux-rdma@vger.kernel.org
 Description:
+               =============== ===============================
                hw_rev:         (RO) Hardware revision number
 
                hca_type:       (RO) Host channel adapter type
 
                board_id:       (RO) Manufacturing board ID
+               =============== ===============================
 
 
 What:          /sys/class/infiniband/mlx4_X/iov/ports/<port-num>/gids/<n>
@@ -337,6 +346,7 @@ Description:
                example, ports/1/pkeys/10 contains the value at index 10 in port
                1's P_Key table.
 
+               ======================= ==========================================
                gids/<n>:               (RO) The physical port gids n = 0..127
 
                admin_guids/<n>:        (RW) Allows examining or changing the
@@ -365,6 +375,7 @@ Description:
                                        guest, whenever it uses its pkey index
                                        1, will actually be using the real pkey
                                        index 10.
+               ======================= ==========================================
 
 
 What:          /sys/class/infiniband/mlx4_X/iov/<pci-slot-num>/ports/<m>/smi_enabled
@@ -376,12 +387,14 @@ Description:
                Enabling QP0 on VFs for selected VF/port. By default, no VFs are
                enabled for QP0 operation.
 
-               smi_enabled:    (RO) Indicates whether smi is currently enabled
-                               for the indicated VF/port
+               ================= ==== ===========================================
+               smi_enabled:      (RO) Indicates whether smi is currently enabled
+                                      for the indicated VF/port
 
-               enable_smi_admin:(RW) Used by the admin to request that smi
-                               capability be enabled or disabled for the
-                               indicated VF/port. 0 = disable, 1 = enable.
+               enable_smi_admin: (RW) Used by the admin to request that smi
+                                      capability be enabled or disabled for the
+                                      indicated VF/port. 0 = disable, 1 = enable.
+               ================= ==== ===========================================
 
                The requested enablement will occur at the next reset of the VF
                (e.g. driver restart on the VM which owns the VF).
@@ -398,6 +411,7 @@ KernelVersion:      v2.6.35
 Contact:       linux-rdma@vger.kernel.org
 Description:
 
+               =============== =============================================
                hw_rev:         (RO) Hardware revision number
 
                hca_type:       (RO) Driver short name. Should normally match
@@ -406,6 +420,7 @@ Description:
 
                board_id:       (RO) Manufacturing board id. (Vendor + device
                                information)
+               =============== =============================================
 
 
 sysfs interface for Intel IB driver qib
@@ -426,6 +441,7 @@ Date:               May, 2010
 KernelVersion: v2.6.35
 Contact:       linux-rdma@vger.kernel.org
 Description:
+               =============== ======================================================
                version:        (RO) Display version information of installed software
                                and drivers.
 
@@ -452,6 +468,7 @@ Description:
                chip_reset:     (WO) Reset the chip if possible by writing
                                "reset" to this file. Only allowed if no user
                                contexts are open that use chip resources.
+               =============== ======================================================
 
 
 What:          /sys/class/infiniband/qibX/ports/N/sl2vl/[0-15]
@@ -471,14 +488,16 @@ Contact:  linux-rdma@vger.kernel.org
 Description:
                Per-port congestion control. Both are binary attributes.
 
-               cc_table_bin:   (RO) Congestion control table size followed by
+               =============== ================================================
+               cc_table_bin    (RO) Congestion control table size followed by
                                table entries.
 
-               cc_settings_bin:(RO) Congestion settings: port control, control
+               cc_settings_bin (RO) Congestion settings: port control, control
                                map and an array of 16 entries for the
                                congestion entries - increase, timer, event log
                                trigger threshold and the minimum injection rate
                                delay.
+               =============== ================================================
 
 What:          /sys/class/infiniband/qibX/ports/N/linkstate/loopback
 What:          /sys/class/infiniband/qibX/ports/N/linkstate/led_override
@@ -491,6 +510,7 @@ Contact:    linux-rdma@vger.kernel.org
 Description:
                [to be documented]
 
+               =============== ===============================================
                loopback:       (WO)
                led_override:   (WO)
                hrtbt_enable:   (RW)
@@ -501,6 +521,7 @@ Description:
                                errors. Possible states are- "Initted",
                                "Present", "IB_link_up", "IB_configured" or
                                "Fatal_Hardware_Error".
+               =============== ===============================================
 
 What:          /sys/class/infiniband/qibX/ports/N/diag_counters/rc_resends
 What:          /sys/class/infiniband/qibX/ports/N/diag_counters/seq_naks
@@ -549,6 +570,7 @@ Contact:    Christian Benvenuti <benve@cisco.com>,
                linux-rdma@vger.kernel.org
 Description:
 
+               =============== ===============================================
                board_id:       (RO) Manufacturing board id
 
                config:         (RO) Report the configuration for this PF
@@ -561,6 +583,7 @@ Description:
 
                iface:          (RO) Shows which network interface this usNIC
                                entry is associated to (visible with ifconfig).
+               =============== ===============================================
 
 What:          /sys/class/infiniband/usnic_X/qpn/summary
 What:          /sys/class/infiniband/usnic_X/qpn/context
@@ -605,6 +628,7 @@ Date:               May, 2016
 KernelVersion: v4.6
 Contact:       linux-rdma@vger.kernel.org
 Description:
+               =============== =============================================
                hw_rev:         (RO) Hardware revision number
 
                board_id:       (RO) Manufacturing board id
@@ -623,6 +647,7 @@ Description:
                                available.
 
                tempsense:      (RO) Thermal sense information
+               =============== =============================================
 
 
 What:          /sys/class/infiniband/hfi1_X/ports/N/CCMgtA/cc_settings_bin
@@ -634,19 +659,21 @@ Contact:  linux-rdma@vger.kernel.org
 Description:
                Per-port congestion control.
 
-               cc_table_bin:   (RO) CCA tables used by PSM2 Congestion control
+               =============== ================================================
+               cc_table_bin    (RO) CCA tables used by PSM2 Congestion control
                                table size followed by table entries. Binary
                                attribute.
 
-               cc_settings_bin:(RO) Congestion settings: port control, control
+               cc_settings_bin (RO) Congestion settings: port control, control
                                map and an array of 16 entries for the
                                congestion entries - increase, timer, event log
                                trigger threshold and the minimum injection rate
                                delay. Binary attribute.
 
-               cc_prescan:     (RW) enable prescanning for faster BECN
+               cc_prescan      (RW) enable prescanning for faster BECN
                                response. Write "on" to enable and "off" to
                                disable.
+               =============== ================================================
 
 What:          /sys/class/infiniband/hfi1_X/ports/N/sc2vl/[0-31]
 What:          /sys/class/infiniband/hfi1_X/ports/N/sl2sc/[0-31]
@@ -655,11 +682,13 @@ Date:             May, 2016
 KernelVersion: v4.6
 Contact:       linux-rdma@vger.kernel.org
 Description:
+               =============== ===================================================
                sc2vl/:         (RO) 32 files (0 - 31) used to translate sl->vl
 
                sl2sc/:         (RO) 32 files (0 - 31) used to translate sl->sc
 
                vl2mtu/:        (RO) 16 files (0 - 15) used to determine MTU for vl
+               =============== ===================================================
 
 
 What:          /sys/class/infiniband/hfi1_X/sdma_N/cpu_list
@@ -670,26 +699,28 @@ Contact:  linux-rdma@vger.kernel.org
 Description:
                sdma<N>/ contains one directory per sdma engine (0 - 15)
 
+               =============== ==============================================
                cpu_list:       (RW) List of cpus for user-process to sdma
                                engine assignment.
 
                vl:             (RO) Displays the virtual lane (vl) the sdma
                                engine maps to.
+               =============== ==============================================
 
                This interface gives the user control on the affinity settings
                for the device. As an example, to set an sdma engine irq
                affinity and thread affinity of a user processes to use the
                sdma engine, which is "near" in terms of NUMA configuration, or
-               physical cpu location, the user will do:
+               physical cpu location, the user will do::
 
-               echo "3" > /proc/irq/<N>/smp_affinity_list
-               echo "4-7" > /sys/devices/.../sdma3/cpu_list
-               cat /sys/devices/.../sdma3/vl
-               0
-               echo "8" > /proc/irq/<M>/smp_affinity_list
-               echo "9-12" > /sys/devices/.../sdma4/cpu_list
-               cat /sys/devices/.../sdma4/vl
-               1
+                 echo "3" > /proc/irq/<N>/smp_affinity_list
+                 echo "4-7" > /sys/devices/.../sdma3/cpu_list
+                 cat /sys/devices/.../sdma3/vl
+                 0
+                 echo "8" > /proc/irq/<M>/smp_affinity_list
+                 echo "9-12" > /sys/devices/.../sdma4/cpu_list
+                 cat /sys/devices/.../sdma4/vl
+                 1
 
                to make sure that when a process runs on cpus 4,5,6, or 7, and
                uses vl=0, then sdma engine 3 is selected by the driver, and
@@ -711,11 +742,13 @@ Date:             Jan, 2016
 KernelVersion: v4.10
 Contact:       linux-rdma@vger.kernel.org
 Description:
+               =============== ==== ========================
                hw_rev:         (RO) Hardware revision number
 
                hca_type:       (RO) Show HCA type (I40IW)
 
                board_id:       (RO) I40IW board ID
+               =============== ==== ========================
 
 
 sysfs interface for QLogic qedr NIC Driver
@@ -728,9 +761,11 @@ KernelVersion:     v4.10
 Contact:       linux-rdma@vger.kernel.org
 Description:
 
+               =============== ==== ========================
                hw_rev:         (RO) Hardware revision number
 
                hca_type:       (RO) Display HCA type
+               =============== ==== ========================
 
 
 sysfs interface for VMware Paravirtual RDMA driver
@@ -744,11 +779,13 @@ KernelVersion:    v4.10
 Contact:       linux-rdma@vger.kernel.org
 Description:
 
+               =============== ==== =====================================
                hw_rev:         (RO) Hardware revision number
 
                hca_type:       (RO) Host channel adapter type
 
                board_id:       (RO) Display PVRDMA manufacturing board ID
+               =============== ==== =====================================
 
 
 sysfs interface for Broadcom NetXtreme-E RoCE driver
@@ -760,6 +797,8 @@ Date:               Feb, 2017
 KernelVersion: v4.11
 Contact:       linux-rdma@vger.kernel.org
 Description:
+               =============== ==== =========================
                hw_rev:         (RO) Hardware revision number
 
                hca_type:       (RO) Host channel adapter type
+               =============== ==== =========================
index 5b154f9226430292a9e62d4199c59bcf542c49b3..037979f7dc4bed3bc1e06a61d6aff3cdfd1960b3 100644 (file)
@@ -2,7 +2,7 @@ rfkill - radio frequency (RF) connector kill switch support
 
 For details to this subsystem look at Documentation/driver-api/rfkill.rst.
 
-For the deprecated /sys/class/rfkill/*/claim knobs of this interface look in
+For the deprecated ``/sys/class/rfkill/*/claim`` knobs of this interface look in
 Documentation/ABI/removed/sysfs-class-rfkill.
 
 What:          /sys/class/rfkill
@@ -36,9 +36,10 @@ KernelVersion        v2.6.22
 Contact:       linux-wireless@vger.kernel.org
 Description:   Whether the soft blocked state is initialised from non-volatile
                storage at startup.
-Values:        A numeric value.
-               0: false
-               1: true
+Values:        A numeric value:
+
+               - 0: false
+               - 1: true
 
 
 What:          /sys/class/rfkill/rfkill[0-9]+/state
@@ -54,6 +55,7 @@ Description:  Current state of the transmitter.
                through this interface. There will likely be another attempt to
                remove it in the future.
 Values:        A numeric value.
+
                0: RFKILL_STATE_SOFT_BLOCKED
                        transmitter is turned off by software
                1: RFKILL_STATE_UNBLOCKED
@@ -69,6 +71,7 @@ KernelVersion v2.6.34
 Contact:       linux-wireless@vger.kernel.org
 Description:   Current hardblock state. This file is read only.
 Values:        A numeric value.
+
                0: inactive
                        The transmitter is (potentially) active.
                1: active
@@ -82,7 +85,9 @@ KernelVersion v2.6.34
 Contact:       linux-wireless@vger.kernel.org
 Description:   Current softblock state. This file is read and write.
 Values:        A numeric value.
+
                0: inactive
                        The transmitter is (potentially) active.
+
                1: active
                        The transmitter is turned off by software.
index 58e94e7d55be5f8ec949545c677b148f0ec46868..91ca63ec7581aa72be7d2bb2228d6ab18d92470f 100644 (file)
@@ -32,11 +32,11 @@ KernelVersion:      2.6.12
 Contact:       linux-integrity@vger.kernel.org
 Description:   The "caps" property contains TPM manufacturer and version info.
 
-               Example output:
+               Example output::
 
-               Manufacturer: 0x53544d20
-               TCG version: 1.2
-               Firmware version: 8.16
+                 Manufacturer: 0x53544d20
+                 TCG version: 1.2
+                 Firmware version: 8.16
 
                Manufacturer is a hex dump of the 4 byte manufacturer info
                space in a TPM. TCG version shows the TCG TPM spec level that
@@ -54,9 +54,9 @@ Description:  The "durations" property shows the 3 vendor-specific values
                any longer than necessary before starting to poll for a
                result.
 
-               Example output:
+               Example output::
 
-               3015000 4508000 180995000 [original]
+                 3015000 4508000 180995000 [original]
 
                Here the short, medium and long durations are displayed in
                usecs. "[original]" indicates that the values are displayed
@@ -92,14 +92,14 @@ Description:        The "pcrs" property will dump the current value of all Platform
                values may be constantly changing, the output is only valid
                for a snapshot in time.
 
-               Example output:
+               Example output::
 
-               PCR-00: 3A 3F 78 0F 11 A4 B4 99 69 FC AA 80 CD 6E 39 57 C3 3B 22 75
-               PCR-01: 3A 3F 78 0F 11 A4 B4 99 69 FC AA 80 CD 6E 39 57 C3 3B 22 75
-               PCR-02: 3A 3F 78 0F 11 A4 B4 99 69 FC AA 80 CD 6E 39 57 C3 3B 22 75
-               PCR-03: 3A 3F 78 0F 11 A4 B4 99 69 FC AA 80 CD 6E 39 57 C3 3B 22 75
-               PCR-04: 3A 3F 78 0F 11 A4 B4 99 69 FC AA 80 CD 6E 39 57 C3 3B 22 75
-               ...
+                 PCR-00: 3A 3F 78 0F 11 A4 B4 99 69 FC AA 80 CD 6E 39 57 C3 3B 22 75
+                 PCR-01: 3A 3F 78 0F 11 A4 B4 99 69 FC AA 80 CD 6E 39 57 C3 3B 22 75
+                 PCR-02: 3A 3F 78 0F 11 A4 B4 99 69 FC AA 80 CD 6E 39 57 C3 3B 22 75
+                 PCR-03: 3A 3F 78 0F 11 A4 B4 99 69 FC AA 80 CD 6E 39 57 C3 3B 22 75
+                 PCR-04: 3A 3F 78 0F 11 A4 B4 99 69 FC AA 80 CD 6E 39 57 C3 3B 22 75
+                 ...
 
                The number of PCRs and hex bytes needed to represent a PCR
                value will vary depending on TPM chip version. For TPM 1.1 and
@@ -119,44 +119,44 @@ Description:      The "pubek" property will return the TPM's public endorsement
                ated at TPM manufacture time and exists for the life of the
                chip.
 
-               Example output:
-
-               Algorithm: 00 00 00 01
-               Encscheme: 00 03
-               Sigscheme: 00 01
-               Parameters: 00 00 08 00 00 00 00 02 00 00 00 00
-               Modulus length: 256
-               Modulus:
-               B4 76 41 82 C9 20 2C 10 18 40 BC 8B E5 44 4C 6C
-               3A B2 92 0C A4 9B 2A 83 EB 5C 12 85 04 48 A0 B6
-               1E E4 81 84 CE B2 F2 45 1C F0 85 99 61 02 4D EB
-               86 C4 F7 F3 29 60 52 93 6B B2 E5 AB 8B A9 09 E3
-               D7 0E 7D CA 41 BF 43 07 65 86 3C 8C 13 7A D0 8B
-               82 5E 96 0B F8 1F 5F 34 06 DA A2 52 C1 A9 D5 26
-               0F F4 04 4B D9 3F 2D F2 AC 2F 74 64 1F 8B CD 3E
-               1E 30 38 6C 70 63 69 AB E2 50 DF 49 05 2E E1 8D
-               6F 78 44 DA 57 43 69 EE 76 6C 38 8A E9 8E A3 F0
-               A7 1F 3C A8 D0 12 15 3E CA 0E BD FA 24 CD 33 C6
-               47 AE A4 18 83 8E 22 39 75 93 86 E6 FD 66 48 B6
-               10 AD 94 14 65 F9 6A 17 78 BD 16 53 84 30 BF 70
-               E0 DC 65 FD 3C C6 B0 1E BF B9 C1 B5 6C EF B1 3A
-               F8 28 05 83 62 26 11 DC B4 6B 5A 97 FF 32 26 B6
-               F7 02 71 CF 15 AE 16 DD D1 C1 8E A8 CF 9B 50 7B
-               C3 91 FF 44 1E CF 7C 39 FE 17 77 21 20 BD CE 9B
-
-               Possible values:
-
-               Algorithm:      TPM_ALG_RSA                     (1)
-               Encscheme:      TPM_ES_RSAESPKCSv15             (2)
+               Example output::
+
+                 Algorithm: 00 00 00 01
+                 Encscheme: 00 03
+                 Sigscheme: 00 01
+                 Parameters: 00 00 08 00 00 00 00 02 00 00 00 00
+                 Modulus length: 256
+                 Modulus:
+                 B4 76 41 82 C9 20 2C 10 18 40 BC 8B E5 44 4C 6C
+                 3A B2 92 0C A4 9B 2A 83 EB 5C 12 85 04 48 A0 B6
+                 1E E4 81 84 CE B2 F2 45 1C F0 85 99 61 02 4D EB
+                 86 C4 F7 F3 29 60 52 93 6B B2 E5 AB 8B A9 09 E3
+                 D7 0E 7D CA 41 BF 43 07 65 86 3C 8C 13 7A D0 8B
+                 82 5E 96 0B F8 1F 5F 34 06 DA A2 52 C1 A9 D5 26
+                 0F F4 04 4B D9 3F 2D F2 AC 2F 74 64 1F 8B CD 3E
+                 1E 30 38 6C 70 63 69 AB E2 50 DF 49 05 2E E1 8D
+                 6F 78 44 DA 57 43 69 EE 76 6C 38 8A E9 8E A3 F0
+                 A7 1F 3C A8 D0 12 15 3E CA 0E BD FA 24 CD 33 C6
+                 47 AE A4 18 83 8E 22 39 75 93 86 E6 FD 66 48 B6
+                 10 AD 94 14 65 F9 6A 17 78 BD 16 53 84 30 BF 70
+                 E0 DC 65 FD 3C C6 B0 1E BF B9 C1 B5 6C EF B1 3A
+                 F8 28 05 83 62 26 11 DC B4 6B 5A 97 FF 32 26 B6
+                 F7 02 71 CF 15 AE 16 DD D1 C1 8E A8 CF 9B 50 7B
+                 C3 91 FF 44 1E CF 7C 39 FE 17 77 21 20 BD CE 9B
+
+               Possible values::
+
+                 Algorithm:    TPM_ALG_RSA                     (1)
+                 Encscheme:    TPM_ES_RSAESPKCSv15             (2)
                                TPM_ES_RSAESOAEP_SHA1_MGF1      (3)
-               Sigscheme:      TPM_SS_NONE                     (1)
-               Parameters, a byte string of 3 u32 values:
+                 Sigscheme:    TPM_SS_NONE                     (1)
+                 Parameters, a byte string of 3 u32 values:
                        Key Length (bits):      00 00 08 00     (2048)
                        Num primes:             00 00 00 02     (2)
                        Exponent Size:          00 00 00 00     (0 means the
                                                                 default exp)
-               Modulus Length: 256 (bytes)
-               Modulus:        The 256 byte Endorsement Key modulus
+                 Modulus Length: 256 (bytes)
+                 Modulus:      The 256 byte Endorsement Key modulus
 
 What:          /sys/class/tpm/tpmX/device/temp_deactivated
 Date:          April 2006
@@ -176,9 +176,9 @@ Description:        The "timeouts" property shows the 4 vendor-specific values
                timeouts is defined by the TPM interface spec that the chip
                conforms to.
 
-               Example output:
+               Example output::
 
-               750000 750000 750000 750000 [original]
+                 750000 750000 750000 750000 [original]
 
                The four timeout values are shown in usecs, with a trailing
                "[original]" or "[adjusted]" depending on whether the values
@@ -191,6 +191,6 @@ Contact:    linux-integrity@vger.kernel.org
 Description:   The "tpm_version_major" property shows the TCG spec major version
                implemented by the TPM device.
 
-               Example output:
+               Example output::
 
-               2
+                 2
index 4404bd9b96c1972336b02707346f951fc3642a6b..42bf1eab5677ba462e05d3f68954dd013e2dfeb7 100644 (file)
@@ -1,5 +1,6 @@
-# Note: This documents additional properties of any device beyond what
-# is documented in Documentation/admin-guide/sysfs-rules.rst
+Note:
+  This documents additional properties of any device beyond what
+  is documented in Documentation/admin-guide/sysfs-rules.rst
 
 What:          /sys/devices/*/of_node
 Date:          February 2015
index 420c1d09e42f36fa9cbd24375cf985815450a575..3a4e2cd0ddcc0e203c44f7cd347e89931b821b95 100644 (file)
@@ -1,29 +1,29 @@
-What:           sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/cap
+What:           /sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/cap
 Date:           December 3, 2009
 KernelVersion:  2.6.32
 Contact:        dmaengine@vger.kernel.org
 Description:   Capabilities the DMA supports.Currently there are DMA_PQ, DMA_PQ_VAL,
                DMA_XOR,DMA_XOR_VAL,DMA_INTERRUPT.
 
-What:           sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/ring_active
+What:           /sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/ring_active
 Date:           December 3, 2009
 KernelVersion:  2.6.32
 Contact:        dmaengine@vger.kernel.org
 Description:   The number of descriptors active in the ring.
 
-What:           sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/ring_size
+What:           /sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/ring_size
 Date:           December 3, 2009
 KernelVersion:  2.6.32
 Contact:        dmaengine@vger.kernel.org
 Description:   Descriptor ring size, total number of descriptors available.
 
-What:           sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/version
+What:           /sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/version
 Date:           December 3, 2009
 KernelVersion:  2.6.32
 Contact:        dmaengine@vger.kernel.org
 Description:   Version of ioatdma device.
 
-What:           sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/intr_coalesce
+What:           /sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/intr_coalesce
 Date:           August 8, 2017
 KernelVersion:  4.14
 Contact:        dmaengine@vger.kernel.org
index 00fa04c76ff3f79ab7a416aa9468eae508a3948c..f5724bb5b4624bb0b7c65650049406f531964fa7 100644 (file)
@@ -12,13 +12,15 @@ Description:
                resets. Three registers are used by the FSBL and
                other Xilinx software products: GLOBAL_GEN_STORAGE{4:6}.
 
-               Usage:
-               # cat /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
-               # echo <value> > /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
+               Usage::
+
+                   # cat /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
+                   # echo <value> > /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
+
+               Example::
 
-               Example:
-               # cat /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
-               # echo 0x1234ABCD > /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
+                   # cat /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
+                   # echo 0x1234ABCD > /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
 
 Users:         Xilinx
 
@@ -39,13 +41,15 @@ Description:
                software products: PERS_GLOB_GEN_STORAGE{4:7}.
                Register is reset only by a POR reset.
 
-               Usage:
-               # cat /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
-               # echo <value> > /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
+               Usage::
+
+                   # cat /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
+                   # echo <value> > /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
+
+               Example::
 
-               Example:
-               # cat /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
-               # echo 0x1234ABCD > /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
+                   # cat /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
+                   # echo 0x1234ABCD > /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
 
 Users:         Xilinx
 
@@ -61,23 +65,28 @@ Description:
 
                Following are available shutdown scopes(subtypes):
 
-               subsystem:      Only the APU along with all of its peripherals
+               subsystem:
+                               Only the APU along with all of its peripherals
                                not used by other processing units will be
                                shut down. This may result in the FPD power
                                domain being shut down provided that no other
                                processing unit uses FPD peripherals or DRAM.
-               ps_only:        The complete PS will be shut down, including the
+               ps_only:
+                               The complete PS will be shut down, including the
                                RPU, PMU, etc.  Only the PL domain (FPGA)
                                remains untouched.
-               system:         The complete system/device is shut down.
+               system:
+                               The complete system/device is shut down.
 
-               Usage:
-               # cat /sys/devices/platform/firmware\:zynqmp-firmware/shutdown_scope
-               # echo <scope> > /sys/devices/platform/firmware\:zynqmp-firmware/shutdown_scope
+               Usage::
+
+                   # cat /sys/devices/platform/firmware\:zynqmp-firmware/shutdown_scope
+                   # echo <scope> > /sys/devices/platform/firmware\:zynqmp-firmware/shutdown_scope
+
+               Example::
 
-               Example:
-               # cat /sys/devices/platform/firmware\:zynqmp-firmware/shutdown_scope
-               # echo "subsystem" > /sys/devices/platform/firmware\:zynqmp-firmware/shutdown_scope
+                   # cat /sys/devices/platform/firmware\:zynqmp-firmware/shutdown_scope
+                   # echo "subsystem" > /sys/devices/platform/firmware\:zynqmp-firmware/shutdown_scope
 
 Users:         Xilinx
 
@@ -94,10 +103,13 @@ Description:
                system restart.
 
                Usage:
-               Set healthy bit
-               # echo 1 > /sys/devices/platform/firmware\:zynqmp-firmware/health_status
 
-               Unset healthy bit
-               # echo 0 > /sys/devices/platform/firmware\:zynqmp-firmware/health_status
+               Set healthy bit::
+
+                   # echo 1 > /sys/devices/platform/firmware\:zynqmp-firmware/health_status
+
+               Unset healthy bit::
+
+                   # echo 0 > /sys/devices/platform/firmware\:zynqmp-firmware/health_status
 
 Users:         Xilinx
index 84972a57caaeb9cfdab006648303fc4db5f56c7f..bada15a329f7ce7cda5e023f45f09e5d1d3ec056 100644 (file)
@@ -6,6 +6,7 @@ Description:    Interface for making ib_srp connect to a new target.
                One can request ib_srp to connect to a new target by writing
                a comma-separated list of login parameters to this sysfs
                attribute. The supported parameters are:
+
                * id_ext, a 16-digit hexadecimal number specifying the eight
                  byte identifier extension in the 16-byte SRP target port
                  identifier. The target port identifier is sent by ib_srp
index c6a32c434ce92a3e0e7daa16864ba931fc4631d2..792f58ba327d3bef5c34a4debf340c617a5e8fbb 100644 (file)
@@ -69,6 +69,7 @@ Description:  Controls if typing interrupts output from speakup. With
                speakup if for example
                the say screen command is used before the
                entire screen  is read.
+
                With no_interrupt set to one, if the say
                screen command is used, and one then types on the keyboard,
                speakup will continue to say the whole screen regardless until
@@ -215,8 +216,10 @@ Description:       This file contains names for key states.
                Again, these are part of the help system.  For instance, if you
                had pressed speakup + keypad 3, you would hear:
                "speakup keypad 3 is go to bottom edge."
+
                The speakup key is depressed, so the name of the key state is
                speakup.
+
                This part of the message comes from the states collection.
 
 What:          /sys/accessibility/speakup/i18n/characters
@@ -297,6 +300,7 @@ KernelVersion:      2.6
 Contact:       speakup@linux-speakup.org
 Description:   Controls if punctuation is spoken by speakup, or by the
                synthesizer.
+
                For example, speakup speaks ">" as "greater", while
                the espeak synthesizer used by the soft driver speaks "greater
                than". Zero lets speakup speak the punctuation. One lets the
index 5def20b9019e93299ed111d53c338e705b1e2639..46ccd233e3594e12234e0da9f985df232bef5664 100644 (file)
@@ -17,6 +17,7 @@ Description:
                directory has a name of the form "<key>-<vendor guid>"
                and contains the following files:
 
+               =============== ========================================
                attributes:     A read-only text file enumerating the
                                EFI variable flags.  Potential values
                                include:
@@ -59,12 +60,14 @@ Description:
 
                size:           As ASCII representation of the size of
                                the variable's value.
+               =============== ========================================
 
 
                In addition, two other magic binary files are provided
                in the top-level directory and are used for adding and
                removing variables:
 
+               =============== ========================================
                new_var:        Takes a "struct efi_variable" and
                                instructs the EFI firmware to create a
                                new variable.
@@ -73,3 +76,4 @@ Description:
                                instructs the EFI firmware to remove any
                                variable that has a matching vendor GUID
                                and variable key name.
+               =============== ========================================
index 32fe7f5c488069c64b8c37951b6dfcfa90f4eb57..1f74f45327ba2bbf12ec0df97ed5de9d33edc9f4 100644 (file)
@@ -7,6 +7,7 @@ Description:
 
                This is only for the powerpc/powernv platform.
 
+               =============== ===============================================
                initiate_dump:  When '1' is written to it,
                                we will initiate a dump.
                                Read this file for supported commands.
@@ -19,8 +20,11 @@ Description:
                                and ID of the dump, use the id and type files.
                                Do not rely on any particular size of dump
                                type or dump id.
+               =============== ===============================================
 
                Each dump has the following files:
+
+               =============== ===============================================
                id:             An ASCII representation of the dump ID
                                in hex (e.g. '0x01')
                type:           An ASCII representation of the type of
@@ -39,3 +43,4 @@ Description:
                                inaccessible.
                                Reading this file will get a list of
                                supported actions.
+               =============== ===============================================
index 2536434d49d06cff06b31331a2f12d7d475725c4..7c8a61a2d005596b3d5a526e1ade6bc30d1886d5 100644 (file)
@@ -38,6 +38,7 @@ Description:
                For each log entry (directory), there are the following
                files:
 
+               ==============  ================================================
                id:             An ASCII representation of the ID of the
                                error log, in hex - e.g. "0x01".
 
@@ -58,3 +59,4 @@ Description:
                                entry will be removed from sysfs.
                                Reading this file will list the supported
                                operations (currently just acknowledge).
+               ==============  ================================================
index 3cf5cdfcd9a8c20a169b71ae75f0fc17cbab1ffd..748593c64568ba4a62d7473addacd5687392a400 100644 (file)
@@ -33,6 +33,8 @@ Description:  If running under Xen:
                Space separated list of supported guest system types. Each type
                is in the format: <class>-<major>.<minor>-<arch>
                With:
+
+                       ======== ============================================
                        <class>: "xen" -- x86: paravirtualized, arm: standard
                                 "hvm" -- x86 only: fully virtualized
                        <major>: major guest interface version
@@ -43,6 +45,7 @@ Description:  If running under Xen:
                                 "x86_64": 64 bit x86 guest
                                 "armv7l": 32 bit arm guest
                                 "aarch64": 64 bit arm guest
+                       ======== ============================================
 
 What:          /sys/hypervisor/properties/changeset
 Date:          March 2009
index 55406ec8a35a34d9c0f67713344e769d5fc76021..951838d4278114bb24a44eb95a12628c9e463714 100644 (file)
@@ -1,3 +1,9 @@
+What:          vDSO
+Date:          July 2011
+KernelVersion: 3.0
+Contact:       Andy Lutomirski <luto@kernel.org>
+Description:
+
 On some architectures, when the kernel loads any userspace program it
 maps an ELF DSO into that program's address space.  This DSO is called
 the vDSO and it often contains useful and highly-optimized alternatives
@@ -23,6 +29,7 @@ Unless otherwise noted, the set of symbols with any given version and the
 ABI of those symbols is considered stable.  It may vary across architectures,
 though.
 
-(As of this writing, this ABI documentation as been confirmed for x86_64.
+Note:
+ As of this writing, this ABI documentation as been confirmed for x86_64.
  The maintainers of the other vDSO-using architectures should confirm
- that it is correct for their architecture.)
+ that it is correct for their architecture.
index 4ab4e99aa863e5054ff28abc5e5a75613d96f4de..c09b640c3cb14afb3a2e0374fffbd44da7b9e033 100644 (file)
@@ -14,7 +14,8 @@ Description:
                This group contains the configuration for user defined ACPI
                tables. The attributes of a user define table are:
 
-               aml             - a binary attribute that the user can use to
+               aml
+                             - a binary attribute that the user can use to
                                fill in the ACPI aml definitions. Once the aml
                                data is written to this file and the file is
                                closed the table will be loaded and ACPI devices
@@ -26,11 +27,26 @@ Description:
                The rest of the attributes are read-only and are valid only
                after the table has been loaded by filling the aml entry:
 
-               signature       - ASCII table signature
-               length          - length of table in bytes, including the header
-               revision        - ACPI Specification minor version number
-               oem_id          - ASCII OEM identification
-               oem_table_id    - ASCII OEM table identification
-               oem_revision    - OEM revision number
-               asl_compiler_id - ASCII ASL compiler vendor ID
-               asl_compiler_revision - ASL compiler version
+               signature
+                               - ASCII table signature
+
+               length
+                               - length of table in bytes, including the header
+
+               revision
+                               - ACPI Specification minor version number
+
+               oem_id
+                               - ASCII OEM identification
+
+               oem_table_id
+                               - ASCII OEM table identification
+
+               oem_revision
+                               - OEM revision number
+
+               asl_compiler_id
+                               - ASCII ASL compiler vendor ID
+
+               asl_compiler_revision
+                               - ASL compiler version
index ed67a4d9f6d63f8bc410c2560df45236bb2d7927..bc6b8bd18da49bf32ab23eb0b12e75e27d81790e 100644 (file)
@@ -15,22 +15,28 @@ KernelVersion:  5.2
 Description:
                The attributes:
 
-               buffer_size     configure the buffer size for this channel
+               buffer_size
+                               configure the buffer size for this channel
 
-               subbuffer_size  configure the sub-buffer size for this channel
+               subbuffer_size
+                               configure the sub-buffer size for this channel
                                (needed for synchronous and isochrnous data)
 
 
-               num_buffers     configure number of buffers used for this
+               num_buffers
+                               configure number of buffers used for this
                                channel
 
-               datatype        configure type of data that will travel over
+               datatype
+                               configure type of data that will travel over
                                this channel
 
-               direction       configure whether this link will be an input
+               direction
+                               configure whether this link will be an input
                                or output
 
-               dbr_size        configure DBR data buffer size (this is used
+               dbr_size
+                               configure DBR data buffer size (this is used
                                for MediaLB communication only)
 
                packets_per_xact
@@ -39,18 +45,23 @@ Description:
                                transmitted via USB (this is used for USB
                                communication only)
 
-               device          name of the device the link is to be attached to
+               device
+                               name of the device the link is to be attached to
 
-               channel         name of the channel the link is to be attached to
+               channel
+                               name of the channel the link is to be attached to
 
-               comp_params     pass parameters needed by some components
+               comp_params
+                               pass parameters needed by some components
 
-               create_link     write '1' to this attribute to trigger the
+               create_link
+                               write '1' to this attribute to trigger the
                                creation of the link. In case of speculative
                                configuration, the creation is post-poned until
                                a physical device is being attached to the bus.
 
-               destroy_link    write '1' to this attribute to destroy an
+               destroy_link
+                               write '1' to this attribute to destroy an
                                active link
 
 What:          /sys/kernel/config/most_video/<link>
@@ -59,22 +70,28 @@ KernelVersion:  5.2
 Description:
                The attributes:
 
-               buffer_size     configure the buffer size for this channel
+               buffer_size
+                               configure the buffer size for this channel
 
-               subbuffer_size  configure the sub-buffer size for this channel
+               subbuffer_size
+                               configure the sub-buffer size for this channel
                                (needed for synchronous and isochrnous data)
 
 
-               num_buffers     configure number of buffers used for this
+               num_buffers
+                               configure number of buffers used for this
                                channel
 
-               datatype        configure type of data that will travel over
+               datatype
+                               configure type of data that will travel over
                                this channel
 
-               direction       configure whether this link will be an input
+               direction
+                               configure whether this link will be an input
                                or output
 
-               dbr_size        configure DBR data buffer size (this is used
+               dbr_size
+                               configure DBR data buffer size (this is used
                                for MediaLB communication only)
 
                packets_per_xact
@@ -83,18 +100,23 @@ Description:
                                transmitted via USB (this is used for USB
                                communication only)
 
-               device          name of the device the link is to be attached to
+               device
+                               name of the device the link is to be attached to
 
-               channel         name of the channel the link is to be attached to
+               channel
+                               name of the channel the link is to be attached to
 
-               comp_params     pass parameters needed by some components
+               comp_params
+                               pass parameters needed by some components
 
-               create_link     write '1' to this attribute to trigger the
+               create_link
+                               write '1' to this attribute to trigger the
                                creation of the link. In case of speculative
                                configuration, the creation is post-poned until
                                a physical device is being attached to the bus.
 
-               destroy_link    write '1' to this attribute to destroy an
+               destroy_link
+                               write '1' to this attribute to destroy an
                                active link
 
 What:          /sys/kernel/config/most_net/<link>
@@ -103,22 +125,28 @@ KernelVersion:  5.2
 Description:
                The attributes:
 
-               buffer_size     configure the buffer size for this channel
+               buffer_size
+                               configure the buffer size for this channel
 
-               subbuffer_size  configure the sub-buffer size for this channel
+               subbuffer_size
+                               configure the sub-buffer size for this channel
                                (needed for synchronous and isochrnous data)
 
 
-               num_buffers     configure number of buffers used for this
+               num_buffers
+                               configure number of buffers used for this
                                channel
 
-               datatype        configure type of data that will travel over
+               datatype
+                               configure type of data that will travel over
                                this channel
 
-               direction       configure whether this link will be an input
+               direction
+                               configure whether this link will be an input
                                or output
 
-               dbr_size        configure DBR data buffer size (this is used
+               dbr_size
+                               configure DBR data buffer size (this is used
                                for MediaLB communication only)
 
                packets_per_xact
@@ -127,18 +155,23 @@ Description:
                                transmitted via USB (this is used for USB
                                communication only)
 
-               device          name of the device the link is to be attached to
+               device
+                               name of the device the link is to be attached to
 
-               channel         name of the channel the link is to be attached to
+               channel
+                               name of the channel the link is to be attached to
 
-               comp_params     pass parameters needed by some components
+               comp_params
+                               pass parameters needed by some components
 
-               create_link     write '1' to this attribute to trigger the
+               create_link
+                               write '1' to this attribute to trigger the
                                creation of the link. In case of speculative
                                configuration, the creation is post-poned until
                                a physical device is being attached to the bus.
 
-               destroy_link    write '1' to this attribute to destroy an
+               destroy_link
+                               write '1' to this attribute to destroy an
                                active link
 
 What:          /sys/kernel/config/most_sound/<card>
@@ -147,7 +180,8 @@ KernelVersion:  5.2
 Description:
                The attributes:
 
-               create_card     write '1' to this attribute to trigger the
+               create_card
+                               write '1' to this attribute to trigger the
                                 registration of the sound card with the ALSA
                                subsystem.
 
@@ -157,22 +191,28 @@ KernelVersion:  5.2
 Description:
                The attributes:
 
-               buffer_size     configure the buffer size for this channel
+               buffer_size
+                               configure the buffer size for this channel
 
-               subbuffer_size  configure the sub-buffer size for this channel
+               subbuffer_size
+                               configure the sub-buffer size for this channel
                                (needed for synchronous and isochrnous data)
 
 
-               num_buffers     configure number of buffers used for this
+               num_buffers
+                               configure number of buffers used for this
                                channel
 
-               datatype        configure type of data that will travel over
+               datatype
+                               configure type of data that will travel over
                                this channel
 
-               direction       configure whether this link will be an input
+               direction
+                               configure whether this link will be an input
                                or output
 
-               dbr_size        configure DBR data buffer size (this is used
+               dbr_size
+                               configure DBR data buffer size (this is used
                                for MediaLB communication only)
 
                packets_per_xact
@@ -181,16 +221,21 @@ Description:
                                transmitted via USB (this is used for USB
                                communication only)
 
-               device          name of the device the link is to be attached to
+               device
+                               name of the device the link is to be attached to
 
-               channel         name of the channel the link is to be attached to
+               channel
+                               name of the channel the link is to be attached to
 
-               comp_params     pass parameters needed by some components
+               comp_params
+                               pass parameters needed by some components
 
-               create_link     write '1' to this attribute to trigger the
+               create_link
+                               write '1' to this attribute to trigger the
                                creation of the link. In case of speculative
                                configuration, the creation is post-poned until
                                a physical device is being attached to the bus.
 
-               destroy_link    write '1' to this attribute to destroy an
+               destroy_link
+                               write '1' to this attribute to destroy an
                                active link
index 840c324ef34d3e67b1c2d39377e075c25be1af9f..cf877bd341df126a56ae57ad64371243760f4a4d 100644 (file)
@@ -10,22 +10,24 @@ Description:
        This interfaces can be used to show spear's PCIe device capability.
 
        Nodes are only visible when configfs is mounted. To mount configfs
-       in /config directory use:
-       # mount -t configfs none /config/
+       in /config directory use::
 
-       For nth PCIe Device Controller
-       /config/pcie-gadget.n/
-               link ... used to enable ltssm and read its status.
-               int_type ...used to configure and read type of supported
-                       interrupt
-               no_of_msi ... used to configure number of MSI vector needed and
+         # mount -t configfs none /config/
+
+       For nth PCIe Device Controller /config/pcie-gadget.n/:
+
+       =============== ======================================================
+       link            used to enable ltssm and read its status.
+       int_type        used to configure and read type of supported interrupt
+       no_of_msi       used to configure number of MSI vector needed and
                        to read no of MSI granted.
-               inta ... write 1 to assert INTA and 0 to de-assert.
-               send_msi ... write MSI vector to be sent.
-               vendor_id ... used to write and read vendor id (hex)
-               device_id ... used to write and read device id (hex)
-               bar0_size ... used to write and read bar0_size
-               bar0_address ... used to write and read bar0 mapped area in hex.
-               bar0_rw_offset ... used to write and read offset of bar0 where
-                       bar0_data will be written or read.
-               bar0_data ... used to write and read data at bar0_rw_offset.
+       inta            write 1 to assert INTA and 0 to de-assert.
+       send_msi        write MSI vector to be sent.
+       vendor_id       used to write and read vendor id (hex)
+       device_id       used to write and read device id (hex)
+       bar0_size       used to write and read bar0_size
+       bar0_address    used to write and read bar0 mapped area in hex.
+       bar0_rw_offset  used to write and read offset of bar0 where bar0_data
+                       will be written or read.
+       bar0_data       used to write and read data at bar0_rw_offset.
+       =============== ======================================================
index 4594cc2435e8cab6a8f3040343cf86d6ed2a232b..dc351e9af80ad0eb93da456c8e696dea08ccbe76 100644 (file)
@@ -12,22 +12,24 @@ Description:
 
                The attributes of a gadget:
 
-               UDC             - bind a gadget to UDC/unbind a gadget;
-                               write UDC's name found in /sys/class/udc/*
-                               to bind a gadget, empty string "" to unbind.
-
-               max_speed       - maximum speed the driver supports. Valid
-                               names are super-speed-plus, super-speed,
-                               high-speed, full-speed, and low-speed.
-
-               bDeviceClass    - USB device class code
-               bDeviceSubClass - USB device subclass code
-               bDeviceProtocol - USB device protocol code
-               bMaxPacketSize0 - maximum endpoint 0 packet size
-               bcdDevice       - bcd device release number
-               bcdUSB          - bcd USB specification version number
-               idProduct       - product ID
-               idVendor        - vendor ID
+               ================  ============================================
+               UDC               bind a gadget to UDC/unbind a gadget;
+                                 write UDC's name found in /sys/class/udc/*
+                                 to bind a gadget, empty string "" to unbind.
+
+               max_speed         maximum speed the driver supports. Valid
+                                 names are super-speed-plus, super-speed,
+                                 high-speed, full-speed, and low-speed.
+
+               bDeviceClass      USB device class code
+               bDeviceSubClass   USB device subclass code
+               bDeviceProtocol   USB device protocol code
+               bMaxPacketSize0   maximum endpoint 0 packet size
+               bcdDevice         bcd device release number
+               bcdUSB            bcd USB specification version number
+               idProduct         product ID
+               idVendor          vendor ID
+               ================  ============================================
 
 What:          /config/usb-gadget/gadget/configs
 Date:          Jun 2013
@@ -41,8 +43,10 @@ KernelVersion:       3.11
 Description:
                The attributes of a configuration:
 
-               bmAttributes    - configuration characteristics
-               MaxPower        - maximum power consumption from the bus
+               ================  ======================================
+               bmAttributes      configuration characteristics
+               MaxPower          maximum power consumption from the bus
+               ================  ======================================
 
 What:          /config/usb-gadget/gadget/configs/config/strings
 Date:          Jun 2013
@@ -57,7 +61,9 @@ KernelVersion:        3.11
 Description:
                The attributes:
 
-               configuration   - configuration description
+               ================  =========================
+               configuration     configuration description
+               ================  =========================
 
 
 What:          /config/usb-gadget/gadget/functions
@@ -76,8 +82,10 @@ Description:
 
                The attributes:
 
-               compatible_id           - 8-byte string for "Compatible ID"
-               sub_compatible_id       - 8-byte string for "Sub Compatible ID"
+               =================       =====================================
+               compatible_id           8-byte string for "Compatible ID"
+               sub_compatible_id       8-byte string for "Sub Compatible ID"
+               =================       =====================================
 
 What:          /config/usb-gadget/gadget/functions/<func>.<inst>/interface.<n>/<property>
 Date:          May 2014
@@ -89,16 +97,19 @@ Description:
 
                The attributes:
 
-               type            - value 1..7 for interpreting the data
-                               1: unicode string
-                               2: unicode string with environment variable
-                               3: binary
-                               4: little-endian 32-bit
-                               5: big-endian 32-bit
-                               6: unicode string with a symbolic link
-                               7: multiple unicode strings
-               data            - blob of data to be interpreted depending on
+               =====           ===============================================
+               type            value 1..7 for interpreting the data
+
+                               - 1: unicode string
+                               - 2: unicode string with environment variable
+                               - 3: binary
+                               - 4: little-endian 32-bit
+                               - 5: big-endian 32-bit
+                               - 6: unicode string with a symbolic link
+                               - 7: multiple unicode strings
+               data            blob of data to be interpreted depending on
                                type
+               =====           ===============================================
 
 What:          /config/usb-gadget/gadget/strings
 Date:          Jun 2013
@@ -113,9 +124,11 @@ KernelVersion:     3.11
 Description:
                The attributes:
 
-               serialnumber    - gadget's serial number (string)
-               product         - gadget's product description
-               manufacturer    - gadget's manufacturer description
+               ============    =================================
+               serialnumber    gadget's serial number (string)
+               product         gadget's product description
+               manufacturer    gadget's manufacturer description
+               ============    =================================
 
 What:          /config/usb-gadget/gadget/os_desc
 Date:          May 2014
@@ -123,8 +136,10 @@ KernelVersion:     3.16
 Description:
                This group contains "OS String" extension handling attributes.
 
-               use             - flag turning "OS Desctiptors" support on/off
-               b_vendor_code   - one-byte value used for custom per-device and
+               =============   ===============================================
+               use             flag turning "OS Desctiptors" support on/off
+               b_vendor_code   one-byte value used for custom per-device and
                                per-interface requests
-               qw_sign         an identifier to be reported as "OS String"
+               qw_sign         an identifier to be reported as "OS String"
                                proper
+               =============   ===============================================
index 0addf7704b4c0ee9639406abfd7f16184d7402fd..272bc1e4ce2e6257639bf1ddf42ae88917d3aa63 100644 (file)
@@ -4,13 +4,17 @@ KernelVersion:        3.11
 Description:
                The attributes:
 
-               ifname          - network device interface name associated with
+               ifname
+                             - network device interface name associated with
                                this function instance
-               qmult           - queue length multiplier for high and
+               qmult   
+                             - queue length multiplier for high and
                                super speed
-               host_addr       - MAC address of host's end of this
+               host_addr
+                             - MAC address of host's end of this
                                Ethernet over USB link
-               dev_addr        - MAC address of device's end of this
+               dev_addr
+                             - MAC address of device's end of this
                                Ethernet over USB link
 
 
index a4c57158fcdef28a8805157b24015eb4edb38568..178c3d5fb64780f64934f9cdff4bf56aa21ceb9a 100644 (file)
@@ -4,11 +4,13 @@ KernelVersion:        3.11
 Description:
                The attributes:
 
-               ifname          - network device interface name associated with
+               ==========      =============================================
+               ifname          network device interface name associated with
                                this function instance
-               qmult           queue length multiplier for high and
+               qmult           queue length multiplier for high and
                                super speed
-               host_addr       MAC address of host's end of this
+               host_addr       MAC address of host's end of this
                                Ethernet over USB link
-               dev_addr        MAC address of device's end of this
+               dev_addr        MAC address of device's end of this
                                Ethernet over USB link
+               ==========      =============================================
index f12e00e6baa34d275be7430c91410da22faca651..748705c4cb5887cb457b5783c8b26c4add996831 100644 (file)
@@ -4,8 +4,10 @@ KernelVersion: 3.19
 Description:
                The attributes:
 
-               protocol        - HID protocol to use
-               report_desc     - blob corresponding to HID report descriptors
+               =============   ============================================
+               protocol        HID protocol to use
+               report_desc     blob corresponding to HID report descriptors
                                except the data passed through /dev/hidg<N>
-               report_length   - HID report length
-               subclass        - HID device subclass to use
+               report_length   HID report length
+               subclass        HID device subclass to use
+               =============   ============================================
index 06beefbcf061a76f2dc1deb5696649eda35c1aaa..e6c6ba5ac7ff4e58ee1be2412dff937946a9b316 100644 (file)
@@ -4,5 +4,7 @@ KernelVersion:  3.13
 Description:
                The attributes:
 
-               qlen            - depth of loopback queue
-               buflen          - buffer length
+               =======         =======================
+               qlen            depth of loopback queue
+               buflen          buffer length
+               =======         =======================
index 9931fb0d63ba44ce155d3e859a5bac2df451298a..c86b63a7bb435be23ad5761d4ca8c6cf98b571ef 100644 (file)
@@ -4,12 +4,14 @@ KernelVersion:        3.13
 Description:
                The attributes:
 
-               stall           - Set to permit function to halt bulk endpoints.
+               ===========     ==============================================
+               stall           Set to permit function to halt bulk endpoints.
                                Disabled on some USB devices known not to work
                                correctly. You should set it to true.
-               num_buffers     Number of pipeline buffers. Valid numbers
+               num_buffers     Number of pipeline buffers. Valid numbers
                                are 2..4. Available only if
                                CONFIG_USB_GADGET_DEBUG_FILES is set.
+               ===========     ==============================================
 
 What:          /config/usb-gadget/gadget/functions/mass_storage.name/lun.name
 Date:          Oct 2013
@@ -17,15 +19,17 @@ KernelVersion:      3.13
 Description:
                The attributes:
 
-               file            - The path to the backing file for the LUN.
+               ===========     ==============================================
+               file            The path to the backing file for the LUN.
                                Required if LUN is not marked as removable.
-               ro              Flag specifying access to the LUN shall be
+               ro              Flag specifying access to the LUN shall be
                                read-only. This is implied if CD-ROM emulation
                                is enabled as well as when it was impossible
                                to open "filename" in R/W mode.
-               removable       Flag specifying that LUN shall be indicated as
+               removable       Flag specifying that LUN shall be indicated as
                                being removable.
-               cdrom           Flag specifying that LUN shall be reported as
+               cdrom           Flag specifying that LUN shall be reported as
                                being a CD-ROM.
-               nofua           Flag specifying that FUA flag
+               nofua           Flag specifying that FUA flag
                                in SCSI WRITE(10,12)
+               ===========     ==============================================
index 6b341df7249c8cb9b3b578ddda5cc08878dced6e..07389cddd51a3d833bab0370529504d9c57763ff 100644 (file)
@@ -4,9 +4,11 @@ KernelVersion: 3.19
 Description:
                The attributes:
 
-               index           - index value for the USB MIDI adapter
-               id              - ID string for the USB MIDI adapter
-               buflen          - MIDI buffer length
-               qlen            - USB read request queue length
-               in_ports        - number of MIDI input ports
-               out_ports       - number of MIDI output ports
+               ==========      ====================================
+               index           index value for the USB MIDI adapter
+               id              ID string for the USB MIDI adapter
+               buflen          MIDI buffer length
+               qlen            USB read request queue length
+               in_ports        number of MIDI input ports
+               out_ports       number of MIDI output ports
+               ==========      ====================================
index 6b0714e3c605f0d04676ee1a95ec084816f4436d..7aa731bac2da326ca4b0a9b58b799cb33b6caeac 100644 (file)
@@ -4,6 +4,8 @@ KernelVersion:  4.1
 Description:
                The attributes:
 
-               pnp_string      - Data to be passed to the host in pnp string
-               q_len           - Number of requests per endpoint
+               ==========      ===========================================
+               pnp_string      Data to be passed to the host in pnp string
+               q_len           Number of requests per endpoint
+               ==========      ===========================================
 
index 137399095d74b53540deed58ffc10b5329a97136..9416eda7fe9330efcd42e10fc473ea22b3d9b309 100644 (file)
@@ -4,14 +4,16 @@ KernelVersion:        3.11
 Description:
                The attributes:
 
-               ifname          - network device interface name associated with
+               =========       =============================================
+               ifname          network device interface name associated with
                                this function instance
-               qmult           queue length multiplier for high and
+               qmult           queue length multiplier for high and
                                super speed
-               host_addr       MAC address of host's end of this
+               host_addr       MAC address of host's end of this
                                Ethernet over USB link
-               dev_addr        MAC address of device's end of this
+               dev_addr        MAC address of device's end of this
                                Ethernet over USB link
-               class           - USB interface class, default is 02 (hex)
-               subclass        - USB interface subclass, default is 06 (hex)
-               protocol        - USB interface protocol, default is 00 (hex)
+               class           USB interface class, default is 02 (hex)
+               subclass        USB interface subclass, default is 06 (hex)
+               protocol        USB interface protocol, default is 00 (hex)
+               =========       =============================================
index f56335af2d88f7d8faf5ad0109e0da75aafe1e2b..1f3d31b607b7cec1f75bdcd74aa9c40b6e0a3edd 100644 (file)
@@ -4,11 +4,13 @@ KernelVersion:        3.13
 Description:
                The attributes:
 
-               pattern         - 0 (all zeros), 1 (mod63), 2 (none)
-               isoc_interval   - 1..16
-               isoc_maxpacket  - 0 - 1023 (fs), 0 - 1024 (hs/ss)
-               isoc_mult       - 0..2 (hs/ss only)
-               isoc_maxburst   - 0..15 (ss only)
-               buflen          - buffer length
-               bulk_qlen       - depth of queue for bulk
-               iso_qlen        - depth of queue for iso
+               ==============    ==================================
+               pattern           0 (all zeros), 1 (mod63), 2 (none)
+               isoc_interval     1..16
+               isoc_maxpacket    0 - 1023 (fs), 0 - 1024 (hs/ss)
+               isoc_mult         0..2 (hs/ss only)
+               isoc_maxburst     0..15 (ss only)
+               buflen            buffer length
+               bulk_qlen         depth of queue for bulk
+               iso_qlen          depth of queue for iso
+               ==============    ==================================
index 9373e2c51ea454e6de4031908ed5cdee4a04e9b6..0061b864351fa97f78f0b06311e699dd947af1ac 100644 (file)
@@ -4,11 +4,13 @@ KernelVersion:        3.11
 Description:
                The attributes:
 
-               ifname          - network device interface name associated with
+               ==========      =============================================
+               ifname          network device interface name associated with
                                this function instance
-               qmult           queue length multiplier for high and
+               qmult           queue length multiplier for high and
                                super speed
-               host_addr       MAC address of host's end of this
+               host_addr       MAC address of host's end of this
                                Ethernet over USB link
-               dev_addr        MAC address of device's end of this
+               dev_addr        MAC address of device's end of this
                                Ethernet over USB link
+               ==========      =============================================
index abfe447c848fc00ba527a9909110f98b42fbab9f..dc23fd776943b9721f175e715fc4a064caa12cfd 100644 (file)
@@ -4,11 +4,13 @@ KernelVersion:        4.14
 Description:
                The attributes:
 
-               c_chmask - capture channel mask
-               c_srate - capture sampling rate
-               c_ssize - capture sample size (bytes)
-               p_chmask - playback channel mask
-               p_srate - playback sampling rate
-               p_ssize - playback sample size (bytes)
-               req_number - the number of pre-allocated request
-                       for both capture and playback
+               ==========      ===================================
+               c_chmask        capture channel mask
+               c_srate         capture sampling rate
+               c_ssize         capture sample size (bytes)
+               p_chmask        playback channel mask
+               p_srate         playback sampling rate
+               p_ssize         playback sample size (bytes)
+               req_number      the number of pre-allocated request
+                               for both capture and playback
+               ==========      ===================================
index 2bfdd4efa9bd3683f80cc7c7f7fe49526cdfaa10..d4356c8b8cd6541516582de48c9d5479effa0b52 100644 (file)
@@ -4,9 +4,11 @@ KernelVersion: 3.18
 Description:
                The attributes:
 
-               c_chmask - capture channel mask
-               c_srate - capture sampling rate
-               c_ssize - capture sample size (bytes)
-               p_chmask - playback channel mask
-               p_srate - playback sampling rate
-               p_ssize - playback sample size (bytes)
+               =========  ============================
+               c_chmask   capture channel mask
+               c_srate    capture sampling rate
+               c_ssize    capture sample size (bytes)
+               p_chmask   playback channel mask
+               p_srate    playback sampling rate
+               p_ssize    playback sample size (bytes)
+               =========  ============================
index 809765bd95730649f89030c4441831559da8da51..ac5e11af79a81b0a8e8b57016103d4ea2090d579 100644 (file)
@@ -3,9 +3,11 @@ Date:          Dec 2014
 KernelVersion: 4.0
 Description:   UVC function directory
 
-               streaming_maxburst      - 0..15 (ss only)
-               streaming_maxpacket     - 1..1023 (fs), 1..3072 (hs/ss)
-               streaming_interval      - 1..16
+               ===================     =============================
+               streaming_maxburst      0..15 (ss only)
+               streaming_maxpacket     1..1023 (fs), 1..3072 (hs/ss)
+               streaming_interval      1..16
+               ===================     =============================
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control
 Date:          Dec 2014
@@ -13,8 +15,11 @@ KernelVersion:       4.0
 Description:   Control descriptors
 
                All attributes read only:
-               bInterfaceNumber        - USB interface number for this
-                                         streaming interface
+
+               ================        =============================
+               bInterfaceNumber        USB interface number for this
+                                       streaming interface
+               ================        =============================
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/class
 Date:          Dec 2014
@@ -47,13 +52,16 @@ KernelVersion:      4.0
 Description:   Default output terminal descriptors
 
                All attributes read only:
-               iTerminal       - index of string descriptor
-               bSourceID       - id of the terminal to which this terminal
+
+               ==============  =============================================
+               iTerminal       index of string descriptor
+               bSourceID       id of the terminal to which this terminal
                                is connected
-               bAssocTerminal  id of the input terminal to which this output
+               bAssocTerminal  id of the input terminal to which this output
                                terminal is associated
-               wTerminalType   - terminal type
-               bTerminalID     - a non-zero id of this terminal
+               wTerminalType   terminal type
+               bTerminalID     a non-zero id of this terminal
+               ==============  =============================================
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/terminal/camera
 Date:          Dec 2014
@@ -66,16 +74,19 @@ KernelVersion:      4.0
 Description:   Default camera terminal descriptors
 
                All attributes read only:
-               bmControls              - bitmap specifying which controls are
-                                       supported for the video stream
-               wOcularFocalLength      - the value of Locular
-               wObjectiveFocalLengthMax- the value of Lmin
-               wObjectiveFocalLengthMin- the value of Lmax
-               iTerminal               - index of string descriptor
-               bAssocTerminal          - id of the output terminal to which
-                                       this terminal is connected
-               wTerminalType           - terminal type
-               bTerminalID             - a non-zero id of this terminal
+
+               ========================  ====================================
+               bmControls                bitmap specifying which controls are
+                                         supported for the video stream
+               wOcularFocalLength        the value of Locular
+               wObjectiveFocalLengthMax  the value of Lmin
+               wObjectiveFocalLengthMin  the value of Lmax
+               iTerminal                 index of string descriptor
+               bAssocTerminal            id of the output terminal to which
+                                         this terminal is connected
+               wTerminalType             terminal type
+               bTerminalID               a non-zero id of this terminal
+               ========================  ====================================
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/processing
 Date:          Dec 2014
@@ -88,13 +99,16 @@ KernelVersion:      4.0
 Description:   Default processing unit descriptors
 
                All attributes read only:
-               iProcessing     - index of string descriptor
-               bmControls      - bitmap specifying which controls are
+
+               =============== ========================================
+               iProcessing     index of string descriptor
+               bmControls      bitmap specifying which controls are
                                supported for the video stream
-               wMaxMultiplier  maximum digital magnification x100
-               bSourceID       id of the terminal to which this unit is
+               wMaxMultiplier  maximum digital magnification x100
+               bSourceID       id of the terminal to which this unit is
                                connected
-               bUnitID         - a non-zero id of this unit
+               bUnitID         a non-zero id of this unit
+               =============== ========================================
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/header
 Date:          Dec 2014
@@ -114,8 +128,11 @@ KernelVersion:     4.0
 Description:   Streaming descriptors
 
                All attributes read only:
-               bInterfaceNumber        - USB interface number for this
-                                         streaming interface
+
+               ================        =============================
+               bInterfaceNumber        USB interface number for this
+                                       streaming interface
+               ================        =============================
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/class
 Date:          Dec 2014
@@ -148,13 +165,16 @@ KernelVersion:    4.0
 Description:   Default color matching descriptors
 
                All attributes read only:
-               bMatrixCoefficients     - matrix used to compute luma and
-                                       chroma values from the color primaries
-               bTransferCharacteristics- optoelectronic transfer
-                                       characteristic of the source picutre,
-                                       also called the gamma function
-               bColorPrimaries         - color primaries and the reference
-                                       white
+
+               ========================  ======================================
+               bMatrixCoefficients       matrix used to compute luma and
+                                         chroma values from the color primaries
+               bTransferCharacteristics  optoelectronic transfer
+                                         characteristic of the source picutre,
+                                         also called the gamma function
+               bColorPrimaries           color primaries and the reference
+                                         white
+               ========================  ======================================
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/mjpeg
 Date:          Dec 2014
@@ -168,47 +188,52 @@ Description:      Specific MJPEG format descriptors
 
                All attributes read only,
                except bmaControls and bDefaultFrameIndex:
-               bFormatIndex            - unique id for this format descriptor;
+
+               ===================     =====================================
+               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
+               bmaControls             this format's data for bmaControls in
                                        the streaming header
-               bmInterfaceFlags        specifies interlace information,
+               bmInterfaceFlags        specifies interlace information,
                                        read-only
-               bAspectRatioY           the X dimension of the picture aspect
+               bAspectRatioY           the X dimension of the picture aspect
                                        ratio, read-only
-               bAspectRatioX           the Y dimension of the picture aspect
+               bAspectRatioX           the Y dimension of the picture aspect
                                        ratio, read-only
-               bmFlags                 characteristics of this format,
+               bmFlags                 characteristics of this format,
                                        read-only
-               bDefaultFrameIndex      - optimum frame index for this stream
+               bDefaultFrameIndex      optimum frame index for this stream
+               ===================     =====================================
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/mjpeg/name/name
 Date:          Dec 2014
 KernelVersion: 4.0
 Description:   Specific MJPEG 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
-               dwMaxVideoFrameBufferSize- the maximum number of bytes the
-                                       compressor will produce for a video
-                                       frame or still image
-               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
+               =========================  =====================================
+               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
+               dwMaxVideoFrameBufferSize  the maximum number of bytes the
+                                          compressor will produce for a video
+                                          frame or still image
+               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/uncompressed
 Date:          Dec 2014
@@ -220,50 +245,54 @@ Date:             Dec 2014
 KernelVersion: 4.0
 Description:   Specific uncompressed format descriptors
 
-               bFormatIndex            - unique id for this format descriptor;
+               ==================      =======================================
+               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
+               bmaControls             this format's data for bmaControls in
                                        the streaming header
-               bmInterfaceFlags        specifies interlace information,
+               bmInterfaceFlags        specifies interlace information,
                                        read-only
-               bAspectRatioY           the X dimension of the picture aspect
+               bAspectRatioY           the X dimension of the picture aspect
                                        ratio, read-only
-               bAspectRatioX           the Y dimension of the picture aspect
+               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
+               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
+               guidFormat              globally unique id used to identify
                                        stream-encoding format
+               ==================      =======================================
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/uncompressed/name/name
 Date:          Dec 2014
 KernelVersion: 4.0
 Description:   Specific uncompressed 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
-               dwMaxVideoFrameBufferSize- the maximum number of bytes the
-                                       compressor will produce for a video
-                                       frame or still image
-               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
+               =========================  =====================================
+               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
+               dwMaxVideoFrameBufferSize  the maximum number of bytes the
+                                          compressor will produce for a video
+                                          frame or still image
+               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
@@ -276,17 +305,20 @@ KernelVersion:    4.0
 Description:   Specific streaming header descriptors
 
                All attributes read only:
-               bTriggerUsage           - how the host software will respond to
+
+               ====================    =====================================
+               bTriggerUsage           how the host software will respond to
                                        a hardware trigger interrupt event
-               bTriggerSupport         flag specifying if hardware
+               bTriggerSupport         flag specifying if hardware
                                        triggering is supported
-               bStillCaptureMethod     method of still image caputre
+               bStillCaptureMethod     method of still image caputre
                                        supported
-               bTerminalLink           id of the output terminal to which
+               bTerminalLink           id of the output terminal to which
                                        the video endpoint of this interface
                                        is connected
-               bmInfo                  capabilities of this video streaming
+               bmInfo                  capabilities of this video streaming
                                        interface
+               ====================    =====================================
 
 What:          /sys/class/udc/udc.name/device/gadget/video4linux/video.name/function_name
 Date:          May 2018
index 5afcd78fbdb7e324d8d12b82224622bc53921a9a..8debcb08a3b5179e065d3e0fbd4cadc836157042 100644 (file)
@@ -23,7 +23,7 @@ error injections without having to know the details of the driver-specific
 commands.
 
 Note that the output of 'error-inj' shall be valid as input to 'error-inj'.
-So this must work:
+So this must work::
 
        $ cat error-inj >einj.txt
        $ cat einj.txt >error-inj
index 2e9ae311e02d23c6dc52e58781f89ee96c3cfe09..c5d678d3914472514eca90fa67f894845a9d374e 100644 (file)
@@ -20,9 +20,13 @@ Description:    Allow the root user to disable/enable in runtime the clock
                 The user can supply a bitmask value, each bit represents
                 a different engine to disable/enable its clock gating feature.
                 The bitmask is composed of 20 bits:
-                0  -  7 : DMA channels
-                8  - 11 : MME engines
-                12 - 19 : TPC engines
+
+               =======   ============
+                0  -  7   DMA channels
+                8  - 11   MME engines
+                12 - 19   TPC engines
+               =======   ============
+
                 The bit's location of a specific engine can be determined
                 using (1 << GAUDI_ENGINE_ID_*). GAUDI_ENGINE_ID_* values
                 are defined in uapi habanalabs.h file in enum gaudi_engine_id
@@ -59,6 +63,7 @@ Description:    Allows the root user to read or write directly through the
                 the generic Linux user-space PCI mapping) because the DDR bar
                 is very small compared to the DDR memory and only the driver can
                 move the bar before and after the transaction.
+
                 If the IOMMU is disabled, it also allows the root user to read
                 or write from the host a device VA of a host mapped memory
 
@@ -73,6 +78,7 @@ Description:    Allows the root user to read or write 64 bit data directly
                 the generic Linux user-space PCI mapping) because the DDR bar
                 is very small compared to the DDR memory and only the driver can
                 move the bar before and after the transaction.
+
                 If the IOMMU is disabled, it also allows the root user to read
                 or write from the host a device VA of a host mapped memory
 
index 6546115a94dae8014be9c01322062731425568cf..ab6099daa8f5e65f3ab1bd76d2b12305cb4c930d 100644 (file)
@@ -6,7 +6,7 @@ Description:
 General information like which GPE is assigned to the EC and whether
 the global lock should get used.
 Knowing the EC GPE one can watch the amount of HW events related to
-the EC here (XY -> GPE number from /sys/kernel/debug/ec/*/gpe):
+the EC here (XY -> GPE number from `/sys/kernel/debug/ec/*/gpe`):
 /sys/firmware/acpi/interrupts/gpeXY
 
 The io file is binary and a userspace tool located here:
@@ -14,7 +14,8 @@ ftp://ftp.suse.com/pub/people/trenn/sources/ec/
 should get used to read out the 256 Embedded Controller registers
 or writing to them.
 
-CAUTION: Do not write to the Embedded Controller if you don't know
-what you are doing! Rebooting afterwards also is a good idea.
-This can influence the way your machine is cooled and fans may
-not get switched on again after you did a wrong write.
+CAUTION:
+  Do not write to the Embedded Controller if you don't know
+  what you are doing! Rebooting afterwards also is a good idea.
+  This can influence the way your machine is cooled and fans may
+  not get switched on again after you did a wrong write.
index 67b1717794d879022e36da5d0b6f69b5dec0fde9..6eee10c3d5a1ae6f5e30f114fea6200ba8d2e44f 100644 (file)
@@ -2,13 +2,19 @@ What:         /sys/kernel/debug/moxtet/input
 Date:          March 2019
 KernelVersion: 5.3
 Contact:       Marek Behún <marek.behun@nic.cz>
-Description:   (R) Read input from the shift registers, in hexadecimal.
+Description:   (Read) Read input from the shift registers, in hexadecimal.
                Returns N+1 bytes, where N is the number of Moxtet connected
                modules. The first byte is from the CPU board itself.
-               Example: 101214
-                        10: CPU board with SD card
-                        12: 2 = PCIe module, 1 = IRQ not active
-                        14: 4 = Peridot module, 1 = IRQ not active
+
+               Example::
+
+                       101214
+
+               ==  =======================================
+               10  CPU board with SD card
+               12  2 = PCIe module, 1 = IRQ not active
+               14  4 = Peridot module, 1 = IRQ not active
+               ==  =======================================
 
 What:          /sys/kernel/debug/moxtet/output
 Date:          March 2019
@@ -17,7 +23,13 @@ Contact:     Marek Behún <marek.behun@nic.cz>
 Description:   (RW) Read last written value to the shift registers, in
                hexadecimal, or write values to the shift registers, also
                in hexadecimal.
-               Example: 0102
-                        01: 01 was last written, or is to be written, to the
-                            first module's shift register
-                        02: the same for second module
+
+               Example::
+
+                   0102
+
+               ==  ================================================
+               01  01 was last written, or is to be written, to the
+                   first module's shift register
+               02  the same for second module
+               ==  ================================================
index 685d5a448423f2d9a5f303786b4ce909d13107d4..f75a655c1531d85f89a297ed9fd49bb70caca58e 100644 (file)
@@ -4,42 +4,42 @@ KernelVersion:        3.4
 Contact:       Kent Yoder <key@linux.vnet.ibm.com>
 Description:
 
-  These debugfs interfaces are built by the nx-crypto driver, built in
+These debugfs interfaces are built by the nx-crypto driver, built in
 arch/powerpc/crypto/nx.
 
 Error Detection
 ===============
 
 errors:
-- A u32 providing a total count of errors since the driver was loaded. The
-only errors counted here are those returned from the hcall, H_COP_OP.
+  A u32 providing a total count of errors since the driver was loaded. The
+  only errors counted here are those returned from the hcall, H_COP_OP.
 
 last_error:
-- The most recent non-zero return code from the H_COP_OP hcall. -EBUSY is not
-recorded here (the hcall will retry until -EBUSY goes away).
+  The most recent non-zero return code from the H_COP_OP hcall. -EBUSY is not
+  recorded here (the hcall will retry until -EBUSY goes away).
 
 last_error_pid:
-- The process ID of the process who received the most recent error from the
-hcall.
+  The process ID of the process who received the most recent error from the
+  hcall.
 
 Device Use
 ==========
 
 aes_bytes:
-- The total number of bytes encrypted using AES in any of the driver's
-supported modes.
+  The total number of bytes encrypted using AES in any of the driver's
+  supported modes.
 
 aes_ops:
-- The total number of AES operations submitted to the hardware.
+  The total number of AES operations submitted to the hardware.
 
 sha256_bytes:
-- The total number of bytes hashed by the hardware using SHA-256.
+  The total number of bytes hashed by the hardware using SHA-256.
 
 sha256_ops:
-- The total number of SHA-256 operations submitted to the hardware.
+  The total number of SHA-256 operations submitted to the hardware.
 
 sha512_bytes:
-- The total number of bytes hashed by the hardware using SHA-512.
+  The total number of bytes hashed by the hardware using SHA-512.
 
 sha512_ops:
-- The total number of SHA-512 operations submitted to the hardware.
+  The total number of SHA-512 operations submitted to the hardware.
index cf11736acb76a9e9822b1fc52a11165476f1671e..f6f65a4faea06c0fc3286b4c4b54c927f0d0fa5c 100644 (file)
@@ -4,16 +4,15 @@ KernelVersion:  2.6.20
 Contact:        Thomas Maier <balagi@justmail.de>
 Description:
 
-debugfs interface
------------------
-
 The pktcdvd module (packet writing driver) creates
 these files in debugfs:
 
 /sys/kernel/debug/pktcdvd/pktcdvd[0-7]/
-    info            (0444) Lots of driver statistics and infos.
 
-Example:
--------
+    ====            ====== ====================================
+    info            0444   Lots of driver statistics and infos.
+    ====            ====== ====================================
+
+Example::
 
-cat /sys/kernel/debug/pktcdvd/pktcdvd0/info
+    cat /sys/kernel/debug/pktcdvd/pktcdvd0/info
index 2b3255ee68fd62a37eabb2d9c90637150db822f8..326df1b74707e1753a6d351b1dd1f783d4b32a43 100644 (file)
@@ -2,8 +2,13 @@ What:          /sys/kernel/debug/turris-mox-rwtm/do_sign
 Date:          Jun 2020
 KernelVersion: 5.8
 Contact:       Marek Behún <marek.behun@nic.cz>
-Description:   (W) Message to sign with the ECDSA private key stored in
-                   device's OTP. The message must be exactly 64 bytes (since
-                   this is intended for SHA-512 hashes).
-               (R) The resulting signature, 136 bytes. This contains the R and
-                   S values of the ECDSA signature, both in big-endian format.
+Description:
+
+               ======= ===========================================================
+               (Write) Message to sign with the ECDSA private key stored in
+                       device's OTP. The message must be exactly 64 bytes
+                       (since this is intended for SHA-512 hashes).
+               (Read)  The resulting signature, 136 bytes. This contains the
+                       R and S values of the ECDSA signature, both in
+                       big-endian format.
+               ======= ===========================================================
index 9d8d9d2def5b35dd367392210d0979190e5f86c8..682e3c09ef4d610e510d81f26a681b9a6b6f2ad6 100644 (file)
@@ -27,16 +27,17 @@ Description:
                for writing, two for the type and at least a single byte of
                data.
 
-               Example:
-               // Request EC info type 3 (EC firmware build date)
-               // Corresponds with sending type 0x00f0 with
-               // MBOX = [38, 00, 03, 00]
-               $ echo 00 f0 38 00 03 00 > /sys/kernel/debug/wilco_ec/raw
-               // View the result. The decoded ASCII result "12/21/18" is
-               // included after the raw hex.
-               // Corresponds with MBOX = [00, 00, 31, 32, 2f, 32, 31, 38, ...]
-               $ cat /sys/kernel/debug/wilco_ec/raw
-               00 00 31 32 2f 32 31 2f 31 38 00 38 00 01 00 2f 00  ..12/21/18.8...
+               Example::
+
+                   // Request EC info type 3 (EC firmware build date)
+                   // Corresponds with sending type 0x00f0 with
+                   // MBOX = [38, 00, 03, 00]
+                   $ echo 00 f0 38 00 03 00 > /sys/kernel/debug/wilco_ec/raw
+                   // View the result. The decoded ASCII result "12/21/18" is
+                   // included after the raw hex.
+                   // Corresponds with MBOX = [00, 00, 31, 32, 2f, 32, 31, 38, ...]
+                   $ cat /sys/kernel/debug/wilco_ec/raw
+                   00 00 31 32 2f 32 31 2f 31 38 00 38 00 01 00 2f 00  ..12/21/18.8...
 
                Note that the first 16 bytes of the received MBOX[] will be
                printed, even if some of the data is junk, and skipping bytes
index fc919ce16008d99c74761406a9351dc275ea0316..5f3a0dc670507163afb6ce65a49b199ce483dd3c 100644 (file)
@@ -10,29 +10,29 @@ Description:
                <uapi/linux/wmi.h>
 
                1) To perform an SMBIOS call from userspace, you'll need to
-               first determine the minimum size of the calling interface
-               buffer for your machine.
-               Platforms that contain larger buffers can return larger
-               objects from the system firmware.
-               Commonly this size is either 4k or 32k.
+                  first determine the minimum size of the calling interface
+                  buffer for your machine.
+                  Platforms that contain larger buffers can return larger
+                  objects from the system firmware.
+                  Commonly this size is either 4k or 32k.
 
-               To determine the size of the buffer read() a u64 dword from
-               the WMI character device /dev/wmi/dell-smbios.
+                  To determine the size of the buffer read() a u64 dword from
+                  the WMI character device /dev/wmi/dell-smbios.
 
                2) After you've determined the minimum size of the calling
-               interface buffer, you can allocate a structure that represents
-               the structure documented above.
+                  interface buffer, you can allocate a structure that represents
+                  the structure documented above.
 
                3) In the 'length' object store the size of the buffer you
-               determined above and allocated.
+                  determined above and allocated.
 
                4) In this buffer object, prepare as necessary for the SMBIOS
-               call you're interested in.  Typically SMBIOS buffers have
-               "class", "select", and "input" defined to values that coincide
-               with the data you are interested in.
-               Documenting class/select/input values is outside of the scope
-               of this documentation. Check with the libsmbios project for
-               further documentation on these values.
+                  call you're interested in.  Typically SMBIOS buffers have
+                  "class", "select", and "input" defined to values that coincide
+                  with the data you are interested in.
+                  Documenting class/select/input values is outside of the scope
+                  of this documentation. Check with the libsmbios project for
+                  further documentation on these values.
 
                6) Run the call by using ioctl() as described in the header.
 
index 3c0bb76e3417e7ce402378e849d4ee7858ae019c..a377b6c093c9425ba9359a1766d1c8b0a9886eaa 100644 (file)
@@ -6,6 +6,7 @@ Description:    The /dev/kmsg character device node provides userspace access
                to the kernel's printk buffer.
 
                Injecting messages:
+
                Every write() to the opened device node places a log entry in
                the kernel's printk buffer.
 
@@ -21,6 +22,7 @@ Description:  The /dev/kmsg character device node provides userspace access
                the messages can always be reliably determined.
 
                Accessing the buffer:
+
                Every read() from the opened device node receives one record
                of the kernel's printk buffer.
 
@@ -48,6 +50,7 @@ Description:  The /dev/kmsg character device node provides userspace access
                if needed, without limiting the interface to a single reader.
 
                The device supports seek with the following parameters:
+
                SEEK_SET, 0
                  seek to the first entry in the buffer
                SEEK_END, 0
@@ -87,18 +90,22 @@ Description:        The /dev/kmsg character device node provides userspace access
                readable context of the message, for reliable processing in
                userspace.
 
-               Example:
-               7,160,424069,-;pci_root PNP0A03:00: host bridge window [io  0x0000-0x0cf7] (ignored)
-                SUBSYSTEM=acpi
-                DEVICE=+acpi:PNP0A03:00
-               6,339,5140900,-;NET: Registered protocol family 10
-               30,340,5690716,-;udevd[80]: starting version 181
+               Example::
+
+                 7,160,424069,-;pci_root PNP0A03:00: host bridge window [io  0x0000-0x0cf7] (ignored)
+                  SUBSYSTEM=acpi
+                  DEVICE=+acpi:PNP0A03:00
+                 6,339,5140900,-;NET: Registered protocol family 10
+                 30,340,5690716,-;udevd[80]: starting version 181
 
                The DEVICE= key uniquely identifies devices the following way:
-                 b12:8        - block dev_t
-                 c127:3       - char dev_t
-                 n8           - netdev ifindex
-                 +sound:card0 - subsystem:devname
+
+                 ============  =================
+                 b12:8         block dev_t
+                 c127:3        char dev_t
+                 n8            netdev ifindex
+                 +sound:card0  subsystem:devname
+                 ============  =================
 
                The flags field carries '-' by default. A 'c' indicates a
                fragment of a line. Note, that these hints about continuation
index 201d10319fa18b588a42246814b13b67047a7dd3..3c477ba48a31233186fa4fe106f8846c3fd5c88b 100644 (file)
@@ -17,26 +17,33 @@ Description:
                echoing a value to <securityfs>/evm made up of the
                following bits:
 
+               ===       ==================================================
                Bit       Effect
+               ===       ==================================================
                0         Enable HMAC validation and creation
                1         Enable digital signature validation
                2         Permit modification of EVM-protected metadata at
                          runtime. Not supported if HMAC validation and
                          creation is enabled.
                31        Disable further runtime modification of EVM policy
+               ===       ==================================================
 
-               For example:
+               For example::
 
-               echo 1 ><securityfs>/evm
+                 echo 1 ><securityfs>/evm
 
                will enable HMAC validation and creation
 
-               echo 0x80000003 ><securityfs>/evm
+               ::
+
+                 echo 0x80000003 ><securityfs>/evm
 
                will enable HMAC and digital signature validation and
                HMAC creation and disable all further modification of policy.
 
-               echo 0x80000006 ><securityfs>/evm
+               ::
+
+                 echo 0x80000006 ><securityfs>/evm
 
                will enable digital signature validation, permit
                modification of EVM-protected metadata and
@@ -65,7 +72,7 @@ Description:
                Shows the set of extended attributes used to calculate or
                validate the EVM signature, and allows additional attributes
                to be added at runtime. Any signatures generated after
-               additional attributes are added (and on files posessing those
+               additional attributes are added (and on files possessing those
                additional attributes) will only be valid if the same
                additional attributes are configured on system boot. Writing
                a single period (.) will lock the xattr list from any further
index 7b265fbb47e37a3f5d63da74e783d9ba91351971..66bdcd188b6c98320ae56b1dcf73585eb891fe91 100644 (file)
@@ -12,15 +12,16 @@ Description:
                The following file operations are supported:
 
                open(2)
-               Currently the only useful flags are O_RDWR.
+                 Currently the only useful flags are O_RDWR.
 
                ioctl(2)
-               Initiate various actions.
-               See the inline documentation in [include/uapi]<linux/gpio.h>
-               for descriptions of all ioctls.
+                 Initiate various actions.
+
+                 See the inline documentation in [include/uapi]<linux/gpio.h>
+                 for descriptions of all ioctls.
 
                close(2)
-               Stops and free up the I/O contexts that was associated
-               with the file descriptor.
+                 Stops and free up the I/O contexts that was associated
+                 with the file descriptor.
 
 Users:         TBD
index cd572912c593898fe82a377be4aa3dda354eaea9..e35263f97fc1a7c89c5eccf8a879223d1c81e02a 100644 (file)
@@ -15,19 +15,22 @@ Description:
                IMA appraisal, if configured, uses these file measurements
                for local measurement appraisal.
 
-               rule format: action [condition ...]
+               ::
 
-               action: measure | dont_measure | appraise | dont_appraise |
-                       audit | hash | dont_hash
-               condition:= base | lsm  [option]
+                 rule format: action [condition ...]
+
+                 action: measure | dont_measure | appraise | dont_appraise |
+                         audit | hash | dont_hash
+                 condition:= base | lsm  [option]
                        base:   [[func=] [mask=] [fsmagic=] [fsuuid=] [uid=]
                                [euid=] [fowner=] [fsname=]]
                        lsm:    [[subj_user=] [subj_role=] [subj_type=]
                                 [obj_user=] [obj_role=] [obj_type=]]
                        option: [[appraise_type=]] [template=] [permit_directio]
                                [appraise_flag=] [keyrings=]
-               base:   func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
-                               [FIRMWARE_CHECK]
+                 base:
+                       func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK]MODULE_CHECK]
+                               [FIRMWARE_CHECK]
                                [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
                                [KEXEC_CMDLINE] [KEY_CHECK]
                        mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
@@ -37,8 +40,9 @@ Description:
                        uid:= decimal value
                        euid:= decimal value
                        fowner:= decimal value
-               lsm:    are LSM specific
-               option: appraise_type:= [imasig] [imasig|modsig]
+                 lsm:  are LSM specific
+                 option:
+                       appraise_type:= [imasig] [imasig|modsig]
                        appraise_flag:= [check_blacklist]
                        Currently, blacklist check is only for files signed with appended
                        signature.
@@ -49,7 +53,7 @@ Description:
                        (eg, ima-ng). Only valid when action is "measure".
                        pcr:= decimal value
 
-               default policy:
+                 default policy:
                        # PROC_SUPER_MAGIC
                        dont_measure fsmagic=0x9fa0
                        dont_appraise fsmagic=0x9fa0
@@ -97,7 +101,8 @@ Description:
 
                Examples of LSM specific definitions:
 
-               SELinux:
+               SELinux::
+
                        dont_measure obj_type=var_log_t
                        dont_appraise obj_type=var_log_t
                        dont_measure obj_type=auditd_log_t
@@ -105,10 +110,11 @@ Description:
                        measure subj_user=system_u func=FILE_CHECK mask=MAY_READ
                        measure subj_role=system_r func=FILE_CHECK mask=MAY_READ
 
-               Smack:
+               Smack::
+
                        measure subj_user=_ func=FILE_CHECK mask=MAY_READ
 
-               Example of measure rules using alternate PCRs:
+               Example of measure rules using alternate PCRs::
 
                        measure func=KEXEC_KERNEL_CHECK pcr=4
                        measure func=KEXEC_INITRAMFS_CHECK pcr=5
index 70dcaf2481f49c99e4e5b23eee5a0f7b671e8369..e58d641443d34a415b451701362b09aaa9f1ba24 100644 (file)
@@ -6,32 +6,38 @@ Description:
                of block devices. Each line contains the following 14
                fields:
 
-                1 - major number
-                2 - minor mumber
-                3 - device name
-                4 - reads completed successfully
-                5 - reads merged
-                6 - sectors read
-                7 - time spent reading (ms)
-                8 - writes completed
-                9 - writes merged
-               10 - sectors written
-               11 - time spent writing (ms)
-               12 - I/Os currently in progress
-               13 - time spent doing I/Os (ms)
-               14 - weighted time spent doing I/Os (ms)
+               ==  ===================================
+                1  major number
+                2  minor mumber
+                3  device name
+                4  reads completed successfully
+                5  reads merged
+                6  sectors read
+                7  time spent reading (ms)
+                8  writes completed
+                9  writes merged
+               10  sectors written
+               11  time spent writing (ms)
+               12  I/Os currently in progress
+               13  time spent doing I/Os (ms)
+               14  weighted time spent doing I/Os (ms)
+               ==  ===================================
 
                Kernel 4.18+ appends four more fields for discard
                tracking putting the total at 18:
 
-               15 - discards completed successfully
-               16 - discards merged
-               17 - sectors discarded
-               18 - time spent discarding
+               ==  ===================================
+               15  discards completed successfully
+               16  discards merged
+               17  sectors discarded
+               18  time spent discarding
+               ==  ===================================
 
                Kernel 5.5+ appends two more fields for flush requests:
 
-               19 - flush requests completed successfully
-               20 - time spent flushing
+               ==  =====================================
+               19  flush requests completed successfully
+               20  time spent flushing
+               ==  =====================================
 
                For more details refer to Documentation/admin-guide/iostats.rst
index 0469781933684cb8bb6e5809e2372a6af6c2e98f..a4e31c46519442dbb42206d363ccaf869babb289 100644 (file)
@@ -14,28 +14,28 @@ Description:
                For more details, see Documentation/filesystems/proc.rst
                and the procfs man page.
 
-               Typical output looks like this:
+               Typical output looks like this::
 
-               00100000-ff709000 ---p 00000000 00:00 0          [rollup]
-               Size:               1192 kB
-               KernelPageSize:        4 kB
-               MMUPageSize:           4 kB
-               Rss:                 884 kB
-               Pss:                 385 kB
-               Pss_Anon:            301 kB
-               Pss_File:             80 kB
-               Pss_Shmem:             4 kB
-               Shared_Clean:        696 kB
-               Shared_Dirty:          0 kB
-               Private_Clean:       120 kB
-               Private_Dirty:        68 kB
-               Referenced:          884 kB
-               Anonymous:            68 kB
-               LazyFree:              0 kB
-               AnonHugePages:         0 kB
-               ShmemPmdMapped:        0 kB
-               Shared_Hugetlb:        0 kB
-               Private_Hugetlb:       0 kB
-               Swap:                  0 kB
-               SwapPss:               0 kB
-               Locked:              385 kB
+                       00100000-ff709000 ---p 00000000 00:00 0          [rollup]
+                       Size:               1192 kB
+                       KernelPageSize:        4 kB
+                       MMUPageSize:           4 kB
+                       Rss:                 884 kB
+                       Pss:                 385 kB
+                       Pss_Anon:            301 kB
+                       Pss_File:             80 kB
+                       Pss_Shmem:             4 kB
+                       Shared_Clean:        696 kB
+                       Shared_Dirty:          0 kB
+                       Private_Clean:       120 kB
+                       Private_Dirty:        68 kB
+                       Referenced:          884 kB
+                       Anonymous:            68 kB
+                       LazyFree:              0 kB
+                       AnonHugePages:         0 kB
+                       ShmemPmdMapped:        0 kB
+                       Shared_Hugetlb:        0 kB
+                       Private_Hugetlb:       0 kB
+                       Swap:                  0 kB
+                       SwapPss:               0 kB
+                       Locked:              385 kB
index d45209abdb1bd979f63f0b0b3c888038fbba2779..5b02540781a236fcb299f9c02cef872419b403d9 100644 (file)
@@ -9,25 +9,25 @@ Description:  Generic interface to platform dependent persistent storage.
                provide a generic interface to show records captured in
                the dying moments.  In the case of a panic the last part
                of the console log is captured, but other interesting
-               data can also be saved.
+               data can also be saved::
 
-               # mount -t pstore -o kmsg_bytes=8000 - /sys/fs/pstore
+                   # mount -t pstore -o kmsg_bytes=8000 - /sys/fs/pstore
 
-               $ ls -l /sys/fs/pstore/
-               total 0
-               -r--r--r-- 1 root root 7896 Nov 30 15:38 dmesg-erst-1
+                   $ ls -l /sys/fs/pstore/
+                   total 0
+                   -r--r--r-- 1 root root 7896 Nov 30 15:38 dmesg-erst-1
 
                Different users of this interface will result in different
                filename prefixes.  Currently two are defined:
 
-               "dmesg" - saved console log
-               "mce"   - architecture dependent data from fatal h/w error
+               "dmesg" - saved console log
+               "mce"   - architecture dependent data from fatal h/w error
 
                Once the information in a file has been read, removing
                the file will signal to the underlying persistent storage
-               device that it can reclaim the space for later re-use.
+               device that it can reclaim the space for later re-use::
 
-               $ rm /sys/fs/pstore/dmesg-erst-1
+                   $ rm /sys/fs/pstore/dmesg-erst-1
 
                The expectation is that all files in /sys/fs/pstore/
                will be saved elsewhere and erased from persistent store
@@ -44,4 +44,3 @@ Description:  Generic interface to platform dependent persistent storage.
                backends are available, the preferred backend may be
                set by passing the pstore.backend= argument to the kernel at
                boot time.
-
index 2322eb748b38774b2936d5411cafa091fef644ab..e34cdeeeb9d420a673f5236ff59ec99242630a40 100644 (file)
@@ -4,23 +4,27 @@ Contact:      Jerome Marchand <jmarchan@redhat.com>
 Description:
                The /sys/block/<disk>/stat files displays the I/O
                statistics of disk <disk>. They contain 11 fields:
-                1 - reads completed successfully
-                2 - reads merged
-                3 - sectors read
-                4 - time spent reading (ms)
-                5 - writes completed
-                6 - writes merged
-                7 - sectors written
-                8 - time spent writing (ms)
-                9 - I/Os currently in progress
-               10 - time spent doing I/Os (ms)
-               11 - weighted time spent doing I/Os (ms)
-               12 - discards completed
-               13 - discards merged
-               14 - sectors discarded
-               15 - time spent discarding (ms)
-               16 - flush requests completed
-               17 - time spent flushing (ms)
+
+               ==  ==============================================
+                1  reads completed successfully
+                2  reads merged
+                3  sectors read
+                4  time spent reading (ms)
+                5  writes completed
+                6  writes merged
+                7  sectors written
+                8  time spent writing (ms)
+                9  I/Os currently in progress
+               10  time spent doing I/Os (ms)
+               11  weighted time spent doing I/Os (ms)
+               12  discards completed
+               13  discards merged
+               14  sectors discarded
+               15  time spent discarding (ms)
+               16  flush requests completed
+               17  time spent flushing (ms)
+               ==  ==============================================
+
                For more details refer Documentation/admin-guide/iostats.rst
 
 
index 17f2bc7dd261c45ecb43087bf35e46665c9592a1..aa0fb500e3c9510cdd7fb5e9ffe475468cc2d86d 100644 (file)
@@ -8,11 +8,13 @@ Description:
 
                It has the following valid values:
 
+               ==      ========================================================
                0       OFF - the LED is not activated on activity
                1       BLINK_ON - the LED blinks on every 10ms when activity is
                        detected.
                2       BLINK_OFF - the LED is on when idle, and blinks off
                        every 10ms when activity is detected.
+               ==      ========================================================
 
                Note that the user must turn sw_activity OFF it they wish to
                control the activity LED via the em_message file.
index 8f070b47f3612c896abbd9c6ec90cf4284972577..14a6fe9422b327593ac42700efaf5ab54b3603c4 100644 (file)
@@ -9,9 +9,9 @@ Description:    To unmap a volume, "normal" or "force" has to be written to:
                is using the device.  When "force" is used, the device is also unmapped
                when device is in use.  All I/Os that are in progress will fail.
 
-               Example:
+               Example::
 
-               # echo "normal" > /sys/block/rnbd0/rnbd/unmap_device
+                 # echo "normal" > /sys/block/rnbd0/rnbd/unmap_device
 
 What:          /sys/block/rnbd<N>/rnbd/state
 Date:          Feb 2020
index e7898cfe5fb12e8d5e4a6d52bd48dafa2c10bb22..58abacf59b2aba5ca5ba338cbfe6396312a3ff91 100644 (file)
@@ -5,6 +5,7 @@ Description:
                This attribute indicates the full path of ACPI namespace
                object associated with the device object.  For example,
                \_SB_.PCI0.
+
                This file is not present for device objects representing
                fixed ACPI hardware features (like power and sleep
                buttons).
@@ -67,14 +68,16 @@ Description:
                The return value is a decimal integer representing the device's
                status bitmap:
 
-               Bit [0] â€“  Set if the device is present.
-               Bit [1] â€“  Set if the device is enabled and decoding its
-                          resources.
-               Bit [2] â€“  Set if the device should be shown in the UI.
-               Bit [3] â€“  Set if the device is functioning properly (cleared if
-                          device failed its diagnostics).
-               Bit [4] â€“  Set if the battery is present.
-               Bits [31:5] â€“  Reserved (must be cleared)
+               ===========  ==================================================
+               Bit [0]      Set if the device is present.
+               Bit [1]      Set if the device is enabled and decoding its
+                            resources.
+               Bit [2]      Set if the device should be shown in the UI.
+               Bit [3]      Set if the device is functioning properly (cleared
+                            if device failed its diagnostics).
+               Bit [4]      Set if the battery is present.
+               Bits [31:5]  Reserved (must be cleared)
+               ===========  ==================================================
 
                If bit [0] is clear, then bit 1 must also be clear (a device
                that is not present cannot be enabled).
index 9d11502b43907c051183a76595cdac6f041b57a8..bf2869c413e72253ba25d5ab8b373b55a6c597b6 100644 (file)
@@ -8,50 +8,50 @@ What:         /sys/bus/coresight/devices/<cti-name>/powered
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) Indicate if the CTI hardware is powered.
+Description:   (Read) Indicate if the CTI hardware is powered.
 
 What:          /sys/bus/coresight/devices/<cti-name>/ctmid
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) Display the associated CTM ID
+Description:   (Read) Display the associated CTM ID
 
 What:          /sys/bus/coresight/devices/<cti-name>/nr_trigger_cons
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) Number of devices connected to triggers on this CTI
+Description:   (Read) Number of devices connected to triggers on this CTI
 
 What:          /sys/bus/coresight/devices/<cti-name>/triggers<N>/name
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) Name of connected device <N>
+Description:   (Read) Name of connected device <N>
 
 What:          /sys/bus/coresight/devices/<cti-name>/triggers<N>/in_signals
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) Input trigger signals from connected device <N>
+Description:   (Read) Input trigger signals from connected device <N>
 
 What:          /sys/bus/coresight/devices/<cti-name>/triggers<N>/in_types
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) Functional types for the input trigger signals
+Description:   (Read) Functional types for the input trigger signals
                from connected device <N>
 
 What:          /sys/bus/coresight/devices/<cti-name>/triggers<N>/out_signals
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) Output trigger signals to connected device <N>
+Description:   (Read) Output trigger signals to connected device <N>
 
 What:          /sys/bus/coresight/devices/<cti-name>/triggers<N>/out_types
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) Functional types for the output trigger signals
+Description:   (Read) Functional types for the output trigger signals
                to connected device <N>
 
 What:          /sys/bus/coresight/devices/<cti-name>/regs/inout_sel
@@ -88,7 +88,7 @@ What:         /sys/bus/coresight/devices/<cti-name>/regs/intack
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (W) Write the INTACK register.
+Description:   (Write) Write the INTACK register.
 
 What:          /sys/bus/coresight/devices/<cti-name>/regs/appset
 Date:          March 2020
@@ -101,99 +101,99 @@ What:             /sys/bus/coresight/devices/<cti-name>/regs/appclear
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (W) Write APPCLEAR register to deactivate channel.
+Description:   (Write) Write APPCLEAR register to deactivate channel.
 
 What:          /sys/bus/coresight/devices/<cti-name>/regs/apppulse
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (W) Write APPPULSE to pulse a channel active for one clock
+Description:   (Write) Write APPPULSE to pulse a channel active for one clock
                cycle.
 
 What:          /sys/bus/coresight/devices/<cti-name>/regs/chinstatus
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) Read current status of channel inputs.
+Description:   (Read) Read current status of channel inputs.
 
 What:          /sys/bus/coresight/devices/<cti-name>/regs/choutstatus
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) read current status of channel outputs.
+Description:   (Read) read current status of channel outputs.
 
 What:          /sys/bus/coresight/devices/<cti-name>/regs/triginstatus
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) read current status of input trigger signals
+Description:   (Read) read current status of input trigger signals
 
 What:          /sys/bus/coresight/devices/<cti-name>/regs/trigoutstatus
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) read current status of output trigger signals.
+Description:   (Read) read current status of output trigger signals.
 
 What:          /sys/bus/coresight/devices/<cti-name>/channels/trigin_attach
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (W) Attach a CTI input trigger to a CTM channel.
+Description:   (Write) Attach a CTI input trigger to a CTM channel.
 
 What:          /sys/bus/coresight/devices/<cti-name>/channels/trigin_detach
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (W) Detach a CTI input trigger from a CTM channel.
+Description:   (Write) Detach a CTI input trigger from a CTM channel.
 
 What:          /sys/bus/coresight/devices/<cti-name>/channels/trigout_attach
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (W) Attach a CTI output trigger to a CTM channel.
+Description:   (Write) Attach a CTI output trigger to a CTM channel.
 
 What:          /sys/bus/coresight/devices/<cti-name>/channels/trigout_detach
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (W) Detach a CTI output trigger from a CTM channel.
+Description:   (Write) Detach a CTI output trigger from a CTM channel.
 
 What:          /sys/bus/coresight/devices/<cti-name>/channels/chan_gate_enable
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (RW) Enable CTIGATE for single channel (W) or list enabled
+Description:   (RW) Enable CTIGATE for single channel (Write) or list enabled
                channels through the gate (R).
 
 What:          /sys/bus/coresight/devices/<cti-name>/channels/chan_gate_disable
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (W) Disable CTIGATE for single channel.
+Description:   (Write) Disable CTIGATE for single channel.
 
 What:          /sys/bus/coresight/devices/<cti-name>/channels/chan_set
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (W) Activate a single channel.
+Description:   (Write) Activate a single channel.
 
 What:          /sys/bus/coresight/devices/<cti-name>/channels/chan_clear
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (W) Deactivate a single channel.
+Description:   (Write) Deactivate a single channel.
 
 What:          /sys/bus/coresight/devices/<cti-name>/channels/chan_pulse
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (W) Pulse a single channel - activate for a single clock cycle.
+Description:   (Write) Pulse a single channel - activate for a single clock cycle.
 
 What:          /sys/bus/coresight/devices/<cti-name>/channels/trigout_filtered
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) List of output triggers filtered across all connections.
+Description:   (Read) List of output triggers filtered across all connections.
 
 What:          /sys/bus/coresight/devices/<cti-name>/channels/trig_filter_enable
 Date:          March 2020
@@ -205,13 +205,13 @@ What:             /sys/bus/coresight/devices/<cti-name>/channels/chan_inuse
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) show channels with at least one attached trigger signal.
+Description:   (Read) show channels with at least one attached trigger signal.
 
 What:          /sys/bus/coresight/devices/<cti-name>/channels/chan_free
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) show channels with no attached trigger signals.
+Description:   (Read) show channels with no attached trigger signals.
 
 What:          /sys/bus/coresight/devices/<cti-name>/channels/chan_xtrigs_sel
 Date:          March 2020
@@ -224,18 +224,18 @@ What:             /sys/bus/coresight/devices/<cti-name>/channels/chan_xtrigs_in
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) Read to see input triggers connected to selected view
+Description:   (Read) Read to see input triggers connected to selected view
                channel.
 
 What:          /sys/bus/coresight/devices/<cti-name>/channels/chan_xtrigs_out
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (R) Read to see output triggers connected to selected view
+Description:   (Read) Read to see output triggers connected to selected view
                channel.
 
 What:          /sys/bus/coresight/devices/<cti-name>/channels/chan_xtrigs_reset
 Date:          March 2020
 KernelVersion  5.7
 Contact:       Mike Leach or Mathieu Poirier
-Description:   (W) Clear all channel / trigger programming.
+Description:   (Write) Clear all channel / trigger programming.
index b5f526081711878eb46f0586415f043b929aaba0..9a383f6a74ebe10cd8991d8493ac931f510b0c07 100644 (file)
@@ -4,7 +4,10 @@ KernelVersion: 3.19
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
 Description:   (RW) Add/remove a sink from a trace path.  There can be multiple
                source for a single sink.
-               ex: echo 1 > /sys/bus/coresight/devices/20010000.etb/enable_sink
+
+               ex::
+
+                 echo 1 > /sys/bus/coresight/devices/20010000.etb/enable_sink
 
 What:          /sys/bus/coresight/devices/<memory_map>.etb/trigger_cntr
 Date:          November 2014
@@ -20,21 +23,21 @@ What:               /sys/bus/coresight/devices/<memory_map>.etb/mgmt/rdp
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Defines the depth, in words, of the trace RAM in powers of
+Description:   (Read) Defines the depth, in words, of the trace RAM in powers of
                2.  The value is read directly from HW register RDP, 0x004.
 
 What:          /sys/bus/coresight/devices/<memory_map>.etb/mgmt/sts
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Shows the value held by the ETB status register.  The value
+Description:   (Read) Shows the value held by the ETB status register.  The value
                is read directly from HW register STS, 0x00C.
 
 What:          /sys/bus/coresight/devices/<memory_map>.etb/mgmt/rrp
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Shows the value held by the ETB RAM Read Pointer register
+Description:   (Read) Shows the value held by the ETB RAM Read Pointer register
                that is used to read entries from the Trace RAM over the APB
                interface.  The value is read directly from HW register RRP,
                0x014.
@@ -43,7 +46,7 @@ What:         /sys/bus/coresight/devices/<memory_map>.etb/mgmt/rwp
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Shows the value held by the ETB RAM Write Pointer register
+Description:   (Read) Shows the value held by the ETB RAM Write Pointer register
                that is used to sets the write pointer to write entries from
                the CoreSight bus into the Trace RAM. The value is read directly
                from HW register RWP, 0x018.
@@ -52,21 +55,21 @@ What:               /sys/bus/coresight/devices/<memory_map>.etb/mgmt/trg
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Similar to "trigger_cntr" above except that this value is
+Description:   (Read) Similar to "trigger_cntr" above except that this value is
                read directly from HW register TRG, 0x01C.
 
 What:          /sys/bus/coresight/devices/<memory_map>.etb/mgmt/ctl
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Shows the value held by the ETB Control register. The value
+Description:   (Read) Shows the value held by the ETB Control register. The value
                is read directly from HW register CTL, 0x020.
 
 What:          /sys/bus/coresight/devices/<memory_map>.etb/mgmt/ffsr
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Shows the value held by the ETB Formatter and Flush Status
+Description:   (Read) Shows the value held by the ETB Formatter and Flush Status
                register.  The value is read directly from HW register FFSR,
                0x300.
 
@@ -74,6 +77,6 @@ What:         /sys/bus/coresight/devices/<memory_map>.etb/mgmt/ffcr
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Shows the value held by the ETB Formatter and Flush Control
+Description:   (Read) Shows the value held by the ETB Formatter and Flush Control
                register.  The value is read directly from HW register FFCR,
                0x304.
index 924265a1295dc021f3a26969c9139a9b7e196ac5..651602a61eac82af31d878a9ba1670aa18bab798 100644 (file)
@@ -146,28 +146,28 @@ What:             /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/nr_addr_cmp
 Date:          November 2014
 KernelVersion: 3.19
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Provides the number of address comparators pairs accessible
+Description:   (Read) Provides the number of address comparators pairs accessible
                on a trace unit, as specified by bit 3:0 of register ETMCCR.
 
 What:          /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/nr_cntr
 Date:          November 2014
 KernelVersion: 3.19
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Provides the number of counters accessible on a trace unit,
+Description:   (Read) Provides the number of counters accessible on a trace unit,
                as specified by bit 15:13 of register ETMCCR.
 
 What:          /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/nr_ctxid_cmp
 Date:          November 2014
 KernelVersion: 3.19
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Provides the number of context ID comparator available on a
+Description:   (Read) Provides the number of context ID comparator available on a
                trace unit, as specified by bit 25:24 of register ETMCCR.
 
 What:          /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/reset
 Date:          November 2014
 KernelVersion: 3.19
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (W) Cancels all configuration on a trace unit and set it back
+Description:   (Write) Cancels all configuration on a trace unit and set it back
                to its boot configuration.
 
 What:          /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/seq_12_event
@@ -216,7 +216,7 @@ What:               /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/curr_seq_state
 Date:          November 2014
 KernelVersion: 3.19
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Holds the current state of the sequencer.
+Description:   (Read) Holds the current state of the sequencer.
 
 What:          /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/sync_freq
 Date:          November 2014
index 614874e2cf53602acc8c5d5b62ac9ffae66d103d..881f0cd99ce4ed7c894ec4bc35c59bf8dc7f1ecc 100644 (file)
@@ -12,75 +12,75 @@ What:               /sys/bus/coresight/devices/etm<N>/cpu
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) The CPU this tracing entity is associated with.
+Description:   (Read) The CPU this tracing entity is associated with.
 
 What:          /sys/bus/coresight/devices/etm<N>/nr_pe_cmp
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Indicates the number of PE comparator inputs that are
+Description:   (Read) Indicates the number of PE comparator inputs that are
                available for tracing.
 
 What:          /sys/bus/coresight/devices/etm<N>/nr_addr_cmp
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Indicates the number of address comparator pairs that are
+Description:   (Read) Indicates the number of address comparator pairs that are
                available for tracing.
 
 What:          /sys/bus/coresight/devices/etm<N>/nr_cntr
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Indicates the number of counters that are available for
+Description:   (Read) Indicates the number of counters that are available for
                tracing.
 
 What:          /sys/bus/coresight/devices/etm<N>/nr_ext_inp
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Indicates how many external inputs are implemented.
+Description:   (Read) Indicates how many external inputs are implemented.
 
 What:          /sys/bus/coresight/devices/etm<N>/numcidc
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Indicates the number of Context ID comparators that are
+Description:   (Read) Indicates the number of Context ID comparators that are
                available for tracing.
 
 What:          /sys/bus/coresight/devices/etm<N>/numvmidc
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Indicates the number of VMID comparators that are available
+Description:   (Read) Indicates the number of VMID comparators that are available
                for tracing.
 
 What:          /sys/bus/coresight/devices/etm<N>/nrseqstate
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Indicates the number of sequencer states that are
+Description:   (Read) Indicates the number of sequencer states that are
                implemented.
 
 What:          /sys/bus/coresight/devices/etm<N>/nr_resource
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Indicates the number of resource selection pairs that are
+Description:   (Read) Indicates the number of resource selection pairs that are
                available for tracing.
 
 What:          /sys/bus/coresight/devices/etm<N>/nr_ss_cmp
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Indicates the number of single-shot comparator controls that
+Description:   (Read) Indicates the number of single-shot comparator controls that
                are available for tracing.
 
 What:          /sys/bus/coresight/devices/etm<N>/reset
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (W) Cancels all configuration on a trace unit and set it back
+Description:   (Write) Cancels all configuration on a trace unit and set it back
                to its boot configuration.
 
 What:          /sys/bus/coresight/devices/etm<N>/mode
@@ -300,7 +300,7 @@ What:               /sys/bus/coresight/devices/etm<N>/addr_cmp_view
 Date:          December 2019
 KernelVersion: 5.5
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Print the current settings for the selected address
+Description:   (Read) Print the current settings for the selected address
                comparator.
 
 What:          /sys/bus/coresight/devices/etm<N>/sshot_idx
@@ -319,7 +319,7 @@ What:               /sys/bus/coresight/devices/etm<N>/sshot_status
 Date:          December 2019
 KernelVersion: 5.5
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Print the current value of the selected single shot
+Description:   (Read) Print the current value of the selected single shot
                status register.
 
 What:          /sys/bus/coresight/devices/etm<N>/sshot_pe_ctrl
@@ -333,111 +333,111 @@ What:           /sys/bus/coresight/devices/etm<N>/mgmt/trcoslsr
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Print the content of the OS Lock Status Register (0x304).
+Description:   (Read) Print the content of the OS Lock Status Register (0x304).
                The value it taken directly  from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/mgmt/trcpdcr
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Print the content of the Power Down Control Register
+Description:   (Read) Print the content of the Power Down Control Register
                (0x310).  The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/mgmt/trcpdsr
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Print the content of the Power Down Status Register
+Description:   (Read) Print the content of the Power Down Status Register
                (0x314).  The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/mgmt/trclsr
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Print the content of the SW Lock Status Register
+Description:   (Read) Print the content of the SW Lock Status Register
                (0xFB4).  The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/mgmt/trcauthstatus
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Print the content of the Authentication Status Register
+Description:   (Read) Print the content of the Authentication Status Register
                (0xFB8).  The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/mgmt/trcdevid
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Print the content of the Device ID Register
+Description:   (Read) Print the content of the Device ID Register
                (0xFC8).  The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/mgmt/trcdevtype
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Print the content of the Device Type Register
+Description:   (Read) Print the content of the Device Type Register
                (0xFCC).  The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/mgmt/trcpidr0
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Print the content of the Peripheral ID0 Register
+Description:   (Read) Print the content of the Peripheral ID0 Register
                (0xFE0).  The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/mgmt/trcpidr1
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Print the content of the Peripheral ID1 Register
+Description:   (Read) Print the content of the Peripheral ID1 Register
                (0xFE4).  The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/mgmt/trcpidr2
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Print the content of the Peripheral ID2 Register
+Description:   (Read) Print the content of the Peripheral ID2 Register
                (0xFE8).  The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/mgmt/trcpidr3
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Print the content of the Peripheral ID3 Register
+Description:   (Read) Print the content of the Peripheral ID3 Register
                (0xFEC).  The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/mgmt/trcconfig
 Date:          February 2016
 KernelVersion: 4.07
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Print the content of the trace configuration register
+Description:   (Read) Print the content of the trace configuration register
                (0x010) as currently set by SW.
 
 What:          /sys/bus/coresight/devices/etm<N>/mgmt/trctraceid
 Date:          February 2016
 KernelVersion: 4.07
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Print the content of the trace ID register (0x040).
+Description:   (Read) Print the content of the trace ID register (0x040).
 
 What:          /sys/bus/coresight/devices/etm<N>/trcidr/trcidr0
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Returns the tracing capabilities of the trace unit (0x1E0).
+Description:   (Read) Returns the tracing capabilities of the trace unit (0x1E0).
                The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/trcidr/trcidr1
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Returns the tracing capabilities of the trace unit (0x1E4).
+Description:   (Read) Returns the tracing capabilities of the trace unit (0x1E4).
                The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/trcidr/trcidr2
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Returns the maximum size of the data value, data address,
+Description:   (Read) Returns the maximum size of the data value, data address,
                VMID, context ID and instuction address in the trace unit
                (0x1E8).  The value is taken directly from the HW.
 
@@ -445,7 +445,7 @@ What:               /sys/bus/coresight/devices/etm<N>/trcidr/trcidr3
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Returns the value associated with various resources
+Description:   (Read) Returns the value associated with various resources
                available to the trace unit.  See the Trace Macrocell
                architecture specification for more details (0x1E8).
                The value is taken directly from the HW.
@@ -454,42 +454,42 @@ What:             /sys/bus/coresight/devices/etm<N>/trcidr/trcidr4
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Returns how many resources the trace unit supports (0x1F0).
+Description:   (Read) Returns how many resources the trace unit supports (0x1F0).
                The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/trcidr/trcidr5
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Returns how many resources the trace unit supports (0x1F4).
+Description:   (Read) Returns how many resources the trace unit supports (0x1F4).
                The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/trcidr/trcidr8
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Returns the maximum speculation depth of the instruction
+Description:   (Read) Returns the maximum speculation depth of the instruction
                trace stream. (0x180).  The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/trcidr/trcidr9
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Returns the number of P0 right-hand keys that the trace unit
+Description:   (Read) Returns the number of P0 right-hand keys that the trace unit
                can use (0x184).  The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/trcidr/trcidr10
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Returns the number of P1 right-hand keys that the trace unit
+Description:   (Read) Returns the number of P1 right-hand keys that the trace unit
                can use (0x188).  The value is taken directly from the HW.
 
 What:          /sys/bus/coresight/devices/etm<N>/trcidr/trcidr11
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Returns the number of special P1 right-hand keys that the
+Description:   (Read) Returns the number of special P1 right-hand keys that the
                trace unit can use (0x18C).  The value is taken directly from
                the HW.
 
@@ -497,7 +497,7 @@ What:               /sys/bus/coresight/devices/etm<N>/trcidr/trcidr12
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Returns the number of conditional P1 right-hand keys that
+Description:   (Read) Returns the number of conditional P1 right-hand keys that
                the trace unit can use (0x190).  The value is taken directly
                from the HW.
 
@@ -505,6 +505,6 @@ What:               /sys/bus/coresight/devices/etm<N>/trcidr/trcidr13
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Returns the number of special conditional P1 right-hand keys
+Description:   (Read) Returns the number of special conditional P1 right-hand keys
                that the trace unit can use (0x194).  The value is taken
                directly from the HW.
index 1dffabe7f48d6500e0f66d2f18c42d388051f3bb..53e1f4815d64314e6d6181978fa2ecbd77f5b9db 100644 (file)
@@ -42,7 +42,7 @@ What:         /sys/bus/coresight/devices/<memory_map>.stm/status
 Date:          April 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) List various control and status registers.  The specific
+Description:   (Read) List various control and status registers.  The specific
                layout and content is driver specific.
 
 What:          /sys/bus/coresight/devices/<memory_map>.stm/traceid
index ab49b9ac3bcb0515f85e6d4e0e660d76df5e3f8a..6aa527296c71080cbbf8ecf3ce53e375a2e70022 100644 (file)
@@ -11,21 +11,21 @@ What:           /sys/bus/coresight/devices/<memory_map>.tmc/mgmt/rsz
 Date:           March 2016
 KernelVersion:  4.7
 Contact:        Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:    (R) Defines the size, in 32-bit words, of the local RAM buffer.
+Description:    (Read) Defines the size, in 32-bit words, of the local RAM buffer.
                 The value is read directly from HW register RSZ, 0x004.
 
 What:           /sys/bus/coresight/devices/<memory_map>.tmc/mgmt/sts
 Date:           March 2016
 KernelVersion:  4.7
 Contact:        Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Shows the value held by the TMC status register.  The value
+Description:   (Read) Shows the value held by the TMC status register.  The value
                 is read directly from HW register STS, 0x00C.
 
 What:          /sys/bus/coresight/devices/<memory_map>.tmc/mgmt/rrp
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Shows the value held by the TMC RAM Read Pointer register
+Description:   (Read) Shows the value held by the TMC RAM Read Pointer register
                that is used to read entries from the Trace RAM over the APB
                interface.  The value is read directly from HW register RRP,
                0x014.
@@ -34,7 +34,7 @@ What:         /sys/bus/coresight/devices/<memory_map>.tmc/mgmt/rwp
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Shows the value held by the TMC RAM Write Pointer register
+Description:   (Read) Shows the value held by the TMC RAM Write Pointer register
                that is used to sets the write pointer to write entries from
                the CoreSight bus into the Trace RAM. The value is read directly
                from HW register RWP, 0x018.
@@ -43,21 +43,21 @@ What:               /sys/bus/coresight/devices/<memory_map>.tmc/mgmt/trg
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Similar to "trigger_cntr" above except that this value is
+Description:   (Read) Similar to "trigger_cntr" above except that this value is
                read directly from HW register TRG, 0x01C.
 
 What:          /sys/bus/coresight/devices/<memory_map>.tmc/mgmt/ctl
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Shows the value held by the TMC Control register. The value
+Description:   (Read) Shows the value held by the TMC Control register. The value
                is read directly from HW register CTL, 0x020.
 
 What:          /sys/bus/coresight/devices/<memory_map>.tmc/mgmt/ffsr
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Shows the value held by the TMC Formatter and Flush Status
+Description:   (Read) Shows the value held by the TMC Formatter and Flush Status
                register.  The value is read directly from HW register FFSR,
                0x300.
 
@@ -65,7 +65,7 @@ What:         /sys/bus/coresight/devices/<memory_map>.tmc/mgmt/ffcr
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Shows the value held by the TMC Formatter and Flush Control
+Description:   (Read) Shows the value held by the TMC Formatter and Flush Control
                register.  The value is read directly from HW register FFCR,
                0x304.
 
@@ -73,7 +73,7 @@ What:         /sys/bus/coresight/devices/<memory_map>.tmc/mgmt/mode
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Shows the value held by the TMC Mode register, which
+Description:   (Read) Shows the value held by the TMC Mode register, which
                indicate the mode the device has been configured to enact.  The
                The value is read directly from the MODE register, 0x028.
 
@@ -81,7 +81,7 @@ What:         /sys/bus/coresight/devices/<memory_map>.tmc/mgmt/devid
 Date:          March 2016
 KernelVersion: 4.7
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:   (R) Indicates the capabilities of the Coresight TMC.
+Description:   (Read) Indicates the capabilities of the Coresight TMC.
                The value is read directly from the DEVID register, 0xFC8,
 
 What:          /sys/bus/coresight/devices/<memory_map>.tmc/buffer_size
index 966f8504bd7b498274129525554b2b07195f9f25..12a733fe357fd43a8128d20cbbd6ae548e838832 100644 (file)
@@ -20,6 +20,7 @@ Contact:      Cornelia Huck <cornelia.huck@de.ibm.com>
 Description:   Contains the ids of the channel paths used by this
                subchannel, as reported by the channel subsystem
                during subchannel recognition.
+
                Note: This is an I/O-subchannel specific attribute.
 Users:         s390-tools, HAL
 
@@ -31,6 +32,7 @@ Description:  Contains the PIM/PAM/POM values, as reported by the
                channel subsystem when last queried by the common I/O
                layer (this implies that this attribute is not necessarily
                in sync with the values current in the channel subsystem).
+
                Note: This is an I/O-subchannel specific attribute.
 Users:         s390-tools, HAL
 
@@ -53,6 +55,7 @@ Description:  This file allows the driver for a device to be specified. When
                opt-out of driver binding using a driver_override name such as
                "none".  Only a single driver may be specified in the override,
                there is no support for parsing delimiters.
+
                Note that unlike the mechanism of the same name for pci, this
                file does not allow to override basic matching rules. I.e.,
                the driver must still match the subchannel type of the device.
index 23543be904f2a30ccc53c879348ed44d08f80b47..b0265ab17200987a7416d9d0865d6d53679c4b61 100644 (file)
@@ -4,6 +4,7 @@ KernelVersion:  5.10
 Contact:       Xu Yilun <yilun.xu@intel.com>
 Description:   Read-only. It returns type of DFL FIU of the device. Now DFL
                supports 2 FIU types, 0 for FME, 1 for PORT.
+
                Format: 0x%x
 
 What:          /sys/bus/dfl/devices/dfl_dev.X/feature_id
@@ -12,4 +13,5 @@ KernelVersion:        5.10
 Contact:       Xu Yilun <yilun.xu@intel.com>
 Description:   Read-only. It returns feature identifier local to its DFL FIU
                type.
+
                Format: 0x%x
index c9278a3b3df166f392a0336c81d452a050703bdb..63a32ddcb95e7f275c236f66f826a75823be78a2 100644 (file)
@@ -8,13 +8,13 @@ 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. All supported attributes are listed
-               below.
+               below::
 
                    event  = "config:0-11"  - event ID
                    evtype = "config:12-15" - event type
                    portid = "config:16-23" - event source
 
-               For example,
+               For example::
 
                    fab_mmio_read = "event=0x06,evtype=0x02,portid=0xff"
 
@@ -40,11 +40,11 @@ Description:        Read-only. Attribute group to describe performance monitoring
 
                All supported performance monitoring events are listed below.
 
-               Basic events (evtype=0x00)
+               Basic events (evtype=0x00)::
 
                    clock = "event=0x00,evtype=0x00,portid=0xff"
 
-               Cache events (evtype=0x01)
+               Cache events (evtype=0x01)::
 
                    cache_read_hit      = "event=0x00,evtype=0x01,portid=0xff"
                    cache_read_miss     = "event=0x01,evtype=0x01,portid=0xff"
@@ -59,7 +59,7 @@ Description:  Read-only. Attribute group to describe performance monitoring
                    cache_rx_req_stall  = "event=0x09,evtype=0x01,portid=0xff"
                    cache_eviction      = "event=0x0a,evtype=0x01,portid=0xff"
 
-               Fabric events (evtype=0x02)
+               Fabric events (evtype=0x02)::
 
                    fab_pcie0_read       = "event=0x00,evtype=0x02,portid=0xff"
                    fab_pcie0_write      = "event=0x01,evtype=0x02,portid=0xff"
@@ -78,7 +78,7 @@ Description:  Read-only. Attribute group to describe performance monitoring
                    fab_port_mmio_read   = "event=0x06,evtype=0x02,portid=?"
                    fab_port_mmio_write  = "event=0x07,evtype=0x02,portid=?"
 
-               VTD events (evtype=0x03)
+               VTD events (evtype=0x03)::
 
                    vtd_port_read_transaction  = "event=0x00,evtype=0x03,portid=?"
                    vtd_port_write_transaction = "event=0x01,evtype=0x03,portid=?"
@@ -88,7 +88,7 @@ Description:  Read-only. Attribute group to describe performance monitoring
                    vtd_port_devtlb_2m_fill    = "event=0x05,evtype=0x03,portid=?"
                    vtd_port_devtlb_1g_fill    = "event=0x06,evtype=0x03,portid=?"
 
-               VTD SIP events (evtype=0x04)
+               VTD SIP events (evtype=0x04)::
 
                    vtd_sip_iotlb_4k_hit  = "event=0x00,evtype=0x04,portid=0xff"
                    vtd_sip_iotlb_2m_hit  = "event=0x01,evtype=0x04,portid=0xff"
index 5bb793ec926c1f6ed84acb7abc2a48e36a440c3b..df7ccc1b2fba6b59d77f72d931519cc71833ac87 100644 (file)
@@ -10,7 +10,8 @@ Description:
                name/value pairs.
 
                Userspace must be prepared for the possibility that attributes
-               define overlapping bit ranges. For example:
+               define overlapping bit ranges. For example::
+
                        attr1 = 'config:0-23'
                        attr2 = 'config:0-7'
                        attr3 = 'config:12-35'
index 2273627df1906379c608b8785f7550226a1cc4ab..de390a010af857354f22e527db0c03cac4c6976e 100644 (file)
@@ -7,7 +7,7 @@ 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. All supported attributes are listed
-                below.
+                below::
 
                                chip = "config:16-31"
                                core  = "config:16-31"
@@ -16,9 +16,9 @@ Description:    Read-only. Attribute group to describe the magic bits
                                offset = "config:32-63"
                                vcpu = "config:16-31"
 
-               For example,
+                For example::
 
-               PM_PB_CYC =  "domain=1,offset=0x80,chip=?,lpar=0x0"
+                 PM_PB_CYC =  "domain=1,offset=0x80,chip=?,lpar=0x0"
 
                In this event, '?' after chip specifies that
                this value will be provided by user while running this event.
index 6a023b42486c610a3c4af8293b97c5a02ed5c063..12e2bf92783fbd08caaa5f60bc1c8474325a2d27 100644 (file)
@@ -7,7 +7,7 @@ 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. All supported attributes are listed
-                below.
+                below::
 
                                counter_info_version  = "config:16-23"
                                length  = "config:24-31"
@@ -20,9 +20,9 @@ Description:    Read-only. Attribute group to describe the magic bits
                                secondary_index = "config:0-15"
                                starting_index = "config:32-63"
 
-               For example,
+                For example::
 
-               processor_core_utilization_instructions_completed = "request=0x94,
+                 processor_core_utilization_instructions_completed = "request=0x94,
                                        phys_processor_idx=?,counter_info_version=0x8,
                                        length=8,offset=0x18"
 
@@ -36,6 +36,7 @@ Description:
                '0' if the hypervisor is configured to forbid access to event
                counters being accumulated by other guests and to physical
                domain event counters.
+
                '1' if that access is allowed.
 
 What:          /sys/bus/event_source/devices/hv_gpci/interface/ga
index 657df13b100d241f5aca4942c0bada25d413bf15..8fe787cc4ab70a4c0fe05949f7db84f640dddfb5 100644 (file)
@@ -3,16 +3,19 @@ Date:         August 2012
 KernelVersion: TBD
 Contact:       Robert Love <robert.w.love@intel.com>, devel@open-fcoe.org
 Description:   The FCoE bus. Attributes in this directory are control interfaces.
+
 Attributes:
 
-       ctlr_create: 'FCoE Controller' instance creation interface. Writing an
+       ctlr_create:
+                    'FCoE Controller' instance creation interface. Writing an
                     <ifname> to this file will allocate and populate sysfs with a
                     fcoe_ctlr_device (ctlr_X). The user can then configure any
                     per-port settings and finally write to the fcoe_ctlr_device's
                     'start' attribute to begin the kernel's discovery and login
                     process.
 
-       ctlr_destroy: 'FCoE Controller' instance removal interface. Writing a
+       ctlr_destroy:
+                      'FCoE Controller' instance removal interface. Writing a
                       fcoe_ctlr_device's sysfs name to this file will log the
                       fcoe_ctlr_device out of the fabric or otherwise connected
                       FCoE devices. It will also free all kernel memory allocated
@@ -32,11 +35,13 @@ Description:        'FCoE Controller' instances on the fcoe bus.
 
 Attributes:
 
-       fcf_dev_loss_tmo: Device loss timeout period (see below). Changing
+       fcf_dev_loss_tmo:
+                         Device loss timeout period (see below). Changing
                          this value will change the dev_loss_tmo for all
                          FCFs discovered by this controller.
 
-       mode:             Display or change the FCoE Controller's mode. Possible
+       mode:
+                         Display or change the FCoE Controller's mode. Possible
                          modes are 'Fabric' and 'VN2VN'. If a FCoE Controller
                          is started in 'Fabric' mode then FIP FCF discovery is
                          initiated and ultimately a fabric login is attempted.
@@ -44,23 +49,30 @@ Attributes:
                          FIP VN2VN discovery and login is performed. A FCoE
                          Controller only supports one mode at a time.
 
-       enabled:          Whether an FCoE controller is enabled or disabled.
+       enabled:
+                         Whether an FCoE controller is enabled or disabled.
                          0 if disabled, 1 if enabled. Writing either 0 or 1
                          to this file will enable or disable the FCoE controller.
 
-       lesb/link_fail:   Link Error Status Block (LESB) link failure count.
+       lesb/link_fail:
+                         Link Error Status Block (LESB) link failure count.
 
-       lesb/vlink_fail:  Link Error Status Block (LESB) virtual link
+       lesb/vlink_fail:
+                         Link Error Status Block (LESB) virtual link
                          failure count.
 
-       lesb/miss_fka:    Link Error Status Block (LESB) missed FCoE
+       lesb/miss_fka:
+                         Link Error Status Block (LESB) missed FCoE
                          Initialization Protocol (FIP) Keep-Alives (FKA).
 
-       lesb/symb_err:    Link Error Status Block (LESB) symbolic error count.
+       lesb/symb_err:
+                         Link Error Status Block (LESB) symbolic error count.
 
-       lesb/err_block:   Link Error Status Block (LESB) block error count.
+       lesb/err_block:
+                         Link Error Status Block (LESB) block error count.
 
-       lesb/fcs_error:   Link Error Status Block (LESB) Fibre Channel
+       lesb/fcs_error:
+                         Link Error Status Block (LESB) Fibre Channel
                          Services error count.
 
 Notes: ctlr_X (global increment starting at 0)
@@ -75,31 +87,41 @@ Description:        'FCoE FCF' instances on the fcoe bus. A FCF is a Fibre Channel
                Fibre Channel frames into a FC fabric. It can also take
                outbound FC frames and pack them in Ethernet packets to
                be sent to their destination on the Ethernet segment.
+
 Attributes:
 
-       fabric_name: Identifies the fabric that the FCF services.
+       fabric_name:
+                    Identifies the fabric that the FCF services.
 
-       switch_name: Identifies the FCF.
+       switch_name:
+                    Identifies the FCF.
 
-       priority:    The switch's priority amongst other FCFs on the same
+       priority:
+                    The switch's priority amongst other FCFs on the same
                     fabric.
 
-       selected:    1 indicates that the switch has been selected for use;
+       selected:
+                    1 indicates that the switch has been selected for use;
                     0 indicates that the switch will not be used.
 
-       fc_map:      The Fibre Channel MAP
+       fc_map:
+                    The Fibre Channel MAP
 
-       vfid:        The Virtual Fabric ID
+       vfid:
+                    The Virtual Fabric ID
 
-       mac:         The FCF's MAC address
+       mac:
+                    The FCF's MAC address
 
-       fka_period:  The FIP Keep-Alive period
+       fka_period:
+                    The FIP Keep-Alive period
 
        fabric_state: The internal kernel state
-                     "Unknown" - Initialization value
-                     "Disconnected" - No link to the FCF/fabric
-                     "Connected" - Host is connected to the FCF
-                     "Deleted" - FCF is being removed from the system
+
+                     - "Unknown" - Initialization value
+                     - "Disconnected" - No link to the FCF/fabric
+                     - "Connected" - Host is connected to the FCF
+                     - "Deleted" - FCF is being removed from the system
 
        dev_loss_tmo: The device loss timeout period for this FCF.
 
index 80256b8b4f26119e0d97fa455e67d4e7e5f4fdeb..bf3c6af6ad89af7e6de86d57763ecc1b7e69179a 100644 (file)
@@ -6,8 +6,10 @@ Description:
                the driver to attempt to bind to the device found at
                this location. The format for the location is Object.Id
                and is the same as found in /sys/bus/fsl-mc/devices/.
-                For example:
-               # echo dpni.2 > /sys/bus/fsl-mc/drivers/fsl_dpaa2_eth/bind
+
+                For example::
+
+                 # echo dpni.2 > /sys/bus/fsl-mc/drivers/fsl_dpaa2_eth/bind
 
 What:          /sys/bus/fsl-mc/drivers/.../unbind
 Date:          December 2016
@@ -17,5 +19,7 @@ Description:
                driver to attempt to unbind from the device found at
                this location. The format for the location is Object.Id
                and is the same as found in /sys/bus/fsl-mc/devices/.
-                For example:
-               # echo dpni.2 > /sys/bus/fsl-mc/drivers/fsl_dpaa2_eth/unbind
+
+                For example::
+
+                 # echo dpni.2 > /sys/bus/fsl-mc/drivers/fsl_dpaa2_eth/unbind
index 9de269bb0ae53a6995ec3c364338bde2228c1ba3..42dfc9399d2dc8c33bb7e8639a65951eca1638e4 100644 (file)
@@ -3,19 +3,25 @@ Date:         February 2011
 Contact:       Minkyu Kang <mk7.kang@samsung.com>
 Description:
                show what device is attached
-               NONE - no device
-               USB - USB device is attached
-               UART - UART is attached
-               CHARGER - Charger is attaced
-               JIG - JIG is attached
+
+               =======  ======================
+               NONE     no device
+               USB      USB device is attached
+               UART     UART is attached
+               CHARGER  Charger is attaced
+               JIG      JIG is attached
+               =======  ======================
 
 What:          /sys/bus/i2c/devices/.../switch
 Date:          February 2011
 Contact:       Minkyu Kang <mk7.kang@samsung.com>
 Description:
                show or set the state of manual switch
-               VAUDIO - switch to VAUDIO path
-               UART - switch to UART path
-               AUDIO - switch to AUDIO path
-               DHOST - switch to DHOST path
-               AUTO - switch automatically by device
+
+               =======  ==============================
+               VAUDIO   switch to VAUDIO path
+               UART     switch to UART path
+               AUDIO    switch to AUDIO path
+               DHOST    switch to DHOST path
+               AUTO     switch automatically by device
+               =======  ==============================
index 0b0de8cd0d13784c3427eef231184d208c2f5f82..b6c69eb80ca44d7138322dcd901cdd78e4a3867e 100644 (file)
@@ -6,15 +6,18 @@ Description:
                Value that exists only for mux devices that can be
                written to control the behaviour of the multiplexer on
                idle. Possible values:
-               -2 - disconnect on idle, i.e. deselect the last used
-                    channel, which is useful when there is a device
-                    with an address that conflicts with another
-                    device on another mux on the same parent bus.
-               -1 - leave the mux as-is, which is the most optimal
-                    setting in terms of I2C operations and is the
-                    default mode.
-               0..<nchans> - set the mux to a predetermined channel,
-                    which is useful if there is one channel that is
-                    used almost always, and you want to reduce the
-                    latency for normal operations after rare
-                    transactions on other channels
+
+               ===========  ===============================================
+               -2           disconnect on idle, i.e. deselect the last used
+                            channel, which is useful when there is a device
+                            with an address that conflicts with another
+                            device on another mux on the same parent bus.
+               -1           leave the mux as-is, which is the most optimal
+                            setting in terms of I2C operations and is the
+                            default mode.
+               0..<nchans>  set the mux to a predetermined channel,
+                            which is useful if there is one channel that is
+                            used almost always, and you want to reduce the
+                            latency for normal operations after rare
+                            transactions on other channels
+               ===========  ===============================================
index 2f332ec36f82a11e205ca7fb58f2f6956aeba1fa..1f4a2662335bb1a68cd401c1a6b85056994eb94b 100644 (file)
@@ -84,6 +84,7 @@ Description:
                by space. Modes can be "hdr-ddr", "hdr-tsp" and "hdr-tsl".
                See the I3C specification for more details about these HDR
                modes.
+
                This entry describes the HDRCAP of the master controller
                driving the bus.
 
@@ -135,6 +136,7 @@ Description:
                Expose the HDR (High Data Rate) capabilities of a device.
                Returns a list of supported HDR mode, each element is separated
                by space. Modes can be "hdr-ddr", "hdr-tsp" and "hdr-tsl".
+
                See the I3C specification for more details about these HDR
                modes.
 
index a9d51810a3bad5e1005fd450d885d585ab96f83a..df42bed09f25d8d3db72b2745e193457d8959a98 100644 (file)
@@ -15,6 +15,7 @@ Description:
                based on hardware generated events (e.g. data ready) or
                provided by a separate driver for other hardware (e.g.
                periodic timer, GPIO or high resolution timer).
+
                Contains trigger type specific elements. These do not
                generalize well and hence are not documented in this file.
                X is the IIO index of the trigger.
@@ -65,6 +66,7 @@ Contact:      linux-iio@vger.kernel.org
 Description:
                When the internal sampling clock can only take a specific set of
                frequencies, we can specify the available values with:
+
                - a small discrete set of values like "0 2 4 6 8"
                - a range with minimum, step and maximum frequencies like
                  "[min step max]"
@@ -665,6 +667,7 @@ Description:
                <type>[Y][_name]_<raw|input>_thresh_falling_value may take
                different values, but the device can only enable both thresholds
                or neither.
+
                Note the driver will assume the last p events requested are
                to be enabled where p is how many it supports (which may vary
                depending on the exact set requested. So if you want to be
@@ -719,6 +722,7 @@ Description:
                <type>[Y][_name]_<raw|input>_roc_falling_value may take
                different values, but the device can only enable both rate of
                change thresholds or neither.
+
                Note the driver will assume the last p events requested are
                to be enabled where p is however many it supports (which may
                vary depending on the exact set requested. So if you want to be
@@ -774,9 +778,11 @@ Description:
                Specifies the value of threshold that the device is comparing
                against for the events enabled by
                <type>Y[_name]_thresh[_rising|falling]_en.
+
                If separate attributes exist for the two directions, but
                direction is not specified for this attribute, then a single
                threshold value applies to both directions.
+
                The raw or input element of the name indicates whether the
                value is in raw device units or in processed units (as _raw
                and _input do on sysfs direct channel read attributes).
@@ -859,6 +865,7 @@ Description:
                If separate attributes exist for the two directions, but
                direction is not specified for this attribute, then a single
                hysteresis value applies to both directions.
+
                For falling events the hysteresis is added to the _value attribute for
                this event to get the upper threshold for when the event goes back to
                normal, for rising events the hysteresis is subtracted from the _value
@@ -905,6 +912,7 @@ Description:
                Specifies the value of rate of change threshold that the
                device is comparing against for the events enabled by
                <type>[Y][_name]_roc[_rising|falling]_en.
+
                If separate attributes exist for the two directions,
                but direction is not specified for this attribute,
                then a single threshold value applies to both directions.
@@ -1304,6 +1312,7 @@ Description:
                Proximity measurement indicating that some
                object is near the sensor, usually by observing
                reflectivity of infrared or ultrasound emitted.
+
                Often these sensors are unit less and as such conversion
                to SI units is not possible. Higher proximity measurements
                indicate closer objects, and vice versa. Units after
@@ -1449,9 +1458,12 @@ Contact: linux-iio@vger.kernel.org
 Description:
                A single positive integer specifying the maximum number of scan
                elements to wait for.
+
                Poll will block until the watermark is reached.
+
                Blocking read will wait until the minimum between the requested
                read amount or the low water mark is available.
+
                Non-blocking read will retrieve the available samples from the
                buffer even if there are less samples then watermark level. This
                allows the application to block on poll with a timeout and read
@@ -1480,11 +1492,13 @@ Description:
                device settings allows it (e.g. if a trigger is set that samples
                data differently that the hardware fifo does then hardware fifo
                will not enabled).
+
                If the hardware fifo is enabled and the level of the hardware
                fifo reaches the hardware fifo watermark level the device will
                flush its hardware fifo to the device buffer. Doing a non
                blocking read on the device when no samples are present in the
                device buffer will also force a flush.
+
                When the hardware fifo is enabled there is no need to use a
                trigger to use buffer mode since the watermark settings
                guarantees that the hardware fifo is flushed to the device
@@ -1522,6 +1536,7 @@ Description:
                A single positive integer specifying the minimum watermark level
                for the hardware fifo of this device. If the device does not
                have a hardware fifo this entry is not present.
+
                If the user sets buffer/watermark to a value less than this one,
                then the hardware watermark will remain unset.
 
@@ -1532,6 +1547,7 @@ Description:
                A single positive integer specifying the maximum watermark level
                for the hardware fifo of this device. If the device does not
                have a hardware fifo this entry is not present.
+
                If the user sets buffer/watermark to a value greater than this
                one, then the hardware watermark will be capped at this value.
 
@@ -1543,6 +1559,7 @@ Description:
                levels for the hardware fifo. This entry is optional and if it
                is not present it means that all the values between
                hwfifo_watermark_min and hwfifo_watermark_max are supported.
+
                If the user sets buffer/watermark to a value greater than
                hwfifo_watermak_min but not equal to any of the values in this
                list, the driver will chose an appropriate value for the
@@ -1604,7 +1621,8 @@ KernelVersion:    4.1.0
 Contact:       linux-iio@vger.kernel.org
 Description:
                '1' (enable) or '0' (disable) specifying the enable
-               of heater function. Same reading values apply
+               of heater function. Same reading values apply.
+
                This ABI is especially applicable for humidity sensors
                to heatup the device and get rid of any condensation
                in some humidity environment
@@ -1627,17 +1645,21 @@ Description:
                Mounting matrix for IIO sensors. This is a rotation matrix which
                informs userspace about sensor chip's placement relative to the
                main hardware it is mounted on.
+
                Main hardware placement is defined according to the local
                reference frame related to the physical quantity the sensor
                measures.
+
                Given that the rotation matrix is defined in a board specific
                way (platform data and / or device-tree), the main hardware
                reference frame definition is left to the implementor's choice
                (see below for a magnetometer example).
+
                Applications should apply this rotation matrix to samples so
                that when main hardware reference frame is aligned onto local
                reference frame, then sensor chip reference frame is also
                perfectly aligned with it.
+
                Matrix is a 3x3 unitary matrix and typically looks like
                [0, 1, 0; 1, 0, 0; 0, 0, -1]. Identity matrix
                [1, 0, 0; 0, 1, 0; 0, 0, 1] means sensor chip and main hardware
@@ -1646,8 +1668,10 @@ Description:
                For example, a mounting matrix for a magnetometer sensor informs
                userspace about sensor chip's ORIENTATION relative to the main
                hardware.
+
                More specifically, main hardware orientation is defined with
                respect to the LOCAL EARTH GEOMAGNETIC REFERENCE FRAME where :
+
                * Y is in the ground plane and positive towards magnetic North ;
                * X is in the ground plane, perpendicular to the North axis and
                  positive towards the East ;
@@ -1656,13 +1680,16 @@ Description:
                An implementor might consider that for a hand-held device, a
                'natural' orientation would be 'front facing camera at the top'.
                The main hardware reference frame could then be described as :
+
                * Y is in the plane of the screen and is positive towards the
                  top of the screen ;
                * X is in the plane of the screen, perpendicular to Y axis, and
                  positive towards the right hand side of the screen ;
                * Z is perpendicular to the screen plane and positive out of the
                  screen.
+
                Another example for a quadrotor UAV might be :
+
                * Y is in the plane of the propellers and positive towards the
                  front-view camera;
                * X is in the plane of the propellers, perpendicular to Y axis,
@@ -1704,6 +1731,7 @@ Description:
                This interface is deprecated; please use the Counter subsystem.
 
                A list of possible counting directions which are:
+
                - "up"  : counter device is increasing.
                - "down": counter device is decreasing.
 
index 2071f9bcfaa5c021fe5ef5e0fa0f9c0f6da41cab..1c2a07f7a75e17675df540c1e5b673e6182bc176 100644 (file)
@@ -5,7 +5,8 @@ Contact:        Peter Rosin <peda@axentia.se>
 Description:
                The DAC is used to find the peak level of an alternating
                voltage input signal by a binary search using the output
-               of a comparator wired to an interrupt pin. Like so:
+               of a comparator wired to an interrupt pin. Like so::
+
                                           _
                                          | \
                     input +------>-------|+ \
@@ -19,10 +20,12 @@ Description:
                            |    irq|------<-------'
                            |       |
                            '-------'
+
                The boolean invert attribute (0/1) should be set when the
                input signal is centered around the maximum value of the
                dac instead of zero. The envelope detector will search
                from below in this case and will also invert the result.
+
                The edge/level of the interrupt is also switched to its
                opposite value.
 
index f30b4c424fb60ada0e51a95d63e963dbbcd2c3d2..4b01150af397d97d5b8388312a17b88197958f98 100644 (file)
@@ -19,9 +19,11 @@ Description:
                is separately set for "GND-Open" and "Supply-Open" modes.
                Channels 0..31 have common low threshold values, but could have different
                sensing_modes.
+
                The low voltage threshold range is between 2..21V.
                Hysteresis between low and high thresholds can not be lower then 2 and
                can not be odd.
+
                If falling threshold results hysteresis to odd value then rising
                threshold is automatically subtracted by one.
 
@@ -34,10 +36,13 @@ Description:
                this value then the threshold rising event is pushed.
                Depending on in_voltageY_sensing_mode the high voltage threshold
                is separately set for "GND-Open" and "Supply-Open" modes.
+
                Channels 0..31 have common high threshold values, but could have different
                sensing_modes.
+
                The high voltage threshold range is between 3..22V.
                Hysteresis between low and high thresholds can not be lower then 2 and
                can not be odd.
+
                If rising threshold results hysteresis to odd value then falling
                threshold is automatically appended by one.
index efe4c85e3c8b59ecf481367b83cf0aad6076eb5c..1975c7a1af34670359413e531eff0c9c41152b50 100644 (file)
@@ -5,10 +5,13 @@ Description:
                The STM32 ADC can be configured to use external trigger sources
                (e.g. timers, pwm or exti gpio). Then, it can be tuned to start
                conversions on external trigger by either:
+
                - "rising-edge"
                - "falling-edge"
                - "both-edges".
+
                Reading returns current trigger polarity.
+
                Writing value before enabling conversions sets trigger polarity.
 
 What:          /sys/bus/iio/devices/triggerX/trigger_polarity_available
index 6158f831c761f7242b0c0afffcea21b1c570205e..adf24c40126f08163d3704e98ed49808414d3c25 100644 (file)
@@ -4,7 +4,7 @@ KernelVersion:  4.7
 Contact:       linux-iio@vger.kernel.org
 Description:
                Writing '1' will perform a FOC (Fast Online Calibration). The
-                corresponding calibration offsets can be read from *_calibbias
+                corresponding calibration offsets can be read from `*_calibbias`
                 entries.
 
 What:          /sys/bus/iio/devices/iio:deviceX/location
index 0e66ae9b0071e80b245796aa5b04bf2b461e39b6..91439d6d60b5c0ce0acd7924602f2a2af8b7b49a 100644 (file)
@@ -3,14 +3,20 @@ KernelVersion:        4.14
 Contact:       arnaud.pouliquen@st.com
 Description:
                For audio purpose only.
+
                Used by audio driver to set/get the spi input frequency.
+
                This is mandatory if DFSDM is slave on SPI bus, to
                provide information on the SPI clock frequency during runtime
                Notice that the SPI frequency should be a multiple of sample
                frequency to ensure the precision.
-               if DFSDM input is SPI master
+
+               if DFSDM input is SPI master:
+
                        Reading  SPI clkout frequency,
                        error on writing
+
                If DFSDM input is SPI Slave:
+
                        Reading returns value previously set.
                        Writing value before starting conversions.
index a133fd8d081ac23f74f881ef387f71c9de6fc585..40df5c9fef996efa5956222c23ca1cb3c0f53a11 100644 (file)
@@ -15,8 +15,11 @@ Description:
                first object echoed in meters. Default value is 6.020.
                This setting limits the time the driver is waiting for a
                echo.
+
                Showing the range of available values is represented as the
                minimum value, the step and the maximum value, all enclosed
                in square brackets.
-               Example:
-               [0.043 0.043 11.008]
+
+               Example::
+
+                       [0.043 0.043 11.008]
index a91aeabe7b244ff07a51bd1bd1ea935b6e7c7e4b..d065cda7dd961de9ecfd8d6fb302584fb4e421f9 100644 (file)
@@ -8,7 +8,9 @@ KernelVersion:  3.4.0
 Contact:       linux-iio@vger.kernel.org
 Description:
                Reading returns either '1' or '0'.
+
                '1' means that the clock in question is present.
+
                '0' means that the clock is missing.
 
 What:          /sys/bus/iio/devices/iio:deviceX/pllY_locked
index 302de64cb4246f21d42ffa93a5996d962ebfe7ce..544548ee794c9a39bdbac3bab5d5aa3b8accec34 100644 (file)
@@ -27,12 +27,12 @@ What:               /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_name
 KernelVersion:
 Contact:       linux-iio@vger.kernel.org
 Description:
-               Reading returns the datasheet name for channel Y:
+               Reading returns the datasheet name for channel Y::
 
-               out_altvoltage0_name: RF8x
-               out_altvoltage1_name: RFAUX8x
-               out_altvoltage2_name: RF16x
-               out_altvoltage3_name: RF32x
+                 out_altvoltage0_name: RF8x
+                 out_altvoltage1_name: RFAUX8x
+                 out_altvoltage2_name: RF16x
+                 out_altvoltage3_name: RF32x
 
 What:          /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_powerdown
 KernelVersion:
index 6adba9058b22b649d772381ae24634c1d8a0f940..66b621f10223f7443fe7cfae33434e33f8474073 100644 (file)
@@ -6,10 +6,14 @@ Description:
                Get measured values from the ADC for these stages. Y is the
                specific stage number corresponding to datasheet stage names
                as follows:
-               1 -> LED2
-               2 -> ALED2/LED3
-               3 -> LED1
-               4 -> ALED1/LED4
+
+               == ==========
+               1  LED2
+               2  ALED2/LED3
+               3  LED1
+               4  ALED1/LED4
+               == ==========
+
                Note that channels 5 and 6 represent LED2-ALED2 and LED1-ALED1
                respectively which simply helper channels containing the
                calculated difference in the value of stage 1 - 2 and 3 - 4.
index f0ce0a0476ea6f32153494a9e14d99868dd00756..220206a20d9865150eed9694ab659cde18c78b65 100644 (file)
@@ -15,5 +15,7 @@ Description:
                Scheme 0 has wider dynamic range, Scheme 1 proximity detection
                is less affected by the ambient IR noise variation.
 
-               0 Sensing IR from LED and ambient
-               1 Sensing IR from LED with ambient IR rejection
+               == =============================================
+               0  Sensing IR from LED and ambient
+               1  Sensing IR from LED with ambient IR rejection
+               == =============================================
index ad2cc63e4bf8252ace73583faa7c9fffbe6cede8..73498ff666bd74a92269bf5e1006d34571869233 100644 (file)
@@ -17,9 +17,11 @@ KernelVersion:       4.13
 Contact:       fabrice.gasnier@st.com
 Description:
                Configure the device counter quadrature modes:
+
                - non-quadrature:
                        Encoder IN1 input servers as the count input (up
                        direction).
+
                - quadrature:
                        Encoder IN1 and IN2 inputs are mixed to get direction
                        and count.
@@ -35,23 +37,26 @@ KernelVersion:      4.13
 Contact:       fabrice.gasnier@st.com
 Description:
                Configure the device encoder/counter active edge:
+
                - rising-edge
                - falling-edge
                - both-edges
 
                In non-quadrature mode, device counts up on active edge.
+
                In quadrature mode, encoder counting scenarios are as follows:
-               ----------------------------------------------------------------
+
+               +---------+----------+--------------------+--------------------+
                | Active  | Level on |      IN1 signal    |     IN2 signal     |
-               | edge    | opposite |------------------------------------------
+               | edge    | opposite +----------+---------+----------+---------+
                |         | signal   |  Rising  | Falling |  Rising  | Falling |
-               ----------------------------------------------------------------
-               | Rising  | High ->  |   Down   |    -    |    Up    |    -    |
-               | edge    | Low  ->  |    Up    |    -    |   Down   |    -    |
-               ----------------------------------------------------------------
-               | Falling | High ->  |    -     |    Up   |    -     |   Down  |
-               | edge    | Low  ->  |    -     |   Down  |    -     |    Up   |
-               ----------------------------------------------------------------
-               | Both    | High ->  |   Down   |    Up   |    Up    |   Down  |
-               | edges   | Low  ->  |    Up    |   Down  |   Down   |    Up   |
-               ----------------------------------------------------------------
+               +---------+----------+----------+---------+----------+---------+
+               | Rising  | High ->  |   Down   |    -    |   Up     |    -    |
+               | edge    | Low  ->  |   Up     |    -    |   Down   |    -    |
+               +---------+----------+----------+---------+----------+---------+
+               | Falling | High ->  |    -     |   Up    |    -     |   Down  |
+               | edge    | Low  ->  |    -     |   Down  |    -     |   Up    |
+               +---------+----------+----------+---------+----------+---------+
+               | Both    | High ->  |   Down   |   Up    |   Up     |   Down  |
+               | edges   | Low  ->  |   Up     |   Down  |   Down   |   Up    |
+               +---------+----------+----------+---------+----------+---------+
index 6275e9f56e6c3d668d8429df3986a2f3625696e7..13f099ef6a953ed4420617d040185dc95b59e869 100644 (file)
@@ -5,11 +5,16 @@ Contact:        linux-iio@vger.kernel.org
 Description:
                 Current configuration and available configurations
                for the bias current.
-               normal          - Normal measurement configurations (default)
-               positivebias    - Positive bias configuration
-               negativebias    - Negative bias configuration
-               disabled        - Only available on HMC5983. Disables magnetic
+
+               ============      ============================================
+               normal            Normal measurement configurations (default)
+               positivebias      Positive bias configuration
+               negativebias      Negative bias configuration
+               disabled          Only available on HMC5983. Disables magnetic
                                  sensor and enables temperature sensor.
-               Note: The effect of this configuration may vary
-               according to the device. For exact documentation
-               check the device's datasheet.
+               ============      ============================================
+
+               Note:
+                 The effect of this configuration may vary
+                 according to the device. For exact documentation
+                 check the device's datasheet.
index 3b3509a3ef2f78068ce349352ab6ab9601f5a565..e5ef6d8e5da11dca0f86b99fdd754fda711f7141 100644 (file)
@@ -5,9 +5,12 @@ Description:
                Open-circuit fault. The detection of open-circuit faults,
                such as those caused by broken thermocouple wires.
                Reading returns either '1' or '0'.
-               '1' = An open circuit such as broken thermocouple wires
-                     has been detected.
-               '0' = No open circuit or broken thermocouple wires are detected
+
+               ===  =======================================================
+               '1'  An open circuit such as broken thermocouple wires
+                    has been detected.
+               '0'  No open circuit or broken thermocouple wires are detected
+               ===  =======================================================
 
 What:          /sys/bus/iio/devices/iio:deviceX/fault_ovuv
 KernelVersion: 5.1
@@ -18,7 +21,11 @@ Description:
                cables by integrated MOSFETs at the T+ and T- inputs, and the
                BIAS output. These MOSFETs turn off when the input voltage is
                negative or greater than VDD.
+
                Reading returns either '1' or '0'.
-               '1' = The input voltage is negative or greater than VDD.
-               '0' = The input voltage is positive and less than VDD (normal
-               state).
+
+               ===  =======================================================
+               '1'  The input voltage is negative or greater than VDD.
+               '0'  The input voltage is positive and less than VDD (normal
+                    state).
+               ===  =======================================================
index b7259234ad70081172e26dd3b9ccc19ef62556d0..c4a4497c249aa5e154c06d9cf6056e7c97418264 100644 (file)
@@ -3,67 +3,85 @@ KernelVersion:        4.11
 Contact:       benjamin.gaignard@st.com
 Description:
                Reading returns the list possible master modes which are:
-               - "reset"     : The UG bit from the TIMx_EGR register is
+
+
+               - "reset"
+                               The UG bit from the TIMx_EGR register is
                                used as trigger output (TRGO).
-               - "enable"    : The Counter Enable signal CNT_EN is used
+               - "enable"
+                               The Counter Enable signal CNT_EN is used
                                as trigger output.
-               - "update"    : The update event is selected as trigger output.
+               - "update"
+                               The update event is selected as trigger output.
                                For instance a master timer can then be used
                                as a prescaler for a slave timer.
-               - "compare_pulse" : The trigger output send a positive pulse
-                                   when the CC1IF flag is to be set.
-               - "OC1REF"    : OC1REF signal is used as trigger output.
-               - "OC2REF"    : OC2REF signal is used as trigger output.
-               - "OC3REF"    : OC3REF signal is used as trigger output.
-               - "OC4REF"    : OC4REF signal is used as trigger output.
+               - "compare_pulse"
+                               The trigger output send a positive pulse
+                               when the CC1IF flag is to be set.
+               - "OC1REF"
+                               OC1REF signal is used as trigger output.
+               - "OC2REF"
+                               OC2REF signal is used as trigger output.
+               - "OC3REF"
+                               OC3REF signal is used as trigger output.
+               - "OC4REF"
+                               OC4REF signal is used as trigger output.
+
                Additional modes (on TRGO2 only):
-               - "OC5REF"    : OC5REF signal is used as trigger output.
-               - "OC6REF"    : OC6REF signal is used as trigger output.
+
+               - "OC5REF"
+                               OC5REF signal is used as trigger output.
+               - "OC6REF"
+                               OC6REF signal is used as trigger output.
                - "compare_pulse_OC4REF":
-                 OC4REF rising or falling edges generate pulses.
+                               OC4REF rising or falling edges generate pulses.
                - "compare_pulse_OC6REF":
-                 OC6REF rising or falling edges generate pulses.
+                               OC6REF rising or falling edges generate pulses.
                - "compare_pulse_OC4REF_r_or_OC6REF_r":
-                 OC4REF or OC6REF rising edges generate pulses.
+                               OC4REF or OC6REF rising edges generate pulses.
                - "compare_pulse_OC4REF_r_or_OC6REF_f":
-                 OC4REF rising or OC6REF falling edges generate pulses.
+                               OC4REF rising or OC6REF falling edges generate
+                               pulses.
                - "compare_pulse_OC5REF_r_or_OC6REF_r":
-                 OC5REF or OC6REF rising edges generate pulses.
+                               OC5REF or OC6REF rising edges generate pulses.
                - "compare_pulse_OC5REF_r_or_OC6REF_f":
-                 OC5REF rising or OC6REF falling edges generate pulses.
-
-               +-----------+   +-------------+            +---------+
-               | Prescaler +-> | Counter     |        +-> | Master  | TRGO(2)
-               +-----------+   +--+--------+-+        |-> | Control +-->
-                                  |        |          ||  +---------+
-                               +--v--------+-+ OCxREF ||  +---------+
-                               | Chx compare +----------> | Output  | ChX
-                               +-----------+-+         |  | Control +-->
-                                     .     |           |  +---------+
-                                     .     |           |    .
-                               +-----------v-+ OC6REF  |    .
-                               | Ch6 compare +---------+>
-                               +-------------+
-
-               Example with: "compare_pulse_OC4REF_r_or_OC6REF_r":
-
-                               X
-                             X   X
-                           X .   . X
-                         X   .   .   X
-                       X     .   .     X
-               count X .     .   .     . X
-                       .     .   .     .
-                       .     .   .     .
-                       +---------------+
-               OC4REF  |     .   .     |
-                     +-+     .   .     +-+
-                       .     +---+     .
-               OC6REF  .     |   |     .
-                     +-------+   +-------+
-                       +-+   +-+
-               TRGO2   | |   | |
-                     +-+ +---+ +---------+
+                               OC5REF rising or OC6REF falling edges generate
+                               pulses.
+
+               ::
+
+                 +-----------+   +-------------+            +---------+
+                 | Prescaler +-> | Counter     |        +-> | Master  | TRGO(2)
+                 +-----------+   +--+--------+-+        |-> | Control +-->
+                                    |        |          ||  +---------+
+                                 +--v--------+-+ OCxREF ||  +---------+
+                                 | Chx compare +----------> | Output  | ChX
+                                 +-----------+-+         |  | Control +-->
+                                       .     |           |  +---------+
+                                       .     |           |    .
+                                 +-----------v-+ OC6REF  |    .
+                                 | Ch6 compare +---------+>
+                                 +-------------+
+
+               Example with: "compare_pulse_OC4REF_r_or_OC6REF_r"::
+
+                                 X
+                               X   X
+                             X .   . X
+                           X   .   .   X
+                         X     .   .     X
+                 count X .     .   .     . X
+                         .     .   .     .
+                         .     .   .     .
+                         +---------------+
+                 OC4REF  |     .   .     |
+                       +-+     .   .     +-+
+                         .     +---+     .
+                 OC6REF  .     |   |     .
+                       +-------+   +-------+
+                         +-+   +-+
+                 TRGO2   | |   | |
+                       +-+ +---+ +---------+
 
 What:          /sys/bus/iio/devices/triggerX/master_mode
 KernelVersion: 4.11
@@ -104,6 +122,7 @@ Description:
                Configure the device counter enable modes, in all case
                counting direction is set by in_count0_count_direction
                attribute and the counter is clocked by the internal clock.
+
                always:
                        Counter is always ON.
 
index 22d0843849a85bd21dcea6045f293a67b7007df2..b7b2278fe0421c6ee5228cb334032e8e889f9e14 100644 (file)
@@ -10,10 +10,13 @@ Date:               June 2015
 KernelVersion: 4.3
 Contact:       Alexander Shishkin <alexander.shishkin@linux.intel.com>
 Description:   (RO) Output port type:
-                 0: not present,
-                 1: MSU (Memory Storage Unit)
-                 2: CTP (Common Trace Port)
-                 4: PTI (MIPI PTI).
+
+                ==  =========================
+                 0  not present,
+                 1  MSU (Memory Storage Unit)
+                 2  CTP (Common Trace Port)
+                 4  PTI (MIPI PTI).
+                ==  =========================
 
 What:          /sys/bus/intel_th/devices/<intel_th_id>-gth/outputs/[0-7]_drop
 Date:          June 2015
index 7fd2601c2831b3ad1392b4615681f123fbc70572..a74252e580a564b833bf4fa06c4c53dc71e61586 100644 (file)
@@ -9,11 +9,13 @@ Date:         June 2015
 KernelVersion: 4.3
 Contact:       Alexander Shishkin <alexander.shishkin@linux.intel.com>
 Description:   (RW) Configure MSC operating mode:
+
                  - "single", for contiguous buffer mode (high-order alloc);
                  - "multi", for multiblock mode;
                  - "ExI", for DCI handler mode;
                  - "debug", for debug mode;
                  - any of the currently loaded buffer sinks.
+
                If operating mode changes, existing buffer is deallocated,
                provided there are no active users and tracing is not enabled,
                otherwise the write will fail.
@@ -23,10 +25,12 @@ Date:               June 2015
 KernelVersion: 4.3
 Contact:       Alexander Shishkin <alexander.shishkin@linux.intel.com>
 Description:   (RW) Configure MSC buffer size for "single" or "multi" modes.
+
                In single mode, this is a single number of pages, has to be
                power of 2. In multiblock mode, this is a comma-separated list
                of numbers of pages for each window to be allocated. Number of
                windows is not limited.
+
                Writing to this file deallocates existing buffer (provided
                there are no active users and tracing is not enabled) and then
                allocates a new one.
index ec0a603d804ba0785a9725ca8d8c0feba4506115..38cc03e408e7be39c2f111390fb0c2f4f75be526 100644 (file)
@@ -235,7 +235,8 @@ KernelVersion:      4.15
 Contact:       Christian Gromm <christian.gromm@microchip.com>
 Description:
                This is to read back the configured direction of the channel.
-               The following strings will be accepted:
+               The following strings will be accepted::
+
                        'tx',
                        'rx'
 Users:
@@ -246,7 +247,8 @@ KernelVersion:      4.15
 Contact:       Christian Gromm <christian.gromm@microchip.com>
 Description:
                This is to read back the configured data type of the channel.
-               The following strings will be accepted:
+               The following strings will be accepted::
+
                        'control',
                        'async',
                        'sync',
index 355958527fa357b51576c574ca46a68b6d01f2df..4a6d61b44f3f4fb59323c21963691455f4dc8be3 100644 (file)
@@ -2,16 +2,16 @@ What:         /sys/bus/moxtet/devices/moxtet-<name>.<addr>/module_description
 Date:          March 2019
 KernelVersion: 5.3
 Contact:       Marek Behún <marek.behun@nic.cz>
-Description:   (R) Moxtet module description. Format: string
+Description:   (Read) Moxtet module description. Format: string
 
 What:          /sys/bus/moxtet/devices/moxtet-<name>.<addr>/module_id
 Date:          March 2019
 KernelVersion: 5.3
 Contact:       Marek Behún <marek.behun@nic.cz>
-Description:   (R) Moxtet module ID. Format: %x
+Description:   (Read) Moxtet module ID. Format: %x
 
 What:          /sys/bus/moxtet/devices/moxtet-<name>.<addr>/module_name
 Date:          March 2019
 KernelVersion: 5.3
 Contact:       Marek Behún <marek.behun@nic.cz>
-Description:   (R) Moxtet module name. Format: string
+Description:   (Read) Moxtet module name. Format: string
index e4f76e7eab938cff005f78518b2326833bb9d6b7..63ef0b9ecce70be910ff1d3da30be7565d3642be 100644 (file)
@@ -1,4 +1,4 @@
-For all of the nmem device attributes under nfit/*, see the 'NVDIMM Firmware
+For all of the nmem device attributes under ``nfit/*``, see the 'NVDIMM Firmware
 Interface Table (NFIT)' section in the ACPI specification
 (http://www.uefi.org/specifications) for more details.
 
index d64380262be8cffa9bcbce619ae3818210ac8a72..bff84a16812a0c5e17c9f0f95eee1dac407084a1 100644 (file)
@@ -1,2 +1,8 @@
+What:          nvdimm
+Date:          July 2020
+KernelVersion: 5.8
+Contact:       Dan Williams <dan.j.williams@intel.com>
+Description:
+
 The libnvdimm sub-system implements a common sysfs interface for
 platform nvdimm resources. See Documentation/driver-api/nvdimm/.
index c1a67275c43f84623959575a6fddf8fd8e5c3c64..8316c33862a047b86fb508a75122bcae16ca9768 100644 (file)
@@ -11,19 +11,26 @@ Description:
                at 'Documentation/powerpc/papr_hcalls.rst' . Below are
                the flags reported in this sysfs file:
 
-               * "not_armed"   : Indicates that NVDIMM contents will not
+               * "not_armed"
+                                 Indicates that NVDIMM contents will not
                                  survive a power cycle.
-               * "flush_fail"  : Indicates that NVDIMM contents
+               * "flush_fail"
+                                 Indicates that NVDIMM contents
                                  couldn't be flushed during last
                                  shut-down event.
-               * "restore_fail": Indicates that NVDIMM contents
+               * "restore_fail"
+                                 Indicates that NVDIMM contents
                                  couldn't be restored during NVDIMM
                                  initialization.
-               * "encrypted"   : NVDIMM contents are encrypted.
-               * "smart_notify": There is health event for the NVDIMM.
-               * "scrubbed"    : Indicating that contents of the
+               * "encrypted"
+                                 NVDIMM contents are encrypted.
+               * "smart_notify"
+                                 There is health event for the NVDIMM.
+               * "scrubbed"
+                                 Indicating that contents of the
                                  NVDIMM have been scrubbed.
-               * "locked"      : Indicating that NVDIMM contents cant
+               * "locked"
+                                 Indicating that NVDIMM contents cant
                                  be modified until next power cycle.
 
 What:          /sys/bus/nd/devices/nmemX/papr/perf_stats
@@ -51,4 +58,4 @@ Description:
                * "MedWDur " : Media Write Duration
                * "CchRHCnt" : Cache Read Hit Count
                * "CchWHCnt" : Cache Write Hit Count
-               * "FastWCnt" : Fast Write Count
\ No newline at end of file
+               * "FastWCnt" : Fast Write Count
index 450296cc7948ecbaab3e70446bcba5b0d1e8807b..77ad9ec3c801966213147ee5c18273f48edda9b0 100644 (file)
@@ -7,8 +7,10 @@ Description:
                this location.  This is useful for overriding default
                bindings.  The format for the location is: DDDD:BB:DD.F.
                That is Domain:Bus:Device.Function and is the same as
-               found in /sys/bus/pci/devices/.  For example:
-               # echo 0000:00:19.0 > /sys/bus/pci/drivers/foo/bind
+               found in /sys/bus/pci/devices/.  For example::
+
+                 # echo 0000:00:19.0 > /sys/bus/pci/drivers/foo/bind
+
                (Note: kernels before 2.6.28 may require echo -n).
 
 What:          /sys/bus/pci/drivers/.../unbind
@@ -20,8 +22,10 @@ Description:
                this location.  This may be useful when overriding default
                bindings.  The format for the location is: DDDD:BB:DD.F.
                That is Domain:Bus:Device.Function and is the same as
-               found in /sys/bus/pci/devices/. For example:
-               # echo 0000:00:19.0 > /sys/bus/pci/drivers/foo/unbind
+               found in /sys/bus/pci/devices/. For example::
+
+                 # echo 0000:00:19.0 > /sys/bus/pci/drivers/foo/unbind
+
                (Note: kernels before 2.6.28 may require echo -n).
 
 What:          /sys/bus/pci/drivers/.../new_id
@@ -38,8 +42,9 @@ Description:
                Class, Class Mask, and Private Driver Data.  The Vendor ID
                and Device ID fields are required, the rest are optional.
                Upon successfully adding an ID, the driver will probe
-               for the device and attempt to bind to it.  For example:
-               # echo "8086 10f5" > /sys/bus/pci/drivers/foo/new_id
+               for the device and attempt to bind to it.  For example::
+
+                 # echo "8086 10f5" > /sys/bus/pci/drivers/foo/new_id
 
 What:          /sys/bus/pci/drivers/.../remove_id
 Date:          February 2009
@@ -54,8 +59,9 @@ Description:
                required, the rest are optional.  After successfully
                removing an ID, the driver will no longer support the
                device.  This is useful to ensure auto probing won't
-               match the driver to the device.  For example:
-               # echo "8086 10f5" > /sys/bus/pci/drivers/foo/remove_id
+               match the driver to the device.  For example::
+
+                 # echo "8086 10f5" > /sys/bus/pci/drivers/foo/remove_id
 
 What:          /sys/bus/pci/rescan
 Date:          January 2009
index 3c9a8c4a25eb89a87448f18fd7b550b4c5e74c55..860db53037a58fae2faa10fcfc8672c0ed20ace9 100644 (file)
@@ -1,6 +1,6 @@
-==========================
 PCIe Device AER statistics
-==========================
+--------------------------
+
 These attributes show up under all the devices that are AER capable. These
 statistical counters indicate the errors "as seen/reported by the device".
 Note that this may mean that if an endpoint is causing problems, the AER
@@ -17,19 +17,18 @@ Description:        List of correctable errors seen and reported by this
                PCI device using ERR_COR. Note that since multiple errors may
                be reported using a single ERR_COR message, thus
                TOTAL_ERR_COR at the end of the file may not match the actual
-               total of all the errors in the file. Sample output:
--------------------------------------------------------------------------
-localhost /sys/devices/pci0000:00/0000:00:1c.0 # cat aer_dev_correctable
-Receiver Error 2
-Bad TLP 0
-Bad DLLP 0
-RELAY_NUM Rollover 0
-Replay Timer Timeout 0
-Advisory Non-Fatal 0
-Corrected Internal Error 0
-Header Log Overflow 0
-TOTAL_ERR_COR 2
--------------------------------------------------------------------------
+               total of all the errors in the file. Sample output::
+
+                   localhost /sys/devices/pci0000:00/0000:00:1c.0 # cat aer_dev_correctable
+                   Receiver Error 2
+                   Bad TLP 0
+                   Bad DLLP 0
+                   RELAY_NUM Rollover 0
+                   Replay Timer Timeout 0
+                   Advisory Non-Fatal 0
+                   Corrected Internal Error 0
+                   Header Log Overflow 0
+                   TOTAL_ERR_COR 2
 
 What:          /sys/bus/pci/devices/<dev>/aer_dev_fatal
 Date:          July 2018
@@ -39,28 +38,27 @@ Description:        List of uncorrectable fatal errors seen and reported by this
                PCI device using ERR_FATAL. Note that since multiple errors may
                be reported using a single ERR_FATAL message, thus
                TOTAL_ERR_FATAL at the end of the file may not match the actual
-               total of all the errors in the file. Sample output:
--------------------------------------------------------------------------
-localhost /sys/devices/pci0000:00/0000:00:1c.0 # cat aer_dev_fatal
-Undefined 0
-Data Link Protocol 0
-Surprise Down Error 0
-Poisoned TLP 0
-Flow Control Protocol 0
-Completion Timeout 0
-Completer Abort 0
-Unexpected Completion 0
-Receiver Overflow 0
-Malformed TLP 0
-ECRC 0
-Unsupported Request 0
-ACS Violation 0
-Uncorrectable Internal Error 0
-MC Blocked TLP 0
-AtomicOp Egress Blocked 0
-TLP Prefix Blocked Error 0
-TOTAL_ERR_FATAL 0
--------------------------------------------------------------------------
+               total of all the errors in the file. Sample output::
+
+                   localhost /sys/devices/pci0000:00/0000:00:1c.0 # cat aer_dev_fatal
+                   Undefined 0
+                   Data Link Protocol 0
+                   Surprise Down Error 0
+                   Poisoned TLP 0
+                   Flow Control Protocol 0
+                   Completion Timeout 0
+                   Completer Abort 0
+                   Unexpected Completion 0
+                   Receiver Overflow 0
+                   Malformed TLP 0
+                   ECRC 0
+                   Unsupported Request 0
+                   ACS Violation 0
+                   Uncorrectable Internal Error 0
+                   MC Blocked TLP 0
+                   AtomicOp Egress Blocked 0
+                   TLP Prefix Blocked Error 0
+                   TOTAL_ERR_FATAL 0
 
 What:          /sys/bus/pci/devices/<dev>/aer_dev_nonfatal
 Date:          July 2018
@@ -70,32 +68,31 @@ Description:        List of uncorrectable nonfatal errors seen and reported by this
                PCI device using ERR_NONFATAL. Note that since multiple errors
                may be reported using a single ERR_FATAL message, thus
                TOTAL_ERR_NONFATAL at the end of the file may not match the
-               actual total of all the errors in the file. Sample output:
--------------------------------------------------------------------------
-localhost /sys/devices/pci0000:00/0000:00:1c.0 # cat aer_dev_nonfatal
-Undefined 0
-Data Link Protocol 0
-Surprise Down Error 0
-Poisoned TLP 0
-Flow Control Protocol 0
-Completion Timeout 0
-Completer Abort 0
-Unexpected Completion 0
-Receiver Overflow 0
-Malformed TLP 0
-ECRC 0
-Unsupported Request 0
-ACS Violation 0
-Uncorrectable Internal Error 0
-MC Blocked TLP 0
-AtomicOp Egress Blocked 0
-TLP Prefix Blocked Error 0
-TOTAL_ERR_NONFATAL 0
--------------------------------------------------------------------------
+               actual total of all the errors in the file. Sample output::
+
+                   localhost /sys/devices/pci0000:00/0000:00:1c.0 # cat aer_dev_nonfatal
+                   Undefined 0
+                   Data Link Protocol 0
+                   Surprise Down Error 0
+                   Poisoned TLP 0
+                   Flow Control Protocol 0
+                   Completion Timeout 0
+                   Completer Abort 0
+                   Unexpected Completion 0
+                   Receiver Overflow 0
+                   Malformed TLP 0
+                   ECRC 0
+                   Unsupported Request 0
+                   ACS Violation 0
+                   Uncorrectable Internal Error 0
+                   MC Blocked TLP 0
+                   AtomicOp Egress Blocked 0
+                   TLP Prefix Blocked Error 0
+                   TOTAL_ERR_NONFATAL 0
 
-============================
 PCIe Rootport AER statistics
-============================
+----------------------------
+
 These attributes show up under only the rootports (or root complex event
 collectors) that are AER capable. These indicate the number of error messages as
 "reported to" the rootport. Please note that the rootports also transmit
index 8a200f4eefbd7557b4d8739e746e6ef8f3355c3e..f85db86d63e834b50a734dec6cbdd7dd0312c218 100644 (file)
@@ -4,6 +4,7 @@ Contact:        Cezary Rojewski <cezary.rojewski@intel.com>
 Description:
                Version of AudioDSP firmware ASoC catpt driver is
                communicating with.
+
                Format: %d.%d.%d.%d, type:major:minor:build.
 
 What:          /sys/devices/pci0000:00/<dev>/fw_info
index 60c60fa624b2a063ea762d47f28b87847d041550..c90d97a80855244e7231f2bd44c11c412aeb986d 100644 (file)
@@ -21,11 +21,11 @@ Description:
                number returns the port to normal operation.
 
                For example: To force the high-speed device attached to
-               port 4 on bus 2 to run at full speed:
+               port 4 on bus 2 to run at full speed::
 
                        echo 4 >/sys/bus/usb/devices/usb2/../companion
 
-               To return the port to high-speed operation:
+               To return the port to high-speed operation::
 
                        echo -4 >/sys/bus/usb/devices/usb2/../companion
 
index 13208b27dd87d5e70c2269ca9d9186de4a6bea74..634ea207a50a9d1b9e982ed69c24c8106719de72 100644 (file)
@@ -4,24 +4,27 @@ Description:
                an individual subdirectory with the following name format of
                device_name "nn:d:iiii", where:
 
-               nn   - two-digit hexadecimal ID of RapidIO network where the
+               ====   ========================================================
+               nn     two-digit hexadecimal ID of RapidIO network where the
                       device resides
-               d    - device type: 'e' - for endpoint or 's' - for switch
-               iiii - four-digit device destID for endpoints, or switchID for
+               d      device type: 'e' - for endpoint or 's' - for switch
+               iiii   four-digit device destID for endpoints, or switchID for
                       switches
+               ====   ========================================================
 
                For example, below is a list of device directories that
                represents a typical RapidIO network with one switch, one host,
                and two agent endpoints, as it is seen by the enumerating host
-               (with destID = 1):
+               (with destID = 1)::
 
-               /sys/bus/rapidio/devices/00:e:0000
-               /sys/bus/rapidio/devices/00:e:0002
-               /sys/bus/rapidio/devices/00:s:0001
+                 /sys/bus/rapidio/devices/00:e:0000
+                 /sys/bus/rapidio/devices/00:e:0002
+                 /sys/bus/rapidio/devices/00:s:0001
 
-               NOTE: An enumerating or discovering endpoint does not create a
-               sysfs entry for itself, this is why an endpoint with destID=1 is
-               not shown in the list.
+               NOTE:
+                 An enumerating or discovering endpoint does not create a
+                 sysfs entry for itself, this is why an endpoint with destID=1
+                 is not shown in the list.
 
 Attributes Common for All RapidIO Devices
 -----------------------------------------
index cc30bee8b5f4430be0e10322ee14cb7cc25f98a8..417a2fe21be1effd9bde442199a6b217c9011c52 100644 (file)
@@ -7,6 +7,8 @@ Description:
 
                Usage: <mon ip addr> <options> <pool name> <rbd image name> [<snap name>]
 
+               Example::
+
                 $ echo "192.168.0.1 name=admin rbd foo" > /sys/bus/rbd/add
 
                The snapshot name can be "-" or omitted to map the image
@@ -23,6 +25,8 @@ Description:
 
                Usage: <dev-id> [force]
 
+               Example::
+
                 $ echo 2 > /sys/bus/rbd/remove
 
                Optional "force" argument which when passed will wait for
@@ -80,26 +84,29 @@ Date:               Oct, 2010
 KernelVersion: v2.6.37
 Contact:       Sage Weil <sage@newdream.net>
 Description:
-               size:           (RO) The size (in bytes) of the mapped block
+
+               ==============  ================================================
+               size            (RO) The size (in bytes) of the mapped block
                                device.
 
-               major:          (RO) The block device major number.
+               major           (RO) The block device major number.
 
-               client_id:      (RO) The ceph unique client id that was assigned
+               client_id       (RO) The ceph unique client id that was assigned
                                for this specific session.
 
-               pool:           (RO) The name of the storage pool where this rbd
+               pool            (RO) The name of the storage pool where this rbd
                                image resides. An rbd image name is unique
                                within its pool.
 
-               name:           (RO) The name of the rbd image.
+               name            (RO) The name of the rbd image.
 
-               refresh:        (WO) Writing to this file will reread the image
+               refresh         (WO) Writing to this file will reread the image
                                header data and set all relevant data structures
                                accordingly.
 
-               current_snap:   (RO) The current snapshot for which the device
+               current_snap    (RO) The current snapshot for which the device
                                is mapped.
+               ==============  ================================================
 
 
 What:          /sys/bus/rbd/devices/<dev-id>/pool_id
@@ -117,11 +124,13 @@ Date:             Oct, 2012
 KernelVersion: v3.7
 Contact:       Sage Weil <sage@newdream.net>
 Description:
-               image_id:       (RO) The unique id for the rbd image. (For rbd
+               =========       ===============================================
+               image_id        (RO) The unique id for the rbd image. (For rbd
                                image format 1 this is empty.)
 
-               features:       (RO) A hexadecimal encoding of the feature bits
+               features        (RO) A hexadecimal encoding of the feature bits
                                for this image.
+               =========       ===============================================
 
 
 What:          /sys/bus/rbd/devices/<dev-id>/parent
@@ -149,14 +158,16 @@ Date:             Aug, 2016
 KernelVersion: v4.9
 Contact:       Sage Weil <sage@newdream.net>
 Description:
-               snap_id:        (RO) The current snapshot's id.
+               ============    ================================================
+               snap_id         (RO) The current snapshot's id.
 
-               config_info:    (RO) The string written into
+               config_info     (RO) The string written into
                                /sys/bus/rbd/add{,_single_major}.
 
-               cluster_fsid:   (RO) The ceph cluster UUID.
+               cluster_fsid    (RO) The ceph cluster UUID.
 
-               client_addr:    (RO) The ceph unique client
+               client_addr     (RO) The ceph unique client
                                entity_addr_t (address + nonce). The format is
                                <address>:<port>/<nonce>: '1.2.3.4:1234/5678' or
                                '[1:2:3:4:5:6:7:8]:1234/5678'.
+               ============    ================================================
index c2a403f20b90820e42c601412b56516d812689b5..50e80238f30dfe276f1cc6dc4e95d30ef7a3dc88 100644 (file)
@@ -8,6 +8,7 @@ Description:
                When the file contains a "1" the bus is operated and periodically
                does a push-pull cycle to write and read data from the
                connected devices.
+
                When writing a "0" or "1" the bus moves to the described state.
 
 What:          /sys/bus/siox/devices/siox-X/device_add
@@ -21,8 +22,10 @@ Description:
                to add a new device dynamically. <type> is the name that is used to match
                to a driver (similar to the platform bus). <inbytes> and <outbytes> define
                the length of the input and output shift register in bytes respectively.
+
                <statustype> defines the 4 bit device type that is check to identify connection
                problems.
+
                The new device is added to the end of the existing chain.
 
 What:          /sys/bus/siox/devices/siox-X/device_remove
index dd565c378b4032f18b1e528f6b3c0bdc6e5e0939..0b4ab9e4b8f475248ec67d1c9f23e7822331954f 100644 (file)
@@ -37,16 +37,18 @@ Contact:    thunderbolt-software@lists.01.org
 Description:   This attribute holds current Thunderbolt security level
                set by the system BIOS. Possible values are:
 
-               none: All devices are automatically authorized
-               user: Devices are only authorized based on writing
-                     appropriate value to the authorized attribute
-               secure: Require devices that support secure connect at
-                       minimum. User needs to authorize each device.
-               dponly: Automatically tunnel Display port (and USB). No
-                       PCIe tunnels are created.
-               usbonly: Automatically tunnel USB controller of the
+               =======  ==================================================
+               none     All devices are automatically authorized
+               user     Devices are only authorized based on writing
+                        appropriate value to the authorized attribute
+               secure   Require devices that support secure connect at
+                        minimum. User needs to authorize each device.
+               dponly   Automatically tunnel Display port (and USB). No
+                        PCIe tunnels are created.
+               usbonly  Automatically tunnel USB controller of the
                         connected Thunderbolt dock (and Display Port). All
                         PCIe links downstream of the dock are removed.
+               =======  ==================================================
 
 What: /sys/bus/thunderbolt/devices/.../authorized
 Date:          Sep 2017
@@ -61,17 +63,23 @@ Description:        This attribute is used to authorize Thunderbolt devices
                yet authorized.
 
                Possible values are supported:
-               1: The device will be authorized and connected
+
+               ==  ===========================================
+               1   The device will be authorized and connected
+               ==  ===========================================
 
                When key attribute contains 32 byte hex string the possible
                values are:
-               1: The 32 byte hex string is added to the device NVM and
-                  the device is authorized.
-               2: Send a challenge based on the 32 byte hex string. If the
-                  challenge response from device is valid, the device is
-                  authorized. In case of failure errno will be ENOKEY if
-                  the device did not contain a key at all, and
-                  EKEYREJECTED if the challenge response did not match.
+
+               ==  ========================================================
+               1   The 32 byte hex string is added to the device NVM and
+                   the device is authorized.
+               2   Send a challenge based on the 32 byte hex string. If the
+                   challenge response from device is valid, the device is
+                   authorized. In case of failure errno will be ENOKEY if
+                   the device did not contain a key at all, and
+                   EKEYREJECTED if the challenge response did not match.
+               ==  ========================================================
 
 What: /sys/bus/thunderbolt/devices/.../boot
 Date:          Jun 2018
@@ -185,10 +193,11 @@ Description:      When new NVM image is written to the non-active NVM
                verification fails an error code is returned instead.
 
                This file will accept writing values "1" or "2"
+
                - Writing "1" will flush the image to the storage
-               area and authenticate the image in one action.
+                 area and authenticate the image in one action.
                - Writing "2" will run some basic validation on the image
-               and flush it to the storage area.
+                 and flush it to the storage area.
 
                When read holds status of the last authentication
                operation if an error occurred during the process. This
@@ -205,9 +214,11 @@ Description:       This contains name of the property directory the XDomain
                question. Following directories are already reserved by
                the Apple XDomain specification:
 
-               network:  IP/ethernet over Thunderbolt
-               targetdm: Target disk mode protocol over Thunderbolt
-               extdisp:  External display mode protocol over Thunderbolt
+               ========  ===============================================
+               network   IP/ethernet over Thunderbolt
+               targetdm  Target disk mode protocol over Thunderbolt
+               extdisp   External display mode protocol over Thunderbolt
+               ========  ===============================================
 
 What:          /sys/bus/thunderbolt/devices/<xdomain>.<service>/modalias
 Date:          Jan 2018
@@ -285,7 +296,8 @@ Description:        For supported devices, automatically authenticate the new Thunderbo
                image when the device is disconnected from the host system.
 
                This file will accept writing values "1" or "2"
+
                - Writing "1" will flush the image to the storage
-               area and prepare the device for authentication on disconnect.
+                 area and prepare the device for authentication on disconnect.
                - Writing "2" will run some basic validation on the image
-               and flush it to the storage area.
+                 and flush it to the storage area.
index 614d216dff1d9f2066c7e834d4497a32bd73a99c..bf2c1968525f01187e55d9c6a1d3638a352b9ae4 100644 (file)
@@ -9,6 +9,7 @@ Description:
                by writing INTERFACE to /sys/bus/usb/drivers_probe
                This allows to avoid side-effects with drivers
                that need multiple interfaces.
+
                A deauthorized interface cannot be probed or claimed.
 
 What:          /sys/bus/usb/devices/usbX/interface_authorized_default
@@ -72,24 +73,27 @@ Description:
                table at compile time. The format for the device ID is:
                idVendor idProduct bInterfaceClass RefIdVendor RefIdProduct
                The vendor ID and device ID fields are required, the
-               rest is optional. The Ref* tuple can be used to tell the
+               rest is optional. The `Ref*` tuple can be used to tell the
                driver to use the same driver_data for the new device as
                it is used for the reference device.
                Upon successfully adding an ID, the driver will probe
-               for the device and attempt to bind to it.  For example:
-               # echo "8086 10f5" > /sys/bus/usb/drivers/foo/new_id
+               for the device and attempt to bind to it.  For example::
+
+                 # echo "8086 10f5" > /sys/bus/usb/drivers/foo/new_id
 
                Here add a new device (0458:7045) using driver_data from
-               an already supported device (0458:704c):
-               # echo "0458 7045 0 0458 704c" > /sys/bus/usb/drivers/foo/new_id
+               an already supported device (0458:704c)::
+
+                 # echo "0458 7045 0 0458 704c" > /sys/bus/usb/drivers/foo/new_id
 
                Reading from this file will list all dynamically added
                device IDs in the same format, with one entry per
-               line. For example:
-               # cat /sys/bus/usb/drivers/foo/new_id
-               8086 10f5
-               dead beef 06
-               f00d cafe
+               line. For example::
+
+                 # cat /sys/bus/usb/drivers/foo/new_id
+                 8086 10f5
+                 dead beef 06
+                 f00d cafe
 
                The list will be truncated at PAGE_SIZE bytes due to
                sysfs restrictions.
@@ -209,9 +213,11 @@ Description:
                advance, and behaves well according to the specification.
                This attribute is a bit-field that controls the behavior of
                a specific port:
+
                 - Bit 0 of this field selects the "old" enumeration scheme,
                   as it is considerably faster (it only causes one USB reset
                   instead of 2).
+
                   The old enumeration scheme can also be selected globally
                   using /sys/module/usbcore/parameters/old_scheme_first, but
                   it is often not desirable as the new scheme was introduced to
@@ -233,10 +239,10 @@ Description:
                poll() for monitoring changes to this value in user space.
 
                Any time this value changes the corresponding hub device will send a
-               udev event with the following attributes:
+               udev event with the following attributes::
 
-               OVER_CURRENT_PORT=/sys/bus/usb/devices/.../(hub interface)/portX
-               OVER_CURRENT_COUNT=[current value of this sysfs attribute]
+                 OVER_CURRENT_PORT=/sys/bus/usb/devices/.../(hub interface)/portX
+                 OVER_CURRENT_COUNT=[current value of this sysfs attribute]
 
 What:          /sys/bus/usb/devices/.../(hub interface)/portX/usb3_lpm_permit
 Date:          November 2015
index 9ade80f81f96c4abaacd17723146bbe362e41ea6..2f86e4223bfc8d25cc9552fe3865e3ccc964803b 100644 (file)
@@ -12,8 +12,11 @@ KernelVersion:       2.6.26
 Contact:       Harrison Metzger <harrisonmetz@gmail.com>
 Description:   Controls the devices display mode.
                For a 6 character display the values are
+
                        MSB 0x06; LSB 0x3F, and
+
                for an 8 character display the values are
+
                        MSB 0x08; LSB 0xFF.
 
 What:          /sys/bus/usb/.../textmode
@@ -37,7 +40,7 @@ KernelVersion:        2.6.26
 Contact:       Harrison Metzger <harrisonmetz@gmail.com>
 Description:   Controls the decimal places on the device.
                To set the nth decimal place, give this field
-               the value of 10 ** n. Assume this field has
+               the value of ``10 ** n``. Assume this field has
                the value k and has 1 or more decimal places set,
                to set the mth place (where m is not already set),
-               change this fields value to k + 10 ** m.
+               change this fields value to ``k + 10 ** m``.
index 452dbe39270ecab61f6ca9b1aa30f628519f761e..59fc804265dba5eba09e0d36c7dcfdf4cab6718d 100644 (file)
@@ -28,8 +28,9 @@ Description:
                Writing UUID to this file will create mediated device of
                type <type-id> for parent device <device>. This is a
                write-only file.
-               For example:
-               # echo "83b8f4f2-509f-382f-3c1e-e6bfe0fa1001" > \
+               For example::
+
+                 # echo "83b8f4f2-509f-382f-3c1e-e6bfe0fa1001" >       \
                       /sys/devices/foo/mdev_supported_types/foo-1/create
 
 What:           /sys/.../mdev_supported_types/<type-id>/devices/
@@ -107,5 +108,6 @@ Description:
                Writing '1' to this file destroys the mediated device. The
                vendor driver can fail the remove() callback if that device
                is active and the vendor driver doesn't support hot unplug.
-               Example:
-               # echo 1 > /sys/bus/mdev/devices/<UUID>/remove
+               Example::
+
+                 # echo 1 > /sys/bus/mdev/devices/<UUID>/remove
index 716cffc457e94c80099459b0b1e6c1b30719c710..f7b8cf6e43989b9a4d4fc0b96d7cebe00a76c115 100644 (file)
@@ -66,13 +66,6 @@ Description:
                the "erase" command on the on-board flash of the connected
                micro.
 
-What:          /sys/class/c2port/c2portX/flash_erase
-Date:          October 2008
-Contact:       Rodolfo Giometti <giometti@linux.it>
-Description:
-               The /sys/class/c2port/c2portX/flash_erase file show the
-               on-board flash size of the connected micro.
-
 What:          /sys/class/c2port/c2portX/reset
 Date:          October 2008
 Contact:       Rodolfo Giometti <giometti@linux.it>
index 3ab175a3f5cb34ee4b25b9adfa2430ff93baba30..1fc86401bf95938ce71d8e7ac4df47c8b399c059 100644 (file)
@@ -24,3 +24,63 @@ Description:
                non-linear
                  The brightness changes non-linearly with each step. Brightness
                  controls should use a linear mapping for a linear perception.
+
+What:          /sys/class/backlight/<backlight>/ambient_light_level
+Date:          Apr, 2010
+KernelVersion: v2.6.35
+Contact:       Michael Hennerich <michael.hennerich@analog.com>
+Description:
+               (RO) Get conversion value of the light sensor.
+
+               The value is automatically updated every 80 ms when the
+               light sensor is enabled.
+
+               The value range is device-driver specific:
+
+               For ADP8870:
+
+                 It returns integer between 0 (dark) and 8000 (max ambient
+                 brightness).
+
+               For ADP8860:
+
+                 It returns a 13-bits integer.
+
+What:          /sys/class/backlight/<backlight>/ambient_light_zone
+Date:          Apr, 2010
+KernelVersion: v2.6.35
+Contact:       Michael Hennerich <michael.hennerich@analog.com>,
+               device-drivers-devel@blackfin.uclinux.org
+
+Description:
+               (RW) Read or write the specific brightness level at which the
+               backlight operates.
+
+               The value meaning is device-driver specific:
+
+               For ADP8860:
+
+                 ==    ==========================
+                  0    Off: Backlight set to 0 mA
+                  1    Level 1: daylight
+                  2    Level 2: bright
+                  3    Level 3: dark
+                 ==    ==========================
+
+               For ADP8870:
+
+                 ==    ==========================
+                  0    Off: Backlight set to 0 mA
+                  1    Level 1: daylight
+                  2    Level 2: bright
+                  3    Level 3: office
+                  4    Level 4: indoor
+                  5    Level 5: dark
+                 ==    ==========================
+
+               Writing 0 returns to normal/automatic ambient light level
+               operation.
+
+               It can be enabled by writing the value stored in
+               /sys/class/backlight/<backlight>/max_brightness to
+               /sys/class/backlight/<backlight>/brightness.
index 54d61c788b1b56292da338ec0f2033fbabb92ab2..6610ac73f9ba06b5084db00020e87d2694345d42 100644 (file)
@@ -6,25 +6,8 @@ adp8860, adp8861 and adp8863 devices: daylight (level 1), office (level 2) and
 dark (level 3). By default the brightness operates at the daylight brightness
 level.
 
-What:          /sys/class/backlight/<backlight>/ambient_light_level
-Date:          Apr, 2010
-KernelVersion: v2.6.35
-Contact:       Michael Hennerich <michael.hennerich@analog.com>
-Description:
-               (RO) 13-bit conversion value for the first light sensor—high
-               byte (Bit 12 to Bit 8). The value is updated every 80 ms (when
-               the light sensor is enabled).
-
-
-What:          /sys/class/backlight/<backlight>/ambient_light_zone
-Date:          Apr, 2010
-KernelVersion: v2.6.35
-Contact:       Michael Hennerich <michael.hennerich@analog.com>
-Description:
-               (RW) Read or write the specific level at which the backlight
-               operates. Value "0" enables automatic ambient light sensing, and
-               values "1", "2" or "3" set the control to daylight, office or
-               dark respectively.
+See also /sys/class/backlight/<backlight>/ambient_light_level and
+/sys/class/backlight/<backlight>/ambient_light_zone.
 
 
 What:          /sys/class/backlight/<backlight>/l1_daylight_max
index 33e648808117770949f81bd72e4b7fe1479705d4..b08ca912cad40c19693f98ace7cdfbe35cb3412e 100644 (file)
@@ -1,3 +1,6 @@
+See also /sys/class/backlight/<backlight>/ambient_light_level and
+/sys/class/backlight/<backlight>/ambient_light_zone.
+
 What:          /sys/class/backlight/<backlight>/<ambient light zone>_max
 What:          /sys/class/backlight/<backlight>/l1_daylight_max
 What:          /sys/class/backlight/<backlight>/l2_bright_max
@@ -27,30 +30,3 @@ Description:
                set to 0. Full off when the backlight is disabled.
                This file will also show the dim brightness level stored for
                this <ambient light zone>.
-
-What:          /sys/class/backlight/<backlight>/ambient_light_level
-Date:          May 2011
-KernelVersion: 3.0
-Contact:       device-drivers-devel@blackfin.uclinux.org
-Description:
-               Get conversion value of the light sensor.
-               This value is updated every 80 ms (when the light sensor
-               is enabled). Returns integer between 0 (dark) and
-               8000 (max ambient brightness)
-
-What:          /sys/class/backlight/<backlight>/ambient_light_zone
-Date:          May 2011
-KernelVersion: 3.0
-Contact:       device-drivers-devel@blackfin.uclinux.org
-Description:
-               Get/Set current ambient light zone. Reading returns
-               integer between 1..5 (1 = daylight, 2 = bright, ..., 5 = dark).
-               Writing a value between 1..5 forces the backlight controller
-               to enter the corresponding ambient light zone.
-               Writing 0 returns to normal/automatic ambient light level
-               operation. The ambient light sensing feature on these devices
-               is an extension to the API documented in
-               Documentation/ABI/stable/sysfs-class-backlight.
-               It can be enabled by writing the value stored in
-               /sys/class/backlight/<backlight>/max_brightness to
-               /sys/class/backlight/<backlight>/brightness.
index c0e0a9ae7b3d9bfb4a344d00490759d2475e013d..8251e78abc493e3ddb7e965e7920fe6baa2c4d01 100644 (file)
@@ -6,8 +6,10 @@ Description:
                Get the ALS output channel used as input in
                ALS-current-control mode (0, 1), where:
 
-               0 - out_current0 (backlight 0)
-               1 - out_current1 (backlight 1)
+               ==  ==========================
+               0   out_current0 (backlight 0)
+               1   out_current1 (backlight 1)
+               ==  ==========================
 
 What:          /sys/class/backlight/<backlight>/als_en
 Date:          May 2012
@@ -30,8 +32,10 @@ Contact:     Johan Hovold <jhovold@gmail.com>
 Description:
                Set the brightness-mapping mode (0, 1), where:
 
-               0 - exponential mode
-               1 - linear mode
+               ==  ================
+               0   exponential mode
+               1   linear mode
+               ==  ================
 
 What:          /sys/class/backlight/<backlight>/pwm
 Date:          April 2012
@@ -40,9 +44,11 @@ Contact:     Johan Hovold <jhovold@gmail.com>
 Description:
                Set the PWM-input control mask (5 bits), where:
 
-               bit 5 - PWM-input enabled in Zone 4
-               bit 4 - PWM-input enabled in Zone 3
-               bit 3 - PWM-input enabled in Zone 2
-               bit 2 - PWM-input enabled in Zone 1
-               bit 1 - PWM-input enabled in Zone 0
-               bit 0 - PWM-input enabled
+               =====   ===========================
+               bit 5   PWM-input enabled in Zone 4
+               bit 4   PWM-input enabled in Zone 3
+               bit 3   PWM-input enabled in Zone 2
+               bit 2   PWM-input enabled in Zone 1
+               bit 1   PWM-input enabled in Zone 0
+               bit 0   PWM-input enabled
+               =====   ===========================
index d773d5697cf588349b74fd7d19e63983472b1632..5402bd74ba43b4303f95d026bcde1df86bbd737a 100644 (file)
@@ -24,7 +24,6 @@ default
        filesystems which do not provide their own BDI.
 
 Files under /sys/class/bdi/<bdi>/
----------------------------------
 
 read_ahead_kb (read-write)
 
index 5819699d66ec08b081cc2c1202ac2fcf14755ece..74ece942722e71ec139f544f0701725f1125c68b 100644 (file)
@@ -17,13 +17,14 @@ Date:               August 2015
 KernelVersion: 4.2
 Description:
                Tell the EC to reboot in various ways. Options are:
-               "cancel": Cancel a pending reboot.
-               "ro": Jump to RO without rebooting.
-               "rw": Jump to RW without rebooting.
-               "cold": Cold reboot.
-               "disable-jump": Disable jump until next reboot.
-               "hibernate": Hibernate the EC.
-               "at-shutdown": Reboot after an AP shutdown.
+
+               - "cancel": Cancel a pending reboot.
+               - "ro": Jump to RO without rebooting.
+               - "rw": Jump to RW without rebooting.
+               - "cold": Cold reboot.
+               - "disable-jump": Disable jump until next reboot.
+               - "hibernate": Hibernate the EC.
+               - "at-shutdown": Reboot after an AP shutdown.
 
 What:          /sys/class/chromeos/<ec-device-name>/version
 Date:          August 2015
index 7970e3713e705ce91c3f0dbceb51efc6c876d2a6..818f55970efbd1418ea68b3a93b729818a2ede67 100644 (file)
@@ -72,11 +72,16 @@ Description:    read/write
                 when performing the START_WORK ioctl. Only applicable when
                 running under hashed page table mmu.
                 Possible values:
-                        none: No prefaulting (default)
-                        work_element_descriptor: Treat the work element
-                                 descriptor as an effective address and
-                                 prefault what it points to.
-                        all: all segments process calling START_WORK maps.
+
+                =======================  ======================================
+               none                     No prefaulting (default)
+               work_element_descriptor  Treat the work element
+                                        descriptor as an effective address and
+                                        prefault what it points to.
+                all                     all segments process calling
+                                        START_WORK maps.
+                =======================  ======================================
+
 Users:         https://github.com/ibm-capi/libcxl
 
 What:           /sys/class/cxl/<afu>/reset
@@ -212,6 +217,7 @@ Description:    read/write
                 card.  A power cycle is required to load the image.
                 "none" could be useful for debugging because the trace arrays
                 are preserved.
+
                 "user" and "factory" means PERST will cause either the user or
                 user or factory image to be loaded.
                 Default is to reload on PERST whichever image the card has
@@ -235,8 +241,11 @@ Contact:   linuxppc-dev@lists.ozlabs.org
 Description:   read/write
                Trust that when an image is reloaded via PERST, it will not
                have changed.
-               0 = don't trust, the image may be different (default)
-               1 = trust that the image will not change.
+
+               ==  =================================================
+               0   don't trust, the image may be different (default)
+               1   trust that the image will not change.
+               ==  =================================================
 Users:         https://github.com/ibm-capi/libcxl
 
 What:           /sys/class/cxl/<card>/psl_timebase_synced
index deefffb3bbe45dba1c855e3525c739363afed0f6..b8ebff4b1c4ca23f35f61ec37e78bb2e377611df 100644 (file)
@@ -62,7 +62,8 @@ Description:
                driver should provide the list of available frequencies
                with its profile. If need to reset the statistics of devfreq
                behavior on a specific device, enter 0(zero) to 'trans_stat'
-               as following:
+               as following::
+
                        echo 0 > /sys/class/devfreq/.../trans_stat
 
 What:          /sys/class/devfreq/.../userspace/set_freq
@@ -117,6 +118,7 @@ Description:
                This work timer is used by devfreq workqueue in order to
                monitor the device status such as utilization. The user
                can change the work timer on runtime according to their demand
-               as following:
+               as following::
+
                        echo deferrable > /sys/class/devfreq/.../timer
                        echo delayed > /sys/class/devfreq/.../timer
index 64791b65c9a384279aab2d6f7206ef7c721a85af..b662f747c83ebd99eac633e92a034ca407ed5354 100644 (file)
@@ -18,9 +18,9 @@ Description:
 
                This will be one of the following strings:
 
-               'consumer unbind'
-               'supplier unbind'
-               'never'
+               'consumer unbind'
+               'supplier unbind'
+               'never'
 
                'consumer unbind' means the device link will be removed when
                the consumer's driver is unbound from the consumer device.
@@ -49,8 +49,10 @@ Description:
 
                This will be one of the following strings:
 
-               '0' - Does not affect runtime power management
-               '1' - Affects runtime power management
+               ===   ========================================
+               '0'   Does not affect runtime power management
+               '1'   Affects runtime power management
+               ===   ========================================
 
 What:          /sys/class/devlink/.../status
 Date:          May 2020
@@ -68,13 +70,13 @@ Description:
 
                This will be one of the following strings:
 
-               'not tracked'
-               'dormant'
-               'available'
-               'consumer probing'
-               'active'
-               'supplier unbinding'
-               'unknown'
+               'not tracked'
+               'dormant'
+               'available'
+               'consumer probing'
+               'active'
+               'supplier unbinding'
+               'unknown'
 
                'not tracked' means this device link does not track the status
                and has no impact on the binding, unbinding and syncing the
@@ -114,8 +116,10 @@ Description:
 
                This will be one of the following strings:
 
+               ===  ================================
                '0'
-               '1' - Affects runtime power management
+               '1'  Affects runtime power management
+               ===  ================================
 
                '0' means the device link can affect other device behaviors
                like binding/unbinding, suspend/resume, runtime power
index 57a726232912e46ae61adfc545ace17d25023558..fde0fecd5de95bbfc151c19a8c0df09e0f966264 100644 (file)
@@ -39,19 +39,22 @@ Description:
                callback.
 
                If the default callback for showing function is used, the
-               format is like this:
-               # cat state
-               USB_OTG=1
-               HDMI=0
-               TA=1
-               EAR_JACK=0
-               #
+               format is like this::
+
+                   # cat state
+                   USB_OTG=1
+                   HDMI=0
+                   TA=1
+                   EAR_JACK=0
+                   #
+
                In this example, the extcon device has USB_OTG and TA
                cables attached and HDMI and EAR_JACK cables detached.
 
                In order to update the state of an extcon device, enter a hex
-               state number starting with 0x:
-               # echo 0xHEX > state
+               state number starting with 0x::
+
+                   # echo 0xHEX > state
 
                This updates the whole state of the extcon device.
                Inputs of all the methods are required to meet the
@@ -84,12 +87,13 @@ Contact:    MyungJoo Ham <myungjoo.ham@samsung.com>
 Description:
                Shows the relations of mutually exclusiveness. For example,
                if the mutually_exclusive array of extcon device is
-               {0x3, 0x5, 0xC, 0x0}, then the output is:
-               # ls mutually_exclusive/
-               0x3
-               0x5
-               0xc
-               #
+               {0x3, 0x5, 0xC, 0x0}, then the output is::
+
+                   # ls mutually_exclusive/
+                   0x3
+                   0x5
+                   0xc
+                   #
 
                Note that mutually_exclusive is a sub-directory of the extcon
                device and the file names under the mutually_exclusive
index 5284fa33d4c55fa449c9fa5deca2053c09bc307e..d78689c357a518c4e2ee16182f744fb9d02495f4 100644 (file)
@@ -28,8 +28,7 @@ Description:  Read fpga manager state as a string.
                * firmware request      = firmware class request in progress
                * firmware request error = firmware request failed
                * write init            = preparing FPGA for programming
-               * write init error      = Error while preparing FPGA for
-                                         programming
+               * write init error      = Error while preparing FPGA for programming
                * write                 = FPGA ready to receive image data
                * write error           = Error while programming
                * write complete        = Doing post programming steps
@@ -47,7 +46,7 @@ Description:  Read fpga manager status as a string.
                programming errors to userspace. This is a list of strings for
                the supported status.
 
-               * reconfig operation error      - invalid operations detected by
+               * reconfig operation error      - invalid operations detected by
                                                  reconfiguration hardware.
                                                  e.g. start reconfiguration
                                                  with errors not cleared
index 2467b6900eae5124662afe397fef320bb9d74e4b..c8553d972eddfde93341b04d161528d13b543afc 100644 (file)
@@ -6,9 +6,11 @@ Description:
                The GNSS receiver type. The currently identified types reflect
                the protocol(s) supported by the receiver:
 
+                       ======          ===========
                        "NMEA"          NMEA 0183
                        "SiRF"          SiRF Binary
                        "UBX"           UBX
+                       ======          ===========
 
                Note that also non-"NMEA" type receivers typically support a
                subset of NMEA 0183 with vendor extensions (e.g. to allow
index 5f67f7ab277bc51af0bdb8ccb94ae03f6936ad6c..2e24ac3bd7efa4e64d8dc084462cc0ef92dc9202 100644 (file)
@@ -3,9 +3,26 @@ Date:          March 2006
 KernelVersion: 2.6.17
 Contact:       Richard Purdie <rpurdie@rpsys.net>
 Description:
-               Set the brightness of the LED. Most LEDs don't
-               have hardware brightness support, so will just be turned on for
-               non-zero brightness settings. The value is between 0 and
+               Set the brightness of the LED.
+
+               Most LEDs don't have hardware brightness support, so will
+               just be turned on for non-zero brightness settings.
+
+               .. Note::
+
+                 For multicolor LEDs, writing to this file will update all
+                 LEDs within the group to a calculated percentage of what
+                 each color LED intensity is set to.
+
+                 The percentage is calculated for each grouped LED via
+                 the equation below::
+
+                   led_brightness = brightness * multi_intensity/max_brightness
+
+                 For additional details please refer to
+                 Documentation/leds/leds-class-multicolor.rst.
+
+               The value is between 0 and
                /sys/class/leds/<led>/max_brightness.
 
                Writing 0 to this file clears active trigger.
@@ -13,6 +30,8 @@ Description:
                Writing non-zero to this file while trigger is active changes the
                top brightness trigger is going to use.
 
+
+
 What:          /sys/class/leds/<led>/max_brightness
 Date:          March 2006
 KernelVersion: 2.6.17
@@ -47,10 +66,11 @@ Contact:    Richard Purdie <rpurdie@rpsys.net>
 Description:
                Set the trigger for this LED. A trigger is a kernel based source
                of LED events.
+
                You can change triggers in a similar manner to the way an IO
                scheduler is chosen. Trigger specific parameters can appear in
                /sys/class/leds/<led> once a given trigger is selected. For
-               their documentation see sysfs-class-led-trigger-*.
+               their documentation see `sysfs-class-led-trigger-*`.
 
 What:          /sys/class/leds/<led>/inverted
 Date:          January 2011
index f520ece9b64c555a3757771e3ad2deda0aabb04f..04f3ffdc593615340a9bed0a4d78584bbb9d6abf 100644 (file)
@@ -1,133 +1,3 @@
-What:          /sys/class/leds/<led>/hw_pattern
-Date:          September 2019
-KernelVersion: 5.5
-Description:
-               Specify a hardware pattern for the EL15203000 LED.
-               The LEDs board supports only predefined patterns by firmware
-               for specific LEDs.
-
-               Breathing mode for Screen frame light tube:
-               "0 4000 1 4000"
-
-                   ^
-                   |
-               Max-|     ---
-                   |    /   \
-                   |   /     \
-                   |  /       \     /
-                   | /         \   /
-               Min-|-           ---
-                   |
-                   0------4------8--> time (sec)
-
-               Cascade mode for Pipe LED:
-               "1 800 2 800 4 800 8 800 16 800"
-
-                     ^
-                     |
-               0 On -|----+                   +----+                   +---
-                     |    |                   |    |                   |
-                 Off-|    +-------------------+    +-------------------+
-                     |
-               1 On -|    +----+                   +----+
-                     |    |    |                   |    |
-                 Off |----+    +-------------------+    +------------------
-                     |
-               2 On -|         +----+                   +----+
-                     |         |    |                   |    |
-                 Off-|---------+    +-------------------+    +-------------
-                     |
-               3 On -|              +----+                   +----+
-                     |              |    |                   |    |
-                 Off-|--------------+    +-------------------+    +--------
-                     |
-               4 On -|                   +----+                   +----+
-                     |                   |    |                   |    |
-                 Off-|-------------------+    +-------------------+    +---
-                     |
-                     0---0.8--1.6--2.4--3.2---4---4.8--5.6--6.4--7.2---8--> time (sec)
-
-               Inverted cascade mode for Pipe LED:
-               "30 800 29 800 27 800 23 800 15 800"
-
-                     ^
-                     |
-               0 On -|    +-------------------+    +-------------------+
-                     |    |                   |    |                   |
-                 Off-|----+                   +----+                   +---
-                     |
-               1 On -|----+    +-------------------+    +------------------
-                     |    |    |                   |    |
-                 Off |    +----+                   +----+
-                     |
-               2 On -|---------+    +-------------------+    +-------------
-                     |         |    |                   |    |
-                 Off-|         +----+                   +----+
-                     |
-               3 On -|--------------+    +-------------------+    +--------
-                     |              |    |                   |    |
-                 Off-|              +----+                   +----+
-                     |
-               4 On -|-------------------+    +-------------------+    +---
-                     |                   |    |                   |    |
-                 Off-|                   +----+                   +----+
-                     |
-                     0---0.8--1.6--2.4--3.2---4---4.8--5.6--6.4--7.2---8--> time (sec)
-
-               Bounce mode for Pipe LED:
-               "1 800 2 800 4 800 8 800 16 800 16 800 8 800 4 800 2 800 1 800"
-
-                     ^
-                     |
-               0 On -|----+                                       +--------
-                     |    |                                       |
-                 Off-|    +---------------------------------------+
-                     |
-               1 On -|    +----+                             +----+
-                     |    |    |                             |    |
-                 Off |----+    +-----------------------------+    +--------
-                     |
-               2 On -|         +----+                   +----+
-                     |         |    |                   |    |
-                 Off-|---------+    +-------------------+    +-------------
-                     |
-               3 On -|              +----+         +----+
-                     |              |    |         |    |
-                 Off-|--------------+    +---------+    +------------------
-                     |
-               4 On -|                   +---------+
-                     |                   |         |
-                 Off-|-------------------+         +-----------------------
-                     |
-                     0---0.8--1.6--2.4--3.2---4---4.8--5.6--6.4--7.2---8--> time (sec)
-
-               Inverted bounce mode for Pipe LED:
-               "30 800 29 800 27 800 23 800 15 800 15 800 23 800 27 800 29 800 30 800"
-
-                     ^
-                     |
-               0 On -|    +---------------------------------------+
-                     |    |                                       |
-                 Off-|----+                                       +--------
-                     |
-               1 On -|----+    +-----------------------------+    +--------
-                     |    |    |                             |    |
-                 Off |    +----+                             +----+
-                     |
-               2 On -|---------+    +-------------------+    +-------------
-                     |         |    |                   |    |
-                 Off-|         +----+                   +----+
-                     |
-               3 On -|--------------+    +---------+    +------------------
-                     |              |    |         |    |
-                 Off-|              +----+         +----+
-                     |
-               4 On -|-------------------+         +-----------------------
-                     |                   |         |
-                 Off-|                   +---------+
-                     |
-                     0---0.8--1.6--2.4--3.2---4---4.8--5.6--6.4--7.2---8--> time (sec)
-
 What:          /sys/class/leds/<led>/repeat
 Date:          September 2019
 KernelVersion: 5.5
index e4c89b261546c367463561adf0017ca7ea18a565..e38a835d0a85e89a9db507fceccf26bc3ef5953b 100644 (file)
@@ -6,8 +6,10 @@ Description:
                Set the ALS output channel to use as input in
                ALS-current-control mode (1, 2), where:
 
-               1 - out_current1
-               2 - out_current2
+               ==  ============
+               1   out_current1
+               2   out_current2
+               ==  ============
 
 What:          /sys/class/leds/<led>/als_en
 Date:          May 2012
@@ -24,14 +26,16 @@ Contact:    Johan Hovold <jhovold@gmail.com>
 Description:
                Set the pattern generator fall and rise times (0..7), where:
 
-               0 - 2048 us
-               1 - 262 ms
-               2 - 524 ms
-               3 - 1.049 s
-               4 - 2.097 s
-               5 - 4.194 s
-               6 - 8.389 s
-               7 - 16.78 s
+               ==  =======
+               0   2048 us
+               1   262 ms
+               2   524 ms
+               3   1.049 s
+               4   2.097 s
+               5   4.194 s
+               6   8.389 s
+               7   16.78 s
+               ==  =======
 
 What:          /sys/class/leds/<led>/id
 Date:          April 2012
@@ -47,8 +51,10 @@ Contact:     Johan Hovold <jhovold@gmail.com>
 Description:
                Set the brightness-mapping mode (0, 1), where:
 
-               0 - exponential mode
-               1 - linear mode
+               ==  ================
+               0   exponential mode
+               1   linear mode
+               ==  ================
 
 What:          /sys/class/leds/<led>/pwm
 Date:          April 2012
@@ -57,9 +63,11 @@ Contact:     Johan Hovold <jhovold@gmail.com>
 Description:
                Set the PWM-input control mask (5 bits), where:
 
-               bit 5 - PWM-input enabled in Zone 4
-               bit 4 - PWM-input enabled in Zone 3
-               bit 3 - PWM-input enabled in Zone 2
-               bit 2 - PWM-input enabled in Zone 1
-               bit 1 - PWM-input enabled in Zone 0
-               bit 0 - PWM-input enabled
+               =====  ===========================
+               bit 5  PWM-input enabled in Zone 4
+               bit 4  PWM-input enabled in Zone 3
+               bit 3  PWM-input enabled in Zone 2
+               bit 2  PWM-input enabled in Zone 1
+               bit 1  PWM-input enabled in Zone 0
+               bit 0  PWM-input enabled
+               =====  ===========================
diff --git a/Documentation/ABI/testing/sysfs-class-led-driver-sc27xx b/Documentation/ABI/testing/sysfs-class-led-driver-sc27xx
deleted file mode 100644 (file)
index 45b1e60..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-What:          /sys/class/leds/<led>/hw_pattern
-Date:          September 2018
-KernelVersion: 4.20
-Description:
-               Specify a hardware pattern for the SC27XX LED. For the SC27XX
-               LED controller, it only supports 4 stages to make a single
-               hardware pattern, which is used to configure the rise time,
-               high time, fall time and low time for the breathing mode.
-
-               For the breathing mode, the SC27XX LED only expects one brightness
-               for the high stage. To be compatible with the hardware pattern
-               format, we should set brightness as 0 for rise stage, fall
-               stage and low stage.
-
-               Min stage duration: 125 ms
-               Max stage duration: 31875 ms
-
-               Since the stage duration step is 125 ms, the duration should be
-               a multiplier of 125, like 125ms, 250ms, 375ms, 500ms ... 31875ms.
-
-               Thus the format of the hardware pattern values should be:
-               "0 rise_duration brightness high_duration 0 fall_duration 0 low_duration".
index 220a0270b47b4981936e1832f83aa11dfd8c9558..11e5677c3672954ad45b189301bf081ff49fa411 100644 (file)
@@ -55,26 +55,35 @@ Description:        read only
                Flash faults are re-read after strobing the flash. Possible
                flash faults:
 
-               * led-over-voltage - flash controller voltage to the flash LED
+               * led-over-voltage
+                       flash controller voltage to the flash LED
                        has exceeded the limit specific to the flash controller
-               * flash-timeout-exceeded - the flash strobe was still on when
+               * flash-timeout-exceeded
+                       the flash strobe was still on when
                        the timeout set by the user has expired; not all flash
                        controllers may set this in all such conditions
-               * controller-over-temperature - the flash controller has
+               * controller-over-temperature
+                       the flash controller has
                        overheated
-               * controller-short-circuit - the short circuit protection
+               * controller-short-circuit
+                       the short circuit protection
                        of the flash controller has been triggered
-               * led-power-supply-over-current - current in the LED power
+               * led-power-supply-over-current
+                       current in the LED power
                        supply has exceeded the limit specific to the flash
                        controller
-               * indicator-led-fault - the flash controller has detected
+               * indicator-led-fault
+                       the flash controller has detected
                        a short or open circuit condition on the indicator LED
-               * led-under-voltage - flash controller voltage to the flash
+               * led-under-voltage
+                       flash controller voltage to the flash
                        LED has been below the minimum limit specific to
                        the flash
-               * controller-under-voltage - the input voltage of the flash
+               * controller-under-voltage
+                       the input voltage of the flash
                        controller is below the limit under which strobing the
                        flash at full current will not be possible;
                        the condition persists until this flag is no longer set
-               * led-over-temperature - the temperature of the LED has exceeded
+               * led-over-temperature
+                       the temperature of the LED has exceeded
                        its allowed upper limit
index eeeddcbdbbe3373a26328c6407550e6964fa9d22..16fc827b10cb60773feb18720b79a8eb6cb224d0 100644 (file)
@@ -1,20 +1,3 @@
-What:          /sys/class/leds/<led>/brightness
-Date:          March 2020
-KernelVersion: 5.9
-Contact:       Dan Murphy <dmurphy@ti.com>
-Description:   read/write
-               Writing to this file will update all LEDs within the group to a
-               calculated percentage of what each color LED intensity is set
-               to. The percentage is calculated for each grouped LED via the
-               equation below:
-
-               led_brightness = brightness * multi_intensity/max_brightness
-
-               For additional details please refer to
-               Documentation/leds/leds-class-multicolor.rst.
-
-               The value of the LED is from 0 to
-               /sys/class/leds/<led>/max_brightness.
 
 What:          /sys/class/leds/<led>/multi_index
 Date:          March 2020
@@ -25,6 +8,9 @@ Description:   read
                as an array of strings as they are indexed in the
                multi_intensity file.
 
+               For additional details please refer to
+               Documentation/leds/leds-class-multicolor.rst.
+
 What:          /sys/class/leds/<led>/multi_intensity
 Date:          March 2020
 KernelVersion: 5.9
@@ -33,3 +19,6 @@ Description:  read/write
                This file contains array of integers. Order of components is
                described by the multi_index array. The maximum intensity should
                not exceed /sys/class/leds/<led>/max_brightness.
+
+               For additional details please refer to
+               Documentation/leds/leds-class-multicolor.rst.
index 451af6d6768c5c8aa87bb49a72602da1d2554cd9..646540950e381ad021eaec6745035896ccd6e7b3 100644 (file)
@@ -19,18 +19,23 @@ KernelVersion:      4.16
 Contact:       linux-leds@vger.kernel.org
 Description:
                Signal the link state of the named network device.
+
                If set to 0 (default), the LED's normal state is off.
+
                If set to 1, the LED's normal state reflects the link state
                of the named network device.
                Setting this value also immediately changes the LED state.
 
+
 What:          /sys/class/leds/<led>/tx
 Date:          Dec 2017
 KernelVersion: 4.16
 Contact:       linux-leds@vger.kernel.org
 Description:
                Signal transmission of data on the named network device.
+
                If set to 0 (default), the LED will not blink on transmission.
+
                If set to 1, the LED will blink for the milliseconds specified
                in interval to signal transmission.
 
@@ -40,6 +45,8 @@ KernelVersion:        4.16
 Contact:       linux-leds@vger.kernel.org
 Description:
                Signal reception of data on the named network device.
+
                If set to 0 (default), the LED will not blink on reception.
+
                If set to 1, the LED will blink for the milliseconds specified
                in interval to signal reception.
index bd92ef9d6faa8d4a65a7c143267c12eceb58256d..d91a07767adf067f5ab6ce3fd04b2bf097a08b09 100644 (file)
@@ -23,8 +23,8 @@ Description:
 
                Since different LED hardware can have different semantics of
                hardware patterns, each driver is expected to provide its own
-               description for the hardware patterns in their ABI documentation
-               file.
+               description for the hardware patterns in their documentation
+               file at Documentation/leds/.
 
 What:          /sys/class/leds/<led>/repeat
 Date:          September 2018
index f440e690daef65dc21c48c253a6b428fb435103b..eb81152b8348c31b02491cb87c434909c339c5cf 100644 (file)
@@ -8,5 +8,6 @@ Description:
                selected for the USB port trigger. Selecting ports makes trigger
                observing them for any connected devices and lighting on LED if
                there are any.
+
                Echoing "1" value selects USB port. Echoing "0" unselects it.
                Current state can be also read.
index 6adab27f646e668eeb46d92ee5fe6ed560ad15c2..b57ffb26e722a3dd9048fedf98ad703b294211fb 100644 (file)
@@ -7,9 +7,11 @@ Description:
                of one LED will update the mode of its two sibling devices as
                well. Possible values are:
 
-               0 - normal
-               1 - audio
-               2 - breathing
+               ==  =========
+               0   normal
+               1   audio
+               2   breathing
+               ==  =========
 
                Normal: LEDs are fully on when enabled
                Audio:  LEDs brightness depends on sound level
index 6ef68260317975d0daf1b62c2070430fef1ba91d..bd0e780c37601d56554591acf58477cc55ba49be 100644 (file)
@@ -41,24 +41,33 @@ Description:
                When read, this entry provides the current state of an Intel
                MIC device in the context of the card OS. Possible values that
                will be read are:
-               "ready" - The MIC device is ready to boot the card OS. On
-               reading this entry after an OSPM resume, a "boot" has to be
-               written to this entry if the card was previously shutdown
-               during OSPM suspend.
-               "booting" - The MIC device has initiated booting a card OS.
-               "online" - The MIC device has completed boot and is online
-               "shutting_down" - The card OS is shutting down.
-               "resetting" - A reset has been initiated for the MIC device
-               "reset_failed" - The MIC device has failed to reset.
+
+
+               ===============  ===============================================
+               "ready"          The MIC device is ready to boot the card OS.
+                                On reading this entry after an OSPM resume,
+                                a "boot" has to be written to this entry if
+                                the card was previously shutdown during OSPM
+                                suspend.
+               "booting"        The MIC device has initiated booting a card OS.
+               "online"         The MIC device has completed boot and is online
+               "shutting_down"  The card OS is shutting down.
+               "resetting"      A reset has been initiated for the MIC device
+               "reset_failed"   The MIC device has failed to reset.
+               ===============  ===============================================
 
                When written, this sysfs entry triggers different state change
                operations depending upon the current state of the card OS.
                Acceptable values are:
-               "boot" - Boot the card OS image specified by the combination
-                        of firmware, ramdisk, cmdline and bootmode
-                       sysfs entries.
-               "reset" - Initiates device reset.
-               "shutdown" - Initiates card OS shutdown.
+
+
+               ==========  ===================================================
+               "boot"      Boot the card OS image specified by the combination
+                           of firmware, ramdisk, cmdline and bootmode
+                           sysfs entries.
+               "reset"     Initiates device reset.
+               "shutdown"  Initiates card OS shutdown.
+               ==========  ===================================================
 
 What:          /sys/class/mic/mic(x)/shutdown_status
 Date:          October 2013
@@ -69,12 +78,15 @@ Description:
                OS can shutdown because of various reasons. When read, this
                entry provides the status on why the card OS was shutdown.
                Possible values are:
-               "nop" -  shutdown status is not applicable, when the card OS is
-                       "online"
-               "crashed" - Shutdown because of a HW or SW crash.
-               "halted" - Shutdown because of a halt command.
-               "poweroff" - Shutdown because of a poweroff command.
-               "restart" - Shutdown because of a restart command.
+
+               ==========  ===================================================
+               "nop"       shutdown status is not applicable, when the card OS
+                           is "online"
+               "crashed"   Shutdown because of a HW or SW crash.
+               "halted"    Shutdown because of a halt command.
+               "poweroff"  Shutdown because of a poweroff command.
+               "restart"   Shutdown because of a restart command.
+               ==========  ===================================================
 
 What:          /sys/class/mic/mic(x)/cmdline
 Date:          October 2013
index 3b404577f380267f2fc30ffb3de88f67555b8c54..1f2002df5ba2378390a7c88573051fc2e1f511fb 100644 (file)
@@ -4,10 +4,13 @@ KernelVersion:        3.17
 Contact:       netdev@vger.kernel.org
 Description:
                Indicates the name assignment type. Possible values are:
-               1: enumerated by the kernel, possibly in an unpredictable way
-               2: predictably named by the kernel
-               3: named by userspace
-               4: renamed
+
+               == ==========================================================
+               1  enumerated by the kernel, possibly in an unpredictable way
+               2  predictably named by the kernel
+               3  named by userspace
+               4  renamed
+               == ==========================================================
 
 What:          /sys/class/net/<iface>/addr_assign_type
 Date:          July 2010
@@ -15,10 +18,13 @@ KernelVersion:      3.2
 Contact:       netdev@vger.kernel.org
 Description:
                Indicates the address assignment type. Possible values are:
-               0: permanent address
-               1: randomly generated
-               2: stolen from another device
-               3: set using dev_set_mac_address
+
+               == =============================
+               0  permanent address
+               1  randomly generated
+               2  stolen from another device
+               3  set using dev_set_mac_address
+               == =============================
 
 What:          /sys/class/net/<iface>/addr_len
 Date:          April 2005
@@ -51,9 +57,12 @@ Description:
                Default value 0 does not forward any link local frames.
 
                Restricted bits:
-               0: 01-80-C2-00-00-00 Bridge Group Address used for STP
-               1: 01-80-C2-00-00-01 (MAC Control) 802.3 used for MAC PAUSE
-               2: 01-80-C2-00-00-02 (Link Aggregation) 802.3ad
+
+               == ========================================================
+               0  01-80-C2-00-00-00 Bridge Group Address used for STP
+               1  01-80-C2-00-00-01 (MAC Control) 802.3 used for MAC PAUSE
+               2  01-80-C2-00-00-02 (Link Aggregation) 802.3ad
+               == ========================================================
 
                Any values not setting these bits can be used. Take special
                care when forwarding control frames e.g. 802.1X-PAE or LLDP.
@@ -74,8 +83,11 @@ Contact:     netdev@vger.kernel.org
 Description:
                Indicates the current physical link state of the interface.
                Posssible values are:
-               0: physical link is down
-               1: physical link is up
+
+               == =====================
+               0  physical link is down
+               1  physical link is up
+               == =====================
 
                Note: some special devices, e.g: bonding and team drivers will
                allow this attribute to be written to force a link state for
@@ -131,21 +143,27 @@ Contact:  netdev@vger.kernel.org
 Description:
                Indicates whether the interface is under test. Possible
                values are:
-               0: interface is not being tested
-               1: interface is being tested
+
+               == =============================
+               0  interface is not being tested
+               1  interface is being tested
+               == =============================
 
                When an interface is under test, it cannot be expected
                to pass packets as normal.
 
-What:          /sys/clas/net/<iface>/duplex
+What:          /sys/class/net/<iface>/duplex
 Date:          October 2009
 KernelVersion: 2.6.33
 Contact:       netdev@vger.kernel.org
 Description:
                Indicates the interface latest or current duplex value. Possible
                values are:
-               half: half duplex
-               full: full duplex
+
+               ====  ===========
+               half  half duplex
+               full  full duplex
+               ====  ===========
 
                Note: This attribute is only valid for interfaces that implement
                the ethtool get_link_ksettings method (mostly Ethernet).
@@ -196,8 +214,11 @@ Description:
                Indicates the interface link mode, as a decimal number. This
                attribute should be used in conjunction with 'dormant' attribute
                to determine the interface usability. Possible values:
-               0: default link mode
-               1: dormant link mode
+
+               ==  =================
+               0   default link mode
+               1   dormant link mode
+               ==  =================
 
 What:          /sys/class/net/<iface>/mtu
 Date:          April 2005
@@ -226,7 +247,9 @@ KernelVersion:      2.6.17
 Contact:       netdev@vger.kernel.org
 Description:
                Indicates the interface RFC2863 operational state as a string.
+
                Possible values are:
+
                "unknown", "notpresent", "down", "lowerlayerdown", "testing",
                "dormant", "up".
 
index f7be0e88b139d0483bca5624aa0cffb9243309b0..06416d0e163d8ec4e13c7d7df566ff468fe4a701 100644 (file)
@@ -91,9 +91,9 @@ Date:         May 2014
 KernelVersion: 3.16
 Contact:       Bjørn Mork <bjorn@mork.no>
 Description:
-               Bit 0: 16-bit NTB supported (set to 1)
-               Bit 1: 32-bit NTB supported
-               Bits 2 â€“ 15: reserved (reset to zero; must be ignored by host)
+               Bit 0: 16-bit NTB supported (set to 1)
+               Bit 1: 32-bit NTB supported
+               Bits 2 â€“ 15: reserved (reset to zero; must be ignored by host)
 
 What:          /sys/class/net/<iface>/cdc_ncm/dwNtbInMaxSize
 Date:          May 2014
index 206cbf538b59c12ceb6df481358334a1bb2af272..40ced0ea431663fee1d71801ad87fb9939610940 100644 (file)
@@ -35,7 +35,9 @@ Description:
                Ethernet driver during bus enumeration, encoded in string.
                This interface mode is used to configure the Ethernet MAC with the
                appropriate mode for its data lines to the PHY hardware.
+
                Possible values are:
+
                <empty> (not available), mii, gmii, sgmii, tbi, rev-mii,
                rmii, rgmii, rgmii-id, rgmii-rxid, rgmii-txid, rtbi, smii
                xgmii, moca, qsgmii, trgmii, 1000base-x, 2500base-x, rxaui,
index ae1276efa45a2562866893abb49739d5997de474..847a7edc3113dd8d97d82bcc7e92ae0b1d32a488 100644 (file)
@@ -11,8 +11,11 @@ Contact:     linuxppc-dev@lists.ozlabs.org
 Description:   read only
                Number of contexts for the AFU, in the format <n>/<max>
                where:
-                       n:      number of currently active contexts, for debug
-                       max:    maximum number of contexts supported by the AFU
+
+                       ====    ===============================================
+                       n       number of currently active contexts, for debug
+                       max     maximum number of contexts supported by the AFU
+                       ====    ===============================================
 
 What:          /sys/class/ocxl/<afu name>/pp_mmio_size
 Date:          January 2018
@@ -40,7 +43,9 @@ Contact:      linuxppc-dev@lists.ozlabs.org
 Description:   read/write
                Control whether the FPGA is reloaded on a link reset. Enabled
                through a vendor-specific logic block on the FPGA.
-                       0       Do not reload FPGA image from flash
-                       1       Reload FPGA image from flash
-                       unavailable
-                               The device does not support this capability
+
+                       ===========  ===========================================
+                       0            Do not reload FPGA image from flash
+                       1            Reload FPGA image from flash
+                       unavailable  The device does not support this capability
+                       ===========  ===========================================
index dde4f26d0780e75e7c7397f0bfb8a4aa3cdbc2f6..ba1ce626591d9c4e666fea449075c44a3f447b17 100644 (file)
@@ -11,15 +11,17 @@ KernelVersion:      2.6.20
 Contact:       Thomas Maier <balagi@justmail.de>
 Description:
 
-               add:            (WO) Write a block device id (major:minor) to
+               ==========      ==============================================
+               add             (WO) Write a block device id (major:minor) to
                                create a new pktcdvd device and map it to the
                                block device.
 
-               remove:         (WO) Write the pktcdvd device id (major:minor)
+               remove          (WO) Write the pktcdvd device id (major:minor)
                                to remove the pktcdvd device.
 
-               device_map:     (RO) Shows the device mapping in format:
+               device_map      (RO) Shows the device mapping in format:
                                pktcdvd[0-7] <pktdevid> <blkdevid>
+               ==========      ==============================================
 
 
 What:          /sys/class/pktcdvd/pktcdvd[0-7]/dev
@@ -65,29 +67,31 @@ Date:               Oct. 2006
 KernelVersion: 2.6.20
 Contact:       Thomas Maier <balagi@justmail.de>
 Description:
-               size:           (RO) Contains the size of the bio write queue.
+               ==============  ================================================
+               size            (RO) Contains the size of the bio write queue.
 
-               congestion_off: (RW) If bio write queue size is below this mark,
+               congestion_off  (RW) If bio write queue size is below this mark,
                                accept new bio requests from the block layer.
 
-               congestion_on:  (RW) If bio write queue size is higher as this
+               congestion_on   (RW) If bio write queue size is higher as this
                                mark, do no longer accept bio write requests
                                from the block layer and wait till the pktcdvd
                                device has processed enough bio's so that bio
                                write queue size is below congestion off mark.
                                A value of <= 0 disables congestion control.
+               ==============  ================================================
 
 
 Example:
 --------
-To use the pktcdvd sysfs interface directly, you can do:
-
-# create a new pktcdvd device mapped to /dev/hdc
-echo "22:0" >/sys/class/pktcdvd/add
-cat /sys/class/pktcdvd/device_map
-# assuming device pktcdvd0 was created, look at stat's
-cat /sys/class/pktcdvd/pktcdvd0/stat/kb_written
-# print the device id of the mapped block device
-fgrep pktcdvd0 /sys/class/pktcdvd/device_map
-# remove device, using pktcdvd0 device id   253:0
-echo "253:0" >/sys/class/pktcdvd/remove
+To use the pktcdvd sysfs interface directly, you can do::
+
+    # create a new pktcdvd device mapped to /dev/hdc
+    echo "22:0" >/sys/class/pktcdvd/add
+    cat /sys/class/pktcdvd/device_map
+    # assuming device pktcdvd0 was created, look at stat's
+    cat /sys/class/pktcdvd/pktcdvd0/stat/kb_written
+    # print the device id of the mapped block device
+    fgrep pktcdvd0 /sys/class/pktcdvd/device_map
+    # remove device, using pktcdvd0 device id   253:0
+    echo "253:0" >/sys/class/pktcdvd/remove
index dbccb2fcd7ce7c65e0416a9307a09e7ba0f2ca91..ca830c6cd8094b047522d6d672be73a7193c2826 100644 (file)
@@ -1,4 +1,4 @@
-===== General Properties =====
+**General Properties**
 
 What:          /sys/class/power_supply/<supply_name>/manufacturer
 Date:          May 2007
@@ -36,14 +36,238 @@ Description:
                Access: Read
                Valid values: "Battery", "UPS", "Mains", "USB", "Wireless"
 
-===== Battery Properties =====
+**Battery and USB properties**
+
+What:          /sys/class/power_supply/<supply_name>/current_avg
+Date:          May 2007
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Battery:
+
+                 Reports an average IBAT current reading for the battery, over
+                 a fixed period. Normally devices will provide a fixed interval
+                 in which they average readings to smooth out the reported
+                 value.
+
+               USB:
+
+                 Reports an average IBUS current reading over a fixed period.
+                 Normally devices will provide a fixed interval in which they
+                 average readings to smooth out the reported value.
+
+               Access: Read
+
+               Valid values: Represented in microamps. Negative values are
+               used for discharging batteries, positive values for charging
+               batteries and for USB IBUS current.
+
+What:          /sys/class/power_supply/<supply_name>/current_max
+Date:          October 2010
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Battery:
+
+                 Reports the maximum IBAT current allowed into the battery.
+
+               USB:
+
+                 Reports the maximum IBUS current the supply can support.
+
+               Access: Read
+               Valid values: Represented in microamps
+
+What:          /sys/class/power_supply/<supply_name>/current_now
+Date:          May 2007
+Contact:       linux-pm@vger.kernel.org
+Description:
+
+               Battery:
+
+                 Reports an instant, single IBAT current reading for the
+                 battery. This value is not averaged/smoothed.
+
+                 Access: Read
+
+               USB:
+
+                 Reports the IBUS current supplied now. This value is generally
+                 read-only reporting, unless the 'online' state of the supply
+                 is set to be programmable, in which case this value can be set
+                 within the reported min/max range.
+
+                 Access: Read, Write
+
+               Valid values: Represented in microamps. Negative values are
+               used for discharging batteries, positive values for charging
+               batteries and for USB IBUS current.
+
+What:          /sys/class/power_supply/<supply_name>/temp
+Date:          May 2007
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Battery:
+
+                 Reports the current TBAT battery temperature reading.
+
+               USB:
+
+                 Reports the current supply temperature reading. This would
+                 normally be the internal temperature of the device itself
+                 (e.g TJUNC temperature of an IC)
+
+               Access: Read
+
+               Valid values: Represented in 1/10 Degrees Celsius
+
+What:          /sys/class/power_supply/<supply_name>/temp_alert_max
+Date:          July 2012
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Battery:
+
+                 Maximum TBAT temperature trip-wire value where the supply will
+                 notify user-space of the event.
+
+               USB:
+
+                 Maximum supply temperature trip-wire value where the supply
+                 will notify user-space of the event.
+
+               This is normally used for the charging scenario where
+               user-space needs to know if the temperature has crossed an
+               upper threshold so it can take appropriate action (e.g. warning
+               user that the temperature is critically high, and charging has
+               stopped).
+
+               Access: Read
+
+               Valid values: Represented in 1/10 Degrees Celsius
+
+What:          /sys/class/power_supply/<supply_name>/temp_alert_min
+Date:          July 2012
+Contact:       linux-pm@vger.kernel.org
+Description:
+
+               Battery:
+
+                 Minimum TBAT temperature trip-wire value where the supply will
+                 notify user-space of the event.
+
+               USB:
+
+                 Minimum supply temperature trip-wire value where the supply
+                 will notify user-space of the event.
+
+               This is normally used for the charging scenario where user-space
+               needs to know if the temperature has crossed a lower threshold
+               so it can take appropriate action (e.g. warning user that
+               temperature level is high, and charging current has been
+               reduced accordingly to remedy the situation).
+
+               Access: Read
+
+               Valid values: Represented in 1/10 Degrees Celsius
+
+What:          /sys/class/power_supply/<supply_name>/temp_max
+Date:          July 2014
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Battery:
+
+                 Reports the maximum allowed TBAT battery temperature for
+                 charging.
+
+               USB:
+
+                 Reports the maximum allowed supply temperature for operation.
+
+               Access: Read
+
+               Valid values: Represented in 1/10 Degrees Celsius
+
+What:          /sys/class/power_supply/<supply_name>/temp_min
+Date:          July 2014
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Battery:
+
+                 Reports the minimum allowed TBAT battery temperature for
+                 charging.
+
+               USB:
+
+                 Reports the minimum allowed supply temperature for operation.
+
+               Access: Read
+
+               Valid values: Represented in 1/10 Degrees Celsius
+
+What:          /sys/class/power_supply/<supply_name>/voltage_max,
+Date:          January 2008
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Battery:
+
+                 Reports the maximum safe VBAT voltage permitted for the
+                 battery, during charging.
+
+               USB:
+
+                 Reports the maximum VBUS voltage the supply can support.
+
+               Access: Read
+
+               Valid values: Represented in microvolts
+
+What:          /sys/class/power_supply/<supply_name>/voltage_min,
+Date:          January 2008
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Battery:
+
+                 Reports the minimum safe VBAT voltage permitted for the
+                 battery, during discharging.
+
+               USB:
+
+                 Reports the minimum VBUS voltage the supply can support.
+
+               Access: Read
+
+               Valid values: Represented in microvolts
+
+What:          /sys/class/power_supply/<supply_name>/voltage_now,
+Date:          May 2007
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Battery:
+
+                 Reports an instant, single VBAT voltage reading for the
+                 battery. This value is not averaged/smoothed.
+
+                 Access: Read
+
+               USB:
+
+                 Reports the VBUS voltage supplied now. This value is generally
+                 read-only reporting, unless the 'online' state of the supply
+                 is set to be programmable, in which case this value can be set
+                 within the reported min/max range.
+
+                 Access: Read, Write
+
+               Valid values: Represented in microvolts
+
+**Battery Properties**
 
 What:          /sys/class/power_supply/<supply_name>/capacity
 Date:          May 2007
 Contact:       linux-pm@vger.kernel.org
 Description:
                Fine grain representation of battery capacity.
+
                Access: Read
+
                Valid values: 0 - 100 (percent)
 
 What:          /sys/class/power_supply/<supply_name>/capacity_alert_max
@@ -58,6 +282,7 @@ Description:
                low).
 
                Access: Read, Write
+
                Valid values: 0 - 100 (percent)
 
 What:          /sys/class/power_supply/<supply_name>/capacity_alert_min
@@ -72,6 +297,7 @@ Description:
                critically low).
 
                Access: Read, Write
+
                Valid values: 0 - 100 (percent)
 
 What:          /sys/class/power_supply/<supply_name>/capacity_error_margin
@@ -87,6 +313,7 @@ Description:
                completely useless.
 
                Access: Read
+
                Valid values: 0 - 100 (percent)
 
 What:          /sys/class/power_supply/<supply_name>/capacity_level
@@ -96,40 +323,10 @@ Description:
                Coarse representation of battery capacity.
 
                Access: Read
-               Valid values: "Unknown", "Critical", "Low", "Normal", "High",
-                             "Full"
-
-What:          /sys/class/power_supply/<supply_name>/current_avg
-Date:          May 2007
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports an average IBAT current reading for the battery, over a
-               fixed period. Normally devices will provide a fixed interval in
-               which they average readings to smooth out the reported value.
-
-               Access: Read
-               Valid values: Represented in microamps. Negative values are used
-               for discharging batteries, positive values for charging batteries.
 
-What:          /sys/class/power_supply/<supply_name>/current_max
-Date:          October 2010
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports the maximum IBAT current allowed into the battery.
-
-               Access: Read
-               Valid values: Represented in microamps
-
-What:          /sys/class/power_supply/<supply_name>/current_now
-Date:          May 2007
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports an instant, single IBAT current reading for the battery.
-               This value is not averaged/smoothed.
-
-               Access: Read
-               Valid values: Represented in microamps. Negative values are used
-               for discharging batteries, positive values for charging batteries.
+               Valid values:
+                             "Unknown", "Critical", "Low", "Normal", "High",
+                             "Full"
 
 What:          /sys/class/power_supply/<supply_name>/charge_control_limit
 Date:          Oct 2012
@@ -139,6 +336,7 @@ Description:
                throttling for thermal cooling or improving battery health.
 
                Access: Read, Write
+
                Valid values: Represented in microamps
 
 What:          /sys/class/power_supply/<supply_name>/charge_control_limit_max
@@ -148,6 +346,7 @@ Description:
                Maximum legal value for the charge_control_limit property.
 
                Access: Read
+
                Valid values: Represented in microamps
 
 What:          /sys/class/power_supply/<supply_name>/charge_control_start_threshold
@@ -168,6 +367,7 @@ Description:
                stop.
 
                Access: Read, Write
+
                Valid values: 0 - 100 (percent)
 
 What:          /sys/class/power_supply/<supply_name>/charge_type
@@ -183,7 +383,9 @@ Description:
                different algorithm.
 
                Access: Read, Write
-               Valid values: "Unknown", "N/A", "Trickle", "Fast", "Standard",
+
+               Valid values:
+                             "Unknown", "N/A", "Trickle", "Fast", "Standard",
                              "Adaptive", "Custom"
 
 What:          /sys/class/power_supply/<supply_name>/charge_term_current
@@ -194,6 +396,7 @@ Description:
                when the battery is considered full and charging should end.
 
                Access: Read
+
                Valid values: Represented in microamps
 
 What:          /sys/class/power_supply/<supply_name>/health
@@ -204,7 +407,9 @@ Description:
                functionality.
 
                Access: Read
-               Valid values: "Unknown", "Good", "Overheat", "Dead",
+
+               Valid values:
+                             "Unknown", "Good", "Overheat", "Dead",
                              "Over voltage", "Unspecified failure", "Cold",
                              "Watchdog timer expire", "Safety timer expire",
                              "Over current", "Calibration required", "Warm",
@@ -218,6 +423,7 @@ Description:
                for a battery charge cycle.
 
                Access: Read
+
                Valid values: Represented in microamps
 
 What:          /sys/class/power_supply/<supply_name>/present
@@ -227,9 +433,13 @@ Description:
                Reports whether a battery is present or not in the system.
 
                Access: Read
+
                Valid values:
+
+                       == =======
                        0: Absent
                        1: Present
+                       == =======
 
 What:          /sys/class/power_supply/<supply_name>/status
 Date:          May 2007
@@ -240,7 +450,9 @@ Description:
                used to enable/disable charging to the battery.
 
                Access: Read, Write
-               Valid values: "Unknown", "Charging", "Discharging",
+
+               Valid values:
+                             "Unknown", "Charging", "Discharging",
                              "Not charging", "Full"
 
 What:          /sys/class/power_supply/<supply_name>/technology
@@ -250,66 +462,11 @@ Description:
                Describes the battery technology supported by the supply.
 
                Access: Read
-               Valid values: "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe",
-                             "NiCd", "LiMn"
-
-What:          /sys/class/power_supply/<supply_name>/temp
-Date:          May 2007
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports the current TBAT battery temperature reading.
-
-               Access: Read
-               Valid values: Represented in 1/10 Degrees Celsius
-
-What:          /sys/class/power_supply/<supply_name>/temp_alert_max
-Date:          July 2012
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Maximum TBAT temperature trip-wire value where the supply will
-               notify user-space of the event. This is normally used for the
-               battery charging scenario where user-space needs to know the
-               battery temperature has crossed an upper threshold so it can
-               take appropriate action (e.g. warning user that battery level is
-               critically high, and charging has stopped).
-
-               Access: Read
-               Valid values: Represented in 1/10 Degrees Celsius
-
-What:          /sys/class/power_supply/<supply_name>/temp_alert_min
-Date:          July 2012
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Minimum TBAT temperature trip-wire value where the supply will
-               notify user-space of the event. This is normally used for the
-               battery charging scenario where user-space needs to know the
-               battery temperature has crossed a lower threshold so it can take
-               appropriate action (e.g. warning user that battery level is
-               high, and charging current has been reduced accordingly to
-               remedy the situation).
-
-               Access: Read
-               Valid values: Represented in 1/10 Degrees Celsius
-
-What:          /sys/class/power_supply/<supply_name>/temp_max
-Date:          July 2014
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports the maximum allowed TBAT battery temperature for
-               charging.
-
-               Access: Read
-               Valid values: Represented in 1/10 Degrees Celsius
 
-What:          /sys/class/power_supply/<supply_name>/temp_min
-Date:          July 2014
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports the minimum allowed TBAT battery temperature for
-               charging.
+               Valid values:
+                             "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe",
+                             "NiCd", "LiMn"
 
-               Access: Read
-               Valid values: Represented in 1/10 Degrees Celsius
 
 What:          /sys/class/power_supply/<supply_name>/voltage_avg,
 Date:          May 2007
@@ -320,72 +477,10 @@ Description:
                which they average readings to smooth out the reported value.
 
                Access: Read
-               Valid values: Represented in microvolts
-
-What:          /sys/class/power_supply/<supply_name>/voltage_max,
-Date:          January 2008
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports the maximum safe VBAT voltage permitted for the battery,
-               during charging.
-
-               Access: Read
-               Valid values: Represented in microvolts
-
-What:          /sys/class/power_supply/<supply_name>/voltage_min,
-Date:          January 2008
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports the minimum safe VBAT voltage permitted for the battery,
-               during discharging.
 
-               Access: Read
                Valid values: Represented in microvolts
 
-What:          /sys/class/power_supply/<supply_name>/voltage_now,
-Date:          May 2007
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports an instant, single VBAT voltage reading for the battery.
-               This value is not averaged/smoothed.
-
-               Access: Read
-               Valid values: Represented in microvolts
-
-===== USB Properties =====
-
-What:          /sys/class/power_supply/<supply_name>/current_avg
-Date:          May 2007
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports an average IBUS current reading over a fixed period.
-               Normally devices will provide a fixed interval in which they
-               average readings to smooth out the reported value.
-
-               Access: Read
-               Valid values: Represented in microamps
-
-
-What:          /sys/class/power_supply/<supply_name>/current_max
-Date:          October 2010
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports the maximum IBUS current the supply can support.
-
-               Access: Read
-               Valid values: Represented in microamps
-
-What:          /sys/class/power_supply/<supply_name>/current_now
-Date:          May 2007
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports the IBUS current supplied now. This value is generally
-               read-only reporting, unless the 'online' state of the supply
-               is set to be programmable, in which case this value can be set
-               within the reported min/max range.
-
-               Access: Read, Write
-               Valid values: Represented in microamps
+**USB Properties**
 
 What:          /sys/class/power_supply/<supply_name>/input_current_limit
 Date:          July 2014
@@ -399,6 +494,7 @@ Description:
                solved using power limit use input_current_limit.
 
                Access: Read, Write
+
                Valid values: Represented in microamps
 
 What:          /sys/class/power_supply/<supply_name>/input_voltage_limit
@@ -416,6 +512,7 @@ Description:
                solved using power limit use input_voltage_limit.
 
                Access: Read, Write
+
                Valid values: Represented in microvolts
 
 What:          /sys/class/power_supply/<supply_name>/input_power_limit
@@ -429,6 +526,7 @@ Description:
                limit only for problems that can be solved using power limit.
 
                Access: Read, Write
+
                Valid values: Represented in microwatts
 
 What:          /sys/class/power_supply/<supply_name>/online,
@@ -441,69 +539,14 @@ Description:
                USB supply so voltage and current can be controlled).
 
                Access: Read, Write
+
                Valid values:
+
+                       == ==================================================
                        0: Offline
                        1: Online Fixed - Fixed Voltage Supply
                        2: Online Programmable - Programmable Voltage Supply
-
-What:          /sys/class/power_supply/<supply_name>/temp
-Date:          May 2007
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports the current supply temperature reading. This would
-               normally be the internal temperature of the device itself (e.g
-               TJUNC temperature of an IC)
-
-               Access: Read
-               Valid values: Represented in 1/10 Degrees Celsius
-
-What:          /sys/class/power_supply/<supply_name>/temp_alert_max
-Date:          July 2012
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Maximum supply temperature trip-wire value where the supply will
-               notify user-space of the event. This is normally used for the
-               charging scenario where user-space needs to know the supply
-               temperature has crossed an upper threshold so it can take
-               appropriate action (e.g. warning user that the supply
-               temperature is critically high, and charging has stopped to
-               remedy the situation).
-
-               Access: Read
-               Valid values: Represented in 1/10 Degrees Celsius
-
-What:          /sys/class/power_supply/<supply_name>/temp_alert_min
-Date:          July 2012
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Minimum supply temperature trip-wire value where the supply will
-               notify user-space of the event. This is normally used for the
-               charging scenario where user-space needs to know the supply
-               temperature has crossed a lower threshold so it can take
-               appropriate action (e.g. warning user that the supply
-               temperature is high, and charging current has been reduced
-               accordingly to remedy the situation).
-
-               Access: Read
-               Valid values: Represented in 1/10 Degrees Celsius
-
-What:          /sys/class/power_supply/<supply_name>/temp_max
-Date:          July 2014
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports the maximum allowed supply temperature for operation.
-
-               Access: Read
-               Valid values: Represented in 1/10 Degrees Celsius
-
-What:          /sys/class/power_supply/<supply_name>/temp_min
-Date:          July 2014
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports the mainimum allowed supply temperature for operation.
-
-               Access: Read
-               Valid values: Represented in 1/10 Degrees Celsius
+                       == ==================================================
 
 What:          /sys/class/power_supply/<supply_name>/usb_type
 Date:          March 2018
@@ -514,40 +557,12 @@ Description:
                is attached.
 
                Access: Read-Only
-               Valid values: "Unknown", "SDP", "DCP", "CDP", "ACA", "C", "PD",
-                             "PD_DRP", "PD_PPS", "BrickID"
-
-What:          /sys/class/power_supply/<supply_name>/voltage_max
-Date:          January 2008
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports the maximum VBUS voltage the supply can support.
-
-               Access: Read
-               Valid values: Represented in microvolts
-
-What:          /sys/class/power_supply/<supply_name>/voltage_min
-Date:          January 2008
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports the minimum VBUS voltage the supply can support.
 
-               Access: Read
-               Valid values: Represented in microvolts
-
-What:          /sys/class/power_supply/<supply_name>/voltage_now
-Date:          May 2007
-Contact:       linux-pm@vger.kernel.org
-Description:
-               Reports the VBUS voltage supplied now. This value is generally
-               read-only reporting, unless the 'online' state of the supply
-               is set to be programmable, in which case this value can be set
-               within the reported min/max range.
-
-               Access: Read, Write
-               Valid values: Represented in microvolts
+               Valid values:
+                             "Unknown", "SDP", "DCP", "CDP", "ACA", "C", "PD",
+                             "PD_DRP", "PD_PPS", "BrickID"
 
-===== Device Specific Properties =====
+**Device Specific Properties**
 
 What:          /sys/class/power/ds2760-battery.*/charge_now
 Date:          May 2010
@@ -581,6 +596,7 @@ Description:
                will drop to 0 A) and will trigger interrupt.
 
                Valid values:
+
                - 5, 6 or 7 (hours),
                - 0: disabled.
 
@@ -595,6 +611,7 @@ Description:
                will drop to 0 A) and will trigger interrupt.
 
                Valid values:
+
                - 4 - 16 (hours), step by 2 (rounded down)
                - 0: disabled.
 
@@ -609,6 +626,7 @@ Description:
                interrupt and start top-off charging mode.
 
                Valid values:
+
                - 100000 - 200000 (microamps), step by 25000 (rounded down)
                - 200000 - 350000 (microamps), step by 50000 (rounded down)
                - 0: disabled.
@@ -624,6 +642,7 @@ Description:
                will drop to 0 A) and will trigger interrupt.
 
                Valid values:
+
                - 0 - 70 (minutes), step by 10 (rounded down)
 
 What:          /sys/class/power_supply/bq24257-charger/ovp_voltage
@@ -637,6 +656,7 @@ Description:
                device datasheet for details.
 
                Valid values:
+
                - 6000000, 6500000, 7000000, 8000000, 9000000, 9500000, 10000000,
                  10500000 (all uV)
 
@@ -652,6 +672,7 @@ Description:
                lower than the set value. See device datasheet for details.
 
                Valid values:
+
                - 4200000, 4280000, 4360000, 4440000, 4520000, 4600000, 4680000,
                  4760000 (all uV)
 
@@ -666,6 +687,7 @@ Description:
                the charger operates normally. See device datasheet for details.
 
                Valid values:
+
                - 1: enabled
                - 0: disabled
 
@@ -681,6 +703,7 @@ Description:
                from the system. See device datasheet for details.
 
                Valid values:
+
                - 1: enabled
                - 0: disabled
 
@@ -692,6 +715,7 @@ Description:
                manufactured.
 
                Access: Read
+
                Valid values: Reported as integer
 
 What:          /sys/class/power_supply/<supply_name>/manufacture_month
@@ -701,6 +725,7 @@ Description:
                Reports the month when the device has been manufactured.
 
                Access: Read
+
                Valid values: 1-12
 
 What:          /sys/class/power_supply/<supply_name>/manufacture_day
index 327a07e22805ba6888fa4d24655325d6a5051cad..914d67caac0d79e3fd9e6f4ea192d1f55dacf53a 100644 (file)
@@ -5,4 +5,5 @@ Description:
                Represents a battery impedance compensation to accelerate charging.
 
                 Access: Read, Write
+
                 Valid values: Represented in milli-ohms. Valid range is [0, 140].
index b4fd32d210c55261dfba8af264e8755314876037..b52f7023f8ba0123334e14c3f920c64d3304e786 100644 (file)
@@ -4,18 +4,20 @@ Description:
        Writing to this can disable charging.
 
        Possible values are:
-               "auto" - draw power as appropriate for detected
-                        power source and battery status.
-               "off"  - do not draw any power.
-               "continuous"
-                      - activate mode described as "linear" in
-                        TWL data sheets.  This uses whatever
-                        current is available and doesn't switch off
-                        when voltage drops.
 
-                        This is useful for unstable power sources
-                        such as bicycle dynamo, but care should
-                        be taken that battery is not over-charged.
+               =============   ===========================================
+               "auto"          draw power as appropriate for detected
+                               power source and battery status.
+               "off"           do not draw any power.
+               "continuous"    activate mode described as "linear" in
+                               TWL data sheets.  This uses whatever
+                               current is available and doesn't switch off
+                               when voltage drops.
+
+                               This is useful for unstable power sources
+                               such as bicycle dynamo, but care should
+                               be taken that battery is not over-charged.
+               =============   ===========================================
 
 What: /sys/class/power_supply/twl4030_ac/mode
 Description:
@@ -23,6 +25,9 @@ Description:
        Writing to this can disable charging.
 
        Possible values are:
-               "auto" - draw power as appropriate for detected
-                        power source and battery status.
-               "off"  - do not draw any power.
+
+               ======  ===========================================
+               "auto"  draw power as appropriate for detected
+                       power source and battery status.
+               "off"   do not draw any power.
+               ======  ===========================================
index 84fde1d0ada065e1fd972acaea4eef4d8c4b7b73..82af180fcaab991056bf3f3218ee03ab4bb840c7 100644 (file)
@@ -4,17 +4,23 @@ KernelVersion:        5.2
 Description:
                What charging algorithm to use:
 
-               Standard: Fully charges battery at a standard rate.
-               Adaptive: Battery settings adaptively optimized based on
+               Standard:
+                       Fully charges battery at a standard rate.
+               Adaptive:
+                       Battery settings adaptively optimized based on
                        typical battery usage pattern.
-               Fast: Battery charges over a shorter period.
-               Trickle: Extends battery lifespan, intended for users who
+               Fast:
+                       Battery charges over a shorter period.
+               Trickle:
+                       Extends battery lifespan, intended for users who
                        primarily use their Chromebook while connected to AC.
-               Custom: A low and high threshold percentage is specified.
+               Custom:
+                       A low and high threshold percentage is specified.
                        Charging begins when level drops below
                        charge_control_start_threshold, and ceases when
                        level is above charge_control_end_threshold.
-               Long Life: Customized charge rate for last longer battery life.
+               Long Life:
+                       Customized charge rate for last longer battery life.
                        On Wilco device this mode is pre-configured in the factory
                        through EC's private PID. Swiching to a different mode will
                        be denied by Wilco EC when Long Life mode is enabled.
index 8716beeb16c16cbb401a68999de909e32a5efc01..19aefb21b639dd1cd607008ee61b59c7d174692a 100644 (file)
@@ -6,6 +6,7 @@ Description:
                The /sys/class/rapidio_port subdirectory contains individual
                subdirectories named as "rapidioN" where N = mport ID registered
                with RapidIO subsystem.
+
                NOTE: An mport ID is not a RapidIO destination ID assigned to a
                given local mport device.
 
@@ -16,7 +17,9 @@ Contact:      Matt Porter <mporter@kernel.crashing.org>,
                Alexandre Bounine <alexandre.bounine@idt.com>
 Description:
                (RO) reports RapidIO common transport system size:
+
                0 = small (8-bit destination ID, max. 256 devices),
+
                1 = large (16-bit destination ID, max. 65536 devices).
 
 What:          /sys/class/rapidio_port/rapidioN/port_destid
@@ -25,31 +28,32 @@ KernelVersion:      v3.15
 Contact:       Matt Porter <mporter@kernel.crashing.org>,
                Alexandre Bounine <alexandre.bounine@idt.com>
 Description:
-               (RO) reports RapidIO destination ID assigned to the given
-               RapidIO mport device. If value 0xFFFFFFFF is returned this means
-               that no valid destination ID have been assigned to the mport
-               (yet). Normally, before enumeration/discovery have been executed
-               only fabric enumerating mports have a valid destination ID
-               assigned to them using "hdid=..." rapidio module parameter.
+
+(RO) reports RapidIO destination ID assigned to the given
+RapidIO mport device. If value 0xFFFFFFFF is returned this means
+that no valid destination ID have been assigned to the mport
+(yet). Normally, before enumeration/discovery have been executed
+only fabric enumerating mports have a valid destination ID
+assigned to them using "hdid=..." rapidio module parameter.
 
 After enumeration or discovery was performed for a given mport device,
 the corresponding subdirectory will also contain subdirectories for each
 child RapidIO device connected to the mport.
 
 The example below shows mport device subdirectory with several child RapidIO
-devices attached to it.
-
-[rio@rapidio ~]$ ls /sys/class/rapidio_port/rapidio0/ -l
-total 0
-drwxr-xr-x 3 root root    0 Feb 11 15:10 00:e:0001
-drwxr-xr-x 3 root root    0 Feb 11 15:10 00:e:0004
-drwxr-xr-x 3 root root    0 Feb 11 15:10 00:e:0007
-drwxr-xr-x 3 root root    0 Feb 11 15:10 00:s:0002
-drwxr-xr-x 3 root root    0 Feb 11 15:10 00:s:0003
-drwxr-xr-x 3 root root    0 Feb 11 15:10 00:s:0005
-lrwxrwxrwx 1 root root    0 Feb 11 15:11 device -> ../../../0000:01:00.0
--r--r--r-- 1 root root 4096 Feb 11 15:11 port_destid
-drwxr-xr-x 2 root root    0 Feb 11 15:11 power
-lrwxrwxrwx 1 root root    0 Feb 11 15:04 subsystem -> ../../../../../../class/rapidio_port
--r--r--r-- 1 root root 4096 Feb 11 15:11 sys_size
--rw-r--r-- 1 root root 4096 Feb 11 15:04 uevent
+devices attached to it::
+
+    [rio@rapidio ~]$ ls /sys/class/rapidio_port/rapidio0/ -l
+    total 0
+    drwxr-xr-x 3 root root    0 Feb 11 15:10 00:e:0001
+    drwxr-xr-x 3 root root    0 Feb 11 15:10 00:e:0004
+    drwxr-xr-x 3 root root    0 Feb 11 15:10 00:e:0007
+    drwxr-xr-x 3 root root    0 Feb 11 15:10 00:s:0002
+    drwxr-xr-x 3 root root    0 Feb 11 15:10 00:s:0003
+    drwxr-xr-x 3 root root    0 Feb 11 15:10 00:s:0005
+    lrwxrwxrwx 1 root root    0 Feb 11 15:11 device -> ../../../0000:01:00.0
+    -r--r--r-- 1 root root 4096 Feb 11 15:11 port_destid
+    drwxr-xr-x 2 root root    0 Feb 11 15:11 power
+    lrwxrwxrwx 1 root root    0 Feb 11 15:04 subsystem -> ../../../../../../class/rapidio_port
+    -r--r--r-- 1 root root 4096 Feb 11 15:11 sys_size
+    -rw-r--r-- 1 root root 4096 Feb 11 15:04 uevent
index 6c0d6c8cb91105779324b78efe4d3c12bb191316..9c8ff79108583f90ebedf3d493fd22b8807142e9 100644 (file)
@@ -21,15 +21,22 @@ KernelVersion:      2.6.36
 Contact:       Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
 Description:
                Reading this file returns a list of available protocols,
-               something like:
+               something like::
+
                    "rc5 [rc6] nec jvc [sony]"
+
                Enabled protocols are shown in [] brackets.
+
                Writing "+proto" will add a protocol to the list of enabled
                protocols.
+
                Writing "-proto" will remove a protocol from the list of enabled
                protocols.
+
                Writing "proto" will enable only "proto".
+
                Writing "none" will disable all protocols.
+
                Write fails with EINVAL if an invalid protocol combination or
                unknown protocol name is used.
 
@@ -39,11 +46,13 @@ KernelVersion:      3.15
 Contact:       Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
 Description:
                Sets the scancode filter expected value.
+
                Use in combination with /sys/class/rc/rcN/filter_mask to set the
                expected value of the bits set in the filter mask.
                If the hardware supports it then scancodes which do not match
                the filter will be ignored. Otherwise the write will fail with
                an error.
+
                This value may be reset to 0 if the current protocol is altered.
 
 What:          /sys/class/rc/rcN/filter_mask
@@ -56,9 +65,11 @@ Description:
                of the scancode which should be compared against the expected
                value. A value of 0 disables the filter to allow all valid
                scancodes to be processed.
+
                If the hardware supports it then scancodes which do not match
                the filter will be ignored. Otherwise the write will fail with
                an error.
+
                This value may be reset to 0 if the current protocol is altered.
 
 What:          /sys/class/rc/rcN/wakeup_protocols
@@ -67,15 +78,22 @@ KernelVersion:      4.11
 Contact:       Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
 Description:
                Reading this file returns a list of available protocols to use
-               for the wakeup filter, something like:
+               for the wakeup filter, something like::
+
                    "rc-5 nec nec-x rc-6-0 rc-6-6a-24 [rc-6-6a-32] rc-6-mce"
+
                Note that protocol variants are listed, so "nec", "sony",
                "rc-5", "rc-6" have their different bit length encodings
                listed if available.
+
                The enabled wakeup protocol is shown in [] brackets.
+
                Only one protocol can be selected at a time.
+
                Writing "proto" will use "proto" for wakeup events.
+
                Writing "none" will disable wakeup.
+
                Write fails with EINVAL if an invalid protocol combination or
                unknown protocol name is used, or if wakeup is not supported by
                the hardware.
@@ -86,13 +104,17 @@ KernelVersion:     3.15
 Contact:       Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
 Description:
                Sets the scancode wakeup filter expected value.
+
                Use in combination with /sys/class/rc/rcN/wakeup_filter_mask to
                set the expected value of the bits set in the wakeup filter mask
                to trigger a system wake event.
+
                If the hardware supports it and wakeup_filter_mask is not 0 then
                scancodes which match the filter will wake the system from e.g.
                suspend to RAM or power off.
+
                Otherwise the write will fail with an error.
+
                This value may be reset to 0 if the wakeup protocol is altered.
 
 What:          /sys/class/rc/rcN/wakeup_filter_mask
@@ -101,11 +123,15 @@ KernelVersion:    3.15
 Contact:       Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
 Description:
                Sets the scancode wakeup filter mask of bits to compare.
+
                Use in combination with /sys/class/rc/rcN/wakeup_filter to set
                the bits of the scancode which should be compared against the
                expected value to trigger a system wake event.
+
                If the hardware supports it and wakeup_filter_mask is not 0 then
                scancodes which match the filter will wake the system from e.g.
                suspend to RAM or power off.
+
                Otherwise the write will fail with an error.
+
                This value may be reset to 0 if the wakeup protocol is altered.
index bc578bc606284bf248fe87169e8cda0dbdfa4f3a..8516f08806dd992b04841d48d4ec55410d9189fb 100644 (file)
@@ -35,13 +35,13 @@ Description:
 
                This will be one of the following strings:
 
-                       off
-                       on
-                       error
-                       fast
-                       normal
-                       idle
-                       standby
+                       off
+                       on
+                       error
+                       fast
+                       normal
+                       idle
+                       standby
 
                "off" means the regulator is not supplying power to the
                system.
@@ -74,9 +74,9 @@ Description:
 
                This will be one of the following strings:
 
-               'voltage'
-               'current'
-               'unknown'
+               'voltage'
+               'current'
+               'unknown'
 
                'voltage' means the regulator output voltage can be controlled
                by software.
@@ -129,11 +129,11 @@ Description:
 
                The opmode value can be one of the following strings:
 
-               'fast'
-               'normal'
-               'idle'
-               'standby'
-               'unknown'
+               'fast'
+               'normal'
+               'idle'
+               'standby'
+               'unknown'
 
                The modes are described in include/linux/regulator/consumer.h
 
@@ -360,9 +360,9 @@ Description:
 
                This will be one of the following strings:
 
-               'enabled'
-               'disabled'
-               'unknown'
+               'enabled'
+               'disabled'
+               'unknown'
 
                'enabled' means the regulator is in bypass mode.
 
index 066b9b6f4924d76b8b116684dd8def5f030d7beb..0c9ee55098b8200138fcc57bed8d29391c1be63b 100644 (file)
@@ -16,11 +16,11 @@ Description:        Remote processor state
 
                Reports the state of the remote processor, which will be one of:
 
-               "offline"
-               "suspended"
-               "running"
-               "crashed"
-               "invalid"
+               "offline"
+               "suspended"
+               "running"
+               "crashed"
+               "invalid"
 
                "offline" means the remote processor is powered off.
 
@@ -38,8 +38,8 @@ Description:  Remote processor state
                Writing this file controls the state of the remote processor.
                The following states can be written:
 
-               "start"
-               "stop"
+               "start"
+               "stop"
 
                Writing "start" will attempt to start the processor running the
                firmware indicated by, or written to,
index c084f203b41ed7903ad29ac7046052a76a2da052..00c0286733d48c2cf845cb169697e8e7994d6bd2 100644 (file)
@@ -5,62 +5,70 @@ Contact:      Jack Wang <jinpu.wang@cloud.ionos.com> Danil Kipnis <danil.kipnis@cloud
 Description:   Provide information about RNBD-client.
                All sysfs files that are not read-only provide the usage information on read:
 
-               Example:
-               # cat /sys/class/rnbd-client/ctl/map_device
+               Example::
 
-               > Usage: echo "sessname=<name of the rtrs session> path=<[srcaddr,]dstaddr>
-               > [path=<[srcaddr,]dstaddr>] device_path=<full path on remote side>
-               > [access_mode=<ro|rw|migration>] > map_device
-               >
-               > addr ::= [ ip:<ipv4> | ip:<ipv6> | gid:<gid> ]
+                   # cat /sys/class/rnbd-client/ctl/map_device
+
+                   > Usage: echo "sessname=<name of the rtrs session> path=<[srcaddr,]dstaddr>
+                   > [path=<[srcaddr,]dstaddr>] device_path=<full path on remote side>
+                   > [access_mode=<ro|rw|migration>] > map_device
+                   >
+                   > addr ::= [ ip:<ipv4> | ip:<ipv6> | gid:<gid> ]
 
 What:          /sys/class/rnbd-client/ctl/map_device
 Date:          Feb 2020
 KernelVersion: 5.7
 Contact:       Jack Wang <jinpu.wang@cloud.ionos.com> Danil Kipnis <danil.kipnis@cloud.ionos.com>
-Description:   Expected format is the following:
+Description:   Expected format is the following::
 
-               sessname=<name of the rtrs session>
-               path=<[srcaddr,]dstaddr> [path=<[srcaddr,]dstaddr> ...]
-               device_path=<full path on remote side>
-               [access_mode=<ro|rw|migration>]
+                   sessname=<name of the rtrs session>
+                   path=<[srcaddr,]dstaddr> [path=<[srcaddr,]dstaddr> ...]
+                   device_path=<full path on remote side>
+                   [access_mode=<ro|rw|migration>]
 
                Where:
 
-               sessname: accepts a string not bigger than 256 chars, which identifies
-               a given session on the client and on the server.
-               I.e. "clt_hostname-srv_hostname" could be a natural choice.
+               sessname:
+                   accepts a string not bigger than 256 chars, which identifies
+                   a given session on the client and on the server.
+                   I.e. "clt_hostname-srv_hostname" could be a natural choice.
+
+               path:
+                   describes a connection between the client and the server by
+                   specifying destination and, when required, the source address.
+                   The addresses are to be provided in the following format::
 
-               path:     describes a connection between the client and the server by
-               specifying destination and, when required, the source address.
-               The addresses are to be provided in the following format:
+                       ip:<IPv6>
+                       ip:<IPv4>
+                       gid:<GID>
 
-               ip:<IPv6>
-               ip:<IPv4>
-               gid:<GID>
+               for example::
 
-               for example:
+                   path=ip:10.0.0.66
 
-               path=ip:10.0.0.66
                The single addr is treated as the destination.
                The connection will be established to this server from any client IP address.
 
-               path=ip:10.0.0.66,ip:10.0.1.66
+               ::
+
+                   path=ip:10.0.0.66,ip:10.0.1.66
+
                First addr is the source address and the second is the destination.
 
                If multiple "path=" options are specified multiple connection
                will be established and data will be sent according to
                the selected multipath policy (see RTRS mp_policy sysfs entry description).
 
-               device_path: Path to the block device on the server side. Path is specified
-               relative to the directory on server side configured in the
-               'dev_search_path' module parameter of the rnbd_server.
-               The rnbd_server prepends the <device_path> received from client
-               with <dev_search_path> and tries to open the
-               <dev_search_path>/<device_path> block device.  On success,
-               a /dev/rnbd<N> device file, a /sys/block/rnbd_client/rnbd<N>/
-               directory and an entry in /sys/class/rnbd-client/ctl/devices
-               will be created.
+               device_path:
+                   Path to the block device on the server side. Path is specified
+                   relative to the directory on server side configured in the
+                   'dev_search_path' module parameter of the rnbd_server.
+                   The rnbd_server prepends the <device_path> received from client
+                   with <dev_search_path> and tries to open the
+                   <dev_search_path>/<device_path> block device.  On success,
+                   a /dev/rnbd<N> device file, a /sys/block/rnbd_client/rnbd<N>/
+                   directory and an entry in /sys/class/rnbd-client/ctl/devices
+                   will be created.
 
                If 'dev_search_path' contains '%SESSNAME%', then each session can
                have different devices namespace, e.g. server was configured with
@@ -68,11 +76,12 @@ Description:        Expected format is the following:
                client has this string "sessname=blya device_path=sda", then server
                will try to open: /run/rnbd-devs/blya/sda.
 
-               access_mode: the access_mode parameter specifies if the device is to be
-               mapped as "ro" read-only or "rw" read-write. The server allows
-               a device to be exported in rw mode only once. The "migration"
-               access mode has to be specified if a second mapping in read-write
-               mode is desired.
+               access_mode:
+                   the access_mode parameter specifies if the device is to be
+                   mapped as "ro" read-only or "rw" read-write. The server allows
+                   a device to be exported in rw mode only once. The "migration"
+                   access mode has to be specified if a second mapping in read-write
+                   mode is desired.
 
                By default "rw" is used.
 
@@ -91,7 +100,7 @@ Description: Expected format is the following:
                is the same as the device name.  By extracting the last part of the
                path the path to the device /dev/<dev-name> can be build.
 
-               o /dev/block/$(cat /sys/class/rnbd-client/ctl/devices/<device_id>/dev)
+               * /dev/block/$(cat /sys/class/rnbd-client/ctl/devices/<device_id>/dev)
 
                How to find the <device_id> of the device is described on the next
                section.
@@ -106,6 +115,6 @@ Description:        For each device mapped on the client a new symbolic link is created
                The <device_id> of each device is created as follows:
 
                - If the 'device_path' provided during mapping contains slashes ("/"),
-               they are replaced by exclamation mark ("!") and used as as the
-               <device_id>. Otherwise, the <device_id> will be the same as the
-               "device_path" provided.
+                 they are replaced by exclamation mark ("!") and used as as the
+                 <device_id>. Otherwise, the <device_id> will be the same as the
+                 "device_path" provided.
index ec950c93e5c6998daf2ee497732f732a2182ec25..ee8ed6494a014b2237389018f86a737866011965 100644 (file)
@@ -7,6 +7,7 @@ Description:    Attribute for calibrating ST-Ericsson AB8500 Real Time Clock
                 calibrate the AB8500.s 32KHz Real Time Clock.
                 Every 60 seconds the AB8500 will correct the RTC's value
                 by adding to it the value of this attribute.
+
                 The range of the attribute is -127 to +127 in units of
                 30.5 micro-seconds (half-parts-per-million of the 32KHz clock)
 Users:          The /vendor/st-ericsson/base_utilities/core/rtc_calibration
index e7e718db8941f25c18cb7a34d23ea7a75c3ca01e..0f7165aab25126de4fd4839943418cdae96b0d95 100644 (file)
@@ -10,10 +10,10 @@ Date:               Feb 2020
 KernelVersion: 5.7
 Contact:       Jack Wang <jinpu.wang@cloud.ionos.com> Danil Kipnis <danil.kipnis@cloud.ionos.com>
 Description:   RW, adds a new path (connection) to an existing session. Expected format is the
-               following:
+               following::
 
-               <[source addr,]destination addr>
-               *addr ::= [ ip:<ipv4|ipv6> | gid:<gid> ]
+                   <[source addr,]destination addr>
+                   *addr ::= [ ip:<ipv4|ipv6> | gid:<gid> ]
 
 What:          /sys/class/rtrs-client/<session-name>/max_reconnect_attempts
 Date:          Feb 2020
@@ -29,10 +29,10 @@ Contact:    Jack Wang <jinpu.wang@cloud.ionos.com> Danil Kipnis <danil.kipnis@cloud
 Description:   Multipath policy specifies which path should be selected on each IO:
 
                round-robin (0):
-               select path in per CPU round-robin manner.
+                   select path in per CPU round-robin manner.
 
                min-inflight (1):
-               select path with minimum inflights.
+                   select path with minimum inflights.
 
 What:          /sys/class/rtrs-client/<session-name>/paths/
 Date:          Feb 2020
@@ -109,8 +109,11 @@ Description:       RTRS expects that each HCA IRQ is pinned to a separate CPU. If it's
                not the case, the processing of an I/O response could be processed on a
                different CPU than where it was originally submitted.  This file shows
                how many interrupts where generated on a non expected CPU.
-               "from:" is the CPU on which the IRQ was expected, but not generated.
-               "to:" is the CPU on which the IRQ was generated, but not expected.
+
+               "from:"
+                   is the CPU on which the IRQ was expected, but not generated.
+               "to:"
+                   is the CPU on which the IRQ was generated, but not expected.
 
 What:          /sys/class/rtrs-client/<session-name>/paths/<src@dst>/stats/reconnects
 Date:          Feb 2020
@@ -125,7 +128,7 @@ Date:               Feb 2020
 KernelVersion: 5.7
 Contact:       Jack Wang <jinpu.wang@cloud.ionos.com> Danil Kipnis <danil.kipnis@cloud.ionos.com>
 Description:   Contains statistics regarding rdma operations and inflight operations.
-               The output consists of 6 values:
+               The output consists of 6 values::
 
-               <read-count> <read-total-size> <write-count> <write-total-size> \
-               <inflights> <failovered>
+                   <read-count> <read-total-size> <write-count> \
+                   <write-total-size> <inflights> <failovered>
index bafc59fd7b69ec355d6631681e3471195b0ae5ca..7c98d8f43c4562904d153e5b63e607ea31f52a8a 100644 (file)
@@ -56,8 +56,9 @@ Description:
                management) on top, which makes it match the Windows IRST (Intel
                Rapid Storage Technology) driver settings. This setting is also
                close to min_power, except that:
+
                a) It does not use host-initiated slumber mode, but it does
-               allow device-initiated slumber
+                  allow device-initiated slumber
                b) It does not enable low power device sleep mode (DevSlp).
 
 What:          /sys/class/scsi_host/hostX/em_message
@@ -70,8 +71,8 @@ Description:
                protocol, writes and reads correspond to the LED message format
                as defined in the AHCI spec.
 
-               The user must turn sw_activity (under /sys/block/*/device/) OFF
-               it they wish to control the activity LED via the em_message
+               The user must turn sw_activity (under `/sys/block/*/device/`)
+               OFF it they wish to control the activity LED via the em_message
                file.
 
                em_message_type: (RO) Displays the current enclosure management
index b834671522d6f98c76a66981c2e9ef36693ad82b..b7794e02ad205626582a693b3ebd7800e402eb8c 100644 (file)
@@ -40,10 +40,13 @@ Description:
                attribute will not return until the operation has finished.
 
                Valid values:
-               - source (The port will behave as source only DFP port)
-               - sink (The port will behave as sink only UFP port)
-               - dual (The port will behave as dual-role-data and
+
+               ======  ==============================================
+               source  (The port will behave as source only DFP port)
+               sink    (The port will behave as sink only UFP port)
+               dual    (The port will behave as dual-role-data and
                        dual-role-power port)
+               ======  ==============================================
 
 What:          /sys/class/typec/<port>/vconn_source
 Date:          April 2017
@@ -59,6 +62,7 @@ Description:
                generates uevent KOBJ_CHANGE.
 
                Valid values:
+
                - "no" when the port is not the VCONN Source
                - "yes" when the port is the VCONN Source
 
@@ -72,6 +76,7 @@ Description:
                power operation mode should show "usb_power_delivery".
 
                Valid values:
+
                - default
                - 1.5A
                - 3.0A
@@ -191,6 +196,7 @@ Date:               April 2017
 Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
 Description:
                Shows type of the plug on the cable:
+
                - type-a - Standard A
                - type-b - Standard B
                - type-c
index a0578751c1e38c475c18dfd183b66e2c7844e0ad..6c5dcad21e198ceca1471c350b3f5074d4302ad8 100644 (file)
@@ -66,11 +66,14 @@ Description:
                 <channel> <type> [<bpst offset>]
 
                 to start (or stop) scanning on a channel.  <type> is one of:
-                    0 - scan
-                    1 - scan outside BP
-                    2 - scan while inactive
-                    3 - scanning disabled
-                    4 - scan (with start time of <bpst offset>)
+
+                  ==   =======================================
+                    0   scan
+                    1   scan outside BP
+                    2   scan while inactive
+                    3   scanning disabled
+                    4   scan (with start time of <bpst offset>)
+                  ==   =======================================
 
 What:           /sys/class/uwb_rc/uwbN/mac_address
 Date:           July 2008
index 9860a8b2ba7504422d8e2e3e5b0e5a402026d742..585caecda3a5fc3a533360eea7ac95589b9c2545 100644 (file)
@@ -91,10 +91,13 @@ Description:
                h/w strapping (for WDT2 only).
 
                At alternate flash the 'access_cs0' sysfs node provides:
-                       ast2400: a way to get access to the primary SPI flash
+
+                       ast2400:
+                               a way to get access to the primary SPI flash
                                chip at CS0 after booting from the alternate
                                chip at CS1.
-                       ast2500: a way to restore the normal address mapping
+                       ast2500:
+                               a way to restore the normal address mapping
                                from (CS0->CS1, CS1->CS0) to (CS0->CS0,
                                CS1->CS1).
 
index a9f2b8b0530fb193be12ccfb7d0a529bf0ba435d..d1739063e762914c6012eb122809a7eac30ef266 100644 (file)
@@ -9,9 +9,10 @@ Description:   The /sys/dev tree provides a method to look up the sysfs
                the form "<major>:<minor>".  These links point to the
                corresponding sysfs path for the given device.
 
-               Example:
-               $ readlink /sys/dev/block/8:32
-               ../../block/sdc
+               Example::
+
+                 $ readlink /sys/dev/block/8:32
+                 ../../block/sdc
 
                Entries in /sys/dev/char and /sys/dev/block will be
                dynamically created and destroyed as devices enter and
index 490ccfd67f125a005cc411bda7496018938691e3..8d202bac9394ad06c2e7792081b562d8deb52287 100644 (file)
@@ -8,26 +8,27 @@ Description:
                 block.
                 For example, on 4-die Xeon platform with up to 6 IIO stacks per
                 die and, therefore, 6 IIO PMON blocks per die, the mapping of
-                IIO PMON block 0 exposes as the following:
+                IIO PMON block 0 exposes as the following::
 
-                $ ls /sys/devices/uncore_iio_0/die*
-                -r--r--r-- /sys/devices/uncore_iio_0/die0
-                -r--r--r-- /sys/devices/uncore_iio_0/die1
-                -r--r--r-- /sys/devices/uncore_iio_0/die2
-                -r--r--r-- /sys/devices/uncore_iio_0/die3
+                   $ ls /sys/devices/uncore_iio_0/die*
+                   -r--r--r-- /sys/devices/uncore_iio_0/die0
+                   -r--r--r-- /sys/devices/uncore_iio_0/die1
+                   -r--r--r-- /sys/devices/uncore_iio_0/die2
+                   -r--r--r-- /sys/devices/uncore_iio_0/die3
 
-                $ tail /sys/devices/uncore_iio_0/die*
-                ==> /sys/devices/uncore_iio_0/die0 <==
-                0000:00
-                ==> /sys/devices/uncore_iio_0/die1 <==
-                0000:40
-                ==> /sys/devices/uncore_iio_0/die2 <==
-                0000:80
-                ==> /sys/devices/uncore_iio_0/die3 <==
-                0000:c0
+                   $ tail /sys/devices/uncore_iio_0/die*
+                   ==> /sys/devices/uncore_iio_0/die0 <==
+                   0000:00
+                   ==> /sys/devices/uncore_iio_0/die1 <==
+                   0000:40
+                   ==> /sys/devices/uncore_iio_0/die2 <==
+                   0000:80
+                   ==> /sys/devices/uncore_iio_0/die3 <==
+                   0000:c0
 
-                Which means:
-                IIO PMU 0 on die 0 belongs to PCI RP on bus 0x00, domain 0x0000
-                IIO PMU 0 on die 1 belongs to PCI RP on bus 0x40, domain 0x0000
-                IIO PMU 0 on die 2 belongs to PCI RP on bus 0x80, domain 0x0000
-                IIO PMU 0 on die 3 belongs to PCI RP on bus 0xc0, domain 0x0000
+                Which means::
+
+                   IIO PMU 0 on die 0 belongs to PCI RP on bus 0x00, domain 0x0000
+                   IIO PMU 0 on die 1 belongs to PCI RP on bus 0x40, domain 0x0000
+                   IIO PMU 0 on die 2 belongs to PCI RP on bus 0x80, domain 0x0000
+                   IIO PMU 0 on die 3 belongs to PCI RP on bus 0xc0, domain 0x0000
index deef3b5723cf2685925a791e20bc97027142b5df..2da2b1fba2c1cd108c5ec514a5b524675d5b5f64 100644 (file)
@@ -47,16 +47,19 @@ Description:
                online/offline state of the memory section.  When written,
                root can toggle the the online/offline state of a removable
                memory section (see removable file description above)
-               using the following commands.
-               # echo online > /sys/devices/system/memory/memoryX/state
-               # echo offline > /sys/devices/system/memory/memoryX/state
+               using the following commands::
+
+                 # echo online > /sys/devices/system/memory/memoryX/state
+                 # echo offline > /sys/devices/system/memory/memoryX/state
 
                For example, if /sys/devices/system/memory/memory22/removable
                contains a value of 1 and
                /sys/devices/system/memory/memory22/state contains the
                string "online" the following command can be executed by
-               by root to offline that section.
-               # echo offline > /sys/devices/system/memory/memory22/state
+               by root to offline that section::
+
+                 # echo offline > /sys/devices/system/memory/memory22/state
+
 Users:         hotplug memory remove tools
                http://www.ibm.com/developerworks/wikis/display/LinuxP/powerpc-utils
 
@@ -78,6 +81,7 @@ Description:
 
                For example, the following symbolic link is created for
                memory section 9 on node0:
+
                /sys/devices/system/memory/memory9/node0 -> ../../node/node0
 
 
@@ -90,4 +94,5 @@ Description:
                points to the corresponding /sys/devices/system/memory/memoryY
                memory section directory.  For example, the following symbolic
                link is created for memory section 9 on node0.
+
                /sys/devices/system/node/node0/memory9 -> ../../memory/memory9
index 7e43cdce9a5272ba85ef1d59f69c76be3d38a414..f7b360a61b2181ea2cf0f501699a68a8c5edd4dc 100644 (file)
@@ -7,6 +7,7 @@ Description:
                (RO) Hexadecimal bitmask of the TAD attributes are reported by
                the platform firmware (see ACPI 6.2, section 9.18.2):
 
+               ======= ======================================================
                BIT(0): AC wakeup implemented if set
                BIT(1): DC wakeup implemented if set
                BIT(2): Get/set real time features implemented if set
@@ -16,6 +17,7 @@ Description:
                BIT(6): The AC timer wakes up from S5 if set
                BIT(7): The DC timer wakes up from S4 if set
                BIT(8): The DC timer wakes up from S5 if set
+               ======= ======================================================
 
                The other bits are reserved.
 
@@ -62,9 +64,11 @@ Description:
                timer status with the following meaning of bits (see ACPI 6.2,
                Section 9.18.5):
 
+               ======= ======================================================
                Bit(0): The timer has expired if set.
                Bit(1): The timer has woken up the system from a sleep state
                        (S3 or S4/S5 if supported) if set.
+               ======= ======================================================
 
                The other bits are reserved.
 
index d548eaac230a43f51eb4b613b7db114f7ce70b19..40f29a01fd143071b2426af9801c2acd1d566fd1 100644 (file)
@@ -3,8 +3,9 @@ Date:           April 2010
 Contact:       Fabien Chouteau <fabien.chouteau@barco.com>
 Description:
                Show the suspend state of an USB composite gadget.
-               1 -> suspended
-               0 -> resumed
+
+               - 1 -> suspended
+               - 0 -> resumed
 
                (_UDC_ is the name of the USB Device Controller driver)
 
@@ -17,5 +18,6 @@ Description:
                Storage mode.
 
                Possible values are:
-                       1 -> ignore the FUA flag
-                       0 -> obey the FUA flag
+
+                       - 1 -> ignore the FUA flag
+                       - 0 -> obey the FUA flag
index 8aa36716882f87179aa8d025b2f1696d6aa1ac3b..378c42694bfb6b4d57c9d9f23dc3179c2a20cf3a 100644 (file)
@@ -9,8 +9,10 @@ Description:
                The protection has information embedded whether it blocks reads,
                writes or both.
                The result is:
-               0 -> the DPS is not keylocked
-               1 -> the DPS is keylocked
+
+               - 0 -> the DPS is not keylocked
+               - 1 -> the DPS is keylocked
+
 Users:         None identified so far.
 
 What:          /sys/devices/platform/docg3/f[0-3]_dps[01]_protection_key
@@ -27,8 +29,12 @@ Description:
                Entering the correct value toggle the lock, and can be observed
                through f[0-3]_dps[01]_is_keylocked.
                Possible values are:
+
                        - 8 bytes
+
                Typical values are:
+
                        - "00000000"
                        - "12345678"
+
 Users:         None identified so far.
index afb5db856e1cad3927c5b14f93c54c205008a79f..07df0ddc0b696ecebbd2436824f10facb448bbdb 100644 (file)
@@ -123,38 +123,40 @@ KernelVersion:    v4.15
 Contact:       openipmi-developer@lists.sourceforge.net
 Description:
 
-               idles:                  (RO) Number of times the interface was
+               ======================  ========================================
+               idles                   (RO) Number of times the interface was
                                        idle while being polled.
 
-               watchdog_pretimeouts:   (RO) Number of watchdog pretimeouts.
+               watchdog_pretimeouts    (RO) Number of watchdog pretimeouts.
 
-               complete_transactions:  (RO) Number of completed messages.
+               complete_transactions   (RO) Number of completed messages.
 
-               events:                 (RO) Number of IPMI events received from
+               events                  (RO) Number of IPMI events received from
                                        the hardware.
 
-               interrupts:             (RO) Number of interrupts the driver
+               interrupts              (RO) Number of interrupts the driver
                                        handled.
 
-               hosed_count:            (RO) Number of times the hardware didn't
+               hosed_count             (RO) Number of times the hardware didn't
                                        follow the state machine.
 
-               long_timeouts:          (RO) Number of times the driver
+               long_timeouts           (RO) Number of times the driver
                                        requested a timer while nothing was in
                                        progress.
 
-               flag_fetches:           (RO) Number of times the driver
+               flag_fetches            (RO) Number of times the driver
                                        requested flags from the hardware.
 
-               attentions:             (RO) Number of time the driver got an
+               attentions              (RO) Number of time the driver got an
                                        ATTN from the hardware.
 
-               incoming_messages:      (RO) Number of asynchronous messages
+               incoming_messages       (RO) Number of asynchronous messages
                                        received.
 
-               short_timeouts:         (RO) Number of times the driver
+               short_timeouts          (RO) Number of times the driver
                                        requested a timer while an operation was
                                        in progress.
+               ======================  ========================================
 
 
 What:          /sys/devices/platform/ipmi_si.*/interrupts_enabled
@@ -201,38 +203,40 @@ Date:             Sep, 2017
 KernelVersion: v4.15
 Contact:       openipmi-developer@lists.sourceforge.net
 Description:
-               hosed:                  (RO) Number of times the hardware didn't
+               ======================  ========================================
+               hosed                   (RO) Number of times the hardware didn't
                                        follow the state machine.
 
-               alerts:                 (RO) Number of alerts received.
+               alerts                  (RO) Number of alerts received.
 
-               sent_messages:          (RO) Number of total messages sent.
+               sent_messages           (RO) Number of total messages sent.
 
-               sent_message_parts:     (RO) Number of message parts sent.
+               sent_message_parts      (RO) Number of message parts sent.
                                        Messages may be broken into parts if
                                        they are long.
 
-               received_messages:      (RO) Number of message responses
+               received_messages       (RO) Number of message responses
                                        received.
 
-               received_message_parts: (RO) Number of message fragments
+               received_message_parts  (RO) Number of message fragments
                                        received.
 
-               events:                 (RO) Number of received events.
+               events                  (RO) Number of received events.
 
-               watchdog_pretimeouts:   (RO) Number of watchdog pretimeouts.
+               watchdog_pretimeouts    (RO) Number of watchdog pretimeouts.
 
-               flag_fetches:           (RO) Number of times a flag fetch was
+               flag_fetches            (RO) Number of times a flag fetch was
                                        requested.
 
-               send_retries:           (RO) Number of time a message was
+               send_retries            (RO) Number of time a message was
                                        retried.
 
-               receive_retries:        (RO) Number of times the receive of a
+               receive_retries         (RO) Number of times the receive of a
                                        message was retried.
 
-               send_errors:            (RO) Number of times the send of a
+               send_errors             (RO) Number of times the send of a
                                        message failed.
 
-               receive_errors:         (RO) Number of errors in receiving
+               receive_errors          (RO) Number of errors in receiving
                                        messages.
+               ======================  ========================================
index 2107082426daf2f5076d7bb851a6dcca189484d9..e45ac2e865d5e44bc2d157f0a36563741fa3db1b 100644 (file)
@@ -17,10 +17,10 @@ Description:
                to overlay planes.
 
                Selects the composition mode for the overlay. Possible values
-               are
+               are:
 
-               0 - Alpha Blending
-               1 - ROP3
+               0 - Alpha Blending
+               1 - ROP3
 
 What:          /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_position
 Date:          May 2012
@@ -30,7 +30,7 @@ Description:
                to overlay planes.
 
                Stores the x,y overlay position on the display in pixels. The
-               position format is `[0-9]+,[0-9]+'.
+               position format is `[0-9]+,[0-9]+`.
 
 What:          /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_rop3
 Date:          May 2012
index a8daceb4a95655b605c37904578b5abcfdcbbfb3..ee253b033280e9abe74c50a0e70e619c31fdf97a 100644 (file)
@@ -102,6 +102,8 @@ Description:
                b[15:0]
                        inform firmware the current software execution
                        stage.
+
+                       ==      ===========================================
                        0       the first stage bootloader didn't run or
                                didn't reach the point of launching second
                                stage bootloader.
@@ -111,21 +113,29 @@ Description:
                        2       both first and second stage bootloader ran
                                and the operating system launch was
                                attempted.
+                       ==      ===========================================
 
                b[16]
+                       ==      ===========================================
                        1       firmware to reset current image retry
                                counter.
                        0       no action.
+                       ==      ===========================================
 
                b[17]
+                       ==      ===========================================
                        1       firmware to clear RSU log
                        0       no action.
+                       ==      ===========================================
 
                b[18]
                        this is negative logic
+
+                       ==      ===========================================
                        1       no action
                        0       firmware record the notify code defined
                                in b[15:0].
+                       ==      ===========================================
 
 What:          /sys/devices/platform/stratix10-rsu.0/dcmf0
 Date:          June 2020
index b555df825447a42d053d583bd11d92719e998cb4..1a04ca8162ad882483e402256059446fea8d6943 100644 (file)
@@ -151,23 +151,28 @@ Description:
                The processor idle states which are available for use have the
                following attributes:
 
-               name: (RO) Name of the idle state (string).
+               ======== ==== =================================================
+               name:    (RO) Name of the idle state (string).
 
                latency: (RO) The latency to exit out of this idle state (in
-               microseconds).
+                             microseconds).
 
-               power: (RO) The power consumed while in this idle state (in
-               milliwatts).
+               power:   (RO) The power consumed while in this idle state (in
+                             milliwatts).
 
-               time: (RO) The total time spent in this idle state (in microseconds).
+               time:    (RO) The total time spent in this idle state
+                             (in microseconds).
 
-               usage: (RO) Number of times this state was entered (a count).
+               usage:   (RO) Number of times this state was entered (a count).
 
-               above: (RO) Number of times this state was entered, but the
-                      observed CPU idle duration was too short for it (a count).
+               above:   (RO) Number of times this state was entered, but the
+                             observed CPU idle duration was too short for it
+                             (a count).
 
-               below: (RO) Number of times this state was entered, but the
-                      observed CPU idle duration was too long for it (a count).
+               below:   (RO) Number of times this state was entered, but the
+                             observed CPU idle duration was too long for it
+                             (a count).
+               ======== ==== =================================================
 
 What:          /sys/devices/system/cpu/cpuX/cpuidle/stateN/desc
 Date:          February 2008
@@ -290,6 +295,7 @@ Description:        Processor frequency boosting control
                This switch controls the boost setting for the whole system.
                Boosting allows the CPU and the firmware to run at a frequency
                beyound it's nominal limit.
+
                More details can be found in
                Documentation/admin-guide/pm/cpufreq.rst
 
@@ -337,43 +343,57 @@ Contact:  Sudeep Holla <sudeep.holla@arm.com>
 Description:   Parameters for the CPU cache attributes
 
                allocation_policy:
-                       - WriteAllocate: allocate a memory location to a cache line
-                                        on a cache miss because of a write
-                       - ReadAllocate: allocate a memory location to a cache line
+                       - WriteAllocate:
+                                       allocate a memory location to a cache line
+                                       on a cache miss because of a write
+                       - ReadAllocate:
+                                       allocate a memory location to a cache line
                                        on a cache miss because of a read
-                       - ReadWriteAllocate: both writeallocate and readallocate
+                       - ReadWriteAllocate:
+                                       both writeallocate and readallocate
 
-               attributes: LEGACY used only on IA64 and is same as write_policy
+               attributes:
+                           LEGACY used only on IA64 and is same as write_policy
 
-               coherency_line_size: the minimum amount of data in bytes that gets
+               coherency_line_size:
+                                    the minimum amount of data in bytes that gets
                                     transferred from memory to cache
 
-               level: the cache hierarchy in the multi-level cache configuration
+               level:
+                       the cache hierarchy in the multi-level cache configuration
 
-               number_of_sets: total number of sets in the cache, a set is a
+               number_of_sets:
+                               total number of sets in the cache, a set is a
                                collection of cache lines with the same cache index
 
-               physical_line_partition: number of physical cache line per cache tag
+               physical_line_partition:
+                               number of physical cache line per cache tag
 
-               shared_cpu_list: the list of logical cpus sharing the cache
+               shared_cpu_list:
+                               the list of logical cpus sharing the cache
 
-               shared_cpu_map: logical cpu mask containing the list of cpus sharing
+               shared_cpu_map:
+                               logical cpu mask containing the list of cpus sharing
                                the cache
 
-               size: the total cache size in kB
+               size:
+                       the total cache size in kB
 
                type:
                        - Instruction: cache that only holds instructions
                        - Data: cache that only caches data
                        - Unified: cache that holds both data and instructions
 
-               ways_of_associativity: degree of freedom in placing a particular block
-                                       of memory in the cache
+               ways_of_associativity:
+                       degree of freedom in placing a particular block
+                       of memory in the cache
 
                write_policy:
-                       - WriteThrough: data is written to both the cache line
+                       - WriteThrough:
+                                       data is written to both the cache line
                                        and to the block in the lower-level memory
-                       - WriteBack: data is written only to the cache line and
+                       - WriteBack:
+                                    data is written only to the cache line and
                                     the modified cache line is written to main
                                     memory only when it is replaced
 
@@ -414,30 +434,30 @@ Description:      POWERNV CPUFreq driver's frequency throttle stats directory and
                throttle attributes exported in the 'throttle_stats' directory:
 
                - turbo_stat : This file gives the total number of times the max
-               frequency is throttled to lower frequency in turbo (at and above
-               nominal frequency) range of frequencies.
+                 frequency is throttled to lower frequency in turbo (at and above
+                 nominal frequency) range of frequencies.
 
                - sub_turbo_stat : This file gives the total number of times the
-               max frequency is throttled to lower frequency in sub-turbo(below
-               nominal frequency) range of frequencies.
+                 max frequency is throttled to lower frequency in sub-turbo(below
+                 nominal frequency) range of frequencies.
 
                - unthrottle : This file gives the total number of times the max
-               frequency is unthrottled after being throttled.
+                 frequency is unthrottled after being throttled.
 
                - powercap : This file gives the total number of times the max
-               frequency is throttled due to 'Power Capping'.
+                 frequency is throttled due to 'Power Capping'.
 
                - overtemp : This file gives the total number of times the max
-               frequency is throttled due to 'CPU Over Temperature'.
+                 frequency is throttled due to 'CPU Over Temperature'.
 
                - supply_fault : This file gives the total number of times the
-               max frequency is throttled due to 'Power Supply Failure'.
+                 max frequency is throttled due to 'Power Supply Failure'.
 
                - overcurrent : This file gives the total number of times the
-               max frequency is throttled due to 'Overcurrent'.
+                 max frequency is throttled due to 'Overcurrent'.
 
                - occ_reset : This file gives the total number of times the max
-               frequency is throttled due to 'OCC Reset'.
+                 frequency is throttled due to 'OCC Reset'.
 
                The sysfs attributes representing different throttle reasons like
                powercap, overtemp, supply_fault, overcurrent and occ_reset map to
@@ -469,8 +489,9 @@ What:               /sys/devices/system/cpu/cpuX/regs/
 Date:          June 2016
 Contact:       Linux ARM Kernel Mailing list <linux-arm-kernel@lists.infradead.org>
 Description:   AArch64 CPU registers
+
                'identification' directory exposes the CPU ID registers for
-                identifying model and revision of the CPU.
+               identifying model and revision of the CPU.
 
 What:          /sys/devices/system/cpu/cpu#/cpu_capacity
 Date:          December 2016
@@ -497,9 +518,11 @@ Description:       Information about CPU vulnerabilities
                vulnerabilities. The output of those files reflects the
                state of the CPUs in the system. Possible output values:
 
+               ================  ==============================================
                "Not affected"    CPU is not affected by the vulnerability
                "Vulnerable"      CPU is affected and no mitigation in effect
                "Mitigation: $M"  CPU is affected and mitigation $M is in effect
+               ================  ==============================================
 
                See also: Documentation/admin-guide/hw-vuln/index.rst
 
@@ -515,12 +538,14 @@ Description:      Control Symetric Multi Threading (SMT)
                control: Read/write interface to control SMT. Possible
                         values:
 
+                        ================ =========================================
                         "on"             SMT is enabled
                         "off"            SMT is disabled
                         "forceoff"       SMT is force disabled. Cannot be changed.
                         "notsupported"   SMT is not supported by the CPU
                         "notimplemented" SMT runtime toggling is not
                                          implemented for the architecture
+                        ================ =========================================
 
                         If control status is "forceoff" or "notsupported" writes
                         are rejected.
@@ -576,7 +601,7 @@ Description:        Secure Virtual Machine
                Facility in POWER9 and newer processors. i.e., it is a Secure
                Virtual Machine.
 
-What:          /sys/devices/system/cpu/cpuX/purr
+What:          /sys/devices/system/cpu/cpuX/purr
 Date:          Apr 2005
 Contact:       Linux for PowerPC mailing list <linuxppc-dev@ozlabs.org>
 Description:   PURR ticks for this CPU since the system boot.
index 470def06ab0a42e40f860d1fe54f8e0d489ec4c3..1a8ee26e92ae61b4c7bb51824e56b43f3ddd2d13 100644 (file)
@@ -5,8 +5,10 @@ Contact:        Vernon Mauery <vernux@us.ibm.com>
 Description:    The state file allows a means by which to change in and
                 out of Premium Real-Time Mode (PRTM), as well as the
                 ability to query the current state.
-                    0 => PRTM off
-                    1 => PRTM enabled
+
+                    - 0 => PRTM off
+                    - 1 => PRTM enabled
+
 Users:          The ibm-prtm userspace daemon uses this interface.
 
 
index 4d63a7904b94a9938fe4e41916de6c1ea6c31be0..42214b4ff14a1372dcbf9822c8c192725366ed56 100644 (file)
@@ -6,11 +6,13 @@ Description:  Read/write the current state of DDR Backup Mode, which controls
                if DDR power rails will be kept powered during system suspend.
                ("on"/"1" = enabled, "off"/"0" = disabled).
                Two types of power switches (or control signals) can be used:
+
                  A. With a momentary power switch (or pulse signal), DDR
                     Backup Mode is enabled by default when available, as the
                     PMIC will be configured only during system suspend.
                  B. With a toggle power switch (or level signal), the
                     following steps must be followed exactly:
+
                       1. Configure PMIC for backup mode, to change the role of
                          the accessory power switch from a power switch to a
                          wake-up switch,
@@ -20,8 +22,10 @@ Description: Read/write the current state of DDR Backup Mode, which controls
                       3. Suspend system,
                       4. Switch accessory power switch on, to resume the
                          system.
+
                     DDR Backup Mode must be explicitly enabled by the user,
                     to invoke step 1.
+
                See also Documentation/devicetree/bindings/mfd/bd9571mwv.txt.
 Users:         User space applications for embedded boards equipped with a
                BD9571MWV PMIC.
index 64ac6d567c4b95eefdb7432a7dab65b3ad7d030d..69d855dc4c47c9e15e1fac119bf40c1c2b91cf86 100644 (file)
@@ -29,8 +29,12 @@ What:           /sys/class/genwqe/genwqe<n>_card/reload_bitstream
 Date:           May 2014
 Contact:        klebers@linux.vnet.ibm.com
 Description:    Interface to trigger a PCIe card reset to reload the bitstream.
+
+               ::
+
                   sudo sh -c 'echo 1 > \
                     /sys/class/genwqe/genwqe0_card/reload_bitstream'
+
                 If successfully, the card will come back with the bitstream set
                 on 'next_bitstream'.
 
@@ -64,8 +68,11 @@ Description:    Base clock frequency of the card.
 What:           /sys/class/genwqe/genwqe<n>_card/device/sriov_numvfs
 Date:           Oct 2013
 Contact:        haver@linux.vnet.ibm.com
-Description:    Enable VFs (1..15):
+Description:    Enable VFs (1..15)::
+
                   sudo sh -c 'echo 15 > \
                     /sys/bus/pci/devices/0000\:1b\:00.0/sriov_numvfs'
-                Disable VFs:
+
+                Disable VFs::
+
                   Write a 0 into the same sysfs entry.
index 53a0725962e1ac53036b78d0f9da6f852092c447..aee85ca1f6be658e8aad45eb867e5c261e6b4510 100644 (file)
@@ -3,14 +3,18 @@ Date:         July 2011
 Contact:       linux-input@vger.kernel.org
 Description:   This controls if mouse clicks should be generated if the trackpoint is quickly pressed. How fast this press has to be
                is being controlled by press_speed.
+
                Values are 0 or 1.
+
                Applies to Thinkpad USB Keyboard with TrackPoint.
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/dragging
 Date:          July 2011
 Contact:       linux-input@vger.kernel.org
 Description:   If this setting is enabled, it is possible to do dragging by pressing the trackpoint. This requires press_to_select to be enabled.
+
                Values are 0 or 1.
+
                Applies to Thinkpad USB Keyboard with TrackPoint.
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/release_to_select
@@ -25,7 +29,9 @@ Date:         July 2011
 Contact:       linux-input@vger.kernel.org
 Description:   This setting controls if the mouse click events generated by pressing the trackpoint (if press_to_select is enabled) generate
                a left or right mouse button click.
+
                Values are 0 or 1.
+
                Applies to Thinkpad USB Keyboard with TrackPoint.
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/sensitivity
@@ -39,12 +45,16 @@ What:               /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-
 Date:          July 2011
 Contact:       linux-input@vger.kernel.org
 Description:   This setting controls how fast the trackpoint needs to be pressed to generate a mouse click if press_to_select is enabled.
+
                Values are decimal integers from 1 (slowest) to 255 (fastest).
+
                Applies to Thinkpad USB Keyboard with TrackPoint.
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/fn_lock
 Date:          July 2014
 Contact:       linux-input@vger.kernel.org
 Description:   This setting controls whether Fn Lock is enabled on the keyboard (i.e. if F1 is Mute or F1)
+
                Values are 0 or 1
+
                Applies to ThinkPad Compact (USB|Bluetooth) Keyboard with TrackPoint.
index 305dffd229a83cab521758cde40d61b055b9d6c6..de07be314efc7f598912961a873fc041d537446e 100644 (file)
@@ -12,7 +12,9 @@ KernelVersion:        4.1
 Contact:       Michal Malý <madcatxster@devoid-pointer.net>
 Description:   Displays a set of alternate modes supported by a wheel. Each
                mode is listed as follows:
+
                  Tag: Mode Name
+
                Currently active mode is marked with an asterisk. List also
                contains an abstract item "native" which always denotes the
                native mode of the wheel. Echoing the mode tag switches the
@@ -24,24 +26,30 @@ Description:        Displays a set of alternate modes supported by a wheel. Each
                This entry is not created for devices that have only one mode.
 
                Currently supported mode switches:
-               Driving Force Pro:
+
+               Driving Force Pro::
+
                  DF-EX --> DFP
 
-               G25:
+               G25::
+
                  DF-EX --> DFP --> G25
 
-               G27:
+               G27::
+
                  DF-EX <*> DFP <-> G25 <-> G27
                  DF-EX <*--------> G25 <-> G27
                  DF-EX <*----------------> G27
 
-               G29:
+               G29::
+
                  DF-EX <*> DFP <-> G25 <-> G27 <-> G29
                  DF-EX <*--------> G25 <-> G27 <-> G29
                  DF-EX <*----------------> G27 <-> G29
                  DF-EX <*------------------------> G29
 
-               DFGT:
+               DFGT::
+
                  DF-EX <*> DFP <-> DFGT
                  DF-EX <*--------> DFGT
 
index e574a5625efe035267d65ff4e9e34611d933e28d..0e323a5cec6c07d2a9b133ed39803bc5c6879386 100644 (file)
@@ -29,12 +29,13 @@ Contact:    linux-input@vger.kernel.org
 Description:
                Threholds to override activation slack.
 
-               activation_width:       (RW) Width threshold to immediately
+               =================       =====================================
+               activation_width        (RW) Width threshold to immediately
                                        start processing touch events.
 
-               activation_height:      (RW) Height threshold to immediately
+               activation_height       (RW) Height threshold to immediately
                                        start processing touch events.
-
+               =================       =====================================
 
 What:          /sys/bus/hid/drivers/ntrig/<dev>/min_width
 What:          /sys/bus/hid/drivers/ntrig/<dev>/min_height
@@ -44,11 +45,13 @@ Contact:    linux-input@vger.kernel.org
 Description:
                Minimum size contact accepted.
 
-               min_width:      (RW) Minimum touch contact width to decide
+               ==========      ===========================================
+               min_width       (RW) Minimum touch contact width to decide
                                activation and activity.
 
-               min_height:     (RW) Minimum touch contact height to decide
+               min_height      (RW) Minimum touch contact height to decide
                                activation and activity.
+               ==========      ===========================================
 
 
 What:          /sys/bus/hid/drivers/ntrig/<dev>/sensor_physical_width
index 8f7982c70d72cc797a18c15720056bb96f573ebc..11cd9bf0ad185e9e91c17806fdda893695424a3d 100644 (file)
@@ -3,17 +3,21 @@ Date:         March 2010
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:   It is possible to switch the dpi setting of the mouse with the
                press of a button.
+
                When read, this file returns the raw number of the actual dpi
                setting reported by the mouse. This number has to be further
                processed to receive the real dpi value:
 
+               ===== =====
                VALUE DPI
+               ===== =====
                1     800
                2     1200
                3     1600
                4     2000
                5     2400
                6     3200
+               ===== =====
 
                This file is readonly.
 Users:         http://roccat.sourceforge.net
@@ -22,6 +26,7 @@ What:         /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-
 Date:          March 2010
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:   When read, this file returns the number of the actual profile.
+
                This file is readonly.
 Users:         http://roccat.sourceforge.net
 
@@ -33,6 +38,7 @@ Description:  When read, this file returns the raw integer version number of the
                further usage in other programs. To receive the real version
                number the decimal point has to be shifted 2 positions to the
                left. E.g. a returned value of 138 means 1.38
+
                This file is readonly.
 Users:         http://roccat.sourceforge.net
 
@@ -43,10 +49,13 @@ Description:        The mouse can store 5 profiles which can be switched by the
                 press of a button. A profile holds information like button
                 mappings, sensitivity, the colors of the 5 leds and light
                 effects.
+
                 When read, these files return the respective profile. The
                 returned data is 975 bytes in size.
+
                When written, this file lets one write the respective profile
                data back to the mouse. The data has to be 975 bytes long.
+
                The mouse will reject invalid data, whereas the profile number
                stored in the profile doesn't need to fit the number of the
                store.
@@ -58,6 +67,7 @@ Contact:      Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:   When read, this file returns the settings stored in the mouse.
                The size of the data is 36 bytes and holds information like the
                startup_profile, tcu state and calibration_data.
+
                When written, this file lets write settings back to the mouse.
                The data has to be 36 bytes long. The mouse will reject invalid
                data.
@@ -67,8 +77,10 @@ What:                /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-
 Date:          March 2010
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:   The integer value of this attribute ranges from 1 to 5.
+
                 When read, this attribute returns the number of the profile
                 that's active when the mouse is powered on.
+
                When written, this file sets the number of the startup profile
                and the mouse activates this profile immediately.
 Users:         http://roccat.sourceforge.net
@@ -80,9 +92,12 @@ Description: The mouse has a "Tracking Control Unit" which lets the user
                calibrate the laser power to fit the mousepad surface.
                When read, this file returns the current state of the TCU,
                where 0 means off and 1 means on.
+
                Writing 0 in this file will switch the TCU off.
+
                Writing 1 in this file will start the calibration which takes
                around 6 seconds to complete and activates the TCU.
+
 Users:         http://roccat.sourceforge.net
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/weight
@@ -93,14 +108,18 @@ Description:       The mouse can be equipped with one of four supplied weights
                and its value can be read out. When read, this file returns the
                raw value returned by the mouse which eases further processing
                in other software.
+
                The values map to the weights as follows:
 
+               ===== ======
                VALUE WEIGHT
+               ===== ======
                0     none
                1     5g
                2     10g
                3     15g
                4     20g
+               ===== ======
 
                This file is readonly.
 Users:         http://roccat.sourceforge.net
index 39dfa5cb1cc56c41af0ca297de0d3c003655ce2d..3bf43d9dcdfe5b1799fc0e8209fad067e6b6686f 100644 (file)
@@ -20,6 +20,7 @@ Description:  This file contains the currently connected and initialized
                the official Nintendo Nunchuck extension and classic is the
                Nintendo Classic Controller extension. The motionp extension can
                be combined with the other two.
+
                Starting with kernel-version 3.11 Motion Plus hotplugging is
                supported and if detected, it's no longer reported as static
                extension. You will get uevent notifications for the motion-plus
@@ -39,9 +40,13 @@ Description: While a device is initialized by the wiimote driver, we perform
                Other strings for each device-type are available and may be
                added if new device-specific detections are added.
                Currently supported are:
-                       gen10: First Wii Remote generation
-                       gen20: Second Wii Remote Plus generation (builtin MP)
+
+                       ============= =======================================
+                       gen10:        First Wii Remote generation
+                       gen20:        Second Wii Remote Plus generation
+                                     (builtin MP)
                        balanceboard: Wii Balance Board
+                       ============= =======================================
 
 What:          /sys/bus/hid/drivers/wiimote/<dev>/bboard_calib
 Date:          May 2013
@@ -54,6 +59,7 @@ Description:  This attribute is only provided if the device was detected as a
                First, 0kg values for all 4 sensors are written, followed by the
                17kg values for all 4 sensors and last the 34kg values for all 4
                sensors.
+
                Calibration data is already applied by the kernel to all input
                values but may be used by user-space to perform other
                transformations.
@@ -68,9 +74,11 @@ Description: This attribute is only provided if the device was detected as a
                is prefixed with a +/-. Each value is a signed 16bit number.
                Data is encoded as decimal numbers and specifies the offsets of
                the analog sticks of the pro-controller.
+
                Calibration data is already applied by the kernel to all input
                values but may be used by user-space to perform other
                transformations.
+
                Calibration data is detected by the kernel during device setup.
                You can write "scan\n" into this file to re-trigger calibration.
                You can also write data directly in the form "x1:y1 x2:y2" to
index 3d316d54f81c22a83a289a82c11c91cf48e5cb49..cd7c578aef2c98dde62fe8d07038c22666766f4e 100644 (file)
@@ -4,6 +4,7 @@ Contact:        linux-input@vger.kernel.org
 Description:    Reports the firmware version provided by the touchscreen, for example "00_T6" on a EXC80H60
 
                Access: Read
+
                Valid values: Represented as string
 
 What:          /sys/bus/i2c/devices/xxx/model
@@ -12,4 +13,5 @@ Contact:      linux-input@vger.kernel.org
 Description:    Reports the model identification provided by the touchscreen, for example "Orion_1320" on a EXC80H60
 
                Access: Read
+
                Valid values: Represented as string
index bb6f5d6ceea0cd370340b3d5b44132f21639316d..4cf595d681e655b399ef67e50f9482e6fdc0e364 100644 (file)
@@ -4,7 +4,9 @@ Contact:        PrasannaKumar Muralidharan <prasannatsmkumar@gmail.com>
 Description:   read-only access to the efuse on the Ingenic JZ4780 SoC
                The SoC has a one time programmable 8K efuse that is
                split into segments. The driver supports read only.
-               The segments are
+               The segments are:
+
+               ===== ======== =================
                0x000   64 bit Random Number
                0x008  128 bit Ingenic Chip ID
                0x018  128 bit Customer ID
@@ -12,5 +14,7 @@ Description:  read-only access to the efuse on the Ingenic JZ4780 SoC
                0x1E0    8 bit Protect Segment
                0x1E1 2296 bit HDMI Key
                0x300 2048 bit Security boot key
+               ===== ======== =================
+
 Users:         any user space application which wants to read the Chip
                and Customer ID
index 73308c2b81b043d54654e04d10ae8d273a7a731a..49f5fd0c8bbd32c43b75a5170a06ae39fceef0af 100644 (file)
@@ -7,8 +7,10 @@ Description:
                 the format of DDDD:BB:DD.F-REG:SIZE:MASK will allow the guest
                 to write and read from the PCI device. That is Domain:Bus:
                 Device.Function-Register:Size:Mask (Domain is optional).
-                For example:
-                #echo 00:19.0-E0:2:FF > /sys/bus/pci/drivers/pciback/quirks
+                For example::
+
+                  #echo 00:19.0-E0:2:FF > /sys/bus/pci/drivers/pciback/quirks
+
                 will allow the guest to read and write to the configuration
                 register 0x0E.
 
index 34d3a3359cf4587fb182eaf146d6b1648d6a7188..28c9c040de5d15956b35771550caec97bf1c033b 100644 (file)
@@ -9,10 +9,12 @@ Description:  Some Samsung laptops have different "performance levels"
                their fans quiet at all costs.  Reading from this file
                will show the current performance level.  Writing to the
                file can change this value.
+
                        Valid options:
-                               "silent"
-                               "normal"
-                               "overclock"
+                               - "silent"
+                               - "normal"
+                               - "overclock"
+
                Note that not all laptops support all of these options.
                Specifically, not all support the "overclock" option,
                and it's still unknown if this value even changes
@@ -25,8 +27,9 @@ Contact:      Corentin Chary <corentin.chary@gmail.com>
 Description:   Max battery charge level can be modified, battery cycle
                life can be extended by reducing the max battery charge
                level.
-               0 means normal battery mode (100% charge)
-               1 means battery life extender mode (80% charge)
+
+               - 0 means normal battery mode (100% charge)
+               - 1 means battery life extender mode (80% charge)
 
 What:          /sys/devices/platform/samsung/usb_charge
 Date:          December 1, 2011
index f34221b52b14b796377893207692c48ddaabf7fb..e5a438d84e1fbfc3f4b8402786af6eac73b50311 100644 (file)
@@ -4,10 +4,12 @@ KernelVersion:        3.15
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This file controls the keyboard backlight operation mode, valid
                values are:
+
                        * 0x1  -> FN-Z
                        * 0x2  -> AUTO (also called TIMER)
                        * 0x8  -> ON
                        * 0x10 -> OFF
+
                Note that from kernel 3.16 onwards this file accepts all listed
                parameters, kernel 3.15 only accepts the first two (FN-Z and
                AUTO).
@@ -41,8 +43,10 @@ KernelVersion:       3.15
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This files controls the status of the touchpad and pointing
                stick (if available), valid values are:
+
                        * 0 -> OFF
                        * 1 -> ON
+
 Users:         KToshiba
 
 What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/available_kbd_modes
@@ -51,10 +55,12 @@ KernelVersion:      3.16
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This file shows the supported keyboard backlight modes
                the system supports, which can be:
+
                        * 0x1  -> FN-Z
                        * 0x2  -> AUTO (also called TIMER)
                        * 0x8  -> ON
                        * 0x10 -> OFF
+
                Note that not all keyboard types support the listed modes.
                See the entry named "available_kbd_modes"
 Users:         KToshiba
@@ -65,6 +71,7 @@ KernelVersion:        3.16
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This file shows the current keyboard backlight type,
                which can be:
+
                        * 1 -> Type 1, supporting modes FN-Z and AUTO
                        * 2 -> Type 2, supporting modes TIMER, ON and OFF
 Users:         KToshiba
@@ -75,10 +82,12 @@ KernelVersion:      4.0
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This file controls the USB Sleep & Charge charging mode, which
                can be:
+
                        * 0 -> Disabled         (0x00)
                        * 1 -> Alternate        (0x09)
                        * 2 -> Auto             (0x21)
                        * 3 -> Typical          (0x11)
+
                Note that from kernel 4.1 onwards this file accepts all listed
                values, kernel 4.0 only supports the first three.
                Note that this feature only works when connected to power, if
@@ -93,8 +102,10 @@ Contact:    Azael Avalos <coproscefalo@gmail.com>
 Description:   This file controls the USB Sleep Functions under battery, and
                set the level at which point they will be disabled, accepted
                values can be:
+
                        * 0     -> Disabled
                        * 1-100 -> Battery level to disable sleep functions
+
                Currently it prints two values, the first one indicates if the
                feature is enabled or disabled, while the second one shows the
                current battery level set.
@@ -107,8 +118,10 @@ Date:              January 23, 2015
 KernelVersion: 4.0
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This file controls the USB Rapid Charge state, which can be:
+
                        * 0 -> Disabled
                        * 1 -> Enabled
+
                Note that toggling this value requires a reboot for changes to
                take effect.
 Users:         KToshiba
@@ -118,8 +131,10 @@ Date:              January 23, 2015
 KernelVersion: 4.0
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This file controls the Sleep & Music state, which values can be:
+
                        * 0 -> Disabled
                        * 1 -> Enabled
+
                Note that this feature only works when connected to power, if
                you want to use it under battery, see the entry named
                "sleep_functions_on_battery"
@@ -138,6 +153,7 @@ KernelVersion:      4.0
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This file controls the state of the internal fan, valid
                values are:
+
                        * 0 -> OFF
                        * 1 -> ON
 
@@ -147,8 +163,10 @@ KernelVersion:     4.0
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This file controls the Special Functions (hotkeys) operation
                mode, valid values are:
+
                        * 0 -> Normal Operation
                        * 1 -> Special Functions
+
                In the "Normal Operation" mode, the F{1-12} keys are as usual
                and the hotkeys are accessed via FN-F{1-12}.
                In the "Special Functions" mode, the F{1-12} keys trigger the
@@ -163,8 +181,10 @@ KernelVersion:     4.0
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This file controls whether the laptop should turn ON whenever
                the LID is opened, valid values are:
+
                        * 0 -> Disabled
                        * 1 -> Enabled
+
                Note that toggling this value requires a reboot for changes to
                take effect.
 Users:         KToshiba
@@ -174,8 +194,10 @@ Date:              February 12, 2015
 KernelVersion: 4.0
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This file controls the USB 3 functionality, valid values are:
+
                        * 0 -> Disabled (Acts as a regular USB 2)
                        * 1 -> Enabled (Full USB 3 functionality)
+
                Note that toggling this value requires a reboot for changes to
                take effect.
 Users:         KToshiba
@@ -188,10 +210,14 @@ Description:      This file controls the Cooling Method feature.
                Reading this file prints two values, the first is the actual cooling method
                and the second is the maximum cooling method supported.
                When the maximum cooling method is ONE, valid values are:
+
                        * 0 -> Maximum Performance
                        * 1 -> Battery Optimized
+
                When the maximum cooling method is TWO, valid values are:
+
                        * 0 -> Maximum Performance
                        * 1 -> Performance
                        * 2 -> Battery Optimized
+
 Users:         KToshiba
index a662370b4dbfa76c0c589601fe4c32d8e42e0ff1..c938690ce10d7bcaf4c413b623f4b9ab6479e176 100644 (file)
@@ -4,10 +4,12 @@ KernelVersion:        3.17
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This file controls the built-in accelerometer protection level,
                valid values are:
+
                        * 0 -> Disabled
                        * 1 -> Low
                        * 2 -> Medium
                        * 3 -> High
+
                The default potection value is set to 2 (Medium).
 Users:         KToshiba
 
index d1a352194d2eaf65d2d8ca435885bbded5424e6a..adc0d0e916078001cd573c896cda7402e7b5e10b 100644 (file)
@@ -18,6 +18,7 @@ Contact:      Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the device type. This is one of the UFS
                device descriptor parameters. The full information about
                the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_class
@@ -26,6 +27,7 @@ Contact:      Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the device class. This is one of the UFS
                device descriptor parameters. The full information about
                the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_sub_class
@@ -34,6 +36,7 @@ Contact:      Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the UFS storage subclass. This is one of
                the UFS device descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/protocol
@@ -43,6 +46,7 @@ Description:  This file shows the protocol supported by an UFS device.
                This is one of the UFS device descriptor parameters.
                The full information about the descriptor could be found
                at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/number_of_luns
@@ -51,6 +55,7 @@ Contact:      Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows number of logical units. This is one of
                the UFS device descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/number_of_wluns
@@ -60,6 +65,7 @@ Description:  This file shows number of well known logical units.
                This is one of the UFS device descriptor parameters.
                The full information about the descriptor could be found
                at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/boot_enable
@@ -69,6 +75,7 @@ Description:  This file shows value that indicates whether the device is
                enabled for boot. This is one of the UFS device descriptor
                parameters. The full information about the descriptor could
                be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/descriptor_access_enable
@@ -79,6 +86,7 @@ Description:  This file shows value that indicates whether the device
                of the boot sequence. This is one of the UFS device descriptor
                parameters. The full information about the descriptor could
                be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/initial_power_mode
@@ -88,6 +96,7 @@ Description:  This file shows value that defines the power mode after
                device initialization or hardware reset. This is one of
                the UFS device descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/high_priority_lun
@@ -96,6 +105,7 @@ Contact:     Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the high priority lun. This is one of
                the UFS device descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/secure_removal_type
@@ -104,6 +114,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the secure removal type. This is one of
                the UFS device descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/support_security_lun
@@ -113,6 +124,7 @@ Description:        This file shows whether the security lun is supported.
                This is one of the UFS device descriptor parameters.
                The full information about the descriptor could be found
                at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/bkops_termination_latency
@@ -122,6 +134,7 @@ Description:        This file shows the background operations termination
                latency. This is one of the UFS device descriptor parameters.
                The full information about the descriptor could be found
                at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/initial_active_icc_level
@@ -130,6 +143,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the initial active ICC level. This is one
                of the UFS device descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/specification_version
@@ -138,6 +152,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the specification version. This is one
                of the UFS device descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/manufacturing_date
@@ -147,6 +162,7 @@ Description:        This file shows the manufacturing date in BCD format.
                This is one of the UFS device descriptor parameters.
                The full information about the descriptor could be found
                at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/manufacturer_id
@@ -155,6 +171,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the manufacturee ID. This is one of the
                UFS device descriptor parameters. The full information about
                the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/rtt_capability
@@ -164,6 +181,7 @@ Description:        This file shows the maximum number of outstanding RTTs
                supported by the device. This is one of the UFS device
                descriptor parameters. The full information about
                the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/rtc_update
@@ -173,6 +191,7 @@ Description:        This file shows the frequency and method of the realtime
                clock update. This is one of the UFS device descriptor
                parameters. The full information about the descriptor
                could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/ufs_features
@@ -182,6 +201,7 @@ Description:        This file shows which features are supported by the device.
                This is one of the UFS device descriptor parameters.
                The full information about the descriptor could be
                found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/ffu_timeout
@@ -190,6 +210,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the FFU timeout. This is one of the
                UFS device descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/queue_depth
@@ -198,6 +219,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the device queue depth. This is one of the
                UFS device descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_version
@@ -206,6 +228,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the device version. This is one of the
                UFS device descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/number_of_secure_wpa
@@ -215,6 +238,7 @@ Description:        This file shows number of secure write protect areas
                supported by the device. This is one of the UFS device
                descriptor parameters. The full information about
                the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/psa_max_data_size
@@ -225,6 +249,7 @@ Description:        This file shows the maximum amount of data that may be
                This is one of the UFS device descriptor parameters.
                The full information about the descriptor could be found
                at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/psa_state_timeout
@@ -234,6 +259,7 @@ Description:        This file shows the command maximum timeout for a change
                in PSA state. This is one of the UFS device descriptor
                parameters. The full information about the descriptor could
                be found at UFS specifications 2.1.
+
                The file is read only.
 
 
@@ -244,6 +270,7 @@ Description:        This file shows the MIPI UniPro version number in BCD format.
                This is one of the UFS interconnect descriptor parameters.
                The full information about the descriptor could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/interconnect_descriptor/mphy_version
@@ -253,6 +280,7 @@ Description:        This file shows the MIPI M-PHY version number in BCD format.
                This is one of the UFS interconnect descriptor parameters.
                The full information about the descriptor could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 
@@ -264,6 +292,7 @@ Description:        This file shows the total memory quantity available to
                of the UFS geometry descriptor parameters. The full
                information about the descriptor could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/max_number_of_luns
@@ -273,6 +302,7 @@ Description:        This file shows the maximum number of logical units
                supported by the UFS device. This is one of the UFS
                geometry descriptor parameters. The full information about
                the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/segment_size
@@ -281,6 +311,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the segment size. This is one of the UFS
                geometry descriptor parameters. The full information about
                the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/allocation_unit_size
@@ -289,6 +320,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the allocation unit size. This is one of
                the UFS geometry descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/min_addressable_block_size
@@ -298,6 +330,7 @@ Description:        This file shows the minimum addressable block size. This
                is one of the UFS geometry descriptor parameters. The full
                information about the descriptor could be found at UFS
                specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/optimal_read_block_size
@@ -307,6 +340,7 @@ Description:        This file shows the optimal read block size. This is one
                of the UFS geometry descriptor parameters. The full
                information about the descriptor could be found at UFS
                specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/optimal_write_block_size
@@ -316,6 +350,7 @@ Description:        This file shows the optimal write block size. This is one
                of the UFS geometry descriptor parameters. The full
                information about the descriptor could be found at UFS
                specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/max_in_buffer_size
@@ -325,6 +360,7 @@ Description:        This file shows the maximum data-in buffer size. This
                is one of the UFS geometry descriptor parameters. The full
                information about the descriptor could be found at UFS
                specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/max_out_buffer_size
@@ -334,6 +370,7 @@ Description:        This file shows the maximum data-out buffer size. This
                is one of the UFS geometry descriptor parameters. The full
                information about the descriptor could be found at UFS
                specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/rpmb_rw_size
@@ -343,6 +380,7 @@ Description:        This file shows the maximum number of RPMB frames allowed
                in Security Protocol In/Out. This is one of the UFS geometry
                descriptor parameters. The full information about the
                descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/dyn_capacity_resource_policy
@@ -352,6 +390,7 @@ Description:        This file shows the dynamic capacity resource policy. This
                is one of the UFS geometry descriptor parameters. The full
                information about the descriptor could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/data_ordering
@@ -361,6 +400,7 @@ Description:        This file shows support for out-of-order data transfer.
                This is one of the UFS geometry descriptor parameters.
                The full information about the descriptor could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/max_number_of_contexts
@@ -370,6 +410,7 @@ Description:        This file shows maximum available number of contexts which
                are supported by the device. This is one of the UFS geometry
                descriptor parameters. The full information about the
                descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/sys_data_tag_unit_size
@@ -378,6 +419,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows system data tag unit size. This is one of
                the UFS geometry descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/sys_data_tag_resource_size
@@ -388,6 +430,7 @@ Description:        This file shows maximum storage area size allocated by
                This is one of the UFS geometry descriptor parameters.
                The full information about the descriptor could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/secure_removal_types
@@ -397,6 +440,7 @@ Description:        This file shows supported secure removal types. This is
                one of the UFS geometry descriptor parameters. The full
                information about the descriptor could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/memory_types
@@ -406,6 +450,7 @@ Description:        This file shows supported memory types. This is one of
                the UFS geometry descriptor parameters. The full
                information about the descriptor could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/*_memory_max_alloc_units
@@ -416,6 +461,7 @@ Description:        This file shows the maximum number of allocation units for
                enhanced type 1-4). This is one of the UFS geometry
                descriptor parameters. The full information about the
                descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/*_memory_capacity_adjustment_factor
@@ -426,6 +472,7 @@ Description:        This file shows the memory capacity adjustment factor for
                enhanced type 1-4). This is one of the UFS geometry
                descriptor parameters. The full information about the
                descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 
@@ -436,6 +483,7 @@ Description:        This file shows preend of life information. This is one
                of the UFS health descriptor parameters. The full
                information about the descriptor could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/health_descriptor/life_time_estimation_a
@@ -445,6 +493,7 @@ Description:        This file shows indication of the device life time
                (method a). This is one of the UFS health descriptor
                parameters. The full information about the descriptor
                could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/health_descriptor/life_time_estimation_b
@@ -454,6 +503,7 @@ Description:        This file shows indication of the device life time
                (method b). This is one of the UFS health descriptor
                parameters. The full information about the descriptor
                could be found at UFS specifications 2.1.
+
                The file is read only.
 
 
@@ -464,6 +514,7 @@ Description:        This file shows maximum VCC, VCCQ and VCCQ2 value for
                active ICC levels from 0 to 15. This is one of the UFS
                power descriptor parameters. The full information about
                the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 
@@ -473,6 +524,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file contains a device manufactureer name string.
                The full information about the descriptor could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/string_descriptors/product_name
@@ -480,6 +532,7 @@ Date:               February 2018
 Contact:       Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file contains a product name string. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/string_descriptors/oem_id
@@ -487,6 +540,7 @@ Date:               February 2018
 Contact:       Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file contains a OEM ID string. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/string_descriptors/serial_number
@@ -495,6 +549,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file contains a device serial number string. The full
                information about the descriptor could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/string_descriptors/product_revision
@@ -503,6 +558,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file contains a product revision string. The full
                information about the descriptor could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 
@@ -512,6 +568,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows boot LUN information. This is one of
                the UFS unit descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/class/scsi_device/*/device/unit_descriptor/lun_write_protect
@@ -520,6 +577,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows LUN write protection status. This is one of
                the UFS unit descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/class/scsi_device/*/device/unit_descriptor/lun_queue_depth
@@ -528,6 +586,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows LUN queue depth. This is one of the UFS
                unit descriptor parameters. The full information about
                the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/class/scsi_device/*/device/unit_descriptor/psa_sensitive
@@ -536,6 +595,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows PSA sensitivity. This is one of the UFS
                unit descriptor parameters. The full information about
                the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/class/scsi_device/*/device/unit_descriptor/lun_memory_type
@@ -544,6 +604,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows LUN memory type. This is one of the UFS
                unit descriptor parameters. The full information about
                the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/class/scsi_device/*/device/unit_descriptor/data_reliability
@@ -553,6 +614,7 @@ Description:        This file defines the device behavior when a power failure
                occurs during a write operation. This is one of the UFS
                unit descriptor parameters. The full information about
                the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/class/scsi_device/*/device/unit_descriptor/logical_block_size
@@ -562,6 +624,7 @@ Description:        This file shows the size of addressable logical blocks
                (calculated as an exponent with base 2). This is one of
                the UFS unit descriptor parameters. The full information about
                the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/class/scsi_device/*/device/unit_descriptor/logical_block_count
@@ -571,6 +634,7 @@ Description:        This file shows total number of addressable logical blocks.
                This is one of the UFS unit descriptor parameters. The full
                information about the descriptor could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/class/scsi_device/*/device/unit_descriptor/erase_block_size
@@ -579,6 +643,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the erase block size. This is one of
                the UFS unit descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/class/scsi_device/*/device/unit_descriptor/provisioning_type
@@ -587,6 +652,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the thin provisioning type. This is one of
                the UFS unit descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/class/scsi_device/*/device/unit_descriptor/physical_memory_resourse_count
@@ -595,6 +661,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the total physical memory resources. This is
                one of the UFS unit descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/class/scsi_device/*/device/unit_descriptor/context_capabilities
@@ -603,6 +670,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the context capabilities. This is one of
                the UFS unit descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/class/scsi_device/*/device/unit_descriptor/large_unit_granularity
@@ -611,6 +679,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the granularity of the LUN. This is one of
                the UFS unit descriptor parameters. The full information
                about the descriptor could be found at UFS specifications 2.1.
+
                The file is read only.
 
 
@@ -619,6 +688,7 @@ Date:               February 2018
 Contact:       Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the device init status. The full information
                about the flag could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/flags/permanent_wpe
@@ -627,6 +697,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows whether permanent write protection is enabled.
                The full information about the flag could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/flags/power_on_wpe
@@ -636,6 +707,7 @@ Description:        This file shows whether write protection is enabled on all
                logical units configured as power on write protected. The
                full information about the flag could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/flags/bkops_enable
@@ -644,6 +716,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows whether the device background operations are
                enabled. The full information about the flag could be
                found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/flags/life_span_mode_enable
@@ -652,6 +725,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows whether the device life span mode is enabled.
                The full information about the flag could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/flags/phy_resource_removal
@@ -660,6 +734,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows whether physical resource removal is enable.
                The full information about the flag could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/flags/busy_rtc
@@ -668,6 +743,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows whether the device is executing internal
                operation related to real time clock. The full information
                about the flag could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/flags/disable_fw_update
@@ -676,6 +752,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows whether the device FW update is permanently
                disabled. The full information about the flag could be found
                at UFS specifications 2.1.
+
                The file is read only.
 
 
@@ -685,6 +762,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file provides the boot lun enabled UFS device attribute.
                The full information about the attribute could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/current_power_mode
@@ -693,6 +771,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file provides the current power mode UFS device attribute.
                The full information about the attribute could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/active_icc_level
@@ -701,6 +780,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file provides the active icc level UFS device attribute.
                The full information about the attribute could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/ooo_data_enabled
@@ -709,6 +789,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file provides the out of order data transfer enabled UFS
                device attribute. The full information about the attribute
                could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/bkops_status
@@ -717,6 +798,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file provides the background operations status UFS device
                attribute. The full information about the attribute could
                be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/purge_status
@@ -725,6 +807,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file provides the purge operation status UFS device
                attribute. The full information about the attribute could
                be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/max_data_in_size
@@ -733,6 +816,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the maximum data size in a DATA IN
                UPIU. The full information about the attribute could
                be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/max_data_out_size
@@ -741,6 +825,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file shows the maximum number of bytes that can be
                requested with a READY TO TRANSFER UPIU. The full information
                about the attribute could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/reference_clock_frequency
@@ -749,6 +834,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file provides the reference clock frequency UFS device
                attribute. The full information about the attribute could
                be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/configuration_descriptor_lock
@@ -765,6 +851,7 @@ Description:        This file provides the maximum current number of
                outstanding RTTs in device that is allowed. The full
                information about the attribute could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/exception_event_control
@@ -773,6 +860,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file provides the exception event control UFS device
                attribute. The full information about the attribute could
                be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/exception_event_status
@@ -781,6 +869,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file provides the exception event status UFS device
                attribute. The full information about the attribute could
                be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/ffu_status
@@ -789,6 +878,7 @@ Contact:    Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file provides the ffu status UFS device attribute.
                The full information about the attribute could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/psa_state
@@ -796,6 +886,7 @@ Date:               February 2018
 Contact:       Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
 Description:   This file show the PSA feature status. The full information
                about the attribute could be found at UFS specifications 2.1.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/psa_data_size
@@ -805,6 +896,7 @@ Description:        This file shows the amount of data that the host plans to
                load to all logical units in pre-soldering state.
                The full information about the attribute could be found at
                UFS specifications 2.1.
+
                The file is read only.
 
 
@@ -815,6 +907,7 @@ Description:        This file shows the The amount of physical memory needed
                to be removed from the physical memory resources pool of
                the particular logical unit. The full information about
                the attribute could be found at UFS specifications 2.1.
+
                The file is read only.
 
 
@@ -824,24 +917,28 @@ Contact:  Subhash Jadavani <subhashj@codeaurora.org>
 Description:   This entry could be used to set or show the UFS device
                runtime power management level. The current driver
                implementation supports 6 levels with next target states:
-               0 - an UFS device will stay active, an UIC link will
-               stay active
-               1 - an UFS device will stay active, an UIC link will
-               hibernate
-               2 - an UFS device will moved to sleep, an UIC link will
-               stay active
-               3 - an UFS device will moved to sleep, an UIC link will
-               hibernate
-               4 - an UFS device will be powered off, an UIC link will
-               hibernate
-               5 - an UFS device will be powered off, an UIC link will
-               be powered off
+
+               ==  ====================================================
+               0   an UFS device will stay active, an UIC link will
+                   stay active
+               1   an UFS device will stay active, an UIC link will
+                   hibernate
+               2   an UFS device will moved to sleep, an UIC link will
+                   stay active
+               3   an UFS device will moved to sleep, an UIC link will
+                   hibernate
+               4   an UFS device will be powered off, an UIC link will
+                   hibernate
+               5   an UFS device will be powered off, an UIC link will
+                   be powered off
+               ==  ====================================================
 
 What:          /sys/bus/platform/drivers/ufshcd/*/rpm_target_dev_state
 Date:          February 2018
 Contact:       Subhash Jadavani <subhashj@codeaurora.org>
 Description:   This entry shows the target power mode of an UFS device
                for the chosen runtime power management level.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/rpm_target_link_state
@@ -849,6 +946,7 @@ Date:               February 2018
 Contact:       Subhash Jadavani <subhashj@codeaurora.org>
 Description:   This entry shows the target state of an UFS UIC link
                for the chosen runtime power management level.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/spm_lvl
@@ -857,24 +955,28 @@ Contact:  Subhash Jadavani <subhashj@codeaurora.org>
 Description:   This entry could be used to set or show the UFS device
                system power management level. The current driver
                implementation supports 6 levels with next target states:
-               0 - an UFS device will stay active, an UIC link will
-               stay active
-               1 - an UFS device will stay active, an UIC link will
-               hibernate
-               2 - an UFS device will moved to sleep, an UIC link will
-               stay active
-               3 - an UFS device will moved to sleep, an UIC link will
-               hibernate
-               4 - an UFS device will be powered off, an UIC link will
-               hibernate
-               5 - an UFS device will be powered off, an UIC link will
-               be powered off
+
+               ==  ====================================================
+               0   an UFS device will stay active, an UIC link will
+                   stay active
+               1   an UFS device will stay active, an UIC link will
+                   hibernate
+               2   an UFS device will moved to sleep, an UIC link will
+                   stay active
+               3   an UFS device will moved to sleep, an UIC link will
+                   hibernate
+               4   an UFS device will be powered off, an UIC link will
+                   hibernate
+               5   an UFS device will be powered off, an UIC link will
+                   be powered off
+               ==  ====================================================
 
 What:          /sys/bus/platform/drivers/ufshcd/*/spm_target_dev_state
 Date:          February 2018
 Contact:       Subhash Jadavani <subhashj@codeaurora.org>
 Description:   This entry shows the target power mode of an UFS device
                for the chosen system power management level.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/spm_target_link_state
@@ -882,18 +984,21 @@ Date:             February 2018
 Contact:       Subhash Jadavani <subhashj@codeaurora.org>
 Description:   This entry shows the target state of an UFS UIC link
                for the chosen system power management level.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_presv_us_en
 Date:          June 2020
 Contact:       Asutosh Das <asutoshd@codeaurora.org>
 Description:   This entry shows if preserve user-space was configured
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_shared_alloc_units
 Date:          June 2020
 Contact:       Asutosh Das <asutoshd@codeaurora.org>
 Description:   This entry shows the shared allocated units of WB buffer
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_type
@@ -901,6 +1006,7 @@ Date:              June 2020
 Contact:       Asutosh Das <asutoshd@codeaurora.org>
 Description:   This entry shows the configured WB type.
                0x1 for shared buffer mode. 0x0 for dedicated buffer mode.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_buff_cap_adj
@@ -910,6 +1016,7 @@ Description:       This entry shows the total user-space decrease in shared
                buffer mode.
                The value of this parameter is 3 for TLC NAND when SLC mode
                is used as WriteBooster Buffer. 2 for MLC NAND.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_max_alloc_units
@@ -917,6 +1024,7 @@ Date:              June 2020
 Contact:       Asutosh Das <asutoshd@codeaurora.org>
 Description:   This entry shows the Maximum total WriteBooster Buffer size
                which is supported by the entire device.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_max_wb_luns
@@ -924,6 +1032,7 @@ Date:              June 2020
 Contact:       Asutosh Das <asutoshd@codeaurora.org>
 Description:   This entry shows the maximum number of luns that can support
                WriteBooster.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_sup_red_type
@@ -937,46 +1046,59 @@ Description:     The supportability of user space reduction mode
                preserve user space type.
                02h: Device can be configured in either user space
                reduction type or preserve user space type.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_sup_wb_type
 Date:          June 2020
 Contact:       Asutosh Das <asutoshd@codeaurora.org>
 Description:   The supportability of WriteBooster Buffer type.
-               00h: LU based WriteBooster Buffer configuration
-               01h: Single shared WriteBooster Buffer
-               configuration
-               02h: Supporting both LU based WriteBooster
-               Buffer and Single shared WriteBooster Buffer
-               configuration
+
+               ===  ==========================================================
+               00h  LU based WriteBooster Buffer configuration
+               01h  Single shared WriteBooster Buffer configuration
+               02h  Supporting both LU based WriteBooster.
+                    Buffer and Single shared WriteBooster Buffer configuration
+               ===  ==========================================================
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/flags/wb_enable
 Date:          June 2020
 Contact:       Asutosh Das <asutoshd@codeaurora.org>
 Description:   This entry shows the status of WriteBooster.
-               0: WriteBooster is not enabled.
-               1: WriteBooster is enabled
+
+               == ============================
+               0  WriteBooster is not enabled.
+               1  WriteBooster is enabled
+               == ============================
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/flags/wb_flush_en
 Date:          June 2020
 Contact:       Asutosh Das <asutoshd@codeaurora.org>
 Description:   This entry shows if flush is enabled.
-               0: Flush operation is not performed.
-               1: Flush operation is performed.
+
+               == =================================
+               0  Flush operation is not performed.
+               1  Flush operation is performed.
+               == =================================
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/flags/wb_flush_during_h8
 Date:          June 2020
 Contact:       Asutosh Das <asutoshd@codeaurora.org>
 Description:   Flush WriteBooster Buffer during hibernate state.
-               0: Device is not allowed to flush the
-               WriteBooster Buffer during link hibernate
-               state.
-               1: Device is allowed to flush the
-               WriteBooster Buffer during link hibernate
-               state
+
+               == =================================================
+               0  Device is not allowed to flush the
+                  WriteBooster Buffer during link hibernate state.
+               1  Device is allowed to flush the
+                  WriteBooster Buffer during link hibernate state.
+               == =================================================
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/wb_avail_buf
@@ -984,23 +1106,30 @@ Date:            June 2020
 Contact:       Asutosh Das <asutoshd@codeaurora.org>
 Description:   This entry shows the amount of unused WriteBooster buffer
                available.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/wb_cur_buf
 Date:          June 2020
 Contact:       Asutosh Das <asutoshd@codeaurora.org>
 Description:   This entry shows the amount of unused current buffer.
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/wb_flush_status
 Date:          June 2020
 Contact:       Asutosh Das <asutoshd@codeaurora.org>
 Description:   This entry shows the flush operation status.
-               00h: idle
-               01h: Flush operation in progress
-               02h: Flush operation stopped prematurely.
-               03h: Flush operation completed successfully
-               04h: Flush operation general failure
+
+
+               ===  ======================================
+               00h  idle
+               01h  Flush operation in progress
+               02h  Flush operation stopped prematurely.
+               03h  Flush operation completed successfully
+               04h  Flush operation general failure
+               ===  ======================================
+
                The file is read only.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/wb_life_time_est
@@ -1008,9 +1137,13 @@ Date:            June 2020
 Contact:       Asutosh Das <asutoshd@codeaurora.org>
 Description:   This entry shows an indication of the WriteBooster Buffer
                lifetime based on the amount of performed program/erase cycles
-               01h: 0% - 10% WriteBooster Buffer life time used
+
+               ===  =============================================
+               01h  0% - 10% WriteBooster Buffer life time used
                ...
-               0Ah: 90% - 100% WriteBooster Buffer life time used
+               0Ah  90% - 100% WriteBooster Buffer life time used
+               ===  =============================================
+
                The file is read only.
 
 What:          /sys/class/scsi_device/*/device/unit_descriptor/wb_buf_alloc_units
@@ -1018,4 +1151,5 @@ Date:             June 2020
 Contact:       Asutosh Das <asutoshd@codeaurora.org>
 Description:   This entry shows the configured size of WriteBooster buffer.
                0400h corresponds to 4GB.
+
                The file is read only.
index d301e7017afe164cf9140252f0168ee23007d197..e92aba4eb594e92f25c4482a360c82df9e4191be 100644 (file)
@@ -5,7 +5,9 @@ Contact:        Jan Kandziora <jjj@gmx.de>
 Description:   When written, this file sets the I2C speed on the connected
                DS28E17 chip. When read, it reads the current setting from
                the DS28E17 chip.
+
                Valid values: 100, 400, 900 [kBaud].
+
                Default 100, can be set by w1_ds28e17.speed= module parameter.
 Users:         w1_ds28e17 driver
 
@@ -17,5 +19,6 @@ Description:  When written, this file sets the multiplier used to calculate
                the busy timeout for I2C operations on the connected DS28E17
                chip. When read, returns the current setting.
                Valid values: 1 to 9.
+
                Default 1, can be set by w1_ds28e17.stretch= module parameter.
 Users:         w1_ds28e17 driver
index 8873bbb075cb9fdb343f1a0b23aeb499cf3efd78..6a37dc33ffdb567af4224e6ef2e9453383ca44d3 100644 (file)
@@ -22,8 +22,10 @@ Description:
                device data to its embedded EEPROM, either restore data
                embedded in device EEPROM. Be aware that devices support
                limited EEPROM writing cycles (typical 50k)
+
                        * 'save': save device RAM to EEPROM
                        * 'restore': restore EEPROM data in device RAM
+
 Users:         any user space application which wants to communicate with
                w1_term device
 
@@ -33,9 +35,11 @@ Date:                May 2020
 Contact:       Akira Shimahara <akira215corp@gmail.com>
 Description:
                (RO) return the power status by asking the device
+
                        * '0': device parasite powered
                        * '1': device externally powered
                        * '-xx': xx is kernel error when reading power status
+
 Users:         any user space application which wants to communicate with
                w1_term device
 
@@ -49,10 +53,12 @@ Description:
                will be changed only in device RAM, so it will be cleared when
                power is lost. Trigger a 'save' to EEPROM command to keep
                values after power-on. Read or write are :
+
                        * '9..14': device resolution in bit
-                       or resolution to set in bit
+                         or resolution to set in bit
                        * '-xx': xx is kernel error when reading the resolution
                        * Anything else: do nothing
+
                Some DS18B20 clones are fixed in 12-bit resolution, so the
                actual resolution is read back from the chip and verified. Error
                is reported if the results differ.
@@ -65,16 +71,18 @@ Date:               May 2020
 Contact:       Akira Shimahara <akira215corp@gmail.com>
 Description:
                (RO) return the temperature in 1/1000 degC.
+
                        * If a bulk read has been triggered, it will directly
-                       return the temperature computed when the bulk read
-                       occurred, if available. If not yet available, nothing
-                       is returned (a debug kernel message is sent), you
-                       should retry later on.
+                         return the temperature computed when the bulk read
+                         occurred, if available. If not yet available, nothing
+                         is returned (a debug kernel message is sent), you
+                         should retry later on.
                        * If no bulk read has been triggered, it will trigger
-                       a conversion and send the result. Note that the
-                       conversion duration depend on the resolution (if
-                       device support this feature). It takes 94ms in 9bits
-                       resolution, 750ms for 12bits.
+                         a conversion and send the result. Note that the
+                         conversion duration depend on the resolution (if
+                         device support this feature). It takes 94ms in 9bits
+                         resolution, 750ms for 12bits.
+
 Users:         any user space application which wants to communicate with
                w1_term device
 
@@ -86,12 +94,14 @@ Description:
                (RW) return the temperature in 1/1000 degC.
                *read*: return 2 lines with the hexa output data sent on the
                bus, return the CRC check and temperature in 1/1000 degC
-               *write* :
+               *write*:
+
                        * '0' : save the 2 or 3 bytes to the device EEPROM
-                       (i.e. TH, TL and config register)
+                         (i.e. TH, TL and config register)
                        * '9..14' : set the device resolution in RAM
-                       (if supported)
+                         (if supported)
                        * Anything else: do nothing
+
                refer to Documentation/w1/slaves/w1_therm.rst for detailed
                information.
 Users:         any user space application which wants to communicate with
@@ -103,14 +113,21 @@ Date:             May 2020
 Contact:       Akira Shimahara <akira215corp@gmail.com>
 Description:
                (RW) trigger a bulk read conversion. read the status
+
                *read*:
-                       * '-1': conversion in progress on at least 1 sensor
-                       * '1' : conversion complete but at least one sensor
+                       * '-1':
+                               conversion in progress on at least 1 sensor
+                       * '1' :
+                               conversion complete but at least one sensor
                                value has not been read yet
-                       * '0' : no bulk operation. Reading temperature will
+                       * '0' :
+                               no bulk operation. Reading temperature will
                                trigger a conversion on each device
-               *write*: 'trigger': trigger a bulk read on all supporting
+
+               *write*:
+                       'trigger': trigger a bulk read on all supporting
                        devices on the bus
+
                Note that if a bulk read is sent but one sensor is not read
                immediately, the next access to temperature on this device
                will return the temperature measured at the time of issue
@@ -128,14 +145,19 @@ Description:
                reset to default (datasheet) conversion time for a new
                resolution.
 
-               *read*: Actual conversion time in milliseconds. *write*:
-                       '0': Set the default conversion time from the datasheet.
-                       '1': Measure and set the conversion time. Make a single
+               *read*:
+                       Actual conversion time in milliseconds.
+
+               *write*:
+                       * '0':
+                            Set the default conversion time from the datasheet.
+                       * '1':
+                            Measure and set the conversion time. Make a single
                             temperature conversion, measure an actual value.
                             Increase it by 20% for temperature range. A new
                             conversion time can be obtained by reading this
                             same attribute.
-                       other positive value:
+                       other positive value:
                             Set the conversion time in milliseconds.
 
 Users:         An application using the w1_term device
@@ -148,16 +170,21 @@ Description:
                (RW) Control optional driver settings.
                Bit masks to read/write (bitwise OR):
 
-                1: Enable check for conversion success. If byte 6 of
+               == ============================================================
+                 1 Enable check for conversion success. If byte 6 of
                    scratchpad memory is 0xC after conversion, and
                    temperature reads 85.00 (powerup value) or 127.94
                    (insufficient power) - return a conversion error.
 
-                2: Enable poll for conversion completion. Generate read cycles
+                2  Enable poll for conversion completion. Generate read cycles
                    after the conversion start and wait for 1's. In parasite
                    power mode this feature is not available.
+               == ============================================================
+
+               *read*:
+                   Currently selected features.
 
-               *read*:  Currently selected features.
-               *write*: Select features.
+               *write*:
+                   Select features.
 
 Users:         An application using the w1_term device
index afc48fc163b5903bdf6d41018b8dfb961a4a1b85..16acaa5712ec9d231151f4723acdcd51baaca128 100644 (file)
@@ -79,7 +79,9 @@ Description:
                When the Wacom Intuos 4 is connected over Bluetooth, the
                image has to contain 256 bytes (64x32 px 1 bit colour).
                The format is also scrambled, like in the USB mode, and it can
-               be summarized by converting 76543210 into GECA6420.
+               be summarized by converting::
+
+                                           76543210 into GECA6420.
                                            HGFEDCBA      HFDB7531
 
 What:          /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_remote/unpair_remote
index 613f42a9d5cdcd7b6a9f754b59387065daa1576f..b16d30a71709f771136c58cb0ad939e3cece1a8d 100644 (file)
@@ -12,11 +12,14 @@ Description:
                image: The image bitmap. Currently a 32-bit BMP.
                status: 1 if the image is valid, 0 if firmware invalidated it.
                type: 0 indicates image is in BMP format.
+
+               ======== ===================================================
                version: The version of the BGRT. Currently 1.
                xoffset: The number of pixels between the left of the screen
                         and the left edge of the image.
                yoffset: The number of pixels between the top of the screen
                         and the top edge of the image.
+               ======== ===================================================
 
 What:          /sys/firmware/acpi/hotplug/
 Date:          February 2013
@@ -33,12 +36,14 @@ Description:
                The following setting is available to user space for each
                hotplug profile:
 
+               ======== =======================================================
                enabled: If set, the ACPI core will handle notifications of
-                       hotplug events associated with the given class of
-                       devices and will allow those devices to be ejected with
-                       the help of the _EJ0 control method.  Unsetting it
-                       effectively disables hotplug for the correspoinding
-                       class of devices.
+                        hotplug events associated with the given class of
+                        devices and will allow those devices to be ejected with
+                        the help of the _EJ0 control method.  Unsetting it
+                        effectively disables hotplug for the correspoinding
+                        class of devices.
+               ======== =======================================================
 
                The value of the above attribute is an integer number: 1 (set)
                or 0 (unset).  Attempts to write any other values to it will
@@ -71,86 +76,90 @@ Description:
                To figure out where all the SCI's are coming from,
                /sys/firmware/acpi/interrupts contains a file listing
                every possible source, and the count of how many
-               times it has triggered.
-
-               $ cd /sys/firmware/acpi/interrupts
-               $ grep . *
-               error:       0
-               ff_gbl_lock:       0   enable
-               ff_pmtimer:       0  invalid
-               ff_pwr_btn:       0   enable
-               ff_rt_clk:       2  disable
-               ff_slp_btn:       0  invalid
-               gpe00:       0  invalid
-               gpe01:       0   enable
-               gpe02:     108   enable
-               gpe03:       0  invalid
-               gpe04:       0  invalid
-               gpe05:       0  invalid
-               gpe06:       0   enable
-               gpe07:       0   enable
-               gpe08:       0  invalid
-               gpe09:       0  invalid
-               gpe0A:       0  invalid
-               gpe0B:       0  invalid
-               gpe0C:       0  invalid
-               gpe0D:       0  invalid
-               gpe0E:       0  invalid
-               gpe0F:       0  invalid
-               gpe10:       0  invalid
-               gpe11:       0  invalid
-               gpe12:       0  invalid
-               gpe13:       0  invalid
-               gpe14:       0  invalid
-               gpe15:       0  invalid
-               gpe16:       0  invalid
-               gpe17:    1084   enable
-               gpe18:       0   enable
-               gpe19:       0  invalid
-               gpe1A:       0  invalid
-               gpe1B:       0  invalid
-               gpe1C:       0  invalid
-               gpe1D:       0  invalid
-               gpe1E:       0  invalid
-               gpe1F:       0  invalid
-               gpe_all:    1192
-               sci:    1194
-               sci_not:     0  
-
-               sci - The number of times the ACPI SCI
-               has been called and claimed an interrupt.
-
-               sci_not - The number of times the ACPI SCI
-               has been called and NOT claimed an interrupt.
-
-               gpe_all - count of SCI caused by GPEs.
-
-               gpeXX - count for individual GPE source
-
-               ff_gbl_lock - Global Lock
-
-               ff_pmtimer - PM Timer
-
-               ff_pwr_btn - Power Button
-
-               ff_rt_clk - Real Time Clock
-
-               ff_slp_btn - Sleep Button
-
-               error - an interrupt that can't be accounted for above.
-
-               invalid: it's either a GPE or a Fixed Event that
-                       doesn't have an event handler.
-
-               disable: the GPE/Fixed Event is valid but disabled.
-
-               enable: the GPE/Fixed Event is valid and enabled.
-
-               Root has permission to clear any of these counters.  Eg.
-               # echo 0 > gpe11
-
-               All counters can be cleared by clearing the total "sci":
-               # echo 0 > sci
+               times it has triggered::
+
+                 $ cd /sys/firmware/acpi/interrupts
+                 $ grep . *
+                 error:             0
+                 ff_gbl_lock:       0   enable
+                 ff_pmtimer:        0  invalid
+                 ff_pwr_btn:        0   enable
+                 ff_rt_clk:         2  disable
+                 ff_slp_btn:        0  invalid
+                 gpe00:             0  invalid
+                 gpe01:             0   enable
+                 gpe02:           108   enable
+                 gpe03:             0  invalid
+                 gpe04:             0  invalid
+                 gpe05:             0  invalid
+                 gpe06:             0   enable
+                 gpe07:             0   enable
+                 gpe08:             0  invalid
+                 gpe09:             0  invalid
+                 gpe0A:             0  invalid
+                 gpe0B:             0  invalid
+                 gpe0C:             0  invalid
+                 gpe0D:             0  invalid
+                 gpe0E:             0  invalid
+                 gpe0F:             0  invalid
+                 gpe10:             0  invalid
+                 gpe11:             0  invalid
+                 gpe12:             0  invalid
+                 gpe13:             0  invalid
+                 gpe14:             0  invalid
+                 gpe15:             0  invalid
+                 gpe16:             0  invalid
+                 gpe17:          1084   enable
+                 gpe18:             0   enable
+                 gpe19:             0  invalid
+                 gpe1A:             0  invalid
+                 gpe1B:             0  invalid
+                 gpe1C:             0  invalid
+                 gpe1D:             0  invalid
+                 gpe1E:             0  invalid
+                 gpe1F:             0  invalid
+                 gpe_all:        1192
+                 sci:            1194
+                 sci_not:           0
+
+               ===========  ==================================================
+               sci          The number of times the ACPI SCI
+                            has been called and claimed an interrupt.
+
+               sci_not      The number of times the ACPI SCI
+                            has been called and NOT claimed an interrupt.
+
+               gpe_all      count of SCI caused by GPEs.
+
+               gpeXX        count for individual GPE source
+
+               ff_gbl_lock  Global Lock
+
+               ff_pmtimer   PM Timer
+
+               ff_pwr_btn   Power Button
+
+               ff_rt_clk    Real Time Clock
+
+               ff_slp_btn   Sleep Button
+
+               error        an interrupt that can't be accounted for above.
+
+               invalid      it's either a GPE or a Fixed Event that
+                            doesn't have an event handler.
+
+               disable      the GPE/Fixed Event is valid but disabled.
+
+               enable       the GPE/Fixed Event is valid and enabled.
+               ===========  ==================================================
+
+               Root has permission to clear any of these counters.  Eg.::
+
+                 # echo 0 > gpe11
+
+               All counters can be cleared by clearing the total "sci"::
+
+                 # echo 0 > sci
 
                None of these counters has an effect on the function
                of the system, they are simply statistics.
@@ -165,32 +174,34 @@ Description:
 
                Let's take power button fixed event for example, please kill acpid
                and other user space applications so that the machine won't shutdown
-               when pressing the power button.
-               # cat ff_pwr_btn
-               0       enabled
-               # press the power button for 3 times;
-               # cat ff_pwr_btn
-               3       enabled
-               # echo disable > ff_pwr_btn
-               # cat ff_pwr_btn
-               3       disabled
-               # press the power button for 3 times;
-               # cat ff_pwr_btn
-               3       disabled
-               # echo enable > ff_pwr_btn
-               # cat ff_pwr_btn
-               4       enabled
-               /*
-                * this is because the status bit is set even if the enable bit is cleared,
-                * and it triggers an ACPI fixed event when the enable bit is set again
-                */
-               # press the power button for 3 times;
-               # cat ff_pwr_btn
-               7       enabled
-               # echo disable > ff_pwr_btn
-               # press the power button for 3 times;
-               # echo clear > ff_pwr_btn       /* clear the status bit */
-               # echo disable > ff_pwr_btn
-               # cat ff_pwr_btn
-               7       enabled
+               when pressing the power button::
+
+                 # cat ff_pwr_btn
+                 0     enabled
+                 # press the power button for 3 times;
+                 # cat ff_pwr_btn
+                 3     enabled
+                 # echo disable > ff_pwr_btn
+                 # cat ff_pwr_btn
+                 3     disabled
+                 # press the power button for 3 times;
+                 # cat ff_pwr_btn
+                 3     disabled
+                 # echo enable > ff_pwr_btn
+                 # cat ff_pwr_btn
+                 4     enabled
+                 /*
+                  * this is because the status bit is set even if the enable
+                  * bit is cleared, and it triggers an ACPI fixed event when
+                  * the enable bit is set again
+                  */
+                 # press the power button for 3 times;
+                 # cat ff_pwr_btn
+                 7     enabled
+                 # echo disable > ff_pwr_btn
+                 # press the power button for 3 times;
+                 # echo clear > ff_pwr_btn     /* clear the status bit */
+                 # echo disable > ff_pwr_btn
+                 # cat ff_pwr_btn
+                 7     enabled
 
index 210ad44b95a557bd16b924940f283101a906d1d9..fe0289c877684958b23e31bc32cbff428a31524b 100644 (file)
@@ -33,7 +33,7 @@ Description:
                doesn't matter), they will be represented in sysfs as
                entries "T-0" through "T-(N-1)":
 
-               Example entry directories:
+               Example entry directories::
 
                        /sys/firmware/dmi/entries/17-0
                        /sys/firmware/dmi/entries/17-1
@@ -50,61 +50,65 @@ Description:
                Each DMI entry in sysfs has the common header values
                exported as attributes:
 
-               handle  : The 16bit 'handle' that is assigned to this
+               ========  =================================================
+               handle    The 16bit 'handle' that is assigned to this
                          entry by the firmware.  This handle may be
                          referred to by other entries.
-               length  : The length of the entry, as presented in the
+               length    The length of the entry, as presented in the
                          entry itself.  Note that this is _not the
                          total count of bytes associated with the
-                         entry_.  This value represents the length of
+                         entry.  This value represents the length of
                          the "formatted" portion of the entry.  This
                          "formatted" region is sometimes followed by
                          the "unformatted" region composed of nul
                          terminated strings, with termination signalled
                          by a two nul characters in series.
-               raw     : The raw bytes of the entry. This includes the
+               raw       The raw bytes of the entry. This includes the
                          "formatted" portion of the entry, the
                          "unformatted" strings portion of the entry,
                          and the two terminating nul characters.
-               type    : The type of the entry.  This value is the same
+               type      The type of the entry.  This value is the same
                          as found in the directory name.  It indicates
                          how the rest of the entry should be interpreted.
-               instance: The instance ordinal of the entry for the
+               instance  The instance ordinal of the entry for the
                          given type.  This value is the same as found
                          in the parent directory name.
-               position: The ordinal position (zero-based) of the entry
+               position  The ordinal position (zero-based) of the entry
                          within the entirety of the DMI entry table.
+               ========  =================================================
 
-               === Entry Specialization ===
+               **Entry Specialization**
 
                Some entry types may have other information available in
                sysfs.  Not all types are specialized.
 
-               --- Type 15 - System Event Log ---
+               **Type 15 - System Event Log**
 
                This entry allows the firmware to export a log of
                events the system has taken.  This information is
                typically backed by nvram, but the implementation
                details are abstracted by this table.  This entry's data
-               is exported in the directory:
+               is exported in the directory::
 
-               /sys/firmware/dmi/entries/15-0/system_event_log
+                 /sys/firmware/dmi/entries/15-0/system_event_log
 
                and has the following attributes (documented in the
                SMBIOS / DMI specification under "System Event Log (Type 15)":
 
-               area_length
-               header_start_offset
-               data_start_offset
-               access_method
-               status
-               change_token
-               access_method_address
-               header_format
-               per_log_type_descriptor_length
-               type_descriptors_supported_count
+               area_length
+               header_start_offset
+               data_start_offset
+               access_method
+               status
+               change_token
+               access_method_address
+               header_format
+               per_log_type_descriptor_length
+               type_descriptors_supported_count
 
                As well, the kernel exports the binary attribute:
 
-               raw_event_log   : The raw binary bits of the event log
+               =============     ====================================
+               raw_event_log     The raw binary bits of the event log
                                  as described by the DMI entry.
+               =============     ====================================
index 6e431d1a4e7976343adb8946d2982e40c7120080..31b57676d4ad5420ef61b62ce5a2bc1775258d30 100644 (file)
@@ -35,10 +35,13 @@ What:               /sys/firmware/efi/esrt/entries/entry$N/fw_type
 Date:          February 2015
 Contact:       Peter Jones <pjones@redhat.com>
 Description:   What kind of firmware entry this is:
-               0 - Unknown
-               1 - System Firmware
-               2 - Device Firmware
-               3 - UEFI Driver
+
+               ==  ===============
+               0   Unknown
+               1   System Firmware
+               2   Device Firmware
+               3   UEFI Driver
+               ==  ===============
 
 What:          /sys/firmware/efi/esrt/entries/entry$N/fw_class
 Date:          February 2015
@@ -71,11 +74,14 @@ Date:               February 2015
 Contact:       Peter Jones <pjones@redhat.com>
 Description:   The result of the last firmware update attempt for the
                firmware resource entry.
-               0 - Success
-               1 - Insufficient resources
-               2 - Incorrect version
-               3 - Invalid format
-               4 - Authentication error
-               5 - AC power event
-               6 - Battery power event
+
+               ==  ======================
+               0   Success
+               1   Insufficient resources
+               2   Incorrect version
+               3   Invalid format
+               4   Authentication error
+               5   AC power event
+               6   Battery power event
+               ==  ======================
 
index c61b9b348e9996da13767058d843974052680a83..9c4d581be396c4ac000236933c75aef7de3aed75 100644 (file)
@@ -14,7 +14,7 @@ Description:  Switching efi runtime services to virtual mode requires
                /sys/firmware/efi/runtime-map/ is the directory the kernel
                exports that information in.
 
-               subdirectories are named with the number of the memory range:
+               subdirectories are named with the number of the memory range::
 
                        /sys/firmware/efi/runtime-map/0
                        /sys/firmware/efi/runtime-map/1
@@ -24,11 +24,13 @@ Description:        Switching efi runtime services to virtual mode requires
 
                Each subdirectory contains five files:
 
-               attribute : The attributes of the memory range.
-               num_pages : The size of the memory range in pages.
-               phys_addr : The physical address of the memory range.
-               type      : The type of the memory range.
-               virt_addr : The virtual address of the memory range.
+               =========   =========================================
+               attribute   The attributes of the memory range.
+               num_pages   The size of the memory range in pages.
+               phys_addr   The physical address of the memory range.
+               type        The type of the memory range.
+               virt_addr   The virtual address of the memory range.
+               =========   =========================================
 
                Above values are all hexadecimal numbers with the '0x' prefix.
 Users:         Kexec
index 0faa0aaf4b6af88e1f4668aca0e147e26d9a438b..7a558354c1ee0182d354fe3c490d0c571abf96cb 100644 (file)
@@ -20,7 +20,7 @@ Description:
 
                        This directory has the same layout (and
                        underlying implementation as /sys/firmware/efi/vars.
-                       See Documentation/ABI/*/sysfs-firmware-efi-vars
+                       See `Documentation/ABI/*/sysfs-firmware-efi-vars`
                        for more information on how to interact with
                        this structure.
 
index eca0d65087dc4239352add5f2167a85ae7a179e8..1f6f4d3a32c06f8f61775a73ec6b08dec8c458a2 100644 (file)
@@ -20,7 +20,7 @@ Description:
                the raw memory map to userspace.
 
                The structure is as follows: Under /sys/firmware/memmap there
-               are subdirectories with the number of the entry as their name:
+               are subdirectories with the number of the entry as their name::
 
                        /sys/firmware/memmap/0
                        /sys/firmware/memmap/1
@@ -34,14 +34,16 @@ Description:
 
                Each directory contains three files:
 
-               start   : The start address (as hexadecimal number with the
+               ========  =====================================================
+               start     The start address (as hexadecimal number with the
                          '0x' prefix).
-               end     : The end address, inclusive (regardless whether the
+               end       The end address, inclusive (regardless whether the
                          firmware provides inclusive or exclusive ranges).
-               type    : Type of the entry as string. See below for a list of
+               type      Type of the entry as string. See below for a list of
                          valid types.
+               ========  =====================================================
 
-               So, for example:
+               So, for example::
 
                        /sys/firmware/memmap/0/start
                        /sys/firmware/memmap/0/end
@@ -57,9 +59,8 @@ Description:
                  - reserved
 
                Following shell snippet can be used to display that memory
-               map in a human-readable format:
+               map in a human-readable format::
 
-               -------------------- 8< ----------------------------------------
                  #!/bin/bash
                  cd /sys/firmware/memmap
                  for dir in * ; do
@@ -68,4 +69,3 @@ Description:
                      type=$(cat $dir/type)
                      printf "%016x-%016x (%s)\n" $start $[ $end +1] "$type"
                  done
-               -------------------- >8 ----------------------------------------
index 011dda4f8e8a062d257c024db3ed0b948a46a768..ee0d6dbc810e5fc5604bd87e235ef74a3c3afce7 100644 (file)
@@ -15,7 +15,7 @@ Description:
                to the fw_cfg device can be found in "docs/specs/fw_cfg.txt"
                in the QEMU source tree.
 
-               === SysFS fw_cfg Interface ===
+               **SysFS fw_cfg Interface**
 
                The fw_cfg sysfs interface described in this document is only
                intended to display discoverable blobs (i.e., those registered
@@ -31,7 +31,7 @@ Description:
 
                        /sys/firmware/qemu_fw_cfg/rev
 
-               --- Discoverable fw_cfg blobs by selector key ---
+               **Discoverable fw_cfg blobs by selector key**
 
                All discoverable blobs listed in the fw_cfg file directory are
                displayed as entries named after their unique selector key
@@ -45,24 +45,26 @@ Description:
                Each such fw_cfg sysfs entry has the following values exported
                as attributes:
 
-               name    : The 56-byte nul-terminated ASCII string used as the
+               ====      ====================================================
+               name      The 56-byte nul-terminated ASCII string used as the
                          blob's 'file name' in the fw_cfg directory.
-               size    : The length of the blob, as given in the fw_cfg
+               size      The length of the blob, as given in the fw_cfg
                          directory.
-               key     : The value of the blob's selector key as given in the
+               key       The value of the blob's selector key as given in the
                          fw_cfg directory. This value is the same as used in
                          the parent directory name.
-               raw     : The raw bytes of the blob, obtained by selecting the
+               raw       The raw bytes of the blob, obtained by selecting the
                          entry via the control register, and reading a number
                          of bytes equal to the blob size from the data
                          register.
+               ====      ====================================================
 
-               --- Listing fw_cfg blobs by file name ---
+               **Listing fw_cfg blobs by file name**
 
                While the fw_cfg device does not impose any specific naming
                convention on the blobs registered in the file directory,
                QEMU developers have traditionally used path name semantics
-               to give each blob a descriptive name. For example:
+               to give each blob a descriptive name. For example::
 
                        "bootorder"
                        "genroms/kvmvapic.bin"
@@ -81,7 +83,7 @@ Description:
                of directories matching the path name components of fw_cfg
                blob names, ending in symlinks to the by_key entry for each
                "basename", as illustrated below (assume current directory is
-               /sys/firmware):
+               /sys/firmware)::
 
                    qemu_fw_cfg/by_name/bootorder -> ../by_key/38
                    qemu_fw_cfg/by_name/etc/e820 -> ../../by_key/35
index 4be7d44aeacf88fc7ad77f707684ae5aee5dc161..5210e0f06ddbe9982420cdf0da7eb57907630184 100644 (file)
@@ -9,7 +9,7 @@ Description:
                http://simplefirmware.org/documentation
 
                While the tables are used by the kernel, user-space
-               can observe them this way:
+               can observe them this way::
 
-               # cd /sys/firmware/sfi/tables
-               # cat $TABLENAME > $TABLENAME.bin
+                 # cd /sys/firmware/sfi/tables
+                 # cat $TABLENAME > $TABLENAME.bin
index 4573fd4b7876cfd1c3d80281f8b4101df35ba1f4..66800baab0965e8438d37a5bd0375b2d45d0c20c 100644 (file)
@@ -5,7 +5,7 @@ Description:
                The /sys/firmware/sgi_uv directory contains information
                about the SGI UV platform.
 
-               Under that directory are a number of files:
+               Under that directory are a number of files::
 
                        partition_id
                        coherence_id
@@ -14,7 +14,7 @@ Description:
                SGI UV systems can be partitioned into multiple physical
                machines, which each partition running a unique copy
                of the operating system.  Each partition will have a unique
-               partition id.  To display the partition id, use the command:
+               partition id.  To display the partition id, use the command::
 
                        cat /sys/firmware/sgi_uv/partition_id
 
@@ -22,6 +22,6 @@ Description:
                A partitioned SGI UV system can have one or more coherence
                domain.  The coherence id indicates which coherence domain
                this partition is in.  To display the coherence id, use the
-               command:
+               command::
 
                        cat /sys/firmware/sgi_uv/coherence_id
index 15595fab88d18469030d5f7f2d500cca44afdbf1..b8631f5a29c4c5779347333098ac14252293dbe3 100644 (file)
@@ -2,21 +2,21 @@ What:         /sys/firmware/turris-mox-rwtm/board_version
 Date:          August 2019
 KernelVersion: 5.4
 Contact:       Marek Behún <marek.behun@nic.cz>
-Description:   (R) Board version burned into eFuses of this Turris Mox board.
+Description:   (Read) Board version burned into eFuses of this Turris Mox board.
                Format: %i
 
 What:          /sys/firmware/turris-mox-rwtm/mac_address*
 Date:          August 2019
 KernelVersion: 5.4
 Contact:       Marek Behún <marek.behun@nic.cz>
-Description:   (R) MAC addresses burned into eFuses of this Turris Mox board.
+Description:   (Read) MAC addresses burned into eFuses of this Turris Mox board.
                Format: %pM
 
 What:          /sys/firmware/turris-mox-rwtm/pubkey
 Date:          August 2019
 KernelVersion: 5.4
 Contact:       Marek Behún <marek.behun@nic.cz>
-Description:   (R) ECDSA public key (in pubkey hex compressed form) computed
+Description:   (Read) ECDSA public key (in pubkey hex compressed form) computed
                as pair to the ECDSA private key burned into eFuses of this
                Turris Mox Board.
                Format: string
@@ -25,7 +25,7 @@ What:         /sys/firmware/turris-mox-rwtm/ram_size
 Date:          August 2019
 KernelVersion: 5.4
 Contact:       Marek Behún <marek.behun@nic.cz>
-Description:   (R) RAM size in MiB of this Turris Mox board as was detected
+Description:   (Read) RAM size in MiB of this Turris Mox board as was detected
                during manufacturing and burned into eFuses. Can be 512 or 1024.
                Format: %i
 
@@ -33,5 +33,5 @@ What:         /sys/firmware/turris-mox-rwtm/serial_number
 Date:          August 2019
 KernelVersion: 5.4
 Contact:       Marek Behún <marek.behun@nic.cz>
-Description:   (R) Serial number burned into eFuses of this Turris Mox device.
+Description:   (Read) Serial number burned into eFuses of this Turris Mox device.
                Format: %016X
index 78604db56279966246980c2070657bf32667a0cf..99e3d92f8299c9a2ff390da172655f38e9bfc5e3 100644 (file)
@@ -45,8 +45,8 @@ Description:
                parameter will have their blocks allocated out of a
                block group specific preallocation pool, so that small
                files are packed closely together.  Each large file
-                will have its blocks allocated out of its own unique
-                preallocation pool.
+               will have its blocks allocated out of its own unique
+               preallocation pool.
 
 What:          /sys/fs/ext4/<disk>/inode_readahead_blks
 Date:          March 2008
index 834d0becae6ddf9a74438b6318764f82789815eb..67b3ed8e8c2f7305592b09ccb347694e81a9d9f4 100644 (file)
@@ -20,10 +20,13 @@ What:               /sys/fs/f2fs/<disk>/gc_idle
 Date:          July 2013
 Contact:       "Namjae Jeon" <namjae.jeon@samsung.com>
 Description:   Controls the victim selection policy for garbage collection.
-               Setting gc_idle = 0(default) will disable this option. Setting
-               gc_idle = 1 will select the Cost Benefit approach & setting
-               gc_idle = 2 will select the greedy approach & setting
-               gc_idle = 3 will select the age-threshold based approach.
+               Setting gc_idle = 0(default) will disable this option. Setting:
+
+               ===========  ===============================================
+               gc_idle = 1  will select the Cost Benefit approach & setting
+               gc_idle = 2  will select the greedy approach & setting
+               gc_idle = 3  will select the age-threshold based approach.
+               ===========  ===============================================
 
 What:          /sys/fs/f2fs/<disk>/reclaim_segments
 Date:          October 2013
@@ -46,10 +49,17 @@ Date:               November 2013
 Contact:       "Jaegeuk Kim" <jaegeuk.kim@samsung.com>
 Description:   Controls the in-place-update policy.
                updates in f2fs. User can set:
-               0x01: F2FS_IPU_FORCE, 0x02: F2FS_IPU_SSR,
-               0x04: F2FS_IPU_UTIL,  0x08: F2FS_IPU_SSR_UTIL,
-               0x10: F2FS_IPU_FSYNC, 0x20: F2FS_IPU_ASYNC,
-               0x40: F2FS_IPU_NOCACHE.
+
+               ====  =================
+               0x01  F2FS_IPU_FORCE
+               0x02  F2FS_IPU_SSR
+               0x04  F2FS_IPU_UTIL
+               0x08  F2FS_IPU_SSR_UTIL
+               0x10  F2FS_IPU_FSYNC
+               0x20  F2FS_IPU_ASYNC,
+               0x40  F2FS_IPU_NOCACHE
+               ====  =================
+
                Refer segment.h for details.
 
 What:          /sys/fs/f2fs/<disk>/min_ipu_util
@@ -332,18 +342,28 @@ Date:             April 2020
 Contact:       "Jaegeuk Kim" <jaegeuk@kernel.org>
 Description:   Give a way to attach REQ_META|FUA to data writes
                given temperature-based bits. Now the bits indicate:
-               *      REQ_META     |      REQ_FUA      |
-               *    5 |    4 |   3 |    2 |    1 |   0 |
-               * Cold | Warm | Hot | Cold | Warm | Hot |
+
+               +-------------------+-------------------+
+               |      REQ_META     |      REQ_FUA      |
+               +------+------+-----+------+------+-----+
+               |    5 |    4 |   3 |    2 |    1 |   0 |
+               +------+------+-----+------+------+-----+
+               | Cold | Warm | Hot | Cold | Warm | Hot |
+               +------+------+-----+------+------+-----+
 
 What:          /sys/fs/f2fs/<disk>/node_io_flag
 Date:          June 2020
 Contact:       "Jaegeuk Kim" <jaegeuk@kernel.org>
 Description:   Give a way to attach REQ_META|FUA to node writes
                given temperature-based bits. Now the bits indicate:
-               *      REQ_META     |      REQ_FUA      |
-               *    5 |    4 |   3 |    2 |    1 |   0 |
-               * Cold | Warm | Hot | Cold | Warm | Hot |
+
+               +-------------------+-------------------+
+               |      REQ_META     |      REQ_FUA      |
+               +------+------+-----+------+------+-----+
+               |    5 |    4 |   3 |    2 |    1 |   0 |
+               +------+------+-----+------+------+-----+
+               | Cold | Warm | Hot | Cold | Warm | Hot |
+               +------+------+-----+------+------+-----+
 
 What:          /sys/fs/f2fs/<disk>/iostat_period_ms
 Date:          April 2020
index 53b7b2ea75154b86e80fbfcf086eca307a32cee9..4dbe0c49b393e5e476c8046d987d56b0a8324de1 100644 (file)
@@ -15,14 +15,17 @@ KernelVersion:      4.3
 Contact:       Boris Ostrovsky <boris.ostrovsky@oracle.com>
 Description:   If running under Xen:
                Describes mode that Xen's performance-monitoring unit (PMU)
-               uses. Accepted values are
-                       "off"  -- PMU is disabled
-                       "self" -- The guest can profile itself
-                       "hv"   -- The guest can profile itself and, if it is
+               uses. Accepted values are:
+
+                       ======    ============================================
+                       "off"     PMU is disabled
+                       "self"    The guest can profile itself
+                       "hv"      The guest can profile itself and, if it is
                                  privileged (e.g. dom0), the hypervisor
-                       "all" --  The guest can profile itself, the hypervisor
+                       "all"     The guest can profile itself, the hypervisor
                                  and all other guests. Only available to
                                  privileged guests.
+                       ======    ============================================
 
 What:           /sys/hypervisor/pmu/pmu_features
 Date:           August 2015
index eca38ce2852d3ab27cba5559aa6db655ba0301bf..7f9bda453c4d1a4bfdcf57031127fa38be610799 100644 (file)
@@ -23,16 +23,17 @@ Description:        The /sys/kernel/boot_params directory contains two
                representation of setup_data type. "data" file is the binary
                representation of setup_data payload.
 
-               The whole boot_params directory structure is like below:
-               /sys/kernel/boot_params
-               |__ data
-               |__ setup_data
-               |   |__ 0
-               |   |   |__ data
-               |   |   |__ type
-               |   |__ 1
-               |       |__ data
-               |       |__ type
-               |__ version
+               The whole boot_params directory structure is like below::
+
+                 /sys/kernel/boot_params
+                 |__ data
+                 |__ setup_data
+                 |   |__ 0
+                 |   |   |__ data
+                 |   |   |__ type
+                 |   |__ 1
+                 |       |__ data
+                 |       |__ type
+                 |__ version
 
 Users:         Kexec
index fdaa2162fae1528529b7045c6e9184ae9620bc01..294387e2c7fb58901cdb0bac3e4ddc75298d7d28 100644 (file)
@@ -7,9 +7,11 @@ Description:
                of the hugepages supported by the kernel/CPU combination.
 
                Under these directories are a number of files:
-                       nr_hugepages
-                       nr_overcommit_hugepages
-                       free_hugepages
-                       surplus_hugepages
-                       resv_hugepages
+
+                       - nr_hugepages
+                       - nr_overcommit_hugepages
+                       - free_hugepages
+                       - surplus_hugepages
+                       - resv_hugepages
+
                See Documentation/admin-guide/mm/hugetlbpage.rst for details.
index dfc13244cda3bb567591fbd6cbcfaee6905731c6..1c9bed5595f5d2b5273fc399b00439d828c4d06b 100644 (file)
@@ -34,8 +34,9 @@ Description:  Kernel Samepage Merging daemon sysfs interface
                in a tree.
 
                run: write 0 to disable ksm, read 0 while ksm is disabled.
-                       write 1 to run ksm, read 1 while ksm is running.
-                       write 2 to disable ksm and unmerge all its pages.
+
+                       - write 1 to run ksm, read 1 while ksm is running.
+                       - write 2 to disable ksm and unmerge all its pages.
 
                sleep_millisecs: how many milliseconds ksm should sleep between
                scans.
index ed35833ad7f05592c53fa615bcf72126de404821..c9f12baf8baac812456058549536f2b717627dd7 100644 (file)
@@ -346,6 +346,7 @@ Description:
                number of objects per slab.  If a slab cannot be allocated
                because of fragmentation, SLUB will retry with the minimum order
                possible depending on its characteristics.
+
                When debug_guardpage_minorder=N (N > 0) parameter is specified
                (see Documentation/admin-guide/kernel-parameters.rst), the minimum possible
                order is used and this sysfs entry can not be used to change
@@ -361,6 +362,7 @@ Description:
                new slab has not been possible at the cache's order and instead
                fallen back to its minimum possible order.  It can be written to
                clear the current count.
+
                Available when CONFIG_SLUB_STATS is enabled.
 
 What:          /sys/kernel/slab/cache/partial
@@ -410,6 +412,7 @@ Description:
                slab from a remote node as opposed to allocating a new slab on
                the local node.  This reduces the amount of wasted memory over
                the entire system but can be expensive.
+
                Available when CONFIG_NUMA is enabled.
 
 What:          /sys/kernel/slab/cache/sanity_checks
index 0aac02e7fb0e22e532dca3aca30c6fe7472bef95..353c0db5bc1f584a09176772d91daf61639084d7 100644 (file)
@@ -17,14 +17,15 @@ KernelVersion:      3.1
 Contact:       Kirill Smelkov <kirr@mns.spb.ru>
 Description:   Maximum time allowed for periodic transfers per microframe (μs)
 
-               [ USB 2.0 sets maximum allowed time for periodic transfers per
+               Note:
+                 USB 2.0 sets maximum allowed time for periodic transfers per
                  microframe to be 80%, that is 100 microseconds out of 125
                  microseconds (full microframe).
 
                  However there are cases, when 80% max isochronous bandwidth is
                  too limiting. For example two video streams could require 110
                  microseconds of isochronous bandwidth per microframe to work
-                 together. ]
+                 together. 
 
                Through this setting it is possible to raise the limit so that
                the host controller would allow allocating more than 100
@@ -45,8 +46,10 @@ Date:                Jan 2012
 KernelVersion:»·3.3
 Contact:       Kay Sievers <kay.sievers@vrfy.org>
 Description:   Module taint flags:
-                       P - proprietary module
-                       O - out-of-tree module
-                       F - force-loaded module
-                       C - staging driver module
-                       E - unsigned module
+                       ==  =====================
+                       P   proprietary module
+                       O   out-of-tree module
+                       F   force-loaded module
+                       C   staging driver module
+                       E   unsigned module
+                       ==  =====================
index 8b0e8205a6a2451331b4c38d4b532742ee2b83ac..c78d358dbdbede7a7088e526f0abf3b77ae0f872 100644 (file)
@@ -4,13 +4,16 @@ KernelVersion:        2.6.20
 Contact:       "Corentin Chary" <corentincj@iksaif.net>
 Description:
                This file allows display switching. The value
-               is composed by 4 bits and defined as follow:
-               4321
-               |||`- LCD
-               ||`-- CRT
-               |`--- TV
-               `---- DVI
-               Ex: - 0 (0000b) means no display
+               is composed by 4 bits and defined as follow::
+
+                 4321
+                 |||`- LCD
+                 ||`-- CRT
+                 |`--- TV
+                 `---- DVI
+
+               Ex:
+                   - 0 (0000b) means no display
                    - 3 (0011b) CRT+LCD.
 
 What:          /sys/devices/platform/asus_laptop/gps
@@ -28,8 +31,10 @@ Contact:     "Corentin Chary" <corentincj@iksaif.net>
 Description:
                Some models like the W1N have a LED display that can be
                used to display several items of information.
-               To control the LED display, use the following :
+               To control the LED display, use the following::
+
                    echo 0x0T000DDD > /sys/devices/platform/asus_laptop/
+
                where T control the 3 letters display, and DDD the 3 digits display.
                The DDD table can be found in Documentation/admin-guide/laptops/asus-laptop.rst
 
index 1efac0ddb417e0b04ffeeb11573eca9488147f06..04885738cf156987afd64c12b035d1b7736cf772 100644 (file)
@@ -5,6 +5,7 @@ Contact:        "Corentin Chary" <corentincj@iksaif.net>
 Description:
                Change CPU clock configuration (write-only).
                There are three available clock configuration:
+
                    * 0 -> Super Performance Mode
                    * 1 -> High Performance Mode
                    * 2 -> Power Saving Mode
index 4cc6a865ae662f6252057aff396d42d837a566b6..b146be74b8e0d225a8c031b8cc67a73c8524e116 100644 (file)
@@ -18,8 +18,10 @@ Description:
                In order to use an extended can_id add the
                CAN_EFF_FLAG (0x80000000U) to the can_id. Example:
 
-               - standard id 0x7ff:
-               echo 0x7ff      > /sys/class/net/can0/mb0_id
+               - standard id 0x7ff::
 
-               - extended id 0x1fffffff:
-               echo 0x9fffffff > /sys/class/net/can0/mb0_id
+                   echo 0x7ff      > /sys/class/net/can0/mb0_id
+
+               - extended id 0x1fffffff::
+
+                   echo 0x9fffffff > /sys/class/net/can0/mb0_id
index 9b917c7453dee769d17f90c593861255c2ef6daf..82bcfe9df66eefc41334dbd73f6294e059eeae2e 100644 (file)
@@ -34,9 +34,12 @@ Description:
                this file. To disable a trigger, write its name preceded
                by '-' instead.
 
-               For example, to enable the keyboard as trigger run:
+               For example, to enable the keyboard as trigger run::
+
                    echo +keyboard > /sys/class/leds/dell::kbd_backlight/start_triggers
-               To disable it:
+
+               To disable it::
+
                    echo -keyboard > /sys/class/leds/dell::kbd_backlight/start_triggers
 
                Note that not all the available triggers can be configured.
@@ -57,7 +60,8 @@ Description:
                with any the above units. If no unit is specified, the value
                is assumed to be expressed in seconds.
 
-               For example, to set the timeout to 10 minutes run:
+               For example, to set the timeout to 10 minutes run::
+
                    echo 10m > /sys/class/leds/dell::kbd_backlight/stop_timeout
 
                Note that when this file is read, the returned value might be
index 205d3b6361e0db9c3c653f56928c6d8609ee000d..e6e0f7f834a7434aa3844c03e65ffbdbd06efb16 100644 (file)
@@ -13,8 +13,8 @@ Description:
                For example the token ID "5" would be available
                as the following attributes:
 
-               0005_location
-               0005_value
+               0005_location
+               0005_value
 
                Tokens will vary from machine to machine, and
                only tokens available on that machine will be
index 3683cb1cdc3de80141134b1563415e590bfce646..d6ab34e81b9b3b6146f7144222571ad176450f95 100644 (file)
@@ -113,8 +113,11 @@ KernelVersion:     5.5
 Contact:       Wu Hao <hao.wu@intel.com>
 Description:   Read-Only. Read this file to get the name of hwmon device, it
                supports values:
-                   'dfl_fme_thermal' - thermal hwmon device name
-                   'dfl_fme_power'   - power hwmon device name
+
+               =================  =========================
+               'dfl_fme_thermal'  thermal hwmon device name
+               'dfl_fme_power'    power hwmon device name
+               =================  =========================
 
 What:          /sys/bus/platform/devices/dfl-fme.0/hwmon/hwmonX/temp1_input
 Date:          October 2019
@@ -169,8 +172,11 @@ KernelVersion:     5.5
 Contact:       Wu Hao <hao.wu@intel.com>
 Description:   Read-Only. Read this file to get the policy of hardware threshold1
                (see 'temp1_max'). It only supports two values (policies):
-                   0 - AP2 state (90% throttling)
-                   1 - AP1 state (50% throttling)
+
+               ==  ==========================
+                0  AP2 state (90% throttling)
+                1  AP1 state (50% throttling)
+               ==  ==========================
 
 What:          /sys/bus/platform/devices/dfl-fme.0/hwmon/hwmonX/power1_input
 Date:          October 2019
index 2cbc660d163b25e3e944b768b63604567984ad78..141834342a4dd01c0f559c2d071e8f59cbdbe132 100644 (file)
@@ -27,12 +27,15 @@ KernelVersion:      v4.10
 Contact:       linux-acpi@vger.kernel.org
 Description:
                (RO) Display the platform power source
+
+               ========= ============================
                bits[3:0] Current power source
-                       0x00 = DC
-                       0x01 = AC
-                       0x02 = USB
-                       0x03 = Wireless Charger
+                         - 0x00 = DC
+                         - 0x01 = AC
+                         - 0x02 = USB
+                         - 0x03 = Wireless Charger
                bits[7:4] Power source sequence number
+               ========= ============================
 
 What:          /sys/bus/platform/devices/INT3407:00/dptf_power/battery_steady_power
 Date:          Jul, 2016
index 5b026c69587ac881efbcdf3fff697722f9df2301..70dbe0733cf622e7c36086329802e488e2b128bc 100644 (file)
@@ -4,9 +4,11 @@ KernelVersion: 2.6.26
 Contact:       "Corentin Chary" <corentincj@iksaif.net>
 Description:
                This file allows display switching.
+
                - 1 = LCD
                - 2 = CRT
                - 3 = LCD+CRT
+
                If you run X11, you should use xrandr instead.
 
 What:          /sys/devices/platform/eeepc/camera
@@ -30,16 +32,20 @@ Contact:    "Corentin Chary" <corentincj@iksaif.net>
 Description:
                Change CPU clock configuration.
                On the Eee PC 1000H there are three available clock configuration:
+
                    * 0 -> Super Performance Mode
                    * 1 -> High Performance Mode
                    * 2 -> Power Saving Mode
+
                On Eee PC 701 there is only 2 available clock configurations.
                Available configuration are listed in available_cpufv file.
                Reading this file will show the raw hexadecimal value which
-               is defined as follow:
-               | 8 bit | 8 bit |
-                   |       `---- Current mode
-                   `------------ Availables modes
+               is defined as follow::
+
+                 | 8 bit | 8 bit |
+                     |       `---- Current mode
+                     `------------ Availables modes
+
                For example, 0x301 means: mode 1 selected, 3 available modes.
 
 What:          /sys/devices/platform/eeepc/available_cpufv
index c394b808be197221e9e7958a0e17c00a5b006efc..b6a138b50d994a326e6055bd5f70c8cb207cf6df 100644 (file)
@@ -5,9 +5,9 @@ Contact:        Wolfram Sang <wsa+renesas@sang-engineering.com>
 Description:
                Reading the file will give you a list of masters which can be
                selected for a demultiplexed bus. The format is
-               "<index>:<name>". Example from a Renesas Lager board:
+               "<index>:<name>". Example from a Renesas Lager board::
 
-               0:/i2c@e6500000 1:/i2c@e6508000
+                 0:/i2c@e6500000 1:/i2c@e6508000
 
 What:          /sys/devices/platform/<i2c-demux-name>/current_master
 Date:          January 2016
index 1b31be3f996a40df66299e4715ee4eb984ec12e1..fd2ac02bc5bd8b6fae8314a4598304f3a8fe7bd5 100644 (file)
@@ -12,6 +12,7 @@ Contact:      "Maxim Mikityanskiy <maxtram95@gmail.com>"
 Description:
                Change fan mode
                There are four available modes:
+
                        * 0 -> Super Silent Mode
                        * 1 -> Standard Mode
                        * 2 -> Dust Cleaning
@@ -32,9 +33,11 @@ KernelVersion:       4.18
 Contact:       "Oleg Keri <ezhi99@gmail.com>"
 Description:
                Control fn-lock mode.
+
                        * 1 -> Switched On
                        * 0 -> Switched Off
 
-               For example:
-               # echo "0" >    \
-               /sys/bus/pci/devices/0000:00:1f.0/PNP0C09:00/VPC2004:00/fn_lock
+               For example::
+
+                 # echo "0" >  \
+                 /sys/bus/pci/devices/0000:00:1f.0/PNP0C09:00/VPC2004:00/fn_lock
index 5aa618987cad6dafb7fdabfd5699124862115aa5..02ae1e9bbfc8d0edeb3c16efd445d69df9f6f2cb 100644 (file)
@@ -8,5 +8,6 @@ Description:
                of 0 and userspace can signal SBL to update firmware,
                on next reboot, by writing a value of 1.
                There are two available states:
+
                    * 0 -> Skip firmware update while rebooting
                    * 1 -> Attempt firmware update on next reboot
index 8af65059d51907de713066d243e73848346bf0e0..e19144fd5d8694db7823d3e2952026199ed9381d 100644 (file)
@@ -7,5 +7,6 @@ Description:
                Thunderbolt controllers to turn on or off when no
                devices are connected (write-only)
                There are two available states:
+
                    * 0 -> Force power disabled
                    * 1 -> Force power enabled
index c1653271872a9ff7d38306558c0f9c2e78fb6abf..a7f81de68046167220459f4e0eef4a53defec572 100644 (file)
@@ -5,6 +5,7 @@ Contact:        "Pavan Savoy" <pavan_savoy@ti.com>
 Description:
                Name of the UART device at which the WL128x chip
                is connected. example: "/dev/ttyS0".
+
                The device name flows down to architecture specific board
                initialization file from the SFI/ATAGS bootloader
                firmware. The name exposed is read from the user-space
index 401d202f478b230014ce7a6ee247cbea76dc45da..e79ca22e2f459b4af1ac7d9e8ff52641c56cfca0 100644 (file)
@@ -5,10 +5,13 @@ Contact:      "Liming Sun <lsun@mellanox.com>"
 Description:
                The Life-cycle state of the SoC, which could be one of the
                following values.
-                 Production - Production state and can be updated to secure
-                 GA Secured - Secure chip and not able to change state
-                 GA Non-Secured - Non-Secure chip and not able to change state
-                 RMA - Return Merchandise Authorization
+
+               ==============  =============================================
+               Production      Production state and can be updated to secure
+               GA Secured      Secure chip and not able to change state
+               GA Non-Secured  Non-Secure chip and not able to change state
+               RMA             Return Merchandise Authorization
+               ==============  =============================================
 
 What:          /sys/bus/platform/devices/MLNXBF04:00/post_reset_wdog
 Date:          Oct 2019
@@ -25,10 +28,13 @@ KernelVersion:      5.5
 Contact:       "Liming Sun <lsun@mellanox.com>"
 Description:
                The source of the boot stream for the next reset. It could be
-               one of the following values.
-                 external - boot from external source (USB or PCIe)
-                 emmc - boot from the onchip eMMC
-                 emmc_legacy - boot from the onchip eMMC in legacy (slow) mode
+               one of the following values:
+
+               ===========  ===============================================
+               external     boot from external source (USB or PCIe)
+               emmc         boot from the onchip eMMC
+               emmc_legacy  boot from the onchip eMMC in legacy (slow) mode
+               ===========  ===============================================
 
 What:          /sys/bus/platform/devices/MLNXBF04:00/second_reset_action
 Date:          Oct 2019
@@ -38,11 +44,14 @@ Description:
                Update the source of the boot stream after next reset. It could
                be one of the following values and will be applied after next
                reset.
-                 external - boot from external source (USB or PCIe)
-                 emmc - boot from the onchip eMMC
-                 emmc_legacy - boot from the onchip eMMC in legacy (slow) mode
-                 swap_emmc - swap the primary / secondary boot partition
-                 none - cancel the action
+
+               ===========  ===============================================
+               external     boot from external source (USB or PCIe)
+               emmc         boot from the onchip eMMC
+               emmc_legacy  boot from the onchip eMMC in legacy (slow) mode
+               swap_emmc    swap the primary / secondary boot partition
+               none         cancel the action
+               ===========  ===============================================
 
 What:          /sys/bus/platform/devices/MLNXBF04:00/secure_boot_fuse_state
 Date:          Oct 2019
@@ -50,9 +59,12 @@ KernelVersion:       5.5
 Contact:       "Liming Sun <lsun@mellanox.com>"
 Description:
                The state of eFuse versions with the following values.
-                 InUse - burnt, valid and currently in use
-                 Used - burnt and valid
-                 Free - not burnt and free to use
-                 Skipped - not burnt but not free (skipped)
-                 Wasted - burnt and invalid
-                 Invalid - not burnt but marked as valid (error state).
+
+               =======  ===============================================
+               InUse    burnt, valid and currently in use
+               Used     burnt and valid
+               Free     not burnt and free to use
+               Skipped  not burnt but not free (skipped)
+               Wasted   burnt and invalid
+               Invalid  not burnt but marked as valid (error state).
+               =======  ===============================================
index 6212697bbf6f5775c3d2614b1817b2cb138a0d48..bc510ccc37a7bf0d446d027b926cd077db8ab850 100644 (file)
@@ -7,9 +7,11 @@ Description:
                The file can show/change the phy mode for role swap of usb.
 
                Write the following strings to change the mode:
-                "host" - switching mode from peripheral to host.
-                "peripheral" - switching mode from host to peripheral.
+
+                - "host" - switching mode from peripheral to host.
+                - "peripheral" - switching mode from host to peripheral.
 
                Read the file, then it shows the following strings:
-                "host" - The mode is host now.
-                "peripheral" - The mode is peripheral now.
+
+                - "host" - The mode is host now.
+                - "peripheral" - The mode is peripheral now.
index 5621c15d5dc0c30756f77971e44919211834a458..8af5b9c3fabbf07bb87cd5e44607cb0680c60f28 100644 (file)
@@ -7,9 +7,11 @@ Description:
                The file can show/change the drd mode of usb.
 
                Write the following string to change the mode:
-                "host" - switching mode from peripheral to host.
-                "peripheral" - switching mode from host to peripheral.
+
+               - "host" - switching mode from peripheral to host.
+               - "peripheral" - switching mode from host to peripheral.
 
                Read the file, then it shows the following strings:
-                "host" - The mode is host now.
-                "peripheral" - The mode is peripheral now.
+               
+               - "host" - The mode is host now.
+               - "peripheral" - The mode is peripheral now.
index 0d07c0395660e68b0754923456550d31e8dbabdb..d5f6e21f0e4280fbaaeffeb4d5e8aa667894674d 100644 (file)
@@ -5,13 +5,22 @@ Contact:      "Sebastien Guiriec" <sebastien.guiriec@intel.com>
 Description:
                LPE Firmware version for SST driver on all atom
                plaforms (BYT/CHT/Merrifield/BSW).
-               If the FW has never been loaded it will display:
+               If the FW has never been loaded it will display::
+
                        "FW not yet loaded"
-               If FW has been loaded it will display:
+
+               If FW has been loaded it will display::
+
                        "v01.aa.bb.cc"
+
                aa: Major version is reflecting SoC version:
+
+                       === =============
                        0d: BYT FW
                        0b: BSW FW
                        07: Merrifield FW
+                       === =============
+
                bb: Minor version
+
                cc: Build version
index 81fcfb45491382ea315484bc8feffbcf5f9b7138..53622d3ba27c64a3e3a0526f46684436a963eb3a 100644 (file)
@@ -16,10 +16,13 @@ Contact:    Krzysztof Opasiak <k.opasiak@samsung.com>
 Description:
                Current status of the device.
                Allowed values:
-               1 - Device is available and can be exported
-               2 - Device is currently exported
-               3 - Fatal error occurred during communication
-                 with peer
+
+               ==  ==========================================
+               1   Device is available and can be exported
+               2   Device is currently exported
+               3   Fatal error occurred during communication
+                   with peer
+               ==  ==========================================
 
 What:          /sys/devices/platform/usbip-vudc.%d/usbip_sockfd
 Date:          April 2016
index 5f60b184a5a5e1fb5314bad202eb218dc5dbaab3..4439d064409173fc1b91e7590fcd378e60f58cdc 100644 (file)
@@ -39,6 +39,7 @@ Description:
                which affects charging via the special USB PowerShare port
                (marked with a small lightning bolt or battery icon) when in
                low power states:
+
                - In S0, the port will always provide power.
                - In S0ix, if usb_charge is enabled, then power will be
                  supplied to the port when on AC or if battery is > 50%.
index 5e6ead29124ccefb781645ba1b00af77f242367e..51c0f578bfce53ffa844d2cee44125eb6e84a353 100644 (file)
@@ -47,14 +47,18 @@ Description:
                suspend-to-disk mechanism.  Reading from this file returns
                the name of the method by which the system will be put to
                sleep on the next suspend.  There are four methods supported:
+
                'firmware' - means that the memory image will be saved to disk
                by some firmware, in which case we also assume that the
                firmware will handle the system suspend.
+
                'platform' - the memory image will be saved by the kernel and
                the system will be put to sleep by the platform driver (e.g.
                ACPI or other PM registers).
+
                'shutdown' - the memory image will be saved by the kernel and
                the system will be powered off.
+
                'reboot' - the memory image will be saved by the kernel and
                the system will be rebooted.
 
@@ -74,12 +78,12 @@ Description:
                The suspend-to-disk method may be chosen by writing to this
                file one of the accepted strings:
 
-               'firmware'
-               'platform'
-               'shutdown'
-               'reboot'
-               'testproc'
-               'test'
+               'firmware'
+               'platform'
+               'shutdown'
+               'reboot'
+               'testproc'
+               'test'
 
                It will only change to 'firmware' or 'platform' if the system
                supports that.
@@ -114,9 +118,9 @@ Description:
                string representing a nonzero integer into it.
 
                To use this debugging feature you should attempt to suspend
-               the machine, then reboot it and run
+               the machine, then reboot it and run::
 
-               dmesg -s 1000000 | grep 'hash matches'
+                 dmesg -s 1000000 | grep 'hash matches'
 
                If you do not get any matches (or they appear to be false
                positives), it is possible that the last PM event point
@@ -244,6 +248,7 @@ Description:
                wakeup sources created with the help of /sys/power/wake_lock.
                When a string is written to /sys/power/wake_unlock, it will be
                assumed to represent the name of a wakeup source to deactivate.
+
                If a wakeup source object of that name exists and is active at
                the moment, it will be deactivated.
 
index 8a8e466eb2c01d39ec2afb7cac46cc183dde94aa..e39dd3a0ceef3e36a27cc03e4510950388b2b093 100644 (file)
@@ -5,7 +5,7 @@ Description:
                /sys/kernel/profiling is the runtime equivalent
                of the boot-time profile= option.
 
-               You can get the same effect running:
+               You can get the same effect running::
 
                        echo 2 > /sys/kernel/profiling
 
index a17f817a93095b22f12b9aff657c0dd50c845fc7..2363ad810ddbee070a87002c28e00e84a2faad7b 100644 (file)
@@ -69,7 +69,7 @@ Description:
                pin offered by the PTP hardware clock. The file name
                is the hardware dependent pin name. Reading from this
                file produces two numbers, the assigned function (see
-               the PTP_PF_ enumeration values in linux/ptp_clock.h)
+               the `PTP_PF_` enumeration values in linux/ptp_clock.h)
                and the channel number. The function and channel
                assignment may be changed by two writing numbers into
                the file.
index aa39f8d7bcdff3c7b789e69752ec65a30bff7cc9..0b6227706b35ed1b18acb086c41b05b83f4480d9 100644 (file)
@@ -6,42 +6,46 @@ Description:
                 Enable passing additional variables for synthetic uevents that
                 are generated by writing /sys/.../uevent file.
 
-                Recognized extended format is ACTION [UUID [KEY=VALUE ...].
+                Recognized extended format is::
 
-                The ACTION is compulsory - it is the name of the uevent action
-                ("add", "change", "remove"). There is no change compared to
-                previous functionality here. The rest of the extended format
-                is optional.
+                       ACTION [UUID [KEY=VALUE ...]
+
+                The ACTION is compulsory - it is the name of the uevent
+                action (``add``, ``change``, ``remove``). There is no change
+                compared to previous functionality here. The rest of the
+                extended format is optional.
 
                 You need to pass UUID first before any KEY=VALUE pairs.
-                The UUID must be in "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
+                The UUID must be in ``xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx``
                 format where 'x' is a hex digit. The UUID is considered to be
                 a transaction identifier so it's possible to use the same UUID
                 value for one or more synthetic uevents in which case we
                 logically group these uevents together for any userspace
                 listeners. The UUID value appears in uevent as
-                "SYNTH_UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" environment
+                ``SYNTH_UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`` environment
                 variable.
 
                 If UUID is not passed in, the generated synthetic uevent gains
-                "SYNTH_UUID=0" environment variable automatically.
+                ``SYNTH_UUID=0`` environment variable automatically.
 
                 The KEY=VALUE pairs can contain alphanumeric characters only.
+
                 It's possible to define zero or more pairs - each pair is then
                 delimited by a space character ' '. Each pair appears in
-                synthetic uevent as "SYNTH_ARG_KEY=VALUE". That means the KEY
-                name gains "SYNTH_ARG_" prefix to avoid possible collisions
+                synthetic uevent as ``SYNTH_ARG_KEY=VALUE``. That means the KEY
+                name gains ``SYNTH_ARG_`` prefix to avoid possible collisions
                 with existing variables.
 
-                Example of valid sequence written to the uevent file:
+                Example of valid sequence written to the uevent file::
 
                     add fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed A=1 B=abc
 
-                This generates synthetic uevent including these variables:
+                This generates synthetic uevent including these variables::
 
                     ACTION=add
                     SYNTH_ARG_A=1
                     SYNTH_ARG_B=abc
                     SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed
+
 Users:
                 udev, userspace tools generating synthetic uevents
index a99c5f86a37a7fdf7b165cc8b9c62a708ce018cc..2969d3694ec0da19013a643f62854b5aee8ba549 100644 (file)
@@ -45,7 +45,8 @@ Description:
                 7. Device is unplugged.
 
                 References:
-                  [WUSB-AM] Association Models Supplement to the
+                  [WUSB-AM]
+                           Association Models Supplement to the
                             Certified Wireless Universal Serial Bus
                             Specification, version 1.0.
 
index 419a92dd0d86a9a8ef1a521aef8b50284ad373ff..1db89b0cf80fe2c9e9f2caf97fdf75c0f44e6e72 100644 (file)
@@ -3,44 +3,52 @@ Date:         2020-01-14
 KernelVersion: 5.6
 Contact:       linux-usb@vger.kernel.org
 Description:   There are two USB charger states:
-               USB_CHARGER_ABSENT
-               USB_CHARGER_PRESENT
+
+               - USB_CHARGER_ABSENT
+               - USB_CHARGER_PRESENT
+
                There are five USB charger types:
-               USB_CHARGER_UNKNOWN_TYPE: Charger type is unknown
-               USB_CHARGER_SDP_TYPE: Standard Downstream Port
-               USB_CHARGER_CDP_TYPE: Charging Downstream Port
-               USB_CHARGER_DCP_TYPE: Dedicated Charging Port
-               USB_CHARGER_ACA_TYPE: Accessory Charging Adapter
+
+               ========================  ==========================
+               USB_CHARGER_UNKNOWN_TYPE  Charger type is unknown
+               USB_CHARGER_SDP_TYPE      Standard Downstream Port
+               USB_CHARGER_CDP_TYPE      Charging Downstream Port
+               USB_CHARGER_DCP_TYPE      Dedicated Charging Port
+               USB_CHARGER_ACA_TYPE      Accessory Charging Adapter
+               ========================  ==========================
+
                https://www.usb.org/document-library/battery-charging-v12-spec-and-adopters-agreement
 
-               Here are two examples taken using udevadm monitor -p when
-               USB charger is online:
-               UDEV  change   /devices/soc0/usbphynop1 (platform)
-               ACTION=change
-               DEVPATH=/devices/soc0/usbphynop1
-               DRIVER=usb_phy_generic
-               MODALIAS=of:Nusbphynop1T(null)Cusb-nop-xceiv
-               OF_COMPATIBLE_0=usb-nop-xceiv
-               OF_COMPATIBLE_N=1
-               OF_FULLNAME=/usbphynop1
-               OF_NAME=usbphynop1
-               SEQNUM=2493
-               SUBSYSTEM=platform
-               USB_CHARGER_STATE=USB_CHARGER_PRESENT
-               USB_CHARGER_TYPE=USB_CHARGER_SDP_TYPE
-               USEC_INITIALIZED=227422826
-
-               USB charger is offline:
-               KERNEL change   /devices/soc0/usbphynop1 (platform)
-               ACTION=change
-               DEVPATH=/devices/soc0/usbphynop1
-               DRIVER=usb_phy_generic
-               MODALIAS=of:Nusbphynop1T(null)Cusb-nop-xceiv
-               OF_COMPATIBLE_0=usb-nop-xceiv
-               OF_COMPATIBLE_N=1
-               OF_FULLNAME=/usbphynop1
-               OF_NAME=usbphynop1
-               SEQNUM=2494
-               SUBSYSTEM=platform
-               USB_CHARGER_STATE=USB_CHARGER_ABSENT
-               USB_CHARGER_TYPE=USB_CHARGER_UNKNOWN_TYPE
+               Here are two examples taken using ``udevadm monitor -p`` when
+               USB charger is online::
+
+                   UDEV  change   /devices/soc0/usbphynop1 (platform)
+                   ACTION=change
+                   DEVPATH=/devices/soc0/usbphynop1
+                   DRIVER=usb_phy_generic
+                   MODALIAS=of:Nusbphynop1T(null)Cusb-nop-xceiv
+                   OF_COMPATIBLE_0=usb-nop-xceiv
+                   OF_COMPATIBLE_N=1
+                   OF_FULLNAME=/usbphynop1
+                   OF_NAME=usbphynop1
+                   SEQNUM=2493
+                   SUBSYSTEM=platform
+                   USB_CHARGER_STATE=USB_CHARGER_PRESENT
+                   USB_CHARGER_TYPE=USB_CHARGER_SDP_TYPE
+                   USEC_INITIALIZED=227422826
+
+               USB charger is offline::
+
+                   KERNEL change   /devices/soc0/usbphynop1 (platform)
+                   ACTION=change
+                   DEVPATH=/devices/soc0/usbphynop1
+                   DRIVER=usb_phy_generic
+                   MODALIAS=of:Nusbphynop1T(null)Cusb-nop-xceiv
+                   OF_COMPATIBLE_0=usb-nop-xceiv
+                   OF_COMPATIBLE_N=1
+                   OF_FULLNAME=/usbphynop1
+                   OF_NAME=usbphynop1
+                   SEQNUM=2494
+                   SUBSYSTEM=platform
+                   USB_CHARGER_STATE=USB_CHARGER_ABSENT
+                   USB_CHARGER_TYPE=USB_CHARGER_UNKNOWN_TYPE
index d35c3cad892c0627e2672c7002693b146c572d8b..2b8eca4bf2b1fde69a612311af44602630ee129a 100644 (file)
@@ -6,22 +6,22 @@ Description:  When the USB Host Controller has entered a state where it is no
                longer functional a uevent will be raised. The uevent will
                contain ACTION=offline and ERROR=DEAD.
 
-               Here is an example taken using udevadm monitor -p:
+               Here is an example taken using udevadm monitor -p::
 
-               KERNEL[130.428945] offline  /devices/pci0000:00/0000:00:10.0/usb2 (usb)
-               ACTION=offline
-               BUSNUM=002
-               DEVNAME=/dev/bus/usb/002/001
-               DEVNUM=001
-               DEVPATH=/devices/pci0000:00/0000:00:10.0/usb2
-               DEVTYPE=usb_device
-               DRIVER=usb
-               ERROR=DEAD
-               MAJOR=189
-               MINOR=128
-               PRODUCT=1d6b/2/414
-               SEQNUM=2168
-               SUBSYSTEM=usb
-               TYPE=9/0/1
+                   KERNEL[130.428945] offline  /devices/pci0000:00/0000:00:10.0/usb2 (usb)
+                   ACTION=offline
+                   BUSNUM=002
+                   DEVNAME=/dev/bus/usb/002/001
+                   DEVNUM=001
+                   DEVPATH=/devices/pci0000:00/0000:00:10.0/usb2
+                   DEVTYPE=usb_device
+                   DRIVER=usb
+                   ERROR=DEAD
+                   MAJOR=189
+                   MINOR=128
+                   PRODUCT=1d6b/2/414
+                   SEQNUM=2168
+                   SUBSYSTEM=usb
+                   TYPE=9/0/1
 
 Users:         chromium-os-dev@chromium.org
index 66046fa1c341eb551567723d26da937a444f9695..e549a61f4d9660fc3560dcbfba2c89aca24a4bb2 100644 (file)
@@ -10,4 +10,14 @@ config WARN_MISSING_DOCUMENTS
 
           If unsure, select 'N'.
 
+config WARN_ABI_ERRORS
+       bool "Warn if there are errors at ABI files"
+       depends on COMPILE_TEST
+       help
+          The files under Documentation/ABI should follow what's
+          described at Documentation/ABI/README. Yet, as they're manually
+          written, it would be possible that some of those files would
+          have errors that would break them for being parsed by
+          scripts/get_abi.pl. Add a check to verify them.
 
+          If unsure, select 'N'.
index 6b12dd82f71249318637aa8b2de73139d95de4b7..61a7310b49e0ce355e8f73e4afa33d6026545387 100644 (file)
@@ -10,6 +10,11 @@ ifeq ($(CONFIG_WARN_MISSING_DOCUMENTS),y)
 $(shell $(srctree)/scripts/documentation-file-ref-check --warn)
 endif
 
+# Check for broken ABI files
+ifeq ($(CONFIG_WARN_ABI_ERRORS),y)
+$(shell $(srctree)/scripts/get_abi.pl validate --dir $(srctree)/Documentation/ABI)
+endif
+
 # You can set these variables from the command line.
 SPHINXBUILD   = sphinx-build
 SPHINXOPTS    =
@@ -21,6 +26,10 @@ BUILDDIR      = $(obj)/output
 PDFLATEX      = xelatex
 LATEXOPTS     = -interaction=batchmode
 
+ifeq ($(KBUILD_VERBOSE),0)
+SPHINXOPTS    += "-q"
+endif
+
 # User-friendly check for sphinx-build
 HAVE_SPHINX := $(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi)
 
index 17996c9070e23a8bbb0621c14ded21f729248100..0ec34863c6742b6b0a0a553ada9bf8269ff66000 100644 (file)
@@ -107,7 +107,7 @@ for a UID/GID will prevent that UID/GID from obtaining auxiliary setid
 privileges, such as allowing a user to set up user namespace UID/GID mappings.
 
 Note on GID policies and setgroups()
-==================
+====================================
 In v5.9 we are adding support for limiting CAP_SETGID privileges as was done
 previously for CAP_SETUID. However, for compatibility with common sandboxing
 related code conventions in userspace, we currently allow arbitrary
diff --git a/Documentation/admin-guide/abi-obsolete.rst b/Documentation/admin-guide/abi-obsolete.rst
new file mode 100644 (file)
index 0000000..d095867
--- /dev/null
@@ -0,0 +1,11 @@
+ABI obsolete symbols
+====================
+
+Documents interfaces that are still remaining in the kernel, but are
+marked to be removed at some later point in time.
+
+The description of the interface will document the reason why it is
+obsolete and when it can be expected to be removed.
+
+.. kernel-abi:: $srctree/Documentation/ABI/obsolete
+   :rst:
diff --git a/Documentation/admin-guide/abi-removed.rst b/Documentation/admin-guide/abi-removed.rst
new file mode 100644 (file)
index 0000000..f7e9e43
--- /dev/null
@@ -0,0 +1,5 @@
+ABI removed symbols
+===================
+
+.. kernel-abi:: $srctree/Documentation/ABI/removed
+   :rst:
diff --git a/Documentation/admin-guide/abi-stable.rst b/Documentation/admin-guide/abi-stable.rst
new file mode 100644 (file)
index 0000000..7049073
--- /dev/null
@@ -0,0 +1,14 @@
+ABI stable symbols
+==================
+
+Documents the interfaces that the developer has defined to be stable.
+
+Userspace programs are free to use these interfaces with no
+restrictions, and backward compatibility for them will be guaranteed
+for at least 2 years.
+
+Most interfaces (like syscalls) are expected to never change and always
+be available.
+
+.. kernel-abi:: $srctree/Documentation/ABI/stable
+   :rst:
diff --git a/Documentation/admin-guide/abi-testing.rst b/Documentation/admin-guide/abi-testing.rst
new file mode 100644 (file)
index 0000000..b205b16
--- /dev/null
@@ -0,0 +1,20 @@
+ABI testing symbols
+===================
+
+Documents interfaces that are felt to be stable,
+as the main development of this interface has been completed.
+
+The interface can be changed to add new features, but the
+current interface will not break by doing this, unless grave
+errors or security problems are found in them.
+
+Userspace programs can start to rely on these interfaces, but they must
+be aware of changes that can occur before these interfaces move to
+be marked stable.
+
+Programs that use these interfaces are strongly encouraged to add their
+name to the description of these interfaces, so that the kernel
+developers can easily notify them if any changes occur.
+
+.. kernel-abi:: $srctree/Documentation/ABI/testing
+   :rst:
diff --git a/Documentation/admin-guide/abi.rst b/Documentation/admin-guide/abi.rst
new file mode 100644 (file)
index 0000000..bcab3ef
--- /dev/null
@@ -0,0 +1,11 @@
+=====================
+Linux ABI description
+=====================
+
+.. toctree::
+   :maxdepth: 2
+
+   abi-stable
+   abi-testing
+   abi-obsolete
+   abi-removed
index a22024f9175e70f64898ff3ff4a5d123b3188752..9b90efcc3a35e923b37fec54879e132adf8ae3ca 100644 (file)
@@ -137,15 +137,24 @@ Boot Kernel With a Boot Config
 ==============================
 
 Since the boot configuration file is loaded with initrd, it will be added
-to the end of the initrd (initramfs) image file with size, checksum and
-12-byte magic word as below.
+to the end of the initrd (initramfs) image file with padding, size,
+checksum and 12-byte magic word as below.
 
-[initrd][bootconfig][size(u32)][checksum(u32)][#BOOTCONFIG\n]
+[initrd][bootconfig][padding][size(le32)][checksum(le32)][#BOOTCONFIG\n]
+
+The size and checksum fields are unsigned 32bit little endian value.
+
+When the boot configuration is added to the initrd image, the total
+file size is aligned to 4 bytes. To fill the gap, null characters
+(``\0``) will be added. Thus the ``size`` is the length of the bootconfig
+file + padding bytes.
 
 The Linux kernel decodes the last part of the initrd image in memory to
 get the boot configuration data.
 Because of this "piggyback" method, there is no need to change or
-update the boot loader and the kernel image itself.
+update the boot loader and the kernel image itself as long as the boot
+loader passes the correct initrd file size. If by any chance, the boot
+loader passes a longer size, the kernel feils to find the bootconfig data.
 
 To do this operation, Linux kernel provides "bootconfig" command under
 tools/bootconfig, which allows admin to apply or delete the config file
@@ -176,7 +185,8 @@ up to 512 key-value pairs. If keys contains 3 words in average, it can
 contain 256 key-value pairs. In most cases, the number of config items
 will be under 100 entries and smaller than 8KB, so it would be enough.
 If the node number exceeds 1024, parser returns an error even if the file
-size is smaller than 32KB.
+size is smaller than 32KB. (Note that this maximum size is not including
+the padding null characters.)
 Anyway, since bootconfig command verifies it when appending a boot config
 to initrd image, user can notice it before boot.
 
index ed1cf94ea50c2773b1e0c21250c06ac8d2336fcd..4e0c4ae44acda53b01ef194ad4ffb6bd84ec6e39 100644 (file)
@@ -18,6 +18,8 @@ etc.
    devices
    sysctl/index
 
+   abi
+
 This section describes CPU vulnerabilities and their mitigations.
 
 .. toctree::
index 526d65d8573a4c448923c606e7f7e36e494740d1..44fde25bb221e0b31268bd5b2f6d4c53fe39bda4 100644 (file)
                                               mds=off [X86]
                                               tsx_async_abort=off [X86]
                                               kvm.nx_huge_pages=off [X86]
+                                              no_entry_flush [PPC]
+                                              no_uaccess_flush [PPC]
 
                                Exceptions:
                                               This does not have any effect on
 
        noefi           Disable EFI runtime services support.
 
+       no_entry_flush  [PPC] Don't flush the L1-D cache when entering the kernel.
+
        noexec          [IA-64]
 
        noexec          [X86]
        nospec_store_bypass_disable
                        [HW] Disable all mitigations for the Speculative Store Bypass vulnerability
 
+       no_uaccess_flush
+                       [PPC] Don't flush the L1-D cache after accessing user data.
+
        noxsave         [BUGS=X86] Disables x86 extended register state save
                        and restore using xsave. The kernel will fallback to
                        enabling legacy floating-point and sse state.
index 37940a0584ec188a686dbef917a9652f81f12af3..10fde58d086972701f732ec0d85fb5540c25a35b 100644 (file)
@@ -478,7 +478,7 @@ order to ask the hardware to enter that state.  Also, for each
 statistics of the given idle state.  That information is exposed by the kernel
 via ``sysfs``.
 
-For each CPU in the system, there is a :file:`/sys/devices/system/cpu<N>/cpuidle/`
+For each CPU in the system, there is a :file:`/sys/devices/system/cpu/cpu<N>/cpuidle/`
 directory in ``sysfs``, where the number ``<N>`` is assigned to the given
 CPU at the initialization time.  That directory contains a set of subdirectories
 called :file:`state0`, :file:`state1` and so on, up to the number of idle state
@@ -494,7 +494,7 @@ object corresponding to it, as follows:
        residency.
 
 ``below``
-       Total number of times this idle state had been asked for, but cerainly
+       Total number of times this idle state had been asked for, but certainly
        a deeper idle state would have been a better match for the observed idle
        duration.
 
index 57fd6ce68fe05d3b1df5cf705c81da98d50144e3..f2ab8a5b6a4b867e760026920929f68a19850194 100644 (file)
@@ -300,6 +300,7 @@ Note:
       0:    0     1     2     3     4     5     6     7
   RSS hash key:
   84:50:f4:00:a8:15:d1:a7:e9:7f:1d:60:35:c7:47:25:42:97:74:ca:56:bb:b6:a1:d8:43:e3:c9:0c:fd:17:55:c2:3a:4d:69:ed:f1:42:89
+
 netdev_tstamp_prequeue
 ----------------------
 
index 62b533d0ba9443ff3e8818947a1e846ebd044528..0c536ae1d7c2b20301fdfac04d237232e28d9f9c 100644 (file)
@@ -148,3 +148,13 @@ SunXi family
         * User Manual
 
           http://dl.linux-sunxi.org/A64/Allwinner%20A64%20User%20Manual%20v1.0.pdf
+
+      - Allwinner H6
+
+       * Datasheet
+
+         https://linux-sunxi.org/images/5/5c/Allwinner_H6_V200_Datasheet_V1.1.pdf
+
+       * User Manual
+
+         https://linux-sunxi.org/images/4/46/Allwinner_H6_V200_User_Manual_V1.1.pdf
index 034d37c605e840b7ffd19ec1b3169d28eb92f2b3..b540178a93f876c923e03fddb05837efc378efd7 100644 (file)
@@ -102,7 +102,9 @@ applications.
 system call) are not checked if the user thread tag checking mode is
 ``PR_MTE_TCF_NONE`` or ``PR_MTE_TCF_ASYNC``. If the tag checking mode is
 ``PR_MTE_TCF_SYNC``, the kernel makes a best effort to check its user
-address accesses, however it cannot always guarantee it.
+address accesses, however it cannot always guarantee it. Kernel accesses
+to user addresses are always performed with an effective ``PSTATE.TCO``
+value of zero, regardless of the user configuration.
 
 Excluding Tags in the ``IRG``, ``ADDG`` and ``SUBG`` instructions
 -----------------------------------------------------------------
index d3587805de6432332c5d6e197b5ee266a165a5b3..71951024729294a70f55d1fa5153390c970c7b64 100644 (file)
@@ -90,6 +90,8 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A76      | #1463225        | ARM64_ERRATUM_1463225       |
 +----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A77      | #1508412        | ARM64_ERRATUM_1508412       |
++----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Neoverse-N1     | #1188873,1418040| ARM64_ERRATUM_1418040       |
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Neoverse-N1     | #1349291        | N/A                         |
index 376dd0ddf39cdcc89d1ea37d49b299f1ed154c7a..ed2b43ec7754e5b886c6edbda64332179ed5ea56 100644 (file)
@@ -38,7 +38,8 @@ needs_sphinx = '1.3'
 # ones.
 extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include',
               'kfigure', 'sphinx.ext.ifconfig', 'automarkup',
-              'maintainers_include', 'sphinx.ext.autosectionlabel' ]
+              'maintainers_include', 'sphinx.ext.autosectionlabel',
+              'kernel_abi']
 
 #
 # cdomain is badly broken in Sphinx 3+.  Leaving it out generates *most*
@@ -50,7 +51,7 @@ if major >= 3:
         support for Sphinx v3.0 and above is brand new. Be prepared for
         possible issues in the generated output.
         ''')
-    if minor > 0 or patch >= 2:
+    if (major > 3) or (minor > 0 or patch >= 2):
         # Sphinx c function parser is more pedantic with regards to type
         # checking. Due to that, having macros at c:function cause problems.
         # Those needed to be scaped by using c_id_attributes[] array
index c09c9ca2ff1cbae16417bf92e05a6193e53641d4..2b68addaadcd756f4cb08eda4133fcae5710e5f0 100644 (file)
@@ -295,11 +295,13 @@ print the number of the test and the status of the test:
 pass::
 
         ok 28 - kmalloc_double_kzfree
+
 or, if kmalloc failed::
 
         # kmalloc_large_oob_right: ASSERTION FAILED at lib/test_kasan.c:163
         Expected ptr is not null, but is
         not ok 4 - kmalloc_large_oob_right
+
 or, if a KASAN report was expected, but not found::
 
         # kmalloc_double_kzfree: EXPECTATION FAILED at lib/test_kasan.c:629
index 1628862e70245186509754e5f2b1e3b87ec7ac56..8d5029ad210a5fcb4e968cf7bafcc2f06814c70c 100644 (file)
@@ -90,7 +90,7 @@ things to try.
    re-run kunit_tool.
 5. Try to run ``make ARCH=um defconfig`` before running ``kunit.py run``. This
    may help clean up any residual config items which could be causing problems.
-6. Finally, try running KUnit outside UML. KUnit and KUnit tests can run be
+6. Finally, try running KUnit outside UML. KUnit and KUnit tests can be
    built into any kernel, or can be built as a module and loaded at runtime.
    Doing so should allow you to determine if UML is causing the issue you're
    seeing. When tests are built-in, they will execute when the kernel boots, and
index d23385e3e1592bea6240287f0422bb94da629022..454f307813ea6689d5ee80954e5d32792a0c8627 100644 (file)
@@ -197,7 +197,7 @@ Now add the following to ``drivers/misc/Kconfig``:
 
        config MISC_EXAMPLE_TEST
                bool "Test for my example"
-               depends on MISC_EXAMPLE && KUNIT
+               depends on MISC_EXAMPLE && KUNIT=y
 
 and the following to ``drivers/misc/Makefile``:
 
index da1d6f0ed6bcc9b653a49f7f70d39c0210890bb7..8dbcdc55260668f596c7b207e549ccae0cd09c37 100644 (file)
@@ -175,17 +175,17 @@ An example Kconfig entry:
 
 .. code-block:: none
 
-        config FOO_KUNIT_TEST
-                tristate "KUnit test for foo" if !KUNIT_ALL_TESTS
-                depends on KUNIT
-                default KUNIT_ALL_TESTS
-                help
-                    This builds unit tests for foo.
+       config FOO_KUNIT_TEST
+               tristate "KUnit test for foo" if !KUNIT_ALL_TESTS
+               depends on KUNIT
+               default KUNIT_ALL_TESTS
+               help
+                 This builds unit tests for foo.
 
-                    For more information on KUnit and unit tests in general, please refer
-                    to the KUnit documentation in Documentation/dev-tools/kunit
+                 For more information on KUnit and unit tests in general, please refer
+                 to the KUnit documentation in Documentation/dev-tools/kunit/.
 
-                    If unsure, say N
+                 If unsure, say N.
 
 
 Test File and Module Names
index 961d3ea3ca19ad2211252395a04f9519ede0161a..9c28c518e6a3aab8aedb554226777f17f1698677 100644 (file)
@@ -92,7 +92,7 @@ behavior of a function called ``add``; the first parameter is always of type
 the second parameter, in this case, is what the value is expected to be; the
 last value is what the value actually is. If ``add`` passes all of these
 expectations, the test case, ``add_test_basic`` will pass; if any one of these
-expectations fail, the test case will fail.
+expectations fails, the test case will fail.
 
 It is important to understand that a test case *fails* when any expectation is
 violated; however, the test will continue running, potentially trying other
@@ -202,7 +202,7 @@ Example:
        kunit_test_suite(example_test_suite);
 
 In the above example the test suite, ``example_test_suite``, would run the test
-cases ``example_test_foo``, ``example_test_bar``, and ``example_test_baz``,
+cases ``example_test_foo``, ``example_test_bar``, and ``example_test_baz``;
 each would have ``example_test_init`` called immediately before it and would
 have ``example_test_exit`` called immediately after it.
 ``kunit_test_suite(example_test_suite)`` registers the test suite with the
@@ -229,7 +229,7 @@ through some sort of indirection where a function is exposed as part of an API
 such that the definition of that function can be changed without affecting the
 rest of the code base. In the kernel this primarily comes from two constructs,
 classes, structs that contain function pointers that are provided by the
-implementer, and architecture specific functions which have definitions selected
+implementer, and architecture-specific functions which have definitions selected
 at compile time.
 
 Classes
@@ -459,7 +459,7 @@ KUnit on non-UML architectures
 By default KUnit uses UML as a way to provide dependencies for code under test.
 Under most circumstances KUnit's usage of UML should be treated as an
 implementation detail of how KUnit works under the hood. Nevertheless, there
-are instances where being able to run architecture specific code or test
+are instances where being able to run architecture-specific code or test
 against real hardware is desirable. For these reasons KUnit supports running on
 other architectures.
 
@@ -561,6 +561,11 @@ Once the kernel is built and installed, a simple
 
 ...will run the tests.
 
+.. note::
+   Note that you should make sure your test depends on ``KUNIT=y`` in Kconfig
+   if the test does not support module build.  Otherwise, it will trigger
+   compile errors if ``CONFIG_KUNIT`` is ``m``.
+
 Writing new tests for other architectures
 -----------------------------------------
 
@@ -594,7 +599,7 @@ writing normal KUnit tests. One special caveat is that you have to reset
 hardware state in between test cases; if this is not possible, you may only be
 able to run one test case per invocation.
 
-.. TODO(brendanhiggins@google.com): Add an actual example of an architecture
+.. TODO(brendanhiggins@google.com): Add an actual example of an architecture-
    dependent KUnit test.
 
 KUnit debugfs representation
index fe22c66e9c15a3c71220db32dc2b17c5401316de..02dc72c976456bb790d5267ec469d1cf49a82967 100644 (file)
@@ -49,3 +49,5 @@ properties:
           - enum:
               - ucrobotics,bubblegum-96 # uCRobotics Bubblegum-96
           - const: actions,s900
+
+additionalProperties: true
index 0bc5020b7539540844b6f0536053156424833861..c15c92fdf2ed80c1e1b04b5cb631ae71b17eb924 100644 (file)
@@ -19,4 +19,7 @@ properties:
           - altr,socfpga-arria5
           - altr,socfpga-arria10
       - const: altr,socfpga
+
+additionalProperties: true
+
 ...
index a3a4d710bd02a00b1ff94f0fdc2b60aa595dd53a..0f03135d91b6165888a5a94f78fec6b5be57f919 100644 (file)
@@ -30,4 +30,6 @@ properties:
               - amazon,al-alpine-v3-evp
           - const: amazon,al-alpine-v3
 
+additionalProperties: true
+
 ...
index 0ee7c5b7b3f66b8fbe50a04c791b986daa8c8778..3341788d10965618e73117c574d2e7e22a55013c 100644 (file)
@@ -173,4 +173,7 @@ properties:
           - enum:
               - amlogic,ad401
           - const: amlogic,a1
+
+additionalProperties: true
+
 ...
index f0daf990e0778456c1887f9cd6f0270fee295ba5..528eee64290ab514fe5baa356ef1af86c8cd012b 100644 (file)
@@ -83,4 +83,6 @@ required:
   - compatible
   - core-module@10000000
 
+additionalProperties: true
+
 ...
index 1d0b4e2bc7d2bf11ba4a7ff719411cc18eac2b75..4f9b21f49e84619b59fd8c4e8ebd8d4a11eca6d4 100644 (file)
@@ -120,4 +120,6 @@ required:
   - compatible
   - soc
 
+additionalProperties: true
+
 ...
index 06efd2a075c9dfb78305f494b2173d2e5b8ce60c..34b437c727517ec14bf357177b79112327439fdb 100644 (file)
@@ -68,4 +68,6 @@ required:
   - compatible
   - core-module@10000000
 
+additionalProperties: true
+
 ...
index 26829a803fda8dddc63d736466480a8bf7e27365..55ef656d1192e24b3b8d1f5278b9f39888e4b60c 100644 (file)
@@ -216,4 +216,6 @@ allOf:
       required:
         - arm,hbi
 
+additionalProperties: true
+
 ...
index 614c91956798a248405d7476cd6beb97e93abc36..6fc5a22ad962f86e18ba10817b480fb6b2ad8a69 100644 (file)
@@ -184,4 +184,6 @@ properties:
           - const: atmel,samv71
           - const: atmel,samv7
 
+additionalProperties: true
+
 ...
index 3ea5f2fdcd96c1874fa675f80f26125bf7e01c4c..e0d2bb71cf502b1e1697a0b9db6a95660df79b44 100644 (file)
@@ -18,4 +18,6 @@ properties:
       - const: lsi,axm5516-amarillo
       - const: lsi,axm5516
 
+additionalProperties: true
+
 ...
index dd52e29b0642db7c4bdcc60115c365ca65ef62f2..812ae8cc595981c353a3fa055e0c3de29dc9093b 100644 (file)
@@ -51,4 +51,6 @@ properties:
               - raspberrypi,3-compute-module-lite
           - const: brcm,bcm2837
 
+additionalProperties: true
+
 ...
index 497600a2ffb9c42e1b6dcfb9538dbf9da6e63554..c6032435743574d9341778c87d348a3a3a2d0a00 100644 (file)
@@ -18,4 +18,6 @@ properties:
           - brcm,bcm28155-ap
       - const: brcm,bcm11351
 
+additionalProperties: true
+
 ...
index e0ee931723dc431d2495229260e151a341171cd0..b3020757380f610f70169b86d41f34cbe8785397 100644 (file)
@@ -18,4 +18,6 @@ properties:
           - brcm,bcm21664-garnet
       - const: brcm,bcm21664
 
+additionalProperties: true
+
 ...
index 40d12ea56e547e11a8980b05fe36bda11f1fa4e4..37f3a6fcde760a67857bc61e6321b0a4b01b9208 100644 (file)
@@ -18,4 +18,6 @@ properties:
           - brcm,bcm23550-sparrow
       - const: brcm,bcm23550
 
+additionalProperties: true
+
 ...
index 988e0bbb2a62877cb3e823856f129ecb0543cd15..434d3c6db61eef2d0f7186d3eb49c5b69f8d243f 100644 (file)
@@ -87,4 +87,7 @@ properties:
           - const: brcm,brcm53012
           - const: brcm,brcm53016
           - const: brcm,bcm4708
+
+additionalProperties: true
+
 ...
index 9ba7b16e1fc4dd3dadca0202fdb8274141894a84..432ccf990f9e8e75c5528a7e444dc36b8e02050c 100644 (file)
@@ -26,4 +26,6 @@ properties:
           - brcm,bcm58305
       - const: brcm,cygnus
 
+additionalProperties: true
+
 ...
index ae614b6722c2b5a313724b39eb38671c618ef81c..294948399f82545fa84c817271ee665f763ebc0f 100644 (file)
@@ -25,4 +25,6 @@ properties:
       - const: brcm,bcm53342
       - const: brcm,hr2
 
+additionalProperties: true
+
 ...
index 0749adf94c28929c64d5cc9ed079d05acd476d9d..c4847abbecd8e792b216e45f08e6893fa250867d 100644 (file)
@@ -20,4 +20,6 @@ properties:
           - brcm,ns2-xmc
       - const: brcm,ns2
 
+additionalProperties: true
+
 ...
index 8c2cacb2bb4f12b02f348704c0a3492939eb29e9..476bc23a7f75c098af05e74b0c27f906612c9804 100644 (file)
@@ -33,4 +33,6 @@ properties:
           - brcm,bcm88312
       - const: brcm,nsp
 
+additionalProperties: true
+
 ...
index c13cb96545a2836008229791e5260610892fbe02..c638e04ebae0fd1e4bf0243c56a08e11577a4de0 100644 (file)
@@ -21,4 +21,6 @@ properties:
           - brcm,bcm958802a802x
       - const: brcm,stingray
 
+additionalProperties: true
+
 ...
index ccdf9f99cb2b01a9eb862c1674924f1207e60111..4eba182abd5358921123606703ab1ae445448cae 100644 (file)
@@ -19,4 +19,6 @@ properties:
           - cavium,thunderx2-cn9900
       - const: brcm,vulcan-soc
 
+additionalProperties: true
+
 ...
index 5880083ab8d01af78b86172405bd0d4dd62d1385..90ba02be48ce5b9ce13a2ae5dc681ab79660b0f2 100644 (file)
@@ -17,4 +17,7 @@ properties:
       - enum:
           - bitmain,sophon-edge
       - const: bitmain,bm1880
+
+additionalProperties: true
+
 ...
index aa5571d23c39b2230218f5f40c4b83f2220d0590..46f78addebb0f35445df83c6c3b37dc726b1a0d0 100644 (file)
@@ -20,3 +20,5 @@ properties:
       - enum:
           - calxeda,highbank
           - calxeda,ecx-2000
+
+additionalProperties: true
index 849e205183392b480db0fa8d5671f1b298f9cc6c..a35de3c9e28474113f3f4f7addf466c6babc27d5 100644 (file)
@@ -15,4 +15,6 @@ properties:
   compatible:
     const: cnxt,cx92755
 
+additionalProperties: true
+
 ...
index 1ca9dfa8ce9ac07a5dc8ce3290d1a9e07a93f9b8..934289446abb652c4848ee2751fc5473d1df5b96 100644 (file)
@@ -621,4 +621,6 @@ properties:
               - fsl,s32v234-evb           # S32V234-EVB2 Customer Evaluation Board
           - const: fsl,s32v234
 
+additionalProperties: true
+
 ...
index 43b8ce2227aaae903c7557e56415aaefbe7ab735..b38458022946f0d3610efcd83d55821e46623f27 100644 (file)
@@ -64,4 +64,7 @@ properties:
         items:
           - const: H836ASDJ
           - const: hisilicon,sd5203
+
+additionalProperties: true
+
 ...
index 06a7b05f435f3d7ef629e0afa17d37b41f38a20c..69cd3087292833c9182774c4e21384757c00a815 100644 (file)
@@ -16,4 +16,7 @@ properties:
       - enum:
           - intel,keembay-evm
       - const: intel,keembay
+
+additionalProperties: true
+
 ...
index f18302efb90eaca2c930816412746d59c9f21dba..d72e92bdf7c14e99eec675ca905a1513d92b2bd3 100644 (file)
@@ -22,3 +22,5 @@ properties:
           - enum:
               - gateworks,gw2358
           - const: intel,ixp43x
+
+additionalProperties: true
index 7597bc93a55fa037889da75e9a4dcea168bd5ec8..5cbcacaeb441e20a831a9c79b59af60055849271 100644 (file)
@@ -42,3 +42,5 @@ properties:
       - description: TI-SCI processor id for the remote processor device
       - description: TI-SCI host id to which processor control ownership
                      should be transferred to
+
+additionalProperties: true
index a9828c50c0fba31ef30a9c2dd5bdc94383685b11..e9bf3054529f1297d383e4b5cd801c9cecb284df 100644 (file)
@@ -59,3 +59,5 @@ properties:
           - const: marvell,cn9130
           - const: marvell,armada-ap807-quad
           - const: marvell,armada-ap807
+
+additionalProperties: true
index 30908963ae26159d96c62f56654df892c4c7576e..f736e8c859fa1dbc7569f6bd72faea3a0372bcf5 100644 (file)
@@ -119,4 +119,7 @@ properties:
           - const: google,krane-sku176
           - const: google,krane
           - const: mediatek,mt8183
+
+additionalProperties: true
+
 ...
index ecf6fa12e6ad26c63ea20e98666caa1112877e89..6193388c63182a7069b45cb21ff84640c85448d2 100644 (file)
@@ -62,4 +62,6 @@ required:
   - compatible
   - axi@600000000
 
+additionalProperties: true
+
 ...
index c068df59fad2b80f6181dbd5aebd2959ba06f9dd..670d24ce8ec5e57d8f075dd70d90f461226ced73 100644 (file)
@@ -16,4 +16,5 @@ properties:
       - const: moxa,moxart-uc-7112-lx
       - const: moxa,moxart
 
+additionalProperties: true
 ...
index 3235ec9e9bad182e8409b5ba4133f5c7bcb2ed70..d581161361547d12c0cfc02f5d50b1fd3ff369d7 100644 (file)
@@ -35,4 +35,7 @@ properties:
           - enum:
               - dell,wyse-ariel
           - const: marvell,mmp3
+
+additionalProperties: true
+
 ...
index c2f980b00b0670cdeb9fad851b5abfd53d3fdd3a..7c787405bb2f40a56fc71b089c02d05b622aaf09 100644 (file)
@@ -31,3 +31,5 @@ properties:
           - enum:
               - 70mai,midrived08 # 70mai midrive d08
           - const: mstar,mercury5
+
+additionalProperties: true
index f7f024910e716d4d7c055f67fe455bb0306e6804..214c97bc30634d21c3769991afe635df4fe4be58 100644 (file)
@@ -21,4 +21,6 @@ properties:
               - ea,ea3250
               - phytec,phy3250
           - const: nxp,lpc3250
+
+additionalProperties: true
 ...
index ad25deba4d8634e4a62c82c28d958b9f2c4ef463..c97d4a580f47b0b1674b9f43b62e3d780f21a8cf 100644 (file)
@@ -178,4 +178,6 @@ properties:
               - qcom,sm8250-mtp
           - const: qcom,sm8250
 
+additionalProperties: true
+
 ...
index 9672aa0c760d101be6b43bdceacc624b4af95911..a5c0444aa2b47b7281f7ff095ce7f6944195372e 100644 (file)
@@ -19,4 +19,6 @@ properties:
           - xunlong,orangepi-i96        # Orange Pi i96
       - const: rda,8810pl
 
+additionalProperties: true
+
 ...
index 845f9c76d6f708ae293e707d5e86a9763bb2b078..9fb0297fe1ced79c9b342f953fa8972a58c95007 100644 (file)
@@ -54,4 +54,7 @@ properties:
           - enum:
               - realtek,mjolnir # Realtek Mjolnir EVB
           - const: realtek,rtd1619
+
+additionalProperties: true
+
 ...
index 01a6d0c571ad541477c94a84df4ee0d6ba6954b0..ff94c45eefb014565740fa0ee1be81882851dc2c 100644 (file)
@@ -299,4 +299,6 @@ properties:
               - renesas,rzn1d400-db # RZN1D-DB (RZ/N1D Demo Board for the RZ/N1D 400 pins package)
           - const: renesas,r9a06g032
 
+additionalProperties: true
+
 ...
index 65b4cc2c63f7c1e5fbf20ce34b20f9dc15f264e2..b621752aaa652b9b5185ddd1c7f37d7d1754a1af 100644 (file)
@@ -569,4 +569,7 @@ properties:
         items:
           - const: zkmagic,a95x-z2
           - const: rockchip,rk3318
+
+additionalProperties: true
+
 ...
index eb92f9eefaba6be07c5d010008b04d0fb65b9853..272508010b02ebb6d648584a60ff974888d59a86 100644 (file)
@@ -180,3 +180,5 @@ properties:
 
 required:
   - compatible
+
+additionalProperties: true
index 0b597032c9239740164eb1cba8811091eb9d0eaf..b25eb35d1b66354b7c0a1673177db80705c43f6c 100644 (file)
@@ -24,4 +24,7 @@ properties:
       - items:
           - const: sirf,prima2-cb
           - const: sirf,prima2
+
+additionalProperties: true
+
 ...
index 2bd519d2e8557fae8f648ab32fe416bb6e39fc71..aa1d4afbc5105fb6b4b5dad4ed1fb2a4b0c64ccf 100644 (file)
@@ -19,4 +19,7 @@ properties:
           - enum:
               - socionext,milbeaut-m10v-evb
           - const: socionext,sc2000a
+
+additionalProperties: true
+
 ...
index 6caf1f9be390f281762243ef57bbabf710d6d480..8c0e91658474f8effdf1518e33c0c3895ba0d1f4 100644 (file)
@@ -60,3 +60,5 @@ properties:
           - enum:
               - socionext,uniphier-pxs3-ref
           - const: socionext,uniphier-pxs3
+
+additionalProperties: true
index f6ec731c9531306a1ee80b4b0f8d0b066704c7a0..605ad3f882efcfe8de256b5dad429eefb0afb056 100644 (file)
@@ -22,4 +22,7 @@ properties:
           - st,spear320
           - st,spear1310
           - st,spear1340
+
+additionalProperties: true
+
 ...
index 0258a96bfbdefb95f40797366232f9a4cb2f9f60..7b6ae3070396547392660abdb1a5e44a25889e5f 100644 (file)
@@ -30,4 +30,6 @@ properties:
               - sprd,sp9863a-1h10
           - const: sprd,sc9863a
 
+additionalProperties: true
+
 ...
index 47f9b8eebaa010561d1d58ca7908f4733dfad497..b1f28d16d3fbccdadb42d357b17175697284d90e 100644 (file)
@@ -20,4 +20,7 @@ properties:
           - st,stih407
           - st,stih410
           - st,stih418
+
+additionalProperties: true
+
 ...
index deacb4e686e83968686d2f038aa10436a5286d4d..009b424e456e9e3366a952f200b2ea6db7e01e82 100644 (file)
@@ -54,8 +54,11 @@ properties:
           - const: st,stm32mp157
       - description: Odyssey STM32MP1 SoM based Boards
         items:
-              - enum:
-                  - seeed,stm32mp157c-odyssey
-              - const: seeed,stm32mp157c-odyssey-som
-              - const: st,stm32mp157
+          - enum:
+              - seeed,stm32mp157c-odyssey
+          - const: seeed,stm32mp157c-odyssey-som
+          - const: st,stm32mp157
+
+additionalProperties: true
+
 ...
index afa00268c7db731ee27d43de83af1d5d6b35484c..cab8e1b6417bff989cc8cb53945b54de4b71ddcb 100644 (file)
@@ -893,3 +893,5 @@ properties:
         items:
           - const: xunlong,orangepi-zero-plus2-h3
           - const: allwinner,sun8i-h3
+
+additionalProperties: true
index 8ae44948e8733619f54368d4dc322ba092bdfc98..767e86354c8e9597c5868aecd0a90c911456e521 100644 (file)
@@ -125,3 +125,5 @@ properties:
           - enum:
               - nvidia,tegra234-vdk
           - const: nvidia,tegra234
+
+additionalProperties: true
index 8297512095435884f7e74329da9f8f5338239265..c6e1c1e63e432365ec7e043c37a568a416169aa3 100644 (file)
@@ -32,4 +32,7 @@ properties:
       - description: K3 J7200 SoC
         items:
           - const: ti,j7200
+
+additionalProperties: true
+
 ...
index e372b43da62fb3a0b039da2970f7391b02358e4b..cc2023bb7fa608405eced3f6e4d74f0798afa66e 100644 (file)
@@ -21,4 +21,7 @@ properties:
           - ti,nspire-tp
           # Clickpad models
           - ti,nspire-clp
+
+additionalProperties: true
+
 ...
index a8765ba29476cac331edd641cab3f6de2dab9092..c022d325fc08b3db313cd020dccc95f631e9dc5e 100644 (file)
@@ -23,4 +23,7 @@ properties:
           - enbw,cmc        # EnBW AM1808 based CMC board
           - lego,ev3        # LEGO MINDSTORMS EV3 (AM1808 based)
       - const: ti,da850
+
+additionalProperties: true
+
 ...
index 0e066290238eef3a3b6cb9db0127fd73ccb0dddb..001bbbcd143283ede9e5f439fc038b4c5faf792f 100644 (file)
@@ -19,4 +19,7 @@ properties:
           - enum:
               - toshiba,tmpv7708-rm-mbrc  # TMPV7708 RM main board
           - const: toshiba,tmpv7708
+
+additionalProperties: true
+
 ...
index accaee9060506321fc7c40f6c3aef0dd820cd577..5db7cfba81a477d17fe56d760f7c34df9f83f80d 100644 (file)
@@ -34,3 +34,5 @@ properties:
         items:
           - const: samsung,golden
           - const: st-ericsson,u8500
+
+additionalProperties: true
index 7b25b6fa34e918148c469caad0d0a504c49fd8c5..29ff399551ca799f93da90604e793d5a0c540a9f 100644 (file)
@@ -21,3 +21,6 @@ properties:
           - wm,wm8650
           - wm,wm8750
           - wm,wm8850
+          
+additionalProperties: true
+
index c73b1f5c7f49f9000d5c317ed9bdaa927eed51db..e0c6787f6e9494785faacbd338209d6c2482bd8b 100644 (file)
@@ -111,4 +111,6 @@ properties:
           - const: xlnx,zynqmp-zcu111
           - const: xlnx,zynqmp
 
+additionalProperties: true
+
 ...
index 2d3fefdccdff437ad2986d2e83d6495d5c954c06..672f8129cd3199a970c58ee69650cd8c1886dfe5 100644 (file)
@@ -23,4 +23,6 @@ properties:
               - zte,zx296718-evb
           - const: zte,zx296718
 
+additionalProperties: true
+
 ...
index ef3deb7b86eaf18468a2b779c9b7786c92d158d0..17ac4a3dd26aa841f53a60ce48806e8203499da8 100644 (file)
@@ -4,7 +4,7 @@ Clock control registers reside in different Hi6220 system controllers,
 please refer the following document to know more about the binding rules
 for these system controllers:
 
-Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+Documentation/devicetree/bindings/arm/hisilicon/hisilicon.yaml
 
 Required Properties:
 
index 4d9e7c73dce919558c0a0166769a040cc8741425..90775c2669b84ba123d9551a58894a9d274ff4d5 100644 (file)
@@ -57,7 +57,7 @@ examples:
     };
 
     can@53fc8000 {
-        compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
+        compatible = "fsl,imx53-flexcan", "fsl,imx25-flexcan";
         reg = <0x53fc8000 0x4000>;
         interrupts = <82>;
         clocks = <&clks IMX5_CLK_CAN1_IPG_GATE>, <&clks IMX5_CLK_CAN1_SERIAL_GATE>;
index 03a76729d26cfec3a486938a858fba30e08c4383..7ce06f9f9f8ee70d8a3d2d817af4724539eada01 100644 (file)
@@ -76,6 +76,12 @@ properties:
   resets:
     maxItems: 1
 
+  wifi-2.4ghz-coexistence:
+    type: boolean
+    description: >
+      Should the pixel frequencies in the WiFi frequencies range be
+      avoided?
+
 required:
   - compatible
   - reg
index 31f085d8ab13e7c136ee35c265504e2eaf019f77..fd3113aa9ccdc2dd831e3b1006b1f68bdaf79150 100644 (file)
@@ -7,17 +7,17 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Toshiba TC358775 DSI to LVDS bridge bindings
 
 maintainers:
- - Vinay Simha BN <simhavcs@gmail.com>
 - Vinay Simha BN <simhavcs@gmail.com>
 
 description: |
- This binding supports DSI to LVDS bridge TC358775
 This binding supports DSI to LVDS bridge TC358775
 
- MIPI DSI-RX Data 4-lane, CLK 1-lane with data rates up to 800 Mbps/lane.
- Video frame size:
- Up to 1600x1200 24-bit/pixel resolution for single-link LVDS display panel
- limited by 135 MHz LVDS speed
- Up to WUXGA (1920x1200 24-bit pixels) resolution for dual-link LVDS display
- panel, limited by 270 MHz LVDS speed.
 MIPI DSI-RX Data 4-lane, CLK 1-lane with data rates up to 800 Mbps/lane.
 Video frame size:
 Up to 1600x1200 24-bit/pixel resolution for single-link LVDS display panel
 limited by 135 MHz LVDS speed
 Up to WUXGA (1920x1200 24-bit pixels) resolution for dual-link LVDS display
 panel, limited by 270 MHz LVDS speed.
 
 properties:
   compatible:
@@ -29,7 +29,7 @@ properties:
 
   vdd-supply:
     maxItems: 1
-    description:  1.2V LVDS Power Supply
+    description: 1.2V LVDS Power Supply
 
   vddio-supply:
     maxItems: 1
@@ -77,16 +77,18 @@ properties:
       - port@1
 
 required:
- - compatible
- - reg
- - vdd-supply
- - vddio-supply
- - stby-gpios
- - reset-gpios
- - ports
+  - compatible
+  - reg
+  - vdd-supply
+  - vddio-supply
+  - stby-gpios
+  - reset-gpios
+  - ports
+
+additionalProperties: false
 
 examples:
- - |
 - |
     #include <dt-bindings/gpio/gpio.h>
 
     /* For single-link LVDS display panel */
@@ -147,7 +149,7 @@ examples:
          };
      };
 
- - |
 - |
     /* For dual-link LVDS display panel */
 
     i2c@78b8000 {
index c60b3bd74337eb85995b815254fe47ea2a43c877..b2fcec4f22fd1087630ffe0a172b3fed3a4b796b 100644 (file)
@@ -13,9 +13,8 @@ properties:
   compatible:
     items:
       - enum:
-        - bananapi,lhr050h41
-        - feixin,k101-im2byl02
-
+          - bananapi,lhr050h41
+          - feixin,k101-im2byl02
       - const: ilitek,ili9881c
 
   backlight: true
index 937323cc9aaac12f3abae9f9941d0ea86c558932..51f423297ec8447b46575016d8b428644ba4822d 100644 (file)
@@ -37,6 +37,9 @@ properties:
 
   reset-gpios: true
 
+  'mantix,tp-rstn-gpios':
+    description: second reset line that triggers DSI config load
+
   backlight: true
 
 required:
@@ -63,6 +66,7 @@ examples:
             avee-supply = <&reg_avee>;
             vddi-supply = <&reg_1v8_p>;
             reset-gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;
+            mantix,tp-rstn-gpios = <&gpio1 24 GPIO_ACTIVE_LOW>;
             backlight = <&backlight>;
         };
     };
index a25387df0865aa94158976c9d26cf1adf580b964..57e5270a0741c0d93d83ccd3ff88f1c16e70d483 100644 (file)
@@ -48,6 +48,7 @@ required:
   - "#address-cells"
   - "#size-cells"
 
+additionalProperties: false
 
 examples:
   - |
index 6a0f3d90d682220df64442618173d3855d40bf54..8ca9e0a049d89ee27aaed14cfddb659a9fe65485 100644 (file)
@@ -1,6 +1,6 @@
-Aspeed AST2500 SoC EDAC node
+Aspeed BMC SoC EDAC node
 
-The Aspeed AST2500 SoC supports DDR3 and DDR4 memory with and without ECC (error
+The Aspeed BMC SoC supports DDR3 and DDR4 memory with and without ECC (error
 correction check).
 
 The memory controller supports SECDED (single bit error correction, double bit
@@ -11,7 +11,10 @@ Note, the bootloader must configure ECC mode in the memory controller.
 
 
 Required properties:
-- compatible: should be "aspeed,ast2500-sdram-edac"
+- compatible: should be one of
+       - "aspeed,ast2400-sdram-edac"
+       - "aspeed,ast2500-sdram-edac"
+       - "aspeed,ast2600-sdram-edac"
 - reg:        sdram controller register set should be <0x1e6e0000 0x174>
 - interrupts: should be AVIC interrupt #0
 
index 9810619a2b5c899aa5d0da640d755aec2a6fb477..7449736376788ba39515fce6b674324b5859ec5c 100644 (file)
@@ -81,14 +81,14 @@ properties:
   at25,byte-len:
     $ref: /schemas/types.yaml#/definitions/uint32
     description:
-       Total eeprom size in bytes. Deprecated, use "size" property instead.
+      Total eeprom size in bytes. Deprecated, use "size" property instead.
     deprecated: true
 
   at25,addr-mode:
     $ref: /schemas/types.yaml#/definitions/uint32
     description:
-       Addr-mode flags, as defined in include/linux/spi/eeprom.h.
-       Deprecated, use "address-width" property instead.
+      Addr-mode flags, as defined in include/linux/spi/eeprom.h.
+      Deprecated, use "address-width" property instead.
     deprecated: true
 
   at25,page-size:
index e2d2c10e536a640a135bf2d7d6d0282c9dc6410a..b032471831e7c711892787b6d279a7dfa46da974 100644 (file)
@@ -43,8 +43,8 @@ properties:
   gpio-controller: true
 
   gpio-line-names:
-      minItems: 1
-      maxItems: 8
+    minItems: 1
+    maxItems: 8
 
 required:
   - compatible
diff --git a/Documentation/devicetree/bindings/i2c/google,cros-ec-i2c-tunnel.yaml b/Documentation/devicetree/bindings/i2c/google,cros-ec-i2c-tunnel.yaml
new file mode 100644 (file)
index 0000000..b386e41
--- /dev/null
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/i2c/google,cros-ec-i2c-tunnel.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: I2C bus that tunnels through the ChromeOS EC (cros-ec)
+
+maintainers:
+  - Doug Anderson <dianders@chromium.org>
+  - Benson Leung <bleung@chromium.org>
+  - Enric Balletbo i Serra <enric.balletbo@collabora.com>
+
+description: |
+  On some ChromeOS board designs we've got a connection to the EC
+  (embedded controller) but no direct connection to some devices on the
+  other side of the EC (like a battery and PMIC).  To get access to
+  those devices we need to tunnel our i2c commands through the EC.
+
+  The node for this device should be under a cros-ec node like
+  google,cros-ec-spi or google,cros-ec-i2c.
+
+allOf:
+  - $ref: i2c-controller.yaml#
+
+properties:
+  compatible:
+    const: google,cros-ec-i2c-tunnel
+
+  google,remote-bus:
+    description: The EC bus we'd like to talk to.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+required:
+  - compatible
+  - google,remote-bus
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    spi0 {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        cros-ec@0 {
+            compatible = "google,cros-ec-spi";
+            reg = <0>;
+            spi-max-frequency = <5000000>;
+
+            i2c-tunnel {
+                compatible = "google,cros-ec-i2c-tunnel";
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                google,remote-bus = <0>;
+
+                battery: sbs-battery@b {
+                    compatible = "sbs,sbs-battery";
+                    reg = <0xb>;
+                    sbs,poll-retry-count = <1>;
+                };
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/i2c/i2c-cros-ec-tunnel.txt b/Documentation/devicetree/bindings/i2c/i2c-cros-ec-tunnel.txt
deleted file mode 100644 (file)
index 898f030..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-I2C bus that tunnels through the ChromeOS EC (cros-ec)
-======================================================
-On some ChromeOS board designs we've got a connection to the EC (embedded
-controller) but no direct connection to some devices on the other side of
-the EC (like a battery and PMIC).  To get access to those devices we need
-to tunnel our i2c commands through the EC.
-
-The node for this device should be under a cros-ec node like google,cros-ec-spi
-or google,cros-ec-i2c.
-
-
-Required properties:
-- compatible: google,cros-ec-i2c-tunnel
-- google,remote-bus: The EC bus we'd like to talk to.
-
-Optional child nodes:
-- One node per I2C device connected to the tunnelled I2C bus.
-
-
-Example:
-       cros-ec@0 {
-               compatible = "google,cros-ec-spi";
-
-               ...
-
-               i2c-tunnel {
-                       compatible = "google,cros-ec-i2c-tunnel";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-
-                       google,remote-bus = <0>;
-
-                       battery: sbs-battery@b {
-                               compatible = "sbs,sbs-battery";
-                               reg = <0xb>;
-                               sbs,poll-retry-count = <1>;
-                       };
-               };
-       }
index 0e7b4b8a7e48deee37153292cb3314f32c62c958..e1e65eb4f795975e3e4357eb8b76509d26c8bb4f 100644 (file)
@@ -19,11 +19,11 @@ properties:
   compatible:
     oneOf:
       - enum:
-        - ingenic,jz4770-i2c
-        - ingenic,x1000-i2c
+          - ingenic,jz4770-i2c
+          - ingenic,x1000-i2c
       - items:
-        - const: ingenic,jz4780-i2c
-        - const: ingenic,jz4770-i2c
+          - const: ingenic,jz4780-i2c
+          - const: ingenic,jz4770-i2c
 
   reg:
     maxItems: 1
index 6feafb7e531e303e70a3d9a45db2fcf2d7b9ca26..930f9e3904d7d9647879059be84c11a270e0be38 100644 (file)
@@ -43,4 +43,5 @@ examples:
         vref-supply = <&adc_vref>;
       };
     };
-...
\ No newline at end of file
+...
+
index d3733ad8785ae489e305b6c8a16f3430833d5801..8f32800fe5b73c24aab14f7b01f39f6733a1218e 100644 (file)
@@ -46,7 +46,8 @@ properties:
   spi-max-frequency: true
 
   spi-cpol: true
-  spi-cpha : true
+
+  spi-cpha: true
 
   "#io-channel-cells":
     const: 1
index 5d92b477e23f91e1065170e505bd871ce4293b15..4e695b97d0156ba916dac2913a191cb300bdb2a5 100644 (file)
@@ -22,8 +22,8 @@ properties:
   adc-reserved-channels:
     $ref: /schemas/types.yaml#/definitions/uint32
     description:
-       Bitmask of reserved channels, i.e. channels that cannot be
-       used by the OS.
+      Bitmask of reserved channels, i.e. channels that cannot be
+      used by the OS.
 
   clocks:
     maxItems: 1
index 9514c3381c422c7c79968852ea5becc4afd70da4..52490cbb0af08755427adc08403bd986eaafe133 100644 (file)
@@ -21,7 +21,7 @@ properties:
 
   gpios:
     description:
-       GPIO used for controlling the reset pin
+      GPIO used for controlling the reset pin
     maxItems: 1
 
   spi-max-frequency: true
index 6a176f551d755f55c4ec6f3a8d9bceb7e3450030..c1772b568cd1b10f7af038babb98f65094a72a43 100644 (file)
@@ -28,6 +28,8 @@ required:
   - reg
   - vref-supply
 
+additionalProperties: false
+
 examples:
   - |
     i2c {
index dc870eb2875f8563b7f62d9d664056fe90945381..7037f82ec7530f99b111e94416d621dd8d7710e2 100644 (file)
@@ -32,6 +32,8 @@ required:
   - compatible
   - reg
 
+additionalProperties: false
+
 examples:
   - |
     i2c0 {
diff --git a/Documentation/devicetree/bindings/input/cros-ec-keyb.txt b/Documentation/devicetree/bindings/input/cros-ec-keyb.txt
deleted file mode 100644 (file)
index 0f6355c..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-ChromeOS EC Keyboard
-
-Google's ChromeOS EC Keyboard is a simple matrix keyboard implemented on
-a separate EC (Embedded Controller) device. It provides a message for reading
-key scans from the EC. These are then converted into keycodes for processing
-by the kernel.
-
-This binding is based on matrix-keymap.txt and extends/modifies it as follows:
-
-Required properties:
-- compatible: "google,cros-ec-keyb"
-
-Optional properties:
-- google,needs-ghost-filter: True to enable a ghost filter for the matrix
-keyboard. This is recommended if the EC does not have its own logic or
-hardware for this.
-
-
-Example:
-
-cros-ec-keyb {
-       compatible = "google,cros-ec-keyb";
-       keypad,num-rows = <8>;
-       keypad,num-columns = <13>;
-       google,needs-ghost-filter;
-       /*
-        * Keymap entries take the form of 0xRRCCKKKK where
-        * RR=Row CC=Column KKKK=Key Code
-        * The values below are for a US keyboard layout and
-        * are taken from the Linux driver. Note that the
-        * 102ND key is not used for US keyboards.
-        */
-       linux,keymap = <
-               /* CAPSLCK F1         B          F10     */
-               0x0001003a 0x0002003b 0x00030030 0x00040044
-               /* N       =          R_ALT      ESC     */
-               0x00060031 0x0008000d 0x000a0064 0x01010001
-               /* F4      G          F7         H       */
-               0x0102003e 0x01030022 0x01040041 0x01060023
-               /* '       F9         BKSPACE    L_CTRL  */
-               0x01080028 0x01090043 0x010b000e 0x0200001d
-               /* TAB     F3         T          F6      */
-               0x0201000f 0x0202003d 0x02030014 0x02040040
-               /* ]       Y          102ND      [       */
-               0x0205001b 0x02060015 0x02070056 0x0208001a
-               /* F8      GRAVE      F2         5       */
-               0x02090042 0x03010029 0x0302003c 0x03030006
-               /* F5      6          -          \       */
-               0x0304003f 0x03060007 0x0308000c 0x030b002b
-               /* R_CTRL  A          D          F       */
-               0x04000061 0x0401001e 0x04020020 0x04030021
-               /* S       K          J          ;       */
-               0x0404001f 0x04050025 0x04060024 0x04080027
-               /* L       ENTER      Z          C       */
-               0x04090026 0x040b001c 0x0501002c 0x0502002e
-               /* V       X          ,          M       */
-               0x0503002f 0x0504002d 0x05050033 0x05060032
-               /* L_SHIFT /          .          SPACE   */
-               0x0507002a 0x05080035 0x05090034 0x050B0039
-               /* 1       3          4          2       */
-               0x06010002 0x06020004 0x06030005 0x06040003
-               /* 8       7          0          9       */
-               0x06050009 0x06060008 0x0608000b 0x0609000a
-               /* L_ALT   DOWN       RIGHT      Q       */
-               0x060a0038 0x060b006c 0x060c006a 0x07010010
-               /* E       R          W          I       */
-               0x07020012 0x07030013 0x07040011 0x07050017
-               /* U       R_SHIFT    P          O       */
-               0x07060016 0x07070036 0x07080019 0x07090018
-               /* UP      LEFT    */
-               0x070b0067 0x070c0069>;
-};
diff --git a/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml b/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml
new file mode 100644 (file)
index 0000000..8e50c14
--- /dev/null
@@ -0,0 +1,92 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/input/google,cros-ec-keyb.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ChromeOS EC Keyboard
+
+maintainers:
+  - Simon Glass <sjg@chromium.org>
+  - Benson Leung <bleung@chromium.org>
+  - Enric Balletbo i Serra <enric.balletbo@collabora.com>
+
+description: |
+  Google's ChromeOS EC Keyboard is a simple matrix keyboard
+  implemented on a separate EC (Embedded Controller) device. It provides
+  a message for reading key scans from the EC. These are then converted
+  into keycodes for processing by the kernel.
+
+allOf:
+  - $ref: "/schemas/input/matrix-keymap.yaml#"
+
+properties:
+  compatible:
+    const: google,cros-ec-keyb
+
+  google,needs-ghost-filter:
+    description:
+      Enable a ghost filter for the matrix keyboard. This is recommended
+      if the EC does not have its own logic or hardware for this.
+    type: boolean
+
+required:
+  - compatible
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    cros-ec-keyb {
+        compatible = "google,cros-ec-keyb";
+        keypad,num-rows = <8>;
+        keypad,num-columns = <13>;
+        google,needs-ghost-filter;
+        /*
+         * Keymap entries take the form of 0xRRCCKKKK where
+         * RR=Row CC=Column KKKK=Key Code
+         * The values below are for a US keyboard layout and
+         * are taken from the Linux driver. Note that the
+         * 102ND key is not used for US keyboards.
+         */
+        linux,keymap = <
+            /* CAPSLCK F1         B          F10     */
+            0x0001003a 0x0002003b 0x00030030 0x00040044
+            /* N       =          R_ALT      ESC     */
+            0x00060031 0x0008000d 0x000a0064 0x01010001
+            /* F4      G          F7         H       */
+            0x0102003e 0x01030022 0x01040041 0x01060023
+            /* '       F9         BKSPACE    L_CTRL  */
+            0x01080028 0x01090043 0x010b000e 0x0200001d
+            /* TAB     F3         T          F6      */
+            0x0201000f 0x0202003d 0x02030014 0x02040040
+            /* ]       Y          102ND      [       */
+            0x0205001b 0x02060015 0x02070056 0x0208001a
+            /* F8      GRAVE      F2         5       */
+            0x02090042 0x03010029 0x0302003c 0x03030006
+            /* F5      6          -          \       */
+            0x0304003f 0x03060007 0x0308000c 0x030b002b
+            /* R_CTRL  A          D          F       */
+            0x04000061 0x0401001e 0x04020020 0x04030021
+            /* S       K          J          ;       */
+            0x0404001f 0x04050025 0x04060024 0x04080027
+            /* L       ENTER      Z          C       */
+            0x04090026 0x040b001c 0x0501002c 0x0502002e
+            /* V       X          ,          M       */
+            0x0503002f 0x0504002d 0x05050033 0x05060032
+            /* L_SHIFT /          .          SPACE   */
+            0x0507002a 0x05080035 0x05090034 0x050B0039
+            /* 1       3          4          2       */
+            0x06010002 0x06020004 0x06030005 0x06040003
+            /* 8       7          0          9       */
+            0x06050009 0x06060008 0x0608000b 0x0609000a
+            /* L_ALT   DOWN       RIGHT      Q       */
+            0x060a0038 0x060b006c 0x060c006a 0x07010010
+            /* E       R          W          I       */
+            0x07020012 0x07030013 0x07040011 0x07050017
+            /* U       R_SHIFT    P          O       */
+            0x07060016 0x07070036 0x07080019 0x07090018
+            /* UP      LEFT    */
+            0x070b0067 0x070c0069>;
+    };
index bbf79d125675dfef4cd07b95ab528f797563d013..1c4c009dedd041c17ebd30aeeeb5ff357b275491 100644 (file)
@@ -94,12 +94,12 @@ properties:
               instances.
 
 required:
- - compatible
- - reg
- - interrupts
- - interrupt-names
- - interrupt-controller
- - "#interrupt-cells"
 - compatible
 - reg
 - interrupts
 - interrupt-names
 - interrupt-controller
 - "#interrupt-cells"
 
 additionalProperties: false
 
index c7cd05656a3e9cf38ac5b66f833ce42d74561502..b5af120114990a7e42acb32824efc91a7232c507 100644 (file)
@@ -32,6 +32,11 @@ description: |
                        | | vint  | bit  |  | 0 |.....|63| vintx  |
                        | +--------------+  +------------+        |
                        |                                         |
+                       |      Unmap                              |
+                       | +--------------+                        |
+  Unmapped events ---->| |   umapidx    |-------------------------> Globalevents
+                       | +--------------+                        |
+                       |                                         |
                        +-----------------------------------------+
 
   Configuration of these Intmap registers that maps global events to vint is
@@ -70,6 +75,11 @@ properties:
         - description: |
             "limit" specifies the limit for translation
 
+  ti,unmapped-event-sources:
+    $ref: /schemas/types.yaml#definitions/phandle-array
+    description:
+      Array of phandles to DMA controllers where the unmapped events originate.
+
 required:
   - compatible
   - reg
@@ -79,6 +89,8 @@ required:
   - ti,sci-dev-id
   - ti,interrupt-ranges
 
+unevaluatedProperties: false
+
 examples:
   - |
     bus {
index cff6a956afb44e287e9be0d9b15b693e4c6fdaa2..e12aee42b12685fe6a26233bc79a73a8d30e6137 100644 (file)
@@ -88,6 +88,8 @@ required:
   - ti,sci-dev-id
   - ti,interrupt-ranges
 
+unevaluatedProperties: false
+
 examples:
   - |
     main_gpio_intr: interrupt-controller0 {
index 4e7e95e331a57dc26dd598c87eb8a8477b2fe062..bc817f77d2b109f20de0e296625e0d861abbfd83 100644 (file)
@@ -32,3 +32,5 @@ properties:
       that a LED can be made so bright that it gets damaged or causes damage
       due to restrictions in a specific system, such as mounting conditions.
     $ref: /schemas/types.yaml#definitions/uint32
+
+additionalProperties: true
index 08b6700ca61edecfe898f987d7d63716f993356a..f1211e7045f12f3696c029e9af8b4c455fce8064 100644 (file)
@@ -43,7 +43,7 @@ properties:
       LED_COLOR_ID available, add a new one.
     $ref: /schemas/types.yaml#definitions/uint32
     minimum: 0
-    maximum: 8
+    maximum: 9
 
   function-enumerator:
     description:
index b1a53f054b895e4c88b195d5cf8f4f817596e57d..37445c68cdef9aac2bab2ef46323c3bf2cdc516b 100644 (file)
@@ -16,7 +16,7 @@ description: |
   modules. This is achieved by adding multi-led nodes layer to the
   monochrome LED bindings.
   The nodes and properties defined in this document are unique to the multicolor
-  LED class.  Common LED nodes and properties are inherited from the common.txt
+  LED class.  Common LED nodes and properties are inherited from the common.yaml
   within this documentation directory.
 
 patternProperties:
@@ -25,10 +25,11 @@ patternProperties:
     description: Represents the LEDs that are to be grouped.
     properties:
       color:
-        const: 8  # LED_COLOR_ID_MULTI
         description: |
-          For multicolor LED support this property should be defined as
-          LED_COLOR_ID_MULTI which can be found in include/linux/leds/common.h.
+          For multicolor LED support this property should be defined as either
+          LED_COLOR_ID_RGB or LED_COLOR_ID_MULTI which can be found in
+          include/linux/leds/common.h.
+        enum: [ 8, 9 ]
 
     $ref: "common.yaml#"
 
index 947542a253ec6bae8ad79292231ef87be69860c1..c192b5feadc76c80147ac2c99c1f34563d2256bd 100644 (file)
@@ -46,6 +46,12 @@ properties:
   vled-supply:
     description: LED supply.
 
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 0
+
 patternProperties:
   '^multi-led@[0-9a-f]$':
     type: object
@@ -69,6 +75,8 @@ required:
   - compatible
   - reg
 
+additionalProperties: false
+
 examples:
   - |
    #include <dt-bindings/gpio/gpio.h>
index cf48cd806e0022a793663cd8d13fde504168ea02..7771ecaac58683a68bd2a6bb03deb1b6b4b486e4 100644 (file)
@@ -47,7 +47,7 @@ Example:
                interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_LOW>;
                clocks = <&infracfg CLK_INFRA_GCE>;
                clock-names = "gce";
-               #mbox-cells = <3>;
+               #mbox-cells = <2>;
        };
 
 Example for a client device:
index 074243c40891088b5938f0f025a7732aff1eca6d..08af356f5d275d590a57f232e88f075c8f93554c 100644 (file)
@@ -17,7 +17,7 @@ properties:
   compatible:
     items:
       - enum:
-        - dell,wyse-ariel-ec  # Dell Wyse Ariel board (3020)
+          - dell,wyse-ariel-ec  # Dell Wyse Ariel board (3020)
       - const: ene,kb3930
   reg:
     maxItems: 1
index f49c0d5d31ad20ed82ae5658a0f0f3f0c8fd043b..76bf16ee27ec746fdb2b49f4b73efeb3a3301008 100644 (file)
@@ -59,6 +59,14 @@ properties:
       whether this nvram is present or not.
     type: boolean
 
+  mtk,rpmsg-name:
+    description:
+      Must be defined if the cros-ec is a rpmsg device for a Mediatek
+      ARM Cortex M4 Co-processor. Contains the name pf the rpmsg
+      device. Used to match the subnode to the rpmsg device announced by
+      the SCP.
+    $ref: "/schemas/types.yaml#/definitions/string"
+
   spi-max-frequency:
     description: Maximum SPI frequency of the device in Hz.
 
@@ -71,6 +79,54 @@ properties:
   wakeup-source:
     description: Button can wake-up the system.
 
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 0
+
+  typec:
+    $ref: "/schemas/chrome/google,cros-ec-typec.yaml#"
+
+  ec-pwm:
+    $ref: "/schemas/pwm/google,cros-ec-pwm.yaml#"
+
+  keyboard-controller:
+    $ref: "/schemas/input/google,cros-ec-keyb.yaml#"
+
+  codecs:
+    type: object
+    additionalProperties: false
+
+    properties:
+      '#address-cells':
+        const: 2
+
+      '#size-cells':
+        const: 1
+
+    patternProperties:
+      "^ec-codec@[a-f0-9]+$":
+        type: object
+        $ref: "/schemas/sound/google,cros-ec-codec.yaml#"
+
+    required:
+      - "#address-cells"
+      - "#size-cells"
+
+patternProperties:
+  "^i2c-tunnel[0-9]*$":
+    type: object
+    $ref: "/schemas/i2c/google,cros-ec-i2c-tunnel.yaml#"
+
+  "^regulator@[0-9]+$":
+    type: object
+    $ref: "/schemas/regulator/google,cros-ec-regulator.yaml#"
+
+  "^extcon[0-9]*$":
+    type: object
+    $ref: "/schemas/extcon/extcon-usbc-cros-ec.yaml#"
+
 required:
   - compatible
 
index dc21b4630c25cdaa407c8c271346139cc93a1a01..ee00d414df100142d52d5a826917f35f80c79203 100644 (file)
@@ -52,4 +52,7 @@ properties:
         items:
           - const: yna,cu2000-neo
           - const: ingenic,x2000e
+
+additionalProperties: true
+
 ...
index d25e80aa8b2aec73eeb22858c265516e01ab8b22..9fee6708e6f5937698dfa8f06ade8b7d863ca0fd 100644 (file)
@@ -36,4 +36,7 @@ properties:
       - description: Virtual Loongson64 Quad Core + VirtIO
         items:
           - const: loongson,loongson64v-4core-virtio
+
+additionalProperties: true
+
 ...
index 58fe9d02a781a035c1b35a0a234a98f8652293bf..0753289fba844cc517d31a55d12d4af7f8ec1f1a 100644 (file)
@@ -32,11 +32,11 @@ allOf:
         clock-output-names:
           oneOf:
             - items:
-              - const: clk_out_sd0
-              - const: clk_in_sd0
+                - const: clk_out_sd0
+                - const: clk_in_sd0
             - items:
-              - const: clk_out_sd1
-              - const: clk_in_sd1
+                - const: clk_out_sd1
+                - const: clk_in_sd1
 
 properties:
   compatible:
index 55883290543b93f520227e41c9d2831d51abe67b..69ff065c9a39ad68f5409210cc49b925cbb02935 100644 (file)
@@ -46,6 +46,8 @@ required:
   - clocks
   - clock-names
 
+unevaluatedProperties: false
+
 examples:
   - |
     #include <dt-bindings/interrupt-controller/arm-gic.h>
index ac79f3adf20b0d2103cad46e7cb8f66efc780af7..1ae945434c53c8ed38b0e094c84043202dbf3c5a 100644 (file)
@@ -3,7 +3,7 @@
 %YAML 1.2
 ---
 $id: "http://devicetree.org/schemas/mmc/sdhci-am654.yaml#"
-$schema : "http://devicetree.org/meta-schemas/core.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
 
 title: TI AM654 MMC Controller
 
@@ -163,13 +163,12 @@ properties:
   ti,driver-strength-ohm:
     description: DLL drive strength in ohms
     $ref: "/schemas/types.yaml#/definitions/uint32"
-    oneOf:
-      - enum:
-        - 33
-        - 40
-        - 50
-        - 66
-        - 100
+    enum:
+      - 33
+      - 40
+      - 50
+      - 66
+      - 100
 
   ti,strobe-sel:
     description: strobe select delay for HS400 speed mode.
@@ -187,6 +186,8 @@ required:
   - clock-names
   - ti,otap-del-sel-legacy
 
+unevaluatedProperties: false
+
 examples:
   - |
     #include <dt-bindings/interrupt-controller/irq.h>
diff --git a/Documentation/devicetree/bindings/net/can/can-controller.yaml b/Documentation/devicetree/bindings/net/can/can-controller.yaml
new file mode 100644 (file)
index 0000000..9cf2ae0
--- /dev/null
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/can/can-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: CAN Controller Generic Binding
+
+maintainers:
+  - Marc Kleine-Budde <mkl@pengutronix.de>
+
+properties:
+  $nodename:
+    pattern: "^can(@.*)?$"
+
+additionalProperties: true
+
+...
diff --git a/Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml b/Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml
new file mode 100644 (file)
index 0000000..13875ea
--- /dev/null
@@ -0,0 +1,139 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/can/fsl,flexcan.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title:
+  Flexcan CAN controller on Freescale's ARM and PowerPC system-on-a-chip (SOC).
+
+maintainers:
+  - Marc Kleine-Budde <mkl@pengutronix.de>
+
+allOf:
+  - $ref: can-controller.yaml#
+
+properties:
+  compatible:
+    oneOf:
+      - enum:
+          - fsl,imx8qm-flexcan
+          - fsl,imx8mp-flexcan
+          - fsl,imx6q-flexcan
+          - fsl,imx28-flexcan
+          - fsl,imx25-flexcan
+          - fsl,p1010-flexcan
+          - fsl,vf610-flexcan
+          - fsl,ls1021ar2-flexcan
+          - fsl,lx2160ar1-flexcan
+      - items:
+          - enum:
+              - fsl,imx53-flexcan
+              - fsl,imx35-flexcan
+          - const: fsl,imx25-flexcan
+      - items:
+          - enum:
+              - fsl,imx7d-flexcan
+              - fsl,imx6ul-flexcan
+              - fsl,imx6sx-flexcan
+          - const: fsl,imx6q-flexcan
+      - items:
+          - enum:
+              - fsl,ls1028ar1-flexcan
+          - const: fsl,lx2160ar1-flexcan
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 2
+
+  clock-names:
+    items:
+      - const: ipg
+      - const: per
+
+  clock-frequency:
+    description: |
+      The oscillator frequency driving the flexcan device, filled in by the
+      boot loader. This property should only be used the used operating system
+      doesn't support the clocks and clock-names property.
+
+  xceiver-supply:
+    description: Regulator that powers the CAN transceiver.
+
+  big-endian:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description: |
+      This means the registers of FlexCAN controller are big endian. This is
+      optional property.i.e. if this property is not present in device tree
+      node then controller is assumed to be little endian. If this property is
+      present then controller is assumed to be big endian.
+
+  fsl,stop-mode:
+    description: |
+      Register bits of stop mode control.
+
+      The format should be as follows:
+      <gpr req_gpr req_bit>
+      gpr is the phandle to general purpose register node.
+      req_gpr is the gpr register offset of CAN stop request.
+      req_bit is the bit offset of CAN stop request.
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    items:
+      items:
+        - description: The 'gpr' is the phandle to general purpose register node.
+        - description: The 'req_gpr' is the gpr register offset of CAN stop request.
+          maximum: 0xff
+        - description: The 'req_bit' is the bit offset of CAN stop request.
+          maximum: 0x1f
+
+  fsl,clk-source:
+    description: |
+      Select the clock source to the CAN Protocol Engine (PE). It's SoC
+      implementation dependent. Refer to RM for detailed definition. If this
+      property is not set in device tree node then driver selects clock source 1
+      by default.
+      0: clock source 0 (oscillator clock)
+      1: clock source 1 (peripheral clock)
+    $ref: /schemas/types.yaml#/definitions/uint32
+    default: 1
+    minimum: 0
+    maximum: 1
+
+  wakeup-source:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      Enable CAN remote wakeup.
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    can@1c000 {
+        compatible = "fsl,p1010-flexcan";
+        reg = <0x1c000 0x1000>;
+        interrupts = <48 0x2>;
+        interrupt-parent = <&mpic>;
+        clock-frequency = <200000000>;
+        fsl,clk-source = <0>;
+    };
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    can@2090000 {
+        compatible = "fsl,imx6q-flexcan";
+        reg = <0x02090000 0x4000>;
+        interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&clks 1>, <&clks 2>;
+        clock-names = "ipg", "per";
+        fsl,stop-mode = <&gpr 0x34 28>;
+    };
diff --git a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
deleted file mode 100644 (file)
index e10b6eb..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-Flexcan CAN controller on Freescale's ARM and PowerPC system-on-a-chip (SOC).
-
-Required properties:
-
-- compatible : Should be "fsl,<processor>-flexcan"
-
-  where <processor> is imx8qm, imx6q, imx28, imx53, imx35, imx25, p1010,
-  vf610, ls1021ar2, lx2160ar1, ls1028ar1.
-
-  The ls1028ar1 must be followed by lx2160ar1, e.g.
-   - "fsl,ls1028ar1-flexcan", "fsl,lx2160ar1-flexcan"
-
-  An implementation should also claim any of the following compatibles
-  that it is fully backwards compatible with:
-
-  - fsl,p1010-flexcan
-
-- reg : Offset and length of the register set for this device
-- interrupts : Interrupt tuple for this device
-
-Optional properties:
-
-- clock-frequency : The oscillator frequency driving the flexcan device
-
-- xceiver-supply: Regulator that powers the CAN transceiver
-
-- big-endian: This means the registers of FlexCAN controller are big endian.
-              This is optional property.i.e. if this property is not present in
-              device tree node then controller is assumed to be little endian.
-              if this property is present then controller is assumed to be big
-              endian.
-
-- fsl,stop-mode: register bits of stop mode control, the format is
-                <&gpr req_gpr req_bit>.
-                gpr is the phandle to general purpose register node.
-                req_gpr is the gpr register offset of CAN stop request.
-                req_bit is the bit offset of CAN stop request.
-
-- fsl,clk-source: Select the clock source to the CAN Protocol Engine (PE).
-                 It's SoC Implementation dependent. Refer to RM for detailed
-                 definition. If this property is not set in device tree node
-                 then driver selects clock source 1 by default.
-                 0: clock source 0 (oscillator clock)
-                 1: clock source 1 (peripheral clock)
-
-- wakeup-source: enable CAN remote wakeup
-
-Example:
-
-       can@1c000 {
-               compatible = "fsl,p1010-flexcan";
-               reg = <0x1c000 0x1000>;
-               interrupts = <48 0x2>;
-               interrupt-parent = <&mpic>;
-               clock-frequency = <200000000>; // filled in by bootloader
-               fsl,clk-source = <0>; // select clock source 0 for PE
-       };
index 3613c2c8f75d785d23468e8e3ca017ff44090ce5..0968b40aef1e8147a63087f8f360107285fb900d 100644 (file)
@@ -33,7 +33,7 @@ tcan4x5x: tcan4x5x@0 {
                spi-max-frequency = <10000000>;
                bosch,mram-cfg = <0x0 0 0 32 0 0 1 1>;
                interrupt-parent = <&gpio1>;
-               interrupts = <14 GPIO_ACTIVE_LOW>;
+               interrupts = <14 IRQ_TYPE_LEVEL_LOW>;
                device-state-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
                device-wake-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
                reset-gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
index fa3ebba4e63584b34ece8b8c3d44c26a72709af1..c1948ce00081b66e18d65769a6700b48455f4ebc 100644 (file)
@@ -46,6 +46,8 @@ required:
   - clocks
   - clock-names
 
+unevaluatedProperties: false
+
 examples:
 # FIXME: Remove defines and include the correct header file
 # once it is available in mainline.
index cfaf8899891871b2f86d83cec69ef1effebe3fc9..9e4dc510a40aa3662bcacb8a2e9c4e14f782a3cb 100644 (file)
@@ -25,7 +25,7 @@ Example (for ARM-based BeagleBone with NPC100 NFC controller on I2C2):
                clock-frequency = <100000>;
 
                interrupt-parent = <&gpio1>;
-               interrupts = <29 GPIO_ACTIVE_HIGH>;
+               interrupts = <29 IRQ_TYPE_LEVEL_HIGH>;
 
                enable-gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>;
                firmware-gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>;
index 92f399ec22b87503029b8a86e40e50ef17c16434..2bd82562ce8e95326ed35feddb663f2a4dfa1833 100644 (file)
@@ -25,7 +25,7 @@ Example (for ARM-based BeagleBone with PN544 on I2C2):
                clock-frequency = <400000>;
 
                interrupt-parent = <&gpio1>;
-               interrupts = <17 GPIO_ACTIVE_HIGH>;
+               interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
 
                enable-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
                firmware-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
index 55913534cbc2b843d91d5d81c390d6a3c16a8998..75e8712e903a6ce9381e4cc0576bbcde32fb08e9 100644 (file)
@@ -65,6 +65,8 @@ properties:
 required:
   - reg
 
+unevaluatedProperties: false
+
 examples:
   - |
     mdio0 {
index f4292d2c54e3c4201561e2828a6b285926e0e4ec..d6cf8a560ef00c42d9f03424061eba51550eb852 100644 (file)
@@ -29,16 +29,16 @@ properties:
   reg-names:
     oneOf:
       - items:
-        - const: dbi
-        - const: dbi2
-        - const: link
-        - const: addr_space
+          - const: dbi
+          - const: dbi2
+          - const: link
+          - const: addr_space
       - items:
-        - const: dbi
-        - const: dbi2
-        - const: link
-        - const: addr_space
-        - const: atu
+          - const: dbi
+          - const: dbi2
+          - const: link
+          - const: addr_space
+          - const: atu
 
   clocks:
     maxItems: 2
index bab2ff4d9dc98bb53be0d00068919681df1cde7d..34756347a14ef59e5242f022a41e35fde3f77097 100644 (file)
@@ -31,10 +31,10 @@ properties:
   clock-names:
     oneOf:
       - items:          # for PXs2
-        - const: link
+          - const: link
       - items:          # for others
-        - const: link
-        - const: phy
+          - const: link
+          - const: phy
 
   resets:
     maxItems: 2
index 15207ca9548f2f0144ba914ba1a24af5a9a6bdeb..83d5d0aceb04ef19adec4ade54560414f4027206 100644 (file)
@@ -7,23 +7,23 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: OMAP USB2 PHY
 
 maintainers:
- - Kishon Vijay Abraham I <kishon@ti.com>
- - Roger Quadros <rogerq@ti.com>
 - Kishon Vijay Abraham I <kishon@ti.com>
 - Roger Quadros <rogerq@ti.com>
 
 properties:
   compatible:
     oneOf:
       - items:
-        - enum:
-          - ti,dra7x-usb2
-          - ti,dra7x-usb2-phy2
-          - ti,am654-usb2
-        - enum:
-          - ti,omap-usb2
+          - enum:
+              - ti,dra7x-usb2
+              - ti,dra7x-usb2-phy2
+              - ti,am654-usb2
+          - enum:
+              - ti,omap-usb2
       - items:
-        - const: ti,am437x-usb2
+          - const: ti,am437x-usb2
       - items:
-        - const: ti,omap-usb2
+          - const: ti,omap-usb2
 
   reg:
     maxItems: 1
@@ -62,6 +62,8 @@ required:
   - clocks
   - clock-names
 
+additionalProperties: false
+
 examples:
   - |
     usb0_phy: phy@4100000 {
index 33391d30c00c5008cc7a2b37e82fd50a7c54dd06..ccdd9e3820d737016724135bb527b03a49130ad5 100644 (file)
@@ -76,22 +76,22 @@ patternProperties:
             items:
               oneOf:
                 - enum: [lcd0_d18_mfp, rmii_crs_dv_mfp, rmii_txd0_mfp,
-                    rmii_txd1_mfp, rmii_txen_mfp, rmii_rxen_mfp, rmii_rxd1_mfp,
-                    rmii_rxd0_mfp, rmii_ref_clk_mfp, i2s_d0_mfp, i2s_pcm1_mfp,
-                    i2s0_pcm0_mfp, i2s1_pcm0_mfp, i2s_d1_mfp, ks_in2_mfp,
-                    ks_in1_mfp, ks_in0_mfp, ks_in3_mfp, ks_out0_mfp,
-                    ks_out1_mfp, ks_out2_mfp, lvds_o_pn_mfp, dsi_dn0_mfp,
-                    dsi_dp2_mfp, lcd0_d17_mfp, dsi_dp3_mfp, dsi_dn3_mfp,
-                    dsi_dp0_mfp, lvds_ee_pn_mfp, spi0_i2c_pcm_mfp,
-                    spi0_i2s_pcm_mfp, dsi_dnp1_cp_mfp, lvds_e_pn_mfp,
-                    dsi_dn2_mfp, uart2_rtsb_mfp, uart2_ctsb_mfp, uart3_rtsb_mfp,
-                    uart3_ctsb_mfp, sd0_d0_mfp, sd0_d1_mfp, sd0_d2_d3_mfp,
-                    sd1_d0_d3_mfp, sd0_cmd_mfp, sd0_clk_mfp, sd1_cmd_mfp,
-                    uart0_rx_mfp, clko_25m_mfp, csi_cn_cp_mfp, sens0_ckout_mfp,
-                    uart0_tx_mfp, i2c0_mfp, csi_dn_dp_mfp, sen0_pclk_mfp,
-                    pcm1_in_mfp, pcm1_clk_mfp, pcm1_sync_mfp, pcm1_out_mfp,
-                    dnand_data_wr_mfp, dnand_acle_ce0_mfp, nand_ceb2_mfp,
-                    nand_ceb3_mfp]
+                         rmii_txd1_mfp, rmii_txen_mfp, rmii_rxen_mfp, rmii_rxd1_mfp,
+                         rmii_rxd0_mfp, rmii_ref_clk_mfp, i2s_d0_mfp, i2s_pcm1_mfp,
+                         i2s0_pcm0_mfp, i2s1_pcm0_mfp, i2s_d1_mfp, ks_in2_mfp,
+                         ks_in1_mfp, ks_in0_mfp, ks_in3_mfp, ks_out0_mfp,
+                         ks_out1_mfp, ks_out2_mfp, lvds_o_pn_mfp, dsi_dn0_mfp,
+                         dsi_dp2_mfp, lcd0_d17_mfp, dsi_dp3_mfp, dsi_dn3_mfp,
+                         dsi_dp0_mfp, lvds_ee_pn_mfp, spi0_i2c_pcm_mfp,
+                         spi0_i2s_pcm_mfp, dsi_dnp1_cp_mfp, lvds_e_pn_mfp,
+                         dsi_dn2_mfp, uart2_rtsb_mfp, uart2_ctsb_mfp, uart3_rtsb_mfp,
+                         uart3_ctsb_mfp, sd0_d0_mfp, sd0_d1_mfp, sd0_d2_d3_mfp,
+                         sd1_d0_d3_mfp, sd0_cmd_mfp, sd0_clk_mfp, sd1_cmd_mfp,
+                         uart0_rx_mfp, clko_25m_mfp, csi_cn_cp_mfp, sens0_ckout_mfp,
+                         uart0_tx_mfp, i2c0_mfp, csi_dn_dp_mfp, sen0_pclk_mfp,
+                         pcm1_in_mfp, pcm1_clk_mfp, pcm1_sync_mfp, pcm1_out_mfp,
+                         dnand_data_wr_mfp, dnand_acle_ce0_mfp, nand_ceb2_mfp,
+                         nand_ceb3_mfp]
             minItems: 1
             maxItems: 32
 
@@ -100,10 +100,10 @@ patternProperties:
               Specify the alternative function to be configured for the
               given gpio pin groups.
             enum: [nor, eth_rmii, eth_smii, spi0, spi1, spi2, spi3, sens0,
-              sens1, uart0, uart1, uart2, uart3, uart4, uart5, uart6, i2s0,
-              i2s1, pcm1, pcm0, ks, jtag, pwm0, pwm1, pwm2, pwm3, pwm4, pwm5,
-              p0, sd0, sd1, sd2, i2c0, i2c1, i2c3, dsi, lvds, usb30, clko_25m,
-              mipi_csi, nand, spdif, ts, lcd0]
+                   sens1, uart0, uart1, uart2, uart3, uart4, uart5, uart6, i2s0,
+                   i2s1, pcm1, pcm0, ks, jtag, pwm0, pwm1, pwm2, pwm3, pwm4, pwm5,
+                   p0, sd0, sd1, sd2, i2c0, i2c1, i2c3, dsi, lvds, usb30, clko_25m,
+                   mipi_csi, nand, spdif, ts, lcd0]
 
         required:
           - groups
@@ -126,14 +126,14 @@ patternProperties:
             items:
               oneOf:
                 - enum: [sirq_drv, rmii_txd01_txen_drv, rmii_rxer_drv,
-                    rmii_crs_drv, rmii_rxd10_drv, rmii_ref_clk_drv,
-                    smi_mdc_mdio_drv, i2s_d0_drv, i2s_bclk0_drv, i2s3_drv,
-                    i2s13_drv, pcm1_drv, ks_in_drv, ks_out_drv, lvds_all_drv,
-                    lcd_dsi_drv, dsi_drv, sd0_d0_d3_drv, sd1_d0_d3_drv,
-                    sd0_cmd_drv, sd0_clk_drv, sd1_cmd_drv, sd1_clk_drv,
-                    spi0_all_drv, uart0_rx_drv, uart0_tx_drv, uart2_all_drv,
-                    i2c0_all_drv, i2c12_all_drv, sens0_pclk_drv,
-                    sens0_ckout_drv, uart3_all_drv]
+                         rmii_crs_drv, rmii_rxd10_drv, rmii_ref_clk_drv,
+                         smi_mdc_mdio_drv, i2s_d0_drv, i2s_bclk0_drv, i2s3_drv,
+                         i2s13_drv, pcm1_drv, ks_in_drv, ks_out_drv, lvds_all_drv,
+                         lcd_dsi_drv, dsi_drv, sd0_d0_d3_drv, sd1_d0_d3_drv,
+                         sd0_cmd_drv, sd0_clk_drv, sd1_cmd_drv, sd1_clk_drv,
+                         spi0_all_drv, uart0_rx_drv, uart0_tx_drv, uart2_all_drv,
+                         i2c0_all_drv, i2c12_all_drv, sens0_pclk_drv,
+                         sens0_ckout_drv, uart3_all_drv]
             minItems: 1
             maxItems: 32
 
@@ -144,29 +144,29 @@ patternProperties:
             items:
               oneOf:
                 - enum: [dnand_dqs, dnand_dqsn, eth_txd0, eth_txd1, eth_txen,
-                    eth_rxer, eth_crs_dv, eth_rxd1, eth_rxd0, eth_ref_clk,
-                    eth_mdc, eth_mdio, sirq0, sirq1, sirq2, i2s_d0, i2s_bclk0,
-                    i2s_lrclk0, i2s_mclk0, i2s_d1, i2s_bclk1, i2s_lrclk1,
-                    i2s_mclk1, ks_in0, ks_in1, ks_in2, ks_in3, ks_out0, ks_out1,
-                    ks_out2, lvds_oep, lvds_oen, lvds_odp, lvds_odn, lvds_ocp,
-                    lvds_ocn, lvds_obp, lvds_obn, lvds_oap, lvds_oan, lvds_eep,
-                    lvds_een, lvds_edp, lvds_edn, lvds_ecp, lvds_ecn, lvds_ebp,
-                    lvds_ebn, lvds_eap, lvds_ean, lcd0_d18, lcd0_d17, dsi_dp3,
-                    dsi_dn3, dsi_dp1, dsi_dn1, dsi_cp, dsi_cn, dsi_dp0, dsi_dn0,
-                    dsi_dp2, dsi_dn2, sd0_d0, sd0_d1, sd0_d2, sd0_d3, sd1_d0,
-                    sd1_d1, sd1_d2, sd1_d3, sd0_cmd, sd0_clk, sd1_cmd, sd1_clk,
-                    spi0_sclk, spi0_ss, spi0_miso, spi0_mosi, uart0_rx,
-                    uart0_tx, i2c0_sclk, i2c0_sdata, sensor0_pclk,
-                    sensor0_ckout, dnand_ale, dnand_cle, dnand_ceb0, dnand_ceb1,
-                    dnand_ceb2, dnand_ceb3, uart2_rx, uart2_tx, uart2_rtsb,
-                    uart2_ctsb, uart3_rx, uart3_tx, uart3_rtsb, uart3_ctsb,
-                    pcm1_in, pcm1_clk, pcm1_sync, pcm1_out, i2c1_sclk,
-                    i2c1_sdata, i2c2_sclk, i2c2_sdata, csi_dn0, csi_dp0,
-                    csi_dn1, csi_dp1, csi_dn2, csi_dp2, csi_dn3, csi_dp3,
-                    csi_cn, csi_cp, dnand_d0, dnand_d1, dnand_d2, dnand_d3,
-                    dnand_d4, dnand_d5, dnand_d6, dnand_d7, dnand_rb, dnand_rdb,
-                    dnand_rdbn, dnand_wrb, porb, clko_25m, bsel, pkg0, pkg1,
-                    pkg2, pkg3]
+                         eth_rxer, eth_crs_dv, eth_rxd1, eth_rxd0, eth_ref_clk,
+                         eth_mdc, eth_mdio, sirq0, sirq1, sirq2, i2s_d0, i2s_bclk0,
+                         i2s_lrclk0, i2s_mclk0, i2s_d1, i2s_bclk1, i2s_lrclk1,
+                         i2s_mclk1, ks_in0, ks_in1, ks_in2, ks_in3, ks_out0, ks_out1,
+                         ks_out2, lvds_oep, lvds_oen, lvds_odp, lvds_odn, lvds_ocp,
+                         lvds_ocn, lvds_obp, lvds_obn, lvds_oap, lvds_oan, lvds_eep,
+                         lvds_een, lvds_edp, lvds_edn, lvds_ecp, lvds_ecn, lvds_ebp,
+                         lvds_ebn, lvds_eap, lvds_ean, lcd0_d18, lcd0_d17, dsi_dp3,
+                         dsi_dn3, dsi_dp1, dsi_dn1, dsi_cp, dsi_cn, dsi_dp0, dsi_dn0,
+                         dsi_dp2, dsi_dn2, sd0_d0, sd0_d1, sd0_d2, sd0_d3, sd1_d0,
+                         sd1_d1, sd1_d2, sd1_d3, sd0_cmd, sd0_clk, sd1_cmd, sd1_clk,
+                         spi0_sclk, spi0_ss, spi0_miso, spi0_mosi, uart0_rx,
+                         uart0_tx, i2c0_sclk, i2c0_sdata, sensor0_pclk,
+                         sensor0_ckout, dnand_ale, dnand_cle, dnand_ceb0, dnand_ceb1,
+                         dnand_ceb2, dnand_ceb3, uart2_rx, uart2_tx, uart2_rtsb,
+                         uart2_ctsb, uart3_rx, uart3_tx, uart3_rtsb, uart3_ctsb,
+                         pcm1_in, pcm1_clk, pcm1_sync, pcm1_out, i2c1_sclk,
+                         i2c1_sdata, i2c2_sclk, i2c2_sdata, csi_dn0, csi_dp0,
+                         csi_dn1, csi_dp1, csi_dn2, csi_dp2, csi_dn3, csi_dp3,
+                         csi_cn, csi_cp, dnand_d0, dnand_d1, dnand_d2, dnand_d3,
+                         dnand_d4, dnand_d5, dnand_d6, dnand_d7, dnand_rb, dnand_rdb,
+                         dnand_rdbn, dnand_wrb, porb, clko_25m, bsel, pkg0, pkg1,
+                         pkg2, pkg3]
             minItems: 1
             maxItems: 64
 
index 5556def6b99bc4b4625717ea82cb753107945012..c4c07121161163478cd18224975263ef37f4f2d0 100644 (file)
@@ -106,7 +106,7 @@ patternProperties:
     required:
       - pinmux
 
-    additionalProperties:  false
+    additionalProperties: false
 
 required:
   - compatible
index 1f0f5757f9e170fa6654e8e6d8687d5b05784c6a..040d2ada36690ac369f27049f04ae988f56426b8 100644 (file)
@@ -71,9 +71,9 @@ patternProperties:
           Specify the alternative function to be configured for the specified
           pins. Functions are only valid for gpio pins.
         enum: [ gpio, cci_i2c0, blsp_uim1, blsp_uim2, blsp_uim3, blsp_uim5,
-          blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c5, blsp_spi1,
-          blsp_spi2, blsp_spi3, blsp_spi5, blsp_uart1, blsp_uart2,
-          blsp_uart3, blsp_uart5, cam_mclk0, cam_mclk1, wlan ]
+                blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c5, blsp_spi1,
+                blsp_spi2, blsp_spi3, blsp_spi5, blsp_uart1, blsp_uart2,
+                blsp_uart3, blsp_uart5, cam_mclk0, cam_mclk1, wlan ]
 
       drive-strength:
         enum: [2, 4, 6, 8, 10, 12, 14, 16]
index d0d1a01140ea79684466b0f83c716514624dc753..9f1dab0c2430b476efef9f929482f1db829babce 100644 (file)
@@ -40,24 +40,24 @@ patternProperties:
           Function to mux.
         $ref: "/schemas/types.yaml#/definitions/string"
         enum: [i2c0, i2c1, i2c2, i2c3, i2c4, i2c5, i2c6, i2c7, i2c8,
-          spi0, spi1, spi2, spi3, spi4, spi5, spi6,
-          uart0, uart1, uart2, uart3, pwm, pcmif_out, pcmif_in]
+               spi0, spi1, spi2, spi3, spi4, spi5, spi6,
+               uart0, uart1, uart2, uart3, pwm, pcmif_out, pcmif_in]
 
       groups:
         description:
           Name of the pin group to use for the functions.
         $ref: "/schemas/types.yaml#/definitions/string"
         enum: [i2c0_grp, i2c1_grp, i2c2_grp, i2c3_grp, i2c4_grp,
-          i2c5_grp, i2c6_grp, i2c7_grp, i2c8_grp,
-          spi0_grp, spi0_cs0_grp, spi0_cs1_grp, spi0_cs2_grp,
-          spi1_grp, spi2_grp, spi3_grp, spi4_grp, spi5_grp, spi6_grp,
-          uart0_grp, uart1_grp, uart2_grp, uart3_grp,
-          pwm0_gpio4_grp, pwm0_gpio8_grp, pwm0_gpio12_grp,
-          pwm0_gpio16_grp, pwm1_gpio5_grp, pwm1_gpio9_grp,
-          pwm1_gpio13_grp, pwm1_gpio17_grp, pwm2_gpio6_grp,
-          pwm2_gpio10_grp, pwm2_gpio14_grp, pwm2_gpio18_grp,
-          pwm3_gpio7_grp, pwm3_gpio11_grp, pwm3_gpio15_grp,
-          pwm3_gpio19_grp, pcmif_out_grp, pcmif_in_grp]
+               i2c5_grp, i2c6_grp, i2c7_grp, i2c8_grp,
+               spi0_grp, spi0_cs0_grp, spi0_cs1_grp, spi0_cs2_grp,
+               spi1_grp, spi2_grp, spi3_grp, spi4_grp, spi5_grp, spi6_grp,
+               uart0_grp, uart1_grp, uart2_grp, uart3_grp,
+               pwm0_gpio4_grp, pwm0_gpio8_grp, pwm0_gpio12_grp,
+               pwm0_gpio16_grp, pwm1_gpio5_grp, pwm1_gpio9_grp,
+               pwm1_gpio13_grp, pwm1_gpio17_grp, pwm2_gpio6_grp,
+               pwm2_gpio10_grp, pwm2_gpio14_grp, pwm2_gpio18_grp,
+               pwm3_gpio7_grp, pwm3_gpio11_grp, pwm3_gpio15_grp,
+               pwm3_gpio19_grp, pcmif_out_grp, pcmif_in_grp]
 
       drive-strength:
         enum: [2, 4, 6, 8, 16, 24, 32]
index a6c91026d4ccd60727bad77636e34eb4715cf72d..9c6fda6b1dd9ac089be820c9608d288de2fad84b 100644 (file)
@@ -28,14 +28,16 @@ description: |
 
 properties:
   mode-normal:
-      $ref: /schemas/types.yaml#/definitions/uint32
-      description: |
-        Default value to set on a reboot if no command was provided.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      Default value to set on a reboot if no command was provided.
 
 patternProperties:
   "^mode-.*$":
     $ref: /schemas/types.yaml#/definitions/uint32
 
+additionalProperties: false
+
 examples:
   - |
     reboot-mode {
index 867e3e6b7e80f734656fbb91fe316356c53efd10..76c227a7cd5cd833e2ed26560625287cbdffa5ac 100644 (file)
@@ -15,10 +15,10 @@ properties:
     oneOf:
       - const: ingenic,jz4740-battery
       - items:
-        - enum:
-          - ingenic,jz4725b-battery
-          - ingenic,jz4770-battery
-        - const: ingenic,jz4740-battery
+          - enum:
+              - ingenic,jz4725b-battery
+              - ingenic,jz4770-battery
+          - const: ingenic,jz4740-battery
 
   io-channels:
     maxItems: 1
index 193a23af2007bc2eb58177eb006e6b8b64737a3e..983fc215c1e51ecfd778b21051eff3dd618d50c8 100644 (file)
@@ -84,12 +84,12 @@ allOf:
     then:
       properties:
         summit,mains-current-limit-microamp:
-          enum: [ 300000,  500000,  700000, 1000000,
-                 1500000, 1800000, 2000000]
+          enum: [ 300000, 500000, 700000, 1000000,
+                  1500000, 1800000, 2000000]
 
         summit,usb-current-limit-microamp:
-          enum: [ 300000,  500000,  700000, 1000000,
-                 1500000, 1800000, 2000000]
+          enum: [ 300000, 500000, 700000, 1000000,
+                  1500000, 1800000, 2000000]
 
         summit,charge-current-compensation-microamp:
           enum: [200000, 450000, 600000, 900000]
@@ -97,12 +97,12 @@ allOf:
     else:
       properties:
         summit,mains-current-limit-microamp:
-          enum: [ 300000,  500000,  700000,  900000, 1200000,
-                 1500000, 1800000, 2000000, 2200000, 2500000]
+          enum: [ 300000, 500000, 700000, 900000, 1200000,
+                  1500000, 1800000, 2000000, 2200000, 2500000]
 
         summit,usb-current-limit-microamp:
-          enum: [ 300000,  500000,  700000,  900000, 1200000,
-                 1500000, 1800000, 2000000, 2200000, 2500000]
+          enum: [ 300000, 500000, 700000, 900000, 1200000,
+                  1500000, 1800000, 2000000, 2200000, 2500000]
 
         summit,charge-current-compensation-microamp:
           enum: [250000, 700000, 900000, 1200000]
index ba175b30f468623f0949b8bd926fc29797c1de56..9245b7199439f0b582180bd7a2f8020c7c877750 100644 (file)
@@ -41,6 +41,8 @@ required:
   - enable-gpios
   - mps,fb-voltage-divider
 
+unevaluatedProperties: false
+
 examples:
   - |
     #include <dt-bindings/gpio/gpio.h>
index c6de49685db7f02f00fe3c17a6fde503b7f99e51..f578e72778a7c0fb1522b769b03adf7e3fa4a52a 100644 (file)
@@ -80,6 +80,8 @@ required:
   - compatible
   - reg
 
+additionalProperties: false
+
 examples:
   - |
     i2c {
index 3f4a1939554d50803ec89d8529953f4fc0c7c228..efc0198eeb74d8fdcdedd73ff511557bb4d1932b 100644 (file)
@@ -25,8 +25,8 @@ select:
   properties:
     compatible:
       items:
-       - enum:
-          - sifive,fu540-c000-ccache
+        - enum:
+            - sifive,fu540-c000-ccache
 
   required:
     - compatible
index 3ab532713dc12dfe0273f320b0ff9700e764890f..3a8647d1da4c75890f5bda47ff201a407aac0782 100644 (file)
@@ -22,4 +22,7 @@ properties:
           - sifive,hifive-unleashed-a00
       - const: sifive,fu540-c000
       - const: sifive,fu540
+
+additionalProperties: true
+
 ...
index 4ad1e456a8012e636ee07957a1ac73951f4846b4..07f6ff89bcc15eff5b6c2ef904f5207a0bacc4f7 100644 (file)
@@ -19,9 +19,9 @@ properties:
           - const: fsl,imx21-rnga
       - items:
           - enum:
-            - fsl,imx6sl-rngb
-            - fsl,imx6sll-rngb
-            - fsl,imx6ull-rngb
+              - fsl,imx6sl-rngb
+              - fsl,imx6sll-rngb
+              - fsl,imx6ull-rngb
           - const: fsl,imx25-rngb
       - const: fsl,imx35-rngc
 
index 9ff85bc6859c47ce4896cbf66ac43a1b74b6b4ba..9702c07a6b6c77e564db9849d3911e6e553e9ad6 100644 (file)
@@ -20,30 +20,30 @@ properties:
       - const: fsl,imx21-uart
       - items:
           - enum:
-            - fsl,imx25-uart
-            - fsl,imx27-uart
-            - fsl,imx31-uart
-            - fsl,imx35-uart
-            - fsl,imx50-uart
-            - fsl,imx51-uart
-            - fsl,imx53-uart
-            - fsl,imx6q-uart
+              - fsl,imx25-uart
+              - fsl,imx27-uart
+              - fsl,imx31-uart
+              - fsl,imx35-uart
+              - fsl,imx50-uart
+              - fsl,imx51-uart
+              - fsl,imx53-uart
+              - fsl,imx6q-uart
           - const: fsl,imx21-uart
       - items:
           - enum:
-            - fsl,imx6sl-uart
-            - fsl,imx6sll-uart
-            - fsl,imx6sx-uart
+              - fsl,imx6sl-uart
+              - fsl,imx6sll-uart
+              - fsl,imx6sx-uart
           - const: fsl,imx6q-uart
           - const: fsl,imx21-uart
       - items:
           - enum:
-            - fsl,imx6ul-uart
-            - fsl,imx7d-uart
-            - fsl,imx8mm-uart
-            - fsl,imx8mn-uart
-            - fsl,imx8mp-uart
-            - fsl,imx8mq-uart
+              - fsl,imx6ul-uart
+              - fsl,imx7d-uart
+              - fsl,imx8mm-uart
+              - fsl,imx8mn-uart
+              - fsl,imx8mp-uart
+              - fsl,imx8mq-uart
           - const: fsl,imx6q-uart
 
   reg:
index 3b9143af2c7cb2e42ce21437425b1ce4afc38c6a..acfb9db021dcd9b553f3b6715fa164b34ab5c03d 100644 (file)
@@ -11,9 +11,10 @@ maintainers:
 
 description: |
   Google's ChromeOS EC codec is a digital mic codec provided by the
-  Embedded Controller (EC) and is controlled via a host-command interface.
-  An EC codec node should only be found as a sub-node of the EC node (see
-  Documentation/devicetree/bindings/mfd/google,cros-ec.yaml).
+  Embedded Controller (EC) and is controlled via a host-command
+  interface.  An EC codec node should only be found inside the "codecs"
+  subnode of a cros-ec node.
+  (see Documentation/devicetree/bindings/mfd/google,cros-ec.yaml).
 
 properties:
   compatible:
@@ -54,14 +55,19 @@ examples:
         #size-cells = <0>;
         cros-ec@0 {
             compatible = "google,cros-ec-spi";
-            #address-cells = <2>;
-            #size-cells = <1>;
             reg = <0>;
-            cros_ec_codec: ec-codec@10500000 {
-                compatible = "google,cros-ec-codec";
-                #sound-dai-cells = <1>;
-                reg = <0x0 0x10500000 0x80000>;
-                memory-region = <&reserved_mem>;
+
+            codecs {
+                #address-cells = <2>;
+                #size-cells = <1>;
+
+                cros_ec_codec: ec-codec@10500000 {
+                    compatible = "google,cros-ec-codec";
+                    #sound-dai-cells = <1>;
+                    reg = <0x0 0x10500000 0x80000>;
+                    memory-region = <&reserved_mem>;
+                };
+
             };
         };
     };
index 7d8bd4e144345452a417539c598a5f4de7fa9be4..4a2129005c0f80aa2ef1cd27f2974925f8224faf 100644 (file)
@@ -10,8 +10,8 @@ maintainers:
   - Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
 
 description:
-        The Microchip Sony/Philips Digital Interface Receiver is a
-        serial port compliant with the IEC-60958 standard.
+  The Microchip Sony/Philips Digital Interface Receiver is a serial port 
+  compliant with the IEC-60958 standard.
 
 properties:
   "#sound-dai-cells":
index a03b0b871fc98605b1824ee1a25b2b36c5e066aa..bdfb63387c536bb4a129ec45edb30e9baaf14197 100644 (file)
@@ -10,8 +10,8 @@ maintainers:
   - Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
 
 description:
-        The Microchip Sony/Philips Digital Interface Transmitter is a
-        serial port compliant with the IEC-60958 standard.
+  The Microchip Sony/Philips Digital Interface Transmitter is a serial port 
+  compliant with the IEC-60958 standard.
 
 properties:
   "#sound-dai-cells":
index f6f9fb49f385606bf84ddf51cd9958258a8074c2..1e23c0e20bc17bfa168ffef5461bedcb64610852 100644 (file)
@@ -26,8 +26,10 @@ properties:
   reg:
     maxItems: 2
     description: LPAIF core registers
+
   reg-names:
-     maxItems: 2
+    maxItems: 2
+
   clocks:
     minItems: 3
     maxItems: 6
@@ -39,8 +41,10 @@ properties:
   interrupts:
     maxItems: 2
     description: LPAIF DMA buffer interrupt
+
   interrupt-names:
     maxItems: 2
+
   qcom,adsp:
     $ref: /schemas/types.yaml#/definitions/phandle
     description: Phandle for the audio DSP node
@@ -141,31 +145,31 @@ allOf:
       properties:
         clock-names:
           oneOf:
-           - items:   #for I2S
-              - const: pcnoc-sway-clk
-              - const: audio-core
-              - const: mclk0
-              - const: pcnoc-mport-clk
-              - const: mi2s-bit-clk0
-              - const: mi2s-bit-clk1
-           - items:   #for HDMI
-              - const: pcnoc-sway-clk
-              - const: audio-core
-              - const: pcnoc-mport-clk
+            - items:   #for I2S
+                - const: pcnoc-sway-clk
+                - const: audio-core
+                - const: mclk0
+                - const: pcnoc-mport-clk
+                - const: mi2s-bit-clk0
+                - const: mi2s-bit-clk1
+            - items:   #for HDMI
+                - const: pcnoc-sway-clk
+                - const: audio-core
+                - const: pcnoc-mport-clk
         reg-names:
           anyOf:
             - items:   #for I2S
-              - const: lpass-lpaif
+                - const: lpass-lpaif
             - items:   #for I2S and HDMI
-              - const: lpass-hdmiif
-              - const: lpass-lpaif
+                - const: lpass-hdmiif
+                - const: lpass-lpaif
         interrupt-names:
           anyOf:
             - items:   #for I2S
-              - const: lpass-irq-lpaif
+                - const: lpass-irq-lpaif
             - items:   #for I2S and HDMI
-              - const: lpass-irq-lpaif
-              - const: lpass-irq-hdmi
+                - const: lpass-irq-lpaif
+                - const: lpass-irq-hdmi
       required:
         - iommus
         - power-domains
index def1db298eacb46b01989124779aeba6c9d6cdd8..644b68edf3e1dae8843aa56ffa43b357c27a0e1c 100644 (file)
@@ -26,6 +26,8 @@ properties:
 required:
   - compatible
 
+additionalProperties: false
+
 examples:
   - |
     #include <dt-bindings/gpio/gpio.h>
index fcfd02d8d32fbaa6890da5c0be4cdcdf7785ca95..e498966d436fbbb8f14e183cf341e5a165f08fc1 100644 (file)
@@ -8,10 +8,16 @@ Required properties:
 
 - reg : The I2C address of the device.
 
+Optional properties:
+
+- realtek,power-up-delay-ms
+  Set a delay time for flush work to be completed,
+  this value is adjustable depending on platform.
 
 Example:
 
 rt1015: codec@28 {
        compatible = "realtek,rt1015";
        reg = <0x28>;
+       realtek,power-up-delay-ms = <50>;
 };
index 6ebcbc15369181988c02e4bee352b43d3162863b..b66a07e21d1e5de756438bc5f690459aa00a00c1 100644 (file)
@@ -33,6 +33,9 @@ properties:
           - const: allwinner,sun4i-a10-system-control
       - const: allwinner,sun8i-a23-system-control
       - const: allwinner,sun8i-h3-system-control
+      - items:
+          - const: allwinner,sun8i-v3s-system-control
+          - const: allwinner,sun8i-h3-system-control
       - items:
           - const: allwinner,sun8i-r40-system-control
           - const: allwinner,sun4i-a10-system-control
index e35d3053250a557253c887efb47fdd4584f1f717..960e2bd66a97031bf040c2b154f731a62b89e325 100644 (file)
@@ -33,8 +33,8 @@ properties:
   compatible:
     items:
       - enum:
-        - arm,sp804
-        - hisilicon,sp804
+          - arm,sp804
+          - hisilicon,sp804
       - const: arm,primecell
 
   interrupts:
@@ -58,11 +58,11 @@ properties:
       clock is used for all clock inputs.
     oneOf:
       - items:
-        - description: clock for timer 1
-        - description: clock for timer 2
-        - description: bus clock
+          - description: clock for timer 1
+          - description: clock for timer 2
+          - description: bus clock
       - items:
-        - description: unified clock for both timers and the bus
+          - description: unified clock for both timers and the bus
 
   clock-names: true
     # The original binding did not specify any clock names, and there is no
index ac20b98e99101c8afaccb877f68053544a112f49..d6af2794d44481ce70e626c9b2d89d795810ec23 100644 (file)
@@ -44,8 +44,8 @@ properties:
     enum: [super-speed, high-speed, full-speed]
 
   phys:
-   minItems: 1
-   maxItems: 2
+    minItems: 1
+    maxItems: 2
 
   phy-names:
     minItems: 1
index 5fe9e6211ba2b9c65b9c764e081666530cb715cc..52ceb07294a35877e916499b39c8b125fa3d8992 100644 (file)
@@ -17,7 +17,7 @@ description: |-
 
 properties:
   compatible:
-   const: ti,hd3ss3220
+    const: ti,hd3ss3220
 
   reg:
     maxItems: 1
index 1aaf3e768c8113f6ecbfc84b8b5cdb1320e409a9..55adea827c3499ac6872c3e73feda2c3b83af5f5 100644 (file)
@@ -15,10 +15,10 @@ properties:
       - const: fsl,imx21-owire
       - items:
           - enum:
-            - fsl,imx27-owire
-            - fsl,imx50-owire
-            - fsl,imx51-owire
-            - fsl,imx53-owire
+              - fsl,imx27-owire
+              - fsl,imx50-owire
+              - fsl,imx51-owire
+              - fsl,imx53-owire
           - const: fsl,imx21-owire
 
   reg:
index 65115448c52db31307881f6439e69925c3c3ae84..673bdff919ea47c7d6bc6636624560f0ff8efc59 100644 (file)
@@ -149,11 +149,11 @@ vidtv_psi.[ch]
        Because the generator is implemented in a separate file, it can be
        reused elsewhere in the media subsystem.
 
-       Currently vidtv supports working with 3 PSI tables: PAT, PMT and
-       SDT.
+       Currently vidtv supports working with 5 PSI tables: PAT, PMT,
+       SDT, NIT and EIT.
 
        The specification for PAT and PMT can be found in *ISO 13818-1:
-       Systems*, while the specification for the SDT can be found in *ETSI
+       Systems*, while the specification for the SDT, NIT, EIT can be found in *ETSI
        EN 300 468: Specification for Service Information (SI) in DVB
        systems*.
 
@@ -197,6 +197,8 @@ vidtv_channel.[ch]
 
        #. Their programs will be concatenated to populate the PAT
 
+       #. Their events will be concatenated to populate the EIT
+
        #. For each program in the PAT, a PMT section will be created
 
        #. The PMT section for a channel will be assigned its streams.
@@ -256,6 +258,42 @@ Using dvb-fe-tool
 The first step to check whether the demod loaded successfully is to run::
 
        $ dvb-fe-tool
+       Device Dummy demod for DVB-T/T2/C/S/S2 (/dev/dvb/adapter0/frontend0) capabilities:
+           CAN_FEC_1_2
+           CAN_FEC_2_3
+           CAN_FEC_3_4
+           CAN_FEC_4_5
+           CAN_FEC_5_6
+           CAN_FEC_6_7
+           CAN_FEC_7_8
+           CAN_FEC_8_9
+           CAN_FEC_AUTO
+           CAN_GUARD_INTERVAL_AUTO
+           CAN_HIERARCHY_AUTO
+           CAN_INVERSION_AUTO
+           CAN_QAM_16
+           CAN_QAM_32
+           CAN_QAM_64
+           CAN_QAM_128
+           CAN_QAM_256
+           CAN_QAM_AUTO
+           CAN_QPSK
+           CAN_TRANSMISSION_MODE_AUTO
+       DVB API Version 5.11, Current v5 delivery system: DVBC/ANNEX_A
+       Supported delivery systems:
+           DVBT
+           DVBT2
+           [DVBC/ANNEX_A]
+           DVBS
+           DVBS2
+       Frequency range for the current standard:
+       From:            51.0 MHz
+       To:              2.15 GHz
+       Step:            62.5 kHz
+       Tolerance:       29.5 MHz
+       Symbol rate ranges for the current standard:
+       From:            1.00 MBauds
+       To:              45.0 MBauds
 
 This should return what is currently set up at the demod struct, i.e.::
 
@@ -314,7 +352,7 @@ For this, one should provide a configuration file known as a 'scan file',
 here's an example::
 
        [Channel]
-       FREQUENCY = 330000000
+       FREQUENCY = 474000000
        MODULATION = QAM/AUTO
        SYMBOL_RATE = 6940000
        INNER_FEC = AUTO
@@ -335,6 +373,14 @@ You can browse scan tables online here: `dvb-scan-tables
 Assuming this channel is named 'channel.conf', you can then run::
 
        $ dvbv5-scan channel.conf
+       dvbv5-scan ~/vidtv.conf
+       ERROR    command BANDWIDTH_HZ (5) not found during retrieve
+       Cannot calc frequency shift. Either bandwidth/symbol-rate is unavailable (yet).
+       Scanning frequency #1 330000000
+           (0x00) Signal= -68.00dBm
+       Scanning frequency #2 474000000
+       Lock   (0x1f) Signal= -34.45dBm C/N= 33.74dB UCB= 0
+       Service Beethoven, provider LinuxTV.org: digital television
 
 For more information on dvb-scan, check its documentation online here:
 `dvb-scan Documentation <https://www.linuxtv.org/wiki/index.php/Dvbscan>`_.
@@ -344,23 +390,38 @@ Using dvb-zap
 
 dvbv5-zap is a command line tool that can be used to record MPEG-TS to disk. The
 typical use is to tune into a channel and put it into record mode. The example
-below - which is taken from the documentation - illustrates that::
+below - which is taken from the documentation - illustrates that\ [1]_::
 
-       $ dvbv5-zap -c dvb_channel.conf "trilhas sonoras" -r
-       using demux '/dev/dvb/adapter0/demux0'
+       $ dvbv5-zap -c dvb_channel.conf "beethoven" -o music.ts -P -t 10
+       using demux 'dvb0.demux0'
        reading channels from file 'dvb_channel.conf'
-       service has pid type 05:  204
-       tuning to 573000000 Hz
-       audio pid 104
-         dvb_set_pesfilter 104
-       Lock   (0x1f) Quality= Good Signal= 100.00% C/N= -13.80dB UCB= 70 postBER= 3.14x10^-3 PER= 0
-       DVR interface '/dev/dvb/adapter0/dvr0' can now be opened
+       tuning to 474000000 Hz
+       pass all PID's to TS
+       dvb_set_pesfilter 8192
+       dvb_dev_set_bufsize: buffer set to 6160384
+       Lock   (0x1f) Quality= Good Signal= -34.66dBm C/N= 33.41dB UCB= 0 postBER= 0 preBER= 1.05x10^-3 PER= 0
+       Lock   (0x1f) Quality= Good Signal= -34.57dBm C/N= 33.46dB UCB= 0 postBER= 0 preBER= 1.05x10^-3 PER= 0
+       Record to file 'music.ts' started
+       received 24587768 bytes (2401 Kbytes/sec)
+       Lock   (0x1f) Quality= Good Signal= -34.42dBm C/N= 33.89dB UCB= 0 postBER= 0 preBER= 2.44x10^-3 PER= 0
+
+.. [1] In this example, it records 10 seconds with all program ID's stored
+       at the music.ts file.
+
 
-The channel can be watched by playing the contents of the DVR interface, with
-some player that recognizes the MPEG-TS format, such as *mplayer* or *vlc*.
+The channel can be watched by playing the contents of the stream with some
+player that  recognizes the MPEG-TS format, such as ``mplayer`` or ``vlc``.
 
 By playing the contents of the stream one can visually inspect the workings of
-vidtv, e.g.::
+vidtv, e.g., to play a recorded TS file with::
+
+       $ mplayer music.ts
+
+or, alternatively, running this command on one terminal::
+
+       $ dvbv5-zap -c dvb_channel.conf "beethoven" -P -r &
+
+And, on a second terminal, playing the contents from DVR interface with::
 
        $ mplayer /dev/dvb/adapter0/dvr0
 
@@ -423,3 +484,30 @@ A nice addition is to simulate some noise when the signal quality is bad by:
 - Updating the error statistics accordingly (e.g. BER, etc).
 
 - Simulating some noise in the encoded data.
+
+Functions and structs used within vidtv
+---------------------------------------
+
+.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_bridge.h
+
+.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_channel.h
+
+.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_demod.h
+
+.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_encoder.h
+
+.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_mux.h
+
+.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_pes.h
+
+.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_psi.h
+
+.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_s302m.h
+
+.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_ts.h
+
+.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_tuner.h
+
+.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_common.c
+
+.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_tuner.c
index bbb0c1c0e5cf980ac059728a4d8b07771289e733..a94f17d9b8365fddc44eb32df1fc50507e908577 100644 (file)
@@ -86,9 +86,6 @@ Other Functions
 .. kernel-doc:: fs/dax.c
    :export:
 
-.. kernel-doc:: fs/direct-io.c
-   :export:
-
 .. kernel-doc:: fs/libfs.c
    :export:
 
index 728ab57a611a468db44f95a1af01d45629ac944d..0f2292e367e62bdf638b9c812b7df38ce1bbb7ff 100644 (file)
@@ -199,7 +199,7 @@ of its elements. Note: Once array is created its size can not be changed.
 
 There is a helper function to create device related seq_file::
 
-   struct dentry *debugfs_create_devm_seqfile(struct device *dev,
+   void debugfs_create_devm_seqfile(struct device *dev,
                                const char *name,
                                struct dentry *parent,
                                int (*read_fn)(struct seq_file *s,
index 805a1e9ea3a5b06edf9af694fea32eee295d4926..849d5b119eb8b0ef1e873f4b8433c60e6290bae6 100644 (file)
@@ -256,6 +256,10 @@ which is 1024 bytes long:
      - s\_padding2
      -
    * - 0x54
+     - \_\_be32
+     - s\_num\_fc\_blocks
+     - Number of fast commit blocks in the journal.
+   * - 0x58
      - \_\_u32
      - s\_padding[42]
      -
@@ -310,6 +314,8 @@ The journal incompat features are any combination of the following:
      - This journal uses v3 of the checksum on-disk format. This is the same as
        v2, but the journal block tag size is fixed regardless of the size of
        block numbers. (JBD2\_FEATURE\_INCOMPAT\_CSUM\_V3)
+   * - 0x20
+     - Journal has fast commit blocks. (JBD2\_FEATURE\_INCOMPAT\_FAST\_COMMIT)
 
 .. _jbd2_checksum_type:
 
index 93e55d7c1d4055960b987076ca82e2c9c04af73f..2eb1ab20498dd40afaa34c68b11b9db89962b813 100644 (file)
@@ -596,6 +596,13 @@ following:
      - Sparse Super Block, v2. If this flag is set, the SB field s\_backup\_bgs
        points to the two block groups that contain backup superblocks
        (COMPAT\_SPARSE\_SUPER2).
+   * - 0x400
+     - Fast commits supported. Although fast commits blocks are
+       backward incompatible, fast commit blocks are not always
+       present in the journal. If fast commit blocks are present in
+       the journal, JBD2 incompat feature
+       (JBD2\_FEATURE\_INCOMPAT\_FAST\_COMMIT) gets
+       set (COMPAT\_FAST\_COMMIT).
 
 .. _super_incompat:
 
index 5a5f70b4063e33ed886c8e13ff5542e351393103..e18f90ffc6fd228c3d53e274420dbace5a4166f6 100644 (file)
@@ -136,10 +136,8 @@ Fast commits
 ~~~~~~~~~~~~
 
 JBD2 to also allows you to perform file-system specific delta commits known as
-fast commits. In order to use fast commits, you first need to call
-:c:func:`jbd2_fc_init` and tell how many blocks at the end of journal
-area should be reserved for fast commits. Along with that, you will also need
-to set following callbacks that perform correspodning work:
+fast commits. In order to use fast commits, you will need to set following
+callbacks that perform correspodning work:
 
 `journal->j_fc_cleanup_cb`: Cleanup function called after every full commit and
 fast commit.
index 874ce0ed340d8cfec5c772809747a0cb4d7c4dac..71b9af13a048fc80fd0680033b0be9146c7fbe86 100644 (file)
@@ -19,9 +19,9 @@ report the "current" state of the lid as either "opened" or "closed".
 
 For most platforms, both the _LID method and the lid notifications are
 reliable. However, there are exceptions. In order to work with these
-exceptional buggy platforms, special restrictions and expections should be
+exceptional buggy platforms, special restrictions and exceptions should be
 taken into account. This document describes the restrictions and the
-expections of the Linux ACPI lid device driver.
+exceptions of the Linux ACPI lid device driver.
 
 
 Restrictions of the returning value of the _LID control method
@@ -46,7 +46,7 @@ state is changed to "closed". The "closed" notification is normally used to
 trigger some system power saving operations on Windows. Since it is fully
 tested, it is reliable from all AML tables.
 
-Expections for the userspace users of the ACPI lid device driver
+Exceptions for the userspace users of the ACPI lid device driver
 ================================================================
 
 The ACPI button driver exports the lid state to the userspace via the
@@ -100,7 +100,7 @@ use the following kernel parameter:
 C. button.lid_init_state=ignore:
    When this option is specified, the ACPI button driver never reports the
    initial lid state and there is a compensation mechanism implemented to
-   ensure that the reliable "closed" notifications can always be delievered
+   ensure that the reliable "closed" notifications can always be delivered
    to the userspace by always pairing "closed" input events with complement
    "opened" input events. But there is still no guarantee that the "opened"
    notifications can be delivered to the userspace when the lid is actually
index bb6d74f23ee0827568456621599aabc4c898c713..59aad6138b6e4e649646dc86222e6b326daa31c2 100644 (file)
@@ -20,9 +20,9 @@ index, like the ASL example below shows::
 
       Name (_CRS, ResourceTemplate ()
       {
-          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
+          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
                   "\\_SB.GPO0", 0, ResourceConsumer) {15}
-          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
+          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
                   "\\_SB.GPO0", 0, ResourceConsumer) {27, 31}
       })
 
@@ -49,15 +49,41 @@ index
 pin
   Pin in the GpioIo()/GpioInt() resource. Typically this is zero.
 active_low
-  If 1 the GPIO is marked as active_low.
+  If 1, the GPIO is marked as active_low.
 
 Since ACPI GpioIo() resource does not have a field saying whether it is
 active low or high, the "active_low" argument can be used here.  Setting
 it to 1 marks the GPIO as active low.
 
+Note, active_low in _DSD does not make sense for GpioInt() resource and
+must be 0. GpioInt() resource has its own means of defining it.
+
 In our Bluetooth example the "reset-gpios" refers to the second GpioIo()
 resource, second pin in that resource with the GPIO number of 31.
 
+The GpioIo() resource unfortunately doesn't explicitly provide an initial
+state of the output pin which driver should use during its initialization.
+
+Linux tries to use common sense here and derives the state from the bias
+and polarity settings. The table below shows the expectations:
+
+=========  =============  ==============
+Pull Bias     Polarity     Requested...
+=========  =============  ==============
+Implicit     x            AS IS (assumed firmware configured for us)
+Explicit     x (no _DSD)  as Pull Bias (Up == High, Down == Low),
+                          assuming non-active (Polarity = !Pull Bias)
+Down         Low          as low, assuming active
+Down         High         as low, assuming non-active
+Up           Low          as high, assuming non-active
+Up           High         as high, assuming active
+=========  =============  ==============
+
+That said, for our above example the both GPIOs, since the bias setting
+is explicit and _DSD is present, will be treated as active with a high
+polarity and Linux will configure the pins in this state until a driver
+reprograms them differently.
+
 It is possible to leave holes in the array of GPIOs. This is useful in
 cases like with SPI host controllers where some chip selects may be
 implemented as GPIOs and some as native signals. For example a SPI host
@@ -112,8 +138,8 @@ Example::
   Package () {
       "gpio-line-names",
       Package () {
-          "SPI0_CS_N", "EXP2_INT", "MUX6_IO", "UART0_RXD", "MUX7_IO",
-          "LVL_C_A1", "MUX0_IO", "SPI1_MISO"
+          "SPI0_CS_N", "EXP2_INT", "MUX6_IO", "UART0_RXD",
+          "MUX7_IO", "LVL_C_A1", "MUX0_IO", "SPI1_MISO",
       }
   }
 
@@ -137,7 +163,7 @@ to the GPIO lines it is going to use and provide the GPIO subsystem with a
 mapping between those names and the ACPI GPIO resources corresponding to them.
 
 To do that, the driver needs to define a mapping table as a NULL-terminated
-array of struct acpi_gpio_mapping objects that each contain a name, a pointer
+array of struct acpi_gpio_mapping objects that each contains a name, a pointer
 to an array of line data (struct acpi_gpio_params) objects and the size of that
 array.  Each struct acpi_gpio_params object consists of three fields,
 crs_entry_index, line_index, active_low, representing the index of the target
@@ -154,13 +180,14 @@ question would look like this::
   static const struct acpi_gpio_mapping bluetooth_acpi_gpios[] = {
     { "reset-gpios", &reset_gpio, 1 },
     { "shutdown-gpios", &shutdown_gpio, 1 },
-    { },
+    { }
   };
 
 Next, the mapping table needs to be passed as the second argument to
-acpi_dev_add_driver_gpios() that will register it with the ACPI device object
-pointed to by its first argument.  That should be done in the driver's .probe()
-routine.  On removal, the driver should unregister its GPIO mapping table by
+acpi_dev_add_driver_gpios() or its managed analogue that will
+register it with the ACPI device object pointed to by its first
+argument. That should be done in the driver's .probe() routine.
+On removal, the driver should unregister its GPIO mapping table by
 calling acpi_dev_remove_driver_gpios() on the ACPI device object where that
 table was previously registered.
 
@@ -191,12 +218,12 @@ The driver might expect to get the right GPIO when it does::
 but since there is no way to know the mapping between "reset" and
 the GpioIo() in _CRS desc will hold ERR_PTR(-ENOENT).
 
-The driver author can solve this by passing the mapping explictly
-(the recommended way and documented in the above chapter).
+The driver author can solve this by passing the mapping explicitly
+(this is the recommended way and it's documented in the above chapter).
 
 The ACPI GPIO mapping tables should not contaminate drivers that are not
 knowing about which exact device they are servicing on. It implies that
-the ACPI GPIO mapping tables are hardly linked to ACPI ID and certain
+the ACPI GPIO mapping tables are hardly linked to an ACPI ID and certain
 objects, as listed in the above chapter, of the device in question.
 
 Getting GPIO descriptor
@@ -229,5 +256,5 @@ Case 2 explicitly tells GPIO core to look for resources in _CRS.
 Be aware that gpiod_get_index() in cases 1 and 2, assuming that there
 are two versions of ACPI device description provided and no mapping is
 present in the driver, will return different resources. That's why a
-certain driver has to handle them carefully as explained in previous
+certain driver has to handle them carefully as explained in the previous
 chapter.
index 0aa7e2c5d32a3d28e3397504aa8c3f7b8097a3fb..6ab6c096404297d27a3faa2386465db0906ed2b4 100644 (file)
@@ -98,7 +98,7 @@ subject to change::
    [    0.188903]   exdebug-0398 ex_trace_point        : Method End [0xf58394d8:\_SB.PCI0.LPCB.ECOK] execution.
 
 Developers can utilize these special log entries to track the AML
-interpretion, thus can aid issue debugging and performance tuning. Note
+interpretation, thus can aid issue debugging and performance tuning. Note
 that, as the "AML tracer" logs are implemented via ACPI_DEBUG_PRINT()
 macro, CONFIG_ACPI_DEBUG is also required to be enabled for enabling
 "AML tracer" logs.
index 1f9ea8221f80c5307d6dfc7cb88cc0b6d30494b0..2062a6023678d04b86abb096ebb7c9bfd9b418ad 100644 (file)
@@ -83,10 +83,6 @@ AMDGPU XGMI Support
 ===================
 
 .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
-   :doc: AMDGPU XGMI Support
-
-.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
-   :internal:
 
 AMDGPU RAS Support
 ==================
@@ -124,9 +120,6 @@ RAS VRAM Bad Pages sysfs Interface
 .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
    :doc: AMDGPU RAS sysfs gpu_vram_bad_pages Interface
 
-.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
-   :internal:
-
 Sample Code
 -----------
 Sample code for testing error injection can be found here:
index 9257f8a48650d99caaef9b8ca4e8fcf185a1ad5d..2b877011cfdf0b511805bd8a4fe09c7b056cd15c 100644 (file)
@@ -20,7 +20,7 @@ ADM1266 is a sequencer that features voltage readback from 17 channels via an
 integrated 12 bit SAR ADC, accessed using a PMBus interface.
 
 The driver is a client driver to the core PMBus driver. Please see
-Documentation/hwmon/pmbus for details on PMBus client drivers.
+Documentation/hwmon/pmbus.rst for details on PMBus client drivers.
 
 
 Sysfs entries
index e6b91ab1297850c86d5905ef77d6219c7de49d16..b797db73822524867b9cd2d55e3a8d1303cb33f1 100644 (file)
@@ -132,6 +132,7 @@ Hardware Monitoring Kernel Drivers
    mcp3021
    menf21bmc
    mlxreg-fan
+   mp2975
    nct6683
    nct6775
    nct7802
index 5b0609c62f4843e005b82ac5a75a6e41ab81957b..81d816b71490d7cb9608450553166985a22a5411 100644 (file)
@@ -20,6 +20,7 @@ This driver implements support for Monolithic Power Systems, Inc. (MPS)
 vendor dual-loop, digital, multi-phase controller MP2975.
 
 This device:
+
 - Supports up to two power rail.
 - Provides 8 pulse-width modulations (PWMs), and can be configured up
   to 8-phase operation for rail 1 and up to 4-phase operation for rail
@@ -32,10 +33,12 @@ This device:
   10-mV DAC, IMVP9 mode with 5-mV DAC.
 
 Device supports:
+
 - SVID interface.
 - AVSBus interface.
 
 Device complaint with:
+
 - PMBus rev 1.3 interface.
 
 Device supports direct format for reading output current, output voltage,
@@ -45,11 +48,14 @@ Device supports VID and direct formats for reading output voltage.
 The below VID modes are supported: VR12, VR13, IMVP9.
 
 The driver provides the next attributes for the current:
+
 - for current in: input, maximum alarm;
 - for current out input, maximum alarm and highest values;
 - for phase current: input and label.
-attributes.
+  attributes.
+
 The driver exports the following attributes via the 'sysfs' files, where
+
 - 'n' is number of telemetry pages (from 1 to 2);
 - 'k' is number of configured phases (from 1 to 8);
 - indexes 1, 1*n for "iin";
@@ -65,11 +71,14 @@ The driver exports the following attributes via the 'sysfs' files, where
 **curr[1-{2n+k}]_label**
 
 The driver provides the next attributes for the voltage:
+
 - for voltage in: input, high critical threshold, high critical alarm, all only
   from page 0;
 - for voltage out: input, low and high critical thresholds, low and high
   critical alarms, from pages 0 and 1;
+
 The driver exports the following attributes via the 'sysfs' files, where
+
 - 'n' is number of telemetry pages (from 1 to 2);
 - indexes 1 for "iin";
 - indexes n+1, n+2 for "vout";
@@ -87,9 +96,12 @@ The driver exports the following attributes via the 'sysfs' files, where
 **in[2-{n+1}1_lcrit_alarm**
 
 The driver provides the next attributes for the power:
+
 - for power in alarm and input.
 - for power out: highest and input.
+
 The driver exports the following attributes via the 'sysfs' files, where
+
 - 'n' is number of telemetry pages (from 1 to 2);
 - indexes 1 for "pin";
 - indexes n+1, n+2 for "pout";
index cf3ca236d2cce86ed4fc0863d867ff75b06d64b0..21c847890d03c4a337ec2824a1a152ede3b300f7 100644 (file)
@@ -57,9 +57,8 @@ to enable them. ::
 They can be enabled individually. The full list of the parameters: ::
 
        make CC=clang LD=ld.lld AR=llvm-ar NM=llvm-nm STRIP=llvm-strip \
-         OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump OBJSIZE=llvm-size \
-         READELF=llvm-readelf HOSTCC=clang HOSTCXX=clang++ HOSTAR=llvm-ar \
-         HOSTLD=ld.lld
+         OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump READELF=llvm-readelf \
+         HOSTCC=clang HOSTCXX=clang++ HOSTAR=llvm-ar HOSTLD=ld.lld
 
 Currently, the integrated assembler is disabled by default. You can pass
 ``LLVM_IAS=1`` to enable it.
index bc70c6aa713844766a878f62abf1052cb0ac8096..e5d63b9400459c2aa401028acab6b880d9a7a7c6 100644 (file)
@@ -17,6 +17,7 @@ LEDs
    uleds
 
    leds-blinkm
+   leds-el15203000
    leds-lm3556
    leds-lp3944
    leds-lp5521
@@ -24,3 +25,4 @@ LEDs
    leds-lp5562
    leds-lp55xx
    leds-mlxcpld
+   leds-sc27xx
diff --git a/Documentation/leds/leds-el15203000.rst b/Documentation/leds/leds-el15203000.rst
new file mode 100644 (file)
index 0000000..12c23d7
--- /dev/null
@@ -0,0 +1,140 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==================================
+Kernel driver for Crane EL15203000
+==================================
+
+/sys/class/leds/<led>/hw_pattern
+--------------------------------
+
+Specify a hardware pattern for the EL15203000 LED.
+
+The LEDs board supports only predefined patterns by firmware
+for specific LEDs.
+
+Breathing mode for Screen frame light tube::
+
+    "0 4000 1 4000"
+
+       ^
+       |
+    Max-|     ---
+       |    /   \
+       |   /     \
+       |  /       \     /
+       | /         \   /
+    Min-|-           ---
+       |
+       0------4------8--> time (sec)
+
+Cascade mode for Pipe LED::
+
+    "1 800 2 800 4 800 8 800 16 800"
+
+       ^
+       |
+  0 On -|----+                   +----+                   +---
+       |    |                   |    |                   |
+    Off-|    +-------------------+    +-------------------+
+       |
+  1 On -|    +----+                   +----+
+       |    |    |                   |    |
+    Off |----+    +-------------------+    +------------------
+       |
+  2 On -|         +----+                   +----+
+       |         |    |                   |    |
+    Off-|---------+    +-------------------+    +-------------
+       |
+  3 On -|              +----+                   +----+
+       |              |    |                   |    |
+    Off-|--------------+    +-------------------+    +--------
+       |
+  4 On -|                   +----+                   +----+
+       |                   |    |                   |    |
+    Off-|-------------------+    +-------------------+    +---
+       |
+       0---0.8--1.6--2.4--3.2---4---4.8--5.6--6.4--7.2---8--> time (sec)
+
+Inverted cascade mode for Pipe LED::
+
+    "30 800 29 800 27 800 23 800 15 800"
+
+       ^
+       |
+  0 On -|    +-------------------+    +-------------------+
+       |    |                   |    |                   |
+    Off-|----+                   +----+                   +---
+       |
+  1 On -|----+    +-------------------+    +------------------
+       |    |    |                   |    |
+    Off |    +----+                   +----+
+       |
+  2 On -|---------+    +-------------------+    +-------------
+       |         |    |                   |    |
+    Off-|         +----+                   +----+
+       |
+  3 On -|--------------+    +-------------------+    +--------
+       |              |    |                   |    |
+    Off-|              +----+                   +----+
+       |
+  4 On -|-------------------+    +-------------------+    +---
+       |                   |    |                   |    |
+    Off-|                   +----+                   +----+
+       |
+       0---0.8--1.6--2.4--3.2---4---4.8--5.6--6.4--7.2---8--> time (sec)
+
+Bounce mode for Pipe LED::
+
+    "1 800 2 800 4 800 8 800 16 800 16 800 8 800 4 800 2 800 1 800"
+
+       ^
+       |
+  0 On -|----+                                       +--------
+       |    |                                       |
+    Off-|    +---------------------------------------+
+       |
+  1 On -|    +----+                             +----+
+       |    |    |                             |    |
+    Off |----+    +-----------------------------+    +--------
+       |
+  2 On -|         +----+                   +----+
+       |         |    |                   |    |
+    Off-|---------+    +-------------------+    +-------------
+       |
+  3 On -|              +----+         +----+
+       |              |    |         |    |
+    Off-|--------------+    +---------+    +------------------
+       |
+  4 On -|                   +---------+
+       |                   |         |
+    Off-|-------------------+         +-----------------------
+       |
+       0---0.8--1.6--2.4--3.2---4---4.8--5.6--6.4--7.2---8--> time (sec)
+
+Inverted bounce mode for Pipe LED::
+
+    "30 800 29 800 27 800 23 800 15 800 15 800 23 800 27 800 29 800 30 800"
+
+       ^
+       |
+  0 On -|    +---------------------------------------+
+       |    |                                       |
+    Off-|----+                                       +--------
+       |
+  1 On -|----+    +-----------------------------+    +--------
+       |    |    |                             |    |
+    Off |    +----+                             +----+
+       |
+  2 On -|---------+    +-------------------+    +-------------
+       |         |    |                   |    |
+    Off-|         +----+                   +----+
+       |
+  3 On -|--------------+    +---------+    +------------------
+       |              |    |         |    |
+    Off-|              +----+         +----+
+       |
+  4 On -|-------------------+         +-----------------------
+       |                   |         |
+    Off-|                   +---------+
+       |
+       0---0.8--1.6--2.4--3.2---4---4.8--5.6--6.4--7.2---8--> time (sec)
diff --git a/Documentation/leds/leds-sc27xx.rst b/Documentation/leds/leds-sc27xx.rst
new file mode 100644 (file)
index 0000000..6bdf6ba
--- /dev/null
@@ -0,0 +1,27 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===================================
+Kernel driver for Spreadtrum SC27XX
+===================================
+
+/sys/class/leds/<led>/hw_pattern
+--------------------------------
+
+Specify a hardware pattern for the SC27XX LED. For the SC27XX
+LED controller, it only supports 4 stages to make a single
+hardware pattern, which is used to configure the rise time,
+high time, fall time and low time for the breathing mode.
+
+For the breathing mode, the SC27XX LED only expects one brightness
+for the high stage. To be compatible with the hardware pattern
+format, we should set brightness as 0 for rise stage, fall
+stage and low stage.
+
+- Min stage duration: 125 ms
+- Max stage duration: 31875 ms
+
+Since the stage duration step is 125 ms, the duration should be
+a multiplier of 125, like 125ms, 250ms, 375ms, 500ms ... 31875ms.
+
+Thus the format of the hardware pattern values should be:
+"0 rise_duration brightness high_duration 0 fall_duration 0 low_duration".
index cec03bd1294aabf6d07cd7e8fcc0d919d0847ece..9f3cfca9f8a4547349205d7d53859fdb4e314d77 100644 (file)
@@ -42,6 +42,7 @@ The validator tracks lock-class usage history and divides the usage into
 (4 usages * n STATEs + 1) categories:
 
 where the 4 usages can be:
+
 - 'ever held in STATE context'
 - 'ever held as readlock in STATE context'
 - 'ever held with STATE enabled'
@@ -49,10 +50,12 @@ where the 4 usages can be:
 
 where the n STATEs are coded in kernel/locking/lockdep_states.h and as of
 now they include:
+
 - hardirq
 - softirq
 
 where the last 1 category is:
+
 - 'ever used'                                       [ == !unused        ]
 
 When locking rules are violated, these usage bits are presented in the
@@ -96,9 +99,9 @@ exact case is for the lock as of the reporting time.
   +--------------+-------------+--------------+
   |              | irq enabled | irq disabled |
   +--------------+-------------+--------------+
-  | ever in irq  |      ?      |       -      |
+  | ever in irq  |     '?'     |      '-'     |
   +--------------+-------------+--------------+
-  | never in irq |      +      |       .      |
+  | never in irq |     '+'     |      '.'     |
   +--------------+-------------+--------------+
 
 The character '-' suggests irq is disabled because if otherwise the
@@ -216,7 +219,7 @@ looks like this::
        BD_MUTEX_PARTITION
   };
 
-mutex_lock_nested(&bdev->bd_contains->bd_mutex, BD_MUTEX_PARTITION);
+  mutex_lock_nested(&bdev->bd_contains->bd_mutex, BD_MUTEX_PARTITION);
 
 In this case the locking is done on a bdev object that is known to be a
 partition.
@@ -334,7 +337,7 @@ Troubleshooting:
 ----------------
 
 The validator tracks a maximum of MAX_LOCKDEP_KEYS number of lock classes.
-Exceeding this number will trigger the following lockdep warning:
+Exceeding this number will trigger the following lockdep warning::
 
        (DEBUG_LOCKS_WARN_ON(id >= MAX_LOCKDEP_KEYS))
 
@@ -420,7 +423,8 @@ the critical section of another reader of the same lock instance.
 
 The difference between recursive readers and non-recursive readers is because:
 recursive readers get blocked only by a write lock *holder*, while non-recursive
-readers could get blocked by a write lock *waiter*. Considering the follow example:
+readers could get blocked by a write lock *waiter*. Considering the follow
+example::
 
        TASK A:                 TASK B:
 
@@ -448,20 +452,22 @@ There are simply four block conditions:
 
 Block condition matrix, Y means the row blocks the column, and N means otherwise.
 
-           | E | r | R |
        +---+---+---+---+
-         E | Y | Y | Y |
+       |   | E | r | R |
+       +---+---+---+---+
+       | E | Y | Y | Y |
+       +---+---+---+---+
+       | r | Y | Y | N |
        +---+---+---+---+
-         r | Y | Y | N |
+       | R | Y | Y | N |
        +---+---+---+---+
-         R | Y | Y | N |
 
        (W: writers, r: non-recursive readers, R: recursive readers)
 
 
 acquired recursively. Unlike non-recursive read locks, recursive read locks
 only get blocked by current write lock *holders* other than write lock
-*waiters*, for example:
+*waiters*, for example::
 
        TASK A:                 TASK B:
 
@@ -491,7 +497,7 @@ Recursive locks don't block each other, while non-recursive locks do (this is
 even true for two non-recursive read locks). A non-recursive lock can block the
 corresponding recursive lock, and vice versa.
 
-A deadlock case with recursive locks involved is as follow:
+A deadlock case with recursive locks involved is as follow::
 
        TASK A:                 TASK B:
 
@@ -510,7 +516,7 @@ because there are 3 types for lockers, there are, in theory, 9 types of lock
 dependencies, but we can show that 4 types of lock dependencies are enough for
 deadlock detection.
 
-For each lock dependency:
+For each lock dependency::
 
        L1 -> L2
 
@@ -525,20 +531,25 @@ same types).
 With the above combination for simplification, there are 4 types of dependency edges
 in the lockdep graph:
 
-1) -(ER)->: exclusive writer to recursive reader dependency, "X -(ER)-> Y" means
+1) -(ER)->:
+           exclusive writer to recursive reader dependency, "X -(ER)-> Y" means
            X -> Y and X is a writer and Y is a recursive reader.
 
-2) -(EN)->: exclusive writer to non-recursive locker dependency, "X -(EN)-> Y" means
+2) -(EN)->:
+           exclusive writer to non-recursive locker dependency, "X -(EN)-> Y" means
            X -> Y and X is a writer and Y is either a writer or non-recursive reader.
 
-3) -(SR)->: shared reader to recursive reader dependency, "X -(SR)-> Y" means
+3) -(SR)->:
+           shared reader to recursive reader dependency, "X -(SR)-> Y" means
            X -> Y and X is a reader (recursive or not) and Y is a recursive reader.
 
-4) -(SN)->: shared reader to non-recursive locker dependency, "X -(SN)-> Y" means
+4) -(SN)->:
+           shared reader to non-recursive locker dependency, "X -(SN)-> Y" means
            X -> Y and X is a reader (recursive or not) and Y is either a writer or
            non-recursive reader.
 
-Note that given two locks, they may have multiple dependencies between them, for example:
+Note that given two locks, they may have multiple dependencies between them,
+for example::
 
        TASK A:
 
@@ -592,11 +603,11 @@ circles that won't cause deadlocks.
 
 Proof for sufficiency (Lemma 1):
 
-Let's say we have a strong circle:
+Let's say we have a strong circle::
 
        L1 -> L2 ... -> Ln -> L1
 
-, which means we have dependencies:
+, which means we have dependencies::
 
        L1 -> L2
        L2 -> L3
@@ -633,7 +644,7 @@ a lock held by P2, and P2 is waiting for a lock held by P3, ... and Pn is waitin
 for a lock held by P1. Let's name the lock Px is waiting as Lx, so since P1 is waiting
 for L1 and holding Ln, so we will have Ln -> L1 in the dependency graph. Similarly,
 we have L1 -> L2, L2 -> L3, ..., Ln-1 -> Ln in the dependency graph, which means we
-have a circle:
+have a circle::
 
        Ln -> L1 -> L2 -> ... -> Ln
 
index 46072ce3d7efb97ca58df861c7527e5789c9eb3a..64420b3314feb4bb1399edbbeb541f0a09030b0e 100644 (file)
@@ -24,7 +24,6 @@ fit into other categories.
    isl29003
    lis3lv02d
    max6875
-   mic/index
    pci-endpoint-test
    spear-pcie-gadget
    uacce
diff --git a/Documentation/misc-devices/mic/index.rst b/Documentation/misc-devices/mic/index.rst
deleted file mode 100644 (file)
index 3a8d063..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-=============================================
-Intel Many Integrated Core (MIC) architecture
-=============================================
-
-.. toctree::
-    :maxdepth: 1
-
-    mic_overview
-    scif_overview
-
-.. only::  subproject and html
-
-   Indices
-   =======
-
-   * :ref:`genindex`
diff --git a/Documentation/misc-devices/mic/mic_overview.rst b/Documentation/misc-devices/mic/mic_overview.rst
deleted file mode 100644 (file)
index 17d956b..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-======================================================
-Intel Many Integrated Core (MIC) architecture overview
-======================================================
-
-An Intel MIC X100 device is a PCIe form factor add-in coprocessor
-card based on the Intel Many Integrated Core (MIC) architecture
-that runs a Linux OS. It is a PCIe endpoint in a platform and therefore
-implements the three required standard address spaces i.e. configuration,
-memory and I/O. The host OS loads a device driver as is typical for
-PCIe devices. The card itself runs a bootstrap after reset that
-transfers control to the card OS downloaded from the host driver. The
-host driver supports OSPM suspend and resume operations. It shuts down
-the card during suspend and reboots the card OS during resume.
-The card OS as shipped by Intel is a Linux kernel with modifications
-for the X100 devices.
-
-Since it is a PCIe card, it does not have the ability to host hardware
-devices for networking, storage and console. We provide these devices
-on X100 coprocessors thus enabling a self-bootable equivalent
-environment for applications. A key benefit of our solution is that it
-leverages the standard virtio framework for network, disk and console
-devices, though in our case the virtio framework is used across a PCIe
-bus. A Virtio Over PCIe (VOP) driver allows creating user space
-backends or devices on the host which are used to probe virtio drivers
-for these devices on the MIC card. The existing VRINGH infrastructure
-in the kernel is used to access virtio rings from the host. The card
-VOP driver allows card virtio drivers to communicate with their user
-space backends on the host via a device page. Ring 3 apps on the host
-can add, remove and configure virtio devices. A thin MIC specific
-virtio_config_ops is implemented which is borrowed heavily from
-previous similar implementations in lguest and s390.
-
-MIC PCIe card has a dma controller with 8 channels. These channels are
-shared between the host s/w and the card s/w. 0 to 3 are used by host
-and 4 to 7 by card. As the dma device doesn't show up as PCIe device,
-a virtual bus called mic bus is created and virtual dma devices are
-created on it by the host/card drivers. On host the channels are private
-and used only by the host driver to transfer data for the virtio devices.
-
-The Symmetric Communication Interface (SCIF (pronounced as skiff)) is a
-low level communications API across PCIe currently implemented for MIC.
-More details are available at scif_overview.txt.
-
-The Coprocessor State Management (COSM) driver on the host allows for
-boot, shutdown and reset of Intel MIC devices. It communicates with a COSM
-"client" driver on the MIC cards over SCIF to perform these functions.
-
-Here is a block diagram of the various components described above. The
-virtio backends are situated on the host rather than the card given better
-single threaded performance for the host compared to MIC, the ability of
-the host to initiate DMA's to/from the card using the MIC DMA engine and
-the fact that the virtio block storage backend can only be on the host::
-
-               +----------+           |             +----------+
-               | Card OS  |           |             | Host OS  |
-               +----------+           |             +----------+
-                                      |
-        +-------+ +--------+ +------+ | +---------+  +--------+ +--------+
-        | Virtio| |Virtio  | |Virtio| | |Virtio   |  |Virtio  | |Virtio  |
-        | Net   | |Console | |Block | | |Net      |  |Console | |Block   |
-        | Driver| |Driver  | |Driver| | |backend  |  |backend | |backend |
-        +---+---+ +---+----+ +--+---+ | +---------+  +----+---+ +--------+
-            |         |         |     |      |            |         |
-            |         |         |     |User  |            |         |
-            |         |         |     |------|------------|--+------|-------
-            +---------+---------+     |Kernel                |
-                      |               |                      |
-  +---------+     +---+----+ +------+ | +------+ +------+ +--+---+  +-------+
-  |MIC DMA  |     |  VOP   | | SCIF | | | SCIF | | COSM | | VOP  |  |MIC DMA|
-  +---+-----+     +---+----+ +--+---+ | +--+---+ +--+---+ +------+  +----+--+
-      |               |         |     |    |        |                    |
-  +---+-----+     +---+----+ +--+---+ | +--+---+ +--+---+ +------+  +----+--+
-  |MIC      |     |  VOP   | |SCIF  | | |SCIF  | | COSM | | VOP  |  | MIC   |
-  |HW Bus   |     |  HW Bus| |HW Bus| | |HW Bus| | Bus  | |HW Bus|  |HW Bus |
-  +---------+     +--------+ +--+---+ | +--+---+ +------+ +------+  +-------+
-      |               |         |     |       |     |                    |
-      |   +-----------+--+      |     |       |    +---------------+     |
-      |   |Intel MIC     |      |     |       |    |Intel MIC      |     |
-      |   |Card Driver   |      |     |       |    |Host Driver    |     |
-      +---+--------------+------+     |       +----+---------------+-----+
-                 |                    |                   |
-             +-------------------------------------------------------------+
-             |                                                             |
-             |                    PCIe Bus                                 |
-             +-------------------------------------------------------------+
diff --git a/Documentation/misc-devices/mic/scif_overview.rst b/Documentation/misc-devices/mic/scif_overview.rst
deleted file mode 100644 (file)
index 4c8ad9e..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-========================================
-Symmetric Communication Interface (SCIF)
-========================================
-
-The Symmetric Communication Interface (SCIF (pronounced as skiff)) is a low
-level communications API across PCIe currently implemented for MIC. Currently
-SCIF provides inter-node communication within a single host platform, where a
-node is a MIC Coprocessor or Xeon based host. SCIF abstracts the details of
-communicating over the PCIe bus while providing an API that is symmetric
-across all the nodes in the PCIe network. An important design objective for SCIF
-is to deliver the maximum possible performance given the communication
-abilities of the hardware. SCIF has been used to implement an offload compiler
-runtime and OFED support for MPI implementations for MIC coprocessors.
-
-SCIF API Components
-===================
-
-The SCIF API has the following parts:
-
-1. Connection establishment using a client server model
-2. Byte stream messaging intended for short messages
-3. Node enumeration to determine online nodes
-4. Poll semantics for detection of incoming connections and messages
-5. Memory registration to pin down pages
-6. Remote memory mapping for low latency CPU accesses via mmap
-7. Remote DMA (RDMA) for high bandwidth DMA transfers
-8. Fence APIs for RDMA synchronization
-
-SCIF exposes the notion of a connection which can be used by peer processes on
-nodes in a SCIF PCIe "network" to share memory "windows" and to communicate. A
-process in a SCIF node initiates a SCIF connection to a peer process on a
-different node via a SCIF "endpoint". SCIF endpoints support messaging APIs
-which are similar to connection oriented socket APIs. Connected SCIF endpoints
-can also register local memory which is followed by data transfer using either
-DMA, CPU copies or remote memory mapping via mmap. SCIF supports both user and
-kernel mode clients which are functionally equivalent.
-
-SCIF Performance for MIC
-========================
-
-DMA bandwidth comparison between the TCP (over ethernet over PCIe) stack versus
-SCIF shows the performance advantages of SCIF for HPC applications and
-runtimes::
-
-             Comparison of TCP and SCIF based BW
-
-  Throughput (GB/sec)
-    8 +                                             PCIe Bandwidth ******
-      +                                                        TCP ######
-    7 +    **************************************             SCIF %%%%%%
-      |                       %%%%%%%%%%%%%%%%%%%
-    6 +                   %%%%
-      |                 %%
-      |               %%%
-    5 +              %%
-      |            %%
-    4 +           %%
-      |          %%
-    3 +         %%
-      |        %
-    2 +      %%
-      |     %%
-      |    %
-    1 +
-      +    ######################################
-    0 +++---+++--+--+-+--+--+-++-+--+-++-+--+-++-+-
-      1       10     100      1000   10000   100000
-                   Transfer Size (KBytes)
-
-SCIF allows memory sharing via mmap(..) between processes on different PCIe
-nodes and thus provides bare-metal PCIe latency. The round trip SCIF mmap
-latency from the host to an x100 MIC for an 8 byte message is 0.44 usecs.
-
-SCIF has a user space library which is a thin IOCTL wrapper providing a user
-space API similar to the kernel API in scif.h. The SCIF user space library
-is distributed @ https://software.intel.com/en-us/mic-developer
-
-Here is some pseudo code for an example of how two applications on two PCIe
-nodes would typically use the SCIF API::
-
-  Process A (on node A)                        Process B (on node B)
-
-  /* get online node information */
-  scif_get_node_ids(..)                        scif_get_node_ids(..)
-  scif_open(..)                                scif_open(..)
-  scif_bind(..)                                scif_bind(..)
-  scif_listen(..)
-  scif_accept(..)                              scif_connect(..)
-  /* SCIF connection established */
-
-  /* Send and receive short messages */
-  scif_send(..)/scif_recv(..)          scif_send(..)/scif_recv(..)
-
-  /* Register memory */
-  scif_register(..)                    scif_register(..)
-
-  /* RDMA */
-  scif_readfrom(..)/scif_writeto(..)   scif_readfrom(..)/scif_writeto(..)
-
-  /* Fence DMAs */
-  scif_fence_signal(..)                        scif_fence_signal(..)
-
-  mmap(..)                             mmap(..)
-
-  /* Access remote registered memory */
-
-  /* Close the endpoints */
-  scif_close(..)                               scif_close(..)
index b165181d5d4daa68cb7cfc3dcecf75d4511c1653..a432dc419fa4031d2b7c82961d6708dd552f688c 100644 (file)
@@ -70,6 +70,7 @@ The ``ice`` driver reports the following versions
         that both the name (as reported by ``fw.app.name``) and version are
         required to uniquely identify the package.
     * - ``fw.app.bundle_id``
+      - running
       - 0xc0000001
       - Unique identifier for the DDP package loaded in the device. Also
         referred to as the DDP Track ID. Can be used to uniquely identify
index f5be243d250a40e75d8bdef11b2489b56d7af691..0a4b73b03b997105bec7f1fa0bb1857c165a928d 100644 (file)
@@ -10,9 +10,9 @@ Overview / What Is J1939
 SAE J1939 defines a higher layer protocol on CAN. It implements a more
 sophisticated addressing scheme and extends the maximum packet size above 8
 bytes. Several derived specifications exist, which differ from the original
-J1939 on the application level, like MilCAN A, NMEA2000 and especially
+J1939 on the application level, like MilCAN A, NMEA2000, and especially
 ISO-11783 (ISOBUS). This last one specifies the so-called ETP (Extended
-Transport Protocol) which is has been included in this implementation. This
+Transport Protocol), which has been included in this implementation. This
 results in a maximum packet size of ((2 ^ 24) - 1) * 7 bytes == 111 MiB.
 
 Specifications used
@@ -32,15 +32,15 @@ sockets, we found some reasons to justify a kernel implementation for the
 addressing and transport methods used by J1939.
 
 * **Addressing:** when a process on an ECU communicates via J1939, it should
-  not necessarily know its source address. Although at least one process per
+  not necessarily know its source address. Although, at least one process per
   ECU should know the source address. Other processes should be able to reuse
   that address. This way, address parameters for different processes
   cooperating for the same ECU, are not duplicated. This way of working is
-  closely related to the UNIX concept where programs do just one thing, and do
+  closely related to the UNIX concept, where programs do just one thing and do
   it well.
 
 * **Dynamic addressing:** Address Claiming in J1939 is time critical.
-  Furthermore data transport should be handled properly during the address
+  Furthermore, data transport should be handled properly during the address
   negotiation. Putting this functionality in the kernel eliminates it as a
   requirement for _every_ user space process that communicates via J1939. This
   results in a consistent J1939 bus with proper addressing.
@@ -58,7 +58,7 @@ Therefore, these parts are left to user space.
 
 The J1939 sockets operate on CAN network devices (see SocketCAN). Any J1939
 user space library operating on CAN raw sockets will still operate properly.
-Since such library does not communicate with the in-kernel implementation, care
+Since such library does not communicate with the in-kernel implementation, care
 must be taken that these two do not interfere. In practice, this means they
 cannot share ECU addresses. A single ECU (or virtual ECU) address is used by
 the library exclusively, or by the in-kernel system exclusively.
@@ -77,13 +77,13 @@ is composed as follows:
 8 bits : PS (PDU Specific)
 
 In J1939-21 distinction is made between PDU1 format (where PF < 240) and PDU2
-format (where PF >= 240). Furthermore, when using PDU2 format, the PS-field
+format (where PF >= 240). Furthermore, when using the PDU2 format, the PS-field
 contains a so-called Group Extension, which is part of the PGN. When using PDU2
 format, the Group Extension is set in the PS-field.
 
 On the other hand, when using PDU1 format, the PS-field contains a so-called
 Destination Address, which is _not_ part of the PGN. When communicating a PGN
-from user space to kernel (or visa versa) and PDU2 format is used, the PS-field
+from user space to kernel (or vice versa) and PDU2 format is used, the PS-field
 of the PGN shall be set to zero. The Destination Address shall be set
 elsewhere.
 
@@ -96,15 +96,15 @@ Addressing
 
 Both static and dynamic addressing methods can be used.
 
-For static addresses, no extra checks are made by the kernel, and provided
+For static addresses, no extra checks are made by the kernel and provided
 addresses are considered right. This responsibility is for the OEM or system
 integrator.
 
 For dynamic addressing, so-called Address Claiming, extra support is foreseen
-in the kernel. In J1939 any ECU is known by it's 64-bit NAME. At the moment of
+in the kernel. In J1939 any ECU is known by its 64-bit NAME. At the moment of
 a successful address claim, the kernel keeps track of both NAME and source
 address being claimed. This serves as a base for filter schemes. By default,
-packets with a destination that is not locally, will be rejected.
+packets with a destination that is not locally will be rejected.
 
 Mixed mode packets (from a static to a dynamic address or vice versa) are
 allowed. The BSD sockets define separate API calls for getting/setting the
@@ -131,31 +131,31 @@ API Calls
 ---------
 
 On CAN, you first need to open a socket for communicating over a CAN network.
-To use J1939, #include <linux/can/j1939.h>. From there, <linux/can.h> will be
+To use J1939, ``#include <linux/can/j1939.h>``. From there, ``<linux/can.h>`` will be
 included too. To open a socket, use:
 
 .. code-block:: C
 
     s = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
 
-J1939 does use SOCK_DGRAM sockets. In the J1939 specification, connections are
+J1939 does use ``SOCK_DGRAM`` sockets. In the J1939 specification, connections are
 mentioned in the context of transport protocol sessions. These still deliver
-packets to the other end (using several CAN packets). SOCK_STREAM is not
+packets to the other end (using several CAN packets). ``SOCK_STREAM`` is not
 supported.
 
-After the successful creation of the socket, you would normally use the bind(2)
-and/or connect(2) system call to bind the socket to a CAN interface.  After
-binding and/or connecting the socket, you can read(2) and write(2) from/to the
-socket or use send(2), sendto(2), sendmsg(2) and the recv*() counterpart
+After the successful creation of the socket, you would normally use the ``bind(2)``
+and/or ``connect(2)`` system call to bind the socket to a CAN interface. After
+binding and/or connecting the socket, you can ``read(2)`` and ``write(2)`` from/to the
+socket or use ``send(2)``, ``sendto(2)``, ``sendmsg(2)`` and the ``recv*()`` counterpart
 operations on the socket as usual. There are also J1939 specific socket options
 described below.
 
-In order to send data, a bind(2) must have been successful. bind(2) assigns a
+In order to send data, a ``bind(2)`` must have been successful. ``bind(2)`` assigns a
 local address to a socket.
 
-Different from CAN is that the payload data is just the data that get send,
-without it's header info. The header info is derived from the sockaddr supplied
-to bind(2), connect(2), sendto(2) and recvfrom(2). A write(2) with size 4 will
+Different from CAN is that the payload data is just the data that get sends,
+without its header info. The header info is derived from the sockaddr supplied
+to ``bind(2)``, ``connect(2)``, ``sendto(2)`` and ``recvfrom(2)``. A ``write(2)`` with size 4 will
 result in a packet with 4 bytes.
 
 The sockaddr structure has extensions for use with J1939 as specified below:
@@ -180,47 +180,47 @@ The sockaddr structure has extensions for use with J1939 as specified below:
          } can_addr;
       }
 
-can_family & can_ifindex serve the same purpose as for other SocketCAN sockets.
+``can_family`` & ``can_ifindex`` serve the same purpose as for other SocketCAN sockets.
 
-can_addr.j1939.pgn specifies the PGN (max 0x3ffff). Individual bits are
+``can_addr.j1939.pgn`` specifies the PGN (max 0x3ffff). Individual bits are
 specified above.
 
-can_addr.j1939.name contains the 64-bit J1939 NAME.
+``can_addr.j1939.name`` contains the 64-bit J1939 NAME.
 
-can_addr.j1939.addr contains the address.
+``can_addr.j1939.addr`` contains the address.
 
-The bind(2) system call assigns the local address, i.e. the source address when
-sending packages. If a PGN during bind(2) is set, it's used as a RX filter.
-I.e.  only packets with a matching PGN are received. If an ADDR or NAME is set
+The ``bind(2)`` system call assigns the local address, i.e. the source address when
+sending packages. If a PGN during ``bind(2)`` is set, it's used as a RX filter.
+I.e. only packets with a matching PGN are received. If an ADDR or NAME is set
 it is used as a receive filter, too. It will match the destination NAME or ADDR
 of the incoming packet. The NAME filter will work only if appropriate Address
 Claiming for this name was done on the CAN bus and registered/cached by the
 kernel.
 
-On the other hand connect(2) assigns the remote address, i.e. the destination
-address. The PGN from connect(2) is used as the default PGN when sending
+On the other hand ``connect(2)`` assigns the remote address, i.e. the destination
+address. The PGN from ``connect(2)`` is used as the default PGN when sending
 packets. If ADDR or NAME is set it will be used as the default destination ADDR
-or NAME. Further a set ADDR or NAME during connect(2) is used as a receive
+or NAME. Further a set ADDR or NAME during ``connect(2)`` is used as a receive
 filter. It will match the source NAME or ADDR of the incoming packet.
 
-Both write(2) and send(2) will send a packet with local address from bind(2) and
-the remote address from connect(2). Use sendto(2) to overwrite the destination
+Both ``write(2)`` and ``send(2)`` will send a packet with local address from ``bind(2)`` and the
+remote address from ``connect(2)``. Use ``sendto(2)`` to overwrite the destination
 address.
 
-If can_addr.j1939.name is set (!= 0) the NAME is looked up by the kernel and
-the corresponding ADDR is used. If can_addr.j1939.name is not set (== 0),
-can_addr.j1939.addr is used.
+If ``can_addr.j1939.name`` is set (!= 0) the NAME is looked up by the kernel and
+the corresponding ADDR is used. If ``can_addr.j1939.name`` is not set (== 0),
+``can_addr.j1939.addr`` is used.
 
 When creating a socket, reasonable defaults are set. Some options can be
-modified with setsockopt(2) & getsockopt(2).
+modified with ``setsockopt(2)`` & ``getsockopt(2)``.
 
 RX path related options:
 
-- SO_J1939_FILTER - configure array of filters
-- SO_J1939_PROMISC - disable filters set by bind(2) and connect(2)
+- ``SO_J1939_FILTER`` - configure array of filters
+- ``SO_J1939_PROMISC`` - disable filters set by ``bind(2)`` and ``connect(2)``
 
 By default no broadcast packets can be send or received. To enable sending or
-receiving broadcast packets use the socket option SO_BROADCAST:
+receiving broadcast packets use the socket option ``SO_BROADCAST``:
 
 .. code-block:: C
 
@@ -261,26 +261,26 @@ The following diagram illustrates the RX path:
      +---------------------------+
 
 TX path related options:
-SO_J1939_SEND_PRIO - change default send priority for the socket
+``SO_J1939_SEND_PRIO`` - change default send priority for the socket
 
 Message Flags during send() and Related System Calls
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-send(2), sendto(2) and sendmsg(2) take a 'flags' argument. Currently
+``send(2)``, ``sendto(2)`` and ``sendmsg(2)`` take a 'flags' argument. Currently
 supported flags are:
 
-* MSG_DONTWAIT, i.e. non-blocking operation.
+* ``MSG_DONTWAIT``, i.e. non-blocking operation.
 
 recvmsg(2)
 ^^^^^^^^^^
 
-In most cases recvmsg(2) is needed if you want to extract more information than
-recvfrom(2) can provide. For example package priority and timestamp. The
+In most cases ``recvmsg(2)`` is needed if you want to extract more information than
+``recvfrom(2)`` can provide. For example package priority and timestamp. The
 Destination Address, name and packet priority (if applicable) are attached to
-the msghdr in the recvmsg(2) call. They can be extracted using cmsg(3) macros,
-with cmsg_level == SOL_J1939 && cmsg_type == SCM_J1939_DEST_ADDR,
-SCM_J1939_DEST_NAME or SCM_J1939_PRIO. The returned data is a uint8_t for
-priority and dst_addr, and uint64_t for dst_name.
+the msghdr in the ``recvmsg(2)`` call. They can be extracted using ``cmsg(3)`` macros,
+with ``cmsg_level == SOL_J1939 && cmsg_type == SCM_J1939_DEST_ADDR``,
+``SCM_J1939_DEST_NAME`` or ``SCM_J1939_PRIO``. The returned data is a ``uint8_t`` for
+``priority`` and ``dst_addr``, and ``uint64_t`` for ``dst_name``.
 
 .. code-block:: C
 
@@ -305,12 +305,12 @@ Dynamic Addressing
 
 Distinction has to be made between using the claimed address and doing an
 address claim. To use an already claimed address, one has to fill in the
-j1939.name member and provide it to bind(2). If the name had claimed an address
+``j1939.name`` member and provide it to ``bind(2)``. If the name had claimed an address
 earlier, all further messages being sent will use that address. And the
-j1939.addr member will be ignored.
+``j1939.addr`` member will be ignored.
 
 An exception on this is PGN 0x0ee00. This is the "Address Claim/Cannot Claim
-Address" message and the kernel will use the j1939.addr member for that PGN if
+Address" message and the kernel will use the ``j1939.addr`` member for that PGN if
 necessary.
 
 To claim an address following code example can be used:
@@ -371,12 +371,12 @@ NAME can send packets.
 
 If another ECU claims the address, the kernel will mark the NAME-SA expired.
 No socket bound to the NAME can send packets (other than address claims). To
-claim another address, some socket bound to NAME, must bind(2) again, but with
-only j1939.addr changed to the new SA, and must then send a valid address claim
+claim another address, some socket bound to NAME, must ``bind(2)`` again, but with
+only ``j1939.addr`` changed to the new SA, and must then send a valid address claim
 packet. This restarts the state machine in the kernel (and any other
 participant on the bus) for this NAME.
 
-can-utils also include the jacd tool, so it can be used as code example or as
+``can-utils`` also include the ``j1939acd`` tool, so it can be used as code example or as
 default Address Claiming daemon.
 
 Send Examples
@@ -403,8 +403,8 @@ Bind:
 
        bind(sock, (struct sockaddr *)&baddr, sizeof(baddr));
 
-Now, the socket 'sock' is bound to the SA 0x20. Since no connect(2) was called,
-at this point we can use only sendto(2) or sendmsg(2).
+Now, the socket 'sock' is bound to the SA 0x20. Since no ``connect(2)`` was called,
+at this point we can use only ``sendto(2)`` or ``sendmsg(2)``.
 
 Send:
 
@@ -414,8 +414,8 @@ Send:
                .can_family = AF_CAN,
                .can_addr.j1939 = {
                        .name = J1939_NO_NAME;
-                       .pgn = 0x30,
-                       .addr = 0x12300,
+                       .addr = 0x30,
+                       .pgn = 0x12300,
                },
        };
 
index d5c9320901c3273b99bcc1b4cda78c5472d9f6fd..4b9ed5874d5ad183d827b698d68c5b4146674a7a 100644 (file)
@@ -110,7 +110,7 @@ Q: I sent a patch and I'm wondering what happened to it?
 Q: How can I tell whether it got merged?
 A: Start by looking at the main patchworks queue for netdev:
 
-  http://patchwork.ozlabs.org/project/netdev/list/
+  https://patchwork.kernel.org/project/netdevbpf/list/
 
 The "State" field will tell you exactly where things are at with your
 patch.
@@ -152,7 +152,7 @@ networking subsystem, and then hands them off to Greg.
 
 There is a patchworks queue that you can see here:
 
-  http://patchwork.ozlabs.org/bundle/davem/stable/?state=*
+  https://patchwork.kernel.org/bundle/netdev/stable/?state=*
 
 It contains the patches which Dave has selected, but not yet handed off
 to Greg.  If Greg already has the patch, then it will be here:
@@ -254,6 +254,32 @@ you will have done run-time testing specific to your change, but at a
 minimum, your changes should survive an ``allyesconfig`` and an
 ``allmodconfig`` build without new warnings or failures.
 
+Q: How do I post corresponding changes to user space components?
+----------------------------------------------------------------
+A: User space code exercising kernel features should be posted
+alongside kernel patches. This gives reviewers a chance to see
+how any new interface is used and how well it works.
+
+When user space tools reside in the kernel repo itself all changes
+should generally come as one series. If series becomes too large
+or the user space project is not reviewed on netdev include a link
+to a public repo where user space patches can be seen.
+
+In case user space tooling lives in a separate repository but is
+reviewed on netdev  (e.g. patches to `iproute2` tools) kernel and
+user space patches should form separate series (threads) when posted
+to the mailing list, e.g.::
+
+  [PATCH net-next 0/3] net: some feature cover letter
+   â””─ [PATCH net-next 1/3] net: some feature prep
+   â””─ [PATCH net-next 2/3] net: some feature do it
+   â””─ [PATCH net-next 3/3] selftest: net: some feature
+
+  [PATCH iproute2-next] ip: add support for some feature
+
+Posting as one thread is discouraged because it confuses patchwork
+(as of patchwork 2.2.2).
+
 Q: Any other tips to help ensure my net/net-next patch gets OK'd?
 -----------------------------------------------------------------
 A: Attention to detail.  Re-read your own work as if you were the
index 256106054c8cb0b9d7fdc0a01f35100a388e6f08..b2f7ec794bc8b6cd3164c3016718474fc8b43756 100644 (file)
@@ -247,8 +247,8 @@ Some of the interface modes are described below:
     speeds (see below.)
 
 ``PHY_INTERFACE_MODE_2500BASEX``
-    This defines a variant of 1000BASE-X which is clocked 2.5 times faster,
-    than the 802.3 standard giving a fixed bit rate of 3.125Gbaud.
+    This defines a variant of 1000BASE-X which is clocked 2.5 times as fast
+    as the 802.3 standard, giving a fixed bit rate of 3.125Gbaud.
 
 ``PHY_INTERFACE_MODE_SGMII``
     This is used for Cisco SGMII, which is a modification of 1000BASE-X
index 8e15bc98830b70bd5e51fd73e1f145c8e6dc9c36..234abedc29b2b525855c0db8f87d83268813ff9d 100644 (file)
@@ -175,5 +175,4 @@ The following structures are internal to the kernel, their members are
 translated to netlink attributes when dumped. Drivers must not overwrite
 the statistics they don't report with 0.
 
-.. kernel-doc:: include/linux/ethtool.h
-    :identifiers: ethtool_pause_stats
+- ethtool_pause_stats()
index 06f743b612c48bbed43f9e48502e277901aa294a..3973556250e17050a32309edd7b225554c81e394 100644 (file)
@@ -39,7 +39,7 @@ Procedure for submitting patches to the -stable tree
    submission guidelines as described in
    :ref:`Documentation/networking/netdev-FAQ.rst <netdev-FAQ>`
    after first checking the stable networking queue at
-   https://patchwork.ozlabs.org/bundle/davem/stable/?series=&submitter=&state=*&q=&archive=
+   https://patchwork.kernel.org/bundle/netdev/stable/?state=*
    to ensure the requested patch is not already queued up.
  - Security patches should not be handled (solely) by the -stable review
    process but should follow the procedures in
index 409dbc4100def91ee496d32f3a66efef1fe8993d..3e81ebab26ed3c4b18dbaae4e13481f724780268 100644 (file)
@@ -15,6 +15,14 @@ else:
 import re
 from itertools import chain
 
+#
+# Python 2 lacks re.ASCII...
+#
+try:
+    ascii_p3 = re.ASCII
+except AttributeError:
+    ascii_p3 = 0
+
 #
 # Regex nastiness.  Of course.
 # Try to identify "function()" that's not already marked up some
@@ -22,22 +30,22 @@ from itertools import chain
 # :c:func: block (i.e. ":c:func:`mmap()`s" flakes out), so the last
 # bit tries to restrict matches to things that won't create trouble.
 #
-RE_function = re.compile(r'\b(([a-zA-Z_]\w+)\(\))', flags=re.ASCII)
+RE_function = re.compile(r'\b(([a-zA-Z_]\w+)\(\))', flags=ascii_p3)
 
 #
 # Sphinx 2 uses the same :c:type role for struct, union, enum and typedef
 #
 RE_generic_type = re.compile(r'\b(struct|union|enum|typedef)\s+([a-zA-Z_]\w+)',
-                             flags=re.ASCII)
+                             flags=ascii_p3)
 
 #
 # Sphinx 3 uses a different C role for each one of struct, union, enum and
 # typedef
 #
-RE_struct = re.compile(r'\b(struct)\s+([a-zA-Z_]\w+)', flags=re.ASCII)
-RE_union = re.compile(r'\b(union)\s+([a-zA-Z_]\w+)', flags=re.ASCII)
-RE_enum = re.compile(r'\b(enum)\s+([a-zA-Z_]\w+)', flags=re.ASCII)
-RE_typedef = re.compile(r'\b(typedef)\s+([a-zA-Z_]\w+)', flags=re.ASCII)
+RE_struct = re.compile(r'\b(struct)\s+([a-zA-Z_]\w+)', flags=ascii_p3)
+RE_union = re.compile(r'\b(union)\s+([a-zA-Z_]\w+)', flags=ascii_p3)
+RE_enum = re.compile(r'\b(enum)\s+([a-zA-Z_]\w+)', flags=ascii_p3)
+RE_typedef = re.compile(r'\b(typedef)\s+([a-zA-Z_]\w+)', flags=ascii_p3)
 
 #
 # Detects a reference to a documentation page of the form Documentation/... with
diff --git a/Documentation/sphinx/kernel_abi.py b/Documentation/sphinx/kernel_abi.py
new file mode 100644 (file)
index 0000000..f3da859
--- /dev/null
@@ -0,0 +1,194 @@
+# -*- coding: utf-8; mode: python -*-
+# coding=utf-8
+# SPDX-License-Identifier: GPL-2.0
+#
+u"""
+    kernel-abi
+    ~~~~~~~~~~
+
+    Implementation of the ``kernel-abi`` reST-directive.
+
+    :copyright:  Copyright (C) 2016  Markus Heiser
+    :copyright:  Copyright (C) 2016-2020  Mauro Carvalho Chehab
+    :maintained-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+    :license:    GPL Version 2, June 1991 see Linux/COPYING for details.
+
+    The ``kernel-abi`` (:py:class:`KernelCmd`) directive calls the
+    scripts/get_abi.pl script to parse the Kernel ABI files.
+
+    Overview of directive's argument and options.
+
+    .. code-block:: rst
+
+        .. kernel-abi:: <ABI directory location>
+            :debug:
+
+    The argument ``<ABI directory location>`` is required. It contains the
+    location of the ABI files to be parsed.
+
+    ``debug``
+      Inserts a code-block with the *raw* reST. Sometimes it is helpful to see
+      what reST is generated.
+
+"""
+
+import codecs
+import os
+import subprocess
+import sys
+import re
+import kernellog
+
+from os import path
+
+from docutils import nodes, statemachine
+from docutils.statemachine import ViewList
+from docutils.parsers.rst import directives, Directive
+from docutils.utils.error_reporting import ErrorString
+
+#
+# AutodocReporter is only good up to Sphinx 1.7
+#
+import sphinx
+
+Use_SSI = sphinx.__version__[:3] >= '1.7'
+if Use_SSI:
+    from sphinx.util.docutils import switch_source_input
+else:
+    from sphinx.ext.autodoc import AutodocReporter
+
+__version__  = '1.0'
+
+def setup(app):
+
+    app.add_directive("kernel-abi", KernelCmd)
+    return dict(
+        version = __version__
+        , parallel_read_safe = True
+        , parallel_write_safe = True
+    )
+
+class KernelCmd(Directive):
+
+    u"""KernelABI (``kernel-abi``) directive"""
+
+    required_arguments = 1
+    optional_arguments = 2
+    has_content = False
+    final_argument_whitespace = True
+
+    option_spec = {
+        "debug"     : directives.flag,
+        "rst"       : directives.unchanged
+    }
+
+    def run(self):
+
+        doc = self.state.document
+        if not doc.settings.file_insertion_enabled:
+            raise self.warning("docutils: file insertion disabled")
+
+        env = doc.settings.env
+        cwd = path.dirname(doc.current_source)
+        cmd = "get_abi.pl rest --enable-lineno --dir "
+        cmd += self.arguments[0]
+
+        if 'rst' in self.options:
+            cmd += " --rst-source"
+
+        srctree = path.abspath(os.environ["srctree"])
+
+        fname = cmd
+
+        # extend PATH with $(srctree)/scripts
+        path_env = os.pathsep.join([
+            srctree + os.sep + "scripts",
+            os.environ["PATH"]
+        ])
+        shell_env = os.environ.copy()
+        shell_env["PATH"]    = path_env
+        shell_env["srctree"] = srctree
+
+        lines = self.runCmd(cmd, shell=True, cwd=cwd, env=shell_env)
+        nodeList = self.nestedParse(lines, self.arguments[0])
+        return nodeList
+
+    def runCmd(self, cmd, **kwargs):
+        u"""Run command ``cmd`` and return it's stdout as unicode."""
+
+        try:
+            proc = subprocess.Popen(
+                cmd
+                , stdout = subprocess.PIPE
+                , stderr = subprocess.PIPE
+                , **kwargs
+            )
+            out, err = proc.communicate()
+
+            out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
+
+            if proc.returncode != 0:
+                raise self.severe(
+                    u"command '%s' failed with return code %d"
+                    % (cmd, proc.returncode)
+                )
+        except OSError as exc:
+            raise self.severe(u"problems with '%s' directive: %s."
+                              % (self.name, ErrorString(exc)))
+        return out
+
+    def nestedParse(self, lines, fname):
+        content = ViewList()
+        node = nodes.section()
+
+        if "debug" in self.options:
+            code_block = "\n\n.. code-block:: rst\n    :linenos:\n"
+            for l in lines.split("\n"):
+                code_block += "\n    " + l
+            lines = code_block + "\n\n"
+
+        line_regex = re.compile("^#define LINENO (\S+)\#([0-9]+)$")
+        ln = 0
+        n = 0
+        f = fname
+
+        for line in lines.split("\n"):
+            n = n + 1
+            match = line_regex.search(line)
+            if match:
+                new_f = match.group(1)
+
+                # Sphinx parser is lazy: it stops parsing contents in the
+                # middle, if it is too big. So, handle it per input file
+                if new_f != f and content:
+                    self.do_parse(content, node)
+                    content = ViewList()
+
+                f = new_f
+
+                # sphinx counts lines from 0
+                ln = int(match.group(2)) - 1
+            else:
+                content.append(line, f, ln)
+
+        kernellog.info(self.state.document.settings.env.app, "%s: parsed %i lines" % (fname, n))
+
+        if content:
+            self.do_parse(content, node)
+
+        return node.children
+
+    def do_parse(self, content, node):
+        if Use_SSI:
+            with switch_source_input(self.state, content):
+                self.state.nested_parse(content, 0, node, match_titles=1)
+        else:
+            buf  = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
+
+            self.state.memo.title_styles  = []
+            self.state.memo.section_level = 0
+            self.state.memo.reporter      = AutodocReporter(content, self.state.memo.reporter)
+            try:
+                self.state.nested_parse(content, 0, node, match_titles=1)
+            finally:
+                self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf
index af924f51a7dcc5838c80a11c3ff4447e500936e2..8ac7d274f542b78d9e6061b4f6900e309d817613 100644 (file)
@@ -25,4 +25,8 @@ def verbose(app, message):
     else:
         app.verbose(message)
 
-
+def info(app, message):
+    if UseLogging:
+        logger.info(message)
+    else:
+        app.info(message)
index 4f206cee31a74e0cf76fd34de78c3e98b3e1440e..283d62541c4ff1ff0e346c11e58b5827951f138f 100644 (file)
@@ -46,7 +46,7 @@ Procedura per sottomettere patch per i sorgenti -stable
    :ref:`Documentation/translations/it_IT/networking/netdev-FAQ.rst <it_netdev-FAQ>`;
    ma solo dopo aver verificato al seguente indirizzo che la patch non sia
    già in coda:
-   https://patchwork.ozlabs.org/bundle/davem/stable/?series=&submitter=&state=*&q=&archive=
+   https://patchwork.kernel.org/bundle/netdev/stable/?state=*
  - Una patch di sicurezza non dovrebbero essere gestite (solamente) dal processo
    di revisione -stable, ma dovrebbe seguire le procedure descritte in
    :ref:`Documentation/translations/it_IT/admin-guide/security-bugs.rst <it_securitybugs>`.
index 69fc5167e6486b6c6378b80a08df7ce1651fb051..acd2cc2a538df5f9a4bb8343c423fa1ef4b7e6d4 100644 (file)
@@ -22,6 +22,7 @@ place where this information is gathered.
    spec_ctrl
    accelerators/ocxl
    ioctl/index
+   iommu
    media/index
 
 .. only::  subproject and html
index 36d5f1f3c6dd32ec72cb3add8126f2a6eeefafd3..e00a66d7237285a9716814d9cf791c06bceb94a7 100644 (file)
@@ -6367,7 +6367,7 @@ accesses that would usually trigger a #GP by KVM into the guest will
 instead get bounced to user space through the KVM_EXIT_X86_RDMSR and
 KVM_EXIT_X86_WRMSR exit notifications.
 
-8.25 KVM_X86_SET_MSR_FILTER
+8.27 KVM_X86_SET_MSR_FILTER
 ---------------------------
 
 :Architectures: x86
@@ -6381,8 +6381,7 @@ In combination with KVM_CAP_X86_USER_SPACE_MSR, this allows user space to
 trap and emulate MSRs that are outside of the scope of KVM as well as
 limit the attack surface on KVM's MSR emulation code.
 
-
-8.26 KVM_CAP_ENFORCE_PV_CPUID
+8.28 KVM_CAP_ENFORCE_PV_CPUID
 -----------------------------
 
 Architectures: x86
index 7d81c0aa4a59c1303224ab8f534825d02143d159..cf62162d4be207e5e9f8beaecf2f044cb7352d8a 100644 (file)
@@ -92,6 +92,10 @@ KVM_FEATURE_ASYNC_PF_INT           14          guest checks this feature bit
                                                async pf acknowledgment msr
                                                0x4b564d07.
 
+KVM_FEATURE_MSI_EXT_DEST_ID        15          guest checks this feature bit
+                                               before using extended destination
+                                               ID bits in MSI address bits 11-5.
+
 KVM_FEATURE_CLOCKSOURCE_STABLE_BIT 24          host will warn if no guest-side
                                                per-cpu warps are expected in
                                                kvmclock
index e52a12960fdc4831ab5298d51f510381133e1db9..450573afa31a611a2d47d5479d3865bf1f24b444 100644 (file)
@@ -82,7 +82,8 @@ Default MMUv2-compatible layout::
   +------------------+
   | VMALLOC area     |  VMALLOC_START            0xc0000000  128MB - 64KB
   +------------------+  VMALLOC_END
-  | Cache aliasing   |  TLBTEMP_BASE_1           0xc7ff0000  DCACHE_WAY_SIZE
+  +------------------+
+  | Cache aliasing   |  TLBTEMP_BASE_1           0xc8000000  DCACHE_WAY_SIZE
   | remap area 1     |
   +------------------+
   | Cache aliasing   |  TLBTEMP_BASE_2                       DCACHE_WAY_SIZE
@@ -124,7 +125,8 @@ Default MMUv2-compatible layout::
   +------------------+
   | VMALLOC area     |  VMALLOC_START            0xa0000000  128MB - 64KB
   +------------------+  VMALLOC_END
-  | Cache aliasing   |  TLBTEMP_BASE_1           0xa7ff0000  DCACHE_WAY_SIZE
+  +------------------+
+  | Cache aliasing   |  TLBTEMP_BASE_1           0xa8000000  DCACHE_WAY_SIZE
   | remap area 1     |
   +------------------+
   | Cache aliasing   |  TLBTEMP_BASE_2                       DCACHE_WAY_SIZE
@@ -167,7 +169,8 @@ Default MMUv2-compatible layout::
   +------------------+
   | VMALLOC area     |  VMALLOC_START            0x90000000  128MB - 64KB
   +------------------+  VMALLOC_END
-  | Cache aliasing   |  TLBTEMP_BASE_1           0x97ff0000  DCACHE_WAY_SIZE
+  +------------------+
+  | Cache aliasing   |  TLBTEMP_BASE_1           0x98000000  DCACHE_WAY_SIZE
   | remap area 1     |
   +------------------+
   | Cache aliasing   |  TLBTEMP_BASE_2                       DCACHE_WAY_SIZE
index 86eb55697c8b9152b7aabd8778e6cb5e6d935d60..4168301b159f4803a4c955def1d1dfb61f732442 100644 (file)
@@ -934,7 +934,7 @@ M:  Evan Quan <evan.quan@amd.com>
 L:     amd-gfx@lists.freedesktop.org
 S:     Supported
 T:     git git://people.freedesktop.org/~agd5f/linux
-F:     drivers/gpu/drm/amd/powerplay/
+F:     drivers/gpu/drm/amd/pm/powerplay/
 
 AMD SEATTLE DEVICE TREE SUPPORT
 M:     Brijesh Singh <brijeshkumar.singh@amd.com>
@@ -978,7 +978,7 @@ M:  Michael Hennerich <Michael.Hennerich@analog.com>
 L:     linux-iio@vger.kernel.org
 S:     Supported
 W:     http://ez.analog.com/community/linux-device-drivers
-F:     Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.txt
+F:     Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml
 F:     drivers/iio/adc/ad7768-1.c
 
 ANALOG DEVICES INC AD7780 DRIVER
@@ -1279,7 +1279,7 @@ M:        Igor Russkikh <irusskikh@marvell.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 W:     https://www.marvell.com/
-Q:     http://patchwork.ozlabs.org/project/netdev/list/
+Q:     https://patchwork.kernel.org/project/netdevbpf/list/
 F:     Documentation/networking/device_drivers/ethernet/aquantia/atlantic.rst
 F:     drivers/net/ethernet/aquantia/atlantic/
 
@@ -1546,6 +1546,7 @@ F:        drivers/clk/sunxi/
 ARM/Allwinner sunXi SoC support
 M:     Maxime Ripard <mripard@kernel.org>
 M:     Chen-Yu Tsai <wens@csie.org>
+R:     Jernej Skrabec <jernej.skrabec@siol.net>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git
@@ -1723,11 +1724,13 @@ F:      arch/arm/mach-ep93xx/micro9.c
 
 ARM/CORESIGHT FRAMEWORK AND DRIVERS
 M:     Mathieu Poirier <mathieu.poirier@linaro.org>
-R:     Suzuki K Poulose <suzuki.poulose@arm.com>
+M:     Suzuki K Poulose <suzuki.poulose@arm.com>
 R:     Mike Leach <mike.leach@linaro.org>
+R:     Leo Yan <leo.yan@linaro.org>
 L:     coresight@lists.linaro.org (moderated for non-subscribers)
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/coresight/linux.git
 F:     Documentation/ABI/testing/sysfs-bus-coresight-devices-*
 F:     Documentation/devicetree/bindings/arm/coresight-cpu-debug.txt
 F:     Documentation/devicetree/bindings/arm/coresight-cti.yaml
@@ -1994,7 +1997,6 @@ N:        lpc18xx
 
 ARM/LPC32XX SOC SUPPORT
 M:     Vladimir Zapolskiy <vz@mleia.com>
-M:     Sylvain Lemieux <slemieux.tyco@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 T:     git git://github.com/vzapolskiy/linux-lpc32xx.git
@@ -2012,7 +2014,6 @@ M:        Philipp Zabel <philipp.zabel@gmail.com>
 S:     Maintained
 
 ARM/Marvell Dove/MV78xx0/Orion SOC support
-M:     Jason Cooper <jason@lakedaemon.net>
 M:     Andrew Lunn <andrew@lunn.ch>
 M:     Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
 M:     Gregory Clement <gregory.clement@bootlin.com>
@@ -2029,7 +2030,6 @@ F:        arch/arm/plat-orion/
 F:     drivers/soc/dove/
 
 ARM/Marvell Kirkwood and Armada 370, 375, 38x, 39x, XP, 3700, 7K/8K, CN9130 SOC support
-M:     Jason Cooper <jason@lakedaemon.net>
 M:     Andrew Lunn <andrew@lunn.ch>
 M:     Gregory Clement <gregory.clement@bootlin.com>
 M:     Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
@@ -2374,8 +2374,7 @@ F:        drivers/i2c/busses/i2c-rk3x.c
 F:     sound/soc/rockchip/
 N:     rockchip
 
-ARM/SAMSUNG EXYNOS ARM ARCHITECTURES
-M:     Kukjin Kim <kgene@kernel.org>
+ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES
 M:     Krzysztof Kozlowski <krzk@kernel.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-samsung-soc@vger.kernel.org
@@ -2404,15 +2403,7 @@ N:       s3c2410
 N:     s3c64xx
 N:     s5pv210
 
-ARM/SAMSUNG MOBILE MACHINE SUPPORT
-M:     Kyungmin Park <kyungmin.park@samsung.com>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     Maintained
-F:     arch/arm/mach-s5pv210/
-
 ARM/SAMSUNG S5P SERIES 2D GRAPHICS ACCELERATION (G2D) SUPPORT
-M:     Kyungmin Park <kyungmin.park@samsung.com>
-M:     Kamil Debski <kamil@wypas.org>
 M:     Andrzej Hajda <a.hajda@samsung.com>
 L:     linux-arm-kernel@lists.infradead.org
 L:     linux-media@vger.kernel.org
@@ -2437,9 +2428,6 @@ S:        Maintained
 F:     drivers/media/platform/s5p-jpeg/
 
 ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT
-M:     Kyungmin Park <kyungmin.park@samsung.com>
-M:     Kamil Debski <kamil@wypas.org>
-M:     Jeongtae Park <jtp.park@samsung.com>
 M:     Andrzej Hajda <a.hajda@samsung.com>
 L:     linux-arm-kernel@lists.infradead.org
 L:     linux-media@vger.kernel.org
@@ -2486,7 +2474,7 @@ F:        drivers/clk/socfpga/
 ARM/SOCFPGA EDAC SUPPORT
 M:     Dinh Nguyen <dinguyen@kernel.org>
 S:     Maintained
-F:     drivers/edac/altera_edac.
+F:     drivers/edac/altera_edac.[ch]
 
 ARM/SPREADTRUM SoC SUPPORT
 M:     Orson Zhai <orsonzhai@gmail.com>
@@ -2642,10 +2630,8 @@ F:       drivers/pinctrl/visconti/
 N:     visconti
 
 ARM/UNIPHIER ARCHITECTURE
-M:     Masahiro Yamada <yamada.masahiro@socionext.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     Maintained
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-uniphier.git
+S:     Orphan
 F:     Documentation/devicetree/bindings/arm/socionext/uniphier.yaml
 F:     Documentation/devicetree/bindings/gpio/socionext,uniphier-gpio.yaml
 F:     Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.yaml
@@ -3246,10 +3232,10 @@ F:      drivers/iio/accel/bma400*
 BPF (Safe dynamic programs and tools)
 M:     Alexei Starovoitov <ast@kernel.org>
 M:     Daniel Borkmann <daniel@iogearbox.net>
+M:     Andrii Nakryiko <andrii@kernel.org>
 R:     Martin KaFai Lau <kafai@fb.com>
 R:     Song Liu <songliubraving@fb.com>
 R:     Yonghong Song <yhs@fb.com>
-R:     Andrii Nakryiko <andrii@kernel.org>
 R:     John Fastabend <john.fastabend@gmail.com>
 R:     KP Singh <kpsingh@chromium.org>
 L:     netdev@vger.kernel.org
@@ -3369,6 +3355,17 @@ S:       Supported
 F:     arch/x86/net/
 X:     arch/x86/net/bpf_jit_comp32.c
 
+BPF LSM (Security Audit and Enforcement using BPF)
+M:     KP Singh <kpsingh@chromium.org>
+R:     Florent Revest <revest@chromium.org>
+R:     Brendan Jackman <jackmanb@chromium.org>
+L:     bpf@vger.kernel.org
+S:     Maintained
+F:     Documentation/bpf/bpf_lsm.rst
+F:     include/linux/bpf_lsm.h
+F:     kernel/bpf/bpf_lsm.c
+F:     security/bpf/
+
 BROADCOM B44 10/100 ETHERNET DRIVER
 M:     Michael Chan <michael.chan@broadcom.com>
 L:     netdev@vger.kernel.org
@@ -3541,11 +3538,12 @@ BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER
 M:     Arend van Spriel <arend.vanspriel@broadcom.com>
 M:     Franky Lin <franky.lin@broadcom.com>
 M:     Hante Meuleman <hante.meuleman@broadcom.com>
-M:     Chi-Hsien Lin <chi-hsien.lin@cypress.com>
-M:     Wright Feng <wright.feng@cypress.com>
+M:     Chi-hsien Lin <chi-hsien.lin@infineon.com>
+M:     Wright Feng <wright.feng@infineon.com>
+M:     Chung-hsien Hsu <chung-hsien.hsu@infineon.com>
 L:     linux-wireless@vger.kernel.org
 L:     brcm80211-dev-list.pdl@broadcom.com
-L:     brcm80211-dev-list@cypress.com
+L:     SHA-cyfmac-dev-list@infineon.com
 S:     Supported
 F:     drivers/net/wireless/broadcom/brcm80211/
 
@@ -3860,7 +3858,7 @@ M:        Roger Quadros <rogerq@ti.com>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
-F:     Documentation/devicetree/bindings/usb/cdns-usb3.txt
+F:     Documentation/devicetree/bindings/usb/cdns,usb3.yaml
 F:     drivers/usb/cdns3/
 
 CADET FM/AM RADIO RECEIVER DRIVER
@@ -4287,6 +4285,7 @@ B:        https://github.com/ClangBuiltLinux/linux/issues
 C:     irc://chat.freenode.net/clangbuiltlinux
 F:     Documentation/kbuild/llvm.rst
 F:     scripts/clang-tools/
+F:     scripts/lld-version.sh
 K:     \b(?i:clang|llvm)\b
 
 CLEANCACHE API
@@ -4713,7 +4712,7 @@ T:        git git://linuxtv.org/anttip/media_tree.git
 F:     drivers/media/dvb-frontends/cxd2820r*
 
 CXGB3 ETHERNET DRIVER (CXGB3)
-M:     Vishal Kulkarni <vishal@chelsio.com>
+M:     Raju Rangoju <rajur@chelsio.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.chelsio.com
@@ -4745,7 +4744,7 @@ W:        http://www.chelsio.com
 F:     drivers/net/ethernet/chelsio/inline_crypto/
 
 CXGB4 ETHERNET DRIVER (CXGB4)
-M:     Vishal Kulkarni <vishal@chelsio.com>
+M:     Raju Rangoju <rajur@chelsio.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.chelsio.com
@@ -4767,7 +4766,7 @@ F:        drivers/infiniband/hw/cxgb4/
 F:     include/uapi/rdma/cxgb4-abi.h
 
 CXGB4VF ETHERNET DRIVER (CXGB4VF)
-M:     Vishal Kulkarni <vishal@gmail.com>
+M:     Raju Rangoju <rajur@chelsio.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.chelsio.com
@@ -5006,9 +5005,8 @@ T:        git git://linuxtv.org/media_tree.git
 F:     drivers/media/platform/sti/delta
 
 DENALI NAND DRIVER
-M:     Masahiro Yamada <yamada.masahiro@socionext.com>
 L:     linux-mtd@lists.infradead.org
-S:     Supported
+S:     Orphan
 F:     drivers/mtd/nand/raw/denali*
 
 DESIGNWARE EDMA CORE IP DRIVER
@@ -6409,7 +6407,7 @@ EDAC-SKYLAKE
 M:     Tony Luck <tony.luck@intel.com>
 L:     linux-edac@vger.kernel.org
 S:     Maintained
-F:     drivers/edac/skx_*.c
+F:     drivers/edac/skx_*.[ch]
 
 EDAC-TI
 M:     Tero Kristo <t-kristo@ti.com>
@@ -6625,6 +6623,7 @@ Q:        http://patchwork.ozlabs.org/project/linux-ext4/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git
 F:     Documentation/filesystems/ext4/
 F:     fs/ext4/
+F:     include/trace/events/ext4.h
 
 Extended Verification Module (EVM)
 M:     Mimi Zohar <zohar@linux.ibm.com>
@@ -7927,7 +7926,7 @@ HISILICON LPC BUS DRIVER
 M:     john.garry@huawei.com
 S:     Maintained
 W:     http://www.hisilicon.com
-F:     Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
+F:     Documentation/devicetree/bindings/arm/hisilicon/low-pin-count.yaml
 F:     drivers/bus/hisi_lpc.c
 
 HISILICON NETWORK SUBSYSTEM 3 DRIVER (HNS3)
@@ -8840,8 +8839,8 @@ S:        Supported
 W:     http://www.intel.com/support/feedback.htm
 W:     http://e1000.sourceforge.net/
 Q:     http://patchwork.ozlabs.org/project/intel-wired-lan/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-queue.git
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue.git
 F:     Documentation/networking/device_drivers/ethernet/intel/
 F:     drivers/net/ethernet/intel/
 F:     drivers/net/ethernet/intel/*/
@@ -8983,22 +8982,6 @@ S:       Supported
 W:     https://01.org/linux-acpi
 F:     drivers/platform/x86/intel_menlow.c
 
-INTEL MIC DRIVERS (mic)
-M:     Sudeep Dutt <sudeep.dutt@intel.com>
-M:     Ashutosh Dixit <ashutosh.dixit@intel.com>
-S:     Supported
-W:     https://github.com/sudeepdutt/mic
-W:     http://software.intel.com/en-us/mic-developer
-F:     Documentation/misc-devices/mic/
-F:     drivers/dma/mic_x100_dma.c
-F:     drivers/dma/mic_x100_dma.h
-F:     drivers/misc/mic/
-F:     include/linux/mic_bus.h
-F:     include/linux/scif.h
-F:     include/uapi/linux/mic_common.h
-F:     include/uapi/linux/mic_ioctl.h
-F:     include/uapi/linux/scif_ioctl.h
-
 INTEL P-Unit IPC DRIVER
 M:     Zha Qipeng <qipeng.zha@intel.com>
 L:     platform-driver-x86@vger.kernel.org
@@ -9103,10 +9086,7 @@ S:       Supported
 F:     drivers/net/wireless/intel/iwlegacy/
 
 INTEL WIRELESS WIFI LINK (iwlwifi)
-M:     Johannes Berg <johannes.berg@intel.com>
-M:     Emmanuel Grumbach <emmanuel.grumbach@intel.com>
 M:     Luca Coelho <luciano.coelho@intel.com>
-M:     Intel Linux Wireless <linuxwifi@intel.com>
 L:     linux-wireless@vger.kernel.org
 S:     Supported
 W:     https://wireless.wiki.kernel.org/en/users/drivers/iwlwifi
@@ -9198,6 +9178,7 @@ F:        include/linux/iomap.h
 
 IOMMU DRIVERS
 M:     Joerg Roedel <joro@8bytes.org>
+M:     Will Deacon <will@kernel.org>
 L:     iommu@lists.linux-foundation.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
@@ -9281,7 +9262,6 @@ F:        kernel/irq/
 
 IRQCHIP DRIVERS
 M:     Thomas Gleixner <tglx@linutronix.de>
-M:     Jason Cooper <jason@lakedaemon.net>
 M:     Marc Zyngier <maz@kernel.org>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
@@ -9681,6 +9661,7 @@ F:        Documentation/virt/kvm/s390*
 F:     arch/s390/include/asm/gmap.h
 F:     arch/s390/include/asm/kvm*
 F:     arch/s390/include/uapi/asm/kvm*
+F:     arch/s390/kernel/uv.c
 F:     arch/s390/kvm/
 F:     arch/s390/mm/gmap.c
 F:     tools/testing/selftests/kvm/*/s390x/
@@ -9869,13 +9850,6 @@ S:       Maintained
 F:     arch/mips/lantiq
 F:     drivers/soc/lantiq
 
-LAPB module
-L:     linux-x25@vger.kernel.org
-S:     Orphan
-F:     Documentation/networking/lapb-module.rst
-F:     include/*/lapb.h
-F:     net/lapb/
-
 LASI 53c700 driver for PARISC
 M:     "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
 L:     linux-scsi@vger.kernel.org
@@ -11190,7 +11164,7 @@ F:      Documentation/devicetree/bindings/input/touchscreen/melfas_mip4.txt
 F:     drivers/input/touchscreen/melfas_mip4.c
 
 MELLANOX BLUEFIELD I2C DRIVER
-M:     Khalil Blaiech <kblaiech@mellanox.com>
+M:     Khalil Blaiech <kblaiech@nvidia.com>
 L:     linux-i2c@vger.kernel.org
 S:     Supported
 F:     drivers/i2c/busses/i2c-mlxbf.c
@@ -11200,7 +11174,7 @@ M:      Tariq Toukan <tariqt@nvidia.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.mellanox.com
-Q:     http://patchwork.ozlabs.org/project/netdev/list/
+Q:     https://patchwork.kernel.org/project/netdevbpf/list/
 F:     drivers/net/ethernet/mellanox/mlx4/en_*
 
 MELLANOX ETHERNET DRIVER (mlx5e)
@@ -11208,7 +11182,7 @@ M:      Saeed Mahameed <saeedm@nvidia.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.mellanox.com
-Q:     http://patchwork.ozlabs.org/project/netdev/list/
+Q:     https://patchwork.kernel.org/project/netdevbpf/list/
 F:     drivers/net/ethernet/mellanox/mlx5/core/en_*
 
 MELLANOX ETHERNET INNOVA DRIVERS
@@ -11216,7 +11190,7 @@ R:      Boris Pismenny <borisp@nvidia.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.mellanox.com
-Q:     http://patchwork.ozlabs.org/project/netdev/list/
+Q:     https://patchwork.kernel.org/project/netdevbpf/list/
 F:     drivers/net/ethernet/mellanox/mlx5/core/accel/*
 F:     drivers/net/ethernet/mellanox/mlx5/core/en_accel/*
 F:     drivers/net/ethernet/mellanox/mlx5/core/fpga/*
@@ -11228,7 +11202,7 @@ M:      Ido Schimmel <idosch@nvidia.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.mellanox.com
-Q:     http://patchwork.ozlabs.org/project/netdev/list/
+Q:     https://patchwork.kernel.org/project/netdevbpf/list/
 F:     drivers/net/ethernet/mellanox/mlxsw/
 F:     tools/testing/selftests/drivers/net/mlxsw/
 
@@ -11237,7 +11211,7 @@ M:      mlxsw@nvidia.com
 L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.mellanox.com
-Q:     http://patchwork.ozlabs.org/project/netdev/list/
+Q:     https://patchwork.kernel.org/project/netdevbpf/list/
 F:     drivers/net/ethernet/mellanox/mlxfw/
 
 MELLANOX HARDWARE PLATFORM SUPPORT
@@ -11256,7 +11230,7 @@ L:      netdev@vger.kernel.org
 L:     linux-rdma@vger.kernel.org
 S:     Supported
 W:     http://www.mellanox.com
-Q:     http://patchwork.ozlabs.org/project/netdev/list/
+Q:     https://patchwork.kernel.org/project/netdevbpf/list/
 F:     drivers/net/ethernet/mellanox/mlx4/
 F:     include/linux/mlx4/
 
@@ -11277,7 +11251,7 @@ L:      netdev@vger.kernel.org
 L:     linux-rdma@vger.kernel.org
 S:     Supported
 W:     http://www.mellanox.com
-Q:     http://patchwork.ozlabs.org/project/netdev/list/
+Q:     https://patchwork.kernel.org/project/netdevbpf/list/
 F:     Documentation/networking/device_drivers/ethernet/mellanox/
 F:     drivers/net/ethernet/mellanox/mlx5/core/
 F:     include/linux/mlx5/
@@ -12157,7 +12131,7 @@ M:      Jakub Kicinski <kuba@kernel.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 W:     http://www.linuxfoundation.org/en/Net
-Q:     http://patchwork.ozlabs.org/project/netdev/list/
+Q:     https://patchwork.kernel.org/project/netdevbpf/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
 F:     Documentation/devicetree/bindings/net/
@@ -12202,7 +12176,7 @@ M:      Jakub Kicinski <kuba@kernel.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 W:     http://www.linuxfoundation.org/en/Net
-Q:     http://patchwork.ozlabs.org/project/netdev/list/
+Q:     https://patchwork.kernel.org/project/netdevbpf/list/
 B:     mailto:netdev@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
@@ -13203,7 +13177,9 @@ M:      Jesper Dangaard Brouer <hawk@kernel.org>
 M:     Ilias Apalodimas <ilias.apalodimas@linaro.org>
 L:     netdev@vger.kernel.org
 S:     Supported
+F:     Documentation/networking/page_pool.rst
 F:     include/net/page_pool.h
+F:     include/trace/events/page_pool.h
 F:     net/core/page_pool.c
 
 PANASONIC LAPTOP ACPI EXTRAS DRIVER
@@ -13431,7 +13407,6 @@ F:      drivers/pci/controller/mobiveil/pcie-mobiveil*
 
 PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support)
 M:     Thomas Petazzoni <thomas.petazzoni@bootlin.com>
-M:     Jason Cooper <jason@lakedaemon.net>
 L:     linux-pci@vger.kernel.org
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
@@ -14237,7 +14212,6 @@ F:      drivers/media/usb/pwc/*
 F:     include/trace/events/pwc.h
 
 PWM FAN DRIVER
-M:     Kamil Debski <kamil@wypas.org>
 M:     Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
 L:     linux-hwmon@vger.kernel.org
 S:     Supported
@@ -14554,6 +14528,14 @@ F:     Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml
 F:     drivers/mailbox/qcom-ipcc.c
 F:     include/dt-bindings/mailbox/qcom-ipcc.h
 
+QUALCOMM IPQ4019 VQMMC REGULATOR DRIVER
+M:     Robert Marko <robert.marko@sartura.hr>
+M:     Luka Perkov <luka.perkov@sartura.hr>
+L:     linux-arm-msm@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml
+F:     drivers/regulator/vqmmc-ipq4019-regulator.c
+
 QUALCOMM RMNET DRIVER
 M:     Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
 M:     Sean Tranchetti <stranche@codeaurora.org>
@@ -14838,7 +14820,7 @@ T:      git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.g
 F:     drivers/net/wireless/realtek/rtlwifi/
 
 REALTEK WIRELESS DRIVER (rtw88)
-M:     Yan-Hsuan Chuang <yhchuang@realtek.com>
+M:     Yan-Hsuan Chuang <tony0620emma@gmail.com>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
 F:     drivers/net/wireless/realtek/rtw88/
@@ -14909,7 +14891,6 @@ RENESAS ETHERNET DRIVERS
 R:     Sergei Shtylyov <sergei.shtylyov@gmail.com>
 L:     netdev@vger.kernel.org
 L:     linux-renesas-soc@vger.kernel.org
-F:     Documentation/devicetree/bindings/net/renesas,*.txt
 F:     Documentation/devicetree/bindings/net/renesas,*.yaml
 F:     drivers/net/ethernet/renesas/
 F:     include/linux/sh_eth.h
@@ -15266,7 +15247,6 @@ F:      drivers/iommu/s390-iommu.c
 S390 IUCV NETWORK LAYER
 M:     Julian Wiedmann <jwi@linux.ibm.com>
 M:     Karsten Graul <kgraul@linux.ibm.com>
-M:     Ursula Braun <ubraun@linux.ibm.com>
 L:     linux-s390@vger.kernel.org
 S:     Supported
 W:     http://www.ibm.com/developerworks/linux/linux390/
@@ -15277,7 +15257,6 @@ F:      net/iucv/
 S390 NETWORK DRIVERS
 M:     Julian Wiedmann <jwi@linux.ibm.com>
 M:     Karsten Graul <kgraul@linux.ibm.com>
-M:     Ursula Braun <ubraun@linux.ibm.com>
 L:     linux-s390@vger.kernel.org
 S:     Supported
 W:     http://www.ibm.com/developerworks/linux/linux390/
@@ -15379,7 +15358,6 @@ F:      security/safesetid/
 
 SAMSUNG AUDIO (ASoC) DRIVERS
 M:     Krzysztof Kozlowski <krzk@kernel.org>
-M:     Sangbeom Kim <sbkim73@samsung.com>
 M:     Sylwester Nawrocki <s.nawrocki@samsung.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Supported
@@ -15414,7 +15392,6 @@ S:      Maintained
 F:     drivers/platform/x86/samsung-laptop.c
 
 SAMSUNG MULTIFUNCTION PMIC DEVICE DRIVERS
-M:     Sangbeom Kim <sbkim73@samsung.com>
 M:     Krzysztof Kozlowski <krzk@kernel.org>
 M:     Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
 L:     linux-kernel@vger.kernel.org
@@ -15448,14 +15425,12 @@ F:    Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
 F:     drivers/nfc/s3fwrn5
 
 SAMSUNG S5C73M3 CAMERA DRIVER
-M:     Kyungmin Park <kyungmin.park@samsung.com>
 M:     Andrzej Hajda <a.hajda@samsung.com>
 L:     linux-media@vger.kernel.org
 S:     Supported
 F:     drivers/media/i2c/s5c73m3/*
 
 SAMSUNG S5K5BAF CAMERA DRIVER
-M:     Kyungmin Park <kyungmin.park@samsung.com>
 M:     Andrzej Hajda <a.hajda@samsung.com>
 L:     linux-media@vger.kernel.org
 S:     Supported
@@ -15473,7 +15448,6 @@ F:      Documentation/devicetree/bindings/crypto/samsung-sss.yaml
 F:     drivers/crypto/s5p-sss.c
 
 SAMSUNG S5P/EXYNOS4 SOC SERIES CAMERA SUBSYSTEM DRIVERS
-M:     Kyungmin Park <kyungmin.park@samsung.com>
 M:     Sylwester Nawrocki <s.nawrocki@samsung.com>
 L:     linux-media@vger.kernel.org
 S:     Supported
@@ -15496,7 +15470,6 @@ F:      include/linux/clk/samsung.h
 F:     include/linux/platform_data/clk-s3c2410.h
 
 SAMSUNG SPI DRIVERS
-M:     Kukjin Kim <kgene@kernel.org>
 M:     Krzysztof Kozlowski <krzk@kernel.org>
 M:     Andi Shyti <andi@etezian.org>
 L:     linux-spi@vger.kernel.org
@@ -15522,7 +15495,6 @@ T:      git https://github.com/lmajewski/linux-samsung-thermal.git
 F:     drivers/thermal/samsung/
 
 SAMSUNG USB2 PHY DRIVER
-M:     Kamil Debski <kamil@wypas.org>
 M:     Sylwester Nawrocki <s.nawrocki@samsung.com>
 L:     linux-kernel@vger.kernel.org
 S:     Supported
@@ -15821,9 +15793,8 @@ F:      drivers/slimbus/
 F:     include/linux/slimbus.h
 
 SFC NETWORK DRIVER
-M:     Solarflare linux maintainers <linux-net-drivers@solarflare.com>
-M:     Edward Cree <ecree@solarflare.com>
-M:     Martin Habets <mhabets@solarflare.com>
+M:     Edward Cree <ecree.xilinx@gmail.com>
+M:     Martin Habets <habetsm.xilinx@gmail.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/sfc/
@@ -15851,7 +15822,6 @@ S:      Maintained
 F:     drivers/misc/sgi-xp/
 
 SHARED MEMORY COMMUNICATIONS (SMC) SOCKETS
-M:     Ursula Braun <ubraun@linux.ibm.com>
 M:     Karsten Graul <kgraul@linux.ibm.com>
 L:     linux-s390@vger.kernel.org
 S:     Supported
@@ -18113,7 +18083,7 @@ M:      Yu Chen <chenyu56@huawei.com>
 M:     Binghui Wang <wangbinghui@hisilicon.com>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
-F:     Documentation/devicetree/bindings/phy/phy-hi3660-usb3.txt
+F:     Documentation/devicetree/bindings/phy/hisilicon,hi3660-usb3.yaml
 F:     drivers/phy/hisilicon/phy-hi3660-usb3.c
 
 USB ISP116X DRIVER
@@ -18198,6 +18168,14 @@ L:     linux-usb@vger.kernel.org
 S:     Supported
 F:     drivers/usb/class/usblp.c
 
+USB RAW GADGET DRIVER
+R:     Andrey Konovalov <andreyknvl@gmail.com>
+L:     linux-usb@vger.kernel.org
+S:     Maintained
+F:     Documentation/usb/raw-gadget.rst
+F:     drivers/usb/gadget/legacy/raw_gadget.c
+F:     include/uapi/linux/usb/raw_gadget.h
+
 USB QMI WWAN NETWORK DRIVER
 M:     Bjørn Mork <bjorn@mork.no>
 L:     netdev@vger.kernel.org
@@ -19023,12 +19001,18 @@ L:    linux-kernel@vger.kernel.org
 S:     Maintained
 N:     axp[128]
 
-X.25 NETWORK LAYER
-M:     Andrew Hendry <andrew.hendry@gmail.com>
+X.25 STACK
+M:     Martin Schiller <ms@dev.tdt.de>
 L:     linux-x25@vger.kernel.org
-S:     Odd Fixes
+S:     Maintained
+F:     Documentation/networking/lapb-module.rst
 F:     Documentation/networking/x25*
+F:     drivers/net/wan/hdlc_x25.c
+F:     drivers/net/wan/lapbether.c
+F:     include/*/lapb.h
 F:     include/net/x25*
+F:     include/uapi/linux/x25.h
+F:     net/lapb/
 F:     net/x25/
 
 X86 ARCHITECTURE (32-BIT AND 64-BIT)
@@ -19142,12 +19126,17 @@ L:    netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Supported
 F:     include/net/xdp.h
+F:     include/net/xdp_priv.h
 F:     include/trace/events/xdp.h
 F:     kernel/bpf/cpumap.c
 F:     kernel/bpf/devmap.c
 F:     net/core/xdp.c
-N:     xdp
-K:     xdp
+F:     samples/bpf/xdp*
+F:     tools/testing/selftests/bpf/*xdp*
+F:     tools/testing/selftests/bpf/*/*xdp*
+F:     drivers/net/ethernet/*/*/*/*/*xdp*
+F:     drivers/net/ethernet/*/*/*xdp*
+K:     (?:\b|_)xdp(?:\b|_)
 
 XDP SOCKETS (AF_XDP)
 M:     Björn Töpel <bjorn.topel@intel.com>
@@ -19156,9 +19145,12 @@ R:     Jonathan Lemon <jonathan.lemon@gmail.com>
 L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Maintained
+F:     Documentation/networking/af_xdp.rst
 F:     include/net/xdp_sock*
 F:     include/net/xsk_buff_pool.h
 F:     include/uapi/linux/if_xdp.h
+F:     include/uapi/linux/xdp_diag.h
+F:     include/net/netns/xdp.h
 F:     net/xdp/
 F:     samples/bpf/xdpsock*
 F:     tools/lib/bpf/xsk*
index ee2284a5cad2e6bd6a8c7d6a9f88ecfb8f714c3c..9ec53d947628d4dd919f84f348ab8223ef69b4e3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 10
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc7
 NAME = Kleptomaniac Octopus
 
 # *DOCUMENTATION*
@@ -433,7 +433,6 @@ NM          = llvm-nm
 OBJCOPY                = llvm-objcopy
 OBJDUMP                = llvm-objdump
 READELF                = llvm-readelf
-OBJSIZE                = llvm-size
 STRIP          = llvm-strip
 else
 CC             = $(CROSS_COMPILE)gcc
@@ -443,7 +442,6 @@ NM          = $(CROSS_COMPILE)nm
 OBJCOPY                = $(CROSS_COMPILE)objcopy
 OBJDUMP                = $(CROSS_COMPILE)objdump
 READELF                = $(CROSS_COMPILE)readelf
-OBJSIZE                = $(CROSS_COMPILE)size
 STRIP          = $(CROSS_COMPILE)strip
 endif
 PAHOLE         = pahole
@@ -509,7 +507,7 @@ KBUILD_LDFLAGS :=
 CLANG_FLAGS :=
 
 export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC
-export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL
+export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL
 export PERL PYTHON PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
 export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ ZSTD
 export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS LDFLAGS_MODULE
@@ -828,7 +826,9 @@ else
 DEBUG_CFLAGS   += -g
 endif
 
+ifneq ($(LLVM_IAS),1)
 KBUILD_AFLAGS  += -Wa,-gdwarf-2
+endif
 
 ifdef CONFIG_DEBUG_INFO_DWARF4
 DEBUG_CFLAGS   += -gdwarf-4
@@ -946,7 +946,7 @@ KBUILD_CFLAGS   += $(call cc-option,-Werror=incompatible-pointer-types)
 KBUILD_CFLAGS   += $(call cc-option,-Werror=designated-init)
 
 # change __FILE__ to the relative path from the srctree
-KBUILD_CFLAGS  += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
+KBUILD_CPPFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
 
 # ensure -fcf-protection is disabled when using retpoline as it is
 # incompatible with -mindirect-branch=thunk-extern
@@ -984,6 +984,12 @@ ifeq ($(CONFIG_RELR),y)
 LDFLAGS_vmlinux        += --pack-dyn-relocs=relr
 endif
 
+# We never want expected sections to be placed heuristically by the
+# linker. All sections should be explicitly named in the linker script.
+ifdef CONFIG_LD_ORPHAN_WARN
+LDFLAGS_vmlinux += --orphan-handling=warn
+endif
+
 # Align the bit size of userspace programs with the kernel
 KBUILD_USERCFLAGS  += $(filter -m32 -m64 --target=%, $(KBUILD_CFLAGS))
 KBUILD_USERLDFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CFLAGS))
index 56b6ccc0e32d396af496541a8fc31809020d6691..ba4e966484ab571b0f541336f8c2b212cca4493a 100644 (file)
@@ -1028,6 +1028,15 @@ config HAVE_STATIC_CALL_INLINE
        bool
        depends on HAVE_STATIC_CALL
 
+config ARCH_WANT_LD_ORPHAN_WARN
+       bool
+       help
+         An arch should select this symbol once all linker sections are explicitly
+         included, size-asserted, or discarded in the linker scripts. This is
+         important because we never want expected sections to be placed heuristically
+         by the linker, since the locations of such sections can change between linker
+         versions.
+
 source "kernel/gcov/Kconfig"
 
 source "scripts/gcc-plugins/Kconfig"
index 7462a7911002451e5fffb0bd927b08f31e5ccb92..4c7b0414a3ff3b2437ab27ece6bbb9b04f9eb31d 100644 (file)
@@ -57,7 +57,7 @@ EXPORT_SYMBOL(pm_power_off);
 void arch_cpu_idle(void)
 {
        wtint(0);
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 
 void arch_cpu_idle_dead(void)
index c6606f4d20d6e3b0ff8c5a8b458120491958bafc..fb98440c0bd4c06aff82e5cde488ec98bbb2499a 100644 (file)
@@ -243,10 +243,8 @@ static inline int constant_fls(unsigned int x)
                x <<= 2;
                r -= 2;
        }
-       if (!(x & 0x80000000u)) {
-               x <<= 1;
+       if (!(x & 0x80000000u))
                r -= 1;
-       }
        return r;
 }
 
index f1ed17edb085b901f3fcd0980a302dd971c14090..163641726a2b928cba14aefd1289322202ec4a64 100644 (file)
 
 #ifdef CONFIG_ARC_HAS_PAE40
 #define PTE_BITS_NON_RWX_IN_PD1        (0xff00000000 | PAGE_MASK | _PAGE_CACHEABLE)
+#define MAX_POSSIBLE_PHYSMEM_BITS 40
 #else
 #define PTE_BITS_NON_RWX_IN_PD1        (PAGE_MASK | _PAGE_CACHEABLE)
+#define MAX_POSSIBLE_PHYSMEM_BITS 32
 #endif
 
 /**************************************************************************
index 17fd1ed700ccab4285973c15fa83b143ad695cea..9152782444b55737ad04a227598fc4a17f69d7a8 100644 (file)
        sr      r5, [ARC_REG_LPB_CTRL]
 1:
 #endif /* CONFIG_ARC_LPB_DISABLE */
-#endif
+
+       /* On HSDK, CCMs need to remapped super early */
+#ifdef CONFIG_ARC_SOC_HSDK
+       mov     r6, 0x60000000
+       lr      r5, [ARC_REG_ICCM_BUILD]
+       breq    r5, 0, 1f
+       sr      r6, [ARC_REG_AUX_ICCM]
+1:
+       lr      r5, [ARC_REG_DCCM_BUILD]
+       breq    r5, 0, 2f
+       sr      r6, [ARC_REG_AUX_DCCM]
+2:
+#endif /* CONFIG_ARC_SOC_HSDK */
+
+#endif /* CONFIG_ISA_ARCV2 */
+
        ; Config DSP_CTRL properly, so kernel may use integer multiply,
        ; multiply-accumulate, and divide operations
        DSP_EARLY_INIT
index feba91c9d969cae7a86afb4daba599c26a098290..f73da203b17026f80fa63b68c4be3acf7f243594 100644 (file)
 
 #ifdef CONFIG_ARC_DW2_UNWIND
 
-static void seed_unwind_frame_info(struct task_struct *tsk,
-                                  struct pt_regs *regs,
-                                  struct unwind_frame_info *frame_info)
+static int
+seed_unwind_frame_info(struct task_struct *tsk, struct pt_regs *regs,
+                      struct unwind_frame_info *frame_info)
 {
-       /*
-        * synchronous unwinding (e.g. dump_stack)
-        *  - uses current values of SP and friends
-        */
-       if (tsk == NULL && regs == NULL) {
+       if (regs) {
+               /*
+                * Asynchronous unwinding of intr/exception
+                *  - Just uses the pt_regs passed
+                */
+               frame_info->task = tsk;
+
+               frame_info->regs.r27 = regs->fp;
+               frame_info->regs.r28 = regs->sp;
+               frame_info->regs.r31 = regs->blink;
+               frame_info->regs.r63 = regs->ret;
+               frame_info->call_frame = 0;
+       } else if (tsk == NULL || tsk == current) {
+               /*
+                * synchronous unwinding (e.g. dump_stack)
+                *  - uses current values of SP and friends
+                */
                unsigned long fp, sp, blink, ret;
                frame_info->task = current;
 
@@ -63,13 +75,17 @@ static void seed_unwind_frame_info(struct task_struct *tsk,
                frame_info->regs.r31 = blink;
                frame_info->regs.r63 = ret;
                frame_info->call_frame = 0;
-       } else if (regs == NULL) {
+       } else {
                /*
-                * Asynchronous unwinding of sleeping task
-                *  - Gets SP etc from task's pt_regs (saved bottom of kernel
-                *    mode stack of task)
+                * Asynchronous unwinding of a likely sleeping task
+                *  - first ensure it is actually sleeping
+                *  - if so, it will be in __switch_to, kernel mode SP of task
+                *    is safe-kept and BLINK at a well known location in there
                 */
 
+               if (tsk->state == TASK_RUNNING)
+                       return -1;
+
                frame_info->task = tsk;
 
                frame_info->regs.r27 = TSK_K_FP(tsk);
@@ -90,19 +106,8 @@ static void seed_unwind_frame_info(struct task_struct *tsk,
                frame_info->regs.r28 += 60;
                frame_info->call_frame = 0;
 
-       } else {
-               /*
-                * Asynchronous unwinding of intr/exception
-                *  - Just uses the pt_regs passed
-                */
-               frame_info->task = tsk;
-
-               frame_info->regs.r27 = regs->fp;
-               frame_info->regs.r28 = regs->sp;
-               frame_info->regs.r31 = regs->blink;
-               frame_info->regs.r63 = regs->ret;
-               frame_info->call_frame = 0;
        }
+       return 0;
 }
 
 #endif
@@ -112,11 +117,12 @@ arc_unwind_core(struct task_struct *tsk, struct pt_regs *regs,
                int (*consumer_fn) (unsigned int, void *), void *arg)
 {
 #ifdef CONFIG_ARC_DW2_UNWIND
-       int ret = 0;
+       int ret = 0, cnt = 0;
        unsigned int address;
        struct unwind_frame_info frame_info;
 
-       seed_unwind_frame_info(tsk, regs, &frame_info);
+       if (seed_unwind_frame_info(tsk, regs, &frame_info))
+               return 0;
 
        while (1) {
                address = UNW_PC(&frame_info);
@@ -132,6 +138,11 @@ arc_unwind_core(struct task_struct *tsk, struct pt_regs *regs,
                        break;
 
                frame_info.regs.r63 = frame_info.regs.r31;
+
+               if (cnt++ > 128) {
+                       printk("unwinder looping too long, aborting !\n");
+                       return 0;
+               }
        }
 
        return address;         /* return the last address it saw */
index c340acd989a09f821fe342fb0d71a38790fa0898..9bb3c24f3677098a6e8b7d410fab51ed723f69d7 100644 (file)
  *  -Changes related to MMU v2 (Rel 4.8)
  *
  * Vineetg: Aug 29th 2008
- *  -In TLB Flush operations (Metal Fix MMU) there is a explict command to
+ *  -In TLB Flush operations (Metal Fix MMU) there is a explicit command to
  *    flush Micro-TLBS. If TLB Index Reg is invalid prior to TLBIVUTLB cmd,
  *    it fails. Thus need to load it with ANY valid value before invoking
  *    TLBIVUTLB cmd
  *
  * Vineetg: Aug 21th 2008:
  *  -Reduced the duration of IRQ lockouts in TLB Flush routines
- *  -Multiple copies of TLB erase code seperated into a "single" function
+ *  -Multiple copies of TLB erase code separated into a "single" function
  *  -In TLB Flush routines, interrupt disabling moved UP to retrieve ASID
  *       in interrupt-safe region.
  *
@@ -66,7 +66,7 @@
  *
  * Although J-TLB is 2 way set assoc, ARC700 caches J-TLB into uTLBS which has
  * much higher associativity. u-D-TLB is 8 ways, u-I-TLB is 4 ways.
- * Given this, the thrasing problem should never happen because once the 3
+ * Given this, the thrashing problem should never happen because once the 3
  * J-TLB entries are created (even though 3rd will knock out one of the prev
  * two), the u-D-TLB and u-I-TLB will have what is required to accomplish memcpy
  *
@@ -127,7 +127,7 @@ static void utlb_invalidate(void)
         * There was however an obscure hardware bug, where uTLB flush would
         * fail when a prior probe for J-TLB (both totally unrelated) would
         * return lkup err - because the entry didn't exist in MMU.
-        * The Workround was to set Index reg with some valid value, prior to
+        * The Workaround was to set Index reg with some valid value, prior to
         * flush. This was fixed in MMU v3
         */
        unsigned int idx;
@@ -272,7 +272,7 @@ noinline void local_flush_tlb_all(void)
 }
 
 /*
- * Flush the entrie MM for userland. The fastest way is to move to Next ASID
+ * Flush the entire MM for userland. The fastest way is to move to Next ASID
  */
 noinline void local_flush_tlb_mm(struct mm_struct *mm)
 {
@@ -303,7 +303,7 @@ noinline void local_flush_tlb_mm(struct mm_struct *mm)
  * Difference between this and Kernel Range Flush is
  *  -Here the fastest way (if range is too large) is to move to next ASID
  *      without doing any explicit Shootdown
- *  -In case of kernel Flush, entry has to be shot down explictly
+ *  -In case of kernel Flush, entry has to be shot down explicitly
  */
 void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                           unsigned long end)
@@ -620,7 +620,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned,
  * Super Page size is configurable in hardware (4K to 16M), but fixed once
  * RTL builds.
  *
- * The exact THP size a Linx configuration will support is a function of:
+ * The exact THP size a Linux configuration will support is a function of:
  *  - MMU page size (typical 8K, RTL fixed)
  *  - software page walker address split between PGD:PTE:PFN (typical
  *    11:8:13, but can be changed with 1 line)
@@ -698,7 +698,7 @@ void local_flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
 
 #endif
 
-/* Read the Cache Build Confuration Registers, Decode them and save into
+/* Read the Cache Build Configuration Registers, Decode them and save into
  * the cpuinfo structure for later use.
  * No Validation is done here, simply read/convert the BCRs
  */
@@ -803,13 +803,13 @@ void arc_mmu_init(void)
        pr_info("%s", arc_mmu_mumbojumbo(0, str, sizeof(str)));
 
        /*
-        * Can't be done in processor.h due to header include depenedencies
+        * Can't be done in processor.h due to header include dependencies
         */
        BUILD_BUG_ON(!IS_ALIGNED((CONFIG_ARC_KVADDR_SIZE << 20), PMD_SIZE));
 
        /*
         * stack top size sanity check,
-        * Can't be done in processor.h due to header include depenedencies
+        * Can't be done in processor.h due to header include dependencies
         */
        BUILD_BUG_ON(!IS_ALIGNED(STACK_TOP, PMD_SIZE));
 
@@ -881,7 +881,7 @@ void arc_mmu_init(void)
  *      the duplicate one.
  * -Knob to be verbose abt it.(TODO: hook them up to debugfs)
  */
-volatile int dup_pd_silent; /* Be slient abt it or complain (default) */
+volatile int dup_pd_silent; /* Be silent abt it or complain (default) */
 
 void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
                          struct pt_regs *regs)
@@ -948,7 +948,7 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
 
 /***********************************************************************
  * Diagnostic Routines
- *  -Called from Low Level TLB Hanlders if things don;t look good
+ *  -Called from Low Level TLB Handlers if things don;t look good
  **********************************************************************/
 
 #ifdef CONFIG_ARC_DBG_TLB_PARANOIA
index 0b63fc095b998a2137281eccf37fd8e83512ff78..b3ea1fa11f870efc264a2a33966bbcd2a191efad 100644 (file)
@@ -17,22 +17,6 @@ int arc_hsdk_axi_dmac_coherent __section(".data") = 0;
 
 #define ARC_CCM_UNUSED_ADDR    0x60000000
 
-static void __init hsdk_init_per_cpu(unsigned int cpu)
-{
-       /*
-        * By default ICCM is mapped to 0x7z while this area is used for
-        * kernel virtual mappings, so move it to currently unused area.
-        */
-       if (cpuinfo_arc700[cpu].iccm.sz)
-               write_aux_reg(ARC_REG_AUX_ICCM, ARC_CCM_UNUSED_ADDR);
-
-       /*
-        * By default DCCM is mapped to 0x8z while this area is used by kernel,
-        * so move it to currently unused area.
-        */
-       if (cpuinfo_arc700[cpu].dccm.sz)
-               write_aux_reg(ARC_REG_AUX_DCCM, ARC_CCM_UNUSED_ADDR);
-}
 
 #define ARC_PERIPHERAL_BASE    0xf0000000
 #define CREG_BASE              (ARC_PERIPHERAL_BASE + 0x1000)
@@ -339,5 +323,4 @@ static const char *hsdk_compat[] __initconst = {
 MACHINE_START(SIMULATION, "hsdk")
        .dt_compat      = hsdk_compat,
        .init_early     = hsdk_init_early,
-       .init_per_cpu   = hsdk_init_per_cpu,
 MACHINE_END
index fe2f17eb2b505ace1720741f7cd550d6eeb6f356..002e0cf025f59b364ac14bc922fd970dcfe93f98 100644 (file)
@@ -35,6 +35,7 @@ config ARM
        select ARCH_USE_CMPXCHG_LOCKREF
        select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
        select ARCH_WANT_IPC_PARSE_VERSION
+       select ARCH_WANT_LD_ORPHAN_WARN
        select BINFMT_FLAT_ARGVP_ENVP_ON_STACK
        select BUILDTIME_TABLE_SORT if MMU
        select CLONE_BACKWARDS
index 4d76eab2b22d761618a4c36c9b906af0fa3d4bf6..e15f76ca2887cbd7fe3ecfcb0c214682d75f2484 100644 (file)
@@ -16,10 +16,6 @@ LDFLAGS_vmlinux      += --be8
 KBUILD_LDFLAGS_MODULE  += --be8
 endif
 
-# We never want expected sections to be placed heuristically by the
-# linker. All sections should be explicitly named in the linker script.
-LDFLAGS_vmlinux += $(call ld-option, --orphan-handling=warn)
-
 GZFLAGS                :=-9
 #KBUILD_CFLAGS +=-pipe
 
index 47f001ca5499dd929f3e440e6d06dcb18c909bc9..e1567418a2b149583f130faa13eb15183b1e6324 100644 (file)
@@ -129,7 +129,9 @@ LDFLAGS_vmlinux += --no-undefined
 # Delete all temporary local symbols
 LDFLAGS_vmlinux += -X
 # Report orphan sections
-LDFLAGS_vmlinux += $(call ld-option, --orphan-handling=warn)
+ifdef CONFIG_LD_ORPHAN_WARN
+LDFLAGS_vmlinux += --orphan-handling=warn
+endif
 # Next argument is a linker script
 LDFLAGS_vmlinux += -T
 
index 2e04ec5b54469b661187ff4c0619c24992e26b79..caa27322a0ab709606215701f73897c48f4bbf3e 100644 (file)
@@ -1472,6 +1472,9 @@ ENTRY(efi_enter_kernel)
                @ issued from HYP mode take us to the correct handler code. We
                @ will disable the MMU before jumping to the kernel proper.
                @
+ ARM(          bic     r1, r1, #(1 << 30)      ) @ clear HSCTLR.TE
+ THUMB(                orr     r1, r1, #(1 << 30)      ) @ set HSCTLR.TE
+               mcr     p15, 4, r1, c1, c0, 0
                adr     r0, __hyp_reentry_vectors
                mcr     p15, 4, r0, c12, c0, 0  @ set HYP vector base (HVBAR)
                isb
index c220dc3c4e0f3bf103b333614328c73f39a82add..243e35f7a56c786cfcd5963831d18c7b75f21ed2 100644 (file)
                        ranges = <0x0 0x100000 0x8000>;
 
                        mac_sw: switch@0 {
-                               compatible = "ti,am4372-cpsw","ti,cpsw-switch";
+                               compatible = "ti,am4372-cpsw-switch", "ti,cpsw-switch";
                                reg = <0x0 0x4000>;
                                ranges = <0 0 0x4000>;
                                clocks = <&cpsw_125mhz_gclk>, <&dpll_clksel_mac_clk>;
index b58220a49cbd85cac6b149c035641ac2a1429c88..74367ee96f2023bd9b597f83a3900d7669fb57e3 100644 (file)
                always-on;
        };
 
+       edac: sdram@1e6e0000 {
+               compatible = "aspeed,ast2600-sdram-edac", "syscon";
+               reg = <0x1e6e0000 0x174>;
+               interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
        ahb {
                compatible = "simple-bus";
                #address-cells = <1>;
index b69c7d40f5d828305bb917a0fc3c2f72d94c8bf0..2f326151116b7a9ca06461536b3881d5b691aa8d 100644 (file)
@@ -32,8 +32,8 @@
                                interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
                                interrupt-names = "int0", "int1";
-                               clocks = <&mcan_clk>, <&l3_iclk_div>;
-                               clock-names = "cclk", "hclk";
+                               clocks = <&l3_iclk_div>, <&mcan_clk>;
+                               clock-names = "hclk", "cclk";
                                bosch,mram-cfg = <0x0 0 0 32 0 0 1 1>;
                        };
                };
index ab291cec650a9204bc3d6c4293b83823f6e40c29..2983e91bc7ddee6be97465167e737187ccd75263 100644 (file)
 };
 
 &clock {
-       clocks = <&clock CLK_XUSBXTI>;
        assigned-clocks = <&clock CLK_FOUT_EPLL>;
        assigned-clock-rates = <45158401>;
 };
index 878e89c201904f022ee19498bc74c03370703476..4ea5c23f181b484ee5ead758b6dc8421441fba1a 100644 (file)
@@ -59,7 +59,7 @@
                                MX50_PAD_CSPI_MISO__CSPI_MISO           0x00
                                MX50_PAD_CSPI_MOSI__CSPI_MOSI           0x00
                                MX50_PAD_CSPI_SS0__GPIO4_11             0xc4
-                               MX50_PAD_ECSPI1_MOSI__CSPI_SS1          0xf4
+                               MX50_PAD_ECSPI1_MOSI__GPIO4_13          0x84
                        >;
                };
 
index d112b50f8c5d98a47f9330335dabe26637af6be8..b4605edfd2ab807ec67153163860b23cc7d5d411 100644 (file)
                #size-cells = <0>;
 
                /* Microchip KSZ9031RNX PHY */
-               rgmii_phy: ethernet-phy@4 {
-                       reg = <4>;
+               rgmii_phy: ethernet-phy@0 {
+                       reg = <0>;
                        interrupts-extended = <&gpio1 28 IRQ_TYPE_LEVEL_LOW>;
                        reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
                        reset-assert-us = <10000>;
index 828dd20cd27d257d56e5a9fdc45093a943194a89..d07d8f83456d241a288be60ce729579b9dded12f 100644 (file)
@@ -98,7 +98,7 @@
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        status = "okay";
 };
 
index f1a41152e9dd70d57beaa6eed9608433cf64b25e..adde62d6fce73b99e9f088fd61916a5e4833f910 100644 (file)
        /delete-property/ #size-cells;
        spi-slave;
        status = "okay";
-       ready-gpio = <&gpio 125 GPIO_ACTIVE_HIGH>;
+       ready-gpios = <&gpio 125 GPIO_ACTIVE_HIGH>;
 
        slave {
                compatible = "olpc,xo1.75-ec";
                spi-cpha;
-               cmd-gpio = <&gpio 155 GPIO_ACTIVE_HIGH>;
+               cmd-gpios = <&gpio 155 GPIO_ACTIVE_HIGH>;
        };
 };
 
index cc4efd0efabd2664cd0fb7afc6232a981dff5f0f..4ae630d37d094fd47505c1f26a142a70bbba28ca 100644 (file)
                                interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&soc_clocks MMP2_CLK_CCIC0>;
                                clock-names = "axi";
+                               power-domains = <&soc_clocks MMP3_POWER_DOMAIN_CAMERA>;
                                #clock-cells = <0>;
                                clock-output-names = "mclk";
                                status = "disabled";
                                interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&soc_clocks MMP2_CLK_CCIC1>;
                                clock-names = "axi";
+                               power-domains = <&soc_clocks MMP3_POWER_DOMAIN_CAMERA>;
                                #clock-cells = <0>;
                                clock-output-names = "mclk";
                                status = "disabled";
index ca109dc182388dfd193d9505d556ce77c5aec940..2e77ccec3fc16553d813b0d925841a98945cc82a 100644 (file)
                states = <1800000 0x1>,
                         <2900000 0x0>;
        };
+
+       vin: vin {
+               compatible = "regulator-fixed";
+               regulator-name = "vin";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
 };
 
 &adc {
 
                regulators {
                        compatible = "st,stpmic1-regulators";
+                       buck1-supply = <&vin>;
+                       buck2-supply = <&vin>;
+                       buck3-supply = <&vin>;
+                       buck4-supply = <&vin>;
                        ldo1-supply = <&v3v3>;
                        ldo2-supply = <&v3v3>;
                        ldo3-supply = <&vdd_ddr>;
+                       ldo4-supply = <&vin>;
                        ldo5-supply = <&v3v3>;
                        ldo6-supply = <&v3v3>;
+                       vref_ddr-supply = <&vin>;
+                       boost-supply = <&vin>;
                        pwr_sw1-supply = <&bst_out>;
                        pwr_sw2-supply = <&bst_out>;
 
index 5dff24e39af8e4c503d23f6c4d20996039e37f56..8456f172d4b1be60811f99605757b395cb28c5fb 100644 (file)
                        linux,code = <KEY_A>;
                        gpios = <&gpiof 3 GPIO_ACTIVE_LOW>;
                };
+
+               /*
+                * The EXTi IRQ line 0 is shared with PMIC,
+                * so mark this as polled GPIO key.
+                */
+               button-2 {
+                       label = "TA3-GPIO-C";
+                       linux,code = <KEY_C>;
+                       gpios = <&gpiog 0 GPIO_ACTIVE_LOW>;
+               };
        };
 
        gpio-keys {
                        wakeup-source;
                };
 
-               button-2 {
-                       label = "TA3-GPIO-C";
-                       linux,code = <KEY_C>;
-                       gpios = <&gpioi 11 GPIO_ACTIVE_LOW>;
-                       wakeup-source;
-               };
-
                button-3 {
                        label = "TA4-GPIO-D";
                        linux,code = <KEY_D>;
@@ -79,7 +82,7 @@
 
                led-0 {
                        label = "green:led5";
-                       gpios = <&gpiog 2 GPIO_ACTIVE_HIGH>;
+                       gpios = <&gpioc 6 GPIO_ACTIVE_HIGH>;
                        default-state = "off";
                };
 
index b4b52cf634afa8d51adff1976fe02cac6384635f..f796a6150313e01c607384645dc1249632abe704 100644 (file)
@@ -68,6 +68,7 @@
                gpio = <&gpiog 3 GPIO_ACTIVE_LOW>;
                regulator-always-on;
                regulator-boot-on;
+               vin-supply = <&vdd>;
        };
 };
 
 
                        vdda: ldo1 {
                                regulator-name = "vdda";
+                               regulator-always-on;
                                regulator-min-microvolt = <2900000>;
                                regulator-max-microvolt = <2900000>;
                                interrupts = <IT_CURLIM_LDO1 0>;
index 04fbb324a541f943280474c184ab8bbe4c5ff0de..803eb8bc9c85c819d296ca6f59d98411cb151229 100644 (file)
        };
 };
 
+&dts {
+       status = "okay";
+};
+
 &i2c4 {
        pinctrl-names = "default";
        pinctrl-0 = <&i2c4_pins_a>;
index a5307745719a02fc2b78bc7302fe57dfe930d23c..93398cfae97ee41d10bddf0d4dc7cc7d3ea05ca2 100644 (file)
                dais = <&sai2a_port &sai2b_port &i2s2_port>;
                status = "okay";
        };
+
+       vin: vin {
+               compatible = "regulator-fixed";
+               regulator-name = "vin";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
 };
 
 &adc {
 
                regulators {
                        compatible = "st,stpmic1-regulators";
+                       buck1-supply = <&vin>;
+                       buck2-supply = <&vin>;
+                       buck3-supply = <&vin>;
+                       buck4-supply = <&vin>;
                        ldo1-supply = <&v3v3>;
+                       ldo2-supply = <&vin>;
                        ldo3-supply = <&vdd_ddr>;
+                       ldo4-supply = <&vin>;
+                       ldo5-supply = <&vin>;
                        ldo6-supply = <&v3v3>;
+                       vref_ddr-supply = <&vin>;
+                       boost-supply = <&vin>;
                        pwr_sw1-supply = <&bst_out>;
                        pwr_sw2-supply = <&bst_out>;
 
index 0f95a6ef8543a77513cabf78c131d8afa3589565..1c5a666c54b533245f03844a2ca3cd03d8cd055f 100644 (file)
                        trips {
                                cpu_alert0: cpu-alert0 {
                                        /* milliCelsius */
-                                       temperature = <850000>;
+                                       temperature = <85000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
index 049e6ab3cf56c6fa9c2a4bc2fe576a38ee663d2d..73de34ae37fdceb3152cbc886246b38142e93a5a 100644 (file)
        pinctrl-names = "default";
        pinctrl-0 = <&gmac_rgmii_pins>;
        phy-handle = <&phy1>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        status = "okay";
 };
 
index 32d5d45a35c036934d56651bbe39f16fb9c39cdf..8945dbb114a2af34f8d7eb3cf28eccf606d2a6c6 100644 (file)
        pinctrl-names = "default";
        pinctrl-0 = <&gmac_rgmii_pins>;
        phy-handle = <&phy1>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-supply = <&reg_gmac_3v3>;
        status = "okay";
 };
index 8c8dee6ea461a801e1bcc5db09ba7178f94b4ba2..9109ca0919ade3a4ad4a17983d7a9ab7493c32d3 100644 (file)
        pinctrl-names = "default";
        pinctrl-0 = <&gmac_rgmii_pins>;
        phy-handle = <&phy1>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        status = "okay";
 };
 
index 9d34eabba121374bd4ecd6dd80cadc946ae656ce..431f70234d364295d724cdc0e8739516ec75b241 100644 (file)
        pinctrl-0 = <&emac_rgmii_pins>;
        phy-supply = <&reg_sw>;
        phy-handle = <&rgmii_phy>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        allwinner,rx-delay-ps = <700>;
        allwinner,tx-delay-ps = <700>;
        status = "okay";
index d9be511f054f0ecf4e5be68bd68bfe7eb25d0d09..d8326a5c681d41c1c29bc615e96ef758c878b157 100644 (file)
        pinctrl-0 = <&emac_rgmii_pins>;
        phy-supply = <&reg_dldo4>;
        phy-handle = <&rgmii_phy>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        status = "okay";
 };
 
index 71fb7320893971336edf1ec145d2f213bb61d34f..babf4cf1b2f6897cda3605aff044cbea96263c97 100644 (file)
        };
 };
 
-&emac {
-       /* LEDs changed to active high on the plus */
-       /delete-property/ allwinner,leds-active-low;
-};
-
 &mmc1 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index 6dbf7b2e0c13c44f06e7970c006f3357f0d0493e..b6ca45d18e51134a4666b7c733c7926c414a0ed2 100644 (file)
@@ -67,7 +67,7 @@
        pinctrl-0 = <&emac_rgmii_pins>;
        phy-supply = <&reg_gmac_3v3>;
        phy-handle = <&ext_rgmii_phy>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        status = "okay";
 };
 
index 2fc62ef0cb3e983bc7beae5ab9e4851ec064fc59..a6a1087a0c9b2bded7eafb7bb1d8b4a160b874c1 100644 (file)
        pinctrl-names = "default";
        pinctrl-0 = <&gmac_rgmii_pins>;
        phy-handle = <&phy1>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-supply = <&reg_dc1sw>;
        status = "okay";
 };
index d3b337b043a15bd15059e66e5b91beed71b00b83..484b93df20cb6958c1ad60e02014af7896cf4b2b 100644 (file)
        pinctrl-names = "default";
        pinctrl-0 = <&gmac_rgmii_pins>;
        phy-handle = <&phy1>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-supply = <&reg_cldo1>;
        status = "okay";
 };
index bbc6335e563141ee41ae97b6546c053ad77470cc..5c3580d712e407fb2cc352ec6288a838804e3036 100644 (file)
        pinctrl-names = "default";
        pinctrl-0 = <&gmac_rgmii_pins>;
        phy-handle = <&phy1>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-supply = <&reg_cldo1>;
        status = "okay";
 };
index 39263e74fbb531be8b856362560328ea7d996a9f..8e5cb3b3fd6863a3a1609d52fa2364eeba813e7a 100644 (file)
        pinctrl-0 = <&emac_rgmii_pins>;
        phy-supply = <&reg_gmac_3v3>;
        phy-handle = <&ext_rgmii_phy>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
 
        status = "okay";
 };
index e500911ce0a5910d908d1d4ba67b39a14fae58e5..6f1e0f0d4f0aeac691de5f16325e26b7396f0906 100644 (file)
        };
 };
 
+&mdio1 {
+       clock-frequency = <5000000>;
+};
 
 &iomuxc {
        pinctrl_gpio_e6185_eeprom_sel: pinctrl-gpio-e6185-eeprom-spi0 {
index aeb1209e080463f2f2c69e5c8669d814cd6cf10f..bb70acc6b52648a61d0459786eb940c41b6ec469 100644 (file)
@@ -93,6 +93,7 @@ CONFIG_SPI=y
 CONFIG_SPI_IMX=y
 CONFIG_SPI_SPIDEV=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_MXC=y
 CONFIG_W1=y
 CONFIG_W1_MASTER_MXC=y
 CONFIG_W1_SLAVE_THERM=y
index 0fa79bd00219140264aea6668157076cfafd3747..221f5c340c8653e40a6be937080669236554180d 100644 (file)
@@ -217,6 +217,7 @@ CONFIG_GPIO_PCA953X=y
 CONFIG_GPIO_PCF857X=y
 CONFIG_GPIO_STMPE=y
 CONFIG_GPIO_74X164=y
+CONFIG_GPIO_MXC=y
 CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_SYSCON=y
 CONFIG_POWER_RESET_SYSCON_POWEROFF=y
index 70b709a669d2b681ab29b2ffc875834cd62f7d10..e00be9faa23bfa7e1a28a8b8f8d0bd8ba0c60a2b 100644 (file)
@@ -166,6 +166,7 @@ CONFIG_SPI_IMX=y
 CONFIG_SPI_ORION=y
 CONFIG_GPIO_ASPEED=m
 CONFIG_GPIO_ASPEED_SGPIO=y
+CONFIG_GPIO_MXC=y
 CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_GPIO=y
 CONFIG_POWER_RESET_QNAP=y
index e731cdf7c88c4ad177513a4be7ff9290007369c1..a611b0c1e540fcada57f3a20dfdcf90e3fad7e36 100644 (file)
@@ -465,6 +465,7 @@ CONFIG_GPIO_PALMAS=y
 CONFIG_GPIO_TPS6586X=y
 CONFIG_GPIO_TPS65910=y
 CONFIG_GPIO_TWL4030=y
+CONFIG_GPIO_MXC=y
 CONFIG_POWER_AVS=y
 CONFIG_ROCKCHIP_IODOMAIN=y
 CONFIG_POWER_RESET_AS3722=y
index 34793aabdb651ad421db09ebf90b7f3540bc005f..58df9fd79a76a5b2e3aa336086bf42eb35c36260 100644 (file)
@@ -81,7 +81,6 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_BINFMT_MISC=y
 CONFIG_CMA=y
 CONFIG_ZSMALLOC=m
-CONFIG_ZSMALLOC_PGTABLE_MAPPING=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
index 213607a1f45c14d17ffc3bdce36baf719f95af37..e26a278d301ab0e05a73158bbd8fb5263f2f84d6 100644 (file)
@@ -44,20 +44,20 @@ int kprobe_exceptions_notify(struct notifier_block *self,
                             unsigned long val, void *data);
 
 /* optinsn template addresses */
-extern __visible kprobe_opcode_t optprobe_template_entry;
-extern __visible kprobe_opcode_t optprobe_template_val;
-extern __visible kprobe_opcode_t optprobe_template_call;
-extern __visible kprobe_opcode_t optprobe_template_end;
-extern __visible kprobe_opcode_t optprobe_template_sub_sp;
-extern __visible kprobe_opcode_t optprobe_template_add_sp;
-extern __visible kprobe_opcode_t optprobe_template_restore_begin;
-extern __visible kprobe_opcode_t optprobe_template_restore_orig_insn;
-extern __visible kprobe_opcode_t optprobe_template_restore_end;
+extern __visible kprobe_opcode_t optprobe_template_entry[];
+extern __visible kprobe_opcode_t optprobe_template_val[];
+extern __visible kprobe_opcode_t optprobe_template_call[];
+extern __visible kprobe_opcode_t optprobe_template_end[];
+extern __visible kprobe_opcode_t optprobe_template_sub_sp[];
+extern __visible kprobe_opcode_t optprobe_template_add_sp[];
+extern __visible kprobe_opcode_t optprobe_template_restore_begin[];
+extern __visible kprobe_opcode_t optprobe_template_restore_orig_insn[];
+extern __visible kprobe_opcode_t optprobe_template_restore_end[];
 
 #define MAX_OPTIMIZED_LENGTH   4
 #define MAX_OPTINSN_SIZE                               \
-       ((unsigned long)&optprobe_template_end -        \
-        (unsigned long)&optprobe_template_entry)
+       ((unsigned long)optprobe_template_end - \
+        (unsigned long)optprobe_template_entry)
 #define RELATIVEJUMP_SIZE      4
 
 struct arch_optimized_insn {
index 3502c2f746ca730c441ad7eb4cd7b1fcbcb78d59..baf7d0204eb5a5394c20f17c45098ba6cb0053e4 100644 (file)
@@ -75,6 +75,8 @@
 #define PTE_HWTABLE_OFF                (PTE_HWTABLE_PTRS * sizeof(pte_t))
 #define PTE_HWTABLE_SIZE       (PTRS_PER_PTE * sizeof(u32))
 
+#define MAX_POSSIBLE_PHYSMEM_BITS      32
+
 /*
  * PMD_SHIFT determines the size of the area a second-level page table can map
  * PGDIR_SHIFT determines what a third-level page table entry can map
index fbb6693c33528055a3f6015b779eb4d1554e2c61..2b85d175e99969a1590be7697bfa88599df811b8 100644 (file)
@@ -25,6 +25,8 @@
 #define PTE_HWTABLE_OFF                (0)
 #define PTE_HWTABLE_SIZE       (PTRS_PER_PTE * sizeof(u64))
 
+#define MAX_POSSIBLE_PHYSMEM_BITS 40
+
 /*
  * PGDIR_SHIFT determines the size a top-level page table entry can map.
  */
index 05fe92aa7d989e2a4207f3269c9caa1b0a2dfd06..0529f90395c94d82611a406d540a450d537dad13 100644 (file)
@@ -32,8 +32,7 @@ u64 perf_reg_abi(struct task_struct *task)
 }
 
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
        regs_user->regs = task_pt_regs(current);
        regs_user->abi = perf_reg_abi(current);
index 8e6ace03e960bef54610ebf653bc6c15d91ef903..9f199b1e838391a71f9018e1763867f597f5ad85 100644 (file)
@@ -71,7 +71,7 @@ void arch_cpu_idle(void)
                arm_pm_idle();
        else
                cpu_do_idle();
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 
 void arch_cpu_idle_prepare(void)
index 5f4922e858d033604900106c7fa249ef5ed19b5a..f7f4620d59c3aff852f73ecbc22c78d69f0e87de 100644 (file)
@@ -40,6 +40,10 @@ SECTIONS
                ARM_DISCARD
 #ifndef CONFIG_SMP_ON_UP
                *(.alt.smp.init)
+#endif
+#ifndef CONFIG_ARM_UNWIND
+               *(.ARM.exidx) *(.ARM.exidx.*)
+               *(.ARM.extab) *(.ARM.extab.*)
 #endif
        }
 
index 2d962fe488210d309f050e7387bc7f1812210d3f..a3a64bf972507b3c311844fce4838aaed4446168 100644 (file)
@@ -35,13 +35,8 @@ ENTRY(ll_get_coherency_base)
 
        /*
         * MMU is disabled, use the physical address of the coherency
-        * base address. However, if the coherency fabric isn't mapped
-        * (i.e its virtual address is zero), it means coherency is
-        * not enabled, so we return 0.
+        * base address, (or 0x0 if the coherency fabric is not mapped)
         */
-       ldr     r1, =coherency_base
-       cmp     r1, #0
-       beq     2f
        adr     r1, 3f
        ldr     r3, [r1]
        ldr     r1, [r1, r3]
index 144b9caa935c42053cb030ff3eb5cb77284873eb..a720259099edfb4bd5c226b104a761dae341dfca 100644 (file)
@@ -288,7 +288,7 @@ static struct gpiod_lookup_table osk_usb_gpio_table = {
        .dev_id = "ohci",
        .table = {
                /* Power GPIO on the I2C-attached TPS65010 */
-               GPIO_LOOKUP("i2c-tps65010", 1, "power", GPIO_ACTIVE_HIGH),
+               GPIO_LOOKUP("tps65010", 0, "power", GPIO_ACTIVE_HIGH),
                GPIO_LOOKUP(OMAP_GPIO_LABEL, 9, "overcurrent",
                            GPIO_ACTIVE_HIGH),
        },
index 3ee7bdff86b236a37924f63692bbc2a9038df6dc..3f62a0c9450ddaa01b629bb0a094394307803340 100644 (file)
@@ -7,7 +7,6 @@ config ARCH_OMAP2
        depends on ARCH_MULTI_V6
        select ARCH_OMAP2PLUS
        select CPU_V6
-       select PM_GENERIC_DOMAINS if PM
        select SOC_HAS_OMAP2_SDRC
 
 config ARCH_OMAP3
@@ -106,6 +105,8 @@ config ARCH_OMAP2PLUS
        select OMAP_DM_TIMER
        select OMAP_GPMC
        select PINCTRL
+       select PM_GENERIC_DOMAINS if PM
+       select PM_GENERIC_DOMAINS_OF if PM
        select RESET_CONTROLLER
        select SOC_BUS
        select TI_SYSC
index a92d277f81a081876960aea5f409f636b5976dd5..c8d317fafe2eaf21cd0f1926ddf48604f301d2e8 100644 (file)
@@ -175,8 +175,11 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
                if (mpuss_can_lose_context) {
                        error = cpu_cluster_pm_enter();
                        if (error) {
-                               omap_set_pwrdm_state(mpu_pd, PWRDM_POWER_ON);
-                               goto cpu_cluster_pm_out;
+                               index = 0;
+                               cx = state_ptr + index;
+                               pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
+                               omap_set_pwrdm_state(mpu_pd, cx->mpu_state);
+                               mpuss_can_lose_context = 0;
                        }
                }
        }
@@ -184,7 +187,6 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
        omap4_enter_lowpower(dev->cpu, cx->cpu_state);
        cpu_done[dev->cpu] = true;
 
-cpu_cluster_pm_out:
        /* Wakeup CPU1 only if it is not offlined */
        if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) {
 
index d57112a276f5ac79da2100970e8ca8c6a78af54a..c23dbf8bebeeb7f4387b90e7827c6a570d940566 100644 (file)
@@ -354,8 +354,8 @@ static void __init free_highpages(void)
        /* set highmem page free */
        for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE,
                                &range_start, &range_end, NULL) {
-               unsigned long start = PHYS_PFN(range_start);
-               unsigned long end = PHYS_PFN(range_end);
+               unsigned long start = PFN_UP(range_start);
+               unsigned long end = PFN_DOWN(range_end);
 
                /* Ignore complete lowmem entries */
                if (end <= max_low)
index 7a449df0b359135e774badd06cdc53dc2aad3fb8..c78180172120ffc87ffbb2ede6600bcb62355d48 100644 (file)
@@ -85,21 +85,21 @@ asm (
                        "optprobe_template_end:\n");
 
 #define TMPL_VAL_IDX \
-       ((unsigned long *)&optprobe_template_val - (unsigned long *)&optprobe_template_entry)
+       ((unsigned long *)optprobe_template_val - (unsigned long *)optprobe_template_entry)
 #define TMPL_CALL_IDX \
-       ((unsigned long *)&optprobe_template_call - (unsigned long *)&optprobe_template_entry)
+       ((unsigned long *)optprobe_template_call - (unsigned long *)optprobe_template_entry)
 #define TMPL_END_IDX \
-       ((unsigned long *)&optprobe_template_end - (unsigned long *)&optprobe_template_entry)
+       ((unsigned long *)optprobe_template_end - (unsigned long *)optprobe_template_entry)
 #define TMPL_ADD_SP \
-       ((unsigned long *)&optprobe_template_add_sp - (unsigned long *)&optprobe_template_entry)
+       ((unsigned long *)optprobe_template_add_sp - (unsigned long *)optprobe_template_entry)
 #define TMPL_SUB_SP \
-       ((unsigned long *)&optprobe_template_sub_sp - (unsigned long *)&optprobe_template_entry)
+       ((unsigned long *)optprobe_template_sub_sp - (unsigned long *)optprobe_template_entry)
 #define TMPL_RESTORE_BEGIN \
-       ((unsigned long *)&optprobe_template_restore_begin - (unsigned long *)&optprobe_template_entry)
+       ((unsigned long *)optprobe_template_restore_begin - (unsigned long *)optprobe_template_entry)
 #define TMPL_RESTORE_ORIGN_INSN \
-       ((unsigned long *)&optprobe_template_restore_orig_insn - (unsigned long *)&optprobe_template_entry)
+       ((unsigned long *)optprobe_template_restore_orig_insn - (unsigned long *)optprobe_template_entry)
 #define TMPL_RESTORE_END \
-       ((unsigned long *)&optprobe_template_restore_end - (unsigned long *)&optprobe_template_entry)
+       ((unsigned long *)optprobe_template_restore_end - (unsigned long *)optprobe_template_entry)
 
 /*
  * ARM can always optimize an instruction when using ARM ISA, except
@@ -234,7 +234,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *or
        }
 
        /* Copy arch-dep-instance from template. */
-       memcpy(code, (unsigned long *)&optprobe_template_entry,
+       memcpy(code, (unsigned long *)optprobe_template_entry,
                        TMPL_END_IDX * sizeof(kprobe_opcode_t));
 
        /* Adjust buffer according to instruction. */
index f858c352f72a47cdef887a9a6d291b4f0a65dadd..a6b5b7ef40aea08f036e58d2684f87f378773644 100644 (file)
@@ -81,6 +81,7 @@ config ARM64
        select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
        select ARCH_WANT_FRAME_POINTERS
        select ARCH_WANT_HUGE_PMD_SHARE if ARM64_4K_PAGES || (ARM64_16K_PAGES && !ARM64_VA_BITS_36)
+       select ARCH_WANT_LD_ORPHAN_WARN
        select ARCH_HAS_UBSAN_SANITIZE_ALL
        select ARM_AMBA
        select ARM_ARCH_TIMER
@@ -636,6 +637,26 @@ config ARM64_ERRATUM_1542419
 
          If unsure, say Y.
 
+config ARM64_ERRATUM_1508412
+       bool "Cortex-A77: 1508412: workaround deadlock on sequence of NC/Device load and store exclusive or PAR read"
+       default y
+       help
+         This option adds a workaround for Arm Cortex-A77 erratum 1508412.
+
+         Affected Cortex-A77 cores (r0p0, r1p0) could deadlock on a sequence
+         of a store-exclusive or read of PAR_EL1 and a load with device or
+         non-cacheable memory attributes. The workaround depends on a firmware
+         counterpart.
+
+         KVM guests must also have the workaround implemented or they can
+         deadlock the system.
+
+         Work around the issue by inserting DMB SY barriers around PAR_EL1
+         register reads and warning KVM users. The DMB barrier is sufficient
+         to prevent a speculative PAR_EL1 read.
+
+         If unsure, say Y.
+
 config CAVIUM_ERRATUM_22375
        bool "Cavium erratum 22375, 24313"
        default y
@@ -982,7 +1003,7 @@ config NUMA
 config NODES_SHIFT
        int "Maximum NUMA Nodes (as a power of 2)"
        range 1 10
-       default "2"
+       default "4"
        depends on NEED_MULTIPLE_NODES
        help
          Specify the maximum number of NUMA Nodes available on the target
index 6f2494dd6d60b60b5967ddc121d886d4ff00b253..5c4ac1c9f4e0295183c26a97bb8be42861766a67 100644 (file)
@@ -54,6 +54,7 @@ config ARCH_BCM_IPROC
 config ARCH_BERLIN
        bool "Marvell Berlin SoC Family"
        select DW_APB_ICTL
+       select DW_APB_TIMER_OF
        select GPIOLIB
        select PINCTRL
        help
index 5789c2d18d43910ed0a03f6d6f112ac04cf71858..6a87d592bd001fb1b7735b1924d12fe926087759 100644 (file)
@@ -28,10 +28,6 @@ LDFLAGS_vmlinux      += --fix-cortex-a53-843419
   endif
 endif
 
-# We never want expected sections to be placed heuristically by the
-# linker. All sections should be explicitly named in the linker script.
-LDFLAGS_vmlinux += $(call ld-option, --orphan-handling=warn)
-
 ifeq ($(CONFIG_ARM64_USE_LSE_ATOMICS), y)
   ifneq ($(CONFIG_ARM64_LSE_ATOMICS), y)
 $(warning LSE atomics not supported by binutils)
index 3ea5182ca4894a5e965025d4292ed8e927a5757c..e5e840b9fbb4392eddffda45e2bdb6b9fb857802 100644 (file)
 &emac {
        pinctrl-names = "default";
        pinctrl-0 = <&rgmii_pins>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-handle = <&ext_rgmii_phy>;
        phy-supply = <&reg_dc1sw>;
        status = "okay";
index d894ec5fa8a1fa115701698797e89e8345573940..70e31743f0bacbcd5cf1b9e384f2a8319bae80a8 100644 (file)
 &emac {
        pinctrl-names = "default";
        pinctrl-0 = <&rgmii_pins>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-handle = <&ext_rgmii_phy>;
        phy-supply = <&reg_gmac_3v3>;
        status = "okay";
index b26181cf9095aca62906bc277788ade5bc40b931..b54099b654c8a676998712adfa495eb5866baf40 100644 (file)
@@ -13,7 +13,7 @@
 &emac {
        pinctrl-names = "default";
        pinctrl-0 = <&rgmii_pins>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-txid";
        phy-handle = <&ext_rgmii_phy>;
        status = "okay";
 };
index 3ab0f0347bc99d9e56ea558dccf440d1dd0fee63..0494bfaf2ffa05f83b3560962870f85db9a927bb 100644 (file)
        status = "okay";
 
        port {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
                csi_ep: endpoint {
                        remote-endpoint = <&ov5640_ep>;
                        bus-width = <8>;
index df1b9263ad0e21614a25c53ce79dcda2970bba51..6e30a564c87f6dc426edf9f60069df4402bdb379 100644 (file)
@@ -36,7 +36,7 @@
        pinctrl-0 = <&emac_rgmii_pins>;
        phy-supply = <&reg_gmac_3v3>;
        phy-handle = <&ext_rgmii_phy>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        /delete-property/ allwinner,leds-active-low;
        status = "okay";
 };
index 7d7aad18f078bb9463c270ca3231254c253b035d..8bf2db9dcbda0b59c6a960277c9380d32d170fc5 100644 (file)
        pinctrl-0 = <&emac_rgmii_pins>;
        phy-supply = <&reg_gmac_3v3>;
        phy-handle = <&ext_rgmii_phy>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        status = "okay";
 };
 
index cb44bfa5981fd41778b2edac5e4827f7a50dad90..33ab44072e6d709586d79f270c751c2281cf95d1 100644 (file)
        pinctrl-0 = <&emac_rgmii_pins>;
        phy-supply = <&reg_gmac_3v3>;
        phy-handle = <&ext_rgmii_phy>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        status = "okay";
 };
 
index 3f7ceeb1a767a70abd44166dd9f3ee1800fbad90..7c9dbde645b52686b327572dc7c7d9fb1c51c535 100644 (file)
@@ -97,7 +97,7 @@
 &emac {
        pinctrl-names = "default";
        pinctrl-0 = <&ext_rgmii_pins>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-handle = <&ext_rgmii_phy>;
        phy-supply = <&reg_aldo2>;
        status = "okay";
index af85b2074867fdd6d13c30196b1620fb717ea868..961732c52aa0ee36acc65a0ce129a6c3873fd849 100644 (file)
 &emac {
        pinctrl-names = "default";
        pinctrl-0 = <&ext_rgmii_pins>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-handle = <&ext_rgmii_phy>;
        phy-supply = <&reg_gmac_3v3>;
        allwinner,rx-delay-ps = <200>;
index feadd21bc0dc1d501b288af4d60312ec672c4a14..46e558ab7729b990fe98eef9df8091cede619f5f 100644 (file)
        flash@0 {
                #address-cells = <1>;
                #size-cells = <1>;
-               compatible = "n25q00a";
+               compatible = "micron,mt25qu02g", "jedec,spi-nor";
                reg = <0>;
                spi-max-frequency = <100000000>;
 
index c07966740e1465facc1bb04b1ad4600257a9a8e5..f9b4a39683cf41cbc8938f216fc61c44916e3cd8 100644 (file)
        flash@0 {
                #address-cells = <1>;
                #size-cells = <1>;
-               compatible = "n25q00a";
+               compatible = "micron,mt25qu02g", "jedec,spi-nor";
                reg = <0>;
                spi-max-frequency = <100000000>;
 
index cb1360ae1211e27b7783eac19ad00244f121e12f..7740f97c240f050455eeb25702a9d0a22c6ff483 100644 (file)
        pinctrl-0 = <&uart_ao_a_pins>;
        pinctrl-names = "default";
 };
+
+&usb {
+       status = "okay";
+       dr_mode = "otg";
+       vbus-supply = <&usb_pwr>;
+};
index b9efc8469265d871d244c2cb2a89be88152d0bf2..724ee179b316e23d9540736a8eac7adabc4c807f 100644 (file)
                #size-cells = <2>;
                ranges;
 
+               usb: usb@ffe09080 {
+                       compatible = "amlogic,meson-axg-usb-ctrl";
+                       reg = <0x0 0xffe09080 0x0 0x20>;
+                       interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       ranges;
+
+                       clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB1_DDR_BRIDGE>;
+                       clock-names = "usb_ctrl", "ddr";
+                       resets = <&reset RESET_USB_OTG>;
+
+                       dr_mode = "otg";
+
+                       phys = <&usb2_phy1>;
+                       phy-names = "usb2-phy1";
+
+                       dwc2: usb@ff400000 {
+                               compatible = "amlogic,meson-g12a-usb", "snps,dwc2";
+                               reg = <0x0 0xff400000 0x0 0x40000>;
+                               interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clkc CLKID_USB1>;
+                               clock-names = "otg";
+                               phys = <&usb2_phy1>;
+                               dr_mode = "peripheral";
+                               g-rx-fifo-size = <192>;
+                               g-np-tx-fifo-size = <128>;
+                               g-tx-fifo-size = <128 128 16 16 16>;
+                       };
+
+                       dwc3: usb@ff500000 {
+                               compatible = "snps,dwc3";
+                               reg = <0x0 0xff500000 0x0 0x100000>;
+                               interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+                               dr_mode = "host";
+                               maximum-speed = "high-speed";
+                               snps,dis_u2_susphy_quirk;
+                       };
+               };
+
                ethmac: ethernet@ff3f0000 {
                        compatible = "amlogic,meson-axg-dwmac",
                                     "snps,dwmac-3.70a",
                                      "timing-adjustment";
                        rx-fifo-depth = <4096>;
                        tx-fifo-depth = <2048>;
+                       resets = <&reset RESET_ETHERNET>;
+                       reset-names = "stmmaceth";
                        status = "disabled";
                };
 
                                clock-names = "core", "clkin0", "clkin1";
                                resets = <&reset RESET_SD_EMMC_C>;
                        };
+
+                       usb2_phy1: phy@9020 {
+                               compatible = "amlogic,meson-gxl-usb2-phy";
+                               #phy-cells = <0>;
+                               reg = <0x0 0x9020 0x0 0x20>;
+                               clocks = <&clkc CLKID_USB>;
+                               clock-names = "phy";
+                               resets = <&reset RESET_USB_OTG>;
+                               reset-names = "phy";
+                       };
                };
 
                sram: sram@fffc0000 {
index 1e83ec5b8c91a13018b3fc7a1651eca7f75290f7..8514fe6a275a320d6b58bcc578ad56dd129690e6 100644 (file)
                };
 
                ethmac: ethernet@ff3f0000 {
-                       compatible = "amlogic,meson-axg-dwmac",
+                       compatible = "amlogic,meson-g12a-dwmac",
                                     "snps,dwmac-3.70a",
                                     "snps,dwmac";
                        reg = <0x0 0xff3f0000 0x0 0x10000>,
                                      "timing-adjustment";
                        rx-fifo-depth = <4096>;
                        tx-fifo-depth = <2048>;
+                       resets = <&reset RESET_ETHERNET>;
+                       reset-names = "stmmaceth";
                        status = "disabled";
 
                        mdio0: mdio {
                                hwrng: rng@218 {
                                        compatible = "amlogic,meson-rng";
                                        reg = <0x0 0x218 0x0 0x4>;
+                                       clocks = <&clkc CLKID_RNG0>;
+                                       clock-names = "core";
                                };
                        };
 
index 5de2815ba99de9627aa7c7954df376c1c74fd9d3..ce1198ad34e425ea9077dea51a263dfd9238b63f 100644 (file)
@@ -19,7 +19,7 @@
        regulator-min-microvolt = <680000>;
        regulator-max-microvolt = <1040000>;
 
-       pwms = <&pwm_AO_cd 1 1500 0>;
+       pwms = <&pwm_ab 0 1500 0>;
 };
 
 &vddcpu_b {
index 0edd137151f89eb6ba63695d28abdfaf18cf6434..726b91d3a905a5cfd9a9322654570a2074ff58d0 100644 (file)
@@ -13,6 +13,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/power/meson-gxbb-power.h>
+#include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
 #include <dt-bindings/thermal/thermal.h>
 
 / {
                        interrupt-names = "macirq";
                        rx-fifo-depth = <4096>;
                        tx-fifo-depth = <2048>;
+                       resets = <&reset RESET_ETHERNET>;
+                       reset-names = "stmmaceth";
                        power-domains = <&pwrc PWRC_GXBB_ETHERNET_MEM_ID>;
                        status = "disabled";
                };
index 55259f973b5a9e411424b96cf78c4e8c71d9bb19..aef8f2b00778d718e360344f68ae9f0c71c639c5 100644 (file)
@@ -5,20 +5,20 @@
        usb {
                compatible = "simple-bus";
                dma-ranges;
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges = <0x0 0x0 0x68500000 0x00400000>;
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges = <0x0 0x0 0x0 0x68500000 0x0 0x00400000>;
 
                usbphy0: usb-phy@0 {
                        compatible = "brcm,sr-usb-combo-phy";
-                       reg = <0x00000000 0x100>;
+                       reg = <0x0 0x00000000 0x0 0x100>;
                        #phy-cells = <1>;
                        status = "disabled";
                };
 
                xhci0: usb@1000 {
                        compatible = "generic-xhci";
-                       reg = <0x00001000 0x1000>;
+                       reg = <0x0 0x00001000 0x0 0x1000>;
                        interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>;
                        phys = <&usbphy0 1>, <&usbphy0 0>;
                        phy-names = "phy0", "phy1";
@@ -28,7 +28,7 @@
 
                bdc0: usb@2000 {
                        compatible = "brcm,bdc-v0.16";
-                       reg = <0x00002000 0x1000>;
+                       reg = <0x0 0x00002000 0x0 0x1000>;
                        interrupts = <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>;
                        phys = <&usbphy0 0>, <&usbphy0 1>;
                        phy-names = "phy0", "phy1";
 
                usbphy1: usb-phy@10000 {
                        compatible = "brcm,sr-usb-combo-phy";
-                       reg = <0x00010000 0x100>;
+                       reg = <0x0 0x00010000 0x0 0x100>;
                        #phy-cells = <1>;
                        status = "disabled";
                };
 
                usbphy2: usb-phy@20000 {
                        compatible = "brcm,sr-usb-hs-phy";
-                       reg = <0x00020000 0x100>;
+                       reg = <0x0 0x00020000 0x0 0x100>;
                        #phy-cells = <0>;
                        status = "disabled";
                };
 
                xhci1: usb@11000 {
                        compatible = "generic-xhci";
-                       reg = <0x00011000 0x1000>;
+                       reg = <0x0 0x00011000 0x0 0x1000>;
                        interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>;
                        phys = <&usbphy1 1>, <&usbphy2>, <&usbphy1 0>;
                        phy-names = "phy0", "phy1", "phy2";
@@ -62,7 +62,7 @@
 
                bdc1: usb@21000 {
                        compatible = "brcm,bdc-v0.16";
-                       reg = <0x00021000 0x1000>;
+                       reg = <0x0 0x00021000 0x0 0x1000>;
                        interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
                        phys = <&usbphy2>;
                        phy-names = "phy0";
index f46eb47cfa4df049b11965ab66f46a2dfe0d07c9..8161dd23797122c99d6dc4fe0347d4997d542c9c 100644 (file)
@@ -75,6 +75,7 @@
 &enetc_port0 {
        phy-handle = <&phy0>;
        phy-connection-type = "sgmii";
+       managed = "in-band-status";
        status = "okay";
 
        mdio {
index 73e4f9466887c21ebb2902bb8598f780d5808960..7a6fb7e1fb82f54b5c332626b3941b5464e1ff05 100644 (file)
                        compatible = "fsl,ls1028a-rcpm", "fsl,qoriq-rcpm-2.1+";
                        reg = <0x0 0x1e34040 0x0 0x1c>;
                        #fsl,rcpm-wakeup-cells = <7>;
+                       little-endian;
                };
 
                ftm_alarm0: timer@2800000 {
index ff5805206a289c9e11d124d0dc2e155d8aee8de4..692d8f4a206da914323292b51dc9c1f94ed99486 100644 (file)
                        compatible = "fsl,ls1088a-rcpm", "fsl,qoriq-rcpm-2.1+";
                        reg = <0x0 0x1e34040 0x0 0x18>;
                        #fsl,rcpm-wakeup-cells = <6>;
+                       little-endian;
                };
 
                ftm_alarm0: timer@2800000 {
index bf72918fe545b2fe1ab688319e844f7452d03245..e7abb74bd8168002a6bf4b66d20f486ba13ae40e 100644 (file)
                        compatible = "fsl,ls208xa-rcpm", "fsl,qoriq-rcpm-2.1+";
                        reg = <0x0 0x1e34040 0x0 0x18>;
                        #fsl,rcpm-wakeup-cells = <6>;
+                       little-endian;
                };
 
                ftm_alarm0: timer@2800000 {
index 6de86a4f0ec4177ae39fd4b4c58cd690f0a66faf..b88c3c99b007eaf6011ea2656a194ce338c3928d 100644 (file)
@@ -72,6 +72,7 @@
        pmic@4b {
                compatible = "rohm,bd71847";
                reg = <0x4b>;
+               pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_pmic>;
                interrupt-parent = <&gpio1>;
                interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
                host-wakeup-gpios = <&gpio2 8 GPIO_ACTIVE_HIGH>;
                device-wakeup-gpios = <&gpio2 7 GPIO_ACTIVE_HIGH>;
                clocks = <&osc_32k>;
+               max-speed = <4000000>;
                clock-names = "extclk";
        };
 };
index f305a530ff6fb9944dff9b5bf07a871e6365a330..521eb3a5a12edb1490aa1772454d5998c4c9b16e 100644 (file)
        pmic@4b {
                compatible = "rohm,bd71847";
                reg = <0x4b>;
+               pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_pmic>;
                interrupt-parent = <&gpio1>;
                interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
index 4107fe914d08d1c0330cfaeb6158c5e97500e89b..49082529764f0670e1be3ef1d4e3517cc5d57dbc 100644 (file)
        pmic@4b {
                compatible = "rohm,bd71847";
                reg = <0x4b>;
+               pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_pmic>;
                interrupt-parent = <&gpio2>;
-               /*
-                * The interrupt is not correct. It should be level low,
-                * however with internal pull up this causes IRQ storm.
-                */
-               interrupts = <8 IRQ_TYPE_EDGE_RISING>;
+               interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
                rohm,reset-snvs-powered;
 
                #clock-cells = <0>;
 
        pinctrl_pmic: pmicirqgrp {
                fsl,pins = <
-                       MX8MM_IOMUXC_SD1_DATA6_GPIO2_IO8        0x41
+                       MX8MM_IOMUXC_SD1_DATA6_GPIO2_IO8        0x141
                >;
        };
 
index b83f400def8bc796179bd98263d7212a310f9a75..05ee062548e4fc2aca21e654aedf1ad7a89d9fce 100644 (file)
 
                opp-1600000000 {
                        opp-hz = /bits/ 64 <1600000000>;
-                       opp-microvolt = <900000>;
+                       opp-microvolt = <950000>;
                        opp-supported-hw = <0xc>, <0x7>;
                        clock-latency-ns = <150000>;
                        opp-suspend;
index 46e76cf32b2f0d3605d1cd3db4f3b2110a3ff9c5..7dfee715a2c4db6f0c182ff754a730a6e44e0928 100644 (file)
@@ -53,6 +53,7 @@
        pmic@4b {
                compatible = "rohm,bd71847";
                reg = <0x4b>;
+               pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_pmic>;
                interrupt-parent = <&gpio1>;
                interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
index 707d8486b4d83fe7f0945aaa8eca8dd8f2e36c9f..8311b95dee49e65f3ab7b6109f3f76127acb8b3a 100644 (file)
@@ -18,6 +18,7 @@
        pmic: pmic@25 {
                compatible = "nxp,pca9450b";
                reg = <0x25>;
+               pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_pmic>;
                interrupt-parent = <&gpio1>;
                interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
index a2d0190921e4939f0cd68aabe683cfe3484c7d7b..7f356edf9f916254584ef49f3af0446aae458399 100644 (file)
        pmic@4b {
                compatible = "rohm,bd71847";
                reg = <0x4b>;
+               pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_pmic>;
                interrupt-parent = <&gpio2>;
-               /*
-                * The interrupt is not correct. It should be level low,
-                * however with internal pull up this causes IRQ storm.
-                */
-               interrupts = <8 IRQ_TYPE_EDGE_RISING>;
+               interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
                rohm,reset-snvs-powered;
 
                regulators {
 
        pinctrl_pmic: pmicirqgrp {
                fsl,pins = <
-                       MX8MN_IOMUXC_SD1_DATA6_GPIO2_IO8        0x101
+                       MX8MN_IOMUXC_SD1_DATA6_GPIO2_IO8        0x141
                >;
        };
 
index 746faf1cf2fb7deecfbb1a22419bd831bbbcbb33..16c7202885d7094bdc03f0a07188a3a7e2d17c54 100644 (file)
                                #index-cells = <1>;
                                reg = <0x32e40200 0x200>;
                        };
-
-                       usbotg2: usb@32e50000 {
-                               compatible = "fsl,imx8mn-usb", "fsl,imx7d-usb";
-                               reg = <0x32e50000 0x200>;
-                               interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clk IMX8MN_CLK_USB1_CTRL_ROOT>;
-                               clock-names = "usb1_ctrl_root_clk";
-                               assigned-clocks = <&clk IMX8MN_CLK_USB_BUS>,
-                                                 <&clk IMX8MN_CLK_USB_CORE_REF>;
-                               assigned-clock-parents = <&clk IMX8MN_SYS_PLL2_500M>,
-                                                        <&clk IMX8MN_SYS_PLL1_100M>;
-                               fsl,usbphy = <&usbphynop2>;
-                               fsl,usbmisc = <&usbmisc2 0>;
-                               status = "disabled";
-                       };
-
-                       usbmisc2: usbmisc@32e50200 {
-                               compatible = "fsl,imx8mn-usbmisc", "fsl,imx7d-usbmisc";
-                               #index-cells = <1>;
-                               reg = <0x32e50200 0x200>;
-                       };
-
                };
 
                dma_apbh: dma-controller@33000000 {
                assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_100M>;
                clock-names = "main_clk";
        };
-
-       usbphynop2: usbphynop2 {
-               compatible = "usb-nop-xceiv";
-               clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
-               assigned-clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
-               assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_100M>;
-               clock-names = "main_clk";
-       };
 };
index 8bc6caa9167d2092c6f44e4c3f025a598cfcbcb0..4338db14c5dafda1eef7b209014b4faf7a862c5f 100644 (file)
@@ -19,6 +19,7 @@ fman0: fman@1a00000 {
        clock-names = "fmanclk";
        fsl,qman-channel-range = <0x800 0x10>;
        ptimer-handle = <&ptp_timer0>;
+       dma-coherent;
 
        muram@0 {
                compatible = "fsl,fman-muram";
index 96c50d48289dffc7dac2784ec92a7d18c5a3db24..a7a83f29f00bd271d51047ec778fbab1d393eaf4 100644 (file)
        flash@0 {
                #address-cells = <1>;
                #size-cells = <1>;
-               compatible = "mt25qu02g";
+               compatible = "micron,mt25qu02g", "jedec,spi-nor";
                reg = <0>;
                spi-max-frequency = <100000000>;
 
index 03733fd92732d4eeb48bd53facedef2bb012a4e9..215d2f70262332ff95a24ce91b78e030a23a7c73 100644 (file)
        compatible = "globalscale,espressobin-v7-emmc", "globalscale,espressobin-v7",
                     "globalscale,espressobin", "marvell,armada3720",
                     "marvell,armada3710";
+
+       aliases {
+               /* ethernet1 is wan port */
+               ethernet1 = &switch0port3;
+               ethernet3 = &switch0port1;
+       };
 };
 
 &switch0 {
        ports {
-               port@1 {
+               switch0port1: port@1 {
                        reg = <1>;
                        label = "lan1";
                        phy-handle = <&switch0phy0>;
                };
 
-               port@3 {
+               switch0port3: port@3 {
                        reg = <3>;
                        label = "wan";
                        phy-handle = <&switch0phy2>;
index 8570c5f47d7d89d0c39e3162cf23034061d1927e..b6f4af8ebafbb9739edcf69dc021c18be3973320 100644 (file)
        model = "Globalscale Marvell ESPRESSOBin Board V7";
        compatible = "globalscale,espressobin-v7", "globalscale,espressobin",
                     "marvell,armada3720", "marvell,armada3710";
+
+       aliases {
+               /* ethernet1 is wan port */
+               ethernet1 = &switch0port3;
+               ethernet3 = &switch0port1;
+       };
 };
 
 &switch0 {
        ports {
-               port@1 {
+               switch0port1: port@1 {
                        reg = <1>;
                        label = "lan1";
                        phy-handle = <&switch0phy0>;
                };
 
-               port@3 {
+               switch0port3: port@3 {
                        reg = <3>;
                        label = "wan";
                        phy-handle = <&switch0phy2>;
index b97218c727277ac1976c6cf2c8c4eeb8375febd6..0775c16e0ec8062cbf77cc3b4bfc4d7540005592 100644 (file)
 / {
        aliases {
                ethernet0 = &eth0;
+               /* for dsa slave device */
+               ethernet1 = &switch0port1;
+               ethernet2 = &switch0port2;
+               ethernet3 = &switch0port3;
                serial0 = &uart0;
                serial1 = &uart1;
        };
                        #address-cells = <1>;
                        #size-cells = <0>;
 
-                       port@0 {
+                       switch0port0: port@0 {
                                reg = <0>;
                                label = "cpu";
                                ethernet = <&eth0>;
                                };
                        };
 
-                       port@1 {
+                       switch0port1: port@1 {
                                reg = <1>;
                                label = "wan";
                                phy-handle = <&switch0phy0>;
                        };
 
-                       port@2 {
+                       switch0port2: port@2 {
                                reg = <2>;
                                label = "lan0";
                                phy-handle = <&switch0phy1>;
                        };
 
-                       port@3 {
+                       switch0port3: port@3 {
                                reg = <3>;
                                label = "lan1";
                                phy-handle = <&switch0phy2>;
index 381a84912ba807b107bb0733a2b339c512c6811d..c28d51cc57973fd03ec3e15ac39a931a7956f03f 100644 (file)
        model = "NVIDIA Jetson TX2 Developer Kit";
        compatible = "nvidia,p2771-0000", "nvidia,tegra186";
 
-       aconnect {
-               status = "okay";
-
-               dma-controller@2930000 {
-                       status = "okay";
-               };
-
-               interrupt-controller@2a40000 {
-                       status = "okay";
-               };
-       };
-
        i2c@3160000 {
                power-monitor@42 {
                        compatible = "ti,ina3221";
index a2893be80507e2fab569a47e8cfb26d7fac151b9..0dc8304a2edddfb7c2c36a950c9c16a50f92ef2f 100644 (file)
@@ -54,7 +54,7 @@
                        status = "okay";
                };
 
-               serial@c280000 {
+               serial@3100000 {
                        status = "okay";
                };
 
index e9c90f0f44ff78b011a120776c87b30acf5e7884..93438d2b9469624d8ecc0175de12d98fcfee2327 100644 (file)
 
                hsp_aon: hsp@c150000 {
                        compatible = "nvidia,tegra194-hsp", "nvidia,tegra186-hsp";
-                       reg = <0x0c150000 0xa0000>;
+                       reg = <0x0c150000 0x90000>;
                        interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
index e18e1a9a3011368d084be90430dfbe0c8fd7d30e..a9caaf7c0d67eb082e5f71671d2a20433cfbc47d 100644 (file)
                vin-supply = <&vdd_5v0_sys>;
        };
 
-       vdd_usb_vbus_otg: regulator@11 {
-               compatible = "regulator-fixed";
-               regulator-name = "USB_VBUS_EN0";
-               regulator-min-microvolt = <5000000>;
-               regulator-max-microvolt = <5000000>;
-               gpio = <&gpio TEGRA_GPIO(CC, 4) GPIO_ACTIVE_HIGH>;
-               enable-active-high;
-               vin-supply = <&vdd_5v0_sys>;
-       };
-
        vdd_hdmi: regulator@10 {
                compatible = "regulator-fixed";
                regulator-name = "VDD_HDMI_5V0";
                enable-active-high;
                vin-supply = <&vdd_3v3_sys>;
        };
+
+       vdd_usb_vbus_otg: regulator@14 {
+               compatible = "regulator-fixed";
+               regulator-name = "USB_VBUS_EN0";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&gpio TEGRA_GPIO(CC, 4) GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+               vin-supply = <&vdd_5v0_sys>;
+       };
 };
index f6e6a24829af81138942599ef54903134a7d316f..b5d9a55262724396f9204a570d49df7727f70406 100644 (file)
@@ -8,7 +8,7 @@
        compatible = "nvidia,tegra234-vdk", "nvidia,tegra234";
 
        aliases {
-               sdhci3 = "/cbb@0/sdhci@3460000";
+               mmc3 = "/bus@0/mmc@3460000";
                serial0 = &uarta;
        };
 
                stdout-path = "serial0:115200n8";
        };
 
-       cbb@0 {
+       bus@0 {
                serial@3100000 {
                        status = "okay";
                };
 
-               sdhci@3460000 {
+               mmc@3460000 {
                        status = "okay";
                        bus-width = <8>;
                        non-removable;
index a94dac76bf3fbddd8c2f808f09b8bdc2d7c368e6..59e0cbfa2214305bc102ff4778bd82d6ce48ad51 100644 (file)
        };
 
        soc: soc {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges = <0 0 0 0xffffffff>;
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges = <0 0 0 0 0x0 0xffffffff>;
                dma-ranges;
                compatible = "simple-bus";
 
                prng: qrng@e1000 {
                        compatible = "qcom,prng-ee";
-                       reg = <0xe3000 0x1000>;
+                       reg = <0x0 0xe3000 0x0 0x1000>;
                        clocks = <&gcc GCC_PRNG_AHB_CLK>;
                        clock-names = "core";
                };
 
                cryptobam: dma@704000 {
                        compatible = "qcom,bam-v1.7.0";
-                       reg = <0x00704000 0x20000>;
+                       reg = <0x0 0x00704000 0x0 0x20000>;
                        interrupts = <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&gcc GCC_CRYPTO_AHB_CLK>;
                        clock-names = "bam_clk";
 
                crypto: crypto@73a000 {
                        compatible = "qcom,crypto-v5.1";
-                       reg = <0x0073a000 0x6000>;
+                       reg = <0x0 0x0073a000 0x0 0x6000>;
                        clocks = <&gcc GCC_CRYPTO_AHB_CLK>,
                                <&gcc GCC_CRYPTO_AXI_CLK>,
                                <&gcc GCC_CRYPTO_CLK>;
 
                tlmm: pinctrl@1000000 {
                        compatible = "qcom,ipq6018-pinctrl";
-                       reg = <0x01000000 0x300000>;
+                       reg = <0x0 0x01000000 0x0 0x300000>;
                        interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
                        gpio-controller;
                        #gpio-cells = <2>;
 
                gcc: gcc@1800000 {
                        compatible = "qcom,gcc-ipq6018";
-                       reg = <0x01800000 0x80000>;
+                       reg = <0x0 0x01800000 0x0 0x80000>;
                        clocks = <&xo>, <&sleep_clk>;
                        clock-names = "xo", "sleep_clk";
                        #clock-cells = <1>;
 
                tcsr_mutex_regs: syscon@1905000 {
                        compatible = "syscon";
-                       reg = <0x01905000 0x8000>;
+                       reg = <0x0 0x01905000 0x0 0x8000>;
                };
 
                tcsr_q6: syscon@1945000 {
                        compatible = "syscon";
-                       reg = <0x01945000 0xe000>;
+                       reg = <0x0 0x01945000 0x0 0xe000>;
                };
 
                blsp_dma: dma@7884000 {
                        compatible = "qcom,bam-v1.7.0";
-                       reg = <0x07884000 0x2b000>;
+                       reg = <0x0 0x07884000 0x0 0x2b000>;
                        interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&gcc GCC_BLSP1_AHB_CLK>;
                        clock-names = "bam_clk";
 
                blsp1_uart3: serial@78b1000 {
                        compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
-                       reg = <0x078b1000 0x200>;
+                       reg = <0x0 0x078b1000 0x0 0x200>;
                        interrupts = <GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&gcc GCC_BLSP1_UART3_APPS_CLK>,
                                <&gcc GCC_BLSP1_AHB_CLK>;
                        compatible = "qcom,spi-qup-v2.2.1";
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       reg = <0x078b5000 0x600>;
+                       reg = <0x0 0x078b5000 0x0 0x600>;
                        interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
                        spi-max-frequency = <50000000>;
                        clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>,
                        compatible = "qcom,spi-qup-v2.2.1";
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       reg = <0x078b6000 0x600>;
+                       reg = <0x0 0x078b6000 0x0 0x600>;
                        interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
                        spi-max-frequency = <50000000>;
                        clocks = <&gcc GCC_BLSP1_QUP2_SPI_APPS_CLK>,
                        compatible = "qcom,i2c-qup-v2.2.1";
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       reg = <0x078b6000 0x600>;
+                       reg = <0x0 0x078b6000 0x0 0x600>;
                        interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&gcc GCC_BLSP1_AHB_CLK>,
                                <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>;
                        compatible = "qcom,i2c-qup-v2.2.1";
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       reg = <0x078b7000 0x600>;
+                       reg = <0x0 0x078b7000 0x0 0x600>;
                        interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&gcc GCC_BLSP1_AHB_CLK>,
                                <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>;
                        compatible = "qcom,msm-qgic2";
                        interrupt-controller;
                        #interrupt-cells = <0x3>;
-                       reg =   <0x0b000000 0x1000>,  /*GICD*/
-                               <0x0b002000 0x1000>,  /*GICC*/
-                               <0x0b001000 0x1000>,  /*GICH*/
-                               <0x0b004000 0x1000>;  /*GICV*/
+                       reg =   <0x0 0x0b000000 0x0 0x1000>,  /*GICD*/
+                               <0x0 0x0b002000 0x0 0x1000>,  /*GICC*/
+                               <0x0 0x0b001000 0x0 0x1000>,  /*GICH*/
+                               <0x0 0x0b004000 0x0 0x1000>;  /*GICV*/
                        interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
                };
 
                watchdog@b017000 {
                        compatible = "qcom,kpss-wdt";
                        interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
-                       reg = <0x0b017000 0x40>;
+                       reg = <0x0 0x0b017000 0x0 0x40>;
                        clocks = <&sleep_clk>;
                        timeout-sec = <10>;
                };
 
                apcs_glb: mailbox@b111000 {
                        compatible = "qcom,ipq6018-apcs-apps-global";
-                       reg = <0x0b111000 0x1000>;
+                       reg = <0x0 0x0b111000 0x0 0x1000>;
                        #clock-cells = <1>;
                        clocks = <&a53pll>, <&xo>;
                        clock-names = "pll", "xo";
 
                a53pll: clock@b116000 {
                        compatible = "qcom,ipq6018-a53pll";
-                       reg = <0x0b116000 0x40>;
+                       reg = <0x0 0x0b116000 0x0 0x40>;
                        #clock-cells = <0>;
                        clocks = <&xo>;
                        clock-names = "xo";
                };
 
                timer@b120000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
+                       #address-cells = <2>;
+                       #size-cells = <2>;
                        ranges;
                        compatible = "arm,armv7-timer-mem";
-                       reg = <0x0b120000 0x1000>;
+                       reg = <0x0 0x0b120000 0x0 0x1000>;
                        clock-frequency = <19200000>;
 
                        frame@b120000 {
                                frame-number = <0>;
                                interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
-                               reg = <0x0b121000 0x1000>,
-                                     <0x0b122000 0x1000>;
+                               reg = <0x0 0x0b121000 0x0 0x1000>,
+                                     <0x0 0x0b122000 0x0 0x1000>;
                        };
 
                        frame@b123000 {
                                frame-number = <1>;
                                interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
-                               reg = <0xb123000 0x1000>;
+                               reg = <0x0 0xb123000 0x0 0x1000>;
                                status = "disabled";
                        };
 
                        frame@b124000 {
                                frame-number = <2>;
                                interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
-                               reg = <0x0b124000 0x1000>;
+                               reg = <0x0 0x0b124000 0x0 0x1000>;
                                status = "disabled";
                        };
 
                        frame@b125000 {
                                frame-number = <3>;
                                interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
-                               reg = <0x0b125000 0x1000>;
+                               reg = <0x0 0x0b125000 0x0 0x1000>;
                                status = "disabled";
                        };
 
                        frame@b126000 {
                                frame-number = <4>;
                                interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
-                               reg = <0x0b126000 0x1000>;
+                               reg = <0x0 0x0b126000 0x0 0x1000>;
                                status = "disabled";
                        };
 
                        frame@b127000 {
                                frame-number = <5>;
                                interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
-                               reg = <0x0b127000 0x1000>;
+                               reg = <0x0 0x0b127000 0x0 0x1000>;
                                status = "disabled";
                        };
 
                        frame@b128000 {
                                frame-number = <6>;
                                interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
-                               reg = <0x0b128000 0x1000>;
+                               reg = <0x0 0x0b128000 0x0 0x1000>;
                                status = "disabled";
                        };
                };
 
                q6v5_wcss: remoteproc@cd00000 {
                        compatible = "qcom,ipq8074-wcss-pil";
-                       reg = <0x0cd00000 0x4040>,
-                               <0x004ab000 0x20>;
+                       reg = <0x0 0x0cd00000 0x0 0x4040>,
+                             <0x0 0x004ab000 0x0 0x20>;
                        reg-names = "qdsp6",
                                    "rmb";
                        interrupts-extended = <&intc GIC_SPI 325 IRQ_TYPE_EDGE_RISING>,
index 9cbf963aa068e950eacbc4ac184a07f4b5ca30b8..c29643442e91f6cdc036663b7a23ba3d4eabfe44 100644 (file)
                clock-frequency = <0>;
        };
 
+       audio_clk_b: audio_clk_b {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <0>;
+       };
+
        audio_clk_c: audio_clk_c {
                compatible = "fixed-clock";
                #clock-cells = <0>;
index 35bd6b904b9c765785b2ec40cbdb2919eab7a660..33768103851935a0ac236226b0c4dd035f488959 100644 (file)
                interrupts = <RK_PB2 IRQ_TYPE_LEVEL_LOW>;
                pinctrl-names = "default";
                pinctrl-0 = <&pmic_int>;
-               rockchip,system-power-controller;
                wakeup-source;
                #clock-cells = <1>;
                clock-output-names = "rk808-clkout1", "xin32k";
index be7a31d81632e911b2f537f45055a9698666cde1..2ee07d15a6e375e0f07cf8ed60354bcacb4c4d0a 100644 (file)
@@ -20,7 +20,7 @@
        gmac_clk: gmac-clock {
                compatible = "fixed-clock";
                clock-frequency = <125000000>;
-               clock-output-names = "gmac_clk";
+               clock-output-names = "gmac_clkin";
                #clock-cells = <0>;
        };
 
index e7a459fa432280bc1902ff8fe39ff46a6626d366..20309076dbac069acb62bd048dbb555e1d2ec53f 100644 (file)
                        label = "red:diy";
                        gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>;
                        default-state = "off";
-                       linux,default-trigger = "mmc1";
+                       linux,default-trigger = "mmc2";
                };
 
                yellow_led: led-2 {
                        label = "yellow:yellow-led";
                        gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>;
                        default-state = "off";
-                       linux,default-trigger = "mmc0";
+                       linux,default-trigger = "mmc1";
                };
        };
 
index ada724b12f014400aecf9d776e488da7a1205ce0..7a9a7aca86c6a0632b3b00e1d9c6f56b774e88ce 100644 (file)
@@ -29,6 +29,9 @@
                i2c6 = &i2c6;
                i2c7 = &i2c7;
                i2c8 = &i2c8;
+               mmc0 = &sdio0;
+               mmc1 = &sdmmc;
+               mmc2 = &sdhci;
                serial0 = &uart0;
                serial1 = &uart1;
                serial2 = &uart2;
index 17a2df6a263e8fc96ce9a959b7e08aa1ba50b8cb..5cfe3cf6f2acb2db8020bbf8821aba0a9c787538 100644 (file)
@@ -500,6 +500,7 @@ CONFIG_GPIO_ALTERA=m
 CONFIG_GPIO_DWAPB=y
 CONFIG_GPIO_MB86S7X=y
 CONFIG_GPIO_MPC8XXX=y
+CONFIG_GPIO_MXC=y
 CONFIG_GPIO_PL061=y
 CONFIG_GPIO_RCAR=y
 CONFIG_GPIO_UNIPHIER=y
index e3d47b52161db1ed0b43e307987585453919c0b2..ec7720dbe2c801bc44344d7893cfc510fed7d0d7 100644 (file)
@@ -10,6 +10,7 @@
  * #imm16 values used for BRK instruction generation
  * 0x004: for installing kprobes
  * 0x005: for installing uprobes
+ * 0x006: for kprobe software single-step
  * Allowed values for kgdb are 0x400 - 0x7ff
  * 0x100: for triggering a fault on purpose (reserved)
  * 0x400: for dynamic BRK instruction
@@ -19,6 +20,7 @@
  */
 #define KPROBES_BRK_IMM                        0x004
 #define UPROBES_BRK_IMM                        0x005
+#define KPROBES_BRK_SS_IMM             0x006
 #define FAULT_BRK_IMM                  0x100
 #define KGDB_DYN_DBG_BRK_IMM           0x400
 #define KGDB_COMPILED_DBG_BRK_IMM      0x401
index 0ac3e06a211842b46e0f962ef5465644a0419135..63d43b5f82f674e9b9bbffdad4f4ea2360b806f5 100644 (file)
@@ -24,6 +24,7 @@
 #define CTR_L1IP(ctr)          (((ctr) >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK)
 
 #define ICACHE_POLICY_VPIPT    0
+#define ICACHE_POLICY_RESERVED 1
 #define ICACHE_POLICY_VIPT     2
 #define ICACHE_POLICY_PIPT     3
 
index 42868dbd29fd9037df97b91d3ce932fd11d20c1c..e7d98997c09c3058dd0656af26528ebd220cd2bc 100644 (file)
@@ -65,7 +65,8 @@
 #define ARM64_HAS_ARMv8_4_TTL                  55
 #define ARM64_HAS_TLB_RANGE                    56
 #define ARM64_MTE                              57
+#define ARM64_WORKAROUND_1508412               58
 
-#define ARM64_NCAPS                            58
+#define ARM64_NCAPS                            59
 
 #endif /* __ASM_CPUCAPS_H */
index f7e7144af174c9dd84d0c4656c59af407896690d..da250e4741bd7ecd8a189d10dab5f18678d5040a 100644 (file)
@@ -268,6 +268,8 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 /*
  * CPU feature detected at boot time based on feature of one or more CPUs.
  * All possible conflicts for a late CPU are ignored.
+ * NOTE: this means that a late CPU with the feature will *not* cause the
+ * capability to be advertised by cpus_have_*cap()!
  */
 #define ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE            \
        (ARM64_CPUCAP_SCOPE_LOCAL_CPU           |       \
@@ -375,6 +377,23 @@ cpucap_multi_entry_cap_matches(const struct arm64_cpu_capabilities *entry,
        return false;
 }
 
+static __always_inline bool is_vhe_hyp_code(void)
+{
+       /* Only defined for code run in VHE hyp context */
+       return __is_defined(__KVM_VHE_HYPERVISOR__);
+}
+
+static __always_inline bool is_nvhe_hyp_code(void)
+{
+       /* Only defined for code run in NVHE hyp context */
+       return __is_defined(__KVM_NVHE_HYPERVISOR__);
+}
+
+static __always_inline bool is_hyp_code(void)
+{
+       return is_vhe_hyp_code() || is_nvhe_hyp_code();
+}
+
 extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
 extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
 extern struct static_key_false arm64_const_caps_ready;
@@ -428,35 +447,40 @@ static __always_inline bool __cpus_have_const_cap(int num)
 }
 
 /*
- * Test for a capability, possibly with a runtime check.
+ * Test for a capability without a runtime check.
  *
- * Before capabilities are finalized, this behaves as cpus_have_cap().
+ * Before capabilities are finalized, this will BUG().
  * After capabilities are finalized, this is patched to avoid a runtime check.
  *
  * @num must be a compile-time constant.
  */
-static __always_inline bool cpus_have_const_cap(int num)
+static __always_inline bool cpus_have_final_cap(int num)
 {
        if (system_capabilities_finalized())
                return __cpus_have_const_cap(num);
        else
-               return cpus_have_cap(num);
+               BUG();
 }
 
 /*
- * Test for a capability without a runtime check.
+ * Test for a capability, possibly with a runtime check for non-hyp code.
  *
- * Before capabilities are finalized, this will BUG().
+ * For hyp code, this behaves the same as cpus_have_final_cap().
+ *
+ * For non-hyp code:
+ * Before capabilities are finalized, this behaves as cpus_have_cap().
  * After capabilities are finalized, this is patched to avoid a runtime check.
  *
  * @num must be a compile-time constant.
  */
-static __always_inline bool cpus_have_final_cap(int num)
+static __always_inline bool cpus_have_const_cap(int num)
 {
-       if (system_capabilities_finalized())
+       if (is_hyp_code())
+               return cpus_have_final_cap(num);
+       else if (system_capabilities_finalized())
                return __cpus_have_const_cap(num);
        else
-               BUG();
+               return cpus_have_cap(num);
 }
 
 static inline void cpus_set_cap(unsigned int num)
index 7219cddeba669f844a8e9611b3ceda597e65c021..ef5b040dee44dff5bd9fd0011e56fa792833f4d9 100644 (file)
@@ -71,6 +71,7 @@
 #define ARM_CPU_PART_CORTEX_A55                0xD05
 #define ARM_CPU_PART_CORTEX_A76                0xD0B
 #define ARM_CPU_PART_NEOVERSE_N1       0xD0C
+#define ARM_CPU_PART_CORTEX_A77                0xD0D
 
 #define APM_CPU_PART_POTENZA           0x000
 
@@ -85,6 +86,8 @@
 #define QCOM_CPU_PART_FALKOR_V1                0x800
 #define QCOM_CPU_PART_FALKOR           0xC00
 #define QCOM_CPU_PART_KRYO             0x200
+#define QCOM_CPU_PART_KRYO_2XX_GOLD    0x800
+#define QCOM_CPU_PART_KRYO_2XX_SILVER  0x801
 #define QCOM_CPU_PART_KRYO_3XX_SILVER  0x803
 #define QCOM_CPU_PART_KRYO_4XX_GOLD    0x804
 #define QCOM_CPU_PART_KRYO_4XX_SILVER  0x805
 #define MIDR_CORTEX_A55 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55)
 #define MIDR_CORTEX_A76        MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76)
 #define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1)
+#define MIDR_CORTEX_A77        MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77)
 #define MIDR_THUNDERX  MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
 #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
 #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
 #define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1)
 #define MIDR_QCOM_FALKOR MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR)
 #define MIDR_QCOM_KRYO MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO)
+#define MIDR_QCOM_KRYO_2XX_GOLD MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_2XX_GOLD)
+#define MIDR_QCOM_KRYO_2XX_SILVER MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_2XX_SILVER)
 #define MIDR_QCOM_KRYO_3XX_SILVER MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_3XX_SILVER)
 #define MIDR_QCOM_KRYO_4XX_GOLD MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_4XX_GOLD)
 #define MIDR_QCOM_KRYO_4XX_SILVER MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_4XX_SILVER)
index ec213b4a165021be50b64f47d97b7018fb0326c7..1c26d7baa67f8d1e12a009bd0e22230f511abeea 100644 (file)
@@ -128,6 +128,9 @@ static inline void local_daif_inherit(struct pt_regs *regs)
 {
        unsigned long flags = regs->pstate & DAIF_MASK;
 
+       if (interrupts_enabled(regs))
+               trace_hardirqs_on();
+
        /*
         * We can't use local_daif_restore(regs->pstate) here as
         * system_has_prio_mask_debugging() won't restore the I bit if it can
index 0b298f48f5bfa231aa2b398d48acc0dab0af221e..657c921fd784a7c12a0e45d814c6bc089f9ca0ec 100644 (file)
@@ -53,6 +53,7 @@
 
 /* kprobes BRK opcodes with ESR encoding  */
 #define BRK64_OPCODE_KPROBES   (AARCH64_BREAK_MON | (KPROBES_BRK_IMM << 5))
+#define BRK64_OPCODE_KPROBES_SS        (AARCH64_BREAK_MON | (KPROBES_BRK_SS_IMM << 5))
 /* uprobes BRK opcodes with ESR encoding  */
 #define BRK64_OPCODE_UPROBES   (AARCH64_BREAK_MON | (UPROBES_BRK_IMM << 5))
 
index 99b9383cd036d7e3744d6f1b4bae9c9c3cd366e8..0756191f44f644b9a3153dd584cda74ecc75dd4e 100644 (file)
@@ -31,7 +31,12 @@ static inline u32 disr_to_esr(u64 disr)
        return esr;
 }
 
+asmlinkage void noinstr enter_el1_irq_or_nmi(struct pt_regs *regs);
+asmlinkage void noinstr exit_el1_irq_or_nmi(struct pt_regs *regs);
 asmlinkage void enter_from_user_mode(void);
+asmlinkage void exit_to_user_mode(void);
+void arm64_enter_nmi(struct pt_regs *regs);
+void arm64_exit_nmi(struct pt_regs *regs);
 void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs);
 void do_undefinstr(struct pt_regs *regs);
 void do_bti(struct pt_regs *regs);
index 97e511d645a210f94d904bb6f48ef4acbc886da0..8699ce30f587ec39ea7cda4cd6a3630f947de1ca 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/percpu.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
-#define MAX_INSN_SIZE                  1
+#define MAX_INSN_SIZE                  2
 
 #define flush_insn_slot(p)             do { } while (0)
 #define kretprobe_blacklist_size       0
index 0aecbab6a7fb3bfc941f0776d5b31e32ca913195..0cd9f0f75c135f3bb62e12792eb76d70bfae316c 100644 (file)
@@ -118,6 +118,8 @@ struct kvm_arch {
         */
        unsigned long *pmu_filter;
        unsigned int pmuver;
+
+       u8 pfr0_csv2;
 };
 
 struct kvm_vcpu_fault_info {
@@ -239,6 +241,7 @@ enum vcpu_sysreg {
 #define cp14_DBGWCR0   (DBGWCR0_EL1 * 2)
 #define cp14_DBGWVR0   (DBGWVR0_EL1 * 2)
 #define cp14_DBGDCCINT (MDCCINT_EL1 * 2)
+#define cp14_DBGVCR    (DBGVCR32_EL2 * 2)
 
 #define NR_COPRO_REGS  (NR_SYS_REGS * 2)
 
index 4ff12a7adcfd112beed24807ef231008447678e3..5628289b9d5e60c1c7ebdd490e13711c7ca5f01b 100644 (file)
@@ -115,8 +115,6 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 #define pte_valid(pte)         (!!(pte_val(pte) & PTE_VALID))
 #define pte_valid_not_user(pte) \
        ((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID)
-#define pte_valid_young(pte) \
-       ((pte_val(pte) & (PTE_VALID | PTE_AF)) == (PTE_VALID | PTE_AF))
 #define pte_valid_user(pte) \
        ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))
 
@@ -124,9 +122,12 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
  * Could the pte be present in the TLB? We must check mm_tlb_flush_pending
  * so that we don't erroneously return false for pages that have been
  * remapped as PROT_NONE but are yet to be flushed from the TLB.
+ * Note that we can't make any assumptions based on the state of the access
+ * flag, since ptep_clear_flush_young() elides a DSB when invalidating the
+ * TLB.
  */
 #define pte_accessible(mm, pte)        \
-       (mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid_young(pte))
+       (mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid(pte))
 
 /*
  * p??_access_permitted() is true for valid user mappings (subject to the
@@ -164,13 +165,6 @@ static inline pmd_t set_pmd_bit(pmd_t pmd, pgprot_t prot)
        return pmd;
 }
 
-static inline pte_t pte_wrprotect(pte_t pte)
-{
-       pte = clear_pte_bit(pte, __pgprot(PTE_WRITE));
-       pte = set_pte_bit(pte, __pgprot(PTE_RDONLY));
-       return pte;
-}
-
 static inline pte_t pte_mkwrite(pte_t pte)
 {
        pte = set_pte_bit(pte, __pgprot(PTE_WRITE));
@@ -196,6 +190,20 @@ static inline pte_t pte_mkdirty(pte_t pte)
        return pte;
 }
 
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+       /*
+        * If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY
+        * clear), set the PTE_DIRTY bit.
+        */
+       if (pte_hw_dirty(pte))
+               pte = pte_mkdirty(pte);
+
+       pte = clear_pte_bit(pte, __pgprot(PTE_WRITE));
+       pte = set_pte_bit(pte, __pgprot(PTE_RDONLY));
+       return pte;
+}
+
 static inline pte_t pte_mkold(pte_t pte)
 {
        return clear_pte_bit(pte, __pgprot(PTE_AF));
@@ -845,12 +853,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
        pte = READ_ONCE(*ptep);
        do {
                old_pte = pte;
-               /*
-                * If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY
-                * clear), set the PTE_DIRTY bit.
-                */
-               if (pte_hw_dirty(pte))
-                       pte = pte_mkdirty(pte);
                pte = pte_wrprotect(pte);
                pte_val(pte) = cmpxchg_relaxed(&pte_val(*ptep),
                                               pte_val(old_pte), pte_val(pte));
index 4266262101fe48833b941639f7a0d8a0d16dd654..006946745352ef348d1d9f1525edf230abeee911 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _ARM_PROBES_H
 #define _ARM_PROBES_H
 
+#include <asm/insn.h>
+
 typedef u32 probe_opcode_t;
 typedef void (probes_handler_t) (u32 opcode, long addr, struct pt_regs *);
 
index 997cf8c8cd5269c9dceda96abb1511d35457ff25..28c85b87b8cd471da2b0c3c601578683c033b9eb 100644 (file)
@@ -193,6 +193,10 @@ struct pt_regs {
        /* Only valid when ARM64_HAS_IRQ_PRIO_MASKING is enabled. */
        u64 pmr_save;
        u64 stackframe[2];
+
+       /* Only valid for some EL1 exceptions. */
+       u64 lockdep_hardirqs;
+       u64 exit_rcu;
 };
 
 static inline bool in_syscall(struct pt_regs const *regs)
index d52c1b3ce5894e7ca51c298a5e6f726b8299d2a0..801861d054268a6aeefdda02c204ab2e5f37fec6 100644 (file)
 #define SYS_CONTEXTIDR_EL1             sys_reg(3, 0, 13, 0, 1)
 #define SYS_TPIDR_EL1                  sys_reg(3, 0, 13, 0, 4)
 
+#define SYS_SCXTNUM_EL1                        sys_reg(3, 0, 13, 0, 7)
+
 #define SYS_CNTKCTL_EL1                        sys_reg(3, 0, 14, 1, 0)
 
 #define SYS_CCSIDR_EL1                 sys_reg(3, 1, 0, 0, 0)
 #define SYS_TPIDR_EL0                  sys_reg(3, 3, 13, 0, 2)
 #define SYS_TPIDRRO_EL0                        sys_reg(3, 3, 13, 0, 3)
 
+#define SYS_SCXTNUM_EL0                        sys_reg(3, 3, 13, 0, 7)
+
 /* Definitions for system register interface to AMU for ARMv8.4 onwards */
 #define SYS_AM_EL0(crm, op2)           sys_reg(3, 3, 13, (crm), (op2))
 #define SYS_AMCR_EL0                   SYS_AM_EL0(2, 0)
 #define SYS_TFSR_EL1_TF0_SHIFT 0
 #define SYS_TFSR_EL1_TF1_SHIFT 1
 #define SYS_TFSR_EL1_TF0       (UL(1) << SYS_TFSR_EL1_TF0_SHIFT)
-#define SYS_TFSR_EL1_TF1       (UK(2) << SYS_TFSR_EL1_TF1_SHIFT)
+#define SYS_TFSR_EL1_TF1       (UL(1) << SYS_TFSR_EL1_TF1_SHIFT)
 
 /* Safe value for MPIDR_EL1: Bit31:RES1, Bit30:U:0, Bit24:MT:0 */
 #define SYS_MPIDR_SAFE_VAL     (BIT(31))
 
 #include <linux/build_bug.h>
 #include <linux/types.h>
+#include <asm/alternative.h>
 
 #define __DEFINE_MRS_MSR_S_REGNUM                              \
 "      .irp    num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30\n" \
                write_sysreg_s(__scs_new, sysreg);                      \
 } while (0)
 
+#define read_sysreg_par() ({                                           \
+       u64 par;                                                        \
+       asm(ALTERNATIVE("nop", "dmb sy", ARM64_WORKAROUND_1508412));    \
+       par = read_sysreg(par_el1);                                     \
+       asm(ALTERNATIVE("nop", "dmb sy", ARM64_WORKAROUND_1508412));    \
+       par;                                                            \
+})
+
 #endif
 
 #endif /* __ASM_SYSREG_H */
index 09977acc007d1562c53ad74c6d0da3d32558a1cd..6069be50baf9fba2d5a05c5e0893b08b2b6a03f8 100644 (file)
@@ -86,13 +86,12 @@ static inline bool is_kernel_in_hyp_mode(void)
 static __always_inline bool has_vhe(void)
 {
        /*
-        * The following macros are defined for code specic to VHE/nVHE.
-        * If has_vhe() is inlined into those compilation units, it can
-        * be determined statically. Otherwise fall back to caps.
+        * Code only run in VHE/NVHE hyp context can assume VHE is present or
+        * absent. Otherwise fall back to caps.
         */
-       if (__is_defined(__KVM_VHE_HYPERVISOR__))
+       if (is_vhe_hyp_code())
                return true;
-       else if (__is_defined(__KVM_NVHE_HYPERVISOR__))
+       else if (is_nvhe_hyp_code())
                return false;
        else
                return cpus_have_final_cap(ARM64_HAS_VIRT_HOST_EXTN);
index 24d75af344b1f6e1bfcffd3fcd40b2ff27c62944..cafaf0da05b7c74c5a406c5d0e07a789732cdafa 100644 (file)
@@ -299,6 +299,8 @@ static const struct midr_range erratum_845719_list[] = {
        MIDR_REV_RANGE(MIDR_CORTEX_A53, 0, 0, 4),
        /* Brahma-B53 r0p[0] */
        MIDR_REV(MIDR_BRAHMA_B53, 0, 0),
+       /* Kryo2XX Silver rAp4 */
+       MIDR_REV(MIDR_QCOM_KRYO_2XX_SILVER, 0xa, 0x4),
        {},
 };
 #endif
@@ -522,6 +524,16 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
                .matches = has_neoverse_n1_erratum_1542419,
                .cpu_enable = cpu_enable_trap_ctr_access,
        },
+#endif
+#ifdef CONFIG_ARM64_ERRATUM_1508412
+       {
+               /* we depend on the firmware portion for correctness */
+               .desc = "ARM erratum 1508412 (kernel portion)",
+               .capability = ARM64_WORKAROUND_1508412,
+               ERRATA_MIDR_RANGE(MIDR_CORTEX_A77,
+                                 0, 0,
+                                 1, 0),
+       },
 #endif
        {
        }
index dcc165b3fc046b8573a579f04dd3e71474c7c471..6f36c4f62f6945f1e74323b4987f4e2684445dcd 100644 (file)
@@ -1337,6 +1337,8 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
                MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
                MIDR_ALL_VERSIONS(MIDR_HISI_TSV110),
                MIDR_ALL_VERSIONS(MIDR_NVIDIA_CARMEL),
+               MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_2XX_GOLD),
+               MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_2XX_SILVER),
                MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_3XX_SILVER),
                MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_SILVER),
                { /* sentinel */ }
index 6a7bb3729d605dd50281794b9563010f71e50385..77605aec25fec843e6169c639b7f3b16392947d8 100644 (file)
@@ -34,10 +34,10 @@ DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
 static struct cpuinfo_arm64 boot_cpu_data;
 
 static const char *icache_policy_str[] = {
-       [0 ... ICACHE_POLICY_PIPT]      = "RESERVED/UNKNOWN",
+       [ICACHE_POLICY_VPIPT]           = "VPIPT",
+       [ICACHE_POLICY_RESERVED]        = "RESERVED/UNKNOWN",
        [ICACHE_POLICY_VIPT]            = "VIPT",
        [ICACHE_POLICY_PIPT]            = "PIPT",
-       [ICACHE_POLICY_VPIPT]           = "VPIPT",
 };
 
 unsigned long __icache_flags;
@@ -334,10 +334,11 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
        case ICACHE_POLICY_VPIPT:
                set_bit(ICACHEF_VPIPT, &__icache_flags);
                break;
-       default:
+       case ICACHE_POLICY_RESERVED:
        case ICACHE_POLICY_VIPT:
                /* Assume aliasing */
                set_bit(ICACHEF_ALIASING, &__icache_flags);
+               break;
        }
 
        pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
index df67c0f2a077efef312cb6ae53ff542b91f2e83f..a71844fb923eef9669bd23b087b752c214b8a763 100644 (file)
@@ -147,6 +147,6 @@ efi_debug_entry:
         * correctly at this alignment, we must ensure that .text is
         * placed at a 4k boundary in the Image to begin with.
         */
-       .align 12
+       .balign SEGMENT_ALIGN
 efi_header_end:
        .endm
index 43d4c329775f7e27cba10cb77ac8f3051246944f..70e0a7591245d6a1cc1ec07c3e13a3d8e10f95e7 100644 (file)
 #include <asm/mmu.h>
 #include <asm/sysreg.h>
 
-static void notrace el1_abort(struct pt_regs *regs, unsigned long esr)
+/*
+ * This is intended to match the logic in irqentry_enter(), handling the kernel
+ * mode transitions only.
+ */
+static void noinstr enter_from_kernel_mode(struct pt_regs *regs)
+{
+       regs->exit_rcu = false;
+
+       if (!IS_ENABLED(CONFIG_TINY_RCU) && is_idle_task(current)) {
+               lockdep_hardirqs_off(CALLER_ADDR0);
+               rcu_irq_enter();
+               trace_hardirqs_off_finish();
+
+               regs->exit_rcu = true;
+               return;
+       }
+
+       lockdep_hardirqs_off(CALLER_ADDR0);
+       rcu_irq_enter_check_tick();
+       trace_hardirqs_off_finish();
+}
+
+/*
+ * This is intended to match the logic in irqentry_exit(), handling the kernel
+ * mode transitions only, and with preemption handled elsewhere.
+ */
+static void noinstr exit_to_kernel_mode(struct pt_regs *regs)
+{
+       lockdep_assert_irqs_disabled();
+
+       if (interrupts_enabled(regs)) {
+               if (regs->exit_rcu) {
+                       trace_hardirqs_on_prepare();
+                       lockdep_hardirqs_on_prepare(CALLER_ADDR0);
+                       rcu_irq_exit();
+                       lockdep_hardirqs_on(CALLER_ADDR0);
+                       return;
+               }
+
+               trace_hardirqs_on();
+       } else {
+               if (regs->exit_rcu)
+                       rcu_irq_exit();
+       }
+}
+
+void noinstr arm64_enter_nmi(struct pt_regs *regs)
+{
+       regs->lockdep_hardirqs = lockdep_hardirqs_enabled();
+
+       __nmi_enter();
+       lockdep_hardirqs_off(CALLER_ADDR0);
+       lockdep_hardirq_enter();
+       rcu_nmi_enter();
+
+       trace_hardirqs_off_finish();
+       ftrace_nmi_enter();
+}
+
+void noinstr arm64_exit_nmi(struct pt_regs *regs)
+{
+       bool restore = regs->lockdep_hardirqs;
+
+       ftrace_nmi_exit();
+       if (restore) {
+               trace_hardirqs_on_prepare();
+               lockdep_hardirqs_on_prepare(CALLER_ADDR0);
+       }
+
+       rcu_nmi_exit();
+       lockdep_hardirq_exit();
+       if (restore)
+               lockdep_hardirqs_on(CALLER_ADDR0);
+       __nmi_exit();
+}
+
+asmlinkage void noinstr enter_el1_irq_or_nmi(struct pt_regs *regs)
+{
+       if (IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) && !interrupts_enabled(regs))
+               arm64_enter_nmi(regs);
+       else
+               enter_from_kernel_mode(regs);
+}
+
+asmlinkage void noinstr exit_el1_irq_or_nmi(struct pt_regs *regs)
+{
+       if (IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) && !interrupts_enabled(regs))
+               arm64_exit_nmi(regs);
+       else
+               exit_to_kernel_mode(regs);
+}
+
+static void noinstr el1_abort(struct pt_regs *regs, unsigned long esr)
 {
        unsigned long far = read_sysreg(far_el1);
 
+       enter_from_kernel_mode(regs);
        local_daif_inherit(regs);
        far = untagged_addr(far);
        do_mem_abort(far, esr, regs);
+       local_daif_mask();
+       exit_to_kernel_mode(regs);
 }
-NOKPROBE_SYMBOL(el1_abort);
 
-static void notrace el1_pc(struct pt_regs *regs, unsigned long esr)
+static void noinstr el1_pc(struct pt_regs *regs, unsigned long esr)
 {
        unsigned long far = read_sysreg(far_el1);
 
+       enter_from_kernel_mode(regs);
        local_daif_inherit(regs);
        do_sp_pc_abort(far, esr, regs);
+       local_daif_mask();
+       exit_to_kernel_mode(regs);
 }
-NOKPROBE_SYMBOL(el1_pc);
 
-static void notrace el1_undef(struct pt_regs *regs)
+static void noinstr el1_undef(struct pt_regs *regs)
 {
+       enter_from_kernel_mode(regs);
        local_daif_inherit(regs);
        do_undefinstr(regs);
+       local_daif_mask();
+       exit_to_kernel_mode(regs);
 }
-NOKPROBE_SYMBOL(el1_undef);
 
-static void notrace el1_inv(struct pt_regs *regs, unsigned long esr)
+static void noinstr el1_inv(struct pt_regs *regs, unsigned long esr)
 {
+       enter_from_kernel_mode(regs);
        local_daif_inherit(regs);
        bad_mode(regs, 0, esr);
+       local_daif_mask();
+       exit_to_kernel_mode(regs);
 }
-NOKPROBE_SYMBOL(el1_inv);
 
-static void notrace el1_dbg(struct pt_regs *regs, unsigned long esr)
+static void noinstr arm64_enter_el1_dbg(struct pt_regs *regs)
+{
+       regs->lockdep_hardirqs = lockdep_hardirqs_enabled();
+
+       lockdep_hardirqs_off(CALLER_ADDR0);
+       rcu_nmi_enter();
+
+       trace_hardirqs_off_finish();
+}
+
+static void noinstr arm64_exit_el1_dbg(struct pt_regs *regs)
+{
+       bool restore = regs->lockdep_hardirqs;
+
+       if (restore) {
+               trace_hardirqs_on_prepare();
+               lockdep_hardirqs_on_prepare(CALLER_ADDR0);
+       }
+
+       rcu_nmi_exit();
+       if (restore)
+               lockdep_hardirqs_on(CALLER_ADDR0);
+}
+
+static void noinstr el1_dbg(struct pt_regs *regs, unsigned long esr)
 {
        unsigned long far = read_sysreg(far_el1);
 
@@ -62,18 +186,21 @@ static void notrace el1_dbg(struct pt_regs *regs, unsigned long esr)
        if (system_uses_irq_prio_masking())
                gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
 
+       arm64_enter_el1_dbg(regs);
        do_debug_exception(far, esr, regs);
+       arm64_exit_el1_dbg(regs);
 }
-NOKPROBE_SYMBOL(el1_dbg);
 
-static void notrace el1_fpac(struct pt_regs *regs, unsigned long esr)
+static void noinstr el1_fpac(struct pt_regs *regs, unsigned long esr)
 {
+       enter_from_kernel_mode(regs);
        local_daif_inherit(regs);
        do_ptrauth_fault(regs, esr);
+       local_daif_mask();
+       exit_to_kernel_mode(regs);
 }
-NOKPROBE_SYMBOL(el1_fpac);
 
-asmlinkage void notrace el1_sync_handler(struct pt_regs *regs)
+asmlinkage void noinstr el1_sync_handler(struct pt_regs *regs)
 {
        unsigned long esr = read_sysreg(esr_el1);
 
@@ -106,20 +233,34 @@ asmlinkage void notrace el1_sync_handler(struct pt_regs *regs)
                el1_inv(regs, esr);
        }
 }
-NOKPROBE_SYMBOL(el1_sync_handler);
 
-static void notrace el0_da(struct pt_regs *regs, unsigned long esr)
+asmlinkage void noinstr enter_from_user_mode(void)
+{
+       lockdep_hardirqs_off(CALLER_ADDR0);
+       CT_WARN_ON(ct_state() != CONTEXT_USER);
+       user_exit_irqoff();
+       trace_hardirqs_off_finish();
+}
+
+asmlinkage void noinstr exit_to_user_mode(void)
+{
+       trace_hardirqs_on_prepare();
+       lockdep_hardirqs_on_prepare(CALLER_ADDR0);
+       user_enter_irqoff();
+       lockdep_hardirqs_on(CALLER_ADDR0);
+}
+
+static void noinstr el0_da(struct pt_regs *regs, unsigned long esr)
 {
        unsigned long far = read_sysreg(far_el1);
 
-       user_exit_irqoff();
+       enter_from_user_mode();
        local_daif_restore(DAIF_PROCCTX);
        far = untagged_addr(far);
        do_mem_abort(far, esr, regs);
 }
-NOKPROBE_SYMBOL(el0_da);
 
-static void notrace el0_ia(struct pt_regs *regs, unsigned long esr)
+static void noinstr el0_ia(struct pt_regs *regs, unsigned long esr)
 {
        unsigned long far = read_sysreg(far_el1);
 
@@ -131,90 +272,80 @@ static void notrace el0_ia(struct pt_regs *regs, unsigned long esr)
        if (!is_ttbr0_addr(far))
                arm64_apply_bp_hardening();
 
-       user_exit_irqoff();
+       enter_from_user_mode();
        local_daif_restore(DAIF_PROCCTX);
        do_mem_abort(far, esr, regs);
 }
-NOKPROBE_SYMBOL(el0_ia);
 
-static void notrace el0_fpsimd_acc(struct pt_regs *regs, unsigned long esr)
+static void noinstr el0_fpsimd_acc(struct pt_regs *regs, unsigned long esr)
 {
-       user_exit_irqoff();
+       enter_from_user_mode();
        local_daif_restore(DAIF_PROCCTX);
        do_fpsimd_acc(esr, regs);
 }
-NOKPROBE_SYMBOL(el0_fpsimd_acc);
 
-static void notrace el0_sve_acc(struct pt_regs *regs, unsigned long esr)
+static void noinstr el0_sve_acc(struct pt_regs *regs, unsigned long esr)
 {
-       user_exit_irqoff();
+       enter_from_user_mode();
        local_daif_restore(DAIF_PROCCTX);
        do_sve_acc(esr, regs);
 }
-NOKPROBE_SYMBOL(el0_sve_acc);
 
-static void notrace el0_fpsimd_exc(struct pt_regs *regs, unsigned long esr)
+static void noinstr el0_fpsimd_exc(struct pt_regs *regs, unsigned long esr)
 {
-       user_exit_irqoff();
+       enter_from_user_mode();
        local_daif_restore(DAIF_PROCCTX);
        do_fpsimd_exc(esr, regs);
 }
-NOKPROBE_SYMBOL(el0_fpsimd_exc);
 
-static void notrace el0_sys(struct pt_regs *regs, unsigned long esr)
+static void noinstr el0_sys(struct pt_regs *regs, unsigned long esr)
 {
-       user_exit_irqoff();
+       enter_from_user_mode();
        local_daif_restore(DAIF_PROCCTX);
        do_sysinstr(esr, regs);
 }
-NOKPROBE_SYMBOL(el0_sys);
 
-static void notrace el0_pc(struct pt_regs *regs, unsigned long esr)
+static void noinstr el0_pc(struct pt_regs *regs, unsigned long esr)
 {
        unsigned long far = read_sysreg(far_el1);
 
        if (!is_ttbr0_addr(instruction_pointer(regs)))
                arm64_apply_bp_hardening();
 
-       user_exit_irqoff();
+       enter_from_user_mode();
        local_daif_restore(DAIF_PROCCTX);
        do_sp_pc_abort(far, esr, regs);
 }
-NOKPROBE_SYMBOL(el0_pc);
 
-static void notrace el0_sp(struct pt_regs *regs, unsigned long esr)
+static void noinstr el0_sp(struct pt_regs *regs, unsigned long esr)
 {
-       user_exit_irqoff();
+       enter_from_user_mode();
        local_daif_restore(DAIF_PROCCTX);
        do_sp_pc_abort(regs->sp, esr, regs);
 }
-NOKPROBE_SYMBOL(el0_sp);
 
-static void notrace el0_undef(struct pt_regs *regs)
+static void noinstr el0_undef(struct pt_regs *regs)
 {
-       user_exit_irqoff();
+       enter_from_user_mode();
        local_daif_restore(DAIF_PROCCTX);
        do_undefinstr(regs);
 }
-NOKPROBE_SYMBOL(el0_undef);
 
-static void notrace el0_bti(struct pt_regs *regs)
+static void noinstr el0_bti(struct pt_regs *regs)
 {
-       user_exit_irqoff();
+       enter_from_user_mode();
        local_daif_restore(DAIF_PROCCTX);
        do_bti(regs);
 }
-NOKPROBE_SYMBOL(el0_bti);
 
-static void notrace el0_inv(struct pt_regs *regs, unsigned long esr)
+static void noinstr el0_inv(struct pt_regs *regs, unsigned long esr)
 {
-       user_exit_irqoff();
+       enter_from_user_mode();
        local_daif_restore(DAIF_PROCCTX);
        bad_el0_sync(regs, 0, esr);
 }
-NOKPROBE_SYMBOL(el0_inv);
 
-static void notrace el0_dbg(struct pt_regs *regs, unsigned long esr)
+static void noinstr el0_dbg(struct pt_regs *regs, unsigned long esr)
 {
        /* Only watchpoints write FAR_EL1, otherwise its UNKNOWN */
        unsigned long far = read_sysreg(far_el1);
@@ -222,30 +353,28 @@ static void notrace el0_dbg(struct pt_regs *regs, unsigned long esr)
        if (system_uses_irq_prio_masking())
                gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
 
-       user_exit_irqoff();
+       enter_from_user_mode();
        do_debug_exception(far, esr, regs);
        local_daif_restore(DAIF_PROCCTX_NOIRQ);
 }
-NOKPROBE_SYMBOL(el0_dbg);
 
-static void notrace el0_svc(struct pt_regs *regs)
+static void noinstr el0_svc(struct pt_regs *regs)
 {
        if (system_uses_irq_prio_masking())
                gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
 
+       enter_from_user_mode();
        do_el0_svc(regs);
 }
-NOKPROBE_SYMBOL(el0_svc);
 
-static void notrace el0_fpac(struct pt_regs *regs, unsigned long esr)
+static void noinstr el0_fpac(struct pt_regs *regs, unsigned long esr)
 {
-       user_exit_irqoff();
+       enter_from_user_mode();
        local_daif_restore(DAIF_PROCCTX);
        do_ptrauth_fault(regs, esr);
 }
-NOKPROBE_SYMBOL(el0_fpac);
 
-asmlinkage void notrace el0_sync_handler(struct pt_regs *regs)
+asmlinkage void noinstr el0_sync_handler(struct pt_regs *regs)
 {
        unsigned long esr = read_sysreg(esr_el1);
 
@@ -297,27 +426,25 @@ asmlinkage void notrace el0_sync_handler(struct pt_regs *regs)
                el0_inv(regs, esr);
        }
 }
-NOKPROBE_SYMBOL(el0_sync_handler);
 
 #ifdef CONFIG_COMPAT
-static void notrace el0_cp15(struct pt_regs *regs, unsigned long esr)
+static void noinstr el0_cp15(struct pt_regs *regs, unsigned long esr)
 {
-       user_exit_irqoff();
+       enter_from_user_mode();
        local_daif_restore(DAIF_PROCCTX);
        do_cp15instr(esr, regs);
 }
-NOKPROBE_SYMBOL(el0_cp15);
 
-static void notrace el0_svc_compat(struct pt_regs *regs)
+static void noinstr el0_svc_compat(struct pt_regs *regs)
 {
        if (system_uses_irq_prio_masking())
                gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
 
+       enter_from_user_mode();
        do_el0_svc_compat(regs);
 }
-NOKPROBE_SYMBOL(el0_svc_compat);
 
-asmlinkage void notrace el0_sync_compat_handler(struct pt_regs *regs)
+asmlinkage void noinstr el0_sync_compat_handler(struct pt_regs *regs)
 {
        unsigned long esr = read_sysreg(esr_el1);
 
@@ -360,5 +487,4 @@ asmlinkage void notrace el0_sync_compat_handler(struct pt_regs *regs)
                el0_inv(regs, esr);
        }
 }
-NOKPROBE_SYMBOL(el0_sync_compat_handler);
 #endif /* CONFIG_COMPAT */
index f30007dff35f7eb89eb8aa5e7e8eb34fa75f009e..d72c818b019ca7530569fd810f356ad426f0cdf1 100644 (file)
 #include <asm/unistd.h>
 
 /*
- * Context tracking subsystem.  Used to instrument transitions
- * between user and kernel mode.
+ * Context tracking and irqflag tracing need to instrument transitions between
+ * user and kernel mode.
  */
-       .macro ct_user_exit_irqoff
-#ifdef CONFIG_CONTEXT_TRACKING
+       .macro user_exit_irqoff
+#if defined(CONFIG_CONTEXT_TRACKING) || defined(CONFIG_TRACE_IRQFLAGS)
        bl      enter_from_user_mode
 #endif
        .endm
 
-       .macro ct_user_enter
-#ifdef CONFIG_CONTEXT_TRACKING
-       bl      context_tracking_user_enter
+       .macro user_enter_irqoff
+#if defined(CONFIG_CONTEXT_TRACKING) || defined(CONFIG_TRACE_IRQFLAGS)
+       bl      exit_to_user_mode
 #endif
        .endm
 
@@ -298,9 +298,6 @@ alternative_if ARM64_HAS_IRQ_PRIO_MASKING
 alternative_else_nop_endif
 
        ldp     x21, x22, [sp, #S_PC]           // load ELR, SPSR
-       .if     \el == 0
-       ct_user_enter
-       .endif
 
 #ifdef CONFIG_ARM64_SW_TTBR0_PAN
 alternative_if_not ARM64_HAS_PAN
@@ -365,6 +362,9 @@ alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
        br      x30
 #endif
        .else
+       /* Ensure any device/NC reads complete */
+       alternative_insn nop, "dmb sy", ARM64_WORKAROUND_1508412
+
        eret
        .endif
        sb
@@ -634,16 +634,8 @@ SYM_CODE_START_LOCAL_NOALIGN(el1_irq)
        gic_prio_irq_setup pmr=x20, tmp=x1
        enable_da_f
 
-#ifdef CONFIG_ARM64_PSEUDO_NMI
-       test_irqs_unmasked      res=x0, pmr=x20
-       cbz     x0, 1f
-       bl      asm_nmi_enter
-1:
-#endif
-
-#ifdef CONFIG_TRACE_IRQFLAGS
-       bl      trace_hardirqs_off
-#endif
+       mov     x0, sp
+       bl      enter_el1_irq_or_nmi
 
        irq_handler
 
@@ -662,26 +654,8 @@ alternative_else_nop_endif
 1:
 #endif
 
-#ifdef CONFIG_ARM64_PSEUDO_NMI
-       /*
-        * When using IRQ priority masking, we can get spurious interrupts while
-        * PMR is set to GIC_PRIO_IRQOFF. An NMI might also have occurred in a
-        * section with interrupts disabled. Skip tracing in those cases.
-        */
-       test_irqs_unmasked      res=x0, pmr=x20
-       cbz     x0, 1f
-       bl      asm_nmi_exit
-1:
-#endif
-
-#ifdef CONFIG_TRACE_IRQFLAGS
-#ifdef CONFIG_ARM64_PSEUDO_NMI
-       test_irqs_unmasked      res=x0, pmr=x20
-       cbnz    x0, 1f
-#endif
-       bl      trace_hardirqs_on
-1:
-#endif
+       mov     x0, sp
+       bl      exit_el1_irq_or_nmi
 
        kernel_exit 1
 SYM_CODE_END(el1_irq)
@@ -723,21 +697,14 @@ SYM_CODE_START_LOCAL_NOALIGN(el0_irq)
        kernel_entry 0
 el0_irq_naked:
        gic_prio_irq_setup pmr=x20, tmp=x0
-       ct_user_exit_irqoff
+       user_exit_irqoff
        enable_da_f
 
-#ifdef CONFIG_TRACE_IRQFLAGS
-       bl      trace_hardirqs_off
-#endif
-
        tbz     x22, #55, 1f
        bl      do_el0_irq_bp_hardening
 1:
        irq_handler
 
-#ifdef CONFIG_TRACE_IRQFLAGS
-       bl      trace_hardirqs_on
-#endif
        b       ret_to_user
 SYM_CODE_END(el0_irq)
 
@@ -756,7 +723,7 @@ SYM_CODE_START_LOCAL(el0_error)
 el0_error_naked:
        mrs     x25, esr_el1
        gic_prio_kentry_setup tmp=x2
-       ct_user_exit_irqoff
+       user_exit_irqoff
        enable_dbg
        mov     x0, sp
        mov     x1, x25
@@ -771,13 +738,17 @@ SYM_CODE_END(el0_error)
 SYM_CODE_START_LOCAL(ret_to_user)
        disable_daif
        gic_prio_kentry_setup tmp=x3
-       ldr     x1, [tsk, #TSK_TI_FLAGS]
-       and     x2, x1, #_TIF_WORK_MASK
+#ifdef CONFIG_TRACE_IRQFLAGS
+       bl      trace_hardirqs_off
+#endif
+       ldr     x19, [tsk, #TSK_TI_FLAGS]
+       and     x2, x19, #_TIF_WORK_MASK
        cbnz    x2, work_pending
 finish_ret_to_user:
+       user_enter_irqoff
        /* Ignore asynchronous tag check faults in the uaccess routines */
        clear_mte_async_tcf
-       enable_step_tsk x1, x2
+       enable_step_tsk x19, x2
 #ifdef CONFIG_GCC_PLUGIN_STACKLEAK
        bl      stackleak_erase
 #endif
@@ -788,11 +759,9 @@ finish_ret_to_user:
  */
 work_pending:
        mov     x0, sp                          // 'regs'
+       mov     x1, x19
        bl      do_notify_resume
-#ifdef CONFIG_TRACE_IRQFLAGS
-       bl      trace_hardirqs_on               // enabled while in userspace
-#endif
-       ldr     x1, [tsk, #TSK_TI_FLAGS]        // re-check for single-step
+       ldr     x19, [tsk, #TSK_TI_FLAGS]       // re-check for single-step
        b       finish_ret_to_user
 SYM_CODE_END(ret_to_user)
 
index 61684a5009148d245d1b8b4e9526f20cad9963b4..c615b285ff5b332bf25eea2dff882100c0066dd0 100644 (file)
@@ -87,7 +87,6 @@ KVM_NVHE_ALIAS(__icache_flags);
 /* Kernel symbols needed for cpus_have_final/const_caps checks. */
 KVM_NVHE_ALIAS(arm64_const_caps_ready);
 KVM_NVHE_ALIAS(cpu_hwcap_keys);
-KVM_NVHE_ALIAS(cpu_hwcaps);
 
 /* Static keys which are set if a vGIC trap should be handled in hyp. */
 KVM_NVHE_ALIAS(vgic_v2_cpuif_trap);
index 9cf2fb87584aed83d64c1c38468c1dd9ea8a2e67..60456a62da11660f3e4316e097501eddadcd7542 100644 (file)
@@ -67,18 +67,3 @@ void __init init_IRQ(void)
                local_daif_restore(DAIF_PROCCTX_NOIRQ);
        }
 }
-
-/*
- * Stubs to make nmi_enter/exit() code callable from ASM
- */
-asmlinkage void notrace asm_nmi_enter(void)
-{
-       nmi_enter();
-}
-NOKPROBE_SYMBOL(asm_nmi_enter);
-
-asmlinkage void notrace asm_nmi_exit(void)
-{
-       nmi_exit();
-}
-NOKPROBE_SYMBOL(asm_nmi_exit);
index af9987c154cabdf284330727e322959c03a30815..9ec34690e25518853e02e8c0c8cd4e137e95622b 100644 (file)
@@ -43,7 +43,7 @@ static void *image_load(struct kimage *image,
        u64 flags, value;
        bool be_image, be_kernel;
        struct kexec_buf kbuf;
-       unsigned long text_offset;
+       unsigned long text_offset, kernel_segment_number;
        struct kexec_segment *kernel_segment;
        int ret;
 
@@ -88,11 +88,37 @@ static void *image_load(struct kimage *image,
        /* Adjust kernel segment with TEXT_OFFSET */
        kbuf.memsz += text_offset;
 
-       ret = kexec_add_buffer(&kbuf);
-       if (ret)
+       kernel_segment_number = image->nr_segments;
+
+       /*
+        * The location of the kernel segment may make it impossible to satisfy
+        * the other segment requirements, so we try repeatedly to find a
+        * location that will work.
+        */
+       while ((ret = kexec_add_buffer(&kbuf)) == 0) {
+               /* Try to load additional data */
+               kernel_segment = &image->segment[kernel_segment_number];
+               ret = load_other_segments(image, kernel_segment->mem,
+                                         kernel_segment->memsz, initrd,
+                                         initrd_len, cmdline);
+               if (!ret)
+                       break;
+
+               /*
+                * We couldn't find space for the other segments; erase the
+                * kernel segment and try the next available hole.
+                */
+               image->nr_segments -= 1;
+               kbuf.buf_min = kernel_segment->mem + kernel_segment->memsz;
+               kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
+       }
+
+       if (ret) {
+               pr_err("Could not find any suitable kernel location!");
                return ERR_PTR(ret);
+       }
 
-       kernel_segment = &image->segment[image->nr_segments - 1];
+       kernel_segment = &image->segment[kernel_segment_number];
        kernel_segment->mem += text_offset;
        kernel_segment->memsz -= text_offset;
        image->start = kernel_segment->mem;
@@ -101,12 +127,7 @@ static void *image_load(struct kimage *image,
                                kernel_segment->mem, kbuf.bufsz,
                                kernel_segment->memsz);
 
-       /* Load additional data */
-       ret = load_other_segments(image,
-                               kernel_segment->mem, kernel_segment->memsz,
-                               initrd, initrd_len, cmdline);
-
-       return ERR_PTR(ret);
+       return NULL;
 }
 
 #ifdef CONFIG_KEXEC_IMAGE_VERIFY_SIG
index 5b0e67b93cdcda8c839e7b52fccdff04c3151d10..03210f64479000152e2b2a60a25cb0914da8c64b 100644 (file)
@@ -240,6 +240,11 @@ static int prepare_elf_headers(void **addr, unsigned long *sz)
        return ret;
 }
 
+/*
+ * Tries to add the initrd and DTB to the image. If it is not possible to find
+ * valid locations, this function will undo changes to the image and return non
+ * zero.
+ */
 int load_other_segments(struct kimage *image,
                        unsigned long kernel_load_addr,
                        unsigned long kernel_size,
@@ -248,7 +253,8 @@ int load_other_segments(struct kimage *image,
 {
        struct kexec_buf kbuf;
        void *headers, *dtb = NULL;
-       unsigned long headers_sz, initrd_load_addr = 0, dtb_len;
+       unsigned long headers_sz, initrd_load_addr = 0, dtb_len,
+                     orig_segments = image->nr_segments;
        int ret = 0;
 
        kbuf.image = image;
@@ -334,6 +340,7 @@ int load_other_segments(struct kimage *image,
        return 0;
 
 out_err:
+       image->nr_segments = orig_segments;
        vfree(dtb);
        return ret;
 }
index 94e8718e722900fa7208e42ec08ee686864ea4bc..f6f58e6265df89d8c1ce7a49ff052728cbdb9c8c 100644 (file)
@@ -73,8 +73,7 @@ u64 perf_reg_abi(struct task_struct *task)
 }
 
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
        regs_user->regs = task_pt_regs(current);
        regs_user->abi = perf_reg_abi(current);
index deba738142ede174a60f9810aeba01ca9b45a15e..f11a1a1f702614b1ae54438fe51b8adae4bd69ee 100644 (file)
@@ -36,25 +36,16 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 static void __kprobes
 post_kprobe_handler(struct kprobe_ctlblk *, struct pt_regs *);
 
-static int __kprobes patch_text(kprobe_opcode_t *addr, u32 opcode)
-{
-       void *addrs[1];
-       u32 insns[1];
-
-       addrs[0] = addr;
-       insns[0] = opcode;
-
-       return aarch64_insn_patch_text(addrs, insns, 1);
-}
-
 static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
 {
+       kprobe_opcode_t *addr = p->ainsn.api.insn;
+       void *addrs[] = {addr, addr + 1};
+       u32 insns[] = {p->opcode, BRK64_OPCODE_KPROBES_SS};
+
        /* prepare insn slot */
-       patch_text(p->ainsn.api.insn, p->opcode);
+       aarch64_insn_patch_text(addrs, insns, 2);
 
-       flush_icache_range((uintptr_t) (p->ainsn.api.insn),
-                          (uintptr_t) (p->ainsn.api.insn) +
-                          MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+       flush_icache_range((uintptr_t)addr, (uintptr_t)(addr + MAX_INSN_SIZE));
 
        /*
         * Needs restoring of return address after stepping xol.
@@ -128,13 +119,18 @@ void *alloc_insn_page(void)
 /* arm kprobe: install breakpoint in text */
 void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
-       patch_text(p->addr, BRK64_OPCODE_KPROBES);
+       void *addr = p->addr;
+       u32 insn = BRK64_OPCODE_KPROBES;
+
+       aarch64_insn_patch_text(&addr, &insn, 1);
 }
 
 /* disarm kprobe: remove breakpoint from text */
 void __kprobes arch_disarm_kprobe(struct kprobe *p)
 {
-       patch_text(p->addr, p->opcode);
+       void *addr = p->addr;
+
+       aarch64_insn_patch_text(&addr, &p->opcode, 1);
 }
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
@@ -163,20 +159,15 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
 }
 
 /*
- * Interrupts need to be disabled before single-step mode is set, and not
- * reenabled until after single-step mode ends.
- * Without disabling interrupt on local CPU, there is a chance of
- * interrupt occurrence in the period of exception return and  start of
- * out-of-line single-step, that result in wrongly single stepping
- * into the interrupt handler.
+ * Mask all of DAIF while executing the instruction out-of-line, to keep things
+ * simple and avoid nesting exceptions. Interrupts do have to be disabled since
+ * the kprobe state is per-CPU and doesn't get migrated.
  */
 static void __kprobes kprobes_save_local_irqflag(struct kprobe_ctlblk *kcb,
                                                struct pt_regs *regs)
 {
        kcb->saved_irqflag = regs->pstate & DAIF_MASK;
-       regs->pstate |= PSR_I_BIT;
-       /* Unmask PSTATE.D for enabling software step exceptions. */
-       regs->pstate &= ~PSR_D_BIT;
+       regs->pstate |= DAIF_MASK;
 }
 
 static void __kprobes kprobes_restore_local_irqflag(struct kprobe_ctlblk *kcb,
@@ -219,10 +210,7 @@ static void __kprobes setup_singlestep(struct kprobe *p,
                slot = (unsigned long)p->ainsn.api.insn;
 
                set_ss_context(kcb, slot);      /* mark pending ss */
-
-               /* IRQs and single stepping do not mix well. */
                kprobes_save_local_irqflag(kcb, regs);
-               kernel_enable_single_step(regs);
                instruction_pointer_set(regs, slot);
        } else {
                /* insn simulation */
@@ -273,12 +261,8 @@ post_kprobe_handler(struct kprobe_ctlblk *kcb, struct pt_regs *regs)
        }
        /* call post handler */
        kcb->kprobe_status = KPROBE_HIT_SSDONE;
-       if (cur->post_handler)  {
-               /* post_handler can hit breakpoint and single step
-                * again, so we enable D-flag for recursive exception.
-                */
+       if (cur->post_handler)
                cur->post_handler(cur, regs, 0);
-       }
 
        reset_current_kprobe();
 }
@@ -302,8 +286,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
                if (!instruction_pointer(regs))
                        BUG();
 
-               kernel_disable_single_step();
-
                if (kcb->kprobe_status == KPROBE_REENTER)
                        restore_previous_kprobe(kcb);
                else
@@ -365,10 +347,6 @@ static void __kprobes kprobe_handler(struct pt_regs *regs)
                         * pre-handler and it returned non-zero, it will
                         * modify the execution path and no need to single
                         * stepping. Let's just reset current kprobe and exit.
-                        *
-                        * pre_handler can hit a breakpoint and can step thru
-                        * before return, keep PSTATE D-flag enabled until
-                        * pre_handler return back.
                         */
                        if (!p->pre_handler || !p->pre_handler(p, regs)) {
                                setup_singlestep(p, regs, kcb, 0);
@@ -399,7 +377,7 @@ kprobe_ss_hit(struct kprobe_ctlblk *kcb, unsigned long addr)
 }
 
 static int __kprobes
-kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr)
+kprobe_breakpoint_ss_handler(struct pt_regs *regs, unsigned int esr)
 {
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
        int retval;
@@ -409,16 +387,15 @@ kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr)
 
        if (retval == DBG_HOOK_HANDLED) {
                kprobes_restore_local_irqflag(kcb, regs);
-               kernel_disable_single_step();
-
                post_kprobe_handler(kcb, regs);
        }
 
        return retval;
 }
 
-static struct step_hook kprobes_step_hook = {
-       .fn = kprobe_single_step_handler,
+static struct break_hook kprobes_break_ss_hook = {
+       .imm = KPROBES_BRK_SS_IMM,
+       .fn = kprobe_breakpoint_ss_handler,
 };
 
 static int __kprobes
@@ -486,7 +463,7 @@ int __kprobes arch_trampoline_kprobe(struct kprobe *p)
 int __init arch_init_kprobes(void)
 {
        register_kernel_break_hook(&kprobes_break_hook);
-       register_kernel_step_hook(&kprobes_step_hook);
+       register_kernel_break_hook(&kprobes_break_ss_hook);
 
        return 0;
 }
index 4784011cecac976f42725a8a22bfa1c5af678907..ed919f633ed8ec1eb326525c7da8830485ee2eb7 100644 (file)
@@ -72,13 +72,13 @@ EXPORT_SYMBOL_GPL(pm_power_off);
 
 void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
 
-static void __cpu_do_idle(void)
+static void noinstr __cpu_do_idle(void)
 {
        dsb(sy);
        wfi();
 }
 
-static void __cpu_do_idle_irqprio(void)
+static void noinstr __cpu_do_idle_irqprio(void)
 {
        unsigned long pmr;
        unsigned long daif_bits;
@@ -108,7 +108,7 @@ static void __cpu_do_idle_irqprio(void)
  *     ensure that interrupts are not masked at the PMR (because the core will
  *     not wake up if we block the wake up signal in the interrupt controller).
  */
-void cpu_do_idle(void)
+void noinstr cpu_do_idle(void)
 {
        if (system_uses_irq_prio_masking())
                __cpu_do_idle_irqprio();
@@ -119,14 +119,14 @@ void cpu_do_idle(void)
 /*
  * This is our default idle handler.
  */
-void arch_cpu_idle(void)
+void noinstr arch_cpu_idle(void)
 {
        /*
         * This should do all the clock switching and wait for interrupt
         * tricks
         */
        cpu_do_idle();
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -522,14 +522,13 @@ static void erratum_1418040_thread_switch(struct task_struct *prev,
        bool prev32, next32;
        u64 val;
 
-       if (!(IS_ENABLED(CONFIG_ARM64_ERRATUM_1418040) &&
-             cpus_have_const_cap(ARM64_WORKAROUND_1418040)))
+       if (!IS_ENABLED(CONFIG_ARM64_ERRATUM_1418040))
                return;
 
        prev32 = is_compat_thread(task_thread_info(prev));
        next32 = is_compat_thread(task_thread_info(next));
 
-       if (prev32 == next32)
+       if (prev32 == next32 || !this_cpu_has_cap(ARM64_WORKAROUND_1418040))
                return;
 
        val = read_sysreg(cntkctl_el1);
index 25f3c80b5ffe454782c646b4fe5fa7e5681a87e6..f6e4e3737405dea81ba0f21faa90050b1750e71a 100644 (file)
@@ -118,6 +118,7 @@ static enum mitigation_state spectre_v2_get_cpu_hw_mitigation_state(void)
                MIDR_ALL_VERSIONS(MIDR_CORTEX_A55),
                MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53),
                MIDR_ALL_VERSIONS(MIDR_HISI_TSV110),
+               MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_2XX_SILVER),
                MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_3XX_SILVER),
                MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_SILVER),
                { /* sentinel */ }
@@ -135,8 +136,6 @@ static enum mitigation_state spectre_v2_get_cpu_hw_mitigation_state(void)
        return SPECTRE_VULNERABLE;
 }
 
-#define SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED   (1)
-
 static enum mitigation_state spectre_v2_get_cpu_fw_mitigation_state(void)
 {
        int ret;
index 43ae4e0c968f66f44503ae59807ef356eac4217a..62d2bda7adb807010439282fc956e63a5d269095 100644 (file)
@@ -66,7 +66,6 @@ static int cpu_psci_cpu_disable(unsigned int cpu)
 
 static void cpu_psci_cpu_die(unsigned int cpu)
 {
-       int ret;
        /*
         * There are no known implementations of PSCI actually using the
         * power state field, pass a sensible default for now.
@@ -74,9 +73,7 @@ static void cpu_psci_cpu_die(unsigned int cpu)
        u32 state = PSCI_POWER_STATE_TYPE_POWER_DOWN <<
                    PSCI_0_2_POWER_STATE_TYPE_SHIFT;
 
-       ret = psci_ops.cpu_off(state);
-
-       pr_crit("unable to power off CPU%u (%d)\n", cpu, ret);
+       psci_ops.cpu_off(state);
 }
 
 static int cpu_psci_cpu_kill(unsigned int cpu)
index 7689f2031c0c41701de66c516fa6773fcec8ead6..793c46d6a44791c11eee1600956ec3f35c54050f 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/uaccess.h>
 
 #include <asm/alternative.h>
+#include <asm/exception.h>
 #include <asm/kprobes.h>
 #include <asm/mmu.h>
 #include <asm/ptrace.h>
@@ -223,16 +224,16 @@ static __kprobes unsigned long _sdei_handler(struct pt_regs *regs,
 }
 
 
-asmlinkage __kprobes notrace unsigned long
+asmlinkage noinstr unsigned long
 __sdei_handler(struct pt_regs *regs, struct sdei_registered_event *arg)
 {
        unsigned long ret;
 
-       nmi_enter();
+       arm64_enter_nmi(regs);
 
        ret = _sdei_handler(regs, arg);
 
-       nmi_exit();
+       arm64_exit_nmi(regs);
 
        return ret;
 }
index 82e75fc2c903f7fe330200f6e0793480dd05ba7f..18e9727d3f64502a4ec763495b850c9ebd105f0a 100644 (file)
@@ -222,6 +222,7 @@ asmlinkage notrace void secondary_start_kernel(void)
        if (system_uses_irq_prio_masking())
                init_gic_priority_masking();
 
+       rcu_cpu_starting(cpu);
        preempt_disable();
        trace_hardirqs_off();
 
@@ -412,6 +413,7 @@ void cpu_die_early(void)
 
        /* Mark this CPU absent */
        set_cpu_present(cpu, 0);
+       rcu_report_dead(cpu);
 
        if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) {
                update_cpu_boot_status(CPU_KILL_ME);
index e4c0dadf0d92c8fa71ebe055780dc4f08764a2d6..f8f758e4a3064e961a8b3d74cb6535574ecaa561 100644 (file)
@@ -121,7 +121,6 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
 
        cortex_a76_erratum_1463225_svc_handler();
        local_daif_restore(DAIF_PROCCTX);
-       user_exit();
 
        if (system_supports_mte() && (flags & _TIF_MTE_ASYNC_FAULT)) {
                /*
index 8af4e0e8573666e8f3bf68930ad412b189bfd04f..2059d8f43f55f05d9bd93ca3515043f4ae0dcf44 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/daifflags.h>
 #include <asm/debug-monitors.h>
 #include <asm/esr.h>
+#include <asm/exception.h>
 #include <asm/extable.h>
 #include <asm/insn.h>
 #include <asm/kprobes.h>
@@ -753,8 +754,10 @@ const char *esr_get_class_string(u32 esr)
  * bad_mode handles the impossible case in the exception vector. This is always
  * fatal.
  */
-asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
+asmlinkage void notrace bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
 {
+       arm64_enter_nmi(regs);
+
        console_verbose();
 
        pr_crit("Bad mode in %s handler detected on CPU%d, code 0x%08x -- %s\n",
@@ -786,7 +789,7 @@ void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
 DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack)
        __aligned(16);
 
-asmlinkage void handle_bad_stack(struct pt_regs *regs)
+asmlinkage void noinstr handle_bad_stack(struct pt_regs *regs)
 {
        unsigned long tsk_stk = (unsigned long)current->stack;
        unsigned long irq_stk = (unsigned long)this_cpu_read(irq_stack_ptr);
@@ -794,6 +797,8 @@ asmlinkage void handle_bad_stack(struct pt_regs *regs)
        unsigned int esr = read_sysreg(esr_el1);
        unsigned long far = read_sysreg(far_el1);
 
+       arm64_enter_nmi(regs);
+
        console_verbose();
        pr_emerg("Insufficient stack space to handle exception!");
 
@@ -865,23 +870,16 @@ bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr)
        }
 }
 
-asmlinkage void do_serror(struct pt_regs *regs, unsigned int esr)
+asmlinkage void noinstr do_serror(struct pt_regs *regs, unsigned int esr)
 {
-       nmi_enter();
+       arm64_enter_nmi(regs);
 
        /* non-RAS errors are not containable */
        if (!arm64_is_ras_serror(esr) || arm64_is_fatal_ras_serror(regs, esr))
                arm64_serror_panic(regs, esr);
 
-       nmi_exit();
-}
-
-asmlinkage void enter_from_user_mode(void)
-{
-       CT_WARN_ON(ct_state() != CONTEXT_USER);
-       user_exit_irqoff();
+       arm64_exit_nmi(regs);
 }
-NOKPROBE_SYMBOL(enter_from_user_mode);
 
 /* GENERIC_BUG traps */
 
index 7f96a1a9f68c49a89dca13b8e8329113032c6c13..79280c53b9a616953eead419df59948c5f7e13a5 100644 (file)
@@ -22,16 +22,21 @@ endif
 
 CC_COMPAT ?= $(CC)
 CC_COMPAT += $(CC_COMPAT_CLANG_FLAGS)
+
+ifneq ($(LLVM),)
+LD_COMPAT ?= $(LD)
+else
+LD_COMPAT ?= $(CROSS_COMPILE_COMPAT)ld
+endif
 else
 CC_COMPAT ?= $(CROSS_COMPILE_COMPAT)gcc
+LD_COMPAT ?= $(CROSS_COMPILE_COMPAT)ld
 endif
 
 cc32-option = $(call try-run,\
         $(CC_COMPAT) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
 cc32-disable-warning = $(call try-run,\
        $(CC_COMPAT) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
-cc32-ldoption = $(call try-run,\
-        $(CC_COMPAT) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2))
 cc32-as-instr = $(call try-run,\
        printf "%b\n" "$(1)" | $(CC_COMPAT) $(VDSO_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3))
 
@@ -122,14 +127,10 @@ dmbinstr := $(call cc32-as-instr,dmb ishld,-DCONFIG_AS_DMB_ISHLD=1)
 VDSO_CFLAGS += $(dmbinstr)
 VDSO_AFLAGS += $(dmbinstr)
 
-VDSO_LDFLAGS := $(VDSO_CPPFLAGS)
 # From arm vDSO Makefile
-VDSO_LDFLAGS += -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1
-VDSO_LDFLAGS += -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
-VDSO_LDFLAGS += -nostdlib -shared -mfloat-abi=soft
-VDSO_LDFLAGS += -Wl,--hash-style=sysv
-VDSO_LDFLAGS += -Wl,--build-id=sha1
-VDSO_LDFLAGS += $(call cc32-ldoption,-fuse-ld=bfd)
+VDSO_LDFLAGS += -Bsymbolic --no-undefined -soname=linux-vdso.so.1
+VDSO_LDFLAGS += -z max-page-size=4096 -z common-page-size=4096
+VDSO_LDFLAGS += -nostdlib -shared --hash-style=sysv --build-id=sha1
 
 
 # Borrow vdsomunge.c from the arm vDSO
@@ -189,8 +190,8 @@ quiet_cmd_vdsold_and_vdso_check = LD32    $@
       cmd_vdsold_and_vdso_check = $(cmd_vdsold); $(cmd_vdso_check)
 
 quiet_cmd_vdsold = LD32    $@
-      cmd_vdsold = $(CC_COMPAT) -Wp,-MD,$(depfile) $(VDSO_LDFLAGS) \
-                   -Wl,-T $(filter %.lds,$^) $(filter %.o,$^) -o $@
+      cmd_vdsold = $(LD_COMPAT) $(VDSO_LDFLAGS) \
+                   -T $(filter %.lds,$^) $(filter %.o,$^) -o $@
 quiet_cmd_vdsocc = CC32    $@
       cmd_vdsocc = $(CC_COMPAT) -Wp,-MD,$(depfile) $(VDSO_CFLAGS) -c -o $@ $<
 quiet_cmd_vdsocc_gettimeofday = CC32    $@
index 6d78c041fdf691b91786c0152534a84d5f46f1a6..1bda604f4c704bd22f810c02fcacd60d720c43e4 100644 (file)
@@ -278,7 +278,7 @@ SECTIONS
         * explicitly check instead of blindly discarding.
         */
        .plt : {
-               *(.plt) *(.plt.*) *(.iplt) *(.igot)
+               *(.plt) *(.plt.*) *(.iplt) *(.igot .igot.plt)
        }
        ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!")
 
index f56122eedffc84866395218d6006c47037b061a5..c0ffb019ca8be1132a56ad7747b4ea85bdf9a98b 100644 (file)
@@ -102,6 +102,20 @@ static int kvm_arm_default_max_vcpus(void)
        return vgic_present ? kvm_vgic_get_max_vcpus() : KVM_MAX_VCPUS;
 }
 
+static void set_default_csv2(struct kvm *kvm)
+{
+       /*
+        * The default is to expose CSV2 == 1 if the HW isn't affected.
+        * Although this is a per-CPU feature, we make it global because
+        * asymmetric systems are just a nuisance.
+        *
+        * Userspace can override this as long as it doesn't promise
+        * the impossible.
+        */
+       if (arm64_get_spectre_v2_state() == SPECTRE_UNAFFECTED)
+               kvm->arch.pfr0_csv2 = 1;
+}
+
 /**
  * kvm_arch_init_vm - initializes a VM data structure
  * @kvm:       pointer to the KVM struct
@@ -127,6 +141,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        /* The maximum number of VCPUs is limited by the host's GIC model */
        kvm->arch.max_vcpus = kvm_arm_default_max_vcpus();
 
+       set_default_csv2(kvm);
+
        return ret;
 out_free_stage2_pgd:
        kvm_free_stage2_pgd(&kvm->arch.mmu);
@@ -808,6 +824,25 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
 
                preempt_enable();
 
+               /*
+                * The ARMv8 architecture doesn't give the hypervisor
+                * a mechanism to prevent a guest from dropping to AArch32 EL0
+                * if implemented by the CPU. If we spot the guest in such
+                * state and that we decided it wasn't supposed to do so (like
+                * with the asymmetric AArch32 case), return to userspace with
+                * a fatal error.
+                */
+               if (!system_supports_32bit_el0() && vcpu_mode_is_32bit(vcpu)) {
+                       /*
+                        * As we have caught the guest red-handed, decide that
+                        * it isn't fit for purpose anymore by making the vcpu
+                        * invalid. The VMM can try and fix it by issuing  a
+                        * KVM_ARM_VCPU_INIT if it really wants to.
+                        */
+                       vcpu->arch.target = -1;
+                       ret = ARM_EXCEPTION_IL;
+               }
+
                ret = handle_exit(vcpu, ret);
        }
 
@@ -1719,7 +1754,8 @@ int kvm_arch_init(void *opaque)
                return -ENODEV;
        }
 
-       if (cpus_have_final_cap(ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE))
+       if (cpus_have_final_cap(ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) ||
+           cpus_have_final_cap(ARM64_WORKAROUND_1508412))
                kvm_info("Guests without required CPU erratum workarounds can deadlock system!\n" \
                         "Only trusted guests should be used on this system.\n");
 
index 313a8fa3c721d66eb22867b2d2eb8d0359b5e988..1f875a8f20c47b3751bdaa618a5e0c26fec7db03 100644 (file)
@@ -140,9 +140,9 @@ static inline bool __translate_far_to_hpfar(u64 far, u64 *hpfar)
         * We do need to save/restore PAR_EL1 though, as we haven't
         * saved the guest context yet, and we may return early...
         */
-       par = read_sysreg(par_el1);
+       par = read_sysreg_par();
        if (!__kvm_at("s1e1r", far))
-               tmp = read_sysreg(par_el1);
+               tmp = read_sysreg_par();
        else
                tmp = SYS_PAR_EL1_F; /* back to the guest */
        write_sysreg(par, par_el1);
@@ -421,7 +421,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
        if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) &&
            kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_SYS64 &&
            handle_tx2_tvm(vcpu))
-               return true;
+               goto guest;
 
        /*
         * We trap the first access to the FP/SIMD to save the host context
@@ -431,13 +431,13 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
         * Similarly for trapped SVE accesses.
         */
        if (__hyp_handle_fpsimd(vcpu))
-               return true;
+               goto guest;
 
        if (__hyp_handle_ptrauth(vcpu))
-               return true;
+               goto guest;
 
        if (!__populate_fault_info(vcpu))
-               return true;
+               goto guest;
 
        if (static_branch_unlikely(&vgic_v2_cpuif_trap)) {
                bool valid;
@@ -452,7 +452,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
                        int ret = __vgic_v2_perform_cpuif_access(vcpu);
 
                        if (ret == 1)
-                               return true;
+                               goto guest;
 
                        /* Promote an illegal access to an SError.*/
                        if (ret == -1)
@@ -468,12 +468,17 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
                int ret = __vgic_v3_perform_cpuif_access(vcpu);
 
                if (ret == 1)
-                       return true;
+                       goto guest;
        }
 
 exit:
        /* Return to the host kernel and handle the exit */
        return false;
+
+guest:
+       /* Re-enter the guest */
+       asm(ALTERNATIVE("nop", "dmb sy", ARM64_WORKAROUND_1508412));
+       return true;
 }
 
 static inline void __kvm_unexpected_el2_exception(void)
index 7a986030145f8c80b53942d8ad2c9ee7be09def9..cce43bfe158fa3a887fa35c725ff61e569c659ee 100644 (file)
@@ -43,7 +43,7 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt)
        ctxt_sys_reg(ctxt, CONTEXTIDR_EL1) = read_sysreg_el1(SYS_CONTEXTIDR);
        ctxt_sys_reg(ctxt, AMAIR_EL1)   = read_sysreg_el1(SYS_AMAIR);
        ctxt_sys_reg(ctxt, CNTKCTL_EL1) = read_sysreg_el1(SYS_CNTKCTL);
-       ctxt_sys_reg(ctxt, PAR_EL1)     = read_sysreg(par_el1);
+       ctxt_sys_reg(ctxt, PAR_EL1)     = read_sysreg_par();
        ctxt_sys_reg(ctxt, TPIDR_EL1)   = read_sysreg(tpidr_el1);
 
        ctxt_sys_reg(ctxt, SP_EL1)      = read_sysreg(sp_el1);
index ff9a0f547b9f0ea78ccd87ff289772b3fdb4db0d..ed27f06a31ba2bbb46db322525cc3bdb55e3f916 100644 (file)
@@ -17,8 +17,6 @@ SYM_FUNC_START(__host_exit)
 
        get_host_ctxt   x0, x1
 
-       ALTERNATIVE(nop, SET_PSTATE_PAN(1), ARM64_HAS_PAN, CONFIG_ARM64_PAN)
-
        /* Store the host regs x2 and x3 */
        stp     x2, x3,   [x0, #CPU_XREG_OFFSET(2)]
 
index 47224dc62c51f5c9df1061ecf49665ea6cbc6e72..b11a9d7db677db887f306d4f801a2bdb37cdcb1d 100644 (file)
@@ -57,16 +57,25 @@ __do_hyp_init:
        cmp     x0, #HVC_STUB_HCALL_NR
        b.lo    __kvm_handle_stub_hvc
 
-       /* Set tpidr_el2 for use by HYP to free a register */
-       msr     tpidr_el2, x2
-
-       mov     x2, #KVM_HOST_SMCCC_FUNC(__kvm_hyp_init)
-       cmp     x0, x2
-       b.eq    1f
+       // We only actively check bits [24:31], and everything
+       // else has to be zero, which we check at build time.
+#if (KVM_HOST_SMCCC_FUNC(__kvm_hyp_init) & 0xFFFFFFFF00FFFFFF)
+#error Unexpected __KVM_HOST_SMCCC_FUNC___kvm_hyp_init value
+#endif
+
+       ror     x0, x0, #24
+       eor     x0, x0, #((KVM_HOST_SMCCC_FUNC(__kvm_hyp_init) >> 24) & 0xF)
+       ror     x0, x0, #4
+       eor     x0, x0, #((KVM_HOST_SMCCC_FUNC(__kvm_hyp_init) >> 28) & 0xF)
+       cbz     x0, 1f
        mov     x0, #SMCCC_RET_NOT_SUPPORTED
        eret
 
-1:     phys_to_ttbr x0, x1
+1:
+       /* Set tpidr_el2 for use by HYP to free a register */
+       msr     tpidr_el2, x2
+
+       phys_to_ttbr x0, x1
 alternative_if ARM64_HAS_CNP
        orr     x0, x0, #TTBR_CNP_BIT
 alternative_else_nop_endif
index bb2d986ff6962bbcb0b0bc31e0194487cb82d9e1..a797abace13f01f26563e3b48d325f6d98c7b545 100644 (file)
 
 SECTIONS {
        HYP_SECTION(.text)
+       /*
+        * .hyp..data..percpu needs to be page aligned to maintain the same
+        * alignment for when linking into vmlinux.
+        */
+       . = ALIGN(PAGE_SIZE);
        HYP_SECTION_NAME(.data..percpu) : {
                PERCPU_INPUT(L1_CACHE_BYTES)
        }
index a457a0306e031fbd3ecf5993f8a14173dfddff8e..8ae8160bc93ab87216429b4f6d4ca3901c6c0fa9 100644 (file)
@@ -250,7 +250,7 @@ void __noreturn hyp_panic(void)
 {
        u64 spsr = read_sysreg_el2(SYS_SPSR);
        u64 elr = read_sysreg_el2(SYS_ELR);
-       u64 par = read_sysreg(par_el1);
+       u64 par = read_sysreg_par();
        bool restore_host = true;
        struct kvm_cpu_context *host_ctxt;
        struct kvm_vcpu *vcpu;
index 39ca71ab88664755d4a0ef8774ec19971035cea7..fbde89a2c6e838d0ad9cbcb9029130b789bf2360 100644 (file)
@@ -128,7 +128,6 @@ void __kvm_tlb_flush_local_vmid(struct kvm_s2_mmu *mmu)
        struct tlb_inv_context cxt;
 
        /* Switch to requested VMID */
-       mmu = kern_hyp_va(mmu);
        __tlb_switch_to_guest(mmu, &cxt);
 
        __tlbi(vmalle1);
index 0cdf6e461cbd257df4932a40ad23da04385fb47c..0271b4a3b9fe183aba1d075f7fda832b52723ff3 100644 (file)
@@ -635,7 +635,7 @@ static void stage2_flush_dcache(void *addr, u64 size)
 
 static bool stage2_pte_cacheable(kvm_pte_t pte)
 {
-       u64 memattr = FIELD_GET(KVM_PTE_LEAF_ATTR_LO_S2_MEMATTR, pte);
+       u64 memattr = pte & KVM_PTE_LEAF_ATTR_LO_S2_MEMATTR;
        return memattr == PAGE_S2_MEMATTR(NORMAL);
 }
 
@@ -846,7 +846,7 @@ int kvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm *kvm)
        u32 start_level = VTCR_EL2_TGRAN_SL0_BASE - sl0;
 
        pgd_sz = kvm_pgd_pages(ia_bits, start_level) * PAGE_SIZE;
-       pgt->pgd = alloc_pages_exact(pgd_sz, GFP_KERNEL | __GFP_ZERO);
+       pgt->pgd = alloc_pages_exact(pgd_sz, GFP_KERNEL_ACCOUNT | __GFP_ZERO);
        if (!pgt->pgd)
                return -ENOMEM;
 
index fe69de16dadc698030954c5d5a60b237b1b201a8..62546e20b25115ecac7a3c00f932cf8e8a60ad17 100644 (file)
@@ -215,7 +215,7 @@ void __noreturn hyp_panic(void)
 {
        u64 spsr = read_sysreg_el2(SYS_SPSR);
        u64 elr = read_sysreg_el2(SYS_ELR);
-       u64 par = read_sysreg(par_el1);
+       u64 par = read_sysreg_par();
 
        __hyp_call_panic(spsr, elr, par);
        unreachable();
index 9824025ccc5c047067f9456c1860606a1afaeb7c..25ea4ecb6449fb3c6475af75723092a815d1059d 100644 (file)
@@ -31,7 +31,7 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
                                val = SMCCC_RET_SUCCESS;
                                break;
                        case SPECTRE_UNAFFECTED:
-                               val = SMCCC_RET_NOT_REQUIRED;
+                               val = SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED;
                                break;
                        }
                        break;
index 19aacc7d64deaf42f3c9bf774c5c920af8f0566c..1a01da9fdc99cd11a9912c31e4893d94cf070cb4 100644 (file)
@@ -787,14 +787,28 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                vma_shift = PAGE_SHIFT;
        }
 
-       if (vma_shift == PUD_SHIFT &&
-           !fault_supports_stage2_huge_mapping(memslot, hva, PUD_SIZE))
-              vma_shift = PMD_SHIFT;
-
-       if (vma_shift == PMD_SHIFT &&
-           !fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE)) {
-               force_pte = true;
+       switch (vma_shift) {
+#ifndef __PAGETABLE_PMD_FOLDED
+       case PUD_SHIFT:
+               if (fault_supports_stage2_huge_mapping(memslot, hva, PUD_SIZE))
+                       break;
+               fallthrough;
+#endif
+       case CONT_PMD_SHIFT:
+               vma_shift = PMD_SHIFT;
+               fallthrough;
+       case PMD_SHIFT:
+               if (fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE))
+                       break;
+               fallthrough;
+       case CONT_PTE_SHIFT:
                vma_shift = PAGE_SHIFT;
+               force_pte = true;
+               fallthrough;
+       case PAGE_SHIFT:
+               break;
+       default:
+               WARN_ONCE(1, "Unknown vma_shift %d", vma_shift);
        }
 
        vma_pagesize = 1UL << vma_shift;
@@ -839,6 +853,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 
        if (kvm_is_device_pfn(pfn)) {
                device = true;
+               force_pte = true;
        } else if (logging_active && !write_fault) {
                /*
                 * Only actually map the page as writable if this was a write
index d9117bc5623720fe0c1d380b0c44686f63b95c07..c1fac9836af1af88723a2f4432096ee88c36e7c8 100644 (file)
@@ -95,7 +95,7 @@ static bool __vcpu_read_sys_reg_from_cpu(int reg, u64 *val)
        case AMAIR_EL1:         *val = read_sysreg_s(SYS_AMAIR_EL12);   break;
        case CNTKCTL_EL1:       *val = read_sysreg_s(SYS_CNTKCTL_EL12); break;
        case ELR_EL1:           *val = read_sysreg_s(SYS_ELR_EL12);     break;
-       case PAR_EL1:           *val = read_sysreg_s(SYS_PAR_EL1);      break;
+       case PAR_EL1:           *val = read_sysreg_par();               break;
        case DACR32_EL2:        *val = read_sysreg_s(SYS_DACR32_EL2);   break;
        case IFSR32_EL2:        *val = read_sysreg_s(SYS_IFSR32_EL2);   break;
        case DBGVCR32_EL2:      *val = read_sysreg_s(SYS_DBGVCR32_EL2); break;
@@ -1038,8 +1038,8 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
        { SYS_DESC(SYS_PMEVTYPERn_EL0(n)),                                      \
          access_pmu_evtyper, reset_unknown, (PMEVTYPER0_EL0 + n), }
 
-static bool access_amu(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
-                            const struct sys_reg_desc *r)
+static bool undef_access(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+                        const struct sys_reg_desc *r)
 {
        kvm_inject_undefined(vcpu);
 
@@ -1047,33 +1047,25 @@ static bool access_amu(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 }
 
 /* Macro to expand the AMU counter and type registers*/
-#define AMU_AMEVCNTR0_EL0(n) { SYS_DESC(SYS_AMEVCNTR0_EL0(n)), access_amu }
-#define AMU_AMEVTYPER0_EL0(n) { SYS_DESC(SYS_AMEVTYPER0_EL0(n)), access_amu }
-#define AMU_AMEVCNTR1_EL0(n) { SYS_DESC(SYS_AMEVCNTR1_EL0(n)), access_amu }
-#define AMU_AMEVTYPER1_EL0(n) { SYS_DESC(SYS_AMEVTYPER1_EL0(n)), access_amu }
-
-static bool trap_ptrauth(struct kvm_vcpu *vcpu,
-                        struct sys_reg_params *p,
-                        const struct sys_reg_desc *rd)
-{
-       /*
-        * If we land here, that is because we didn't fixup the access on exit
-        * by allowing the PtrAuth sysregs. The only way this happens is when
-        * the guest does not have PtrAuth support enabled.
-        */
-       kvm_inject_undefined(vcpu);
-
-       return false;
-}
+#define AMU_AMEVCNTR0_EL0(n) { SYS_DESC(SYS_AMEVCNTR0_EL0(n)), undef_access }
+#define AMU_AMEVTYPER0_EL0(n) { SYS_DESC(SYS_AMEVTYPER0_EL0(n)), undef_access }
+#define AMU_AMEVCNTR1_EL0(n) { SYS_DESC(SYS_AMEVCNTR1_EL0(n)), undef_access }
+#define AMU_AMEVTYPER1_EL0(n) { SYS_DESC(SYS_AMEVTYPER1_EL0(n)), undef_access }
 
 static unsigned int ptrauth_visibility(const struct kvm_vcpu *vcpu,
                        const struct sys_reg_desc *rd)
 {
-       return vcpu_has_ptrauth(vcpu) ? 0 : REG_HIDDEN_USER | REG_HIDDEN_GUEST;
+       return vcpu_has_ptrauth(vcpu) ? 0 : REG_HIDDEN;
 }
 
+/*
+ * If we land here on a PtrAuth access, that is because we didn't
+ * fixup the access on exit by allowing the PtrAuth sysregs. The only
+ * way this happens is when the guest does not have PtrAuth support
+ * enabled.
+ */
 #define __PTRAUTH_KEY(k)                                               \
-       { SYS_DESC(SYS_## k), trap_ptrauth, reset_unknown, k,           \
+       { SYS_DESC(SYS_## k), undef_access, reset_unknown, k,           \
        .visibility = ptrauth_visibility}
 
 #define PTRAUTH_KEY(k)                                                 \
@@ -1128,9 +1120,8 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu,
                if (!vcpu_has_sve(vcpu))
                        val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
                val &= ~(0xfUL << ID_AA64PFR0_AMU_SHIFT);
-               if (!(val & (0xfUL << ID_AA64PFR0_CSV2_SHIFT)) &&
-                   arm64_get_spectre_v2_state() == SPECTRE_UNAFFECTED)
-                       val |= (1UL << ID_AA64PFR0_CSV2_SHIFT);
+               val &= ~(0xfUL << ID_AA64PFR0_CSV2_SHIFT);
+               val |= ((u64)vcpu->kvm->arch.pfr0_csv2 << ID_AA64PFR0_CSV2_SHIFT);
        } else if (id == SYS_ID_AA64PFR1_EL1) {
                val &= ~(0xfUL << ID_AA64PFR1_MTE_SHIFT);
        } else if (id == SYS_ID_AA64ISAR1_EL1 && !vcpu_has_ptrauth(vcpu)) {
@@ -1153,6 +1144,22 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu,
        return val;
 }
 
+static unsigned int id_visibility(const struct kvm_vcpu *vcpu,
+                                 const struct sys_reg_desc *r)
+{
+       u32 id = sys_reg((u32)r->Op0, (u32)r->Op1,
+                        (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);
+
+       switch (id) {
+       case SYS_ID_AA64ZFR0_EL1:
+               if (!vcpu_has_sve(vcpu))
+                       return REG_RAZ;
+               break;
+       }
+
+       return 0;
+}
+
 /* cpufeature ID register access trap handlers */
 
 static bool __access_id_reg(struct kvm_vcpu *vcpu,
@@ -1171,7 +1178,9 @@ static bool access_id_reg(struct kvm_vcpu *vcpu,
                          struct sys_reg_params *p,
                          const struct sys_reg_desc *r)
 {
-       return __access_id_reg(vcpu, p, r, false);
+       bool raz = sysreg_visible_as_raz(vcpu, r);
+
+       return __access_id_reg(vcpu, p, r, raz);
 }
 
 static bool access_raz_id_reg(struct kvm_vcpu *vcpu,
@@ -1192,71 +1201,40 @@ static unsigned int sve_visibility(const struct kvm_vcpu *vcpu,
        if (vcpu_has_sve(vcpu))
                return 0;
 
-       return REG_HIDDEN_USER | REG_HIDDEN_GUEST;
-}
-
-/* Visibility overrides for SVE-specific ID registers */
-static unsigned int sve_id_visibility(const struct kvm_vcpu *vcpu,
-                                     const struct sys_reg_desc *rd)
-{
-       if (vcpu_has_sve(vcpu))
-               return 0;
-
-       return REG_HIDDEN_USER;
+       return REG_HIDDEN;
 }
 
-/* Generate the emulated ID_AA64ZFR0_EL1 value exposed to the guest */
-static u64 guest_id_aa64zfr0_el1(const struct kvm_vcpu *vcpu)
-{
-       if (!vcpu_has_sve(vcpu))
-               return 0;
-
-       return read_sanitised_ftr_reg(SYS_ID_AA64ZFR0_EL1);
-}
-
-static bool access_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
-                                  struct sys_reg_params *p,
-                                  const struct sys_reg_desc *rd)
-{
-       if (p->is_write)
-               return write_to_read_only(vcpu, p, rd);
-
-       p->regval = guest_id_aa64zfr0_el1(vcpu);
-       return true;
-}
-
-static int get_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
-               const struct sys_reg_desc *rd,
-               const struct kvm_one_reg *reg, void __user *uaddr)
-{
-       u64 val;
-
-       if (WARN_ON(!vcpu_has_sve(vcpu)))
-               return -ENOENT;
-
-       val = guest_id_aa64zfr0_el1(vcpu);
-       return reg_to_user(uaddr, &val, reg->id);
-}
-
-static int set_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
-               const struct sys_reg_desc *rd,
-               const struct kvm_one_reg *reg, void __user *uaddr)
+static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
+                              const struct sys_reg_desc *rd,
+                              const struct kvm_one_reg *reg, void __user *uaddr)
 {
        const u64 id = sys_reg_to_index(rd);
        int err;
        u64 val;
-
-       if (WARN_ON(!vcpu_has_sve(vcpu)))
-               return -ENOENT;
+       u8 csv2;
 
        err = reg_from_user(&val, uaddr, id);
        if (err)
                return err;
 
-       /* This is what we mean by invariant: you can't change it. */
-       if (val != guest_id_aa64zfr0_el1(vcpu))
+       /*
+        * Allow AA64PFR0_EL1.CSV2 to be set from userspace as long as
+        * it doesn't promise more than what is actually provided (the
+        * guest could otherwise be covered in ectoplasmic residue).
+        */
+       csv2 = cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_CSV2_SHIFT);
+       if (csv2 > 1 ||
+           (csv2 && arm64_get_spectre_v2_state() != SPECTRE_UNAFFECTED))
                return -EINVAL;
 
+       /* We can only differ with CSV2, and anything else is an error */
+       val ^= read_id_reg(vcpu, rd, false);
+       val &= ~(0xFUL << ID_AA64PFR0_CSV2_SHIFT);
+       if (val)
+               return -EINVAL;
+
+       vcpu->kvm->arch.pfr0_csv2 = csv2;
+
        return 0;
 }
 
@@ -1299,13 +1277,17 @@ static int __set_id_reg(const struct kvm_vcpu *vcpu,
 static int get_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
                      const struct kvm_one_reg *reg, void __user *uaddr)
 {
-       return __get_id_reg(vcpu, rd, uaddr, false);
+       bool raz = sysreg_visible_as_raz(vcpu, rd);
+
+       return __get_id_reg(vcpu, rd, uaddr, raz);
 }
 
 static int set_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
                      const struct kvm_one_reg *reg, void __user *uaddr)
 {
-       return __set_id_reg(vcpu, rd, uaddr, false);
+       bool raz = sysreg_visible_as_raz(vcpu, rd);
+
+       return __set_id_reg(vcpu, rd, uaddr, raz);
 }
 
 static int get_raz_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
@@ -1384,19 +1366,13 @@ static bool access_ccsidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
        return true;
 }
 
-static bool access_mte_regs(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
-                           const struct sys_reg_desc *r)
-{
-       kvm_inject_undefined(vcpu);
-       return false;
-}
-
 /* sys_reg_desc initialiser for known cpufeature ID registers */
 #define ID_SANITISED(name) {                   \
        SYS_DESC(SYS_##name),                   \
        .access = access_id_reg,                \
        .get_user = get_id_reg,                 \
        .set_user = set_id_reg,                 \
+       .visibility = id_visibility,            \
 }
 
 /*
@@ -1514,11 +1490,12 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 
        /* AArch64 ID registers */
        /* CRm=4 */
-       ID_SANITISED(ID_AA64PFR0_EL1),
+       { SYS_DESC(SYS_ID_AA64PFR0_EL1), .access = access_id_reg,
+         .get_user = get_id_reg, .set_user = set_id_aa64pfr0_el1, },
        ID_SANITISED(ID_AA64PFR1_EL1),
        ID_UNALLOCATED(4,2),
        ID_UNALLOCATED(4,3),
-       { SYS_DESC(SYS_ID_AA64ZFR0_EL1), access_id_aa64zfr0_el1, .get_user = get_id_aa64zfr0_el1, .set_user = set_id_aa64zfr0_el1, .visibility = sve_id_visibility },
+       ID_SANITISED(ID_AA64ZFR0_EL1),
        ID_UNALLOCATED(4,5),
        ID_UNALLOCATED(4,6),
        ID_UNALLOCATED(4,7),
@@ -1557,8 +1534,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_ACTLR_EL1), access_actlr, reset_actlr, ACTLR_EL1 },
        { SYS_DESC(SYS_CPACR_EL1), NULL, reset_val, CPACR_EL1, 0 },
 
-       { SYS_DESC(SYS_RGSR_EL1), access_mte_regs },
-       { SYS_DESC(SYS_GCR_EL1), access_mte_regs },
+       { SYS_DESC(SYS_RGSR_EL1), undef_access },
+       { SYS_DESC(SYS_GCR_EL1), undef_access },
 
        { SYS_DESC(SYS_ZCR_EL1), NULL, reset_val, ZCR_EL1, 0, .visibility = sve_visibility },
        { SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 },
@@ -1584,8 +1561,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_ERXMISC0_EL1), trap_raz_wi },
        { SYS_DESC(SYS_ERXMISC1_EL1), trap_raz_wi },
 
-       { SYS_DESC(SYS_TFSR_EL1), access_mte_regs },
-       { SYS_DESC(SYS_TFSRE0_EL1), access_mte_regs },
+       { SYS_DESC(SYS_TFSR_EL1), undef_access },
+       { SYS_DESC(SYS_TFSRE0_EL1), undef_access },
 
        { SYS_DESC(SYS_FAR_EL1), access_vm_reg, reset_unknown, FAR_EL1 },
        { SYS_DESC(SYS_PAR_EL1), NULL, reset_unknown, PAR_EL1 },
@@ -1621,6 +1598,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_CONTEXTIDR_EL1), access_vm_reg, reset_val, CONTEXTIDR_EL1, 0 },
        { SYS_DESC(SYS_TPIDR_EL1), NULL, reset_unknown, TPIDR_EL1 },
 
+       { SYS_DESC(SYS_SCXTNUM_EL1), undef_access },
+
        { SYS_DESC(SYS_CNTKCTL_EL1), NULL, reset_val, CNTKCTL_EL1, 0},
 
        { SYS_DESC(SYS_CCSIDR_EL1), access_ccsidr },
@@ -1649,14 +1628,16 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_TPIDR_EL0), NULL, reset_unknown, TPIDR_EL0 },
        { SYS_DESC(SYS_TPIDRRO_EL0), NULL, reset_unknown, TPIDRRO_EL0 },
 
-       { SYS_DESC(SYS_AMCR_EL0), access_amu },
-       { SYS_DESC(SYS_AMCFGR_EL0), access_amu },
-       { SYS_DESC(SYS_AMCGCR_EL0), access_amu },
-       { SYS_DESC(SYS_AMUSERENR_EL0), access_amu },
-       { SYS_DESC(SYS_AMCNTENCLR0_EL0), access_amu },
-       { SYS_DESC(SYS_AMCNTENSET0_EL0), access_amu },
-       { SYS_DESC(SYS_AMCNTENCLR1_EL0), access_amu },
-       { SYS_DESC(SYS_AMCNTENSET1_EL0), access_amu },
+       { SYS_DESC(SYS_SCXTNUM_EL0), undef_access },
+
+       { SYS_DESC(SYS_AMCR_EL0), undef_access },
+       { SYS_DESC(SYS_AMCFGR_EL0), undef_access },
+       { SYS_DESC(SYS_AMCGCR_EL0), undef_access },
+       { SYS_DESC(SYS_AMUSERENR_EL0), undef_access },
+       { SYS_DESC(SYS_AMCNTENCLR0_EL0), undef_access },
+       { SYS_DESC(SYS_AMCNTENSET0_EL0), undef_access },
+       { SYS_DESC(SYS_AMCNTENCLR1_EL0), undef_access },
+       { SYS_DESC(SYS_AMCNTENSET1_EL0), undef_access },
        AMU_AMEVCNTR0_EL0(0),
        AMU_AMEVCNTR0_EL0(1),
        AMU_AMEVCNTR0_EL0(2),
@@ -1897,9 +1878,9 @@ static const struct sys_reg_desc cp14_regs[] = {
        { Op1( 0), CRn( 0), CRm( 1), Op2( 0), trap_raz_wi },
        DBG_BCR_BVR_WCR_WVR(1),
        /* DBGDCCINT */
-       { Op1( 0), CRn( 0), CRm( 2), Op2( 0), trap_debug32 },
+       { Op1( 0), CRn( 0), CRm( 2), Op2( 0), trap_debug32, NULL, cp14_DBGDCCINT },
        /* DBGDSCRext */
-       { Op1( 0), CRn( 0), CRm( 2), Op2( 2), trap_debug32 },
+       { Op1( 0), CRn( 0), CRm( 2), Op2( 2), trap_debug32, NULL, cp14_DBGDSCRext },
        DBG_BCR_BVR_WCR_WVR(2),
        /* DBGDTR[RT]Xint */
        { Op1( 0), CRn( 0), CRm( 3), Op2( 0), trap_raz_wi },
@@ -1914,7 +1895,7 @@ static const struct sys_reg_desc cp14_regs[] = {
        { Op1( 0), CRn( 0), CRm( 6), Op2( 2), trap_raz_wi },
        DBG_BCR_BVR_WCR_WVR(6),
        /* DBGVCR */
-       { Op1( 0), CRn( 0), CRm( 7), Op2( 0), trap_debug32 },
+       { Op1( 0), CRn( 0), CRm( 7), Op2( 0), trap_debug32, NULL, cp14_DBGVCR },
        DBG_BCR_BVR_WCR_WVR(7),
        DBG_BCR_BVR_WCR_WVR(8),
        DBG_BCR_BVR_WCR_WVR(9),
@@ -2185,7 +2166,7 @@ static void perform_access(struct kvm_vcpu *vcpu,
        trace_kvm_sys_access(*vcpu_pc(vcpu), params, r);
 
        /* Check for regs disabled by runtime config */
-       if (sysreg_hidden_from_guest(vcpu, r)) {
+       if (sysreg_hidden(vcpu, r)) {
                kvm_inject_undefined(vcpu);
                return;
        }
@@ -2684,7 +2665,7 @@ int kvm_arm_sys_reg_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg
                return get_invariant_sys_reg(reg->id, uaddr);
 
        /* Check for regs disabled by runtime config */
-       if (sysreg_hidden_from_user(vcpu, r))
+       if (sysreg_hidden(vcpu, r))
                return -ENOENT;
 
        if (r->get_user)
@@ -2709,7 +2690,7 @@ int kvm_arm_sys_reg_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg
                return set_invariant_sys_reg(reg->id, uaddr);
 
        /* Check for regs disabled by runtime config */
-       if (sysreg_hidden_from_user(vcpu, r))
+       if (sysreg_hidden(vcpu, r))
                return -ENOENT;
 
        if (r->set_user)
@@ -2780,7 +2761,7 @@ static int walk_one_sys_reg(const struct kvm_vcpu *vcpu,
        if (!(rd->reg || rd->get_user))
                return 0;
 
-       if (sysreg_hidden_from_user(vcpu, rd))
+       if (sysreg_hidden(vcpu, rd))
                return 0;
 
        if (!copy_reg_to_user(rd, uind))
index 5a6fc30f59894db482b667c20dd892baba0e6c7f..0f95964339b164518944d93bb062e2c0519ff28e 100644 (file)
@@ -59,8 +59,8 @@ struct sys_reg_desc {
                                   const struct sys_reg_desc *rd);
 };
 
-#define REG_HIDDEN_USER                (1 << 0) /* hidden from userspace ioctls */
-#define REG_HIDDEN_GUEST       (1 << 1) /* hidden from guest */
+#define REG_HIDDEN             (1 << 0) /* hidden from userspace and guest */
+#define REG_RAZ                        (1 << 1) /* RAZ from userspace and guest */
 
 static __printf(2, 3)
 inline void print_sys_reg_msg(const struct sys_reg_params *p,
@@ -111,22 +111,22 @@ static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r
        __vcpu_sys_reg(vcpu, r->reg) = r->val;
 }
 
-static inline bool sysreg_hidden_from_guest(const struct kvm_vcpu *vcpu,
-                                           const struct sys_reg_desc *r)
+static inline bool sysreg_hidden(const struct kvm_vcpu *vcpu,
+                                const struct sys_reg_desc *r)
 {
        if (likely(!r->visibility))
                return false;
 
-       return r->visibility(vcpu, r) & REG_HIDDEN_GUEST;
+       return r->visibility(vcpu, r) & REG_HIDDEN;
 }
 
-static inline bool sysreg_hidden_from_user(const struct kvm_vcpu *vcpu,
-                                          const struct sys_reg_desc *r)
+static inline bool sysreg_visible_as_raz(const struct kvm_vcpu *vcpu,
+                                        const struct sys_reg_desc *r)
 {
        if (likely(!r->visibility))
                return false;
 
-       return r->visibility(vcpu, r) & REG_HIDDEN_USER;
+       return r->visibility(vcpu, r) & REG_RAZ;
 }
 
 static inline int cmp_sys_reg(const struct sys_reg_desc *i1,
index 52d6f24f65dcf2ba571ae9a1a4e384e065b75c46..15a6c98ee92f05cdf35f19c5ed5cbd7a6738f699 100644 (file)
@@ -273,6 +273,23 @@ static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
        return extract_bytes(value, addr & 7, len);
 }
 
+static unsigned long vgic_uaccess_read_v3r_typer(struct kvm_vcpu *vcpu,
+                                                gpa_t addr, unsigned int len)
+{
+       unsigned long mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
+       int target_vcpu_id = vcpu->vcpu_id;
+       u64 value;
+
+       value = (u64)(mpidr & GENMASK(23, 0)) << 32;
+       value |= ((target_vcpu_id & 0xffff) << 8);
+
+       if (vgic_has_its(vcpu->kvm))
+               value |= GICR_TYPER_PLPIS;
+
+       /* reporting of the Last bit is not supported for userspace */
+       return extract_bytes(value, addr & 7, len);
+}
+
 static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu,
                                             gpa_t addr, unsigned int len)
 {
@@ -593,8 +610,9 @@ static const struct vgic_register_region vgic_v3_rd_registers[] = {
        REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
                vgic_mmio_read_v3r_iidr, vgic_mmio_write_wi, 4,
                VGIC_ACCESS_32bit),
-       REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
-               vgic_mmio_read_v3r_typer, vgic_mmio_write_wi, 8,
+       REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_TYPER,
+               vgic_mmio_read_v3r_typer, vgic_mmio_write_wi,
+               vgic_uaccess_read_v3r_typer, vgic_mmio_uaccess_write_wi, 8,
                VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_LENGTH(GICR_WAKER,
                vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
index e0bf83d556f23a48883562087d544a714dbe04ca..dc8d2a216a6e647e93972687207f212f3ddeb6b3 100644 (file)
@@ -56,9 +56,8 @@
        stp \reg1, \reg2, [\ptr], \val
        .endm
 
-       .weak memcpy
 SYM_FUNC_START_ALIAS(__memcpy)
-SYM_FUNC_START_PI(memcpy)
+SYM_FUNC_START_WEAK_PI(memcpy)
 #include "copy_template.S"
        ret
 SYM_FUNC_END_PI(memcpy)
index 02cda2e33bde292916830beca52c1d4ef271fd4a..1035dce4bdaf42572708d94412420ee4c37253fc 100644 (file)
@@ -45,9 +45,8 @@ C_h   .req    x12
 D_l    .req    x13
 D_h    .req    x14
 
-       .weak memmove
 SYM_FUNC_START_ALIAS(__memmove)
-SYM_FUNC_START_PI(memmove)
+SYM_FUNC_START_WEAK_PI(memmove)
        cmp     dstin, src
        b.lo    __memcpy
        add     tmp1, src, count
index 77c3c7ba008423389aff39923e81225fb4082426..a9c1c9a01ea906954953c6dce74d4c3e482328da 100644 (file)
@@ -42,9 +42,8 @@ dst           .req    x8
 tmp3w          .req    w9
 tmp3           .req    x9
 
-       .weak memset
 SYM_FUNC_START_ALIAS(__memset)
-SYM_FUNC_START_PI(memset)
+SYM_FUNC_START_WEAK_PI(memset)
        mov     dst, dstin      /* Preserve return value.  */
        and     A_lw, val, #255
        orr     A_lw, A_lw, A_lw, lsl #8
index 94c99c1c19e3fb6913f57115fa96814d94cfe291..795d224f184ff2ce63d8427f5e70d4a9a89fd4ef 100644 (file)
@@ -262,7 +262,7 @@ static bool __kprobes is_spurious_el1_translation_fault(unsigned long addr,
        local_irq_save(flags);
        asm volatile("at s1e1r, %0" :: "r" (addr));
        isb();
-       par = read_sysreg(par_el1);
+       par = read_sysreg_par();
        local_irq_restore(flags);
 
        /*
@@ -789,25 +789,6 @@ void __init hook_debug_fault_code(int nr,
  */
 static void debug_exception_enter(struct pt_regs *regs)
 {
-       /*
-        * Tell lockdep we disabled irqs in entry.S. Do nothing if they were
-        * already disabled to preserve the last enabled/disabled addresses.
-        */
-       if (interrupts_enabled(regs))
-               trace_hardirqs_off();
-
-       if (user_mode(regs)) {
-               RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
-       } else {
-               /*
-                * We might have interrupted pretty much anything.  In
-                * fact, if we're a debug exception, we can even interrupt
-                * NMI processing. We don't want this code makes in_nmi()
-                * to return true, but we need to notify RCU.
-                */
-               rcu_nmi_enter();
-       }
-
        preempt_disable();
 
        /* This code is a bit fragile.  Test it. */
@@ -818,12 +799,6 @@ NOKPROBE_SYMBOL(debug_exception_enter);
 static void debug_exception_exit(struct pt_regs *regs)
 {
        preempt_enable_no_resched();
-
-       if (!user_mode(regs))
-               rcu_nmi_exit();
-
-       if (interrupts_enabled(regs))
-               trace_hardirqs_on();
 }
 NOKPROBE_SYMBOL(debug_exception_exit);
 
index 1c0f3e02f731edd8b962b2d62a8954236b91c3d7..ca692a8157315dda46557a3962cc3df6d121f439 100644 (file)
@@ -1444,11 +1444,28 @@ static void __remove_pgd_mapping(pgd_t *pgdir, unsigned long start, u64 size)
        free_empty_tables(start, end, PAGE_OFFSET, PAGE_END);
 }
 
+static bool inside_linear_region(u64 start, u64 size)
+{
+       /*
+        * Linear mapping region is the range [PAGE_OFFSET..(PAGE_END - 1)]
+        * accommodating both its ends but excluding PAGE_END. Max physical
+        * range which can be mapped inside this linear mapping range, must
+        * also be derived from its end points.
+        */
+       return start >= __pa(_PAGE_OFFSET(vabits_actual)) &&
+              (start + size - 1) <= __pa(PAGE_END - 1);
+}
+
 int arch_add_memory(int nid, u64 start, u64 size,
                    struct mhp_params *params)
 {
        int ret, flags = 0;
 
+       if (!inside_linear_region(start, size)) {
+               pr_err("[%llx %llx] is outside linear mapping region\n", start, start + size);
+               return -EINVAL;
+       }
+
        if (rodata_full || debug_pagealloc_enabled())
                flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
 
index eb32838b8210f8a43bf4b2a335c43760d46f91ef..09b7f88a2d6ad42184b664141c9672262b6b4b38 100644 (file)
@@ -32,8 +32,7 @@ u64 perf_reg_abi(struct task_struct *task)
 }
 
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
        regs_user->regs = task_pt_regs(current);
        regs_user->abi = perf_reg_abi(current);
index f730869e21eed4829e5f5e90c96f64f1bbc95b68..69af6bc87e6473d2c0c868cf364893e3593f8adf 100644 (file)
@@ -102,6 +102,6 @@ void arch_cpu_idle(void)
 #ifdef CONFIG_CPU_PM_STOP
        asm volatile("stop\n");
 #endif
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 #endif
index aea0a40b77a9b4153afbffec789bac2750a4db94..bc1364db58feb01e82c1fd407dea4ee0a8611944 100644 (file)
@@ -57,7 +57,7 @@ asmlinkage void ret_from_kernel_thread(void);
  */
 void arch_cpu_idle(void)
 {
-       local_irq_enable();
+       raw_local_irq_enable();
        __asm__("sleep");
 }
 
index 5a0a95d93ddb7d03cc5d168ded46b3886c37a13d..67767c5ed98c3a14ab4813614416ca3f731fc96a 100644 (file)
@@ -44,7 +44,7 @@ void arch_cpu_idle(void)
 {
        __vmwait();
        /*  interrupts wake us up, but irqs are still disabled */
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 
 /*
index 336d0570e1fab4d3479c59fb034860c07709d0a2..dd8c166ffd7b5ffbf56e3217a209512745d7e65b 100644 (file)
 #endif
 
 #endif /* CONFIG_SPARSEMEM */
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+int memory_add_physaddr_to_nid(u64 addr);
+#define memory_add_physaddr_to_nid memory_add_physaddr_to_nid
+#endif
+
 #endif /* _ASM_IA64_SPARSEMEM_H */
index 6b61a703bcf55b35801d13083cf512db265651e8..c9ff8796b5097e0498256482f10cb96b10b1d802 100644 (file)
@@ -239,7 +239,7 @@ void arch_cpu_idle(void)
        if (mark_idle)
                (*mark_idle)(1);
 
-       safe_halt();
+       raw_safe_halt();
 
        if (mark_idle)
                (*mark_idle)(0);
index a9e46e525cd0ad4a3c0495da84090911afceb4b3..f99860771ff4854f13b1c3832edb53f1fd61ac1c 100644 (file)
@@ -149,5 +149,5 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
 
 void arch_cpu_idle(void)
 {
-       local_irq_enable();
+       raw_local_irq_enable();
 }
index a95a894aceaf1237852d5b18bb61a145099bc20f..f0c83033710472aca1e30a521c54d2214b23df9d 100644 (file)
@@ -152,6 +152,7 @@ static struct clk __init *alchemy_clk_setup_cpu(const char *parent_name,
 {
        struct clk_init_data id;
        struct clk_hw *h;
+       struct clk *clk;
 
        h = kzalloc(sizeof(*h), GFP_KERNEL);
        if (!h)
@@ -164,7 +165,13 @@ static struct clk __init *alchemy_clk_setup_cpu(const char *parent_name,
        id.ops = &alchemy_clkops_cpu;
        h->init = &id;
 
-       return clk_register(NULL, h);
+       clk = clk_register(NULL, h);
+       if (IS_ERR(clk)) {
+               pr_err("failed to register clock\n");
+               kfree(h);
+       }
+
+       return clk;
 }
 
 /* AUXPLLs ************************************************************/
index a950fc1ddb4da419d498ab64d94dc89dbb3b08fc..6c0532d7b21191a8c0e4eccc1d2ada2acb71f8ad 100644 (file)
@@ -154,6 +154,7 @@ static inline void pmd_clear(pmd_t *pmdp)
 
 #if defined(CONFIG_XPA)
 
+#define MAX_POSSIBLE_PHYSMEM_BITS 40
 #define pte_pfn(x)             (((unsigned long)((x).pte_high >> _PFN_SHIFT)) | (unsigned long)((x).pte_low << _PAGE_PRESENT_SHIFT))
 static inline pte_t
 pfn_pte(unsigned long pfn, pgprot_t prot)
@@ -169,6 +170,7 @@ pfn_pte(unsigned long pfn, pgprot_t prot)
 
 #elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
 
+#define MAX_POSSIBLE_PHYSMEM_BITS 36
 #define pte_pfn(x)             ((unsigned long)((x).pte_high >> 6))
 
 static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
@@ -183,6 +185,7 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
 
 #else
 
+#define MAX_POSSIBLE_PHYSMEM_BITS 32
 #ifdef CONFIG_CPU_VR41XX
 #define pte_pfn(x)             ((unsigned long)((x).pte >> (PAGE_SHIFT + 2)))
 #define pfn_pte(pfn, prot)     __pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot))
index 5bc3b04693c7d4446a19a95a498b625f7701da04..18e69ebf5691dd58c2d3a52f8e33525576844404 100644 (file)
@@ -33,19 +33,19 @@ static void __cpuidle r3081_wait(void)
 {
        unsigned long cfg = read_c0_conf();
        write_c0_conf(cfg | R30XX_CONF_HALT);
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 
 static void __cpuidle r39xx_wait(void)
 {
        if (!need_resched())
                write_c0_conf(read_c0_conf() | TX39_CONF_HALT);
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 
 void __cpuidle r4k_wait(void)
 {
-       local_irq_enable();
+       raw_local_irq_enable();
        __r4k_wait();
 }
 
@@ -64,7 +64,7 @@ void __cpuidle r4k_wait_irqoff(void)
                "       .set    arch=r4000      \n"
                "       wait                    \n"
                "       .set    pop             \n");
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 
 /*
@@ -84,7 +84,7 @@ static void __cpuidle rm7k_wait_irqoff(void)
                "       wait                                            \n"
                "       mtc0    $1, $12         # stalls until W stage  \n"
                "       .set    pop                                     \n");
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 
 /*
@@ -257,7 +257,7 @@ void arch_cpu_idle(void)
        if (cpu_wait)
                cpu_wait();
        else
-               local_irq_enable();
+               raw_local_irq_enable();
 }
 
 #ifdef CONFIG_CPU_IDLE
index 0d4253208bde1cb2979301a5fc3bbc0cc2c297ff..ca579deef93916e6ee86758c51b4699a6e93146d 100644 (file)
@@ -262,8 +262,8 @@ static void __init bootmem_init(void)
 static void __init bootmem_init(void)
 {
        phys_addr_t ramstart, ramend;
-       phys_addr_t start, end;
-       u64 i;
+       unsigned long start, end;
+       int i;
 
        ramstart = memblock_start_of_DRAM();
        ramend = memblock_end_of_DRAM();
@@ -300,7 +300,7 @@ static void __init bootmem_init(void)
 
        min_low_pfn = ARCH_PFN_OFFSET;
        max_pfn = PFN_DOWN(ramend);
-       for_each_mem_range(i, &start, &end) {
+       for_each_mem_pfn_range(i, MAX_NUMNODES, &start, &end, NULL) {
                /*
                 * Skip highmem here so we get an accurate max_low_pfn if low
                 * memory stops short of high memory.
index 38e2894d5fa32bdbb6d578be275a8dbef6b4e2ca..1b939abbe4caaf5c0406c9550d3c3dc05d1ccf82 100644 (file)
@@ -438,6 +438,7 @@ int has_transparent_hugepage(void)
        }
        return mask == PM_HUGE_MASK;
 }
+EXPORT_SYMBOL(has_transparent_hugepage);
 
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE  */
 
index 4ffe857e6adad401d1d5a5f2063755af37f43b2e..50b4eb19a6cc9962198ddbe12e1ba02bf2324d4b 100644 (file)
@@ -33,7 +33,7 @@ EXPORT_SYMBOL(pm_power_off);
 
 void arch_cpu_idle(void)
 {
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 
 /*
index 0ff391f00334c63bef8851b444985cbfa7c1848d..3c98728cce2491c80e586945760b4603e1714c71 100644 (file)
@@ -79,7 +79,7 @@ void machine_power_off(void)
  */
 void arch_cpu_idle(void)
 {
-       local_irq_enable();
+       raw_local_irq_enable();
        if (mfspr(SPR_UPR) & SPR_UPR_PMP)
                mtspr(SPR_PMR, mfspr(SPR_PMR) | SPR_PMR_DME);
 }
index f196d96e2f9f55f2739b4e518b1daddb24e6d701..a92a23d6acd931c2fb047a898b3c6eef9d488e20 100644 (file)
@@ -169,7 +169,7 @@ void __cpuidle arch_cpu_idle_dead(void)
 
 void __cpuidle arch_cpu_idle(void)
 {
-       local_irq_enable();
+       raw_local_irq_enable();
 
        /* nop on real hardware, qemu will idle sleep. */
        asm volatile("or %%r10,%%r10,%%r10\n":::);
index e9f13fe084929bd9ad322c432d9a59f1674d9ecd..5181872f94523c9e0e9259797e8176cc83b21112 100644 (file)
@@ -152,6 +152,7 @@ config PPC
        select ARCH_USE_QUEUED_SPINLOCKS        if PPC_QUEUED_SPINLOCKS
        select ARCH_WANT_IPC_PARSE_VERSION
        select ARCH_WANT_IRQS_OFF_ACTIVATE_MM
+       select ARCH_WANT_LD_ORPHAN_WARN
        select ARCH_WEAK_RELEASE_ACQUIRE
        select BINFMT_ELF
        select BUILDTIME_TABLE_SORT
index a4d56f0a41d95522a1f4ca3f8bac6808b2e26b8a..5c8c06215dd4ba7c6efefe1e948620ba6e4f4095 100644 (file)
@@ -123,7 +123,6 @@ endif
 LDFLAGS_vmlinux-y := -Bstatic
 LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie
 LDFLAGS_vmlinux        := $(LDFLAGS_vmlinux-y)
-LDFLAGS_vmlinux += $(call ld-option,--orphan-handling=warn)
 
 ifdef CONFIG_PPC64
 ifeq ($(call cc-option-yn,-mcmodel=medium),y)
@@ -248,7 +247,6 @@ KBUILD_CFLAGS               += $(call cc-option,-mno-string)
 cpu-as-$(CONFIG_40x)           += -Wa,-m405
 cpu-as-$(CONFIG_44x)           += -Wa,-m440
 cpu-as-$(CONFIG_ALTIVEC)       += $(call as-option,-Wa$(comma)-maltivec)
-cpu-as-$(CONFIG_E200)          += -Wa,-me200
 cpu-as-$(CONFIG_E500)          += -Wa,-me500
 
 # When using '-many -mpower4' gas will first try and find a matching power4
index 36443cda8dcf237977c78a45a81530e0c5a3bef0..1376be95e975f4ab51b1e7fe395826f7dccc5475 100644 (file)
@@ -36,8 +36,10 @@ static inline bool pte_user(pte_t pte)
  */
 #ifdef CONFIG_PTE_64BIT
 #define PTE_RPN_MASK   (~((1ULL << PTE_RPN_SHIFT) - 1))
+#define MAX_POSSIBLE_PHYSMEM_BITS 36
 #else
 #define PTE_RPN_MASK   (~((1UL << PTE_RPN_SHIFT) - 1))
+#define MAX_POSSIBLE_PHYSMEM_BITS 32
 #endif
 
 /*
index 3ee1ec60be8442d4fd9d724eec8b9800d731a619..a39e2d193fdc13f9ff3d950cc257b993a516229e 100644 (file)
@@ -27,6 +27,7 @@
 #endif
 .endm
 
+#ifdef CONFIG_PPC_KUAP
 .macro kuap_check_amr gpr1, gpr2
 #ifdef CONFIG_PPC_KUAP_DEBUG
        BEGIN_MMU_FTR_SECTION_NESTED(67)
@@ -38,6 +39,7 @@
        END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_RADIX_KUAP, 67)
 #endif
 .endm
+#endif
 
 .macro kuap_save_amr_and_lock gpr1, gpr2, use_cr, msr_pr_cr
 #ifdef CONFIG_PPC_KUAP
 
 #else /* !__ASSEMBLY__ */
 
+#include <linux/jump_label.h>
+
+DECLARE_STATIC_KEY_FALSE(uaccess_flush_key);
+
 #ifdef CONFIG_PPC_KUAP
 
 #include <asm/mmu.h>
@@ -103,8 +109,16 @@ static inline void kuap_check_amr(void)
 
 static inline unsigned long get_kuap(void)
 {
+       /*
+        * We return AMR_KUAP_BLOCKED when we don't support KUAP because
+        * prevent_user_access_return needs to return AMR_KUAP_BLOCKED to
+        * cause restore_user_access to do a flush.
+        *
+        * This has no effect in terms of actually blocking things on hash,
+        * so it doesn't break anything.
+        */
        if (!early_mmu_has_feature(MMU_FTR_RADIX_KUAP))
-               return 0;
+               return AMR_KUAP_BLOCKED;
 
        return mfspr(SPRN_AMR);
 }
@@ -123,6 +137,29 @@ static inline void set_kuap(unsigned long value)
        isync();
 }
 
+static inline bool
+bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
+{
+       return WARN(mmu_has_feature(MMU_FTR_RADIX_KUAP) &&
+                   (regs->kuap & (is_write ? AMR_KUAP_BLOCK_WRITE : AMR_KUAP_BLOCK_READ)),
+                   "Bug: %s fault blocked by AMR!", is_write ? "Write" : "Read");
+}
+#else /* CONFIG_PPC_KUAP */
+static inline void kuap_restore_amr(struct pt_regs *regs, unsigned long amr) { }
+
+static inline unsigned long kuap_get_and_check_amr(void)
+{
+       return 0UL;
+}
+
+static inline unsigned long get_kuap(void)
+{
+       return AMR_KUAP_BLOCKED;
+}
+
+static inline void set_kuap(unsigned long value) { }
+#endif /* !CONFIG_PPC_KUAP */
+
 static __always_inline void allow_user_access(void __user *to, const void __user *from,
                                              unsigned long size, unsigned long dir)
 {
@@ -142,6 +179,8 @@ static inline void prevent_user_access(void __user *to, const void __user *from,
                                       unsigned long size, unsigned long dir)
 {
        set_kuap(AMR_KUAP_BLOCKED);
+       if (static_branch_unlikely(&uaccess_flush_key))
+               do_uaccess_flush();
 }
 
 static inline unsigned long prevent_user_access_return(void)
@@ -149,6 +188,8 @@ static inline unsigned long prevent_user_access_return(void)
        unsigned long flags = get_kuap();
 
        set_kuap(AMR_KUAP_BLOCKED);
+       if (static_branch_unlikely(&uaccess_flush_key))
+               do_uaccess_flush();
 
        return flags;
 }
@@ -156,30 +197,9 @@ static inline unsigned long prevent_user_access_return(void)
 static inline void restore_user_access(unsigned long flags)
 {
        set_kuap(flags);
+       if (static_branch_unlikely(&uaccess_flush_key) && flags == AMR_KUAP_BLOCKED)
+               do_uaccess_flush();
 }
-
-static inline bool
-bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
-{
-       return WARN(mmu_has_feature(MMU_FTR_RADIX_KUAP) &&
-                   (regs->kuap & (is_write ? AMR_KUAP_BLOCK_WRITE : AMR_KUAP_BLOCK_READ)),
-                   "Bug: %s fault blocked by AMR!", is_write ? "Write" : "Read");
-}
-#else /* CONFIG_PPC_KUAP */
-static inline void kuap_restore_amr(struct pt_regs *regs, unsigned long amr)
-{
-}
-
-static inline void kuap_check_amr(void)
-{
-}
-
-static inline unsigned long kuap_get_and_check_amr(void)
-{
-       return 0;
-}
-#endif /* CONFIG_PPC_KUAP */
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H */
index e0b52940e43cb4f6dc2b235d8ff0e984bd306322..750918451dd263c02773b158b16c91d625f4926b 100644 (file)
@@ -242,6 +242,18 @@ extern void radix_init_pseries(void);
 static inline void radix_init_pseries(void) { };
 #endif
 
+#ifdef CONFIG_HOTPLUG_CPU
+#define arch_clear_mm_cpumask_cpu(cpu, mm)                             \
+       do {                                                            \
+               if (cpumask_test_cpu(cpu, mm_cpumask(mm))) {            \
+                       atomic_dec(&(mm)->context.active_cpus);         \
+                       cpumask_clear_cpu(cpu, mm_cpumask(mm));         \
+               }                                                       \
+       } while (0)
+
+void cleanup_cpu_mmu_context(void);
+#endif
+
 static inline int get_user_context(mm_context_t *ctx, unsigned long ea)
 {
        int index = ea >> MAX_EA_BITS_PER_CONTEXT;
index ebe95aa04d53888bd717708e80446981a3eee1eb..1d32b174ab6aec3fb5403c11bddd7f938a78c2e8 100644 (file)
        nop;                                                            \
        nop
 
+#define ENTRY_FLUSH_SLOT                                               \
+       ENTRY_FLUSH_FIXUP_SECTION;                                      \
+       nop;                                                            \
+       nop;                                                            \
+       nop;
+
 /*
  * r10 must be free to use, r13 must be paca
  */
 #define INTERRUPT_TO_KERNEL                                            \
-       STF_ENTRY_BARRIER_SLOT
+       STF_ENTRY_BARRIER_SLOT;                                         \
+       ENTRY_FLUSH_SLOT
 
 /*
  * Macros for annotating the expected destination of (h)rfid
        RFSCV;                                                          \
        b       rfscv_flush_fallback
 
+#else /* __ASSEMBLY__ */
+/* Prototype for function defined in exceptions-64s.S */
+void do_uaccess_flush(void);
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_EXCEPTION_H */
index b0af97add751712f76b61145966212fb4c86428c..fbd406cd6916c9451a766411724925a62d06933b 100644 (file)
@@ -205,6 +205,22 @@ label##3:                                          \
        FTR_ENTRY_OFFSET 955b-956b;                     \
        .popsection;
 
+#define UACCESS_FLUSH_FIXUP_SECTION                    \
+959:                                                   \
+       .pushsection __uaccess_flush_fixup,"a";         \
+       .align 2;                                       \
+960:                                                   \
+       FTR_ENTRY_OFFSET 959b-960b;                     \
+       .popsection;
+
+#define ENTRY_FLUSH_FIXUP_SECTION                      \
+957:                                                   \
+       .pushsection __entry_flush_fixup,"a";           \
+       .align 2;                                       \
+958:                                                   \
+       FTR_ENTRY_OFFSET 957b-958b;                     \
+       .popsection;
+
 #define RFI_FLUSH_FIXUP_SECTION                                \
 951:                                                   \
        .pushsection __rfi_flush_fixup,"a";             \
@@ -237,8 +253,11 @@ label##3:                                          \
 #include <linux/types.h>
 
 extern long stf_barrier_fallback;
+extern long entry_flush_fallback;
 extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup;
 extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup;
+extern long __start___uaccess_flush_fixup, __stop___uaccess_flush_fixup;
+extern long __start___entry_flush_fixup, __stop___entry_flush_fixup;
 extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup;
 extern long __start___barrier_nospec_fixup, __stop___barrier_nospec_fixup;
 extern long __start__btb_flush_fixup, __stop__btb_flush_fixup;
index 1d0f7d838b2e2f01d0199fe5aa6a0fe650e499ff..0d93331d0fabbefb07d414d1bec39bcc10014834 100644 (file)
@@ -14,7 +14,7 @@
 #define KUAP_CURRENT_WRITE     8
 #define KUAP_CURRENT           (KUAP_CURRENT_READ | KUAP_CURRENT_WRITE)
 
-#ifdef CONFIG_PPC64
+#ifdef CONFIG_PPC_BOOK3S_64
 #include <asm/book3s/64/kup-radix.h>
 #endif
 #ifdef CONFIG_PPC_8xx
@@ -35,6 +35,9 @@
 .macro kuap_check      current, gpr
 .endm
 
+.macro kuap_check_amr  gpr1, gpr2
+.endm
+
 #endif
 
 #else /* !__ASSEMBLY__ */
@@ -53,17 +56,28 @@ static inline void setup_kuep(bool disabled) { }
 void setup_kuap(bool disabled);
 #else
 static inline void setup_kuap(bool disabled) { }
+
+static inline bool
+bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
+{
+       return false;
+}
+
+static inline void kuap_check_amr(void) { }
+
+/*
+ * book3s/64/kup-radix.h defines these functions for the !KUAP case to flush
+ * the L1D cache after user accesses. Only include the empty stubs for other
+ * platforms.
+ */
+#ifndef CONFIG_PPC_BOOK3S_64
 static inline void allow_user_access(void __user *to, const void __user *from,
                                     unsigned long size, unsigned long dir) { }
 static inline void prevent_user_access(void __user *to, const void __user *from,
                                       unsigned long size, unsigned long dir) { }
 static inline unsigned long prevent_user_access_return(void) { return 0UL; }
 static inline void restore_user_access(unsigned long flags) { }
-static inline bool
-bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
-{
-       return false;
-}
+#endif /* CONFIG_PPC_BOOK3S_64 */
 #endif /* CONFIG_PPC_KUAP */
 
 static inline void allow_read_from_user(const void __user *from, unsigned long size)
index 91c69ff53a8a849e12b0b5638205b331e7143687..6cda76b57c5dd044a0db10783882a33927245927 100644 (file)
@@ -46,5 +46,10 @@ u64 memory_hotplug_max(void);
 #define __HAVE_ARCH_RESERVED_KERNEL_PAGES
 #endif
 
+#ifdef CONFIG_MEMORY_HOTPLUG
+extern int create_section_mapping(unsigned long start, unsigned long end,
+                                 int nid, pgprot_t prot);
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_MMZONE_H_ */
index 85ed2390fb99587e5f2fbcabb8954ab4e1b4dd1f..567cdc55740241c653c56f3e5f37b4fc2a178098 100644 (file)
@@ -63,7 +63,7 @@ static inline void restore_user_access(unsigned long flags)
 static inline bool
 bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
 {
-       return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xf0000000),
+       return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xff000000),
                    "Bug: fault blocked by AP register !");
 }
 
index 1d9ac0f9c794416dade15930995cb4f645fcc375..0bd1b144eb76851de95267b8737f14b6ff7359a0 100644 (file)
  * respectively NA for All or X for Supervisor and no access for User.
  * Then we use the APG to say whether accesses are according to Page rules or
  * "all Supervisor" rules (Access to all)
- * Therefore, we define 2 APG groups. lsb is _PMD_USER
- * 0 => Kernel => 01 (all accesses performed according to page definition)
- * 1 => User => 00 (all accesses performed as supervisor iaw page definition)
- * 2-15 => Not Used
- */
-#define MI_APG_INIT    0x40000000
-
-/*
- * 0 => Kernel => 01 (all accesses performed according to page definition)
- * 1 => User => 10 (all accesses performed according to swaped page definition)
- * 2-15 => Not Used
- */
-#define MI_APG_KUEP    0x60000000
+ * _PAGE_ACCESSED is also managed via APG. When _PAGE_ACCESSED is not set, say
+ * "all User" rules, that will lead to NA for all.
+ * Therefore, we define 4 APG groups. lsb is _PAGE_ACCESSED
+ * 0 => Kernel => 11 (all accesses performed according as user iaw page definition)
+ * 1 => Kernel+Accessed => 01 (all accesses performed according to page definition)
+ * 2 => User => 11 (all accesses performed according as user iaw page definition)
+ * 3 => User+Accessed => 00 (all accesses performed as supervisor iaw page definition) for INIT
+ *                    => 10 (all accesses performed according to swaped page definition) for KUEP
+ * 4-15 => Not Used
+ */
+#define MI_APG_INIT    0xdc000000
+#define MI_APG_KUEP    0xde000000
 
 /* The effective page number register.  When read, contains the information
  * about the last instruction TLB miss.  When MI_RPN is written, bits in
 #define MD_Ks          0x80000000      /* Should not be set */
 #define MD_Kp          0x40000000      /* Should always be set */
 
-/*
- * All pages' PP data bits are set to either 000 or 011 or 001, which means
- * respectively RW for Supervisor and no access for User, or RO for
- * Supervisor and no access for user and NA for ALL.
- * Then we use the APG to say whether accesses are according to Page rules or
- * "all Supervisor" rules (Access to all)
- * Therefore, we define 2 APG groups. lsb is _PMD_USER
- * 0 => Kernel => 01 (all accesses performed according to page definition)
- * 1 => User => 00 (all accesses performed as supervisor iaw page definition)
- * 2-15 => Not Used
- */
-#define MD_APG_INIT    0x40000000
-
-/*
- * 0 => No user => 01 (all accesses performed according to page definition)
- * 1 => User => 10 (all accesses performed according to swaped page definition)
- * 2-15 => Not Used
- */
-#define MD_APG_KUAP    0x60000000
+/* See explanation above at the definition of MI_APG_INIT */
+#define MD_APG_INIT    0xdc000000
+#define MD_APG_KUAP    0xde000000
 
 /* The effective page number register.  When read, contains the information
  * about the last instruction TLB miss.  When MD_RPN is written, bits in
index ee2243ba96cfa98cec006c06f7254e5a2b891966..96522f7f0618a0eb9096858f2b63ff2b98bc3046 100644 (file)
@@ -153,8 +153,10 @@ int map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot);
  */
 #if defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT)
 #define PTE_RPN_MASK   (~((1ULL << PTE_RPN_SHIFT) - 1))
+#define MAX_POSSIBLE_PHYSMEM_BITS 36
 #else
 #define PTE_RPN_MASK   (~((1UL << PTE_RPN_SHIFT) - 1))
+#define MAX_POSSIBLE_PHYSMEM_BITS 32
 #endif
 
 /*
index 66f403a7da44c4e1021e8fd7281ac056edeb146d..1581204467e1de1a685fd00b5a2ed9432383bd68 100644 (file)
@@ -39,9 +39,9 @@
  * into the TLB.
  */
 #define _PAGE_GUARDED  0x0010  /* Copied to L1 G entry in DTLB */
-#define _PAGE_SPECIAL  0x0020  /* SW entry */
+#define _PAGE_ACCESSED 0x0020  /* Copied to L1 APG 1 entry in I/DTLB */
 #define _PAGE_EXEC     0x0040  /* Copied to PP (bit 21) in ITLB */
-#define _PAGE_ACCESSED 0x0080  /* software: page referenced */
+#define _PAGE_SPECIAL  0x0080  /* SW entry */
 
 #define _PAGE_NA       0x0200  /* Supervisor NA, User no access */
 #define _PAGE_RO       0x0600  /* Supervisor RO, User no access */
 
 #define _PMD_PRESENT   0x0001
 #define _PMD_PRESENT_MASK      _PMD_PRESENT
-#define _PMD_BAD       0x0fd0
+#define _PMD_BAD       0x0f90
 #define _PMD_PAGE_MASK 0x000c
 #define _PMD_PAGE_8M   0x000c
 #define _PMD_PAGE_512K 0x0004
-#define _PMD_USER      0x0020  /* APG 1 */
+#define _PMD_ACCESSED  0x0020  /* APG 1 */
+#define _PMD_USER      0x0040  /* APG 2 */
 
 #define _PTE_NONE_MASK 0
 
index fbb8fa32150fd969962ff9ee731e46c99bbb6f86..b774a4477d5f1a256895c1778af1e7372fb7eeb9 100644 (file)
@@ -86,12 +86,19 @@ static inline bool security_ftr_enabled(u64 feature)
 // Software required to flush link stack on context switch
 #define SEC_FTR_FLUSH_LINK_STACK       0x0000000000001000ull
 
+// The L1-D cache should be flushed when entering the kernel
+#define SEC_FTR_L1D_FLUSH_ENTRY                0x0000000000004000ull
+
+// The L1-D cache should be flushed after user accesses from the kernel
+#define SEC_FTR_L1D_FLUSH_UACCESS      0x0000000000008000ull
 
 // Features enabled by default
 #define SEC_FTR_DEFAULT \
        (SEC_FTR_L1D_FLUSH_HV | \
         SEC_FTR_L1D_FLUSH_PR | \
         SEC_FTR_BNDS_CHK_SPEC_BAR | \
+        SEC_FTR_L1D_FLUSH_ENTRY | \
+        SEC_FTR_L1D_FLUSH_UACCESS | \
         SEC_FTR_FAVOUR_SECURITY)
 
 #endif /* _ASM_POWERPC_SECURITY_FEATURES_H */
index 9efbddee2bca9bbd96fa6dd101ce92fe022a9043..a466749703f1fbde304ea51df8abd21d60c82d28 100644 (file)
@@ -52,12 +52,16 @@ enum l1d_flush_type {
 };
 
 void setup_rfi_flush(enum l1d_flush_type, bool enable);
+void setup_entry_flush(bool enable);
+void setup_uaccess_flush(bool enable);
 void do_rfi_flush_fixups(enum l1d_flush_type types);
 #ifdef CONFIG_PPC_BARRIER_NOSPEC
 void setup_barrier_nospec(void);
 #else
 static inline void setup_barrier_nospec(void) { };
 #endif
+void do_uaccess_flush_fixups(enum l1d_flush_type types);
+void do_entry_flush_fixups(enum l1d_flush_type types);
 void do_barrier_nospec_fixups(bool enable);
 extern bool barrier_nospec_enabled;
 
index 1e6fa371cc387901f084ab64d7167e15fd61ec08..d072866842e4229159fcb6635745fd19a2788413 100644 (file)
@@ -13,9 +13,9 @@
 #endif /* CONFIG_SPARSEMEM */
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-extern int create_section_mapping(unsigned long start, unsigned long end,
-                                 int nid, pgprot_t prot);
 extern int remove_section_mapping(unsigned long start, unsigned long end);
+extern int memory_add_physaddr_to_nid(u64 start);
+#define memory_add_physaddr_to_nid memory_add_physaddr_to_nid
 
 #ifdef CONFIG_NUMA
 extern int hot_add_scn_to_nid(unsigned long scn_addr);
@@ -26,6 +26,5 @@ static inline int hot_add_scn_to_nid(unsigned long scn_addr)
 }
 #endif /* CONFIG_NUMA */
 #endif /* CONFIG_MEMORY_HOTPLUG */
-
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_SPARSEMEM_H */
index 8728590f514a8ccf3421ec75266d7657e64cb759..3beeb030cd78e9bbcababbf4de178c588fbe0eee 100644 (file)
@@ -6,6 +6,7 @@
 
 struct device;
 struct device_node;
+struct drmem_lmb;
 
 #ifdef CONFIG_NUMA
 
@@ -61,6 +62,9 @@ static inline int early_cpu_to_node(int cpu)
         */
        return (nid < 0) ? 0 : nid;
 }
+
+int of_drconf_to_nid_single(struct drmem_lmb *lmb);
+
 #else
 
 static inline int early_cpu_to_node(int cpu) { return 0; }
@@ -84,10 +88,12 @@ static inline int cpu_distance(__be32 *cpu1_assoc, __be32 *cpu2_assoc)
        return 0;
 }
 
-#endif /* CONFIG_NUMA */
+static inline int of_drconf_to_nid_single(struct drmem_lmb *lmb)
+{
+       return first_online_node;
+}
 
-struct drmem_lmb;
-int of_drconf_to_nid_single(struct drmem_lmb *lmb);
+#endif /* CONFIG_NUMA */
 
 #if defined(CONFIG_NUMA) && defined(CONFIG_PPC_SPLPAR)
 extern int find_and_online_cpu_nid(int cpu);
index ef5bbb705c08b7b12a7c11451305f2a64d8b5266..501c9a79038c081fbecfbd9fa1f13ada323f8f79 100644 (file)
@@ -178,7 +178,7 @@ do {                                                                \
  * are no aliasing issues.
  */
 #define __put_user_asm_goto(x, addr, label, op)                        \
-       asm volatile goto(                                      \
+       asm_volatile_goto(                                      \
                "1:     " op "%U1%X1 %0,%1      # put_user\n"   \
                EX_TABLE(1b, %l2)                               \
                :                                               \
@@ -191,7 +191,7 @@ do {                                                                \
        __put_user_asm_goto(x, ptr, label, "std")
 #else /* __powerpc64__ */
 #define __put_user_asm2_goto(x, addr, label)                   \
-       asm volatile goto(                                      \
+       asm_volatile_goto(                                      \
                "1:     stw%X1 %0, %1\n"                        \
                "2:     stw%X1 %L0, %L1\n"                      \
                EX_TABLE(1b, %l2)                               \
index 6b50bf15d8c19123181d1298cd35c3d3d3ff1e09..bf3270426d82d6569d48fedb0fefbbf7d1061b06 100644 (file)
@@ -264,8 +264,9 @@ static int eeh_addr_cache_show(struct seq_file *s, void *v)
 {
        struct pci_io_addr_range *piar;
        struct rb_node *n;
+       unsigned long flags;
 
-       spin_lock(&pci_io_addr_cache_root.piar_lock);
+       spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
        for (n = rb_first(&pci_io_addr_cache_root.rb_root); n; n = rb_next(n)) {
                piar = rb_entry(n, struct pci_io_addr_range, rb_node);
 
@@ -273,7 +274,7 @@ static int eeh_addr_cache_show(struct seq_file *s, void *v)
                       (piar->flags & IORESOURCE_IO) ? "i/o" : "mem",
                       &piar->addr_lo, &piar->addr_hi, pci_name(piar->pcidev));
        }
-       spin_unlock(&pci_io_addr_cache_root.piar_lock);
+       spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
 
        return 0;
 }
index f7d748b887059e26842270e94bf44d23f1f59d3b..4d01f09ecf80819e1275264bd0b06ea8fce1977d 100644 (file)
@@ -1000,8 +1000,6 @@ TRAMP_REAL_BEGIN(system_reset_idle_wake)
  * Vectors for the FWNMI option.  Share common code.
  */
 TRAMP_REAL_BEGIN(system_reset_fwnmi)
-       /* XXX: fwnmi guest could run a nested/PR guest, so why no test?  */
-       __IKVM_REAL(system_reset)=0
        GEN_INT_ENTRY system_reset, virt=0
 
 #endif /* CONFIG_PPC_PSERIES */
@@ -1412,6 +1410,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
  *   If none is found, do a Linux page fault. Linux page faults can happen in
  *   kernel mode due to user copy operations of course.
  *
+ *   KVM: The KVM HDSI handler may perform a load with MSR[DR]=1 in guest
+ *   MMU context, which may cause a DSI in the host, which must go to the
+ *   KVM handler. MSR[IR] is not enabled, so the real-mode handler will
+ *   always be used regardless of AIL setting.
+ *
  * - Radix MMU
  *   The hardware loads from the Linux page table directly, so a fault goes
  *   immediately to Linux page fault.
@@ -1422,10 +1425,8 @@ INT_DEFINE_BEGIN(data_access)
        IVEC=0x300
        IDAR=1
        IDSISR=1
-#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
        IKVM_SKIP=1
        IKVM_REAL=1
-#endif
 INT_DEFINE_END(data_access)
 
 EXC_REAL_BEGIN(data_access, 0x300, 0x80)
@@ -1464,6 +1465,8 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
  *   ppc64_bolted_size (first segment). The kernel handler must avoid stomping
  *   on user-handler data structures.
  *
+ *   KVM: Same as 0x300, DSLB must test for KVM guest.
+ *
  * A dedicated save area EXSLB is used (XXX: but it actually need not be
  * these days, we could use EXGEN).
  */
@@ -1472,10 +1475,8 @@ INT_DEFINE_BEGIN(data_access_slb)
        IAREA=PACA_EXSLB
        IRECONCILE=0
        IDAR=1
-#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
        IKVM_SKIP=1
        IKVM_REAL=1
-#endif
 INT_DEFINE_END(data_access_slb)
 
 EXC_REAL_BEGIN(data_access_slb, 0x380, 0x80)
@@ -2951,15 +2952,8 @@ TRAMP_REAL_BEGIN(stf_barrier_fallback)
        .endr
        blr
 
-TRAMP_REAL_BEGIN(rfi_flush_fallback)
-       SET_SCRATCH0(r13);
-       GET_PACA(r13);
-       std     r1,PACA_EXRFI+EX_R12(r13)
-       ld      r1,PACAKSAVE(r13)
-       std     r9,PACA_EXRFI+EX_R9(r13)
-       std     r10,PACA_EXRFI+EX_R10(r13)
-       std     r11,PACA_EXRFI+EX_R11(r13)
-       mfctr   r9
+/* Clobbers r10, r11, ctr */
+.macro L1D_DISPLACEMENT_FLUSH
        ld      r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13)
        ld      r11,PACA_L1D_FLUSH_SIZE(r13)
        srdi    r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */
@@ -2970,7 +2964,7 @@ TRAMP_REAL_BEGIN(rfi_flush_fallback)
        sync
 
        /*
-        * The load adresses are at staggered offsets within cachelines,
+        * The load addresses are at staggered offsets within cachelines,
         * which suits some pipelines better (on others it should not
         * hurt).
         */
@@ -2985,7 +2979,30 @@ TRAMP_REAL_BEGIN(rfi_flush_fallback)
        ld      r11,(0x80 + 8)*7(r10)
        addi    r10,r10,0x80*8
        bdnz    1b
+.endm
 
+TRAMP_REAL_BEGIN(entry_flush_fallback)
+       std     r9,PACA_EXRFI+EX_R9(r13)
+       std     r10,PACA_EXRFI+EX_R10(r13)
+       std     r11,PACA_EXRFI+EX_R11(r13)
+       mfctr   r9
+       L1D_DISPLACEMENT_FLUSH
+       mtctr   r9
+       ld      r9,PACA_EXRFI+EX_R9(r13)
+       ld      r10,PACA_EXRFI+EX_R10(r13)
+       ld      r11,PACA_EXRFI+EX_R11(r13)
+       blr
+
+TRAMP_REAL_BEGIN(rfi_flush_fallback)
+       SET_SCRATCH0(r13);
+       GET_PACA(r13);
+       std     r1,PACA_EXRFI+EX_R12(r13)
+       ld      r1,PACAKSAVE(r13)
+       std     r9,PACA_EXRFI+EX_R9(r13)
+       std     r10,PACA_EXRFI+EX_R10(r13)
+       std     r11,PACA_EXRFI+EX_R11(r13)
+       mfctr   r9
+       L1D_DISPLACEMENT_FLUSH
        mtctr   r9
        ld      r9,PACA_EXRFI+EX_R9(r13)
        ld      r10,PACA_EXRFI+EX_R10(r13)
@@ -3003,32 +3020,7 @@ TRAMP_REAL_BEGIN(hrfi_flush_fallback)
        std     r10,PACA_EXRFI+EX_R10(r13)
        std     r11,PACA_EXRFI+EX_R11(r13)
        mfctr   r9
-       ld      r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13)
-       ld      r11,PACA_L1D_FLUSH_SIZE(r13)
-       srdi    r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */
-       mtctr   r11
-       DCBT_BOOK3S_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */
-
-       /* order ld/st prior to dcbt stop all streams with flushing */
-       sync
-
-       /*
-        * The load adresses are at staggered offsets within cachelines,
-        * which suits some pipelines better (on others it should not
-        * hurt).
-        */
-1:
-       ld      r11,(0x80 + 8)*0(r10)
-       ld      r11,(0x80 + 8)*1(r10)
-       ld      r11,(0x80 + 8)*2(r10)
-       ld      r11,(0x80 + 8)*3(r10)
-       ld      r11,(0x80 + 8)*4(r10)
-       ld      r11,(0x80 + 8)*5(r10)
-       ld      r11,(0x80 + 8)*6(r10)
-       ld      r11,(0x80 + 8)*7(r10)
-       addi    r10,r10,0x80*8
-       bdnz    1b
-
+       L1D_DISPLACEMENT_FLUSH
        mtctr   r9
        ld      r9,PACA_EXRFI+EX_R9(r13)
        ld      r10,PACA_EXRFI+EX_R10(r13)
@@ -3079,8 +3071,21 @@ TRAMP_REAL_BEGIN(rfscv_flush_fallback)
        RFSCV
 
 USE_TEXT_SECTION()
-       MASKED_INTERRUPT
-       MASKED_INTERRUPT hsrr=1
+
+_GLOBAL(do_uaccess_flush)
+       UACCESS_FLUSH_FIXUP_SECTION
+       nop
+       nop
+       nop
+       blr
+       L1D_DISPLACEMENT_FLUSH
+       blr
+_ASM_NOKPROBE_SYMBOL(do_uaccess_flush)
+EXPORT_SYMBOL(do_uaccess_flush)
+
+
+MASKED_INTERRUPT
+MASKED_INTERRUPT hsrr=1
 
 #ifdef CONFIG_KVM_BOOK3S_64_HANDLER
 kvmppc_skip_interrupt:
index 44c9018aed1b08bb380a0f980c1c5f3675c420f3..a1ae00689e0f4898d17a6782a9e82afc7756edd7 100644 (file)
@@ -284,11 +284,7 @@ _ENTRY(saved_ksp_limit)
 
        rlwimi  r11, r10, 22, 20, 29    /* Compute PTE address */
        lwz     r11, 0(r11)             /* Get Linux PTE */
-#ifdef CONFIG_SWAP
        li      r9, _PAGE_PRESENT | _PAGE_ACCESSED
-#else
-       li      r9, _PAGE_PRESENT
-#endif
        andc.   r9, r9, r11             /* Check permission */
        bne     5f
 
@@ -369,11 +365,7 @@ _ENTRY(saved_ksp_limit)
 
        rlwimi  r11, r10, 22, 20, 29    /* Compute PTE address */
        lwz     r11, 0(r11)             /* Get Linux PTE */
-#ifdef CONFIG_SWAP
        li      r9, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
-#else
-       li      r9, _PAGE_PRESENT | _PAGE_EXEC
-#endif
        andc.   r9, r9, r11             /* Check permission */
        bne     5f
 
index 9f359d3fba749230d03ac883083f69ff30f09b70..ee0bfebc375f26237919173698761c593e939347 100644 (file)
@@ -202,9 +202,7 @@ SystemCall:
 
 InstructionTLBMiss:
        mtspr   SPRN_SPRG_SCRATCH0, r10
-#if defined(ITLB_MISS_KERNEL) || defined(CONFIG_SWAP) || defined(CONFIG_HUGETLBFS)
        mtspr   SPRN_SPRG_SCRATCH1, r11
-#endif
 
        /* If we are faulting a kernel address, we have to use the
         * kernel page tables.
@@ -224,25 +222,13 @@ InstructionTLBMiss:
 3:
        mtcr    r11
 #endif
-#if defined(CONFIG_HUGETLBFS) || !defined(CONFIG_PIN_TLB_TEXT)
        lwz     r11, (swapper_pg_dir-PAGE_OFFSET)@l(r10)        /* Get level 1 entry */
        mtspr   SPRN_MD_TWC, r11
-#else
-       lwz     r10, (swapper_pg_dir-PAGE_OFFSET)@l(r10)        /* Get level 1 entry */
-       mtspr   SPRN_MI_TWC, r10        /* Set segment attributes */
-       mtspr   SPRN_MD_TWC, r10
-#endif
        mfspr   r10, SPRN_MD_TWC
        lwz     r10, 0(r10)     /* Get the pte */
-#if defined(CONFIG_HUGETLBFS) || !defined(CONFIG_PIN_TLB_TEXT)
+       rlwimi  r11, r10, 0, _PAGE_GUARDED | _PAGE_ACCESSED
        rlwimi  r11, r10, 32 - 9, _PMD_PAGE_512K
        mtspr   SPRN_MI_TWC, r11
-#endif
-#ifdef CONFIG_SWAP
-       rlwinm  r11, r10, 32-5, _PAGE_PRESENT
-       and     r11, r11, r10
-       rlwimi  r10, r11, 0, _PAGE_PRESENT
-#endif
        /* The Linux PTE won't go exactly into the MMU TLB.
         * Software indicator bits 20 and 23 must be clear.
         * Software indicator bits 22, 24, 25, 26, and 27 must be
@@ -256,9 +242,7 @@ InstructionTLBMiss:
 
        /* Restore registers */
 0:     mfspr   r10, SPRN_SPRG_SCRATCH0
-#if defined(ITLB_MISS_KERNEL) || defined(CONFIG_SWAP) || defined(CONFIG_HUGETLBFS)
        mfspr   r11, SPRN_SPRG_SCRATCH1
-#endif
        rfi
        patch_site      0b, patch__itlbmiss_exit_1
 
@@ -268,9 +252,7 @@ InstructionTLBMiss:
        addi    r10, r10, 1
        stw     r10, (itlb_miss_counter - PAGE_OFFSET)@l(0)
        mfspr   r10, SPRN_SPRG_SCRATCH0
-#if defined(ITLB_MISS_KERNEL) || defined(CONFIG_SWAP)
        mfspr   r11, SPRN_SPRG_SCRATCH1
-#endif
        rfi
 #endif
 
@@ -297,30 +279,16 @@ DataStoreTLBMiss:
        mfspr   r10, SPRN_MD_TWC
        lwz     r10, 0(r10)     /* Get the pte */
 
-       /* Insert the Guarded flag into the TWC from the Linux PTE.
+       /* Insert Guarded and Accessed flags into the TWC from the Linux PTE.
         * It is bit 27 of both the Linux PTE and the TWC (at least
         * I got that right :-).  It will be better when we can put
         * this into the Linux pgd/pmd and load it in the operation
         * above.
         */
-       rlwimi  r11, r10, 0, _PAGE_GUARDED
+       rlwimi  r11, r10, 0, _PAGE_GUARDED | _PAGE_ACCESSED
        rlwimi  r11, r10, 32 - 9, _PMD_PAGE_512K
        mtspr   SPRN_MD_TWC, r11
 
-       /* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set.
-        * We also need to know if the insn is a load/store, so:
-        * Clear _PAGE_PRESENT and load that which will
-        * trap into DTLB Error with store bit set accordinly.
-        */
-       /* PRESENT=0x1, ACCESSED=0x20
-        * r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5));
-        * r10 = (r10 & ~PRESENT) | r11;
-        */
-#ifdef CONFIG_SWAP
-       rlwinm  r11, r10, 32-5, _PAGE_PRESENT
-       and     r11, r11, r10
-       rlwimi  r10, r11, 0, _PAGE_PRESENT
-#endif
        /* The Linux PTE won't go exactly into the MMU TLB.
         * Software indicator bits 24, 25, 26, and 27 must be
         * set.  All other Linux PTE bits control the behavior
@@ -711,7 +679,7 @@ initial_mmu:
        li      r9, 4                           /* up to 4 pages of 8M */
        mtctr   r9
        lis     r9, KERNELBASE@h                /* Create vaddr for TLB */
-       li      r10, MI_PS8MEG | MI_SVALID      /* Set 8M byte page */
+       li      r10, MI_PS8MEG | _PMD_ACCESSED | MI_SVALID
        li      r11, MI_BOOTINIT                /* Create RPN for address 0 */
 1:
        mtspr   SPRN_MI_CTR, r8 /* Set instruction MMU control */
@@ -775,7 +743,7 @@ _GLOBAL(mmu_pin_tlb)
 #ifdef CONFIG_PIN_TLB_TEXT
        LOAD_REG_IMMEDIATE(r5, 28 << 8)
        LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
-       LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG)
+       LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
        LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT)
        LOAD_REG_ADDR(r9, _sinittext)
        li      r0, 4
@@ -797,7 +765,7 @@ _GLOBAL(mmu_pin_tlb)
        LOAD_REG_IMMEDIATE(r5, 28 << 8 | MD_TWAM)
 #ifdef CONFIG_PIN_TLB_DATA
        LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
-       LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG)
+       LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
 #ifdef CONFIG_PIN_TLB_IMMR
        li      r0, 3
 #else
@@ -834,7 +802,7 @@ _GLOBAL(mmu_pin_tlb)
 #endif
 #ifdef CONFIG_PIN_TLB_IMMR
        LOAD_REG_IMMEDIATE(r0, VIRT_IMMR_BASE | MD_EVALID)
-       LOAD_REG_IMMEDIATE(r7, MD_SVALID | MD_PS512K | MD_GUARDED)
+       LOAD_REG_IMMEDIATE(r7, MD_SVALID | MD_PS512K | MD_GUARDED | _PMD_ACCESSED)
        mfspr   r8, SPRN_IMMR
        rlwinm  r8, r8, 0, 0xfff80000
        ori     r8, r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | \
index 5eb9eedac920034e43de70e6e2a1b998f8209983..a0dda2a1f2df0aef3d880fd3dc09ddf672b331c6 100644 (file)
@@ -156,6 +156,7 @@ __after_mmu_off:
        bl      initial_bats
        bl      load_segment_registers
 BEGIN_MMU_FTR_SECTION
+       bl      reloc_offset
        bl      early_hash_table
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
 #if defined(CONFIG_BOOTX_TEXT)
@@ -457,11 +458,7 @@ InstructionTLBMiss:
        cmplw   0,r1,r3
 #endif
        mfspr   r2, SPRN_SPRG_PGDIR
-#ifdef CONFIG_SWAP
        li      r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
-#else
-       li      r1,_PAGE_PRESENT | _PAGE_EXEC
-#endif
 #if defined(CONFIG_MODULES) || defined(CONFIG_DEBUG_PAGEALLOC)
        bgt-    112f
        lis     r2, (swapper_pg_dir - PAGE_OFFSET)@ha   /* if kernel address, use */
@@ -523,11 +520,7 @@ DataLoadTLBMiss:
        lis     r1, TASK_SIZE@h         /* check if kernel address */
        cmplw   0,r1,r3
        mfspr   r2, SPRN_SPRG_PGDIR
-#ifdef CONFIG_SWAP
        li      r1, _PAGE_PRESENT | _PAGE_ACCESSED
-#else
-       li      r1, _PAGE_PRESENT
-#endif
        bgt-    112f
        lis     r2, (swapper_pg_dir - PAGE_OFFSET)@ha   /* if kernel address, use */
        addi    r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l        /* kernel page table */
@@ -603,11 +596,7 @@ DataStoreTLBMiss:
        lis     r1, TASK_SIZE@h         /* check if kernel address */
        cmplw   0,r1,r3
        mfspr   r2, SPRN_SPRG_PGDIR
-#ifdef CONFIG_SWAP
        li      r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED
-#else
-       li      r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT
-#endif
        bgt-    112f
        lis     r2, (swapper_pg_dir - PAGE_OFFSET)@ha   /* if kernel address, use */
        addi    r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l        /* kernel page table */
@@ -932,7 +921,7 @@ early_hash_table:
        ori     r6, r6, 3       /* 256kB table */
        mtspr   SPRN_SDR1, r6
        lis     r6, early_hash@h
-       lis     r3, Hash@ha
+       addis   r3, r3, Hash@ha
        stw     r6, Hash@l(r3)
        blr
 
index ae0e2632393d867bf866b1a58627fee691124ad7..1f835539fda420d7f6d0005a7da502da7d42c473 100644 (file)
@@ -52,9 +52,9 @@ void arch_cpu_idle(void)
                 * interrupts enabled, some don't.
                 */
                if (irqs_disabled())
-                       local_irq_enable();
+                       raw_local_irq_enable();
        } else {
-               local_irq_enable();
+               raw_local_irq_enable();
                /*
                 * Go into low thread priority and possibly
                 * low power mode.
index bb9cab3641d7d5b399b0663bee55204afad11cfc..74fd47f46fa586cb2b0e8465a6ee13d3fd09e460 100644 (file)
@@ -945,7 +945,13 @@ early_initcall(disable_hardlockup_detector);
 static enum l1d_flush_type enabled_flush_types;
 static void *l1d_flush_fallback_area;
 static bool no_rfi_flush;
+static bool no_entry_flush;
+static bool no_uaccess_flush;
 bool rfi_flush;
+bool entry_flush;
+bool uaccess_flush;
+DEFINE_STATIC_KEY_FALSE(uaccess_flush_key);
+EXPORT_SYMBOL(uaccess_flush_key);
 
 static int __init handle_no_rfi_flush(char *p)
 {
@@ -955,6 +961,22 @@ static int __init handle_no_rfi_flush(char *p)
 }
 early_param("no_rfi_flush", handle_no_rfi_flush);
 
+static int __init handle_no_entry_flush(char *p)
+{
+       pr_info("entry-flush: disabled on command line.");
+       no_entry_flush = true;
+       return 0;
+}
+early_param("no_entry_flush", handle_no_entry_flush);
+
+static int __init handle_no_uaccess_flush(char *p)
+{
+       pr_info("uaccess-flush: disabled on command line.");
+       no_uaccess_flush = true;
+       return 0;
+}
+early_param("no_uaccess_flush", handle_no_uaccess_flush);
+
 /*
  * The RFI flush is not KPTI, but because users will see doco that says to use
  * nopti we hijack that option here to also disable the RFI flush.
@@ -986,6 +1008,32 @@ void rfi_flush_enable(bool enable)
        rfi_flush = enable;
 }
 
+void entry_flush_enable(bool enable)
+{
+       if (enable) {
+               do_entry_flush_fixups(enabled_flush_types);
+               on_each_cpu(do_nothing, NULL, 1);
+       } else {
+               do_entry_flush_fixups(L1D_FLUSH_NONE);
+       }
+
+       entry_flush = enable;
+}
+
+void uaccess_flush_enable(bool enable)
+{
+       if (enable) {
+               do_uaccess_flush_fixups(enabled_flush_types);
+               static_branch_enable(&uaccess_flush_key);
+               on_each_cpu(do_nothing, NULL, 1);
+       } else {
+               static_branch_disable(&uaccess_flush_key);
+               do_uaccess_flush_fixups(L1D_FLUSH_NONE);
+       }
+
+       uaccess_flush = enable;
+}
+
 static void __ref init_fallback_flush(void)
 {
        u64 l1d_size, limit;
@@ -1044,10 +1092,28 @@ void setup_rfi_flush(enum l1d_flush_type types, bool enable)
 
        enabled_flush_types = types;
 
-       if (!no_rfi_flush && !cpu_mitigations_off())
+       if (!cpu_mitigations_off() && !no_rfi_flush)
                rfi_flush_enable(enable);
 }
 
+void setup_entry_flush(bool enable)
+{
+       if (cpu_mitigations_off())
+               return;
+
+       if (!no_entry_flush)
+               entry_flush_enable(enable);
+}
+
+void setup_uaccess_flush(bool enable)
+{
+       if (cpu_mitigations_off())
+               return;
+
+       if (!no_uaccess_flush)
+               uaccess_flush_enable(enable);
+}
+
 #ifdef CONFIG_DEBUG_FS
 static int rfi_flush_set(void *data, u64 val)
 {
@@ -1075,9 +1141,63 @@ static int rfi_flush_get(void *data, u64 *val)
 
 DEFINE_SIMPLE_ATTRIBUTE(fops_rfi_flush, rfi_flush_get, rfi_flush_set, "%llu\n");
 
+static int entry_flush_set(void *data, u64 val)
+{
+       bool enable;
+
+       if (val == 1)
+               enable = true;
+       else if (val == 0)
+               enable = false;
+       else
+               return -EINVAL;
+
+       /* Only do anything if we're changing state */
+       if (enable != entry_flush)
+               entry_flush_enable(enable);
+
+       return 0;
+}
+
+static int entry_flush_get(void *data, u64 *val)
+{
+       *val = entry_flush ? 1 : 0;
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_entry_flush, entry_flush_get, entry_flush_set, "%llu\n");
+
+static int uaccess_flush_set(void *data, u64 val)
+{
+       bool enable;
+
+       if (val == 1)
+               enable = true;
+       else if (val == 0)
+               enable = false;
+       else
+               return -EINVAL;
+
+       /* Only do anything if we're changing state */
+       if (enable != uaccess_flush)
+               uaccess_flush_enable(enable);
+
+       return 0;
+}
+
+static int uaccess_flush_get(void *data, u64 *val)
+{
+       *val = uaccess_flush ? 1 : 0;
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_uaccess_flush, uaccess_flush_get, uaccess_flush_set, "%llu\n");
+
 static __init int rfi_flush_debugfs_init(void)
 {
        debugfs_create_file("rfi_flush", 0600, powerpc_debugfs_root, NULL, &fops_rfi_flush);
+       debugfs_create_file("entry_flush", 0600, powerpc_debugfs_root, NULL, &fops_entry_flush);
+       debugfs_create_file("uaccess_flush", 0600, powerpc_debugfs_root, NULL, &fops_uaccess_flush);
        return 0;
 }
 device_initcall(rfi_flush_debugfs_init);
index 3c6b9822f9789b7524fe1cb29c17350986b851ae..8c2857cbd96097b25a3105ad533df080b50f534a 100644 (file)
@@ -1393,13 +1393,14 @@ static void add_cpu_to_masks(int cpu)
 /* Activate a secondary processor. */
 void start_secondary(void *unused)
 {
-       unsigned int cpu = smp_processor_id();
+       unsigned int cpu = raw_smp_processor_id();
 
        mmgrab(&init_mm);
        current->active_mm = &init_mm;
 
        smp_store_cpu_info(cpu);
        set_dec(tb_ticks_per_jiffy);
+       rcu_cpu_starting(cpu);
        preempt_disable();
        cpu_callin_map[cpu] = 1;
 
index 8e50818aa50bce04310f6389ce3d5efff082af39..310bcd768cd5a3d68e442035991650e8c68e3ab8 100644 (file)
@@ -2,7 +2,7 @@
 
 #include <linux/err.h>
 #include <asm/asm-prototypes.h>
-#include <asm/book3s/64/kup-radix.h>
+#include <asm/kup.h>
 #include <asm/cputime.h>
 #include <asm/hw_irq.h>
 #include <asm/kprobes.h>
index e0548b4950deb6be5e1a2f81cf29305f3949c065..6db90cdf11da8c74e08790772a351a727f1d3548 100644 (file)
@@ -131,6 +131,20 @@ SECTIONS
                __stop___stf_entry_barrier_fixup = .;
        }
 
+       . = ALIGN(8);
+       __uaccess_flush_fixup : AT(ADDR(__uaccess_flush_fixup) - LOAD_OFFSET) {
+               __start___uaccess_flush_fixup = .;
+               *(__uaccess_flush_fixup)
+               __stop___uaccess_flush_fixup = .;
+       }
+
+       . = ALIGN(8);
+       __entry_flush_fixup : AT(ADDR(__entry_flush_fixup) - LOAD_OFFSET) {
+               __start___entry_flush_fixup = .;
+               *(__entry_flush_fixup)
+               __stop___entry_flush_fixup = .;
+       }
+
        . = ALIGN(8);
        __stf_exit_barrier_fixup : AT(ADDR(__stf_exit_barrier_fixup) - LOAD_OFFSET) {
                __start___stf_exit_barrier_fixup = .;
index 85215e79db42cf11c1b5b6e78eafe32503a7b058..a0ebc29f30b27995f2b3d479c4b3df5bb3514c5b 100644 (file)
@@ -1214,12 +1214,9 @@ void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu)
 static bool kvmppc_xive_vcpu_id_valid(struct kvmppc_xive *xive, u32 cpu)
 {
        /* We have a block of xive->nr_servers VPs. We just need to check
-        * raw vCPU ids are below the expected limit for this guest's
-        * core stride ; kvmppc_pack_vcpu_id() will pack them down to an
-        * index that can be safely used to compute a VP id that belongs
-        * to the VP block.
+        * packed vCPU ids are below that.
         */
-       return cpu < xive->nr_servers * xive->kvm->arch.emul_smt_mode;
+       return kvmppc_pack_vcpu_id(xive->kvm, cpu) < xive->nr_servers;
 }
 
 int kvmppc_xive_compute_vp_id(struct kvmppc_xive *xive, u32 cpu, u32 *vp)
index d0c2db0e07fa2c683df30648d32ee18667d93d5b..a59a94f02733d0d3a1c18a9276d0212ed0e4d6e0 100644 (file)
@@ -251,6 +251,13 @@ static vm_fault_t xive_native_esb_fault(struct vm_fault *vmf)
        }
 
        state = &sb->irq_state[src];
+
+       /* Some sanity checking */
+       if (!state->valid) {
+               pr_devel("%s: source %lx invalid !\n", __func__, irq);
+               return VM_FAULT_SIGBUS;
+       }
+
        kvmppc_xive_select_irq(state, &hw_num, &xd);
 
        arch_spin_lock(&sb->lock);
index 4c0a7ee9fa000c0be78b629633eece27abc8ebbc..321c12a9ef6b8b1e1b7c37590932d111f97ce162 100644 (file)
@@ -234,6 +234,110 @@ void do_stf_barrier_fixups(enum stf_barrier_type types)
        do_stf_exit_barrier_fixups(types);
 }
 
+void do_uaccess_flush_fixups(enum l1d_flush_type types)
+{
+       unsigned int instrs[4], *dest;
+       long *start, *end;
+       int i;
+
+       start = PTRRELOC(&__start___uaccess_flush_fixup);
+       end = PTRRELOC(&__stop___uaccess_flush_fixup);
+
+       instrs[0] = 0x60000000; /* nop */
+       instrs[1] = 0x60000000; /* nop */
+       instrs[2] = 0x60000000; /* nop */
+       instrs[3] = 0x4e800020; /* blr */
+
+       i = 0;
+       if (types == L1D_FLUSH_FALLBACK) {
+               instrs[3] = 0x60000000; /* nop */
+               /* fallthrough to fallback flush */
+       }
+
+       if (types & L1D_FLUSH_ORI) {
+               instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
+               instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/
+       }
+
+       if (types & L1D_FLUSH_MTTRIG)
+               instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */
+
+       for (i = 0; start < end; start++, i++) {
+               dest = (void *)start + *start;
+
+               pr_devel("patching dest %lx\n", (unsigned long)dest);
+
+               patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
+
+               patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
+               patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
+               patch_instruction((struct ppc_inst *)(dest + 3), ppc_inst(instrs[3]));
+       }
+
+       printk(KERN_DEBUG "uaccess-flush: patched %d locations (%s flush)\n", i,
+               (types == L1D_FLUSH_NONE)       ? "no" :
+               (types == L1D_FLUSH_FALLBACK)   ? "fallback displacement" :
+               (types &  L1D_FLUSH_ORI)        ? (types & L1D_FLUSH_MTTRIG)
+                                                       ? "ori+mttrig type"
+                                                       : "ori type" :
+               (types &  L1D_FLUSH_MTTRIG)     ? "mttrig type"
+                                               : "unknown");
+}
+
+void do_entry_flush_fixups(enum l1d_flush_type types)
+{
+       unsigned int instrs[3], *dest;
+       long *start, *end;
+       int i;
+
+       start = PTRRELOC(&__start___entry_flush_fixup);
+       end = PTRRELOC(&__stop___entry_flush_fixup);
+
+       instrs[0] = 0x60000000; /* nop */
+       instrs[1] = 0x60000000; /* nop */
+       instrs[2] = 0x60000000; /* nop */
+
+       i = 0;
+       if (types == L1D_FLUSH_FALLBACK) {
+               instrs[i++] = 0x7d4802a6; /* mflr r10           */
+               instrs[i++] = 0x60000000; /* branch patched below */
+               instrs[i++] = 0x7d4803a6; /* mtlr r10           */
+       }
+
+       if (types & L1D_FLUSH_ORI) {
+               instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
+               instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/
+       }
+
+       if (types & L1D_FLUSH_MTTRIG)
+               instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */
+
+       for (i = 0; start < end; start++, i++) {
+               dest = (void *)start + *start;
+
+               pr_devel("patching dest %lx\n", (unsigned long)dest);
+
+               patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
+
+               if (types == L1D_FLUSH_FALLBACK)
+                       patch_branch((struct ppc_inst *)(dest + 1), (unsigned long)&entry_flush_fallback,
+                                    BRANCH_SET_LINK);
+               else
+                       patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
+
+               patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
+       }
+
+       printk(KERN_DEBUG "entry-flush: patched %d locations (%s flush)\n", i,
+               (types == L1D_FLUSH_NONE)       ? "no" :
+               (types == L1D_FLUSH_FALLBACK)   ? "fallback displacement" :
+               (types &  L1D_FLUSH_ORI)        ? (types & L1D_FLUSH_MTTRIG)
+                                                       ? "ori+mttrig type"
+                                                       : "ori type" :
+               (types &  L1D_FLUSH_MTTRIG)     ? "mttrig type"
+                                               : "unknown");
+}
+
 void do_rfi_flush_fixups(enum l1d_flush_type types)
 {
        unsigned int instrs[3], *dest;
index 0203cdf48c5476d178b7cb438e21af9c6f2a659f..52e170bd95ae1739658c35be14a6d5174cfe5f74 100644 (file)
@@ -68,7 +68,7 @@ static __always_inline void tlbiel_hash_set_isa300(unsigned int set, unsigned in
        rs = ((unsigned long)pid << PPC_BITLSHIFT(31));
 
        asm volatile(PPC_TLBIEL(%0, %1, %2, %3, %4)
-                    : : "r"(rb), "r"(rs), "i"(ric), "i"(prs), "r"(r)
+                    : : "r"(rb), "r"(rs), "i"(ric), "i"(prs), "i"(r)
                     : "memory");
 }
 
@@ -92,16 +92,15 @@ static void tlbiel_all_isa300(unsigned int num_sets, unsigned int is)
        asm volatile("ptesync": : :"memory");
 
        /*
-        * Flush the first set of the TLB, and any caching of partition table
-        * entries. Then flush the remaining sets of the TLB. Hash mode uses
-        * partition scoped TLB translations.
+        * Flush the partition table cache if this is HV mode.
         */
-       tlbiel_hash_set_isa300(0, is, 0, 2, 0);
-       for (set = 1; set < num_sets; set++)
-               tlbiel_hash_set_isa300(set, is, 0, 0, 0);
+       if (early_cpu_has_feature(CPU_FTR_HVMODE))
+               tlbiel_hash_set_isa300(0, is, 0, 2, 0);
 
        /*
-        * Now invalidate the process table cache.
+        * Now invalidate the process table cache. UPRT=0 HPT modes (what
+        * current hardware implements) do not use the process table, but
+        * add the flushes anyway.
         *
         * From ISA v3.0B p. 1078:
         *     The following forms are invalid.
@@ -110,6 +109,14 @@ static void tlbiel_all_isa300(unsigned int num_sets, unsigned int is)
         */
        tlbiel_hash_set_isa300(0, is, 0, 2, 1);
 
+       /*
+        * Then flush the sets of the TLB proper. Hash mode uses
+        * partition scoped TLB translations, which may be flushed
+        * in !HV mode.
+        */
+       for (set = 0; set < num_sets; set++)
+               tlbiel_hash_set_isa300(set, is, 0, 0, 0);
+
        ppc_after_tlbiel_barrier();
 
        asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT "; isync" : : :"memory");
index 1c54821de7bfb58a132d2e846b570517087bc594..0c8557220ae28a328a44dbc80d47b7f86be08f60 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/export.h>
 #include <linux/gfp.h>
 #include <linux/slab.h>
+#include <linux/cpu.h>
 
 #include <asm/mmu_context.h>
 #include <asm/pgalloc.h>
@@ -307,3 +308,22 @@ void radix__switch_mmu_context(struct mm_struct *prev, struct mm_struct *next)
        isync();
 }
 #endif
+
+/**
+ * cleanup_cpu_mmu_context - Clean up MMU details for this CPU (newly offlined)
+ *
+ * This clears the CPU from mm_cpumask for all processes, and then flushes the
+ * local TLB to ensure TLB coherency in case the CPU is onlined again.
+ *
+ * KVM guest translations are not necessarily flushed here. If KVM started
+ * using mm_cpumask or the Linux APIs which do, this would have to be resolved.
+ */
+#ifdef CONFIG_HOTPLUG_CPU
+void cleanup_cpu_mmu_context(void)
+{
+       int cpu = smp_processor_id();
+
+       clear_tasks_mm_cpumask(cpu);
+       tlbiel_all();
+}
+#endif
index 01ec2a252f09122997db8dc9e6bc186b1005ed0c..3fc325bebe4dff309192e1195318f1d88027bb0d 100644 (file)
@@ -50,6 +50,7 @@
 #include <asm/rtas.h>
 #include <asm/kasan.h>
 #include <asm/svm.h>
+#include <asm/mmzone.h>
 
 #include <mm/mmu_decl.h>
 
index 63f61d8b55e5033e7402beb8668f7180d2fe6292..f2bf98bdcea28f12fdbc201ae744e2d4ca2ceaed 100644 (file)
@@ -742,8 +742,7 @@ static int __init parse_numa_properties(void)
                        of_node_put(cpu);
                }
 
-               if (likely(nid > 0))
-                       node_set_online(nid);
+               node_set_online(nid);
        }
 
        get_n_mem_cells(&n_mem_addr_cells, &n_mem_size_cells);
index 9ed4fcccf8a9b14cee08c84ace2fe188db6c7baf..7b25548ec42b0db3ae872adce803de2a75ef9e03 100644 (file)
@@ -1336,7 +1336,7 @@ static void dump_trace_imc_data(struct perf_event *event)
                        /* If this is a valid record, create the sample */
                        struct perf_output_handle handle;
 
-                       if (perf_output_begin(&handle, event, header.size))
+                       if (perf_output_begin(&handle, &data, event, header.size))
                                return;
 
                        perf_output_sample(&handle, &header, &data, event);
index 8e53f2fc3fe07f3e5b782f067094e50bb94fa33d..6f681b105eec21bb1d0375f136aaea0e6a71da1a 100644 (file)
@@ -144,8 +144,7 @@ u64 perf_reg_abi(struct task_struct *task)
 }
 
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
        regs_user->regs = task_pt_regs(current);
        regs_user->abi = (regs_user->regs) ? perf_reg_abi(current) :
index 74ebe664b01688851cea4cf0bfb132c635586072..adae2a6712e11f92860ea8d52b317cdef512e44b 100644 (file)
@@ -911,6 +911,8 @@ static int smp_core99_cpu_disable(void)
 
        mpic_cpu_set_priority(0xf);
 
+       cleanup_cpu_mmu_context();
+
        return 0;
 }
 
index 9acaa0f131b96e6cd6a3b1d63b487640da52e5e3..4426a109ec2f4390044e74a62218166bd5805292 100644 (file)
@@ -98,7 +98,7 @@ static void init_fw_feat_flags(struct device_node *np)
                security_ftr_clear(SEC_FTR_BNDS_CHK_SPEC_BAR);
 }
 
-static void pnv_setup_rfi_flush(void)
+static void pnv_setup_security_mitigations(void)
 {
        struct device_node *np, *fw_features;
        enum l1d_flush_type type;
@@ -122,12 +122,31 @@ static void pnv_setup_rfi_flush(void)
                        type = L1D_FLUSH_ORI;
        }
 
+       /*
+        * If we are non-Power9 bare metal, we don't need to flush on kernel
+        * entry or after user access: they fix a P9 specific vulnerability.
+        */
+       if (!pvr_version_is(PVR_POWER9)) {
+               security_ftr_clear(SEC_FTR_L1D_FLUSH_ENTRY);
+               security_ftr_clear(SEC_FTR_L1D_FLUSH_UACCESS);
+       }
+
        enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && \
                 (security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR)   || \
                  security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV));
 
        setup_rfi_flush(type, enable);
        setup_count_cache_flush();
+
+       enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
+                security_ftr_enabled(SEC_FTR_L1D_FLUSH_ENTRY);
+       setup_entry_flush(enable);
+
+       enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
+                security_ftr_enabled(SEC_FTR_L1D_FLUSH_UACCESS);
+       setup_uaccess_flush(enable);
+
+       setup_stf_barrier();
 }
 
 static void __init pnv_check_guarded_cores(void)
@@ -156,8 +175,7 @@ static void __init pnv_setup_arch(void)
 {
        set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT);
 
-       pnv_setup_rfi_flush();
-       setup_stf_barrier();
+       pnv_setup_security_mitigations();
 
        /* Initialize SMP */
        pnv_smp_init();
@@ -193,11 +211,16 @@ static void __init pnv_init(void)
                add_preferred_console("hvc", 0, NULL);
 
        if (!radix_enabled()) {
+               size_t size = sizeof(struct slb_entry) * mmu_slb_size;
                int i;
 
                /* Allocate per cpu area to save old slb contents during MCE */
-               for_each_possible_cpu(i)
-                       paca_ptrs[i]->mce_faulty_slbs = memblock_alloc_node(mmu_slb_size, __alignof__(*paca_ptrs[i]->mce_faulty_slbs), cpu_to_node(i));
+               for_each_possible_cpu(i) {
+                       paca_ptrs[i]->mce_faulty_slbs =
+                                       memblock_alloc_node(size,
+                                               __alignof__(struct slb_entry),
+                                               cpu_to_node(i));
+               }
        }
 }
 
index 54c4ba45c7ce8f07c45c1e718bcde917021f47f2..cbb67813cd5df2babcf58477ae014feda352a57d 100644 (file)
@@ -143,6 +143,9 @@ static int pnv_smp_cpu_disable(void)
                xive_smp_disable_cpu();
        else
                xics_migrate_irqs_away();
+
+       cleanup_cpu_mmu_context();
+
        return 0;
 }
 
index f2837e33bf5d91ede0a8e9e56de1cd284c71b588..a02012f1b04afdc4c74d4cb1955d398606e37856 100644 (file)
@@ -90,6 +90,9 @@ static int pseries_cpu_disable(void)
                xive_smp_disable_cpu();
        else
                xics_migrate_irqs_away();
+
+       cleanup_cpu_mmu_context();
+
        return 0;
 }
 
index d6f4162478a505448acfac6d64907f3a7824fc1d..2f73cb5bf12d5635f81a63a5fdb7ab7e53dda0d3 100644 (file)
@@ -349,8 +349,8 @@ void post_mobility_fixup(void)
 
        cpus_read_unlock();
 
-       /* Possibly switch to a new RFI flush type */
-       pseries_setup_rfi_flush();
+       /* Possibly switch to a new L1 flush type */
+       pseries_setup_security_mitigations();
 
        /* Reinitialise system information for hv-24x7 */
        read_24x7_sys_info();
index 133f6adcb39cb5167aa4057cc12e5feca55fe5d2..b3ac2455faadc51cdfcb45a251dc112d1df0a5d4 100644 (file)
@@ -458,7 +458,8 @@ again:
                        return hwirq;
                }
 
-               virq = irq_create_mapping(NULL, hwirq);
+               virq = irq_create_mapping_affinity(NULL, hwirq,
+                                                  entry->affinity);
 
                if (!virq) {
                        pr_debug("rtas_msi: Failed mapping hwirq %d\n", hwirq);
index 13fa370a87e4eb0d660482060a3b3d424483b559..593840847cd3dc83324ee4c157c1afaeff3efe16 100644 (file)
@@ -111,7 +111,7 @@ static inline unsigned long cmo_get_page_size(void)
 
 int dlpar_workqueue_init(void);
 
-void pseries_setup_rfi_flush(void);
+void pseries_setup_security_mitigations(void);
 void pseries_lpar_read_hblkrm_characteristics(void);
 
 #endif /* _PSERIES_PSERIES_H */
index 633c45ec406da897d89f1228ddf1281830be575a..090c13f6c8815c67992f8f55dec929faac3bbfb2 100644 (file)
@@ -542,7 +542,7 @@ static void init_cpu_char_feature_flags(struct h_cpu_char_result *result)
                security_ftr_clear(SEC_FTR_BNDS_CHK_SPEC_BAR);
 }
 
-void pseries_setup_rfi_flush(void)
+void pseries_setup_security_mitigations(void)
 {
        struct h_cpu_char_result result;
        enum l1d_flush_type types;
@@ -579,6 +579,16 @@ void pseries_setup_rfi_flush(void)
 
        setup_rfi_flush(types, enable);
        setup_count_cache_flush();
+
+       enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
+                security_ftr_enabled(SEC_FTR_L1D_FLUSH_ENTRY);
+       setup_entry_flush(enable);
+
+       enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
+                security_ftr_enabled(SEC_FTR_L1D_FLUSH_UACCESS);
+       setup_uaccess_flush(enable);
+
+       setup_stf_barrier();
 }
 
 #ifdef CONFIG_PCI_IOV
@@ -768,8 +778,7 @@ static void __init pSeries_setup_arch(void)
 
        fwnmi_init();
 
-       pseries_setup_rfi_flush();
-       setup_stf_barrier();
+       pseries_setup_security_mitigations();
        pseries_lpar_read_hblkrm_characteristics();
 
        /* By default, only probe PCI (can be overridden by rtas_pci) */
index b0ab66e5fdb1d54e25bd2c7ede74e2187f9cb6d1..5b2e79e5bfa5bf8af384e64e3ca1888b2ff4df92 100644 (file)
@@ -14,4 +14,6 @@
 #define PGDIR_SIZE      (_AC(1, UL) << PGDIR_SHIFT)
 #define PGDIR_MASK      (~(PGDIR_SIZE - 1))
 
+#define MAX_POSSIBLE_PHYSMEM_BITS 34
+
 #endif /* _ASM_RISCV_PGTABLE_32_H */
index c47e6b35c551f4a8500d3bd3200528b46ce3a034..824b2c9da75bd2095274c2ef73933944cc900845 100644 (file)
@@ -476,7 +476,7 @@ do {                                                                        \
 do {                                                                   \
        long __kr_err;                                                  \
                                                                        \
-       __put_user_nocheck(*((type *)(dst)), (type *)(src), __kr_err);  \
+       __put_user_nocheck(*((type *)(src)), (type *)(dst), __kr_err);  \
        if (unlikely(__kr_err))                                         \
                goto err_label;                                         \
 } while (0)
index 82a5693b18614e10cb1f36052e690ba0af12fd41..134388cbaaa1d3ba1bdc5c5b7a765327006c1732 100644 (file)
@@ -4,6 +4,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include <asm/barrier.h>
+
 static inline void cpu_relax(void)
 {
 #ifdef __riscv_muldiv
index 99e12faa54986a3c32e26b6dc34ee4cf8f45b22c..765b62434f303d2c99f63b82be3799725b82e5dc 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2013 Linaro Limited
  * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
index 11e2a4fe66e0af9bb0650cf2156432f9c965fad6..7e849797c9c38ddc81311787dcf5188ba9de7a02 100644 (file)
@@ -35,12 +35,17 @@ ENTRY(_start)
        .word 0
 #endif
        .balign 8
+#ifdef CONFIG_RISCV_M_MODE
+       /* Image load offset (0MB) from start of RAM for M-mode */
+       .dword 0
+#else
 #if __riscv_xlen == 64
        /* Image load offset(2MB) from start of RAM */
        .dword 0x200000
 #else
        /* Image load offset(4MB) from start of RAM */
        .dword 0x400000
+#endif
 #endif
        /* Effective size of kernel image */
        .dword _end - _start
index 04a38fbeb9c7a1e3322abceb9ce7c739faf48a55..fd304a248de68a02c8dcd3ceb58fc8bb4ea8b83f 100644 (file)
@@ -36,8 +36,7 @@ u64 perf_reg_abi(struct task_struct *task)
 }
 
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
        regs_user->regs = task_pt_regs(current);
        regs_user->abi = perf_reg_abi(current);
index 19225ec65db62f608f14493009410711a99b2783..dd5f985b1f40e0418f4bdac872819275a0766cd0 100644 (file)
@@ -36,7 +36,7 @@ extern asmlinkage void ret_from_kernel_thread(void);
 void arch_cpu_idle(void)
 {
        wait_for_interrupt();
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 
 void show_regs(struct pt_regs *regs)
index c424cc6dd833687d9f60b0d9bfe0a0ea2c3a8bc4..117f3212a8e4b767ad0376f37c8a543b2c74a239 100644 (file)
@@ -75,6 +75,7 @@ void __init setup_arch(char **cmdline_p)
        *cmdline_p = boot_command_line;
 
        early_ioremap_setup();
+       jump_label_init();
        parse_early_param();
 
        efi_init();
index 11ebee9e4c1d6fdbe684acc3283ff6eade12335e..3a19def868eccd8c5544a6629592be0932204646 100644 (file)
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 vdso.lds
 *.tmp
+vdso-syms.S
index 7d6a94d45ec94190234f74994fffbf3491741732..0cfd6da784f84187487a369b479a6dabd41dbbc8 100644 (file)
@@ -43,19 +43,14 @@ $(obj)/vdso.o: $(obj)/vdso.so
 SYSCFLAGS_vdso.so.dbg = $(c_flags)
 $(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) FORCE
        $(call if_changed,vdsold)
+SYSCFLAGS_vdso.so.dbg = -shared -s -Wl,-soname=linux-vdso.so.1 \
+       -Wl,--build-id=sha1 -Wl,--hash-style=both
 
 # We also create a special relocatable object that should mirror the symbol
 # table and layout of the linked DSO. With ld --just-symbols we can then
 # refer to these symbols in the kernel code rather than hand-coded addresses.
-
-SYSCFLAGS_vdso.so.dbg = -shared -s -Wl,-soname=linux-vdso.so.1 \
-       -Wl,--build-id=sha1 -Wl,--hash-style=both
-$(obj)/vdso-dummy.o: $(src)/vdso.lds $(obj)/rt_sigreturn.o FORCE
-       $(call if_changed,vdsold)
-
-LDFLAGS_vdso-syms.o := -r --just-symbols
-$(obj)/vdso-syms.o: $(obj)/vdso-dummy.o FORCE
-       $(call if_changed,ld)
+$(obj)/vdso-syms.S: $(obj)/vdso.so FORCE
+       $(call if_changed,so2s)
 
 # strip rule for the .so file
 $(obj)/%.so: OBJCOPYFLAGS := -S
@@ -73,6 +68,11 @@ quiet_cmd_vdsold = VDSOLD  $@
                            $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ && \
                    rm $@.tmp
 
+# Extracts symbol offsets from the VDSO, converting them into an assembly file
+# that contains the same symbols at the same offsets.
+quiet_cmd_so2s = SO2S    $@
+      cmd_so2s = $(NM) -D $< | $(srctree)/$(src)/so2s.sh > $@
+
 # install commands for the unstripped file
 quiet_cmd_vdso_install = INSTALL $@
       cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
diff --git a/arch/riscv/kernel/vdso/so2s.sh b/arch/riscv/kernel/vdso/so2s.sh
new file mode 100755 (executable)
index 0000000..e64cb6d
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2020 Palmer Dabbelt <palmerdabbelt@google.com>
+
+sed 's!\([0-9a-f]*\) T \([a-z0-9_]*\)\(@@LINUX_4.15\)*!.global \2\n.set \2,0x\1!' \
+| grep '^\.'
index 1359e21c0c62a8d7f4e90e174ee8948e9072aedd..3c8b9e433c673754e29444ffe2e75883c8ce0e99 100644 (file)
@@ -86,6 +86,7 @@ static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long a
        pmd_t *pmd, *pmd_k;
        pte_t *pte_k;
        int index;
+       unsigned long pfn;
 
        /* User mode accesses just cause a SIGSEGV */
        if (user_mode(regs))
@@ -100,7 +101,8 @@ static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long a
         * of a task switch.
         */
        index = pgd_index(addr);
-       pgd = (pgd_t *)pfn_to_virt(csr_read(CSR_SATP)) + index;
+       pfn = csr_read(CSR_SATP) & SATP_PPN;
+       pgd = (pgd_t *)pfn_to_virt(pfn) + index;
        pgd_k = init_mm.pgd + index;
 
        if (!pgd_present(*pgd_k)) {
index ea933b789a882f29bec8b1f81892747764b7de3e..8e577f14f1205d67eaf3ec44b0df941a598da0a6 100644 (file)
@@ -154,9 +154,8 @@ disable:
 
 void __init setup_bootmem(void)
 {
-       phys_addr_t mem_size = 0;
-       phys_addr_t total_mem = 0;
-       phys_addr_t mem_start, start, end = 0;
+       phys_addr_t mem_start = 0;
+       phys_addr_t start, end = 0;
        phys_addr_t vmlinux_end = __pa_symbol(&_end);
        phys_addr_t vmlinux_start = __pa_symbol(&_start);
        u64 i;
@@ -164,21 +163,18 @@ void __init setup_bootmem(void)
        /* Find the memory region containing the kernel */
        for_each_mem_range(i, &start, &end) {
                phys_addr_t size = end - start;
-               if (!total_mem)
+               if (!mem_start)
                        mem_start = start;
                if (start <= vmlinux_start && vmlinux_end <= end)
                        BUG_ON(size == 0);
-               total_mem = total_mem + size;
        }
 
        /*
-        * Remove memblock from the end of usable area to the
-        * end of region
+        * The maximal physical memory size is -PAGE_OFFSET.
+        * Make sure that any memory beyond mem_start + (-PAGE_OFFSET) is removed
+        * as it is unusable by kernel.
         */
-       mem_size = min(total_mem, (phys_addr_t)-PAGE_OFFSET);
-       if (mem_start + mem_size < end)
-               memblock_remove(mem_start + mem_size,
-                               end - mem_start - mem_size);
+       memblock_enforce_memory_limit(mem_start - PAGE_OFFSET);
 
        /* Reserve from the start of the kernel to the end of the kernel */
        memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);
@@ -297,6 +293,7 @@ pmd_t fixmap_pmd[PTRS_PER_PMD] __page_aligned_bss;
 #define NUM_EARLY_PMDS         (1UL + MAX_EARLY_MAPPING_SIZE / PGDIR_SIZE)
 #endif
 pmd_t early_pmd[PTRS_PER_PMD * NUM_EARLY_PMDS] __initdata __aligned(PAGE_SIZE);
+pmd_t early_dtb_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE);
 
 static pmd_t *__init get_pmd_virt_early(phys_addr_t pa)
 {
@@ -494,6 +491,18 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
                                   load_pa + (va - PAGE_OFFSET),
                                   map_size, PAGE_KERNEL_EXEC);
 
+#ifndef __PAGETABLE_PMD_FOLDED
+       /* Setup early PMD for DTB */
+       create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA,
+                          (uintptr_t)early_dtb_pmd, PGDIR_SIZE, PAGE_TABLE);
+       /* Create two consecutive PMD mappings for FDT early scan */
+       pa = dtb_pa & ~(PMD_SIZE - 1);
+       create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA,
+                          pa, PMD_SIZE, PAGE_KERNEL);
+       create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA + PMD_SIZE,
+                          pa + PMD_SIZE, PMD_SIZE, PAGE_KERNEL);
+       dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PMD_SIZE - 1));
+#else
        /* Create two consecutive PGD mappings for FDT early scan */
        pa = dtb_pa & ~(PGDIR_SIZE - 1);
        create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA,
@@ -501,6 +510,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
        create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA + PGDIR_SIZE,
                           pa + PGDIR_SIZE, PGDIR_SIZE, PAGE_KERNEL);
        dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PGDIR_SIZE - 1));
+#endif
        dtb_early_pa = dtb_pa;
 
        /*
index 0784bf3caf43d95a732a0b0b96d418c8b8c15de8..fe6f529ac82cf27bf23e3d50b1a4017d39d9f746 100644 (file)
@@ -1,3 +1,4 @@
+CONFIG_UAPI_HEADER_TEST=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_WATCH_QUEUE=y
@@ -93,9 +94,10 @@ CONFIG_CLEANCACHE=y
 CONFIG_FRONTSWAP=y
 CONFIG_CMA_DEBUG=y
 CONFIG_CMA_DEBUGFS=y
+CONFIG_CMA_AREAS=7
 CONFIG_MEM_SOFT_DIRTY=y
 CONFIG_ZSWAP=y
-CONFIG_ZSMALLOC=m
+CONFIG_ZSMALLOC=y
 CONFIG_ZSMALLOC_STAT=y
 CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
 CONFIG_IDLE_PAGE_TRACKING=y
@@ -378,7 +380,6 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_CGROUP_NET_PRIO=y
 CONFIG_BPF_JIT=y
 CONFIG_NET_PKTGEN=m
-# CONFIG_NET_DROP_MONITOR is not set
 CONFIG_PCI=y
 # CONFIG_PCIEASPM is not set
 CONFIG_PCI_DEBUG=y
@@ -386,7 +387,7 @@ CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_S390=y
 CONFIG_DEVTMPFS=y
 CONFIG_CONNECTOR=y
-CONFIG_ZRAM=m
+CONFIG_ZRAM=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_DRBD=m
@@ -689,6 +690,7 @@ CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_DH=m
 CONFIG_CRYPTO_ECDH=m
 CONFIG_CRYPTO_ECRDSA=m
+CONFIG_CRYPTO_SM2=m
 CONFIG_CRYPTO_CURVE25519=m
 CONFIG_CRYPTO_GCM=y
 CONFIG_CRYPTO_CHACHA20POLY1305=m
@@ -709,7 +711,6 @@ CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
 CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_AES_TI=m
@@ -753,6 +754,7 @@ CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_CRC32_S390=y
+CONFIG_CRYPTO_DEV_VIRTIO=m
 CONFIG_CORDIC=m
 CONFIG_CRC32_SELFTEST=y
 CONFIG_CRC4=m
@@ -829,6 +831,7 @@ CONFIG_NETDEV_NOTIFIER_ERROR_INJECT=m
 CONFIG_FAULT_INJECTION=y
 CONFIG_FAILSLAB=y
 CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAULT_INJECTION_USERCOPY=y
 CONFIG_FAIL_MAKE_REQUEST=y
 CONFIG_FAIL_IO_TIMEOUT=y
 CONFIG_FAIL_FUTEX=y
index 905bc8c4cfaf5ee63dae4c5646b0ad5ecefa70a3..17d5df2c1eff34833f81fd8d6ad29c39a9aa0ec4 100644 (file)
@@ -87,9 +87,10 @@ CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_CLEANCACHE=y
 CONFIG_FRONTSWAP=y
+CONFIG_CMA_AREAS=7
 CONFIG_MEM_SOFT_DIRTY=y
 CONFIG_ZSWAP=y
-CONFIG_ZSMALLOC=m
+CONFIG_ZSMALLOC=y
 CONFIG_ZSMALLOC_STAT=y
 CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
 CONFIG_IDLE_PAGE_TRACKING=y
@@ -371,7 +372,6 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_CGROUP_NET_PRIO=y
 CONFIG_BPF_JIT=y
 CONFIG_NET_PKTGEN=m
-# CONFIG_NET_DROP_MONITOR is not set
 CONFIG_PCI=y
 # CONFIG_PCIEASPM is not set
 CONFIG_HOTPLUG_PCI=y
@@ -379,7 +379,7 @@ CONFIG_HOTPLUG_PCI_S390=y
 CONFIG_UEVENT_HELPER=y
 CONFIG_DEVTMPFS=y
 CONFIG_CONNECTOR=y
-CONFIG_ZRAM=m
+CONFIG_ZRAM=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_DRBD=m
@@ -680,6 +680,7 @@ CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_DH=m
 CONFIG_CRYPTO_ECDH=m
 CONFIG_CRYPTO_ECRDSA=m
+CONFIG_CRYPTO_SM2=m
 CONFIG_CRYPTO_CURVE25519=m
 CONFIG_CRYPTO_GCM=y
 CONFIG_CRYPTO_CHACHA20POLY1305=m
@@ -701,7 +702,6 @@ CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
 CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_AES_TI=m
@@ -745,6 +745,7 @@ CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_CRC32_S390=y
+CONFIG_CRYPTO_DEV_VIRTIO=m
 CONFIG_CORDIC=m
 CONFIG_PRIME_NUMBERS=m
 CONFIG_CRC4=m
index 8f67c55625f9eb0f744ebc529361f6a97d80a4dd..a302630341effc410cbc1587663639f94b75920d 100644 (file)
@@ -17,11 +17,11 @@ CONFIG_HZ_100=y
 # CONFIG_CHSC_SCH is not set
 # CONFIG_SCM_BUS is not set
 CONFIG_CRASH_DUMP=y
-# CONFIG_SECCOMP is not set
 # CONFIG_PFAULT is not set
 # CONFIG_S390_HYPFS_FS is not set
 # CONFIG_VIRTUALIZATION is not set
 # CONFIG_S390_GUEST is not set
+# CONFIG_SECCOMP is not set
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
index 6b8d8c69b1a116a4fb1d8c42f877544697c31713..b5dbae78969b9876dc24c29c22e9a69298b5478b 100644 (file)
@@ -692,16 +692,6 @@ static inline int pud_large(pud_t pud)
        return !!(pud_val(pud) & _REGION3_ENTRY_LARGE);
 }
 
-static inline unsigned long pud_pfn(pud_t pud)
-{
-       unsigned long origin_mask;
-
-       origin_mask = _REGION_ENTRY_ORIGIN;
-       if (pud_large(pud))
-               origin_mask = _REGION3_ENTRY_ORIGIN_LARGE;
-       return (pud_val(pud) & origin_mask) >> PAGE_SHIFT;
-}
-
 #define pmd_leaf       pmd_large
 static inline int pmd_large(pmd_t pmd)
 {
@@ -747,16 +737,6 @@ static inline int pmd_none(pmd_t pmd)
        return pmd_val(pmd) == _SEGMENT_ENTRY_EMPTY;
 }
 
-static inline unsigned long pmd_pfn(pmd_t pmd)
-{
-       unsigned long origin_mask;
-
-       origin_mask = _SEGMENT_ENTRY_ORIGIN;
-       if (pmd_large(pmd))
-               origin_mask = _SEGMENT_ENTRY_ORIGIN_LARGE;
-       return (pmd_val(pmd) & origin_mask) >> PAGE_SHIFT;
-}
-
 #define pmd_write pmd_write
 static inline int pmd_write(pmd_t pmd)
 {
@@ -1238,11 +1218,39 @@ static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)
 #define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
 #define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
 
-#define pmd_deref(pmd) (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN)
-#define pud_deref(pud) (pud_val(pud) & _REGION_ENTRY_ORIGIN)
 #define p4d_deref(pud) (p4d_val(pud) & _REGION_ENTRY_ORIGIN)
 #define pgd_deref(pgd) (pgd_val(pgd) & _REGION_ENTRY_ORIGIN)
 
+static inline unsigned long pmd_deref(pmd_t pmd)
+{
+       unsigned long origin_mask;
+
+       origin_mask = _SEGMENT_ENTRY_ORIGIN;
+       if (pmd_large(pmd))
+               origin_mask = _SEGMENT_ENTRY_ORIGIN_LARGE;
+       return pmd_val(pmd) & origin_mask;
+}
+
+static inline unsigned long pmd_pfn(pmd_t pmd)
+{
+       return pmd_deref(pmd) >> PAGE_SHIFT;
+}
+
+static inline unsigned long pud_deref(pud_t pud)
+{
+       unsigned long origin_mask;
+
+       origin_mask = _REGION_ENTRY_ORIGIN;
+       if (pud_large(pud))
+               origin_mask = _REGION3_ENTRY_ORIGIN_LARGE;
+       return pud_val(pud) & origin_mask;
+}
+
+static inline unsigned long pud_pfn(pud_t pud)
+{
+       return pud_deref(pud) >> PAGE_SHIFT;
+}
+
 /*
  * The pgd_offset function *always* adds the index for the top-level
  * region/segment table. This is done to get a sequence like the
index a996d3990a02b211ddf6d0c5bb6cab7a9ad798be..0c2151451ba593be330d1252f8609d9c53cb762b 100644 (file)
@@ -26,14 +26,14 @@ static inline int arch_is_kernel_initmem_freed(unsigned long addr)
  * final .boot.data section, which should be identical in the decompressor and
  * the decompressed kernel (that is checked during the build).
  */
-#define __bootdata(var) __section(".boot.data.var") var
+#define __bootdata(var) __section(".boot.data." #var) var
 
 /*
  * .boot.preserved.data is similar to .boot.data, but it is not part of the
  * .init section and thus will be preserved for later use in the decompressed
  * kernel.
  */
-#define __bootdata_preserved(var) __section(".boot.preserved.data.var") var
+#define __bootdata_preserved(var) __section(".boot.preserved.data." #var) var
 
 extern unsigned long __sdma, __edma;
 extern unsigned long __stext_dma, __etext_dma;
diff --git a/arch/s390/include/asm/vdso/vdso.h b/arch/s390/include/asm/vdso/vdso.h
deleted file mode 100644 (file)
index e69de29..0000000
index ece58f2217cbe20d3a10974a607a08b7e8fbdcee..483051e10db3890cb2ca58a9fe12ee5344438495 100644 (file)
@@ -53,22 +53,14 @@ int main(void)
        /* stack_frame offsets */
        OFFSET(__SF_BACKCHAIN, stack_frame, back_chain);
        OFFSET(__SF_GPRS, stack_frame, gprs);
-       OFFSET(__SF_EMPTY, stack_frame, empty1);
-       OFFSET(__SF_SIE_CONTROL, stack_frame, empty1[0]);
-       OFFSET(__SF_SIE_SAVEAREA, stack_frame, empty1[1]);
-       OFFSET(__SF_SIE_REASON, stack_frame, empty1[2]);
-       OFFSET(__SF_SIE_FLAGS, stack_frame, empty1[3]);
+       OFFSET(__SF_EMPTY, stack_frame, empty1[0]);
+       OFFSET(__SF_SIE_CONTROL, stack_frame, empty1[1]);
+       OFFSET(__SF_SIE_SAVEAREA, stack_frame, empty1[2]);
+       OFFSET(__SF_SIE_REASON, stack_frame, empty1[3]);
+       OFFSET(__SF_SIE_FLAGS, stack_frame, empty1[4]);
        BLANK();
        OFFSET(__VDSO_GETCPU_VAL, vdso_per_cpu_data, getcpu_val);
        BLANK();
-       /* constants used by the vdso */
-       DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME);
-       DEFINE(__CLOCK_MONOTONIC, CLOCK_MONOTONIC);
-       DEFINE(__CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE);
-       DEFINE(__CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_COARSE);
-       DEFINE(__CLOCK_THREAD_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID);
-       DEFINE(__CLOCK_COARSE_RES, LOW_RES_NSEC);
-       BLANK();
        /* idle data offsets */
        OFFSET(__CLOCK_IDLE_ENTER, s390_idle_data, clock_idle_enter);
        OFFSET(__CLOCK_IDLE_EXIT, s390_idle_data, clock_idle_exit);
index 86235919c2d15fe2f2fe855c39a4e4c9ba300f08..92beb14446449e16323641ac4526102d4c072235 100644 (file)
@@ -422,6 +422,7 @@ ENTRY(system_call)
 #endif
        LOCKDEP_SYS_EXIT
 .Lsysc_tif:
+       DISABLE_INTS
        TSTMSK  __PT_FLAGS(%r11),_PIF_WORK
        jnz     .Lsysc_work
        TSTMSK  __TI_flags(%r12),_TIF_WORK
@@ -444,6 +445,7 @@ ENTRY(system_call)
 # One of the work bits is on. Find out which one.
 #
 .Lsysc_work:
+       ENABLE_INTS
        TSTMSK  __TI_flags(%r12),_TIF_NEED_RESCHED
        jo      .Lsysc_reschedule
        TSTMSK  __PT_FLAGS(%r11),_PIF_SYSCALL_RESTART
@@ -761,12 +763,7 @@ ENTRY(io_int_handler)
        xc      __PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
        TSTMSK  __LC_CPU_FLAGS,_CIF_IGNORE_IRQ
        jo      .Lio_restore
-#if IS_ENABLED(CONFIG_TRACE_IRQFLAGS)
-       tmhh    %r8,0x300
-       jz      1f
        TRACE_IRQS_OFF
-1:
-#endif
        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
 .Lio_loop:
        lgr     %r2,%r11                # pass pointer to pt_regs
@@ -789,12 +786,7 @@ ENTRY(io_int_handler)
        TSTMSK  __LC_CPU_FLAGS,_CIF_WORK
        jnz     .Lio_work
 .Lio_restore:
-#if IS_ENABLED(CONFIG_TRACE_IRQFLAGS)
-       tm      __PT_PSW(%r11),3
-       jno     0f
        TRACE_IRQS_ON
-0:
-#endif
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r11)
        tm      __PT_PSW+1(%r11),0x01   # returning to user ?
        jno     .Lio_exit_kernel
@@ -974,12 +966,7 @@ ENTRY(ext_int_handler)
        xc      __PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
        TSTMSK  __LC_CPU_FLAGS,_CIF_IGNORE_IRQ
        jo      .Lio_restore
-#if IS_ENABLED(CONFIG_TRACE_IRQFLAGS)
-       tmhh    %r8,0x300
-       jz      1f
        TRACE_IRQS_OFF
-1:
-#endif
        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
        lgr     %r2,%r11                # pass pointer to pt_regs
        lghi    %r3,EXT_INTERRUPT
@@ -1066,6 +1053,7 @@ EXPORT_SYMBOL(save_fpu_regs)
  *     %r4
  */
 load_fpu_regs:
+       stnsm   __SF_EMPTY(%r15),0xfc
        lg      %r4,__LC_CURRENT
        aghi    %r4,__TASK_thread
        TSTMSK  __LC_CPU_FLAGS,_CIF_FPU
@@ -1097,6 +1085,7 @@ load_fpu_regs:
 .Lload_fpu_regs_done:
        ni      __LC_CPU_FLAGS+7,255-_CIF_FPU
 .Lload_fpu_regs_exit:
+       ssm     __SF_EMPTY(%r15)
        BR_EX   %r14
 .Lload_fpu_regs_end:
 ENDPROC(load_fpu_regs)
index f7f1e64e0d980f6e36bd1621d7ed01b2393c1331..2b85096964f8423e232c3fe016a435468d9d9461 100644 (file)
@@ -33,10 +33,10 @@ void enabled_wait(void)
                PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
        clear_cpu_flag(CIF_NOHZ_DELAY);
 
-       local_irq_save(flags);
+       raw_local_irq_save(flags);
        /* Call the assembler magic in entry.S */
        psw_idle(idle, psw_mask);
-       local_irq_restore(flags);
+       raw_local_irq_restore(flags);
 
        /* Account time spent with enabled wait psw loaded as idle time. */
        raw_write_seqcount_begin(&idle->seqcount);
@@ -123,7 +123,7 @@ void arch_cpu_idle_enter(void)
 void arch_cpu_idle(void)
 {
        enabled_wait();
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 
 void arch_cpu_idle_exit(void)
index 4f9e4626df553f999c16214f118f7522b31228ce..19cd7b961c45c57e7d59d2d3bd774334c38c1edb 100644 (file)
@@ -672,7 +672,7 @@ static void cpumsf_output_event_pid(struct perf_event *event,
        rcu_read_lock();
 
        perf_prepare_sample(&header, data, event, regs);
-       if (perf_output_begin(&handle, event, header.size))
+       if (perf_output_begin(&handle, data, event, header.size))
                goto out;
 
        /* Update the process ID (see also kernel/events/core.c) */
@@ -2228,4 +2228,4 @@ out:
 }
 
 arch_initcall(init_cpum_sampling_pmu);
-core_param(cpum_sfb_size, CPUM_SF_MAX_SDB, sfb_size, 0640);
+core_param(cpum_sfb_size, CPUM_SF_MAX_SDB, sfb_size, 0644);
index 4352a504f2354fe04a5730736958f24c709c7428..6e9e5d5e927ef51cb50d9564277f2130396c8b12 100644 (file)
@@ -53,8 +53,7 @@ u64 perf_reg_abi(struct task_struct *task)
 }
 
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
        /*
         * Use the regs from the first interruption and let
index ebfe86d097f0afa6c83f8582e1909eeccda6d620..390d97daa2b3ff245f6c216712468072dae6f326 100644 (file)
@@ -855,13 +855,14 @@ void __init smp_detect_cpus(void)
 
 static void smp_init_secondary(void)
 {
-       int cpu = smp_processor_id();
+       int cpu = raw_smp_processor_id();
 
        S390_lowcore.last_update_clock = get_tod_clock();
        restore_access_regs(S390_lowcore.access_regs_save_area);
        set_cpu_flag(CIF_ASCE_PRIMARY);
        set_cpu_flag(CIF_ASCE_SECONDARY);
        cpu_init();
+       rcu_cpu_starting(cpu);
        preempt_disable();
        init_cpu_timer();
        vtime_init();
index 14bd9d58edc902822a8070e0a59fee58f8abdad0..883bfed9f5c2ce38e25ebc24d4e408fbcaccb6cd 100644 (file)
@@ -129,8 +129,15 @@ int uv_destroy_page(unsigned long paddr)
                .paddr = paddr
        };
 
-       if (uv_call(0, (u64)&uvcb))
+       if (uv_call(0, (u64)&uvcb)) {
+               /*
+                * Older firmware uses 107/d as an indication of a non secure
+                * page. Let us emulate the newer variant (no-op).
+                */
+               if (uvcb.header.rc == 0x107 && uvcb.header.rrc == 0xd)
+                       return 0;
                return -EINVAL;
+       }
        return 0;
 }
 
index 6b74b92c1a586abc73c46c7a31a975f95d325b23..425d3d75320bf192e1510f75fd80fbb7e2718eb2 100644 (file)
@@ -2312,7 +2312,7 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)
                struct kvm_s390_pv_unp unp = {};
 
                r = -EINVAL;
-               if (!kvm_s390_pv_is_protected(kvm))
+               if (!kvm_s390_pv_is_protected(kvm) || !mm_is_protected(kvm->mm))
                        break;
 
                r = -EFAULT;
@@ -3564,7 +3564,6 @@ static void kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
                vcpu->arch.sie_block->pp = 0;
                vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
                vcpu->arch.sie_block->todpr = 0;
-               vcpu->arch.sie_block->cpnc = 0;
        }
 }
 
@@ -3582,7 +3581,6 @@ static void kvm_arch_vcpu_ioctl_clear_reset(struct kvm_vcpu *vcpu)
 
        regs->etoken = 0;
        regs->etoken_extension = 0;
-       regs->diag318 = 0;
 }
 
 int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
index eb99e2f95ebed41679db4dc7ca172f4d76696fae..f5847f9dec7c9e6bf90c2165b2d5eaefc09ccfe0 100644 (file)
@@ -208,7 +208,6 @@ int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc)
                return -EIO;
        }
        kvm->arch.gmap->guest_handle = uvcb.guest_handle;
-       atomic_set(&kvm->mm->context.is_protected, 1);
        return 0;
 }
 
@@ -228,6 +227,8 @@ int kvm_s390_pv_set_sec_parms(struct kvm *kvm, void *hdr, u64 length, u16 *rc,
        *rrc = uvcb.header.rrc;
        KVM_UV_EVENT(kvm, 3, "PROTVIRT VM SET PARMS: rc %x rrc %x",
                     *rc, *rrc);
+       if (!cc)
+               atomic_set(&kvm->mm->context.is_protected, 1);
        return cc ? -EINVAL : 0;
 }
 
index daca7bad66de3e6a5ca68d3a14f3270069e3ecf9..8c0c68e7770ea1d74a3680cc948b41d6b7709205 100644 (file)
@@ -33,7 +33,7 @@ EXPORT_SYMBOL(__delay);
 
 static void __udelay_disabled(unsigned long long usecs)
 {
-       unsigned long cr0, cr0_new, psw_mask, flags;
+       unsigned long cr0, cr0_new, psw_mask;
        struct s390_idle_data idle;
        u64 end;
 
@@ -45,9 +45,8 @@ static void __udelay_disabled(unsigned long long usecs)
        psw_mask = __extract_psw() | PSW_MASK_EXT | PSW_MASK_WAIT;
        set_clock_comparator(end);
        set_cpu_flag(CIF_IGNORE_IRQ);
-       local_irq_save(flags);
        psw_idle(&idle, psw_mask);
-       local_irq_restore(flags);
+       trace_hardirqs_off();
        clear_cpu_flag(CIF_IGNORE_IRQ);
        set_clock_comparator(S390_lowcore.clock_comparator);
        __ctl_load(cr0, 0, 0);
index cfb0017f33a70444b6d8d0a636d35937489725b2..64795d03492632b629aaef4b88907ef8adb12677 100644 (file)
@@ -2690,6 +2690,8 @@ static const struct mm_walk_ops reset_acc_walk_ops = {
 #include <linux/sched/mm.h>
 void s390_reset_acc(struct mm_struct *mm)
 {
+       if (!mm_is_protected(mm))
+               return;
        /*
         * we might be called during
         * reset:                             we walk the pages and clear
index d33f21545dfdb82bff668c8092a2a8e58ec069fc..9a6bae503fe61c0b54866bdf1c3d6f5459c44194 100644 (file)
@@ -101,6 +101,10 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
                if (ret)
                        break;
 
+               /* the PCI function will be scanned once function 0 appears */
+               if (!zdev->zbus->bus)
+                       break;
+
                pdev = pci_scan_single_device(zdev->zbus->bus, zdev->devfn);
                if (!pdev)
                        break;
index 743f257cf2cbdd0cfa0aed3a935edded9ce0d513..75217fb63d7b362026d2057bab89fdd19003db7f 100644 (file)
@@ -103,9 +103,10 @@ static int zpci_set_irq_affinity(struct irq_data *data, const struct cpumask *de
 {
        struct msi_desc *entry = irq_get_msi_desc(data->irq);
        struct msi_msg msg = entry->msg;
+       int cpu_addr = smp_cpu_get_cpu_address(cpumask_first(dest));
 
        msg.address_lo &= 0xff0000ff;
-       msg.address_lo |= (cpumask_first(dest) << 8);
+       msg.address_lo |= (cpu_addr << 8);
        pci_write_msi_msg(data->irq, &msg);
 
        return IRQ_SET_MASK_OK;
@@ -238,6 +239,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
        unsigned long bit;
        struct msi_desc *msi;
        struct msi_msg msg;
+       int cpu_addr;
        int rc, irq;
 
        zdev->aisb = -1UL;
@@ -287,9 +289,15 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                                         handle_percpu_irq);
                msg.data = hwirq - bit;
                if (irq_delivery == DIRECTED) {
+                       if (msi->affinity)
+                               cpu = cpumask_first(&msi->affinity->mask);
+                       else
+                               cpu = 0;
+                       cpu_addr = smp_cpu_get_cpu_address(cpu);
+
                        msg.address_lo = zdev->msi_addr & 0xff0000ff;
-                       msg.address_lo |= msi->affinity ?
-                               (cpumask_first(&msi->affinity->mask) << 8) : 0;
+                       msg.address_lo |= (cpu_addr << 8);
+
                        for_each_possible_cpu(cpu) {
                                airq_iv_set_data(zpci_ibv[cpu], hwirq, irq);
                        }
index 0dc0f52f9bb8d3119887dd2fc8b08eaf685ec417..f59814983bd59ffcf5be94d45124f6f5c34399d3 100644 (file)
@@ -22,7 +22,7 @@ static void (*sh_idle)(void);
 void default_idle(void)
 {
        set_bl_bit();
-       local_irq_enable();
+       raw_local_irq_enable();
        /* Isn't this racy ? */
        cpu_sleep();
        clear_bl_bit();
index 065e2d4b729084c0d4c50cf0bfdb2b0d51c87df4..396f46bca52eb67a968e02732e2f350a0afd6218 100644 (file)
@@ -50,7 +50,7 @@ static void pmc_leon_idle_fixup(void)
        register unsigned int address = (unsigned int)leon3_irqctrl_regs;
 
        /* Interrupts need to be enabled to not hang the CPU */
-       local_irq_enable();
+       raw_local_irq_enable();
 
        __asm__ __volatile__ (
                "wr     %%g0, %%asr19\n"
@@ -66,7 +66,7 @@ static void pmc_leon_idle_fixup(void)
 static void pmc_leon_idle(void)
 {
        /* Interrupts need to be enabled to not hang the CPU */
-       local_irq_enable();
+       raw_local_irq_enable();
 
        /* For systems without power-down, this will be no-op */
        __asm__ __volatile__ ("wr       %g0, %asr19\n\t");
index adfcaeab3ddc5be0c0869b2b74ac627bba578fbf..a023637359154e9bbd874a574bd9f95ba50c5b10 100644 (file)
@@ -74,7 +74,7 @@ void arch_cpu_idle(void)
 {
        if (sparc_idle)
                (*sparc_idle)();
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 
 /* XXX cli/sti -> local_irq_xxx here, check this works once SMP is fixed. */
index a75093b993f9aed5c2dd77af4e2f74468a315736..6f8c7822fc065d394c0e573aa5eae10851a34542 100644 (file)
@@ -62,11 +62,11 @@ void arch_cpu_idle(void)
 {
        if (tlb_type != hypervisor) {
                touch_nmi_watchdog();
-               local_irq_enable();
+               raw_local_irq_enable();
        } else {
                unsigned long pstate;
 
-               local_irq_enable();
+               raw_local_irq_enable();
 
                 /* The sun4v sleeping code requires that we have PSTATE.IE cleared over
                  * the cpu sleep hypervisor call.
index 5393e13e07e0a9108addf8dfa2e05c1343a290e7..2bbf28cf3aa9258ab1b8970e500c049e708ab842 100644 (file)
@@ -33,7 +33,13 @@ do {                                                 \
 } while (0)
 
 #ifdef CONFIG_3_LEVEL_PGTABLES
-#define __pmd_free_tlb(tlb,x, address)   tlb_remove_page((tlb),virt_to_page(x))
+
+#define __pmd_free_tlb(tlb, pmd, address)              \
+do {                                                   \
+       pgtable_pmd_page_dtor(virt_to_page(pmd));       \
+       tlb_remove_page((tlb),virt_to_page(pmd));       \
+} while (0)                                            \
+
 #endif
 
 #endif
index 3bed09538dd951766fd6bc3219433577cf73fc5b..9505a7e87396a68a1576dc929a9958219f2247cc 100644 (file)
@@ -217,7 +217,7 @@ void arch_cpu_idle(void)
 {
        cpu_tasks[current_thread_info()->cpu].pid = os_getpid();
        um_idle_sleep();
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 
 int __cant_sleep(void) {
index 95c355181dcdd2e3967b810e9b7299398676d222..bfb70c456b302ad8a19cde1869768e8c208573bf 100644 (file)
@@ -21,7 +21,7 @@
  * on some systems.
  */
 
-void __section(".__syscall_stub")
+void __attribute__ ((__section__ (".__syscall_stub")))
 stub_clone_handler(void)
 {
        struct stub_data *data = (struct stub_data *) STUB_DATA;
index f6946b81f74a95da92bce9f483dcbd6ca6aa7cff..fbf26e0f7a6a9be1066c9a60348903a401b6050b 100644 (file)
@@ -100,6 +100,7 @@ config X86
        select ARCH_WANT_DEFAULT_BPF_JIT        if X86_64
        select ARCH_WANTS_DYNAMIC_TASK_STRUCT
        select ARCH_WANT_HUGE_PMD_SHARE
+       select ARCH_WANT_LD_ORPHAN_WARN
        select ARCH_WANTS_THP_SWAP              if X86_64
        select BUILDTIME_TABLE_SORT
        select CLKEVT_I8253
index 154259f18b8b960b9aee729fb2e1ddc1e7538634..1bf21746f4cea13fedcd1fd562d70f9121f82454 100644 (file)
@@ -209,9 +209,6 @@ ifdef CONFIG_X86_64
 LDFLAGS_vmlinux += -z max-page-size=0x200000
 endif
 
-# We never want expected sections to be placed heuristically by the
-# linker. All sections should be explicitly named in the linker script.
-LDFLAGS_vmlinux += $(call ld-option, --orphan-handling=warn)
 
 archscripts: scripts_basic
        $(Q)$(MAKE) $(build)=arch/x86/tools relocs
index ee249088cbfe2ff46f2b7e2c76252b1f9001bc9f..40b8fd375d522052f5359040c862ab9ba102e69c 100644 (file)
@@ -61,7 +61,9 @@ KBUILD_LDFLAGS += $(call ld-option,--no-ld-generated-unwind-info)
 # Compressed kernel should be built as PIE since it may be loaded at any
 # address by the bootloader.
 LDFLAGS_vmlinux := -pie $(call ld-option, --no-dynamic-linker)
-LDFLAGS_vmlinux += $(call ld-option, --orphan-handling=warn)
+ifdef CONFIG_LD_ORPHAN_WARN
+LDFLAGS_vmlinux += --orphan-handling=warn
+endif
 LDFLAGS_vmlinux += -T
 
 hostprogs      := mkpiggy
index a5e5db6ada3c76c8132be74e420d77771c488e64..39b2eded7bc2b633c8fafa2bce50ed788b054a83 100644 (file)
@@ -164,6 +164,7 @@ void initialize_identity_maps(void *rmode)
        add_identity_map(cmdline, cmdline + COMMAND_LINE_SIZE);
 
        /* Load the new page-table. */
+       sev_verify_cbit(top_level_pgt);
        write_cr3(top_level_pgt);
 }
 
index dd07e7b41b115e65e9c762024bd77ae61de35b8f..aa561795efd16182fa185964045ec40571d0b71b 100644 (file)
@@ -68,6 +68,9 @@ SYM_FUNC_START(get_sev_encryption_bit)
 SYM_FUNC_END(get_sev_encryption_bit)
 
        .code64
+
+#include "../../kernel/sev_verify_cbit.S"
+
 SYM_FUNC_START(set_sev_encryption_mask)
 #ifdef CONFIG_AMD_MEM_ENCRYPT
        push    %rbp
@@ -81,6 +84,19 @@ SYM_FUNC_START(set_sev_encryption_mask)
 
        bts     %rax, sme_me_mask(%rip) /* Create the encryption mask */
 
+       /*
+        * Read MSR_AMD64_SEV again and store it to sev_status. Can't do this in
+        * get_sev_encryption_bit() because this function is 32-bit code and
+        * shared between 64-bit and 32-bit boot path.
+        */
+       movl    $MSR_AMD64_SEV, %ecx    /* Read the SEV MSR */
+       rdmsr
+
+       /* Store MSR value in sev_status */
+       shlq    $32, %rdx
+       orq     %rdx, %rax
+       movq    %rax, sev_status(%rip)
+
 .Lno_sev_mask:
        movq    %rbp, %rsp              /* Restore original stack pointer */
 
@@ -96,5 +112,7 @@ SYM_FUNC_END(set_sev_encryption_mask)
 
 #ifdef CONFIG_AMD_MEM_ENCRYPT
        .balign 8
-SYM_DATA(sme_me_mask, .quad 0)
+SYM_DATA(sme_me_mask,          .quad 0)
+SYM_DATA(sev_status,           .quad 0)
+SYM_DATA(sev_check_data,       .quad 0)
 #endif
index 6d31f1b4c4d1085f3bee1d7fc495d29b3409bce0..d9a631c5973c7f6423299baae66167579a8bdcff 100644 (file)
@@ -159,4 +159,6 @@ void boot_page_fault(void);
 void boot_stage1_vc(void);
 void boot_stage2_vc(void);
 
+unsigned long sev_verify_cbit(unsigned long cr3);
+
 #endif /* BOOT_COMPRESSED_MISC_H */
index 954cb2702e239f856f56c05ef693201667e2675d..27826c265aab484770a3b82b7cde24116cb66d7b 100644 (file)
@@ -32,13 +32,12 @@ struct ghcb *boot_ghcb;
  */
 static bool insn_has_rep_prefix(struct insn *insn)
 {
+       insn_byte_t p;
        int i;
 
        insn_get_prefixes(insn);
 
-       for (i = 0; i < insn->prefixes.nbytes; i++) {
-               insn_byte_t p = insn->prefixes.bytes[i];
-
+       for_each_insn_prefix(insn, i, p) {
                if (p == 0xf2 || p == 0xf3)
                        return true;
        }
index e508dbd918139781de284623106b3c2ce9e50421..c44aba290fbb861e7ae34592911fe34fe0794fa1 100644 (file)
@@ -158,6 +158,7 @@ static unsigned int crypto_poly1305_setdctxkey(struct poly1305_desc_ctx *dctx,
                        dctx->s[1] = get_unaligned_le32(&inp[4]);
                        dctx->s[2] = get_unaligned_le32(&inp[8]);
                        dctx->s[3] = get_unaligned_le32(&inp[12]);
+                       acc += POLY1305_BLOCK_SIZE;
                        dctx->sset = true;
                }
        }
index 1f47e24fb65cf8a7525be8a53934eb4fa63da7d1..379819244b91d275b2c98f7ff38a59049c24b42a 100644 (file)
 440    common  process_madvise         sys_process_madvise
 
 #
-# x32-specific system call numbers start at 512 to avoid cache impact
-# for native 64-bit operation. The __x32_compat_sys stubs are created
-# on-the-fly for compat_sys_*() compatibility system calls if X86_X32
-# is defined.
+# Due to a historical design error, certain syscalls are numbered differently
+# in x32 as compared to native x86_64.  These syscalls have numbers 512-547.
+# Do not add new syscalls to this range.  Numbers 548 and above are available
+# for non-x32 use.
 #
 512    x32     rt_sigaction            compat_sys_rt_sigaction
 513    x32     rt_sigreturn            compat_sys_x32_rt_sigreturn
 545    x32     execveat                compat_sys_execveat
 546    x32     preadv2                 compat_sys_preadv64v2
 547    x32     pwritev2                compat_sys_pwritev64v2
+# This is the end of the legacy x32 range.  Numbers 548 and above are
+# not special and are not to be used for x32-specific syscalls.
index f1926e9f2143c65b175997c6372cde1e9f887e4f..af457f8cb29ddabda6bc5d15f717355f2d1c7bd0 100644 (file)
@@ -2630,7 +2630,7 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status)
                u64 pebs_enabled = cpuc->pebs_enabled;
 
                handled++;
-               x86_pmu.drain_pebs(regs);
+               x86_pmu.drain_pebs(regs, &data);
                status &= x86_pmu.intel_ctrl | GLOBAL_STATUS_TRACE_TOPAPMI;
 
                /*
@@ -4987,6 +4987,12 @@ __init int intel_pmu_init(void)
 
        x86_add_quirk(intel_arch_events_quirk); /* Install first, so it runs last */
 
+       if (version >= 5) {
+               x86_pmu.intel_cap.anythread_deprecated = edx.split.anythread_deprecated;
+               if (x86_pmu.intel_cap.anythread_deprecated)
+                       pr_cont(" AnyThread deprecated, ");
+       }
+
        /*
         * Install the hw-cache-events table:
         */
@@ -5512,6 +5518,10 @@ __init int intel_pmu_init(void)
        x86_pmu.intel_ctrl |=
                ((1LL << x86_pmu.num_counters_fixed)-1) << INTEL_PMC_IDX_FIXED;
 
+       /* AnyThread may be deprecated on arch perfmon v5 or later */
+       if (x86_pmu.intel_cap.anythread_deprecated)
+               x86_pmu.format_attrs = intel_arch_formats_attr;
+
        if (x86_pmu.event_constraints) {
                /*
                 * event on fixed counter2 (REF_CYCLES) only works on this
index 442e1ed4acd49d62235dc1e42a2604ac669693dd..4eb7ee5fed72d8bc5ee28bcf693af6925b329723 100644 (file)
 MODULE_LICENSE("GPL");
 
 #define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format)                \
-static ssize_t __cstate_##_var##_show(struct kobject *kobj,    \
-                               struct kobj_attribute *attr,    \
+static ssize_t __cstate_##_var##_show(struct device *dev,      \
+                               struct device_attribute *attr,  \
                                char *page)                     \
 {                                                              \
        BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE);             \
        return sprintf(page, _format "\n");                     \
 }                                                              \
-static struct kobj_attribute format_attr_##_var =              \
+static struct device_attribute format_attr_##_var =            \
        __ATTR(_name, 0444, __cstate_##_var##_show, NULL)
 
 static ssize_t cstate_get_attr_cpumask(struct device *dev,
index 404315df1e1676398fabc56054db3d34dfbf629b..485c5066f8b8c8746becc4060471a60e09636eb2 100644 (file)
@@ -642,8 +642,8 @@ int intel_pmu_drain_bts_buffer(void)
        rcu_read_lock();
        perf_prepare_sample(&header, &data, event, &regs);
 
-       if (perf_output_begin(&handle, event, header.size *
-                             (top - base - skip)))
+       if (perf_output_begin(&handle, &data, event,
+                             header.size * (top - base - skip)))
                goto unlock;
 
        for (at = base; at < top; at++) {
@@ -670,7 +670,9 @@ unlock:
 
 static inline void intel_pmu_drain_pebs_buffer(void)
 {
-       x86_pmu.drain_pebs(NULL);
+       struct perf_sample_data data;
+
+       x86_pmu.drain_pebs(NULL, &data);
 }
 
 /*
@@ -1719,23 +1721,24 @@ intel_pmu_save_and_restart_reload(struct perf_event *event, int count)
        return 0;
 }
 
-static void __intel_pmu_pebs_event(struct perf_event *event,
-                                  struct pt_regs *iregs,
-                                  void *base, void *top,
-                                  int bit, int count,
-                                  void (*setup_sample)(struct perf_event *,
-                                               struct pt_regs *,
-                                               void *,
-                                               struct perf_sample_data *,
-                                               struct pt_regs *))
+static __always_inline void
+__intel_pmu_pebs_event(struct perf_event *event,
+                      struct pt_regs *iregs,
+                      struct perf_sample_data *data,
+                      void *base, void *top,
+                      int bit, int count,
+                      void (*setup_sample)(struct perf_event *,
+                                           struct pt_regs *,
+                                           void *,
+                                           struct perf_sample_data *,
+                                           struct pt_regs *))
 {
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
-       struct perf_sample_data data;
        struct x86_perf_regs perf_regs;
        struct pt_regs *regs = &perf_regs.regs;
        void *at = get_next_pebs_record_by_bit(base, top, bit);
-       struct pt_regs dummy_iregs;
+       static struct pt_regs dummy_iregs;
 
        if (hwc->flags & PERF_X86_EVENT_AUTO_RELOAD) {
                /*
@@ -1752,14 +1755,14 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
                iregs = &dummy_iregs;
 
        while (count > 1) {
-               setup_sample(event, iregs, at, &data, regs);
-               perf_event_output(event, &data, regs);
+               setup_sample(event, iregs, at, data, regs);
+               perf_event_output(event, data, regs);
                at += cpuc->pebs_record_size;
                at = get_next_pebs_record_by_bit(at, top, bit);
                count--;
        }
 
-       setup_sample(event, iregs, at, &data, regs);
+       setup_sample(event, iregs, at, data, regs);
        if (iregs == &dummy_iregs) {
                /*
                 * The PEBS records may be drained in the non-overflow context,
@@ -1767,18 +1770,18 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
                 * last record the same as other PEBS records, and doesn't
                 * invoke the generic overflow handler.
                 */
-               perf_event_output(event, &data, regs);
+               perf_event_output(event, data, regs);
        } else {
                /*
                 * All but the last records are processed.
                 * The last one is left to be able to call the overflow handler.
                 */
-               if (perf_event_overflow(event, &data, regs))
+               if (perf_event_overflow(event, data, regs))
                        x86_pmu_stop(event, 0);
        }
 }
 
-static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
+static void intel_pmu_drain_pebs_core(struct pt_regs *iregs, struct perf_sample_data *data)
 {
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
        struct debug_store *ds = cpuc->ds;
@@ -1812,7 +1815,7 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
                return;
        }
 
-       __intel_pmu_pebs_event(event, iregs, at, top, 0, n,
+       __intel_pmu_pebs_event(event, iregs, data, at, top, 0, n,
                               setup_pebs_fixed_sample_data);
 }
 
@@ -1835,7 +1838,7 @@ static void intel_pmu_pebs_event_update_no_drain(struct cpu_hw_events *cpuc, int
        }
 }
 
-static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
+static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_data *data)
 {
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
        struct debug_store *ds = cpuc->ds;
@@ -1913,7 +1916,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
                 * that caused the PEBS record. It's called collision.
                 * If collision happened, the record will be dropped.
                 */
-               if (p->status != (1ULL << bit)) {
+               if (pebs_status != (1ULL << bit)) {
                        for_each_set_bit(i, (unsigned long *)&pebs_status, size)
                                error[i]++;
                        continue;
@@ -1937,19 +1940,19 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
                if (error[bit]) {
                        perf_log_lost_samples(event, error[bit]);
 
-                       if (perf_event_account_interrupt(event))
+                       if (iregs && perf_event_account_interrupt(event))
                                x86_pmu_stop(event, 0);
                }
 
                if (counts[bit]) {
-                       __intel_pmu_pebs_event(event, iregs, base,
+                       __intel_pmu_pebs_event(event, iregs, data, base,
                                               top, bit, counts[bit],
                                               setup_pebs_fixed_sample_data);
                }
        }
 }
 
-static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs)
+static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_data *data)
 {
        short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {};
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
@@ -1997,7 +2000,7 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs)
                if (WARN_ON_ONCE(!event->attr.precise_ip))
                        continue;
 
-               __intel_pmu_pebs_event(event, iregs, base,
+               __intel_pmu_pebs_event(event, iregs, data, base,
                                       top, bit, counts[bit],
                                       setup_pebs_adaptive_sample_data);
        }
index 86d012b3e0b42ae316e407b55a3e332f1a2f7de3..80d52cbe2fde549e7d4f4a54f3c9b3195b6448cf 100644 (file)
@@ -94,8 +94,8 @@ end:
        return map;
 }
 
-ssize_t uncore_event_show(struct kobject *kobj,
-                         struct kobj_attribute *attr, char *buf)
+ssize_t uncore_event_show(struct device *dev,
+                         struct device_attribute *attr, char *buf)
 {
        struct uncore_event_desc *event =
                container_of(attr, struct uncore_event_desc, attr);
index 83d2a7d490e038e8c3c068adeadbb3eb91c7f347..9efea154349d3984798d5105145a1fe97d3afcf3 100644 (file)
@@ -157,7 +157,7 @@ struct intel_uncore_box {
 #define UNCORE_BOX_FLAG_CFL8_CBOX_MSR_OFFS     2
 
 struct uncore_event_desc {
-       struct kobj_attribute attr;
+       struct device_attribute attr;
        const char *config;
 };
 
@@ -179,8 +179,8 @@ struct pci2phy_map {
 struct pci2phy_map *__find_pci2phy_map(int segment);
 int uncore_pcibus_to_physid(struct pci_bus *bus);
 
-ssize_t uncore_event_show(struct kobject *kobj,
-                         struct kobj_attribute *attr, char *buf);
+ssize_t uncore_event_show(struct device *dev,
+                         struct device_attribute *attr, char *buf);
 
 static inline struct intel_uncore_pmu *dev_to_uncore_pmu(struct device *dev)
 {
@@ -201,14 +201,14 @@ extern int __uncore_max_dies;
 }
 
 #define DEFINE_UNCORE_FORMAT_ATTR(_var, _name, _format)                        \
-static ssize_t __uncore_##_var##_show(struct kobject *kobj,            \
-                               struct kobj_attribute *attr,            \
+static ssize_t __uncore_##_var##_show(struct device *dev,              \
+                               struct device_attribute *attr,          \
                                char *page)                             \
 {                                                                      \
        BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE);                     \
        return sprintf(page, _format "\n");                             \
 }                                                                      \
-static struct kobj_attribute format_attr_##_var =                      \
+static struct device_attribute format_attr_##_var =                    \
        __ATTR(_name, 0444, __uncore_##_var##_show, NULL)
 
 static inline bool uncore_pmc_fixed(int idx)
index 39e632ed6ca9613dafb683bb6111244c341b16f8..bbd1120ae16101a835766c2c76e05d0b1c1b449d 100644 (file)
@@ -475,7 +475,7 @@ enum perf_snb_uncore_imc_freerunning_types {
 static struct freerunning_counters snb_uncore_imc_freerunning[] = {
        [SNB_PCI_UNCORE_IMC_DATA_READS]         = { SNB_UNCORE_PCI_IMC_DATA_READS_BASE,
                                                        0x0, 0x0, 1, 32 },
-       [SNB_PCI_UNCORE_IMC_DATA_READS]         = { SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE,
+       [SNB_PCI_UNCORE_IMC_DATA_WRITES]        = { SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE,
                                                        0x0, 0x0, 1, 32 },
        [SNB_PCI_UNCORE_IMC_GT_REQUESTS]        = { SNB_UNCORE_PCI_IMC_GT_REQUESTS_BASE,
                                                        0x0, 0x0, 1, 32 },
index ee2b9b9fc2a50e3e63c93bf8f4bd7d13acbf9c60..6a8edfe59b09c94605b412aab5e2e01db346ded7 100644 (file)
@@ -585,6 +585,7 @@ union perf_capabilities {
                u64     pebs_baseline:1;
                u64     perf_metrics:1;
                u64     pebs_output_pt_available:1;
+               u64     anythread_deprecated:1;
        };
        u64     capabilities;
 };
@@ -727,7 +728,7 @@ struct x86_pmu {
        int             pebs_record_size;
        int             pebs_buffer_size;
        int             max_pebs_events;
-       void            (*drain_pebs)(struct pt_regs *regs);
+       void            (*drain_pebs)(struct pt_regs *regs, struct perf_sample_data *data);
        struct event_constraint *pebs_constraints;
        void            (*pebs_aliases)(struct perf_event *event);
        unsigned long   large_pebs_flags;
index 7c0120e2e957f6d37c72e8cf3b37a9901fa44291..7dbbeaacd9956654f66e00a45e38c1cc8fea4a0e 100644 (file)
@@ -93,18 +93,6 @@ static const char *const rapl_domain_names[NR_RAPL_DOMAINS] __initconst = {
  * any other bit is reserved
  */
 #define RAPL_EVENT_MASK        0xFFULL
-
-#define DEFINE_RAPL_FORMAT_ATTR(_var, _name, _format)          \
-static ssize_t __rapl_##_var##_show(struct kobject *kobj,      \
-                               struct kobj_attribute *attr,    \
-                               char *page)                     \
-{                                                              \
-       BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE);             \
-       return sprintf(page, _format "\n");                     \
-}                                                              \
-static struct kobj_attribute format_attr_##_var =              \
-       __ATTR(_name, 0444, __rapl_##_var##_show, NULL)
-
 #define RAPL_CNTR_WIDTH 32
 
 #define RAPL_EVENT_ATTR_STR(_name, v, str)                                     \
@@ -441,7 +429,7 @@ static struct attribute_group rapl_pmu_events_group = {
        .attrs = attrs_empty,
 };
 
-DEFINE_RAPL_FORMAT_ATTR(event, event, "config:0-7");
+PMU_FORMAT_ATTR(event, "config:0-7");
 static struct attribute *rapl_formats_attr[] = {
        &format_attr_event.attr,
        NULL,
index 40e0e322161d7bbc4b88e854c4a4e6f503e627f9..284e73661a18bde5d17ba6b03efd78d9be1cd309 100644 (file)
@@ -273,11 +273,15 @@ void __init hv_apic_init(void)
                pr_info("Hyper-V: Using enlightened APIC (%s mode)",
                        x2apic_enabled() ? "x2apic" : "xapic");
                /*
-                * With x2apic, architectural x2apic MSRs are equivalent to the
-                * respective synthetic MSRs, so there's no need to override
-                * the apic accessors.  The only exception is
-                * hv_apic_eoi_write, because it benefits from lazy EOI when
-                * available, but it works for both xapic and x2apic modes.
+                * When in x2apic mode, don't use the Hyper-V specific APIC
+                * accessors since the field layout in the ICR register is
+                * different in x2apic mode. Furthermore, the architectural
+                * x2apic MSRs function just as well as the Hyper-V
+                * synthetic APIC MSRs, so there's no benefit in having
+                * separate Hyper-V accessors for x2apic mode. The only
+                * exception is hv_apic_eoi_write, because it benefits from
+                * lazy EOI when available, but the same accessor works for
+                * both xapic and x2apic because the field layout is the same.
                 */
                apic_set_eoi_write(hv_apic_eoi_write);
                if (!x2apic_enabled()) {
index 5c1ae3eff9d4275c9fefa0eae1b5a3095aee5238..a8c3d284fa46c4ad3f2dd4b8116d7ee6008d7f81 100644 (file)
@@ -201,6 +201,21 @@ static inline int insn_offset_immediate(struct insn *insn)
        return insn_offset_displacement(insn) + insn->displacement.nbytes;
 }
 
+/**
+ * for_each_insn_prefix() -- Iterate prefixes in the instruction
+ * @insn: Pointer to struct insn.
+ * @idx:  Index storage.
+ * @prefix: Prefix byte.
+ *
+ * Iterate prefix bytes of given @insn. Each prefix byte is stored in @prefix
+ * and the index is stored in @idx (note that this @idx is just for a cursor,
+ * do not change it.)
+ * Since prefixes.nbytes can be bigger than 4 if some prefixes
+ * are repeated, it cannot be used for looping over the prefixes.
+ */
+#define for_each_insn_prefix(insn, idx, prefix)        \
+       for (idx = 0; idx < ARRAY_SIZE(insn->prefixes.bytes) && (prefix = insn->prefixes.bytes[idx]) != 0; idx++)
+
 #define POP_SS_OPCODE 0x1f
 #define MOV_SREG_OPCODE 0x8e
 
index d44858b6935334ab334e84079fa3d1e440c077de..7e5f33a0d0e2fe093ec2f273b5642037501e6861 100644 (file)
@@ -639,6 +639,7 @@ struct kvm_vcpu_arch {
        int cpuid_nent;
        struct kvm_cpuid_entry2 *cpuid_entries;
 
+       unsigned long cr3_lm_rsvd_bits;
        int maxphyaddr;
        int max_tdp_level;
 
@@ -1655,6 +1656,7 @@ int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
 int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
 int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v);
 int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu);
+int kvm_cpu_has_extint(struct kvm_vcpu *v);
 int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu);
 int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
 void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event);
index e039a933aca3c38859a395e53f5736573dae9ea0..29dd27b5a339db16cfb1b40aa68004cf7b2bac0c 100644 (file)
@@ -88,8 +88,6 @@ static inline void __mwaitx(unsigned long eax, unsigned long ebx,
 
 static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
 {
-       trace_hardirqs_on();
-
        mds_idle_clear_cpu_buffers();
        /* "mwait %eax, %ecx;" */
        asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
index 6960cd6d1f2319e9245a027e290b6c9e53ef5e79..b9a7fd0a27e2d541fdcd63c004918080f8fe499e 100644 (file)
@@ -137,7 +137,9 @@ union cpuid10_edx {
        struct {
                unsigned int num_counters_fixed:5;
                unsigned int bit_width_fixed:8;
-               unsigned int reserved:19;
+               unsigned int reserved1:2;
+               unsigned int anythread_deprecated:1;
+               unsigned int reserved2:16;
        } split;
        unsigned int full;
 };
index 6bfc878f677155a9352bee303effe64ac9abb04b..6a9ccc1b2be5d1b8ade62585ef50753ea8b8d679 100644 (file)
 #endif
 
 #endif /* CONFIG_SPARSEMEM */
+
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_NUMA_KEEP_MEMINFO
+extern int phys_to_target_node(phys_addr_t start);
+#define phys_to_target_node phys_to_target_node
+extern int memory_add_physaddr_to_nid(u64 start);
+#define memory_add_physaddr_to_nid memory_add_physaddr_to_nid
+#endif
+#endif /* __ASSEMBLY__ */
+
 #endif /* _ASM_X86_SPARSEMEM_H */
index 172d3e4a9e4b85cdf1cb8c26f943a3b50f4843ad..648eb23fe7f0b4db3b43deeb3b9b8d30e6cb9ba3 100644 (file)
@@ -2,14 +2,8 @@
 #ifndef _ASM_X86_UV_UV_H
 #define _ASM_X86_UV_UV_H
 
-#include <asm/tlbflush.h>
-
 enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC};
 
-struct cpumask;
-struct mm_struct;
-struct flush_tlb_info;
-
 #ifdef CONFIG_X86_UV
 #include <linux/efi.h>
 
@@ -44,10 +38,6 @@ static inline int is_uv_system(void) { return 0; }
 static inline int is_uv_hubbed(int uv) { return 0; }
 static inline void uv_cpu_init(void)   { }
 static inline void uv_system_init(void)        { }
-static inline const struct cpumask *
-uv_flush_tlb_others(const struct cpumask *cpumask,
-                   const struct flush_tlb_info *info)
-{ return cpumask; }
 
 #endif /* X86_UV */
 
index 812e9b4c111412db345b82854799351571a72a0a..950afebfba888573a6bf50226a0b70a589f05947 100644 (file)
@@ -32,6 +32,7 @@
 #define KVM_FEATURE_POLL_CONTROL       12
 #define KVM_FEATURE_PV_SCHED_YIELD     13
 #define KVM_FEATURE_ASYNC_PF_INT       14
+#define KVM_FEATURE_MSI_EXT_DEST_ID    15
 
 #define KVM_HINTS_REALTIME      0
 
index 4adbe65afe235f9a71f290e874486d4a1dbfa3cf..2400ad62f330b9f518b3bcfa3462f5fd2e659e78 100644 (file)
@@ -807,6 +807,15 @@ static inline temp_mm_state_t use_temporary_mm(struct mm_struct *mm)
        temp_mm_state_t temp_state;
 
        lockdep_assert_irqs_disabled();
+
+       /*
+        * Make sure not to be in TLB lazy mode, as otherwise we'll end up
+        * with a stale address space WITHOUT being in lazy mode after
+        * restoring the previous mm.
+        */
+       if (this_cpu_read(cpu_tlbstate.is_lazy))
+               leave_mm(smp_processor_id());
+
        temp_state.mm = this_cpu_read(cpu_tlbstate.loaded_mm);
        switch_mm_irqs_off(NULL, mm, current);
 
index 714233cee0b5760db7615c0d76d6d89aaa4ef74d..235f5cde06fc304ff75630b9faae8f9a2a48c3da 100644 (file)
@@ -33,7 +33,7 @@ static union uvh_apicid               uvh_apicid;
 static int                     uv_node_id;
 
 /* Unpack AT/OEM/TABLE ID's to be NULL terminated strings */
-static u8 uv_archtype[UV_AT_SIZE];
+static u8 uv_archtype[UV_AT_SIZE + 1];
 static u8 oem_id[ACPI_OEM_ID_SIZE + 1];
 static u8 oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
 
@@ -161,7 +161,7 @@ static int __init early_set_hub_type(void)
        /* UV4/4A only have a revision difference */
        case UV4_HUB_PART_NUMBER:
                uv_min_hub_revision_id = node_id.s.revision
-                                        + UV4_HUB_REVISION_BASE;
+                                        + UV4_HUB_REVISION_BASE - 1;
                uv_hub_type_set(UV4);
                if (uv_min_hub_revision_id == UV4A_HUB_REVISION_BASE)
                        uv_hub_type_set(UV4|UV4A);
@@ -290,6 +290,9 @@ static void __init uv_stringify(int len, char *to, char *from)
 {
        /* Relies on 'to' being NULL chars so result will be NULL terminated */
        strncpy(to, from, len-1);
+
+       /* Trim trailing spaces */
+       (void)strim(to);
 }
 
 /* Find UV arch type entry in UVsystab */
@@ -317,7 +320,7 @@ static int __init decode_arch_type(unsigned long ptr)
 
        if (n > 0 && n < sizeof(uv_ate->archtype)) {
                pr_info("UV: UVarchtype received from BIOS\n");
-               uv_stringify(UV_AT_SIZE, uv_archtype, uv_ate->archtype);
+               uv_stringify(sizeof(uv_archtype), uv_archtype, uv_ate->archtype);
                return 1;
        }
        return 0;
@@ -366,7 +369,7 @@ static int __init early_get_arch_type(void)
        return ret;
 }
 
-static int __init uv_set_system_type(char *_oem_id)
+static int __init uv_set_system_type(char *_oem_id, char *_oem_table_id)
 {
        /* Save OEM_ID passed from ACPI MADT */
        uv_stringify(sizeof(oem_id), oem_id, _oem_id);
@@ -375,7 +378,7 @@ static int __init uv_set_system_type(char *_oem_id)
        if (!early_get_arch_type())
 
                /* If not use OEM ID for UVarchtype */
-               uv_stringify(UV_AT_SIZE, uv_archtype, _oem_id);
+               uv_stringify(sizeof(uv_archtype), uv_archtype, oem_id);
 
        /* Check if not hubbed */
        if (strncmp(uv_archtype, "SGI", 3) != 0) {
@@ -386,13 +389,23 @@ static int __init uv_set_system_type(char *_oem_id)
                        /* (Not hubless), not a UV */
                        return 0;
 
+               /* Is UV hubless system */
+               uv_hubless_system = 0x01;
+
+               /* UV5 Hubless */
+               if (strncmp(uv_archtype, "NSGI5", 5) == 0)
+                       uv_hubless_system |= 0x20;
+
                /* UV4 Hubless: CH */
-               if (strncmp(uv_archtype, "NSGI4", 5) == 0)
-                       uv_hubless_system = 0x11;
+               else if (strncmp(uv_archtype, "NSGI4", 5) == 0)
+                       uv_hubless_system |= 0x10;
 
                /* UV3 Hubless: UV300/MC990X w/o hub */
                else
-                       uv_hubless_system = 0x9;
+                       uv_hubless_system |= 0x8;
+
+               /* Copy APIC type */
+               uv_stringify(sizeof(oem_table_id), oem_table_id, _oem_table_id);
 
                pr_info("UV: OEM IDs %s/%s, SystemType %d, HUBLESS ID %x\n",
                        oem_id, oem_table_id, uv_system_type, uv_hubless_system);
@@ -456,7 +469,7 @@ static int __init uv_acpi_madt_oem_check(char *_oem_id, char *_oem_table_id)
        uv_cpu_info->p_uv_hub_info = &uv_hub_info_node0;
 
        /* If not UV, return. */
-       if (likely(uv_set_system_type(_oem_id) == 0))
+       if (uv_set_system_type(_oem_id, _oem_table_id) == 0)
                return 0;
 
        /* Save and Decode OEM Table ID */
index d3f0db463f96ab57021e42958b057194fad1ad93..d41b70fe4918e3f8f9613b87e452d55d01984671 100644 (file)
@@ -739,11 +739,13 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
        if (boot_cpu_has(X86_FEATURE_IBPB)) {
                setup_force_cpu_cap(X86_FEATURE_USE_IBPB);
 
+               spectre_v2_user_ibpb = mode;
                switch (cmd) {
                case SPECTRE_V2_USER_CMD_FORCE:
                case SPECTRE_V2_USER_CMD_PRCTL_IBPB:
                case SPECTRE_V2_USER_CMD_SECCOMP_IBPB:
                        static_branch_enable(&switch_mm_always_ibpb);
+                       spectre_v2_user_ibpb = SPECTRE_V2_USER_STRICT;
                        break;
                case SPECTRE_V2_USER_CMD_PRCTL:
                case SPECTRE_V2_USER_CMD_AUTO:
@@ -757,8 +759,6 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
                pr_info("mitigation: Enabling %s Indirect Branch Prediction Barrier\n",
                        static_key_enabled(&switch_mm_always_ibpb) ?
                        "always-on" : "conditional");
-
-               spectre_v2_user_ibpb = mode;
        }
 
        /*
@@ -1254,6 +1254,14 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
        return 0;
 }
 
+static bool is_spec_ib_user_controlled(void)
+{
+       return spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL ||
+               spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP ||
+               spectre_v2_user_stibp == SPECTRE_V2_USER_PRCTL ||
+               spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP;
+}
+
 static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
 {
        switch (ctrl) {
@@ -1261,16 +1269,26 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
                if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
                    spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
                        return 0;
+
                /*
-                * Indirect branch speculation is always disabled in strict
-                * mode. It can neither be enabled if it was force-disabled
-                * by a  previous prctl call.
+                * With strict mode for both IBPB and STIBP, the instruction
+                * code paths avoid checking this task flag and instead,
+                * unconditionally run the instruction. However, STIBP and IBPB
+                * are independent and either can be set to conditionally
+                * enabled regardless of the mode of the other.
+                *
+                * If either is set to conditional, allow the task flag to be
+                * updated, unless it was force-disabled by a previous prctl
+                * call. Currently, this is possible on an AMD CPU which has the
+                * feature X86_FEATURE_AMD_STIBP_ALWAYS_ON. In this case, if the
+                * kernel is booted with 'spectre_v2_user=seccomp', then
+                * spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP and
+                * spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED.
                 */
-               if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
-                   spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
-                   spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED ||
+               if (!is_spec_ib_user_controlled() ||
                    task_spec_ib_force_disable(task))
                        return -EPERM;
+
                task_clear_spec_ib_disable(task);
                task_update_spec_tif(task);
                break;
@@ -1283,10 +1301,10 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
                if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
                    spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
                        return -EPERM;
-               if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
-                   spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
-                   spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
+
+               if (!is_spec_ib_user_controlled())
                        return 0;
+
                task_set_spec_ib_disable(task);
                if (ctrl == PR_SPEC_FORCE_DISABLE)
                        task_set_spec_ib_force_disable(task);
@@ -1351,20 +1369,17 @@ static int ib_prctl_get(struct task_struct *task)
        if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
            spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
                return PR_SPEC_ENABLE;
-       else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
-           spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
-           spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
-               return PR_SPEC_DISABLE;
-       else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL ||
-           spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP ||
-           spectre_v2_user_stibp == SPECTRE_V2_USER_PRCTL ||
-           spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP) {
+       else if (is_spec_ib_user_controlled()) {
                if (task_spec_ib_force_disable(task))
                        return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
                if (task_spec_ib_disable(task))
                        return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
                return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
-       } else
+       } else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
+           spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
+           spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
+               return PR_SPEC_DISABLE;
+       else
                return PR_SPEC_NOT_AFFECTED;
 }
 
index 4102b866e7c0ed80dcbf2834c96089f84176df71..32b7099e35111910b09a237e3da0ac273801dbf3 100644 (file)
@@ -1384,8 +1384,10 @@ noinstr void do_machine_check(struct pt_regs *regs)
         * When there's any problem use only local no_way_out state.
         */
        if (!lmce) {
-               if (mce_end(order) < 0)
-                       no_way_out = worst >= MCE_PANIC_SEVERITY;
+               if (mce_end(order) < 0) {
+                       if (!no_way_out)
+                               no_way_out = worst >= MCE_PANIC_SEVERITY;
+               }
        } else {
                /*
                 * If there was a fatal machine check we should have
index 6a99535d7f3794309a89c05d60463bf122724140..7e8e07bddd5fefb2652b9ced595b71f1211f5eb2 100644 (file)
@@ -100,53 +100,6 @@ static int has_newer_microcode(void *mc, unsigned int csig, int cpf, int new_rev
        return find_matching_signature(mc, csig, cpf);
 }
 
-/*
- * Given CPU signature and a microcode patch, this function finds if the
- * microcode patch has matching family and model with the CPU.
- *
- * %true - if there's a match
- * %false - otherwise
- */
-static bool microcode_matches(struct microcode_header_intel *mc_header,
-                             unsigned long sig)
-{
-       unsigned long total_size = get_totalsize(mc_header);
-       unsigned long data_size = get_datasize(mc_header);
-       struct extended_sigtable *ext_header;
-       unsigned int fam_ucode, model_ucode;
-       struct extended_signature *ext_sig;
-       unsigned int fam, model;
-       int ext_sigcount, i;
-
-       fam   = x86_family(sig);
-       model = x86_model(sig);
-
-       fam_ucode   = x86_family(mc_header->sig);
-       model_ucode = x86_model(mc_header->sig);
-
-       if (fam == fam_ucode && model == model_ucode)
-               return true;
-
-       /* Look for ext. headers: */
-       if (total_size <= data_size + MC_HEADER_SIZE)
-               return false;
-
-       ext_header   = (void *) mc_header + data_size + MC_HEADER_SIZE;
-       ext_sig      = (void *)ext_header + EXT_HEADER_SIZE;
-       ext_sigcount = ext_header->count;
-
-       for (i = 0; i < ext_sigcount; i++) {
-               fam_ucode   = x86_family(ext_sig->sig);
-               model_ucode = x86_model(ext_sig->sig);
-
-               if (fam == fam_ucode && model == model_ucode)
-                       return true;
-
-               ext_sig++;
-       }
-       return false;
-}
-
 static struct ucode_patch *memdup_patch(void *data, unsigned int size)
 {
        struct ucode_patch *p;
@@ -164,7 +117,7 @@ static struct ucode_patch *memdup_patch(void *data, unsigned int size)
        return p;
 }
 
-static void save_microcode_patch(void *data, unsigned int size)
+static void save_microcode_patch(struct ucode_cpu_info *uci, void *data, unsigned int size)
 {
        struct microcode_header_intel *mc_hdr, *mc_saved_hdr;
        struct ucode_patch *iter, *tmp, *p = NULL;
@@ -210,6 +163,9 @@ static void save_microcode_patch(void *data, unsigned int size)
        if (!p)
                return;
 
+       if (!find_matching_signature(p->data, uci->cpu_sig.sig, uci->cpu_sig.pf))
+               return;
+
        /*
         * Save for early loading. On 32-bit, that needs to be a physical
         * address as the APs are running from physical addresses, before
@@ -344,13 +300,14 @@ scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save)
 
                size -= mc_size;
 
-               if (!microcode_matches(mc_header, uci->cpu_sig.sig)) {
+               if (!find_matching_signature(data, uci->cpu_sig.sig,
+                                            uci->cpu_sig.pf)) {
                        data += mc_size;
                        continue;
                }
 
                if (save) {
-                       save_microcode_patch(data, mc_size);
+                       save_microcode_patch(uci, data, mc_size);
                        goto next;
                }
 
@@ -483,14 +440,14 @@ static void show_saved_mc(void)
  * Save this microcode patch. It will be loaded early when a CPU is
  * hot-added or resumes.
  */
-static void save_mc_for_early(u8 *mc, unsigned int size)
+static void save_mc_for_early(struct ucode_cpu_info *uci, u8 *mc, unsigned int size)
 {
        /* Synchronization during CPU hotplug. */
        static DEFINE_MUTEX(x86_cpu_microcode_mutex);
 
        mutex_lock(&x86_cpu_microcode_mutex);
 
-       save_microcode_patch(mc, size);
+       save_microcode_patch(uci, mc, size);
        show_saved_mc();
 
        mutex_unlock(&x86_cpu_microcode_mutex);
@@ -935,7 +892,7 @@ static enum ucode_state generic_load_microcode(int cpu, struct iov_iter *iter)
         * permanent memory. So it will be loaded early when a CPU is hot added
         * or resumes.
         */
-       save_mc_for_early(new_mc, new_mc_size);
+       save_mc_for_early(uci, new_mc, new_mc_size);
 
        pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
                 cpu, new_rev, uci->cpu_sig.rev);
index e5f4ee8f4c3bbd7ed9b1c10e383fe28a190931ff..e8b5f1cf1ae8ceb13f263793c2489589e9627e5d 100644 (file)
@@ -570,6 +570,8 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
 
        if (d) {
                cpumask_set_cpu(cpu, &d->cpu_mask);
+               if (r->cache.arch_has_per_cpu_cfg)
+                       rdt_domain_reconfigure_cdp(r);
                return;
        }
 
@@ -923,6 +925,7 @@ static __init void rdt_init_res_defs_intel(void)
                    r->rid == RDT_RESOURCE_L2CODE) {
                        r->cache.arch_has_sparse_bitmaps = false;
                        r->cache.arch_has_empty_bitmaps = false;
+                       r->cache.arch_has_per_cpu_cfg = false;
                } else if (r->rid == RDT_RESOURCE_MBA) {
                        r->msr_base = MSR_IA32_MBA_THRTL_BASE;
                        r->msr_update = mba_wrmsr_intel;
@@ -943,6 +946,7 @@ static __init void rdt_init_res_defs_amd(void)
                    r->rid == RDT_RESOURCE_L2CODE) {
                        r->cache.arch_has_sparse_bitmaps = true;
                        r->cache.arch_has_empty_bitmaps = true;
+                       r->cache.arch_has_per_cpu_cfg = true;
                } else if (r->rid == RDT_RESOURCE_MBA) {
                        r->msr_base = MSR_IA32_MBA_BW_BASE;
                        r->msr_update = mba_wrmsr_amd;
index 80fa997fae60e30a68cd329ed50220a960f3c2d8..f65d3c0dbc417bbf6004bc4248b3b12e5434c3de 100644 (file)
@@ -360,6 +360,8 @@ struct msr_param {
  *                     executing entities
  * @arch_has_sparse_bitmaps:   True if a bitmap like f00f is valid.
  * @arch_has_empty_bitmaps:    True if the '0' bitmap is valid.
+ * @arch_has_per_cpu_cfg:      True if QOS_CFG register for this cache
+ *                             level has CPU scope.
  */
 struct rdt_cache {
        unsigned int    cbm_len;
@@ -369,6 +371,7 @@ struct rdt_cache {
        unsigned int    shareable_bits;
        bool            arch_has_sparse_bitmaps;
        bool            arch_has_empty_bitmaps;
+       bool            arch_has_per_cpu_cfg;
 };
 
 /**
index af323e2e3100af073c78c4213f10625ad86b0422..f3418428682b1acb28c6606a138b63cfb9075791 100644 (file)
@@ -507,6 +507,24 @@ unlock:
        return ret ?: nbytes;
 }
 
+/**
+ * rdtgroup_remove - the helper to remove resource group safely
+ * @rdtgrp: resource group to remove
+ *
+ * On resource group creation via a mkdir, an extra kernfs_node reference is
+ * taken to ensure that the rdtgroup structure remains accessible for the
+ * rdtgroup_kn_unlock() calls where it is removed.
+ *
+ * Drop the extra reference here, then free the rdtgroup structure.
+ *
+ * Return: void
+ */
+static void rdtgroup_remove(struct rdtgroup *rdtgrp)
+{
+       kernfs_put(rdtgrp->kn);
+       kfree(rdtgrp);
+}
+
 struct task_move_callback {
        struct callback_head    work;
        struct rdtgroup         *rdtgrp;
@@ -529,7 +547,7 @@ static void move_myself(struct callback_head *head)
            (rdtgrp->flags & RDT_DELETED)) {
                current->closid = 0;
                current->rmid = 0;
-               kfree(rdtgrp);
+               rdtgroup_remove(rdtgrp);
        }
 
        if (unlikely(current->flags & PF_EXITING))
@@ -1769,7 +1787,6 @@ static int rdtgroup_mkdir_info_resdir(struct rdt_resource *r, char *name,
        if (IS_ERR(kn_subdir))
                return PTR_ERR(kn_subdir);
 
-       kernfs_get(kn_subdir);
        ret = rdtgroup_kn_set_ugid(kn_subdir);
        if (ret)
                return ret;
@@ -1792,7 +1809,6 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)
        kn_info = kernfs_create_dir(parent_kn, "info", parent_kn->mode, NULL);
        if (IS_ERR(kn_info))
                return PTR_ERR(kn_info);
-       kernfs_get(kn_info);
 
        ret = rdtgroup_add_files(kn_info, RF_TOP_INFO);
        if (ret)
@@ -1813,12 +1829,6 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)
                        goto out_destroy;
        }
 
-       /*
-        * This extra ref will be put in kernfs_remove() and guarantees
-        * that @rdtgrp->kn is always accessible.
-        */
-       kernfs_get(kn_info);
-
        ret = rdtgroup_kn_set_ugid(kn_info);
        if (ret)
                goto out_destroy;
@@ -1847,12 +1857,6 @@ mongroup_create_dir(struct kernfs_node *parent_kn, struct rdtgroup *prgrp,
        if (dest_kn)
                *dest_kn = kn;
 
-       /*
-        * This extra ref will be put in kernfs_remove() and guarantees
-        * that @rdtgrp->kn is always accessible.
-        */
-       kernfs_get(kn);
-
        ret = rdtgroup_kn_set_ugid(kn);
        if (ret)
                goto out_destroy;
@@ -1905,8 +1909,13 @@ static int set_cache_qos_cfg(int level, bool enable)
 
        r_l = &rdt_resources_all[level];
        list_for_each_entry(d, &r_l->domains, list) {
-               /* Pick one CPU from each domain instance to update MSR */
-               cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
+               if (r_l->cache.arch_has_per_cpu_cfg)
+                       /* Pick all the CPUs in the domain instance */
+                       for_each_cpu(cpu, &d->cpu_mask)
+                               cpumask_set_cpu(cpu, cpu_mask);
+               else
+                       /* Pick one CPU from each domain instance to update MSR */
+                       cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
        }
        cpu = get_cpu();
        /* Update QOS_CFG MSR on this cpu if it's in cpu_mask. */
@@ -2079,8 +2088,7 @@ void rdtgroup_kn_unlock(struct kernfs_node *kn)
                    rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED)
                        rdtgroup_pseudo_lock_remove(rdtgrp);
                kernfs_unbreak_active_protection(kn);
-               kernfs_put(rdtgrp->kn);
-               kfree(rdtgrp);
+               rdtgroup_remove(rdtgrp);
        } else {
                kernfs_unbreak_active_protection(kn);
        }
@@ -2139,13 +2147,11 @@ static int rdt_get_tree(struct fs_context *fc)
                                          &kn_mongrp);
                if (ret < 0)
                        goto out_info;
-               kernfs_get(kn_mongrp);
 
                ret = mkdir_mondata_all(rdtgroup_default.kn,
                                        &rdtgroup_default, &kn_mondata);
                if (ret < 0)
                        goto out_mongrp;
-               kernfs_get(kn_mondata);
                rdtgroup_default.mon.mon_data_kn = kn_mondata;
        }
 
@@ -2357,7 +2363,7 @@ static void free_all_child_rdtgrp(struct rdtgroup *rdtgrp)
                if (atomic_read(&sentry->waitcount) != 0)
                        sentry->flags = RDT_DELETED;
                else
-                       kfree(sentry);
+                       rdtgroup_remove(sentry);
        }
 }
 
@@ -2399,7 +2405,7 @@ static void rmdir_all_sub(void)
                if (atomic_read(&rdtgrp->waitcount) != 0)
                        rdtgrp->flags = RDT_DELETED;
                else
-                       kfree(rdtgrp);
+                       rdtgroup_remove(rdtgrp);
        }
        /* Notify online CPUs to update per cpu storage and PQR_ASSOC MSR */
        update_closid_rmid(cpu_online_mask, &rdtgroup_default);
@@ -2499,11 +2505,6 @@ static int mkdir_mondata_subdir(struct kernfs_node *parent_kn,
        if (IS_ERR(kn))
                return PTR_ERR(kn);
 
-       /*
-        * This extra ref will be put in kernfs_remove() and guarantees
-        * that kn is always accessible.
-        */
-       kernfs_get(kn);
        ret = rdtgroup_kn_set_ugid(kn);
        if (ret)
                goto out_destroy;
@@ -2838,8 +2839,8 @@ static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
        /*
         * kernfs_remove() will drop the reference count on "kn" which
         * will free it. But we still need it to stick around for the
-        * rdtgroup_kn_unlock(kn} call below. Take one extra reference
-        * here, which will be dropped inside rdtgroup_kn_unlock().
+        * rdtgroup_kn_unlock(kn) call. Take one extra reference here,
+        * which will be dropped by kernfs_put() in rdtgroup_remove().
         */
        kernfs_get(kn);
 
@@ -2880,6 +2881,7 @@ static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
 out_idfree:
        free_rmid(rdtgrp->mon.rmid);
 out_destroy:
+       kernfs_put(rdtgrp->kn);
        kernfs_remove(rdtgrp->kn);
 out_free_rgrp:
        kfree(rdtgrp);
@@ -2892,7 +2894,7 @@ static void mkdir_rdt_prepare_clean(struct rdtgroup *rgrp)
 {
        kernfs_remove(rgrp->kn);
        free_rmid(rgrp->mon.rmid);
-       kfree(rgrp);
+       rdtgroup_remove(rgrp);
 }
 
 /*
@@ -3049,11 +3051,6 @@ static int rdtgroup_rmdir_mon(struct kernfs_node *kn, struct rdtgroup *rdtgrp,
        WARN_ON(list_empty(&prdtgrp->mon.crdtgrp_list));
        list_del(&rdtgrp->mon.crdtgrp_list);
 
-       /*
-        * one extra hold on this, will drop when we kfree(rdtgrp)
-        * in rdtgroup_kn_unlock()
-        */
-       kernfs_get(kn);
        kernfs_remove(rdtgrp->kn);
 
        return 0;
@@ -3065,11 +3062,6 @@ static int rdtgroup_ctrl_remove(struct kernfs_node *kn,
        rdtgrp->flags = RDT_DELETED;
        list_del(&rdtgrp->rdtgroup_list);
 
-       /*
-        * one extra hold on this, will drop when we kfree(rdtgrp)
-        * in rdtgroup_kn_unlock()
-        */
-       kernfs_get(kn);
        kernfs_remove(rdtgrp->kn);
        return 0;
 }
index 25c06b67e7e01ff9cc63d87dec6356f7fb0a2599..97aa900386cbbe507cdf538de42f3f226dd02bdb 100644 (file)
@@ -78,6 +78,9 @@ static int copy_code(struct pt_regs *regs, u8 *buf, unsigned long src,
        if (!user_mode(regs))
                return copy_from_kernel_nofault(buf, (u8 *)src, nbytes);
 
+       /* The user space code from other tasks cannot be accessed. */
+       if (regs != task_pt_regs(current))
+               return -EPERM;
        /*
         * Make sure userspace isn't trying to trick us into dumping kernel
         * memory by pointing the userspace instruction pointer at it.
@@ -85,6 +88,12 @@ static int copy_code(struct pt_regs *regs, u8 *buf, unsigned long src,
        if (__chk_range_not_ok(src, nbytes, TASK_SIZE_MAX))
                return -EINVAL;
 
+       /*
+        * Even if named copy_from_user_nmi() this can be invoked from
+        * other contexts and will not try to resolve a pagefault, which is
+        * the correct thing to do here as this code can be called from any
+        * context.
+        */
        return copy_from_user_nmi(buf, (void __user *)src, nbytes);
 }
 
@@ -115,13 +124,19 @@ void show_opcodes(struct pt_regs *regs, const char *loglvl)
        u8 opcodes[OPCODE_BUFSIZE];
        unsigned long prologue = regs->ip - PROLOGUE_SIZE;
 
-       if (copy_code(regs, opcodes, prologue, sizeof(opcodes))) {
-               printk("%sCode: Unable to access opcode bytes at RIP 0x%lx.\n",
-                      loglvl, prologue);
-       } else {
+       switch (copy_code(regs, opcodes, prologue, sizeof(opcodes))) {
+       case 0:
                printk("%sCode: %" __stringify(PROLOGUE_SIZE) "ph <%02x> %"
                       __stringify(EPILOGUE_SIZE) "ph\n", loglvl, opcodes,
                       opcodes[PROLOGUE_SIZE], opcodes + PROLOGUE_SIZE + 1);
+               break;
+       case -EPERM:
+               /* No access to the user space stack of other tasks. Ignore. */
+               break;
+       default:
+               printk("%sCode: Unable to access opcode bytes at RIP 0x%lx.\n",
+                      loglvl, prologue);
+               break;
        }
 }
 
index 7eb2a1c879695dcf1712964eb546e77b26d5513a..3c417734790f0390089beaa9da01e612c750c54a 100644 (file)
@@ -161,6 +161,21 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
 
        /* Setup early boot stage 4-/5-level pagetables. */
        addq    phys_base(%rip), %rax
+
+       /*
+        * For SEV guests: Verify that the C-bit is correct. A malicious
+        * hypervisor could lie about the C-bit position to perform a ROP
+        * attack on the guest by writing to the unencrypted stack and wait for
+        * the next RET instruction.
+        * %rsi carries pointer to realmode data and is callee-clobbered. Save
+        * and restore it.
+        */
+       pushq   %rsi
+       movq    %rax, %rdi
+       call    sev_verify_cbit
+       popq    %rsi
+
+       /* Switch to new page-table */
        movq    %rax, %cr3
 
        /* Ensure I am executing from virtual addresses */
@@ -279,6 +294,7 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
 SYM_CODE_END(secondary_startup_64)
 
 #include "verify_cpu.S"
+#include "sev_verify_cbit.S"
 
 #ifdef CONFIG_HOTPLUG_CPU
 /*
index 57c2ecf43134380ca2bb36c51cc66b1a3b074454..ce831f9448e71e107f07479bca4e497038bae3c8 100644 (file)
@@ -200,8 +200,7 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params,
        params->hdr.hardware_subarch = boot_params.hdr.hardware_subarch;
 
        /* Copying screen_info will do? */
-       memcpy(&params->screen_info, &boot_params.screen_info,
-                               sizeof(struct screen_info));
+       memcpy(&params->screen_info, &screen_info, sizeof(struct screen_info));
 
        /* Fill in memsize later */
        params->screen_info.ext_mem_k = 0;
index bb7e1132290b0073b0ff3b0ac68d69d48016d2a8..f9e5352b3bef9b1b99153c9cb0392f9c50048aea 100644 (file)
@@ -101,8 +101,7 @@ u64 perf_reg_abi(struct task_struct *task)
 }
 
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
        regs_user->regs = task_pt_regs(current);
        regs_user->abi = perf_reg_abi(current);
@@ -129,12 +128,20 @@ u64 perf_reg_abi(struct task_struct *task)
                return PERF_SAMPLE_REGS_ABI_64;
 }
 
+static DEFINE_PER_CPU(struct pt_regs, nmi_user_regs);
+
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
+       struct pt_regs *regs_user_copy = this_cpu_ptr(&nmi_user_regs);
        struct pt_regs *user_regs = task_pt_regs(current);
 
+       if (!in_nmi()) {
+               regs_user->regs = user_regs;
+               regs_user->abi = perf_reg_abi(current);
+               return;
+       }
+
        /*
         * If we're in an NMI that interrupted task_pt_regs setup, then
         * we can't sample user regs at all.  This check isn't really
index ba4593a913fab3dc6f5b136470c07c02699aeefd..145a7ac0c19aa1f9a6e72d47d65a257029ec434a 100644 (file)
@@ -685,7 +685,7 @@ void arch_cpu_idle(void)
  */
 void __cpuidle default_idle(void)
 {
-       safe_halt();
+       raw_safe_halt();
 }
 #if defined(CONFIG_APM_MODULE) || defined(CONFIG_HALTPOLL_CPUIDLE_MODULE)
 EXPORT_SYMBOL(default_idle);
@@ -736,6 +736,8 @@ void stop_this_cpu(void *dummy)
 /*
  * AMD Erratum 400 aware idle routine. We handle it the same way as C3 power
  * states (local apic timer and TSC stop).
+ *
+ * XXX this function is completely buggered vs RCU and tracing.
  */
 static void amd_e400_idle(void)
 {
@@ -757,9 +759,9 @@ static void amd_e400_idle(void)
         * The switch back from broadcast mode needs to be called with
         * interrupts disabled.
         */
-       local_irq_disable();
+       raw_local_irq_disable();
        tick_broadcast_exit();
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 
 /*
@@ -801,9 +803,9 @@ static __cpuidle void mwait_idle(void)
                if (!need_resched())
                        __sti_mwait(0, 0);
                else
-                       local_irq_enable();
+                       raw_local_irq_enable();
        } else {
-               local_irq_enable();
+               raw_local_irq_enable();
        }
        __current_clr_polling();
 }
index 5f83ccaab877b57c88412c38d7fa8b3532249cfa..7d04b356d44d3362b9d59c561f4c680514a56a2b 100644 (file)
@@ -178,6 +178,32 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code)
                goto fail;
        regs->dx = val >> 32;
 
+       /*
+        * This is a VC handler and the #VC is only raised when SEV-ES is
+        * active, which means SEV must be active too. Do sanity checks on the
+        * CPUID results to make sure the hypervisor does not trick the kernel
+        * into the no-sev path. This could map sensitive data unencrypted and
+        * make it accessible to the hypervisor.
+        *
+        * In particular, check for:
+        *      - Hypervisor CPUID bit
+        *      - Availability of CPUID leaf 0x8000001f
+        *      - SEV CPUID bit.
+        *
+        * The hypervisor might still report the wrong C-bit position, but this
+        * can't be checked here.
+        */
+
+       if ((fn == 1 && !(regs->cx & BIT(31))))
+               /* Hypervisor bit */
+               goto fail;
+       else if (fn == 0x80000000 && (regs->ax < 0x8000001f))
+               /* SEV leaf check */
+               goto fail;
+       else if ((fn == 0x8000001f && !(regs->ax & BIT(1))))
+               /* SEV bit */
+               goto fail;
+
        /* Skip over the CPUID two-byte opcode */
        regs->ip += 2;
 
index 4a96726fbaf88b4d079a7d1e3ca6857d51fc27ff..0bd1a0fc587e0f830e25e5b4199972ad1471ff96 100644 (file)
@@ -374,8 +374,8 @@ fault:
        return ES_EXCEPTION;
 }
 
-static bool vc_slow_virt_to_phys(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
-                                unsigned long vaddr, phys_addr_t *paddr)
+static enum es_result vc_slow_virt_to_phys(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
+                                          unsigned long vaddr, phys_addr_t *paddr)
 {
        unsigned long va = (unsigned long)vaddr;
        unsigned int level;
@@ -394,15 +394,19 @@ static bool vc_slow_virt_to_phys(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
                if (user_mode(ctxt->regs))
                        ctxt->fi.error_code |= X86_PF_USER;
 
-               return false;
+               return ES_EXCEPTION;
        }
 
+       if (WARN_ON_ONCE(pte_val(*pte) & _PAGE_ENC))
+               /* Emulated MMIO to/from encrypted memory not supported */
+               return ES_UNSUPPORTED;
+
        pa = (phys_addr_t)pte_pfn(*pte) << PAGE_SHIFT;
        pa |= va & ~page_level_mask(level);
 
        *paddr = pa;
 
-       return true;
+       return ES_OK;
 }
 
 /* Include code shared with pre-decompression boot stage */
@@ -731,6 +735,7 @@ static enum es_result vc_do_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
 {
        u64 exit_code, exit_info_1, exit_info_2;
        unsigned long ghcb_pa = __pa(ghcb);
+       enum es_result res;
        phys_addr_t paddr;
        void __user *ref;
 
@@ -740,11 +745,12 @@ static enum es_result vc_do_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
 
        exit_code = read ? SVM_VMGEXIT_MMIO_READ : SVM_VMGEXIT_MMIO_WRITE;
 
-       if (!vc_slow_virt_to_phys(ghcb, ctxt, (unsigned long)ref, &paddr)) {
-               if (!read)
+       res = vc_slow_virt_to_phys(ghcb, ctxt, (unsigned long)ref, &paddr);
+       if (res != ES_OK) {
+               if (res == ES_EXCEPTION && !read)
                        ctxt->fi.error_code |= X86_PF_WRITE;
 
-               return ES_EXCEPTION;
+               return res;
        }
 
        exit_info_1 = paddr;
diff --git a/arch/x86/kernel/sev_verify_cbit.S b/arch/x86/kernel/sev_verify_cbit.S
new file mode 100644 (file)
index 0000000..ee04941
--- /dev/null
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ *     sev_verify_cbit.S - Code for verification of the C-bit position reported
+ *                         by the Hypervisor when running with SEV enabled.
+ *
+ *     Copyright (c) 2020  Joerg Roedel (jroedel@suse.de)
+ *
+ * sev_verify_cbit() is called before switching to a new long-mode page-table
+ * at boot.
+ *
+ * Verify that the C-bit position is correct by writing a random value to
+ * an encrypted memory location while on the current page-table. Then it
+ * switches to the new page-table to verify the memory content is still the
+ * same. After that it switches back to the current page-table and when the
+ * check succeeded it returns. If the check failed the code invalidates the
+ * stack pointer and goes into a hlt loop. The stack-pointer is invalidated to
+ * make sure no interrupt or exception can get the CPU out of the hlt loop.
+ *
+ * New page-table pointer is expected in %rdi (first parameter)
+ *
+ */
+SYM_FUNC_START(sev_verify_cbit)
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+       /* First check if a C-bit was detected */
+       movq    sme_me_mask(%rip), %rsi
+       testq   %rsi, %rsi
+       jz      3f
+
+       /* sme_me_mask != 0 could mean SME or SEV - Check also for SEV */
+       movq    sev_status(%rip), %rsi
+       testq   %rsi, %rsi
+       jz      3f
+
+       /* Save CR4 in %rsi */
+       movq    %cr4, %rsi
+
+       /* Disable Global Pages */
+       movq    %rsi, %rdx
+       andq    $(~X86_CR4_PGE), %rdx
+       movq    %rdx, %cr4
+
+       /*
+        * Verified that running under SEV - now get a random value using
+        * RDRAND. This instruction is mandatory when running as an SEV guest.
+        *
+        * Don't bail out of the loop if RDRAND returns errors. It is better to
+        * prevent forward progress than to work with a non-random value here.
+        */
+1:     rdrand  %rdx
+       jnc     1b
+
+       /* Store value to memory and keep it in %rdx */
+       movq    %rdx, sev_check_data(%rip)
+
+       /* Backup current %cr3 value to restore it later */
+       movq    %cr3, %rcx
+
+       /* Switch to new %cr3 - This might unmap the stack */
+       movq    %rdi, %cr3
+
+       /*
+        * Compare value in %rdx with memory location. If C-bit is incorrect
+        * this would read the encrypted data and make the check fail.
+        */
+       cmpq    %rdx, sev_check_data(%rip)
+
+       /* Restore old %cr3 */
+       movq    %rcx, %cr3
+
+       /* Restore previous CR4 */
+       movq    %rsi, %cr4
+
+       /* Check CMPQ result */
+       je      3f
+
+       /*
+        * The check failed, prevent any forward progress to prevent ROP
+        * attacks, invalidate the stack and go into a hlt loop.
+        */
+       xorq    %rsp, %rsp
+       subq    $0x1000, %rsp
+2:     hlt
+       jmp 2b
+3:
+#endif
+       /* Return page-table pointer */
+       movq    %rdi, %rax
+       ret
+SYM_FUNC_END(sev_verify_cbit)
index 992fb1415c0f1fcd7b5ec0b2346073dc41c1f332..ae64f98ec2ab6a213202bb15b16d34abc6780806 100644 (file)
@@ -514,16 +514,10 @@ int tboot_force_iommu(void)
        if (!tboot_enabled())
                return 0;
 
-       if (intel_iommu_tboot_noforce)
-               return 1;
-
-       if (no_iommu || swiotlb || dmar_disabled)
+       if (no_iommu || dmar_disabled)
                pr_warn("Forcing Intel-IOMMU to enabled\n");
 
        dmar_disabled = 0;
-#ifdef CONFIG_SWIOTLB
-       swiotlb = 0;
-#endif
        no_iommu = 0;
 
        return 1;
index 3c70fb34028b1d74bd38d00f98c8cfa6836d21af..e19df6cde35d1d5d7c6a1ffb09e2d26cc39d1b95 100644 (file)
@@ -793,19 +793,6 @@ static __always_inline unsigned long debug_read_clear_dr6(void)
        set_debugreg(DR6_RESERVED, 6);
        dr6 ^= DR6_RESERVED; /* Flip to positive polarity */
 
-       /*
-        * Clear the virtual DR6 value, ptrace routines will set bits here for
-        * things we want signals for.
-        */
-       current->thread.virtual_dr6 = 0;
-
-       /*
-        * The SDM says "The processor clears the BTF flag when it
-        * generates a debug exception."  Clear TIF_BLOCKSTEP to keep
-        * TIF_BLOCKSTEP in sync with the hardware BTF flag.
-        */
-       clear_thread_flag(TIF_BLOCKSTEP);
-
        return dr6;
 }
 
@@ -873,6 +860,20 @@ static __always_inline void exc_debug_kernel(struct pt_regs *regs,
         */
        WARN_ON_ONCE(user_mode(regs));
 
+       if (test_thread_flag(TIF_BLOCKSTEP)) {
+               /*
+                * The SDM says "The processor clears the BTF flag when it
+                * generates a debug exception." but PTRACE_BLOCKSTEP requested
+                * it for userspace, but we just took a kernel #DB, so re-set
+                * BTF.
+                */
+               unsigned long debugctl;
+
+               rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
+               debugctl |= DEBUGCTLMSR_BTF;
+               wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
+       }
+
        /*
         * Catch SYSENTER with TF set and clear DR_STEP. If this hit a
         * watchpoint at the same time then that will still be handled.
@@ -935,6 +936,22 @@ static __always_inline void exc_debug_user(struct pt_regs *regs,
        irqentry_enter_from_user_mode(regs);
        instrumentation_begin();
 
+       /*
+        * Start the virtual/ptrace DR6 value with just the DR_STEP mask
+        * of the real DR6. ptrace_triggered() will set the DR_TRAPn bits.
+        *
+        * Userspace expects DR_STEP to be visible in ptrace_get_debugreg(6)
+        * even if it is not the result of PTRACE_SINGLESTEP.
+        */
+       current->thread.virtual_dr6 = (dr6 & DR_STEP);
+
+       /*
+        * The SDM says "The processor clears the BTF flag when it
+        * generates a debug exception."  Clear TIF_BLOCKSTEP to keep
+        * TIF_BLOCKSTEP in sync with the hardware BTF flag.
+        */
+       clear_thread_flag(TIF_BLOCKSTEP);
+
        /*
         * If dr6 has no reason to give us about the origin of this trap,
         * then it's very likely the result of an icebp/int01 trap.
index 6a339ce328e0a7eb2546ae1f5f8517b293100226..73f8001000669e2595fe8a4a9eeb7bf9108e9c62 100644 (file)
@@ -321,19 +321,12 @@ EXPORT_SYMBOL_GPL(unwind_get_return_address);
 
 unsigned long *unwind_get_return_address_ptr(struct unwind_state *state)
 {
-       struct task_struct *task = state->task;
-
        if (unwind_done(state))
                return NULL;
 
        if (state->regs)
                return &state->regs->ip;
 
-       if (task != current && state->sp == task->thread.sp) {
-               struct inactive_task_frame *frame = (void *)task->thread.sp;
-               return &frame->ret_addr;
-       }
-
        if (state->sp)
                return (unsigned long *)state->sp - 1;
 
@@ -663,7 +656,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
        } else {
                struct inactive_task_frame *frame = (void *)task->thread.sp;
 
-               state->sp = task->thread.sp;
+               state->sp = task->thread.sp + sizeof(*frame);
                state->bp = READ_ONCE_NOCHECK(frame->bp);
                state->ip = READ_ONCE_NOCHECK(frame->ret_addr);
                state->signal = (void *)state->ip == ret_from_fork;
index 3fdaa042823d026366eaddcf95dc0f7de0775e89..138bdb1fd1360aebc3cd5cc95a0821117c9ccfe7 100644 (file)
@@ -255,12 +255,13 @@ static volatile u32 good_2byte_insns[256 / 32] = {
 
 static bool is_prefix_bad(struct insn *insn)
 {
+       insn_byte_t p;
        int i;
 
-       for (i = 0; i < insn->prefixes.nbytes; i++) {
+       for_each_insn_prefix(insn, i, p) {
                insn_attr_t attr;
 
-               attr = inat_get_opcode_attribute(insn->prefixes.bytes[i]);
+               attr = inat_get_opcode_attribute(p);
                switch (attr) {
                case INAT_MAKE_PREFIX(INAT_PFX_ES):
                case INAT_MAKE_PREFIX(INAT_PFX_CS):
@@ -715,6 +716,7 @@ static const struct uprobe_xol_ops push_xol_ops = {
 static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn)
 {
        u8 opc1 = OPCODE1(insn);
+       insn_byte_t p;
        int i;
 
        switch (opc1) {
@@ -746,8 +748,8 @@ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn)
         * Intel and AMD behavior differ in 64-bit mode: Intel ignores 66 prefix.
         * No one uses these insns, reject any branch insns with such prefix.
         */
-       for (i = 0; i < insn->prefixes.nbytes; i++) {
-               if (insn->prefixes.bytes[i] == 0x66)
+       for_each_insn_prefix(insn, i, p) {
+               if (p == 0x66)
                        return -ENOTSUPP;
        }
 
index 06a278b3701d127b7f7096f23091f69891467362..83637a2ff6052e37a90bdc4080b0707f1f7bf8c0 100644 (file)
@@ -90,6 +90,20 @@ static int kvm_check_cpuid(struct kvm_cpuid_entry2 *entries, int nent)
        return 0;
 }
 
+void kvm_update_pv_runtime(struct kvm_vcpu *vcpu)
+{
+       struct kvm_cpuid_entry2 *best;
+
+       best = kvm_find_cpuid_entry(vcpu, KVM_CPUID_FEATURES, 0);
+
+       /*
+        * save the feature bitmap to avoid cpuid lookup for every PV
+        * operation
+        */
+       if (best)
+               vcpu->arch.pv_cpuid.features = best->eax;
+}
+
 void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
@@ -124,13 +138,6 @@ void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu)
                (best->eax & (1 << KVM_FEATURE_PV_UNHALT)))
                best->eax &= ~(1 << KVM_FEATURE_PV_UNHALT);
 
-       /*
-        * save the feature bitmap to avoid cpuid lookup for every PV
-        * operation
-        */
-       if (best)
-               vcpu->arch.pv_cpuid.features = best->eax;
-
        if (!kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT)) {
                best = kvm_find_cpuid_entry(vcpu, 0x1, 0);
                if (best)
@@ -162,6 +169,8 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
                vcpu->arch.guest_supported_xcr0 =
                        (best->eax | ((u64)best->edx << 32)) & supported_xcr0;
 
+       kvm_update_pv_runtime(vcpu);
+
        vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu);
        kvm_mmu_reset_context(vcpu);
 
@@ -169,6 +178,8 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
        vcpu->arch.cr4_guest_rsvd_bits =
            __cr4_reserved_bits(guest_cpuid_has, vcpu);
 
+       vcpu->arch.cr3_lm_rsvd_bits = rsvd_bits(cpuid_maxphyaddr(vcpu), 63);
+
        /* Invoke the vendor callback only after the above state is updated. */
        kvm_x86_ops.vcpu_after_set_cpuid(vcpu);
 }
@@ -672,7 +683,9 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
 
                edx.split.num_counters_fixed = min(cap.num_counters_fixed, MAX_FIXED_COUNTERS);
                edx.split.bit_width_fixed = cap.bit_width_fixed;
-               edx.split.reserved = 0;
+               edx.split.anythread_deprecated = 1;
+               edx.split.reserved1 = 0;
+               edx.split.reserved2 = 0;
 
                entry->eax = eax.full;
                entry->ebx = cap.events_mask;
index bf8577947ed23f9ec0ffcf9350c64a12d6f2e77e..f7a6e8f83783cd89d779596d7c6cbaae5f42a8ea 100644 (file)
@@ -11,6 +11,7 @@ extern u32 kvm_cpu_caps[NCAPINTS] __read_mostly;
 void kvm_set_cpu_caps(void);
 
 void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu);
+void kvm_update_pv_runtime(struct kvm_vcpu *vcpu);
 struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
                                              u32 function, u32 index);
 int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid,
index 0d917eb70319498965590068afa61e4e85d3841a..56cae1ff9e3fe46362947f0911b39573d44397a8 100644 (file)
@@ -4046,6 +4046,12 @@ static int em_clflush(struct x86_emulate_ctxt *ctxt)
        return X86EMUL_CONTINUE;
 }
 
+static int em_clflushopt(struct x86_emulate_ctxt *ctxt)
+{
+       /* emulating clflushopt regardless of cpuid */
+       return X86EMUL_CONTINUE;
+}
+
 static int em_movsxd(struct x86_emulate_ctxt *ctxt)
 {
        ctxt->dst.val = (s32) ctxt->src.val;
@@ -4585,7 +4591,7 @@ static const struct opcode group11[] = {
 };
 
 static const struct gprefix pfx_0f_ae_7 = {
-       I(SrcMem | ByteOp, em_clflush), N, N, N,
+       I(SrcMem | ByteOp, em_clflush), I(SrcMem | ByteOp, em_clflushopt), N, N,
 };
 
 static const struct group_dual group15 = { {
index 99d118ffc67dbac05d0cc2186bc48d09926c8ac2..814698e5b1526180da42043045e87a521870698d 100644 (file)
@@ -40,29 +40,10 @@ static int pending_userspace_extint(struct kvm_vcpu *v)
  * check if there is pending interrupt from
  * non-APIC source without intack.
  */
-static int kvm_cpu_has_extint(struct kvm_vcpu *v)
-{
-       u8 accept = kvm_apic_accept_pic_intr(v);
-
-       if (accept) {
-               if (irqchip_split(v->kvm))
-                       return pending_userspace_extint(v);
-               else
-                       return v->kvm->arch.vpic->output;
-       } else
-               return 0;
-}
-
-/*
- * check if there is injectable interrupt:
- * when virtual interrupt delivery enabled,
- * interrupt from apic will handled by hardware,
- * we don't need to check it here.
- */
-int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v)
+int kvm_cpu_has_extint(struct kvm_vcpu *v)
 {
        /*
-        * FIXME: interrupt.injected represents an interrupt that it's
+        * FIXME: interrupt.injected represents an interrupt whose
         * side-effects have already been applied (e.g. bit from IRR
         * already moved to ISR). Therefore, it is incorrect to rely
         * on interrupt.injected to know if there is a pending
@@ -75,6 +56,23 @@ int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v)
        if (!lapic_in_kernel(v))
                return v->arch.interrupt.injected;
 
+       if (!kvm_apic_accept_pic_intr(v))
+               return 0;
+
+       if (irqchip_split(v->kvm))
+               return pending_userspace_extint(v);
+       else
+               return v->kvm->arch.vpic->output;
+}
+
+/*
+ * check if there is injectable interrupt:
+ * when virtual interrupt delivery enabled,
+ * interrupt from apic will handled by hardware,
+ * we don't need to check it here.
+ */
+int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v)
+{
        if (kvm_cpu_has_extint(v))
                return 1;
 
@@ -91,20 +89,6 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_injectable_intr);
  */
 int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
 {
-       /*
-        * FIXME: interrupt.injected represents an interrupt that it's
-        * side-effects have already been applied (e.g. bit from IRR
-        * already moved to ISR). Therefore, it is incorrect to rely
-        * on interrupt.injected to know if there is a pending
-        * interrupt in the user-mode LAPIC.
-        * This leads to nVMX/nSVM not be able to distinguish
-        * if it should exit from L2 to L1 on EXTERNAL_INTERRUPT on
-        * pending interrupt or should re-inject an injected
-        * interrupt.
-        */
-       if (!lapic_in_kernel(v))
-               return v->arch.interrupt.injected;
-
        if (kvm_cpu_has_extint(v))
                return 1;
 
@@ -118,16 +102,21 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt);
  */
 static int kvm_cpu_get_extint(struct kvm_vcpu *v)
 {
-       if (kvm_cpu_has_extint(v)) {
-               if (irqchip_split(v->kvm)) {
-                       int vector = v->arch.pending_external_vector;
-
-                       v->arch.pending_external_vector = -1;
-                       return vector;
-               } else
-                       return kvm_pic_read_irq(v->kvm); /* PIC */
-       } else
+       if (!kvm_cpu_has_extint(v)) {
+               WARN_ON(!lapic_in_kernel(v));
                return -1;
+       }
+
+       if (!lapic_in_kernel(v))
+               return v->arch.interrupt.nr;
+
+       if (irqchip_split(v->kvm)) {
+               int vector = v->arch.pending_external_vector;
+
+               v->arch.pending_external_vector = -1;
+               return vector;
+       } else
+               return kvm_pic_read_irq(v->kvm); /* PIC */
 }
 
 /*
@@ -135,13 +124,7 @@ static int kvm_cpu_get_extint(struct kvm_vcpu *v)
  */
 int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
 {
-       int vector;
-
-       if (!lapic_in_kernel(v))
-               return v->arch.interrupt.nr;
-
-       vector = kvm_cpu_get_extint(v);
-
+       int vector = kvm_cpu_get_extint(v);
        if (vector != -1)
                return vector;                  /* PIC */
 
index 105e7859d1f2301544636aa6619458ab41faa238..86c33d53c90a0527b7adbd2afb1aa99877c58eb7 100644 (file)
@@ -2465,7 +2465,7 @@ int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu)
        struct kvm_lapic *apic = vcpu->arch.apic;
        u32 ppr;
 
-       if (!kvm_apic_hw_enabled(apic))
+       if (!kvm_apic_present(vcpu))
                return -1;
 
        __apic_update_ppr(apic, &ppr);
index 17587f496ec74aa260674361fb05712142c2df24..7a6ae9e90bd708880e38781cb839d92f22992a2b 100644 (file)
@@ -225,7 +225,7 @@ static gfn_t get_mmio_spte_gfn(u64 spte)
 {
        u64 gpa = spte & shadow_nonpresent_or_rsvd_lower_gfn_mask;
 
-       gpa |= (spte >> shadow_nonpresent_or_rsvd_mask_len)
+       gpa |= (spte >> SHADOW_NONPRESENT_OR_RSVD_MASK_LEN)
               & shadow_nonpresent_or_rsvd_mask;
 
        return gpa >> PAGE_SHIFT;
@@ -591,15 +591,15 @@ static u64 mmu_spte_get_lockless(u64 *sptep)
 static u64 restore_acc_track_spte(u64 spte)
 {
        u64 new_spte = spte;
-       u64 saved_bits = (spte >> shadow_acc_track_saved_bits_shift)
-                        & shadow_acc_track_saved_bits_mask;
+       u64 saved_bits = (spte >> SHADOW_ACC_TRACK_SAVED_BITS_SHIFT)
+                        & SHADOW_ACC_TRACK_SAVED_BITS_MASK;
 
        WARN_ON_ONCE(spte_ad_enabled(spte));
        WARN_ON_ONCE(!is_access_track_spte(spte));
 
        new_spte &= ~shadow_acc_track_mask;
-       new_spte &= ~(shadow_acc_track_saved_bits_mask <<
-                     shadow_acc_track_saved_bits_shift);
+       new_spte &= ~(SHADOW_ACC_TRACK_SAVED_BITS_MASK <<
+                     SHADOW_ACC_TRACK_SAVED_BITS_SHIFT);
        new_spte |= saved_bits;
 
        return new_spte;
@@ -856,12 +856,14 @@ static int pte_list_add(struct kvm_vcpu *vcpu, u64 *spte,
        } else {
                rmap_printk("pte_list_add: %p %llx many->many\n", spte, *spte);
                desc = (struct pte_list_desc *)(rmap_head->val & ~1ul);
-               while (desc->sptes[PTE_LIST_EXT-1] && desc->more) {
-                       desc = desc->more;
+               while (desc->sptes[PTE_LIST_EXT-1]) {
                        count += PTE_LIST_EXT;
-               }
-               if (desc->sptes[PTE_LIST_EXT-1]) {
-                       desc->more = mmu_alloc_pte_list_desc(vcpu);
+
+                       if (!desc->more) {
+                               desc->more = mmu_alloc_pte_list_desc(vcpu);
+                               desc = desc->more;
+                               break;
+                       }
                        desc = desc->more;
                }
                for (i = 0; desc->sptes[i]; ++i)
@@ -3515,7 +3517,7 @@ static bool get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr, u64 *sptep)
 {
        u64 sptes[PT64_ROOT_MAX_LEVEL];
        struct rsvd_bits_validate *rsvd_check;
-       int root = vcpu->arch.mmu->root_level;
+       int root = vcpu->arch.mmu->shadow_root_level;
        int leaf;
        int level;
        bool reserved = false;
index d9c5665a55e97d5e1426be6140fa69c559f9496a..fcac2cac78fe0781838c3d49ae5860a19e2d1e12 100644 (file)
@@ -55,7 +55,7 @@ u64 make_mmio_spte(struct kvm_vcpu *vcpu, u64 gfn, unsigned int access)
        mask |= shadow_mmio_value | access;
        mask |= gpa | shadow_nonpresent_or_rsvd_mask;
        mask |= (gpa & shadow_nonpresent_or_rsvd_mask)
-               << shadow_nonpresent_or_rsvd_mask_len;
+               << SHADOW_NONPRESENT_OR_RSVD_MASK_LEN;
 
        return mask;
 }
@@ -231,12 +231,12 @@ u64 mark_spte_for_access_track(u64 spte)
                  !spte_can_locklessly_be_made_writable(spte),
                  "kvm: Writable SPTE is not locklessly dirty-trackable\n");
 
-       WARN_ONCE(spte & (shadow_acc_track_saved_bits_mask <<
-                         shadow_acc_track_saved_bits_shift),
+       WARN_ONCE(spte & (SHADOW_ACC_TRACK_SAVED_BITS_MASK <<
+                         SHADOW_ACC_TRACK_SAVED_BITS_SHIFT),
                  "kvm: Access Tracking saved bit locations are not zero\n");
 
-       spte |= (spte & shadow_acc_track_saved_bits_mask) <<
-               shadow_acc_track_saved_bits_shift;
+       spte |= (spte & SHADOW_ACC_TRACK_SAVED_BITS_MASK) <<
+               SHADOW_ACC_TRACK_SAVED_BITS_SHIFT;
        spte &= ~shadow_acc_track_mask;
 
        return spte;
@@ -245,7 +245,7 @@ u64 mark_spte_for_access_track(u64 spte)
 void kvm_mmu_set_mmio_spte_mask(u64 mmio_value, u64 access_mask)
 {
        BUG_ON((u64)(unsigned)access_mask != access_mask);
-       WARN_ON(mmio_value & (shadow_nonpresent_or_rsvd_mask << shadow_nonpresent_or_rsvd_mask_len));
+       WARN_ON(mmio_value & (shadow_nonpresent_or_rsvd_mask << SHADOW_NONPRESENT_OR_RSVD_MASK_LEN));
        WARN_ON(mmio_value & shadow_nonpresent_or_rsvd_lower_gfn_mask);
        shadow_mmio_value = mmio_value | SPTE_MMIO_MASK;
        shadow_mmio_access_mask = access_mask;
@@ -306,9 +306,9 @@ void kvm_mmu_reset_all_pte_masks(void)
        low_phys_bits = boot_cpu_data.x86_phys_bits;
        if (boot_cpu_has_bug(X86_BUG_L1TF) &&
            !WARN_ON_ONCE(boot_cpu_data.x86_cache_bits >=
-                         52 - shadow_nonpresent_or_rsvd_mask_len)) {
+                         52 - SHADOW_NONPRESENT_OR_RSVD_MASK_LEN)) {
                low_phys_bits = boot_cpu_data.x86_cache_bits
-                       - shadow_nonpresent_or_rsvd_mask_len;
+                       - SHADOW_NONPRESENT_OR_RSVD_MASK_LEN;
                shadow_nonpresent_or_rsvd_mask =
                        rsvd_bits(low_phys_bits, boot_cpu_data.x86_cache_bits - 1);
        }
index 4ecf40e0b8fe647fa76a84c1799f1f7ee54e8350..5c75a451c00036f0d06246ff90ff62479c5e7318 100644 (file)
@@ -104,20 +104,20 @@ extern u64 __read_mostly shadow_acc_track_mask;
  */
 extern u64 __read_mostly shadow_nonpresent_or_rsvd_mask;
 
+/*
+ * The number of high-order 1 bits to use in the mask above.
+ */
+#define SHADOW_NONPRESENT_OR_RSVD_MASK_LEN 5
+
 /*
  * The mask/shift to use for saving the original R/X bits when marking the PTE
  * as not-present for access tracking purposes. We do not save the W bit as the
  * PTEs being access tracked also need to be dirty tracked, so the W bit will be
  * restored only when a write is attempted to the page.
  */
-static const u64 shadow_acc_track_saved_bits_mask = PT64_EPT_READABLE_MASK |
-                                                   PT64_EPT_EXECUTABLE_MASK;
-static const u64 shadow_acc_track_saved_bits_shift = PT64_SECOND_AVAIL_BITS_SHIFT;
-
-/*
- * The number of high-order 1 bits to use in the mask above.
- */
-static const u64 shadow_nonpresent_or_rsvd_mask_len = 5;
+#define SHADOW_ACC_TRACK_SAVED_BITS_MASK (PT64_EPT_READABLE_MASK | \
+                                         PT64_EPT_EXECUTABLE_MASK)
+#define SHADOW_ACC_TRACK_SAVED_BITS_SHIFT PT64_SECOND_AVAIL_BITS_SHIFT
 
 /*
  * In some cases, we need to preserve the GFN of a non-present or reserved
index 27e381c9da6c24bbdc3e7e59d9dda0b59a005ebf..ff28a5c6abd6340085f2a765a482fdac7a7d2ea1 100644 (file)
@@ -49,7 +49,14 @@ bool is_tdp_mmu_root(struct kvm *kvm, hpa_t hpa)
 {
        struct kvm_mmu_page *sp;
 
+       if (!kvm->arch.tdp_mmu_enabled)
+               return false;
+       if (WARN_ON(!VALID_PAGE(hpa)))
+               return false;
+
        sp = to_shadow_page(hpa);
+       if (WARN_ON(!sp))
+               return false;
 
        return sp->tdp_mmu_page && sp->root_count;
 }
index c0b14106258a7c84241fba9e7b94c2affbcf2cf1..566f4d18185b1d4bcd2573c0038f687b1b3fc29e 100644 (file)
@@ -642,8 +642,8 @@ static int __sev_dbg_decrypt(struct kvm *kvm, unsigned long src_paddr,
         * Its safe to read more than we are asked, caller should ensure that
         * destination has enough space.
         */
-       src_paddr = round_down(src_paddr, 16);
        offset = src_paddr & 15;
+       src_paddr = round_down(src_paddr, 16);
        sz = round_up(sz + offset, 16);
 
        return __sev_issue_dbg_cmd(kvm, src_paddr, dst_paddr, sz, err, false);
index 2f32fd09e2598b24563e4dbfafb1e98174e95151..79b3a564f1c98d8a129e6e6c07e4c9fa80f353e5 100644 (file)
@@ -1309,8 +1309,10 @@ static int svm_create_vcpu(struct kvm_vcpu *vcpu)
                svm->avic_is_running = true;
 
        svm->msrpm = svm_vcpu_alloc_msrpm();
-       if (!svm->msrpm)
+       if (!svm->msrpm) {
+               err = -ENOMEM;
                goto error_free_vmcb_page;
+       }
 
        svm_vcpu_init_msrpm(vcpu, svm->msrpm);
 
@@ -3741,6 +3743,7 @@ static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
 static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
+       struct kvm_cpuid_entry2 *best;
 
        vcpu->arch.xsaves_enabled = guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) &&
                                    boot_cpu_has(X86_FEATURE_XSAVE) &&
@@ -3753,6 +3756,13 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
        /* Check again if INVPCID interception if required */
        svm_check_invpcid(svm);
 
+       /* For sev guests, the memory encryption bit is not reserved in CR3.  */
+       if (sev_guest(vcpu->kvm)) {
+               best = kvm_find_cpuid_entry(vcpu, 0x8000001F, 0);
+               if (best)
+                       vcpu->arch.cr3_lm_rsvd_bits &= ~(1UL << (best->ebx & 0x3f));
+       }
+
        if (!kvm_vcpu_apicv_active(vcpu))
                return;
 
index e5325bd0f3047231d2d597a2f8255585605da648..f3199bb02f22dfd9b8338d7d3465842fb3f7718e 100644 (file)
@@ -297,14 +297,13 @@ const struct evmcs_field vmcs_field_to_evmcs_1[] = {
 };
 const unsigned int nr_evmcs_1_fields = ARRAY_SIZE(vmcs_field_to_evmcs_1);
 
-void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf)
+__init void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf)
 {
        vmcs_conf->pin_based_exec_ctrl &= ~EVMCS1_UNSUPPORTED_PINCTRL;
        vmcs_conf->cpu_based_2nd_exec_ctrl &= ~EVMCS1_UNSUPPORTED_2NDEXEC;
 
        vmcs_conf->vmexit_ctrl &= ~EVMCS1_UNSUPPORTED_VMEXIT_CTRL;
        vmcs_conf->vmentry_ctrl &= ~EVMCS1_UNSUPPORTED_VMENTRY_CTRL;
-
 }
 #endif
 
index e5f7a7ebf27d6047ebdd2b7f824aab201f1a1b5c..bd41d9462355fd65909554b41b3ce49654ef3e4d 100644 (file)
@@ -185,7 +185,7 @@ static inline void evmcs_load(u64 phys_addr)
        vp_ap->enlighten_vmentry = 1;
 }
 
-void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf);
+__init void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf);
 #else /* !IS_ENABLED(CONFIG_HYPERV) */
 static inline void evmcs_write64(unsigned long field, u64 value) {}
 static inline void evmcs_write32(unsigned long field, u32 value) {}
@@ -194,7 +194,6 @@ static inline u64 evmcs_read64(unsigned long field) { return 0; }
 static inline u32 evmcs_read32(unsigned long field) { return 0; }
 static inline u16 evmcs_read16(unsigned long field) { return 0; }
 static inline void evmcs_load(u64 phys_addr) {}
-static inline void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf) {}
 static inline void evmcs_touch_msr_bitmap(void) {}
 #endif /* IS_ENABLED(CONFIG_HYPERV) */
 
index d14c94d0aff17924f964f1a47446ff8069cde01c..47b8357b97517ecda8a3c52d99dfe10cbf0e91c0 100644 (file)
@@ -2560,8 +2560,10 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
        vmcs_conf->vmexit_ctrl         = _vmexit_control;
        vmcs_conf->vmentry_ctrl        = _vmentry_control;
 
-       if (static_branch_unlikely(&enable_evmcs))
+#if IS_ENABLED(CONFIG_HYPERV)
+       if (enlightened_vmcs)
                evmcs_sanitize_exec_ctrls(vmcs_conf);
+#endif
 
        return 0;
 }
@@ -6834,7 +6836,6 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
 static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx;
-       unsigned long *msr_bitmap;
        int i, cpu, err;
 
        BUILD_BUG_ON(offsetof(struct vcpu_vmx, vcpu) != 0);
@@ -6894,7 +6895,6 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
        bitmap_fill(vmx->shadow_msr_intercept.read, MAX_POSSIBLE_PASSTHROUGH_MSRS);
        bitmap_fill(vmx->shadow_msr_intercept.write, MAX_POSSIBLE_PASSTHROUGH_MSRS);
 
-       msr_bitmap = vmx->vmcs01.msr_bitmap;
        vmx_disable_intercept_for_msr(vcpu, MSR_IA32_TSC, MSR_TYPE_R);
        vmx_disable_intercept_for_msr(vcpu, MSR_FS_BASE, MSR_TYPE_RW);
        vmx_disable_intercept_for_msr(vcpu, MSR_GS_BASE, MSR_TYPE_RW);
index 397f599b20e5a8aeb4ff1423a346d1c4d2c1e2c4..e545a8a613b19719eb81469cdeaf1e1f7fb74684 100644 (file)
@@ -255,24 +255,23 @@ static struct kmem_cache *x86_emulator_cache;
 
 /*
  * When called, it means the previous get/set msr reached an invalid msr.
- * Return 0 if we want to ignore/silent this failed msr access, or 1 if we want
- * to fail the caller.
+ * Return true if we want to ignore/silent this failed msr access.
  */
-static int kvm_msr_ignored_check(struct kvm_vcpu *vcpu, u32 msr,
-                                u64 data, bool write)
+static bool kvm_msr_ignored_check(struct kvm_vcpu *vcpu, u32 msr,
+                                 u64 data, bool write)
 {
        const char *op = write ? "wrmsr" : "rdmsr";
 
        if (ignore_msrs) {
                if (report_ignored_msrs)
-                       vcpu_unimpl(vcpu, "ignored %s: 0x%x data 0x%llx\n",
-                                   op, msr, data);
+                       kvm_pr_unimpl("ignored %s: 0x%x data 0x%llx\n",
+                                     op, msr, data);
                /* Mask the error */
-               return 0;
+               return true;
        } else {
-               vcpu_debug_ratelimited(vcpu, "unhandled %s: 0x%x data 0x%llx\n",
-                                      op, msr, data);
-               return -ENOENT;
+               kvm_debug_ratelimited("unhandled %s: 0x%x data 0x%llx\n",
+                                     op, msr, data);
+               return false;
        }
 }
 
@@ -1042,7 +1041,7 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
        }
 
        if (is_long_mode(vcpu) &&
-           (cr3 & rsvd_bits(cpuid_maxphyaddr(vcpu), 63)))
+           (cr3 & vcpu->arch.cr3_lm_rsvd_bits))
                return 1;
        else if (is_pae_paging(vcpu) &&
                 !load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3))
@@ -1416,7 +1415,8 @@ static int do_get_msr_feature(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
        if (r == KVM_MSR_RET_INVALID) {
                /* Unconditionally clear the output for simplicity */
                *data = 0;
-               r = kvm_msr_ignored_check(vcpu, index, 0, false);
+               if (kvm_msr_ignored_check(vcpu, index, 0, false))
+                       r = 0;
        }
 
        if (r)
@@ -1540,7 +1540,7 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data,
        struct msr_data msr;
 
        if (!host_initiated && !kvm_msr_allowed(vcpu, index, KVM_MSR_FILTER_WRITE))
-               return -EPERM;
+               return KVM_MSR_RET_FILTERED;
 
        switch (index) {
        case MSR_FS_BASE:
@@ -1581,7 +1581,8 @@ static int kvm_set_msr_ignored_check(struct kvm_vcpu *vcpu,
        int ret = __kvm_set_msr(vcpu, index, data, host_initiated);
 
        if (ret == KVM_MSR_RET_INVALID)
-               ret = kvm_msr_ignored_check(vcpu, index, data, true);
+               if (kvm_msr_ignored_check(vcpu, index, data, true))
+                       ret = 0;
 
        return ret;
 }
@@ -1599,7 +1600,7 @@ int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data,
        int ret;
 
        if (!host_initiated && !kvm_msr_allowed(vcpu, index, KVM_MSR_FILTER_READ))
-               return -EPERM;
+               return KVM_MSR_RET_FILTERED;
 
        msr.index = index;
        msr.host_initiated = host_initiated;
@@ -1618,7 +1619,8 @@ static int kvm_get_msr_ignored_check(struct kvm_vcpu *vcpu,
        if (ret == KVM_MSR_RET_INVALID) {
                /* Unconditionally clear *data for simplicity */
                *data = 0;
-               ret = kvm_msr_ignored_check(vcpu, index, 0, false);
+               if (kvm_msr_ignored_check(vcpu, index, 0, false))
+                       ret = 0;
        }
 
        return ret;
@@ -1662,9 +1664,9 @@ static int complete_emulated_wrmsr(struct kvm_vcpu *vcpu)
 static u64 kvm_msr_reason(int r)
 {
        switch (r) {
-       case -ENOENT:
+       case KVM_MSR_RET_INVALID:
                return KVM_MSR_EXIT_REASON_UNKNOWN;
-       case -EPERM:
+       case KVM_MSR_RET_FILTERED:
                return KVM_MSR_EXIT_REASON_FILTER;
        default:
                return KVM_MSR_EXIT_REASON_INVAL;
@@ -1965,7 +1967,7 @@ static void kvm_write_system_time(struct kvm_vcpu *vcpu, gpa_t system_time,
        struct kvm_arch *ka = &vcpu->kvm->arch;
 
        if (vcpu->vcpu_id == 0 && !host_initiated) {
-               if (ka->boot_vcpu_runs_old_kvmclock && old_msr)
+               if (ka->boot_vcpu_runs_old_kvmclock != old_msr)
                        kvm_make_request(KVM_REQ_MASTERCLOCK_UPDATE, vcpu);
 
                ka->boot_vcpu_runs_old_kvmclock = old_msr;
@@ -3063,9 +3065,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                        /* Values other than LBR and BTF are vendor-specific,
                           thus reserved and should throw a #GP */
                        return 1;
-               }
-               vcpu_unimpl(vcpu, "%s: MSR_IA32_DEBUGCTLMSR 0x%llx, nop\n",
-                           __func__, data);
+               } else if (report_ignored_msrs)
+                       vcpu_unimpl(vcpu, "%s: MSR_IA32_DEBUGCTLMSR 0x%llx, nop\n",
+                                   __func__, data);
                break;
        case 0x200 ... 0x2ff:
                return kvm_mtrr_set_msr(vcpu, msr, data);
@@ -3463,29 +3465,63 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                msr_info->data = vcpu->arch.efer;
                break;
        case MSR_KVM_WALL_CLOCK:
+               if (!guest_pv_has(vcpu, KVM_FEATURE_CLOCKSOURCE))
+                       return 1;
+
+               msr_info->data = vcpu->kvm->arch.wall_clock;
+               break;
        case MSR_KVM_WALL_CLOCK_NEW:
+               if (!guest_pv_has(vcpu, KVM_FEATURE_CLOCKSOURCE2))
+                       return 1;
+
                msr_info->data = vcpu->kvm->arch.wall_clock;
                break;
        case MSR_KVM_SYSTEM_TIME:
+               if (!guest_pv_has(vcpu, KVM_FEATURE_CLOCKSOURCE))
+                       return 1;
+
+               msr_info->data = vcpu->arch.time;
+               break;
        case MSR_KVM_SYSTEM_TIME_NEW:
+               if (!guest_pv_has(vcpu, KVM_FEATURE_CLOCKSOURCE2))
+                       return 1;
+
                msr_info->data = vcpu->arch.time;
                break;
        case MSR_KVM_ASYNC_PF_EN:
+               if (!guest_pv_has(vcpu, KVM_FEATURE_ASYNC_PF))
+                       return 1;
+
                msr_info->data = vcpu->arch.apf.msr_en_val;
                break;
        case MSR_KVM_ASYNC_PF_INT:
+               if (!guest_pv_has(vcpu, KVM_FEATURE_ASYNC_PF_INT))
+                       return 1;
+
                msr_info->data = vcpu->arch.apf.msr_int_val;
                break;
        case MSR_KVM_ASYNC_PF_ACK:
+               if (!guest_pv_has(vcpu, KVM_FEATURE_ASYNC_PF))
+                       return 1;
+
                msr_info->data = 0;
                break;
        case MSR_KVM_STEAL_TIME:
+               if (!guest_pv_has(vcpu, KVM_FEATURE_STEAL_TIME))
+                       return 1;
+
                msr_info->data = vcpu->arch.st.msr_val;
                break;
        case MSR_KVM_PV_EOI_EN:
+               if (!guest_pv_has(vcpu, KVM_FEATURE_PV_EOI))
+                       return 1;
+
                msr_info->data = vcpu->arch.pv_eoi.msr_val;
                break;
        case MSR_KVM_POLL_CONTROL:
+               if (!guest_pv_has(vcpu, KVM_FEATURE_POLL_CONTROL))
+                       return 1;
+
                msr_info->data = vcpu->arch.msr_kvm_poll_control;
                break;
        case MSR_IA32_P5_MC_ADDR:
@@ -4015,21 +4051,23 @@ static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
 
 static int kvm_cpu_accept_dm_intr(struct kvm_vcpu *vcpu)
 {
+       /*
+        * We can accept userspace's request for interrupt injection
+        * as long as we have a place to store the interrupt number.
+        * The actual injection will happen when the CPU is able to
+        * deliver the interrupt.
+        */
+       if (kvm_cpu_has_extint(vcpu))
+               return false;
+
+       /* Acknowledging ExtINT does not happen if LINT0 is masked.  */
        return (!lapic_in_kernel(vcpu) ||
                kvm_apic_accept_pic_intr(vcpu));
 }
 
-/*
- * if userspace requested an interrupt window, check that the
- * interrupt window is open.
- *
- * No need to exit to userspace if we already have an interrupt queued.
- */
 static int kvm_vcpu_ready_for_interrupt_injection(struct kvm_vcpu *vcpu)
 {
        return kvm_arch_interrupt_allowed(vcpu) &&
-               !kvm_cpu_has_interrupt(vcpu) &&
-               !kvm_event_needs_reinjection(vcpu) &&
                kvm_cpu_accept_dm_intr(vcpu);
 }
 
@@ -4575,6 +4613,8 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
 
        case KVM_CAP_ENFORCE_PV_FEATURE_CPUID:
                vcpu->arch.pv_cpuid.enforce = cap->args[0];
+               if (vcpu->arch.pv_cpuid.enforce)
+                       kvm_update_pv_runtime(vcpu);
 
                return 0;
 
index 3900ab0c6004d20567242107e09ee1e08557de59..e7ca622a468f5f14538f10b6bbed473f30108b49 100644 (file)
@@ -376,7 +376,13 @@ int kvm_handle_memory_failure(struct kvm_vcpu *vcpu, int r,
 int kvm_handle_invpcid(struct kvm_vcpu *vcpu, unsigned long type, gva_t gva);
 bool kvm_msr_allowed(struct kvm_vcpu *vcpu, u32 index, u32 type);
 
-#define  KVM_MSR_RET_INVALID  2
+/*
+ * Internal error codes that are used to indicate that MSR emulation encountered
+ * an error that should result in #GP in the guest, unless userspace
+ * handles it.
+ */
+#define  KVM_MSR_RET_INVALID   2       /* in-kernel MSR emulation #GP condition */
+#define  KVM_MSR_RET_FILTERED  3       /* #GP due to userspace MSR filter */
 
 #define __cr4_reserved_bits(__cpu_has, __c)             \
 ({                                                      \
index 58f7fb95c7f49cf2f2d6cae191cb1cbbf1bf782f..4229950a5d78c328a38f185119cc85098a36ce66 100644 (file)
@@ -63,13 +63,12 @@ static bool is_string_insn(struct insn *insn)
  */
 bool insn_has_rep_prefix(struct insn *insn)
 {
+       insn_byte_t p;
        int i;
 
        insn_get_prefixes(insn);
 
-       for (i = 0; i < insn->prefixes.nbytes; i++) {
-               insn_byte_t p = insn->prefixes.bytes[i];
-
+       for_each_insn_prefix(insn, i, p) {
                if (p == 0xf2 || p == 0xf3)
                        return true;
        }
@@ -95,14 +94,15 @@ static int get_seg_reg_override_idx(struct insn *insn)
 {
        int idx = INAT_SEG_REG_DEFAULT;
        int num_overrides = 0, i;
+       insn_byte_t p;
 
        insn_get_prefixes(insn);
 
        /* Look for any segment override prefixes. */
-       for (i = 0; i < insn->prefixes.nbytes; i++) {
+       for_each_insn_prefix(insn, i, p) {
                insn_attr_t attr;
 
-               attr = inat_get_opcode_attribute(insn->prefixes.bytes[i]);
+               attr = inat_get_opcode_attribute(p);
                switch (attr) {
                case INAT_MAKE_PREFIX(INAT_PFX_CS):
                        idx = INAT_SEG_REG_CS;
index 037faac46b0cc92f2a31297910ea63b35d10d83b..1e299ac73c8698622c7e631a4571b5b88e8b32f7 100644 (file)
@@ -16,8 +16,6 @@
  * to a jmp to memcpy_erms which does the REP; MOVSB mem copy.
  */
 
-.weak memcpy
-
 /*
  * memcpy - Copy a memory block.
  *
@@ -30,7 +28,7 @@
  * rax original destination
  */
 SYM_FUNC_START_ALIAS(__memcpy)
-SYM_FUNC_START_LOCAL(memcpy)
+SYM_FUNC_START_WEAK(memcpy)
        ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \
                      "jmp memcpy_erms", X86_FEATURE_ERMS
 
index 7ff00ea64e4fe558f11a8f4c8961551edf35d84b..41902fe8b85982e10409c1a68e86cf01ee1519fd 100644 (file)
@@ -24,9 +24,7 @@
  * Output:
  * rax: dest
  */
-.weak memmove
-
-SYM_FUNC_START_ALIAS(memmove)
+SYM_FUNC_START_WEAK(memmove)
 SYM_FUNC_START(__memmove)
 
        mov %rdi, %rax
index 9ff15ee404a48b4de82c8a1314075bd6bba8a0d2..0bfd26e4ca9e938af774c5b1e4fea753d47d156c 100644 (file)
@@ -6,8 +6,6 @@
 #include <asm/alternative-asm.h>
 #include <asm/export.h>
 
-.weak memset
-
 /*
  * ISO C memset - set a memory block to a byte value. This function uses fast
  * string to get better performance than the original function. The code is
@@ -19,7 +17,7 @@
  *
  * rax   original destination
  */
-SYM_FUNC_START_ALIAS(memset)
+SYM_FUNC_START_WEAK(memset)
 SYM_FUNC_START(__memset)
        /*
         * Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended
index efbb3de472df4613a32308b000cf9ee1300bd154..bc0833713be955444359d83ad013125f295f1dfd 100644 (file)
@@ -39,6 +39,7 @@
  */
 u64 sme_me_mask __section(".data") = 0;
 u64 sev_status __section(".data") = 0;
+u64 sev_check_data __section(".data") = 0;
 EXPORT_SYMBOL(sme_me_mask);
 DEFINE_STATIC_KEY_FALSE(sev_enable_key);
 EXPORT_SYMBOL_GPL(sev_enable_key);
index 44148691d78b0d5868c523618ab9b678c39a9d77..5eb4dc2b97dac9a056daeba7ce4d68e37e138052 100644 (file)
@@ -938,6 +938,7 @@ int phys_to_target_node(phys_addr_t start)
 
        return meminfo_to_nid(&numa_reserved_meminfo, start);
 }
+EXPORT_SYMBOL_GPL(phys_to_target_node);
 
 int memory_add_physaddr_to_nid(u64 start)
 {
@@ -947,4 +948,5 @@ int memory_add_physaddr_to_nid(u64 start)
                nid = numa_meminfo.blk[0].nid;
        return nid;
 }
+EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
 #endif
index 8f5759df77766f6bbc67d822d13c36cd98f3ce5a..e1e8d4e3a213930a38d738b47305dc5c8ba2e736 100644 (file)
@@ -78,28 +78,30 @@ int __init efi_alloc_page_tables(void)
        gfp_mask = GFP_KERNEL | __GFP_ZERO;
        efi_pgd = (pgd_t *)__get_free_pages(gfp_mask, PGD_ALLOCATION_ORDER);
        if (!efi_pgd)
-               return -ENOMEM;
+               goto fail;
 
        pgd = efi_pgd + pgd_index(EFI_VA_END);
        p4d = p4d_alloc(&init_mm, pgd, EFI_VA_END);
-       if (!p4d) {
-               free_page((unsigned long)efi_pgd);
-               return -ENOMEM;
-       }
+       if (!p4d)
+               goto free_pgd;
 
        pud = pud_alloc(&init_mm, p4d, EFI_VA_END);
-       if (!pud) {
-               if (pgtable_l5_enabled())
-                       free_page((unsigned long) pgd_page_vaddr(*pgd));
-               free_pages((unsigned long)efi_pgd, PGD_ALLOCATION_ORDER);
-               return -ENOMEM;
-       }
+       if (!pud)
+               goto free_p4d;
 
        efi_mm.pgd = efi_pgd;
        mm_init_cpumask(&efi_mm);
        init_new_context(NULL, &efi_mm);
 
        return 0;
+
+free_p4d:
+       if (pgtable_l5_enabled())
+               free_page((unsigned long)pgd_page_vaddr(*pgd));
+free_pgd:
+       free_pages((unsigned long)efi_pgd, PGD_ALLOCATION_ORDER);
+fail:
+       return -ENOMEM;
 }
 
 /*
index fdcd58af707aebefb183380b1ecd2517dbb8b260..27361cbb7ca9bed47194fe4127e231a8d3c39c0d 100644 (file)
@@ -8,7 +8,7 @@
 #include <sysdep/mcontext.h>
 #include <sys/ucontext.h>
 
-void __section(".__syscall_stub")
+void __attribute__ ((__section__ (".__syscall_stub")))
 stub_segv_handler(int sig, siginfo_t *info, void *p)
 {
        ucontext_t *uc = p;
index 799f4eba0a621f7296516506a57ff8b0fd5ba948..043c73dfd2c98388c4adcdb9cb001ce0de0b15dc 100644 (file)
@@ -93,10 +93,20 @@ void xen_init_lock_cpu(int cpu)
 
 void xen_uninit_lock_cpu(int cpu)
 {
+       int irq;
+
        if (!xen_pvspin)
                return;
 
-       unbind_from_irqhandler(per_cpu(lock_kicker_irq, cpu), NULL);
+       /*
+        * When booting the kernel with 'mitigations=auto,nosmt', the secondary
+        * CPUs are not activated, and lock_kicker_irq is not initialized.
+        */
+       irq = per_cpu(lock_kicker_irq, cpu);
+       if (irq == -1)
+               return;
+
+       unbind_from_irqhandler(irq, NULL);
        per_cpu(lock_kicker_irq, cpu) = -1;
        kfree(per_cpu(irq_name, cpu));
        per_cpu(irq_name, cpu) = NULL;
index fa054a1772e10ed00a13428981d1dbd589c61363..4dc04e6c01d730f0f7045951b1eb258f1dac4d34 100644 (file)
@@ -69,7 +69,7 @@
  */
 #define VMALLOC_START          (XCHAL_KSEG_CACHED_VADDR - 0x10000000)
 #define VMALLOC_END            (VMALLOC_START + 0x07FEFFFF)
-#define TLBTEMP_BASE_1         (VMALLOC_END + 1)
+#define TLBTEMP_BASE_1         (VMALLOC_START + 0x08000000)
 #define TLBTEMP_BASE_2         (TLBTEMP_BASE_1 + DCACHE_WAY_SIZE)
 #if 2 * DCACHE_WAY_SIZE > ICACHE_WAY_SIZE
 #define TLBTEMP_SIZE           (2 * DCACHE_WAY_SIZE)
index b9758119feca19bf267da7f27d045c7e81e3d834..5c9fb8005aa89827b9782433a88577e45cc32dd4 100644 (file)
@@ -302,7 +302,7 @@ strncpy_from_user(char *dst, const char __user *src, long count)
        return -EFAULT;
 }
 #else
-long strncpy_from_user(char *dst, const char *src, long count);
+long strncpy_from_user(char *dst, const char __user *src, long count);
 #endif
 
 /*
index 5835406b3cecb0290dca51d7d8dcb360e5479f21..085b8c77b9d9605ca02dd461eedd95860aaa5aeb 100644 (file)
@@ -70,8 +70,10 @@ static inline void kmap_invalidate_coherent(struct page *page,
                        kvaddr = TLBTEMP_BASE_1 +
                                (page_to_phys(page) & DCACHE_ALIAS_MASK);
 
+                       preempt_disable();
                        __invalidate_dcache_page_alias(kvaddr,
                                                       page_to_phys(page));
+                       preempt_enable();
                }
        }
 }
@@ -156,6 +158,7 @@ void flush_dcache_page(struct page *page)
                if (!alias && !mapping)
                        return;
 
+               preempt_disable();
                virt = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK);
                __flush_invalidate_dcache_page_alias(virt, phys);
 
@@ -166,6 +169,7 @@ void flush_dcache_page(struct page *page)
 
                if (mapping)
                        __invalidate_icache_page_alias(virt, phys);
+               preempt_enable();
        }
 
        /* There shouldn't be an entry in the cache for this page anymore. */
@@ -199,8 +203,10 @@ void local_flush_cache_page(struct vm_area_struct *vma, unsigned long address,
        unsigned long phys = page_to_phys(pfn_to_page(pfn));
        unsigned long virt = TLBTEMP_BASE_1 + (address & DCACHE_ALIAS_MASK);
 
+       preempt_disable();
        __flush_invalidate_dcache_page_alias(virt, phys);
        __invalidate_icache_page_alias(virt, phys);
+       preempt_enable();
 }
 EXPORT_SYMBOL(local_flush_cache_page);
 
@@ -227,11 +233,13 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep)
                unsigned long phys = page_to_phys(page);
                unsigned long tmp;
 
+               preempt_disable();
                tmp = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK);
                __flush_invalidate_dcache_page_alias(tmp, phys);
                tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK);
                __flush_invalidate_dcache_page_alias(tmp, phys);
                __invalidate_icache_page_alias(tmp, phys);
+               preempt_enable();
 
                clear_bit(PG_arch_1, &page->flags);
        }
@@ -265,7 +273,9 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
 
        if (alias) {
                unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
+               preempt_disable();
                __flush_invalidate_dcache_page_alias(t, phys);
+               preempt_enable();
        }
 
        /* Copy data */
@@ -280,9 +290,11 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
        if (alias) {
                unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
 
+               preempt_disable();
                __flush_invalidate_dcache_range((unsigned long) dst, len);
                if ((vma->vm_flags & VM_EXEC) != 0)
                        __invalidate_icache_page_alias(t, phys);
+               preempt_enable();
 
        } else if ((vma->vm_flags & VM_EXEC) != 0) {
                __flush_dcache_range((unsigned long)dst,len);
@@ -304,7 +316,9 @@ extern void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
 
        if (alias) {
                unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
+               preempt_disable();
                __flush_invalidate_dcache_page_alias(t, phys);
+               preempt_enable();
        }
 
        memcpy(dst, src, len);
index c6fc83efee0c94148a0da0608fec7d6e02ee140d..8731b7ad930884e26778e7c24751b0c1ce74877c 100644 (file)
@@ -89,8 +89,8 @@ static void __init free_highpages(void)
        /* set highmem page free */
        for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE,
                                &range_start, &range_end, NULL) {
-               unsigned long start = PHYS_PFN(range_start);
-               unsigned long end = PHYS_PFN(range_end);
+               unsigned long start = PFN_UP(range_start);
+               unsigned long end = PFN_DOWN(range_end);
 
                /* Ignore complete lowmem entries */
                if (end <= max_low)
index e6e26d7a1ffbba5079318041d7b793c9ed656724..fa01bef35bb1fe77b26d797cfdb76e7e04082ac3 100644 (file)
@@ -1044,6 +1044,7 @@ static int __bio_iov_append_get_pages(struct bio *bio, struct iov_iter *iter)
        ssize_t size, left;
        unsigned len, i;
        size_t offset;
+       int ret = 0;
 
        if (WARN_ON_ONCE(!max_append_sectors))
                return 0;
@@ -1066,15 +1067,17 @@ static int __bio_iov_append_get_pages(struct bio *bio, struct iov_iter *iter)
 
                len = min_t(size_t, PAGE_SIZE - offset, left);
                if (bio_add_hw_page(q, bio, page, len, offset,
-                               max_append_sectors, &same_page) != len)
-                       return -EINVAL;
+                               max_append_sectors, &same_page) != len) {
+                       ret = -EINVAL;
+                       break;
+               }
                if (same_page)
                        put_page(page);
                offset = 0;
        }
 
-       iov_iter_advance(iter, size);
-       return 0;
+       iov_iter_advance(iter, size - left);
+       return ret;
 }
 
 /**
index f9b55614d67d45db0ef1527c3467b61343fcac59..54fbe1e80cc41a2ea6891e497a24a6f7205a868b 100644 (file)
@@ -657,13 +657,20 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
                        goto fail;
                }
 
+               if (radix_tree_preload(GFP_KERNEL)) {
+                       blkg_free(new_blkg);
+                       ret = -ENOMEM;
+                       goto fail;
+               }
+
                rcu_read_lock();
                spin_lock_irq(&q->queue_lock);
 
                blkg = blkg_lookup_check(pos, pol, q);
                if (IS_ERR(blkg)) {
                        ret = PTR_ERR(blkg);
-                       goto fail_unlock;
+                       blkg_free(new_blkg);
+                       goto fail_preloaded;
                }
 
                if (blkg) {
@@ -672,10 +679,12 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
                        blkg = blkg_create(pos, q, new_blkg);
                        if (IS_ERR(blkg)) {
                                ret = PTR_ERR(blkg);
-                               goto fail_unlock;
+                               goto fail_preloaded;
                        }
                }
 
+               radix_tree_preload_end();
+
                if (pos == blkcg)
                        goto success;
        }
@@ -685,6 +694,8 @@ success:
        ctx->body = input;
        return 0;
 
+fail_preloaded:
+       radix_tree_preload_end();
 fail_unlock:
        spin_unlock_irq(&q->queue_lock);
        rcu_read_unlock();
@@ -838,6 +849,7 @@ static void blkcg_fill_root_iostats(void)
                        blkg_iostat_set(&blkg->iostat.cur, &tmp);
                        u64_stats_update_end(&blkg->iostat.sync);
                }
+               disk_put_part(part);
        }
 }
 
index 53abb5c73d99f90a90033855b60f2d27e3546104..fd5cee9f1a3bec1b6b3a8a80171d02a15960f8fd 100644 (file)
@@ -231,6 +231,12 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error)
                return;
        }
 
+       /*
+        * Flush request has to be marked as IDLE when it is really ended
+        * because its .end_io() is called from timeout code path too for
+        * avoiding use-after-free.
+        */
+       WRITE_ONCE(flush_rq->state, MQ_RQ_IDLE);
        if (fq->rq_status != BLK_STS_OK)
                error = fq->rq_status;
 
index bcf5e4580603370216ad5027fa93515623b857ba..97b7c282156524548d20420e6c29db448801c830 100644 (file)
@@ -144,7 +144,7 @@ static struct bio *blk_bio_write_same_split(struct request_queue *q,
 static inline unsigned get_max_io_size(struct request_queue *q,
                                       struct bio *bio)
 {
-       unsigned sectors = blk_max_size_offset(q, bio->bi_iter.bi_sector);
+       unsigned sectors = blk_max_size_offset(q, bio->bi_iter.bi_sector, 0);
        unsigned max_sectors = sectors;
        unsigned pbs = queue_physical_block_size(q) >> SECTOR_SHIFT;
        unsigned lbs = queue_logical_block_size(q) >> SECTOR_SHIFT;
index 9741d1d83e989c8e3a18ed6eef4024bc781f0271..659cdb8a07fef767582a83ce2c55206295df647a 100644 (file)
@@ -547,7 +547,10 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
 
        t->io_min = max(t->io_min, b->io_min);
        t->io_opt = lcm_not_zero(t->io_opt, b->io_opt);
-       t->chunk_sectors = lcm_not_zero(t->chunk_sectors, b->chunk_sectors);
+
+       /* Set non-power-of-2 compatible chunk_sectors boundary */
+       if (b->chunk_sectors)
+               t->chunk_sectors = gcd(t->chunk_sectors, b->chunk_sectors);
 
        /* Physical block size a multiple of the logical block size? */
        if (t->physical_block_size & (t->logical_block_size - 1)) {
index 0a273211fec28383eb85311acbf811a7b10f0623..9387f050c248a7f5d6636fb17cd6a0d086f21196 100644 (file)
@@ -49,7 +49,7 @@ static void disk_release_events(struct gendisk *disk);
  * Set disk capacity and notify if the size is not currently
  * zero and will not be set to zero
  */
-void set_capacity_revalidate_and_notify(struct gendisk *disk, sector_t size,
+bool set_capacity_revalidate_and_notify(struct gendisk *disk, sector_t size,
                                        bool update_bdev)
 {
        sector_t capacity = get_capacity(disk);
@@ -62,7 +62,10 @@ void set_capacity_revalidate_and_notify(struct gendisk *disk, sector_t size,
                char *envp[] = { "RESIZE=1", NULL };
 
                kobject_uevent_env(&disk_to_dev(disk)->kobj, KOBJ_CHANGE, envp);
+               return true;
        }
+
+       return false;
 }
 
 EXPORT_SYMBOL_GPL(set_capacity_revalidate_and_notify);
index 35abcb1ec051d566048fb8761389c052d79dfcb0..86f8195d8039e5da6e5465277a9e22a692524ac8 100644 (file)
@@ -103,6 +103,13 @@ int blk_ksm_init(struct blk_keyslot_manager *ksm, unsigned int num_slots)
        spin_lock_init(&ksm->idle_slots_lock);
 
        slot_hashtable_size = roundup_pow_of_two(num_slots);
+       /*
+        * hash_ptr() assumes bits != 0, so ensure the hash table has at least 2
+        * buckets.  This only makes a difference when there is only 1 keyslot.
+        */
+       if (slot_hashtable_size < 2)
+               slot_hashtable_size = 2;
+
        ksm->log_slot_ht_size = ilog2(slot_hashtable_size);
        ksm->slot_hashtable = kvmalloc_array(slot_hashtable_size,
                                             sizeof(ksm->slot_hashtable[0]),
index c0cd1b9075e3d265598f08e15cd6e439017e3697..5762280377186c47739ed9da226022b061658895 100644 (file)
@@ -145,6 +145,7 @@ obj-$(CONFIG_OF)            += of/
 obj-$(CONFIG_SSB)              += ssb/
 obj-$(CONFIG_BCMA)             += bcma/
 obj-$(CONFIG_VHOST_RING)       += vhost/
+obj-$(CONFIG_VHOST_IOTLB)      += vhost/
 obj-$(CONFIG_VHOST)            += vhost/
 obj-$(CONFIG_VLYNQ)            += vlynq/
 obj-$(CONFIG_GREYBUS)          += greybus/
index be79b2135facc7a2912ed15979fb9b9f5e8b4e6d..48019660a0967922e5c14b8d60f384219ecf4297 100644 (file)
@@ -357,7 +357,6 @@ static void speakup_cut(struct vc_data *vc)
        mark_cut_flag = 0;
        synth_printf("%s\n", spk_msg_get(MSG_CUT));
 
-       speakup_clear_selection();
        ret = speakup_set_selection(tty);
 
        switch (ret) {
index 032f3264fba12bd925f7cad46f379b6de8b90a22..7df7afad5ab4244b64ab6e8dc926e978b4eae837 100644 (file)
@@ -22,13 +22,6 @@ struct speakup_selection_work {
        struct tty_struct *tty;
 };
 
-void speakup_clear_selection(void)
-{
-       console_lock();
-       clear_selection();
-       console_unlock();
-}
-
 static void __speakup_set_selection(struct work_struct *work)
 {
        struct speakup_selection_work *ssw =
@@ -51,6 +44,10 @@ static void __speakup_set_selection(struct work_struct *work)
                goto unref;
        }
 
+       console_lock();
+       clear_selection();
+       console_unlock();
+
        set_selection_kernel(&sel, tty);
 
 unref:
index 74fe49c2c5110da46dfd72920d809ac23f3346cf..33594f5a79837e871c091639668e80eccb1b023a 100644 (file)
@@ -70,7 +70,6 @@ void spk_do_flush(void);
 void speakup_start_ttys(void);
 void synth_buffer_add(u16 ch);
 void synth_buffer_clear(void);
-void speakup_clear_selection(void);
 int speakup_set_selection(struct tty_struct *tty);
 void speakup_cancel_selection(void);
 int speakup_paste_selection(struct tty_struct *tty);
index a831ff64f8ba579e9acd967f7906e43a633dac6d..6284aff434a1af562c53781f2b2684a0b7bf9dbe 100644 (file)
@@ -47,9 +47,12 @@ static int spk_ttyio_ldisc_open(struct tty_struct *tty)
 {
        struct spk_ldisc_data *ldisc_data;
 
+       if (tty != speakup_tty)
+               /* Somebody tried to use this line discipline outside speakup */
+               return -ENODEV;
+
        if (!tty->ops->write)
                return -EOPNOTSUPP;
-       speakup_tty = tty;
 
        ldisc_data = kmalloc(sizeof(*ldisc_data), GFP_KERNEL);
        if (!ldisc_data)
@@ -57,7 +60,7 @@ static int spk_ttyio_ldisc_open(struct tty_struct *tty)
 
        init_completion(&ldisc_data->completion);
        ldisc_data->buf_free = true;
-       speakup_tty->disc_data = ldisc_data;
+       tty->disc_data = ldisc_data;
 
        return 0;
 }
@@ -181,9 +184,25 @@ static int spk_ttyio_initialise_ldisc(struct spk_synth *synth)
 
        tty_unlock(tty);
 
+       mutex_lock(&speakup_tty_mutex);
+       speakup_tty = tty;
        ret = tty_set_ldisc(tty, N_SPEAKUP);
        if (ret)
-               pr_err("speakup: Failed to set N_SPEAKUP on tty\n");
+               speakup_tty = NULL;
+       mutex_unlock(&speakup_tty_mutex);
+
+       if (!ret)
+               /* Success */
+               return 0;
+
+       pr_err("speakup: Failed to set N_SPEAKUP on tty\n");
+
+       tty_lock(tty);
+       if (tty->ops->close)
+               tty->ops->close(tty, NULL);
+       tty_unlock(tty);
+
+       tty_kclose(tty);
 
        return ret;
 }
@@ -298,11 +317,13 @@ static unsigned char ttyio_in(int timeout)
        struct spk_ldisc_data *ldisc_data = speakup_tty->disc_data;
        char rv;
 
-       if (wait_for_completion_timeout(&ldisc_data->completion,
+       if (!timeout) {
+               if (!try_wait_for_completion(&ldisc_data->completion))
+                       return 0xff;
+       } else if (wait_for_completion_timeout(&ldisc_data->completion,
                                        usecs_to_jiffies(timeout)) == 0) {
-               if (timeout)
-                       pr_warn("spk_ttyio: timeout (%d)  while waiting for input\n",
-                               timeout);
+               pr_warn("spk_ttyio: timeout (%d)  while waiting for input\n",
+                       timeout);
                return 0xff;
        }
 
index 7398f1196e103732845570dd83cdf3ca1d6698ac..91fca3033a45a6a987c282b3d035aa084d0a45e2 100644 (file)
@@ -32,6 +32,10 @@ enum {
        E_NEW_DEFAULT,
 };
 
+/*
+ * Note: add new members at the end, speakupmap.h depends on the values of the
+ * enum starting from SPELL_DELAY (see inc_dec_var)
+ */
 enum var_id_t {
        VERSION = 0, SYNTH, SILENT, SYNTH_DIRECT,
        KEYMAP, CHARS,
@@ -42,9 +46,9 @@ enum var_id_t {
        SAY_CONTROL, SAY_WORD_CTL, NO_INTERRUPT, KEY_ECHO,
        SPELL_DELAY, PUNC_LEVEL, READING_PUNC,
        ATTRIB_BLEEP, BLEEPS,
-       RATE, PITCH, INFLECTION, VOL, TONE, PUNCT, VOICE, FREQUENCY, LANG,
+       RATE, PITCH, VOL, TONE, PUNCT, VOICE, FREQUENCY, LANG,
        DIRECT, PAUSE,
-       CAPS_START, CAPS_STOP, CHARTAB,
+       CAPS_START, CAPS_STOP, CHARTAB, INFLECTION,
        MAXVARS
 };
 
index bc96457c9e2512f4369dcc4eccdcb2f66d38f03b..a322a7bd286ba6a05b484a23358e5ee19622033b 100644 (file)
@@ -578,7 +578,7 @@ acpi_video_bqc_value_to_level(struct acpi_video_device *device,
                                ACPI_VIDEO_FIRST_LEVEL - 1 - bqc_value;
 
                level = device->brightness->levels[bqc_value +
-                                                  ACPI_VIDEO_FIRST_LEVEL];
+                                                  ACPI_VIDEO_FIRST_LEVEL];
        } else {
                level = bqc_value;
        }
@@ -990,8 +990,8 @@ set_level:
                goto out_free_levels;
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                         "found %d brightness levels\n",
-                         br->count - ACPI_VIDEO_FIRST_LEVEL));
+                         "found %d brightness levels\n",
+                         br->count - ACPI_VIDEO_FIRST_LEVEL));
        return 0;
 
 out_free_levels:
index 552fd9ffaca4e2d530cfc5151df76a82409f973f..3294cc8dc0730340c2b9703b09a8952ae60019a2 100644 (file)
@@ -633,6 +633,10 @@ int apei_map_generic_address(struct acpi_generic_address *reg)
        if (rc)
                return rc;
 
+       /* IO space doesn't need mapping */
+       if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
+               return 0;
+
        if (!acpi_os_map_generic_address(reg))
                return -ENXIO;
 
index 9929ff50c0c095f465d7a66272c8b2e35e9fd26a..770d84071a3286f8a0e61aa244ff6a4bd8e2d0e6 100644 (file)
@@ -44,7 +44,7 @@ static DEFINE_SPINLOCK(iort_fwnode_lock);
  * iort_set_fwnode() - Create iort_fwnode and use it to register
  *                    iommu data in the iort_fwnode_list
  *
- * @node: IORT table node associated with the IOMMU
+ * @iort_node: IORT table node associated with the IOMMU
  * @fwnode: fwnode associated with the IORT node
  *
  * Returns: 0 on success
@@ -673,7 +673,8 @@ static int iort_dev_find_its_id(struct device *dev, u32 id,
 /**
  * iort_get_device_domain() - Find MSI domain related to a device
  * @dev: The device.
- * @req_id: Requester ID for the device.
+ * @id: Requester ID for the device.
+ * @bus_token: irq domain bus token.
  *
  * Returns: the MSI domain for this device, NULL otherwise
  */
@@ -1136,7 +1137,7 @@ static int rc_dma_get_range(struct device *dev, u64 *size)
  *
  * @dev: device to configure
  * @dma_addr: device DMA address result pointer
- * @size: DMA range size result pointer
+ * @dma_size: DMA range size result pointer
  */
 void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
 {
@@ -1526,6 +1527,7 @@ static __init const struct iort_dev_config *iort_get_dev_cfg(
 /**
  * iort_add_platform_device() - Allocate a platform device for IORT node
  * @node: Pointer to device ACPI IORT node
+ * @ops: Pointer to IORT device config struct
  *
  * Returns: 0 on success, <0 failure
  */
index cab4af532f36ecd8e0b25db9f1d04e62fdb456d1..08ee1c7b12e00004b05f01c5cd9a7fbf64cfb1f1 100644 (file)
@@ -987,7 +987,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
         */
        if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
            (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
-            (battery->capacity_now <= battery->alarm)))
+            (battery->capacity_now <= battery->alarm)))
                acpi_pm_wakeup_event(&battery->device->dev);
 
        return result;
index da4b125ab4c3ea2bd606060e8c8d2968c0e8d403..0d93a5ef4d0710a1d9dc5f1260bd114b4e4d5008 100644 (file)
@@ -73,19 +73,6 @@ MODULE_DEVICE_TABLE(acpi, button_device_ids);
 
 /* Please keep this list sorted alphabetically by vendor and model */
 static const struct dmi_system_id dmi_lid_quirks[] = {
-       {
-               /*
-                * Acer Switch 10 SW5-012. _LID method messes with home and
-                * power button GPIO IRQ settings causing an interrupt storm on
-                * both GPIOs. This is unfixable without a DSDT override, so we
-                * have to disable the lid-switch functionality altogether :|
-                */
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),
-               },
-               .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_DISABLED,
-       },
        {
                /* GP-electronic T701, _LID method points to a floating GPIO */
                .matches = {
@@ -102,7 +89,18 @@ static const struct dmi_system_id dmi_lid_quirks[] = {
                 */
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "E2215T MD60198"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "E2215T"),
+               },
+               .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
+       },
+       {
+               /*
+                * Medion Akoya E2228T, notification of the LID device only
+                * happens on close, not on open and _LID always returns closed.
+                */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "E2228T"),
                },
                .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
        },
index 45d4b7b69de879cfd4e492899912abcefcdde636..24e076f44d23827874c4d476ba8323d55dfa993c 100644 (file)
@@ -231,7 +231,8 @@ static void hot_remove_dock_devices(struct dock_station *ds)
         * between them).
         */
        list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
-               dock_hotplug_event(dd, ACPI_NOTIFY_EJECT_REQUEST, false);
+               dock_hotplug_event(dd, ACPI_NOTIFY_EJECT_REQUEST,
+                                  DOCK_CALL_HANDLER);
 
        list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
                acpi_bus_trim(dd->adev);
index 4c1992fce15076cc1496be3ec5b33c47ff56d225..5fca18296bf6801514c154dca99969f1049008a3 100644 (file)
@@ -106,6 +106,7 @@ static int pch_fivr_remove(struct platform_device *pdev)
 
 static const struct acpi_device_id pch_fivr_device_ids[] = {
        {"INTC1045", 0},
+       {"INTC1049", 0},
        {"", 0},
 };
 MODULE_DEVICE_TABLE(acpi, pch_fivr_device_ids);
index 06741305fc7708f60b9f5b489e34b99fc1dd46cd..a24d5d7aa1178471ef387b15ee4827ebfa4feacc 100644 (file)
@@ -229,6 +229,8 @@ static const struct acpi_device_id int3407_device_ids[] = {
        {"INT3532", 0},
        {"INTC1047", 0},
        {"INTC1050", 0},
+       {"INTC1060", 0},
+       {"INTC1061", 0},
        {"", 0},
 };
 MODULE_DEVICE_TABLE(acpi, int3407_device_ids);
index 8d420c7e7178102f683ea56e98e6e5cf8a6dc698..d14025a85ce85a0a30b2ecd94f08dbc9b9a9533c 100644 (file)
@@ -25,10 +25,16 @@ static const struct acpi_device_id int340x_thermal_device_ids[] = {
        {"INT340A"},
        {"INT340B"},
        {"INTC1040"},
+       {"INTC1041"},
        {"INTC1043"},
        {"INTC1044"},
        {"INTC1045"},
+       {"INTC1046"},
        {"INTC1047"},
+       {"INTC1048"},
+       {"INTC1049"},
+       {"INTC1060"},
+       {"INTC1061"},
        {""},
 };
 
index 170643927044980228fe1a78b864297ed73d4189..92e59f45329bc576c97ca3c702cd40462fe1c22f 100644 (file)
@@ -31,7 +31,7 @@ int acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data)
        event.type = type;
        event.data = data;
        return (blocking_notifier_call_chain(&acpi_chain_head, 0, (void *)&event)
-                        == NOTIFY_BAD) ? -EINVAL : 0;
+                       == NOTIFY_BAD) ? -EINVAL : 0;
 }
 EXPORT_SYMBOL(acpi_notifier_call_chain);
 
index b1a7f8d6965e432a0a62f8f111d60d8c30d94eba..fe6b6792c8bba2ccb42d00f44e6a059a6f9c1f1b 100644 (file)
@@ -101,7 +101,7 @@ static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares,
 
        switch (gsi) {
        case 0 ... 255:
-               sprintf(ev_name, "_%c%02hhX",
+               sprintf(ev_name, "_%c%02X",
                        trigger == ACPI_EDGE_SENSITIVE ? 'E' : 'L', gsi);
 
                if (ACPI_SUCCESS(acpi_get_handle(handle, ev_name, &evt_handle)))
index 62873388b24f7d94100d6f6a713cc550d90a8150..66c3983f0ccca7aacb83feb63c34c5b9e4e36cab 100644 (file)
@@ -27,6 +27,7 @@ static const struct acpi_device_id fan_device_ids[] = {
        {"PNP0C0B", 0},
        {"INT3404", 0},
        {"INTC1044", 0},
+       {"INTC1048", 0},
        {"", 0},
 };
 MODULE_DEVICE_TABLE(acpi, fan_device_ids);
@@ -351,6 +352,7 @@ static int acpi_fan_get_fps(struct acpi_device *device)
                struct acpi_fan_fps *fps = &fan->fps[i];
 
                snprintf(fps->name, ACPI_FPS_NAME_LEN, "state%d", i);
+               sysfs_attr_init(&fps->dev_attr.attr);
                fps->dev_attr.show = show_state;
                fps->dev_attr.store = NULL;
                fps->dev_attr.attr.name = fps->name;
index 43411a7457cd7f4520eb80bd05aa73d724db616d..e3638bafb94110f541ce1bd0f3cfd7f3e9ff8344 100644 (file)
@@ -134,7 +134,7 @@ int acpi_add_power_resource(acpi_handle handle);
 void acpi_power_add_remove_device(struct acpi_device *adev, bool add);
 int acpi_power_wakeup_list_init(struct list_head *list, int *system_level);
 int acpi_device_sleep_wake(struct acpi_device *dev,
-                           int enable, int sleep_state, int dev_state);
+                          int enable, int sleep_state, int dev_state);
 int acpi_power_get_inferred_state(struct acpi_device *device, int *state);
 int acpi_power_on_resources(struct acpi_device *device, int state);
 int acpi_power_transition(struct acpi_device *device, int state);
index 756227837b3b4876d14c447ca7fdb9194a6193b2..442608220b5c80be7d4b6349dc2e9fa52646dc65 100644 (file)
@@ -1564,7 +1564,7 @@ static ssize_t format1_show(struct device *dev,
                                        le16_to_cpu(nfit_dcr->dcr->code));
                        break;
                }
-               if (rc != ENXIO)
+               if (rc != -ENXIO)
                        break;
        }
        mutex_unlock(&acpi_desc->init_mutex);
@@ -2175,10 +2175,10 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
  * these commands.
  */
 enum nfit_aux_cmds {
-        NFIT_CMD_TRANSLATE_SPA = 5,
-        NFIT_CMD_ARS_INJECT_SET = 7,
-        NFIT_CMD_ARS_INJECT_CLEAR = 8,
-        NFIT_CMD_ARS_INJECT_GET = 9,
+       NFIT_CMD_TRANSLATE_SPA = 5,
+       NFIT_CMD_ARS_INJECT_SET = 7,
+       NFIT_CMD_ARS_INJECT_CLEAR = 8,
+       NFIT_CMD_ARS_INJECT_GET = 9,
 };
 
 static void acpi_nfit_init_dsms(struct acpi_nfit_desc *acpi_desc)
@@ -2632,7 +2632,7 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
        nfit_blk->bdw_offset = nfit_mem->bdw->offset;
        mmio = &nfit_blk->mmio[BDW];
        mmio->addr.base = devm_nvdimm_memremap(dev, nfit_mem->spa_bdw->address,
-                        nfit_mem->spa_bdw->length, nd_blk_memremap_flags(ndbr));
+                       nfit_mem->spa_bdw->length, nd_blk_memremap_flags(ndbr));
        if (!mmio->addr.base) {
                dev_dbg(dev, "%s failed to map bdw\n",
                                nvdimm_name(nvdimm));
index dea8a60e18a4c00929cb6f7c759615f075bcfe12..14ee631cb7cf121b673829120bb221ee369d8b6f 100644 (file)
@@ -175,7 +175,7 @@ static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev,
         * configure the IRQ assigned to this slot|dev|pin.  The 'source_index'
         * indicates which resource descriptor in the resource template (of
         * the link device) this interrupt is allocated from.
-        * 
+        *
         * NOTE: Don't query the Link Device for IRQ information at this time
         *       because Link Device enumeration may not have occurred yet
         *       (e.g. exists somewhere 'below' this _PRT entry in the ACPI
index 606da5d77ad32aee516a7eea39a8eaabacdc1e42..fb4c5632a232bf6a2c1d60a4639c5f9842ef3d2e 100644 (file)
@@ -6,8 +6,8 @@
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
  *  Copyright (C) 2002       Dominik Brodowski <devel@brodo.de>
  *
- * TBD: 
- *      1. Support more than one IRQ resource entry per link device (index).
+ * TBD:
+ *     1. Support more than one IRQ resource entry per link device (index).
  *     2. Implement start/stop mechanism and use ACPI Bus Driver facilities
  *        for IRQ management (e.g. start()->_SRS).
  */
@@ -249,8 +249,8 @@ static int acpi_pci_link_get_current(struct acpi_pci_link *link)
                }
        }
 
-       /* 
-        * Query and parse _CRS to get the current IRQ assignment. 
+       /*
+        * Query and parse _CRS to get the current IRQ assignment.
         */
 
        status = acpi_walk_resources(link->device->handle, METHOD_NAME__CRS,
@@ -396,7 +396,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
 /*
  * "acpi_irq_balance" (default in APIC mode) enables ACPI to use PIC Interrupt
  * Link Devices to move the PIRQs around to minimize sharing.
- * 
+ *
  * "acpi_irq_nobalance" (default in PIC mode) tells ACPI not to move any PIC IRQs
  * that the BIOS has already set to active.  This is necessary because
  * ACPI has no automatic means of knowing what ISA IRQs are used.  Note that
@@ -414,7 +414,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
  *
  * Note that PCI IRQ routers have a list of possible IRQs,
  * which may not include the IRQs this table says are available.
- * 
+ *
  * Since this heuristic can't tell the difference between a link
  * that no device will attach to, vs. a link which may be shared
  * by multiple active devices -- it is not optimal.
index 7ddd57abadd1da36cf559db61e7df4343b74b584..95f23acd5b8020cef9ea4e056cd50284c695211f 100644 (file)
@@ -173,7 +173,7 @@ static int pci_mcfg_quirk_matches(struct mcfg_fixup *f, u16 segment,
 {
        if (!memcmp(f->oem_id, mcfg_oem_id, ACPI_OEM_ID_SIZE) &&
            !memcmp(f->oem_table_id, mcfg_oem_table_id,
-                   ACPI_OEM_TABLE_ID_SIZE) &&
+                   ACPI_OEM_TABLE_ID_SIZE) &&
            f->oem_revision == mcfg_oem_revision &&
            f->segment == segment &&
            resource_contains(&f->bus_range, bus_range))
index 837b875d075e5b4775d97f3e5c0f5075d8103d36..8048da85b7e0787b340086200776a35f6310f06b 100644 (file)
@@ -13,7 +13,7 @@
  * 1. via "Device Specific (D-State) Control"
  * 2. via "Power Resource Control".
  * The code below deals with ACPI Power Resources control.
- * 
+ *
  * An ACPI "power resource object" represents a software controllable power
  * plane, clock plane, or other resource depended on by a device.
  *
@@ -645,7 +645,7 @@ int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p)
  * -ENODEV if the execution of either _DSW or _PSW has failed
  */
 int acpi_device_sleep_wake(struct acpi_device *dev,
-                           int enable, int sleep_state, int dev_state)
+                          int enable, int sleep_state, int dev_state)
 {
        union acpi_object in_arg[3];
        struct acpi_object_list arg_list = { 3, in_arg };
@@ -690,7 +690,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev,
 
 /*
  * Prepare a wakeup device, two steps (Ref ACPI 2.0:P229):
- * 1. Power on the power resources required for the wakeup device 
+ * 1. Power on the power resources required for the wakeup device
  * 2. Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
  *    State Wake) for the device, if present
  */
index 5909e8fa4013f2c6c831b1a28d9d69ca4cec98fb..b04a68950ff14299804809b10f480419219fdaa6 100644 (file)
@@ -354,7 +354,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
                                  (u32) px->control, (u32) px->status));
 
                /*
-                * Check that ACPI's u64 MHz will be valid as u32 KHz in cpufreq
+                * Check that ACPI's u64 MHz will be valid as u32 KHz in cpufreq
                 */
                if (!px->core_frequency ||
                    ((u32)(px->core_frequency * 1000) !=
@@ -627,7 +627,7 @@ int acpi_processor_preregister_performance(
                goto err_ret;
 
        /*
-        * Now that we have _PSD data from all CPUs, lets setup P-state 
+        * Now that we have _PSD data from all CPUs, lets setup P-state
         * domain info.
         */
        for_each_possible_cpu(i) {
@@ -693,7 +693,7 @@ int acpi_processor_preregister_performance(
                        if (match_pdomain->domain != pdomain->domain)
                                continue;
 
-                       match_pr->performance->shared_type = 
+                       match_pr->performance->shared_type =
                                        pr->performance->shared_type;
                        cpumask_copy(match_pr->performance->shared_cpu_map,
                                     pr->performance->shared_cpu_map);
index f158b8c30113b3809354a9709bf42bd63b2e6eaa..e6d9f4de280000d17e9a29ef5c0af478782e2280 100644 (file)
@@ -366,7 +366,7 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
                                         state_readers[i].mode,
                                         ACPI_SBS_BATTERY,
                                         state_readers[i].command,
-                                        (u8 *)battery +
+                                        (u8 *)battery +
                                                state_readers[i].offset);
                if (result)
                        goto end;
index 87b74e9015e5bab92c130fca27f49132362754cb..53c2862c4c75dc05235eb8b98cb08d8b1be0fcdd 100644 (file)
@@ -176,7 +176,7 @@ int acpi_smbus_write(struct acpi_smb_hc *hc, u8 protocol, u8 address,
 EXPORT_SYMBOL_GPL(acpi_smbus_write);
 
 int acpi_smbus_register_callback(struct acpi_smb_hc *hc,
-                                smbus_alarm_callback callback, void *context)
+                                smbus_alarm_callback callback, void *context)
 {
        mutex_lock(&hc->lock);
        hc->callback = callback;
index c3522bb8279246861da743b7841492ef8b578d8c..695c390e28843953b437effeb098f1d72323fefd 100644 (file)
@@ -24,9 +24,9 @@ enum acpi_sbs_device_addr {
 typedef void (*smbus_alarm_callback)(void *context);
 
 extern int acpi_smbus_read(struct acpi_smb_hc *hc, u8 protocol, u8 address,
-              u8 command, u8 * data);
+               u8 command, u8 *data);
 extern int acpi_smbus_write(struct acpi_smb_hc *hc, u8 protocol, u8 slave_address,
-               u8 command, u8 * data, u8 length);
+               u8 command, u8 *data, u8 length);
 extern int acpi_smbus_register_callback(struct acpi_smb_hc *hc,
-                                smbus_alarm_callback callback, void *context);
+               smbus_alarm_callback callback, void *context);
 extern int acpi_smbus_unregister_callback(struct acpi_smb_hc *hc);
index a896e5e87c935d923c1cb9bc93b7bce363dfaff3..bc6a79e3322092a1eefd89ec577f8c8d4ea7ad71 100644 (file)
@@ -1453,7 +1453,7 @@ int acpi_dma_get_range(struct device *dev, u64 *dma_addr, u64 *offset,
 }
 
 /**
- * acpi_dma_configure - Set-up DMA configuration for the device.
+ * acpi_dma_configure_id - Set-up DMA configuration for the device.
  * @dev: The pointer to the device
  * @attr: device dma attributes
  * @input_id: input device id const value pointer
index 3a032afd9d05f3a7e9d2aea2c14e58e904b42a12..4f5463b2a217817d006e85df8180818871115491 100644 (file)
@@ -178,14 +178,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"),
                },
        },
-        {
-         .callback = video_detect_force_video,
-         .ident = "ThinkPad X201T",
-         .matches = {
-                DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201T"),
-                },
-        },
+       {
+        .callback = video_detect_force_video,
+        .ident = "ThinkPad X201T",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201T"),
+               },
+       },
 
        /* The native backlight controls do not work on some older machines */
        {
index f89dd9a99e6e099c9926da0afe1b4d138ed92f6c..b02bf770aead322d4227c49674704efefdbb856b 100644 (file)
@@ -44,7 +44,7 @@ void acpi_enable_wakeup_devices(u8 sleep_state)
                if (!dev->wakeup.flags.valid
                    || sleep_state > (u32) dev->wakeup.sleep_state
                    || !(device_may_wakeup(&dev->dev)
-                       || dev->wakeup.prepare_count))
+                        || dev->wakeup.prepare_count))
                        continue;
 
                if (device_may_wakeup(&dev->dev))
@@ -69,7 +69,7 @@ void acpi_disable_wakeup_devices(u8 sleep_state)
                if (!dev->wakeup.flags.valid
                    || sleep_state > (u32) dev->wakeup.sleep_state
                    || !(device_may_wakeup(&dev->dev)
-                       || dev->wakeup.prepare_count))
+                        || dev->wakeup.prepare_count))
                        continue;
 
                acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
index eb9dc14e5147aaebbc210c1481ce146a6d9c57a4..20190f66ced987c10badfad6012bdfdbe678345b 100644 (file)
@@ -2100,7 +2100,7 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
        pp->dhfis_bits &= ~done_mask;
        pp->dmafis_bits &= ~done_mask;
        pp->sdbfis_bits |= done_mask;
-       ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
+       ata_qc_complete_multiple(ap, ata_qc_get_active(ap) ^ done_mask);
 
        if (!ap->qc_active) {
                DPRINTK("over\n");
index 7af74fb450a0d01c5aaf90e9ba1a2859041b6250..09ad73361879e1a7b84944382e8927a01d4d00e4 100644 (file)
@@ -1706,6 +1706,8 @@ static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb)
 
        if (push_scqe(card, vc, scq, &scqe, skb) != 0) {
                atomic_inc(&vcc->stats->tx_err);
+               dma_unmap_single(&card->pcidev->dev, NS_PRV_DMA(skb), skb->len,
+                                DMA_TO_DEVICE);
                dev_kfree_skb_any(skb);
                return -EIO;
        }
index c852f16c111b248046bc1e73e0246eb49e1ae332..d661ada1518fb49ceab77789043946abfa32d3d8 100644 (file)
@@ -773,8 +773,7 @@ static void __device_link_del(struct kref *kref)
        dev_dbg(link->consumer, "Dropping the link to %s\n",
                dev_name(link->supplier));
 
-       if (link->flags & DL_FLAG_PM_RUNTIME)
-               pm_runtime_drop_link(link->consumer);
+       pm_runtime_drop_link(link);
 
        list_del_rcu(&link->s_node);
        list_del_rcu(&link->c_node);
@@ -788,8 +787,7 @@ static void __device_link_del(struct kref *kref)
        dev_info(link->consumer, "Dropping the link to %s\n",
                 dev_name(link->supplier));
 
-       if (link->flags & DL_FLAG_PM_RUNTIME)
-               pm_runtime_drop_link(link->consumer);
+       pm_runtime_drop_link(link);
 
        list_del(&link->s_node);
        list_del(&link->c_node);
@@ -4264,6 +4262,7 @@ static inline bool fwnode_is_primary(struct fwnode_handle *fwnode)
  */
 void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
 {
+       struct device *parent = dev->parent;
        struct fwnode_handle *fn = dev->fwnode;
 
        if (fwnode) {
@@ -4278,7 +4277,8 @@ void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
        } else {
                if (fwnode_is_primary(fn)) {
                        dev->fwnode = fn->secondary;
-                       fn->secondary = NULL;
+                       if (!(parent && fn == parent->fwnode))
+                               fn->secondary = ERR_PTR(-ENODEV);
                } else {
                        dev->fwnode = NULL;
                }
index b42229b74fd69688b1af2ea0de19008c8e169ba2..148e81969e04625ce1645c4c1857facb3360d1bd 100644 (file)
@@ -1117,6 +1117,8 @@ static void __device_release_driver(struct device *dev, struct device *parent)
 
        drv = dev->driver;
        if (drv) {
+               pm_runtime_get_sync(dev);
+
                while (device_links_busy(dev)) {
                        __device_driver_unlock(dev, parent);
 
@@ -1128,13 +1130,12 @@ static void __device_release_driver(struct device *dev, struct device *parent)
                         * have released the driver successfully while this one
                         * was waiting, so check for that.
                         */
-                       if (dev->driver != drv)
+                       if (dev->driver != drv) {
+                               pm_runtime_put(dev);
                                return;
+                       }
                }
 
-               pm_runtime_get_sync(dev);
-               pm_runtime_clean_up_links(dev);
-
                driver_sysfs_remove(dev);
 
                if (dev->bus)
index 6f605f7820bb5fe55707645b7dea56eb70d21b5c..bfda153b1a41deed5a36ae53912fc7b0a4346980 100644 (file)
@@ -1642,42 +1642,6 @@ void pm_runtime_remove(struct device *dev)
        pm_runtime_reinit(dev);
 }
 
-/**
- * pm_runtime_clean_up_links - Prepare links to consumers for driver removal.
- * @dev: Device whose driver is going to be removed.
- *
- * Check links from this device to any consumers and if any of them have active
- * runtime PM references to the device, drop the usage counter of the device
- * (as many times as needed).
- *
- * Links with the DL_FLAG_MANAGED flag unset are ignored.
- *
- * Since the device is guaranteed to be runtime-active at the point this is
- * called, nothing else needs to be done here.
- *
- * Moreover, this is called after device_links_busy() has returned 'false', so
- * the status of each link is guaranteed to be DL_STATE_SUPPLIER_UNBIND and
- * therefore rpm_active can't be manipulated concurrently.
- */
-void pm_runtime_clean_up_links(struct device *dev)
-{
-       struct device_link *link;
-       int idx;
-
-       idx = device_links_read_lock();
-
-       list_for_each_entry_rcu(link, &dev->links.consumers, s_node,
-                               device_links_read_lock_held()) {
-               if (!(link->flags & DL_FLAG_MANAGED))
-                       continue;
-
-               while (refcount_dec_not_one(&link->rpm_active))
-                       pm_runtime_put_noidle(dev);
-       }
-
-       device_links_read_unlock(idx);
-}
-
 /**
  * pm_runtime_get_suppliers - Resume and reference-count supplier devices.
  * @dev: Consumer device.
@@ -1729,7 +1693,7 @@ void pm_runtime_new_link(struct device *dev)
        spin_unlock_irq(&dev->power.lock);
 }
 
-void pm_runtime_drop_link(struct device *dev)
+static void pm_runtime_drop_link_count(struct device *dev)
 {
        spin_lock_irq(&dev->power.lock);
        WARN_ON(dev->power.links_count == 0);
@@ -1737,6 +1701,25 @@ void pm_runtime_drop_link(struct device *dev)
        spin_unlock_irq(&dev->power.lock);
 }
 
+/**
+ * pm_runtime_drop_link - Prepare for device link removal.
+ * @link: Device link going away.
+ *
+ * Drop the link count of the consumer end of @link and decrement the supplier
+ * device's runtime PM usage counter as many times as needed to drop all of the
+ * PM runtime reference to it from the consumer.
+ */
+void pm_runtime_drop_link(struct device_link *link)
+{
+       if (!(link->flags & DL_FLAG_PM_RUNTIME))
+               return;
+
+       pm_runtime_drop_link_count(link->consumer);
+
+       while (refcount_dec_not_one(&link->rpm_active))
+               pm_runtime_put(link->supplier);
+}
+
 static bool pm_runtime_need_not_resume(struct device *dev)
 {
        return atomic_read(&dev->power.usage_count) <= 1 &&
index cb1191d6e945f27bd1c5582321cd6ef5496727bf..a58084c2ed7ceb128ea9de08e7cda190d627b591 100644 (file)
@@ -255,7 +255,8 @@ static void loop_set_size(struct loop_device *lo, loff_t size)
 
        bd_set_nr_sectors(bdev, size);
 
-       set_capacity_revalidate_and_notify(lo->lo_disk, size, false);
+       if (!set_capacity_revalidate_and_notify(lo->lo_disk, size, false))
+               kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
 }
 
 static inline int
index 0bed21c0c81b29b7dd45ff451db8042f11b05d2f..aaae9220f3a008eaca642778b4909819ce8876b4 100644 (file)
@@ -296,7 +296,7 @@ static void nbd_size_clear(struct nbd_device *nbd)
        }
 }
 
-static void nbd_size_update(struct nbd_device *nbd)
+static void nbd_size_update(struct nbd_device *nbd, bool start)
 {
        struct nbd_config *config = nbd->config;
        struct block_device *bdev = bdget_disk(nbd->disk, 0);
@@ -313,7 +313,8 @@ static void nbd_size_update(struct nbd_device *nbd)
        if (bdev) {
                if (bdev->bd_disk) {
                        bd_set_nr_sectors(bdev, nr_sectors);
-                       set_blocksize(bdev, config->blksize);
+                       if (start)
+                               set_blocksize(bdev, config->blksize);
                } else
                        set_bit(GD_NEED_PART_SCAN, &nbd->disk->state);
                bdput(bdev);
@@ -328,7 +329,7 @@ static void nbd_size_set(struct nbd_device *nbd, loff_t blocksize,
        config->blksize = blocksize;
        config->bytesize = blocksize * nr_blocks;
        if (nbd->task_recv != NULL)
-               nbd_size_update(nbd);
+               nbd_size_update(nbd, false);
 }
 
 static void nbd_complete_rq(struct request *req)
@@ -1308,7 +1309,7 @@ static int nbd_start_device(struct nbd_device *nbd)
                args->index = i;
                queue_work(nbd->recv_workq, &args->work);
        }
-       nbd_size_update(nbd);
+       nbd_size_update(nbd, true);
        return error;
 }
 
@@ -1517,6 +1518,7 @@ static void nbd_release(struct gendisk *disk, fmode_t mode)
        if (test_bit(NBD_RT_DISCONNECT_ON_CLOSE, &nbd->config->runtime_flags) &&
                        bdev->bd_openers == 0)
                nbd_disconnect_and_put(nbd);
+       bdput(bdev);
 
        nbd_config_put(nbd);
        nbd_put(nbd);
index d2e7db43a52a7c22363f5a38c4911179f18496c3..c24d9b5ad81af26c2761daf8a29948a44e8ff607 100644 (file)
@@ -47,6 +47,8 @@ struct nullb_device {
        unsigned int nr_zones_closed;
        struct blk_zone *zones;
        sector_t zone_size_sects;
+       spinlock_t zone_lock;
+       unsigned long *zone_locks;
 
        unsigned long size; /* device size in MB */
        unsigned long completion_nsec; /* time in ns to complete a request */
index 7d94f2d47a6af6326051d90a7543ba410bbb9877..beb34b4f76b0e6c7f2fe91167fea922c786e5f3a 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/vmalloc.h>
+#include <linux/bitmap.h>
 #include "null_blk.h"
 
 #define CREATE_TRACE_POINTS
@@ -45,6 +46,22 @@ int null_init_zoned_dev(struct nullb_device *dev, struct request_queue *q)
        if (!dev->zones)
                return -ENOMEM;
 
+       /*
+        * With memory backing, the zone_lock spinlock needs to be temporarily
+        * released to avoid scheduling in atomic context. To guarantee zone
+        * information protection, use a bitmap to lock zones with
+        * wait_on_bit_lock_io(). Sleeping on the lock is OK as memory backing
+        * implies that the queue is marked with BLK_MQ_F_BLOCKING.
+        */
+       spin_lock_init(&dev->zone_lock);
+       if (dev->memory_backed) {
+               dev->zone_locks = bitmap_zalloc(dev->nr_zones, GFP_KERNEL);
+               if (!dev->zone_locks) {
+                       kvfree(dev->zones);
+                       return -ENOMEM;
+               }
+       }
+
        if (dev->zone_nr_conv >= dev->nr_zones) {
                dev->zone_nr_conv = dev->nr_zones - 1;
                pr_info("changed the number of conventional zones to %u",
@@ -123,15 +140,31 @@ int null_register_zoned_dev(struct nullb *nullb)
 
 void null_free_zoned_dev(struct nullb_device *dev)
 {
+       bitmap_free(dev->zone_locks);
        kvfree(dev->zones);
 }
 
+static inline void null_lock_zone(struct nullb_device *dev, unsigned int zno)
+{
+       if (dev->memory_backed)
+               wait_on_bit_lock_io(dev->zone_locks, zno, TASK_UNINTERRUPTIBLE);
+       spin_lock_irq(&dev->zone_lock);
+}
+
+static inline void null_unlock_zone(struct nullb_device *dev, unsigned int zno)
+{
+       spin_unlock_irq(&dev->zone_lock);
+
+       if (dev->memory_backed)
+               clear_and_wake_up_bit(zno, dev->zone_locks);
+}
+
 int null_report_zones(struct gendisk *disk, sector_t sector,
                unsigned int nr_zones, report_zones_cb cb, void *data)
 {
        struct nullb *nullb = disk->private_data;
        struct nullb_device *dev = nullb->dev;
-       unsigned int first_zone, i;
+       unsigned int first_zone, i, zno;
        struct blk_zone zone;
        int error;
 
@@ -142,15 +175,18 @@ int null_report_zones(struct gendisk *disk, sector_t sector,
        nr_zones = min(nr_zones, dev->nr_zones - first_zone);
        trace_nullb_report_zones(nullb, nr_zones);
 
-       for (i = 0; i < nr_zones; i++) {
+       zno = first_zone;
+       for (i = 0; i < nr_zones; i++, zno++) {
                /*
                 * Stacked DM target drivers will remap the zone information by
                 * modifying the zone information passed to the report callback.
                 * So use a local copy to avoid corruption of the device zone
                 * array.
                 */
-               memcpy(&zone, &dev->zones[first_zone + i],
-                      sizeof(struct blk_zone));
+               null_lock_zone(dev, zno);
+               memcpy(&zone, &dev->zones[zno], sizeof(struct blk_zone));
+               null_unlock_zone(dev, zno);
+
                error = cb(&zone, i, data);
                if (error)
                        return error;
@@ -159,6 +195,10 @@ int null_report_zones(struct gendisk *disk, sector_t sector,
        return nr_zones;
 }
 
+/*
+ * This is called in the case of memory backing from null_process_cmd()
+ * with the target zone already locked.
+ */
 size_t null_zone_valid_read_len(struct nullb *nullb,
                                sector_t sector, unsigned int len)
 {
@@ -295,22 +335,26 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
        if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
                return null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
 
+       null_lock_zone(dev, zno);
+
        switch (zone->cond) {
        case BLK_ZONE_COND_FULL:
                /* Cannot write to a full zone */
-               return BLK_STS_IOERR;
+               ret = BLK_STS_IOERR;
+               goto unlock;
        case BLK_ZONE_COND_EMPTY:
        case BLK_ZONE_COND_CLOSED:
                ret = null_check_zone_resources(dev, zone);
                if (ret != BLK_STS_OK)
-                       return ret;
+                       goto unlock;
                break;
        case BLK_ZONE_COND_IMP_OPEN:
        case BLK_ZONE_COND_EXP_OPEN:
                break;
        default:
                /* Invalid zone condition */
-               return BLK_STS_IOERR;
+               ret = BLK_STS_IOERR;
+               goto unlock;
        }
 
        /*
@@ -326,11 +370,14 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
                else
                        cmd->rq->__sector = sector;
        } else if (sector != zone->wp) {
-               return BLK_STS_IOERR;
+               ret = BLK_STS_IOERR;
+               goto unlock;
        }
 
-       if (zone->wp + nr_sectors > zone->start + zone->capacity)
-               return BLK_STS_IOERR;
+       if (zone->wp + nr_sectors > zone->start + zone->capacity) {
+               ret = BLK_STS_IOERR;
+               goto unlock;
+       }
 
        if (zone->cond == BLK_ZONE_COND_CLOSED) {
                dev->nr_zones_closed--;
@@ -341,9 +388,19 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
        if (zone->cond != BLK_ZONE_COND_EXP_OPEN)
                zone->cond = BLK_ZONE_COND_IMP_OPEN;
 
+       /*
+        * Memory backing allocation may sleep: release the zone_lock spinlock
+        * to avoid scheduling in atomic context. Zone operation atomicity is
+        * still guaranteed through the zone_locks bitmap.
+        */
+       if (dev->memory_backed)
+               spin_unlock_irq(&dev->zone_lock);
        ret = null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
+       if (dev->memory_backed)
+               spin_lock_irq(&dev->zone_lock);
+
        if (ret != BLK_STS_OK)
-               return ret;
+               goto unlock;
 
        zone->wp += nr_sectors;
        if (zone->wp == zone->start + zone->capacity) {
@@ -353,7 +410,12 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
                        dev->nr_zones_imp_open--;
                zone->cond = BLK_ZONE_COND_FULL;
        }
-       return BLK_STS_OK;
+       ret = BLK_STS_OK;
+
+unlock:
+       null_unlock_zone(dev, zno);
+
+       return ret;
 }
 
 static blk_status_t null_open_zone(struct nullb_device *dev, struct blk_zone *zone)
@@ -464,16 +526,30 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
                                   sector_t sector)
 {
        struct nullb_device *dev = cmd->nq->dev;
-       unsigned int zone_no = null_zone_no(dev, sector);
-       struct blk_zone *zone = &dev->zones[zone_no];
-       blk_status_t ret = BLK_STS_OK;
+       unsigned int zone_no;
+       struct blk_zone *zone;
+       blk_status_t ret;
        size_t i;
 
+       if (op == REQ_OP_ZONE_RESET_ALL) {
+               for (i = dev->zone_nr_conv; i < dev->nr_zones; i++) {
+                       null_lock_zone(dev, i);
+                       zone = &dev->zones[i];
+                       if (zone->cond != BLK_ZONE_COND_EMPTY) {
+                               null_reset_zone(dev, zone);
+                               trace_nullb_zone_op(cmd, i, zone->cond);
+                       }
+                       null_unlock_zone(dev, i);
+               }
+               return BLK_STS_OK;
+       }
+
+       zone_no = null_zone_no(dev, sector);
+       zone = &dev->zones[zone_no];
+
+       null_lock_zone(dev, zone_no);
+
        switch (op) {
-       case REQ_OP_ZONE_RESET_ALL:
-               for (i = dev->zone_nr_conv; i < dev->nr_zones; i++)
-                       null_reset_zone(dev, &dev->zones[i]);
-               break;
        case REQ_OP_ZONE_RESET:
                ret = null_reset_zone(dev, zone);
                break;
@@ -487,30 +563,44 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
                ret = null_finish_zone(dev, zone);
                break;
        default:
-               return BLK_STS_NOTSUPP;
+               ret = BLK_STS_NOTSUPP;
+               break;
        }
 
        if (ret == BLK_STS_OK)
                trace_nullb_zone_op(cmd, zone_no, zone->cond);
 
+       null_unlock_zone(dev, zone_no);
+
        return ret;
 }
 
 blk_status_t null_process_zoned_cmd(struct nullb_cmd *cmd, enum req_opf op,
                                    sector_t sector, sector_t nr_sectors)
 {
+       struct nullb_device *dev = cmd->nq->dev;
+       unsigned int zno = null_zone_no(dev, sector);
+       blk_status_t sts;
+
        switch (op) {
        case REQ_OP_WRITE:
-               return null_zone_write(cmd, sector, nr_sectors, false);
+               sts = null_zone_write(cmd, sector, nr_sectors, false);
+               break;
        case REQ_OP_ZONE_APPEND:
-               return null_zone_write(cmd, sector, nr_sectors, true);
+               sts = null_zone_write(cmd, sector, nr_sectors, true);
+               break;
        case REQ_OP_ZONE_RESET:
        case REQ_OP_ZONE_RESET_ALL:
        case REQ_OP_ZONE_OPEN:
        case REQ_OP_ZONE_CLOSE:
        case REQ_OP_ZONE_FINISH:
-               return null_zone_mgmt(cmd, op, sector);
+               sts = null_zone_mgmt(cmd, op, sector);
+               break;
        default:
-               return null_process_cmd(cmd, op, sector, nr_sectors);
+               null_lock_zone(dev, zno);
+               sts = null_process_cmd(cmd, op, sector, nr_sectors);
+               null_unlock_zone(dev, zno);
        }
+
+       return sts;
 }
index 8d581c7536fb510f08aebd3abdf3425b4a7ff7bd..eb8ef65778c35eab417668f89165520db47b3cf2 100644 (file)
@@ -443,22 +443,27 @@ static void ace_fix_driveid(u16 *id)
 #define ACE_FSM_NUM_STATES              11
 
 /* Set flag to exit FSM loop and reschedule tasklet */
-static inline void ace_fsm_yield(struct ace_device *ace)
+static inline void ace_fsm_yieldpoll(struct ace_device *ace)
 {
-       dev_dbg(ace->dev, "ace_fsm_yield()\n");
        tasklet_schedule(&ace->fsm_tasklet);
        ace->fsm_continue_flag = 0;
 }
 
+static inline void ace_fsm_yield(struct ace_device *ace)
+{
+       dev_dbg(ace->dev, "%s()\n", __func__);
+       ace_fsm_yieldpoll(ace);
+}
+
 /* Set flag to exit FSM loop and wait for IRQ to reschedule tasklet */
 static inline void ace_fsm_yieldirq(struct ace_device *ace)
 {
        dev_dbg(ace->dev, "ace_fsm_yieldirq()\n");
 
-       if (!ace->irq)
-               /* No IRQ assigned, so need to poll */
-               tasklet_schedule(&ace->fsm_tasklet);
-       ace->fsm_continue_flag = 0;
+       if (ace->irq > 0)
+               ace->fsm_continue_flag = 0;
+       else
+               ace_fsm_yieldpoll(ace);
 }
 
 static bool ace_has_next_request(struct request_queue *q)
@@ -1053,12 +1058,12 @@ static int ace_setup(struct ace_device *ace)
                ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ);
 
        /* Now we can hook up the irq handler */
-       if (ace->irq) {
+       if (ace->irq > 0) {
                rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace);
                if (rc) {
                        /* Failure - fall back to polled mode */
                        dev_err(ace->dev, "request_irq failed\n");
-                       ace->irq = 0;
+                       ace->irq = rc;
                }
        }
 
@@ -1110,7 +1115,7 @@ static void ace_teardown(struct ace_device *ace)
 
        tasklet_kill(&ace->fsm_tasklet);
 
-       if (ace->irq)
+       if (ace->irq > 0)
                free_irq(ace->irq, ace);
 
        iounmap(ace->baseaddr);
@@ -1123,11 +1128,6 @@ static int ace_alloc(struct device *dev, int id, resource_size_t physaddr,
        int rc;
        dev_dbg(dev, "ace_alloc(%p)\n", dev);
 
-       if (!physaddr) {
-               rc = -ENODEV;
-               goto err_noreg;
-       }
-
        /* Allocate and initialize the ace device structure */
        ace = kzalloc(sizeof(struct ace_device), GFP_KERNEL);
        if (!ace) {
@@ -1153,7 +1153,6 @@ err_setup:
        dev_set_drvdata(dev, NULL);
        kfree(ace);
 err_alloc:
-err_noreg:
        dev_err(dev, "could not initialize device, err=%i\n", rc);
        return rc;
 }
@@ -1176,10 +1175,11 @@ static void ace_free(struct device *dev)
 
 static int ace_probe(struct platform_device *dev)
 {
-       resource_size_t physaddr = 0;
        int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */
+       resource_size_t physaddr;
+       struct resource *res;
        u32 id = dev->id;
-       int irq = 0;
+       int irq;
        int i;
 
        dev_dbg(&dev->dev, "ace_probe(%p)\n", dev);
@@ -1190,12 +1190,15 @@ static int ace_probe(struct platform_device *dev)
        if (of_find_property(dev->dev.of_node, "8-bit", NULL))
                bus_width = ACE_BUS_WIDTH_8;
 
-       for (i = 0; i < dev->num_resources; i++) {
-               if (dev->resource[i].flags & IORESOURCE_MEM)
-                       physaddr = dev->resource[i].start;
-               if (dev->resource[i].flags & IORESOURCE_IRQ)
-                       irq = dev->resource[i].start;
-       }
+       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -EINVAL;
+
+       physaddr = res->start;
+       if (!physaddr)
+               return -ENODEV;
+
+       irq = platform_get_irq_optional(dev, 0);
 
        /* Call the bus-independent setup code */
        return ace_alloc(&dev->dev, id, physaddr, irq, bus_width);
index 09346ae308eb22f94f7d0dc8cd060b12625c53dd..78cc64b42b30a619fddca092e73c8d8944850db4 100644 (file)
@@ -47,7 +47,7 @@ enum {
 struct intel_tlv {
        u8 type;
        u8 len;
-       u8 val[0];
+       u8 val[];
 } __packed;
 
 struct intel_version_tlv {
index efb088df1276689bb59136fbd0816a3c74903eef..92ecf1a78ec73e4ab382273a9bfab47916385da4 100644 (file)
@@ -227,6 +227,9 @@ static int sysc_wait_softreset(struct sysc *ddata)
        u32 sysc_mask, syss_done, rstval;
        int syss_offset, error = 0;
 
+       if (ddata->cap->regbits->srst_shift < 0)
+               return 0;
+
        syss_offset = ddata->offsets[SYSC_SYSSTATUS];
        sysc_mask = BIT(ddata->cap->regbits->srst_shift);
 
@@ -970,9 +973,15 @@ static int sysc_enable_module(struct device *dev)
                        return error;
                }
        }
-       error = sysc_wait_softreset(ddata);
-       if (error)
-               dev_warn(ddata->dev, "OCP softreset timed out\n");
+       /*
+        * Some modules like i2c and hdq1w have unusable reset status unless
+        * the module reset quirk is enabled. Skip status check on enable.
+        */
+       if (!(ddata->cfg.quirks & SYSC_MODULE_QUIRK_ENA_RESETDONE)) {
+               error = sysc_wait_softreset(ddata);
+               if (error)
+                       dev_warn(ddata->dev, "OCP softreset timed out\n");
+       }
        if (ddata->cfg.quirks & SYSC_QUIRK_OPT_CLKS_IN_RESET)
                sysc_disable_opt_clocks(ddata);
 
@@ -1373,17 +1382,17 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
        SYSC_QUIRK("hdmi", 0, 0, 0x10, -ENODEV, 0x50030200, 0xffffffff,
                   SYSC_QUIRK_OPT_CLKS_NEEDED),
        SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff,
-                  SYSC_MODULE_QUIRK_HDQ1W),
+                  SYSC_MODULE_QUIRK_HDQ1W | SYSC_MODULE_QUIRK_ENA_RESETDONE),
        SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff,
-                  SYSC_MODULE_QUIRK_HDQ1W),
+                  SYSC_MODULE_QUIRK_HDQ1W | SYSC_MODULE_QUIRK_ENA_RESETDONE),
        SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x00000036, 0x000000ff,
-                  SYSC_MODULE_QUIRK_I2C),
+                  SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE),
        SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x0000003c, 0x000000ff,
-                  SYSC_MODULE_QUIRK_I2C),
+                  SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE),
        SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x00000040, 0x000000ff,
-                  SYSC_MODULE_QUIRK_I2C),
+                  SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE),
        SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0,
-                  SYSC_MODULE_QUIRK_I2C),
+                  SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE),
        SYSC_QUIRK("gpu", 0x50000000, 0x14, -ENODEV, -ENODEV, 0x00010201, 0xffffffff, 0),
        SYSC_QUIRK("gpu", 0x50000000, 0xfe00, 0xfe10, -ENODEV, 0x40000000 , 0xffffffff,
                   SYSC_MODULE_QUIRK_SGX),
@@ -2880,7 +2889,7 @@ static int sysc_check_active_timer(struct sysc *ddata)
 
        if ((ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) &&
            (ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE))
-               return -EBUSY;
+               return -ENXIO;
 
        return 0;
 }
index 6bb023de17f1fb086daa1ba5ff122a7e8e5c7d13..35229e5143cacde3771a460f2e1c820579eca025 100644 (file)
@@ -41,6 +41,11 @@ int tpm_read_log_efi(struct tpm_chip *chip)
        log_size = log_tbl->size;
        memunmap(log_tbl);
 
+       if (!log_size) {
+               pr_warn("UEFI TPM log area empty\n");
+               return -EIO;
+       }
+
        log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl) + log_size,
                           MEMREMAP_WB);
        if (!log_tbl) {
index 0b214963539de2ee6977f85344f9b12d3c5dae57..4ed6e660273a4142d015991fde826de1e7598537 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/kernel.h>
+#include <linux/dmi.h>
 #include "tpm.h"
 #include "tpm_tis_core.h"
 
@@ -49,8 +50,8 @@ static inline struct tpm_tis_tcg_phy *to_tpm_tis_tcg_phy(struct tpm_tis_data *da
        return container_of(data, struct tpm_tis_tcg_phy, priv);
 }
 
-static bool interrupts = true;
-module_param(interrupts, bool, 0444);
+static int interrupts = -1;
+module_param(interrupts, int, 0444);
 MODULE_PARM_DESC(interrupts, "Enable interrupts");
 
 static bool itpm;
@@ -63,6 +64,28 @@ module_param(force, bool, 0444);
 MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry");
 #endif
 
+static int tpm_tis_disable_irq(const struct dmi_system_id *d)
+{
+       if (interrupts == -1) {
+               pr_notice("tpm_tis: %s detected: disabling interrupts.\n", d->ident);
+               interrupts = 0;
+       }
+
+       return 0;
+}
+
+static const struct dmi_system_id tpm_tis_dmi_table[] = {
+       {
+               .callback = tpm_tis_disable_irq,
+               .ident = "ThinkPad T490s",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T490s"),
+               },
+       },
+       {}
+};
+
 #if defined(CONFIG_PNP) && defined(CONFIG_ACPI)
 static int has_hid(struct acpi_device *dev, const char *hid)
 {
@@ -192,6 +215,8 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info)
        int irq = -1;
        int rc;
 
+       dmi_check_system(tpm_tis_dmi_table);
+
        rc = check_acpi_tpm2(dev);
        if (rc)
                return rc;
index a2da8f768b94c058f124d35107a5c033cc8c5a9c..1836cc56e357b7b428808e5a0d32163e68f2e491 100644 (file)
@@ -435,12 +435,12 @@ static struct port_buffer *alloc_buf(struct virtio_device *vdev, size_t buf_size
                /*
                 * Allocate DMA memory from ancestor. When a virtio
                 * device is created by remoteproc, the DMA memory is
-                * associated with the grandparent device:
-                * vdev => rproc => platform-dev.
+                * associated with the parent device:
+                * virtioY => remoteprocX#vdevYbuffer.
                 */
-               if (!vdev->dev.parent || !vdev->dev.parent->parent)
+               buf->dev = vdev->dev.parent;
+               if (!buf->dev)
                        goto free_buf;
-               buf->dev = vdev->dev.parent->parent;
 
                /* Increase device refcnt to avoid freeing it */
                get_device(buf->dev);
index 0de0be0cf5484ce12124cdbf5a9f86166e2b5a22..f358ad9072990cf1dbdbeb5012ea1ae33c47f077 100644 (file)
@@ -443,9 +443,9 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
        hws[IMX8MM_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", base + 0x9880, 24, 1, imx8mm_a53_core_sels, ARRAY_SIZE(imx8mm_a53_core_sels));
 
        /* BUS */
-       hws[IMX8MM_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi",  imx8mm_main_axi_sels, base + 0x8800);
+       hws[IMX8MM_CLK_MAIN_AXI] = imx8m_clk_hw_composite_bus_critical("main_axi",  imx8mm_main_axi_sels, base + 0x8800);
        hws[IMX8MM_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mm_enet_axi_sels, base + 0x8880);
-       hws[IMX8MM_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_critical("nand_usdhc_bus", imx8mm_nand_usdhc_sels, base + 0x8900);
+       hws[IMX8MM_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_bus_critical("nand_usdhc_bus", imx8mm_nand_usdhc_sels, base + 0x8900);
        hws[IMX8MM_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mm_vpu_bus_sels, base + 0x8980);
        hws[IMX8MM_CLK_DISP_AXI] = imx8m_clk_hw_composite_bus("disp_axi", imx8mm_disp_axi_sels, base + 0x8a00);
        hws[IMX8MM_CLK_DISP_APB] = imx8m_clk_hw_composite_bus("disp_apb", imx8mm_disp_apb_sels, base + 0x8a80);
@@ -453,11 +453,11 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
        hws[IMX8MM_CLK_USB_BUS] = imx8m_clk_hw_composite_bus("usb_bus", imx8mm_usb_bus_sels, base + 0x8b80);
        hws[IMX8MM_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mm_gpu_axi_sels, base + 0x8c00);
        hws[IMX8MM_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mm_gpu_ahb_sels, base + 0x8c80);
-       hws[IMX8MM_CLK_NOC] = imx8m_clk_hw_composite_critical("noc", imx8mm_noc_sels, base + 0x8d00);
-       hws[IMX8MM_CLK_NOC_APB] = imx8m_clk_hw_composite_critical("noc_apb", imx8mm_noc_apb_sels, base + 0x8d80);
+       hws[IMX8MM_CLK_NOC] = imx8m_clk_hw_composite_bus_critical("noc", imx8mm_noc_sels, base + 0x8d00);
+       hws[IMX8MM_CLK_NOC_APB] = imx8m_clk_hw_composite_bus_critical("noc_apb", imx8mm_noc_apb_sels, base + 0x8d80);
 
        /* AHB */
-       hws[IMX8MM_CLK_AHB] = imx8m_clk_hw_composite_critical("ahb", imx8mm_ahb_sels, base + 0x9000);
+       hws[IMX8MM_CLK_AHB] = imx8m_clk_hw_composite_bus_critical("ahb", imx8mm_ahb_sels, base + 0x9000);
        hws[IMX8MM_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mm_audio_ahb_sels, base + 0x9100);
 
        /* IPG */
index e984de543f0bcd9b3a091718485522e27e76325b..f3c5e6cf55dd4083961fce83a6ca3e54a017d375 100644 (file)
@@ -431,7 +431,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
        hws[IMX8MN_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", base + 0x9880, 24, 1, imx8mn_a53_core_sels, ARRAY_SIZE(imx8mn_a53_core_sels));
 
        /* BUS */
-       hws[IMX8MN_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mn_main_axi_sels, base + 0x8800);
+       hws[IMX8MN_CLK_MAIN_AXI] = imx8m_clk_hw_composite_bus_critical("main_axi", imx8mn_main_axi_sels, base + 0x8800);
        hws[IMX8MN_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mn_enet_axi_sels, base + 0x8880);
        hws[IMX8MN_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_bus("nand_usdhc_bus", imx8mn_nand_usdhc_sels, base + 0x8900);
        hws[IMX8MN_CLK_DISP_AXI] = imx8m_clk_hw_composite_bus("disp_axi", imx8mn_disp_axi_sels, base + 0x8a00);
@@ -439,9 +439,9 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
        hws[IMX8MN_CLK_USB_BUS] = imx8m_clk_hw_composite_bus("usb_bus", imx8mn_usb_bus_sels, base + 0x8b80);
        hws[IMX8MN_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mn_gpu_axi_sels, base + 0x8c00);
        hws[IMX8MN_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mn_gpu_ahb_sels, base + 0x8c80);
-       hws[IMX8MN_CLK_NOC] = imx8m_clk_hw_composite_critical("noc", imx8mn_noc_sels, base + 0x8d00);
+       hws[IMX8MN_CLK_NOC] = imx8m_clk_hw_composite_bus_critical("noc", imx8mn_noc_sels, base + 0x8d00);
 
-       hws[IMX8MN_CLK_AHB] = imx8m_clk_hw_composite_critical("ahb", imx8mn_ahb_sels, base + 0x9000);
+       hws[IMX8MN_CLK_AHB] = imx8m_clk_hw_composite_bus_critical("ahb", imx8mn_ahb_sels, base + 0x9000);
        hws[IMX8MN_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mn_audio_ahb_sels, base + 0x9100);
        hws[IMX8MN_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb", base + 0x9080, 0, 1);
        hws[IMX8MN_CLK_IPG_AUDIO_ROOT] = imx_clk_hw_divider2("ipg_audio_root", "audio_ahb", base + 0x9180, 0, 1);
index 12ce4770f702a41a849b848897f2f4219d6492ff..48e212477f52a34d860f069d3ca697851c56d678 100644 (file)
@@ -557,9 +557,9 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
        /* CORE SEL */
        hws[IMX8MP_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", ccm_base + 0x9880, 24, 1, imx8mp_a53_core_sels, ARRAY_SIZE(imx8mp_a53_core_sels));
 
-       hws[IMX8MP_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mp_main_axi_sels, ccm_base + 0x8800);
+       hws[IMX8MP_CLK_MAIN_AXI] = imx8m_clk_hw_composite_bus_critical("main_axi", imx8mp_main_axi_sels, ccm_base + 0x8800);
        hws[IMX8MP_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mp_enet_axi_sels, ccm_base + 0x8880);
-       hws[IMX8MP_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_critical("nand_usdhc_bus", imx8mp_nand_usdhc_sels, ccm_base + 0x8900);
+       hws[IMX8MP_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_bus_critical("nand_usdhc_bus", imx8mp_nand_usdhc_sels, ccm_base + 0x8900);
        hws[IMX8MP_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mp_vpu_bus_sels, ccm_base + 0x8980);
        hws[IMX8MP_CLK_MEDIA_AXI] = imx8m_clk_hw_composite_bus("media_axi", imx8mp_media_axi_sels, ccm_base + 0x8a00);
        hws[IMX8MP_CLK_MEDIA_APB] = imx8m_clk_hw_composite_bus("media_apb", imx8mp_media_apb_sels, ccm_base + 0x8a80);
@@ -567,12 +567,12 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
        hws[IMX8MP_CLK_HDMI_AXI] = imx8m_clk_hw_composite_bus("hdmi_axi", imx8mp_media_axi_sels, ccm_base + 0x8b80);
        hws[IMX8MP_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mp_gpu_axi_sels, ccm_base + 0x8c00);
        hws[IMX8MP_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mp_gpu_ahb_sels, ccm_base + 0x8c80);
-       hws[IMX8MP_CLK_NOC] = imx8m_clk_hw_composite_critical("noc", imx8mp_noc_sels, ccm_base + 0x8d00);
-       hws[IMX8MP_CLK_NOC_IO] = imx8m_clk_hw_composite_critical("noc_io", imx8mp_noc_io_sels, ccm_base + 0x8d80);
+       hws[IMX8MP_CLK_NOC] = imx8m_clk_hw_composite_bus_critical("noc", imx8mp_noc_sels, ccm_base + 0x8d00);
+       hws[IMX8MP_CLK_NOC_IO] = imx8m_clk_hw_composite_bus_critical("noc_io", imx8mp_noc_io_sels, ccm_base + 0x8d80);
        hws[IMX8MP_CLK_ML_AXI] = imx8m_clk_hw_composite_bus("ml_axi", imx8mp_ml_axi_sels, ccm_base + 0x8e00);
        hws[IMX8MP_CLK_ML_AHB] = imx8m_clk_hw_composite_bus("ml_ahb", imx8mp_ml_ahb_sels, ccm_base + 0x8e80);
 
-       hws[IMX8MP_CLK_AHB] = imx8m_clk_hw_composite_critical("ahb_root", imx8mp_ahb_sels, ccm_base + 0x9000);
+       hws[IMX8MP_CLK_AHB] = imx8m_clk_hw_composite_bus_critical("ahb_root", imx8mp_ahb_sels, ccm_base + 0x9000);
        hws[IMX8MP_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mp_audio_ahb_sels, ccm_base + 0x9100);
        hws[IMX8MP_CLK_MIPI_DSI_ESC_RX] = imx8m_clk_hw_composite_bus("mipi_dsi_esc_rx", imx8mp_mipi_dsi_esc_rx_sels, ccm_base + 0x9200);
 
index 8265d1d48af4231cc763b250aa93d51728533b64..06292d4a98ff748defe7c2b01aec1971b57cd617 100644 (file)
@@ -431,7 +431,7 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
        hws[IMX8MQ_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", base + 0x9880, 24, 1, imx8mq_a53_core_sels, ARRAY_SIZE(imx8mq_a53_core_sels));
 
        /* BUS */
-       hws[IMX8MQ_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mq_main_axi_sels, base + 0x8800);
+       hws[IMX8MQ_CLK_MAIN_AXI] = imx8m_clk_hw_composite_bus_critical("main_axi", imx8mq_main_axi_sels, base + 0x8800);
        hws[IMX8MQ_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mq_enet_axi_sels, base + 0x8880);
        hws[IMX8MQ_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_bus("nand_usdhc_bus", imx8mq_nand_usdhc_sels, base + 0x8900);
        hws[IMX8MQ_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mq_vpu_bus_sels, base + 0x8980);
@@ -441,12 +441,12 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
        hws[IMX8MQ_CLK_USB_BUS] = imx8m_clk_hw_composite_bus("usb_bus", imx8mq_usb_bus_sels, base + 0x8b80);
        hws[IMX8MQ_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mq_gpu_axi_sels, base + 0x8c00);
        hws[IMX8MQ_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mq_gpu_ahb_sels, base + 0x8c80);
-       hws[IMX8MQ_CLK_NOC] = imx8m_clk_hw_composite_critical("noc", imx8mq_noc_sels, base + 0x8d00);
-       hws[IMX8MQ_CLK_NOC_APB] = imx8m_clk_hw_composite_critical("noc_apb", imx8mq_noc_apb_sels, base + 0x8d80);
+       hws[IMX8MQ_CLK_NOC] = imx8m_clk_hw_composite_bus_critical("noc", imx8mq_noc_sels, base + 0x8d00);
+       hws[IMX8MQ_CLK_NOC_APB] = imx8m_clk_hw_composite_bus_critical("noc_apb", imx8mq_noc_apb_sels, base + 0x8d80);
 
        /* AHB */
        /* AHB clock is used by the AHB bus therefore marked as critical */
-       hws[IMX8MQ_CLK_AHB] = imx8m_clk_hw_composite_critical("ahb", imx8mq_ahb_sels, base + 0x9000);
+       hws[IMX8MQ_CLK_AHB] = imx8m_clk_hw_composite_bus_critical("ahb", imx8mq_ahb_sels, base + 0x9000);
        hws[IMX8MQ_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mq_audio_ahb_sels, base + 0x9100);
 
        /* IPG */
index 3b796b3da2498c36a65494fbbc01dd8f85127724..1d7be0c86538a54e1774260ef90d8d59d548c183 100644 (file)
@@ -549,6 +549,11 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
                        IMX_COMPOSITE_BUS, \
                        CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE)
 
+#define imx8m_clk_hw_composite_bus_critical(name, parent_names, reg)   \
+       imx8m_clk_hw_composite_flags(name, parent_names, ARRAY_SIZE(parent_names), reg, \
+                       IMX_COMPOSITE_BUS, \
+                       CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE | CLK_IS_CRITICAL)
+
 #define imx8m_clk_hw_composite_core(name, parent_names, reg)   \
        imx8m_clk_hw_composite_flags(name, parent_names, \
                        ARRAY_SIZE(parent_names), reg, \
index c4a39604cffdd32a5904f21a429b0dee378610e3..e365312da54ece08098293b1a831c803415db814 100644 (file)
@@ -26,7 +26,10 @@ struct clk_regmap {
        void            *data;
 };
 
-#define to_clk_regmap(_hw) container_of(_hw, struct clk_regmap, hw)
+static inline struct clk_regmap *to_clk_regmap(struct clk_hw *hw)
+{
+       return container_of(hw, struct clk_regmap, hw);
+}
 
 /**
  * struct clk_regmap_gate_data - regmap backed gate specific data
index 6cfc1bccb25538a32e9760dbbdac4b4e02280275..14ec659a3a77f955f0c425758a494442a0674566 100644 (file)
@@ -24,7 +24,11 @@ struct clk_regmap {
        unsigned int enable_mask;
        bool enable_is_inverted;
 };
-#define to_clk_regmap(_hw) container_of(_hw, struct clk_regmap, hw)
+
+static inline struct clk_regmap *to_clk_regmap(struct clk_hw *hw)
+{
+       return container_of(hw, struct clk_regmap, hw);
+}
 
 int clk_is_enabled_regmap(struct clk_hw *hw);
 int clk_enable_regmap(struct clk_hw *hw);
index e27771df8e2390c9cc1bc1113cffb2caf78d00f0..a60aee1a1a29150a94fd4a43d69f4154023baab4 100644 (file)
@@ -368,7 +368,7 @@ static const struct regmap_config ti_eqep_regmap32_config = {
        .reg_bits = 32,
        .val_bits = 32,
        .reg_stride = 4,
-       .max_register = 0x24,
+       .max_register = QUPRD,
 };
 
 static const struct regmap_config ti_eqep_regmap16_config = {
@@ -376,7 +376,7 @@ static const struct regmap_config ti_eqep_regmap16_config = {
        .reg_bits = 16,
        .val_bits = 16,
        .reg_stride = 2,
-       .max_register = 0x1e,
+       .max_register = QCPRDLAT,
 };
 
 static int ti_eqep_probe(struct platform_device *pdev)
index 2c7171e0b001027a7364bd9b84af9444186710f8..85de313ddec29cdc33824ec98964abe2bae8c962 100644 (file)
@@ -71,6 +71,7 @@ config CPU_FREQ_DEFAULT_GOV_USERSPACE
 
 config CPU_FREQ_DEFAULT_GOV_ONDEMAND
        bool "ondemand"
+       depends on !(X86_INTEL_PSTATE && SMP)
        select CPU_FREQ_GOV_ONDEMAND
        select CPU_FREQ_GOV_PERFORMANCE
        help
@@ -83,6 +84,7 @@ config CPU_FREQ_DEFAULT_GOV_ONDEMAND
 
 config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
        bool "conservative"
+       depends on !(X86_INTEL_PSTATE && SMP)
        select CPU_FREQ_GOV_CONSERVATIVE
        select CPU_FREQ_GOV_PERFORMANCE
        help
index f4b60663efe65335b0501db403a6315a43227566..1e7e3f2ff09f0d6236491bb2f380a2b3ad2d6273 100644 (file)
@@ -1907,6 +1907,18 @@ void cpufreq_resume(void)
        }
 }
 
+/**
+ * cpufreq_driver_test_flags - Test cpufreq driver's flags against given ones.
+ * @flags: Flags to test against the current cpufreq driver's flags.
+ *
+ * Assumes that the driver is there, so callers must ensure that this is the
+ * case.
+ */
+bool cpufreq_driver_test_flags(u16 flags)
+{
+       return !!(cpufreq_driver->flags & flags);
+}
+
 /**
  *     cpufreq_get_current_driver - return current driver's name
  *
@@ -2187,7 +2199,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
         * exactly same freq is called again and so we can save on few function
         * calls.
         */
-       if (target_freq == policy->cur)
+       if (target_freq == policy->cur &&
+           !(cpufreq_driver->flags & CPUFREQ_NEED_UPDATE_LIMITS))
                return 0;
 
        /* Save last value to restore later on errors */
@@ -2241,7 +2254,7 @@ static int cpufreq_init_governor(struct cpufreq_policy *policy)
                return -EINVAL;
 
        /* Platform doesn't want dynamic frequency switching ? */
-       if (policy->governor->dynamic_switching &&
+       if (policy->governor->flags & CPUFREQ_GOV_DYNAMIC_SWITCHING &&
            cpufreq_driver->flags & CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING) {
                struct cpufreq_governor *gov = cpufreq_fallback_governor();
 
@@ -2267,6 +2280,8 @@ static int cpufreq_init_governor(struct cpufreq_policy *policy)
                }
        }
 
+       policy->strict_target = !!(policy->governor->flags & CPUFREQ_GOV_STRICT_TARGET);
+
        return 0;
 }
 
index c56773c257579fa177866a88c3159964373f3f69..bab8e6140377142d8527ba0ea70ea8bed867cbd7 100644 (file)
@@ -156,7 +156,7 @@ void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy);
 #define CPUFREQ_DBS_GOVERNOR_INITIALIZER(_name_)                       \
        {                                                               \
                .name = _name_,                                         \
-               .dynamic_switching = true,                              \
+               .flags = CPUFREQ_GOV_DYNAMIC_SWITCHING,                 \
                .owner = THIS_MODULE,                                   \
                .init = cpufreq_dbs_governor_init,                      \
                .exit = cpufreq_dbs_governor_exit,                      \
index 71c1d9aba77271957dbb3f4bccacbba9c20674d3..addd93f2a4202bb832053186ff8d9faf077c8f91 100644 (file)
@@ -20,6 +20,7 @@ static void cpufreq_gov_performance_limits(struct cpufreq_policy *policy)
 static struct cpufreq_governor cpufreq_gov_performance = {
        .name           = "performance",
        .owner          = THIS_MODULE,
+       .flags          = CPUFREQ_GOV_STRICT_TARGET,
        .limits         = cpufreq_gov_performance_limits,
 };
 
index 7749522355b5946914ac8099d58789a75729c1a2..8d830d860e9129baa02aaa6f384c433160a26f86 100644 (file)
@@ -21,6 +21,7 @@ static struct cpufreq_governor cpufreq_gov_powersave = {
        .name           = "powersave",
        .limits         = cpufreq_gov_powersave_limits,
        .owner          = THIS_MODULE,
+       .flags          = CPUFREQ_GOV_STRICT_TARGET,
 };
 
 MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
index 776a58bab0ffd5f67266fe8ef703b6a867d0ef57..ab93bce8ae77d9573319f793961d4cb8b6fced8d 100644 (file)
@@ -223,7 +223,6 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
        case EPS_BRAND_C3:
                pr_cont("C3\n");
                return -ENODEV;
-               break;
        }
        /* Enable Enhanced PowerSaver */
        rdmsrl(MSR_IA32_MISC_ENABLE, val);
index 3c1455518738f80d5f1e28e06ebc07273e656a50..36a3ccfe6d3d1cce010b0e08f74d82a72f6f36f0 100644 (file)
@@ -2527,7 +2527,7 @@ static void intel_cpufreq_trace(struct cpudata *cpu, unsigned int trace_type, in
 }
 
 static void intel_cpufreq_adjust_hwp(struct cpudata *cpu, u32 target_pstate,
-                                    bool fast_switch)
+                                    bool strict, bool fast_switch)
 {
        u64 prev = READ_ONCE(cpu->hwp_req_cached), value = prev;
 
@@ -2539,7 +2539,7 @@ static void intel_cpufreq_adjust_hwp(struct cpudata *cpu, u32 target_pstate,
         * field in it, so opportunistically update the max too if needed.
         */
        value &= ~HWP_MAX_PERF(~0L);
-       value |= HWP_MAX_PERF(cpu->max_perf_ratio);
+       value |= HWP_MAX_PERF(strict ? target_pstate : cpu->max_perf_ratio);
 
        if (value == prev)
                return;
@@ -2562,20 +2562,20 @@ static void intel_cpufreq_adjust_perf_ctl(struct cpudata *cpu,
                              pstate_funcs.get_val(cpu, target_pstate));
 }
 
-static int intel_cpufreq_update_pstate(struct cpudata *cpu, int target_pstate,
-                                      bool fast_switch)
+static int intel_cpufreq_update_pstate(struct cpufreq_policy *policy,
+                                      int target_pstate, bool fast_switch)
 {
+       struct cpudata *cpu = all_cpu_data[policy->cpu];
        int old_pstate = cpu->pstate.current_pstate;
 
        target_pstate = intel_pstate_prepare_request(cpu, target_pstate);
-       if (target_pstate != old_pstate) {
+       if (hwp_active) {
+               intel_cpufreq_adjust_hwp(cpu, target_pstate,
+                                        policy->strict_target, fast_switch);
+               cpu->pstate.current_pstate = target_pstate;
+       } else if (target_pstate != old_pstate) {
+               intel_cpufreq_adjust_perf_ctl(cpu, target_pstate, fast_switch);
                cpu->pstate.current_pstate = target_pstate;
-               if (hwp_active)
-                       intel_cpufreq_adjust_hwp(cpu, target_pstate,
-                                                fast_switch);
-               else
-                       intel_cpufreq_adjust_perf_ctl(cpu, target_pstate,
-                                                     fast_switch);
        }
 
        intel_cpufreq_trace(cpu, fast_switch ? INTEL_PSTATE_TRACE_FAST_SWITCH :
@@ -2611,7 +2611,7 @@ static int intel_cpufreq_target(struct cpufreq_policy *policy,
                break;
        }
 
-       target_pstate = intel_cpufreq_update_pstate(cpu, target_pstate, false);
+       target_pstate = intel_cpufreq_update_pstate(policy, target_pstate, false);
 
        freqs.new = target_pstate * cpu->pstate.scaling;
 
@@ -2630,7 +2630,7 @@ static unsigned int intel_cpufreq_fast_switch(struct cpufreq_policy *policy,
 
        target_pstate = DIV_ROUND_UP(target_freq, cpu->pstate.scaling);
 
-       target_pstate = intel_cpufreq_update_pstate(cpu, target_pstate, true);
+       target_pstate = intel_cpufreq_update_pstate(policy, target_pstate, true);
 
        return target_pstate * cpu->pstate.scaling;
 }
@@ -3032,6 +3032,7 @@ static int __init intel_pstate_init(void)
                        hwp_mode_bdw = id->driver_data;
                        intel_pstate.attr = hwp_cpufreq_attrs;
                        intel_cpufreq.attr = hwp_cpufreq_attrs;
+                       intel_cpufreq.flags |= CPUFREQ_NEED_UPDATE_LIMITS;
                        if (!default_driver)
                                default_driver = &intel_pstate;
 
index 123fb006810d5da028c926b3a68da2b324095500..182a4dbca0952c7cc6a7db2e1d5940555000c926 100644 (file)
@@ -593,7 +593,6 @@ static void longhaul_setup_voltagescaling(void)
                break;
        default:
                return;
-               break;
        }
        if (min_vid_speed >= highest_speed)
                return;
index e855e8612a67d4ea3b094e2a56cec4c29c7a41d4..8286205c7165dc61a490ecd52df0e9bed6b8ffd6 100644 (file)
@@ -8,6 +8,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/clk-provider.h>
 #include <linux/cpu.h>
 #include <linux/cpufreq.h>
 #include <linux/cpumask.h>
@@ -228,15 +229,22 @@ static struct cpufreq_driver scmi_cpufreq_driver = {
 static int scmi_cpufreq_probe(struct scmi_device *sdev)
 {
        int ret;
+       struct device *dev = &sdev->dev;
 
        handle = sdev->handle;
 
        if (!handle || !handle->perf_ops)
                return -ENODEV;
 
+#ifdef CONFIG_COMMON_CLK
+       /* dummy clock provider as needed by OPP if clocks property is used */
+       if (of_find_property(dev->of_node, "#clock-cells", NULL))
+               devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, NULL);
+#endif
+
        ret = cpufreq_register_driver(&scmi_cpufreq_driver);
        if (ret) {
-               dev_err(&sdev->dev, "%s: registering cpufreq failed, err: %d\n",
+               dev_err(dev, "%s: registering cpufreq failed, err: %d\n",
                        __func__, ret);
        }
 
index a13a2d1e444ed6e62ff357927f1912b6d0408131..0b66df4ed513408f1b28e2ca5a5094c41a885717 100644 (file)
@@ -240,7 +240,7 @@ unsigned int speedstep_get_frequency(enum speedstep_processor processor)
                return pentium3_get_frequency(processor);
        default:
                return 0;
-       };
+       }
        return 0;
 }
 EXPORT_SYMBOL_GPL(speedstep_get_frequency);
index 4b4079f515596a3ed7132d5f973c390b873116c1..7eb2c56c65dee968794c7f6b73708f35148374ce 100644 (file)
@@ -42,6 +42,8 @@ static const struct tegra186_cpufreq_cluster_info tegra186_clusters[] = {
 struct tegra186_cpufreq_cluster {
        const struct tegra186_cpufreq_cluster_info *info;
        struct cpufreq_frequency_table *table;
+       u32 ref_clk_khz;
+       u32 div;
 };
 
 struct tegra186_cpufreq_data {
@@ -94,7 +96,7 @@ static int tegra186_cpufreq_set_target(struct cpufreq_policy *policy,
 
 static unsigned int tegra186_cpufreq_get(unsigned int cpu)
 {
-       struct cpufreq_frequency_table *tbl;
+       struct tegra186_cpufreq_data *data = cpufreq_get_driver_data();
        struct cpufreq_policy *policy;
        void __iomem *edvd_reg;
        unsigned int i, freq = 0;
@@ -104,17 +106,23 @@ static unsigned int tegra186_cpufreq_get(unsigned int cpu)
        if (!policy)
                return 0;
 
-       tbl = policy->freq_table;
        edvd_reg = policy->driver_data;
        ndiv = readl(edvd_reg) & EDVD_CORE_VOLT_FREQ_F_MASK;
 
-       for (i = 0; tbl[i].frequency != CPUFREQ_TABLE_END; i++) {
-               if ((tbl[i].driver_data & EDVD_CORE_VOLT_FREQ_F_MASK) == ndiv) {
-                       freq = tbl[i].frequency;
-                       break;
+       for (i = 0; i < data->num_clusters; i++) {
+               struct tegra186_cpufreq_cluster *cluster = &data->clusters[i];
+               int core;
+
+               for (core = 0; core < ARRAY_SIZE(cluster->info->cpus); core++) {
+                       if (cluster->info->cpus[core] != policy->cpu)
+                               continue;
+
+                       freq = (cluster->ref_clk_khz * ndiv) / cluster->div;
+                       goto out;
                }
        }
 
+out:
        cpufreq_cpu_put(policy);
 
        return freq;
@@ -133,7 +141,7 @@ static struct cpufreq_driver tegra186_cpufreq_driver = {
 
 static struct cpufreq_frequency_table *init_vhint_table(
        struct platform_device *pdev, struct tegra_bpmp *bpmp,
-       unsigned int cluster_id)
+       struct tegra186_cpufreq_cluster *cluster)
 {
        struct cpufreq_frequency_table *table;
        struct mrq_cpu_vhint_request req;
@@ -152,7 +160,7 @@ static struct cpufreq_frequency_table *init_vhint_table(
 
        memset(&req, 0, sizeof(req));
        req.addr = phys;
-       req.cluster_id = cluster_id;
+       req.cluster_id = cluster->info->bpmp_cluster_id;
 
        memset(&msg, 0, sizeof(msg));
        msg.mrq = MRQ_CPU_VHINT;
@@ -185,6 +193,9 @@ static struct cpufreq_frequency_table *init_vhint_table(
                goto free;
        }
 
+       cluster->ref_clk_khz = data->ref_clk_hz / 1000;
+       cluster->div = data->pdiv * data->mdiv;
+
        for (i = data->vfloor, j = 0; i <= data->vceil; i++) {
                struct cpufreq_frequency_table *point;
                u16 ndiv = data->ndiv[i];
@@ -202,8 +213,7 @@ static struct cpufreq_frequency_table *init_vhint_table(
 
                point = &table[j++];
                point->driver_data = edvd_val;
-               point->frequency = data->ref_clk_hz * ndiv / data->pdiv /
-                       data->mdiv / 1000;
+               point->frequency = (cluster->ref_clk_khz * ndiv) / cluster->div;
        }
 
        table[j].frequency = CPUFREQ_TABLE_END;
@@ -245,8 +255,7 @@ static int tegra186_cpufreq_probe(struct platform_device *pdev)
                struct tegra186_cpufreq_cluster *cluster = &data->clusters[i];
 
                cluster->info = &tegra186_clusters[i];
-               cluster->table = init_vhint_table(
-                       pdev, bpmp, cluster->info->bpmp_cluster_id);
+               cluster->table = init_vhint_table(pdev, bpmp, cluster);
                if (IS_ERR(cluster->table)) {
                        err = PTR_ERR(cluster->table);
                        goto put_bpmp;
index e8956706a2917a2bc2c128790508b7177699f899..191966dc8d023b603c1ef7757e70f08a620b53c0 100644 (file)
@@ -189,7 +189,7 @@ static int tegra_cpuidle_state_enter(struct cpuidle_device *dev,
        }
 
        local_fiq_disable();
-       tegra_pm_set_cpu_in_lp2();
+       RCU_NONIDLE(tegra_pm_set_cpu_in_lp2());
        cpu_pm_enter();
 
        switch (index) {
@@ -207,7 +207,7 @@ static int tegra_cpuidle_state_enter(struct cpuidle_device *dev,
        }
 
        cpu_pm_exit();
-       tegra_pm_clear_cpu_in_lp2();
+       RCU_NONIDLE(tegra_pm_clear_cpu_in_lp2());
        local_fiq_enable();
 
        return err ?: index;
index fa2f1b4fad7b4236214ed8c429fdb4dd8a461ea9..a94bf28f858a7f0fb513534c7190d1274d232348 100644 (file)
@@ -7,7 +7,7 @@
  *
  * This file add support for MD5 and SHA1/SHA224/SHA256/SHA384/SHA512.
  *
- * You could find the datasheet in Documentation/arm/sunxi/README
+ * You could find the datasheet in Documentation/arm/sunxi.rst
  */
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
index 78503006949c8fb8647ea1c3035dd1f95d52e416..cfde9ee4356b138260ae51f110a991febb3d4b30 100644 (file)
@@ -7,7 +7,7 @@
  *
  * This file handle the PRNG
  *
- * You could find a link for the datasheet in Documentation/arm/sunxi/README
+ * You could find a link for the datasheet in Documentation/arm/sunxi.rst
  */
 #include "sun8i-ce.h"
 #include <linux/dma-mapping.h>
index 654328160d19b2bef593803f945a82fa7928b8fb..5b7af4498bd5a6f937a5ae15caced491237f8c8e 100644 (file)
@@ -7,7 +7,7 @@
  *
  * This file handle the TRNG
  *
- * You could find a link for the datasheet in Documentation/arm/sunxi/README
+ * You could find a link for the datasheet in Documentation/arm/sunxi.rst
  */
 #include "sun8i-ce.h"
 #include <linux/dma-mapping.h>
index 567428e10b7b1fe06ba4aed46858a1104448d41a..d2834c2cfa10deaaafc4acfdc25043840597ccec 100644 (file)
@@ -50,7 +50,6 @@ config DEV_DAX_HMEM
          Say M if unsure.
 
 config DEV_DAX_HMEM_DEVICES
-       depends on NUMA_KEEP_MEMINFO # for phys_to_target_node()
        depends on DEV_DAX_HMEM && DAX=y
        def_bool y
 
index 518a1437862ac2212f2dbe7795add9740b6e377a..90284ffda58a7b43e45d4617ab8cdde1a1411a80 100644 (file)
@@ -318,24 +318,6 @@ config INTEL_IOP_ADMA
        help
          Enable support for the Intel(R) IOP Series RAID engines.
 
-config INTEL_MIC_X100_DMA
-       tristate "Intel MIC X100 DMA Driver"
-       depends on 64BIT && X86 && INTEL_MIC_BUS
-       select DMA_ENGINE
-       help
-         This enables DMA support for the Intel Many Integrated Core
-         (MIC) family of PCIe form factor coprocessor X100 devices that
-         run a 64 bit Linux OS. This driver will be used by both MIC
-         host and card drivers.
-
-         If you are building host kernel with a MIC device or a card
-         kernel for a MIC device, then say M (recommended) or Y, else
-         say N. If unsure say N.
-
-         More information about the Intel MIC family as well as the Linux
-         OS and tools for MIC to use with this driver are available from
-         <http://software.intel.com/en-us/mic-developer>.
-
 config K3_DMA
        tristate "Hisilicon K3 DMA support"
        depends on ARCH_HI3xxx || ARCH_HISI || COMPILE_TEST
index e60f81331d4c74c16292d03297778dd8a0ff28a9..948a8da05f8b6829c498d9961b9c3e8dfc665586 100644 (file)
@@ -44,7 +44,6 @@ obj-$(CONFIG_INTEL_IDMA64) += idma64.o
 obj-$(CONFIG_INTEL_IOATDMA) += ioat/
 obj-$(CONFIG_INTEL_IDXD) += idxd/
 obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
-obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o
 obj-$(CONFIG_K3_DMA) += k3dma.o
 obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o
 obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o
index 7974fa0400d8c2ab3fecfacabc86fbb4353334f8..962cbb5e5f7fcb630806ec7abb75be479ffa9899 100644 (file)
@@ -1039,16 +1039,15 @@ static int get_dma_id(struct dma_device *device)
 static int __dma_async_device_channel_register(struct dma_device *device,
                                               struct dma_chan *chan)
 {
-       int rc = 0;
+       int rc;
 
        chan->local = alloc_percpu(typeof(*chan->local));
        if (!chan->local)
-               goto err_out;
+               return -ENOMEM;
        chan->dev = kzalloc(sizeof(*chan->dev), GFP_KERNEL);
        if (!chan->dev) {
-               free_percpu(chan->local);
-               chan->local = NULL;
-               goto err_out;
+               rc = -ENOMEM;
+               goto err_free_local;
        }
 
        /*
@@ -1061,7 +1060,8 @@ static int __dma_async_device_channel_register(struct dma_device *device,
        if (chan->chan_id < 0) {
                pr_err("%s: unable to alloc ida for chan: %d\n",
                       __func__, chan->chan_id);
-               goto err_out;
+               rc = chan->chan_id;
+               goto err_free_dev;
        }
 
        chan->dev->device.class = &dma_devclass;
@@ -1082,9 +1082,10 @@ static int __dma_async_device_channel_register(struct dma_device *device,
        mutex_lock(&device->chan_mutex);
        ida_free(&device->chan_ida, chan->chan_id);
        mutex_unlock(&device->chan_mutex);
- err_out:
-       free_percpu(chan->local);
+ err_free_dev:
        kfree(chan->dev);
+ err_free_local:
+       free_percpu(chan->local);
        return rc;
 }
 
index 200b9109cacf21e44b58b18cc36eb60cb04965c3..663344987e3f31129359a2ce01602dae904bbe64 100644 (file)
@@ -271,7 +271,7 @@ int idxd_wq_map_portal(struct idxd_wq *wq)
        resource_size_t start;
 
        start = pci_resource_start(pdev, IDXD_WQ_BAR);
-       start = start + wq->id * IDXD_PORTAL_SIZE;
+       start += idxd_get_wq_portal_full_offset(wq->id, IDXD_PORTAL_LIMITED);
 
        wq->dportal = devm_ioremap(dev, start, IDXD_PORTAL_SIZE);
        if (!wq->dportal)
@@ -295,7 +295,7 @@ void idxd_wq_disable_cleanup(struct idxd_wq *wq)
        int i, wq_offset;
 
        lockdep_assert_held(&idxd->dev_lock);
-       memset(&wq->wqcfg, 0, sizeof(wq->wqcfg));
+       memset(wq->wqcfg, 0, idxd->wqcfg_size);
        wq->type = IDXD_WQT_NONE;
        wq->size = 0;
        wq->group = NULL;
@@ -304,8 +304,8 @@ void idxd_wq_disable_cleanup(struct idxd_wq *wq)
        clear_bit(WQ_FLAG_DEDICATED, &wq->flags);
        memset(wq->name, 0, WQ_NAME_SIZE);
 
-       for (i = 0; i < 8; i++) {
-               wq_offset = idxd->wqcfg_offset + wq->id * 32 + i * sizeof(u32);
+       for (i = 0; i < WQCFG_STRIDES(idxd); i++) {
+               wq_offset = WQCFG_OFFSET(idxd, wq->id, i);
                iowrite32(0, idxd->reg_base + wq_offset);
                dev_dbg(dev, "WQ[%d][%d][%#x]: %#x\n",
                        wq->id, i, wq_offset,
@@ -539,10 +539,10 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
        if (!wq->group)
                return 0;
 
-       memset(&wq->wqcfg, 0, sizeof(union wqcfg));
+       memset(wq->wqcfg, 0, idxd->wqcfg_size);
 
        /* byte 0-3 */
-       wq->wqcfg.wq_size = wq->size;
+       wq->wqcfg->wq_size = wq->size;
 
        if (wq->size == 0) {
                dev_warn(dev, "Incorrect work queue size: 0\n");
@@ -550,22 +550,21 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
        }
 
        /* bytes 4-7 */
-       wq->wqcfg.wq_thresh = wq->threshold;
+       wq->wqcfg->wq_thresh = wq->threshold;
 
        /* byte 8-11 */
-       wq->wqcfg.priv = !!(wq->type == IDXD_WQT_KERNEL);
-       wq->wqcfg.mode = 1;
-
-       wq->wqcfg.priority = wq->priority;
+       wq->wqcfg->priv = !!(wq->type == IDXD_WQT_KERNEL);
+       wq->wqcfg->mode = 1;
+       wq->wqcfg->priority = wq->priority;
 
        /* bytes 12-15 */
-       wq->wqcfg.max_xfer_shift = ilog2(wq->max_xfer_bytes);
-       wq->wqcfg.max_batch_shift = ilog2(wq->max_batch_size);
+       wq->wqcfg->max_xfer_shift = ilog2(wq->max_xfer_bytes);
+       wq->wqcfg->max_batch_shift = ilog2(wq->max_batch_size);
 
        dev_dbg(dev, "WQ %d CFGs\n", wq->id);
-       for (i = 0; i < 8; i++) {
-               wq_offset = idxd->wqcfg_offset + wq->id * 32 + i * sizeof(u32);
-               iowrite32(wq->wqcfg.bits[i], idxd->reg_base + wq_offset);
+       for (i = 0; i < WQCFG_STRIDES(idxd); i++) {
+               wq_offset = WQCFG_OFFSET(idxd, wq->id, i);
+               iowrite32(wq->wqcfg->bits[i], idxd->reg_base + wq_offset);
                dev_dbg(dev, "WQ[%d][%d][%#x]: %#x\n",
                        wq->id, i, wq_offset,
                        ioread32(idxd->reg_base + wq_offset));
index c64df197e724854401690e96b48f5b328df4ff53..d48f193daacc08bd93a0a95dc4db2f14d91865d1 100644 (file)
@@ -103,7 +103,7 @@ struct idxd_wq {
        u32 priority;
        enum idxd_wq_state state;
        unsigned long flags;
-       union wqcfg wqcfg;
+       union wqcfg *wqcfg;
        u32 vec_ptr;            /* interrupt steering */
        struct dsa_hw_desc **hw_descs;
        int num_descs;
@@ -183,6 +183,7 @@ struct idxd_device {
        int max_wq_size;
        int token_limit;
        int nr_tokens;          /* non-reserved tokens */
+       unsigned int wqcfg_size;
 
        union sw_err_reg sw_err;
        wait_queue_head_t cmd_waitq;
index 11e5ce16817728c1989aed2c5a79ff8d097c2e2e..0a4432b063b5ceb260415d050b93e823dbedf88d 100644 (file)
@@ -178,6 +178,9 @@ static int idxd_setup_internals(struct idxd_device *idxd)
                wq->idxd_cdev.minor = -1;
                wq->max_xfer_bytes = idxd->max_xfer_bytes;
                wq->max_batch_size = idxd->max_batch_size;
+               wq->wqcfg = devm_kzalloc(dev, idxd->wqcfg_size, GFP_KERNEL);
+               if (!wq->wqcfg)
+                       return -ENOMEM;
        }
 
        for (i = 0; i < idxd->max_engines; i++) {
@@ -251,6 +254,8 @@ static void idxd_read_caps(struct idxd_device *idxd)
        dev_dbg(dev, "total workqueue size: %u\n", idxd->max_wq_size);
        idxd->max_wqs = idxd->hw.wq_cap.num_wqs;
        dev_dbg(dev, "max workqueues: %u\n", idxd->max_wqs);
+       idxd->wqcfg_size = 1 << (idxd->hw.wq_cap.wqcfg_size + IDXD_WQCFG_MIN);
+       dev_dbg(dev, "wqcfg size: %u\n", idxd->wqcfg_size);
 
        /* reading operation capabilities */
        for (i = 0; i < 4; i++) {
index a39e7ae6b3d93a047060db4230b3723c3a9cd1b8..54390334c243a01b448dbd09f411c68d6a361c9e 100644 (file)
@@ -8,7 +8,7 @@
 
 #define IDXD_MMIO_BAR          0
 #define IDXD_WQ_BAR            2
-#define IDXD_PORTAL_SIZE       0x4000
+#define IDXD_PORTAL_SIZE       PAGE_SIZE
 
 /* MMIO Device BAR0 Registers */
 #define IDXD_VER_OFFSET                        0x00
@@ -43,7 +43,8 @@ union wq_cap_reg {
        struct {
                u64 total_wq_size:16;
                u64 num_wqs:8;
-               u64 rsvd:24;
+               u64 wqcfg_size:4;
+               u64 rsvd:20;
                u64 shared_mode:1;
                u64 dedicated_mode:1;
                u64 rsvd2:1;
@@ -55,6 +56,7 @@ union wq_cap_reg {
        u64 bits;
 } __packed;
 #define IDXD_WQCAP_OFFSET              0x20
+#define IDXD_WQCFG_MIN                 5
 
 union group_cap_reg {
        struct {
@@ -333,4 +335,23 @@ union wqcfg {
        };
        u32 bits[8];
 } __packed;
+
+/*
+ * This macro calculates the offset into the WQCFG register
+ * idxd - struct idxd *
+ * n - wq id
+ * ofs - the index of the 32b dword for the config register
+ *
+ * The WQCFG register block is divided into groups per each wq. The n index
+ * allows us to move to the register group that's for that particular wq.
+ * Each register is 32bits. The ofs gives us the number of register to access.
+ */
+#define WQCFG_OFFSET(_idxd_dev, n, ofs) \
+({\
+       typeof(_idxd_dev) __idxd_dev = (_idxd_dev);     \
+       (__idxd_dev)->wqcfg_offset + (n) * (__idxd_dev)->wqcfg_size + sizeof(u32) * (ofs);      \
+})
+
+#define WQCFG_STRIDES(_idxd_dev) ((_idxd_dev)->wqcfg_size / sizeof(u32))
+
 #endif
index 156a1ee233aa569890855eb5385509d51123a068..417048e3c42aa88cdb27288625695720407018a1 100644 (file)
@@ -74,7 +74,7 @@ int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc)
        if (idxd->state != IDXD_DEV_ENABLED)
                return -EIO;
 
-       portal = wq->dportal + idxd_get_wq_portal_offset(IDXD_PORTAL_UNLIMITED);
+       portal = wq->dportal;
        /*
         * The wmb() flushes writes to coherent DMA data before possibly
         * triggering a DMA read. The wmb() is necessary even on UP because
index 0be385587c4cad2cd5c8cd3c6078a697c18743e8..289c59ed74b9770f7ab7bee036059a6aac223b77 100644 (file)
 #define DCA2_TAG_MAP_BYTE3 0x82
 #define DCA2_TAG_MAP_BYTE4 0x82
 
-/* verify if tag map matches expected values */
-static inline int dca2_tag_map_valid(u8 *tag_map)
-{
-       return ((tag_map[0] == DCA2_TAG_MAP_BYTE0) &&
-               (tag_map[1] == DCA2_TAG_MAP_BYTE1) &&
-               (tag_map[2] == DCA2_TAG_MAP_BYTE2) &&
-               (tag_map[3] == DCA2_TAG_MAP_BYTE3) &&
-               (tag_map[4] == DCA2_TAG_MAP_BYTE4));
-}
-
 /*
  * "Legacy" DCA systems do not implement the DCA register set in the
  * I/OAT device.  Software needs direct support for their tag mappings.
diff --git a/drivers/dma/mic_x100_dma.c b/drivers/dma/mic_x100_dma.c
deleted file mode 100644 (file)
index fea8608..0000000
+++ /dev/null
@@ -1,770 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel MIC X100 DMA Driver.
- *
- * Adapted from IOAT dma driver.
- */
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/seq_file.h>
-#include <linux/vmalloc.h>
-
-#include "mic_x100_dma.h"
-
-#define MIC_DMA_MAX_XFER_SIZE_CARD  (1 * 1024 * 1024 -\
-                                      MIC_DMA_ALIGN_BYTES)
-#define MIC_DMA_MAX_XFER_SIZE_HOST  (1 * 1024 * 1024 >> 1)
-#define MIC_DMA_DESC_TYPE_SHIFT        60
-#define MIC_DMA_MEMCPY_LEN_SHIFT 46
-#define MIC_DMA_STAT_INTR_SHIFT 59
-
-/* high-water mark for pushing dma descriptors */
-static int mic_dma_pending_level = 4;
-
-/* Status descriptor is used to write a 64 bit value to a memory location */
-enum mic_dma_desc_format_type {
-       MIC_DMA_MEMCPY = 1,
-       MIC_DMA_STATUS,
-};
-
-static inline u32 mic_dma_hw_ring_inc(u32 val)
-{
-       return (val + 1) % MIC_DMA_DESC_RX_SIZE;
-}
-
-static inline u32 mic_dma_hw_ring_dec(u32 val)
-{
-       return val ? val - 1 : MIC_DMA_DESC_RX_SIZE - 1;
-}
-
-static inline void mic_dma_hw_ring_inc_head(struct mic_dma_chan *ch)
-{
-       ch->head = mic_dma_hw_ring_inc(ch->head);
-}
-
-/* Prepare a memcpy desc */
-static inline void mic_dma_memcpy_desc(struct mic_dma_desc *desc,
-       dma_addr_t src_phys, dma_addr_t dst_phys, u64 size)
-{
-       u64 qw0, qw1;
-
-       qw0 = src_phys;
-       qw0 |= (size >> MIC_DMA_ALIGN_SHIFT) << MIC_DMA_MEMCPY_LEN_SHIFT;
-       qw1 = MIC_DMA_MEMCPY;
-       qw1 <<= MIC_DMA_DESC_TYPE_SHIFT;
-       qw1 |= dst_phys;
-       desc->qw0 = qw0;
-       desc->qw1 = qw1;
-}
-
-/* Prepare a status desc. with @data to be written at @dst_phys */
-static inline void mic_dma_prep_status_desc(struct mic_dma_desc *desc, u64 data,
-       dma_addr_t dst_phys, bool generate_intr)
-{
-       u64 qw0, qw1;
-
-       qw0 = data;
-       qw1 = (u64) MIC_DMA_STATUS << MIC_DMA_DESC_TYPE_SHIFT | dst_phys;
-       if (generate_intr)
-               qw1 |= (1ULL << MIC_DMA_STAT_INTR_SHIFT);
-       desc->qw0 = qw0;
-       desc->qw1 = qw1;
-}
-
-static void mic_dma_cleanup(struct mic_dma_chan *ch)
-{
-       struct dma_async_tx_descriptor *tx;
-       u32 tail;
-       u32 last_tail;
-
-       spin_lock(&ch->cleanup_lock);
-       tail = mic_dma_read_cmp_cnt(ch);
-       /*
-        * This is the barrier pair for smp_wmb() in fn.
-        * mic_dma_tx_submit_unlock. It's required so that we read the
-        * updated cookie value from tx->cookie.
-        */
-       smp_rmb();
-       for (last_tail = ch->last_tail; tail != last_tail;) {
-               tx = &ch->tx_array[last_tail];
-               if (tx->cookie) {
-                       dma_cookie_complete(tx);
-                       dmaengine_desc_get_callback_invoke(tx, NULL);
-                       tx->callback = NULL;
-               }
-               last_tail = mic_dma_hw_ring_inc(last_tail);
-       }
-       /* finish all completion callbacks before incrementing tail */
-       smp_mb();
-       ch->last_tail = last_tail;
-       spin_unlock(&ch->cleanup_lock);
-}
-
-static u32 mic_dma_ring_count(u32 head, u32 tail)
-{
-       u32 count;
-
-       if (head >= tail)
-               count = (tail - 0) + (MIC_DMA_DESC_RX_SIZE - head);
-       else
-               count = tail - head;
-       return count - 1;
-}
-
-/* Returns the num. of free descriptors on success, -ENOMEM on failure */
-static int mic_dma_avail_desc_ring_space(struct mic_dma_chan *ch, int required)
-{
-       struct device *dev = mic_dma_ch_to_device(ch);
-       u32 count;
-
-       count = mic_dma_ring_count(ch->head, ch->last_tail);
-       if (count < required) {
-               mic_dma_cleanup(ch);
-               count = mic_dma_ring_count(ch->head, ch->last_tail);
-       }
-
-       if (count < required) {
-               dev_dbg(dev, "Not enough desc space");
-               dev_dbg(dev, "%s %d required=%u, avail=%u\n",
-                       __func__, __LINE__, required, count);
-               return -ENOMEM;
-       } else {
-               return count;
-       }
-}
-
-/* Program memcpy descriptors into the descriptor ring and update s/w head ptr*/
-static int mic_dma_prog_memcpy_desc(struct mic_dma_chan *ch, dma_addr_t src,
-                                   dma_addr_t dst, size_t len)
-{
-       size_t current_transfer_len;
-       size_t max_xfer_size = to_mic_dma_dev(ch)->max_xfer_size;
-       /* 3 is added to make sure we have enough space for status desc */
-       int num_desc = len / max_xfer_size + 3;
-       int ret;
-
-       if (len % max_xfer_size)
-               num_desc++;
-
-       ret = mic_dma_avail_desc_ring_space(ch, num_desc);
-       if (ret < 0)
-               return ret;
-       do {
-               current_transfer_len = min(len, max_xfer_size);
-               mic_dma_memcpy_desc(&ch->desc_ring[ch->head],
-                                   src, dst, current_transfer_len);
-               mic_dma_hw_ring_inc_head(ch);
-               len -= current_transfer_len;
-               dst = dst + current_transfer_len;
-               src = src + current_transfer_len;
-       } while (len > 0);
-       return 0;
-}
-
-/* It's a h/w quirk and h/w needs 2 status descriptors for every status desc */
-static void mic_dma_prog_intr(struct mic_dma_chan *ch)
-{
-       mic_dma_prep_status_desc(&ch->desc_ring[ch->head], 0,
-                                ch->status_dest_micpa, false);
-       mic_dma_hw_ring_inc_head(ch);
-       mic_dma_prep_status_desc(&ch->desc_ring[ch->head], 0,
-                                ch->status_dest_micpa, true);
-       mic_dma_hw_ring_inc_head(ch);
-}
-
-/* Wrapper function to program memcpy descriptors/status descriptors */
-static int mic_dma_do_dma(struct mic_dma_chan *ch, int flags, dma_addr_t src,
-                         dma_addr_t dst, size_t len)
-{
-       if (len && -ENOMEM == mic_dma_prog_memcpy_desc(ch, src, dst, len)) {
-               return -ENOMEM;
-       } else {
-               /* 3 is the maximum number of status descriptors */
-               int ret = mic_dma_avail_desc_ring_space(ch, 3);
-
-               if (ret < 0)
-                       return ret;
-       }
-
-       /* Above mic_dma_prog_memcpy_desc() makes sure we have enough space */
-       if (flags & DMA_PREP_FENCE) {
-               mic_dma_prep_status_desc(&ch->desc_ring[ch->head], 0,
-                                        ch->status_dest_micpa, false);
-               mic_dma_hw_ring_inc_head(ch);
-       }
-
-       if (flags & DMA_PREP_INTERRUPT)
-               mic_dma_prog_intr(ch);
-
-       return 0;
-}
-
-static inline void mic_dma_issue_pending(struct dma_chan *ch)
-{
-       struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
-
-       spin_lock(&mic_ch->issue_lock);
-       /*
-        * Write to head triggers h/w to act on the descriptors.
-        * On MIC, writing the same head value twice causes
-        * a h/w error. On second write, h/w assumes we filled
-        * the entire ring & overwrote some of the descriptors.
-        */
-       if (mic_ch->issued == mic_ch->submitted)
-               goto out;
-       mic_ch->issued = mic_ch->submitted;
-       /*
-        * make descriptor updates visible before advancing head,
-        * this is purposefully not smp_wmb() since we are also
-        * publishing the descriptor updates to a dma device
-        */
-       wmb();
-       mic_dma_write_reg(mic_ch, MIC_DMA_REG_DHPR, mic_ch->issued);
-out:
-       spin_unlock(&mic_ch->issue_lock);
-}
-
-static inline void mic_dma_update_pending(struct mic_dma_chan *ch)
-{
-       if (mic_dma_ring_count(ch->issued, ch->submitted)
-                       > mic_dma_pending_level)
-               mic_dma_issue_pending(&ch->api_ch);
-}
-
-static dma_cookie_t mic_dma_tx_submit_unlock(struct dma_async_tx_descriptor *tx)
-{
-       struct mic_dma_chan *mic_ch = to_mic_dma_chan(tx->chan);
-       dma_cookie_t cookie;
-
-       dma_cookie_assign(tx);
-       cookie = tx->cookie;
-       /*
-        * We need an smp write barrier here because another CPU might see
-        * an update to submitted and update h/w head even before we
-        * assigned a cookie to this tx.
-        */
-       smp_wmb();
-       mic_ch->submitted = mic_ch->head;
-       spin_unlock(&mic_ch->prep_lock);
-       mic_dma_update_pending(mic_ch);
-       return cookie;
-}
-
-static inline struct dma_async_tx_descriptor *
-allocate_tx(struct mic_dma_chan *ch)
-{
-       u32 idx = mic_dma_hw_ring_dec(ch->head);
-       struct dma_async_tx_descriptor *tx = &ch->tx_array[idx];
-
-       dma_async_tx_descriptor_init(tx, &ch->api_ch);
-       tx->tx_submit = mic_dma_tx_submit_unlock;
-       return tx;
-}
-
-/* Program a status descriptor with dst as address and value to be written */
-static struct dma_async_tx_descriptor *
-mic_dma_prep_status_lock(struct dma_chan *ch, dma_addr_t dst, u64 src_val,
-                        unsigned long flags)
-{
-       struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
-       int result;
-
-       spin_lock(&mic_ch->prep_lock);
-       result = mic_dma_avail_desc_ring_space(mic_ch, 4);
-       if (result < 0)
-               goto error;
-       mic_dma_prep_status_desc(&mic_ch->desc_ring[mic_ch->head], src_val, dst,
-                                false);
-       mic_dma_hw_ring_inc_head(mic_ch);
-       result = mic_dma_do_dma(mic_ch, flags, 0, 0, 0);
-       if (result < 0)
-               goto error;
-
-       return allocate_tx(mic_ch);
-error:
-       dev_err(mic_dma_ch_to_device(mic_ch),
-               "Error enqueueing dma status descriptor, error=%d\n", result);
-       spin_unlock(&mic_ch->prep_lock);
-       return NULL;
-}
-
-/*
- * Prepare a memcpy descriptor to be added to the ring.
- * Note that the temporary descriptor adds an extra overhead of copying the
- * descriptor to ring. So, we copy directly to the descriptor ring
- */
-static struct dma_async_tx_descriptor *
-mic_dma_prep_memcpy_lock(struct dma_chan *ch, dma_addr_t dma_dest,
-                        dma_addr_t dma_src, size_t len, unsigned long flags)
-{
-       struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
-       struct device *dev = mic_dma_ch_to_device(mic_ch);
-       int result;
-
-       if (!len && !flags)
-               return NULL;
-
-       spin_lock(&mic_ch->prep_lock);
-       result = mic_dma_do_dma(mic_ch, flags, dma_src, dma_dest, len);
-       if (result >= 0)
-               return allocate_tx(mic_ch);
-       dev_err(dev, "Error enqueueing dma, error=%d\n", result);
-       spin_unlock(&mic_ch->prep_lock);
-       return NULL;
-}
-
-static struct dma_async_tx_descriptor *
-mic_dma_prep_interrupt_lock(struct dma_chan *ch, unsigned long flags)
-{
-       struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
-       int ret;
-
-       spin_lock(&mic_ch->prep_lock);
-       ret = mic_dma_do_dma(mic_ch, flags, 0, 0, 0);
-       if (!ret)
-               return allocate_tx(mic_ch);
-       spin_unlock(&mic_ch->prep_lock);
-       return NULL;
-}
-
-/* Return the status of the transaction */
-static enum dma_status
-mic_dma_tx_status(struct dma_chan *ch, dma_cookie_t cookie,
-                 struct dma_tx_state *txstate)
-{
-       struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
-
-       if (DMA_COMPLETE != dma_cookie_status(ch, cookie, txstate))
-               mic_dma_cleanup(mic_ch);
-
-       return dma_cookie_status(ch, cookie, txstate);
-}
-
-static irqreturn_t mic_dma_thread_fn(int irq, void *data)
-{
-       mic_dma_cleanup((struct mic_dma_chan *)data);
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t mic_dma_intr_handler(int irq, void *data)
-{
-       struct mic_dma_chan *ch = ((struct mic_dma_chan *)data);
-
-       mic_dma_ack_interrupt(ch);
-       return IRQ_WAKE_THREAD;
-}
-
-static int mic_dma_alloc_desc_ring(struct mic_dma_chan *ch)
-{
-       u64 desc_ring_size = MIC_DMA_DESC_RX_SIZE * sizeof(*ch->desc_ring);
-       struct device *dev = &to_mbus_device(ch)->dev;
-
-       desc_ring_size = ALIGN(desc_ring_size, MIC_DMA_ALIGN_BYTES);
-       ch->desc_ring = kzalloc(desc_ring_size, GFP_KERNEL);
-
-       if (!ch->desc_ring)
-               return -ENOMEM;
-
-       ch->desc_ring_micpa = dma_map_single(dev, ch->desc_ring,
-                                            desc_ring_size, DMA_BIDIRECTIONAL);
-       if (dma_mapping_error(dev, ch->desc_ring_micpa))
-               goto map_error;
-
-       ch->tx_array = vzalloc(array_size(MIC_DMA_DESC_RX_SIZE,
-                                         sizeof(*ch->tx_array)));
-       if (!ch->tx_array)
-               goto tx_error;
-       return 0;
-tx_error:
-       dma_unmap_single(dev, ch->desc_ring_micpa, desc_ring_size,
-                        DMA_BIDIRECTIONAL);
-map_error:
-       kfree(ch->desc_ring);
-       return -ENOMEM;
-}
-
-static void mic_dma_free_desc_ring(struct mic_dma_chan *ch)
-{
-       u64 desc_ring_size = MIC_DMA_DESC_RX_SIZE * sizeof(*ch->desc_ring);
-
-       vfree(ch->tx_array);
-       desc_ring_size = ALIGN(desc_ring_size, MIC_DMA_ALIGN_BYTES);
-       dma_unmap_single(&to_mbus_device(ch)->dev, ch->desc_ring_micpa,
-                        desc_ring_size, DMA_BIDIRECTIONAL);
-       kfree(ch->desc_ring);
-       ch->desc_ring = NULL;
-}
-
-static void mic_dma_free_status_dest(struct mic_dma_chan *ch)
-{
-       dma_unmap_single(&to_mbus_device(ch)->dev, ch->status_dest_micpa,
-                        L1_CACHE_BYTES, DMA_BIDIRECTIONAL);
-       kfree(ch->status_dest);
-}
-
-static int mic_dma_alloc_status_dest(struct mic_dma_chan *ch)
-{
-       struct device *dev = &to_mbus_device(ch)->dev;
-
-       ch->status_dest = kzalloc(L1_CACHE_BYTES, GFP_KERNEL);
-       if (!ch->status_dest)
-               return -ENOMEM;
-       ch->status_dest_micpa = dma_map_single(dev, ch->status_dest,
-                                       L1_CACHE_BYTES, DMA_BIDIRECTIONAL);
-       if (dma_mapping_error(dev, ch->status_dest_micpa)) {
-               kfree(ch->status_dest);
-               ch->status_dest = NULL;
-               return -ENOMEM;
-       }
-       return 0;
-}
-
-static int mic_dma_check_chan(struct mic_dma_chan *ch)
-{
-       if (mic_dma_read_reg(ch, MIC_DMA_REG_DCHERR) ||
-           mic_dma_read_reg(ch, MIC_DMA_REG_DSTAT) & MIC_DMA_CHAN_QUIESCE) {
-               mic_dma_disable_chan(ch);
-               mic_dma_chan_mask_intr(ch);
-               dev_err(mic_dma_ch_to_device(ch),
-                       "%s %d error setting up mic dma chan %d\n",
-                       __func__, __LINE__, ch->ch_num);
-               return -EBUSY;
-       }
-       return 0;
-}
-
-static int mic_dma_chan_setup(struct mic_dma_chan *ch)
-{
-       if (MIC_DMA_CHAN_MIC == ch->owner)
-               mic_dma_chan_set_owner(ch);
-       mic_dma_disable_chan(ch);
-       mic_dma_chan_mask_intr(ch);
-       mic_dma_write_reg(ch, MIC_DMA_REG_DCHERRMSK, 0);
-       mic_dma_chan_set_desc_ring(ch);
-       ch->last_tail = mic_dma_read_reg(ch, MIC_DMA_REG_DTPR);
-       ch->head = ch->last_tail;
-       ch->issued = 0;
-       mic_dma_chan_unmask_intr(ch);
-       mic_dma_enable_chan(ch);
-       return mic_dma_check_chan(ch);
-}
-
-static void mic_dma_chan_destroy(struct mic_dma_chan *ch)
-{
-       mic_dma_disable_chan(ch);
-       mic_dma_chan_mask_intr(ch);
-}
-
-static int mic_dma_setup_irq(struct mic_dma_chan *ch)
-{
-       ch->cookie =
-               to_mbus_hw_ops(ch)->request_threaded_irq(to_mbus_device(ch),
-                       mic_dma_intr_handler, mic_dma_thread_fn,
-                       "mic dma_channel", ch, ch->ch_num);
-       return PTR_ERR_OR_ZERO(ch->cookie);
-}
-
-static inline void mic_dma_free_irq(struct mic_dma_chan *ch)
-{
-       to_mbus_hw_ops(ch)->free_irq(to_mbus_device(ch), ch->cookie, ch);
-}
-
-static int mic_dma_chan_init(struct mic_dma_chan *ch)
-{
-       int ret = mic_dma_alloc_desc_ring(ch);
-
-       if (ret)
-               goto ring_error;
-       ret = mic_dma_alloc_status_dest(ch);
-       if (ret)
-               goto status_error;
-       ret = mic_dma_chan_setup(ch);
-       if (ret)
-               goto chan_error;
-       return ret;
-chan_error:
-       mic_dma_free_status_dest(ch);
-status_error:
-       mic_dma_free_desc_ring(ch);
-ring_error:
-       return ret;
-}
-
-static int mic_dma_drain_chan(struct mic_dma_chan *ch)
-{
-       struct dma_async_tx_descriptor *tx;
-       int err = 0;
-       dma_cookie_t cookie;
-
-       tx = mic_dma_prep_memcpy_lock(&ch->api_ch, 0, 0, 0, DMA_PREP_FENCE);
-       if (!tx) {
-               err = -ENOMEM;
-               goto error;
-       }
-
-       cookie = tx->tx_submit(tx);
-       if (dma_submit_error(cookie))
-               err = -ENOMEM;
-       else
-               err = dma_sync_wait(&ch->api_ch, cookie);
-       if (err) {
-               dev_err(mic_dma_ch_to_device(ch), "%s %d TO chan 0x%x\n",
-                       __func__, __LINE__, ch->ch_num);
-               err = -EIO;
-       }
-error:
-       mic_dma_cleanup(ch);
-       return err;
-}
-
-static inline void mic_dma_chan_uninit(struct mic_dma_chan *ch)
-{
-       mic_dma_chan_destroy(ch);
-       mic_dma_cleanup(ch);
-       mic_dma_free_status_dest(ch);
-       mic_dma_free_desc_ring(ch);
-}
-
-static int mic_dma_init(struct mic_dma_device *mic_dma_dev,
-                       enum mic_dma_chan_owner owner)
-{
-       int i, first_chan = mic_dma_dev->start_ch;
-       struct mic_dma_chan *ch;
-       int ret;
-
-       for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
-               ch = &mic_dma_dev->mic_ch[i];
-               ch->ch_num = i;
-               ch->owner = owner;
-               spin_lock_init(&ch->cleanup_lock);
-               spin_lock_init(&ch->prep_lock);
-               spin_lock_init(&ch->issue_lock);
-               ret = mic_dma_setup_irq(ch);
-               if (ret)
-                       goto error;
-       }
-       return 0;
-error:
-       for (i = i - 1; i >= first_chan; i--)
-               mic_dma_free_irq(ch);
-       return ret;
-}
-
-static void mic_dma_uninit(struct mic_dma_device *mic_dma_dev)
-{
-       int i, first_chan = mic_dma_dev->start_ch;
-       struct mic_dma_chan *ch;
-
-       for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
-               ch = &mic_dma_dev->mic_ch[i];
-               mic_dma_free_irq(ch);
-       }
-}
-
-static int mic_dma_alloc_chan_resources(struct dma_chan *ch)
-{
-       int ret = mic_dma_chan_init(to_mic_dma_chan(ch));
-       if (ret)
-               return ret;
-       return MIC_DMA_DESC_RX_SIZE;
-}
-
-static void mic_dma_free_chan_resources(struct dma_chan *ch)
-{
-       struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
-       mic_dma_drain_chan(mic_ch);
-       mic_dma_chan_uninit(mic_ch);
-}
-
-/* Set the fn. handlers and register the dma device with dma api */
-static int mic_dma_register_dma_device(struct mic_dma_device *mic_dma_dev,
-                                      enum mic_dma_chan_owner owner)
-{
-       int i, first_chan = mic_dma_dev->start_ch;
-
-       dma_cap_zero(mic_dma_dev->dma_dev.cap_mask);
-       /*
-        * This dma engine is not capable of host memory to host memory
-        * transfers
-        */
-       dma_cap_set(DMA_MEMCPY, mic_dma_dev->dma_dev.cap_mask);
-
-       if (MIC_DMA_CHAN_HOST == owner)
-               dma_cap_set(DMA_PRIVATE, mic_dma_dev->dma_dev.cap_mask);
-       mic_dma_dev->dma_dev.device_alloc_chan_resources =
-               mic_dma_alloc_chan_resources;
-       mic_dma_dev->dma_dev.device_free_chan_resources =
-               mic_dma_free_chan_resources;
-       mic_dma_dev->dma_dev.device_tx_status = mic_dma_tx_status;
-       mic_dma_dev->dma_dev.device_prep_dma_memcpy = mic_dma_prep_memcpy_lock;
-       mic_dma_dev->dma_dev.device_prep_dma_imm_data =
-               mic_dma_prep_status_lock;
-       mic_dma_dev->dma_dev.device_prep_dma_interrupt =
-               mic_dma_prep_interrupt_lock;
-       mic_dma_dev->dma_dev.device_issue_pending = mic_dma_issue_pending;
-       mic_dma_dev->dma_dev.copy_align = MIC_DMA_ALIGN_SHIFT;
-       INIT_LIST_HEAD(&mic_dma_dev->dma_dev.channels);
-       for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
-               mic_dma_dev->mic_ch[i].api_ch.device = &mic_dma_dev->dma_dev;
-               dma_cookie_init(&mic_dma_dev->mic_ch[i].api_ch);
-               list_add_tail(&mic_dma_dev->mic_ch[i].api_ch.device_node,
-                             &mic_dma_dev->dma_dev.channels);
-       }
-       return dmaenginem_async_device_register(&mic_dma_dev->dma_dev);
-}
-
-/*
- * Initializes dma channels and registers the dma device with the
- * dma engine api.
- */
-static struct mic_dma_device *mic_dma_dev_reg(struct mbus_device *mbdev,
-                                             enum mic_dma_chan_owner owner)
-{
-       struct mic_dma_device *mic_dma_dev;
-       int ret;
-       struct device *dev = &mbdev->dev;
-
-       mic_dma_dev = devm_kzalloc(dev, sizeof(*mic_dma_dev), GFP_KERNEL);
-       if (!mic_dma_dev) {
-               ret = -ENOMEM;
-               goto alloc_error;
-       }
-       mic_dma_dev->mbdev = mbdev;
-       mic_dma_dev->dma_dev.dev = dev;
-       mic_dma_dev->mmio = mbdev->mmio_va;
-       if (MIC_DMA_CHAN_HOST == owner) {
-               mic_dma_dev->start_ch = 0;
-               mic_dma_dev->max_xfer_size = MIC_DMA_MAX_XFER_SIZE_HOST;
-       } else {
-               mic_dma_dev->start_ch = 4;
-               mic_dma_dev->max_xfer_size = MIC_DMA_MAX_XFER_SIZE_CARD;
-       }
-       ret = mic_dma_init(mic_dma_dev, owner);
-       if (ret)
-               goto init_error;
-       ret = mic_dma_register_dma_device(mic_dma_dev, owner);
-       if (ret)
-               goto reg_error;
-       return mic_dma_dev;
-reg_error:
-       mic_dma_uninit(mic_dma_dev);
-init_error:
-       mic_dma_dev = NULL;
-alloc_error:
-       dev_err(dev, "Error at %s %d ret=%d\n", __func__, __LINE__, ret);
-       return mic_dma_dev;
-}
-
-static void mic_dma_dev_unreg(struct mic_dma_device *mic_dma_dev)
-{
-       mic_dma_uninit(mic_dma_dev);
-}
-
-/* DEBUGFS CODE */
-static int mic_dma_reg_show(struct seq_file *s, void *pos)
-{
-       struct mic_dma_device *mic_dma_dev = s->private;
-       int i, chan_num, first_chan = mic_dma_dev->start_ch;
-       struct mic_dma_chan *ch;
-
-       seq_printf(s, "SBOX_DCR: %#x\n",
-                  mic_dma_mmio_read(&mic_dma_dev->mic_ch[first_chan],
-                                    MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR));
-       seq_puts(s, "DMA Channel Registers\n");
-       seq_printf(s, "%-10s| %-10s %-10s %-10s %-10s %-10s",
-                  "Channel", "DCAR", "DTPR", "DHPR", "DRAR_HI", "DRAR_LO");
-       seq_printf(s, " %-11s %-14s %-10s\n", "DCHERR", "DCHERRMSK", "DSTAT");
-       for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
-               ch = &mic_dma_dev->mic_ch[i];
-               chan_num = ch->ch_num;
-               seq_printf(s, "%-10i| %-#10x %-#10x %-#10x %-#10x",
-                          chan_num,
-                          mic_dma_read_reg(ch, MIC_DMA_REG_DCAR),
-                          mic_dma_read_reg(ch, MIC_DMA_REG_DTPR),
-                          mic_dma_read_reg(ch, MIC_DMA_REG_DHPR),
-                          mic_dma_read_reg(ch, MIC_DMA_REG_DRAR_HI));
-               seq_printf(s, " %-#10x %-#10x %-#14x %-#10x\n",
-                          mic_dma_read_reg(ch, MIC_DMA_REG_DRAR_LO),
-                          mic_dma_read_reg(ch, MIC_DMA_REG_DCHERR),
-                          mic_dma_read_reg(ch, MIC_DMA_REG_DCHERRMSK),
-                          mic_dma_read_reg(ch, MIC_DMA_REG_DSTAT));
-       }
-       return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(mic_dma_reg);
-
-/* Debugfs parent dir */
-static struct dentry *mic_dma_dbg;
-
-static int mic_dma_driver_probe(struct mbus_device *mbdev)
-{
-       struct mic_dma_device *mic_dma_dev;
-       enum mic_dma_chan_owner owner;
-
-       if (MBUS_DEV_DMA_MIC == mbdev->id.device)
-               owner = MIC_DMA_CHAN_MIC;
-       else
-               owner = MIC_DMA_CHAN_HOST;
-
-       mic_dma_dev = mic_dma_dev_reg(mbdev, owner);
-       dev_set_drvdata(&mbdev->dev, mic_dma_dev);
-
-       if (mic_dma_dbg) {
-               mic_dma_dev->dbg_dir = debugfs_create_dir(dev_name(&mbdev->dev),
-                                                         mic_dma_dbg);
-               debugfs_create_file("mic_dma_reg", 0444, mic_dma_dev->dbg_dir,
-                                   mic_dma_dev, &mic_dma_reg_fops);
-       }
-       return 0;
-}
-
-static void mic_dma_driver_remove(struct mbus_device *mbdev)
-{
-       struct mic_dma_device *mic_dma_dev;
-
-       mic_dma_dev = dev_get_drvdata(&mbdev->dev);
-       debugfs_remove_recursive(mic_dma_dev->dbg_dir);
-       mic_dma_dev_unreg(mic_dma_dev);
-}
-
-static struct mbus_device_id id_table[] = {
-       {MBUS_DEV_DMA_MIC, MBUS_DEV_ANY_ID},
-       {MBUS_DEV_DMA_HOST, MBUS_DEV_ANY_ID},
-       {0},
-};
-
-static struct mbus_driver mic_dma_driver = {
-       .driver.name =  KBUILD_MODNAME,
-       .driver.owner = THIS_MODULE,
-       .id_table = id_table,
-       .probe = mic_dma_driver_probe,
-       .remove = mic_dma_driver_remove,
-};
-
-static int __init mic_x100_dma_init(void)
-{
-       int rc = mbus_register_driver(&mic_dma_driver);
-       if (rc)
-               return rc;
-       mic_dma_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
-       return 0;
-}
-
-static void __exit mic_x100_dma_exit(void)
-{
-       debugfs_remove_recursive(mic_dma_dbg);
-       mbus_unregister_driver(&mic_dma_driver);
-}
-
-module_init(mic_x100_dma_init);
-module_exit(mic_x100_dma_exit);
-
-MODULE_DEVICE_TABLE(mbus, id_table);
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Intel(R) MIC X100 DMA Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/mic_x100_dma.h b/drivers/dma/mic_x100_dma.h
deleted file mode 100644 (file)
index 68ef43a..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel MIC X100 DMA Driver.
- *
- * Adapted from IOAT dma driver.
- */
-#ifndef _MIC_X100_DMA_H_
-#define _MIC_X100_DMA_H_
-
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/debugfs.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/mic_bus.h>
-
-#include "dmaengine.h"
-
-/*
- * MIC has a total of 8 dma channels.
- * Four channels are assigned for host SW use & the remaining for MIC SW.
- * MIC DMA transfer size & addresses need to be 64 byte aligned.
- */
-#define MIC_DMA_MAX_NUM_CHAN   8
-#define MIC_DMA_NUM_CHAN       4
-#define MIC_DMA_ALIGN_SHIFT    DMAENGINE_ALIGN_64_BYTES
-#define MIC_DMA_ALIGN_BYTES    (1 << MIC_DMA_ALIGN_SHIFT)
-#define MIC_DMA_DESC_RX_SIZE   (128 * 1024 - 4)
-
-/*
- * Register descriptions
- * All the registers are 32 bit registers.
- * DCR is a global register and all others are per-channel.
- * DCR - bits 0, 2, 4, 6, 8, 10, 12, 14 - enable bits for channels 0 to 7
- *      bits 1, 3, 5, 7, 9, 11, 13, 15 - owner bits for channels 0 to 7
- * DCAR - bit 24 & 25 interrupt masks for mic owned & host owned channels
- * DHPR - head of the descriptor ring updated by s/w
- * DTPR - tail of the descriptor ring updated by h/w
- * DRAR_LO - lower 32 bits of descriptor ring's mic address
- * DRAR_HI - 3:0 - remaining 4 bits of descriptor ring's mic address
- *          20:4 descriptor ring size
- *          25:21 mic smpt entry number
- * DSTAT - 16:0 h/w completion count; 31:28 dma engine status
- * DCHERR - this register is non-zero on error
- * DCHERRMSK - interrupt mask register
- */
-#define MIC_DMA_HW_CMP_CNT_MASK                0x1ffff
-#define MIC_DMA_CHAN_QUIESCE           0x20000000
-#define MIC_DMA_SBOX_BASE              0x00010000
-#define MIC_DMA_SBOX_DCR               0x0000A280
-#define MIC_DMA_SBOX_CH_BASE           0x0001A000
-#define MIC_DMA_SBOX_CHAN_OFF          0x40
-#define MIC_DMA_SBOX_DCAR_IM0          (0x1 << 24)
-#define MIC_DMA_SBOX_DCAR_IM1          (0x1 << 25)
-#define MIC_DMA_SBOX_DRARHI_SYS_MASK   (0x1 << 26)
-#define MIC_DMA_REG_DCAR               0
-#define MIC_DMA_REG_DHPR               4
-#define MIC_DMA_REG_DTPR               8
-#define MIC_DMA_REG_DRAR_LO            20
-#define MIC_DMA_REG_DRAR_HI            24
-#define MIC_DMA_REG_DSTAT              32
-#define MIC_DMA_REG_DCHERR             44
-#define MIC_DMA_REG_DCHERRMSK          48
-
-/* HW dma desc */
-struct mic_dma_desc {
-       u64 qw0;
-       u64 qw1;
-};
-
-enum mic_dma_chan_owner {
-       MIC_DMA_CHAN_MIC = 0,
-       MIC_DMA_CHAN_HOST
-};
-
-/*
- * mic_dma_chan - channel specific information
- * @ch_num: channel number
- * @owner: owner of this channel
- * @last_tail: cached value of descriptor ring tail
- * @head: index of next descriptor in desc_ring
- * @issued: hardware notification point
- * @submitted: index that will be used to submit descriptors to h/w
- * @api_ch: dma engine api channel
- * @desc_ring: dma descriptor ring
- * @desc_ring_micpa: mic physical address of desc_ring
- * @status_dest: destination for status (fence) descriptor
- * @status_dest_micpa: mic address for status_dest,
- *                    DMA controller uses this address
- * @tx_array: array of async_tx
- * @cleanup_lock: lock held when processing completed tx
- * @prep_lock: lock held in prep_memcpy & released in tx_submit
- * @issue_lock: lock used to synchronize writes to head
- * @cookie: mic_irq cookie used with mic irq request
- */
-struct mic_dma_chan {
-       int ch_num;
-       enum mic_dma_chan_owner owner;
-       u32 last_tail;
-       u32 head;
-       u32 issued;
-       u32 submitted;
-       struct dma_chan api_ch;
-       struct mic_dma_desc *desc_ring;
-       dma_addr_t desc_ring_micpa;
-       u64 *status_dest;
-       dma_addr_t status_dest_micpa;
-       struct dma_async_tx_descriptor *tx_array;
-       spinlock_t cleanup_lock;
-       spinlock_t prep_lock;
-       spinlock_t issue_lock;
-       struct mic_irq *cookie;
-};
-
-/*
- * struct mic_dma_device - per mic device
- * @mic_ch: dma channels
- * @dma_dev: underlying dma device
- * @mbdev: mic bus dma device
- * @mmio: virtual address of the mmio space
- * @dbg_dir: debugfs directory
- * @start_ch: first channel number that can be used
- * @max_xfer_size: maximum transfer size per dma descriptor
- */
-struct mic_dma_device {
-       struct mic_dma_chan mic_ch[MIC_DMA_MAX_NUM_CHAN];
-       struct dma_device dma_dev;
-       struct mbus_device *mbdev;
-       void __iomem *mmio;
-       struct dentry *dbg_dir;
-       int start_ch;
-       size_t max_xfer_size;
-};
-
-static inline struct mic_dma_chan *to_mic_dma_chan(struct dma_chan *ch)
-{
-       return container_of(ch, struct mic_dma_chan, api_ch);
-}
-
-static inline struct mic_dma_device *to_mic_dma_dev(struct mic_dma_chan *ch)
-{
-       return
-       container_of((const typeof(((struct mic_dma_device *)0)->mic_ch)*)
-                    (ch - ch->ch_num), struct mic_dma_device, mic_ch);
-}
-
-static inline struct mbus_device *to_mbus_device(struct mic_dma_chan *ch)
-{
-       return to_mic_dma_dev(ch)->mbdev;
-}
-
-static inline struct mbus_hw_ops *to_mbus_hw_ops(struct mic_dma_chan *ch)
-{
-       return to_mbus_device(ch)->hw_ops;
-}
-
-static inline struct device *mic_dma_ch_to_device(struct mic_dma_chan *ch)
-{
-       return to_mic_dma_dev(ch)->dma_dev.dev;
-}
-
-static inline void __iomem *mic_dma_chan_to_mmio(struct mic_dma_chan *ch)
-{
-       return to_mic_dma_dev(ch)->mmio;
-}
-
-static inline u32 mic_dma_read_reg(struct mic_dma_chan *ch, u32 reg)
-{
-       return ioread32(mic_dma_chan_to_mmio(ch) + MIC_DMA_SBOX_CH_BASE +
-                       ch->ch_num * MIC_DMA_SBOX_CHAN_OFF + reg);
-}
-
-static inline void mic_dma_write_reg(struct mic_dma_chan *ch, u32 reg, u32 val)
-{
-       iowrite32(val, mic_dma_chan_to_mmio(ch) + MIC_DMA_SBOX_CH_BASE +
-                 ch->ch_num * MIC_DMA_SBOX_CHAN_OFF + reg);
-}
-
-static inline u32 mic_dma_mmio_read(struct mic_dma_chan *ch, u32 offset)
-{
-       return ioread32(mic_dma_chan_to_mmio(ch) + offset);
-}
-
-static inline void mic_dma_mmio_write(struct mic_dma_chan *ch, u32 val,
-                                     u32 offset)
-{
-       iowrite32(val, mic_dma_chan_to_mmio(ch) + offset);
-}
-
-static inline u32 mic_dma_read_cmp_cnt(struct mic_dma_chan *ch)
-{
-       return mic_dma_read_reg(ch, MIC_DMA_REG_DSTAT) &
-              MIC_DMA_HW_CMP_CNT_MASK;
-}
-
-static inline void mic_dma_chan_set_owner(struct mic_dma_chan *ch)
-{
-       u32 dcr = mic_dma_mmio_read(ch, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
-       u32 chan_num = ch->ch_num;
-
-       dcr = (dcr & ~(0x1 << (chan_num * 2))) | (ch->owner << (chan_num * 2));
-       mic_dma_mmio_write(ch, dcr, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
-}
-
-static inline void mic_dma_enable_chan(struct mic_dma_chan *ch)
-{
-       u32 dcr = mic_dma_mmio_read(ch, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
-
-       dcr |= 2 << (ch->ch_num << 1);
-       mic_dma_mmio_write(ch, dcr, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
-}
-
-static inline void mic_dma_disable_chan(struct mic_dma_chan *ch)
-{
-       u32 dcr = mic_dma_mmio_read(ch, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
-
-       dcr &= ~(2 << (ch->ch_num << 1));
-       mic_dma_mmio_write(ch, dcr, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
-}
-
-static void mic_dma_chan_set_desc_ring(struct mic_dma_chan *ch)
-{
-       u32 drar_hi;
-       dma_addr_t desc_ring_micpa = ch->desc_ring_micpa;
-
-       drar_hi = (MIC_DMA_DESC_RX_SIZE & 0x1ffff) << 4;
-       if (MIC_DMA_CHAN_MIC == ch->owner) {
-               drar_hi |= (desc_ring_micpa >> 32) & 0xf;
-       } else {
-               drar_hi |= MIC_DMA_SBOX_DRARHI_SYS_MASK;
-               drar_hi |= ((desc_ring_micpa >> 34)
-                           & 0x1f) << 21;
-               drar_hi |= (desc_ring_micpa >> 32) & 0x3;
-       }
-       mic_dma_write_reg(ch, MIC_DMA_REG_DRAR_LO, (u32) desc_ring_micpa);
-       mic_dma_write_reg(ch, MIC_DMA_REG_DRAR_HI, drar_hi);
-}
-
-static inline void mic_dma_chan_mask_intr(struct mic_dma_chan *ch)
-{
-       u32 dcar = mic_dma_read_reg(ch, MIC_DMA_REG_DCAR);
-
-       if (MIC_DMA_CHAN_MIC == ch->owner)
-               dcar |= MIC_DMA_SBOX_DCAR_IM0;
-       else
-               dcar |= MIC_DMA_SBOX_DCAR_IM1;
-       mic_dma_write_reg(ch, MIC_DMA_REG_DCAR, dcar);
-}
-
-static inline void mic_dma_chan_unmask_intr(struct mic_dma_chan *ch)
-{
-       u32 dcar = mic_dma_read_reg(ch, MIC_DMA_REG_DCAR);
-
-       if (MIC_DMA_CHAN_MIC == ch->owner)
-               dcar &= ~MIC_DMA_SBOX_DCAR_IM0;
-       else
-               dcar &= ~MIC_DMA_SBOX_DCAR_IM1;
-       mic_dma_write_reg(ch, MIC_DMA_REG_DCAR, dcar);
-}
-
-static void mic_dma_ack_interrupt(struct mic_dma_chan *ch)
-{
-       if (MIC_DMA_CHAN_MIC == ch->owner) {
-               /* HW errata */
-               mic_dma_chan_mask_intr(ch);
-               mic_dma_chan_unmask_intr(ch);
-       }
-       to_mbus_hw_ops(ch)->ack_interrupt(to_mbus_device(ch), ch->ch_num);
-}
-#endif
index e9f0101d92fa6ffc9ec19437f2d571d9af5c523e..0f5c19370f6d7b7225e47229eed334a623cdfe8e 100644 (file)
@@ -2799,7 +2799,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
         * If burst size is smaller than bus width then make sure we only
         * transfer one at a time to avoid a burst stradling an MFIFO entry.
         */
-       if (desc->rqcfg.brst_size * 8 < pl330->pcfg.data_bus_width)
+       if (burst * 8 < pl330->pcfg.data_bus_width)
                desc->rqcfg.brst_len = 1;
 
        desc->bytes_requested = len;
index aa24e554f7b44bca3b17021c945ed891db03283f..8563a392f30bfcfdbef84869736f64ed26c46808 100644 (file)
@@ -83,7 +83,7 @@ EXPORT_SYMBOL(xudma_rflow_is_gp);
 #define XUDMA_GET_PUT_RESOURCE(res)                                    \
 struct udma_##res *xudma_##res##_get(struct udma_dev *ud, int id)      \
 {                                                                      \
-       return __udma_reserve_##res(ud, false, id);                     \
+       return __udma_reserve_##res(ud, UDMA_TP_NORMAL, id);            \
 }                                                                      \
 EXPORT_SYMBOL(xudma_##res##_get);                                      \
                                                                        \
index c9fe5e3a6b55caf47abf9a0b21ca0942a454149c..268a080587149250c42c210f45fdffcb95114943 100644 (file)
@@ -1522,29 +1522,38 @@ static void omap_dma_free(struct omap_dmadev *od)
        }
 }
 
+/* Currently used by omap2 & 3 to block deeper SoC idle states */
+static bool omap_dma_busy(struct omap_dmadev *od)
+{
+       struct omap_chan *c;
+       int lch = -1;
+
+       while (1) {
+               lch = find_next_bit(od->lch_bitmap, od->lch_count, lch + 1);
+               if (lch >= od->lch_count)
+                       break;
+               c = od->lch_map[lch];
+               if (!c)
+                       continue;
+               if (omap_dma_chan_read(c, CCR) & CCR_ENABLE)
+                       return true;
+       }
+
+       return false;
+}
+
 /* Currently only used for omap2. For omap1, also a check for lcd_dma is needed */
 static int omap_dma_busy_notifier(struct notifier_block *nb,
                                  unsigned long cmd, void *v)
 {
        struct omap_dmadev *od;
-       struct omap_chan *c;
-       int lch = -1;
 
        od = container_of(nb, struct omap_dmadev, nb);
 
        switch (cmd) {
        case CPU_CLUSTER_PM_ENTER:
-               while (1) {
-                       lch = find_next_bit(od->lch_bitmap, od->lch_count,
-                                           lch + 1);
-                       if (lch >= od->lch_count)
-                               break;
-                       c = od->lch_map[lch];
-                       if (!c)
-                               continue;
-                       if (omap_dma_chan_read(c, CCR) & CCR_ENABLE)
-                               return NOTIFY_BAD;
-               }
+               if (omap_dma_busy(od))
+                       return NOTIFY_BAD;
                break;
        case CPU_CLUSTER_PM_ENTER_FAILED:
        case CPU_CLUSTER_PM_EXIT:
@@ -1595,6 +1604,8 @@ static int omap_dma_context_notifier(struct notifier_block *nb,
 
        switch (cmd) {
        case CPU_CLUSTER_PM_ENTER:
+               if (omap_dma_busy(od))
+                       return NOTIFY_BAD;
                omap_dma_context_save(od);
                break;
        case CPU_CLUSTER_PM_ENTER_FAILED:
index ecff35402860f20c5653b91e2855df6eaff03e94..22faea653ea82010c4411530c4e08cb330995920 100644 (file)
@@ -517,8 +517,8 @@ struct xilinx_dma_device {
 #define to_dma_tx_descriptor(tx) \
        container_of(tx, struct xilinx_dma_tx_descriptor, async_tx)
 #define xilinx_dma_poll_timeout(chan, reg, val, cond, delay_us, timeout_us) \
-       readl_poll_timeout(chan->xdev->regs + chan->ctrl_offset + reg, val, \
-                          cond, delay_us, timeout_us)
+       readl_poll_timeout_atomic(chan->xdev->regs + chan->ctrl_offset + reg, \
+                                 val, cond, delay_us, timeout_us)
 
 /* IO accessors */
 static inline u32 dma_read(struct xilinx_dma_chan *chan, u32 reg)
@@ -948,8 +948,10 @@ static u32 xilinx_dma_get_residue(struct xilinx_dma_chan *chan,
 {
        struct xilinx_cdma_tx_segment *cdma_seg;
        struct xilinx_axidma_tx_segment *axidma_seg;
+       struct xilinx_aximcdma_tx_segment *aximcdma_seg;
        struct xilinx_cdma_desc_hw *cdma_hw;
        struct xilinx_axidma_desc_hw *axidma_hw;
+       struct xilinx_aximcdma_desc_hw *aximcdma_hw;
        struct list_head *entry;
        u32 residue = 0;
 
@@ -961,13 +963,23 @@ static u32 xilinx_dma_get_residue(struct xilinx_dma_chan *chan,
                        cdma_hw = &cdma_seg->hw;
                        residue += (cdma_hw->control - cdma_hw->status) &
                                   chan->xdev->max_buffer_len;
-               } else {
+               } else if (chan->xdev->dma_config->dmatype ==
+                          XDMA_TYPE_AXIDMA) {
                        axidma_seg = list_entry(entry,
                                                struct xilinx_axidma_tx_segment,
                                                node);
                        axidma_hw = &axidma_seg->hw;
                        residue += (axidma_hw->control - axidma_hw->status) &
                                   chan->xdev->max_buffer_len;
+               } else {
+                       aximcdma_seg =
+                               list_entry(entry,
+                                          struct xilinx_aximcdma_tx_segment,
+                                          node);
+                       aximcdma_hw = &aximcdma_seg->hw;
+                       residue +=
+                               (aximcdma_hw->control - aximcdma_hw->status) &
+                               chan->xdev->max_buffer_len;
                }
        }
 
@@ -1135,7 +1147,7 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
                        upper_32_bits(chan->seg_p + sizeof(*chan->seg_mv) *
                                ((i + 1) % XILINX_DMA_NUM_DESCS));
                        chan->seg_mv[i].phys = chan->seg_p +
-                               sizeof(*chan->seg_v) * i;
+                               sizeof(*chan->seg_mv) * i;
                        list_add_tail(&chan->seg_mv[i].node,
                                      &chan->free_seg_list);
                }
@@ -1560,7 +1572,7 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
 static void xilinx_mcdma_start_transfer(struct xilinx_dma_chan *chan)
 {
        struct xilinx_dma_tx_descriptor *head_desc, *tail_desc;
-       struct xilinx_axidma_tx_segment *tail_segment;
+       struct xilinx_aximcdma_tx_segment *tail_segment;
        u32 reg;
 
        /*
@@ -1582,7 +1594,7 @@ static void xilinx_mcdma_start_transfer(struct xilinx_dma_chan *chan)
        tail_desc = list_last_entry(&chan->pending_list,
                                    struct xilinx_dma_tx_descriptor, node);
        tail_segment = list_last_entry(&tail_desc->segments,
-                                      struct xilinx_axidma_tx_segment, node);
+                                      struct xilinx_aximcdma_tx_segment, node);
 
        reg = dma_ctrl_read(chan, XILINX_MCDMA_CHAN_CR_OFFSET(chan->tdest));
 
@@ -1864,6 +1876,7 @@ static void append_desc_queue(struct xilinx_dma_chan *chan,
        struct xilinx_vdma_tx_segment *tail_segment;
        struct xilinx_dma_tx_descriptor *tail_desc;
        struct xilinx_axidma_tx_segment *axidma_tail_segment;
+       struct xilinx_aximcdma_tx_segment *aximcdma_tail_segment;
        struct xilinx_cdma_tx_segment *cdma_tail_segment;
 
        if (list_empty(&chan->pending_list))
@@ -1885,11 +1898,17 @@ static void append_desc_queue(struct xilinx_dma_chan *chan,
                                                struct xilinx_cdma_tx_segment,
                                                node);
                cdma_tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
-       } else {
+       } else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
                axidma_tail_segment = list_last_entry(&tail_desc->segments,
                                               struct xilinx_axidma_tx_segment,
                                               node);
                axidma_tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
+       } else {
+               aximcdma_tail_segment =
+                       list_last_entry(&tail_desc->segments,
+                                       struct xilinx_aximcdma_tx_segment,
+                                       node);
+               aximcdma_tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
        }
 
        /*
@@ -2836,10 +2855,11 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
                chan->stop_transfer = xilinx_dma_stop_transfer;
        }
 
-       /* check if SG is enabled (only for AXIDMA and CDMA) */
+       /* check if SG is enabled (only for AXIDMA, AXIMCDMA, and CDMA) */
        if (xdev->dma_config->dmatype != XDMA_TYPE_VDMA) {
-               if (dma_ctrl_read(chan, XILINX_DMA_REG_DMASR) &
-                   XILINX_DMA_DMASR_SG_MASK)
+               if (xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA ||
+                   dma_ctrl_read(chan, XILINX_DMA_REG_DMASR) &
+                           XILINX_DMA_DMASR_SG_MASK)
                        chan->has_sg = true;
                dev_dbg(chan->dev, "ch %d: SG %s\n", chan->id,
                        chan->has_sg ? "enabled" : "disabled");
index fa0c3b5797e4b966c99b5f67fa82f4375adcf90f..81c42664f21baf889e2c7f72cc0c142671595e73 100644 (file)
@@ -292,13 +292,6 @@ config EDAC_LAYERSCAPE
          Support for error detection and correction on Freescale memory
          controllers on Layerscape SoCs.
 
-config EDAC_MV64X60
-       tristate "Marvell MV64x60"
-       depends on MV64X60
-       help
-         Support for error detection and correction on the Marvell
-         MV64360 and MV64460 chipsets.
-
 config EDAC_PASEMI
        tristate "PA Semi PWRficient"
        depends on PPC_PASEMI && PCI
@@ -524,10 +517,10 @@ config EDAC_QCOM
          health, you should probably say 'Y' here.
 
 config EDAC_ASPEED
-       tristate "Aspeed AST 2500 SoC"
-       depends on MACH_ASPEED_G5
+       tristate "Aspeed AST BMC SoC"
+       depends on ARCH_ASPEED
        help
-         Support for error detection and correction on the Aspeed AST 2500 SoC.
+         Support for error detection and correction on the Aspeed AST BMC SoC.
 
          First, ECC must be configured in the bootloader. Then, this driver
          will expose error counters via the EDAC kernel framework.
index 3cd1aeb0a916082807ec90bdcd0fee5865786d09..464d3d8d850abe852a51294c14d650ef0d504cb6 100644 (file)
@@ -65,7 +65,6 @@ obj-$(CONFIG_EDAC_SKX)                        += skx_edac.o
 i10nm_edac-y                           := skx_common.o i10nm_base.o
 obj-$(CONFIG_EDAC_I10NM)               += i10nm_edac.o
 
-obj-$(CONFIG_EDAC_MV64X60)             += mv64x60_edac.o
 obj-$(CONFIG_EDAC_CELL)                        += cell_edac.o
 obj-$(CONFIG_EDAC_PPC4XX)              += ppc4xx_edac.o
 obj-$(CONFIG_EDAC_AMD8111)             += amd8111_edac.o
index 1362274d840b918067c49dad867444627f4bf9bc..15b0d39d284517e2b3de1400381424d4b41e5bc9 100644 (file)
@@ -18,6 +18,9 @@ static struct amd64_family_type *fam_type;
 /* Per-node stuff */
 static struct ecc_settings **ecc_stngs;
 
+/* Device for the PCI component */
+static struct device *pci_ctl_dev;
+
 /*
  * Valid scrub rates for the K8 hardware memory scrubber. We map the scrubbing
  * bandwidth to a valid bit pattern. The 'set' operation finds the 'matching-
@@ -2461,14 +2464,11 @@ static int map_err_sym_to_channel(int err_sym, int sym_size)
                case 0x20:
                case 0x21:
                        return 0;
-                       break;
                case 0x22:
                case 0x23:
                        return 1;
-                       break;
                default:
                        return err_sym >> 4;
-                       break;
                }
        /* x8 symbols */
        else
@@ -2478,17 +2478,12 @@ static int map_err_sym_to_channel(int err_sym, int sym_size)
                        WARN(1, KERN_ERR "Invalid error symbol: 0x%x\n",
                                          err_sym);
                        return -1;
-                       break;
-
                case 0x11:
                        return 0;
-                       break;
                case 0x12:
                        return 1;
-                       break;
                default:
                        return err_sym >> 3;
-                       break;
                }
        return -1;
 }
@@ -2683,6 +2678,9 @@ reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 pci_id1, u16 pci_id2)
                        return -ENODEV;
                }
 
+               if (!pci_ctl_dev)
+                       pci_ctl_dev = &pvt->F0->dev;
+
                edac_dbg(1, "F0: %s\n", pci_name(pvt->F0));
                edac_dbg(1, "F3: %s\n", pci_name(pvt->F3));
                edac_dbg(1, "F6: %s\n", pci_name(pvt->F6));
@@ -2707,6 +2705,9 @@ reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 pci_id1, u16 pci_id2)
                return -ENODEV;
        }
 
+       if (!pci_ctl_dev)
+               pci_ctl_dev = &pvt->F2->dev;
+
        edac_dbg(1, "F1: %s\n", pci_name(pvt->F1));
        edac_dbg(1, "F2: %s\n", pci_name(pvt->F2));
        edac_dbg(1, "F3: %s\n", pci_name(pvt->F3));
@@ -3623,21 +3624,10 @@ static void remove_one_instance(unsigned int nid)
 
 static void setup_pci_device(void)
 {
-       struct mem_ctl_info *mci;
-       struct amd64_pvt *pvt;
-
        if (pci_ctl)
                return;
 
-       mci = edac_mc_find(0);
-       if (!mci)
-               return;
-
-       pvt = mci->pvt_info;
-       if (pvt->umc)
-               pci_ctl = edac_pci_create_generic_ctl(&pvt->F0->dev, EDAC_MOD_STR);
-       else
-               pci_ctl = edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR);
+       pci_ctl = edac_pci_create_generic_ctl(pci_ctl_dev, EDAC_MOD_STR);
        if (!pci_ctl) {
                pr_warn("%s(): Unable to create PCI control\n", __func__);
                pr_warn("%s(): PCI error report via EDAC not set\n", __func__);
@@ -3716,6 +3706,8 @@ static int __init amd64_edac_init(void)
        return 0;
 
 err_pci:
+       pci_ctl_dev = NULL;
+
        msrs_free(msrs);
        msrs = NULL;
 
@@ -3745,6 +3737,8 @@ static void __exit amd64_edac_exit(void)
        kfree(ecc_stngs);
        ecc_stngs = NULL;
 
+       pci_ctl_dev = NULL;
+
        msrs_free(msrs);
        msrs = NULL;
 }
index 9c6e326b4c14fa71478343a255e85d93ef122237..2a49f68a7cf94061259a2511f272bfc2f1966797 100644 (file)
@@ -179,7 +179,6 @@ static int amd76x_process_error_info(struct mem_ctl_info *mci,
 static void amd76x_check(struct mem_ctl_info *mci)
 {
        struct amd76x_error_info info;
-       edac_dbg(3, "\n");
        amd76x_get_error_info(mci, &info);
        amd76x_process_error_info(mci, &info, 1);
 }
index fde809efc5205192ccf9052ca1d12a94902279af..a46da56d6d544ff3f9e20ec10513daee32d489e7 100644 (file)
@@ -239,7 +239,7 @@ static int init_csrows(struct mem_ctl_info *mci)
        int rc;
 
        /* retrieve info about physical memory from device tree */
-       np = of_find_node_by_path("/memory");
+       np = of_find_node_by_name(NULL, "memory");
        if (!np) {
                dev_err(mci->pdev, "dt: missing /memory node\n");
                return -ENODEV;
@@ -375,10 +375,13 @@ static int aspeed_remove(struct platform_device *pdev)
 
 
 static const struct of_device_id aspeed_of_match[] = {
+       { .compatible = "aspeed,ast2400-sdram-edac" },
        { .compatible = "aspeed,ast2500-sdram-edac" },
+       { .compatible = "aspeed,ast2600-sdram-edac" },
        {},
 };
 
+MODULE_DEVICE_TABLE(of, aspeed_of_match);
 
 static struct platform_driver aspeed_driver = {
        .driver         = {
@@ -392,5 +395,5 @@ module_platform_driver(aspeed_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Stefan Schaeckeler <sschaeck@cisco.com>");
-MODULE_DESCRIPTION("Aspeed AST2500 EDAC driver");
+MODULE_DESCRIPTION("Aspeed BMC SoC EDAC driver");
 MODULE_VERSION("1.0");
index 313d08018166b2cbc5f8e89f4aa3289b97ab5c8e..ac7c9b42d4c74b816ca39b015fafd404e207e983 100644 (file)
@@ -980,7 +980,6 @@ static void e752x_check(struct mem_ctl_info *mci)
 {
        struct e752x_error_info info;
 
-       edac_dbg(3, "\n");
        e752x_get_error_info(mci, &info);
        e752x_process_error_info(mci, &info, 1);
 }
index 75d7ce62b3becf311ec1e8dbb1511380d567bf57..497e710fca3df585207dbca5f256fc3e9d4c23af 100644 (file)
@@ -333,7 +333,6 @@ static void e7xxx_check(struct mem_ctl_info *mci)
 {
        struct e7xxx_error_info info;
 
-       edac_dbg(3, "\n");
        e7xxx_get_error_info(mci, &info);
        e7xxx_process_error_info(mci, &info, 1);
 }
index c4c0e0bdce146a913268ba5f200c0602dae368a6..fc2d2c2180649d239ad3befdb75a27782249e769 100644 (file)
@@ -258,7 +258,7 @@ extern struct edac_device_ctl_info *edac_device_alloc_ctl_info(
 extern void edac_device_free_ctl_info(struct edac_device_ctl_info *ctl_info);
 
 /**
- * edac_device_add_device: Insert the 'edac_dev' structure into the
+ * edac_device_add_device - Insert the 'edac_dev' structure into the
  *      edac_device global list and create sysfs entries associated with
  *      edac_device structure.
  *
@@ -271,9 +271,8 @@ extern void edac_device_free_ctl_info(struct edac_device_ctl_info *ctl_info);
 extern int edac_device_add_device(struct edac_device_ctl_info *edac_dev);
 
 /**
- * edac_device_del_device:
- *     Remove sysfs entries for specified edac_device structure and
- *     then remove edac_device structure from global list
+ * edac_device_del_device - Remove sysfs entries for specified edac_device
+ *     structure and then remove edac_device structure from global list
  *
  * @dev:
  *     Pointer to struct &device representing the edac device
@@ -286,7 +285,7 @@ extern int edac_device_add_device(struct edac_device_ctl_info *edac_dev);
 extern struct edac_device_ctl_info *edac_device_del_device(struct device *dev);
 
 /**
- * Log correctable errors.
+ * edac_device_handle_ce_count - Log correctable errors.
  *
  * @edac_dev: pointer to struct &edac_device_ctl_info
  * @inst_nr: number of the instance where the CE error happened
@@ -299,7 +298,7 @@ void edac_device_handle_ce_count(struct edac_device_ctl_info *edac_dev,
                                 const char *msg);
 
 /**
- * Log uncorrectable errors.
+ * edac_device_handle_ue_count - Log uncorrectable errors.
  *
  * @edac_dev: pointer to struct &edac_device_ctl_info
  * @inst_nr: number of the instance where the CE error happened
index eef8724faae082387806010b4c74ac7330053e82..f6d462d0be2d552de828f3ee2b85980aaf32ef2d 100644 (file)
@@ -163,6 +163,7 @@ const char * const edac_mem_types[] = {
        [MEM_RDDR4]     = "Registered-DDR4",
        [MEM_LPDDR4]    = "Low-Power-DDR4-RAM",
        [MEM_LRDDR4]    = "Load-Reduced-DDR4-RAM",
+       [MEM_DDR5]      = "Unbuffered-DDR5",
        [MEM_NVDIMM]    = "Non-volatile-RAM",
        [MEM_WIO2]      = "Wide-IO-2",
 };
index c8d11da85becfdb9b67794f1f61c35667553f87f..238a4ad1e526ee87d4d5bc1c8ed292ca8ec25d0f 100644 (file)
@@ -6,27 +6,32 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/io.h>
 #include <asm/cpu_device_id.h>
 #include <asm/intel-family.h>
 #include <asm/mce.h>
 #include "edac_module.h"
 #include "skx_common.h"
 
-#define I10NM_REVISION "v0.0.3"
+#define I10NM_REVISION "v0.0.4"
 #define EDAC_MOD_STR   "i10nm_edac"
 
 /* Debug macros */
 #define i10nm_printk(level, fmt, arg...)       \
        edac_printk(level, "i10nm", fmt, ##arg)
 
-#define I10NM_GET_SCK_BAR(d, reg)              \
+#define I10NM_GET_SCK_BAR(d, reg)      \
        pci_read_config_dword((d)->uracu, 0xd0, &(reg))
 #define I10NM_GET_IMC_BAR(d, i, reg)   \
        pci_read_config_dword((d)->uracu, 0xd8 + (i) * 4, &(reg))
 #define I10NM_GET_DIMMMTR(m, i, j)     \
-       (*(u32 *)((m)->mbase + 0x2080c + (i) * 0x4000 + (j) * 4))
+       readl((m)->mbase + 0x2080c + (i) * (m)->chan_mmio_sz + (j) * 4)
 #define I10NM_GET_MCDDRTCFG(m, i, j)   \
-       (*(u32 *)((m)->mbase + 0x20970 + (i) * 0x4000 + (j) * 4))
+       readl((m)->mbase + 0x20970 + (i) * (m)->chan_mmio_sz + (j) * 4)
+#define I10NM_GET_MCMTR(m, i)          \
+       readl((m)->mbase + 0x20ef8 + (i) * (m)->chan_mmio_sz)
+#define I10NM_GET_AMAP(m, i)           \
+       readl((m)->mbase + 0x20814 + (i) * (m)->chan_mmio_sz)
 
 #define I10NM_GET_SCK_MMIO_BASE(reg)   (GET_BITFIELD(reg, 0, 28) << 23)
 #define I10NM_GET_IMC_MMIO_OFFSET(reg) (GET_BITFIELD(reg, 0, 10) << 12)
@@ -126,12 +131,22 @@ static struct res_config i10nm_cfg0 = {
        .type                   = I10NM,
        .decs_did               = 0x3452,
        .busno_cfg_offset       = 0xcc,
+       .ddr_chan_mmio_sz       = 0x4000,
 };
 
 static struct res_config i10nm_cfg1 = {
        .type                   = I10NM,
        .decs_did               = 0x3452,
        .busno_cfg_offset       = 0xd0,
+       .ddr_chan_mmio_sz       = 0x4000,
+};
+
+static struct res_config spr_cfg = {
+       .type                   = SPR,
+       .decs_did               = 0x3252,
+       .busno_cfg_offset       = 0xd0,
+       .ddr_chan_mmio_sz       = 0x8000,
+       .support_ddr5           = true,
 };
 
 static const struct x86_cpu_id i10nm_cpuids[] = {
@@ -140,6 +155,7 @@ static const struct x86_cpu_id i10nm_cpuids[] = {
        X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ICELAKE_X,         X86_STEPPINGS(0x0, 0x3), &i10nm_cfg0),
        X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ICELAKE_X,         X86_STEPPINGS(0x4, 0xf), &i10nm_cfg1),
        X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ICELAKE_D,         X86_STEPPINGS(0x0, 0xf), &i10nm_cfg1),
+       X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(SAPPHIRERAPIDS_X,  X86_STEPPINGS(0x0, 0xf), &spr_cfg),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, i10nm_cpuids);
@@ -148,18 +164,19 @@ static bool i10nm_check_ecc(struct skx_imc *imc, int chan)
 {
        u32 mcmtr;
 
-       mcmtr = *(u32 *)(imc->mbase + 0x20ef8 + chan * 0x4000);
+       mcmtr = I10NM_GET_MCMTR(imc, chan);
        edac_dbg(1, "ch%d mcmtr reg %x\n", chan, mcmtr);
 
        return !!GET_BITFIELD(mcmtr, 2, 2);
 }
 
-static int i10nm_get_dimm_config(struct mem_ctl_info *mci)
+static int i10nm_get_dimm_config(struct mem_ctl_info *mci,
+                                struct res_config *cfg)
 {
        struct skx_pvt *pvt = mci->pvt_info;
        struct skx_imc *imc = pvt->imc;
+       u32 mtr, amap, mcddrtcfg;
        struct dimm_info *dimm;
-       u32 mtr, mcddrtcfg;
        int i, j, ndimms;
 
        for (i = 0; i < I10NM_NUM_CHANNELS; i++) {
@@ -167,6 +184,7 @@ static int i10nm_get_dimm_config(struct mem_ctl_info *mci)
                        continue;
 
                ndimms = 0;
+               amap = I10NM_GET_AMAP(imc, i);
                for (j = 0; j < I10NM_NUM_DIMMS; j++) {
                        dimm = edac_get_dimm(mci, i, j, 0);
                        mtr = I10NM_GET_DIMMMTR(imc, i, j);
@@ -175,8 +193,8 @@ static int i10nm_get_dimm_config(struct mem_ctl_info *mci)
                                 mtr, mcddrtcfg, imc->mc, i, j);
 
                        if (IS_DIMM_PRESENT(mtr))
-                               ndimms += skx_get_dimm_info(mtr, 0, 0, dimm,
-                                                           imc, i, j);
+                               ndimms += skx_get_dimm_info(mtr, 0, amap, dimm,
+                                                           imc, i, j, cfg);
                        else if (IS_NVDIMM_PRESENT(mcddrtcfg, j))
                                ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
                                                              EDAC_MOD_STR);
@@ -300,10 +318,11 @@ static int __init i10nm_init(void)
                        d->imc[i].lmc = i;
                        d->imc[i].src_id  = src_id;
                        d->imc[i].node_id = node_id;
+                       d->imc[i].chan_mmio_sz = cfg->ddr_chan_mmio_sz;
 
                        rc = skx_register_mci(&d->imc[i], d->imc[i].mdev,
                                              "Intel_10nm Socket", EDAC_MOD_STR,
-                                             i10nm_get_dimm_config);
+                                             i10nm_get_dimm_config, cfg);
                        if (rc < 0)
                                goto fail;
                }
index 5c1eea96230c3fc5252576da7f6a5fb378f5bdea..9065bc4386ffd872b5da299a0d2a369eeae62763 100644 (file)
@@ -273,7 +273,6 @@ static void i3000_check(struct mem_ctl_info *mci)
 {
        struct i3000_error_info info;
 
-       edac_dbg(1, "MC%d\n", mci->mc_idx);
        i3000_get_error_info(mci, &info);
        i3000_process_error_info(mci, &info, 1);
 }
index a8988db6d4235f65fa33793b4bd2d55d8e63dfab..afccdebf5ac1ebe7cfd7dafe8fdc0bb3173c6b9c 100644 (file)
@@ -253,7 +253,6 @@ static void i3200_check(struct mem_ctl_info *mci)
 {
        struct i3200_error_info info;
 
-       edac_dbg(1, "MC%d\n", mci->mc_idx);
        i3200_get_and_clear_error_info(mci, &info);
        i3200_process_error_info(mci, &info);
 }
index 1a6f69c859ab9007c8d6a8c8e097c4d421f25a8b..ba46057d422076aa16efb38efe01aa1da9d943a9 100644 (file)
@@ -765,7 +765,7 @@ static void i5000_clear_error(struct mem_ctl_info *mci)
 static void i5000_check_error(struct mem_ctl_info *mci)
 {
        struct i5000_error_info info;
-       edac_dbg(4, "MC%d\n", mci->mc_idx);
+
        i5000_get_error_info(mci, &info);
        i5000_process_error_info(mci, &info, 1);
 }
index 92d63eb533aee7b4e4309171bb99d11b586c3ffe..f76624ee82ef752cef9ccf9b5f13b71903879524 100644 (file)
@@ -686,7 +686,7 @@ static void i5400_clear_error(struct mem_ctl_info *mci)
 static void i5400_check_error(struct mem_ctl_info *mci)
 {
        struct i5400_error_info info;
-       edac_dbg(4, "MC%d\n", mci->mc_idx);
+
        i5400_get_error_info(mci, &info);
        i5400_process_error_info(mci, &info);
 }
index a2ca929e2168f56a9e394e0e150efbbd28043431..933dcf3cfdff6c9eb63a51a4099d3546508a6729 100644 (file)
@@ -176,7 +176,6 @@ static void i82443bxgx_edacmc_check(struct mem_ctl_info *mci)
 {
        struct i82443bxgx_edacmc_error_info info;
 
-       edac_dbg(1, "MC%d\n", mci->mc_idx);
        i82443bxgx_edacmc_get_error_info(mci, &info);
        i82443bxgx_edacmc_process_error_info(mci, &info, 1);
 }
index 3e3a80ffb3222a0072404e6b346a26062f9334fc..fbec90d00f1eef7a30dad2e14f95a0b66afcc31a 100644 (file)
@@ -135,7 +135,6 @@ static void i82860_check(struct mem_ctl_info *mci)
 {
        struct i82860_error_info info;
 
-       edac_dbg(1, "MC%d\n", mci->mc_idx);
        i82860_get_error_info(mci, &info);
        i82860_process_error_info(mci, &info, 1);
 }
index ceac925af38cc07d3031233db81aaf1791fba002..553880b9fc1220978e48085ab2fb527e6c493c77 100644 (file)
@@ -262,7 +262,6 @@ static void i82875p_check(struct mem_ctl_info *mci)
 {
        struct i82875p_error_info info;
 
-       edac_dbg(1, "MC%d\n", mci->mc_idx);
        i82875p_get_error_info(mci, &info);
        i82875p_process_error_info(mci, &info, 1);
 }
index 6be99e0d850dc12b68b96d907d6d94f7f5fb1f53..d99f005832cf913ac556662ba794786e41c0e37a 100644 (file)
@@ -330,7 +330,6 @@ static void i82975x_check(struct mem_ctl_info *mci)
 {
        struct i82975x_error_info info;
 
-       edac_dbg(1, "MC%d\n", mci->mc_idx);
        i82975x_get_error_info(mci, &info);
        i82975x_process_error_info(mci, &info, 1);
 }
index c47963240b6596bf4b189a4a8a7b9b7126788f91..9a9ff5ad611acf5ed490211f9170285b4935f9f3 100644 (file)
@@ -333,7 +333,6 @@ static void ie31200_check(struct mem_ctl_info *mci)
 {
        struct ie31200_error_info info;
 
-       edac_dbg(1, "MC%d\n", mci->mc_idx);
        ie31200_get_and_clear_error_info(mci, &info);
        ie31200_process_error_info(mci, &info);
 }
diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c
deleted file mode 100644 (file)
index 3c68bb5..0000000
+++ /dev/null
@@ -1,883 +0,0 @@
-/*
- * Marvell MV64x60 Memory Controller kernel module for PPC platforms
- *
- * Author: Dave Jiang <djiang@mvista.com>
- *
- * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/edac.h>
-#include <linux/gfp.h>
-
-#include "edac_module.h"
-#include "mv64x60_edac.h"
-
-static const char *mv64x60_ctl_name = "MV64x60";
-static int edac_dev_idx;
-static int edac_pci_idx;
-static int edac_mc_idx;
-
-/*********************** PCI err device **********************************/
-#ifdef CONFIG_PCI
-static void mv64x60_pci_check(struct edac_pci_ctl_info *pci)
-{
-       struct mv64x60_pci_pdata *pdata = pci->pvt_info;
-       u32 cause;
-
-       cause = readl(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
-       if (!cause)
-               return;
-
-       printk(KERN_ERR "Error in PCI %d Interface\n", pdata->pci_hose);
-       printk(KERN_ERR "Cause register: 0x%08x\n", cause);
-       printk(KERN_ERR "Address Low: 0x%08x\n",
-              readl(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_LO));
-       printk(KERN_ERR "Address High: 0x%08x\n",
-              readl(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_HI));
-       printk(KERN_ERR "Attribute: 0x%08x\n",
-              readl(pdata->pci_vbase + MV64X60_PCI_ERROR_ATTR));
-       printk(KERN_ERR "Command: 0x%08x\n",
-              readl(pdata->pci_vbase + MV64X60_PCI_ERROR_CMD));
-       writel(~cause, pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
-
-       if (cause & MV64X60_PCI_PE_MASK)
-               edac_pci_handle_pe(pci, pci->ctl_name);
-
-       if (!(cause & MV64X60_PCI_PE_MASK))
-               edac_pci_handle_npe(pci, pci->ctl_name);
-}
-
-static irqreturn_t mv64x60_pci_isr(int irq, void *dev_id)
-{
-       struct edac_pci_ctl_info *pci = dev_id;
-       struct mv64x60_pci_pdata *pdata = pci->pvt_info;
-       u32 val;
-
-       val = readl(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
-       if (!val)
-               return IRQ_NONE;
-
-       mv64x60_pci_check(pci);
-
-       return IRQ_HANDLED;
-}
-
-/*
- * Bit 0 of MV64x60_PCIx_ERR_MASK does not exist on the 64360 and because of
- * errata FEr-#11 and FEr-##16 for the 64460, it should be 0 on that chip as
- * well.  IOW, don't set bit 0.
- */
-
-/* Erratum FEr PCI-#16: clear bit 0 of PCI SERRn Mask reg. */
-static int __init mv64x60_pci_fixup(struct platform_device *pdev)
-{
-       struct resource *r;
-       void __iomem *pci_serr;
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!r) {
-               printk(KERN_ERR "%s: Unable to get resource for "
-                      "PCI err regs\n", __func__);
-               return -ENOENT;
-       }
-
-       pci_serr = ioremap(r->start, resource_size(r));
-       if (!pci_serr)
-               return -ENOMEM;
-
-       writel(readl(pci_serr) & ~0x1, pci_serr);
-       iounmap(pci_serr);
-
-       return 0;
-}
-
-static int mv64x60_pci_err_probe(struct platform_device *pdev)
-{
-       struct edac_pci_ctl_info *pci;
-       struct mv64x60_pci_pdata *pdata;
-       struct resource *r;
-       int res = 0;
-
-       if (!devres_open_group(&pdev->dev, mv64x60_pci_err_probe, GFP_KERNEL))
-               return -ENOMEM;
-
-       pci = edac_pci_alloc_ctl_info(sizeof(*pdata), "mv64x60_pci_err");
-       if (!pci)
-               return -ENOMEM;
-
-       pdata = pci->pvt_info;
-
-       pdata->pci_hose = pdev->id;
-       pdata->name = "mv64x60_pci_err";
-       platform_set_drvdata(pdev, pci);
-       pci->dev = &pdev->dev;
-       pci->dev_name = dev_name(&pdev->dev);
-       pci->mod_name = EDAC_MOD_STR;
-       pci->ctl_name = pdata->name;
-
-       if (edac_op_state == EDAC_OPSTATE_POLL)
-               pci->edac_check = mv64x60_pci_check;
-
-       pdata->edac_idx = edac_pci_idx++;
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
-               printk(KERN_ERR "%s: Unable to get resource for "
-                      "PCI err regs\n", __func__);
-               res = -ENOENT;
-               goto err;
-       }
-
-       if (!devm_request_mem_region(&pdev->dev,
-                                    r->start,
-                                    resource_size(r),
-                                    pdata->name)) {
-               printk(KERN_ERR "%s: Error while requesting mem region\n",
-                      __func__);
-               res = -EBUSY;
-               goto err;
-       }
-
-       pdata->pci_vbase = devm_ioremap(&pdev->dev,
-                                       r->start,
-                                       resource_size(r));
-       if (!pdata->pci_vbase) {
-               printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__);
-               res = -ENOMEM;
-               goto err;
-       }
-
-       res = mv64x60_pci_fixup(pdev);
-       if (res < 0) {
-               printk(KERN_ERR "%s: PCI fixup failed\n", __func__);
-               goto err;
-       }
-
-       writel(0, pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
-       writel(0, pdata->pci_vbase + MV64X60_PCI_ERROR_MASK);
-       writel(MV64X60_PCIx_ERR_MASK_VAL,
-                 pdata->pci_vbase + MV64X60_PCI_ERROR_MASK);
-
-       if (edac_pci_add_device(pci, pdata->edac_idx) > 0) {
-               edac_dbg(3, "failed edac_pci_add_device()\n");
-               goto err;
-       }
-
-       if (edac_op_state == EDAC_OPSTATE_INT) {
-               pdata->irq = platform_get_irq(pdev, 0);
-               res = devm_request_irq(&pdev->dev,
-                                      pdata->irq,
-                                      mv64x60_pci_isr,
-                                      0,
-                                      "[EDAC] PCI err",
-                                      pci);
-               if (res < 0) {
-                       printk(KERN_ERR "%s: Unable to request irq %d for "
-                              "MV64x60 PCI ERR\n", __func__, pdata->irq);
-                       res = -ENODEV;
-                       goto err2;
-               }
-               printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for PCI Err\n",
-                      pdata->irq);
-       }
-
-       devres_remove_group(&pdev->dev, mv64x60_pci_err_probe);
-
-       /* get this far and it's successful */
-       edac_dbg(3, "success\n");
-
-       return 0;
-
-err2:
-       edac_pci_del_device(&pdev->dev);
-err:
-       edac_pci_free_ctl_info(pci);
-       devres_release_group(&pdev->dev, mv64x60_pci_err_probe);
-       return res;
-}
-
-static int mv64x60_pci_err_remove(struct platform_device *pdev)
-{
-       struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev);
-
-       edac_dbg(0, "\n");
-
-       edac_pci_del_device(&pdev->dev);
-
-       edac_pci_free_ctl_info(pci);
-
-       return 0;
-}
-
-static struct platform_driver mv64x60_pci_err_driver = {
-       .probe = mv64x60_pci_err_probe,
-       .remove = mv64x60_pci_err_remove,
-       .driver = {
-                  .name = "mv64x60_pci_err",
-       }
-};
-
-#endif /* CONFIG_PCI */
-
-/*********************** SRAM err device **********************************/
-static void mv64x60_sram_check(struct edac_device_ctl_info *edac_dev)
-{
-       struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info;
-       u32 cause;
-
-       cause = readl(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
-       if (!cause)
-               return;
-
-       printk(KERN_ERR "Error in internal SRAM\n");
-       printk(KERN_ERR "Cause register: 0x%08x\n", cause);
-       printk(KERN_ERR "Address Low: 0x%08x\n",
-              readl(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_LO));
-       printk(KERN_ERR "Address High: 0x%08x\n",
-              readl(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_HI));
-       printk(KERN_ERR "Data Low: 0x%08x\n",
-              readl(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_LO));
-       printk(KERN_ERR "Data High: 0x%08x\n",
-              readl(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_HI));
-       printk(KERN_ERR "Parity: 0x%08x\n",
-              readl(pdata->sram_vbase + MV64X60_SRAM_ERR_PARITY));
-       writel(0, pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
-
-       edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
-}
-
-static irqreturn_t mv64x60_sram_isr(int irq, void *dev_id)
-{
-       struct edac_device_ctl_info *edac_dev = dev_id;
-       struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info;
-       u32 cause;
-
-       cause = readl(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
-       if (!cause)
-               return IRQ_NONE;
-
-       mv64x60_sram_check(edac_dev);
-
-       return IRQ_HANDLED;
-}
-
-static int mv64x60_sram_err_probe(struct platform_device *pdev)
-{
-       struct edac_device_ctl_info *edac_dev;
-       struct mv64x60_sram_pdata *pdata;
-       struct resource *r;
-       int res = 0;
-
-       if (!devres_open_group(&pdev->dev, mv64x60_sram_err_probe, GFP_KERNEL))
-               return -ENOMEM;
-
-       edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata),
-                                             "sram", 1, NULL, 0, 0, NULL, 0,
-                                             edac_dev_idx);
-       if (!edac_dev) {
-               devres_release_group(&pdev->dev, mv64x60_sram_err_probe);
-               return -ENOMEM;
-       }
-
-       pdata = edac_dev->pvt_info;
-       pdata->name = "mv64x60_sram_err";
-       edac_dev->dev = &pdev->dev;
-       platform_set_drvdata(pdev, edac_dev);
-       edac_dev->dev_name = dev_name(&pdev->dev);
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
-               printk(KERN_ERR "%s: Unable to get resource for "
-                      "SRAM err regs\n", __func__);
-               res = -ENOENT;
-               goto err;
-       }
-
-       if (!devm_request_mem_region(&pdev->dev,
-                                    r->start,
-                                    resource_size(r),
-                                    pdata->name)) {
-               printk(KERN_ERR "%s: Error while request mem region\n",
-                      __func__);
-               res = -EBUSY;
-               goto err;
-       }
-
-       pdata->sram_vbase = devm_ioremap(&pdev->dev,
-                                        r->start,
-                                        resource_size(r));
-       if (!pdata->sram_vbase) {
-               printk(KERN_ERR "%s: Unable to setup SRAM err regs\n",
-                      __func__);
-               res = -ENOMEM;
-               goto err;
-       }
-
-       /* setup SRAM err registers */
-       writel(0, pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
-
-       edac_dev->mod_name = EDAC_MOD_STR;
-       edac_dev->ctl_name = pdata->name;
-
-       if (edac_op_state == EDAC_OPSTATE_POLL)
-               edac_dev->edac_check = mv64x60_sram_check;
-
-       pdata->edac_idx = edac_dev_idx++;
-
-       if (edac_device_add_device(edac_dev) > 0) {
-               edac_dbg(3, "failed edac_device_add_device()\n");
-               goto err;
-       }
-
-       if (edac_op_state == EDAC_OPSTATE_INT) {
-               pdata->irq = platform_get_irq(pdev, 0);
-               res = devm_request_irq(&pdev->dev,
-                                      pdata->irq,
-                                      mv64x60_sram_isr,
-                                      0,
-                                      "[EDAC] SRAM err",
-                                      edac_dev);
-               if (res < 0) {
-                       printk(KERN_ERR
-                              "%s: Unable to request irq %d for "
-                              "MV64x60 SRAM ERR\n", __func__, pdata->irq);
-                       res = -ENODEV;
-                       goto err2;
-               }
-
-               printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for SRAM Err\n",
-                      pdata->irq);
-       }
-
-       devres_remove_group(&pdev->dev, mv64x60_sram_err_probe);
-
-       /* get this far and it's successful */
-       edac_dbg(3, "success\n");
-
-       return 0;
-
-err2:
-       edac_device_del_device(&pdev->dev);
-err:
-       devres_release_group(&pdev->dev, mv64x60_sram_err_probe);
-       edac_device_free_ctl_info(edac_dev);
-       return res;
-}
-
-static int mv64x60_sram_err_remove(struct platform_device *pdev)
-{
-       struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev);
-
-       edac_dbg(0, "\n");
-
-       edac_device_del_device(&pdev->dev);
-       edac_device_free_ctl_info(edac_dev);
-
-       return 0;
-}
-
-static struct platform_driver mv64x60_sram_err_driver = {
-       .probe = mv64x60_sram_err_probe,
-       .remove = mv64x60_sram_err_remove,
-       .driver = {
-                  .name = "mv64x60_sram_err",
-       }
-};
-
-/*********************** CPU err device **********************************/
-static void mv64x60_cpu_check(struct edac_device_ctl_info *edac_dev)
-{
-       struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info;
-       u32 cause;
-
-       cause = readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) &
-           MV64x60_CPU_CAUSE_MASK;
-       if (!cause)
-               return;
-
-       printk(KERN_ERR "Error on CPU interface\n");
-       printk(KERN_ERR "Cause register: 0x%08x\n", cause);
-       printk(KERN_ERR "Address Low: 0x%08x\n",
-              readl(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_LO));
-       printk(KERN_ERR "Address High: 0x%08x\n",
-              readl(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_HI));
-       printk(KERN_ERR "Data Low: 0x%08x\n",
-              readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_LO));
-       printk(KERN_ERR "Data High: 0x%08x\n",
-              readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_HI));
-       printk(KERN_ERR "Parity: 0x%08x\n",
-              readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_PARITY));
-       writel(0, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE);
-
-       edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
-}
-
-static irqreturn_t mv64x60_cpu_isr(int irq, void *dev_id)
-{
-       struct edac_device_ctl_info *edac_dev = dev_id;
-       struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info;
-       u32 cause;
-
-       cause = readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) &
-           MV64x60_CPU_CAUSE_MASK;
-       if (!cause)
-               return IRQ_NONE;
-
-       mv64x60_cpu_check(edac_dev);
-
-       return IRQ_HANDLED;
-}
-
-static int mv64x60_cpu_err_probe(struct platform_device *pdev)
-{
-       struct edac_device_ctl_info *edac_dev;
-       struct resource *r;
-       struct mv64x60_cpu_pdata *pdata;
-       int res = 0;
-
-       if (!devres_open_group(&pdev->dev, mv64x60_cpu_err_probe, GFP_KERNEL))
-               return -ENOMEM;
-
-       edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata),
-                                             "cpu", 1, NULL, 0, 0, NULL, 0,
-                                             edac_dev_idx);
-       if (!edac_dev) {
-               devres_release_group(&pdev->dev, mv64x60_cpu_err_probe);
-               return -ENOMEM;
-       }
-
-       pdata = edac_dev->pvt_info;
-       pdata->name = "mv64x60_cpu_err";
-       edac_dev->dev = &pdev->dev;
-       platform_set_drvdata(pdev, edac_dev);
-       edac_dev->dev_name = dev_name(&pdev->dev);
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
-               printk(KERN_ERR "%s: Unable to get resource for "
-                      "CPU err regs\n", __func__);
-               res = -ENOENT;
-               goto err;
-       }
-
-       if (!devm_request_mem_region(&pdev->dev,
-                                    r->start,
-                                    resource_size(r),
-                                    pdata->name)) {
-               printk(KERN_ERR "%s: Error while requesting mem region\n",
-                      __func__);
-               res = -EBUSY;
-               goto err;
-       }
-
-       pdata->cpu_vbase[0] = devm_ioremap(&pdev->dev,
-                                          r->start,
-                                          resource_size(r));
-       if (!pdata->cpu_vbase[0]) {
-               printk(KERN_ERR "%s: Unable to setup CPU err regs\n", __func__);
-               res = -ENOMEM;
-               goto err;
-       }
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!r) {
-               printk(KERN_ERR "%s: Unable to get resource for "
-                      "CPU err regs\n", __func__);
-               res = -ENOENT;
-               goto err;
-       }
-
-       if (!devm_request_mem_region(&pdev->dev,
-                                    r->start,
-                                    resource_size(r),
-                                    pdata->name)) {
-               printk(KERN_ERR "%s: Error while requesting mem region\n",
-                      __func__);
-               res = -EBUSY;
-               goto err;
-       }
-
-       pdata->cpu_vbase[1] = devm_ioremap(&pdev->dev,
-                                          r->start,
-                                          resource_size(r));
-       if (!pdata->cpu_vbase[1]) {
-               printk(KERN_ERR "%s: Unable to setup CPU err regs\n", __func__);
-               res = -ENOMEM;
-               goto err;
-       }
-
-       /* setup CPU err registers */
-       writel(0, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE);
-       writel(0, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK);
-       writel(0x000000ff, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK);
-
-       edac_dev->mod_name = EDAC_MOD_STR;
-       edac_dev->ctl_name = pdata->name;
-       if (edac_op_state == EDAC_OPSTATE_POLL)
-               edac_dev->edac_check = mv64x60_cpu_check;
-
-       pdata->edac_idx = edac_dev_idx++;
-
-       if (edac_device_add_device(edac_dev) > 0) {
-               edac_dbg(3, "failed edac_device_add_device()\n");
-               goto err;
-       }
-
-       if (edac_op_state == EDAC_OPSTATE_INT) {
-               pdata->irq = platform_get_irq(pdev, 0);
-               res = devm_request_irq(&pdev->dev,
-                                      pdata->irq,
-                                      mv64x60_cpu_isr,
-                                      0,
-                                      "[EDAC] CPU err",
-                                      edac_dev);
-               if (res < 0) {
-                       printk(KERN_ERR
-                              "%s: Unable to request irq %d for MV64x60 "
-                              "CPU ERR\n", __func__, pdata->irq);
-                       res = -ENODEV;
-                       goto err2;
-               }
-
-               printk(KERN_INFO EDAC_MOD_STR
-                      " acquired irq %d for CPU Err\n", pdata->irq);
-       }
-
-       devres_remove_group(&pdev->dev, mv64x60_cpu_err_probe);
-
-       /* get this far and it's successful */
-       edac_dbg(3, "success\n");
-
-       return 0;
-
-err2:
-       edac_device_del_device(&pdev->dev);
-err:
-       devres_release_group(&pdev->dev, mv64x60_cpu_err_probe);
-       edac_device_free_ctl_info(edac_dev);
-       return res;
-}
-
-static int mv64x60_cpu_err_remove(struct platform_device *pdev)
-{
-       struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev);
-
-       edac_dbg(0, "\n");
-
-       edac_device_del_device(&pdev->dev);
-       edac_device_free_ctl_info(edac_dev);
-       return 0;
-}
-
-static struct platform_driver mv64x60_cpu_err_driver = {
-       .probe = mv64x60_cpu_err_probe,
-       .remove = mv64x60_cpu_err_remove,
-       .driver = {
-                  .name = "mv64x60_cpu_err",
-       }
-};
-
-/*********************** DRAM err device **********************************/
-
-static void mv64x60_mc_check(struct mem_ctl_info *mci)
-{
-       struct mv64x60_mc_pdata *pdata = mci->pvt_info;
-       u32 reg;
-       u32 err_addr;
-       u32 sdram_ecc;
-       u32 comp_ecc;
-       u32 syndrome;
-
-       reg = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
-       if (!reg)
-               return;
-
-       err_addr = reg & ~0x3;
-       sdram_ecc = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_RCVD);
-       comp_ecc = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CALC);
-       syndrome = sdram_ecc ^ comp_ecc;
-
-       /* first bit clear in ECC Err Reg, 1 bit error, correctable by HW */
-       if (!(reg & 0x1))
-               edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
-                                    err_addr >> PAGE_SHIFT,
-                                    err_addr & PAGE_MASK, syndrome,
-                                    0, 0, -1,
-                                    mci->ctl_name, "");
-       else    /* 2 bit error, UE */
-               edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
-                                    err_addr >> PAGE_SHIFT,
-                                    err_addr & PAGE_MASK, 0,
-                                    0, 0, -1,
-                                    mci->ctl_name, "");
-
-       /* clear the error */
-       writel(0, pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
-}
-
-static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id)
-{
-       struct mem_ctl_info *mci = dev_id;
-       struct mv64x60_mc_pdata *pdata = mci->pvt_info;
-       u32 reg;
-
-       reg = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
-       if (!reg)
-               return IRQ_NONE;
-
-       /* writing 0's to the ECC err addr in check function clears irq */
-       mv64x60_mc_check(mci);
-
-       return IRQ_HANDLED;
-}
-
-static void get_total_mem(struct mv64x60_mc_pdata *pdata)
-{
-       struct device_node *np = NULL;
-       const unsigned int *reg;
-
-       np = of_find_node_by_type(NULL, "memory");
-       if (!np)
-               return;
-
-       reg = of_get_property(np, "reg", NULL);
-
-       pdata->total_mem = reg[1];
-}
-
-static void mv64x60_init_csrows(struct mem_ctl_info *mci,
-                               struct mv64x60_mc_pdata *pdata)
-{
-       struct csrow_info *csrow;
-       struct dimm_info *dimm;
-
-       u32 devtype;
-       u32 ctl;
-
-       get_total_mem(pdata);
-
-       ctl = readl(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
-
-       csrow = mci->csrows[0];
-       dimm = csrow->channels[0]->dimm;
-
-       dimm->nr_pages = pdata->total_mem >> PAGE_SHIFT;
-       dimm->grain = 8;
-
-       dimm->mtype = (ctl & MV64X60_SDRAM_REGISTERED) ? MEM_RDDR : MEM_DDR;
-
-       devtype = (ctl >> 20) & 0x3;
-       switch (devtype) {
-       case 0x0:
-               dimm->dtype = DEV_X32;
-               break;
-       case 0x2:               /* could be X8 too, but no way to tell */
-               dimm->dtype = DEV_X16;
-               break;
-       case 0x3:
-               dimm->dtype = DEV_X4;
-               break;
-       default:
-               dimm->dtype = DEV_UNKNOWN;
-               break;
-       }
-
-       dimm->edac_mode = EDAC_SECDED;
-}
-
-static int mv64x60_mc_err_probe(struct platform_device *pdev)
-{
-       struct mem_ctl_info *mci;
-       struct edac_mc_layer layers[2];
-       struct mv64x60_mc_pdata *pdata;
-       struct resource *r;
-       u32 ctl;
-       int res = 0;
-
-       if (!devres_open_group(&pdev->dev, mv64x60_mc_err_probe, GFP_KERNEL))
-               return -ENOMEM;
-
-       layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
-       layers[0].size = 1;
-       layers[0].is_virt_csrow = true;
-       layers[1].type = EDAC_MC_LAYER_CHANNEL;
-       layers[1].size = 1;
-       layers[1].is_virt_csrow = false;
-       mci = edac_mc_alloc(edac_mc_idx, ARRAY_SIZE(layers), layers,
-                           sizeof(struct mv64x60_mc_pdata));
-       if (!mci) {
-               printk(KERN_ERR "%s: No memory for CPU err\n", __func__);
-               devres_release_group(&pdev->dev, mv64x60_mc_err_probe);
-               return -ENOMEM;
-       }
-
-       pdata = mci->pvt_info;
-       mci->pdev = &pdev->dev;
-       platform_set_drvdata(pdev, mci);
-       pdata->name = "mv64x60_mc_err";
-       mci->dev_name = dev_name(&pdev->dev);
-       pdata->edac_idx = edac_mc_idx++;
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
-               printk(KERN_ERR "%s: Unable to get resource for "
-                      "MC err regs\n", __func__);
-               res = -ENOENT;
-               goto err;
-       }
-
-       if (!devm_request_mem_region(&pdev->dev,
-                                    r->start,
-                                    resource_size(r),
-                                    pdata->name)) {
-               printk(KERN_ERR "%s: Error while requesting mem region\n",
-                      __func__);
-               res = -EBUSY;
-               goto err;
-       }
-
-       pdata->mc_vbase = devm_ioremap(&pdev->dev,
-                                      r->start,
-                                      resource_size(r));
-       if (!pdata->mc_vbase) {
-               printk(KERN_ERR "%s: Unable to setup MC err regs\n", __func__);
-               res = -ENOMEM;
-               goto err;
-       }
-
-       ctl = readl(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
-       if (!(ctl & MV64X60_SDRAM_ECC)) {
-               /* Non-ECC RAM? */
-               printk(KERN_WARNING "%s: No ECC DIMMs discovered\n", __func__);
-               res = -ENODEV;
-               goto err;
-       }
-
-       edac_dbg(3, "init mci\n");
-       mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
-       mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
-       mci->edac_cap = EDAC_FLAG_SECDED;
-       mci->mod_name = EDAC_MOD_STR;
-       mci->ctl_name = mv64x60_ctl_name;
-
-       if (edac_op_state == EDAC_OPSTATE_POLL)
-               mci->edac_check = mv64x60_mc_check;
-
-       mci->ctl_page_to_phys = NULL;
-
-       mci->scrub_mode = SCRUB_SW_SRC;
-
-       mv64x60_init_csrows(mci, pdata);
-
-       /* setup MC registers */
-       writel(0, pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
-       ctl = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL);
-       ctl = (ctl & 0xff00ffff) | 0x10000;
-       writel(ctl, pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL);
-
-       res = edac_mc_add_mc(mci);
-       if (res) {
-               edac_dbg(3, "failed edac_mc_add_mc()\n");
-               goto err;
-       }
-
-       if (edac_op_state == EDAC_OPSTATE_INT) {
-               /* acquire interrupt that reports errors */
-               pdata->irq = platform_get_irq(pdev, 0);
-               res = devm_request_irq(&pdev->dev,
-                                      pdata->irq,
-                                      mv64x60_mc_isr,
-                                      0,
-                                      "[EDAC] MC err",
-                                      mci);
-               if (res < 0) {
-                       printk(KERN_ERR "%s: Unable to request irq %d for "
-                              "MV64x60 DRAM ERR\n", __func__, pdata->irq);
-                       res = -ENODEV;
-                       goto err2;
-               }
-
-               printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for MC Err\n",
-                      pdata->irq);
-       }
-
-       /* get this far and it's successful */
-       edac_dbg(3, "success\n");
-
-       return 0;
-
-err2:
-       edac_mc_del_mc(&pdev->dev);
-err:
-       devres_release_group(&pdev->dev, mv64x60_mc_err_probe);
-       edac_mc_free(mci);
-       return res;
-}
-
-static int mv64x60_mc_err_remove(struct platform_device *pdev)
-{
-       struct mem_ctl_info *mci = platform_get_drvdata(pdev);
-
-       edac_dbg(0, "\n");
-
-       edac_mc_del_mc(&pdev->dev);
-       edac_mc_free(mci);
-       return 0;
-}
-
-static struct platform_driver mv64x60_mc_err_driver = {
-       .probe = mv64x60_mc_err_probe,
-       .remove = mv64x60_mc_err_remove,
-       .driver = {
-                  .name = "mv64x60_mc_err",
-       }
-};
-
-static struct platform_driver * const drivers[] = {
-       &mv64x60_mc_err_driver,
-       &mv64x60_cpu_err_driver,
-       &mv64x60_sram_err_driver,
-#ifdef CONFIG_PCI
-       &mv64x60_pci_err_driver,
-#endif
-};
-
-static int __init mv64x60_edac_init(void)
-{
-
-       printk(KERN_INFO "Marvell MV64x60 EDAC driver " MV64x60_REVISION "\n");
-       printk(KERN_INFO "\t(C) 2006-2007 MontaVista Software\n");
-
-       /* make sure error reporting method is sane */
-       switch (edac_op_state) {
-       case EDAC_OPSTATE_POLL:
-       case EDAC_OPSTATE_INT:
-               break;
-       default:
-               edac_op_state = EDAC_OPSTATE_INT;
-               break;
-       }
-
-       return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
-}
-module_init(mv64x60_edac_init);
-
-static void __exit mv64x60_edac_exit(void)
-{
-       platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
-}
-module_exit(mv64x60_edac_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Montavista Software, Inc.");
-module_param(edac_op_state, int, 0444);
-MODULE_PARM_DESC(edac_op_state,
-                "EDAC Error Reporting state: 0=Poll, 2=Interrupt");
diff --git a/drivers/edac/mv64x60_edac.h b/drivers/edac/mv64x60_edac.h
deleted file mode 100644 (file)
index c7f209c..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * EDAC defs for Marvell MV64x60 bridge chip
- *
- * Author: Dave Jiang <djiang@mvista.com>
- *
- * 2007 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- *
- */
-#ifndef _MV64X60_EDAC_H_
-#define _MV64X60_EDAC_H_
-
-#define MV64x60_REVISION " Ver: 2.0.0"
-#define EDAC_MOD_STR   "MV64x60_edac"
-
-#define mv64x60_printk(level, fmt, arg...) \
-       edac_printk(level, "MV64x60", fmt, ##arg)
-
-#define mv64x60_mc_printk(mci, level, fmt, arg...) \
-       edac_mc_chipset_printk(mci, level, "MV64x60", fmt, ##arg)
-
-/* CPU Error Report Registers */
-#define MV64x60_CPU_ERR_ADDR_LO                0x00    /* 0x0070 */
-#define MV64x60_CPU_ERR_ADDR_HI                0x08    /* 0x0078 */
-#define MV64x60_CPU_ERR_DATA_LO                0x00    /* 0x0128 */
-#define MV64x60_CPU_ERR_DATA_HI                0x08    /* 0x0130 */
-#define MV64x60_CPU_ERR_PARITY         0x10    /* 0x0138 */
-#define MV64x60_CPU_ERR_CAUSE          0x18    /* 0x0140 */
-#define MV64x60_CPU_ERR_MASK           0x20    /* 0x0148 */
-
-#define MV64x60_CPU_CAUSE_MASK         0x07ffffff
-
-/* SRAM Error Report Registers */
-#define MV64X60_SRAM_ERR_CAUSE         0x08    /* 0x0388 */
-#define MV64X60_SRAM_ERR_ADDR_LO       0x10    /* 0x0390 */
-#define MV64X60_SRAM_ERR_ADDR_HI       0x78    /* 0x03f8 */
-#define MV64X60_SRAM_ERR_DATA_LO       0x18    /* 0x0398 */
-#define MV64X60_SRAM_ERR_DATA_HI       0x20    /* 0x03a0 */
-#define MV64X60_SRAM_ERR_PARITY                0x28    /* 0x03a8 */
-
-/* SDRAM Controller Registers */
-#define MV64X60_SDRAM_CONFIG           0x00    /* 0x1400 */
-#define MV64X60_SDRAM_ERR_DATA_HI      0x40    /* 0x1440 */
-#define MV64X60_SDRAM_ERR_DATA_LO      0x44    /* 0x1444 */
-#define MV64X60_SDRAM_ERR_ECC_RCVD     0x48    /* 0x1448 */
-#define MV64X60_SDRAM_ERR_ECC_CALC     0x4c    /* 0x144c */
-#define MV64X60_SDRAM_ERR_ADDR         0x50    /* 0x1450 */
-#define MV64X60_SDRAM_ERR_ECC_CNTL     0x54    /* 0x1454 */
-#define MV64X60_SDRAM_ERR_ECC_ERR_CNT  0x58    /* 0x1458 */
-
-#define MV64X60_SDRAM_REGISTERED       0x20000
-#define MV64X60_SDRAM_ECC              0x40000
-
-#ifdef CONFIG_PCI
-/*
- * Bit 0 of MV64x60_PCIx_ERR_MASK does not exist on the 64360 and because of
- * errata FEr-#11 and FEr-##16 for the 64460, it should be 0 on that chip as
- * well.  IOW, don't set bit 0.
- */
-#define MV64X60_PCIx_ERR_MASK_VAL      0x00a50c24
-
-/* Register offsets from PCIx error address low register */
-#define MV64X60_PCI_ERROR_ADDR_LO      0x00
-#define MV64X60_PCI_ERROR_ADDR_HI      0x04
-#define MV64X60_PCI_ERROR_ATTR         0x08
-#define MV64X60_PCI_ERROR_CMD          0x10
-#define MV64X60_PCI_ERROR_CAUSE                0x18
-#define MV64X60_PCI_ERROR_MASK         0x1c
-
-#define MV64X60_PCI_ERR_SWrPerr                0x0002
-#define MV64X60_PCI_ERR_SRdPerr                0x0004
-#define        MV64X60_PCI_ERR_MWrPerr         0x0020
-#define MV64X60_PCI_ERR_MRdPerr                0x0040
-
-#define MV64X60_PCI_PE_MASK    (MV64X60_PCI_ERR_SWrPerr | \
-                               MV64X60_PCI_ERR_SRdPerr | \
-                               MV64X60_PCI_ERR_MWrPerr | \
-                               MV64X60_PCI_ERR_MRdPerr)
-
-struct mv64x60_pci_pdata {
-       int pci_hose;
-       void __iomem *pci_vbase;
-       char *name;
-       int irq;
-       int edac_idx;
-};
-
-#endif                         /* CONFIG_PCI */
-
-struct mv64x60_mc_pdata {
-       void __iomem *mc_vbase;
-       int total_mem;
-       char *name;
-       int irq;
-       int edac_idx;
-};
-
-struct mv64x60_cpu_pdata {
-       void __iomem *cpu_vbase[2];
-       char *name;
-       int irq;
-       int edac_idx;
-};
-
-struct mv64x60_sram_pdata {
-       void __iomem *sram_vbase;
-       char *name;
-       int irq;
-       int edac_idx;
-};
-
-#endif
index 851e53e122aab01dc41e8c34bcdc9a2a23698eb4..d0aef83dca2a2b047648fb932dbdaedd6b844f70 100644 (file)
@@ -204,7 +204,6 @@ static void r82600_check(struct mem_ctl_info *mci)
 {
        struct r82600_error_info info;
 
-       edac_dbg(1, "MC%d\n", mci->mc_idx);
        r82600_get_error_info(mci, &info);
        r82600_process_error_info(mci, &info, 1);
 }
index 2c7db95df32631edbb10f417e431296d70973c0b..6a4f0b27c65457267018b01d8f341d18e06c8a82 100644 (file)
@@ -174,7 +174,7 @@ static bool skx_check_ecc(u32 mcmtr)
        return !!GET_BITFIELD(mcmtr, 2, 2);
 }
 
-static int skx_get_dimm_config(struct mem_ctl_info *mci)
+static int skx_get_dimm_config(struct mem_ctl_info *mci, struct res_config *cfg)
 {
        struct skx_pvt *pvt = mci->pvt_info;
        u32 mtr, mcmtr, amap, mcddrtcfg;
@@ -195,7 +195,7 @@ static int skx_get_dimm_config(struct mem_ctl_info *mci)
                        pci_read_config_dword(imc->chan[i].cdev,
                                              0x80 + 4 * j, &mtr);
                        if (IS_DIMM_PRESENT(mtr)) {
-                               ndimms += skx_get_dimm_info(mtr, mcmtr, amap, dimm, imc, i, j);
+                               ndimms += skx_get_dimm_info(mtr, mcmtr, amap, dimm, imc, i, j, cfg);
                        } else if (IS_NVDIMM_PRESENT(mcddrtcfg, j)) {
                                ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
                                                              EDAC_MOD_STR);
@@ -702,7 +702,7 @@ static int __init skx_init(void)
                        d->imc[i].node_id = node_id;
                        rc = skx_register_mci(&d->imc[i], d->imc[i].chan[0].cdev,
                                              "Skylake Socket", EDAC_MOD_STR,
-                                             skx_get_dimm_config);
+                                             skx_get_dimm_config, cfg);
                        if (rc < 0)
                                goto fail;
                }
index 2b4ce8e5ac2fa6e48721cea55e878784df57fdf4..81c3e2ec6f568a0b295774cc6bfdb3722e1af775 100644 (file)
@@ -304,15 +304,25 @@ static int skx_get_dimm_attr(u32 reg, int lobit, int hibit, int add,
 #define numcol(reg)    skx_get_dimm_attr(reg, 0, 1, 10, 0, 2, "cols")
 
 int skx_get_dimm_info(u32 mtr, u32 mcmtr, u32 amap, struct dimm_info *dimm,
-                     struct skx_imc *imc, int chan, int dimmno)
+                     struct skx_imc *imc, int chan, int dimmno,
+                     struct res_config *cfg)
 {
-       int  banks = 16, ranks, rows, cols, npages;
+       int  banks, ranks, rows, cols, npages;
+       enum mem_type mtype;
        u64 size;
 
        ranks = numrank(mtr);
        rows = numrow(mtr);
        cols = numcol(mtr);
 
+       if (cfg->support_ddr5 && (amap & 0x8)) {
+               banks = 32;
+               mtype = MEM_DDR5;
+       } else {
+               banks = 16;
+               mtype = MEM_DDR4;
+       }
+
        /*
         * Compute size in 8-byte (2^3) words, then shift to MiB (2^20)
         */
@@ -332,7 +342,7 @@ int skx_get_dimm_info(u32 mtr, u32 mcmtr, u32 amap, struct dimm_info *dimm,
        dimm->nr_pages = npages;
        dimm->grain = 32;
        dimm->dtype = get_width(mtr);
-       dimm->mtype = MEM_DDR4;
+       dimm->mtype = mtype;
        dimm->edac_mode = EDAC_SECDED; /* likely better than this */
        snprintf(dimm->label, sizeof(dimm->label), "CPU_SrcID#%u_MC#%u_Chan#%u_DIMM#%u",
                 imc->src_id, imc->lmc, chan, dimmno);
@@ -390,7 +400,8 @@ unknown_size:
 
 int skx_register_mci(struct skx_imc *imc, struct pci_dev *pdev,
                     const char *ctl_name, const char *mod_str,
-                    get_dimm_config_f get_dimm_config)
+                    get_dimm_config_f get_dimm_config,
+                    struct res_config *cfg)
 {
        struct mem_ctl_info *mci;
        struct edac_mc_layer layers[2];
@@ -425,13 +436,15 @@ int skx_register_mci(struct skx_imc *imc, struct pci_dev *pdev,
        }
 
        mci->mtype_cap = MEM_FLAG_DDR4 | MEM_FLAG_NVDIMM;
+       if (cfg->support_ddr5)
+               mci->mtype_cap |= MEM_FLAG_DDR5;
        mci->edac_ctl_cap = EDAC_FLAG_NONE;
        mci->edac_cap = EDAC_FLAG_NONE;
        mci->mod_name = mod_str;
        mci->dev_name = pci_name(pdev);
        mci->ctl_page_to_phys = NULL;
 
-       rc = get_dimm_config(mci);
+       rc = get_dimm_config(mci, cfg);
        if (rc < 0)
                goto fail;
 
index 78f8c1de0b71c80ddcdb7d64fc4bd63a064d0f3f..bf56bebff1384a56e42659469b7ed0725a336f6e 100644 (file)
@@ -59,6 +59,7 @@ struct skx_dev {
                struct mem_ctl_info *mci;
                struct pci_dev *mdev; /* for i10nm CPU */
                void __iomem *mbase;  /* for i10nm CPU */
+               int chan_mmio_sz;     /* for i10nm CPU */
                u8 mc;  /* system wide mc# */
                u8 lmc; /* socket relative mc# */
                u8 src_id, node_id;
@@ -82,7 +83,8 @@ struct skx_pvt {
 
 enum type {
        SKX,
-       I10NM
+       I10NM,
+       SPR
 };
 
 enum {
@@ -118,9 +120,13 @@ struct res_config {
        unsigned int decs_did;
        /* Default bus number configuration register offset */
        int busno_cfg_offset;
+       /* Per DDR channel memory-mapped I/O size */
+       int ddr_chan_mmio_sz;
+       bool support_ddr5;
 };
 
-typedef int (*get_dimm_config_f)(struct mem_ctl_info *mci);
+typedef int (*get_dimm_config_f)(struct mem_ctl_info *mci,
+                                struct res_config *cfg);
 typedef bool (*skx_decode_f)(struct decoded_addr *res);
 typedef void (*skx_show_retry_log_f)(struct decoded_addr *res, char *msg, int len);
 
@@ -136,14 +142,16 @@ int skx_get_all_bus_mappings(struct res_config *cfg, struct list_head **list);
 int skx_get_hi_lo(unsigned int did, int off[], u64 *tolm, u64 *tohm);
 
 int skx_get_dimm_info(u32 mtr, u32 mcmtr, u32 amap, struct dimm_info *dimm,
-                     struct skx_imc *imc, int chan, int dimmno);
+                     struct skx_imc *imc, int chan, int dimmno,
+                     struct res_config *cfg);
 
 int skx_get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc,
                        int chan, int dimmno, const char *mod_str);
 
 int skx_register_mci(struct skx_imc *imc, struct pci_dev *pdev,
                     const char *ctl_name, const char *mod_str,
-                    get_dimm_config_f get_dimm_config);
+                    get_dimm_config_f get_dimm_config,
+                    struct res_config *cfg);
 
 int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
                        void *data);
index 12211dc040e8f1050e59b61c420e2bff03b4a0be..7e7146b22c160739b75ef70a8f9811254d980200 100644 (file)
@@ -1344,7 +1344,8 @@ static int mc_probe(struct platform_device *pdev)
 
 #ifdef CONFIG_EDAC_DEBUG
        if (priv->p_data->quirks & DDR_ECC_DATA_POISON_SUPPORT) {
-               if (edac_create_sysfs_attributes(mci)) {
+               rc = edac_create_sysfs_attributes(mci);
+               if (rc) {
                        edac_printk(KERN_ERR, EDAC_MC,
                                        "Failed to create sysfs entries\n");
                        goto free_edac_mc;
index a65e2f78a402237500181e2368219d0d1c90da96..49ab5721aab25c36d9269c90332501077fc43b5b 100644 (file)
@@ -238,7 +238,6 @@ static void x38_check(struct mem_ctl_info *mci)
 {
        struct x38_error_info info;
 
-       edac_dbg(1, "MC%d\n", mci->mc_idx);
        x38_get_and_clear_error_info(mci, &info);
        x38_process_error_info(mci, &info);
 }
index 9853bd3c4d456b490855a36425935b29378427c6..017e5d8bd869a752d14bd7cdf58032e9d8a96787 100644 (file)
@@ -197,6 +197,8 @@ static int scmi_base_implementation_list_get(const struct scmi_handle *handle,
                        protocols_imp[tot_num_ret + loop] = *(list + loop);
 
                tot_num_ret += loop_num_ret;
+
+               scmi_reset_rx_to_maxsz(handle, t);
        } while (loop_num_ret);
 
        scmi_xfer_put(handle, t);
index c1cfe3ee3d55a826ff1f97ca8156873a61c212ca..4645677d86f1b1648bccfb99c9f88a2393a98dff 100644 (file)
@@ -192,6 +192,8 @@ scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id,
                }
 
                tot_rate_cnt += num_returned;
+
+               scmi_reset_rx_to_maxsz(handle, t);
                /*
                 * check for both returned and remaining to avoid infinite
                 * loop due to buggy firmware
index 37fb583f1bf5f9e1362b121ca6eb9796345009fc..65063fa948d412e41b81aff9489bcfd0802fd8e2 100644 (file)
@@ -147,6 +147,8 @@ int scmi_do_xfer_with_response(const struct scmi_handle *h,
                               struct scmi_xfer *xfer);
 int scmi_xfer_get_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
                       size_t tx_size, size_t rx_size, struct scmi_xfer **p);
+void scmi_reset_rx_to_maxsz(const struct scmi_handle *handle,
+                           struct scmi_xfer *xfer);
 int scmi_handle_put(const struct scmi_handle *handle);
 struct scmi_handle *scmi_handle_get(struct device *dev);
 void scmi_set_handle(struct scmi_device *scmi_dev);
index c5dea87edf8f2c61b6be519232434be9a91e6f50..3dfd8b6a0ebf789089c17d87a3348619fbccfc27 100644 (file)
@@ -402,6 +402,14 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
        return ret;
 }
 
+void scmi_reset_rx_to_maxsz(const struct scmi_handle *handle,
+                           struct scmi_xfer *xfer)
+{
+       struct scmi_info *info = handle_to_scmi_info(handle);
+
+       xfer->rx.len = info->desc->max_msg_size;
+}
+
 #define SCMI_MAX_RESPONSE_TIMEOUT      (2 * MSEC_PER_SEC)
 
 /**
index 2754f9d01636ae711eb31d8ca3f6f83c5bac02d6..ce336899d6366172487dab71e9c9ca77778f3848 100644 (file)
@@ -1403,15 +1403,21 @@ static void scmi_protocols_late_init(struct work_struct *work)
                                "finalized PENDING handler - key:%X\n",
                                hndl->key);
                        ret = scmi_event_handler_enable_events(hndl);
+                       if (ret) {
+                               dev_dbg(ni->handle->dev,
+                                       "purging INVALID handler - key:%X\n",
+                                       hndl->key);
+                               scmi_put_active_handler(ni, hndl);
+                       }
                } else {
                        ret = scmi_valid_pending_handler(ni, hndl);
-               }
-               if (ret) {
-                       dev_dbg(ni->handle->dev,
-                               "purging PENDING handler - key:%X\n",
-                               hndl->key);
-                       /* this hndl can be only a pending one */
-                       scmi_put_handler_unlocked(ni, hndl);
+                       if (ret) {
+                               dev_dbg(ni->handle->dev,
+                                       "purging PENDING handler - key:%X\n",
+                                       hndl->key);
+                               /* this hndl can be only a pending one */
+                               scmi_put_handler_unlocked(ni, hndl);
+                       }
                }
        }
        mutex_unlock(&ni->pending_mtx);
@@ -1468,7 +1474,7 @@ int scmi_notification_init(struct scmi_handle *handle)
        ni->gid = gid;
        ni->handle = handle;
 
-       ni->notify_wq = alloc_workqueue("scmi_notify",
+       ni->notify_wq = alloc_workqueue(dev_name(handle->dev),
                                        WQ_UNBOUND | WQ_FREEZABLE | WQ_SYSFS,
                                        0);
        if (!ni->notify_wq)
index ed475b40bd083a0d20424977cfa223633e1199f0..82fb3babff72133f67997491b30beb8a575d87c2 100644 (file)
@@ -304,6 +304,8 @@ scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain,
                }
 
                tot_opp_cnt += num_returned;
+
+               scmi_reset_rx_to_maxsz(handle, t);
                /*
                 * check for both returned and remaining to avoid infinite
                 * loop due to buggy firmware
index f063cfe17e0299b04185b47a070c18a779227a4b..a981a22cfe8912b4ae68bbadc18f275ada8c514f 100644 (file)
@@ -36,9 +36,7 @@ struct scmi_msg_reset_domain_reset {
 #define EXPLICIT_RESET_ASSERT  BIT(1)
 #define ASYNCHRONOUS_RESET     BIT(2)
        __le32 reset_state;
-#define ARCH_RESET_TYPE                BIT(31)
-#define COLD_RESET_STATE       BIT(0)
-#define ARCH_COLD_RESET                (ARCH_RESET_TYPE | COLD_RESET_STATE)
+#define ARCH_COLD_RESET                0
 };
 
 struct scmi_msg_reset_notify {
index 9703cf6356a0452c3af99d608c6ba52febd6c901..b4232d611033e5ff83168bf6a20772bbe6801c88 100644 (file)
@@ -166,6 +166,8 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
                }
 
                desc_index += num_returned;
+
+               scmi_reset_rx_to_maxsz(handle, t);
                /*
                 * check for both returned and remaining to avoid infinite
                 * loop due to buggy firmware
index 1a03c3ec02300226384d32ad2d1219e9dade9edf..82a82a5dc86ae0e7554256a33d1e9d1e10909901 100644 (file)
@@ -149,6 +149,6 @@ static const struct scmi_transport_ops scmi_smc_ops = {
 const struct scmi_desc scmi_smc_desc = {
        .ops = &scmi_smc_ops,
        .max_rx_timeout_ms = 30,
-       .max_msg = 1,
+       .max_msg = 20,
        .max_msg_size = 128,
 };
index 36ec1f7188934ca416992f9d5275421b6f3b74a4..d9895491ff34e374b1343ec29ce449404d6faa30 100644 (file)
@@ -270,7 +270,7 @@ config EFI_DEV_PATH_PARSER
 
 config EFI_EARLYCON
        def_bool y
-       depends on SERIAL_EARLYCON && !ARM && !IA64
+       depends on EFI && SERIAL_EARLYCON && !ARM && !IA64
        select FONT_SUPPORT
        select ARCH_USE_MEMREMAP_PROT
 
index 5e5480a0a32d7dc91cd56acd5b0af9d6a0c59e26..6c6eec044a978a03821dbb0f0b3e2a6ed1814aa4 100644 (file)
@@ -390,10 +390,10 @@ static int __init efisubsys_init(void)
 
        if (efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE |
                                      EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME)) {
-               efivar_ssdt_load();
                error = generic_ops_register();
                if (error)
                        goto err_put;
+               efivar_ssdt_load();
                platform_device_register_simple("efivars", 0, NULL, 0);
        }
 
index 8d1ff2454e2e3aa49dfe1350995b63b650bf44dd..d08ac824c993ce978881b424a242890dbd1e8eee 100644 (file)
 #include <linux/of_platform.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#include <linux/hashtable.h>
 
 #include <linux/firmware/xlnx-zynqmp.h>
 #include "zynqmp-debug.h"
 
+/* Max HashMap Order for PM API feature check (1<<7 = 128) */
+#define PM_API_FEATURE_CHECK_MAX_ORDER  7
+
 static bool feature_check_enabled;
-static u32 zynqmp_pm_features[PM_API_MAX];
+DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER);
+
+/**
+ * struct pm_api_feature_data - PM API Feature data
+ * @pm_api_id:         PM API Id, used as key to index into hashmap
+ * @feature_status:    status of PM API feature: valid, invalid
+ * @hentry:            hlist_node that hooks this entry into hashtable
+ */
+struct pm_api_feature_data {
+       u32 pm_api_id;
+       int feature_status;
+       struct hlist_node hentry;
+};
 
 static const struct mfd_cell firmware_devs[] = {
        {
@@ -142,26 +158,37 @@ static int zynqmp_pm_feature(u32 api_id)
        int ret;
        u32 ret_payload[PAYLOAD_ARG_CNT];
        u64 smc_arg[2];
+       struct pm_api_feature_data *feature_data;
 
        if (!feature_check_enabled)
                return 0;
 
-       /* Return value if feature is already checked */
-       if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED)
-               return zynqmp_pm_features[api_id];
+       /* Check for existing entry in hash table for given api */
+       hash_for_each_possible(pm_api_features_map, feature_data, hentry,
+                              api_id) {
+               if (feature_data->pm_api_id == api_id)
+                       return feature_data->feature_status;
+       }
+
+       /* Add new entry if not present */
+       feature_data = kmalloc(sizeof(*feature_data), GFP_KERNEL);
+       if (!feature_data)
+               return -ENOMEM;
 
+       feature_data->pm_api_id = api_id;
        smc_arg[0] = PM_SIP_SVC | PM_FEATURE_CHECK;
        smc_arg[1] = api_id;
 
        ret = do_fw_call(smc_arg[0], smc_arg[1], 0, ret_payload);
-       if (ret) {
-               zynqmp_pm_features[api_id] = PM_FEATURE_INVALID;
-               return PM_FEATURE_INVALID;
-       }
+       if (ret)
+               ret = -EOPNOTSUPP;
+       else
+               ret = ret_payload[1];
 
-       zynqmp_pm_features[api_id] = ret_payload[1];
+       feature_data->feature_status = ret;
+       hash_add(pm_api_features_map, &feature_data->hentry, api_id);
 
-       return zynqmp_pm_features[api_id];
+       return ret;
 }
 
 /**
@@ -197,9 +224,12 @@ int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1,
         * Make sure to stay in x0 register
         */
        u64 smc_arg[4];
+       int ret;
 
-       if (zynqmp_pm_feature(pm_api_id) == PM_FEATURE_INVALID)
-               return -ENOTSUPP;
+       /* Check if feature is supported or not */
+       ret = zynqmp_pm_feature(pm_api_id);
+       if (ret < 0)
+               return ret;
 
        smc_arg[0] = PM_SIP_SVC | pm_api_id;
        smc_arg[1] = ((u64)arg1 << 32) | arg0;
@@ -612,7 +642,7 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay);
  */
 int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type)
 {
-       return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY,
+       return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SD_DLL_RESET,
                                   type, 0, NULL);
 }
 EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset);
@@ -1249,9 +1279,17 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)
 
 static int zynqmp_firmware_remove(struct platform_device *pdev)
 {
+       struct pm_api_feature_data *feature_data;
+       int i;
+
        mfd_remove_devices(&pdev->dev);
        zynqmp_pm_api_debugfs_exit();
 
+       hash_for_each(pm_api_features_map, i, feature_data, hentry) {
+               hash_del(&feature_data->hentry);
+               kfree(feature_data);
+       }
+
        return 0;
 }
 
index 7cd5a29fc437ebc3d0c1f1613f9717d26789106d..5645226ca3ce07245af876fc6e89c53088bf9e51 100644 (file)
@@ -142,6 +142,7 @@ config FPGA_DFL
        tristate "FPGA Device Feature List (DFL) support"
        select FPGA_BRIDGE
        select FPGA_REGION
+       depends on HAS_IOMEM
        help
          Device Feature List (DFL) defines a feature list structure that
          creates a linked list of feature headers within the MMIO space
index e44d5de2a1201a1ecce4d6d9985c473dcc071a26..b966f5e28ebffd5f3a97bcd43f1001156641b43d 100644 (file)
@@ -1114,6 +1114,7 @@ static const struct aspeed_gpio_config ast2500_config =
 
 static const struct aspeed_bank_props ast2600_bank_props[] = {
        /*     input      output   */
+       {4, 0xffffffff,  0x00ffffff}, /* Q/R/S/T */
        {5, 0xffffffff,  0xffffff00}, /* U/V/W/X */
        {6, 0x0000ffff,  0x0000ffff}, /* Y/Z */
        { },
index a5b326754124dee3b86496a14243999cdea19cb4..2a9046c0fb165405c3381d2f26070959c2a7d35d 100644 (file)
@@ -343,8 +343,8 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type)
 #ifdef CONFIG_PM_SLEEP
 static int dwapb_irq_set_wake(struct irq_data *d, unsigned int enable)
 {
-       struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d);
-       struct dwapb_gpio *gpio = igc->private;
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct dwapb_gpio *gpio = to_dwapb_gpio(gc);
        struct dwapb_context *ctx = gpio->ports[0].ctx;
        irq_hw_number_t bit = irqd_to_hwirq(d);
 
index 6d59e3a4376116f62af91dc5fc8df24c871e4ac7..f7ceb2b11afc55ec9eefdc5fed6a46fbc2e9ff5a 100644 (file)
@@ -1114,13 +1114,23 @@ static void omap_gpio_idle(struct gpio_bank *bank, bool may_lose_context)
 {
        struct device *dev = bank->chip.parent;
        void __iomem *base = bank->base;
-       u32 nowake;
+       u32 mask, nowake;
 
        bank->saved_datain = readl_relaxed(base + bank->regs->datain);
 
        if (!bank->enabled_non_wakeup_gpios)
                goto update_gpio_context_count;
 
+       /* Check for pending EDGE_FALLING, ignore EDGE_BOTH */
+       mask = bank->enabled_non_wakeup_gpios & bank->context.fallingdetect;
+       mask &= ~bank->context.risingdetect;
+       bank->saved_datain |= mask;
+
+       /* Check for pending EDGE_RISING, ignore EDGE_BOTH */
+       mask = bank->enabled_non_wakeup_gpios & bank->context.risingdetect;
+       mask &= ~bank->context.fallingdetect;
+       bank->saved_datain &= ~mask;
+
        if (!may_lose_context)
                goto update_gpio_context_count;
 
index a68941d19ac60892e9b03185b98cdef552aa026b..2a07fd96707eed77b3820894d0775299fde37677 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
+/*
+ * PLX PEX8311 PCI LCS_INTCSR Interrupt Control/Status
+ *
+ * Bit: Description
+ *   0: Enable Interrupt Sources (Bit 0)
+ *   1: Enable Interrupt Sources (Bit 1)
+ *   2: Generate Internal PCI Bus Internal SERR# Interrupt
+ *   3: Mailbox Interrupt Enable
+ *   4: Power Management Interrupt Enable
+ *   5: Power Management Interrupt
+ *   6: Slave Read Local Data Parity Check Error Enable
+ *   7: Slave Read Local Data Parity Check Error Status
+ *   8: Internal PCI Wire Interrupt Enable
+ *   9: PCI Express Doorbell Interrupt Enable
+ *  10: PCI Abort Interrupt Enable
+ *  11: Local Interrupt Input Enable
+ *  12: Retry Abort Enable
+ *  13: PCI Express Doorbell Interrupt Active
+ *  14: PCI Abort Interrupt Active
+ *  15: Local Interrupt Input Active
+ *  16: Local Interrupt Output Enable
+ *  17: Local Doorbell Interrupt Enable
+ *  18: DMA Channel 0 Interrupt Enable
+ *  19: DMA Channel 1 Interrupt Enable
+ *  20: Local Doorbell Interrupt Active
+ *  21: DMA Channel 0 Interrupt Active
+ *  22: DMA Channel 1 Interrupt Active
+ *  23: Built-In Self-Test (BIST) Interrupt Active
+ *  24: Direct Master was the Bus Master during a Master or Target Abort
+ *  25: DMA Channel 0 was the Bus Master during a Master or Target Abort
+ *  26: DMA Channel 1 was the Bus Master during a Master or Target Abort
+ *  27: Target Abort after internal 256 consecutive Master Retrys
+ *  28: PCI Bus wrote data to LCS_MBOX0
+ *  29: PCI Bus wrote data to LCS_MBOX1
+ *  30: PCI Bus wrote data to LCS_MBOX2
+ *  31: PCI Bus wrote data to LCS_MBOX3
+ */
+#define PLX_PEX8311_PCI_LCS_INTCSR  0x68
+#define INTCSR_INTERNAL_PCI_WIRE    BIT(8)
+#define INTCSR_LOCAL_INPUT          BIT(11)
+
 /**
  * struct idio_24_gpio_reg - GPIO device registers structure
  * @out0_7:    Read: FET Outputs 0-7
@@ -92,6 +133,7 @@ struct idio_24_gpio_reg {
 struct idio_24_gpio {
        struct gpio_chip chip;
        raw_spinlock_t lock;
+       __u8 __iomem *plx;
        struct idio_24_gpio_reg __iomem *reg;
        unsigned long irq_mask;
 };
@@ -334,13 +376,13 @@ static void idio_24_irq_mask(struct irq_data *data)
        unsigned long flags;
        const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
        unsigned char new_irq_mask;
-       const unsigned long bank_offset = bit_offset/8 * 8;
+       const unsigned long bank_offset = bit_offset / 8;
        unsigned char cos_enable_state;
 
        raw_spin_lock_irqsave(&idio24gpio->lock, flags);
 
-       idio24gpio->irq_mask &= BIT(bit_offset);
-       new_irq_mask = idio24gpio->irq_mask >> bank_offset;
+       idio24gpio->irq_mask &= ~BIT(bit_offset);
+       new_irq_mask = idio24gpio->irq_mask >> bank_offset * 8;
 
        if (!new_irq_mask) {
                cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
@@ -363,12 +405,12 @@ static void idio_24_irq_unmask(struct irq_data *data)
        unsigned long flags;
        unsigned char prev_irq_mask;
        const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
-       const unsigned long bank_offset = bit_offset/8 * 8;
+       const unsigned long bank_offset = bit_offset / 8;
        unsigned char cos_enable_state;
 
        raw_spin_lock_irqsave(&idio24gpio->lock, flags);
 
-       prev_irq_mask = idio24gpio->irq_mask >> bank_offset;
+       prev_irq_mask = idio24gpio->irq_mask >> bank_offset * 8;
        idio24gpio->irq_mask |= BIT(bit_offset);
 
        if (!prev_irq_mask) {
@@ -455,6 +497,7 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        struct device *const dev = &pdev->dev;
        struct idio_24_gpio *idio24gpio;
        int err;
+       const size_t pci_plx_bar_index = 1;
        const size_t pci_bar_index = 2;
        const char *const name = pci_name(pdev);
        struct gpio_irq_chip *girq;
@@ -469,12 +512,13 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                return err;
        }
 
-       err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name);
+       err = pcim_iomap_regions(pdev, BIT(pci_plx_bar_index) | BIT(pci_bar_index), name);
        if (err) {
                dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
                return err;
        }
 
+       idio24gpio->plx = pcim_iomap_table(pdev)[pci_plx_bar_index];
        idio24gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
 
        idio24gpio->chip.label = name;
@@ -504,6 +548,12 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        /* Software board reset */
        iowrite8(0, &idio24gpio->reg->soft_reset);
+       /*
+        * enable PLX PEX8311 internal PCI wire interrupt and local interrupt
+        * input
+        */
+       iowrite8((INTCSR_INTERNAL_PCI_WIRE | INTCSR_LOCAL_INPUT) >> 8,
+                idio24gpio->plx + PLX_PEX8311_PCI_LCS_INTCSR + 1);
 
        err = devm_gpiochip_add_data(dev, &idio24gpio->chip, idio24gpio);
        if (err) {
index c54dd08f2cbfd3c75d74ffec723f4e0e5f72e4f7..d5eb9ca119016c6ba7882334ee2eaf16ce77949a 100644 (file)
@@ -183,7 +183,7 @@ static int sifive_gpio_probe(struct platform_device *pdev)
                return PTR_ERR(chip->regs);
 
        ngpio = of_irq_count(node);
-       if (ngpio >= SIFIVE_GPIO_MAX) {
+       if (ngpio > SIFIVE_GPIO_MAX) {
                dev_err(dev, "Too many GPIO interrupts (max=%d)\n",
                        SIFIVE_GPIO_MAX);
                return -ENXIO;
index cb41dd757338068000e7b69404f76c2380d61c7b..b42644cbffb80ebdf3dbc5cb06e7e2d5726e48f0 100644 (file)
@@ -7,22 +7,7 @@
 
 struct gpio_device;
 
-#ifdef CONFIG_GPIO_CDEV
-
 int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt);
 void gpiolib_cdev_unregister(struct gpio_device *gdev);
 
-#else
-
-static inline int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt)
-{
-       return 0;
-}
-
-static inline void gpiolib_cdev_unregister(struct gpio_device *gdev)
-{
-}
-
-#endif /* CONFIG_GPIO_CDEV */
-
 #endif /* GPIOLIB_CDEV_H */
index 3cdf9effc13a5f2332120028ce19db2924cfa491..089ddcaa9bc64a8bfaac05e52f2dbde0c8f3436b 100644 (file)
@@ -480,11 +480,23 @@ static void gpiodevice_release(struct device *dev)
        kfree(gdev);
 }
 
+#ifdef CONFIG_GPIO_CDEV
+#define gcdev_register(gdev, devt)     gpiolib_cdev_register((gdev), (devt))
+#define gcdev_unregister(gdev)         gpiolib_cdev_unregister((gdev))
+#else
+/*
+ * gpiolib_cdev_register() indirectly calls device_add(), which is still
+ * required even when cdev is not selected.
+ */
+#define gcdev_register(gdev, devt)     device_add(&(gdev)->dev)
+#define gcdev_unregister(gdev)         device_del(&(gdev)->dev)
+#endif
+
 static int gpiochip_setup_dev(struct gpio_device *gdev)
 {
        int ret;
 
-       ret = gpiolib_cdev_register(gdev, gpio_devt);
+       ret = gcdev_register(gdev, gpio_devt);
        if (ret)
                return ret;
 
@@ -500,7 +512,7 @@ static int gpiochip_setup_dev(struct gpio_device *gdev)
        return 0;
 
 err_remove_device:
-       gpiolib_cdev_unregister(gdev);
+       gcdev_unregister(gdev);
        return ret;
 }
 
@@ -825,7 +837,7 @@ void gpiochip_remove(struct gpio_chip *gc)
         * be removed, else it will be dangling until the last user is
         * gone.
         */
-       gpiolib_cdev_unregister(gdev);
+       gcdev_unregister(gdev);
        put_device(&gdev->dev);
 }
 EXPORT_SYMBOL_GPL(gpiochip_remove);
index 37da3537ba2e723247b274eee8699ff9f5e62e04..026789b466db9a83aed5be61f1e018a8edf7f9c4 100644 (file)
@@ -80,6 +80,7 @@ MODULE_FIRMWARE("amdgpu/renoir_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/navi10_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/navi14_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/navi12_gpu_info.bin");
+MODULE_FIRMWARE("amdgpu/green_sardine_gpu_info.bin");
 
 #define AMDGPU_RESUME_MS               2000
 
@@ -239,9 +240,11 @@ bool amdgpu_device_supports_baco(struct drm_device *dev)
        return amdgpu_asic_supports_baco(adev);
 }
 
+/*
+ * VRAM access helper functions
+ */
+
 /**
- * VRAM access helper functions.
- *
  * amdgpu_device_vram_access - read/write a buffer in vram
  *
  * @adev: amdgpu_device pointer
@@ -705,7 +708,7 @@ void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev,
 /**
  * amdgpu_invalid_rreg - dummy reg read function
  *
- * @adev: amdgpu device pointer
+ * @adev: amdgpu_device pointer
  * @reg: offset of register
  *
  * Dummy register read function.  Used for register blocks
@@ -722,7 +725,7 @@ static uint32_t amdgpu_invalid_rreg(struct amdgpu_device *adev, uint32_t reg)
 /**
  * amdgpu_invalid_wreg - dummy reg write function
  *
- * @adev: amdgpu device pointer
+ * @adev: amdgpu_device pointer
  * @reg: offset of register
  * @v: value to write to the register
  *
@@ -739,7 +742,7 @@ static void amdgpu_invalid_wreg(struct amdgpu_device *adev, uint32_t reg, uint32
 /**
  * amdgpu_invalid_rreg64 - dummy 64 bit reg read function
  *
- * @adev: amdgpu device pointer
+ * @adev: amdgpu_device pointer
  * @reg: offset of register
  *
  * Dummy register read function.  Used for register blocks
@@ -756,7 +759,7 @@ static uint64_t amdgpu_invalid_rreg64(struct amdgpu_device *adev, uint32_t reg)
 /**
  * amdgpu_invalid_wreg64 - dummy reg write function
  *
- * @adev: amdgpu device pointer
+ * @adev: amdgpu_device pointer
  * @reg: offset of register
  * @v: value to write to the register
  *
@@ -773,7 +776,7 @@ static void amdgpu_invalid_wreg64(struct amdgpu_device *adev, uint32_t reg, uint
 /**
  * amdgpu_block_invalid_rreg - dummy reg read function
  *
- * @adev: amdgpu device pointer
+ * @adev: amdgpu_device pointer
  * @block: offset of instance
  * @reg: offset of register
  *
@@ -793,7 +796,7 @@ static uint32_t amdgpu_block_invalid_rreg(struct amdgpu_device *adev,
 /**
  * amdgpu_block_invalid_wreg - dummy reg write function
  *
- * @adev: amdgpu device pointer
+ * @adev: amdgpu_device pointer
  * @block: offset of instance
  * @reg: offset of register
  * @v: value to write to the register
@@ -813,7 +816,7 @@ static void amdgpu_block_invalid_wreg(struct amdgpu_device *adev,
 /**
  * amdgpu_device_asic_init - Wrapper for atom asic_init
  *
- * @dev: drm_device pointer
+ * @adev: amdgpu_device pointer
  *
  * Does any asic specific work and then calls atom asic init.
  */
@@ -827,7 +830,7 @@ static int amdgpu_device_asic_init(struct amdgpu_device *adev)
 /**
  * amdgpu_device_vram_scratch_init - allocate the VRAM scratch page
  *
- * @adev: amdgpu device pointer
+ * @adev: amdgpu_device pointer
  *
  * Allocates a scratch page of VRAM for use by various things in the
  * driver.
@@ -844,7 +847,7 @@ static int amdgpu_device_vram_scratch_init(struct amdgpu_device *adev)
 /**
  * amdgpu_device_vram_scratch_fini - Free the VRAM scratch page
  *
- * @adev: amdgpu device pointer
+ * @adev: amdgpu_device pointer
  *
  * Frees the VRAM scratch page.
  */
@@ -1803,7 +1806,10 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
                chip_name = "arcturus";
                break;
        case CHIP_RENOIR:
-               chip_name = "renoir";
+               if (adev->apu_flags & AMD_APU_IS_RENOIR)
+                       chip_name = "renoir";
+               else
+                       chip_name = "green_sardine";
                break;
        case CHIP_NAVI10:
                chip_name = "navi10";
@@ -3011,7 +3017,7 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
 /**
  * amdgpu_device_has_dc_support - check if dc is supported
  *
- * @adev: amdgpu_device_pointer
+ * @adev: amdgpu_device pointer
  *
  * Returns true for supported, false for not supported
  */
@@ -4045,7 +4051,7 @@ static int amdgpu_device_recover_vram(struct amdgpu_device *adev)
 /**
  * amdgpu_device_reset_sriov - reset ASIC for SR-IOV vf
  *
- * @adev: amdgpu device pointer
+ * @adev: amdgpu_device pointer
  * @from_hypervisor: request from hypervisor
  *
  * do VF FLR and reinitialize Asic
@@ -4100,7 +4106,7 @@ error:
 /**
  * amdgpu_device_has_job_running - check if there is any job in mirror list
  *
- * @adev: amdgpu device pointer
+ * @adev: amdgpu_device pointer
  *
  * check if there is any job in mirror list
  */
@@ -4128,7 +4134,7 @@ bool amdgpu_device_has_job_running(struct amdgpu_device *adev)
 /**
  * amdgpu_device_should_recover_gpu - check if we should try GPU recovery
  *
- * @adev: amdgpu device pointer
+ * @adev: amdgpu_device pointer
  *
  * Check amdgpu_gpu_recovery and SRIOV status to see if we should try to recover
  * a hung GPU.
@@ -4477,7 +4483,7 @@ static int amdgpu_device_suspend_display_audio(struct amdgpu_device *adev)
 /**
  * amdgpu_device_gpu_recover - reset the asic and recover scheduler
  *
- * @adev: amdgpu device pointer
+ * @adev: amdgpu_device pointer
  * @job: which job trigger hang
  *
  * Attempt to reset the GPU if it has hung (all asics).
@@ -4497,7 +4503,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
        bool need_emergency_restart = false;
        bool audio_suspended = false;
 
-       /**
+       /*
         * Special case: RAS triggered and full reset isn't supported
         */
        need_emergency_restart = amdgpu_ras_need_emergency_restart(adev);
@@ -4846,7 +4852,7 @@ int amdgpu_device_baco_enter(struct drm_device *dev)
        if (!amdgpu_device_supports_baco(adev_to_drm(adev)))
                return -ENOTSUPP;
 
-       if (ras && ras->supported)
+       if (ras && ras->supported && adev->nbio.funcs->enable_doorbell_interrupt)
                adev->nbio.funcs->enable_doorbell_interrupt(adev, false);
 
        return amdgpu_dpm_baco_enter(adev);
@@ -4865,7 +4871,7 @@ int amdgpu_device_baco_exit(struct drm_device *dev)
        if (ret)
                return ret;
 
-       if (ras && ras->supported)
+       if (ras && ras->supported && adev->nbio.funcs->enable_doorbell_interrupt)
                adev->nbio.funcs->enable_doorbell_interrupt(adev, true);
 
        return 0;
index c241317edee7813a8530336d43f319582b766ebe..8e988f07f085691c1b68c1591e95c2c48b128cb3 100644 (file)
@@ -1055,10 +1055,10 @@ static const struct pci_device_id pciidlist[] = {
        {0x1002, 0x15dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RAVEN|AMD_IS_APU},
        {0x1002, 0x15d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RAVEN|AMD_IS_APU},
        /* Arcturus */
-       {0x1002, 0x738C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS|AMD_EXP_HW_SUPPORT},
-       {0x1002, 0x7388, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS|AMD_EXP_HW_SUPPORT},
-       {0x1002, 0x738E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS|AMD_EXP_HW_SUPPORT},
-       {0x1002, 0x7390, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS|AMD_EXP_HW_SUPPORT},
+       {0x1002, 0x738C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS},
+       {0x1002, 0x7388, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS},
+       {0x1002, 0x738E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS},
+       {0x1002, 0x7390, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS},
        /* Navi10 */
        {0x1002, 0x7310, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
        {0x1002, 0x7312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
@@ -1066,6 +1066,7 @@ static const struct pci_device_id pciidlist[] = {
        {0x1002, 0x7319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
        {0x1002, 0x731A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
        {0x1002, 0x731B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
+       {0x1002, 0x731E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
        {0x1002, 0x731F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
        /* Navi14 */
        {0x1002, 0x7340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI14},
index aa7f230c71bf5aa48328accb28fa2d417282183e..7e8265da9f2508e1eb9e584e9848462a45cd63fc 100644 (file)
@@ -596,6 +596,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
        struct ww_acquire_ctx ticket;
        struct list_head list, duplicates;
        uint64_t va_flags;
+       uint64_t vm_size;
        int r = 0;
 
        if (args->va_address < AMDGPU_VA_RESERVED_SIZE) {
@@ -616,6 +617,15 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
 
        args->va_address &= AMDGPU_GMC_HOLE_MASK;
 
+       vm_size = adev->vm_manager.max_pfn * AMDGPU_GPU_PAGE_SIZE;
+       vm_size -= AMDGPU_VA_RESERVED_SIZE;
+       if (args->va_address + args->map_size > vm_size) {
+               dev_dbg(&dev->pdev->dev,
+                       "va_address 0x%llx is in top reserved area 0x%llx\n",
+                       args->va_address + args->map_size, vm_size);
+               return -EINVAL;
+       }
+
        if ((args->flags & ~valid_flags) && (args->flags & ~prt_flags)) {
                dev_dbg(&dev->pdev->dev, "invalid flags combination 0x%08X\n",
                        args->flags);
index f203e4a6a3f2b062dce032044229d109e817def3..731f3aa2e6ba64b6a5dcbd5a0af758b468f49a0a 100644 (file)
@@ -81,8 +81,8 @@ static const struct ttm_resource_manager_func amdgpu_gtt_mgr_func;
 /**
  * amdgpu_gtt_mgr_init - init GTT manager and DRM MM
  *
- * @man: TTM memory type manager
- * @p_size: maximum size of GTT
+ * @adev: amdgpu_device pointer
+ * @gtt_size: maximum size of GTT
  *
  * Allocate and initialize the GTT manager.
  */
@@ -123,7 +123,7 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size)
 /**
  * amdgpu_gtt_mgr_fini - free and destroy GTT manager
  *
- * @man: TTM memory type manager
+ * @adev: amdgpu_device pointer
  *
  * Destroy and free the GTT manager, returns -EBUSY if ranges are still
  * allocated inside it.
index 96a9699f87ba840256bf69b924aa76db9e19763c..a6dbe4b83533f7888a2e60bf36350d5951247062 100644 (file)
@@ -2524,6 +2524,7 @@ int parse_ta_bin_descriptor(struct psp_context *psp,
                psp->asd_feature_version   = le32_to_cpu(desc->fw_version);
                psp->asd_ucode_size        = le32_to_cpu(desc->size_bytes);
                psp->asd_start_addr        = ucode_start_addr;
+               psp->asd_fw                = psp->ta_fw;
                break;
        case TA_FW_TYPE_PSP_XGMI:
                psp->ta_xgmi_ucode_version = le32_to_cpu(desc->fw_version);
index 8039d239958466989b6626187584867f14c9f58a..a0248d78190f2c1d016e94be98ddf0d55262d4ff 100644 (file)
@@ -69,10 +69,10 @@ static int amdgpu_ttm_backend_bind(struct ttm_bo_device *bdev,
 
 static int amdgpu_ttm_init_on_chip(struct amdgpu_device *adev,
                                    unsigned int type,
-                                   uint64_t size)
+                                   uint64_t size_in_page)
 {
        return ttm_range_man_init(&adev->mman.bdev, type,
-                                 false, size >> PAGE_SHIFT);
+                                 false, size_in_page);
 }
 
 /**
index 5eb63288d15743bd22d21e142f4184628d0d009f..edbb8194ee81b1e52b4f7056e8dec4d1b65085df 100644 (file)
@@ -67,6 +67,7 @@ struct amdgpu_uvd {
        unsigned                harvest_config;
        /* store image width to adjust nb memory state */
        unsigned                decode_image_width;
+       uint32_t                keyselect;
 };
 
 int amdgpu_uvd_sw_init(struct amdgpu_device *adev);
index f3b7287e84c43ea433a8bbcc9a959842059517dd..a563328e3daea297e3eb836940ddf3caad5d07a7 100644 (file)
@@ -39,6 +39,7 @@
 #define FIRMWARE_RAVEN2                "amdgpu/raven2_vcn.bin"
 #define FIRMWARE_ARCTURUS      "amdgpu/arcturus_vcn.bin"
 #define FIRMWARE_RENOIR        "amdgpu/renoir_vcn.bin"
+#define FIRMWARE_GREEN_SARDINE         "amdgpu/green_sardine_vcn.bin"
 #define FIRMWARE_NAVI10        "amdgpu/navi10_vcn.bin"
 #define FIRMWARE_NAVI14        "amdgpu/navi14_vcn.bin"
 #define FIRMWARE_NAVI12        "amdgpu/navi12_vcn.bin"
@@ -50,6 +51,7 @@ MODULE_FIRMWARE(FIRMWARE_PICASSO);
 MODULE_FIRMWARE(FIRMWARE_RAVEN2);
 MODULE_FIRMWARE(FIRMWARE_ARCTURUS);
 MODULE_FIRMWARE(FIRMWARE_RENOIR);
+MODULE_FIRMWARE(FIRMWARE_GREEN_SARDINE);
 MODULE_FIRMWARE(FIRMWARE_NAVI10);
 MODULE_FIRMWARE(FIRMWARE_NAVI14);
 MODULE_FIRMWARE(FIRMWARE_NAVI12);
@@ -89,7 +91,11 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
                        adev->vcn.indirect_sram = true;
                break;
        case CHIP_RENOIR:
-               fw_name = FIRMWARE_RENOIR;
+               if (adev->apu_flags & AMD_APU_IS_RENOIR)
+                       fw_name = FIRMWARE_RENOIR;
+               else
+                       fw_name = FIRMWARE_GREEN_SARDINE;
+
                if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
                    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
                        adev->vcn.indirect_sram = true;
index c6abb16e80182705921b0a02a232da9de0e1bda6..58c83a7ad0fd9d224b7339cbcd5c1d949769b977 100644 (file)
@@ -112,8 +112,8 @@ struct amdgpu_bo_list_entry;
 #define AMDGPU_MMHUB_0                         1
 #define AMDGPU_MMHUB_1                         2
 
-/* hardcode that limit for now */
-#define AMDGPU_VA_RESERVED_SIZE                        (1ULL << 20)
+/* Reserve 2MB at top/bottom of address space for kernel use */
+#define AMDGPU_VA_RESERVED_SIZE                        (2ULL << 20)
 
 /* max vmids dedicated for process */
 #define AMDGPU_VM_MAX_RESERVED_VMID    1
index 01c1171afbe02f18208128f37b4e001cfffafc48..0c6b7c5ecfec897a4868475e3823b3f5f57a8522 100644 (file)
@@ -168,8 +168,7 @@ static const struct ttm_resource_manager_func amdgpu_vram_mgr_func;
 /**
  * amdgpu_vram_mgr_init - init VRAM manager and DRM MM
  *
- * @man: TTM memory type manager
- * @p_size: maximum size of VRAM
+ * @adev: amdgpu_device pointer
  *
  * Allocate and initialize the VRAM manager.
  */
@@ -199,7 +198,7 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev)
 /**
  * amdgpu_vram_mgr_fini - free and destroy VRAM manager
  *
- * @man: TTM memory type manager
+ * @adev: amdgpu_device pointer
  *
  * Destroy and free the VRAM manager, returns -EBUSY if ranges are still
  * allocated inside it.
@@ -229,7 +228,7 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev)
 /**
  * amdgpu_vram_mgr_vis_size - Calculate visible node size
  *
- * @adev: amdgpu device structure
+ * @adev: amdgpu_device pointer
  * @node: MM node structure
  *
  * Calculate how many bytes of the MM node are inside visible VRAM
index 03ff8bd1fee84df67998a4be24adc8e3ed26c526..5442df0941024c83324de7a5685d7f66498c21ca 100644 (file)
@@ -1336,11 +1336,13 @@ cik_asic_reset_method(struct amdgpu_device *adev)
 
        switch (adev->asic_type) {
        case CHIP_BONAIRE:
-       case CHIP_HAWAII:
                /* disable baco reset until it works */
                /* smu7_asic_get_baco_capability(adev, &baco_reset); */
                baco_reset = false;
                break;
+       case CHIP_HAWAII:
+               baco_reset = cik_asic_supports_baco(adev);
+               break;
        default:
                baco_reset = false;
                break;
index 20f108818b2b966f5893f05e7b72e233d0b3054a..a3c3fe96515f2133cbe79382f822951deaea9fc9 100644 (file)
@@ -1071,22 +1071,19 @@ static int cik_sdma_soft_reset(void *handle)
 {
        u32 srbm_soft_reset = 0;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       u32 tmp = RREG32(mmSRBM_STATUS2);
+       u32 tmp;
 
-       if (tmp & SRBM_STATUS2__SDMA_BUSY_MASK) {
-               /* sdma0 */
-               tmp = RREG32(mmSDMA0_F32_CNTL + SDMA0_REGISTER_OFFSET);
-               tmp |= SDMA0_F32_CNTL__HALT_MASK;
-               WREG32(mmSDMA0_F32_CNTL + SDMA0_REGISTER_OFFSET, tmp);
-               srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_SDMA_MASK;
-       }
-       if (tmp & SRBM_STATUS2__SDMA1_BUSY_MASK) {
-               /* sdma1 */
-               tmp = RREG32(mmSDMA0_F32_CNTL + SDMA1_REGISTER_OFFSET);
-               tmp |= SDMA0_F32_CNTL__HALT_MASK;
-               WREG32(mmSDMA0_F32_CNTL + SDMA1_REGISTER_OFFSET, tmp);
-               srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_SDMA1_MASK;
-       }
+       /* sdma0 */
+       tmp = RREG32(mmSDMA0_F32_CNTL + SDMA0_REGISTER_OFFSET);
+       tmp |= SDMA0_F32_CNTL__HALT_MASK;
+       WREG32(mmSDMA0_F32_CNTL + SDMA0_REGISTER_OFFSET, tmp);
+       srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_SDMA_MASK;
+
+       /* sdma1 */
+       tmp = RREG32(mmSDMA0_F32_CNTL + SDMA1_REGISTER_OFFSET);
+       tmp |= SDMA0_F32_CNTL__HALT_MASK;
+       WREG32(mmSDMA0_F32_CNTL + SDMA1_REGISTER_OFFSET, tmp);
+       srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_SDMA1_MASK;
 
        if (srbm_soft_reset) {
                tmp = RREG32(mmSRBM_SOFT_RESET);
index 56fdbe626d3031f58e4adc5a9f92f451dc84b425..55f4b8c3b933838c3a3937859efb05914cd61c05 100644 (file)
 #define PA_SC_ENHANCE_3__FORCE_PBB_WORKLOAD_MODE_TO_ZERO__SHIFT 0x3
 #define PA_SC_ENHANCE_3__FORCE_PBB_WORKLOAD_MODE_TO_ZERO_MASK   0x00000008L
 
+#define mmCGTT_SPI_CS_CLK_CTRL                 0x507c
+#define mmCGTT_SPI_CS_CLK_CTRL_BASE_IDX         1
+
 MODULE_FIRMWARE("amdgpu/navi10_ce.bin");
 MODULE_FIRMWARE("amdgpu/navi10_pfp.bin");
 MODULE_FIRMWARE("amdgpu/navi10_me.bin");
@@ -3094,6 +3097,7 @@ static const struct soc15_reg_golden golden_settings_gc_rlc_spm_10_1_2_nv12[] =
 
 static const struct soc15_reg_golden golden_settings_gc_10_3[] =
 {
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_CS_CLK_CTRL, 0x78000000, 0x78000100),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_PS_CLK_CTRL, 0xff7f0fff, 0x78000100),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_RA0_CLK_CTRL, 0xff7f0fff, 0x30000100),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_RA1_CLK_CTRL, 0xff7f0fff, 0x7e000100),
@@ -3101,6 +3105,8 @@ static const struct soc15_reg_golden golden_settings_gc_10_3[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000280),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x00800000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_EXCEPTION_CONTROL, 0x7fff0f1f, 0x00b80000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0 ,mmGCEA_SDP_TAG_RESERVE0, 0xffffffff, 0x10100100),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCEA_SDP_TAG_RESERVE1, 0xffffffff, 0x17000088),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCR_GENERAL_CNTL_Sienna_Cichlid, 0x1ff1ffff, 0x00000500),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGE_PC_CNTL, 0x003fffff, 0x00280400),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2A_ADDR_MATCH_MASK, 0xffffffff, 0xffffffcf),
index 6959aebae6d41833ec664f7b924216238e4f56c4..0d8e203b10efb2a645d67e8cc51384f811bd698b 100644 (file)
@@ -117,6 +117,13 @@ MODULE_FIRMWARE("amdgpu/renoir_mec.bin");
 MODULE_FIRMWARE("amdgpu/renoir_mec2.bin");
 MODULE_FIRMWARE("amdgpu/renoir_rlc.bin");
 
+MODULE_FIRMWARE("amdgpu/green_sardine_ce.bin");
+MODULE_FIRMWARE("amdgpu/green_sardine_pfp.bin");
+MODULE_FIRMWARE("amdgpu/green_sardine_me.bin");
+MODULE_FIRMWARE("amdgpu/green_sardine_mec.bin");
+MODULE_FIRMWARE("amdgpu/green_sardine_mec2.bin");
+MODULE_FIRMWARE("amdgpu/green_sardine_rlc.bin");
+
 #define mmTCP_CHAN_STEER_0_ARCT                                                                0x0b03
 #define mmTCP_CHAN_STEER_0_ARCT_BASE_IDX                                                       0
 #define mmTCP_CHAN_STEER_1_ARCT                                                                0x0b04
@@ -1630,7 +1637,10 @@ static int gfx_v9_0_init_microcode(struct amdgpu_device *adev)
                chip_name = "arcturus";
                break;
        case CHIP_RENOIR:
-               chip_name = "renoir";
+               if (adev->apu_flags & AMD_APU_IS_RENOIR)
+                       chip_name = "renoir";
+               else
+                       chip_name = "green_sardine";
                break;
        default:
                BUG();
index 1ce741a0c6a74ce0fe183dfc635e50e9cb0039e9..8eeba8096493bf31ea328ee8b345146e6ebc3953 100644 (file)
@@ -455,6 +455,15 @@ void nv_set_virt_ops(struct amdgpu_device *adev)
        adev->virt.ops = &xgpu_nv_virt_ops;
 }
 
+static bool nv_is_headless_sku(struct pci_dev *pdev)
+{
+       if ((pdev->device == 0x731E &&
+           (pdev->revision == 0xC6 || pdev->revision == 0xC7)) ||
+           (pdev->device == 0x7340 && pdev->revision == 0xC9))
+               return true;
+       return false;
+}
+
 int nv_set_ip_blocks(struct amdgpu_device *adev)
 {
        int r;
@@ -491,7 +500,8 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
                if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT &&
                    !amdgpu_sriov_vf(adev))
                        amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
-               amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
+               if (!nv_is_headless_sku(adev->pdev))
+                       amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
                amdgpu_device_ip_block_add(adev, &jpeg_v2_0_ip_block);
                if (adev->enable_mes)
                        amdgpu_device_ip_block_add(adev, &mes_v10_1_ip_block);
index 75489313dbadf77ad7c48616a40526180a43cf0a..c4828bd3264bcfe6c5cc208e7bcb6b0587dd4240 100644 (file)
@@ -39,6 +39,8 @@
 
 MODULE_FIRMWARE("amdgpu/renoir_asd.bin");
 MODULE_FIRMWARE("amdgpu/renoir_ta.bin");
+MODULE_FIRMWARE("amdgpu/green_sardine_asd.bin");
+MODULE_FIRMWARE("amdgpu/green_sardine_ta.bin");
 
 /* address block */
 #define smnMP1_FIRMWARE_FLAGS          0x3010024
@@ -54,7 +56,10 @@ static int psp_v12_0_init_microcode(struct psp_context *psp)
 
        switch (adev->asic_type) {
        case CHIP_RENOIR:
-               chip_name = "renoir";
+               if (adev->apu_flags & AMD_APU_IS_RENOIR)
+                       chip_name = "renoir";
+               else
+                       chip_name = "green_sardine";
                break;
        default:
                BUG();
index 86fb1eddf5a6f0ece961190362341e9d0a4edbba..e82f49f62f6e6d81525197cb817323c0d960cd03 100644 (file)
@@ -69,6 +69,7 @@ MODULE_FIRMWARE("amdgpu/picasso_sdma.bin");
 MODULE_FIRMWARE("amdgpu/raven2_sdma.bin");
 MODULE_FIRMWARE("amdgpu/arcturus_sdma.bin");
 MODULE_FIRMWARE("amdgpu/renoir_sdma.bin");
+MODULE_FIRMWARE("amdgpu/green_sardine_sdma.bin");
 
 #define SDMA0_POWER_CNTL__ON_OFF_CONDITION_HOLD_TIME_MASK  0x000000F8L
 #define SDMA0_POWER_CNTL__ON_OFF_STATUS_DURATION_TIME_MASK 0xFC000000L
@@ -619,7 +620,10 @@ static int sdma_v4_0_init_microcode(struct amdgpu_device *adev)
                chip_name = "arcturus";
                break;
        case CHIP_RENOIR:
-               chip_name = "renoir";
+               if (adev->apu_flags & AMD_APU_IS_RENOIR)
+                       chip_name = "renoir";
+               else
+                       chip_name = "green_sardine";
                break;
        default:
                BUG();
index afcccc6c0fc619380d625fa415e1b6be8bbea2f8..f57c5f57efa8a9e90d64765fdfef080954038a76 100644 (file)
@@ -1195,8 +1195,7 @@ static int soc15_common_early_init(void *handle)
 
                        adev->pg_flags = AMD_PG_SUPPORT_SDMA |
                                AMD_PG_SUPPORT_MMHUB |
-                               AMD_PG_SUPPORT_VCN |
-                               AMD_PG_SUPPORT_VCN_DPG;
+                               AMD_PG_SUPPORT_VCN;
                } else {
                        adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
                                AMD_CG_SUPPORT_GFX_MGLS |
@@ -1243,7 +1242,15 @@ static int soc15_common_early_init(void *handle)
                break;
        case CHIP_RENOIR:
                adev->asic_funcs = &soc15_asic_funcs;
-               adev->apu_flags |= AMD_APU_IS_RENOIR;
+               if (adev->pdev->device == 0x1636)
+                       adev->apu_flags |= AMD_APU_IS_RENOIR;
+               else
+                       adev->apu_flags |= AMD_APU_IS_GREEN_SARDINE;
+
+               if (adev->apu_flags & AMD_APU_IS_RENOIR)
+                       adev->external_rev_id = adev->rev_id + 0x91;
+               else
+                       adev->external_rev_id = adev->rev_id + 0xa1;
                adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
                                 AMD_CG_SUPPORT_GFX_MGLS |
                                 AMD_CG_SUPPORT_GFX_3D_CGCG |
@@ -1268,7 +1275,6 @@ static int soc15_common_early_init(void *handle)
                                 AMD_PG_SUPPORT_VCN |
                                 AMD_PG_SUPPORT_JPEG |
                                 AMD_PG_SUPPORT_VCN_DPG;
-               adev->external_rev_id = adev->rev_id + 0x91;
                break;
        default:
                /* FIXME: not supported yet */
index 7cf4b11a65c5ca0cbb5a2bc16eab3e9f59b21ec5..41800fcad410201386ea1963a3814710eb072344 100644 (file)
@@ -277,15 +277,8 @@ static void uvd_v3_1_mc_resume(struct amdgpu_device *adev)
  */
 static int uvd_v3_1_fw_validate(struct amdgpu_device *adev)
 {
-       void *ptr;
-       uint32_t ucode_len, i;
-       uint32_t keysel;
-
-       ptr = adev->uvd.inst[0].cpu_addr;
-       ptr += 192 + 16;
-       memcpy(&ucode_len, ptr, 4);
-       ptr += ucode_len;
-       memcpy(&keysel, ptr, 4);
+       int i;
+       uint32_t keysel = adev->uvd.keyselect;
 
        WREG32(mmUVD_FW_START, keysel);
 
@@ -550,6 +543,8 @@ static int uvd_v3_1_sw_init(void *handle)
        struct amdgpu_ring *ring;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        int r;
+       void *ptr;
+       uint32_t ucode_len;
 
        /* UVD TRAP */
        r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 124, &adev->uvd.inst->irq);
@@ -571,6 +566,13 @@ static int uvd_v3_1_sw_init(void *handle)
        if (r)
                return r;
 
+       /* Retrieval firmware validate key */
+       ptr = adev->uvd.inst[0].cpu_addr;
+       ptr += 192 + 16;
+       memcpy(&ucode_len, ptr, 4);
+       ptr += ucode_len;
+       memcpy(&adev->uvd.keyselect, ptr, 4);
+
        r = amdgpu_uvd_entity_init(adev);
 
        return r;
index e074f7ed388c0af7b4140f1f551d5948814f93b4..b5f8f3d731cb00647fe02f729e8cd50c4c3152f4 100644 (file)
@@ -1011,6 +1011,11 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
        tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1);
        WREG32_SOC15(VCN, inst_idx, mmUVD_RBC_RB_CNTL, tmp);
 
+       /* Stall DPG before WPTR/RPTR reset */
+       WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, mmUVD_POWER_STATUS),
+               UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK,
+               ~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK);
+
        /* set the write pointer delay */
        WREG32_SOC15(VCN, inst_idx, mmUVD_RBC_RB_WPTR_CNTL, 0);
 
@@ -1033,6 +1038,10 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
        WREG32_SOC15(VCN, inst_idx, mmUVD_RBC_RB_WPTR,
                lower_32_bits(ring->wptr));
 
+       /* Unstall DPG */
+       WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, mmUVD_POWER_STATUS),
+               0, ~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK);
+
        return 0;
 }
 
@@ -1556,8 +1565,14 @@ static int vcn_v3_0_pause_dpg_mode(struct amdgpu_device *adev,
                                        UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,
                                        UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
 
+                               /* Stall DPG before WPTR/RPTR reset */
+                               WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, mmUVD_POWER_STATUS),
+                                       UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK,
+                                       ~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK);
+
                                /* Restore */
                                ring = &adev->vcn.inst[inst_idx].ring_enc[0];
+                               ring->wptr = 0;
                                WREG32_SOC15(VCN, inst_idx, mmUVD_RB_BASE_LO, ring->gpu_addr);
                                WREG32_SOC15(VCN, inst_idx, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
                                WREG32_SOC15(VCN, inst_idx, mmUVD_RB_SIZE, ring->ring_size / 4);
@@ -1565,14 +1580,16 @@ static int vcn_v3_0_pause_dpg_mode(struct amdgpu_device *adev,
                                WREG32_SOC15(VCN, inst_idx, mmUVD_RB_WPTR, lower_32_bits(ring->wptr));
 
                                ring = &adev->vcn.inst[inst_idx].ring_enc[1];
+                               ring->wptr = 0;
                                WREG32_SOC15(VCN, inst_idx, mmUVD_RB_BASE_LO2, ring->gpu_addr);
                                WREG32_SOC15(VCN, inst_idx, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
                                WREG32_SOC15(VCN, inst_idx, mmUVD_RB_SIZE2, ring->ring_size / 4);
                                WREG32_SOC15(VCN, inst_idx, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr));
                                WREG32_SOC15(VCN, inst_idx, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr));
 
-                               WREG32_SOC15(VCN, inst_idx, mmUVD_RBC_RB_WPTR,
-                                       RREG32_SOC15(VCN, inst_idx, mmUVD_SCRATCH2) & 0x7FFFFFFF);
+                               /* Unstall DPG */
+                               WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, mmUVD_POWER_STATUS),
+                                       0, ~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK);
 
                                SOC15_WAIT_ON_RREG(VCN, inst_idx, mmUVD_POWER_STATUS,
                                        UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON, UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
@@ -1630,10 +1647,6 @@ static void vcn_v3_0_dec_ring_set_wptr(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
 
-       if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-               WREG32_SOC15(VCN, ring->me, mmUVD_SCRATCH2,
-                       lower_32_bits(ring->wptr) | 0x80000000);
-
        if (ring->use_doorbell) {
                adev->wb.wb[ring->wptr_offs] = lower_32_bits(ring->wptr);
                WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
index 5e2254b9e93165bb03af515256ebf1e3a67aead6..3de5e14c5ae316f559518e13bbf73ef2922da386 100644 (file)
@@ -798,10 +798,10 @@ int kfd_create_crat_image_acpi(void **crat_image, size_t *size)
        }
 
        pcrat_image = kvmalloc(crat_table->length, GFP_KERNEL);
-       memcpy(pcrat_image, crat_table, crat_table->length);
        if (!pcrat_image)
                return -ENOMEM;
 
+       memcpy(pcrat_image, crat_table, crat_table->length);
        *crat_image = pcrat_image;
        *size = crat_table->length;
 
index f24abf428534e4f8bde0d760fa5a1e8cabfa18e0..60dfdd432aba0ed47e723d259e6313a5dad4557a 100644 (file)
@@ -42,6 +42,7 @@ config DRM_AMD_DC_SI
 config DEBUG_KERNEL_DC
        bool "Enable kgdb break in DC"
        depends on DRM_AMD_DC
+       depends on KGDB
        help
          Choose this option if you want to hit kdgb_break in assert.
 
index e2b23486ba4c9dac4f8f30570c07bc5e12327249..9b6809f309f44c936905a5e6028902d583fa23f6 100644 (file)
@@ -100,6 +100,8 @@ MODULE_FIRMWARE(FIRMWARE_SIENNA_CICHLID_DMUB);
 #define FIRMWARE_NAVY_FLOUNDER_DMUB "amdgpu/navy_flounder_dmcub.bin"
 MODULE_FIRMWARE(FIRMWARE_NAVY_FLOUNDER_DMUB);
 #endif
+#define FIRMWARE_GREEN_SARDINE_DMUB "amdgpu/green_sardine_dmcub.bin"
+MODULE_FIRMWARE(FIRMWARE_GREEN_SARDINE_DMUB);
 
 #define FIRMWARE_RAVEN_DMCU            "amdgpu/raven_dmcu.bin"
 MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU);
@@ -583,7 +585,7 @@ static void amdgpu_dm_fbc_init(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
        struct amdgpu_device *adev = drm_to_adev(dev);
-       struct dm_comressor_info *compressor = &adev->dm.compressor;
+       struct dm_compressor_info *compressor = &adev->dm.compressor;
        struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(connector);
        struct drm_display_mode *mode;
        unsigned long max_size = 0;
@@ -973,6 +975,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
        case CHIP_RAVEN:
        case CHIP_RENOIR:
                init_data.flags.gpu_vm_support = true;
+               if (ASICREV_IS_GREEN_SARDINE(adev->external_rev_id))
+                       init_data.flags.disable_dmcu = true;
                break;
        default:
                break;
@@ -1037,7 +1041,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
        amdgpu_dm_init_color_mod();
 
 #ifdef CONFIG_DRM_AMD_DC_HDCP
-       if (adev->asic_type >= CHIP_RAVEN) {
+       if (adev->dm.dc->caps.max_links > 0 && adev->asic_type >= CHIP_RAVEN) {
                adev->dm.hdcp_workqueue = hdcp_create_workqueue(adev, &init_params.cp_psp, adev->dm.dc);
 
                if (!adev->dm.hdcp_workqueue)
@@ -1267,6 +1271,8 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
        case CHIP_RENOIR:
                dmub_asic = DMUB_ASIC_DCN21;
                fw_name_dmub = FIRMWARE_RENOIR_DMUB;
+               if (ASICREV_IS_GREEN_SARDINE(adev->external_rev_id))
+                       fw_name_dmub = FIRMWARE_GREEN_SARDINE_DMUB;
                break;
 #if defined(CONFIG_DRM_AMD_DC_DCN3_0)
        case CHIP_SIENNA_CICHLID:
@@ -7500,7 +7506,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
        bool mode_set_reset_required = false;
 
        drm_atomic_helper_update_legacy_modeset_state(dev, state);
-       drm_atomic_helper_calc_timestamping_constants(state);
 
        dm_state = dm_atomic_get_new_state(state);
        if (dm_state && dm_state->context) {
@@ -7527,6 +7532,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                }
        }
 
+       drm_atomic_helper_calc_timestamping_constants(state);
+
        /* update changed items */
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
                struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
index 34f6369bf51fb34d8fb27860928887a86568b21e..a8a0e8cb1a118f8da0bb0eec81ceb7aa730c3a77 100644 (file)
@@ -86,7 +86,7 @@ struct irq_list_head {
  * @bo_ptr: Pointer to the buffer object
  * @gpu_addr: MMIO gpu addr
  */
-struct dm_comressor_info {
+struct dm_compressor_info {
        void *cpu_addr;
        struct amdgpu_bo *bo_ptr;
        uint64_t gpu_addr;
@@ -148,7 +148,7 @@ struct amdgpu_dm_backlight_caps {
  * @soc_bounding_box: SOC bounding box values provided by gpu_info FW
  * @cached_state: Caches device atomic state for suspend/resume
  * @cached_dc_state: Cached state of content streams
- * @compressor: Frame buffer compression buffer. See &struct dm_comressor_info
+ * @compressor: Frame buffer compression buffer. See &struct dm_compressor_info
  * @force_timing_sync: set via debugfs. When set, indicates that all connected
  *                    displays will be forced to synchronize.
  */
@@ -324,7 +324,7 @@ struct amdgpu_display_manager {
        struct drm_atomic_state *cached_state;
        struct dc_state *cached_dc_state;
 
-       struct dm_comressor_info compressor;
+       struct dm_compressor_info compressor;
 
        const struct firmware *fw_dmcu;
        uint32_t dmcu_fw_version;
index efb909ef7a0f732ca6e905cc5efc3575c150562f..857f156e4985b4ed91ab304900b01eeaac8234ba 100644 (file)
@@ -166,6 +166,11 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
                        rn_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
                        break;
                }
+
+               if (ASICREV_IS_GREEN_SARDINE(asic_id.hw_internal_rev)) {
+                       rn_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
+                       break;
+               }
                if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev)) {
                        rv2_clk_mgr_construct(ctx, clk_mgr, pp_smu);
                        break;
index 2f8fee05547ac56ed82bc0132bc55ac9db5a39eb..c001307b0a59aea67df1982aee26f5cd10e4b149 100644 (file)
@@ -163,8 +163,17 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base,
                        new_clocks->dppclk_khz = 100000;
        }
 
-       if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
-               if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
+       /*
+        * Temporally ignore thew 0 cases for disp and dpp clks.
+        * We may have a new feature that requires 0 clks in the future.
+        */
+       if (new_clocks->dppclk_khz == 0 || new_clocks->dispclk_khz == 0) {
+               new_clocks->dppclk_khz = clk_mgr_base->clks.dppclk_khz;
+               new_clocks->dispclk_khz = clk_mgr_base->clks.dispclk_khz;
+       }
+
+       if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr_base->clks.dppclk_khz)) {
+               if (clk_mgr_base->clks.dppclk_khz > new_clocks->dppclk_khz)
                        dpp_clock_lowered = true;
                clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz;
                update_dppclk = true;
index 1eb29c3621224a3d4bfa1fa5a9e3dc0f13bba74b..45ad05f6e03b9d965e7ea4af841a5f10bfd443d6 100644 (file)
@@ -1571,8 +1571,8 @@ static void init_state(struct dc *dc, struct dc_state *context)
 
 struct dc_state *dc_create_state(struct dc *dc)
 {
-       struct dc_state *context = kzalloc(sizeof(struct dc_state),
-                                          GFP_KERNEL);
+       struct dc_state *context = kvzalloc(sizeof(struct dc_state),
+                                           GFP_KERNEL);
 
        if (!context)
                return NULL;
index e430148e47cf4f25ea109011ab31127a1d6e2dbc..59d48cf819ea8e1a51ac024b979996566cd3c2c3 100644 (file)
@@ -120,6 +120,8 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
                        dc_version = DCN_VERSION_1_01;
                if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev))
                        dc_version = DCN_VERSION_2_1;
+               if (ASICREV_IS_GREEN_SARDINE(asic_id.hw_internal_rev))
+                       dc_version = DCN_VERSION_2_1;
                break;
 #endif
 
index 9cc65dc1970f88adac661ceb0a4ada134f0f520e..49ae5ff12da633db5227b344e3f4a77187bddc57 100644 (file)
@@ -1149,7 +1149,8 @@ static uint32_t dcn3_get_pix_clk_dividers(
 static const struct clock_source_funcs dcn3_clk_src_funcs = {
        .cs_power_down = dce110_clock_source_power_down,
        .program_pix_clk = dcn3_program_pix_clk,
-       .get_pix_clk_dividers = dcn3_get_pix_clk_dividers
+       .get_pix_clk_dividers = dcn3_get_pix_clk_dividers,
+       .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
 };
 #endif
 /*****************************************/
index 24fb39a11e5d5c261a7b4e5dc8daf991fd399191..2455d210ccf68579e196c4a9fac764af116cfe7b 100644 (file)
@@ -2105,12 +2105,12 @@ static bool dcn30_internal_validate_bw(
 
                if (split[i]) {
                        if (odm) {
-                               if (split[i] == 4 && old_pipe->next_odm_pipe->next_odm_pipe)
+                               if (split[i] == 4 && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe)
                                        old_index = old_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;
                                else if (old_pipe->next_odm_pipe)
                                        old_index = old_pipe->next_odm_pipe->pipe_idx;
                        } else {
-                               if (split[i] == 4 && old_pipe->bottom_pipe->bottom_pipe &&
+                               if (split[i] == 4 && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&
                                                old_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
                                        old_index = old_pipe->bottom_pipe->bottom_pipe->pipe_idx;
                                else if (old_pipe->bottom_pipe &&
@@ -2150,10 +2150,12 @@ static bool dcn30_internal_validate_bw(
                                goto validate_fail;
                        newly_split[pipe_4to1->pipe_idx] = true;
 
-                       if (odm && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe)
+                       if (odm && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe
+                                       && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe)
                                old_index = old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;
-                       else if (!odm && old_pipe->bottom_pipe->bottom_pipe->bottom_pipe &&
-                                               old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
+                       else if (!odm && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&
+                                       old_pipe->bottom_pipe->bottom_pipe->bottom_pipe &&
+                                       old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
                                old_index = old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx;
                        else
                                old_index = -1;
index 3be2c90b0c618e601b484b5b8267481b733a2ffd..21583699f9926c478f3be2dcb130cc0520cfcfaa 100644 (file)
@@ -117,6 +117,12 @@ static const struct ddc_registers ddc_data_regs_dcn[] = {
        ddc_data_regs_dcn2(4),
        ddc_data_regs_dcn2(5),
        ddc_data_regs_dcn2(6),
+       {
+                       DDC_GPIO_VGA_REG_LIST(DATA),
+                       .ddc_setup = 0,
+                       .phy_aux_cntl = 0,
+                       .dc_gpio_aux_ctrl_5 = 0
+       }
 };
 
 static const struct ddc_registers ddc_clk_regs_dcn[] = {
@@ -126,6 +132,12 @@ static const struct ddc_registers ddc_clk_regs_dcn[] = {
        ddc_clk_regs_dcn2(4),
        ddc_clk_regs_dcn2(5),
        ddc_clk_regs_dcn2(6),
+       {
+                       DDC_GPIO_VGA_REG_LIST(CLK),
+                       .ddc_setup = 0,
+                       .phy_aux_cntl = 0,
+                       .dc_gpio_aux_ctrl_5 = 0
+       }
 };
 
 static const struct ddc_sh_mask ddc_shift[] = {
index f67c18375bfdb7ae63adce970a42cfebf969a19a..dac427b68fd7b5c97a1e0715ac27759d497aa747 100644 (file)
@@ -63,13 +63,13 @@ enum gpio_result dal_gpio_open_ex(
        enum gpio_mode mode)
 {
        if (gpio->pin) {
-               ASSERT_CRITICAL(false);
+               BREAK_TO_DEBUGGER();
                return GPIO_RESULT_ALREADY_OPENED;
        }
 
        // No action if allocation failed during gpio construct
        if (!gpio->hw_container.ddc) {
-               ASSERT_CRITICAL(false);
+               BREAK_TO_DEBUGGER();
                return GPIO_RESULT_NON_SPECIFIC_ERROR;
        }
        gpio->mode = mode;
index 2a1fea501f8c160c717f4f91ee980049e0b52ff3..3f1e7a196a23ab301bf7d3442ae1a730fc4fb340 100644 (file)
@@ -299,8 +299,8 @@ irq_source_info_dcn20[DAL_IRQ_SOURCES_NUMBER] = {
        pflip_int_entry(1),
        pflip_int_entry(2),
        pflip_int_entry(3),
-       [DC_IRQ_SOURCE_PFLIP5] = dummy_irq_entry(),
-       [DC_IRQ_SOURCE_PFLIP6] = dummy_irq_entry(),
+       pflip_int_entry(4),
+       pflip_int_entry(5),
        [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(),
        gpio_pad_int_entry(0),
        gpio_pad_int_entry(1),
index 49689f71f4f1eafcae07c66ff1cc1bb38810c5c7..0effbb2bd74a696451359e75f1c13f2a7111b9aa 100644 (file)
@@ -306,8 +306,8 @@ irq_source_info_dcn30[DAL_IRQ_SOURCES_NUMBER] = {
        pflip_int_entry(1),
        pflip_int_entry(2),
        pflip_int_entry(3),
-       [DC_IRQ_SOURCE_PFLIP5] = dummy_irq_entry(),
-       [DC_IRQ_SOURCE_PFLIP6] = dummy_irq_entry(),
+       pflip_int_entry(4),
+       pflip_int_entry(5),
        [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(),
        gpio_pad_int_entry(0),
        gpio_pad_int_entry(1),
index 330acaaed79aef8a9264bf6a87742fff8fe41faa..95cb56929e79e76fc2a6320a8f5b0477d27e8fa1 100644 (file)
  * general debug capabilities
  *
  */
-#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB)
-#define ASSERT_CRITICAL(expr) do {     \
-       if (WARN_ON(!(expr))) { \
-               kgdb_breakpoint(); \
-       } \
-} while (0)
+#ifdef CONFIG_DEBUG_KERNEL_DC
+#define dc_breakpoint()                kgdb_breakpoint()
 #else
-#define ASSERT_CRITICAL(expr) do {     \
-       if (WARN_ON(!(expr))) { \
-               ; \
-       } \
-} while (0)
+#define dc_breakpoint()                do {} while (0)
 #endif
 
-#if defined(CONFIG_DEBUG_KERNEL_DC)
-#define ASSERT(expr) ASSERT_CRITICAL(expr)
+#define ASSERT_CRITICAL(expr) do {             \
+               if (WARN_ON(!(expr)))           \
+                       dc_breakpoint();        \
+       } while (0)
 
-#else
-#define ASSERT(expr) WARN_ON_ONCE(!(expr))
-#endif
+#define ASSERT(expr) do {                      \
+               if (WARN_ON_ONCE(!(expr)))      \
+                       dc_breakpoint();        \
+       } while (0)
 
-#if defined(CONFIG_DEBUG_KERNEL_DC) && (defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB))
 #define BREAK_TO_DEBUGGER() \
        do { \
                DRM_DEBUG_DRIVER("%s():%d\n", __func__, __LINE__); \
-               kgdb_breakpoint(); \
+               dc_breakpoint(); \
        } while (0)
-#else
-#define BREAK_TO_DEBUGGER() DRM_DEBUG_DRIVER("%s():%d\n", __func__, __LINE__)
-#endif
 
 #define DC_ERR(...)  do { \
        dm_error(__VA_ARGS__); \
index b267987aed068e69f03634f90da72d4c28e39e66..ffcb059297d30faebc60d1ffde8c9d4f3d9a814e 100644 (file)
@@ -205,6 +205,10 @@ enum {
 #if defined(CONFIG_DRM_AMD_DC_DCN3_0)
 #define ASICREV_IS_SIENNA_CICHLID_P(eChipRev)        ((eChipRev >= NV_SIENNA_CICHLID_P_A0))
 #endif
+#define GREEN_SARDINE_A0 0xA1
+#ifndef ASICREV_IS_GREEN_SARDINE
+#define ASICREV_IS_GREEN_SARDINE(eChipRev) ((eChipRev >= GREEN_SARDINE_A0) && (eChipRev < 0xFF))
+#endif
 
 /*
  * ASIC chip ID
index 10dc481ecbc4be28e0b2919f4b4aa042c35c345e..06c1aabf10cef840355453f08467cd220e7de8fc 100644 (file)
@@ -45,6 +45,7 @@ enum amd_apu_flags {
        AMD_APU_IS_RAVEN2 = 0x00000002UL,
        AMD_APU_IS_PICASSO = 0x00000004UL,
        AMD_APU_IS_RENOIR = 0x00000008UL,
+       AMD_APU_IS_GREEN_SARDINE = 0x00000010UL,
 };
 
 /**
index 3898a95ec28b18cdb92874fb705e771420baf3d2..518796a26eda9cffd7a5e94aaed38e180a2e8768 100644 (file)
@@ -229,6 +229,7 @@ struct pp_smumgr_func {
        bool (*is_hw_avfs_present)(struct pp_hwmgr  *hwmgr);
        int (*update_dpm_settings)(struct pp_hwmgr *hwmgr, void *profile_setting);
        int (*smc_table_manager)(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw); /*rw: true for read, false for write */
+       int (*stop_smc)(struct pp_hwmgr *hwmgr);
 };
 
 struct pp_hwmgr_func {
index ad100b533d0496c8f4f4c5be28c3ced01692208b..5f46f1a4f38efa357e9afd450642dbc47c583e96 100644 (file)
@@ -113,4 +113,6 @@ extern int smum_update_dpm_settings(struct pp_hwmgr *hwmgr, void *profile_settin
 
 extern int smum_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw);
 
+extern int smum_stop_smc(struct pp_hwmgr *hwmgr);
+
 #endif
index 3be40114e63d2e274ac17006961570becaa1cd78..45f608838f6ebf0e457e65fd8191846b9e03ea39 100644 (file)
@@ -142,12 +142,12 @@ static const struct baco_cmd_entry exit_baco_tbl[] =
        { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK,           BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 },
        { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK,          BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 },
        { CMD_DELAY_MS, 0, 0, 0, 20, 0 },
-       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x20 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 },
        { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 },
-       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 },
        { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 },
        { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 },
-       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x10 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 },
        { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 },
        { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 }
 };
@@ -155,6 +155,7 @@ static const struct baco_cmd_entry exit_baco_tbl[] =
 static const struct baco_cmd_entry clean_baco_tbl[] =
 {
        { CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 },
        { CMD_WRITE, mmCP_PFP_UCODE_ADDR, 0, 0, 0, 0 }
 };
 
index 1e8919b0acdb262c714f4229be9855c64bbf436c..35629140fc7aa0e65ac99c7eba9a7aceff7b3a03 100644 (file)
@@ -1541,6 +1541,10 @@ static int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
        PP_ASSERT_WITH_CODE((tmp_result == 0),
                        "Failed to reset to default!", result = tmp_result);
 
+       tmp_result = smum_stop_smc(hwmgr);
+       PP_ASSERT_WITH_CODE((tmp_result == 0),
+                       "Failed to stop smc!", result = tmp_result);
+
        tmp_result = smu7_force_switch_to_arbf0(hwmgr);
        PP_ASSERT_WITH_CODE((tmp_result == 0),
                        "Failed to force to switch arbf0!", result = tmp_result);
@@ -1585,18 +1589,24 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
        data->current_profile_setting.sclk_down_hyst = 100;
        data->current_profile_setting.sclk_activity = SMU7_SCLK_TARGETACTIVITY_DFLT;
        data->current_profile_setting.bupdate_mclk = 1;
-       if (adev->gmc.vram_width == 256) {
-               data->current_profile_setting.mclk_up_hyst = 10;
-               data->current_profile_setting.mclk_down_hyst = 60;
-               data->current_profile_setting.mclk_activity = 25;
-       } else if (adev->gmc.vram_width == 128) {
-               data->current_profile_setting.mclk_up_hyst = 5;
-               data->current_profile_setting.mclk_down_hyst = 16;
-               data->current_profile_setting.mclk_activity = 20;
-       } else if (adev->gmc.vram_width == 64) {
-               data->current_profile_setting.mclk_up_hyst = 3;
-               data->current_profile_setting.mclk_down_hyst = 16;
-               data->current_profile_setting.mclk_activity = 20;
+       if (hwmgr->chip_id >= CHIP_POLARIS10) {
+               if (adev->gmc.vram_width == 256) {
+                       data->current_profile_setting.mclk_up_hyst = 10;
+                       data->current_profile_setting.mclk_down_hyst = 60;
+                       data->current_profile_setting.mclk_activity = 25;
+               } else if (adev->gmc.vram_width == 128) {
+                       data->current_profile_setting.mclk_up_hyst = 5;
+                       data->current_profile_setting.mclk_down_hyst = 16;
+                       data->current_profile_setting.mclk_activity = 20;
+               } else if (adev->gmc.vram_width == 64) {
+                       data->current_profile_setting.mclk_up_hyst = 3;
+                       data->current_profile_setting.mclk_down_hyst = 16;
+                       data->current_profile_setting.mclk_activity = 20;
+               }
+       } else {
+               data->current_profile_setting.mclk_up_hyst = 0;
+               data->current_profile_setting.mclk_down_hyst = 100;
+               data->current_profile_setting.mclk_activity = SMU7_MCLK_TARGETACTIVITY_DFLT;
        }
        hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
        hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
index e4d1f3d66ef4888fe4a9d2add1fe240db14731d0..329bf4d44bbceb0f1e0afe052f5b9c8abf0c2117 100644 (file)
@@ -2726,10 +2726,7 @@ static int ci_initialize_mc_reg_table(struct pp_hwmgr *hwmgr)
 
 static bool ci_is_dpm_running(struct pp_hwmgr *hwmgr)
 {
-       return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device,
-                                            CGS_IND_REG__SMC, FEATURE_STATUS,
-                                            VOLTAGE_CONTROLLER_ON))
-               ? true : false;
+       return ci_is_smc_ram_running(hwmgr);
 }
 
 static int ci_smu_init(struct pp_hwmgr *hwmgr)
@@ -2939,6 +2936,29 @@ static int ci_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type)
        return 0;
 }
 
+static void ci_reset_smc(struct pp_hwmgr *hwmgr)
+{
+       PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+                                 SMC_SYSCON_RESET_CNTL,
+                                 rst_reg, 1);
+}
+
+
+static void ci_stop_smc_clock(struct pp_hwmgr *hwmgr)
+{
+       PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+                                 SMC_SYSCON_CLOCK_CNTL_0,
+                                 ck_disable, 1);
+}
+
+static int ci_stop_smc(struct pp_hwmgr *hwmgr)
+{
+       ci_reset_smc(hwmgr);
+       ci_stop_smc_clock(hwmgr);
+
+       return 0;
+}
+
 const struct pp_smumgr_func ci_smu_funcs = {
        .name = "ci_smu",
        .smu_init = ci_smu_init,
@@ -2964,4 +2984,5 @@ const struct pp_smumgr_func ci_smu_funcs = {
        .is_dpm_running = ci_is_dpm_running,
        .update_dpm_settings = ci_update_dpm_settings,
        .update_smc_table = ci_update_smc_table,
+       .stop_smc = ci_stop_smc,
 };
index b6fb480668416a92892f5e6d85122d0a5ac2eb8b..b6921db3c1305988ff974e34352e4d49264f8193 100644 (file)
@@ -245,3 +245,11 @@ int smum_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t tabl
 
        return -EINVAL;
 }
+
+int smum_stop_smc(struct pp_hwmgr *hwmgr)
+{
+       if (hwmgr->smumgr_funcs->stop_smc)
+               return hwmgr->smumgr_funcs->stop_smc(hwmgr);
+
+       return 0;
+}
index fc4f95fa87cf62b381da5449320bacb7cb9ce2f7..b1e5ec01527b82d7035ba705fe5b1ad4de4188c0 100644 (file)
@@ -1029,17 +1029,6 @@ static int smu_smc_hw_setup(struct smu_context *smu)
                return ret;
        }
 
-       /*
-        * Set initialized values (get from vbios) to dpm tables context such as
-        * gfxclk, memclk, dcefclk, and etc. And enable the DPM feature for each
-        * type of clks.
-        */
-       ret = smu_set_default_dpm_table(smu);
-       if (ret) {
-               dev_err(adev->dev, "Failed to setup default dpm clock tables!\n");
-               return ret;
-       }
-
        ret = smu_notify_display_change(smu);
        if (ret)
                return ret;
index 8d8081c6bd3850f62a18d2b9879341ea3ce6c89f..ef1a62e86a0ee2d11f86f27aa713790bb19fc8ed 100644 (file)
@@ -1361,14 +1361,9 @@ static int navi10_get_fan_speed_rpm(struct smu_context *smu,
        if (!speed)
                return -EINVAL;
 
-       switch (smu_v11_0_get_fan_control_mode(smu)) {
-       case AMD_FAN_CTRL_AUTO:
-               return navi10_get_smu_metrics_data(smu,
-                                                  METRICS_CURR_FANSPEED,
-                                                  speed);
-       default:
-               return smu_v11_0_get_fan_speed_rpm(smu, speed);
-       }
+       return navi10_get_smu_metrics_data(smu,
+                                          METRICS_CURR_FANSPEED,
+                                          speed);
 }
 
 static int navi10_get_fan_parameters(struct smu_context *smu)
@@ -2534,29 +2529,6 @@ static const struct i2c_algorithm navi10_i2c_algo = {
        .functionality = navi10_i2c_func,
 };
 
-static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
-{
-       struct amdgpu_device *adev = to_amdgpu_device(control);
-       int res;
-
-       control->owner = THIS_MODULE;
-       control->class = I2C_CLASS_SPD;
-       control->dev.parent = &adev->pdev->dev;
-       control->algo = &navi10_i2c_algo;
-       snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
-
-       res = i2c_add_adapter(control);
-       if (res)
-               DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
-
-       return res;
-}
-
-static void navi10_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control)
-{
-       i2c_del_adapter(control);
-}
-
 static ssize_t navi10_get_gpu_metrics(struct smu_context *smu,
                                      void **table)
 {
@@ -2687,8 +2659,6 @@ static const struct pptable_funcs navi10_ppt_funcs = {
        .set_default_dpm_table = navi10_set_default_dpm_table,
        .dpm_set_vcn_enable = navi10_dpm_set_vcn_enable,
        .dpm_set_jpeg_enable = navi10_dpm_set_jpeg_enable,
-       .i2c_init = navi10_i2c_control_init,
-       .i2c_fini = navi10_i2c_control_fini,
        .print_clk_levels = navi10_print_clk_levels,
        .force_clk_levels = navi10_force_clk_levels,
        .populate_umd_state_clk = navi10_populate_umd_state_clk,
index 685a8a3b25d4d75466aeeb839bb1edfd3a15ac4f..895d89bea7faa68f6d9d11f24c8068fcb1b64b1a 100644 (file)
@@ -1177,14 +1177,9 @@ static int sienna_cichlid_get_fan_speed_rpm(struct smu_context *smu,
        if (!speed)
                return -EINVAL;
 
-       switch (smu_v11_0_get_fan_control_mode(smu)) {
-       case AMD_FAN_CTRL_AUTO:
-               return sienna_cichlid_get_smu_metrics_data(smu,
-                                                          METRICS_CURR_FANSPEED,
-                                                          speed);
-       default:
-               return smu_v11_0_get_fan_speed_rpm(smu, speed);
-       }
+       return sienna_cichlid_get_smu_metrics_data(smu,
+                                               METRICS_CURR_FANSPEED,
+                                               speed);
 }
 
 static int sienna_cichlid_get_fan_parameters(struct smu_context *smu)
index 2380759ddf480bd20dba8557ca292122fa49c1db..6db96fa1df0926d51df428f0fc5649ca731b22c9 100644 (file)
@@ -1164,7 +1164,12 @@ int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
        if (ret)
                return ret;
 
-       crystal_clock_freq = amdgpu_asic_get_xclk(adev);
+       /*
+        * crystal_clock_freq div by 4 is required since the fan control
+        * module refers to 25MHz
+        */
+
+       crystal_clock_freq = amdgpu_asic_get_xclk(adev) / 4;
        tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
        WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
                     REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
index 834a156e3a7502b0626e983c4483f2ef0e3df3f5..0a1e1cf57e199dfc37c9544edc361516144f2113 100644 (file)
@@ -742,7 +742,6 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
        case DRM_MODE_DPMS_SUSPEND:
                if (ast->tx_chip_type == AST_TX_DP501)
                        ast_set_dp501_video_output(crtc->dev, 1);
-               ast_crtc_load_lut(ast, crtc);
                break;
        case DRM_MODE_DPMS_OFF:
                if (ast->tx_chip_type == AST_TX_DP501)
@@ -777,6 +776,21 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc,
        return 0;
 }
 
+static void
+ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state)
+{
+       struct ast_private *ast = to_ast_private(crtc->dev);
+       struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc->state);
+       struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
+
+       /*
+        * The gamma LUT has to be reloaded after changing the primary
+        * plane's color format.
+        */
+       if (old_ast_crtc_state->format != ast_crtc_state->format)
+               ast_crtc_load_lut(ast, crtc);
+}
+
 static void
 ast_crtc_helper_atomic_enable(struct drm_crtc *crtc,
                              struct drm_crtc_state *old_crtc_state)
@@ -830,6 +844,7 @@ ast_crtc_helper_atomic_disable(struct drm_crtc *crtc,
 
 static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {
        .atomic_check = ast_crtc_helper_atomic_check,
+       .atomic_flush = ast_crtc_helper_atomic_flush,
        .atomic_enable = ast_crtc_helper_atomic_enable,
        .atomic_disable = ast_crtc_helper_atomic_disable,
 };
index 511d67b16d14d0903bec53dc6ab9de2d4473fab5..ef8c230e0f626f33da98cb1f66d3d56eb7a22d76 100644 (file)
@@ -13,7 +13,7 @@ config DRM_CDNS_MHDP8546
 if DRM_CDNS_MHDP8546
 
 config DRM_CDNS_MHDP8546_J721E
-       depends on ARCH_K3_J721E_SOC || COMPILE_TEST
+       depends on ARCH_K3 || COMPILE_TEST
        bool "J721E Cadence DPI/DP wrapper support"
        default y
        help
index 748df1cacd2b79aec363d2fd7e2221df74b4b582..0c79a9ba48bb6407d7a001b2e03cca139d4ed28d 100644 (file)
@@ -2327,12 +2327,6 @@ static enum drm_connector_status dw_hdmi_detect(struct dw_hdmi *hdmi)
 {
        enum drm_connector_status result;
 
-       mutex_lock(&hdmi->mutex);
-       hdmi->force = DRM_FORCE_UNSPECIFIED;
-       dw_hdmi_update_power(hdmi);
-       dw_hdmi_update_phy_mask(hdmi);
-       mutex_unlock(&hdmi->mutex);
-
        result = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
 
        mutex_lock(&hdmi->mutex);
index 90807a6b415ca8598e83f72dd0a589c0d3cbc0b6..deeed73f4ed6924d92a9f66668a1249a6f144f4d 100644 (file)
@@ -374,6 +374,10 @@ static bool is_edid_digital_input_dp(const struct edid *edid)
  * drm_dp_downstream_is_type() - is the downstream facing port of certain type?
  * @dpcd: DisplayPort configuration data
  * @port_cap: port capabilities
+ * @type: port type to be checked. Can be:
+ *       %DP_DS_PORT_TYPE_DP, %DP_DS_PORT_TYPE_VGA, %DP_DS_PORT_TYPE_DVI,
+ *       %DP_DS_PORT_TYPE_HDMI, %DP_DS_PORT_TYPE_NON_EDID,
+ *       %DP_DS_PORT_TYPE_DP_DUALMODE or %DP_DS_PORT_TYPE_WIRELESS.
  *
  * Caveat: Only works with DPCD 1.1+ port caps.
  *
@@ -870,6 +874,7 @@ EXPORT_SYMBOL(drm_dp_downstream_444_to_420_conversion);
 
 /**
  * drm_dp_downstream_mode() - return a mode for downstream facing port
+ * @dev: DRM device
  * @dpcd: DisplayPort configuration data
  * @port_cap: port capabilities
  *
@@ -1028,7 +1033,8 @@ EXPORT_SYMBOL(drm_dp_downstream_debug);
 
 /**
  * drm_dp_subconnector_type() - get DP branch device type
- *
+ * @dpcd: DisplayPort configuration data
+ * @port_cap: port capabilities
  */
 enum drm_mode_subconnector
 drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
@@ -1079,6 +1085,10 @@ EXPORT_SYMBOL(drm_dp_subconnector_type);
 
 /**
  * drm_mode_set_dp_subconnector_property - set subconnector for DP connector
+ * @connector: connector to set property on
+ * @status: connector status
+ * @dpcd: DisplayPort configuration data
+ * @port_cap: port capabilities
  *
  * Called by a driver on every detect event.
  */
index a82f37d4425826b72f9bb036fad293c51408574f..631125b46e04c6df67a5a14a13cc4b98b6061137 100644 (file)
@@ -3741,7 +3741,7 @@ drm_add_cmdb_modes(struct drm_connector *connector, u8 svd)
 /**
  * drm_display_mode_from_cea_vic() - return a mode for CEA VIC
  * @dev: DRM device
- * @vic: CEA VIC of the mode
+ * @video_code: CEA VIC of the mode
  *
  * Creates a new mode matching the specified CEA VIC.
  *
index 19d73868490e65d3b35040a47065378186101674..69c2c079d8036bcde1d17b717c50ea5168cea2a1 100644 (file)
@@ -1085,6 +1085,8 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
         */
        drm_gem_object_get(obj);
 
+       vma->vm_private_data = obj;
+
        if (obj->funcs && obj->funcs->mmap) {
                ret = obj->funcs->mmap(obj, vma);
                if (ret) {
@@ -1107,8 +1109,6 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
                vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
        }
 
-       vma->vm_private_data = obj;
-
        return 0;
 }
 EXPORT_SYMBOL(drm_gem_mmap_obj);
index d77c9f8ff26ced1e994792f36e4cc49321bb31f3..e00616d94f26ef9b21584fd2a0f8311b5a714d32 100644 (file)
@@ -593,8 +593,13 @@ int drm_gem_shmem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
        /* Remove the fake offset */
        vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node);
 
-       if (obj->import_attach)
+       if (obj->import_attach) {
+               /* Drop the reference drm_gem_mmap_obj() acquired.*/
+               drm_gem_object_put(obj);
+               vma->vm_private_data = NULL;
+
                return dma_buf_mmap(obj->dma_buf, vma, 0);
+       }
 
        shmem = to_drm_gem_shmem_obj(obj);
 
index 50cad0e4a92e381677a181be89d2155c05fc4d4f..375c79e23ca59500ac32a5b90c6825987ae8ac9b 100644 (file)
@@ -140,7 +140,7 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo,
        unsigned int c = 0;
 
        if (pl_flag & DRM_GEM_VRAM_PL_FLAG_TOPDOWN)
-               pl_flag = TTM_PL_FLAG_TOPDOWN;
+               invariant_flags = TTM_PL_FLAG_TOPDOWN;
 
        gbo->placement.placement = gbo->placements;
        gbo->placement.busy_placement = gbo->placements;
index d6808f678db541388e1e808085d4ec022e6acd43..9f955f2010c25770f53110a2ff92ba98d0caadf4 100644 (file)
@@ -794,6 +794,7 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
 
 /**
  * drm_prime_pages_to_sg - converts a page array into an sg list
+ * @dev: DRM device
  * @pages: pointer to the array of page pointers to convert
  * @nr_pages: length of the page vector
  *
index 6417f374b923a454a4279753aee7e4fb3a91d64a..951d5f708e92b0b9600eb8501bc2390c6b85246b 100644 (file)
@@ -1,7 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config DRM_EXYNOS
        tristate "DRM Support for Samsung SoC Exynos Series"
-       depends on OF && DRM && (ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS || ARCH_MULTIPLATFORM || COMPILE_TEST)
+       depends on OF && DRM && COMMON_CLK
+       depends on ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS || ARCH_MULTIPLATFORM || COMPILE_TEST
        depends on MMU
        select DRM_KMS_HELPER
        select VIDEOMODE_HELPERS
index 15eb3770d817e974af5455c6f7d1815342c1d0eb..361e3a0c5ab6b56b5405566d39fcefa338b3c8f0 100644 (file)
@@ -347,6 +347,7 @@ int psb_irq_postinstall(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
+       unsigned int i;
 
        spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
@@ -359,20 +360,12 @@ int psb_irq_postinstall(struct drm_device *dev)
        PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
        PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
 
-       if (dev->vblank[0].enabled)
-               psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
-       else
-               psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-       if (dev->vblank[1].enabled)
-               psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
-       else
-               psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-       if (dev->vblank[2].enabled)
-               psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
-       else
-               psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
+       for (i = 0; i < dev->num_crtcs; ++i) {
+               if (dev->vblank[i].enabled)
+                       psb_enable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE);
+               else
+                       psb_disable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE);
+       }
 
        if (dev_priv->ops->hotplug_enable)
                dev_priv->ops->hotplug_enable(dev, true);
@@ -385,6 +378,7 @@ void psb_irq_uninstall(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
+       unsigned int i;
 
        spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
@@ -393,14 +387,10 @@ void psb_irq_uninstall(struct drm_device *dev)
 
        PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
 
-       if (dev->vblank[0].enabled)
-               psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-       if (dev->vblank[1].enabled)
-               psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-       if (dev->vblank[2].enabled)
-               psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
+       for (i = 0; i < dev->num_crtcs; ++i) {
+               if (dev->vblank[i].enabled)
+                       psb_disable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE);
+       }
 
        dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG |
                                  _PSB_IRQ_MSVDX_FLAG |
index 829b2a40a48219810c162c0d8c312dceec470b40..3bfe6ed67da182f358f3b09dd924034dc943a4da 100644 (file)
@@ -10636,6 +10636,10 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
            val & PLANE_CTL_FLIP_HORIZONTAL)
                plane_config->rotation |= DRM_MODE_REFLECT_X;
 
+       /* 90/270 degree rotation would require extra work */
+       if (drm_rotation_90_or_270(plane_config->rotation))
+               goto error;
+
        base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & 0xfffff000;
        plane_config->base = base;
 
@@ -12874,10 +12878,11 @@ compute_sink_pipe_bpp(const struct drm_connector_state *conn_state,
        case 10 ... 11:
                bpp = 10 * 3;
                break;
-       case 12:
+       case 12 ... 16:
                bpp = 12 * 3;
                break;
        default:
+               MISSING_CASE(conn_state->max_bpc);
                return -EINVAL;
        }
 
@@ -18016,16 +18021,6 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915)
        if (!HAS_GMCH(i915))
                sanitize_watermarks(i915);
 
-       /*
-        * Force all active planes to recompute their states. So that on
-        * mode_setcrtc after probe, all the intel_plane_state variables
-        * are already calculated and there is no assert_plane warnings
-        * during bootup.
-        */
-       ret = intel_initial_commit(dev);
-       if (ret)
-               drm_dbg_kms(&i915->drm, "Initial commit in probe failed.\n");
-
        return 0;
 }
 
@@ -18034,11 +18029,21 @@ int intel_modeset_init(struct drm_i915_private *i915)
 {
        int ret;
 
-       intel_overlay_setup(i915);
-
        if (!HAS_DISPLAY(i915))
                return 0;
 
+       /*
+        * Force all active planes to recompute their states. So that on
+        * mode_setcrtc after probe, all the intel_plane_state variables
+        * are already calculated and there is no assert_plane warnings
+        * during bootup.
+        */
+       ret = intel_initial_commit(&i915->drm);
+       if (ret)
+               return ret;
+
+       intel_overlay_setup(i915);
+
        ret = intel_fbdev_init(&i915->drm);
        if (ret)
                return ret;
index 8a9d0bdde1bfb229a725e94b4a4c3c659fc9ed52..40e9cb29233d4d49c730b037e9c4ac0431e8dc23 100644 (file)
@@ -1754,7 +1754,7 @@ void intel_psr_atomic_check(struct drm_connector *connector,
                return;
 
        intel_connector = to_intel_connector(connector);
-       dig_port = enc_to_dig_port(intel_attached_encoder(intel_connector));
+       dig_port = enc_to_dig_port(to_intel_encoder(new_state->best_encoder));
        if (dev_priv->psr.dp != &dig_port->dp)
                return;
 
index 7c90a63c273d8d52e2148f45bee13e94d4e27e6e..fcce6909f201769876dea539f22681ff37d80ec6 100644 (file)
@@ -508,21 +508,6 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
        if (!obj)
                return -ENOENT;
 
-       /*
-        * Already in the desired write domain? Nothing for us to do!
-        *
-        * We apply a little bit of cunning here to catch a broader set of
-        * no-ops. If obj->write_domain is set, we must be in the same
-        * obj->read_domains, and only that domain. Therefore, if that
-        * obj->write_domain matches the request read_domains, we are
-        * already in the same read/write domain and can skip the operation,
-        * without having to further check the requested write_domain.
-        */
-       if (READ_ONCE(obj->write_domain) == read_domains) {
-               err = 0;
-               goto out;
-       }
-
        /*
         * Try to flush the object off the GPU without holding the lock.
         * We will repeat the flush holding the lock in the normal manner
@@ -560,6 +545,19 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
        if (err)
                goto out;
 
+       /*
+        * Already in the desired write domain? Nothing for us to do!
+        *
+        * We apply a little bit of cunning here to catch a broader set of
+        * no-ops. If obj->write_domain is set, we must be in the same
+        * obj->read_domains, and only that domain. Therefore, if that
+        * obj->write_domain matches the request read_domains, we are
+        * already in the same read/write domain and can skip the operation,
+        * without having to further check the requested write_domain.
+        */
+       if (READ_ONCE(obj->write_domain) == read_domains)
+               goto out_unpin;
+
        err = i915_gem_object_lock_interruptible(obj, NULL);
        if (err)
                goto out_unpin;
index b5c15557cc87b8eaced85355b8e1eb5d4abfcabd..d6711caa7f399564120d7eb9dca039bcf3183bd0 100644 (file)
@@ -56,6 +56,8 @@ struct drm_i915_gem_object_ops {
        void (*truncate)(struct drm_i915_gem_object *obj);
        void (*writeback)(struct drm_i915_gem_object *obj);
 
+       int (*pread)(struct drm_i915_gem_object *obj,
+                    const struct drm_i915_gem_pread *arg);
        int (*pwrite)(struct drm_i915_gem_object *obj,
                      const struct drm_i915_gem_pwrite *arg);
 
index 28147aab47b9ae60e8cef05378524b6d73833193..3a4dfe2ef1da5b9d847105f49bfacd50524a3252 100644 (file)
@@ -134,6 +134,58 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
                          vaddr, dma);
 }
 
+static int
+phys_pwrite(struct drm_i915_gem_object *obj,
+           const struct drm_i915_gem_pwrite *args)
+{
+       void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
+       char __user *user_data = u64_to_user_ptr(args->data_ptr);
+       int err;
+
+       err = i915_gem_object_wait(obj,
+                                  I915_WAIT_INTERRUPTIBLE |
+                                  I915_WAIT_ALL,
+                                  MAX_SCHEDULE_TIMEOUT);
+       if (err)
+               return err;
+
+       /*
+        * We manually control the domain here and pretend that it
+        * remains coherent i.e. in the GTT domain, like shmem_pwrite.
+        */
+       i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
+
+       if (copy_from_user(vaddr, user_data, args->size))
+               return -EFAULT;
+
+       drm_clflush_virt_range(vaddr, args->size);
+       intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);
+
+       i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
+       return 0;
+}
+
+static int
+phys_pread(struct drm_i915_gem_object *obj,
+          const struct drm_i915_gem_pread *args)
+{
+       void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
+       char __user *user_data = u64_to_user_ptr(args->data_ptr);
+       int err;
+
+       err = i915_gem_object_wait(obj,
+                                  I915_WAIT_INTERRUPTIBLE,
+                                  MAX_SCHEDULE_TIMEOUT);
+       if (err)
+               return err;
+
+       drm_clflush_virt_range(vaddr, args->size);
+       if (copy_to_user(user_data, vaddr, args->size))
+               return -EFAULT;
+
+       return 0;
+}
+
 static void phys_release(struct drm_i915_gem_object *obj)
 {
        fput(obj->base.filp);
@@ -144,6 +196,9 @@ static const struct drm_i915_gem_object_ops i915_gem_phys_ops = {
        .get_pages = i915_gem_object_get_pages_phys,
        .put_pages = i915_gem_object_put_pages_phys,
 
+       .pread  = phys_pread,
+       .pwrite = phys_pwrite,
+
        .release = phys_release,
 };
 
index d8b206e53660a9d0457b0d790dc8d4e8ea5e2a0f..a24cc1ff08a0c4a6b2d4853fdfa5af04973cca91 100644 (file)
 #include "i915_trace.h"
 #include "intel_breadcrumbs.h"
 #include "intel_context.h"
+#include "intel_engine_pm.h"
 #include "intel_gt_pm.h"
 #include "intel_gt_requests.h"
 
-static void irq_enable(struct intel_engine_cs *engine)
+static bool irq_enable(struct intel_engine_cs *engine)
 {
        if (!engine->irq_enable)
-               return;
+               return false;
 
        /* Caller disables interrupts */
        spin_lock(&engine->gt->irq_lock);
        engine->irq_enable(engine);
        spin_unlock(&engine->gt->irq_lock);
+
+       return true;
 }
 
 static void irq_disable(struct intel_engine_cs *engine)
@@ -57,12 +60,11 @@ static void irq_disable(struct intel_engine_cs *engine)
 
 static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b)
 {
-       lockdep_assert_held(&b->irq_lock);
-
-       if (!b->irq_engine || b->irq_armed)
-               return;
-
-       if (!intel_gt_pm_get_if_awake(b->irq_engine->gt))
+       /*
+        * Since we are waiting on a request, the GPU should be busy
+        * and should have its own rpm reference.
+        */
+       if (GEM_WARN_ON(!intel_gt_pm_get_if_awake(b->irq_engine->gt)))
                return;
 
        /*
@@ -73,25 +75,24 @@ static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b)
         */
        WRITE_ONCE(b->irq_armed, true);
 
-       /*
-        * Since we are waiting on a request, the GPU should be busy
-        * and should have its own rpm reference. This is tracked
-        * by i915->gt.awake, we can forgo holding our own wakref
-        * for the interrupt as before i915->gt.awake is released (when
-        * the driver is idle) we disarm the breadcrumbs.
-        */
-
-       if (!b->irq_enabled++)
-               irq_enable(b->irq_engine);
+       /* Requests may have completed before we could enable the interrupt. */
+       if (!b->irq_enabled++ && irq_enable(b->irq_engine))
+               irq_work_queue(&b->irq_work);
 }
 
-static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b)
+static void intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b)
 {
-       lockdep_assert_held(&b->irq_lock);
-
-       if (!b->irq_engine || !b->irq_armed)
+       if (!b->irq_engine)
                return;
 
+       spin_lock(&b->irq_lock);
+       if (!b->irq_armed)
+               __intel_breadcrumbs_arm_irq(b);
+       spin_unlock(&b->irq_lock);
+}
+
+static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b)
+{
        GEM_BUG_ON(!b->irq_enabled);
        if (!--b->irq_enabled)
                irq_disable(b->irq_engine);
@@ -100,20 +101,37 @@ static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b)
        intel_gt_pm_put_async(b->irq_engine->gt);
 }
 
+static void intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b)
+{
+       spin_lock(&b->irq_lock);
+       if (b->irq_armed)
+               __intel_breadcrumbs_disarm_irq(b);
+       spin_unlock(&b->irq_lock);
+}
+
 static void add_signaling_context(struct intel_breadcrumbs *b,
                                  struct intel_context *ce)
 {
-       intel_context_get(ce);
-       list_add_tail(&ce->signal_link, &b->signalers);
-       if (list_is_first(&ce->signal_link, &b->signalers))
-               __intel_breadcrumbs_arm_irq(b);
+       lockdep_assert_held(&ce->signal_lock);
+
+       spin_lock(&b->signalers_lock);
+       list_add_rcu(&ce->signal_link, &b->signalers);
+       spin_unlock(&b->signalers_lock);
 }
 
-static void remove_signaling_context(struct intel_breadcrumbs *b,
+static bool remove_signaling_context(struct intel_breadcrumbs *b,
                                     struct intel_context *ce)
 {
-       list_del(&ce->signal_link);
-       intel_context_put(ce);
+       lockdep_assert_held(&ce->signal_lock);
+
+       if (!list_empty(&ce->signals))
+               return false;
+
+       spin_lock(&b->signalers_lock);
+       list_del_rcu(&ce->signal_link);
+       spin_unlock(&b->signalers_lock);
+
+       return true;
 }
 
 static inline bool __request_completed(const struct i915_request *rq)
@@ -174,73 +192,103 @@ static void add_retire(struct intel_breadcrumbs *b, struct intel_timeline *tl)
                intel_engine_add_retire(b->irq_engine, tl);
 }
 
-static bool __signal_request(struct i915_request *rq, struct list_head *signals)
+static bool __signal_request(struct i915_request *rq)
 {
-       clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags);
+       GEM_BUG_ON(test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags));
 
        if (!__dma_fence_signal(&rq->fence)) {
                i915_request_put(rq);
                return false;
        }
 
-       list_add_tail(&rq->signal_link, signals);
        return true;
 }
 
+static struct llist_node *
+slist_add(struct llist_node *node, struct llist_node *head)
+{
+       node->next = head;
+       return node;
+}
+
 static void signal_irq_work(struct irq_work *work)
 {
        struct intel_breadcrumbs *b = container_of(work, typeof(*b), irq_work);
        const ktime_t timestamp = ktime_get();
-       struct intel_context *ce, *cn;
-       struct list_head *pos, *next;
-       LIST_HEAD(signal);
-
-       spin_lock(&b->irq_lock);
+       struct llist_node *signal, *sn;
+       struct intel_context *ce;
 
-       if (list_empty(&b->signalers))
-               __intel_breadcrumbs_disarm_irq(b);
+       signal = NULL;
+       if (unlikely(!llist_empty(&b->signaled_requests)))
+               signal = llist_del_all(&b->signaled_requests);
 
-       list_splice_init(&b->signaled_requests, &signal);
+       /*
+        * Keep the irq armed until the interrupt after all listeners are gone.
+        *
+        * Enabling/disabling the interrupt is rather costly, roughly a couple
+        * of hundred microseconds. If we are proactive and enable/disable
+        * the interrupt around every request that wants a breadcrumb, we
+        * quickly drown in the extra orders of magnitude of latency imposed
+        * on request submission.
+        *
+        * So we try to be lazy, and keep the interrupts enabled until no
+        * more listeners appear within a breadcrumb interrupt interval (that
+        * is until a request completes that no one cares about). The
+        * observation is that listeners come in batches, and will often
+        * listen to a bunch of requests in succession. Though note on icl+,
+        * interrupts are always enabled due to concerns with rc6 being
+        * dysfunctional with per-engine interrupt masking.
+        *
+        * We also try to avoid raising too many interrupts, as they may
+        * be generated by userspace batches and it is unfortunately rather
+        * too easy to drown the CPU under a flood of GPU interrupts. Thus
+        * whenever no one appears to be listening, we turn off the interrupts.
+        * Fewer interrupts should conserve power -- at the very least, fewer
+        * interrupt draw less ire from other users of the system and tools
+        * like powertop.
+        */
+       if (!signal && READ_ONCE(b->irq_armed) && list_empty(&b->signalers))
+               intel_breadcrumbs_disarm_irq(b);
 
-       list_for_each_entry_safe(ce, cn, &b->signalers, signal_link) {
-               GEM_BUG_ON(list_empty(&ce->signals));
+       rcu_read_lock();
+       list_for_each_entry_rcu(ce, &b->signalers, signal_link) {
+               struct i915_request *rq;
 
-               list_for_each_safe(pos, next, &ce->signals) {
-                       struct i915_request *rq =
-                               list_entry(pos, typeof(*rq), signal_link);
+               list_for_each_entry_rcu(rq, &ce->signals, signal_link) {
+                       bool release;
 
-                       GEM_BUG_ON(!check_signal_order(ce, rq));
                        if (!__request_completed(rq))
                                break;
 
+                       if (!test_and_clear_bit(I915_FENCE_FLAG_SIGNAL,
+                                               &rq->fence.flags))
+                               break;
+
                        /*
                         * Queue for execution after dropping the signaling
                         * spinlock as the callback chain may end up adding
                         * more signalers to the same context or engine.
                         */
-                       __signal_request(rq, &signal);
-               }
+                       spin_lock(&ce->signal_lock);
+                       list_del_rcu(&rq->signal_link);
+                       release = remove_signaling_context(b, ce);
+                       spin_unlock(&ce->signal_lock);
 
-               /*
-                * We process the list deletion in bulk, only using a list_add
-                * (not list_move) above but keeping the status of
-                * rq->signal_link known with the I915_FENCE_FLAG_SIGNAL bit.
-                */
-               if (!list_is_first(pos, &ce->signals)) {
-                       /* Advance the list to the first incomplete request */
-                       __list_del_many(&ce->signals, pos);
-                       if (&ce->signals == pos) { /* now empty */
+                       if (__signal_request(rq))
+                               /* We own signal_node now, xfer to local list */
+                               signal = slist_add(&rq->signal_node, signal);
+
+                       if (release) {
                                add_retire(b, ce->timeline);
-                               remove_signaling_context(b, ce);
+                               intel_context_put(ce);
                        }
                }
        }
+       rcu_read_unlock();
 
-       spin_unlock(&b->irq_lock);
-
-       list_for_each_safe(pos, next, &signal) {
+       llist_for_each_safe(signal, sn, signal) {
                struct i915_request *rq =
-                       list_entry(pos, typeof(*rq), signal_link);
+                       llist_entry(signal, typeof(*rq), signal_node);
                struct list_head cb_list;
 
                spin_lock(&rq->lock);
@@ -251,6 +299,9 @@ static void signal_irq_work(struct irq_work *work)
 
                i915_request_put(rq);
        }
+
+       if (!READ_ONCE(b->irq_armed) && !list_empty(&b->signalers))
+               intel_breadcrumbs_arm_irq(b);
 }
 
 struct intel_breadcrumbs *
@@ -262,14 +313,15 @@ intel_breadcrumbs_create(struct intel_engine_cs *irq_engine)
        if (!b)
                return NULL;
 
-       spin_lock_init(&b->irq_lock);
+       b->irq_engine = irq_engine;
+
+       spin_lock_init(&b->signalers_lock);
        INIT_LIST_HEAD(&b->signalers);
-       INIT_LIST_HEAD(&b->signaled_requests);
+       init_llist_head(&b->signaled_requests);
 
+       spin_lock_init(&b->irq_lock);
        init_irq_work(&b->irq_work, signal_irq_work);
 
-       b->irq_engine = irq_engine;
-
        return b;
 }
 
@@ -292,27 +344,28 @@ void intel_breadcrumbs_reset(struct intel_breadcrumbs *b)
 
 void intel_breadcrumbs_park(struct intel_breadcrumbs *b)
 {
-       unsigned long flags;
-
-       if (!READ_ONCE(b->irq_armed))
-               return;
-
-       spin_lock_irqsave(&b->irq_lock, flags);
-       __intel_breadcrumbs_disarm_irq(b);
-       spin_unlock_irqrestore(&b->irq_lock, flags);
-
-       if (!list_empty(&b->signalers))
-               irq_work_queue(&b->irq_work);
+       /* Kick the work once more to drain the signalers */
+       irq_work_sync(&b->irq_work);
+       while (unlikely(READ_ONCE(b->irq_armed))) {
+               local_irq_disable();
+               signal_irq_work(&b->irq_work);
+               local_irq_enable();
+               cond_resched();
+       }
+       GEM_BUG_ON(!list_empty(&b->signalers));
 }
 
 void intel_breadcrumbs_free(struct intel_breadcrumbs *b)
 {
+       irq_work_sync(&b->irq_work);
+       GEM_BUG_ON(!list_empty(&b->signalers));
+       GEM_BUG_ON(b->irq_armed);
        kfree(b);
 }
 
-static void insert_breadcrumb(struct i915_request *rq,
-                             struct intel_breadcrumbs *b)
+static void insert_breadcrumb(struct i915_request *rq)
 {
+       struct intel_breadcrumbs *b = READ_ONCE(rq->engine)->breadcrumbs;
        struct intel_context *ce = rq->context;
        struct list_head *pos;
 
@@ -327,12 +380,14 @@ static void insert_breadcrumb(struct i915_request *rq,
         * its signal completion.
         */
        if (__request_completed(rq)) {
-               if (__signal_request(rq, &b->signaled_requests))
+               if (__signal_request(rq) &&
+                   llist_add(&rq->signal_node, &b->signaled_requests))
                        irq_work_queue(&b->irq_work);
                return;
        }
 
        if (list_empty(&ce->signals)) {
+               intel_context_get(ce);
                add_signaling_context(b, ce);
                pos = &ce->signals;
        } else {
@@ -358,18 +413,22 @@ static void insert_breadcrumb(struct i915_request *rq,
                                break;
                }
        }
-       list_add(&rq->signal_link, pos);
+       list_add_rcu(&rq->signal_link, pos);
        GEM_BUG_ON(!check_signal_order(ce, rq));
+       GEM_BUG_ON(test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags));
        set_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags);
 
-       /* Check after attaching to irq, interrupt may have already fired. */
-       if (__request_completed(rq))
-               irq_work_queue(&b->irq_work);
+       /*
+        * Defer enabling the interrupt to after HW submission and recheck
+        * the request as it may have completed and raised the interrupt as
+        * we were attaching it into the lists.
+        */
+       irq_work_queue(&b->irq_work);
 }
 
 bool i915_request_enable_breadcrumb(struct i915_request *rq)
 {
-       struct intel_breadcrumbs *b;
+       struct intel_context *ce = rq->context;
 
        /* Serialises with i915_request_retire() using rq->lock */
        if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags))
@@ -384,67 +443,30 @@ bool i915_request_enable_breadcrumb(struct i915_request *rq)
        if (!test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags))
                return true;
 
-       /*
-        * rq->engine is locked by rq->engine->active.lock. That however
-        * is not known until after rq->engine has been dereferenced and
-        * the lock acquired. Hence we acquire the lock and then validate
-        * that rq->engine still matches the lock we hold for it.
-        *
-        * Here, we are using the breadcrumb lock as a proxy for the
-        * rq->engine->active.lock, and we know that since the breadcrumb
-        * will be serialised within i915_request_submit/i915_request_unsubmit,
-        * the engine cannot change while active as long as we hold the
-        * breadcrumb lock on that engine.
-        *
-        * From the dma_fence_enable_signaling() path, we are outside of the
-        * request submit/unsubmit path, and so we must be more careful to
-        * acquire the right lock.
-        */
-       b = READ_ONCE(rq->engine)->breadcrumbs;
-       spin_lock(&b->irq_lock);
-       while (unlikely(b != READ_ONCE(rq->engine)->breadcrumbs)) {
-               spin_unlock(&b->irq_lock);
-               b = READ_ONCE(rq->engine)->breadcrumbs;
-               spin_lock(&b->irq_lock);
-       }
-
-       /*
-        * Now that we are finally serialised with request submit/unsubmit,
-        * [with b->irq_lock] and with i915_request_retire() [via checking
-        * SIGNALED with rq->lock] confirm the request is indeed active. If
-        * it is no longer active, the breadcrumb will be attached upon
-        * i915_request_submit().
-        */
+       spin_lock(&ce->signal_lock);
        if (test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags))
-               insert_breadcrumb(rq, b);
-
-       spin_unlock(&b->irq_lock);
+               insert_breadcrumb(rq);
+       spin_unlock(&ce->signal_lock);
 
        return true;
 }
 
 void i915_request_cancel_breadcrumb(struct i915_request *rq)
 {
-       struct intel_breadcrumbs *b = rq->engine->breadcrumbs;
+       struct intel_context *ce = rq->context;
+       bool release;
 
-       /*
-        * We must wait for b->irq_lock so that we know the interrupt handler
-        * has released its reference to the intel_context and has completed
-        * the DMA_FENCE_FLAG_SIGNALED_BIT/I915_FENCE_FLAG_SIGNAL dance (if
-        * required).
-        */
-       spin_lock(&b->irq_lock);
-       if (test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags)) {
-               struct intel_context *ce = rq->context;
+       if (!test_and_clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags))
+               return;
 
-               list_del(&rq->signal_link);
-               if (list_empty(&ce->signals))
-                       remove_signaling_context(b, ce);
+       spin_lock(&ce->signal_lock);
+       list_del_rcu(&rq->signal_link);
+       release = remove_signaling_context(rq->engine->breadcrumbs, ce);
+       spin_unlock(&ce->signal_lock);
+       if (release)
+               intel_context_put(ce);
 
-               clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags);
-               i915_request_put(rq);
-       }
-       spin_unlock(&b->irq_lock);
+       i915_request_put(rq);
 }
 
 static void print_signals(struct intel_breadcrumbs *b, struct drm_printer *p)
@@ -454,18 +476,17 @@ static void print_signals(struct intel_breadcrumbs *b, struct drm_printer *p)
 
        drm_printf(p, "Signals:\n");
 
-       spin_lock_irq(&b->irq_lock);
-       list_for_each_entry(ce, &b->signalers, signal_link) {
-               list_for_each_entry(rq, &ce->signals, signal_link) {
+       rcu_read_lock();
+       list_for_each_entry_rcu(ce, &b->signalers, signal_link) {
+               list_for_each_entry_rcu(rq, &ce->signals, signal_link)
                        drm_printf(p, "\t[%llx:%llx%s] @ %dms\n",
                                   rq->fence.context, rq->fence.seqno,
                                   i915_request_completed(rq) ? "!" :
                                   i915_request_started(rq) ? "*" :
                                   "",
                                   jiffies_to_msecs(jiffies - rq->emitted_jiffies));
-               }
        }
-       spin_unlock_irq(&b->irq_lock);
+       rcu_read_unlock();
 }
 
 void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine,
index 8e53b99426958ffe2ce462890ddc754f34f7cf19..a74bb3062bd8a9ecc6c17f8709f30ff73fc3f4d0 100644 (file)
  * the overhead of waking that client is much preferred.
  */
 struct intel_breadcrumbs {
-       spinlock_t irq_lock; /* protects the lists used in hardirq context */
-
        /* Not all breadcrumbs are attached to physical HW */
        struct intel_engine_cs *irq_engine;
 
+       spinlock_t signalers_lock; /* protects the list of signalers */
        struct list_head signalers;
-       struct list_head signaled_requests;
+       struct llist_head signaled_requests;
 
+       spinlock_t irq_lock; /* protects the interrupt from hardirq context */
        struct irq_work irq_work; /* for use from inside irq_lock */
-
        unsigned int irq_enabled;
-
        bool irq_armed;
 };
 
index 92a3f25c400636b195f92041aaccaebc460e0be0..349e7fa1488dcd9be5a8ed745fdbec30803c49b4 100644 (file)
@@ -25,11 +25,18 @@ static struct intel_context *intel_context_alloc(void)
        return kmem_cache_zalloc(global.slab_ce, GFP_KERNEL);
 }
 
-void intel_context_free(struct intel_context *ce)
+static void rcu_context_free(struct rcu_head *rcu)
 {
+       struct intel_context *ce = container_of(rcu, typeof(*ce), rcu);
+
        kmem_cache_free(global.slab_ce, ce);
 }
 
+void intel_context_free(struct intel_context *ce)
+{
+       call_rcu(&ce->rcu, rcu_context_free);
+}
+
 struct intel_context *
 intel_context_create(struct intel_engine_cs *engine)
 {
@@ -356,8 +363,7 @@ static int __intel_context_active(struct i915_active *active)
 }
 
 void
-intel_context_init(struct intel_context *ce,
-                  struct intel_engine_cs *engine)
+intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine)
 {
        GEM_BUG_ON(!engine->cops);
        GEM_BUG_ON(!engine->gt->vm);
@@ -373,7 +379,8 @@ intel_context_init(struct intel_context *ce,
 
        ce->vm = i915_vm_get(engine->gt->vm);
 
-       INIT_LIST_HEAD(&ce->signal_link);
+       /* NB ce->signal_link/lock is used under RCU */
+       spin_lock_init(&ce->signal_lock);
        INIT_LIST_HEAD(&ce->signals);
 
        mutex_init(&ce->pin_mutex);
index 552cb57a2e8cdc9201cc35717a8bc2a972019cd3..52fa9c1327464f0cfa6ec85845b3e4776a186066 100644 (file)
@@ -25,6 +25,7 @@ DECLARE_EWMA(runtime, 3, 8);
 struct i915_gem_context;
 struct i915_gem_ww_ctx;
 struct i915_vma;
+struct intel_breadcrumbs;
 struct intel_context;
 struct intel_ring;
 
@@ -44,7 +45,16 @@ struct intel_context_ops {
 };
 
 struct intel_context {
-       struct kref ref;
+       /*
+        * Note: Some fields may be accessed under RCU.
+        *
+        * Unless otherwise noted a field can safely be assumed to be protected
+        * by strong reference counting.
+        */
+       union {
+               struct kref ref; /* no kref_get_unless_zero()! */
+               struct rcu_head rcu;
+       };
 
        struct intel_engine_cs *engine;
        struct intel_engine_cs *inflight;
@@ -54,8 +64,15 @@ struct intel_context {
        struct i915_address_space *vm;
        struct i915_gem_context __rcu *gem_context;
 
-       struct list_head signal_link;
-       struct list_head signals;
+       /*
+        * @signal_lock protects the list of requests that need signaling,
+        * @signals. While there are any requests that need signaling,
+        * we add the context to the breadcrumbs worker, and remove it
+        * upon completion/cancellation of the last request.
+        */
+       struct list_head signal_link; /* Accessed under RCU */
+       struct list_head signals; /* Guarded by signal_lock */
+       spinlock_t signal_lock; /* protects signals, the list of requests */
 
        struct i915_vma *state;
        struct intel_ring *ring;
index 7c3a1012e702046de696e82191ab1bef23bb9009..760fefdfe39216361b74dd1a8faf330b0e045641 100644 (file)
@@ -245,22 +245,14 @@ static inline u32 *gen12_emit_pipe_control(u32 *batch, u32 flags0, u32 flags1, u
 }
 
 static inline u32 *
-__gen8_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset, u32 flags0, u32 flags1)
+__gen8_emit_write_rcs(u32 *cs, u32 value, u32 offset, u32 flags0, u32 flags1)
 {
-       /* We're using qword write, offset should be aligned to 8 bytes. */
-       GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8));
-
-       /* w/a for post sync ops following a GPGPU operation we
-        * need a prior CS_STALL, which is emitted by the flush
-        * following the batch.
-        */
        *cs++ = GFX_OP_PIPE_CONTROL(6) | flags0;
-       *cs++ = flags1 | PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_GLOBAL_GTT_IVB;
-       *cs++ = gtt_offset;
+       *cs++ = flags1 | PIPE_CONTROL_QW_WRITE;
+       *cs++ = offset;
        *cs++ = 0;
        *cs++ = value;
-       /* We're thrashing one dword of HWS. */
-       *cs++ = 0;
+       *cs++ = 0; /* We're thrashing one extra dword. */
 
        return cs;
 }
@@ -268,13 +260,38 @@ __gen8_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset, u32 flags0, u32 f
 static inline u32*
 gen8_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset, u32 flags)
 {
-       return __gen8_emit_ggtt_write_rcs(cs, value, gtt_offset, 0, flags);
+       /* We're using qword write, offset should be aligned to 8 bytes. */
+       GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8));
+
+       return __gen8_emit_write_rcs(cs,
+                                    value,
+                                    gtt_offset,
+                                    0,
+                                    flags | PIPE_CONTROL_GLOBAL_GTT_IVB);
 }
 
 static inline u32*
 gen12_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset, u32 flags0, u32 flags1)
 {
-       return __gen8_emit_ggtt_write_rcs(cs, value, gtt_offset, flags0, flags1);
+       /* We're using qword write, offset should be aligned to 8 bytes. */
+       GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8));
+
+       return __gen8_emit_write_rcs(cs,
+                                    value,
+                                    gtt_offset,
+                                    flags0,
+                                    flags1 | PIPE_CONTROL_GLOBAL_GTT_IVB);
+}
+
+static inline u32 *
+__gen8_emit_flush_dw(u32 *cs, u32 value, u32 gtt_offset, u32 flags)
+{
+       *cs++ = (MI_FLUSH_DW + 1) | flags;
+       *cs++ = gtt_offset;
+       *cs++ = 0;
+       *cs++ = value;
+
+       return cs;
 }
 
 static inline u32 *
@@ -285,12 +302,10 @@ gen8_emit_ggtt_write(u32 *cs, u32 value, u32 gtt_offset, u32 flags)
        /* Offset should be aligned to 8 bytes for both (QW/DW) write types */
        GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8));
 
-       *cs++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW | flags;
-       *cs++ = gtt_offset | MI_FLUSH_DW_USE_GTT;
-       *cs++ = 0;
-       *cs++ = value;
-
-       return cs;
+       return __gen8_emit_flush_dw(cs,
+                                   value,
+                                   gtt_offset | MI_FLUSH_DW_USE_GTT,
+                                   flags | MI_FLUSH_DW_OP_STOREDW);
 }
 
 static inline void __intel_engine_reset(struct intel_engine_cs *engine,
index 5bfb5f7ed02c9aa1e78b0a7a0d06b6a0bc8447ab..efdeb7b7b2a0abf62dccf83699b371d3b5a32ff8 100644 (file)
@@ -371,7 +371,8 @@ static void __setup_engine_capabilities(struct intel_engine_cs *engine)
                 * instances.
                 */
                if ((INTEL_GEN(i915) >= 11 &&
-                    engine->gt->info.vdbox_sfc_access & engine->mask) ||
+                    (engine->gt->info.vdbox_sfc_access &
+                     BIT(engine->instance))) ||
                    (INTEL_GEN(i915) >= 9 && engine->instance == 0))
                        engine->uabi_capabilities |=
                                I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC;
index a32aabce7901dc7ef113ec09814832ba8b466161..0952bf1572346fd1ee73989888680cc06cf898f9 100644 (file)
 struct virtual_engine {
        struct intel_engine_cs base;
        struct intel_context context;
+       struct rcu_work rcu;
 
        /*
         * We allow only a single request through the virtual engine at a time
@@ -3547,6 +3548,19 @@ static const struct intel_context_ops execlists_context_ops = {
        .destroy = execlists_context_destroy,
 };
 
+static u32 hwsp_offset(const struct i915_request *rq)
+{
+       const struct intel_timeline_cacheline *cl;
+
+       /* Before the request is executed, the timeline/cachline is fixed */
+
+       cl = rcu_dereference_protected(rq->hwsp_cacheline, 1);
+       if (cl)
+               return cl->ggtt_offset;
+
+       return rcu_dereference_protected(rq->timeline, 1)->hwsp_offset;
+}
+
 static int gen8_emit_init_breadcrumb(struct i915_request *rq)
 {
        u32 *cs;
@@ -3569,7 +3583,7 @@ static int gen8_emit_init_breadcrumb(struct i915_request *rq)
        *cs++ = MI_NOOP;
 
        *cs++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT;
-       *cs++ = i915_request_timeline(rq)->hwsp_offset;
+       *cs++ = hwsp_offset(rq);
        *cs++ = 0;
        *cs++ = rq->fence.seqno - 1;
 
@@ -4886,11 +4900,9 @@ gen8_emit_fini_breadcrumb_tail(struct i915_request *request, u32 *cs)
        return gen8_emit_wa_tail(request, cs);
 }
 
-static u32 *emit_xcs_breadcrumb(struct i915_request *request, u32 *cs)
+static u32 *emit_xcs_breadcrumb(struct i915_request *rq, u32 *cs)
 {
-       u32 addr = i915_request_active_timeline(request)->hwsp_offset;
-
-       return gen8_emit_ggtt_write(cs, request->fence.seqno, addr, 0);
+       return gen8_emit_ggtt_write(cs, rq->fence.seqno, hwsp_offset(rq), 0);
 }
 
 static u32 *gen8_emit_fini_breadcrumb(struct i915_request *rq, u32 *cs)
@@ -4909,7 +4921,7 @@ static u32 *gen8_emit_fini_breadcrumb_rcs(struct i915_request *request, u32 *cs)
        /* XXX flush+write+CS_STALL all in one upsets gem_concurrent_blt:kbl */
        cs = gen8_emit_ggtt_write_rcs(cs,
                                      request->fence.seqno,
-                                     i915_request_active_timeline(request)->hwsp_offset,
+                                     hwsp_offset(request),
                                      PIPE_CONTROL_FLUSH_ENABLE |
                                      PIPE_CONTROL_CS_STALL);
 
@@ -4921,7 +4933,7 @@ gen11_emit_fini_breadcrumb_rcs(struct i915_request *request, u32 *cs)
 {
        cs = gen8_emit_ggtt_write_rcs(cs,
                                      request->fence.seqno,
-                                     i915_request_active_timeline(request)->hwsp_offset,
+                                     hwsp_offset(request),
                                      PIPE_CONTROL_CS_STALL |
                                      PIPE_CONTROL_TILE_CACHE_FLUSH |
                                      PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
@@ -4983,7 +4995,9 @@ gen12_emit_fini_breadcrumb_tail(struct i915_request *request, u32 *cs)
 
 static u32 *gen12_emit_fini_breadcrumb(struct i915_request *rq, u32 *cs)
 {
-       return gen12_emit_fini_breadcrumb_tail(rq, emit_xcs_breadcrumb(rq, cs));
+       /* XXX Stalling flush before seqno write; post-sync not */
+       cs = emit_xcs_breadcrumb(rq, __gen8_emit_flush_dw(cs, 0, 0, 0));
+       return gen12_emit_fini_breadcrumb_tail(rq, cs);
 }
 
 static u32 *
@@ -4991,7 +5005,7 @@ gen12_emit_fini_breadcrumb_rcs(struct i915_request *request, u32 *cs)
 {
        cs = gen12_emit_ggtt_write_rcs(cs,
                                       request->fence.seqno,
-                                      i915_request_active_timeline(request)->hwsp_offset,
+                                      hwsp_offset(request),
                                       PIPE_CONTROL0_HDC_PIPELINE_FLUSH,
                                       PIPE_CONTROL_CS_STALL |
                                       PIPE_CONTROL_TILE_CACHE_FLUSH |
@@ -5412,44 +5426,90 @@ static struct list_head *virtual_queue(struct virtual_engine *ve)
        return &ve->base.execlists.default_priolist.requests[0];
 }
 
-static void virtual_context_destroy(struct kref *kref)
+static void rcu_virtual_context_destroy(struct work_struct *wrk)
 {
        struct virtual_engine *ve =
-               container_of(kref, typeof(*ve), context.ref);
+               container_of(wrk, typeof(*ve), rcu.work);
        unsigned int n;
 
-       GEM_BUG_ON(!list_empty(virtual_queue(ve)));
-       GEM_BUG_ON(ve->request);
        GEM_BUG_ON(ve->context.inflight);
 
+       /* Preempt-to-busy may leave a stale request behind. */
+       if (unlikely(ve->request)) {
+               struct i915_request *old;
+
+               spin_lock_irq(&ve->base.active.lock);
+
+               old = fetch_and_zero(&ve->request);
+               if (old) {
+                       GEM_BUG_ON(!i915_request_completed(old));
+                       __i915_request_submit(old);
+                       i915_request_put(old);
+               }
+
+               spin_unlock_irq(&ve->base.active.lock);
+       }
+
+       /*
+        * Flush the tasklet in case it is still running on another core.
+        *
+        * This needs to be done before we remove ourselves from the siblings'
+        * rbtrees as in the case it is running in parallel, it may reinsert
+        * the rb_node into a sibling.
+        */
+       tasklet_kill(&ve->base.execlists.tasklet);
+
+       /* Decouple ourselves from the siblings, no more access allowed. */
        for (n = 0; n < ve->num_siblings; n++) {
                struct intel_engine_cs *sibling = ve->siblings[n];
                struct rb_node *node = &ve->nodes[sibling->id].rb;
-               unsigned long flags;
 
                if (RB_EMPTY_NODE(node))
                        continue;
 
-               spin_lock_irqsave(&sibling->active.lock, flags);
+               spin_lock_irq(&sibling->active.lock);
 
                /* Detachment is lazily performed in the execlists tasklet */
                if (!RB_EMPTY_NODE(node))
                        rb_erase_cached(node, &sibling->execlists.virtual);
 
-               spin_unlock_irqrestore(&sibling->active.lock, flags);
+               spin_unlock_irq(&sibling->active.lock);
        }
        GEM_BUG_ON(__tasklet_is_scheduled(&ve->base.execlists.tasklet));
+       GEM_BUG_ON(!list_empty(virtual_queue(ve)));
 
        if (ve->context.state)
                __execlists_context_fini(&ve->context);
        intel_context_fini(&ve->context);
 
+       intel_breadcrumbs_free(ve->base.breadcrumbs);
        intel_engine_free_request_pool(&ve->base);
 
        kfree(ve->bonds);
        kfree(ve);
 }
 
+static void virtual_context_destroy(struct kref *kref)
+{
+       struct virtual_engine *ve =
+               container_of(kref, typeof(*ve), context.ref);
+
+       GEM_BUG_ON(!list_empty(&ve->context.signals));
+
+       /*
+        * When destroying the virtual engine, we have to be aware that
+        * it may still be in use from an hardirq/softirq context causing
+        * the resubmission of a completed request (background completion
+        * due to preempt-to-busy). Before we can free the engine, we need
+        * to flush the submission code and tasklets that are still potentially
+        * accessing the engine. Flushing the tasklets requires process context,
+        * and since we can guard the resubmit onto the engine with an RCU read
+        * lock, we can delegate the free of the engine to an RCU worker.
+        */
+       INIT_RCU_WORK(&ve->rcu, rcu_virtual_context_destroy);
+       queue_rcu_work(system_wq, &ve->rcu);
+}
+
 static void virtual_engine_initial_hint(struct virtual_engine *ve)
 {
        int swp;
index b8f56e62158e2e249aecd39f9e7d80d4c7555d69..4f74706967fdc0f59a772e30d5fe6dc1da44e52e 100644 (file)
@@ -131,7 +131,19 @@ static const struct drm_i915_mocs_entry skl_mocs_table[] = {
        GEN9_MOCS_ENTRIES,
        MOCS_ENTRY(I915_MOCS_CACHED,
                   LE_3_WB | LE_TC_2_LLC_ELLC | LE_LRUM(3),
-                  L3_3_WB)
+                  L3_3_WB),
+
+       /*
+        * mocs:63
+        * - used by the L3 for all of its evictions.
+        *   Thus it is expected to allow LLC cacheability to enable coherent
+        *   flows to be maintained.
+        * - used to force L3 uncachable cycles.
+        *   Thus it is expected to make the surface L3 uncacheable.
+        */
+       MOCS_ENTRY(63,
+                  LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
+                  L3_1_UC)
 };
 
 /* NOTE: the LE_TGT_CACHE is not used on Broxton */
@@ -243,8 +255,9 @@ static const struct drm_i915_mocs_entry tgl_mocs_table[] = {
         * only, __init_mocs_table() take care to program unused index with
         * this entry.
         */
-       MOCS_ENTRY(1, LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
-                  L3_3_WB),
+       MOCS_ENTRY(I915_MOCS_PTE,
+                  LE_0_PAGETABLE | LE_TC_0_PAGETABLE,
+                  L3_1_UC),
        GEN11_MOCS_ENTRIES,
 
        /* Implicitly enable L1 - HDC:L1 + L3 + LLC */
index ab675d35030d7fb5c47c4fec5a3de09cddd21e2e..d7b8e4457fc28e6e54b35fc38a92b19922d645f1 100644 (file)
@@ -56,9 +56,12 @@ static inline void set(struct intel_uncore *uncore, i915_reg_t reg, u32 val)
 
 static void gen11_rc6_enable(struct intel_rc6 *rc6)
 {
-       struct intel_uncore *uncore = rc6_to_uncore(rc6);
+       struct intel_gt *gt = rc6_to_gt(rc6);
+       struct intel_uncore *uncore = gt->uncore;
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
+       u32 pg_enable;
+       int i;
 
        /* 2b: Program RC6 thresholds.*/
        set(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16 | 85);
@@ -102,10 +105,19 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6)
                GEN6_RC_CTL_RC6_ENABLE |
                GEN6_RC_CTL_EI_MODE(1);
 
-       set(uncore, GEN9_PG_ENABLE,
-           GEN9_RENDER_PG_ENABLE |
-           GEN9_MEDIA_PG_ENABLE |
-           GEN11_MEDIA_SAMPLER_PG_ENABLE);
+       pg_enable =
+               GEN9_RENDER_PG_ENABLE |
+               GEN9_MEDIA_PG_ENABLE |
+               GEN11_MEDIA_SAMPLER_PG_ENABLE;
+
+       if (INTEL_GEN(gt->i915) >= 12) {
+               for (i = 0; i < I915_MAX_VCS; i++)
+                       if (HAS_ENGINE(gt, _VCS(i)))
+                               pg_enable |= (VDN_HCP_POWERGATE_ENABLE(i) |
+                                             VDN_MFX_POWERGATE_ENABLE(i));
+       }
+
+       set(uncore, GEN9_PG_ENABLE, pg_enable);
 }
 
 static void gen9_rc6_enable(struct intel_rc6 *rc6)
index e6a00eea063169e0c396f793ed5e585052d0237f..c1c9cc0ad3b95db06090cafa566c93d22e07a68a 100644 (file)
@@ -883,6 +883,10 @@ void intel_rps_park(struct intel_rps *rps)
                adj = -2;
        rps->last_adj = adj;
        rps->cur_freq = max_t(int, rps->cur_freq + adj, rps->min_freq);
+       if (rps->cur_freq < rps->efficient_freq) {
+               rps->cur_freq = rps->efficient_freq;
+               rps->last_adj = 0;
+       }
 
        GT_TRACE(rps_to_gt(rps), "park:%x\n", rps->cur_freq);
 }
index a2f74cefe4c3fa59ed74ddb1bf284aabe0b7fedf..7ea94d201fe6fbd9c5e8d1e160621bfd2ceaf273 100644 (file)
@@ -188,10 +188,14 @@ cacheline_alloc(struct intel_timeline_hwsp *hwsp, unsigned int cacheline)
        return cl;
 }
 
-static void cacheline_acquire(struct intel_timeline_cacheline *cl)
+static void cacheline_acquire(struct intel_timeline_cacheline *cl,
+                             u32 ggtt_offset)
 {
-       if (cl)
-               i915_active_acquire(&cl->active);
+       if (!cl)
+               return;
+
+       cl->ggtt_offset = ggtt_offset;
+       i915_active_acquire(&cl->active);
 }
 
 static void cacheline_release(struct intel_timeline_cacheline *cl)
@@ -340,7 +344,7 @@ int intel_timeline_pin(struct intel_timeline *tl, struct i915_gem_ww_ctx *ww)
        GT_TRACE(tl->gt, "timeline:%llx using HWSP offset:%x\n",
                 tl->fence_context, tl->hwsp_offset);
 
-       cacheline_acquire(tl->hwsp_cacheline);
+       cacheline_acquire(tl->hwsp_cacheline, tl->hwsp_offset);
        if (atomic_fetch_inc(&tl->pin_count)) {
                cacheline_release(tl->hwsp_cacheline);
                __i915_vma_unpin(tl->hwsp_ggtt);
@@ -515,7 +519,7 @@ __intel_timeline_get_seqno(struct intel_timeline *tl,
        GT_TRACE(tl->gt, "timeline:%llx using HWSP offset:%x\n",
                 tl->fence_context, tl->hwsp_offset);
 
-       cacheline_acquire(cl);
+       cacheline_acquire(cl, tl->hwsp_offset);
        tl->hwsp_cacheline = cl;
 
        *seqno = timeline_advance(tl);
@@ -573,9 +577,7 @@ int intel_timeline_read_hwsp(struct i915_request *from,
        if (err)
                goto out;
 
-       *hwsp = i915_ggtt_offset(cl->hwsp->vma) +
-               ptr_unmask_bits(cl->vaddr, CACHELINE_BITS) * CACHELINE_BYTES;
-
+       *hwsp = cl->ggtt_offset;
 out:
        i915_active_release(&cl->active);
        return err;
index 02181c5020db0739f4ce11d854be126a655c3efc..4474f487f58991ad0bf133a7ee6e8bf54bb8ea79 100644 (file)
@@ -94,6 +94,8 @@ struct intel_timeline_cacheline {
        struct intel_timeline_hwsp *hwsp;
        void *vaddr;
 
+       u32 ggtt_offset;
+
        struct rcu_head rcu;
 };
 
index 6c580d0d9ea8fe51b3be101d74956cca59d2f950..4a3bde7c9f21712c8f6622bb877f63971b68fde7 100644 (file)
@@ -131,8 +131,10 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa)
                        return;
                }
 
-               if (wal->list)
+               if (wal->list) {
                        memcpy(list, wal->list, sizeof(*wa) * wal->count);
+                       kfree(wal->list);
+               }
 
                wal->list = list;
        }
index f011ea42487e11001b9840665be545276f496794..463af675faddb078648d1f94c18161c12fe1be16 100644 (file)
@@ -103,10 +103,13 @@ static int __shmem_rw(struct file *file, loff_t off,
                        return PTR_ERR(page);
 
                vaddr = kmap(page);
-               if (write)
+               if (write) {
                        memcpy(vaddr + offset_in_page(off), ptr, this);
-               else
+                       set_page_dirty(page);
+               } else {
                        memcpy(ptr, vaddr + offset_in_page(off), this);
+               }
+               mark_page_accessed(page);
                kunmap(page);
                put_page(page);
 
index 7ba16ddfe75f3b745bd646469149ceeed3849945..d7898e87791feeb1eacf1c1a05bc6eaa7a04e0ad 100644 (file)
@@ -164,7 +164,7 @@ static unsigned char virtual_dp_monitor_edid[GVT_EDID_NUM][EDID_SIZE] = {
 
 /* let the virtual display supports DP1.2 */
 static u8 dpcd_fix_data[DPCD_HEADER_SIZE] = {
-       0x12, 0x014, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+       0x12, 0x014, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
 static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
index 9831361f181eb85d05d430592135230943e84fbf..a81cf0f01e78eec1f510b434b49875f8720f4b49 100644 (file)
@@ -255,7 +255,7 @@ struct intel_gvt_mmio {
 #define F_CMD_ACCESS   (1 << 3)
 /* This reg has been accessed by a VM */
 #define F_ACCESSED     (1 << 4)
-/* This reg has been accessed through GPU commands */
+/* This reg could be accessed by unaligned address */
 #define F_UNALIGN      (1 << 6)
 /* This reg is in GVT's mmio save-restor list and in hardware
  * logical context image
index 3be37e6fe33da016b66123b6077996621899e262..eb342a7599438c641168768ac6c20a92d7d449ee 100644 (file)
@@ -1489,7 +1489,8 @@ static int hws_pga_write(struct intel_vgpu *vgpu, unsigned int offset,
        const struct intel_engine_cs *engine =
                intel_gvt_render_mmio_to_engine(vgpu->gvt, offset);
 
-       if (!intel_gvt_ggtt_validate_range(vgpu, value, I915_GTT_PAGE_SIZE)) {
+       if (value != 0 &&
+           !intel_gvt_ggtt_validate_range(vgpu, value, I915_GTT_PAGE_SIZE)) {
                gvt_vgpu_err("write invalid HWSP address, reg:0x%x, value:0x%x\n",
                              offset, value);
                return -EINVAL;
@@ -1650,6 +1651,34 @@ static int edp_psr_imr_iir_write(struct intel_vgpu *vgpu,
        return 0;
 }
 
+/**
+ * FixMe:
+ * If guest fills non-priv batch buffer on ApolloLake/Broxton as Mesa i965 did:
+ * 717e7539124d (i965: Use a WC map and memcpy for the batch instead of pwrite.)
+ * Due to the missing flush of bb filled by VM vCPU, host GPU hangs on executing
+ * these MI_BATCH_BUFFER.
+ * Temporarily workaround this by setting SNOOP bit for PAT3 used by PPGTT
+ * PML4 PTE: PAT(0) PCD(1) PWT(1).
+ * The performance is still expected to be low, will need further improvement.
+ */
+static int bxt_ppat_low_write(struct intel_vgpu *vgpu, unsigned int offset,
+                             void *p_data, unsigned int bytes)
+{
+       u64 pat =
+               GEN8_PPAT(0, CHV_PPAT_SNOOP) |
+               GEN8_PPAT(1, 0) |
+               GEN8_PPAT(2, 0) |
+               GEN8_PPAT(3, CHV_PPAT_SNOOP) |
+               GEN8_PPAT(4, CHV_PPAT_SNOOP) |
+               GEN8_PPAT(5, CHV_PPAT_SNOOP) |
+               GEN8_PPAT(6, CHV_PPAT_SNOOP) |
+               GEN8_PPAT(7, CHV_PPAT_SNOOP);
+
+       vgpu_vreg(vgpu, offset) = lower_32_bits(pat);
+
+       return 0;
+}
+
 static int guc_status_read(struct intel_vgpu *vgpu,
                           unsigned int offset, void *p_data,
                           unsigned int bytes)
@@ -2812,7 +2841,7 @@ static int init_bdw_mmio_info(struct intel_gvt *gvt)
 
        MMIO_DH(GEN6_PCODE_MAILBOX, D_BDW_PLUS, NULL, mailbox_write);
 
-       MMIO_D(GEN8_PRIVATE_PAT_LO, D_BDW_PLUS);
+       MMIO_D(GEN8_PRIVATE_PAT_LO, D_BDW_PLUS & ~D_BXT);
        MMIO_D(GEN8_PRIVATE_PAT_HI, D_BDW_PLUS);
 
        MMIO_D(GAMTARBMODE, D_BDW_PLUS);
@@ -3139,7 +3168,7 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
                 NULL, NULL);
 
        MMIO_DFH(GAMT_CHKN_BIT_REG, D_KBL | D_CFL, F_CMD_ACCESS, NULL, NULL);
-       MMIO_D(GEN9_CTX_PREEMPT_REG, D_SKL_PLUS);
+       MMIO_D(GEN9_CTX_PREEMPT_REG, D_SKL_PLUS & ~D_BXT);
 
        return 0;
 }
@@ -3313,9 +3342,21 @@ static int init_bxt_mmio_info(struct intel_gvt *gvt)
        MMIO_D(GEN8_PUSHBUS_SHIFT, D_BXT);
        MMIO_D(GEN6_GFXPAUSE, D_BXT);
        MMIO_DFH(GEN8_L3SQCREG1, D_BXT, F_CMD_ACCESS, NULL, NULL);
+       MMIO_DFH(GEN8_L3CNTLREG, D_BXT, F_CMD_ACCESS, NULL, NULL);
+       MMIO_DFH(_MMIO(0x20D8), D_BXT, F_CMD_ACCESS, NULL, NULL);
+       MMIO_F(GEN8_RING_CS_GPR(RENDER_RING_BASE, 0), 0x40, F_CMD_ACCESS,
+              0, 0, D_BXT, NULL, NULL);
+       MMIO_F(GEN8_RING_CS_GPR(GEN6_BSD_RING_BASE, 0), 0x40, F_CMD_ACCESS,
+              0, 0, D_BXT, NULL, NULL);
+       MMIO_F(GEN8_RING_CS_GPR(BLT_RING_BASE, 0), 0x40, F_CMD_ACCESS,
+              0, 0, D_BXT, NULL, NULL);
+       MMIO_F(GEN8_RING_CS_GPR(VEBOX_RING_BASE, 0), 0x40, F_CMD_ACCESS,
+              0, 0, D_BXT, NULL, NULL);
 
        MMIO_DFH(GEN9_CTX_PREEMPT_REG, D_BXT, F_CMD_ACCESS, NULL, NULL);
 
+       MMIO_DH(GEN8_PRIVATE_PAT_LO, D_BXT, NULL, bxt_ppat_low_write);
+
        return 0;
 }
 
index ad8a9df49f295f1dd7e94fc50303fa1e2e83e8c3..778eb8cab61097eca795f2b4ce5e613dda61ae90 100644 (file)
@@ -829,8 +829,10 @@ static int intel_vgpu_open(struct mdev_device *mdev)
        /* Take a module reference as mdev core doesn't take
         * a reference for vendor driver.
         */
-       if (!try_module_get(THIS_MODULE))
+       if (!try_module_get(THIS_MODULE)) {
+               ret = -ENODEV;
                goto undo_group;
+       }
 
        ret = kvmgt_guest_init(mdev);
        if (ret)
index 1570eb8aa97836130e8f3ca703947359991a9c3e..aed2ef6466a2db765db71bfa52696d698aa134ee 100644 (file)
@@ -1277,7 +1277,7 @@ void intel_vgpu_clean_submission(struct intel_vgpu *vgpu)
 
        i915_context_ppgtt_root_restore(s, i915_vm_to_ppgtt(s->shadow[0]->vm));
        for_each_engine(engine, vgpu->gvt->gt, id)
-               intel_context_unpin(s->shadow[id]);
+               intel_context_put(s->shadow[id]);
 
        kmem_cache_destroy(s->workloads);
 }
@@ -1369,11 +1369,6 @@ int intel_vgpu_setup_submission(struct intel_vgpu *vgpu)
                        ce->ring = __intel_context_ring_size(ring_size);
                }
 
-               ret = intel_context_pin(ce);
-               intel_context_put(ce);
-               if (ret)
-                       goto out_shadow_ctx;
-
                s->shadow[i] = ce;
        }
 
@@ -1405,7 +1400,6 @@ out_shadow_ctx:
                if (IS_ERR(s->shadow[i]))
                        break;
 
-               intel_context_unpin(s->shadow[i]);
                intel_context_put(s->shadow[i]);
        }
        i915_vm_put(&ppgtt->vm);
@@ -1479,6 +1473,7 @@ void intel_vgpu_destroy_workload(struct intel_vgpu_workload *workload)
 {
        struct intel_vgpu_submission *s = &workload->vgpu->submission;
 
+       intel_context_unpin(s->shadow[workload->engine->id]);
        release_shadow_batch_buffer(workload);
        release_shadow_wa_ctx(&workload->wa_ctx);
 
@@ -1724,6 +1719,12 @@ intel_vgpu_create_workload(struct intel_vgpu *vgpu,
                return ERR_PTR(ret);
        }
 
+       ret = intel_context_pin(s->shadow[engine->id]);
+       if (ret) {
+               intel_vgpu_destroy_workload(workload);
+               return ERR_PTR(ret);
+       }
+
        return workload;
 }
 
index f6d7e33c7099e7976bd7388858af2b869657757e..399582aeeefb9c240ebeef328ab58771a13f541f 100644 (file)
@@ -439,7 +439,8 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
 
        if (IS_BROADWELL(dev_priv))
                ret = intel_gvt_hypervisor_set_edid(vgpu, PORT_B);
-       else
+       /* FixMe: Re-enable APL/BXT once vfio_edid enabled */
+       else if (!IS_BROXTON(dev_priv))
                ret = intel_gvt_hypervisor_set_edid(vgpu, PORT_D);
        if (ret)
                goto out_clean_sched_policy;
index bb0c12975f38e577309d099544edbd097a7405f7..58276694c848d2e5e2e83e732dffec6538d4f4a7 100644 (file)
@@ -179,30 +179,6 @@ try_again:
        return ret;
 }
 
-static int
-i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
-                    struct drm_i915_gem_pwrite *args,
-                    struct drm_file *file)
-{
-       void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
-       char __user *user_data = u64_to_user_ptr(args->data_ptr);
-
-       /*
-        * We manually control the domain here and pretend that it
-        * remains coherent i.e. in the GTT domain, like shmem_pwrite.
-        */
-       i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
-
-       if (copy_from_user(vaddr, user_data, args->size))
-               return -EFAULT;
-
-       drm_clflush_virt_range(vaddr, args->size);
-       intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);
-
-       i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
-       return 0;
-}
-
 static int
 i915_gem_create(struct drm_file *file,
                struct intel_memory_region *mr,
@@ -527,6 +503,12 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
 
        trace_i915_gem_object_pread(obj, args->offset, args->size);
 
+       ret = -ENODEV;
+       if (obj->ops->pread)
+               ret = obj->ops->pread(obj, args);
+       if (ret != -ENODEV)
+               goto out;
+
        ret = i915_gem_object_wait(obj,
                                   I915_WAIT_INTERRUPTIBLE,
                                   MAX_SCHEDULE_TIMEOUT);
@@ -866,8 +848,6 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
        if (ret == -EFAULT || ret == -ENOSPC) {
                if (i915_gem_object_has_struct_page(obj))
                        ret = i915_gem_shmem_pwrite(obj, args);
-               else
-                       ret = i915_gem_phys_pwrite(obj, args, file);
        }
 
        i915_gem_object_unpin_pages(obj);
index 366ddfc8df6b65982a69445f83943506e5a86724..fb5e30de78c2a022a0ca817e46910e3491f8111a 100644 (file)
@@ -389,6 +389,7 @@ static const struct intel_device_info ilk_m_info = {
        GEN5_FEATURES,
        PLATFORM(INTEL_IRONLAKE),
        .is_mobile = 1,
+       .has_rps = true,
        .display.has_fbc = 1,
 };
 
index e94976976571fe61181dd87f24cb3227eb7a544a..3640d0e229d22595b6f5d9e44d98f663e401520d 100644 (file)
@@ -909,8 +909,13 @@ static int gen8_oa_read(struct i915_perf_stream *stream,
                                       DRM_I915_PERF_RECORD_OA_REPORT_LOST);
                if (ret)
                        return ret;
-               intel_uncore_write(uncore, oastatus_reg,
-                                  oastatus & ~GEN8_OASTATUS_REPORT_LOST);
+
+               intel_uncore_rmw(uncore, oastatus_reg,
+                                GEN8_OASTATUS_COUNTER_OVERFLOW |
+                                GEN8_OASTATUS_REPORT_LOST,
+                                IS_GEN_RANGE(uncore->i915, 8, 10) ?
+                                (GEN8_OASTATUS_HEAD_POINTER_WRAP |
+                                 GEN8_OASTATUS_TAIL_POINTER_WRAP) : 0);
        }
 
        return gen8_append_oa_reports(stream, buf, count, offset);
index d805d4da6181befa5b292f478fe1200693316cf7..5cd83eac940c321424eeeb87ec1ddb6b0f14489a 100644 (file)
@@ -676,6 +676,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
 #define  GEN7_OASTATUS2_MEM_SELECT_GGTT     (1 << 0) /* 0: PPGTT, 1: GGTT */
 
 #define GEN8_OASTATUS _MMIO(0x2b08)
+#define  GEN8_OASTATUS_TAIL_POINTER_WRAP    (1 << 17)
+#define  GEN8_OASTATUS_HEAD_POINTER_WRAP    (1 << 16)
 #define  GEN8_OASTATUS_OVERRUN_STATUS      (1 << 3)
 #define  GEN8_OASTATUS_COUNTER_OVERFLOW     (1 << 2)
 #define  GEN8_OASTATUS_OABUFFER_OVERFLOW    (1 << 1)
@@ -8971,10 +8973,6 @@ enum {
 #define   GEN9_PWRGT_MEDIA_STATUS_MASK         (1 << 0)
 #define   GEN9_PWRGT_RENDER_STATUS_MASK                (1 << 1)
 
-#define POWERGATE_ENABLE                       _MMIO(0xa210)
-#define    VDN_HCP_POWERGATE_ENABLE(n)         BIT(((n) * 2) + 3)
-#define    VDN_MFX_POWERGATE_ENABLE(n)         BIT(((n) * 2) + 4)
-
 #define  GTFIFODBG                             _MMIO(0x120000)
 #define    GT_FIFO_SBDEDICATE_FREE_ENTRY_CHV   (0x1f << 20)
 #define    GT_FIFO_FREE_ENTRIES_CHV            (0x7f << 13)
@@ -9114,9 +9112,11 @@ enum {
 #define GEN9_MEDIA_PG_IDLE_HYSTERESIS          _MMIO(0xA0C4)
 #define GEN9_RENDER_PG_IDLE_HYSTERESIS         _MMIO(0xA0C8)
 #define GEN9_PG_ENABLE                         _MMIO(0xA210)
-#define GEN9_RENDER_PG_ENABLE                  REG_BIT(0)
-#define GEN9_MEDIA_PG_ENABLE                   REG_BIT(1)
-#define GEN11_MEDIA_SAMPLER_PG_ENABLE          REG_BIT(2)
+#define   GEN9_RENDER_PG_ENABLE                        REG_BIT(0)
+#define   GEN9_MEDIA_PG_ENABLE                 REG_BIT(1)
+#define   GEN11_MEDIA_SAMPLER_PG_ENABLE                REG_BIT(2)
+#define   VDN_HCP_POWERGATE_ENABLE(n)          REG_BIT(3 + 2 * (n))
+#define   VDN_MFX_POWERGATE_ENABLE(n)          REG_BIT(4 + 2 * (n))
 #define GEN8_PUSHBUS_CONTROL                   _MMIO(0xA248)
 #define GEN8_PUSHBUS_ENABLE                    _MMIO(0xA250)
 #define GEN8_PUSHBUS_SHIFT                     _MMIO(0xA25C)
index 16b721080195f0aa1fb2f4e52c0ea8957d077655..620b6fab2c5cfb8cd19dfbf0ae12d9f80ba93b3d 100644 (file)
@@ -176,7 +176,9 @@ struct i915_request {
        struct intel_context *context;
        struct intel_ring *ring;
        struct intel_timeline __rcu *timeline;
+
        struct list_head signal_link;
+       struct llist_node signal_node;
 
        /*
         * The rcu epoch of when this request was allocated. Used to judiciously
index ffb5287e055a93fcfc54ecec8aa63401e12969b7..caa9b041616b0d0903788589ad4a7ae7965339c6 100644 (file)
@@ -314,8 +314,10 @@ static void __vma_release(struct dma_fence_work *work)
 {
        struct i915_vma_work *vw = container_of(work, typeof(*vw), base);
 
-       if (vw->pinned)
+       if (vw->pinned) {
                __i915_gem_object_unpin_pages(vw->pinned);
+               i915_gem_object_put(vw->pinned);
+       }
 
        i915_vm_free_pt_stash(vw->vm, &vw->stash);
        i915_vm_put(vw->vm);
@@ -431,7 +433,7 @@ int i915_vma_bind(struct i915_vma *vma,
 
                if (vma->obj) {
                        __i915_gem_object_pin_pages(vma->obj);
-                       work->pinned = vma->obj;
+                       work->pinned = i915_gem_object_get(vma->obj);
                }
        } else {
                vma->ops->bind_vma(vma->vm, NULL, vma, cache_level, bind_flags);
index 6b5e9d88646de4aa683b8a004517b93954420362..180e1078ef7c1a16421fd118c5e3a54e7e0282eb 100644 (file)
@@ -87,7 +87,7 @@ __intel_memory_region_get_pages_buddy(struct intel_memory_region *mem,
                min_order = ilog2(size) - ilog2(mem->mm.chunk_size);
        }
 
-       if (size > BIT(mem->mm.max_order) * mem->mm.chunk_size)
+       if (size > mem->mm.size)
                return -E2BIG;
 
        n_pages = size >> ilog2(mem->mm.chunk_size);
index 34e0d22d456bd81736045e8fb75415ebac4c7b4e..cfb806767fc524e146a2783606062500b238c8bc 100644 (file)
@@ -7118,23 +7118,10 @@ static void icl_init_clock_gating(struct drm_i915_private *dev_priv)
 
 static void tgl_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-       u32 vd_pg_enable = 0;
-       unsigned int i;
-
        /* Wa_1409120013:tgl */
        I915_WRITE(ILK_DPFC_CHICKEN,
                   ILK_DPFC_CHICKEN_COMP_DUMMY_PIXEL);
 
-       /* This is not a WA. Enable VD HCP & MFX_ENC powergate */
-       for (i = 0; i < I915_MAX_VCS; i++) {
-               if (HAS_ENGINE(&dev_priv->gt, _VCS(i)))
-                       vd_pg_enable |= VDN_HCP_POWERGATE_ENABLE(i) |
-                                       VDN_MFX_POWERGATE_ENABLE(i);
-       }
-
-       I915_WRITE(POWERGATE_ENABLE,
-                  I915_READ(POWERGATE_ENABLE) | vd_pg_enable);
-
        /* Wa_1409825376:tgl (pre-prod)*/
        if (IS_TGL_DISP_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_B1))
                I915_WRITE(GEN9_CLKGATE_DIS_3, I915_READ(GEN9_CLKGATE_DIS_3) |
index 64bbb82882494a28c7914e8f102af0252c8b2d6a..e424a6d1a68c9433c0ba7f646e95f8255780a307 100644 (file)
@@ -2293,8 +2293,10 @@ static int perf_request_latency(void *arg)
                struct intel_context *ce;
 
                ce = intel_context_create(engine);
-               if (IS_ERR(ce))
+               if (IS_ERR(ce)) {
+                       err = PTR_ERR(ce);
                        goto out;
+               }
 
                err = intel_context_pin(ce);
                if (err) {
@@ -2467,8 +2469,10 @@ static int perf_series_engines(void *arg)
                struct intel_context *ce;
 
                ce = intel_context_create(engine);
-               if (IS_ERR(ce))
+               if (IS_ERR(ce)) {
+                       err = PTR_ERR(ce);
                        goto out;
+               }
 
                err = intel_context_pin(ce);
                if (err) {
index 334b0648e253e96039c2b2941466a7d63d0fde84..0aeba8e3af28daecde5424c9458683f8faf5d4db 100644 (file)
@@ -261,6 +261,82 @@ err_close_objects:
        return err;
 }
 
+static int igt_mock_splintered_region(void *arg)
+{
+       struct intel_memory_region *mem = arg;
+       struct drm_i915_private *i915 = mem->i915;
+       struct drm_i915_gem_object *obj;
+       unsigned int expected_order;
+       LIST_HEAD(objects);
+       u64 size;
+       int err = 0;
+
+       /*
+        * Sanity check we can still allocate everything even if the
+        * mm.max_order != mm.size. i.e our starting address space size is not a
+        * power-of-two.
+        */
+
+       size = (SZ_4G - 1) & PAGE_MASK;
+       mem = mock_region_create(i915, 0, size, PAGE_SIZE, 0);
+       if (IS_ERR(mem))
+               return PTR_ERR(mem);
+
+       if (mem->mm.size != size) {
+               pr_err("%s size mismatch(%llu != %llu)\n",
+                      __func__, mem->mm.size, size);
+               err = -EINVAL;
+               goto out_put;
+       }
+
+       expected_order = get_order(rounddown_pow_of_two(size));
+       if (mem->mm.max_order != expected_order) {
+               pr_err("%s order mismatch(%u != %u)\n",
+                      __func__, mem->mm.max_order, expected_order);
+               err = -EINVAL;
+               goto out_put;
+       }
+
+       obj = igt_object_create(mem, &objects, size, 0);
+       if (IS_ERR(obj)) {
+               err = PTR_ERR(obj);
+               goto out_close;
+       }
+
+       close_objects(mem, &objects);
+
+       /*
+        * While we should be able allocate everything without any flag
+        * restrictions, if we consider I915_BO_ALLOC_CONTIGUOUS then we are
+        * actually limited to the largest power-of-two for the region size i.e
+        * max_order, due to the inner workings of the buddy allocator. So make
+        * sure that does indeed hold true.
+        */
+
+       obj = igt_object_create(mem, &objects, size, I915_BO_ALLOC_CONTIGUOUS);
+       if (!IS_ERR(obj)) {
+               pr_err("%s too large contiguous allocation was not rejected\n",
+                      __func__);
+               err = -EINVAL;
+               goto out_close;
+       }
+
+       obj = igt_object_create(mem, &objects, rounddown_pow_of_two(size),
+                               I915_BO_ALLOC_CONTIGUOUS);
+       if (IS_ERR(obj)) {
+               pr_err("%s largest possible contiguous allocation failed\n",
+                      __func__);
+               err = PTR_ERR(obj);
+               goto out_close;
+       }
+
+out_close:
+       close_objects(mem, &objects);
+out_put:
+       intel_memory_region_put(mem);
+       return err;
+}
+
 static int igt_gpu_write_dw(struct intel_context *ce,
                            struct i915_vma *vma,
                            u32 dword,
@@ -771,6 +847,7 @@ int intel_memory_region_mock_selftests(void)
        static const struct i915_subtest tests[] = {
                SUBTEST(igt_mock_fill),
                SUBTEST(igt_mock_contiguous),
+               SUBTEST(igt_mock_splintered_region),
        };
        struct intel_memory_region *mem;
        struct drm_i915_private *i915;
index 09660f5a0a4c9f6f4c0172662a209137ee473c03..979d96f27c43a7c81f965b1f505caad062c44c50 100644 (file)
@@ -24,7 +24,7 @@ mock_object_create(struct intel_memory_region *mem,
        struct drm_i915_private *i915 = mem->i915;
        struct drm_i915_gem_object *obj;
 
-       if (size > BIT(mem->mm.max_order) * mem->mm.chunk_size)
+       if (size > mem->mm.size)
                return ERR_PTR(-E2BIG);
 
        obj = i915_gem_object_alloc();
index 71d84c7a5378a4bfaeb77598910749f8756d37a4..d07b39b8afd21a0a7c43b45760d750bd1e4ae997 100644 (file)
@@ -111,10 +111,6 @@ static int dw_hdmi_imx_parse_dt(struct imx_hdmi *hdmi)
        return 0;
 }
 
-static void dw_hdmi_imx_encoder_disable(struct drm_encoder *encoder)
-{
-}
-
 static void dw_hdmi_imx_encoder_enable(struct drm_encoder *encoder)
 {
        struct imx_hdmi *hdmi = enc_to_imx_hdmi(encoder);
@@ -140,7 +136,6 @@ static int dw_hdmi_imx_atomic_check(struct drm_encoder *encoder,
 
 static const struct drm_encoder_helper_funcs dw_hdmi_imx_encoder_helper_funcs = {
        .enable     = dw_hdmi_imx_encoder_enable,
-       .disable    = dw_hdmi_imx_encoder_disable,
        .atomic_check = dw_hdmi_imx_atomic_check,
 };
 
@@ -219,15 +214,9 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
        hdmi->dev = &pdev->dev;
        encoder = &hdmi->encoder;
 
-       encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
-       /*
-        * If we failed to find the CRTC(s) which this encoder is
-        * supposed to be connected to, it's because the CRTC has
-        * not been registered yet.  Defer probing, and hope that
-        * the required CRTC is added later.
-        */
-       if (encoder->possible_crtcs == 0)
-               return -EPROBE_DEFER;
+       ret = imx_drm_encoder_parse_of(drm, encoder, dev->of_node);
+       if (ret)
+               return ret;
 
        ret = dw_hdmi_imx_parse_dt(hdmi);
        if (ret < 0)
index 7d00c49fd5a5409f1ca70c7c34fef0ed46a1be45..9bf5ad6d18a22822d2f2fe2dcdba41a836f3e72f 100644 (file)
@@ -20,6 +20,7 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_managed.h>
 #include <drm/drm_of.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
@@ -212,7 +213,9 @@ static int imx_drm_bind(struct device *dev)
        drm->mode_config.allow_fb_modifiers = true;
        drm->mode_config.normalize_zpos = true;
 
-       drm_mode_config_init(drm);
+       ret = drmm_mode_config_init(drm);
+       if (ret)
+               return ret;
 
        ret = drm_vblank_init(drm, MAX_CRTC);
        if (ret)
@@ -251,7 +254,6 @@ err_poll_fini:
        drm_kms_helper_poll_fini(drm);
        component_unbind_all(drm->dev, drm);
 err_kms:
-       drm_mode_config_cleanup(drm);
        drm_dev_put(drm);
 
        return ret;
@@ -267,11 +269,9 @@ static void imx_drm_unbind(struct device *dev)
 
        component_unbind_all(drm->dev, drm);
 
-       drm_mode_config_cleanup(drm);
+       drm_dev_put(drm);
 
        dev_set_drvdata(dev, NULL);
-
-       drm_dev_put(drm);
 }
 
 static const struct component_master_ops imx_drm_ops = {
index af757d1e21fedfc3e7d0e0a95a9560ce768d6266..41e2978cb1ebf278fa93ac803d6ea74d06ad5ecd 100644 (file)
@@ -62,7 +62,6 @@ struct imx_ldb_channel {
        struct i2c_adapter *ddc;
        int chno;
        void *edid;
-       int edid_len;
        struct drm_display_mode mode;
        int mode_valid;
        u32 bus_format;
@@ -536,15 +535,14 @@ static int imx_ldb_panel_ddc(struct device *dev,
        }
 
        if (!channel->ddc) {
+               int edid_len;
+
                /* if no DDC available, fallback to hardcoded EDID */
                dev_dbg(dev, "no ddc available\n");
 
-               edidp = of_get_property(child, "edid",
-                                       &channel->edid_len);
+               edidp = of_get_property(child, "edid", &edid_len);
                if (edidp) {
-                       channel->edid = kmemdup(edidp,
-                                               channel->edid_len,
-                                               GFP_KERNEL);
+                       channel->edid = kmemdup(edidp, edid_len, GFP_KERNEL);
                } else if (!channel->panel) {
                        /* fallback to display-timings node */
                        ret = of_get_drm_display_mode(child,
index 813bb6156a680e5384ccd3cb8398b92a072d0595..2a8d2e32e7b42678850cf9758019653cc4957882 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
-#include <linux/spinlock.h>
 #include <linux/videodev2.h>
 
 #include <video/imx-ipu-v3.h>
@@ -104,8 +103,6 @@ struct imx_tve {
        struct drm_connector connector;
        struct drm_encoder encoder;
        struct device *dev;
-       spinlock_t lock;        /* register lock */
-       bool enabled;
        int mode;
        int di_hsync_pin;
        int di_vsync_pin;
@@ -129,30 +126,10 @@ static inline struct imx_tve *enc_to_tve(struct drm_encoder *e)
        return container_of(e, struct imx_tve, encoder);
 }
 
-static void tve_lock(void *__tve)
-__acquires(&tve->lock)
-{
-       struct imx_tve *tve = __tve;
-
-       spin_lock(&tve->lock);
-}
-
-static void tve_unlock(void *__tve)
-__releases(&tve->lock)
-{
-       struct imx_tve *tve = __tve;
-
-       spin_unlock(&tve->lock);
-}
-
 static void tve_enable(struct imx_tve *tve)
 {
-       if (!tve->enabled) {
-               tve->enabled = true;
-               clk_prepare_enable(tve->clk);
-               regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,
-                                  TVE_EN, TVE_EN);
-       }
+       clk_prepare_enable(tve->clk);
+       regmap_update_bits(tve->regmap, TVE_COM_CONF_REG, TVE_EN, TVE_EN);
 
        /* clear interrupt status register */
        regmap_write(tve->regmap, TVE_STAT_REG, 0xffffffff);
@@ -169,11 +146,8 @@ static void tve_enable(struct imx_tve *tve)
 
 static void tve_disable(struct imx_tve *tve)
 {
-       if (tve->enabled) {
-               tve->enabled = false;
-               regmap_update_bits(tve->regmap, TVE_COM_CONF_REG, TVE_EN, 0);
-               clk_disable_unprepare(tve->clk);
-       }
+       regmap_update_bits(tve->regmap, TVE_COM_CONF_REG, TVE_EN, 0);
+       clk_disable_unprepare(tve->clk);
 }
 
 static int tve_setup_tvout(struct imx_tve *tve)
@@ -500,8 +474,7 @@ static struct regmap_config tve_regmap_config = {
 
        .readable_reg = imx_tve_readable_reg,
 
-       .lock = tve_lock,
-       .unlock = tve_unlock,
+       .fast_io = true,
 
        .max_register = 0xdc,
 };
@@ -511,7 +484,7 @@ static const char * const imx_tve_modes[] = {
        [TVE_MODE_VGA] = "vga",
 };
 
-static const int of_get_tve_mode(struct device_node *np)
+static int of_get_tve_mode(struct device_node *np)
 {
        const char *bm;
        int ret, i;
@@ -544,7 +517,6 @@ static int imx_tve_bind(struct device *dev, struct device *master, void *data)
        memset(tve, 0, sizeof(*tve));
 
        tve->dev = dev;
-       spin_lock_init(&tve->lock);
 
        ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
        if (ddc_node) {
index 8232f512b9ed8ec84af4760817a1d4d399b0922c..2eb8df4697dfac6c0bd1e6a2098a62a296e0498c 100644 (file)
@@ -28,7 +28,6 @@ struct imx_parallel_display {
        struct drm_bridge bridge;
        struct device *dev;
        void *edid;
-       int edid_len;
        u32 bus_format;
        u32 bus_flags;
        struct drm_display_mode mode;
@@ -41,11 +40,6 @@ static inline struct imx_parallel_display *con_to_imxpd(struct drm_connector *c)
        return container_of(c, struct imx_parallel_display, connector);
 }
 
-static inline struct imx_parallel_display *enc_to_imxpd(struct drm_encoder *e)
-{
-       return container_of(e, struct imx_parallel_display, encoder);
-}
-
 static inline struct imx_parallel_display *bridge_to_imxpd(struct drm_bridge *b)
 {
        return container_of(b, struct imx_parallel_display, bridge);
@@ -310,6 +304,7 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
        struct device_node *np = dev->of_node;
        const u8 *edidp;
        struct imx_parallel_display *imxpd;
+       int edid_len;
        int ret;
        u32 bus_format = 0;
        const char *fmt;
@@ -323,9 +318,9 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
        if (ret && ret != -ENODEV)
                return ret;
 
-       edidp = of_get_property(np, "edid", &imxpd->edid_len);
+       edidp = of_get_property(np, "edid", &edid_len);
        if (edidp)
-               imxpd->edid = kmemdup(edidp, imxpd->edid_len, GFP_KERNEL);
+               imxpd->edid = devm_kmemdup(dev, edidp, edid_len, GFP_KERNEL);
 
        ret = of_property_read_string(np, "interface-pix-fmt", &fmt);
        if (!ret) {
@@ -349,17 +344,8 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
        return 0;
 }
 
-static void imx_pd_unbind(struct device *dev, struct device *master,
-       void *data)
-{
-       struct imx_parallel_display *imxpd = dev_get_drvdata(dev);
-
-       kfree(imxpd->edid);
-}
-
 static const struct component_ops imx_pd_ops = {
        .bind   = imx_pd_bind,
-       .unbind = imx_pd_unbind,
 };
 
 static int imx_pd_probe(struct platform_device *pdev)
index c592957ed07fc7c247db06929dd8768f11a8fa06..92f8bd907193f56c1c8916fe558414e8eb67393d 100644 (file)
@@ -413,7 +413,13 @@ static int mcde_probe(struct platform_device *pdev)
                                              match);
        if (ret) {
                dev_err(dev, "failed to add component master\n");
-               goto clk_disable;
+               /*
+                * The EPOD regulator is already disabled at this point so some
+                * special errorpath code is needed
+                */
+               clk_disable_unprepare(mcde->mcde_clk);
+               regulator_disable(mcde->vana);
+               return ret;
        }
 
        return 0;
index cf11c4850b40567f86c236c0c8d2cc1153d512ed..52f11a63a3304a616352b7d56d8b1fd1f6602c24 100644 (file)
@@ -522,15 +522,6 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
        return 0;
 }
 
-static void mtk_dpi_encoder_destroy(struct drm_encoder *encoder)
-{
-       drm_encoder_cleanup(encoder);
-}
-
-static const struct drm_encoder_funcs mtk_dpi_encoder_funcs = {
-       .destroy = mtk_dpi_encoder_destroy,
-};
-
 static int mtk_dpi_bridge_attach(struct drm_bridge *bridge,
                                 enum drm_bridge_attach_flags flags)
 {
index 4a188a942c38ec841653eebe37d60a5a927fadc4..65fd99c528af2446119bb1109f9636627619003d 100644 (file)
@@ -444,7 +444,10 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
        u32 horizontal_sync_active_byte;
        u32 horizontal_backporch_byte;
        u32 horizontal_frontporch_byte;
+       u32 horizontal_front_back_byte;
+       u32 data_phy_cycles_byte;
        u32 dsi_tmp_buf_bpp, data_phy_cycles;
+       u32 delta;
        struct mtk_phy_timing *timing = &dsi->phy_timing;
 
        struct videomode *vm = &dsi->vm;
@@ -466,50 +469,30 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
        horizontal_sync_active_byte = (vm->hsync_len * dsi_tmp_buf_bpp - 10);
 
        if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
-               horizontal_backporch_byte = vm->hback_porch * dsi_tmp_buf_bpp;
+               horizontal_backporch_byte = vm->hback_porch * dsi_tmp_buf_bpp - 10;
        else
                horizontal_backporch_byte = (vm->hback_porch + vm->hsync_len) *
-                                           dsi_tmp_buf_bpp;
+                                           dsi_tmp_buf_bpp - 10;
 
        data_phy_cycles = timing->lpx + timing->da_hs_prepare +
-                         timing->da_hs_zero + timing->da_hs_exit;
-
-       if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
-               if ((vm->hfront_porch + vm->hback_porch) * dsi_tmp_buf_bpp >
-                   data_phy_cycles * dsi->lanes + 18) {
-                       horizontal_frontporch_byte =
-                               vm->hfront_porch * dsi_tmp_buf_bpp -
-                               (data_phy_cycles * dsi->lanes + 18) *
-                               vm->hfront_porch /
-                               (vm->hfront_porch + vm->hback_porch);
-
-                       horizontal_backporch_byte =
-                               horizontal_backporch_byte -
-                               (data_phy_cycles * dsi->lanes + 18) *
-                               vm->hback_porch /
-                               (vm->hfront_porch + vm->hback_porch);
-               } else {
-                       DRM_WARN("HFP less than d-phy, FPS will under 60Hz\n");
-                       horizontal_frontporch_byte = vm->hfront_porch *
-                                                    dsi_tmp_buf_bpp;
-               }
+                         timing->da_hs_zero + timing->da_hs_exit + 3;
+
+       delta = dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST ? 18 : 12;
+
+       horizontal_frontporch_byte = vm->hfront_porch * dsi_tmp_buf_bpp;
+       horizontal_front_back_byte = horizontal_frontporch_byte + horizontal_backporch_byte;
+       data_phy_cycles_byte = data_phy_cycles * dsi->lanes + delta;
+
+       if (horizontal_front_back_byte > data_phy_cycles_byte) {
+               horizontal_frontporch_byte -= data_phy_cycles_byte *
+                                             horizontal_frontporch_byte /
+                                             horizontal_front_back_byte;
+
+               horizontal_backporch_byte -= data_phy_cycles_byte *
+                                            horizontal_backporch_byte /
+                                            horizontal_front_back_byte;
        } else {
-               if ((vm->hfront_porch + vm->hback_porch) * dsi_tmp_buf_bpp >
-                   data_phy_cycles * dsi->lanes + 12) {
-                       horizontal_frontporch_byte =
-                               vm->hfront_porch * dsi_tmp_buf_bpp -
-                               (data_phy_cycles * dsi->lanes + 12) *
-                               vm->hfront_porch /
-                               (vm->hfront_porch + vm->hback_porch);
-                       horizontal_backporch_byte = horizontal_backporch_byte -
-                               (data_phy_cycles * dsi->lanes + 12) *
-                               vm->hback_porch /
-                               (vm->hfront_porch + vm->hback_porch);
-               } else {
-                       DRM_WARN("HFP less than d-phy, FPS will under 60Hz\n");
-                       horizontal_frontporch_byte = vm->hfront_porch *
-                                                    dsi_tmp_buf_bpp;
-               }
+               DRM_WARN("HFP + HBP less than d-phy, FPS will under 60Hz\n");
        }
 
        writel(horizontal_sync_active_byte, dsi->regs + DSI_HSA_WC);
index b721b8b262ce97346d0f6125ccd3f4fe54f54b78..9e1224d54729fadbe72afde9a853fe1db634ade3 100644 (file)
@@ -22,6 +22,7 @@
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_plane.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_vblank.h>
@@ -484,17 +485,27 @@ static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane,
        writel(ctrl, mxsfb->base + LCDC_AS_CTRL);
 }
 
+static bool mxsfb_format_mod_supported(struct drm_plane *plane,
+                                      uint32_t format,
+                                      uint64_t modifier)
+{
+       return modifier == DRM_FORMAT_MOD_LINEAR;
+}
+
 static const struct drm_plane_helper_funcs mxsfb_plane_primary_helper_funcs = {
+       .prepare_fb = drm_gem_fb_prepare_fb,
        .atomic_check = mxsfb_plane_atomic_check,
        .atomic_update = mxsfb_plane_primary_atomic_update,
 };
 
 static const struct drm_plane_helper_funcs mxsfb_plane_overlay_helper_funcs = {
+       .prepare_fb = drm_gem_fb_prepare_fb,
        .atomic_check = mxsfb_plane_atomic_check,
        .atomic_update = mxsfb_plane_overlay_atomic_update,
 };
 
 static const struct drm_plane_funcs mxsfb_plane_funcs = {
+       .format_mod_supported   = mxsfb_format_mod_supported,
        .update_plane           = drm_atomic_helper_update_plane,
        .disable_plane          = drm_atomic_helper_disable_plane,
        .destroy                = drm_plane_cleanup,
index 498622c0c670dcdf041b69790e1d47babe7bb4a7..f75088186fba3f4802f8486c9cc61e59e82b56bc 100644 (file)
@@ -44,6 +44,7 @@ int core507d_new_(const struct nv50_core_func *, struct nouveau_drm *, s32,
                  struct nv50_core **);
 int core507d_init(struct nv50_core *);
 void core507d_ntfy_init(struct nouveau_bo *, u32);
+int core507d_read_caps(struct nv50_disp *disp);
 int core507d_caps_init(struct nouveau_drm *, struct nv50_disp *);
 int core507d_ntfy_wait_done(struct nouveau_bo *, u32, struct nvif_device *);
 int core507d_update(struct nv50_core *, u32 *, bool);
@@ -55,6 +56,7 @@ extern const struct nv50_outp_func pior507d;
 int core827d_new(struct nouveau_drm *, s32, struct nv50_core **);
 
 int core907d_new(struct nouveau_drm *, s32, struct nv50_core **);
+int core907d_caps_init(struct nouveau_drm *drm, struct nv50_disp *disp);
 extern const struct nv50_outp_func dac907d;
 extern const struct nv50_outp_func sor907d;
 
index 248edf69e1683170f2bab46941e4b539d79fa6a4..e6f16a7750f07c2090c9acb2259b02701b020619 100644 (file)
@@ -78,18 +78,55 @@ core507d_ntfy_init(struct nouveau_bo *bo, u32 offset)
 }
 
 int
-core507d_caps_init(struct nouveau_drm *drm, struct nv50_disp *disp)
+core507d_read_caps(struct nv50_disp *disp)
 {
        struct nvif_push *push = disp->core->chan.push;
        int ret;
 
-       if ((ret = PUSH_WAIT(push, 2)))
+       ret = PUSH_WAIT(push, 6);
+       if (ret)
                return ret;
 
+       PUSH_MTHD(push, NV507D, SET_NOTIFIER_CONTROL,
+                 NVDEF(NV507D, SET_NOTIFIER_CONTROL, MODE, WRITE) |
+                 NVVAL(NV507D, SET_NOTIFIER_CONTROL, OFFSET, NV50_DISP_CORE_NTFY >> 2) |
+                 NVDEF(NV507D, SET_NOTIFIER_CONTROL, NOTIFY, ENABLE));
+
        PUSH_MTHD(push, NV507D, GET_CAPABILITIES, 0x00000000);
+
+       PUSH_MTHD(push, NV507D, SET_NOTIFIER_CONTROL,
+                 NVDEF(NV507D, SET_NOTIFIER_CONTROL, NOTIFY, DISABLE));
+
        return PUSH_KICK(push);
 }
 
+int
+core507d_caps_init(struct nouveau_drm *drm, struct nv50_disp *disp)
+{
+       struct nv50_core *core = disp->core;
+       struct nouveau_bo *bo = disp->sync;
+       s64 time;
+       int ret;
+
+       NVBO_WR32(bo, NV50_DISP_CORE_NTFY, NV_DISP_CORE_NOTIFIER_1, CAPABILITIES_1,
+                                    NVDEF(NV_DISP_CORE_NOTIFIER_1, CAPABILITIES_1, DONE, FALSE));
+
+       ret = core507d_read_caps(disp);
+       if (ret < 0)
+               return ret;
+
+       time = nvif_msec(core->chan.base.device, 2000ULL,
+                        if (NVBO_TD32(bo, NV50_DISP_CORE_NTFY,
+                                      NV_DISP_CORE_NOTIFIER_1, CAPABILITIES_1, DONE, ==, TRUE))
+                                break;
+                        usleep_range(1, 2);
+                        );
+       if (time < 0)
+               NV_ERROR(drm, "core caps notifier timeout\n");
+
+       return 0;
+}
+
 int
 core507d_init(struct nv50_core *core)
 {
index b17c03529c784e81408ee5739877cad07a2f95b8..8564d4dffaff0aa0e6b64bff1c091180b6a19787 100644 (file)
 #include "core.h"
 #include "head.h"
 
+#include <nvif/push507c.h>
+#include <nvif/timer.h>
+
+#include <nvhw/class/cl907d.h>
+
+#include "nouveau_bo.h"
+
+int
+core907d_caps_init(struct nouveau_drm *drm, struct nv50_disp *disp)
+{
+       struct nv50_core *core = disp->core;
+       struct nouveau_bo *bo = disp->sync;
+       s64 time;
+       int ret;
+
+       NVBO_WR32(bo, NV50_DISP_CORE_NTFY, NV907D_CORE_NOTIFIER_3, CAPABILITIES_4,
+                                    NVDEF(NV907D_CORE_NOTIFIER_3, CAPABILITIES_4, DONE, FALSE));
+
+       ret = core507d_read_caps(disp);
+       if (ret < 0)
+               return ret;
+
+       time = nvif_msec(core->chan.base.device, 2000ULL,
+                        if (NVBO_TD32(bo, NV50_DISP_CORE_NTFY,
+                                      NV907D_CORE_NOTIFIER_3, CAPABILITIES_4, DONE, ==, TRUE))
+                                break;
+                        usleep_range(1, 2);
+                        );
+       if (time < 0)
+               NV_ERROR(drm, "core caps notifier timeout\n");
+
+       return 0;
+}
+
 static const struct nv50_core_func
 core907d = {
        .init = core507d_init,
        .ntfy_init = core507d_ntfy_init,
-       .caps_init = core507d_caps_init,
+       .caps_init = core907d_caps_init,
        .ntfy_wait_done = core507d_ntfy_wait_done,
        .update = core507d_update,
        .head = &head907d,
index 66846f37208051989e991c0f24b1b9f6d1a6969f..1cd3a2a35dfb7faad430424e861fe3d681edbcec 100644 (file)
@@ -26,7 +26,7 @@ static const struct nv50_core_func
 core917d = {
        .init = core507d_init,
        .ntfy_init = core507d_ntfy_init,
-       .caps_init = core507d_caps_init,
+       .caps_init = core907d_caps_init,
        .ntfy_wait_done = core507d_ntfy_wait_done,
        .update = core507d_update,
        .head = &head917d,
index b111fe24a06bd27ed9a8ccb25aef8b1a7e259f66..36d6b6093d16d907207e2e47685302e4064b057c 100644 (file)
@@ -455,7 +455,7 @@ nv50_outp_get_old_connector(struct nouveau_encoder *outp,
  * DAC
  *****************************************************************************/
 static void
-nv50_dac_disable(struct drm_encoder *encoder)
+nv50_dac_disable(struct drm_encoder *encoder, struct drm_atomic_state *state)
 {
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
        struct nv50_core *core = nv50_disp(encoder->dev)->core;
@@ -467,7 +467,7 @@ nv50_dac_disable(struct drm_encoder *encoder)
 }
 
 static void
-nv50_dac_enable(struct drm_encoder *encoder)
+nv50_dac_enable(struct drm_encoder *encoder, struct drm_atomic_state *state)
 {
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
        struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
@@ -525,8 +525,8 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 static const struct drm_encoder_helper_funcs
 nv50_dac_help = {
        .atomic_check = nv50_outp_atomic_check,
-       .enable = nv50_dac_enable,
-       .disable = nv50_dac_disable,
+       .atomic_enable = nv50_dac_enable,
+       .atomic_disable = nv50_dac_disable,
        .detect = nv50_dac_detect
 };
 
@@ -1055,7 +1055,7 @@ nv50_dp_bpc_to_depth(unsigned int bpc)
 }
 
 static void
-nv50_msto_enable(struct drm_encoder *encoder)
+nv50_msto_enable(struct drm_encoder *encoder, struct drm_atomic_state *state)
 {
        struct nv50_head *head = nv50_head(encoder->crtc);
        struct nv50_head_atom *armh = nv50_head_atom(head->base.base.state);
@@ -1101,7 +1101,7 @@ nv50_msto_enable(struct drm_encoder *encoder)
 }
 
 static void
-nv50_msto_disable(struct drm_encoder *encoder)
+nv50_msto_disable(struct drm_encoder *encoder, struct drm_atomic_state *state)
 {
        struct nv50_msto *msto = nv50_msto(encoder);
        struct nv50_mstc *mstc = msto->mstc;
@@ -1118,8 +1118,8 @@ nv50_msto_disable(struct drm_encoder *encoder)
 
 static const struct drm_encoder_helper_funcs
 nv50_msto_help = {
-       .disable = nv50_msto_disable,
-       .enable = nv50_msto_enable,
+       .atomic_disable = nv50_msto_disable,
+       .atomic_enable = nv50_msto_enable,
        .atomic_check = nv50_msto_atomic_check,
 };
 
@@ -1645,8 +1645,7 @@ nv50_sor_disable(struct drm_encoder *encoder,
 }
 
 static void
-nv50_sor_enable(struct drm_encoder *encoder,
-               struct drm_atomic_state *state)
+nv50_sor_enable(struct drm_encoder *encoder, struct drm_atomic_state *state)
 {
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
        struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
@@ -1873,7 +1872,7 @@ nv50_pior_atomic_check(struct drm_encoder *encoder,
 }
 
 static void
-nv50_pior_disable(struct drm_encoder *encoder)
+nv50_pior_disable(struct drm_encoder *encoder, struct drm_atomic_state *state)
 {
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
        struct nv50_core *core = nv50_disp(encoder->dev)->core;
@@ -1885,7 +1884,7 @@ nv50_pior_disable(struct drm_encoder *encoder)
 }
 
 static void
-nv50_pior_enable(struct drm_encoder *encoder)
+nv50_pior_enable(struct drm_encoder *encoder, struct drm_atomic_state *state)
 {
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
        struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
@@ -1921,14 +1920,14 @@ nv50_pior_enable(struct drm_encoder *encoder)
        }
 
        core->func->pior->ctrl(core, nv_encoder->or, ctrl, asyh);
-       nv_encoder->crtc = encoder->crtc;
+       nv_encoder->crtc = &nv_crtc->base;
 }
 
 static const struct drm_encoder_helper_funcs
 nv50_pior_help = {
        .atomic_check = nv50_pior_atomic_check,
-       .enable = nv50_pior_enable,
-       .disable = nv50_pior_disable,
+       .atomic_enable = nv50_pior_enable,
+       .atomic_disable = nv50_pior_disable,
 };
 
 static void
index 2e444bac701dd1aca08d6cfc37b02d0ff795f524..6a463f308b64fffed630459777c2e50b3982762c 100644 (file)
 #define NV_DISP_CORE_NOTIFIER_1_COMPLETION_0_DONE_TRUE                               0x00000001
 #define NV_DISP_CORE_NOTIFIER_1_COMPLETION_0_R0                                      15:1
 #define NV_DISP_CORE_NOTIFIER_1_COMPLETION_0_TIMESTAMP                               29:16
-
+#define NV_DISP_CORE_NOTIFIER_1_CAPABILITIES_1                                       0x00000001
+#define NV_DISP_CORE_NOTIFIER_1_CAPABILITIES_1_DONE                                  0:0
+#define NV_DISP_CORE_NOTIFIER_1_CAPABILITIES_1_DONE_FALSE                            0x00000000
+#define NV_DISP_CORE_NOTIFIER_1_CAPABILITIES_1_DONE_TRUE                             0x00000001
 
 // class methods
 #define NV507D_UPDATE                                                           (0x00000080)
index 34bc3eafac7d18660bcfca05eae502a06150d7ad..79aff6ff31385c45fcf223fe0efc4fc4c01b752b 100644 (file)
 #ifndef _cl907d_h_
 #define _cl907d_h_
 
+#define NV907D_CORE_NOTIFIER_3_CAPABILITIES_4                                       0x00000004
+#define NV907D_CORE_NOTIFIER_3_CAPABILITIES_4_DONE                                  0:0
+#define NV907D_CORE_NOTIFIER_3_CAPABILITIES_4_DONE_FALSE                            0x00000000
+#define NV907D_CORE_NOTIFIER_3_CAPABILITIES_4_DONE_TRUE                             0x00000001
 #define NV907D_CORE_NOTIFIER_3_CAPABILITIES_CAP_SOR0_20                             0x00000014
 #define NV907D_CORE_NOTIFIER_3_CAPABILITIES_CAP_SOR0_20_SINGLE_LVDS18               0:0
 #define NV907D_CORE_NOTIFIER_3_CAPABILITIES_CAP_SOR0_20_SINGLE_LVDS18_FALSE         0x00000000
index 2ee75646ad6fcb44e33435981d92e2147885d9b8..7daa12eec01bb3fdb9d8e6c10c2eeb7fd1804b86 100644 (file)
@@ -350,14 +350,13 @@ set_placement_list(struct nouveau_drm *drm, struct ttm_place *pl, unsigned *n,
 
        if (domain & NOUVEAU_GEM_DOMAIN_VRAM) {
                struct nvif_mmu *mmu = &drm->client.mmu;
-               const u8 type = mmu->type[drm->ttm.type_vram].type;
 
                pl[*n].mem_type = TTM_PL_VRAM;
                pl[*n].flags = flags & ~TTM_PL_FLAG_CACHED;
 
                /* Some BARs do not support being ioremapped WC */
                if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA &&
-                   type & NVIF_MEM_UNCACHED)
+                   mmu->type[drm->ttm.type_vram].type & NVIF_MEM_UNCACHED)
                        pl[*n].flags &= ~TTM_PL_FLAG_WC;
 
                (*n)++;
@@ -1215,8 +1214,8 @@ retry:
                        }
 
                        reg->bus.offset = handle;
-                       ret = 0;
                }
+               ret = 0;
                break;
        default:
                ret = -EINVAL;
index 49dd0cbc332ffa0107d9ba9e45867b33dc69ed41..8b4b3688c7ae3a608f0e76d5aec9d54571d94da0 100644 (file)
@@ -532,11 +532,13 @@ static void
 nouveau_connector_set_edid(struct nouveau_connector *nv_connector,
                           struct edid *edid)
 {
-       struct edid *old_edid = nv_connector->edid;
+       if (nv_connector->edid != edid) {
+               struct edid *old_edid = nv_connector->edid;
 
-       drm_connector_update_edid_property(&nv_connector->base, edid);
-       kfree(old_edid);
-       nv_connector->edid = edid;
+               drm_connector_update_edid_property(&nv_connector->base, edid);
+               kfree(old_edid);
+               nv_connector->edid = edid;
+       }
 }
 
 static enum drm_connector_status
@@ -669,8 +671,10 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
        /* Try retrieving EDID via DDC */
        if (!drm->vbios.fp_no_ddc) {
                status = nouveau_connector_detect(connector, force);
-               if (status == connector_status_connected)
+               if (status == connector_status_connected) {
+                       edid = nv_connector->edid;
                        goto out;
+               }
        }
 
        /* On some laptops (Sony, i'm looking at you) there appears to
@@ -1023,29 +1027,6 @@ get_tmds_link_bandwidth(struct drm_connector *connector)
                return 112000 * duallink_scale;
 }
 
-enum drm_mode_status
-nouveau_conn_mode_clock_valid(const struct drm_display_mode *mode,
-                             const unsigned min_clock,
-                             const unsigned max_clock,
-                             unsigned int *clock_out)
-{
-       unsigned int clock = mode->clock;
-
-       if ((mode->flags & DRM_MODE_FLAG_3D_MASK) ==
-           DRM_MODE_FLAG_3D_FRAME_PACKING)
-               clock *= 2;
-
-       if (clock < min_clock)
-               return MODE_CLOCK_LOW;
-       if (clock > max_clock)
-               return MODE_CLOCK_HIGH;
-
-       if (clock_out)
-               *clock_out = clock;
-
-       return MODE_OK;
-}
-
 static enum drm_mode_status
 nouveau_connector_mode_valid(struct drm_connector *connector,
                             struct drm_display_mode *mode)
@@ -1053,7 +1034,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
        struct nouveau_connector *nv_connector = nouveau_connector(connector);
        struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
        struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
-       unsigned min_clock = 25000, max_clock = min_clock;
+       unsigned int min_clock = 25000, max_clock = min_clock, clock = mode->clock;
 
        switch (nv_encoder->dcb->type) {
        case DCB_OUTPUT_LVDS:
@@ -1082,8 +1063,15 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
                return MODE_BAD;
        }
 
-       return nouveau_conn_mode_clock_valid(mode, min_clock, max_clock,
-                                            NULL);
+       if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
+               clock *= 2;
+
+       if (clock < min_clock)
+               return MODE_CLOCK_LOW;
+       if (clock > max_clock)
+               return MODE_CLOCK_HIGH;
+
+       return MODE_OK;
 }
 
 static struct drm_encoder *
index 7b640e05bd4cdc76a69dde97122ed1f1eccd6fa5..040ed88d362d795591aaad854e9dd70de94fd47f 100644 (file)
@@ -231,23 +231,30 @@ nv50_dp_mode_valid(struct drm_connector *connector,
                   const struct drm_display_mode *mode,
                   unsigned *out_clock)
 {
-       const unsigned min_clock = 25000;
-       unsigned max_clock, ds_clock, clock;
-       enum drm_mode_status ret;
+       const unsigned int min_clock = 25000;
+       unsigned int max_rate, mode_rate, ds_max_dotclock, clock = mode->clock;
+       const u8 bpp = connector->display_info.bpc * 3;
 
        if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace)
                return MODE_NO_INTERLACE;
 
-       max_clock = outp->dp.link_nr * outp->dp.link_bw;
-       ds_clock = drm_dp_downstream_max_dotclock(outp->dp.dpcd,
-                                                 outp->dp.downstream_ports);
-       if (ds_clock)
-               max_clock = min(max_clock, ds_clock);
+       if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
+               clock *= 2;
+
+       max_rate = outp->dp.link_nr * outp->dp.link_bw;
+       mode_rate = DIV_ROUND_UP(clock * bpp, 8);
+       if (mode_rate > max_rate)
+               return MODE_CLOCK_HIGH;
+
+       ds_max_dotclock = drm_dp_downstream_max_dotclock(outp->dp.dpcd, outp->dp.downstream_ports);
+       if (ds_max_dotclock && clock > ds_max_dotclock)
+               return MODE_CLOCK_HIGH;
+
+       if (clock < min_clock)
+               return MODE_CLOCK_LOW;
 
-       clock = mode->clock * (connector->display_info.bpc * 3) / 10;
-       ret = nouveau_conn_mode_clock_valid(mode, min_clock, max_clock,
-                                           &clock);
        if (out_clock)
                *out_clock = clock;
-       return ret;
+
+       return MODE_OK;
 }
index 89adadf4706b456b5f1a0d8a85ae91273dc7e842..c2051380d18c05486c30c4c4640720a2a486fc58 100644 (file)
@@ -190,7 +190,8 @@ nouveau_gem_new(struct nouveau_cli *cli, u64 size, int align, uint32_t domain,
         * to the caller, instead of a normal nouveau_bo ttm reference. */
        ret = drm_gem_object_init(drm->dev, &nvbo->bo.base, size);
        if (ret) {
-               nouveau_bo_ref(NULL, &nvbo);
+               drm_gem_object_release(&nvbo->bo.base);
+               kfree(nvbo);
                return ret;
        }
 
@@ -557,8 +558,10 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
                        NV_PRINTK(err, cli, "validating bo list\n");
                validate_fini(op, chan, NULL, NULL);
                return ret;
+       } else if (ret > 0) {
+               *apply_relocs = true;
        }
-       *apply_relocs = ret;
+
        return 0;
 }
 
@@ -661,7 +664,6 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
                nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data);
        }
 
-       u_free(reloc);
        return ret;
 }
 
@@ -871,9 +873,10 @@ out:
                                break;
                        }
                }
-               u_free(reloc);
        }
 out_prevalid:
+       if (!IS_ERR(reloc))
+               u_free(reloc);
        u_free(bo);
        u_free(push);
 
index 2df1c04605594f5733efb6dc0cd8e7ddb075873c..4f69e4c3dafde298f6f7707b719a074a5dca5076 100644 (file)
@@ -105,11 +105,11 @@ nouveau_svmm_bind(struct drm_device *dev, void *data,
        struct nouveau_cli *cli = nouveau_cli(file_priv);
        struct drm_nouveau_svm_bind *args = data;
        unsigned target, cmd, priority;
-       unsigned long addr, end, size;
+       unsigned long addr, end;
        struct mm_struct *mm;
 
        args->va_start &= PAGE_MASK;
-       args->va_end &= PAGE_MASK;
+       args->va_end = ALIGN(args->va_end, PAGE_SIZE);
 
        /* Sanity check arguments */
        if (args->reserved0 || args->reserved1)
@@ -118,8 +118,6 @@ nouveau_svmm_bind(struct drm_device *dev, void *data,
                return -EINVAL;
        if (args->va_start >= args->va_end)
                return -EINVAL;
-       if (!args->npages)
-               return -EINVAL;
 
        cmd = args->header >> NOUVEAU_SVM_BIND_COMMAND_SHIFT;
        cmd &= NOUVEAU_SVM_BIND_COMMAND_MASK;
@@ -151,12 +149,6 @@ nouveau_svmm_bind(struct drm_device *dev, void *data,
        if (args->stride)
                return -EINVAL;
 
-       size = ((unsigned long)args->npages) << PAGE_SHIFT;
-       if ((args->va_start + size) <= args->va_start)
-               return -EINVAL;
-       if ((args->va_start + size) > args->va_end)
-               return -EINVAL;
-
        /*
         * Ok we are ask to do something sane, for now we only support migrate
         * commands but we will add things like memory policy (what to do on
@@ -171,7 +163,7 @@ nouveau_svmm_bind(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
-       for (addr = args->va_start, end = args->va_start + size; addr < end;) {
+       for (addr = args->va_start, end = args->va_end; addr < end;) {
                struct vm_area_struct *vma;
                unsigned long next;
 
index dcb70677d0accac488ac98712e56903ad025c571..7851bec5f0e5feccd8b2be5f1fbcb2b6180a21bf 100644 (file)
@@ -2924,17 +2924,34 @@ nvkm_device_del(struct nvkm_device **pdevice)
        }
 }
 
+/* returns true if the GPU is in the CPU native byte order */
 static inline bool
 nvkm_device_endianness(struct nvkm_device *device)
 {
-       u32 boot1 = nvkm_rd32(device, 0x000004) & 0x01000001;
 #ifdef __BIG_ENDIAN
-       if (!boot1)
-               return false;
+       const bool big_endian = true;
 #else
-       if (boot1)
-               return false;
+       const bool big_endian = false;
 #endif
+
+       /* Read NV_PMC_BOOT_1, and assume non-functional endian switch if it
+        * doesn't contain the expected values.
+        */
+       u32 pmc_boot_1 = nvkm_rd32(device, 0x000004);
+       if (pmc_boot_1 && pmc_boot_1 != 0x01000001)
+               return !big_endian; /* Assume GPU is LE in this case. */
+
+       /* 0 means LE and 0x01000001 means BE GPU. Condition is true when
+        * GPU/CPU endianness don't match.
+        */
+       if (big_endian == !pmc_boot_1) {
+               nvkm_wr32(device, 0x000004, 0x01000001);
+               nvkm_rd32(device, 0x000000);
+               if (nvkm_rd32(device, 0x000004) != (big_endian ? 0x01000001 : 0x00000000))
+                       return !big_endian; /* Assume GPU is LE on any unexpected read-back. */
+       }
+
+       /* CPU/GPU endianness should (hopefully) match. */
        return true;
 }
 
@@ -2987,14 +3004,10 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
        if (detect) {
                /* switch mmio to cpu's native endianness */
                if (!nvkm_device_endianness(device)) {
-                       nvkm_wr32(device, 0x000004, 0x01000001);
-                       nvkm_rd32(device, 0x000000);
-                       if (!nvkm_device_endianness(device)) {
-                               nvdev_error(device,
-                                           "GPU not supported on big-endian\n");
-                               ret = -ENOSYS;
-                               goto done;
-                       }
+                       nvdev_error(device,
+                                   "Couldn't switch GPU to CPUs endianess\n");
+                       ret = -ENOSYS;
+                       goto done;
                }
 
                boot0 = nvkm_rd32(device, 0x000000);
index 033fd30074b078021f60c64edeae4fbea65931d8..282e4c837cd930e5b29bd85ec74020f19aff7ed7 100644 (file)
@@ -195,8 +195,7 @@ static void sdi_bridge_mode_set(struct drm_bridge *bridge,
        sdi->pixelclock = adjusted_mode->clock * 1000;
 }
 
-static void sdi_bridge_enable(struct drm_bridge *bridge,
-                             struct drm_bridge_state *bridge_state)
+static void sdi_bridge_enable(struct drm_bridge *bridge)
 {
        struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
        struct dispc_clock_info dispc_cinfo;
@@ -259,8 +258,7 @@ err_get_dispc:
        regulator_disable(sdi->vdds_sdi_reg);
 }
 
-static void sdi_bridge_disable(struct drm_bridge *bridge,
-                              struct drm_bridge_state *bridge_state)
+static void sdi_bridge_disable(struct drm_bridge *bridge)
 {
        struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
 
@@ -278,8 +276,8 @@ static const struct drm_bridge_funcs sdi_bridge_funcs = {
        .mode_valid = sdi_bridge_mode_valid,
        .mode_fixup = sdi_bridge_mode_fixup,
        .mode_set = sdi_bridge_mode_set,
-       .atomic_enable = sdi_bridge_enable,
-       .atomic_disable = sdi_bridge_disable,
+       .enable = sdi_bridge_enable,
+       .disable = sdi_bridge_disable,
 };
 
 static void sdi_bridge_init(struct sdi_device *sdi)
index 3482e28e30fc9ed3c68698891e6ffcf0929e9598..0c5f22e95c2dbbafb9850faf2aeb4771788d09ad 100644 (file)
@@ -26,7 +26,9 @@
 struct mantix {
        struct device *dev;
        struct drm_panel panel;
+
        struct gpio_desc *reset_gpio;
+       struct gpio_desc *tp_rstn_gpio;
 
        struct regulator *avdd;
        struct regulator *avee;
@@ -124,6 +126,10 @@ static int mantix_unprepare(struct drm_panel *panel)
 {
        struct mantix *ctx = panel_to_mantix(panel);
 
+       gpiod_set_value_cansleep(ctx->tp_rstn_gpio, 1);
+       usleep_range(5000, 6000);
+       gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
        regulator_disable(ctx->avee);
        regulator_disable(ctx->avdd);
        /* T11 */
@@ -165,13 +171,10 @@ static int mantix_prepare(struct drm_panel *panel)
                return ret;
        }
 
-       /* T3+T5 */
-       usleep_range(10000, 12000);
-
-       gpiod_set_value_cansleep(ctx->reset_gpio, 1);
-       usleep_range(5150, 7000);
-
+       /* T3 + T4 + time for voltage to become stable: */
+       usleep_range(6000, 7000);
        gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+       gpiod_set_value_cansleep(ctx->tp_rstn_gpio, 0);
 
        /* T6 */
        msleep(50);
@@ -204,7 +207,7 @@ static int mantix_get_modes(struct drm_panel *panel,
        if (!mode) {
                dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",
                        default_mode.hdisplay, default_mode.vdisplay,
-                       drm_mode_vrefresh(mode));
+                       drm_mode_vrefresh(&default_mode));
                return -ENOMEM;
        }
 
@@ -236,12 +239,18 @@ static int mantix_probe(struct mipi_dsi_device *dsi)
        if (!ctx)
                return -ENOMEM;
 
-       ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+       ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
        if (IS_ERR(ctx->reset_gpio)) {
                dev_err(dev, "cannot get reset gpio\n");
                return PTR_ERR(ctx->reset_gpio);
        }
 
+       ctx->tp_rstn_gpio = devm_gpiod_get(dev, "mantix,tp-rstn", GPIOD_OUT_HIGH);
+       if (IS_ERR(ctx->tp_rstn_gpio)) {
+               dev_err(dev, "cannot get tp-rstn gpio\n");
+               return PTR_ERR(ctx->tp_rstn_gpio);
+       }
+
        mipi_dsi_set_drvdata(dsi, ctx);
        ctx->dev = dev;
 
index e95fdfb16b6c9cc4dcc0c0a38a10eec5834c6a94..ba0b3ead150f9023cea090475b9d9d367c324e7b 100644 (file)
@@ -629,7 +629,7 @@ static int acx565akm_probe(struct spi_device *spi)
        lcd->spi = spi;
        mutex_init(&lcd->mutex);
 
-       lcd->reset_gpio = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW);
+       lcd->reset_gpio = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_HIGH);
        if (IS_ERR(lcd->reset_gpio)) {
                dev_err(&spi->dev, "failed to get reset GPIO\n");
                return PTR_ERR(lcd->reset_gpio);
index 37d4cb7a5491c4a58ea1a3102ac3f05032e4a9fc..0fc084110e5ba0c7761a05118a5a6bba57923bd9 100644 (file)
@@ -626,6 +626,7 @@ static int panfrost_probe(struct platform_device *pdev)
 err_out1:
        pm_runtime_disable(pfdev->dev);
        panfrost_device_fini(pfdev);
+       pm_runtime_set_suspended(pfdev->dev);
 err_out0:
        drm_dev_put(ddev);
        return err;
@@ -640,9 +641,9 @@ static int panfrost_remove(struct platform_device *pdev)
        panfrost_gem_shrinker_cleanup(ddev);
 
        pm_runtime_get_sync(pfdev->dev);
-       panfrost_device_fini(pfdev);
-       pm_runtime_put_sync_suspend(pfdev->dev);
        pm_runtime_disable(pfdev->dev);
+       panfrost_device_fini(pfdev);
+       pm_runtime_set_suspended(pfdev->dev);
 
        drm_dev_put(ddev);
        return 0;
index 1a6cea0e0bd743baf77dfc82571f86134ea743ef..62d4d710a57118dcc02481a6cdb8ac4a7cdc8c86 100644 (file)
@@ -105,14 +105,12 @@ void panfrost_gem_mapping_put(struct panfrost_gem_mapping *mapping)
        kref_put(&mapping->refcount, panfrost_gem_mapping_release);
 }
 
-void panfrost_gem_teardown_mappings(struct panfrost_gem_object *bo)
+void panfrost_gem_teardown_mappings_locked(struct panfrost_gem_object *bo)
 {
        struct panfrost_gem_mapping *mapping;
 
-       mutex_lock(&bo->mappings.lock);
        list_for_each_entry(mapping, &bo->mappings.list, node)
                panfrost_gem_teardown_mapping(mapping);
-       mutex_unlock(&bo->mappings.lock);
 }
 
 int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv)
index b3517ff9630cb23a8753d066303fb5880adcf984..8088d5fd8480e809f0a50f61ef3b09c4f45388e4 100644 (file)
@@ -82,7 +82,7 @@ struct panfrost_gem_mapping *
 panfrost_gem_mapping_get(struct panfrost_gem_object *bo,
                         struct panfrost_file_priv *priv);
 void panfrost_gem_mapping_put(struct panfrost_gem_mapping *mapping);
-void panfrost_gem_teardown_mappings(struct panfrost_gem_object *bo);
+void panfrost_gem_teardown_mappings_locked(struct panfrost_gem_object *bo);
 
 void panfrost_gem_shrinker_init(struct drm_device *dev);
 void panfrost_gem_shrinker_cleanup(struct drm_device *dev);
index 288e46c40673a9d102580030b8a107c2d2af3572..1b9f68d8e9aa69ab3c5bea17bb5d541b19ebe72c 100644 (file)
@@ -40,18 +40,26 @@ static bool panfrost_gem_purge(struct drm_gem_object *obj)
 {
        struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
        struct panfrost_gem_object *bo = to_panfrost_bo(obj);
+       bool ret = false;
 
        if (atomic_read(&bo->gpu_usecount))
                return false;
 
-       if (!mutex_trylock(&shmem->pages_lock))
+       if (!mutex_trylock(&bo->mappings.lock))
                return false;
 
-       panfrost_gem_teardown_mappings(bo);
+       if (!mutex_trylock(&shmem->pages_lock))
+               goto unlock_mappings;
+
+       panfrost_gem_teardown_mappings_locked(bo);
        drm_gem_shmem_purge_locked(obj);
+       ret = true;
 
        mutex_unlock(&shmem->pages_lock);
-       return true;
+
+unlock_mappings:
+       mutex_unlock(&bo->mappings.lock);
+       return ret;
 }
 
 static unsigned long
index f292c6a6e20fb9b1ba1937693dbef958b27df958..41edd0a421b256cb35311156ed6bf5cb1b056847 100644 (file)
@@ -544,7 +544,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
        struct device_node  *port, *endpoint;
        int ret = 0, child_count = 0;
        const char *name;
-       u32 endpoint_id;
+       u32 endpoint_id = 0;
 
        lvds->drm_dev = drm_dev;
        port = of_graph_get_port_by_id(dev->of_node, 1);
index 77497b45f9a28d25b54860de57bc3b0431286f60..55960cbb101900d3a3760fc6418784d8b5cc2276 100644 (file)
@@ -814,9 +814,15 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
                 *
                 * XXX(hch): this has no business in a driver and needs to move
                 * to the device tree.
+                *
+                * If we have two subsequent calls to dma_direct_set_offset
+                * returns -EINVAL. Unfortunately, this happens when we have two
+                * backends in the system, and will result in the driver
+                * reporting an error while it has been setup properly before.
+                * Ignore EINVAL, but it should really be removed eventually.
                 */
                ret = dma_direct_set_offset(drm->dev, PHYS_OFFSET, 0, SZ_4G);
-               if (ret)
+               if (ret && ret != -EINVAL)
                        return ret;
        }
 
index b51cc685c13adbff30cc21fd36bb08d639950029..edb60ae0a9b75f667b67f65d7380c1208b8f977e 100644 (file)
@@ -407,6 +407,7 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
        struct drm_framebuffer *fb = state->fb;
        const struct drm_format_info *format = fb->format;
        uint64_t modifier = fb->modifier;
+       unsigned int ch1_phase_idx;
        u32 out_fmt_val;
        u32 in_fmt_val, in_mod_val, in_ps_val;
        unsigned int i;
@@ -442,18 +443,19 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
         * I have no idea what this does exactly, but it seems to be
         * related to the scaler FIR filter phase parameters.
         */
+       ch1_phase_idx = (format->num_planes > 1) ? 1 : 0;
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZPHASE_REG,
-                    frontend->data->ch_phase[0].horzphase);
+                    frontend->data->ch_phase[0]);
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZPHASE_REG,
-                    frontend->data->ch_phase[1].horzphase);
+                    frontend->data->ch_phase[ch1_phase_idx]);
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE0_REG,
-                    frontend->data->ch_phase[0].vertphase[0]);
+                    frontend->data->ch_phase[0]);
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE0_REG,
-                    frontend->data->ch_phase[1].vertphase[0]);
+                    frontend->data->ch_phase[ch1_phase_idx]);
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG,
-                    frontend->data->ch_phase[0].vertphase[1]);
+                    frontend->data->ch_phase[0]);
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG,
-                    frontend->data->ch_phase[1].vertphase[1]);
+                    frontend->data->ch_phase[ch1_phase_idx]);
 
        /*
         * Checking the input format is sufficient since we currently only
@@ -687,30 +689,12 @@ static const struct dev_pm_ops sun4i_frontend_pm_ops = {
 };
 
 static const struct sun4i_frontend_data sun4i_a10_frontend = {
-       .ch_phase               = {
-               {
-                       .horzphase = 0,
-                       .vertphase = { 0, 0 },
-               },
-               {
-                       .horzphase = 0xfc000,
-                       .vertphase = { 0xfc000, 0xfc000 },
-               },
-       },
+       .ch_phase               = { 0x000, 0xfc000 },
        .has_coef_rdy           = true,
 };
 
 static const struct sun4i_frontend_data sun8i_a33_frontend = {
-       .ch_phase               = {
-               {
-                       .horzphase = 0x400,
-                       .vertphase = { 0x400, 0x400 },
-               },
-               {
-                       .horzphase = 0x400,
-                       .vertphase = { 0x400, 0x400 },
-               },
-       },
+       .ch_phase               = { 0x400, 0xfc400 },
        .has_coef_access_ctrl   = true,
 };
 
index 0c382c1ddb0fe81b0eb8f63999d0f6e2856d650c..2e7b76e50c2ba21942fa16b4c5d42f33c6f15326 100644 (file)
@@ -115,11 +115,7 @@ struct reset_control;
 struct sun4i_frontend_data {
        bool    has_coef_access_ctrl;
        bool    has_coef_rdy;
-
-       struct {
-               u32     horzphase;
-               u32     vertphase[2];
-       } ch_phase[2];
+       u32     ch_phase[2];
 };
 
 struct sun4i_frontend {
index d4c08043dd81df69156965b03425b23d737b6d91..92add2cef2e7debf5f43e2de8170bc295a4f8677 100644 (file)
@@ -208,6 +208,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,
        phy_node = of_parse_phandle(dev->of_node, "phys", 0);
        if (!phy_node) {
                dev_err(dev, "Can't found PHY phandle\n");
+               ret = -EINVAL;
                goto err_disable_clk_tmds;
        }
 
index ba9d1c3e7cacf1bedeb3e73c4f9752bda1e5b32f..e4baf07992a4da636228638d2db344ea4eb4ff0a 100644 (file)
@@ -90,7 +90,7 @@ static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
        if (!fpriv)
                return -ENOMEM;
 
-       idr_init(&fpriv->contexts);
+       idr_init_base(&fpriv->contexts, 1);
        mutex_init(&fpriv->lock);
        filp->driver_priv = fpriv;
 
index 5a4fd0dbf4cf7bd7481ba2f392aeb6ca267b05d4..47d26b5d99456bdd0a3d1facc99f2d90949075a8 100644 (file)
@@ -129,7 +129,6 @@ int tegra_output_probe(struct tegra_output *output)
 
                if (!output->ddc) {
                        err = -EPROBE_DEFER;
-                       of_node_put(ddc);
                        return err;
                }
        }
index e88a17c2937f26819f0ef1c774d2317f6bfcb1ac..cc2aa2308a515820e9c1590cd598523032f91e6e 100644 (file)
@@ -397,7 +397,6 @@ struct tegra_sor;
 struct tegra_sor_ops {
        const char *name;
        int (*probe)(struct tegra_sor *sor);
-       int (*remove)(struct tegra_sor *sor);
        void (*audio_enable)(struct tegra_sor *sor);
        void (*audio_disable)(struct tegra_sor *sor);
 };
@@ -2942,6 +2941,24 @@ static const struct drm_encoder_helper_funcs tegra_sor_dp_helpers = {
        .atomic_check = tegra_sor_encoder_atomic_check,
 };
 
+static void tegra_sor_disable_regulator(void *data)
+{
+       struct regulator *reg = data;
+
+       regulator_disable(reg);
+}
+
+static int tegra_sor_enable_regulator(struct tegra_sor *sor, struct regulator *reg)
+{
+       int err;
+
+       err = regulator_enable(reg);
+       if (err)
+               return err;
+
+       return devm_add_action_or_reset(sor->dev, tegra_sor_disable_regulator, reg);
+}
+
 static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
 {
        int err;
@@ -2953,7 +2970,7 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
                return PTR_ERR(sor->avdd_io_supply);
        }
 
-       err = regulator_enable(sor->avdd_io_supply);
+       err = tegra_sor_enable_regulator(sor, sor->avdd_io_supply);
        if (err < 0) {
                dev_err(sor->dev, "failed to enable AVDD I/O supply: %d\n",
                        err);
@@ -2967,7 +2984,7 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
                return PTR_ERR(sor->vdd_pll_supply);
        }
 
-       err = regulator_enable(sor->vdd_pll_supply);
+       err = tegra_sor_enable_regulator(sor, sor->vdd_pll_supply);
        if (err < 0) {
                dev_err(sor->dev, "failed to enable VDD PLL supply: %d\n",
                        err);
@@ -2981,7 +2998,7 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
                return PTR_ERR(sor->hdmi_supply);
        }
 
-       err = regulator_enable(sor->hdmi_supply);
+       err = tegra_sor_enable_regulator(sor, sor->hdmi_supply);
        if (err < 0) {
                dev_err(sor->dev, "failed to enable HDMI supply: %d\n", err);
                return err;
@@ -2992,19 +3009,9 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
        return 0;
 }
 
-static int tegra_sor_hdmi_remove(struct tegra_sor *sor)
-{
-       regulator_disable(sor->hdmi_supply);
-       regulator_disable(sor->vdd_pll_supply);
-       regulator_disable(sor->avdd_io_supply);
-
-       return 0;
-}
-
 static const struct tegra_sor_ops tegra_sor_hdmi_ops = {
        .name = "HDMI",
        .probe = tegra_sor_hdmi_probe,
-       .remove = tegra_sor_hdmi_remove,
        .audio_enable = tegra_sor_hdmi_audio_enable,
        .audio_disable = tegra_sor_hdmi_audio_disable,
 };
@@ -3017,7 +3024,7 @@ static int tegra_sor_dp_probe(struct tegra_sor *sor)
        if (IS_ERR(sor->avdd_io_supply))
                return PTR_ERR(sor->avdd_io_supply);
 
-       err = regulator_enable(sor->avdd_io_supply);
+       err = tegra_sor_enable_regulator(sor, sor->avdd_io_supply);
        if (err < 0)
                return err;
 
@@ -3025,25 +3032,16 @@ static int tegra_sor_dp_probe(struct tegra_sor *sor)
        if (IS_ERR(sor->vdd_pll_supply))
                return PTR_ERR(sor->vdd_pll_supply);
 
-       err = regulator_enable(sor->vdd_pll_supply);
+       err = tegra_sor_enable_regulator(sor, sor->vdd_pll_supply);
        if (err < 0)
                return err;
 
        return 0;
 }
 
-static int tegra_sor_dp_remove(struct tegra_sor *sor)
-{
-       regulator_disable(sor->vdd_pll_supply);
-       regulator_disable(sor->avdd_io_supply);
-
-       return 0;
-}
-
 static const struct tegra_sor_ops tegra_sor_dp_ops = {
        .name = "DP",
        .probe = tegra_sor_dp_probe,
-       .remove = tegra_sor_dp_remove,
 };
 
 static int tegra_sor_init(struct host1x_client *client)
@@ -3145,6 +3143,7 @@ static int tegra_sor_init(struct host1x_client *client)
                if (err < 0) {
                        dev_err(sor->dev, "failed to deassert SOR reset: %d\n",
                                err);
+                       clk_disable_unprepare(sor->clk);
                        return err;
                }
 
@@ -3152,12 +3151,17 @@ static int tegra_sor_init(struct host1x_client *client)
        }
 
        err = clk_prepare_enable(sor->clk_safe);
-       if (err < 0)
+       if (err < 0) {
+               clk_disable_unprepare(sor->clk);
                return err;
+       }
 
        err = clk_prepare_enable(sor->clk_dp);
-       if (err < 0)
+       if (err < 0) {
+               clk_disable_unprepare(sor->clk_safe);
+               clk_disable_unprepare(sor->clk);
                return err;
+       }
 
        return 0;
 }
@@ -3764,17 +3768,16 @@ static int tegra_sor_probe(struct platform_device *pdev)
                return err;
 
        err = tegra_output_probe(&sor->output);
-       if (err < 0) {
-               dev_err(&pdev->dev, "failed to probe output: %d\n", err);
-               return err;
-       }
+       if (err < 0)
+               return dev_err_probe(&pdev->dev, err,
+                                    "failed to probe output\n");
 
        if (sor->ops && sor->ops->probe) {
                err = sor->ops->probe(sor);
                if (err < 0) {
                        dev_err(&pdev->dev, "failed to probe %s: %d\n",
                                sor->ops->name, err);
-                       goto output;
+                       goto remove;
                }
        }
 
@@ -3955,9 +3958,6 @@ unregister:
 rpm_disable:
        pm_runtime_disable(&pdev->dev);
 remove:
-       if (sor->ops && sor->ops->remove)
-               sor->ops->remove(sor);
-output:
        tegra_output_remove(&sor->output);
        return err;
 }
@@ -3976,12 +3976,6 @@ static int tegra_sor_remove(struct platform_device *pdev)
 
        pm_runtime_disable(&pdev->dev);
 
-       if (sor->ops && sor->ops->remove) {
-               err = sor->ops->remove(sor);
-               if (err < 0)
-                       dev_err(&pdev->dev, "failed to remove SOR: %d\n", err);
-       }
-
        tegra_output_remove(&sor->output);
 
        return 0;
index 915f8bfdb58cad0f355b4e5c94fbf37df651309a..182c586525eb844807588c2e62064e779f887d9f 100644 (file)
@@ -568,7 +568,6 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
                ret = v3d_job_init(v3d, file_priv, &bin->base,
                                   v3d_job_free, args->in_sync_bcl);
                if (ret) {
-                       kfree(bin);
                        v3d_job_put(&render->base);
                        kfree(bin);
                        return ret;
index 74ceebd62fbce4aa131ff6444bfc912c630ec7c9..cc74a3f3a07af960564935aeca7614343c1d9b7e 100644 (file)
@@ -449,7 +449,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size,
        }
 
        if (IS_ERR(cma_obj)) {
-               struct drm_printer p = drm_info_printer(vc4->dev->dev);
+               struct drm_printer p = drm_info_printer(vc4->base.dev);
                DRM_ERROR("Failed to allocate from CMA:\n");
                vc4_bo_stats_print(&p, vc4);
                return ERR_PTR(-ENOMEM);
@@ -590,7 +590,7 @@ static void vc4_bo_cache_time_work(struct work_struct *work)
 {
        struct vc4_dev *vc4 =
                container_of(work, struct vc4_dev, bo_cache.time_work);
-       struct drm_device *dev = vc4->dev;
+       struct drm_device *dev = &vc4->base;
 
        mutex_lock(&vc4->bo_lock);
        vc4_bo_cache_free_old(dev);
@@ -1005,6 +1005,7 @@ int vc4_get_tiling_ioctl(struct drm_device *dev, void *data,
        return 0;
 }
 
+static void vc4_bo_cache_destroy(struct drm_device *dev, void *unused);
 int vc4_bo_cache_init(struct drm_device *dev)
 {
        struct vc4_dev *vc4 = to_vc4_dev(dev);
@@ -1033,10 +1034,10 @@ int vc4_bo_cache_init(struct drm_device *dev)
        INIT_WORK(&vc4->bo_cache.time_work, vc4_bo_cache_time_work);
        timer_setup(&vc4->bo_cache.time_timer, vc4_bo_cache_time_timer, 0);
 
-       return 0;
+       return drmm_add_action_or_reset(dev, vc4_bo_cache_destroy, NULL);
 }
 
-void vc4_bo_cache_destroy(struct drm_device *dev)
+static void vc4_bo_cache_destroy(struct drm_device *dev, void *unused)
 {
        struct vc4_dev *vc4 = to_vc4_dev(dev);
        int i;
index f1a5fd5dab6f5caf103a98764449fa79bfaf374f..839610f8092af6842c08e65d4128cd937c24ede1 100644 (file)
@@ -257,37 +257,37 @@ static int vc4_drm_bind(struct device *dev)
 
        dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
-       vc4 = devm_kzalloc(dev, sizeof(*vc4), GFP_KERNEL);
-       if (!vc4)
-               return -ENOMEM;
-
        /* If VC4 V3D is missing, don't advertise render nodes. */
        node = of_find_matching_node_and_match(NULL, vc4_v3d_dt_match, NULL);
        if (!node || !of_device_is_available(node))
                vc4_drm_driver.driver_features &= ~DRIVER_RENDER;
        of_node_put(node);
 
-       drm = drm_dev_alloc(&vc4_drm_driver, dev);
-       if (IS_ERR(drm))
-               return PTR_ERR(drm);
+       vc4 = devm_drm_dev_alloc(dev, &vc4_drm_driver, struct vc4_dev, base);
+       if (IS_ERR(vc4))
+               return PTR_ERR(vc4);
+
+       drm = &vc4->base;
        platform_set_drvdata(pdev, drm);
-       vc4->dev = drm;
-       drm->dev_private = vc4;
        INIT_LIST_HEAD(&vc4->debugfs_list);
 
        mutex_init(&vc4->bin_bo_lock);
 
        ret = vc4_bo_cache_init(drm);
        if (ret)
-               goto dev_put;
+               return ret;
 
-       drm_mode_config_init(drm);
+       ret = drmm_mode_config_init(drm);
+       if (ret)
+               return ret;
 
-       vc4_gem_init(drm);
+       ret = vc4_gem_init(drm);
+       if (ret)
+               return ret;
 
        ret = component_bind_all(dev, drm);
        if (ret)
-               goto gem_destroy;
+               return ret;
 
        ret = vc4_plane_create_additional_planes(drm);
        if (ret)
@@ -312,29 +312,17 @@ static int vc4_drm_bind(struct device *dev)
 
 unbind_all:
        component_unbind_all(dev, drm);
-gem_destroy:
-       vc4_gem_destroy(drm);
-       vc4_bo_cache_destroy(drm);
-dev_put:
-       drm_dev_put(drm);
+
        return ret;
 }
 
 static void vc4_drm_unbind(struct device *dev)
 {
        struct drm_device *drm = dev_get_drvdata(dev);
-       struct vc4_dev *vc4 = to_vc4_dev(drm);
 
        drm_dev_unregister(drm);
 
        drm_atomic_helper_shutdown(drm);
-
-       drm_mode_config_cleanup(drm);
-
-       drm_atomic_private_obj_fini(&vc4->load_tracker);
-       drm_atomic_private_obj_fini(&vc4->ctm_manager);
-
-       drm_dev_put(drm);
 }
 
 static const struct component_master_ops vc4_drm_ops = {
index 90b911fd2a7f3b43191fdba401ea03ecc19809c1..c5f2944d5bc606f25216389db01b98cf0dee0f3f 100644 (file)
@@ -14,6 +14,7 @@
 #include <drm/drm_device.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_managed.h>
 #include <drm/drm_mm.h>
 #include <drm/drm_modeset_lock.h>
 
@@ -71,7 +72,7 @@ struct vc4_perfmon {
 };
 
 struct vc4_dev {
-       struct drm_device *dev;
+       struct drm_device base;
 
        struct vc4_hvs *hvs;
        struct vc4_v3d *v3d;
@@ -218,6 +219,7 @@ struct vc4_dev {
 
        struct drm_modeset_lock ctm_state_lock;
        struct drm_private_obj ctm_manager;
+       struct drm_private_obj hvs_channels;
        struct drm_private_obj load_tracker;
 
        /* List of vc4_debugfs_info_entry for adding to debugfs once
@@ -234,7 +236,7 @@ struct vc4_dev {
 static inline struct vc4_dev *
 to_vc4_dev(struct drm_device *dev)
 {
-       return (struct vc4_dev *)dev->dev_private;
+       return container_of(dev, struct vc4_dev, base);
 }
 
 struct vc4_bo {
@@ -287,7 +289,7 @@ struct vc4_bo {
 static inline struct vc4_bo *
 to_vc4_bo(struct drm_gem_object *bo)
 {
-       return (struct vc4_bo *)bo;
+       return container_of(to_drm_gem_cma_obj(bo), struct vc4_bo, base);
 }
 
 struct vc4_fence {
@@ -300,7 +302,7 @@ struct vc4_fence {
 static inline struct vc4_fence *
 to_vc4_fence(struct dma_fence *fence)
 {
-       return (struct vc4_fence *)fence;
+       return container_of(fence, struct vc4_fence, base);
 }
 
 struct vc4_seqno_cb {
@@ -347,7 +349,7 @@ struct vc4_plane {
 static inline struct vc4_plane *
 to_vc4_plane(struct drm_plane *plane)
 {
-       return (struct vc4_plane *)plane;
+       return container_of(plane, struct vc4_plane, base);
 }
 
 enum vc4_scaling_mode {
@@ -423,7 +425,7 @@ struct vc4_plane_state {
 static inline struct vc4_plane_state *
 to_vc4_plane_state(struct drm_plane_state *state)
 {
-       return (struct vc4_plane_state *)state;
+       return container_of(state, struct vc4_plane_state, base);
 }
 
 enum vc4_encoder_type {
@@ -499,7 +501,7 @@ struct vc4_crtc {
 static inline struct vc4_crtc *
 to_vc4_crtc(struct drm_crtc *crtc)
 {
-       return (struct vc4_crtc *)crtc;
+       return container_of(crtc, struct vc4_crtc, base);
 }
 
 static inline const struct vc4_crtc_data *
@@ -530,6 +532,9 @@ struct vc4_crtc_state {
                unsigned int top;
                unsigned int bottom;
        } margins;
+
+       /* Transitional state below, only valid during atomic commits */
+       bool update_muxing;
 };
 
 #define VC4_HVS_CHANNEL_DISABLED ((unsigned int)-1)
@@ -537,7 +542,7 @@ struct vc4_crtc_state {
 static inline struct vc4_crtc_state *
 to_vc4_crtc_state(struct drm_crtc_state *crtc_state)
 {
-       return (struct vc4_crtc_state *)crtc_state;
+       return container_of(crtc_state, struct vc4_crtc_state, base);
 }
 
 #define V3D_READ(offset) readl(vc4->v3d->regs + offset)
@@ -809,7 +814,6 @@ struct drm_gem_object *vc4_prime_import_sg_table(struct drm_device *dev,
                                                 struct sg_table *sgt);
 void *vc4_prime_vmap(struct drm_gem_object *obj);
 int vc4_bo_cache_init(struct drm_device *dev);
-void vc4_bo_cache_destroy(struct drm_device *dev);
 int vc4_bo_inc_usecnt(struct vc4_bo *bo);
 void vc4_bo_dec_usecnt(struct vc4_bo *bo);
 void vc4_bo_add_to_purgeable_pool(struct vc4_bo *bo);
@@ -874,8 +878,7 @@ extern struct platform_driver vc4_dsi_driver;
 extern const struct dma_fence_ops vc4_fence_ops;
 
 /* vc4_gem.c */
-void vc4_gem_init(struct drm_device *dev);
-void vc4_gem_destroy(struct drm_device *dev);
+int vc4_gem_init(struct drm_device *dev);
 int vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
 int vc4_wait_seqno_ioctl(struct drm_device *dev, void *data,
index 9f01ddd5b932655eadf3849f3262dc2b28277477..b641252939d878ee83527d9774fd91b426ababce 100644 (file)
@@ -314,16 +314,16 @@ vc4_reset_work(struct work_struct *work)
        struct vc4_dev *vc4 =
                container_of(work, struct vc4_dev, hangcheck.reset_work);
 
-       vc4_save_hang_state(vc4->dev);
+       vc4_save_hang_state(&vc4->base);
 
-       vc4_reset(vc4->dev);
+       vc4_reset(&vc4->base);
 }
 
 static void
 vc4_hangcheck_elapsed(struct timer_list *t)
 {
        struct vc4_dev *vc4 = from_timer(vc4, t, hangcheck.timer);
-       struct drm_device *dev = vc4->dev;
+       struct drm_device *dev = &vc4->base;
        uint32_t ct0ca, ct1ca;
        unsigned long irqflags;
        struct vc4_exec_info *bin_exec, *render_exec;
@@ -1000,7 +1000,7 @@ vc4_job_handle_completed(struct vc4_dev *vc4)
                list_del(&exec->head);
 
                spin_unlock_irqrestore(&vc4->job_lock, irqflags);
-               vc4_complete_exec(vc4->dev, exec);
+               vc4_complete_exec(&vc4->base, exec);
                spin_lock_irqsave(&vc4->job_lock, irqflags);
        }
 
@@ -1258,13 +1258,13 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
        return 0;
 
 fail:
-       vc4_complete_exec(vc4->dev, exec);
+       vc4_complete_exec(&vc4->base, exec);
 
        return ret;
 }
 
-void
-vc4_gem_init(struct drm_device *dev)
+static void vc4_gem_destroy(struct drm_device *dev, void *unused);
+int vc4_gem_init(struct drm_device *dev)
 {
        struct vc4_dev *vc4 = to_vc4_dev(dev);
 
@@ -1285,10 +1285,11 @@ vc4_gem_init(struct drm_device *dev)
 
        INIT_LIST_HEAD(&vc4->purgeable.list);
        mutex_init(&vc4->purgeable.lock);
+
+       return drmm_add_action_or_reset(dev, vc4_gem_destroy, NULL);
 }
 
-void
-vc4_gem_destroy(struct drm_device *dev)
+static void vc4_gem_destroy(struct drm_device *dev, void *unused)
 {
        struct vc4_dev *vc4 = to_vc4_dev(dev);
 
index e8f99e29065559a58bfc7be61e48d3239445304f..afc178b0d89f47fb286dc21c134e6013bf5b8fda 100644 (file)
@@ -760,12 +760,54 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 {
 }
 
+#define WIFI_2_4GHz_CH1_MIN_FREQ       2400000000ULL
+#define WIFI_2_4GHz_CH1_MAX_FREQ       2422000000ULL
+
+static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
+                                        struct drm_crtc_state *crtc_state,
+                                        struct drm_connector_state *conn_state)
+{
+       struct drm_display_mode *mode = &crtc_state->adjusted_mode;
+       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+       unsigned long long pixel_rate = mode->clock * 1000;
+       unsigned long long tmds_rate;
+
+       if (vc4_hdmi->variant->unsupported_odd_h_timings &&
+           ((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
+            (mode->hsync_end % 2) || (mode->htotal % 2)))
+               return -EINVAL;
+
+       /*
+        * The 1440p@60 pixel rate is in the same range than the first
+        * WiFi channel (between 2.4GHz and 2.422GHz with 22MHz
+        * bandwidth). Slightly lower the frequency to bring it out of
+        * the WiFi range.
+        */
+       tmds_rate = pixel_rate * 10;
+       if (vc4_hdmi->disable_wifi_frequencies &&
+           (tmds_rate >= WIFI_2_4GHz_CH1_MIN_FREQ &&
+            tmds_rate <= WIFI_2_4GHz_CH1_MAX_FREQ)) {
+               mode->clock = 238560;
+               pixel_rate = mode->clock * 1000;
+       }
+
+       if (pixel_rate > vc4_hdmi->variant->max_pixel_clock)
+               return -EINVAL;
+
+       return 0;
+}
+
 static enum drm_mode_status
 vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
                            const struct drm_display_mode *mode)
 {
        struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 
+       if (vc4_hdmi->variant->unsupported_odd_h_timings &&
+           ((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
+            (mode->hsync_end % 2) || (mode->htotal % 2)))
+               return MODE_H_ILLEGAL;
+
        if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
                return MODE_CLOCK_HIGH;
 
@@ -773,6 +815,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
 }
 
 static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
+       .atomic_check = vc4_hdmi_encoder_atomic_check,
        .mode_valid = vc4_hdmi_encoder_mode_valid,
        .disable = vc4_hdmi_encoder_disable,
        .enable = vc4_hdmi_encoder_enable,
@@ -922,6 +965,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
                                    struct snd_soc_dai *dai)
 {
        struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
+       struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
        struct device *dev = &vc4_hdmi->pdev->dev;
        u32 audio_packet_config, channel_mask;
        u32 channel_map;
@@ -981,6 +1025,8 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
        HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
        vc4_hdmi_set_n_cts(vc4_hdmi);
 
+       vc4_hdmi_set_audio_infoframe(encoder);
+
        return 0;
 }
 
@@ -988,11 +1034,9 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
                                  struct snd_soc_dai *dai)
 {
        struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
-       struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               vc4_hdmi_set_audio_infoframe(encoder);
                vc4_hdmi->audio.streaming = true;
 
                if (vc4_hdmi->variant->phy_rng_enable)
@@ -1076,6 +1120,7 @@ static const struct snd_soc_dapm_route vc4_hdmi_audio_routes[] = {
 };
 
 static const struct snd_soc_component_driver vc4_hdmi_audio_component_drv = {
+       .name                   = "vc4-hdmi-codec-dai-component",
        .controls               = vc4_hdmi_audio_controls,
        .num_controls           = ARRAY_SIZE(vc4_hdmi_audio_controls),
        .dapm_widgets           = vc4_hdmi_audio_widgets,
@@ -1692,6 +1737,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
                vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
        }
 
+       vc4_hdmi->disable_wifi_frequencies =
+               of_property_read_bool(dev->of_node, "wifi-2.4ghz-coexistence");
+
        pm_runtime_enable(dev);
 
        drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
@@ -1815,6 +1863,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = {
                PHY_LANE_2,
                PHY_LANE_CK,
        },
+       .unsupported_odd_h_timings      = true,
 
        .init_resources         = vc5_hdmi_init_resources,
        .csc_setup              = vc5_hdmi_csc_setup,
@@ -1840,6 +1889,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {
                PHY_LANE_CK,
                PHY_LANE_2,
        },
+       .unsupported_odd_h_timings      = true,
 
        .init_resources         = vc5_hdmi_init_resources,
        .csc_setup              = vc5_hdmi_csc_setup,
index 63c6f8bddf1deb27d3ff17d270d276df20ebb2f8..0526a9cf608a3b5fb242de70353a91199ad1b40f 100644 (file)
@@ -62,6 +62,9 @@ struct vc4_hdmi_variant {
         */
        enum vc4_hdmi_phy_channel phy_lane_mapping[4];
 
+       /* The BCM2711 cannot deal with odd horizontal pixel timings */
+       bool unsupported_odd_h_timings;
+
        /* Callback to get the resources (memory region, interrupts,
         * clocks, etc) for that variant.
         */
@@ -139,6 +142,14 @@ struct vc4_hdmi {
        int hpd_gpio;
        bool hpd_active_low;
 
+       /*
+        * On some systems (like the RPi4), some modes are in the same
+        * frequency range than the WiFi channels (1440p@60Hz for
+        * example). Should we take evasive actions because that system
+        * has a wifi adapter?
+        */
+       bool disable_wifi_frequencies;
+
        struct cec_adapter *cec_adap;
        struct cec_msg cec_rx_msg;
        bool cec_tx_ok;
index 4d0a833366cee10eb6fca2644433738b78985eeb..b72b2bd05a815c7b31064ac8ea807760c9e5a350 100644 (file)
@@ -560,7 +560,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct drm_device *drm = dev_get_drvdata(master);
-       struct vc4_dev *vc4 = drm->dev_private;
+       struct vc4_dev *vc4 = to_vc4_dev(drm);
        struct vc4_hvs *hvs = NULL;
        int ret;
        u32 dispctrl;
@@ -679,7 +679,7 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master,
                           void *data)
 {
        struct drm_device *drm = dev_get_drvdata(master);
-       struct vc4_dev *vc4 = drm->dev_private;
+       struct vc4_dev *vc4 = to_vc4_dev(drm);
        struct vc4_hvs *hvs = vc4->hvs;
 
        if (drm_mm_node_allocated(&vc4->hvs->mitchell_netravali_filter))
index 149825ff5df8d41f2a815c735cb087b41aea536f..ba310c0ab5f69e6b779e5a7058ef6741b8476d2b 100644 (file)
@@ -24,6 +24,8 @@
 #include "vc4_drv.h"
 #include "vc4_regs.h"
 
+#define HVS_NUM_CHANNELS 3
+
 struct vc4_ctm_state {
        struct drm_private_state base;
        struct drm_color_ctm *ctm;
@@ -35,6 +37,17 @@ static struct vc4_ctm_state *to_vc4_ctm_state(struct drm_private_state *priv)
        return container_of(priv, struct vc4_ctm_state, base);
 }
 
+struct vc4_hvs_state {
+       struct drm_private_state base;
+       unsigned int unassigned_channels;
+};
+
+static struct vc4_hvs_state *
+to_vc4_hvs_state(struct drm_private_state *priv)
+{
+       return container_of(priv, struct vc4_hvs_state, base);
+}
+
 struct vc4_load_tracker_state {
        struct drm_private_state base;
        u64 hvs_load;
@@ -51,7 +64,7 @@ static struct vc4_ctm_state *vc4_get_ctm_state(struct drm_atomic_state *state,
                                               struct drm_private_obj *manager)
 {
        struct drm_device *dev = state->dev;
-       struct vc4_dev *vc4 = dev->dev_private;
+       struct vc4_dev *vc4 = to_vc4_dev(dev);
        struct drm_private_state *priv_state;
        int ret;
 
@@ -93,6 +106,29 @@ static const struct drm_private_state_funcs vc4_ctm_state_funcs = {
        .atomic_destroy_state = vc4_ctm_destroy_state,
 };
 
+static void vc4_ctm_obj_fini(struct drm_device *dev, void *unused)
+{
+       struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+       drm_atomic_private_obj_fini(&vc4->ctm_manager);
+}
+
+static int vc4_ctm_obj_init(struct vc4_dev *vc4)
+{
+       struct vc4_ctm_state *ctm_state;
+
+       drm_modeset_lock_init(&vc4->ctm_state_lock);
+
+       ctm_state = kzalloc(sizeof(*ctm_state), GFP_KERNEL);
+       if (!ctm_state)
+               return -ENOMEM;
+
+       drm_atomic_private_obj_init(&vc4->base, &vc4->ctm_manager, &ctm_state->base,
+                                   &vc4_ctm_state_funcs);
+
+       return drmm_add_action_or_reset(&vc4->base, vc4_ctm_obj_fini, NULL);
+}
+
 /* Converts a DRM S31.32 value to the HW S0.9 format. */
 static u16 vc4_ctm_s31_32_to_s0_9(u64 in)
 {
@@ -146,6 +182,19 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state)
                  VC4_SET_FIELD(ctm_state->fifo, SCALER_OLEDOFFS_DISPFIFO));
 }
 
+static struct vc4_hvs_state *
+vc4_hvs_get_global_state(struct drm_atomic_state *state)
+{
+       struct vc4_dev *vc4 = to_vc4_dev(state->dev);
+       struct drm_private_state *priv_state;
+
+       priv_state = drm_atomic_get_private_obj_state(state, &vc4->hvs_channels);
+       if (IS_ERR(priv_state))
+               return ERR_CAST(priv_state);
+
+       return to_vc4_hvs_state(priv_state);
+}
+
 static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4,
                                     struct drm_atomic_state *state)
 {
@@ -190,10 +239,7 @@ static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4,
 {
        struct drm_crtc_state *crtc_state;
        struct drm_crtc *crtc;
-       unsigned char dsp2_mux = 0;
-       unsigned char dsp3_mux = 3;
-       unsigned char dsp4_mux = 3;
-       unsigned char dsp5_mux = 3;
+       unsigned char mux;
        unsigned int i;
        u32 reg;
 
@@ -201,50 +247,59 @@ static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4,
                struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
                struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 
-               if (!crtc_state->active)
+               if (!vc4_state->update_muxing)
                        continue;
 
                switch (vc4_crtc->data->hvs_output) {
                case 2:
-                       dsp2_mux = (vc4_state->assigned_channel == 2) ? 0 : 1;
+                       mux = (vc4_state->assigned_channel == 2) ? 0 : 1;
+                       reg = HVS_READ(SCALER_DISPECTRL);
+                       HVS_WRITE(SCALER_DISPECTRL,
+                                 (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) |
+                                 VC4_SET_FIELD(mux, SCALER_DISPECTRL_DSP2_MUX));
                        break;
 
                case 3:
-                       dsp3_mux = vc4_state->assigned_channel;
+                       if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED)
+                               mux = 3;
+                       else
+                               mux = vc4_state->assigned_channel;
+
+                       reg = HVS_READ(SCALER_DISPCTRL);
+                       HVS_WRITE(SCALER_DISPCTRL,
+                                 (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) |
+                                 VC4_SET_FIELD(mux, SCALER_DISPCTRL_DSP3_MUX));
                        break;
 
                case 4:
-                       dsp4_mux = vc4_state->assigned_channel;
+                       if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED)
+                               mux = 3;
+                       else
+                               mux = vc4_state->assigned_channel;
+
+                       reg = HVS_READ(SCALER_DISPEOLN);
+                       HVS_WRITE(SCALER_DISPEOLN,
+                                 (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) |
+                                 VC4_SET_FIELD(mux, SCALER_DISPEOLN_DSP4_MUX));
+
                        break;
 
                case 5:
-                       dsp5_mux = vc4_state->assigned_channel;
+                       if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED)
+                               mux = 3;
+                       else
+                               mux = vc4_state->assigned_channel;
+
+                       reg = HVS_READ(SCALER_DISPDITHER);
+                       HVS_WRITE(SCALER_DISPDITHER,
+                                 (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) |
+                                 VC4_SET_FIELD(mux, SCALER_DISPDITHER_DSP5_MUX));
                        break;
 
                default:
                        break;
                }
        }
-
-       reg = HVS_READ(SCALER_DISPECTRL);
-       HVS_WRITE(SCALER_DISPECTRL,
-                 (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) |
-                 VC4_SET_FIELD(dsp2_mux, SCALER_DISPECTRL_DSP2_MUX));
-
-       reg = HVS_READ(SCALER_DISPCTRL);
-       HVS_WRITE(SCALER_DISPCTRL,
-                 (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) |
-                 VC4_SET_FIELD(dsp3_mux, SCALER_DISPCTRL_DSP3_MUX));
-
-       reg = HVS_READ(SCALER_DISPEOLN);
-       HVS_WRITE(SCALER_DISPEOLN,
-                 (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) |
-                 VC4_SET_FIELD(dsp4_mux, SCALER_DISPEOLN_DSP4_MUX));
-
-       reg = HVS_READ(SCALER_DISPDITHER);
-       HVS_WRITE(SCALER_DISPDITHER,
-                 (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) |
-                 VC4_SET_FIELD(dsp5_mux, SCALER_DISPDITHER_DSP5_MUX));
 }
 
 static void
@@ -609,50 +664,148 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = {
        .atomic_destroy_state = vc4_load_tracker_destroy_state,
 };
 
-#define NUM_OUTPUTS  6
-#define NUM_CHANNELS 3
+static void vc4_load_tracker_obj_fini(struct drm_device *dev, void *unused)
+{
+       struct vc4_dev *vc4 = to_vc4_dev(dev);
 
-static int
-vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
+       if (!vc4->load_tracker_available)
+               return;
+
+       drm_atomic_private_obj_fini(&vc4->load_tracker);
+}
+
+static int vc4_load_tracker_obj_init(struct vc4_dev *vc4)
 {
-       unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0);
-       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
-       struct drm_crtc *crtc;
-       int i, ret;
+       struct vc4_load_tracker_state *load_state;
 
-       /*
-        * Since the HVS FIFOs are shared across all the pixelvalves and
-        * the TXP (and thus all the CRTCs), we need to pull the current
-        * state of all the enabled CRTCs so that an update to a single
-        * CRTC still keeps the previous FIFOs enabled and assigned to
-        * the same CRTCs, instead of evaluating only the CRTC being
-        * modified.
-        */
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               struct drm_crtc_state *crtc_state;
+       if (!vc4->load_tracker_available)
+               return 0;
 
-               if (!crtc->state->enable)
-                       continue;
+       load_state = kzalloc(sizeof(*load_state), GFP_KERNEL);
+       if (!load_state)
+               return -ENOMEM;
 
-               crtc_state = drm_atomic_get_crtc_state(state, crtc);
-               if (IS_ERR(crtc_state))
-                       return PTR_ERR(crtc_state);
-       }
+       drm_atomic_private_obj_init(&vc4->base, &vc4->load_tracker,
+                                   &load_state->base,
+                                   &vc4_load_tracker_state_funcs);
+
+       return drmm_add_action_or_reset(&vc4->base, vc4_load_tracker_obj_fini, NULL);
+}
+
+static struct drm_private_state *
+vc4_hvs_channels_duplicate_state(struct drm_private_obj *obj)
+{
+       struct vc4_hvs_state *old_state = to_vc4_hvs_state(obj->state);
+       struct vc4_hvs_state *state;
+
+       state = kzalloc(sizeof(*state), GFP_KERNEL);
+       if (!state)
+               return NULL;
+
+       __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base);
+
+       state->unassigned_channels = old_state->unassigned_channels;
+
+       return &state->base;
+}
+
+static void vc4_hvs_channels_destroy_state(struct drm_private_obj *obj,
+                                          struct drm_private_state *state)
+{
+       struct vc4_hvs_state *hvs_state = to_vc4_hvs_state(state);
+
+       kfree(hvs_state);
+}
+
+static const struct drm_private_state_funcs vc4_hvs_state_funcs = {
+       .atomic_duplicate_state = vc4_hvs_channels_duplicate_state,
+       .atomic_destroy_state = vc4_hvs_channels_destroy_state,
+};
+
+static void vc4_hvs_channels_obj_fini(struct drm_device *dev, void *unused)
+{
+       struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+       drm_atomic_private_obj_fini(&vc4->hvs_channels);
+}
+
+static int vc4_hvs_channels_obj_init(struct vc4_dev *vc4)
+{
+       struct vc4_hvs_state *state;
+
+       state = kzalloc(sizeof(*state), GFP_KERNEL);
+       if (!state)
+               return -ENOMEM;
+
+       state->unassigned_channels = GENMASK(HVS_NUM_CHANNELS - 1, 0);
+       drm_atomic_private_obj_init(&vc4->base, &vc4->hvs_channels,
+                                   &state->base,
+                                   &vc4_hvs_state_funcs);
+
+       return drmm_add_action_or_reset(&vc4->base, vc4_hvs_channels_obj_fini, NULL);
+}
+
+/*
+ * The BCM2711 HVS has up to 7 outputs connected to the pixelvalves and
+ * the TXP (and therefore all the CRTCs found on that platform).
+ *
+ * The naive (and our initial) implementation would just iterate over
+ * all the active CRTCs, try to find a suitable FIFO, and then remove it
+ * from the pool of available FIFOs. However, there are a few corner
+ * cases that need to be considered:
+ *
+ * - When running in a dual-display setup (so with two CRTCs involved),
+ *   we can update the state of a single CRTC (for example by changing
+ *   its mode using xrandr under X11) without affecting the other. In
+ *   this case, the other CRTC wouldn't be in the state at all, so we
+ *   need to consider all the running CRTCs in the DRM device to assign
+ *   a FIFO, not just the one in the state.
+ *
+ * - To fix the above, we can't use drm_atomic_get_crtc_state on all
+ *   enabled CRTCs to pull their CRTC state into the global state, since
+ *   a page flip would start considering their vblank to complete. Since
+ *   we don't have a guarantee that they are actually active, that
+ *   vblank might never happen, and shouldn't even be considered if we
+ *   want to do a page flip on a single CRTC. That can be tested by
+ *   doing a modetest -v first on HDMI1 and then on HDMI0.
+ *
+ * - Since we need the pixelvalve to be disabled and enabled back when
+ *   the FIFO is changed, we should keep the FIFO assigned for as long
+ *   as the CRTC is enabled, only considering it free again once that
+ *   CRTC has been disabled. This can be tested by booting X11 on a
+ *   single display, and changing the resolution down and then back up.
+ */
+static int vc4_pv_muxing_atomic_check(struct drm_device *dev,
+                                     struct drm_atomic_state *state)
+{
+       struct vc4_hvs_state *hvs_new_state;
+       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
+       struct drm_crtc *crtc;
+       unsigned int i;
+
+       hvs_new_state = vc4_hvs_get_global_state(state);
+       if (!hvs_new_state)
+               return -EINVAL;
 
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+               struct vc4_crtc_state *old_vc4_crtc_state =
+                       to_vc4_crtc_state(old_crtc_state);
                struct vc4_crtc_state *new_vc4_crtc_state =
                        to_vc4_crtc_state(new_crtc_state);
                struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
                unsigned int matching_channels;
 
-               if (old_crtc_state->enable && !new_crtc_state->enable)
-                       new_vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED;
-
-               if (!new_crtc_state->enable)
+               /* Nothing to do here, let's skip it */
+               if (old_crtc_state->enable == new_crtc_state->enable)
                        continue;
 
-               if (new_vc4_crtc_state->assigned_channel != VC4_HVS_CHANNEL_DISABLED) {
-                       unassigned_channels &= ~BIT(new_vc4_crtc_state->assigned_channel);
+               /* Muxing will need to be modified, mark it as such */
+               new_vc4_crtc_state->update_muxing = true;
+
+               /* If we're disabling our CRTC, we put back our channel */
+               if (!new_crtc_state->enable) {
+                       hvs_new_state->unassigned_channels |= BIT(old_vc4_crtc_state->assigned_channel);
+                       new_vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED;
                        continue;
                }
 
@@ -680,17 +833,29 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
                 * the future, we will need to have something smarter,
                 * but it works so far.
                 */
-               matching_channels = unassigned_channels & vc4_crtc->data->hvs_available_channels;
+               matching_channels = hvs_new_state->unassigned_channels & vc4_crtc->data->hvs_available_channels;
                if (matching_channels) {
                        unsigned int channel = ffs(matching_channels) - 1;
 
                        new_vc4_crtc_state->assigned_channel = channel;
-                       unassigned_channels &= ~BIT(channel);
+                       hvs_new_state->unassigned_channels &= ~BIT(channel);
                } else {
                        return -EINVAL;
                }
        }
 
+       return 0;
+}
+
+static int
+vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
+{
+       int ret;
+
+       ret = vc4_pv_muxing_atomic_check(dev, state);
+       if (ret)
+               return ret;
+
        ret = vc4_ctm_atomic_check(dev, state);
        if (ret < 0)
                return ret;
@@ -711,8 +876,6 @@ static const struct drm_mode_config_funcs vc4_mode_funcs = {
 int vc4_kms_load(struct drm_device *dev)
 {
        struct vc4_dev *vc4 = to_vc4_dev(dev);
-       struct vc4_ctm_state *ctm_state;
-       struct vc4_load_tracker_state *load_state;
        bool is_vc5 = of_device_is_compatible(dev->dev->of_node,
                                              "brcm,bcm2711-vc5");
        int ret;
@@ -751,26 +914,17 @@ int vc4_kms_load(struct drm_device *dev)
        dev->mode_config.async_page_flip = true;
        dev->mode_config.allow_fb_modifiers = true;
 
-       drm_modeset_lock_init(&vc4->ctm_state_lock);
-
-       ctm_state = kzalloc(sizeof(*ctm_state), GFP_KERNEL);
-       if (!ctm_state)
-               return -ENOMEM;
-
-       drm_atomic_private_obj_init(dev, &vc4->ctm_manager, &ctm_state->base,
-                                   &vc4_ctm_state_funcs);
+       ret = vc4_ctm_obj_init(vc4);
+       if (ret)
+               return ret;
 
-       if (vc4->load_tracker_available) {
-               load_state = kzalloc(sizeof(*load_state), GFP_KERNEL);
-               if (!load_state) {
-                       drm_atomic_private_obj_fini(&vc4->ctm_manager);
-                       return -ENOMEM;
-               }
+       ret = vc4_load_tracker_obj_init(vc4);
+       if (ret)
+               return ret;
 
-               drm_atomic_private_obj_init(dev, &vc4->load_tracker,
-                                           &load_state->base,
-                                           &vc4_load_tracker_state_funcs);
-       }
+       ret = vc4_hvs_channels_obj_init(vc4);
+       if (ret)
+               return ret;
 
        drm_mode_config_reset(dev);
 
index f7ab979721b32bc3ad7cacbd9648da079676b606..65d0dac69b0bc3cd2bb50c4e321b137aa3190dd1 100644 (file)
@@ -168,7 +168,7 @@ static void vc4_v3d_init_hw(struct drm_device *dev)
 
 int vc4_v3d_get_bin_slot(struct vc4_dev *vc4)
 {
-       struct drm_device *dev = vc4->dev;
+       struct drm_device *dev = &vc4->base;
        unsigned long irqflags;
        int slot;
        uint64_t seqno = 0;
@@ -246,7 +246,7 @@ static int bin_bo_alloc(struct vc4_dev *vc4)
        INIT_LIST_HEAD(&list);
 
        while (true) {
-               struct vc4_bo *bo = vc4_bo_create(vc4->dev, size, true,
+               struct vc4_bo *bo = vc4_bo_create(&vc4->base, size, true,
                                                  VC4_BO_TYPE_BIN);
 
                if (IS_ERR(bo)) {
@@ -361,7 +361,7 @@ static int vc4_v3d_runtime_suspend(struct device *dev)
        struct vc4_v3d *v3d = dev_get_drvdata(dev);
        struct vc4_dev *vc4 = v3d->vc4;
 
-       vc4_irq_uninstall(vc4->dev);
+       vc4_irq_uninstall(&vc4->base);
 
        clk_disable_unprepare(v3d->clk);
 
@@ -378,11 +378,11 @@ static int vc4_v3d_runtime_resume(struct device *dev)
        if (ret != 0)
                return ret;
 
-       vc4_v3d_init_hw(vc4->dev);
+       vc4_v3d_init_hw(&vc4->base);
 
        /* We disabled the IRQ as part of vc4_irq_uninstall in suspend. */
-       enable_irq(vc4->dev->irq);
-       vc4_irq_postinstall(vc4->dev);
+       enable_irq(vc4->base.irq);
+       vc4_irq_postinstall(&vc4->base);
 
        return 0;
 }
index b3dae9ec1a38bf18c16a480ee5ded8cb16d0dfa1..d166ee262ce4390f0987d07e589aebe59f25bd5e 100644 (file)
@@ -133,73 +133,6 @@ enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat)
 }
 EXPORT_SYMBOL_GPL(ipu_pixelformat_to_colorspace);
 
-bool ipu_pixelformat_is_planar(u32 pixelformat)
-{
-       switch (pixelformat) {
-       case V4L2_PIX_FMT_YUV420:
-       case V4L2_PIX_FMT_YVU420:
-       case V4L2_PIX_FMT_YUV422P:
-       case V4L2_PIX_FMT_NV12:
-       case V4L2_PIX_FMT_NV21:
-       case V4L2_PIX_FMT_NV16:
-       case V4L2_PIX_FMT_NV61:
-               return true;
-       }
-
-       return false;
-}
-EXPORT_SYMBOL_GPL(ipu_pixelformat_is_planar);
-
-enum ipu_color_space ipu_mbus_code_to_colorspace(u32 mbus_code)
-{
-       switch (mbus_code & 0xf000) {
-       case 0x1000:
-               return IPUV3_COLORSPACE_RGB;
-       case 0x2000:
-               return IPUV3_COLORSPACE_YUV;
-       default:
-               return IPUV3_COLORSPACE_UNKNOWN;
-       }
-}
-EXPORT_SYMBOL_GPL(ipu_mbus_code_to_colorspace);
-
-int ipu_stride_to_bytes(u32 pixel_stride, u32 pixelformat)
-{
-       switch (pixelformat) {
-       case V4L2_PIX_FMT_YUV420:
-       case V4L2_PIX_FMT_YVU420:
-       case V4L2_PIX_FMT_YUV422P:
-       case V4L2_PIX_FMT_NV12:
-       case V4L2_PIX_FMT_NV21:
-       case V4L2_PIX_FMT_NV16:
-       case V4L2_PIX_FMT_NV61:
-               /*
-                * for the planar YUV formats, the stride passed to
-                * cpmem must be the stride in bytes of the Y plane.
-                * And all the planar YUV formats have an 8-bit
-                * Y component.
-                */
-               return (8 * pixel_stride) >> 3;
-       case V4L2_PIX_FMT_RGB565:
-       case V4L2_PIX_FMT_YUYV:
-       case V4L2_PIX_FMT_UYVY:
-               return (16 * pixel_stride) >> 3;
-       case V4L2_PIX_FMT_BGR24:
-       case V4L2_PIX_FMT_RGB24:
-               return (24 * pixel_stride) >> 3;
-       case V4L2_PIX_FMT_BGR32:
-       case V4L2_PIX_FMT_RGB32:
-       case V4L2_PIX_FMT_XBGR32:
-       case V4L2_PIX_FMT_XRGB32:
-               return (32 * pixel_stride) >> 3;
-       default:
-               break;
-       }
-
-       return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(ipu_stride_to_bytes);
-
 int ipu_degrees_to_rot_mode(enum ipu_rotate_mode *mode, int degrees,
                            bool hflip, bool vflip)
 {
index a50ba4a4a1d71be06763f9ec0d23300b303d10d3..b88f889b3932ea3bb6abe8c3db1d3497fe4b6aa1 100644 (file)
 #define CP_2WHEEL_MOUSE_HACK           0x02
 #define CP_2WHEEL_MOUSE_HACK_ON                0x04
 
+#define VA_INVAL_LOGICAL_BOUNDARY      0x08
+
 /*
  * Some USB barcode readers from cypress have usage min and usage max in
  * the wrong order
  */
-static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+static __u8 *cp_rdesc_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
 {
-       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
        unsigned int i;
 
-       if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
-               return rdesc;
-
        if (*rsize < 4)
                return rdesc;
 
@@ -48,6 +46,40 @@ static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
        return rdesc;
 }
 
+static __u8 *va_logical_boundary_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
+{
+       /*
+        * Varmilo VA104M (with VID Cypress and device ID 07B1) incorrectly
+        * reports Logical Minimum of its Consumer Control device as 572
+        * (0x02 0x3c). Fix this by setting its Logical Minimum to zero.
+        */
+       if (*rsize == 25 &&
+                       rdesc[0] == 0x05 && rdesc[1] == 0x0c &&
+                       rdesc[2] == 0x09 && rdesc[3] == 0x01 &&
+                       rdesc[6] == 0x19 && rdesc[7] == 0x00 &&
+                       rdesc[11] == 0x16 && rdesc[12] == 0x3c && rdesc[13] == 0x02) {
+               hid_info(hdev,
+                        "fixing up varmilo VA104M consumer control report descriptor\n");
+               rdesc[12] = 0x00;
+               rdesc[13] = 0x00;
+       }
+       return rdesc;
+}
+
+static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
+{
+       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+       if (quirks & CP_RDESC_SWAPPED_MIN_MAX)
+               rdesc = cp_rdesc_fixup(hdev, rdesc, rsize);
+       if (quirks & VA_INVAL_LOGICAL_BOUNDARY)
+               rdesc = va_logical_boundary_fixup(hdev, rdesc, rsize);
+
+       return rdesc;
+}
+
 static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
@@ -128,6 +160,8 @@ static const struct hid_device_id cp_devices[] = {
                .driver_data = CP_RDESC_SWAPPED_MIN_MAX },
        { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE),
                .driver_data = CP_2WHEEL_MOUSE_HACK },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_VARMILO_VA104M_07B1),
+               .driver_data = VA_INVAL_LOGICAL_BOUNDARY },
        { }
 };
 MODULE_DEVICE_TABLE(hid, cp_devices);
index d69842f79fc665c53243331c3efc9e458233ca65..f170feaac40baea80173f96c939f13a75843d78e 100644 (file)
 #define USB_DEVICE_ID_CYPRESS_BARCODE_4        0xed81
 #define USB_DEVICE_ID_CYPRESS_TRUETOUCH        0xc001
 
+#define USB_DEVICE_ID_CYPRESS_VARMILO_VA104M_07B1   0X07b1
+
 #define USB_VENDOR_ID_DATA_MODUL       0x7374
 #define USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH  0x1201
 
 #define USB_VENDOR_ID_FRUCTEL  0x25B6
 #define USB_DEVICE_ID_GAMETEL_MT_MODE  0x0002
 
+#define USB_VENDOR_ID_GAMEVICE 0x27F8
+#define USB_DEVICE_ID_GAMEVICE_GV186   0x0BBE
+#define USB_DEVICE_ID_GAMEVICE_KISHI   0x0BBF
+
 #define USB_VENDOR_ID_GAMERON          0x0810
 #define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
 #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002
 #define USB_DEVICE_ID_PENPOWER         0x00f4
 
 #define USB_VENDOR_ID_GREENASIA                0x0e8f
+#define USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR 0x3010
 #define USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD        0x3013
 
 #define USB_VENDOR_ID_GRETAGMACBETH    0x0971
 #define USB_VENDOR_ID_LOGITECH         0x046d
 #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
 #define USB_DEVICE_ID_LOGITECH_T651    0xb00c
+#define USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD 0xb309
 #define USB_DEVICE_ID_LOGITECH_C007    0xc007
 #define USB_DEVICE_ID_LOGITECH_C077    0xc077
 #define USB_DEVICE_ID_LOGITECH_RECEIVER        0xc101
 
 #define USB_VENDOR_ID_UGTIZER                  0x2179
 #define USB_DEVICE_ID_UGTIZER_TABLET_GP0610    0x0053
+#define USB_DEVICE_ID_UGTIZER_TABLET_GT5040    0x0077
 
 #define USB_VENDOR_ID_VIEWSONIC                        0x0543
 #define USB_DEVICE_ID_VIEWSONIC_PD1011         0xe621
index 9770db624bfafca5c176075e09030cee41f0341c..4dca1139245934a2525af7bb51bdd9003475785a 100644 (file)
@@ -319,6 +319,9 @@ static const struct hid_device_id hid_battery_quirks[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK,
                USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD),
          HID_BATTERY_QUIRK_IGNORE },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
+               USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD),
+         HID_BATTERY_QUIRK_IGNORE },
        {}
 };
 
index 044a93f3c11786078951cf374b01a61e8bf4e7c1..742c052b0110af4b2b1666d179dd27b6747b02f5 100644 (file)
 
 #include "hid-ids.h"
 
+#define QUIRK_TOUCHPAD_ON_OFF_REPORT           BIT(0)
+
+static __u8 *ite_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize)
+{
+       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+       if (quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) {
+               if (*rsize == 188 && rdesc[162] == 0x81 && rdesc[163] == 0x02) {
+                       hid_info(hdev, "Fixing up ITE keyboard report descriptor\n");
+                       rdesc[163] = HID_MAIN_ITEM_RELATIVE;
+               }
+       }
+
+       return rdesc;
+}
+
+static int ite_input_mapping(struct hid_device *hdev,
+               struct hid_input *hi, struct hid_field *field,
+               struct hid_usage *usage, unsigned long **bit,
+               int *max)
+{
+
+       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+       if ((quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) &&
+           (usage->hid & HID_USAGE_PAGE) == 0x00880000) {
+               if (usage->hid == 0x00880078) {
+                       /* Touchpad on, userspace expects F22 for this */
+                       hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F22);
+                       return 1;
+               }
+               if (usage->hid == 0x00880079) {
+                       /* Touchpad off, userspace expects F23 for this */
+                       hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F23);
+                       return 1;
+               }
+               return -1;
+       }
+
+       return 0;
+}
+
 static int ite_event(struct hid_device *hdev, struct hid_field *field,
                     struct hid_usage *usage, __s32 value)
 {
@@ -37,13 +79,27 @@ static int ite_event(struct hid_device *hdev, struct hid_field *field,
        return 0;
 }
 
+static int ite_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       int ret;
+
+       hid_set_drvdata(hdev, (void *)id->driver_data);
+
+       ret = hid_open_report(hdev);
+       if (ret)
+               return ret;
+
+       return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+}
+
 static const struct hid_device_id ite_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
        { HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
        /* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
        { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
                     USB_VENDOR_ID_SYNAPTICS,
-                    USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) },
+                    USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012),
+         .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
        /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */
        { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
                     USB_VENDOR_ID_SYNAPTICS,
@@ -55,6 +111,9 @@ MODULE_DEVICE_TABLE(hid, ite_devices);
 static struct hid_driver ite_driver = {
        .name = "itetech",
        .id_table = ite_devices,
+       .probe = ite_probe,
+       .report_fixup = ite_report_fixup,
+       .input_mapping = ite_input_mapping,
        .event = ite_event,
 };
 module_hid_driver(ite_driver);
index 72fb6e54a50a0197b1f8e975ac87040e62c439a6..1ffcfc9a1e033b9015a2c88ce72b2b5710e4ee49 100644 (file)
@@ -328,7 +328,7 @@ static const char mse_bluetooth_descriptor[] = {
        0x25, 0x01,             /*      LOGICAL_MAX (1)                 */
        0x75, 0x01,             /*      REPORT_SIZE (1)                 */
        0x95, 0x04,             /*      REPORT_COUNT (4)                */
-       0x81, 0x06,             /*      INPUT                           */
+       0x81, 0x02,             /*      INPUT (Data,Var,Abs)            */
        0xC0,                   /*    END_COLLECTION                    */
        0xC0,                   /*  END_COLLECTION                      */
 };
@@ -866,11 +866,24 @@ static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev,
        schedule_work(&djrcv_dev->work);
 }
 
+/*
+ * Some quad/bluetooth keyboards have a builtin touchpad in this case we see
+ * only 1 paired device with a device_type of REPORT_TYPE_KEYBOARD. For the
+ * touchpad to work we must also forward mouse input reports to the dj_hiddev
+ * created for the keyboard (instead of forwarding them to a second paired
+ * device with a device_type of REPORT_TYPE_MOUSE as we normally would).
+ */
+static const u16 kbd_builtin_touchpad_ids[] = {
+       0xb309, /* Dinovo Edge */
+       0xb30c, /* Dinovo Mini */
+};
+
 static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev,
                                            struct hidpp_event *hidpp_report,
                                            struct dj_workitem *workitem)
 {
        struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
+       int i, id;
 
        workitem->type = WORKITEM_TYPE_PAIRED;
        workitem->device_type = hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] &
@@ -882,6 +895,13 @@ static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev,
                workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA |
                                               POWER_KEYS | MEDIA_CENTER |
                                               HIDPP;
+               id = (workitem->quad_id_msb << 8) | workitem->quad_id_lsb;
+               for (i = 0; i < ARRAY_SIZE(kbd_builtin_touchpad_ids); i++) {
+                       if (id == kbd_builtin_touchpad_ids[i]) {
+                               workitem->reports_supported |= STD_MOUSE;
+                               break;
+                       }
+               }
                break;
        case REPORT_TYPE_MOUSE:
                workitem->reports_supported |= STD_MOUSE | HIDPP;
index b8b53dc95e86b7b0f3ad96ae02b1cd5a159d8eff..0ca7231195473e3a2c8e29ea31d1e70e9e1579e4 100644 (file)
@@ -93,6 +93,8 @@ MODULE_PARM_DESC(disable_tap_to_click,
 #define HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS  BIT(3)
 #define HIDPP_CAPABILITY_BATTERY_VOLTAGE       BIT(4)
 
+#define lg_map_key_clear(c)  hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
+
 /*
  * There are two hidpp protocols in use, the first version hidpp10 is known
  * as register access protocol or RAP, the second version hidpp20 is known as
@@ -2950,6 +2952,26 @@ static int g920_get_config(struct hidpp_device *hidpp,
        return g920_ff_set_autocenter(hidpp, data);
 }
 
+/* -------------------------------------------------------------------------- */
+/* Logitech Dinovo Mini keyboard with builtin touchpad                        */
+/* -------------------------------------------------------------------------- */
+#define DINOVO_MINI_PRODUCT_ID         0xb30c
+
+static int lg_dinovo_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
+               return 0;
+
+       switch (usage->hid & HID_USAGE) {
+       case 0x00d: lg_map_key_clear(KEY_MEDIA);        break;
+       default:
+               return 0;
+       }
+       return 1;
+}
+
 /* -------------------------------------------------------------------------- */
 /* HID++1.0 devices which use HID++ reports for their wheels                  */
 /* -------------------------------------------------------------------------- */
@@ -3185,6 +3207,9 @@ static int hidpp_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        field->application != HID_GD_MOUSE)
                return m560_input_mapping(hdev, hi, field, usage, bit, max);
 
+       if (hdev->product == DINOVO_MINI_PRODUCT_ID)
+               return lg_dinovo_input_mapping(hdev, hi, field, usage, bit, max);
+
        return 0;
 }
 
@@ -3947,6 +3972,7 @@ static const struct hid_device_id hidpp_devices[] = {
          LDJ_DEVICE(0x405e), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
        { /* Mouse Logitech MX Anywhere 2 */
          LDJ_DEVICE(0x404a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
+       { LDJ_DEVICE(0x4072), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
        { LDJ_DEVICE(0xb013), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
        { LDJ_DEVICE(0xb018), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
        { LDJ_DEVICE(0xb01f), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
@@ -3971,6 +3997,9 @@ static const struct hid_device_id hidpp_devices[] = {
        { /* Keyboard MX5000 (Bluetooth-receiver in HID proxy mode) */
          LDJ_DEVICE(0xb305),
          .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
+       { /* Dinovo Edge (Bluetooth-receiver in HID proxy mode) */
+         LDJ_DEVICE(0xb309),
+         .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
        { /* Keyboard MX5500 (Bluetooth-receiver in HID proxy mode) */
          LDJ_DEVICE(0xb30b),
          .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
@@ -4013,6 +4042,9 @@ static const struct hid_device_id hidpp_devices[] = {
        { /* MX5000 keyboard over Bluetooth */
          HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb305),
          .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
+       { /* Dinovo Edge keyboard over Bluetooth */
+         HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb309),
+         .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
        { /* MX5500 keyboard over Bluetooth */
          HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b),
          .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
index 0d27ccb55dd93d6e2d3c4cfe8104ae7aa07780cc..4211b9839209b147b3c0fb44a7944f1f768ffc1d 100644 (file)
@@ -49,6 +49,36 @@ enum {
        MCP2221_ALT_F_NOT_GPIOD = 0xEF,
 };
 
+/* MCP GPIO direction encoding */
+enum {
+       MCP2221_DIR_OUT = 0x00,
+       MCP2221_DIR_IN = 0x01,
+};
+
+#define MCP_NGPIO      4
+
+/* MCP GPIO set command layout */
+struct mcp_set_gpio {
+       u8 cmd;
+       u8 dummy;
+       struct {
+               u8 change_value;
+               u8 value;
+               u8 change_direction;
+               u8 direction;
+       } gpio[MCP_NGPIO];
+} __packed;
+
+/* MCP GPIO get command layout */
+struct mcp_get_gpio {
+       u8 cmd;
+       u8 dummy;
+       struct {
+               u8 direction;
+               u8 value;
+       } gpio[MCP_NGPIO];
+} __packed;
+
 /*
  * There is no way to distinguish responses. Therefore next command
  * is sent only after response to previous has been received. Mutex
@@ -542,7 +572,7 @@ static int mcp_gpio_get(struct gpio_chip *gc,
 
        mcp->txbuf[0] = MCP2221_GPIO_GET;
 
-       mcp->gp_idx = (offset + 1) * 2;
+       mcp->gp_idx = offsetof(struct mcp_get_gpio, gpio[offset].value);
 
        mutex_lock(&mcp->lock);
        ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
@@ -559,7 +589,7 @@ static void mcp_gpio_set(struct gpio_chip *gc,
        memset(mcp->txbuf, 0, 18);
        mcp->txbuf[0] = MCP2221_GPIO_SET;
 
-       mcp->gp_idx = ((offset + 1) * 4) - 1;
+       mcp->gp_idx = offsetof(struct mcp_set_gpio, gpio[offset].value);
 
        mcp->txbuf[mcp->gp_idx - 1] = 1;
        mcp->txbuf[mcp->gp_idx] = !!value;
@@ -575,7 +605,7 @@ static int mcp_gpio_dir_set(struct mcp2221 *mcp,
        memset(mcp->txbuf, 0, 18);
        mcp->txbuf[0] = MCP2221_GPIO_SET;
 
-       mcp->gp_idx = (offset + 1) * 5;
+       mcp->gp_idx = offsetof(struct mcp_set_gpio, gpio[offset].direction);
 
        mcp->txbuf[mcp->gp_idx - 1] = 1;
        mcp->txbuf[mcp->gp_idx] = val;
@@ -590,7 +620,7 @@ static int mcp_gpio_direction_input(struct gpio_chip *gc,
        struct mcp2221 *mcp = gpiochip_get_data(gc);
 
        mutex_lock(&mcp->lock);
-       ret = mcp_gpio_dir_set(mcp, offset, 0);
+       ret = mcp_gpio_dir_set(mcp, offset, MCP2221_DIR_IN);
        mutex_unlock(&mcp->lock);
 
        return ret;
@@ -603,7 +633,7 @@ static int mcp_gpio_direction_output(struct gpio_chip *gc,
        struct mcp2221 *mcp = gpiochip_get_data(gc);
 
        mutex_lock(&mcp->lock);
-       ret = mcp_gpio_dir_set(mcp, offset, 1);
+       ret = mcp_gpio_dir_set(mcp, offset, MCP2221_DIR_OUT);
        mutex_unlock(&mcp->lock);
 
        /* Can't configure as output, bailout early */
@@ -623,7 +653,7 @@ static int mcp_gpio_get_direction(struct gpio_chip *gc,
 
        mcp->txbuf[0] = MCP2221_GPIO_GET;
 
-       mcp->gp_idx = (offset + 1) * 2;
+       mcp->gp_idx = offsetof(struct mcp_get_gpio, gpio[offset].direction);
 
        mutex_lock(&mcp->lock);
        ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
@@ -632,7 +662,7 @@ static int mcp_gpio_get_direction(struct gpio_chip *gc,
        if (ret)
                return ret;
 
-       if (mcp->gpio_dir)
+       if (mcp->gpio_dir == MCP2221_DIR_IN)
                return GPIO_LINE_DIRECTION_IN;
 
        return GPIO_LINE_DIRECTION_OUT;
@@ -758,7 +788,7 @@ static int mcp2221_raw_event(struct hid_device *hdev,
                                mcp->status = -ENOENT;
                        } else {
                                mcp->status = !!data[mcp->gp_idx];
-                               mcp->gpio_dir = !!data[mcp->gp_idx + 1];
+                               mcp->gpio_dir = data[mcp->gp_idx + 1];
                        }
                        break;
                default:
@@ -860,7 +890,7 @@ static int mcp2221_probe(struct hid_device *hdev,
        mcp->gc->get_direction = mcp_gpio_get_direction;
        mcp->gc->set = mcp_gpio_set;
        mcp->gc->get = mcp_gpio_get;
-       mcp->gc->ngpio = 4;
+       mcp->gc->ngpio = MCP_NGPIO;
        mcp->gc->base = -1;
        mcp->gc->can_sleep = 1;
        mcp->gc->parent = &hdev->dev;
index 7a2be0205dfd12a81a82e963893ca664512bb526..bf7ecab5d9e5ed2db8488cf2329456eaed46b0c7 100644 (file)
@@ -83,7 +83,12 @@ static const struct hid_device_id hid_quirks[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER), HID_QUIRK_NO_INIT_REPORTS },
        { HID_USB_DEVICE(USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28), HID_QUIRK_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY), HID_QUIRK_NO_INIT_REPORTS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR), HID_QUIRK_MULTI_INPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD), HID_QUIRK_MULTI_INPUT },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_GAMEVICE, USB_DEVICE_ID_GAMEVICE_GV186),
+               HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GAMEVICE, USB_DEVICE_ID_GAMEVICE_KISHI),
+               HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
        { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
index 94c7398b5c279f21775f5b1b5e550e0d848818c6..3dd7d324673783dd710a68cf4b35cfb26f6a06bd 100644 (file)
@@ -483,7 +483,8 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
                return 1;
 
        ptr = raw_data;
-       ptr++; /* Skip report id */
+       if (report->id)
+               ptr++; /* Skip report id */
 
        spin_lock_irqsave(&pdata->lock, flags);
 
index 86b568037cb8af6ed004c4067f4d4314d3ed04b1..8e9c9e646cb7dd45d2e84c299e8c34b0936898fd 100644 (file)
@@ -385,6 +385,8 @@ static const struct hid_device_id uclogic_devices[] = {
                                USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER,
                                USB_DEVICE_ID_UGTIZER_TABLET_GP0610) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER,
+                               USB_DEVICE_ID_UGTIZER_TABLET_GT5040) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
                                USB_DEVICE_ID_UGEE_TABLET_G5) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
index 7d20d1fcf8d208f32bda368e7b33b516c76606a0..d26d8cd98efcfddc869155a07779828c54eee6bc 100644 (file)
@@ -997,6 +997,8 @@ int uclogic_params_init(struct uclogic_params *params,
                break;
        case VID_PID(USB_VENDOR_ID_UGTIZER,
                     USB_DEVICE_ID_UGTIZER_TABLET_GP0610):
+       case VID_PID(USB_VENDOR_ID_UGTIZER,
+                    USB_DEVICE_ID_UGTIZER_TABLET_GT5040):
        case VID_PID(USB_VENDOR_ID_UGEE,
                     USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
        case VID_PID(USB_VENDOR_ID_UGEE,
index 786e3e9af1c9e8e098fc4f606b6a7d2191a073c6..aeff1ffb0c8b3fd2796ee166c1a56e9545e1d6ad 100644 (file)
@@ -943,6 +943,11 @@ static void i2c_hid_acpi_enable_wakeup(struct device *dev)
        }
 }
 
+static void i2c_hid_acpi_shutdown(struct device *dev)
+{
+       acpi_device_set_power(ACPI_COMPANION(dev), ACPI_STATE_D3_COLD);
+}
+
 static const struct acpi_device_id i2c_hid_acpi_match[] = {
        {"ACPI0C50", 0 },
        {"PNP0C50", 0 },
@@ -959,6 +964,8 @@ static inline int i2c_hid_acpi_pdata(struct i2c_client *client,
 static inline void i2c_hid_acpi_fix_up_power(struct device *dev) {}
 
 static inline void i2c_hid_acpi_enable_wakeup(struct device *dev) {}
+
+static inline void i2c_hid_acpi_shutdown(struct device *dev) {}
 #endif
 
 #ifdef CONFIG_OF
@@ -1175,6 +1182,8 @@ static void i2c_hid_shutdown(struct i2c_client *client)
 
        i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
        free_irq(client->irq, ihid);
+
+       i2c_hid_acpi_shutdown(&client->dev);
 }
 
 #ifdef CONFIG_PM_SLEEP
index 0cde10fe0e71fb67ba62202f041503cf99693124..f202ac7f4b3d47c254f1bc90e1f5facaa2d20260 100644 (file)
@@ -244,9 +244,13 @@ int hv_synic_cleanup(unsigned int cpu)
 
        /*
         * Hyper-V does not provide a way to change the connect CPU once
-        * it is set; we must prevent the connect CPU from going offline.
+        * it is set; we must prevent the connect CPU from going offline
+        * while the VM is running normally. But in the panic or kexec()
+        * path where the vmbus is already disconnected, the CPU must be
+        * allowed to shut down.
         */
-       if (cpu == VMBUS_CONNECT_CPU)
+       if (cpu == VMBUS_CONNECT_CPU &&
+           vmbus_connection.conn_state == CONNECTED)
                return -EBUSY;
 
        /*
index b64d2efbefe71a5df31d1bd3c934faf19ecb515d..eb56e09ae15f3999478b0e75f601836c92ad175a 100644 (file)
@@ -1275,7 +1275,7 @@ static void balloon_up(struct work_struct *dummy)
 
        /* Refuse to balloon below the floor. */
        if (avail_pages < num_pages || avail_pages - num_pages < floor) {
-               pr_warn("Balloon request will be partially fulfilled. %s\n",
+               pr_info("Balloon request will be partially fulfilled. %s\n",
                        avail_pages < num_pages ? "Not enough memory." :
                        "Balloon floor reached.");
 
index d06597303d5aeb79755b0ad285b4a5dd89df936c..3197cda7bcd9fc5416135b2198d95df4aba8542a 100644 (file)
@@ -171,7 +171,7 @@ static umode_t amd_energy_is_visible(const void *_data,
                                     enum hwmon_sensor_types type,
                                     u32 attr, int channel)
 {
-       return 0444;
+       return 0440;
 }
 
 static int energy_accumulator(void *p)
index a18887990f4a2120c45c0d2ef744df7353b54fc8..79b498f816fe914286db46a122955adf994a0a38 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/hwmon.h>
 #include <linux/workqueue.h>
 #include <linux/err.h>
+#include <linux/bits.h>
 
 /* data port used by Apple SMC */
 #define APPLESMC_DATA_PORT     0x300
 
 #define APPLESMC_MAX_DATA_LENGTH 32
 
-/* wait up to 128 ms for a status change. */
-#define APPLESMC_MIN_WAIT      0x0010
-#define APPLESMC_RETRY_WAIT    0x0100
-#define APPLESMC_MAX_WAIT      0x20000
+/* Apple SMC status bits */
+#define SMC_STATUS_AWAITING_DATA  BIT(0) /* SMC has data waiting to be read */
+#define SMC_STATUS_IB_CLOSED      BIT(1) /* Will ignore any input */
+#define SMC_STATUS_BUSY           BIT(2) /* Command in progress */
+
+/* Initial wait is 8us */
+#define APPLESMC_MIN_WAIT      0x0008
 
 #define APPLESMC_READ_CMD      0x10
 #define APPLESMC_WRITE_CMD     0x11
@@ -151,65 +155,84 @@ static unsigned int key_at_index;
 static struct workqueue_struct *applesmc_led_wq;
 
 /*
- * wait_read - Wait for a byte to appear on SMC port. Callers must
- * hold applesmc_lock.
+ * Wait for specific status bits with a mask on the SMC.
+ * Used before all transactions.
+ * This does 10 fast loops of 8us then exponentially backs off for a
+ * minimum total wait of 262ms. Depending on usleep_range this could
+ * run out past 500ms.
  */
-static int wait_read(void)
+
+static int wait_status(u8 val, u8 mask)
 {
-       unsigned long end = jiffies + (APPLESMC_MAX_WAIT * HZ) / USEC_PER_SEC;
        u8 status;
        int us;
+       int i;
 
-       for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
-               usleep_range(us, us * 16);
+       us = APPLESMC_MIN_WAIT;
+       for (i = 0; i < 24 ; i++) {
                status = inb(APPLESMC_CMD_PORT);
-               /* read: wait for smc to settle */
-               if (status & 0x01)
+               if ((status & mask) == val)
                        return 0;
-               /* timeout: give up */
-               if (time_after(jiffies, end))
-                       break;
+               usleep_range(us, us * 2);
+               if (i > 9)
+                       us <<= 1;
        }
-
-       pr_warn("wait_read() fail: 0x%02x\n", status);
        return -EIO;
 }
 
-/*
- * send_byte - Write to SMC port, retrying when necessary. Callers
- * must hold applesmc_lock.
- */
+/* send_byte - Write to SMC data port. Callers must hold applesmc_lock. */
+
 static int send_byte(u8 cmd, u16 port)
 {
-       u8 status;
-       int us;
-       unsigned long end = jiffies + (APPLESMC_MAX_WAIT * HZ) / USEC_PER_SEC;
+       int status;
+
+       status = wait_status(0, SMC_STATUS_IB_CLOSED);
+       if (status)
+               return status;
+       /*
+        * This needs to be a separate read looking for bit 0x04
+        * after bit 0x02 falls. If consolidated with the wait above
+        * this extra read may not happen if status returns both
+        * simultaneously and this would appear to be required.
+        */
+       status = wait_status(SMC_STATUS_BUSY, SMC_STATUS_BUSY);
+       if (status)
+               return status;
 
        outb(cmd, port);
-       for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
-               usleep_range(us, us * 16);
-               status = inb(APPLESMC_CMD_PORT);
-               /* write: wait for smc to settle */
-               if (status & 0x02)
-                       continue;
-               /* ready: cmd accepted, return */
-               if (status & 0x04)
-                       return 0;
-               /* timeout: give up */
-               if (time_after(jiffies, end))
-                       break;
-               /* busy: long wait and resend */
-               udelay(APPLESMC_RETRY_WAIT);
-               outb(cmd, port);
-       }
-
-       pr_warn("send_byte(0x%02x, 0x%04x) fail: 0x%02x\n", cmd, port, status);
-       return -EIO;
+       return 0;
 }
 
+/* send_command - Write a command to the SMC. Callers must hold applesmc_lock. */
+
 static int send_command(u8 cmd)
 {
-       return send_byte(cmd, APPLESMC_CMD_PORT);
+       int ret;
+
+       ret = wait_status(0, SMC_STATUS_IB_CLOSED);
+       if (ret)
+               return ret;
+       outb(cmd, APPLESMC_CMD_PORT);
+       return 0;
+}
+
+/*
+ * Based on logic from the Apple driver. This is issued before any interaction
+ * If busy is stuck high, issue a read command to reset the SMC state machine.
+ * If busy is stuck high after the command then the SMC is jammed.
+ */
+
+static int smc_sane(void)
+{
+       int ret;
+
+       ret = wait_status(0, SMC_STATUS_BUSY);
+       if (!ret)
+               return ret;
+       ret = send_command(APPLESMC_READ_CMD);
+       if (ret)
+               return ret;
+       return wait_status(0, SMC_STATUS_BUSY);
 }
 
 static int send_argument(const char *key)
@@ -226,6 +249,11 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
 {
        u8 status, data = 0;
        int i;
+       int ret;
+
+       ret = smc_sane();
+       if (ret)
+               return ret;
 
        if (send_command(cmd) || send_argument(key)) {
                pr_warn("%.4s: read arg fail\n", key);
@@ -239,7 +267,8 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
        }
 
        for (i = 0; i < len; i++) {
-               if (wait_read()) {
+               if (wait_status(SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY,
+                               SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY)) {
                        pr_warn("%.4s: read data[%d] fail\n", key, i);
                        return -EIO;
                }
@@ -250,19 +279,24 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
        for (i = 0; i < 16; i++) {
                udelay(APPLESMC_MIN_WAIT);
                status = inb(APPLESMC_CMD_PORT);
-               if (!(status & 0x01))
+               if (!(status & SMC_STATUS_AWAITING_DATA))
                        break;
                data = inb(APPLESMC_DATA_PORT);
        }
        if (i)
                pr_warn("flushed %d bytes, last value is: %d\n", i, data);
 
-       return 0;
+       return wait_status(0, SMC_STATUS_BUSY);
 }
 
 static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
 {
        int i;
+       int ret;
+
+       ret = smc_sane();
+       if (ret)
+               return ret;
 
        if (send_command(cmd) || send_argument(key)) {
                pr_warn("%s: write arg fail\n", key);
@@ -281,7 +315,7 @@ static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
                }
        }
 
-       return 0;
+       return wait_status(0, SMC_STATUS_BUSY);
 }
 
 static int read_register_count(unsigned int *count)
index 57923d72490c0742951b58773610ef0afb7663bd..be83b98411c7dc84a29b1cd9ba0efba904d8366b 100644 (file)
@@ -122,8 +122,8 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
        switch (idx) {
        case MAX20730_DEBUGFS_VOUT_MIN:
                ret = VOLT_FROM_REG(data->mfr_voutmin * 10000);
-               len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d.%d\n",
-                              ret / 10000, ret % 10000);
+               len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d.%d\n",
+                               ret / 10000, ret % 10000);
                break;
        case MAX20730_DEBUGFS_FREQUENCY:
                val = (data->mfr_devset1 & MAX20730_MFR_DEVSET1_FSW_MASK)
@@ -141,7 +141,7 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
                        ret = 800;
                else
                        ret = 900;
-               len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
+               len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
                break;
        case MAX20730_DEBUGFS_PG_DELAY:
                val = (data->mfr_devset1 & MAX20730_MFR_DEVSET1_TSTAT_MASK)
@@ -223,7 +223,7 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
        case MAX20730_DEBUGFS_OC_PROTECT_MODE:
                ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_OCPM_MASK)
                        >> MAX20730_MFR_DEVSET2_OCPM_BIT_POS;
-               len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
+               len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
                break;
        case MAX20730_DEBUGFS_SS_TIMING:
                val = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_SS_MASK)
@@ -241,32 +241,32 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
        case MAX20730_DEBUGFS_IMAX:
                ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_IMAX_MASK)
                        >> MAX20730_MFR_DEVSET2_IMAX_BIT_POS;
-               len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
+               len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
                break;
        case MAX20730_DEBUGFS_OPERATION:
                ret = i2c_smbus_read_byte_data(psu->client, PMBUS_OPERATION);
                if (ret < 0)
                        return ret;
-               len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
+               len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
                break;
        case MAX20730_DEBUGFS_ON_OFF_CONFIG:
                ret = i2c_smbus_read_byte_data(psu->client, PMBUS_ON_OFF_CONFIG);
                if (ret < 0)
                        return ret;
-               len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
+               len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
                break;
        case MAX20730_DEBUGFS_SMBALERT_MASK:
                ret = i2c_smbus_read_word_data(psu->client,
                                               PMBUS_SMB_ALERT_MASK);
                if (ret < 0)
                        return ret;
-               len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
+               len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
                break;
        case MAX20730_DEBUGFS_VOUT_MODE:
                ret = i2c_smbus_read_byte_data(psu->client, PMBUS_VOUT_MODE);
                if (ret < 0)
                        return ret;
-               len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
+               len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
                break;
        case MAX20730_DEBUGFS_VOUT_COMMAND:
                ret = i2c_smbus_read_word_data(psu->client, PMBUS_VOUT_COMMAND);
@@ -274,8 +274,8 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
                        return ret;
 
                ret = VOLT_FROM_REG(ret * 10000);
-               len = snprintf(tbuf, DEBUG_FS_DATA_MAX,
-                              "%d.%d\n", ret / 10000, ret % 10000);
+               len = scnprintf(tbuf, DEBUG_FS_DATA_MAX,
+                               "%d.%d\n", ret / 10000, ret % 10000);
                break;
        case MAX20730_DEBUGFS_VOUT_MAX:
                ret = i2c_smbus_read_word_data(psu->client, PMBUS_VOUT_MAX);
@@ -283,8 +283,8 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
                        return ret;
 
                ret = VOLT_FROM_REG(ret * 10000);
-               len = snprintf(tbuf, DEBUG_FS_DATA_MAX,
-                              "%d.%d\n", ret / 10000, ret % 10000);
+               len = scnprintf(tbuf, DEBUG_FS_DATA_MAX,
+                               "%d.%d\n", ret / 10000, ret % 10000);
                break;
        default:
                len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
index 170a9f82ca614c1e0eb7436c887e4bc758a0a512..b0e2820a2d578f62ca0db7ac565ca5404065c790 100644 (file)
@@ -941,12 +941,16 @@ static ssize_t pmbus_show_sensor(struct device *dev,
        struct i2c_client *client = to_i2c_client(dev->parent);
        struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
        struct pmbus_data *data = i2c_get_clientdata(client);
+       ssize_t ret;
 
+       mutex_lock(&data->update_lock);
        pmbus_update_sensor_data(client, sensor);
        if (sensor->data < 0)
-               return sensor->data;
-
-       return snprintf(buf, PAGE_SIZE, "%lld\n", pmbus_reg2data(data, sensor));
+               ret = sensor->data;
+       else
+               ret = snprintf(buf, PAGE_SIZE, "%lld\n", pmbus_reg2data(data, sensor));
+       mutex_unlock(&data->update_lock);
+       return ret;
 }
 
 static ssize_t pmbus_set_sensor(struct device *dev,
@@ -2012,8 +2016,11 @@ static ssize_t pmbus_show_samples(struct device *dev,
        int val;
        struct i2c_client *client = to_i2c_client(dev->parent);
        struct pmbus_samples_reg *reg = to_samples_reg(devattr);
+       struct pmbus_data *data = i2c_get_clientdata(client);
 
+       mutex_lock(&data->update_lock);
        val = _pmbus_read_word_data(client, reg->page, 0xff, reg->attr->reg);
+       mutex_unlock(&data->update_lock);
        if (val < 0)
                return val;
 
index bdba2143021a6107bdebc738f9d02c1407a38bbe..1f63807c0399eb44b4e88aaebb0d4930e2e0b69f 100644 (file)
@@ -54,16 +54,18 @@ static irqreturn_t pulse_handler(int irq, void *dev_id)
 static void sample_timer(struct timer_list *t)
 {
        struct pwm_fan_ctx *ctx = from_timer(ctx, t, rpm_timer);
+       unsigned int delta = ktime_ms_delta(ktime_get(), ctx->sample_start);
        int pulses;
-       u64 tmp;
 
-       pulses = atomic_read(&ctx->pulses);
-       atomic_sub(pulses, &ctx->pulses);
-       tmp = (u64)pulses * ktime_ms_delta(ktime_get(), ctx->sample_start) * 60;
-       do_div(tmp, ctx->pulses_per_revolution * 1000);
-       ctx->rpm = tmp;
+       if (delta) {
+               pulses = atomic_read(&ctx->pulses);
+               atomic_sub(pulses, &ctx->pulses);
+               ctx->rpm = (unsigned int)(pulses * 1000 * 60) /
+                       (ctx->pulses_per_revolution * delta);
+
+               ctx->sample_start = ktime_get();
+       }
 
-       ctx->sample_start = ktime_get();
        mod_timer(&ctx->rpm_timer, jiffies + HZ);
 }
 
index 6994c1309b2b6c66abb8dc6eb52e2d4396daa77c..cc9e8025c533c018942d5fb5e9b751fb8873a228 100644 (file)
@@ -1689,6 +1689,7 @@ static void __exit coresight_exit(void)
 module_init(coresight_init);
 module_exit(coresight_exit);
 
+MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Pratik Patel <pratikp@codeaurora.org>");
 MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier@linaro.org>");
 MODULE_DESCRIPTION("Arm CoreSight tracer driver");
index 392757f3a019e8f753b383896be5f89e83ed061c..7ff7e7780bbfbcde5b74f7a2f118b0a3914d1267 100644 (file)
@@ -1065,6 +1065,13 @@ static int cti_create_con_sysfs_attr(struct device *dev,
        }
        eattr->var = con;
        con->con_attrs[attr_idx] = &eattr->attr.attr;
+       /*
+        * Initialize the dynamically allocated attribute
+        * to avoid LOCKDEP splat. See include/linux/sysfs.h
+        * for more details.
+        */
+       sysfs_attr_init(con->con_attrs[attr_idx]);
+
        return 0;
 }
 
index c2c9b127d0748045155bcec51b8d191a8daec760..bdc34ca449f7145ba06755738e4e97029310564f 100644 (file)
@@ -210,7 +210,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
        u32 id;
        int cpu = event->cpu;
        cpumask_t *mask;
-       struct coresight_device *sink;
+       struct coresight_device *sink = NULL;
        struct etm_event_data *event_data = NULL;
 
        event_data = alloc_event_data(cpu);
index a4f473ef4e5c04c87abdb5d0343115a2f098dfc4..a49e0ed4a599d538ea45815c10daed5f37eb9977 100644 (file)
@@ -733,7 +733,8 @@ config I2C_LPC2K
 
 config I2C_MLXBF
         tristate "Mellanox BlueField I2C controller"
-        depends on ARM64
+        depends on MELLANOX_PLATFORM && ARM64
+       select I2C_SLAVE
         help
           Enabling this option will add I2C SMBus support for Mellanox BlueField
           system.
index 44974b53a6268149007cff3c5c394ba3c6b56b63..0d15f4c1e9f7e3ae17a03f7b39465b47f8cf5abe 100644 (file)
@@ -159,7 +159,6 @@ static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev)
        u32 raw_stat, stat, enabled, tmp;
        u8 val = 0, slave_activity;
 
-       regmap_read(dev->map, DW_IC_INTR_STAT, &stat);
        regmap_read(dev->map, DW_IC_ENABLE, &enabled);
        regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &raw_stat);
        regmap_read(dev->map, DW_IC_STATUS, &tmp);
@@ -168,32 +167,30 @@ static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev)
        if (!enabled || !(raw_stat & ~DW_IC_INTR_ACTIVITY) || !dev->slave)
                return 0;
 
+       stat = i2c_dw_read_clear_intrbits_slave(dev);
        dev_dbg(dev->dev,
                "%#x STATUS SLAVE_ACTIVITY=%#x : RAW_INTR_STAT=%#x : INTR_STAT=%#x\n",
                enabled, slave_activity, raw_stat, stat);
 
-       if ((stat & DW_IC_INTR_RX_FULL) && (stat & DW_IC_INTR_STOP_DET))
-               i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, &val);
+       if (stat & DW_IC_INTR_RX_FULL) {
+               if (dev->status != STATUS_WRITE_IN_PROGRESS) {
+                       dev->status = STATUS_WRITE_IN_PROGRESS;
+                       i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED,
+                                       &val);
+               }
+
+               regmap_read(dev->map, DW_IC_DATA_CMD, &tmp);
+               val = tmp;
+               if (!i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED,
+                                    &val))
+                       dev_vdbg(dev->dev, "Byte %X acked!", val);
+       }
 
        if (stat & DW_IC_INTR_RD_REQ) {
                if (slave_activity) {
-                       if (stat & DW_IC_INTR_RX_FULL) {
-                               regmap_read(dev->map, DW_IC_DATA_CMD, &tmp);
-                               val = tmp;
-
-                               if (!i2c_slave_event(dev->slave,
-                                                    I2C_SLAVE_WRITE_RECEIVED,
-                                                    &val)) {
-                                       dev_vdbg(dev->dev, "Byte %X acked!",
-                                                val);
-                               }
-                               regmap_read(dev->map, DW_IC_CLR_RD_REQ, &tmp);
-                               stat = i2c_dw_read_clear_intrbits_slave(dev);
-                       } else {
-                               regmap_read(dev->map, DW_IC_CLR_RD_REQ, &tmp);
-                               regmap_read(dev->map, DW_IC_CLR_RX_UNDER, &tmp);
-                               stat = i2c_dw_read_clear_intrbits_slave(dev);
-                       }
+                       regmap_read(dev->map, DW_IC_CLR_RD_REQ, &tmp);
+
+                       dev->status = STATUS_READ_IN_PROGRESS;
                        if (!i2c_slave_event(dev->slave,
                                             I2C_SLAVE_READ_REQUESTED,
                                             &val))
@@ -205,21 +202,11 @@ static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev)
                if (!i2c_slave_event(dev->slave, I2C_SLAVE_READ_PROCESSED,
                                     &val))
                        regmap_read(dev->map, DW_IC_CLR_RX_DONE, &tmp);
-
-               i2c_slave_event(dev->slave, I2C_SLAVE_STOP, &val);
-               stat = i2c_dw_read_clear_intrbits_slave(dev);
-               return 1;
        }
 
-       if (stat & DW_IC_INTR_RX_FULL) {
-               regmap_read(dev->map, DW_IC_DATA_CMD, &tmp);
-               val = tmp;
-               if (!i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED,
-                                    &val))
-                       dev_vdbg(dev->dev, "Byte %X acked!", val);
-       } else {
+       if (stat & DW_IC_INTR_STOP_DET) {
+               dev->status = STATUS_IDLE;
                i2c_slave_event(dev->slave, I2C_SLAVE_STOP, &val);
-               stat = i2c_dw_read_clear_intrbits_slave(dev);
        }
 
        return 1;
@@ -230,7 +217,6 @@ static irqreturn_t i2c_dw_isr_slave(int this_irq, void *dev_id)
        struct dw_i2c_dev *dev = dev_id;
        int ret;
 
-       i2c_dw_read_clear_intrbits_slave(dev);
        ret = i2c_dw_irq_handler_slave(dev);
        if (ret > 0)
                complete(&dev->cmd_complete);
index c98529c76348e32097031fa4ba25fc0d7cbc0799..e6f8d6e45a15a90e2d28db4baa124245e7844e51 100644 (file)
@@ -412,6 +412,19 @@ static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx)
        dma->chan_using = NULL;
 }
 
+static void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits)
+{
+       unsigned int temp;
+
+       /*
+        * i2sr_clr_opcode is the value to clear all interrupts. Here we want to
+        * clear only <bits>, so we write ~i2sr_clr_opcode with just <bits>
+        * toggled. This is required because i.MX needs W0C and Vybrid uses W1C.
+        */
+       temp = ~i2c_imx->hwdata->i2sr_clr_opcode ^ bits;
+       imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
+}
+
 static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool atomic)
 {
        unsigned long orig_jiffies = jiffies;
@@ -424,8 +437,7 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool a
 
                /* check for arbitration lost */
                if (temp & I2SR_IAL) {
-                       temp &= ~I2SR_IAL;
-                       imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
+                       i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
                        return -EAGAIN;
                }
 
@@ -469,7 +481,7 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic)
                 */
                readb_poll_timeout_atomic(addr, regval, regval & I2SR_IIF, 5, 1000 + 100);
                i2c_imx->i2csr = regval;
-               imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR);
+               i2c_imx_clear_irq(i2c_imx, I2SR_IIF | I2SR_IAL);
        } else {
                wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10);
        }
@@ -478,6 +490,16 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic)
                dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
                return -ETIMEDOUT;
        }
+
+       /* check for arbitration lost */
+       if (i2c_imx->i2csr & I2SR_IAL) {
+               dev_dbg(&i2c_imx->adapter.dev, "<%s> Arbitration lost\n", __func__);
+               i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
+
+               i2c_imx->i2csr = 0;
+               return -EAGAIN;
+       }
+
        dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__);
        i2c_imx->i2csr = 0;
        return 0;
@@ -593,6 +615,8 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic)
                /* Stop I2C transaction */
                dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
                temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+               if (!(temp & I2CR_MSTA))
+                       i2c_imx->stopped = 1;
                temp &= ~(I2CR_MSTA | I2CR_MTX);
                if (i2c_imx->dma)
                        temp &= ~I2CR_DMAEN;
@@ -623,9 +647,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
        if (temp & I2SR_IIF) {
                /* save status register */
                i2c_imx->i2csr = temp;
-               temp &= ~I2SR_IIF;
-               temp |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IIF);
-               imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
+               i2c_imx_clear_irq(i2c_imx, I2SR_IIF);
                wake_up(&i2c_imx->queue);
                return IRQ_HANDLED;
        }
@@ -758,9 +780,12 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
                 */
                dev_dbg(dev, "<%s> clear MSTA\n", __func__);
                temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+               if (!(temp & I2CR_MSTA))
+                       i2c_imx->stopped = 1;
                temp &= ~(I2CR_MSTA | I2CR_MTX);
                imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
-               i2c_imx_bus_busy(i2c_imx, 0, false);
+               if (!i2c_imx->stopped)
+                       i2c_imx_bus_busy(i2c_imx, 0, false);
        } else {
                /*
                 * For i2c master receiver repeat restart operation like:
@@ -885,9 +910,12 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
                                dev_dbg(&i2c_imx->adapter.dev,
                                        "<%s> clear MSTA\n", __func__);
                                temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+                               if (!(temp & I2CR_MSTA))
+                                       i2c_imx->stopped =  1;
                                temp &= ~(I2CR_MSTA | I2CR_MTX);
                                imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
-                               i2c_imx_bus_busy(i2c_imx, 0, atomic);
+                               if (!i2c_imx->stopped)
+                                       i2c_imx_bus_busy(i2c_imx, 0, atomic);
                        } else {
                                /*
                                 * For i2c master receiver repeat restart operation like:
index ee59e0da082dfbe3b55acadb37010c6b344f9321..2fb0532d8a1611591221cf226d96bd963d69b0d1 100644 (file)
  * Master. Default value is set to 400MHz.
  */
 #define MLXBF_I2C_TYU_PLL_OUT_FREQ  (400 * 1000 * 1000)
-/* Reference clock for Bluefield 1 - 156 MHz. */
-#define MLXBF_I2C_TYU_PLL_IN_FREQ   (156 * 1000 * 1000)
-/* Reference clock for BlueField 2 - 200 MHz. */
-#define MLXBF_I2C_YU_PLL_IN_FREQ    (200 * 1000 * 1000)
+/* Reference clock for Bluefield - 156 MHz. */
+#define MLXBF_I2C_PLL_IN_FREQ       (156 * 1000 * 1000)
 
 /* Constant used to determine the PLL frequency. */
 #define MLNXBF_I2C_COREPLL_CONST    16384
@@ -489,44 +487,6 @@ static struct mutex mlxbf_i2c_bus_lock;
 
 #define MLXBF_I2C_FREQUENCY_1GHZ  1000000000
 
-static void mlxbf_i2c_write(void __iomem *io, int reg, u32 val)
-{
-       writel(val, io + reg);
-}
-
-static u32 mlxbf_i2c_read(void __iomem *io, int reg)
-{
-       return readl(io + reg);
-}
-
-/*
- * This function is used to read data from Master GW Data Descriptor.
- * Data bytes in the Master GW Data Descriptor are shifted left so the
- * data starts at the MSB of the descriptor registers as set by the
- * underlying hardware. TYU_READ_DATA enables byte swapping while
- * reading data bytes, and MUST be called by the SMBus read routines
- * to copy data from the 32 * 32-bit HW Data registers a.k.a Master GW
- * Data Descriptor.
- */
-static u32 mlxbf_i2c_read_data(void __iomem *io, int reg)
-{
-       return (u32)be32_to_cpu(mlxbf_i2c_read(io, reg));
-}
-
-/*
- * This function is used to write data to the Master GW Data Descriptor.
- * Data copied to the Master GW Data Descriptor MUST be shifted left so
- * the data starts at the MSB of the descriptor registers as required by
- * the underlying hardware. TYU_WRITE_DATA enables byte swapping when
- * writing data bytes, and MUST be called by the SMBus write routines to
- * copy data to the 32 * 32-bit HW Data registers a.k.a Master GW Data
- * Descriptor.
- */
-static void mlxbf_i2c_write_data(void __iomem *io, int reg, u32 val)
-{
-       mlxbf_i2c_write(io, reg, (u32)cpu_to_be32(val));
-}
-
 /*
  * Function to poll a set of bits at a specific address; it checks whether
  * the bits are equal to zero when eq_zero is set to 'true', and not equal
@@ -541,7 +501,7 @@ static u32 mlxbf_smbus_poll(void __iomem *io, u32 addr, u32 mask,
        timeout = (timeout / MLXBF_I2C_POLL_FREQ_IN_USEC) + 1;
 
        do {
-               bits = mlxbf_i2c_read(io, addr) & mask;
+               bits = readl(io + addr) & mask;
                if (eq_zero ? bits == 0 : bits != 0)
                        return eq_zero ? 1 : bits;
                udelay(MLXBF_I2C_POLL_FREQ_IN_USEC);
@@ -609,16 +569,16 @@ static int mlxbf_i2c_smbus_check_status(struct mlxbf_i2c_priv *priv)
                         MLXBF_I2C_SMBUS_TIMEOUT);
 
        /* Read cause status bits. */
-       cause_status_bits = mlxbf_i2c_read(priv->mst_cause->io,
-                                          MLXBF_I2C_CAUSE_ARBITER);
+       cause_status_bits = readl(priv->mst_cause->io +
+                                       MLXBF_I2C_CAUSE_ARBITER);
        cause_status_bits &= MLXBF_I2C_CAUSE_MASTER_ARBITER_BITS_MASK;
 
        /*
         * Parse both Cause and Master GW bits, then return transaction status.
         */
 
-       master_status_bits = mlxbf_i2c_read(priv->smbus->io,
-                                           MLXBF_I2C_SMBUS_MASTER_STATUS);
+       master_status_bits = readl(priv->smbus->io +
+                                       MLXBF_I2C_SMBUS_MASTER_STATUS);
        master_status_bits &= MLXBF_I2C_SMBUS_MASTER_STATUS_MASK;
 
        if (mlxbf_i2c_smbus_transaction_success(master_status_bits,
@@ -649,10 +609,17 @@ static void mlxbf_i2c_smbus_write_data(struct mlxbf_i2c_priv *priv,
 
        aligned_length = round_up(length, 4);
 
-       /* Copy data bytes from 4-byte aligned source buffer. */
+       /*
+        * Copy data bytes from 4-byte aligned source buffer.
+        * Data copied to the Master GW Data Descriptor MUST be shifted
+        * left so the data starts at the MSB of the descriptor registers
+        * as required by the underlying hardware. Enable byte swapping
+        * when writing data bytes to the 32 * 32-bit HW Data registers
+        * a.k.a Master GW Data Descriptor.
+        */
        for (offset = 0; offset < aligned_length; offset += sizeof(u32)) {
                data32 = *((u32 *)(data + offset));
-               mlxbf_i2c_write_data(priv->smbus->io, addr + offset, data32);
+               iowrite32be(data32, priv->smbus->io + addr + offset);
        }
 }
 
@@ -664,15 +631,23 @@ static void mlxbf_i2c_smbus_read_data(struct mlxbf_i2c_priv *priv,
 
        mask = sizeof(u32) - 1;
 
+       /*
+        * Data bytes in the Master GW Data Descriptor are shifted left
+        * so the data starts at the MSB of the descriptor registers as
+        * set by the underlying hardware. Enable byte swapping while
+        * reading data bytes from the 32 * 32-bit HW Data registers
+        * a.k.a Master GW Data Descriptor.
+        */
+
        for (offset = 0; offset < (length & ~mask); offset += sizeof(u32)) {
-               data32 = mlxbf_i2c_read_data(priv->smbus->io, addr + offset);
+               data32 = ioread32be(priv->smbus->io + addr + offset);
                *((u32 *)(data + offset)) = data32;
        }
 
        if (!(length & mask))
                return;
 
-       data32 = mlxbf_i2c_read_data(priv->smbus->io, addr + offset);
+       data32 = ioread32be(priv->smbus->io + addr + offset);
 
        for (byte = 0; byte < (length & mask); byte++) {
                data[offset + byte] = data32 & GENMASK(7, 0);
@@ -698,16 +673,16 @@ static int mlxbf_i2c_smbus_enable(struct mlxbf_i2c_priv *priv, u8 slave,
        command |= rol32(pec_en, MLXBF_I2C_MASTER_SEND_PEC_SHIFT);
 
        /* Clear status bits. */
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_STATUS, 0x0);
+       writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_STATUS);
        /* Set the cause data. */
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_CAUSE_OR_CLEAR, ~0x0);
+       writel(~0x0, priv->smbus->io + MLXBF_I2C_CAUSE_OR_CLEAR);
        /* Zero PEC byte. */
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_PEC, 0x0);
+       writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_PEC);
        /* Zero byte count. */
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_RS_BYTES, 0x0);
+       writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_RS_BYTES);
 
        /* GW activation. */
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_GW, command);
+       writel(command, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_GW);
 
        /*
         * Poll master status and check status bits. An ACK is sent when
@@ -823,8 +798,8 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv,
                 * needs to be 'manually' reset. This should be removed in
                 * next tag integration.
                 */
-               mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_FSM,
-                               MLXBF_I2C_SMBUS_MASTER_FSM_PS_STATE_MASK);
+               writel(MLXBF_I2C_SMBUS_MASTER_FSM_PS_STATE_MASK,
+                       priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_FSM);
        }
 
        return ret;
@@ -1113,8 +1088,8 @@ static void mlxbf_i2c_set_timings(struct mlxbf_i2c_priv *priv,
        timer |= mlxbf_i2c_set_timer(priv, timings->scl_low,
                                     false, MLXBF_I2C_MASK_16,
                                     MLXBF_I2C_SHIFT_16);
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_TIMER_SCL_LOW_SCL_HIGH,
-                         timer);
+       writel(timer, priv->smbus->io +
+               MLXBF_I2C_SMBUS_TIMER_SCL_LOW_SCL_HIGH);
 
        timer = mlxbf_i2c_set_timer(priv, timings->sda_rise, false,
                                    MLXBF_I2C_MASK_8, MLXBF_I2C_SHIFT_0);
@@ -1124,37 +1099,34 @@ static void mlxbf_i2c_set_timings(struct mlxbf_i2c_priv *priv,
                                     MLXBF_I2C_MASK_8, MLXBF_I2C_SHIFT_16);
        timer |= mlxbf_i2c_set_timer(priv, timings->scl_fall, false,
                                     MLXBF_I2C_MASK_8, MLXBF_I2C_SHIFT_24);
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_TIMER_FALL_RISE_SPIKE,
-                         timer);
+       writel(timer, priv->smbus->io +
+               MLXBF_I2C_SMBUS_TIMER_FALL_RISE_SPIKE);
 
        timer = mlxbf_i2c_set_timer(priv, timings->hold_start, true,
                                    MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0);
        timer |= mlxbf_i2c_set_timer(priv, timings->hold_data, true,
                                     MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16);
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_TIMER_THOLD, timer);
+       writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_TIMER_THOLD);
 
        timer = mlxbf_i2c_set_timer(priv, timings->setup_start, true,
                                    MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0);
        timer |= mlxbf_i2c_set_timer(priv, timings->setup_stop, true,
                                     MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16);
-       mlxbf_i2c_write(priv->smbus->io,
-                       MLXBF_I2C_SMBUS_TIMER_TSETUP_START_STOP, timer);
+       writel(timer, priv->smbus->io +
+               MLXBF_I2C_SMBUS_TIMER_TSETUP_START_STOP);
 
        timer = mlxbf_i2c_set_timer(priv, timings->setup_data, true,
                                    MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0);
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_TIMER_TSETUP_DATA,
-                         timer);
+       writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_TIMER_TSETUP_DATA);
 
        timer = mlxbf_i2c_set_timer(priv, timings->buf, false,
                                    MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0);
        timer |= mlxbf_i2c_set_timer(priv, timings->thigh_max, false,
                                     MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16);
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_THIGH_MAX_TBUF,
-                       timer);
+       writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_THIGH_MAX_TBUF);
 
        timer = timings->timeout;
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SCL_LOW_TIMEOUT,
-                       timer);
+       writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_SCL_LOW_TIMEOUT);
 }
 
 enum mlxbf_i2c_timings_config {
@@ -1286,9 +1258,9 @@ static int mlxbf_i2c_get_gpio(struct platform_device *pdev,
                return -EFAULT;
 
        gpio_res->io = devm_ioremap(dev, params->start, size);
-       if (IS_ERR(gpio_res->io)) {
+       if (!gpio_res->io) {
                devm_release_mem_region(dev, params->start, size);
-               return PTR_ERR(gpio_res->io);
+               return -ENOMEM;
        }
 
        return 0;
@@ -1351,9 +1323,9 @@ static int mlxbf_i2c_get_corepll(struct platform_device *pdev,
                return -EFAULT;
 
        corepll_res->io = devm_ioremap(dev, params->start, size);
-       if (IS_ERR(corepll_res->io)) {
+       if (!corepll_res->io) {
                devm_release_mem_region(dev, params->start, size);
-               return PTR_ERR(corepll_res->io);
+               return -ENOMEM;
        }
 
        return 0;
@@ -1426,19 +1398,15 @@ static int mlxbf_i2c_init_master(struct platform_device *pdev,
         * platform firmware; disabling the bus might compromise the system
         * functionality.
         */
-       config_reg = mlxbf_i2c_read(gpio_res->io,
-                                   MLXBF_I2C_GPIO_0_FUNC_EN_0);
+       config_reg = readl(gpio_res->io + MLXBF_I2C_GPIO_0_FUNC_EN_0);
        config_reg = MLXBF_I2C_GPIO_SMBUS_GW_ASSERT_PINS(priv->bus,
                                                         config_reg);
-       mlxbf_i2c_write(gpio_res->io, MLXBF_I2C_GPIO_0_FUNC_EN_0,
-                       config_reg);
+       writel(config_reg, gpio_res->io + MLXBF_I2C_GPIO_0_FUNC_EN_0);
 
-       config_reg = mlxbf_i2c_read(gpio_res->io,
-                                   MLXBF_I2C_GPIO_0_FORCE_OE_EN);
+       config_reg = readl(gpio_res->io + MLXBF_I2C_GPIO_0_FORCE_OE_EN);
        config_reg = MLXBF_I2C_GPIO_SMBUS_GW_RESET_PINS(priv->bus,
                                                        config_reg);
-       mlxbf_i2c_write(gpio_res->io, MLXBF_I2C_GPIO_0_FORCE_OE_EN,
-                       config_reg);
+       writel(config_reg, gpio_res->io + MLXBF_I2C_GPIO_0_FORCE_OE_EN);
 
        mutex_unlock(gpio_res->lock);
 
@@ -1452,10 +1420,9 @@ static u64 mlxbf_calculate_freq_from_tyu(struct mlxbf_i2c_resource *corepll_res)
        u32 corepll_val;
        u16 core_f;
 
-       pad_frequency = MLXBF_I2C_TYU_PLL_IN_FREQ;
+       pad_frequency = MLXBF_I2C_PLL_IN_FREQ;
 
-       corepll_val = mlxbf_i2c_read(corepll_res->io,
-                                    MLXBF_I2C_CORE_PLL_REG1);
+       corepll_val = readl(corepll_res->io + MLXBF_I2C_CORE_PLL_REG1);
 
        /* Get Core PLL configuration bits. */
        core_f = rol32(corepll_val, MLXBF_I2C_COREPLL_CORE_F_TYU_SHIFT) &
@@ -1488,12 +1455,10 @@ static u64 mlxbf_calculate_freq_from_yu(struct mlxbf_i2c_resource *corepll_res)
        u8 core_od, core_r;
        u32 core_f;
 
-       pad_frequency = MLXBF_I2C_YU_PLL_IN_FREQ;
+       pad_frequency = MLXBF_I2C_PLL_IN_FREQ;
 
-       corepll_reg1_val = mlxbf_i2c_read(corepll_res->io,
-                                         MLXBF_I2C_CORE_PLL_REG1);
-       corepll_reg2_val = mlxbf_i2c_read(corepll_res->io,
-                                         MLXBF_I2C_CORE_PLL_REG2);
+       corepll_reg1_val = readl(corepll_res->io + MLXBF_I2C_CORE_PLL_REG1);
+       corepll_reg2_val = readl(corepll_res->io + MLXBF_I2C_CORE_PLL_REG2);
 
        /* Get Core PLL configuration bits */
        core_f = rol32(corepll_reg1_val, MLXBF_I2C_COREPLL_CORE_F_YU_SHIFT) &
@@ -1585,7 +1550,7 @@ static int mlxbf_slave_enable(struct mlxbf_i2c_priv *priv, u8 addr)
         * (7-bit address, 1 status bit (1 if enabled, 0 if not)).
         */
        for (reg = 0; reg < reg_cnt; reg++) {
-               slave_reg = mlxbf_i2c_read(priv->smbus->io,
+               slave_reg = readl(priv->smbus->io +
                                MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4);
                /*
                 * Each register holds 4 slave addresses. So, we have to keep
@@ -1643,8 +1608,8 @@ static int mlxbf_slave_enable(struct mlxbf_i2c_priv *priv, u8 addr)
 
        /* Enable the slave address and update the register. */
        slave_reg |= (1 << MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT) << (byte * 8);
-       mlxbf_i2c_write(priv->smbus->io,
-                       MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4, slave_reg);
+       writel(slave_reg, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG +
+               reg * 0x4);
 
        return 0;
 }
@@ -1668,7 +1633,7 @@ static int mlxbf_slave_disable(struct mlxbf_i2c_priv *priv)
         * (7-bit address, 1 status bit (1 if enabled, 0 if not)).
         */
        for (reg = 0; reg < reg_cnt; reg++) {
-               slave_reg = mlxbf_i2c_read(priv->smbus->io,
+               slave_reg = readl(priv->smbus->io +
                                MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4);
 
                /* Check whether the address slots are empty. */
@@ -1708,8 +1673,8 @@ static int mlxbf_slave_disable(struct mlxbf_i2c_priv *priv)
 
        /* Cleanup the slave address slot. */
        slave_reg &= ~(GENMASK(7, 0) << (slave_byte * 8));
-       mlxbf_i2c_write(priv->smbus->io,
-                       MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4, slave_reg);
+       writel(slave_reg, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG +
+               reg * 0x4);
 
        return 0;
 }
@@ -1752,9 +1717,9 @@ static int mlxbf_i2c_init_coalesce(struct platform_device *pdev,
                        return -EFAULT;
 
                coalesce_res->io = ioremap(params->start, size);
-               if (IS_ERR(coalesce_res->io)) {
+               if (!coalesce_res->io) {
                        release_mem_region(params->start, size);
-                       return PTR_ERR(coalesce_res->io);
+                       return -ENOMEM;
                }
 
                priv->coalesce = coalesce_res;
@@ -1801,7 +1766,7 @@ static int mlxbf_i2c_init_slave(struct platform_device *pdev,
        int ret;
 
        /* Reset FSM. */
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_FSM, 0);
+       writel(0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_FSM);
 
        /*
         * Enable slave cause interrupt bits. Drive
@@ -1810,15 +1775,13 @@ static int mlxbf_i2c_init_slave(struct platform_device *pdev,
         * masters issue a Read and Write, respectively. But, clear all
         * interrupts first.
         */
-       mlxbf_i2c_write(priv->slv_cause->io,
-                         MLXBF_I2C_CAUSE_OR_CLEAR, ~0);
+       writel(~0, priv->slv_cause->io + MLXBF_I2C_CAUSE_OR_CLEAR);
        int_reg = MLXBF_I2C_CAUSE_READ_WAIT_FW_RESPONSE;
        int_reg |= MLXBF_I2C_CAUSE_WRITE_SUCCESS;
-       mlxbf_i2c_write(priv->slv_cause->io,
-                         MLXBF_I2C_CAUSE_OR_EVTEN0, int_reg);
+       writel(int_reg, priv->slv_cause->io + MLXBF_I2C_CAUSE_OR_EVTEN0);
 
        /* Finally, set the 'ready' bit to start handling transactions. */
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_READY, 0x1);
+       writel(0x1, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_READY);
 
        /* Initialize the cause coalesce resource. */
        ret = mlxbf_i2c_init_coalesce(pdev, priv);
@@ -1844,23 +1807,21 @@ static bool mlxbf_i2c_has_coalesce(struct mlxbf_i2c_priv *priv, bool *read,
                                MLXBF_I2C_CAUSE_YU_SLAVE_BIT :
                                priv->bus + MLXBF_I2C_CAUSE_TYU_SLAVE_BIT;
 
-       coalesce0_reg = mlxbf_i2c_read(priv->coalesce->io,
-                                      MLXBF_I2C_CAUSE_COALESCE_0);
+       coalesce0_reg = readl(priv->coalesce->io + MLXBF_I2C_CAUSE_COALESCE_0);
        is_set = coalesce0_reg & (1 << slave_shift);
 
        if (!is_set)
                return false;
 
        /* Check the source of the interrupt, i.e. whether a Read or Write. */
-       cause_reg = mlxbf_i2c_read(priv->slv_cause->io,
-                                    MLXBF_I2C_CAUSE_ARBITER);
+       cause_reg = readl(priv->slv_cause->io + MLXBF_I2C_CAUSE_ARBITER);
        if (cause_reg & MLXBF_I2C_CAUSE_READ_WAIT_FW_RESPONSE)
                *read = true;
        else if (cause_reg & MLXBF_I2C_CAUSE_WRITE_SUCCESS)
                *write = true;
 
        /* Clear cause bits. */
-       mlxbf_i2c_write(priv->slv_cause->io, MLXBF_I2C_CAUSE_OR_CLEAR, ~0x0);
+       writel(~0x0, priv->slv_cause->io + MLXBF_I2C_CAUSE_OR_CLEAR);
 
        return true;
 }
@@ -1900,8 +1861,8 @@ static int mlxbf_smbus_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes)
         * address, if supplied.
         */
        if (recv_bytes > 0) {
-               data32 = mlxbf_i2c_read_data(priv->smbus->io,
-                                            MLXBF_I2C_SLAVE_DATA_DESC_ADDR);
+               data32 = ioread32be(priv->smbus->io +
+                                       MLXBF_I2C_SLAVE_DATA_DESC_ADDR);
 
                /* Parse the received bytes. */
                switch (recv_bytes) {
@@ -1966,7 +1927,7 @@ static int mlxbf_smbus_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes)
        control32 |= rol32(write_size, MLXBF_I2C_SLAVE_WRITE_BYTES_SHIFT);
        control32 |= rol32(pec_en, MLXBF_I2C_SLAVE_SEND_PEC_SHIFT);
 
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_GW, control32);
+       writel(control32, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_GW);
 
        /*
         * Wait until the transfer is completed; the driver will wait
@@ -1975,10 +1936,9 @@ static int mlxbf_smbus_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes)
        mlxbf_smbus_slave_wait_for_idle(priv, MLXBF_I2C_SMBUS_TIMEOUT);
 
        /* Release the Slave GW. */
-       mlxbf_i2c_write(priv->smbus->io,
-                       MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES, 0x0);
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_PEC, 0x0);
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_READY, 0x1);
+       writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES);
+       writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_PEC);
+       writel(0x1, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_READY);
 
        return 0;
 }
@@ -2023,10 +1983,9 @@ static int mlxbf_smbus_irq_recv(struct mlxbf_i2c_priv *priv, u8 recv_bytes)
        i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
 
        /* Release the Slave GW. */
-       mlxbf_i2c_write(priv->smbus->io,
-                       MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES, 0x0);
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_PEC, 0x0);
-       mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_READY, 0x1);
+       writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES);
+       writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_PEC);
+       writel(0x1, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_READY);
 
        return ret;
 }
@@ -2061,8 +2020,8 @@ static irqreturn_t mlxbf_smbus_irq(int irq, void *ptr)
         * slave, if the higher 8 bits are sent then the slave expect N bytes
         * from the master.
         */
-       rw_bytes_reg = mlxbf_i2c_read(priv->smbus->io,
-                                     MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES);
+       rw_bytes_reg = readl(priv->smbus->io +
+                               MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES);
        recv_bytes = (rw_bytes_reg >> 8) & GENMASK(7, 0);
 
        /*
@@ -2264,6 +2223,7 @@ static const struct of_device_id mlxbf_i2c_dt_ids[] = {
 
 MODULE_DEVICE_TABLE(of, mlxbf_i2c_dt_ids);
 
+#ifdef CONFIG_ACPI
 static const struct acpi_device_id mlxbf_i2c_acpi_ids[] = {
        { "MLNXBF03", (kernel_ulong_t)&mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_1] },
        { "MLNXBF23", (kernel_ulong_t)&mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_2] },
@@ -2305,6 +2265,12 @@ static int mlxbf_i2c_acpi_probe(struct device *dev, struct mlxbf_i2c_priv *priv)
 
        return ret;
 }
+#else
+static int mlxbf_i2c_acpi_probe(struct device *dev, struct mlxbf_i2c_priv *priv)
+{
+       return -ENOENT;
+}
+#endif /* CONFIG_ACPI */
 
 static int mlxbf_i2c_of_probe(struct device *dev, struct mlxbf_i2c_priv *priv)
 {
@@ -2473,7 +2439,9 @@ static struct platform_driver mlxbf_i2c_driver = {
        .driver = {
                .name = "i2c-mlxbf",
                .of_match_table = mlxbf_i2c_dt_ids,
+#ifdef CONFIG_ACPI
                .acpi_match_table = ACPI_PTR(mlxbf_i2c_acpi_ids),
+#endif /* CONFIG_ACPI  */
        },
 };
 
@@ -2502,5 +2470,5 @@ static void __exit mlxbf_i2c_exit(void)
 module_exit(mlxbf_i2c_exit);
 
 MODULE_DESCRIPTION("Mellanox BlueField I2C bus driver");
-MODULE_AUTHOR("Khalil Blaiech <kblaiech@mellanox.com>");
+MODULE_AUTHOR("Khalil Blaiech <kblaiech@nvidia.com>");
 MODULE_LICENSE("GPL v2");
index 0cbdfbe605b55ebdcb3cb25e1ccac224ad9fabe2..33de99b7bc20c0ea215991c43efa1f89529e474e 100644 (file)
@@ -475,6 +475,10 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
 {
        u16 control_reg;
 
+       writel(I2C_DMA_HARD_RST, i2c->pdmabase + OFFSET_RST);
+       udelay(50);
+       writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);
+
        mtk_i2c_writew(i2c, I2C_SOFT_RST, OFFSET_SOFTRESET);
 
        /* Set ioconfig */
@@ -529,10 +533,6 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
 
        mtk_i2c_writew(i2c, control_reg, OFFSET_CONTROL);
        mtk_i2c_writew(i2c, I2C_DELAY_LEN, OFFSET_DELAY_LEN);
-
-       writel(I2C_DMA_HARD_RST, i2c->pdmabase + OFFSET_RST);
-       udelay(50);
-       writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);
 }
 
 static const struct i2c_spec_values *mtk_i2c_get_spec(unsigned int speed)
index f13735beca584405e0394ab878e434a92ab956f7..1c259b5188de8b2e2b7d6e202d088ee51c7f002c 100644 (file)
@@ -194,9 +194,9 @@ static irqreturn_t cci_isr(int irq, void *dev)
        if (unlikely(val & CCI_IRQ_STATUS_0_I2C_M1_ERROR)) {
                if (val & CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERR ||
                        val & CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERR)
-                       cci->master[0].status = -ENXIO;
+                       cci->master[1].status = -ENXIO;
                else
-                       cci->master[0].status = -EIO;
+                       cci->master[1].status = -EIO;
 
                writel(CCI_HALT_REQ_I2C_M1_Q0Q1, cci->base + CCI_HALT_REQ);
                ret = IRQ_HANDLED;
index fbc04b60cfd1cf76e7f657b6989f859e38504cfb..5a47915869ae41a7ee1da7a2c44f7e43a44aeebb 100644 (file)
@@ -801,7 +801,8 @@ static int qup_i2c_bam_schedule_desc(struct qup_i2c_dev *qup)
        if (ret || qup->bus_err || qup->qup_err) {
                reinit_completion(&qup->xfer);
 
-               if (qup_i2c_change_state(qup, QUP_RUN_STATE)) {
+               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
+               if (ret) {
                        dev_err(qup->dev, "change to run state timed out");
                        goto desc_err;
                }
index cab7255599991962c67c629ba148f8e22278efc7..bdd60770779ad5231699da43e553d6552c392541 100644 (file)
@@ -129,6 +129,7 @@ struct sh_mobile_i2c_data {
        int sr;
        bool send_stop;
        bool stop_after_dma;
+       bool atomic_xfer;
 
        struct resource *res;
        struct dma_chan *dma_tx;
@@ -330,13 +331,15 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, enum sh_mobile_i2c_op
                ret = iic_rd(pd, ICDR);
                break;
        case OP_RX_STOP: /* enable DTE interrupt, issue stop */
-               iic_wr(pd, ICIC,
-                      ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
+               if (!pd->atomic_xfer)
+                       iic_wr(pd, ICIC,
+                              ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
                iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK);
                break;
        case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */
-               iic_wr(pd, ICIC,
-                      ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
+               if (!pd->atomic_xfer)
+                       iic_wr(pd, ICIC,
+                              ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
                ret = iic_rd(pd, ICDR);
                iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK);
                break;
@@ -429,7 +432,8 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
 
        if (wakeup) {
                pd->sr |= SW_DONE;
-               wake_up(&pd->wait);
+               if (!pd->atomic_xfer)
+                       wake_up(&pd->wait);
        }
 
        /* defeat write posting to avoid spurious WAIT interrupts */
@@ -581,6 +585,9 @@ static void start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg,
        pd->pos = -1;
        pd->sr = 0;
 
+       if (pd->atomic_xfer)
+               return;
+
        pd->dma_buf = i2c_get_dma_safe_msg_buf(pd->msg, 8);
        if (pd->dma_buf)
                sh_mobile_i2c_xfer_dma(pd);
@@ -637,15 +644,13 @@ static int poll_busy(struct sh_mobile_i2c_data *pd)
        return i ? 0 : -ETIMEDOUT;
 }
 
-static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
-                             struct i2c_msg *msgs,
-                             int num)
+static int sh_mobile_xfer(struct sh_mobile_i2c_data *pd,
+                        struct i2c_msg *msgs, int num)
 {
-       struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter);
        struct i2c_msg  *msg;
        int err = 0;
        int i;
-       long timeout;
+       long time_left;
 
        /* Wake up device and enable clock */
        pm_runtime_get_sync(pd->dev);
@@ -662,15 +667,35 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
                if (do_start)
                        i2c_op(pd, OP_START);
 
-               /* The interrupt handler takes care of the rest... */
-               timeout = wait_event_timeout(pd->wait,
-                                      pd->sr & (ICSR_TACK | SW_DONE),
-                                      adapter->timeout);
-
-               /* 'stop_after_dma' tells if DMA transfer was complete */
-               i2c_put_dma_safe_msg_buf(pd->dma_buf, pd->msg, pd->stop_after_dma);
+               if (pd->atomic_xfer) {
+                       unsigned long j = jiffies + pd->adap.timeout;
+
+                       time_left = time_before_eq(jiffies, j);
+                       while (time_left &&
+                              !(pd->sr & (ICSR_TACK | SW_DONE))) {
+                               unsigned char sr = iic_rd(pd, ICSR);
+
+                               if (sr & (ICSR_AL   | ICSR_TACK |
+                                         ICSR_WAIT | ICSR_DTE)) {
+                                       sh_mobile_i2c_isr(0, pd);
+                                       udelay(150);
+                               } else {
+                                       cpu_relax();
+                               }
+                               time_left = time_before_eq(jiffies, j);
+                       }
+               } else {
+                       /* The interrupt handler takes care of the rest... */
+                       time_left = wait_event_timeout(pd->wait,
+                                       pd->sr & (ICSR_TACK | SW_DONE),
+                                       pd->adap.timeout);
+
+                       /* 'stop_after_dma' tells if DMA xfer was complete */
+                       i2c_put_dma_safe_msg_buf(pd->dma_buf, pd->msg,
+                                                pd->stop_after_dma);
+               }
 
-               if (!timeout) {
+               if (!time_left) {
                        dev_err(pd->dev, "Transfer request timed out\n");
                        if (pd->dma_direction != DMA_NONE)
                                sh_mobile_i2c_cleanup_dma(pd);
@@ -696,14 +721,35 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
        return err ?: num;
 }
 
+static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
+                             struct i2c_msg *msgs,
+                             int num)
+{
+       struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter);
+
+       pd->atomic_xfer = false;
+       return sh_mobile_xfer(pd, msgs, num);
+}
+
+static int sh_mobile_i2c_xfer_atomic(struct i2c_adapter *adapter,
+                                    struct i2c_msg *msgs,
+                                    int num)
+{
+       struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter);
+
+       pd->atomic_xfer = true;
+       return sh_mobile_xfer(pd, msgs, num);
+}
+
 static u32 sh_mobile_i2c_func(struct i2c_adapter *adapter)
 {
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;
 }
 
 static const struct i2c_algorithm sh_mobile_i2c_algorithm = {
-       .functionality  = sh_mobile_i2c_func,
-       .master_xfer    = sh_mobile_i2c_xfer,
+       .functionality = sh_mobile_i2c_func,
+       .master_xfer = sh_mobile_i2c_xfer,
+       .master_xfer_atomic = sh_mobile_i2c_xfer_atomic,
 };
 
 static const struct i2c_adapter_quirks sh_mobile_i2c_quirks = {
index 56f5b8077cbad7b1f096c3ee596374d2dffefc1c..d79335506ecd3c3f5aa3beabde8e0dd74cef10a3 100644 (file)
@@ -126,26 +126,9 @@ static __cpuidle int intel_idle(struct cpuidle_device *dev,
        struct cpuidle_state *state = &drv->states[index];
        unsigned long eax = flg2MWAIT(state->flags);
        unsigned long ecx = 1; /* break on interrupt flag */
-       bool tick;
-
-       if (!static_cpu_has(X86_FEATURE_ARAT)) {
-               /*
-                * Switch over to one-shot tick broadcast if the target C-state
-                * is deeper than C1.
-                */
-               if ((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) {
-                       tick = true;
-                       tick_broadcast_enter();
-               } else {
-                       tick = false;
-               }
-       }
 
        mwait_idle_with_hints(eax, ecx);
 
-       if (!static_cpu_has(X86_FEATURE_ARAT) && tick)
-               tick_broadcast_exit();
-
        return index;
 }
 
@@ -1157,6 +1140,20 @@ static bool __init intel_idle_max_cstate_reached(int cstate)
        return false;
 }
 
+static bool __init intel_idle_state_needs_timer_stop(struct cpuidle_state *state)
+{
+       unsigned long eax = flg2MWAIT(state->flags);
+
+       if (boot_cpu_has(X86_FEATURE_ARAT))
+               return false;
+
+       /*
+        * Switch over to one-shot tick broadcast if the target C-state
+        * is deeper than C1.
+        */
+       return !!((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK);
+}
+
 #ifdef CONFIG_ACPI_PROCESSOR_CSTATE
 #include <acpi/processor.h>
 
@@ -1239,7 +1236,7 @@ static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
                struct acpi_processor_cx *cx;
                struct cpuidle_state *state;
 
-               if (intel_idle_max_cstate_reached(cstate))
+               if (intel_idle_max_cstate_reached(cstate - 1))
                        break;
 
                cx = &acpi_state_table.states[cstate];
@@ -1269,6 +1266,9 @@ static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
                if (disabled_states_mask & BIT(cstate))
                        state->flags |= CPUIDLE_FLAG_OFF;
 
+               if (intel_idle_state_needs_timer_stop(state))
+                       state->flags |= CPUIDLE_FLAG_TIMER_STOP;
+
                state->enter = intel_idle;
                state->enter_s2idle = intel_idle_s2idle;
        }
@@ -1507,6 +1507,9 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
                     !(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_ALWAYS_ENABLE)))
                        drv->states[drv->state_count].flags |= CPUIDLE_FLAG_OFF;
 
+               if (intel_idle_state_needs_timer_stop(&drv->states[drv->state_count]))
+                       drv->states[drv->state_count].flags |= CPUIDLE_FLAG_TIMER_STOP;
+
                drv->state_count++;
        }
 
index beb38d9d607dc4fac58660826f5c6473c94c9bba..560a3373ff20d769da08651759e2ca86c3e2c96f 100644 (file)
@@ -126,6 +126,12 @@ enum kx_chipset {
        KX_MAX_CHIPS /* this must be last */
 };
 
+enum kx_acpi_type {
+       ACPI_GENERIC,
+       ACPI_SMO8500,
+       ACPI_KIOX010A,
+};
+
 struct kxcjk1013_data {
        struct i2c_client *client;
        struct iio_trigger *dready_trig;
@@ -143,7 +149,7 @@ struct kxcjk1013_data {
        bool motion_trigger_on;
        int64_t timestamp;
        enum kx_chipset chipset;
-       bool is_smo8500_device;
+       enum kx_acpi_type acpi_type;
 };
 
 enum kxcjk1013_axis {
@@ -270,6 +276,32 @@ static const struct {
                              {19163, 1, 0},
                              {38326, 0, 1} };
 
+#ifdef CONFIG_ACPI
+enum kiox010a_fn_index {
+       KIOX010A_SET_LAPTOP_MODE = 1,
+       KIOX010A_SET_TABLET_MODE = 2,
+};
+
+static int kiox010a_dsm(struct device *dev, int fn_index)
+{
+       acpi_handle handle = ACPI_HANDLE(dev);
+       guid_t kiox010a_dsm_guid;
+       union acpi_object *obj;
+
+       if (!handle)
+               return -ENODEV;
+
+       guid_parse("1f339696-d475-4e26-8cad-2e9f8e6d7a91", &kiox010a_dsm_guid);
+
+       obj = acpi_evaluate_dsm(handle, &kiox010a_dsm_guid, 1, fn_index, NULL);
+       if (!obj)
+               return -EIO;
+
+       ACPI_FREE(obj);
+       return 0;
+}
+#endif
+
 static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
                              enum kxcjk1013_mode mode)
 {
@@ -347,6 +379,13 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
 {
        int ret;
 
+#ifdef CONFIG_ACPI
+       if (data->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);
+       }
+#endif
+
        ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_WHO_AM_I);
        if (ret < 0) {
                dev_err(&data->client->dev, "Error reading who_am_i\n");
@@ -1247,7 +1286,7 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private)
 
 static const char *kxcjk1013_match_acpi_device(struct device *dev,
                                               enum kx_chipset *chipset,
-                                              bool *is_smo8500_device)
+                                              enum kx_acpi_type *acpi_type)
 {
        const struct acpi_device_id *id;
 
@@ -1256,7 +1295,9 @@ static const char *kxcjk1013_match_acpi_device(struct device *dev,
                return NULL;
 
        if (strcmp(id->id, "SMO8500") == 0)
-               *is_smo8500_device = true;
+               *acpi_type = ACPI_SMO8500;
+       else if (strcmp(id->id, "KIOX010A") == 0)
+               *acpi_type = ACPI_KIOX010A;
 
        *chipset = (enum kx_chipset)id->driver_data;
 
@@ -1299,7 +1340,7 @@ static int kxcjk1013_probe(struct i2c_client *client,
        } else if (ACPI_HANDLE(&client->dev)) {
                name = kxcjk1013_match_acpi_device(&client->dev,
                                                   &data->chipset,
-                                                  &data->is_smo8500_device);
+                                                  &data->acpi_type);
        } else
                return -ENODEV;
 
@@ -1316,7 +1357,7 @@ static int kxcjk1013_probe(struct i2c_client *client,
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &kxcjk1013_info;
 
-       if (client->irq > 0 && !data->is_smo8500_device) {
+       if (client->irq > 0 && data->acpi_type != ACPI_SMO8500) {
                ret = devm_request_threaded_irq(&client->dev, client->irq,
                                                kxcjk1013_data_rdy_trig_poll,
                                                kxcjk1013_event_handler,
index 92b25083e23f10633be5d62c4432dcba078be895..1aafbe2cfe676c42090b1d0fee8d732d20c48e75 100644 (file)
@@ -71,7 +71,7 @@
 #define JZ4725B_ADC_BATTERY_HIGH_VREF_BITS     10
 #define JZ4740_ADC_BATTERY_HIGH_VREF           (7500 * 0.986)
 #define JZ4740_ADC_BATTERY_HIGH_VREF_BITS      12
-#define JZ4770_ADC_BATTERY_VREF                        6600
+#define JZ4770_ADC_BATTERY_VREF                        1200
 #define JZ4770_ADC_BATTERY_VREF_BITS           12
 
 #define JZ_ADC_IRQ_AUX                 BIT(0)
@@ -177,13 +177,12 @@ static void ingenic_adc_set_config(struct ingenic_adc *adc,
        mutex_unlock(&adc->lock);
 }
 
-static void ingenic_adc_enable(struct ingenic_adc *adc,
-                              int engine,
-                              bool enabled)
+static void ingenic_adc_enable_unlocked(struct ingenic_adc *adc,
+                                       int engine,
+                                       bool enabled)
 {
        u8 val;
 
-       mutex_lock(&adc->lock);
        val = readb(adc->base + JZ_ADC_REG_ENABLE);
 
        if (enabled)
@@ -192,20 +191,41 @@ static void ingenic_adc_enable(struct ingenic_adc *adc,
                val &= ~BIT(engine);
 
        writeb(val, adc->base + JZ_ADC_REG_ENABLE);
+}
+
+static void ingenic_adc_enable(struct ingenic_adc *adc,
+                              int engine,
+                              bool enabled)
+{
+       mutex_lock(&adc->lock);
+       ingenic_adc_enable_unlocked(adc, engine, enabled);
        mutex_unlock(&adc->lock);
 }
 
 static int ingenic_adc_capture(struct ingenic_adc *adc,
                               int engine)
 {
+       u32 cfg;
        u8 val;
        int ret;
 
-       ingenic_adc_enable(adc, engine, true);
+       /*
+        * Disable CMD_SEL temporarily, because it causes wrong VBAT readings,
+        * probably due to the switch of VREF. We must keep the lock here to
+        * avoid races with the buffer enable/disable functions.
+        */
+       mutex_lock(&adc->lock);
+       cfg = readl(adc->base + JZ_ADC_REG_CFG);
+       writel(cfg & ~JZ_ADC_REG_CFG_CMD_SEL, adc->base + JZ_ADC_REG_CFG);
+
+       ingenic_adc_enable_unlocked(adc, engine, true);
        ret = readb_poll_timeout(adc->base + JZ_ADC_REG_ENABLE, val,
                                 !(val & BIT(engine)), 250, 1000);
        if (ret)
-               ingenic_adc_enable(adc, engine, false);
+               ingenic_adc_enable_unlocked(adc, engine, false);
+
+       writel(cfg, adc->base + JZ_ADC_REG_CFG);
+       mutex_unlock(&adc->lock);
 
        return ret;
 }
index ac415cb089cdd080695d77edc5ba1898961e6a89..79c1dd68b9092c2449967f12837e0a3314114f70 100644 (file)
@@ -9,9 +9,9 @@
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/mod_devicetable.h>
 #include <linux/platform_device.h>
+#include <linux/property.h>
 #include <linux/iopoll.h>
 #include <linux/io.h>
 #include <linux/iio/iio.h>
@@ -276,6 +276,8 @@ static int mt6577_auxadc_probe(struct platform_device *pdev)
                goto err_disable_clk;
        }
 
+       adc_dev->dev_comp = device_get_match_data(&pdev->dev);
+
        mutex_init(&adc_dev->lock);
 
        mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
index cd870c08918262e4c4e8c2560d9e8de1151c7bc4..a83199b212a430c11f0b42b6fe09a3a163ae0756 100644 (file)
  * struct stm32_adc_common_regs - stm32 common registers
  * @csr:       common status register offset
  * @ccr:       common control register offset
- * @eoc1_msk:  adc1 end of conversion flag in @csr
- * @eoc2_msk:  adc2 end of conversion flag in @csr
- * @eoc3_msk:  adc3 end of conversion flag in @csr
+ * @eoc_msk:    array of eoc (end of conversion flag) masks in csr for adc1..n
+ * @ovr_msk:    array of ovr (overrun flag) masks in csr for adc1..n
  * @ier:       interrupt enable register offset for each adc
  * @eocie_msk: end of conversion interrupt enable mask in @ier
  */
 struct stm32_adc_common_regs {
        u32 csr;
        u32 ccr;
-       u32 eoc1_msk;
-       u32 eoc2_msk;
-       u32 eoc3_msk;
+       u32 eoc_msk[STM32_ADC_MAX_ADCS];
+       u32 ovr_msk[STM32_ADC_MAX_ADCS];
        u32 ier;
        u32 eocie_msk;
 };
@@ -282,21 +280,20 @@ out:
 static const struct stm32_adc_common_regs stm32f4_adc_common_regs = {
        .csr = STM32F4_ADC_CSR,
        .ccr = STM32F4_ADC_CCR,
-       .eoc1_msk = STM32F4_EOC1 | STM32F4_OVR1,
-       .eoc2_msk = STM32F4_EOC2 | STM32F4_OVR2,
-       .eoc3_msk = STM32F4_EOC3 | STM32F4_OVR3,
+       .eoc_msk = { STM32F4_EOC1, STM32F4_EOC2, STM32F4_EOC3},
+       .ovr_msk = { STM32F4_OVR1, STM32F4_OVR2, STM32F4_OVR3},
        .ier = STM32F4_ADC_CR1,
-       .eocie_msk = STM32F4_EOCIE | STM32F4_OVRIE,
+       .eocie_msk = STM32F4_EOCIE,
 };
 
 /* STM32H7 common registers definitions */
 static const struct stm32_adc_common_regs stm32h7_adc_common_regs = {
        .csr = STM32H7_ADC_CSR,
        .ccr = STM32H7_ADC_CCR,
-       .eoc1_msk = STM32H7_EOC_MST | STM32H7_OVR_MST,
-       .eoc2_msk = STM32H7_EOC_SLV | STM32H7_OVR_SLV,
+       .eoc_msk = { STM32H7_EOC_MST, STM32H7_EOC_SLV},
+       .ovr_msk = { STM32H7_OVR_MST, STM32H7_OVR_SLV},
        .ier = STM32H7_ADC_IER,
-       .eocie_msk = STM32H7_EOCIE | STM32H7_OVRIE,
+       .eocie_msk = STM32H7_EOCIE,
 };
 
 static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = {
@@ -318,6 +315,7 @@ static void stm32_adc_irq_handler(struct irq_desc *desc)
 {
        struct stm32_adc_priv *priv = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
+       int i;
        u32 status;
 
        chained_irq_enter(chip, desc);
@@ -335,17 +333,12 @@ static void stm32_adc_irq_handler(struct irq_desc *desc)
         * before invoking the interrupt handler (e.g. call ISR only for
         * IRQ-enabled ADCs).
         */
-       if (status & priv->cfg->regs->eoc1_msk &&
-           stm32_adc_eoc_enabled(priv, 0))
-               generic_handle_irq(irq_find_mapping(priv->domain, 0));
-
-       if (status & priv->cfg->regs->eoc2_msk &&
-           stm32_adc_eoc_enabled(priv, 1))
-               generic_handle_irq(irq_find_mapping(priv->domain, 1));
-
-       if (status & priv->cfg->regs->eoc3_msk &&
-           stm32_adc_eoc_enabled(priv, 2))
-               generic_handle_irq(irq_find_mapping(priv->domain, 2));
+       for (i = 0; i < priv->cfg->num_irqs; i++) {
+               if ((status & priv->cfg->regs->eoc_msk[i] &&
+                    stm32_adc_eoc_enabled(priv, i)) ||
+                    (status & priv->cfg->regs->ovr_msk[i]))
+                       generic_handle_irq(irq_find_mapping(priv->domain, i));
+       }
 
        chained_irq_exit(chip, desc);
 };
index b3f31f14734725accf978f43202adeee82966dd6..16c02c30dec7558e6d57e1ad6e5962fe057c9bea 100644 (file)
@@ -154,6 +154,7 @@ struct stm32_adc;
  * @start_conv:                routine to start conversions
  * @stop_conv:         routine to stop conversions
  * @unprepare:         optional unprepare routine (disable, power-down)
+ * @irq_clear:         routine to clear irqs
  * @smp_cycles:                programmable sampling time (ADC clock cycles)
  */
 struct stm32_adc_cfg {
@@ -166,6 +167,7 @@ struct stm32_adc_cfg {
        void (*start_conv)(struct iio_dev *, bool dma);
        void (*stop_conv)(struct iio_dev *);
        void (*unprepare)(struct iio_dev *);
+       void (*irq_clear)(struct iio_dev *indio_dev, u32 msk);
        const unsigned int *smp_cycles;
 };
 
@@ -621,6 +623,13 @@ static void stm32f4_adc_stop_conv(struct iio_dev *indio_dev)
                           STM32F4_ADON | STM32F4_DMA | STM32F4_DDS);
 }
 
+static void stm32f4_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
+{
+       struct stm32_adc *adc = iio_priv(indio_dev);
+
+       stm32_adc_clr_bits(adc, adc->cfg->regs->isr_eoc.reg, msk);
+}
+
 static void stm32h7_adc_start_conv(struct iio_dev *indio_dev, bool dma)
 {
        struct stm32_adc *adc = iio_priv(indio_dev);
@@ -659,6 +668,13 @@ static void stm32h7_adc_stop_conv(struct iio_dev *indio_dev)
        stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK);
 }
 
+static void stm32h7_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
+{
+       struct stm32_adc *adc = iio_priv(indio_dev);
+       /* On STM32H7 IRQs are cleared by writing 1 into ISR register */
+       stm32_adc_set_bits(adc, adc->cfg->regs->isr_eoc.reg, msk);
+}
+
 static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev)
 {
        struct stm32_adc *adc = iio_priv(indio_dev);
@@ -1235,17 +1251,40 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev,
        }
 }
 
+static void stm32_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
+{
+       struct stm32_adc *adc = iio_priv(indio_dev);
+
+       adc->cfg->irq_clear(indio_dev, msk);
+}
+
 static irqreturn_t stm32_adc_threaded_isr(int irq, void *data)
 {
        struct iio_dev *indio_dev = data;
        struct stm32_adc *adc = iio_priv(indio_dev);
        const struct stm32_adc_regspec *regs = adc->cfg->regs;
        u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
+       u32 mask = stm32_adc_readl(adc, regs->ier_eoc.reg);
 
-       if (status & regs->isr_ovr.mask)
+       /* Check ovr status right now, as ovr mask should be already disabled */
+       if (status & regs->isr_ovr.mask) {
+               /*
+                * Clear ovr bit to avoid subsequent calls to IRQ handler.
+                * This requires to stop ADC first. OVR bit state in ISR,
+                * is propaged to CSR register by hardware.
+                */
+               adc->cfg->stop_conv(indio_dev);
+               stm32_adc_irq_clear(indio_dev, regs->isr_ovr.mask);
                dev_err(&indio_dev->dev, "Overrun, stopping: restart needed\n");
+               return IRQ_HANDLED;
+       }
 
-       return IRQ_HANDLED;
+       if (!(status & mask))
+               dev_err_ratelimited(&indio_dev->dev,
+                                   "Unexpected IRQ: IER=0x%08x, ISR=0x%08x\n",
+                                   mask, status);
+
+       return IRQ_NONE;
 }
 
 static irqreturn_t stm32_adc_isr(int irq, void *data)
@@ -1254,6 +1293,10 @@ static irqreturn_t stm32_adc_isr(int irq, void *data)
        struct stm32_adc *adc = iio_priv(indio_dev);
        const struct stm32_adc_regspec *regs = adc->cfg->regs;
        u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
+       u32 mask = stm32_adc_readl(adc, regs->ier_eoc.reg);
+
+       if (!(status & mask))
+               return IRQ_WAKE_THREAD;
 
        if (status & regs->isr_ovr.mask) {
                /*
@@ -2046,6 +2089,7 @@ static const struct stm32_adc_cfg stm32f4_adc_cfg = {
        .start_conv = stm32f4_adc_start_conv,
        .stop_conv = stm32f4_adc_stop_conv,
        .smp_cycles = stm32f4_adc_smp_cycles,
+       .irq_clear = stm32f4_adc_irq_clear,
 };
 
 static const struct stm32_adc_cfg stm32h7_adc_cfg = {
@@ -2057,6 +2101,7 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = {
        .prepare = stm32h7_adc_prepare,
        .unprepare = stm32h7_adc_unprepare,
        .smp_cycles = stm32h7_adc_smp_cycles,
+       .irq_clear = stm32h7_adc_irq_clear,
 };
 
 static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
@@ -2069,6 +2114,7 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
        .prepare = stm32h7_adc_prepare,
        .unprepare = stm32h7_adc_unprepare,
        .smp_cycles = stm32h7_adc_smp_cycles,
+       .irq_clear = stm32h7_adc_irq_clear,
 };
 
 static const struct of_device_id stm32_adc_of_match[] = {
index c62cacc04672ba1f79c660117b25161dfc9b361a..e3f507771f17e6d38aa0c5f0dd0d4ac42ef56651 100644 (file)
@@ -256,7 +256,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
        struct cros_ec_sensorhub *sensor_hub = dev_get_drvdata(dev->parent);
        struct cros_ec_dev *ec = sensor_hub->ec;
        struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
-       u32 ver_mask;
+       u32 ver_mask, temp;
        int frequencies[ARRAY_SIZE(state->frequencies) / 2] = { 0 };
        int ret, i;
 
@@ -311,10 +311,16 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
                                                 &frequencies[2],
                                                 &state->fifo_max_event_count);
                } else {
-                       frequencies[1] = state->resp->info_3.min_frequency;
-                       frequencies[2] = state->resp->info_3.max_frequency;
-                       state->fifo_max_event_count =
-                           state->resp->info_3.fifo_max_event_count;
+                       if (state->resp->info_3.max_frequency == 0) {
+                               get_default_min_max_freq(state->resp->info.type,
+                                                        &frequencies[1],
+                                                        &frequencies[2],
+                                                        &temp);
+                       } else {
+                               frequencies[1] = state->resp->info_3.min_frequency;
+                               frequencies[2] = state->resp->info_3.max_frequency;
+                       }
+                       state->fifo_max_event_count = state->resp->info_3.fifo_max_event_count;
                }
                for (i = 0; i < ARRAY_SIZE(frequencies); i++) {
                        state->frequencies[2 * i] = frequencies[i] / 1000;
index 8c8d8870ca0755f78bb744e8533bb7cdd36b9da0..99562ba85ee430989beca58cca7f234d98d1c596 100644 (file)
@@ -156,11 +156,13 @@ static const struct st_lsm6dsx_ext_dev_settings st_lsm6dsx_ext_dev_table[] = {
 static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw)
 {
        struct st_lsm6dsx_sensor *sensor;
-       u32 odr;
+       u32 odr, timeout;
 
        sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
        odr = (hw->enable_mask & BIT(ST_LSM6DSX_ID_ACC)) ? sensor->odr : 12500;
-       msleep((2000000U / odr) + 1);
+       /* set 10ms as minimum timeout for i2c slave configuration */
+       timeout = max_t(u32, 2000000U / odr + 1, 10);
+       msleep(timeout);
 }
 
 /*
index cade6dc0305b676d71cecaa94cd24310c326d1a1..33ad4dd0b5c7b5dfba060984cedef3673874bfbf 100644 (file)
@@ -544,6 +544,7 @@ config VCNL4000
 
 config VCNL4035
        tristate "VCNL4035 combined ALS and proximity sensor"
+       select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
        select REGMAP_I2C
        depends on I2C
index 32a51432ec4f7352333ddb3042151b66ebef7607..9325e189a2153615ae36b131a89d349e08d4cc58 100644 (file)
@@ -73,6 +73,9 @@ config INFINIBAND_ADDR_TRANS_CONFIGFS
          This allows the user to config the default GID type that the CM
          uses for each device, when initiaing new connections.
 
+config INFINIBAND_VIRT_DMA
+       def_bool !HIGHMEM
+
 if INFINIBAND_USER_ACCESS || !INFINIBAND_USER_ACCESS
 source "drivers/infiniband/hw/mthca/Kconfig"
 source "drivers/infiniband/hw/qib/Kconfig"
index 5740d1ba3568700759290d907560f27148e9dc21..012156624b8299a11f38bcda378505240cc96a42 100644 (file)
@@ -859,8 +859,8 @@ static struct cm_id_private *cm_alloc_id_priv(struct ib_device *device,
        atomic_set(&cm_id_priv->work_count, -1);
        refcount_set(&cm_id_priv->refcount, 1);
 
-       ret = xa_alloc_cyclic_irq(&cm.local_id_table, &id, NULL, xa_limit_32b,
-                                 &cm.local_id_next, GFP_KERNEL);
+       ret = xa_alloc_cyclic(&cm.local_id_table, &id, NULL, xa_limit_32b,
+                             &cm.local_id_next, GFP_KERNEL);
        if (ret < 0)
                goto error;
        cm_id_priv->id.local_id = (__force __be32)id ^ cm.random_id_operand;
@@ -878,8 +878,8 @@ error:
  */
 static void cm_finalize_id(struct cm_id_private *cm_id_priv)
 {
-       xa_store_irq(&cm.local_id_table, cm_local_id(cm_id_priv->id.local_id),
-                    cm_id_priv, GFP_KERNEL);
+       xa_store(&cm.local_id_table, cm_local_id(cm_id_priv->id.local_id),
+                cm_id_priv, GFP_ATOMIC);
 }
 
 struct ib_cm_id *ib_create_cm_id(struct ib_device *device,
@@ -1169,7 +1169,7 @@ retest:
        spin_unlock(&cm.lock);
        spin_unlock_irq(&cm_id_priv->lock);
 
-       xa_erase_irq(&cm.local_id_table, cm_local_id(cm_id->local_id));
+       xa_erase(&cm.local_id_table, cm_local_id(cm_id->local_id));
        cm_deref_id(cm_id_priv);
        wait_for_completion(&cm_id_priv->comp);
        while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
@@ -4482,7 +4482,7 @@ static int __init ib_cm_init(void)
        cm.remote_id_table = RB_ROOT;
        cm.remote_qp_table = RB_ROOT;
        cm.remote_sidr_table = RB_ROOT;
-       xa_init_flags(&cm.local_id_table, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ);
+       xa_init_flags(&cm.local_id_table, XA_FLAGS_ALLOC);
        get_random_bytes(&cm.random_id_operand, sizeof cm.random_id_operand);
        INIT_LIST_HEAD(&cm.timewait_list);
 
index 7c2ab1f2fbea3785d445f06a2d463330de59a231..a77750b8954db039ebeb2f040e7a028fb011da16 100644 (file)
@@ -405,10 +405,10 @@ static int cma_comp_exch(struct rdma_id_private *id_priv,
        /*
         * The FSM uses a funny double locking where state is protected by both
         * the handler_mutex and the spinlock. State is not allowed to change
-        * away from a handler_mutex protected value without also holding
+        * to/from a handler_mutex protected value without also holding
         * handler_mutex.
         */
-       if (comp == RDMA_CM_CONNECT)
+       if (comp == RDMA_CM_CONNECT || exch == RDMA_CM_CONNECT)
                lockdep_assert_held(&id_priv->handler_mutex);
 
        spin_lock_irqsave(&id_priv->lock, flags);
@@ -4038,17 +4038,23 @@ out:
        return ret;
 }
 
-int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
+/**
+ * rdma_connect_locked - Initiate an active connection request.
+ * @id: Connection identifier to connect.
+ * @conn_param: Connection information used for connected QPs.
+ *
+ * Same as rdma_connect() but can only be called from the
+ * RDMA_CM_EVENT_ROUTE_RESOLVED handler callback.
+ */
+int rdma_connect_locked(struct rdma_cm_id *id,
+                       struct rdma_conn_param *conn_param)
 {
        struct rdma_id_private *id_priv =
                container_of(id, struct rdma_id_private, id);
        int ret;
 
-       mutex_lock(&id_priv->handler_mutex);
-       if (!cma_comp_exch(id_priv, RDMA_CM_ROUTE_RESOLVED, RDMA_CM_CONNECT)) {
-               ret = -EINVAL;
-               goto err_unlock;
-       }
+       if (!cma_comp_exch(id_priv, RDMA_CM_ROUTE_RESOLVED, RDMA_CM_CONNECT))
+               return -EINVAL;
 
        if (!id->qp) {
                id_priv->qp_num = conn_param->qp_num;
@@ -4066,11 +4072,33 @@ int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
                ret = -ENOSYS;
        if (ret)
                goto err_state;
-       mutex_unlock(&id_priv->handler_mutex);
        return 0;
 err_state:
        cma_comp_exch(id_priv, RDMA_CM_CONNECT, RDMA_CM_ROUTE_RESOLVED);
-err_unlock:
+       return ret;
+}
+EXPORT_SYMBOL(rdma_connect_locked);
+
+/**
+ * rdma_connect - Initiate an active connection request.
+ * @id: Connection identifier to connect.
+ * @conn_param: Connection information used for connected QPs.
+ *
+ * Users must have resolved a route for the rdma_cm_id to connect with by having
+ * called rdma_resolve_route before calling this routine.
+ *
+ * This call will either connect to a remote QP or obtain remote QP information
+ * for unconnected rdma_cm_id's.  The actual operation is based on the
+ * rdma_cm_id's port space.
+ */
+int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
+{
+       struct rdma_id_private *id_priv =
+               container_of(id, struct rdma_id_private, id);
+       int ret;
+
+       mutex_lock(&id_priv->handler_mutex);
+       ret = rdma_connect_locked(id, conn_param);
        mutex_unlock(&id_priv->handler_mutex);
        return ret;
 }
index f367d523a46b81d0ff94cb7444d66e5d04dc6439..302f898c5833fce490c052fb5eb2450a703848fe 100644 (file)
@@ -401,9 +401,6 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_GID_ENTRY)(
        if (!rdma_is_port_valid(ib_dev, port_num))
                return -EINVAL;
 
-       if (!rdma_ib_or_roce(ib_dev, port_num))
-               return -EOPNOTSUPP;
-
        gid_attr = rdma_get_gid_attr(ib_dev, port_num, gid_index);
        if (IS_ERR(gid_attr))
                return PTR_ERR(gid_attr);
index 7eaf995382168803c955489bacb014d57e7ba18c..c87b94ea2939743cd4dad351b0c787699b4b7f89 100644 (file)
@@ -15245,7 +15245,8 @@ int hfi1_init_dd(struct hfi1_devdata *dd)
                    & CCE_REVISION_SW_MASK);
 
        /* alloc netdev data */
-       if (hfi1_netdev_alloc(dd))
+       ret = hfi1_netdev_alloc(dd);
+       if (ret)
                goto bail_cleanup;
 
        ret = set_up_context_variables(dd);
index 8ca51e43cf53030a1c0b33a5c9dae3de409a276a..329ee4f48d9576f3635db7b362d8d206832f98a1 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright(c) 2020 Cornelis Networks, Inc.
  * Copyright(c) 2015-2020 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
@@ -206,8 +207,6 @@ static int hfi1_file_open(struct inode *inode, struct file *fp)
        spin_lock_init(&fd->tid_lock);
        spin_lock_init(&fd->invalid_lock);
        fd->rec_cpu_num = -1; /* no cpu affinity by default */
-       fd->mm = current->mm;
-       mmgrab(fd->mm);
        fd->dd = dd;
        fp->private_data = fd;
        return 0;
@@ -711,7 +710,6 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
 
        deallocate_ctxt(uctxt);
 done:
-       mmdrop(fdata->mm);
 
        if (atomic_dec_and_test(&dd->user_refcount))
                complete(&dd->user_comp);
index b4c6bff60a4e814e1ed241d2e51c9f544b47c422..e09e8244a94c4e2201ce73ea79fd26d04414e349 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _HFI1_KERNEL_H
 #define _HFI1_KERNEL_H
 /*
+ * Copyright(c) 2020 Cornelis Networks, Inc.
  * Copyright(c) 2015-2020 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
@@ -1451,7 +1452,6 @@ struct hfi1_filedata {
        u32 invalid_tid_idx;
        /* protect invalid_tids array and invalid_tid_idx */
        spinlock_t invalid_lock;
-       struct mm_struct *mm;
 };
 
 extern struct xarray hfi1_dev_table;
index 24ca17b77b72b8e0c42733b801d6521047244246..f3fb28e3d5d74060f9d299df5870292f621fff79 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright(c) 2020 Cornelis Networks, Inc.
  * Copyright(c) 2016 - 2017 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
 #include <linux/rculist.h>
 #include <linux/mmu_notifier.h>
 #include <linux/interval_tree_generic.h>
+#include <linux/sched/mm.h>
 
 #include "mmu_rb.h"
 #include "trace.h"
 
-struct mmu_rb_handler {
-       struct mmu_notifier mn;
-       struct rb_root_cached root;
-       void *ops_arg;
-       spinlock_t lock;        /* protect the RB tree */
-       struct mmu_rb_ops *ops;
-       struct mm_struct *mm;
-       struct list_head lru_list;
-       struct work_struct del_work;
-       struct list_head del_list;
-       struct workqueue_struct *wq;
-};
-
 static unsigned long mmu_node_start(struct mmu_rb_node *);
 static unsigned long mmu_node_last(struct mmu_rb_node *);
 static int mmu_notifier_range_start(struct mmu_notifier *,
@@ -92,37 +81,36 @@ static unsigned long mmu_node_last(struct mmu_rb_node *node)
        return PAGE_ALIGN(node->addr + node->len) - 1;
 }
 
-int hfi1_mmu_rb_register(void *ops_arg, struct mm_struct *mm,
+int hfi1_mmu_rb_register(void *ops_arg,
                         struct mmu_rb_ops *ops,
                         struct workqueue_struct *wq,
                         struct mmu_rb_handler **handler)
 {
-       struct mmu_rb_handler *handlr;
+       struct mmu_rb_handler *h;
        int ret;
 
-       handlr = kmalloc(sizeof(*handlr), GFP_KERNEL);
-       if (!handlr)
+       h = kmalloc(sizeof(*h), GFP_KERNEL);
+       if (!h)
                return -ENOMEM;
 
-       handlr->root = RB_ROOT_CACHED;
-       handlr->ops = ops;
-       handlr->ops_arg = ops_arg;
-       INIT_HLIST_NODE(&handlr->mn.hlist);
-       spin_lock_init(&handlr->lock);
-       handlr->mn.ops = &mn_opts;
-       handlr->mm = mm;
-       INIT_WORK(&handlr->del_work, handle_remove);
-       INIT_LIST_HEAD(&handlr->del_list);
-       INIT_LIST_HEAD(&handlr->lru_list);
-       handlr->wq = wq;
-
-       ret = mmu_notifier_register(&handlr->mn, handlr->mm);
+       h->root = RB_ROOT_CACHED;
+       h->ops = ops;
+       h->ops_arg = ops_arg;
+       INIT_HLIST_NODE(&h->mn.hlist);
+       spin_lock_init(&h->lock);
+       h->mn.ops = &mn_opts;
+       INIT_WORK(&h->del_work, handle_remove);
+       INIT_LIST_HEAD(&h->del_list);
+       INIT_LIST_HEAD(&h->lru_list);
+       h->wq = wq;
+
+       ret = mmu_notifier_register(&h->mn, current->mm);
        if (ret) {
-               kfree(handlr);
+               kfree(h);
                return ret;
        }
 
-       *handler = handlr;
+       *handler = h;
        return 0;
 }
 
@@ -134,7 +122,7 @@ void hfi1_mmu_rb_unregister(struct mmu_rb_handler *handler)
        struct list_head del_list;
 
        /* Unregister first so we don't get any more notifications. */
-       mmu_notifier_unregister(&handler->mn, handler->mm);
+       mmu_notifier_unregister(&handler->mn, handler->mn.mm);
 
        /*
         * Make sure the wq delete handler is finished running.  It will not
@@ -166,6 +154,10 @@ int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler,
        int ret = 0;
 
        trace_hfi1_mmu_rb_insert(mnode->addr, mnode->len);
+
+       if (current->mm != handler->mn.mm)
+               return -EPERM;
+
        spin_lock_irqsave(&handler->lock, flags);
        node = __mmu_rb_search(handler, mnode->addr, mnode->len);
        if (node) {
@@ -180,6 +172,7 @@ int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler,
                __mmu_int_rb_remove(mnode, &handler->root);
                list_del(&mnode->list); /* remove from LRU list */
        }
+       mnode->handler = handler;
 unlock:
        spin_unlock_irqrestore(&handler->lock, flags);
        return ret;
@@ -217,6 +210,9 @@ bool hfi1_mmu_rb_remove_unless_exact(struct mmu_rb_handler *handler,
        unsigned long flags;
        bool ret = false;
 
+       if (current->mm != handler->mn.mm)
+               return ret;
+
        spin_lock_irqsave(&handler->lock, flags);
        node = __mmu_rb_search(handler, addr, len);
        if (node) {
@@ -239,6 +235,9 @@ void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg)
        unsigned long flags;
        bool stop = false;
 
+       if (current->mm != handler->mn.mm)
+               return;
+
        INIT_LIST_HEAD(&del_list);
 
        spin_lock_irqsave(&handler->lock, flags);
@@ -272,6 +271,9 @@ void hfi1_mmu_rb_remove(struct mmu_rb_handler *handler,
 {
        unsigned long flags;
 
+       if (current->mm != handler->mn.mm)
+               return;
+
        /* Validity of handler and node pointers has been checked by caller. */
        trace_hfi1_mmu_rb_remove(node->addr, node->len);
        spin_lock_irqsave(&handler->lock, flags);
index f04cec1e99d11a2d1edb2640667a9156ccca3828..423aacc67e9488aa70dbf18fa91cb2570d37f0d7 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright(c) 2020 Cornelis Networks, Inc.
  * Copyright(c) 2016 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
@@ -54,6 +55,7 @@ struct mmu_rb_node {
        unsigned long len;
        unsigned long __last;
        struct rb_node node;
+       struct mmu_rb_handler *handler;
        struct list_head list;
 };
 
@@ -71,7 +73,19 @@ struct mmu_rb_ops {
                     void *evict_arg, bool *stop);
 };
 
-int hfi1_mmu_rb_register(void *ops_arg, struct mm_struct *mm,
+struct mmu_rb_handler {
+       struct mmu_notifier mn;
+       struct rb_root_cached root;
+       void *ops_arg;
+       spinlock_t lock;        /* protect the RB tree */
+       struct mmu_rb_ops *ops;
+       struct list_head lru_list;
+       struct work_struct del_work;
+       struct list_head del_list;
+       struct workqueue_struct *wq;
+};
+
+int hfi1_mmu_rb_register(void *ops_arg,
                         struct mmu_rb_ops *ops,
                         struct workqueue_struct *wq,
                         struct mmu_rb_handler **handler);
index f81ca20f4b693e1597fc1cd10d62a21acdf05a2f..b94fc7fd75a9618739e23b6cab14490d8392e0cb 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright(c) 2020 Cornelis Networks, Inc.
  * Copyright(c) 2015-2018 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
@@ -173,15 +174,18 @@ static void unpin_rcv_pages(struct hfi1_filedata *fd,
 {
        struct page **pages;
        struct hfi1_devdata *dd = fd->uctxt->dd;
+       struct mm_struct *mm;
 
        if (mapped) {
                pci_unmap_single(dd->pcidev, node->dma_addr,
                                 node->npages * PAGE_SIZE, PCI_DMA_FROMDEVICE);
                pages = &node->pages[idx];
+               mm = mm_from_tid_node(node);
        } else {
                pages = &tidbuf->pages[idx];
+               mm = current->mm;
        }
-       hfi1_release_user_pages(fd->mm, pages, npages, mapped);
+       hfi1_release_user_pages(mm, pages, npages, mapped);
        fd->tid_n_pinned -= npages;
 }
 
@@ -216,12 +220,12 @@ static int pin_rcv_pages(struct hfi1_filedata *fd, struct tid_user_buf *tidbuf)
         * pages, accept the amount pinned so far and program only that.
         * User space knows how to deal with partially programmed buffers.
         */
-       if (!hfi1_can_pin_pages(dd, fd->mm, fd->tid_n_pinned, npages)) {
+       if (!hfi1_can_pin_pages(dd, current->mm, fd->tid_n_pinned, npages)) {
                kfree(pages);
                return -ENOMEM;
        }
 
-       pinned = hfi1_acquire_user_pages(fd->mm, vaddr, npages, true, pages);
+       pinned = hfi1_acquire_user_pages(current->mm, vaddr, npages, true, pages);
        if (pinned <= 0) {
                kfree(pages);
                return pinned;
@@ -756,7 +760,7 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd,
 
        if (fd->use_mn) {
                ret = mmu_interval_notifier_insert(
-                       &node->notifier, fd->mm,
+                       &node->notifier, current->mm,
                        tbuf->vaddr + (pageidx * PAGE_SIZE), npages * PAGE_SIZE,
                        &tid_mn_ops);
                if (ret)
index 332abb446861a9354fea43c21dc5379ea2314625..d45c7b6988d4d56ec284669d97bc2415361f199b 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _HFI1_USER_EXP_RCV_H
 #define _HFI1_USER_EXP_RCV_H
 /*
+ * Copyright(c) 2020 - Cornelis Networks, Inc.
  * Copyright(c) 2015 - 2017 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
@@ -95,4 +96,9 @@ int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd,
 int hfi1_user_exp_rcv_invalid(struct hfi1_filedata *fd,
                              struct hfi1_tid_info *tinfo);
 
+static inline struct mm_struct *mm_from_tid_node(struct tid_rb_node *node)
+{
+       return node->notifier.mm;
+}
+
 #endif /* _HFI1_USER_EXP_RCV_H */
index a92346e88628bd0a9d214df2b58e0aaf4e891ec9..4a4956f96a7ebccdc75bfa7ca5372874f3a6a03c 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright(c) 2020 - Cornelis Networks, Inc.
  * Copyright(c) 2015 - 2018 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
@@ -188,7 +189,6 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt,
        atomic_set(&pq->n_reqs, 0);
        init_waitqueue_head(&pq->wait);
        atomic_set(&pq->n_locked, 0);
-       pq->mm = fd->mm;
 
        iowait_init(&pq->busy, 0, NULL, NULL, defer_packet_queue,
                    activate_packet_queue, NULL, NULL);
@@ -230,7 +230,7 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt,
 
        cq->nentries = hfi1_sdma_comp_ring_size;
 
-       ret = hfi1_mmu_rb_register(pq, pq->mm, &sdma_rb_ops, dd->pport->hfi1_wq,
+       ret = hfi1_mmu_rb_register(pq, &sdma_rb_ops, dd->pport->hfi1_wq,
                                   &pq->handler);
        if (ret) {
                dd_dev_err(dd, "Failed to register with MMU %d", ret);
@@ -980,13 +980,13 @@ static int pin_sdma_pages(struct user_sdma_request *req,
 
        npages -= node->npages;
 retry:
-       if (!hfi1_can_pin_pages(pq->dd, pq->mm,
+       if (!hfi1_can_pin_pages(pq->dd, current->mm,
                                atomic_read(&pq->n_locked), npages)) {
                cleared = sdma_cache_evict(pq, npages);
                if (cleared >= npages)
                        goto retry;
        }
-       pinned = hfi1_acquire_user_pages(pq->mm,
+       pinned = hfi1_acquire_user_pages(current->mm,
                                         ((unsigned long)iovec->iov.iov_base +
                                         (node->npages * PAGE_SIZE)), npages, 0,
                                         pages + node->npages);
@@ -995,7 +995,7 @@ retry:
                return pinned;
        }
        if (pinned != npages) {
-               unpin_vector_pages(pq->mm, pages, node->npages, pinned);
+               unpin_vector_pages(current->mm, pages, node->npages, pinned);
                return -EFAULT;
        }
        kfree(node->pages);
@@ -1008,7 +1008,8 @@ retry:
 static void unpin_sdma_pages(struct sdma_mmu_node *node)
 {
        if (node->npages) {
-               unpin_vector_pages(node->pq->mm, node->pages, 0, node->npages);
+               unpin_vector_pages(mm_from_sdma_node(node), node->pages, 0,
+                                  node->npages);
                atomic_sub(node->npages, &node->pq->n_locked);
        }
 }
index 9972e0e6545e8a56fa3b6fdaea6d0a84d8b4361f..1e8c02fe8ad1d8e6fc90dd2e53ca66d4ae99833e 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _HFI1_USER_SDMA_H
 #define _HFI1_USER_SDMA_H
 /*
+ * Copyright(c) 2020 - Cornelis Networks, Inc.
  * Copyright(c) 2015 - 2018 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
@@ -133,7 +134,6 @@ struct hfi1_user_sdma_pkt_q {
        unsigned long unpinned;
        struct mmu_rb_handler *handler;
        atomic_t n_locked;
-       struct mm_struct *mm;
 };
 
 struct hfi1_user_sdma_comp_q {
@@ -250,4 +250,9 @@ int hfi1_user_sdma_process_request(struct hfi1_filedata *fd,
                                   struct iovec *iovec, unsigned long dim,
                                   unsigned long *count);
 
+static inline struct mm_struct *mm_from_sdma_node(struct sdma_mmu_node *node)
+{
+       return node->rb.handler->mn.mm;
+}
+
 #endif /* _HFI1_USER_SDMA_H */
index 6d30850696c518d02f326e821b4267601b024dcc..0468028ffe390d3b9aaeec03ac655f26b03f3684 100644 (file)
@@ -2936,6 +2936,7 @@ static int hns_roce_v2_mw_write_mtpt(void *mb_buf, struct hns_roce_mw *mw)
 
        roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_R_INV_EN_S, 1);
        roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_L_INV_EN_S, 1);
+       roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_LW_EN_S, 1);
 
        roce_set_bit(mpt_entry->byte_12_mw_pa, V2_MPT_BYTE_12_PA_S, 0);
        roce_set_bit(mpt_entry->byte_12_mw_pa, V2_MPT_BYTE_12_MR_MW_S, 1);
@@ -4989,11 +4990,11 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
                                              V2_QPC_BYTE_28_AT_M,
                                              V2_QPC_BYTE_28_AT_S);
        qp_attr->retry_cnt = roce_get_field(context.byte_212_lsn,
-                                           V2_QPC_BYTE_212_RETRY_CNT_M,
-                                           V2_QPC_BYTE_212_RETRY_CNT_S);
+                                           V2_QPC_BYTE_212_RETRY_NUM_INIT_M,
+                                           V2_QPC_BYTE_212_RETRY_NUM_INIT_S);
        qp_attr->rnr_retry = roce_get_field(context.byte_244_rnr_rxack,
-                                           V2_QPC_BYTE_244_RNR_CNT_M,
-                                           V2_QPC_BYTE_244_RNR_CNT_S);
+                                           V2_QPC_BYTE_244_RNR_NUM_INIT_M,
+                                           V2_QPC_BYTE_244_RNR_NUM_INIT_S);
 
 done:
        qp_attr->cur_qp_state = qp_attr->qp_state;
index 29c9dd4bcbc66e90e2f17667833b9f7ea0528b63..be7f2fe1e88398f20157bf5e9397f3dc548e7138 100644 (file)
@@ -1661,7 +1661,7 @@ struct hns_roce_query_pf_caps_d {
        __le32 rsv_uars_rsv_qps;
 };
 #define V2_QUERY_PF_CAPS_D_NUM_SRQS_S 0
-#define V2_QUERY_PF_CAPS_D_NUM_SRQS_M GENMASK(20, 0)
+#define V2_QUERY_PF_CAPS_D_NUM_SRQS_M GENMASK(19, 0)
 
 #define V2_QUERY_PF_CAPS_D_RQWQE_HOP_NUM_S 20
 #define V2_QUERY_PF_CAPS_D_RQWQE_HOP_NUM_M GENMASK(21, 20)
index 2408b279e4c24adb7b300d126e7437e2a08c6c9e..584932d3cc44b93c844378c922e5cbdceadb75fd 100644 (file)
 #define DRV_VERSION    __stringify(DRV_VERSION_MAJOR) "."              \
        __stringify(DRV_VERSION_MINOR) "." __stringify(DRV_VERSION_BUILD)
 
-static int push_mode;
-module_param(push_mode, int, 0644);
-MODULE_PARM_DESC(push_mode, "Low latency mode: 0=disabled (default), 1=enabled)");
-
 static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "debug flags: 0=disabled (default), 0x7fffffff=all");
@@ -1580,7 +1576,6 @@ static enum i40iw_status_code i40iw_setup_init_state(struct i40iw_handler *hdl,
        if (status)
                goto exit;
        iwdev->obj_next = iwdev->obj_mem;
-       iwdev->push_mode = push_mode;
 
        init_waitqueue_head(&iwdev->vchnl_waitq);
        init_waitqueue_head(&dev->vf_reqs);
index 581ecbadf5861fb9bcf643ba5d9a5c5d921fd43f..533f3caecb7a90fb74cf918b3de6e301cfa5dd38 100644 (file)
@@ -167,39 +167,16 @@ static void i40iw_dealloc_ucontext(struct ib_ucontext *context)
  */
 static int i40iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
 {
-       struct i40iw_ucontext *ucontext;
-       u64 db_addr_offset, push_offset, pfn;
-
-       ucontext = to_ucontext(context);
-       if (ucontext->iwdev->sc_dev.is_pf) {
-               db_addr_offset = I40IW_DB_ADDR_OFFSET;
-               push_offset = I40IW_PUSH_OFFSET;
-               if (vma->vm_pgoff)
-                       vma->vm_pgoff += I40IW_PF_FIRST_PUSH_PAGE_INDEX - 1;
-       } else {
-               db_addr_offset = I40IW_VF_DB_ADDR_OFFSET;
-               push_offset = I40IW_VF_PUSH_OFFSET;
-               if (vma->vm_pgoff)
-                       vma->vm_pgoff += I40IW_VF_FIRST_PUSH_PAGE_INDEX - 1;
-       }
+       struct i40iw_ucontext *ucontext = to_ucontext(context);
+       u64 dbaddr;
 
-       vma->vm_pgoff += db_addr_offset >> PAGE_SHIFT;
-
-       if (vma->vm_pgoff == (db_addr_offset >> PAGE_SHIFT)) {
-               vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-       } else {
-               if ((vma->vm_pgoff - (push_offset >> PAGE_SHIFT)) % 2)
-                       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-               else
-                       vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-       }
+       if (vma->vm_pgoff || vma->vm_end - vma->vm_start != PAGE_SIZE)
+               return -EINVAL;
 
-       pfn = vma->vm_pgoff +
-             (pci_resource_start(ucontext->iwdev->ldev->pcidev, 0) >>
-              PAGE_SHIFT);
+       dbaddr = I40IW_DB_ADDR_OFFSET + pci_resource_start(ucontext->iwdev->ldev->pcidev, 0);
 
-       return rdma_user_mmap_io(context, vma, pfn, PAGE_SIZE,
-                                vma->vm_page_prot, NULL);
+       return rdma_user_mmap_io(context, vma, dbaddr >> PAGE_SHIFT, PAGE_SIZE,
+                                pgprot_noncached(vma->vm_page_prot), NULL);
 }
 
 /**
index 89e04ca62ae0fa4965cdaba51dd7fb68a76a3012..246e3cbe0b2c7c84ef7fe83b52c256bd5a1e714f 100644 (file)
@@ -3305,7 +3305,8 @@ static int mlx5_add_netdev_notifier(struct mlx5_ib_dev *dev, u8 port_num)
        int err;
 
        dev->port[port_num].roce.nb.notifier_call = mlx5_netdev_event;
-       err = register_netdevice_notifier(&dev->port[port_num].roce.nb);
+       err = register_netdevice_notifier_net(mlx5_core_net(dev->mdev),
+                                             &dev->port[port_num].roce.nb);
        if (err) {
                dev->port[port_num].roce.nb.notifier_call = NULL;
                return err;
@@ -3317,7 +3318,8 @@ static int mlx5_add_netdev_notifier(struct mlx5_ib_dev *dev, u8 port_num)
 static void mlx5_remove_netdev_notifier(struct mlx5_ib_dev *dev, u8 port_num)
 {
        if (dev->port[port_num].roce.nb.notifier_call) {
-               unregister_netdevice_notifier(&dev->port[port_num].roce.nb);
+               unregister_netdevice_notifier_net(mlx5_core_net(dev->mdev),
+                                                 &dev->port[port_num].roce.nb);
                dev->port[port_num].roce.nb.notifier_call = NULL;
        }
 }
index c3cfea243af8c1da5338f0d14242d0cf5c2772c9..119b2573c9a08c1ef902bea3aec351eefa15de95 100644 (file)
@@ -803,8 +803,10 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
        }
 
        mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
-       if (IS_ERR(mailbox))
+       if (IS_ERR(mailbox)) {
+               err = PTR_ERR(mailbox);
                goto err_out_arm;
+       }
 
        cq_context = mailbox->buf;
 
@@ -846,9 +848,9 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
        }
 
        spin_lock_irq(&dev->cq_table.lock);
-       if (mthca_array_set(&dev->cq_table.cq,
-                           cq->cqn & (dev->limits.num_cqs - 1),
-                           cq)) {
+       err = mthca_array_set(&dev->cq_table.cq,
+                             cq->cqn & (dev->limits.num_cqs - 1), cq);
+       if (err) {
                spin_unlock_irq(&dev->cq_table.lock);
                goto err_out_free_mr;
        }
index c7169d2c69e5b0438816a491458be80a7593f5d8..c4bc58736e489ecfdf58cf629830c795cca441d2 100644 (file)
@@ -727,6 +727,7 @@ int qedr_iw_destroy_listen(struct iw_cm_id *cm_id)
                                                    listener->qed_handle);
 
        cm_id->rem_ref(cm_id);
+       kfree(listener);
        return rc;
 }
 
index fa2a3fa0c3e4e116125c6a122bd6126103ecf7a4..6895bac5399070b2d14f2f38375b18de4c1d3ac4 100644 (file)
@@ -266,7 +266,7 @@ static int pvrdma_register_device(struct pvrdma_dev *dev)
        }
        ret = ib_device_set_netdev(&dev->ib_dev, dev->netdev, 1);
        if (ret)
-               return ret;
+               goto err_srq_free;
        spin_lock_init(&dev->srq_tbl_lock);
        rdma_set_device_sysfs_group(&dev->ib_dev, &pvrdma_attr_group);
 
index f0e5ffba2d51d1544cf928011f2e64497c69657a..97ed8f952f6e94c750083333f4f17dfc03e764a0 100644 (file)
@@ -176,7 +176,7 @@ struct pvrdma_port_attr {
        u8                      subnet_timeout;
        u8                      init_type_reply;
        u8                      active_width;
-       u16                     active_speed;
+       u                     active_speed;
        u8                      phys_state;
        u8                      reserved[2];
 };
index 9ef5f5ce1ff6b077dba090385bc9d3af0ca8ca2c..c8e268082952b002d7671512d29cd1486406c152 100644 (file)
@@ -1,7 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config INFINIBAND_RDMAVT
        tristate "RDMA verbs transport library"
-       depends on X86_64 && ARCH_DMA_ADDR_T_64BIT
+       depends on INFINIBAND_VIRT_DMA
+       depends on X86_64
        depends on PCI
        select DMA_VIRT_OPS
        help
index 52218684ad4ab0f77ceb0d1bc4a0c2e81a550c8b..670a9623b46e1169fc978d74ea47236389474a56 100644 (file)
@@ -524,6 +524,7 @@ static noinline int check_support(struct rvt_dev_info *rdi, int verb)
 int rvt_register_device(struct rvt_dev_info *rdi)
 {
        int ret = 0, i;
+       u64 dma_mask;
 
        if (!rdi)
                return -EINVAL;
@@ -580,8 +581,10 @@ int rvt_register_device(struct rvt_dev_info *rdi)
 
        /* DMA Operations */
        rdi->ibdev.dev.dma_parms = rdi->ibdev.dev.parent->dma_parms;
-       dma_set_coherent_mask(&rdi->ibdev.dev,
-                             rdi->ibdev.dev.parent->coherent_dma_mask);
+       dma_mask = IS_ENABLED(CONFIG_64BIT) ? DMA_BIT_MASK(64) : DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(&rdi->ibdev.dev, dma_mask);
+       if (ret)
+               goto bail_wss;
 
        /* Protection Domain */
        spin_lock_init(&rdi->n_pds_lock);
index a0c6c7dfc1814f0d864cca4e35cb211f76598ef4..8810bfa680495a136a7fb8561488b1646f5f1a64 100644 (file)
@@ -2,7 +2,7 @@
 config RDMA_RXE
        tristate "Software RDMA over Ethernet (RoCE) driver"
        depends on INET && PCI && INFINIBAND
-       depends on !64BIT || ARCH_DMA_ADDR_T_64BIT
+       depends on INFINIBAND_VIRT_DMA
        select NET_UDP_TUNNEL
        select CRYPTO_CRC32
        select DMA_VIRT_OPS
index 38021e2c868811dcd8cef2c8b2223f061beefc62..df0d173d6acba6c8c8d461f4cb1d6b54918c15f0 100644 (file)
@@ -16,15 +16,24 @@ void rxe_init_av(struct rdma_ah_attr *attr, struct rxe_av *av)
 
 int rxe_av_chk_attr(struct rxe_dev *rxe, struct rdma_ah_attr *attr)
 {
+       const struct ib_global_route *grh = rdma_ah_read_grh(attr);
        struct rxe_port *port;
+       int type;
 
        port = &rxe->port;
 
        if (rdma_ah_get_ah_flags(attr) & IB_AH_GRH) {
-               u8 sgid_index = rdma_ah_read_grh(attr)->sgid_index;
+               if (grh->sgid_index > port->attr.gid_tbl_len) {
+                       pr_warn("invalid sgid index = %d\n",
+                                       grh->sgid_index);
+                       return -EINVAL;
+               }
 
-               if (sgid_index > port->attr.gid_tbl_len) {
-                       pr_warn("invalid sgid index = %d\n", sgid_index);
+               type = rdma_gid_attr_network_type(grh->sgid_attr);
+               if (type < RDMA_NETWORK_IPV4 ||
+                   type > RDMA_NETWORK_IPV6) {
+                       pr_warn("invalid network type for rdma_rxe = %d\n",
+                                       type);
                        return -EINVAL;
                }
        }
@@ -65,11 +74,29 @@ void rxe_av_to_attr(struct rxe_av *av, struct rdma_ah_attr *attr)
 void rxe_av_fill_ip_info(struct rxe_av *av, struct rdma_ah_attr *attr)
 {
        const struct ib_gid_attr *sgid_attr = attr->grh.sgid_attr;
+       int ibtype;
+       int type;
 
        rdma_gid2ip((struct sockaddr *)&av->sgid_addr, &sgid_attr->gid);
        rdma_gid2ip((struct sockaddr *)&av->dgid_addr,
                    &rdma_ah_read_grh(attr)->dgid);
-       av->network_type = rdma_gid_attr_network_type(sgid_attr);
+
+       ibtype = rdma_gid_attr_network_type(sgid_attr);
+
+       switch (ibtype) {
+       case RDMA_NETWORK_IPV4:
+               type = RXE_NETWORK_TYPE_IPV4;
+               break;
+       case RDMA_NETWORK_IPV6:
+               type = RXE_NETWORK_TYPE_IPV4;
+               break;
+       default:
+               /* not reached - checked in rxe_av_chk_attr */
+               type = 0;
+               break;
+       }
+
+       av->network_type = type;
 }
 
 struct rxe_av *rxe_get_av(struct rxe_pkt_info *pkt)
index 575e1a4ec82121272c7821932f220d744ddf0b91..34bef7d8e6b41b4845a3de5b165726b7dc150779 100644 (file)
@@ -442,7 +442,7 @@ struct sk_buff *rxe_init_packet(struct rxe_dev *rxe, struct rxe_av *av,
        if (IS_ERR(attr))
                return NULL;
 
-       if (av->network_type == RXE_NETWORK_TYPE_IPV6)
+       if (av->network_type == RXE_NETWORK_TYPE_IPV4)
                hdr_len = ETH_HLEN + sizeof(struct udphdr) +
                        sizeof(struct iphdr);
        else
index 1fc022362fbe4973298623e164a4394f03a93378..f9c832e82552f9259d4926d02225458222e0f4cb 100644 (file)
@@ -1118,6 +1118,7 @@ int rxe_register_device(struct rxe_dev *rxe, const char *ibdev_name)
        int err;
        struct ib_device *dev = &rxe->ib_dev;
        struct crypto_shash *tfm;
+       u64 dma_mask;
 
        strlcpy(dev->node_desc, "rxe", sizeof(dev->node_desc));
 
@@ -1130,7 +1131,10 @@ int rxe_register_device(struct rxe_dev *rxe, const char *ibdev_name)
                            rxe->ndev->dev_addr);
        dev->dev.dma_parms = &rxe->dma_parms;
        dma_set_max_seg_size(&dev->dev, UINT_MAX);
-       dma_set_coherent_mask(&dev->dev, dma_get_required_mask(&dev->dev));
+       dma_mask = IS_ENABLED(CONFIG_64BIT) ? DMA_BIT_MASK(64) : DMA_BIT_MASK(32);
+       err = dma_coerce_mask_and_coherent(&dev->dev, dma_mask);
+       if (err)
+               return err;
 
        dev->uverbs_cmd_mask = BIT_ULL(IB_USER_VERBS_CMD_GET_CONTEXT)
            | BIT_ULL(IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL)
index b622fc62f2cd6d4699cb9a1ed6ead9e44cd6bee2..3450ba5081df51a2c717746e6419ba750cd8d8d5 100644 (file)
@@ -1,6 +1,7 @@
 config RDMA_SIW
        tristate "Software RDMA over TCP/IP (iWARP) driver"
        depends on INET && INFINIBAND && LIBCRC32C
+       depends on INFINIBAND_VIRT_DMA
        select DMA_VIRT_OPS
        help
        This driver implements the iWARP RDMA transport over
index ca8bc72968672f7cbcc3563db5db47fcaf3dc28f..181e06c1c43d7eb080c06246215bb32186575895 100644 (file)
@@ -306,6 +306,7 @@ static struct siw_device *siw_device_create(struct net_device *netdev)
        struct siw_device *sdev = NULL;
        struct ib_device *base_dev;
        struct device *parent = netdev->dev.parent;
+       u64 dma_mask;
        int rv;
 
        if (!parent) {
@@ -384,8 +385,10 @@ static struct siw_device *siw_device_create(struct net_device *netdev)
        base_dev->dev.parent = parent;
        base_dev->dev.dma_parms = &sdev->dma_parms;
        dma_set_max_seg_size(&base_dev->dev, UINT_MAX);
-       dma_set_coherent_mask(&base_dev->dev,
-                             dma_get_required_mask(&base_dev->dev));
+       dma_mask = IS_ENABLED(CONFIG_64BIT) ? DMA_BIT_MASK(64) : DMA_BIT_MASK(32);
+       if (dma_coerce_mask_and_coherent(&base_dev->dev, dma_mask))
+               goto error;
+
        base_dev->num_comp_vectors = num_possible_cpus();
 
        xa_init_flags(&sdev->qp_xa, XA_FLAGS_ALLOC1);
index 2f3ebc0a75d92466456ab8948b50e723ab45f870..2bd18b0068934145de9440665eb80a438dc11a5a 100644 (file)
@@ -620,7 +620,7 @@ static void iser_route_handler(struct rdma_cm_id *cma_id)
        conn_param.private_data = (void *)&req_hdr;
        conn_param.private_data_len = sizeof(struct iser_cm_hdr);
 
-       ret = rdma_connect(cma_id, &conn_param);
+       ret = rdma_connect_locked(cma_id, &conn_param);
        if (ret) {
                iser_err("failure connecting: %d\n", ret);
                goto failure;
index 776e89231c52f77a5096d46b2286c0f2377e2458..f298adc02acba2e7fbe24bf1da40d47b0edc7453 100644 (file)
@@ -1674,9 +1674,9 @@ static int rtrs_rdma_route_resolved(struct rtrs_clt_con *con)
        uuid_copy(&msg.sess_uuid, &sess->s.uuid);
        uuid_copy(&msg.paths_uuid, &clt->paths_uuid);
 
-       err = rdma_connect(con->c.cm_id, &param);
+       err = rdma_connect_locked(con->c.cm_id, &param);
        if (err)
-               rtrs_err(clt, "rdma_connect(): %d\n", err);
+               rtrs_err(clt, "rdma_connect_locked(): %d\n", err);
 
        return err;
 }
index 0065eb17ae36b49ebb9097cee09ff7688f3fbf8c..53a8becac82761f80860fdb9eb4b057cccaa2767 100644 (file)
@@ -622,10 +622,11 @@ static int srpt_refresh_port(struct srpt_port *sport)
 /**
  * srpt_unregister_mad_agent - unregister MAD callback functions
  * @sdev: SRPT HCA pointer.
+ * @port_cnt: number of ports with registered MAD
  *
  * Note: It is safe to call this function more than once for the same device.
  */
-static void srpt_unregister_mad_agent(struct srpt_device *sdev)
+static void srpt_unregister_mad_agent(struct srpt_device *sdev, int port_cnt)
 {
        struct ib_port_modify port_modify = {
                .clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP,
@@ -633,7 +634,7 @@ static void srpt_unregister_mad_agent(struct srpt_device *sdev)
        struct srpt_port *sport;
        int i;
 
-       for (i = 1; i <= sdev->device->phys_port_cnt; i++) {
+       for (i = 1; i <= port_cnt; i++) {
                sport = &sdev->port[i - 1];
                WARN_ON(sport->port != i);
                if (sport->mad_agent) {
@@ -3185,7 +3186,8 @@ static int srpt_add_one(struct ib_device *device)
                if (ret) {
                        pr_err("MAD registration failed for %s-%d.\n",
                               dev_name(&sdev->device->dev), i);
-                       goto err_event;
+                       i--;
+                       goto err_port;
                }
        }
 
@@ -3197,7 +3199,8 @@ static int srpt_add_one(struct ib_device *device)
        pr_debug("added %s.\n", dev_name(&device->dev));
        return 0;
 
-err_event:
+err_port:
+       srpt_unregister_mad_agent(sdev, i);
        ib_unregister_event_handler(&sdev->event_handler);
 err_cm:
        if (sdev->cm_id)
@@ -3221,7 +3224,7 @@ static void srpt_remove_one(struct ib_device *device, void *client_data)
        struct srpt_device *sdev = client_data;
        int i;
 
-       srpt_unregister_mad_agent(sdev);
+       srpt_unregister_mad_agent(sdev, sdev->device->phys_port_cnt);
 
        ib_unregister_event_handler(&sdev->event_handler);
 
index 41435a699b53e81b5bb7daa860b8c6f62c4c0316..bdeb010efee680a3e160f862344a3e1e81c59801 100644 (file)
@@ -256,6 +256,7 @@ enum rdma_ch_state {
  * @rdma_cm:      See below.
  * @rdma_cm.cm_id: RDMA CM ID associated with the channel.
  * @cq:            IB completion queue for this channel.
+ * @cq_size:      Number of CQEs in @cq.
  * @zw_cqe:       Zero-length write CQE.
  * @rcu:           RCU head.
  * @kref:         kref for this channel.
index c77cdb3b62b5b4c7ed5ab4905bcdcf59ca761dec..8c73377ac82ca4abb9510f559d8c1f3ce3afec1b 100644 (file)
@@ -241,6 +241,7 @@ static const struct xpad_device {
        { 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
        { 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
        { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 },
+       { 0x1209, 0x2882, "Ardwiino Controller", 0, XTYPE_XBOX360 },
        { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 },
        { 0x12ab, 0x0303, "Mortal Kombat Klassic FightStick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
@@ -418,6 +419,7 @@ static const struct usb_device_id xpad_table[] = {
        XPAD_XBOXONE_VENDOR(0x0f0d),            /* Hori Controllers */
        XPAD_XBOX360_VENDOR(0x1038),            /* SteelSeries Controllers */
        XPAD_XBOX360_VENDOR(0x11c9),            /* Nacon GC100XF */
+       XPAD_XBOX360_VENDOR(0x1209),            /* Ardwiino Controllers */
        XPAD_XBOX360_VENDOR(0x12ab),            /* X-Box 360 dance pads */
        XPAD_XBOX360_VENDOR(0x1430),            /* RedOctane X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x146b),            /* BigBen Interactive Controllers */
index 27126e621eb60a8f1290d32488c9b29b7ee25d11..d450f11b98a703598dfa826cd49f74b888cb0efd 100644 (file)
@@ -99,7 +99,8 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio,
        switch (data) {
 
        case SUNKBD_RET_RESET:
-               schedule_work(&sunkbd->tq);
+               if (sunkbd->enabled)
+                       schedule_work(&sunkbd->tq);
                sunkbd->reset = -1;
                break;
 
@@ -200,16 +201,12 @@ static int sunkbd_initialize(struct sunkbd *sunkbd)
 }
 
 /*
- * sunkbd_reinit() sets leds and beeps to a state the computer remembers they
- * were in.
+ * sunkbd_set_leds_beeps() sets leds and beeps to a state the computer remembers
+ * they were in.
  */
 
-static void sunkbd_reinit(struct work_struct *work)
+static void sunkbd_set_leds_beeps(struct sunkbd *sunkbd)
 {
-       struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq);
-
-       wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
-
        serio_write(sunkbd->serio, SUNKBD_CMD_SETLED);
        serio_write(sunkbd->serio,
                (!!test_bit(LED_CAPSL,   sunkbd->dev->led) << 3) |
@@ -222,11 +219,39 @@ static void sunkbd_reinit(struct work_struct *work)
                SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd));
 }
 
+
+/*
+ * sunkbd_reinit() wait for the keyboard reset to complete and restores state
+ * of leds and beeps.
+ */
+
+static void sunkbd_reinit(struct work_struct *work)
+{
+       struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq);
+
+       /*
+        * It is OK that we check sunkbd->enabled without pausing serio,
+        * as we only want to catch true->false transition that will
+        * happen once and we will be woken up for it.
+        */
+       wait_event_interruptible_timeout(sunkbd->wait,
+                                        sunkbd->reset >= 0 || !sunkbd->enabled,
+                                        HZ);
+
+       if (sunkbd->reset >= 0 && sunkbd->enabled)
+               sunkbd_set_leds_beeps(sunkbd);
+}
+
 static void sunkbd_enable(struct sunkbd *sunkbd, bool enable)
 {
        serio_pause_rx(sunkbd->serio);
        sunkbd->enabled = enable;
        serio_continue_rx(sunkbd->serio);
+
+       if (!enable) {
+               wake_up_interruptible(&sunkbd->wait);
+               cancel_work_sync(&sunkbd->tq);
+       }
 }
 
 /*
index 5fe92d4ba3f0c5dd715c628e7d78d6db7613ecb1..4cc4e8ff42b33fa6c2e61d7e539e1c9a2561f284 100644 (file)
@@ -696,7 +696,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
        struct input_dev *input_dev;
        const struct adxl34x_platform_data *pdata;
        int err, range, i;
-       unsigned char revid;
+       int revid;
 
        if (!irq) {
                dev_err(dev, "no IRQ?\n");
index cae1a3fae83a4db6a88c7ad64bec134874122787..d14a65683c5e6854a686e4e4331103bc715998f7 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/input.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/acpi.h>
 #include <linux/dmi.h>
index c75b00c45d7505657119df8c4d4ebe6666eb3529..36e3cd9086716959dfca41d0e22e97a0b895dbc9 100644 (file)
@@ -78,7 +78,7 @@ struct elan_transport_ops {
        int (*iap_reset)(struct i2c_client *client);
 
        int (*prepare_fw_update)(struct i2c_client *client, u16 ic_type,
-                                u8 iap_version);
+                                u8 iap_version, u16 fw_page_size);
        int (*write_fw_block)(struct i2c_client *client, u16 fw_page_size,
                              const u8 *page, u16 checksum, int idx);
        int (*finish_fw_update)(struct i2c_client *client,
index c599e21a8478439f218531cedf1d54d24703f542..61ed3f5ca2199521d395c020811c45c3ede959dd 100644 (file)
@@ -497,7 +497,8 @@ static int __elan_update_firmware(struct elan_tp_data *data,
        u16 sw_checksum = 0, fw_checksum = 0;
 
        error = data->ops->prepare_fw_update(client, data->ic_type,
-                                            data->iap_version);
+                                            data->iap_version,
+                                            data->fw_page_size);
        if (error)
                return error;
 
index 5a496d4ffa4911fb15dc570c4b686d1223458297..13dc097eb6c652983399c1fbefea7475a4ea0ff2 100644 (file)
@@ -517,7 +517,7 @@ static int elan_i2c_set_flash_key(struct i2c_client *client)
        return 0;
 }
 
-static int elan_read_write_iap_type(struct i2c_client *client)
+static int elan_read_write_iap_type(struct i2c_client *client, u16 fw_page_size)
 {
        int error;
        u16 constant;
@@ -526,7 +526,7 @@ static int elan_read_write_iap_type(struct i2c_client *client)
 
        do {
                error = elan_i2c_write_cmd(client, ETP_I2C_IAP_TYPE_CMD,
-                                          ETP_I2C_IAP_TYPE_REG);
+                                          fw_page_size / 2);
                if (error) {
                        dev_err(&client->dev,
                                "cannot write iap type: %d\n", error);
@@ -543,7 +543,7 @@ static int elan_read_write_iap_type(struct i2c_client *client)
                constant = le16_to_cpup((__le16 *)val);
                dev_dbg(&client->dev, "iap type reg: 0x%04x\n", constant);
 
-               if (constant == ETP_I2C_IAP_TYPE_REG)
+               if (constant == fw_page_size / 2)
                        return 0;
 
        } while (--retry > 0);
@@ -553,7 +553,7 @@ static int elan_read_write_iap_type(struct i2c_client *client)
 }
 
 static int elan_i2c_prepare_fw_update(struct i2c_client *client, u16 ic_type,
-                                     u8 iap_version)
+                                     u8 iap_version, u16 fw_page_size)
 {
        struct device *dev = &client->dev;
        int error;
@@ -594,7 +594,7 @@ static int elan_i2c_prepare_fw_update(struct i2c_client *client, u16 ic_type,
        }
 
        if (ic_type >= 0x0D && iap_version >= 1) {
-               error = elan_read_write_iap_type(client);
+               error = elan_read_write_iap_type(client, fw_page_size);
                if (error)
                        return error;
        }
index 8ff823751f3ba05fa918e6f2aa9c7cb1884438f0..1820f1cfc1dc4d78e60250a704a04038c08e6c80 100644 (file)
@@ -340,7 +340,7 @@ static int elan_smbus_set_flash_key(struct i2c_client *client)
 }
 
 static int elan_smbus_prepare_fw_update(struct i2c_client *client, u16 ic_type,
-                                       u8 iap_version)
+                                       u8 iap_version, u16 fw_page_size)
 {
        struct device *dev = &client->dev;
        int len;
index a4c9b9652560a9b1791bb2d24e2191ae8d915520..7ecb65176c1aa4eacfcb561dd5ab0740118fee78 100644 (file)
@@ -219,6 +219,10 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
                        DMI_MATCH(DMI_SYS_VENDOR, "PEGATRON CORPORATION"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "C15B"),
                },
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ByteSpeed LLC"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ByteSpeed Laptop C15B"),
+               },
        },
        { }
 };
index d3eda48032e396ad1d006506b7976ba5be33672c..abae23af0791e1183b519423774e39f9156d75f9 100644 (file)
@@ -122,6 +122,7 @@ module_param_named(unmask_kbd_data, i8042_unmask_kbd_data, bool, 0600);
 MODULE_PARM_DESC(unmask_kbd_data, "Unconditional enable (may reveal sensitive data) of normally sanitize-filtered kbd data traffic debug log [pre-condition: i8042.debug=1 enabled]");
 #endif
 
+static bool i8042_present;
 static bool i8042_bypass_aux_irq_test;
 static char i8042_kbd_firmware_id[128];
 static char i8042_aux_firmware_id[128];
@@ -343,6 +344,9 @@ int i8042_command(unsigned char *param, int command)
        unsigned long flags;
        int retval;
 
+       if (!i8042_present)
+               return -1;
+
        spin_lock_irqsave(&i8042_lock, flags);
        retval = __i8042_command(param, command);
        spin_unlock_irqrestore(&i8042_lock, flags);
@@ -1467,7 +1471,8 @@ static int __init i8042_setup_aux(void)
        if (error)
                goto err_free_ports;
 
-       if (aux_enable())
+       error = aux_enable();
+       if (error)
                goto err_free_irq;
 
        i8042_aux_irq_registered = true;
@@ -1612,12 +1617,15 @@ static int __init i8042_init(void)
 
        err = i8042_platform_init();
        if (err)
-               return err;
+               return (err == -ENODEV) ? 0 : err;
 
        err = i8042_controller_check();
        if (err)
                goto err_platform_exit;
 
+       /* Set this before creating the dev to allow i8042_command to work right away */
+       i8042_present = true;
+
        pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0);
        if (IS_ERR(pdev)) {
                err = PTR_ERR(pdev);
@@ -1636,6 +1644,9 @@ static int __init i8042_init(void)
 
 static void __exit i8042_exit(void)
 {
+       if (!i8042_present)
+               return;
+
        platform_device_unregister(i8042_platform_device);
        platform_driver_unregister(&i8042_driver);
        i8042_platform_exit();
index f012fe746df01ebd3cdb430437638c882b64c5c0..cc18f54ea887f74ccd00953be9259458946b995c 100644 (file)
@@ -96,6 +96,7 @@ config TOUCHSCREEN_AD7879_SPI
 config TOUCHSCREEN_ADC
        tristate "Generic ADC based resistive touchscreen"
        depends on IIO
+       select IIO_BUFFER
        select IIO_BUFFER_CB
        help
          Say Y here if you want to use the generic ADC
index 98f17fa3a8926e2e02d7e9c0bba3090291905cec..b6f75367a284ab351b4f4d20475d463ef19dd6fc 100644 (file)
@@ -2183,11 +2183,11 @@ static int mxt_initialize(struct mxt_data *data)
                msleep(MXT_FW_RESET_TIME);
        }
 
-       error = mxt_acquire_irq(data);
+       error = mxt_check_retrigen(data);
        if (error)
                return error;
 
-       error = mxt_check_retrigen(data);
+       error = mxt_acquire_irq(data);
        if (error)
                return error;
 
index eea47b4c84aa779e23a663eb1e6c7ec0f3a8246f..5ad519c9f2396cea0d25b0dd30ef0d6de24b5555 100644 (file)
@@ -971,6 +971,9 @@ void icc_node_add(struct icc_node *node, struct icc_provider *provider)
        }
        node->avg_bw = node->init_avg;
        node->peak_bw = node->init_peak;
+       if (provider->aggregate)
+               provider->aggregate(node, 0, node->init_avg, node->init_peak,
+                                   &node->avg_bw, &node->peak_bw);
        provider->set(node, node);
        node->avg_bw = 0;
        node->peak_bw = 0;
@@ -1080,7 +1083,6 @@ static int of_count_icc_providers(struct device_node *np)
                        count++;
                count += of_count_icc_providers(child);
        }
-       of_node_put(np);
 
        return count;
 }
index cf10a4b9611bc31bf592f0e0c3aba4dcfbeabe30..bf01d09dba6c43c563c6c2360c8a177a07513ab8 100644 (file)
@@ -79,6 +79,7 @@ EXPORT_SYMBOL_GPL(qcom_icc_aggregate);
 int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
 {
        struct qcom_icc_provider *qp;
+       struct qcom_icc_node *qn;
        struct icc_node *node;
 
        if (!src)
@@ -87,6 +88,12 @@ int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
                node = src;
 
        qp = to_qcom_provider(node->provider);
+       qn = node->data;
+
+       qn->sum_avg[QCOM_ICC_BUCKET_AMC] = max_t(u64, qn->sum_avg[QCOM_ICC_BUCKET_AMC],
+                                                node->avg_bw);
+       qn->max_peak[QCOM_ICC_BUCKET_AMC] = max_t(u64, qn->max_peak[QCOM_ICC_BUCKET_AMC],
+                                                 node->peak_bw);
 
        qcom_icc_bcm_voter_commit(qp->voter);
 
index 42c6c558166265438f80e962bd1f4a18ef41840d..e8371d40ab8d82f6acb8bbb085f8ce0d14e80d52 100644 (file)
@@ -182,7 +182,7 @@ DEFINE_QNODE(mas_pcnoc_sdcc_1, MSM8916_MASTER_SDCC_1, 8, -1, -1, MSM8916_PNOC_IN
 DEFINE_QNODE(mas_pcnoc_sdcc_2, MSM8916_MASTER_SDCC_2, 8, -1, -1, MSM8916_PNOC_INT_1);
 DEFINE_QNODE(mas_qdss_bam, MSM8916_MASTER_QDSS_BAM, 8, -1, -1, MSM8916_SNOC_QDSS_INT);
 DEFINE_QNODE(mas_qdss_etr, MSM8916_MASTER_QDSS_ETR, 8, -1, -1, MSM8916_SNOC_QDSS_INT);
-DEFINE_QNODE(mas_snoc_cfg, MSM8916_MASTER_SNOC_CFG, 4, 20, -1, MSM8916_SNOC_QDSS_INT);
+DEFINE_QNODE(mas_snoc_cfg, MSM8916_MASTER_SNOC_CFG, 4, -1, -1, MSM8916_SNOC_QDSS_INT);
 DEFINE_QNODE(mas_spdm, MSM8916_MASTER_SPDM, 4, -1, -1, MSM8916_PNOC_MAS_0);
 DEFINE_QNODE(mas_tcu0, MSM8916_MASTER_TCU0, 8, -1, -1, MSM8916_SLAVE_EBI_CH0, MSM8916_BIMC_SNOC_MAS, MSM8916_SLAVE_AMPSS_L2);
 DEFINE_QNODE(mas_tcu1, MSM8916_MASTER_TCU1, 8, -1, -1, MSM8916_SLAVE_EBI_CH0, MSM8916_BIMC_SNOC_MAS, MSM8916_SLAVE_AMPSS_L2);
@@ -208,14 +208,14 @@ DEFINE_QNODE(pcnoc_snoc_mas, MSM8916_PNOC_SNOC_MAS, 8, 29, -1, MSM8916_PNOC_SNOC
 DEFINE_QNODE(pcnoc_snoc_slv, MSM8916_PNOC_SNOC_SLV, 8, -1, 45, MSM8916_SNOC_INT_0, MSM8916_SNOC_INT_BIMC, MSM8916_SNOC_INT_1);
 DEFINE_QNODE(qdss_int, MSM8916_SNOC_QDSS_INT, 8, -1, -1, MSM8916_SNOC_INT_0, MSM8916_SNOC_INT_BIMC);
 DEFINE_QNODE(slv_apps_l2, MSM8916_SLAVE_AMPSS_L2, 8, -1, -1, 0);
-DEFINE_QNODE(slv_apss, MSM8916_SLAVE_APSS, 4, -1, 20, 0);
+DEFINE_QNODE(slv_apss, MSM8916_SLAVE_APSS, 4, -1, -1, 0);
 DEFINE_QNODE(slv_audio, MSM8916_SLAVE_LPASS, 4, -1, -1, 0);
 DEFINE_QNODE(slv_bimc_cfg, MSM8916_SLAVE_BIMC_CFG, 4, -1, -1, 0);
 DEFINE_QNODE(slv_blsp_1, MSM8916_SLAVE_BLSP_1, 4, -1, -1, 0);
 DEFINE_QNODE(slv_boot_rom, MSM8916_SLAVE_BOOT_ROM, 4, -1, -1, 0);
 DEFINE_QNODE(slv_camera_cfg, MSM8916_SLAVE_CAMERA_CFG, 4, -1, -1, 0);
-DEFINE_QNODE(slv_cats_0, MSM8916_SLAVE_CATS_128, 16, -1, 106, 0);
-DEFINE_QNODE(slv_cats_1, MSM8916_SLAVE_OCMEM_64, 8, -1, 107, 0);
+DEFINE_QNODE(slv_cats_0, MSM8916_SLAVE_CATS_128, 16, -1, -1, 0);
+DEFINE_QNODE(slv_cats_1, MSM8916_SLAVE_OCMEM_64, 8, -1, -1, 0);
 DEFINE_QNODE(slv_clk_ctl, MSM8916_SLAVE_CLK_CTL, 4, -1, -1, 0);
 DEFINE_QNODE(slv_crypto_0_cfg, MSM8916_SLAVE_CRYPTO_0_CFG, 4, -1, -1, 0);
 DEFINE_QNODE(slv_dehr_cfg, MSM8916_SLAVE_DEHR_CFG, 4, -1, -1, 0);
@@ -239,7 +239,7 @@ DEFINE_QNODE(slv_sdcc_2, MSM8916_SLAVE_SDCC_2, 4, -1, -1, 0);
 DEFINE_QNODE(slv_security, MSM8916_SLAVE_SECURITY, 4, -1, -1, 0);
 DEFINE_QNODE(slv_snoc_cfg, MSM8916_SLAVE_SNOC_CFG, 4, -1, -1, 0);
 DEFINE_QNODE(slv_spdm, MSM8916_SLAVE_SPDM, 4, -1, -1, 0);
-DEFINE_QNODE(slv_srvc_snoc, MSM8916_SLAVE_SRVC_SNOC, 8, -1, 29, 0);
+DEFINE_QNODE(slv_srvc_snoc, MSM8916_SLAVE_SRVC_SNOC, 8, -1, -1, 0);
 DEFINE_QNODE(slv_tcsr, MSM8916_SLAVE_TCSR, 4, -1, -1, 0);
 DEFINE_QNODE(slv_tlmm, MSM8916_SLAVE_TLMM, 4, -1, -1, 0);
 DEFINE_QNODE(slv_usb_hs, MSM8916_SLAVE_USB_HS, 4, -1, -1, 0);
@@ -249,7 +249,7 @@ DEFINE_QNODE(snoc_bimc_0_slv, MSM8916_SNOC_BIMC_0_SLV, 8, -1, 24, MSM8916_SLAVE_
 DEFINE_QNODE(snoc_bimc_1_mas, MSM8916_SNOC_BIMC_1_MAS, 16, -1, -1, MSM8916_SNOC_BIMC_1_SLV);
 DEFINE_QNODE(snoc_bimc_1_slv, MSM8916_SNOC_BIMC_1_SLV, 8, -1, -1, MSM8916_SLAVE_EBI_CH0);
 DEFINE_QNODE(snoc_int_0, MSM8916_SNOC_INT_0, 8, 99, 130, MSM8916_SLAVE_QDSS_STM, MSM8916_SLAVE_IMEM, MSM8916_SNOC_PNOC_MAS);
-DEFINE_QNODE(snoc_int_1, MSM8916_SNOC_INT_1, 8, 100, 131, MSM8916_SLAVE_APSS, MSM8916_SLAVE_CATS_128, MSM8916_SLAVE_OCMEM_64);
+DEFINE_QNODE(snoc_int_1, MSM8916_SNOC_INT_1, 8, -1, -1, MSM8916_SLAVE_APSS, MSM8916_SLAVE_CATS_128, MSM8916_SLAVE_OCMEM_64);
 DEFINE_QNODE(snoc_int_bimc, MSM8916_SNOC_INT_BIMC, 8, 101, 132, MSM8916_SNOC_BIMC_0_MAS);
 DEFINE_QNODE(snoc_pcnoc_mas, MSM8916_SNOC_PNOC_MAS, 8, -1, -1, MSM8916_SNOC_PNOC_SLV);
 DEFINE_QNODE(snoc_pcnoc_slv, MSM8916_SNOC_PNOC_SLV, 8, -1, -1, MSM8916_PNOC_INT_0);
index 3a313e11e73d76bf1f5392343d8d6aead33c1eb4..da68ce375a89dfb679260b34dfa3425eb425f431 100644 (file)
@@ -618,6 +618,8 @@ static int msm8974_icc_set(struct icc_node *src, struct icc_node *dst)
 
        do_div(rate, src_qn->buswidth);
 
+       rate = min_t(u32, rate, INT_MAX);
+
        if (src_qn->rate == rate)
                return 0;
 
@@ -635,6 +637,14 @@ static int msm8974_icc_set(struct icc_node *src, struct icc_node *dst)
        return 0;
 }
 
+static int msm8974_get_bw(struct icc_node *node, u32 *avg, u32 *peak)
+{
+       *avg = 0;
+       *peak = 0;
+
+       return 0;
+}
+
 static int msm8974_icc_probe(struct platform_device *pdev)
 {
        const struct msm8974_icc_desc *desc;
@@ -688,6 +698,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
        provider->aggregate = icc_std_aggregate;
        provider->xlate = of_icc_xlate_onecell;
        provider->data = data;
+       provider->get_bw = msm8974_get_bw;
 
        ret = icc_provider_add(provider);
        if (ret) {
@@ -758,6 +769,7 @@ static struct platform_driver msm8974_noc_driver = {
        .driver = {
                .name = "qnoc-msm8974",
                .of_match_table = msm8974_noc_of_match,
+               .sync_state = icc_sync_state,
        },
 };
 module_platform_driver(msm8974_noc_driver);
index d4769a5ea182ef54b1661e6b611e5fea289c7d5e..9820709b43dbde757fad773744424d5be0ef10ee 100644 (file)
@@ -157,8 +157,8 @@ struct qcom_icc_desc {
        }
 
 DEFINE_QNODE(mas_apps_proc, QCS404_MASTER_AMPSS_M0, 8, 0, -1, QCS404_SLAVE_EBI_CH0, QCS404_BIMC_SNOC_SLV);
-DEFINE_QNODE(mas_oxili, QCS404_MASTER_GRAPHICS_3D, 8, 6, -1, QCS404_SLAVE_EBI_CH0, QCS404_BIMC_SNOC_SLV);
-DEFINE_QNODE(mas_mdp, QCS404_MASTER_MDP_PORT0, 8, 8, -1, QCS404_SLAVE_EBI_CH0, QCS404_BIMC_SNOC_SLV);
+DEFINE_QNODE(mas_oxili, QCS404_MASTER_GRAPHICS_3D, 8, -1, -1, QCS404_SLAVE_EBI_CH0, QCS404_BIMC_SNOC_SLV);
+DEFINE_QNODE(mas_mdp, QCS404_MASTER_MDP_PORT0, 8, -1, -1, QCS404_SLAVE_EBI_CH0, QCS404_BIMC_SNOC_SLV);
 DEFINE_QNODE(mas_snoc_bimc_1, QCS404_SNOC_BIMC_1_MAS, 8, 76, -1, QCS404_SLAVE_EBI_CH0);
 DEFINE_QNODE(mas_tcu_0, QCS404_MASTER_TCU_0, 8, -1, -1, QCS404_SLAVE_EBI_CH0, QCS404_BIMC_SNOC_SLV);
 DEFINE_QNODE(mas_spdm, QCS404_MASTER_SPDM, 4, -1, -1, QCS404_PNOC_INT_3);
index bf11b82ed55cf8a521b384c57f0318c8f219bf76..8d9044ed18ab9efbd25f4a49922abdd587e41879 100644 (file)
@@ -553,6 +553,9 @@ static int qnoc_probe(struct platform_device *pdev)
                return ret;
        }
 
+       for (i = 0; i < qp->num_bcms; i++)
+               qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
+
        for (i = 0; i < num_nodes; i++) {
                size_t j;
 
@@ -576,9 +579,6 @@ static int qnoc_probe(struct platform_device *pdev)
        }
        data->num_nodes = num_nodes;
 
-       for (i = 0; i < qp->num_bcms; i++)
-               qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
-
        platform_set_drvdata(pdev, qp);
 
        return 0;
index d79e3163e2c38b5ade1949066861e3a05fef2ab8..5304aea3b05850cdb986174fe85d9abb9fc2444f 100644 (file)
@@ -151,7 +151,7 @@ DEFINE_QBCM(bcm_mc0, "MC0", true, &ebi);
 DEFINE_QBCM(bcm_sh0, "SH0", true, &qns_llcc);
 DEFINE_QBCM(bcm_mm0, "MM0", false, &qns_mem_noc_hf);
 DEFINE_QBCM(bcm_sh1, "SH1", false, &qns_apps_io);
-DEFINE_QBCM(bcm_mm1, "MM1", false, &qxm_camnoc_hf0_uncomp, &qxm_camnoc_hf1_uncomp, &qxm_camnoc_sf_uncomp, &qxm_camnoc_hf0, &qxm_camnoc_hf1, &qxm_mdp0, &qxm_mdp1);
+DEFINE_QBCM(bcm_mm1, "MM1", true, &qxm_camnoc_hf0_uncomp, &qxm_camnoc_hf1_uncomp, &qxm_camnoc_sf_uncomp, &qxm_camnoc_hf0, &qxm_camnoc_hf1, &qxm_mdp0, &qxm_mdp1);
 DEFINE_QBCM(bcm_sh2, "SH2", false, &qns_memnoc_snoc);
 DEFINE_QBCM(bcm_mm2, "MM2", false, &qns2_mem_noc);
 DEFINE_QBCM(bcm_sh3, "SH3", false, &acm_tcu);
@@ -489,6 +489,9 @@ static int qnoc_probe(struct platform_device *pdev)
                return ret;
        }
 
+       for (i = 0; i < qp->num_bcms; i++)
+               qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
+
        for (i = 0; i < num_nodes; i++) {
                size_t j;
 
@@ -512,9 +515,6 @@ static int qnoc_probe(struct platform_device *pdev)
        }
        data->num_nodes = num_nodes;
 
-       for (i = 0; i < qp->num_bcms; i++)
-               qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
-
        platform_set_drvdata(pdev, qp);
 
        return 0;
index 9218efed04a072235e992ec572e2f884980d6bce..c76b2c7f9b106dad1a2807bacbbbf939531de873 100644 (file)
@@ -551,6 +551,9 @@ static int qnoc_probe(struct platform_device *pdev)
                return ret;
        }
 
+       for (i = 0; i < qp->num_bcms; i++)
+               qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
+
        for (i = 0; i < num_nodes; i++) {
                size_t j;
 
@@ -574,9 +577,6 @@ static int qnoc_probe(struct platform_device *pdev)
        }
        data->num_nodes = num_nodes;
 
-       for (i = 0; i < qp->num_bcms; i++)
-               qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
-
        platform_set_drvdata(pdev, qp);
 
        return 0;
@@ -627,6 +627,7 @@ static struct platform_driver qnoc_driver = {
        .driver = {
                .name = "qnoc-sm8150",
                .of_match_table = qnoc_of_match,
+               .sync_state = icc_sync_state,
        },
 };
 module_platform_driver(qnoc_driver);
index 9b58946f789837b654f7cad7ad747afc7493d3b6..cc558fec74e38780de5d42b75ca412cee7a9bb7b 100644 (file)
@@ -567,6 +567,9 @@ static int qnoc_probe(struct platform_device *pdev)
                return ret;
        }
 
+       for (i = 0; i < qp->num_bcms; i++)
+               qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
+
        for (i = 0; i < num_nodes; i++) {
                size_t j;
 
@@ -590,9 +593,6 @@ static int qnoc_probe(struct platform_device *pdev)
        }
        data->num_nodes = num_nodes;
 
-       for (i = 0; i < qp->num_bcms; i++)
-               qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
-
        platform_set_drvdata(pdev, qp);
 
        return 0;
@@ -643,6 +643,7 @@ static struct platform_driver qnoc_driver = {
        .driver = {
                .name = "qnoc-sm8250",
                .of_match_table = qnoc_of_match,
+               .sync_state = icc_sync_state,
        },
 };
 module_platform_driver(qnoc_driver);
index f696ac7c5f8931251dd0c052ddff26278d250c7e..89647700bab2dc4e20c85017e82d2ebd4f5dc208 100644 (file)
@@ -409,7 +409,11 @@ extern bool amd_iommu_np_cache;
 /* Only true if all IOMMUs support device IOTLBs */
 extern bool amd_iommu_iotlb_sup;
 
-#define MAX_IRQS_PER_TABLE     256
+/*
+ * AMD IOMMU hardware only support 512 IRTEs despite
+ * the architectural limitation of 2048 entries.
+ */
+#define MAX_IRQS_PER_TABLE     512
 #define IRQ_TABLE_ALIGNMENT    128
 
 struct irq_remap_table {
index 82e4af8f09bbb7ec3a6b79b9feca31baa35c14f3..23a790f8f55061a412fe055076620e551681cee9 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/iommu_table.h>
 #include <asm/io_apic.h>
 #include <asm/irq_remapping.h>
+#include <asm/set_memory.h>
 
 #include <linux/crash_dump.h>
 
@@ -672,11 +673,27 @@ static void __init free_command_buffer(struct amd_iommu *iommu)
        free_pages((unsigned long)iommu->cmd_buf, get_order(CMD_BUFFER_SIZE));
 }
 
+static void *__init iommu_alloc_4k_pages(struct amd_iommu *iommu,
+                                        gfp_t gfp, size_t size)
+{
+       int order = get_order(size);
+       void *buf = (void *)__get_free_pages(gfp, order);
+
+       if (buf &&
+           iommu_feature(iommu, FEATURE_SNP) &&
+           set_memory_4k((unsigned long)buf, (1 << order))) {
+               free_pages((unsigned long)buf, order);
+               buf = NULL;
+       }
+
+       return buf;
+}
+
 /* allocates the memory where the IOMMU will log its events to */
 static int __init alloc_event_buffer(struct amd_iommu *iommu)
 {
-       iommu->evt_buf = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
-                                                 get_order(EVT_BUFFER_SIZE));
+       iommu->evt_buf = iommu_alloc_4k_pages(iommu, GFP_KERNEL | __GFP_ZERO,
+                                             EVT_BUFFER_SIZE);
 
        return iommu->evt_buf ? 0 : -ENOMEM;
 }
@@ -715,8 +732,8 @@ static void __init free_event_buffer(struct amd_iommu *iommu)
 /* allocates the memory where the IOMMU will log its events to */
 static int __init alloc_ppr_log(struct amd_iommu *iommu)
 {
-       iommu->ppr_log = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
-                                                 get_order(PPR_LOG_SIZE));
+       iommu->ppr_log = iommu_alloc_4k_pages(iommu, GFP_KERNEL | __GFP_ZERO,
+                                             PPR_LOG_SIZE);
 
        return iommu->ppr_log ? 0 : -ENOMEM;
 }
@@ -838,7 +855,7 @@ static int iommu_init_ga(struct amd_iommu *iommu)
 
 static int __init alloc_cwwb_sem(struct amd_iommu *iommu)
 {
-       iommu->cmd_sem = (void *)get_zeroed_page(GFP_KERNEL);
+       iommu->cmd_sem = iommu_alloc_4k_pages(iommu, GFP_KERNEL | __GFP_ZERO, 1);
 
        return iommu->cmd_sem ? 0 : -ENOMEM;
 }
index be4318044f96c19d1055a07231f87dc911f8ebe5..702fbaa6c9ada10fe73e41269e24c0891520ea3a 100644 (file)
@@ -69,6 +69,10 @@ struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu)
 {
        struct qcom_smmu *qsmmu;
 
+       /* Check to make sure qcom_scm has finished probing */
+       if (!qcom_scm_is_available())
+               return ERR_PTR(-EPROBE_DEFER);
+
        qsmmu = devm_kzalloc(smmu->dev, sizeof(*qsmmu), GFP_KERNEL);
        if (!qsmmu)
                return ERR_PTR(-ENOMEM);
index 404b40af31cb27aa2ff57620060ef1d53ae5f2c7..b46dbfa6d0ed691c86a2970dda3c8d04baa35c26 100644 (file)
@@ -333,6 +333,13 @@ static void  dmar_pci_bus_del_dev(struct dmar_pci_notify_info *info)
        dmar_iommu_notify_scope_dev(info);
 }
 
+static inline void vf_inherit_msi_domain(struct pci_dev *pdev)
+{
+       struct pci_dev *physfn = pci_physfn(pdev);
+
+       dev_set_msi_domain(&pdev->dev, dev_get_msi_domain(&physfn->dev));
+}
+
 static int dmar_pci_bus_notifier(struct notifier_block *nb,
                                 unsigned long action, void *data)
 {
@@ -342,8 +349,20 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb,
        /* Only care about add/remove events for physical functions.
         * For VFs we actually do the lookup based on the corresponding
         * PF in device_to_iommu() anyway. */
-       if (pdev->is_virtfn)
+       if (pdev->is_virtfn) {
+               /*
+                * Ensure that the VF device inherits the irq domain of the
+                * PF device. Ideally the device would inherit the domain
+                * from the bus, but DMAR can have multiple units per bus
+                * which makes this impossible. The VF 'bus' could inherit
+                * from the PF device, but that's yet another x86'sism to
+                * inflict on everybody else.
+                */
+               if (action == BUS_NOTIFY_ADD_DEVICE)
+                       vf_inherit_msi_domain(pdev);
                return NOTIFY_DONE;
+       }
+
        if (action != BUS_NOTIFY_ADD_DEVICE &&
            action != BUS_NOTIFY_REMOVED_DEVICE)
                return NOTIFY_DONE;
@@ -967,7 +986,8 @@ static int map_iommu(struct intel_iommu *iommu, u64 phys_addr)
                warn_invalid_dmar(phys_addr, " returns all ones");
                goto unmap;
        }
-       iommu->vccap = dmar_readq(iommu->reg + DMAR_VCCAP_REG);
+       if (ecap_vcs(iommu->ecap))
+               iommu->vccap = dmar_readq(iommu->reg + DMAR_VCCAP_REG);
 
        /* the registers might be more than one page */
        map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
index 8651f6d4dfa032c00f9c2149ae643a3614960fb7..a49afa11673cc5aae3e346a9429cbe412ec8d84e 100644 (file)
@@ -179,7 +179,7 @@ static int rwbf_quirk;
  * (used when kernel is launched w/ TXT)
  */
 static int force_on = 0;
-int intel_iommu_tboot_noforce;
+static int intel_iommu_tboot_noforce;
 static int no_platform_optin;
 
 #define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
@@ -1833,7 +1833,7 @@ static void free_dmar_iommu(struct intel_iommu *iommu)
                if (ecap_prs(iommu->ecap))
                        intel_svm_finish_prq(iommu);
        }
-       if (ecap_vcs(iommu->ecap) && vccap_pasid(iommu->vccap))
+       if (vccap_pasid(iommu->vccap))
                ioasid_unregister_allocator(&iommu->pasid_allocator);
 
 #endif
@@ -2525,6 +2525,9 @@ struct dmar_domain *find_domain(struct device *dev)
 {
        struct device_domain_info *info;
 
+       if (unlikely(!dev || !dev->iommu))
+               return NULL;
+
        if (unlikely(attach_deferred(dev)))
                return NULL;
 
@@ -3209,7 +3212,7 @@ static void register_pasid_allocator(struct intel_iommu *iommu)
         * is active. All vIOMMU allocators will eventually be calling the same
         * host allocator.
         */
-       if (!ecap_vcs(iommu->ecap) || !vccap_pasid(iommu->vccap))
+       if (!vccap_pasid(iommu->vccap))
                return;
 
        pr_info("Register custom PASID allocator\n");
@@ -3815,9 +3818,8 @@ bounce_map_single(struct device *dev, phys_addr_t paddr, size_t size,
         * page aligned, we don't need to use a bounce page.
         */
        if (!IS_ALIGNED(paddr | size, VTD_PAGE_SIZE)) {
-               tlb_addr = swiotlb_tbl_map_single(dev,
-                               phys_to_dma_unencrypted(dev, io_tlb_start),
-                               paddr, size, aligned_size, dir, attrs);
+               tlb_addr = swiotlb_tbl_map_single(dev, paddr, size,
+                               aligned_size, dir, attrs);
                if (tlb_addr == DMA_MAPPING_ERROR) {
                        goto swiotlb_error;
                } else {
@@ -4882,7 +4884,8 @@ int __init intel_iommu_init(void)
         * Intel IOMMU is required for a TXT/tboot launch or platform
         * opt in, so enforce that.
         */
-       force_on = tboot_force_iommu() || platform_optin_force_iommu();
+       force_on = (!intel_iommu_tboot_noforce && tboot_force_iommu()) ||
+                   platform_optin_force_iommu();
 
        if (iommu_init_mempool()) {
                if (force_on)
index f1861fa3d0e4a4091454938ba788bd33c12cc285..3242ebd0bca36a766f5bd92b02dc46f89efe7093 100644 (file)
@@ -279,6 +279,7 @@ int intel_svm_bind_gpasid(struct iommu_domain *domain, struct device *dev,
        struct intel_iommu *iommu = device_to_iommu(dev, NULL, NULL);
        struct intel_svm_dev *sdev = NULL;
        struct dmar_domain *dmar_domain;
+       struct device_domain_info *info;
        struct intel_svm *svm = NULL;
        int ret = 0;
 
@@ -310,6 +311,10 @@ int intel_svm_bind_gpasid(struct iommu_domain *domain, struct device *dev,
        if (data->hpasid <= 0 || data->hpasid >= PASID_MAX)
                return -EINVAL;
 
+       info = get_domain_info(dev);
+       if (!info)
+               return -EINVAL;
+
        dmar_domain = to_dmar_domain(domain);
 
        mutex_lock(&pasid_mutex);
@@ -357,6 +362,7 @@ int intel_svm_bind_gpasid(struct iommu_domain *domain, struct device *dev,
                goto out;
        }
        sdev->dev = dev;
+       sdev->sid = PCI_DEVID(info->bus, info->devfn);
 
        /* Only count users if device has aux domains */
        if (iommu_dev_feature_enabled(dev, IOMMU_DEV_FEAT_AUX))
@@ -1029,7 +1035,7 @@ no_pasid:
                        resp.qw0 = QI_PGRP_PASID(req->pasid) |
                                QI_PGRP_DID(req->rid) |
                                QI_PGRP_PASID_P(req->pasid_present) |
-                               QI_PGRP_PDP(req->pasid_present) |
+                               QI_PGRP_PDP(req->priv_data_present) |
                                QI_PGRP_RESP_CODE(result) |
                                QI_PGRP_RESP_TYPE;
                        resp.qw1 = QI_PGRP_IDX(req->prg_index) |
index 8c470f451a323e590293309c0331af3db10bebaf..0f4dc25d46c925129a3e7fe3cc6df62198a2b2c1 100644 (file)
@@ -264,16 +264,18 @@ int iommu_probe_device(struct device *dev)
         */
        iommu_alloc_default_domain(group, dev);
 
-       if (group->default_domain)
+       if (group->default_domain) {
                ret = __iommu_attach_device(group->default_domain, dev);
+               if (ret) {
+                       iommu_group_put(group);
+                       goto err_release;
+               }
+       }
 
        iommu_create_device_direct_mappings(group, dev);
 
        iommu_group_put(group);
 
-       if (ret)
-               goto err_release;
-
        if (ops->probe_finalize)
                ops->probe_finalize(dev);
 
@@ -2071,7 +2073,7 @@ EXPORT_SYMBOL_GPL(iommu_uapi_cache_invalidate);
 
 static int iommu_check_bind_data(struct iommu_gpasid_bind_data *data)
 {
-       u32 mask;
+       u64 mask;
        int i;
 
        if (data->version != IOMMU_GPASID_BIND_VERSION_1)
index c6098eee0c7cf217f83153ad406e63bd35426b27..2aa79c32ee228d530945b68b49f8f23372eb7043 100644 (file)
@@ -180,7 +180,6 @@ config IRQ_MIPS_CPU
        select GENERIC_IRQ_CHIP
        select GENERIC_IRQ_IPI if SYS_SUPPORTS_MULTITHREADING
        select IRQ_DOMAIN
-       select IRQ_DOMAIN_HIERARCHY if GENERIC_IRQ_IPI
        select GENERIC_IRQ_EFFECTIVE_AFF_MASK
 
 config CLPS711X_IRQCHIP
@@ -315,7 +314,6 @@ config KEYSTONE_IRQ
 config MIPS_GIC
        bool
        select GENERIC_IRQ_IPI
-       select IRQ_DOMAIN_HIERARCHY
        select MIPS_CM
 
 config INGENIC_IRQ
@@ -591,6 +589,7 @@ config LOONGSON_PCH_MSI
 
 config MST_IRQ
        bool "MStar Interrupt Controller"
+       depends on ARCH_MEDIATEK || ARCH_MSTARV7 || COMPILE_TEST
        default ARCH_MEDIATEK
        select IRQ_DOMAIN
        select IRQ_DOMAIN_HIERARCHY
index 97838eb705f9339aa3790bb46e44d2a4f682f2bf..cbc7c740e4dc39f1740df68f6b0e031d512e8d2b 100644 (file)
@@ -244,7 +244,7 @@ static int bcm2836_cpu_dying(unsigned int cpu)
 
 #define BITS_PER_MBOX  32
 
-static void bcm2836_arm_irqchip_smp_init(void)
+static void __init bcm2836_arm_irqchip_smp_init(void)
 {
        struct irq_fwspec ipi_fwspec = {
                .fwnode         = intc.domain->fwnode,
index 0fec31931e1155eeb74ade55e61b2ff93649a800..4069c215328b3e0eb0f34fbd6a4fab197b95cea6 100644 (file)
@@ -42,7 +42,6 @@
 #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING          (1ULL << 0)
 #define ITS_FLAGS_WORKAROUND_CAVIUM_22375      (1ULL << 1)
 #define ITS_FLAGS_WORKAROUND_CAVIUM_23144      (1ULL << 2)
-#define ITS_FLAGS_SAVE_SUSPEND_STATE           (1ULL << 3)
 
 #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING    (1 << 0)
 #define RDIST_FLAGS_RD_TABLES_PREALLOCATED     (1 << 1)
@@ -4741,9 +4740,6 @@ static int its_save_disable(void)
        list_for_each_entry(its, &its_nodes, entry) {
                void __iomem *base;
 
-               if (!(its->flags & ITS_FLAGS_SAVE_SUSPEND_STATE))
-                       continue;
-
                base = its->base;
                its->ctlr_save = readl_relaxed(base + GITS_CTLR);
                err = its_force_quiescent(base);
@@ -4762,9 +4758,6 @@ err:
                list_for_each_entry_continue_reverse(its, &its_nodes, entry) {
                        void __iomem *base;
 
-                       if (!(its->flags & ITS_FLAGS_SAVE_SUSPEND_STATE))
-                               continue;
-
                        base = its->base;
                        writel_relaxed(its->ctlr_save, base + GITS_CTLR);
                }
@@ -4784,9 +4777,6 @@ static void its_restore_enable(void)
                void __iomem *base;
                int i;
 
-               if (!(its->flags & ITS_FLAGS_SAVE_SUSPEND_STATE))
-                       continue;
-
                base = its->base;
 
                /*
@@ -4794,7 +4784,10 @@ static void its_restore_enable(void)
                 * don't restore it since writing to CBASER or BASER<n>
                 * registers is undefined according to the GIC v3 ITS
                 * Specification.
+                *
+                * Firmware resuming with the ITS enabled is terminally broken.
                 */
+               WARN_ON(readl_relaxed(base + GITS_CTLR) & GITS_CTLR_ENABLE);
                ret = its_force_quiescent(base);
                if (ret) {
                        pr_err("ITS@%pa: failed to quiesce on resume: %d\n",
@@ -5074,9 +5067,6 @@ static int __init its_probe_one(struct resource *res,
                ctlr |= GITS_CTLR_ImDe;
        writel_relaxed(ctlr, its->base + GITS_CTLR);
 
-       if (GITS_TYPER_HCC(typer))
-               its->flags |= ITS_FLAGS_SAVE_SUSPEND_STATE;
-
        err = its_init_domain(handle, its);
        if (err)
                goto out_free_tables;
index 4be0775918981a3cb4c249c3601f5ac69ee617fa..143657b0cf281aa57b0876d1c167a536ff419d7e 100644 (file)
@@ -154,8 +154,8 @@ static const struct irq_domain_ops mst_intc_domain_ops = {
        .free           = irq_domain_free_irqs_common,
 };
 
-int __init
-mst_intc_of_init(struct device_node *dn, struct device_node *parent)
+static int __init mst_intc_of_init(struct device_node *dn,
+                                  struct device_node *parent)
 {
        struct irq_domain *domain, *domain_parent;
        struct mst_intc_chip_data *cd;
index 3819185bfd02c63f6f0a2abbd7bb8ee60b5f291a..cb7f60b3b4a920c2aef276d3eff817bc52d22ba3 100644 (file)
@@ -71,8 +71,7 @@ struct intc_irqpin_priv {
 };
 
 struct intc_irqpin_config {
-       unsigned int irlm_bit;
-       unsigned needs_irlm:1;
+       int irlm_bit;           /* -1 if non-existent */
 };
 
 static unsigned long intc_irqpin_read32(void __iomem *iomem)
@@ -349,11 +348,10 @@ static const struct irq_domain_ops intc_irqpin_irq_domain_ops = {
 
 static const struct intc_irqpin_config intc_irqpin_irlm_r8a777x = {
        .irlm_bit = 23, /* ICR0.IRLM0 */
-       .needs_irlm = 1,
 };
 
 static const struct intc_irqpin_config intc_irqpin_rmobile = {
-       .needs_irlm = 0,
+       .irlm_bit = -1,
 };
 
 static const struct of_device_id intc_irqpin_dt_ids[] = {
@@ -470,7 +468,7 @@ static int intc_irqpin_probe(struct platform_device *pdev)
        }
 
        /* configure "individual IRQ mode" where needed */
-       if (config && config->needs_irlm) {
+       if (config && config->irlm_bit >= 0) {
                if (io[INTC_IRQPIN_REG_IRLM])
                        intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_IRLM,
                                                      config->irlm_bit, 1, 1);
index eaa3e9fe54e918d85429696a9a2a30bc8249e4e0..6f432d2a5cebdc388f5c7d88e1c807f4d83fc28f 100644 (file)
@@ -99,7 +99,7 @@ static inline void plic_irq_toggle(const struct cpumask *mask,
                                   struct irq_data *d, int enable)
 {
        int cpu;
-       struct plic_priv *priv = irq_get_chip_data(d->irq);
+       struct plic_priv *priv = irq_data_get_irq_chip_data(d);
 
        writel(enable, priv->regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID);
        for_each_cpu(cpu, mask) {
@@ -115,7 +115,7 @@ static void plic_irq_unmask(struct irq_data *d)
 {
        struct cpumask amask;
        unsigned int cpu;
-       struct plic_priv *priv = irq_get_chip_data(d->irq);
+       struct plic_priv *priv = irq_data_get_irq_chip_data(d);
 
        cpumask_and(&amask, &priv->lmask, cpu_online_mask);
        cpu = cpumask_any_and(irq_data_get_affinity_mask(d),
@@ -127,7 +127,7 @@ static void plic_irq_unmask(struct irq_data *d)
 
 static void plic_irq_mask(struct irq_data *d)
 {
-       struct plic_priv *priv = irq_get_chip_data(d->irq);
+       struct plic_priv *priv = irq_data_get_irq_chip_data(d);
 
        plic_irq_toggle(&priv->lmask, d, 0);
 }
@@ -138,7 +138,7 @@ static int plic_set_affinity(struct irq_data *d,
 {
        unsigned int cpu;
        struct cpumask amask;
-       struct plic_priv *priv = irq_get_chip_data(d->irq);
+       struct plic_priv *priv = irq_data_get_irq_chip_data(d);
 
        cpumask_and(&amask, &priv->lmask, mask_val);
 
@@ -151,7 +151,7 @@ static int plic_set_affinity(struct irq_data *d,
                return -EINVAL;
 
        plic_irq_toggle(&priv->lmask, d, 0);
-       plic_irq_toggle(cpumask_of(cpu), d, 1);
+       plic_irq_toggle(cpumask_of(cpu), d, !irqd_irq_masked(d));
 
        irq_data_update_effective_affinity(d, cpumask_of(cpu));
 
index 1d027623c776080da8136ccf0611277e8d7ee780..abd011fcecf4a30d020c0c1e48fb44fd92acca8b 100644 (file)
@@ -136,7 +136,7 @@ static int exiu_domain_translate(struct irq_domain *domain,
                if (fwspec->param_count != 2)
                        return -EINVAL;
                *hwirq = fwspec->param[0];
-               *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+               *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
        }
        return 0;
 }
index 0c2c61db26b45dfaf1bb995c89e9cdcdeb276431..8662d7b7b2625af83c70235569e8f5da6e603d5e 100644 (file)
@@ -195,6 +195,10 @@ static const struct stm32_desc_irq stm32mp1_desc_irq[] = {
        { .exti = 25, .irq_parent = 107, .chip = &stm32_exti_h_chip_direct },
        { .exti = 30, .irq_parent = 52, .chip = &stm32_exti_h_chip_direct },
        { .exti = 47, .irq_parent = 93, .chip = &stm32_exti_h_chip_direct },
+       { .exti = 48, .irq_parent = 138, .chip = &stm32_exti_h_chip_direct },
+       { .exti = 50, .irq_parent = 139, .chip = &stm32_exti_h_chip_direct },
+       { .exti = 52, .irq_parent = 140, .chip = &stm32_exti_h_chip_direct },
+       { .exti = 53, .irq_parent = 141, .chip = &stm32_exti_h_chip_direct },
        { .exti = 54, .irq_parent = 135, .chip = &stm32_exti_h_chip_direct },
        { .exti = 61, .irq_parent = 100, .chip = &stm32_exti_h_chip_direct },
        { .exti = 65, .irq_parent = 144, .chip = &stm32_exti_h_chip },
index e0cceb81c6486bbf0cc2225fde3147bd05fb7be2..b2ab8db439d928b1ff73e40d7c782a9d357fc8f7 100644 (file)
@@ -85,6 +85,17 @@ struct ti_sci_inta_vint_desc {
  * @base:              Base address of the memory mapped IO registers
  * @pdev:              Pointer to platform device.
  * @ti_sci_id:         TI-SCI device identifier
+ * @unmapped_cnt:      Number of @unmapped_dev_ids entries
+ * @unmapped_dev_ids:  Pointer to an array of TI-SCI device identifiers of
+ *                     unmapped event sources.
+ *                     Unmapped Events are not part of the Global Event Map and
+ *                     they are converted to Global event within INTA to be
+ *                     received by the same INTA to generate an interrupt.
+ *                     In case an interrupt request comes for a device which is
+ *                     generating Unmapped Event, we must use the INTA's TI-SCI
+ *                     device identifier in place of the source device
+ *                     identifier to let sysfw know where it has to program the
+ *                     Global Event number.
  */
 struct ti_sci_inta_irq_domain {
        const struct ti_sci_handle *sci;
@@ -96,11 +107,37 @@ struct ti_sci_inta_irq_domain {
        void __iomem *base;
        struct platform_device *pdev;
        u32 ti_sci_id;
+
+       int unmapped_cnt;
+       u16 *unmapped_dev_ids;
 };
 
 #define to_vint_desc(e, i) container_of(e, struct ti_sci_inta_vint_desc, \
                                        events[i])
 
+static u16 ti_sci_inta_get_dev_id(struct ti_sci_inta_irq_domain *inta, u32 hwirq)
+{
+       u16 dev_id = HWIRQ_TO_DEVID(hwirq);
+       int i;
+
+       if (inta->unmapped_cnt == 0)
+               return dev_id;
+
+       /*
+        * For devices sending Unmapped Events we must use the INTA's TI-SCI
+        * device identifier number to be able to convert it to a Global Event
+        * and map it to an interrupt.
+        */
+       for (i = 0; i < inta->unmapped_cnt; i++) {
+               if (dev_id == inta->unmapped_dev_ids[i]) {
+                       dev_id = inta->ti_sci_id;
+                       break;
+               }
+       }
+
+       return dev_id;
+}
+
 /**
  * ti_sci_inta_irq_handler() - Chained IRQ handler for the vint irqs
  * @desc:      Pointer to irq_desc corresponding to the irq
@@ -251,7 +288,7 @@ static struct ti_sci_inta_event_desc *ti_sci_inta_alloc_event(struct ti_sci_inta
        u16 dev_id, dev_index;
        int err;
 
-       dev_id = HWIRQ_TO_DEVID(hwirq);
+       dev_id = ti_sci_inta_get_dev_id(inta, hwirq);
        dev_index = HWIRQ_TO_IRQID(hwirq);
 
        event_desc = &vint_desc->events[free_bit];
@@ -352,14 +389,15 @@ static void ti_sci_inta_free_irq(struct ti_sci_inta_event_desc *event_desc,
 {
        struct ti_sci_inta_vint_desc *vint_desc;
        struct ti_sci_inta_irq_domain *inta;
+       u16 dev_id;
 
        vint_desc = to_vint_desc(event_desc, event_desc->vint_bit);
        inta = vint_desc->domain->host_data;
+       dev_id = ti_sci_inta_get_dev_id(inta, hwirq);
        /* free event irq */
        mutex_lock(&inta->vint_mutex);
        inta->sci->ops.rm_irq_ops.free_event_map(inta->sci,
-                                                HWIRQ_TO_DEVID(hwirq),
-                                                HWIRQ_TO_IRQID(hwirq),
+                                                dev_id, HWIRQ_TO_IRQID(hwirq),
                                                 inta->ti_sci_id,
                                                 vint_desc->vint_id,
                                                 event_desc->global_event,
@@ -574,6 +612,41 @@ static struct msi_domain_info ti_sci_inta_msi_domain_info = {
        .chip   = &ti_sci_inta_msi_irq_chip,
 };
 
+static int ti_sci_inta_get_unmapped_sources(struct ti_sci_inta_irq_domain *inta)
+{
+       struct device *dev = &inta->pdev->dev;
+       struct device_node *node = dev_of_node(dev);
+       struct of_phandle_iterator it;
+       int count, err, ret, i;
+
+       count = of_count_phandle_with_args(node, "ti,unmapped-event-sources", NULL);
+       if (count <= 0)
+               return 0;
+
+       inta->unmapped_dev_ids = devm_kcalloc(dev, count,
+                                             sizeof(*inta->unmapped_dev_ids),
+                                             GFP_KERNEL);
+       if (!inta->unmapped_dev_ids)
+               return -ENOMEM;
+
+       i = 0;
+       of_for_each_phandle(&it, err, node, "ti,unmapped-event-sources", NULL, 0) {
+               u32 dev_id;
+
+               ret = of_property_read_u32(it.node, "ti,sci-dev-id", &dev_id);
+               if (ret) {
+                       dev_err(dev, "ti,sci-dev-id read failure for %pOFf\n", it.node);
+                       of_node_put(it.node);
+                       return ret;
+               }
+               inta->unmapped_dev_ids[i++] = dev_id;
+       }
+
+       inta->unmapped_cnt = count;
+
+       return 0;
+}
+
 static int ti_sci_inta_irq_domain_probe(struct platform_device *pdev)
 {
        struct irq_domain *parent_domain, *domain, *msi_domain;
@@ -629,6 +702,10 @@ static int ti_sci_inta_irq_domain_probe(struct platform_device *pdev)
        if (IS_ERR(inta->base))
                return PTR_ERR(inta->base);
 
+       ret = ti_sci_inta_get_unmapped_sources(inta);
+       if (ret)
+               return ret;
+
        domain = irq_domain_add_linear(dev_of_node(dev),
                                       ti_sci_get_num_resources(inta->vint),
                                       &ti_sci_inta_irq_domain_ops, inta);
index 9644424591dab899bdeffc8503766df0419df987..4bc453f5bbaa6d3314db7a49eb7f7661548b7839 100644 (file)
@@ -712,10 +712,6 @@ static bool block_size_is_power_of_two(struct cache *cache)
        return cache->sectors_per_block_shift >= 0;
 }
 
-/* gcc on ARM generates spurious references to __udivdi3 and __umoddi3 */
-#if defined(CONFIG_ARM) && __GNUC__ == 4 && __GNUC_MINOR__ <= 6
-__always_inline
-#endif
 static dm_block_t block_div(dm_block_t b, uint32_t n)
 {
        do_div(b, n);
index 3fc3757def55ec29466a0ecddf4c197d6586c6de..5a7a1b90e671cfa09c64dc268547f31101f18cd9 100644 (file)
@@ -3462,7 +3462,7 @@ static int get_mac(struct crypto_shash **hash, struct alg_spec *a, char **error,
        int r;
 
        if (a->alg_string) {
-               *hash = crypto_alloc_shash(a->alg_string, 0, 0);
+               *hash = crypto_alloc_shash(a->alg_string, 0, CRYPTO_ALG_ALLOCATES_MEMORY);
                if (IS_ERR(*hash)) {
                        *error = error_alg;
                        r = PTR_ERR(*hash);
@@ -3519,7 +3519,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
                struct journal_completion comp;
 
                comp.ic = ic;
-               ic->journal_crypt = crypto_alloc_skcipher(ic->journal_crypt_alg.alg_string, 0, 0);
+               ic->journal_crypt = crypto_alloc_skcipher(ic->journal_crypt_alg.alg_string, 0, CRYPTO_ALG_ALLOCATES_MEMORY);
                if (IS_ERR(ic->journal_crypt)) {
                        *error = "Invalid journal cipher";
                        r = PTR_ERR(ic->journal_crypt);
index ce543b761be7b2b7bab1acaa40446c008e477680..7eeb7c4169c949c768f3aafa3a325bf622d0e51a 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/atomic.h>
-#include <linux/lcm.h>
 #include <linux/blk-mq.h>
 #include <linux/mount.h>
 #include <linux/dax.h>
@@ -1247,12 +1246,6 @@ void dm_table_event_callback(struct dm_table *t,
 
 void dm_table_event(struct dm_table *t)
 {
-       /*
-        * You can no longer call dm_table_event() from interrupt
-        * context, use a bottom half instead.
-        */
-       BUG_ON(in_interrupt());
-
        mutex_lock(&_event_lock);
        if (t->event_fn)
                t->event_fn(t->event_context);
@@ -1455,10 +1448,6 @@ int dm_calculate_queue_limits(struct dm_table *table,
                        zone_sectors = ti_limits.chunk_sectors;
                }
 
-               /* Stack chunk_sectors if target-specific splitting is required */
-               if (ti->max_io_len)
-                       ti_limits.chunk_sectors = lcm_not_zero(ti->max_io_len,
-                                                              ti_limits.chunk_sectors);
                /* Set I/O hints portion of queue limits */
                if (ti->type->io_hints)
                        ti->type->io_hints(ti, &ti_limits);
index 9ae4ce7df95c752a210ca254c4757d95a7058af4..d5223a0e5cc51e309c93ab035b2f54fd7ce7d69c 100644 (file)
@@ -319,7 +319,7 @@ err1:
 #else
 static int persistent_memory_claim(struct dm_writecache *wc)
 {
-       BUG();
+       return -EOPNOTSUPP;
 }
 #endif
 
@@ -2041,7 +2041,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
        struct wc_memory_superblock s;
 
        static struct dm_arg _args[] = {
-               {0, 10, "Invalid number of feature args"},
+               {0, 16, "Invalid number of feature args"},
        };
 
        as.argc = argc;
@@ -2479,6 +2479,8 @@ static void writecache_status(struct dm_target *ti, status_type_t type,
                        extra_args += 2;
                if (wc->autocommit_time_set)
                        extra_args += 2;
+               if (wc->max_age != MAX_AGE_UNSPECIFIED)
+                       extra_args += 2;
                if (wc->cleaner)
                        extra_args++;
                if (wc->writeback_fua_set)
index c18fc25485186de70b172d5b80f4e3a190fd419b..4e0cbfe3f14d434f9fefeae37b1d6f71e79b4f63 100644 (file)
@@ -476,8 +476,10 @@ static int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
                return -EAGAIN;
 
        map = dm_get_live_table(md, &srcu_idx);
-       if (!map)
-               return -EIO;
+       if (!map) {
+               ret = -EIO;
+               goto out;
+       }
 
        do {
                struct dm_target *tgt;
@@ -507,7 +509,6 @@ out:
 
 static int dm_prepare_ioctl(struct mapped_device *md, int *srcu_idx,
                            struct block_device **bdev)
-       __acquires(md->io_barrier)
 {
        struct dm_target *tgt;
        struct dm_table *map;
@@ -541,7 +542,6 @@ retry:
 }
 
 static void dm_unprepare_ioctl(struct mapped_device *md, int srcu_idx)
-       __releases(md->io_barrier)
 {
        dm_put_live_table(md, srcu_idx);
 }
@@ -1037,15 +1037,18 @@ static sector_t max_io_len(struct dm_target *ti, sector_t sector)
        sector_t max_len;
 
        /*
-        * Does the target need to split even further?
-        * - q->limits.chunk_sectors reflects ti->max_io_len so
-        *   blk_max_size_offset() provides required splitting.
-        * - blk_max_size_offset() also respects q->limits.max_sectors
+        * Does the target need to split IO even further?
+        * - varied (per target) IO splitting is a tenet of DM; this
+        *   explains why stacked chunk_sectors based splitting via
+        *   blk_max_size_offset() isn't possible here. So pass in
+        *   ti->max_io_len to override stacked chunk_sectors.
         */
-       max_len = blk_max_size_offset(ti->table->md->queue,
-                                     target_offset);
-       if (len > max_len)
-               len = max_len;
+       if (ti->max_io_len) {
+               max_len = blk_max_size_offset(ti->table->md->queue,
+                                             target_offset, ti->max_io_len);
+               if (len > max_len)
+                       len = max_len;
+       }
 
        return len;
 }
@@ -1196,11 +1199,9 @@ static int dm_dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff,
                 * ->zero_page_range() is mandatory dax operation. If we are
                 *  here, something is wrong.
                 */
-               dm_put_live_table(md, srcu_idx);
                goto out;
        }
        ret = ti->type->dax_zero_page_range(ti, pgoff, nr_pages);
-
  out:
        dm_put_live_table(md, srcu_idx);
 
index a3cb104956d5629162d5091de479d723ea50fb2e..7e152bbb4fa66ef46db0a16048437d97461ce6ad 100644 (file)
@@ -253,17 +253,31 @@ config VIDEO_MEDIATEK_VCODEC
        depends on MTK_IOMMU || COMPILE_TEST
        depends on VIDEO_DEV && VIDEO_V4L2
        depends on ARCH_MEDIATEK || COMPILE_TEST
+       depends on VIDEO_MEDIATEK_VPU || MTK_SCP
+       # The two following lines ensure we have the same state ("m" or "y") as
+       # our dependencies, to avoid missing symbols during link.
+       depends on VIDEO_MEDIATEK_VPU || !VIDEO_MEDIATEK_VPU
+       depends on MTK_SCP || !MTK_SCP
        select VIDEOBUF2_DMA_CONTIG
        select V4L2_MEM2MEM_DEV
-       select VIDEO_MEDIATEK_VPU
-       select MTK_SCP
+       select VIDEO_MEDIATEK_VCODEC_VPU if VIDEO_MEDIATEK_VPU
+       select VIDEO_MEDIATEK_VCODEC_SCP if MTK_SCP
        help
-           Mediatek video codec driver provides HW capability to
-           encode and decode in a range of video formats
-           This driver rely on VPU driver to communicate with VPU.
+         Mediatek video codec driver provides HW capability to
+         encode and decode in a range of video formats on MT8173
+         and MT8183.
+
+         Note that support for MT8173 requires VIDEO_MEDIATEK_VPU to
+         also be selected. Support for MT8183 depends on MTK_SCP.
+
+         To compile this driver as modules, choose M here: the
+         modules will be called mtk-vcodec-dec and mtk-vcodec-enc.
+
+config VIDEO_MEDIATEK_VCODEC_VPU
+       bool
 
-           To compile this driver as modules, choose M here: the
-           modules will be called mtk-vcodec-dec and mtk-vcodec-enc.
+config VIDEO_MEDIATEK_VCODEC_SCP
+       bool
 
 config VIDEO_MEM2MEM_DEINTERLACE
        tristate "Deinterlace support"
index cd902b18066940c23bfbcbc8ef67af8e0dbd0fb5..63fce1b85d26686189ab2f997e6fb0517da502f7 100644 (file)
@@ -307,6 +307,7 @@ static int mmpcam_platform_remove(struct platform_device *pdev)
  * Suspend/resume support.
  */
 
+#ifdef CONFIG_PM
 static int mmpcam_runtime_resume(struct device *dev)
 {
        struct mmp_camera *cam = dev_get_drvdata(dev);
@@ -352,6 +353,7 @@ static int __maybe_unused mmpcam_resume(struct device *dev)
                return mccic_resume(&cam->mcam);
        return 0;
 }
+#endif
 
 static const struct dev_pm_ops mmpcam_pm_ops = {
        SET_RUNTIME_PM_OPS(mmpcam_runtime_suspend, mmpcam_runtime_resume, NULL)
index f679c6e1a3e9be38e040de7f69aee07b68840d83..4618d43dbbc849047af345579dbc09ad576e192a 100644 (file)
@@ -24,4 +24,12 @@ mtk-vcodec-enc-y := venc/venc_vp8_if.o \
 
 mtk-vcodec-common-y := mtk_vcodec_intr.o \
                mtk_vcodec_util.o \
-               mtk_vcodec_fw.o
+               mtk_vcodec_fw.o \
+
+ifneq ($(CONFIG_VIDEO_MEDIATEK_VCODEC_VPU),)
+mtk-vcodec-common-y += mtk_vcodec_fw_vpu.o
+endif
+
+ifneq ($(CONFIG_VIDEO_MEDIATEK_VCODEC_SCP),)
+mtk-vcodec-common-y += mtk_vcodec_fw_scp.o
+endif
index d14bc208ea5e3ef1f1313956240c4f1e44801f6c..145686d2c219c49a39438cfe28525ad2c7aef950 100644 (file)
@@ -241,7 +241,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
        }
        dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
 
-       dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, VPU_RST_DEC);
+       dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, DECODER);
        if (IS_ERR(dev->fw_handler))
                return PTR_ERR(dev->fw_handler);
 
index dcfa2c2d4def3d25dcc56728f47f0307a06b307e..3be8a04c4c67934f6f4bb1caac06baeffc05d645 100644 (file)
@@ -293,7 +293,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
        }
        dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
 
-       dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, VPU_RST_ENC);
+       dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, ENCODER);
        if (IS_ERR(dev->fw_handler))
                return PTR_ERR(dev->fw_handler);
 
index 6c2a2568d844f7934bd602775bba5503d0682d1b..94b39ae5c2e1e05ac0e8bce3c4a52823b4da64f8 100644 (file)
 // SPDX-License-Identifier: GPL-2.0
 
 #include "mtk_vcodec_fw.h"
+#include "mtk_vcodec_fw_priv.h"
 #include "mtk_vcodec_util.h"
 #include "mtk_vcodec_drv.h"
 
-struct mtk_vcodec_fw_ops {
-       int (*load_firmware)(struct mtk_vcodec_fw *fw);
-       unsigned int (*get_vdec_capa)(struct mtk_vcodec_fw *fw);
-       unsigned int (*get_venc_capa)(struct mtk_vcodec_fw *fw);
-       void * (*map_dm_addr)(struct mtk_vcodec_fw *fw, u32 dtcm_dmem_addr);
-       int (*ipi_register)(struct mtk_vcodec_fw *fw, int id,
-                           mtk_vcodec_ipi_handler handler, const char *name, void *priv);
-       int (*ipi_send)(struct mtk_vcodec_fw *fw, int id, void *buf,
-                       unsigned int len, unsigned int wait);
-};
-
-struct mtk_vcodec_fw {
-       enum mtk_vcodec_fw_type type;
-       const struct mtk_vcodec_fw_ops *ops;
-       struct platform_device *pdev;
-       struct mtk_scp *scp;
-};
-
-static int mtk_vcodec_vpu_load_firmware(struct mtk_vcodec_fw *fw)
-{
-       return vpu_load_firmware(fw->pdev);
-}
-
-static unsigned int mtk_vcodec_vpu_get_vdec_capa(struct mtk_vcodec_fw *fw)
-{
-       return vpu_get_vdec_hw_capa(fw->pdev);
-}
-
-static unsigned int mtk_vcodec_vpu_get_venc_capa(struct mtk_vcodec_fw *fw)
-{
-       return vpu_get_venc_hw_capa(fw->pdev);
-}
-
-static void *mtk_vcodec_vpu_map_dm_addr(struct mtk_vcodec_fw *fw,
-                                       u32 dtcm_dmem_addr)
-{
-       return vpu_mapping_dm_addr(fw->pdev, dtcm_dmem_addr);
-}
-
-static int mtk_vcodec_vpu_set_ipi_register(struct mtk_vcodec_fw *fw, int id,
-                                          mtk_vcodec_ipi_handler handler,
-                                          const char *name, void *priv)
-{
-       /*
-        * The handler we receive takes a void * as its first argument. We
-        * cannot change this because it needs to be passed down to the rproc
-        * subsystem when SCP is used. VPU takes a const argument, which is
-        * more constrained, so the conversion below is safe.
-        */
-       ipi_handler_t handler_const = (ipi_handler_t)handler;
-
-       return vpu_ipi_register(fw->pdev, id, handler_const, name, priv);
-}
-
-static int mtk_vcodec_vpu_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf,
-                                  unsigned int len, unsigned int wait)
-{
-       return vpu_ipi_send(fw->pdev, id, buf, len);
-}
-
-static const struct mtk_vcodec_fw_ops mtk_vcodec_vpu_msg = {
-       .load_firmware = mtk_vcodec_vpu_load_firmware,
-       .get_vdec_capa = mtk_vcodec_vpu_get_vdec_capa,
-       .get_venc_capa = mtk_vcodec_vpu_get_venc_capa,
-       .map_dm_addr = mtk_vcodec_vpu_map_dm_addr,
-       .ipi_register = mtk_vcodec_vpu_set_ipi_register,
-       .ipi_send = mtk_vcodec_vpu_ipi_send,
-};
-
-static int mtk_vcodec_scp_load_firmware(struct mtk_vcodec_fw *fw)
-{
-       return rproc_boot(scp_get_rproc(fw->scp));
-}
-
-static unsigned int mtk_vcodec_scp_get_vdec_capa(struct mtk_vcodec_fw *fw)
-{
-       return scp_get_vdec_hw_capa(fw->scp);
-}
-
-static unsigned int mtk_vcodec_scp_get_venc_capa(struct mtk_vcodec_fw *fw)
-{
-       return scp_get_venc_hw_capa(fw->scp);
-}
-
-static void *mtk_vcodec_vpu_scp_dm_addr(struct mtk_vcodec_fw *fw,
-                                       u32 dtcm_dmem_addr)
-{
-       return scp_mapping_dm_addr(fw->scp, dtcm_dmem_addr);
-}
-
-static int mtk_vcodec_scp_set_ipi_register(struct mtk_vcodec_fw *fw, int id,
-                                          mtk_vcodec_ipi_handler handler,
-                                          const char *name, void *priv)
-{
-       return scp_ipi_register(fw->scp, id, handler, priv);
-}
-
-static int mtk_vcodec_scp_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf,
-                                  unsigned int len, unsigned int wait)
-{
-       return scp_ipi_send(fw->scp, id, buf, len, wait);
-}
-
-static const struct mtk_vcodec_fw_ops mtk_vcodec_rproc_msg = {
-       .load_firmware = mtk_vcodec_scp_load_firmware,
-       .get_vdec_capa = mtk_vcodec_scp_get_vdec_capa,
-       .get_venc_capa = mtk_vcodec_scp_get_venc_capa,
-       .map_dm_addr = mtk_vcodec_vpu_scp_dm_addr,
-       .ipi_register = mtk_vcodec_scp_set_ipi_register,
-       .ipi_send = mtk_vcodec_scp_ipi_send,
-};
-
-static void mtk_vcodec_reset_handler(void *priv)
-{
-       struct mtk_vcodec_dev *dev = priv;
-       struct mtk_vcodec_ctx *ctx;
-
-       mtk_v4l2_err("Watchdog timeout!!");
-
-       mutex_lock(&dev->dev_mutex);
-       list_for_each_entry(ctx, &dev->ctx_list, list) {
-               ctx->state = MTK_STATE_ABORT;
-               mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ABORT",
-                              ctx->id);
-       }
-       mutex_unlock(&dev->dev_mutex);
-}
-
 struct mtk_vcodec_fw *mtk_vcodec_fw_select(struct mtk_vcodec_dev *dev,
                                           enum mtk_vcodec_fw_type type,
-                                          enum rst_id rst_id)
+                                          enum mtk_vcodec_fw_use fw_use)
 {
-       const struct mtk_vcodec_fw_ops *ops;
-       struct mtk_vcodec_fw *fw;
-       struct platform_device *fw_pdev = NULL;
-       struct mtk_scp *scp = NULL;
-
        switch (type) {
        case VPU:
-               ops = &mtk_vcodec_vpu_msg;
-               fw_pdev = vpu_get_plat_device(dev->plat_dev);
-               if (!fw_pdev) {
-                       mtk_v4l2_err("firmware device is not ready");
-                       return ERR_PTR(-EINVAL);
-               }
-               vpu_wdt_reg_handler(fw_pdev, mtk_vcodec_reset_handler,
-                                   dev, rst_id);
-               break;
+               return mtk_vcodec_fw_vpu_init(dev, fw_use);
        case SCP:
-               ops = &mtk_vcodec_rproc_msg;
-               scp = scp_get(dev->plat_dev);
-               if (!scp) {
-                       mtk_v4l2_err("could not get vdec scp handle");
-                       return ERR_PTR(-EPROBE_DEFER);
-               }
-               break;
+               return mtk_vcodec_fw_scp_init(dev);
        default:
                mtk_v4l2_err("invalid vcodec fw type");
                return ERR_PTR(-EINVAL);
        }
-
-       fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL);
-       if (!fw)
-               return ERR_PTR(-EINVAL);
-
-       fw->type = type;
-       fw->ops = ops;
-       fw->pdev = fw_pdev;
-       fw->scp = scp;
-
-       return fw;
 }
 EXPORT_SYMBOL_GPL(mtk_vcodec_fw_select);
 
 void mtk_vcodec_fw_release(struct mtk_vcodec_fw *fw)
 {
-       switch (fw->type) {
-       case VPU:
-               put_device(&fw->pdev->dev);
-               break;
-       case SCP:
-               scp_put(fw->scp);
-               break;
-       }
+       fw->ops->release(fw);
 }
 EXPORT_SYMBOL_GPL(mtk_vcodec_fw_release);
 
index fadbbe6ba6cd4102b4440ad371e89fabbd9cb28d..539bb626772cc5d9a00ed386a197644a8dd73aec 100644 (file)
@@ -15,6 +15,11 @@ enum mtk_vcodec_fw_type {
        SCP,
 };
 
+enum mtk_vcodec_fw_use {
+       DECODER,
+       ENCODER,
+};
+
 struct mtk_vcodec_fw;
 
 typedef void (*mtk_vcodec_ipi_handler) (void *data,
@@ -22,7 +27,7 @@ typedef void (*mtk_vcodec_ipi_handler) (void *data,
 
 struct mtk_vcodec_fw *mtk_vcodec_fw_select(struct mtk_vcodec_dev *dev,
                                           enum mtk_vcodec_fw_type type,
-                                          enum rst_id rst_id);
+                                          enum mtk_vcodec_fw_use fw_use);
 void mtk_vcodec_fw_release(struct mtk_vcodec_fw *fw);
 
 int mtk_vcodec_fw_load_firmware(struct mtk_vcodec_fw *fw);
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_priv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_priv.h
new file mode 100644 (file)
index 0000000..b41e661
--- /dev/null
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _MTK_VCODEC_FW_PRIV_H_
+#define _MTK_VCODEC_FW_PRIV_H_
+
+#include "mtk_vcodec_fw.h"
+
+struct mtk_vcodec_dev;
+
+struct mtk_vcodec_fw {
+       enum mtk_vcodec_fw_type type;
+       const struct mtk_vcodec_fw_ops *ops;
+       struct platform_device *pdev;
+       struct mtk_scp *scp;
+};
+
+struct mtk_vcodec_fw_ops {
+       int (*load_firmware)(struct mtk_vcodec_fw *fw);
+       unsigned int (*get_vdec_capa)(struct mtk_vcodec_fw *fw);
+       unsigned int (*get_venc_capa)(struct mtk_vcodec_fw *fw);
+       void *(*map_dm_addr)(struct mtk_vcodec_fw *fw, u32 dtcm_dmem_addr);
+       int (*ipi_register)(struct mtk_vcodec_fw *fw, int id,
+                           mtk_vcodec_ipi_handler handler, const char *name,
+                           void *priv);
+       int (*ipi_send)(struct mtk_vcodec_fw *fw, int id, void *buf,
+                       unsigned int len, unsigned int wait);
+       void (*release)(struct mtk_vcodec_fw *fw);
+};
+
+#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCODEC_VPU)
+struct mtk_vcodec_fw *mtk_vcodec_fw_vpu_init(struct mtk_vcodec_dev *dev,
+                                            enum mtk_vcodec_fw_use fw_use);
+#else
+static inline struct mtk_vcodec_fw *
+mtk_vcodec_fw_vpu_init(struct mtk_vcodec_dev *dev,
+                      enum mtk_vcodec_fw_use fw_use)
+{
+       return ERR_PTR(-ENODEV);
+}
+#endif /* CONFIG_VIDEO_MEDIATEK_VCODEC_VPU */
+
+#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCODEC_SCP)
+struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(struct mtk_vcodec_dev *dev);
+#else
+static inline struct mtk_vcodec_fw *
+mtk_vcodec_fw_scp_init(struct mtk_vcodec_dev *dev)
+{
+       return ERR_PTR(-ENODEV);
+}
+#endif /* CONFIG_VIDEO_MEDIATEK_VCODEC_SCP */
+
+#endif /* _MTK_VCODEC_FW_PRIV_H_ */
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c
new file mode 100644 (file)
index 0000000..d8e66b6
--- /dev/null
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "mtk_vcodec_fw_priv.h"
+#include "mtk_vcodec_util.h"
+#include "mtk_vcodec_drv.h"
+
+static int mtk_vcodec_scp_load_firmware(struct mtk_vcodec_fw *fw)
+{
+       return rproc_boot(scp_get_rproc(fw->scp));
+}
+
+static unsigned int mtk_vcodec_scp_get_vdec_capa(struct mtk_vcodec_fw *fw)
+{
+       return scp_get_vdec_hw_capa(fw->scp);
+}
+
+static unsigned int mtk_vcodec_scp_get_venc_capa(struct mtk_vcodec_fw *fw)
+{
+       return scp_get_venc_hw_capa(fw->scp);
+}
+
+static void *mtk_vcodec_vpu_scp_dm_addr(struct mtk_vcodec_fw *fw,
+                                       u32 dtcm_dmem_addr)
+{
+       return scp_mapping_dm_addr(fw->scp, dtcm_dmem_addr);
+}
+
+static int mtk_vcodec_scp_set_ipi_register(struct mtk_vcodec_fw *fw, int id,
+                                          mtk_vcodec_ipi_handler handler,
+                                          const char *name, void *priv)
+{
+       return scp_ipi_register(fw->scp, id, handler, priv);
+}
+
+static int mtk_vcodec_scp_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf,
+                                  unsigned int len, unsigned int wait)
+{
+       return scp_ipi_send(fw->scp, id, buf, len, wait);
+}
+
+static void mtk_vcodec_scp_release(struct mtk_vcodec_fw *fw)
+{
+       scp_put(fw->scp);
+}
+
+static const struct mtk_vcodec_fw_ops mtk_vcodec_rproc_msg = {
+       .load_firmware = mtk_vcodec_scp_load_firmware,
+       .get_vdec_capa = mtk_vcodec_scp_get_vdec_capa,
+       .get_venc_capa = mtk_vcodec_scp_get_venc_capa,
+       .map_dm_addr = mtk_vcodec_vpu_scp_dm_addr,
+       .ipi_register = mtk_vcodec_scp_set_ipi_register,
+       .ipi_send = mtk_vcodec_scp_ipi_send,
+       .release = mtk_vcodec_scp_release,
+};
+
+struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(struct mtk_vcodec_dev *dev)
+{
+       struct mtk_vcodec_fw *fw;
+       struct mtk_scp *scp;
+
+       scp = scp_get(dev->plat_dev);
+       if (!scp) {
+               mtk_v4l2_err("could not get vdec scp handle");
+               return ERR_PTR(-EPROBE_DEFER);
+       }
+
+       fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL);
+       fw->type = SCP;
+       fw->ops = &mtk_vcodec_rproc_msg;
+       fw->scp = scp;
+
+       return fw;
+}
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c
new file mode 100644 (file)
index 0000000..cd27f63
--- /dev/null
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "mtk_vcodec_fw_priv.h"
+#include "mtk_vcodec_util.h"
+#include "mtk_vcodec_drv.h"
+
+static int mtk_vcodec_vpu_load_firmware(struct mtk_vcodec_fw *fw)
+{
+       return vpu_load_firmware(fw->pdev);
+}
+
+static unsigned int mtk_vcodec_vpu_get_vdec_capa(struct mtk_vcodec_fw *fw)
+{
+       return vpu_get_vdec_hw_capa(fw->pdev);
+}
+
+static unsigned int mtk_vcodec_vpu_get_venc_capa(struct mtk_vcodec_fw *fw)
+{
+       return vpu_get_venc_hw_capa(fw->pdev);
+}
+
+static void *mtk_vcodec_vpu_map_dm_addr(struct mtk_vcodec_fw *fw,
+                                       u32 dtcm_dmem_addr)
+{
+       return vpu_mapping_dm_addr(fw->pdev, dtcm_dmem_addr);
+}
+
+static int mtk_vcodec_vpu_set_ipi_register(struct mtk_vcodec_fw *fw, int id,
+                                          mtk_vcodec_ipi_handler handler,
+                                          const char *name, void *priv)
+{
+       /*
+        * The handler we receive takes a void * as its first argument. We
+        * cannot change this because it needs to be passed down to the rproc
+        * subsystem when SCP is used. VPU takes a const argument, which is
+        * more constrained, so the conversion below is safe.
+        */
+       ipi_handler_t handler_const = (ipi_handler_t)handler;
+
+       return vpu_ipi_register(fw->pdev, id, handler_const, name, priv);
+}
+
+static int mtk_vcodec_vpu_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf,
+                                  unsigned int len, unsigned int wait)
+{
+       return vpu_ipi_send(fw->pdev, id, buf, len);
+}
+
+static void mtk_vcodec_vpu_release(struct mtk_vcodec_fw *fw)
+{
+       put_device(&fw->pdev->dev);
+}
+
+static void mtk_vcodec_vpu_reset_handler(void *priv)
+{
+       struct mtk_vcodec_dev *dev = priv;
+       struct mtk_vcodec_ctx *ctx;
+
+       mtk_v4l2_err("Watchdog timeout!!");
+
+       mutex_lock(&dev->dev_mutex);
+       list_for_each_entry(ctx, &dev->ctx_list, list) {
+               ctx->state = MTK_STATE_ABORT;
+               mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ABORT",
+                              ctx->id);
+       }
+       mutex_unlock(&dev->dev_mutex);
+}
+
+static const struct mtk_vcodec_fw_ops mtk_vcodec_vpu_msg = {
+       .load_firmware = mtk_vcodec_vpu_load_firmware,
+       .get_vdec_capa = mtk_vcodec_vpu_get_vdec_capa,
+       .get_venc_capa = mtk_vcodec_vpu_get_venc_capa,
+       .map_dm_addr = mtk_vcodec_vpu_map_dm_addr,
+       .ipi_register = mtk_vcodec_vpu_set_ipi_register,
+       .ipi_send = mtk_vcodec_vpu_ipi_send,
+       .release = mtk_vcodec_vpu_release,
+};
+
+struct mtk_vcodec_fw *mtk_vcodec_fw_vpu_init(struct mtk_vcodec_dev *dev,
+                                            enum mtk_vcodec_fw_use fw_use)
+{
+       struct platform_device *fw_pdev;
+       struct mtk_vcodec_fw *fw;
+       enum rst_id rst_id;
+
+       switch (fw_use) {
+       case ENCODER:
+               rst_id = VPU_RST_ENC;
+               break;
+       case DECODER:
+       default:
+               rst_id = VPU_RST_DEC;
+               break;
+       }
+
+       fw_pdev = vpu_get_plat_device(dev->plat_dev);
+       if (!fw_pdev) {
+               mtk_v4l2_err("firmware device is not ready");
+               return ERR_PTR(-EINVAL);
+       }
+       vpu_wdt_reg_handler(fw_pdev, mtk_vcodec_vpu_reset_handler, dev, rst_id);
+
+       fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL);
+       fw->type = VPU;
+       fw->ops = &mtk_vcodec_vpu_msg;
+       fw->pdev = fw_pdev;
+
+       return fw;
+}
index 7b79a33dc9d6e43d0458798f3a64887af0a3406b..05c9fbd51f0c057586afbe588541c4a93c9e3487 100644 (file)
@@ -243,8 +243,19 @@ struct venc_controls {
 
        u32 header_mode;
 
-       u32 profile;
-       u32 level;
+       struct {
+               u32 h264;
+               u32 mpeg4;
+               u32 hevc;
+               u32 vp8;
+               u32 vp9;
+       } profile;
+       struct {
+               u32 h264;
+               u32 mpeg4;
+               u32 hevc;
+               u32 vp9;
+       } level;
 };
 
 struct venus_buffer {
index 57877eacecf08758af00459e6abc3e687bcebcd2..a9538c2cc3c9dcee80b963c83f6c2578e1f9050a 100644 (file)
@@ -794,7 +794,7 @@ skip_pmdomains:
        return 0;
 
 opp_dl_add_err:
-       dev_pm_domain_detach(core->opp_pmdomain, true);
+       dev_pm_opp_detach_genpd(core->opp_table);
 opp_attach_err:
        if (core->pd_dl_venus) {
                device_link_del(core->pd_dl_venus);
@@ -832,7 +832,7 @@ skip_pmdomains:
        if (core->opp_dl_venus)
                device_link_del(core->opp_dl_venus);
 
-       dev_pm_domain_detach(core->opp_pmdomain, true);
+       dev_pm_opp_detach_genpd(core->opp_table);
 }
 
 static int core_get_v4(struct device *dev)
index f8b1484e7dcd7449ef8ba746e76a962d5d12a204..47246528ac7ef5985a668bcca61e909ae0c69b29 100644 (file)
@@ -537,6 +537,7 @@ static int venc_set_properties(struct venus_inst *inst)
        struct hfi_quantization quant;
        struct hfi_quantization_range quant_range;
        u32 ptype, rate_control, bitrate;
+       u32 profile, level;
        int ret;
 
        ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2);
@@ -684,7 +685,35 @@ static int venc_set_properties(struct venus_inst *inst)
        if (ret)
                return ret;
 
-       ret = venus_helper_set_profile_level(inst, ctr->profile, ctr->level);
+       switch (inst->hfi_codec) {
+       case HFI_VIDEO_CODEC_H264:
+               profile = ctr->profile.h264;
+               level = ctr->level.h264;
+               break;
+       case HFI_VIDEO_CODEC_MPEG4:
+               profile = ctr->profile.mpeg4;
+               level = ctr->level.mpeg4;
+               break;
+       case HFI_VIDEO_CODEC_VP8:
+               profile = ctr->profile.vp8;
+               level = 0;
+               break;
+       case HFI_VIDEO_CODEC_VP9:
+               profile = ctr->profile.vp9;
+               level = ctr->level.vp9;
+               break;
+       case HFI_VIDEO_CODEC_HEVC:
+               profile = ctr->profile.hevc;
+               level = ctr->level.hevc;
+               break;
+       case HFI_VIDEO_CODEC_MPEG2:
+       default:
+               profile = 0;
+               level = 0;
+               break;
+       }
+
+       ret = venus_helper_set_profile_level(inst, profile, level);
        if (ret)
                return ret;
 
index 0708b3b89d0cfc08198727ae0cde5d553ed0c5fd..cf860e6446c0db469f5c48a49009dc530d5e71c1 100644 (file)
@@ -103,15 +103,25 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
                ctr->h264_entropy_mode = ctrl->val;
                break;
        case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
+               ctr->profile.mpeg4 = ctrl->val;
+               break;
        case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+               ctr->profile.h264 = ctrl->val;
+               break;
        case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
+               ctr->profile.hevc = ctrl->val;
+               break;
        case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
-               ctr->profile = ctrl->val;
+               ctr->profile.vp8 = ctrl->val;
                break;
        case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
+               ctr->level.mpeg4 = ctrl->val;
+               break;
        case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+               ctr->level.h264 = ctrl->val;
+               break;
        case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
-               ctr->level = ctrl->val;
+               ctr->level.hevc = ctrl->val;
                break;
        case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
                ctr->h264_i_qp = ctrl->val;
index 74b054947bbed9cba1ead45d0615bd3accd1682f..fc64d0c8492a950288d0d2c42548ea61c0989873 100644 (file)
@@ -4,36 +4,43 @@
  * validate the existing APIs in the media subsystem. It can also aid
  * developers working on userspace applications.
  *
- * When this module is loaded, it will attempt to modprobe 'dvb_vidtv_tuner' and 'dvb_vidtv_demod'.
+ * When this module is loaded, it will attempt to modprobe 'dvb_vidtv_tuner'
+ * and 'dvb_vidtv_demod'.
  *
  * Copyright (C) 2020 Daniel W. S. Almeida
  */
 
+#include <linux/dev_printk.h>
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
-#include <linux/dev_printk.h>
 #include <linux/time.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
 
 #include "vidtv_bridge.h"
+#include "vidtv_common.h"
 #include "vidtv_demod.h"
-#include "vidtv_tuner.h"
-#include "vidtv_ts.h"
 #include "vidtv_mux.h"
-#include "vidtv_common.h"
+#include "vidtv_ts.h"
+#include "vidtv_tuner.h"
 
-//#define MUX_BUF_MAX_SZ
-//#define MUX_BUF_MIN_SZ
+#define MUX_BUF_MIN_SZ 90164
+#define MUX_BUF_MAX_SZ (MUX_BUF_MIN_SZ * 10)
 #define TUNER_DEFAULT_ADDR 0x68
 #define DEMOD_DEFAULT_ADDR 0x60
+#define VIDTV_DEFAULT_NETWORK_ID 0xff44
+#define VIDTV_DEFAULT_NETWORK_NAME "LinuxTV.org"
+#define VIDTV_DEFAULT_TS_ID 0x4081
 
-/* LNBf fake parameters: ranges used by an Universal (extended) European LNBf */
-#define LNB_CUT_FREQUENCY      11700000
-#define LNB_LOW_FREQ           9750000
-#define LNB_HIGH_FREQ          10600000
-
+/*
+ * The LNBf fake parameters here are the ranges used by an
+ * Universal (extended) European LNBf, which is likely the most common LNBf
+ * found on Satellite digital TV system nowadays.
+ */
+#define LNB_CUT_FREQUENCY      11700000        /* high IF frequency */
+#define LNB_LOW_FREQ           9750000         /* low IF frequency */
+#define LNB_HIGH_FREQ          10600000        /* transition frequency */
 
 static unsigned int drop_tslock_prob_on_low_snr;
 module_param(drop_tslock_prob_on_low_snr, uint, 0);
@@ -92,7 +99,8 @@ MODULE_PARM_DESC(si_period_msec, "How often to send SI packets. Default: 40ms");
 
 static unsigned int pcr_period_msec = 40;
 module_param(pcr_period_msec, uint, 0);
-MODULE_PARM_DESC(pcr_period_msec, "How often to send PCR packets. Default: 40ms");
+MODULE_PARM_DESC(pcr_period_msec,
+                "How often to send PCR packets. Default: 40ms");
 
 static unsigned int mux_rate_kbytes_sec = 4096;
 module_param(mux_rate_kbytes_sec, uint, 0);
@@ -104,16 +112,14 @@ MODULE_PARM_DESC(pcr_pid, "PCR PID for all channels: defaults to 0x200");
 
 static unsigned int mux_buf_sz_pkts;
 module_param(mux_buf_sz_pkts, uint, 0);
-MODULE_PARM_DESC(mux_buf_sz_pkts, "Size for the internal mux buffer in multiples of 188 bytes");
-
-#define MUX_BUF_MIN_SZ 90164
-#define MUX_BUF_MAX_SZ (MUX_BUF_MIN_SZ * 10)
+MODULE_PARM_DESC(mux_buf_sz_pkts,
+                "Size for the internal mux buffer in multiples of 188 bytes");
 
 static u32 vidtv_bridge_mux_buf_sz_for_mux_rate(void)
 {
        u32 max_elapsed_time_msecs =  VIDTV_MAX_SLEEP_USECS / USEC_PER_MSEC;
-       u32 nbytes_expected;
        u32 mux_buf_sz = mux_buf_sz_pkts * TS_PACKET_LEN;
+       u32 nbytes_expected;
 
        nbytes_expected = mux_rate_kbytes_sec;
        nbytes_expected *= max_elapsed_time_msecs;
@@ -143,14 +149,12 @@ static bool vidtv_bridge_check_demod_lock(struct vidtv_dvb *dvb, u32 n)
                          FE_HAS_LOCK);
 }
 
-static void
-vidtv_bridge_on_new_pkts_avail(void *priv, u8 *buf, u32 npkts)
+/*
+ * called on a separate thread by the mux when new packets become available
+ */
+static void vidtv_bridge_on_new_pkts_avail(void *priv, u8 *buf, u32 npkts)
 {
-       /*
-        * called on a separate thread by the mux when new packets become
-        * available
-        */
-       struct vidtv_dvb *dvb = (struct vidtv_dvb *)priv;
+       struct vidtv_dvb *dvb = priv;
 
        /* drop packets if we lose the lock */
        if (vidtv_bridge_check_demod_lock(dvb, 0))
@@ -159,7 +163,17 @@ vidtv_bridge_on_new_pkts_avail(void *priv, u8 *buf, u32 npkts)
 
 static int vidtv_start_streaming(struct vidtv_dvb *dvb)
 {
-       struct vidtv_mux_init_args mux_args = {0};
+       struct vidtv_mux_init_args mux_args = {
+               .mux_rate_kbytes_sec         = mux_rate_kbytes_sec,
+               .on_new_packets_available_cb = vidtv_bridge_on_new_pkts_avail,
+               .pcr_period_usecs            = pcr_period_msec * USEC_PER_MSEC,
+               .si_period_usecs             = si_period_msec * USEC_PER_MSEC,
+               .pcr_pid                     = pcr_pid,
+               .transport_stream_id         = VIDTV_DEFAULT_TS_ID,
+               .network_id                  = VIDTV_DEFAULT_NETWORK_ID,
+               .network_name                = VIDTV_DEFAULT_NETWORK_NAME,
+               .priv                        = dvb,
+       };
        struct device *dev = &dvb->pdev->dev;
        u32 mux_buf_sz;
 
@@ -168,19 +182,17 @@ static int vidtv_start_streaming(struct vidtv_dvb *dvb)
                return 0;
        }
 
-       mux_buf_sz = (mux_buf_sz_pkts) ? mux_buf_sz_pkts : vidtv_bridge_mux_buf_sz_for_mux_rate();
+       if (mux_buf_sz_pkts)
+               mux_buf_sz = mux_buf_sz_pkts;
+       else
+               mux_buf_sz = vidtv_bridge_mux_buf_sz_for_mux_rate();
 
-       mux_args.mux_rate_kbytes_sec         = mux_rate_kbytes_sec;
-       mux_args.on_new_packets_available_cb = vidtv_bridge_on_new_pkts_avail;
-       mux_args.mux_buf_sz                  = mux_buf_sz;
-       mux_args.pcr_period_usecs            = pcr_period_msec * 1000;
-       mux_args.si_period_usecs             = si_period_msec * 1000;
-       mux_args.pcr_pid                     = pcr_pid;
-       mux_args.transport_stream_id         = VIDTV_DEFAULT_TS_ID;
-       mux_args.priv                        = dvb;
+       mux_args.mux_buf_sz  = mux_buf_sz;
 
        dvb->streaming = true;
-       dvb->mux = vidtv_mux_init(dvb->fe[0], dev, mux_args);
+       dvb->mux = vidtv_mux_init(dvb->fe[0], dev, &mux_args);
+       if (!dvb->mux)
+               return -ENOMEM;
        vidtv_mux_start_thread(dvb->mux);
 
        dev_dbg_ratelimited(dev, "Started streaming\n");
@@ -204,8 +216,8 @@ static int vidtv_start_feed(struct dvb_demux_feed *feed)
 {
        struct dvb_demux *demux = feed->demux;
        struct vidtv_dvb *dvb   = demux->priv;
-       int rc;
        int ret;
+       int rc;
 
        if (!demux->dmx.frontend)
                return -EINVAL;
@@ -243,9 +255,9 @@ static int vidtv_stop_feed(struct dvb_demux_feed *feed)
 
 static struct dvb_frontend *vidtv_get_frontend_ptr(struct i2c_client *c)
 {
-       /* the demod will set this when its probe function runs */
        struct vidtv_demod_state *state = i2c_get_clientdata(c);
 
+       /* the demod will set this when its probe function runs */
        return &state->frontend;
 }
 
@@ -253,6 +265,11 @@ static int vidtv_master_xfer(struct i2c_adapter *i2c_adap,
                             struct i2c_msg msgs[],
                             int num)
 {
+       /*
+        * Right now, this virtual driver doesn't really send or receive
+        * messages from I2C. A real driver will require an implementation
+        * here.
+        */
        return 0;
 }
 
@@ -320,11 +337,10 @@ static int vidtv_bridge_dmxdev_init(struct vidtv_dvb *dvb)
 
 static int vidtv_bridge_probe_demod(struct vidtv_dvb *dvb, u32 n)
 {
-       struct vidtv_demod_config cfg = {};
-
-       cfg.drop_tslock_prob_on_low_snr     = drop_tslock_prob_on_low_snr;
-       cfg.recover_tslock_prob_on_good_snr = recover_tslock_prob_on_good_snr;
-
+       struct vidtv_demod_config cfg = {
+               .drop_tslock_prob_on_low_snr     = drop_tslock_prob_on_low_snr,
+               .recover_tslock_prob_on_good_snr = recover_tslock_prob_on_good_snr,
+       };
        dvb->i2c_client_demod[n] = dvb_module_probe("dvb_vidtv_demod",
                                                    NULL,
                                                    &dvb->i2c_adapter,
@@ -343,14 +359,14 @@ static int vidtv_bridge_probe_demod(struct vidtv_dvb *dvb, u32 n)
 
 static int vidtv_bridge_probe_tuner(struct vidtv_dvb *dvb, u32 n)
 {
-       struct vidtv_tuner_config cfg = {};
+       struct vidtv_tuner_config cfg = {
+               .fe                       = dvb->fe[n],
+               .mock_power_up_delay_msec = mock_power_up_delay_msec,
+               .mock_tune_delay_msec     = mock_tune_delay_msec,
+       };
        u32 freq;
        int i;
 
-       cfg.fe                       = dvb->fe[n];
-       cfg.mock_power_up_delay_msec = mock_power_up_delay_msec;
-       cfg.mock_tune_delay_msec     = mock_tune_delay_msec;
-
        /* TODO: check if the frequencies are at a valid range */
 
        memcpy(cfg.vidtv_valid_dvb_t_freqs,
@@ -389,9 +405,7 @@ static int vidtv_bridge_probe_tuner(struct vidtv_dvb *dvb, u32 n)
 
 static int vidtv_bridge_dvb_init(struct vidtv_dvb *dvb)
 {
-       int ret;
-       int i;
-       int j;
+       int ret, i, j;
 
        ret = vidtv_bridge_i2c_register_adap(dvb);
        if (ret < 0)
index 78fe8472fa37982fcae6925f93462b46a236649d..2528adaee27d3614374d0039f3d9ecac35c84b3c 100644 (file)
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/types.h>
+
 #include <media/dmxdev.h>
 #include <media/dvb_demux.h>
 #include <media/dvb_frontend.h>
+
 #include "vidtv_mux.h"
 
 /**
@@ -32,7 +34,7 @@
  * @adapter: Represents a DTV adapter. See 'dvb_register_adapter'.
  * @demux: The demux used by the dvb_dmx_swfilter_packets() call.
  * @dmx_dev: Represents a demux device.
- * @dmx_frontend: The frontends associated with the demux.
+ * @dmx_fe: The frontends associated with the demux.
  * @i2c_adapter: The i2c_adapter associated with the bridge driver.
  * @i2c_client_demod: The i2c_clients associated with the demodulator modules.
  * @i2c_client_tuner: The i2c_clients associated with the tuner modules.
index f2b97cf08e87a655d3f952beb9b3713222cb5e6a..8ad6c0744d36306e8dbc5a839828b915be8aaa54 100644 (file)
@@ -9,6 +9,7 @@
  * When vidtv boots, it will create some hardcoded channels.
  * Their services will be concatenated to populate the SDT.
  * Their programs will be concatenated to populate the PAT
+ * Their events will be concatenated to populate the EIT
  * For each program in the PAT, a PMT section will be created
  * The PMT section for a channel will be assigned its streams.
  * Every stream will have its corresponding encoder polled to produce TS packets
  * Copyright (C) 2020 Daniel W. S. Almeida
  */
 
-#include <linux/types.h>
-#include <linux/slab.h>
 #include <linux/dev_printk.h>
 #include <linux/ratelimit.h>
+#include <linux/slab.h>
+#include <linux/types.h>
 
 #include "vidtv_channel.h"
-#include "vidtv_psi.h"
+#include "vidtv_common.h"
 #include "vidtv_encoder.h"
 #include "vidtv_mux.h"
-#include "vidtv_common.h"
+#include "vidtv_psi.h"
 #include "vidtv_s302m.h"
 
 static void vidtv_channel_encoder_destroy(struct vidtv_encoder *e)
 {
-       struct vidtv_encoder *curr = e;
        struct vidtv_encoder *tmp = NULL;
+       struct vidtv_encoder *curr = e;
 
        while (curr) {
                /* forward the call to the derived type */
@@ -44,55 +45,88 @@ static void vidtv_channel_encoder_destroy(struct vidtv_encoder *e)
 }
 
 #define ENCODING_ISO8859_15 "\x0b"
+#define TS_NIT_PID     0x10
 
+/*
+ * init an audio only channel with a s302m encoder
+ */
 struct vidtv_channel
 *vidtv_channel_s302m_init(struct vidtv_channel *head, u16 transport_stream_id)
 {
-       /*
-        * init an audio only channel with a s302m encoder
-        */
-       const u16 s302m_service_id          = 0x880;
-       const u16 s302m_program_num         = 0x880;
-       const u16 s302m_program_pid         = 0x101; /* packet id for PMT*/
-       const u16 s302m_es_pid              = 0x111; /* packet id for the ES */
        const __be32 s302m_fid              = cpu_to_be32(VIDTV_S302M_FORMAT_IDENTIFIER);
-
-       char *name = ENCODING_ISO8859_15 "Beethoven";
+       char *event_text = ENCODING_ISO8859_15 "Bagatelle No. 25 in A minor for solo piano, also known as F\xfcr Elise, composed by Ludwig van Beethoven";
+       char *event_name = ENCODING_ISO8859_15 "Ludwig van Beethoven: F\xfcr Elise";
+       struct vidtv_s302m_encoder_init_args encoder_args = {};
+       char *iso_language_code = ENCODING_ISO8859_15 "eng";
        char *provider = ENCODING_ISO8859_15 "LinuxTV.org";
+       char *name = ENCODING_ISO8859_15 "Beethoven";
+       const u16 s302m_es_pid              = 0x111; /* packet id for the ES */
+       const u16 s302m_program_pid         = 0x101; /* packet id for PMT*/
+       const u16 s302m_service_id          = 0x880;
+       const u16 s302m_program_num         = 0x880;
+       const u16 s302m_beethoven_event_id  = 1;
+       struct vidtv_channel *s302m;
 
-       struct vidtv_channel *s302m = kzalloc(sizeof(*s302m), GFP_KERNEL);
-       struct vidtv_s302m_encoder_init_args encoder_args = {};
+       s302m = kzalloc(sizeof(*s302m), GFP_KERNEL);
+       if (!s302m)
+               return NULL;
 
        s302m->name = kstrdup(name, GFP_KERNEL);
+       if (!s302m->name)
+               goto free_s302m;
 
-       s302m->service = vidtv_psi_sdt_service_init(NULL, s302m_service_id);
+       s302m->service = vidtv_psi_sdt_service_init(NULL, s302m_service_id, false, true);
+       if (!s302m->service)
+               goto free_name;
 
        s302m->service->descriptor = (struct vidtv_psi_desc *)
                                     vidtv_psi_service_desc_init(NULL,
-                                                                DIGITAL_TELEVISION_SERVICE,
+                                                                DIGITAL_RADIO_SOUND_SERVICE,
                                                                 name,
                                                                 provider);
+       if (!s302m->service->descriptor)
+               goto free_service;
 
        s302m->transport_stream_id = transport_stream_id;
 
        s302m->program = vidtv_psi_pat_program_init(NULL,
                                                    s302m_service_id,
                                                    s302m_program_pid);
+       if (!s302m->program)
+               goto free_service;
 
        s302m->program_num = s302m_program_num;
 
        s302m->streams = vidtv_psi_pmt_stream_init(NULL,
                                                   STREAM_PRIVATE_DATA,
                                                   s302m_es_pid);
+       if (!s302m->streams)
+               goto free_program;
 
        s302m->streams->descriptor = (struct vidtv_psi_desc *)
                                     vidtv_psi_registration_desc_init(NULL,
                                                                      s302m_fid,
                                                                      NULL,
                                                                      0);
+       if (!s302m->streams->descriptor)
+               goto free_streams;
+
        encoder_args.es_pid = s302m_es_pid;
 
        s302m->encoders = vidtv_s302m_encoder_init(encoder_args);
+       if (!s302m->encoders)
+               goto free_streams;
+
+       s302m->events = vidtv_psi_eit_event_init(NULL, s302m_beethoven_event_id);
+       if (!s302m->events)
+               goto free_encoders;
+       s302m->events->descriptor = (struct vidtv_psi_desc *)
+                                   vidtv_psi_short_event_desc_init(NULL,
+                                                                   iso_language_code,
+                                                                   event_name,
+                                                                   event_text);
+       if (!s302m->events->descriptor)
+               goto free_events;
 
        if (head) {
                while (head->next)
@@ -102,6 +136,68 @@ struct vidtv_channel
        }
 
        return s302m;
+
+free_events:
+       vidtv_psi_eit_event_destroy(s302m->events);
+free_encoders:
+       vidtv_s302m_encoder_destroy(s302m->encoders);
+free_streams:
+       vidtv_psi_pmt_stream_destroy(s302m->streams);
+free_program:
+       vidtv_psi_pat_program_destroy(s302m->program);
+free_service:
+       vidtv_psi_sdt_service_destroy(s302m->service);
+free_name:
+       kfree(s302m->name);
+free_s302m:
+       kfree(s302m);
+
+       return NULL;
+}
+
+static struct vidtv_psi_table_eit_event
+*vidtv_channel_eit_event_cat_into_new(struct vidtv_mux *m)
+{
+       /* Concatenate the events */
+       const struct vidtv_channel *cur_chnl = m->channels;
+       struct vidtv_psi_table_eit_event *curr = NULL;
+       struct vidtv_psi_table_eit_event *head = NULL;
+       struct vidtv_psi_table_eit_event *tail = NULL;
+       struct vidtv_psi_desc *desc = NULL;
+       u16 event_id;
+
+       if (!cur_chnl)
+               return NULL;
+
+       while (cur_chnl) {
+               curr = cur_chnl->events;
+
+               if (!curr)
+                       dev_warn_ratelimited(m->dev,
+                                            "No events found for channel %s\n",
+                                            cur_chnl->name);
+
+               while (curr) {
+                       event_id = be16_to_cpu(curr->event_id);
+                       tail = vidtv_psi_eit_event_init(tail, event_id);
+                       if (!tail) {
+                               vidtv_psi_eit_event_destroy(head);
+                               return NULL;
+                       }
+
+                       desc = vidtv_psi_desc_clone(curr->descriptor);
+                       vidtv_psi_desc_assign(&tail->descriptor, desc);
+
+                       if (!head)
+                               head = tail;
+
+                       curr = curr->next;
+               }
+
+               cur_chnl = cur_chnl->next;
+       }
+
+       return head;
 }
 
 static struct vidtv_psi_table_sdt_service
@@ -125,13 +221,21 @@ static struct vidtv_psi_table_sdt_service
 
                if (!curr)
                        dev_warn_ratelimited(m->dev,
-                                            "No services found for channel %s\n", cur_chnl->name);
+                                            "No services found for channel %s\n",
+                                            cur_chnl->name);
 
                while (curr) {
                        service_id = be16_to_cpu(curr->service_id);
-                       tail = vidtv_psi_sdt_service_init(tail, service_id);
+                       tail = vidtv_psi_sdt_service_init(tail,
+                                                         service_id,
+                                                         curr->EIT_schedule,
+                                                         curr->EIT_present_following);
+                       if (!tail)
+                               goto free;
 
                        desc = vidtv_psi_desc_clone(curr->descriptor);
+                       if (!desc)
+                               goto free_tail;
                        vidtv_psi_desc_assign(&tail->descriptor, desc);
 
                        if (!head)
@@ -144,6 +248,12 @@ static struct vidtv_psi_table_sdt_service
        }
 
        return head;
+
+free_tail:
+       vidtv_psi_sdt_service_destroy(tail);
+free:
+       vidtv_psi_sdt_service_destroy(head);
+       return NULL;
 }
 
 static struct vidtv_psi_table_pat_program*
@@ -174,6 +284,10 @@ vidtv_channel_pat_prog_cat_into_new(struct vidtv_mux *m)
                        tail = vidtv_psi_pat_program_init(tail,
                                                          serv_id,
                                                          pid);
+                       if (!tail) {
+                               vidtv_psi_pat_program_destroy(head);
+                               return NULL;
+                       }
 
                        if (!head)
                                head = tail;
@@ -183,30 +297,30 @@ vidtv_channel_pat_prog_cat_into_new(struct vidtv_mux *m)
 
                cur_chnl = cur_chnl->next;
        }
+       /* Add the NIT table */
+       vidtv_psi_pat_program_init(tail, 0, TS_NIT_PID);
 
        return head;
 }
 
+/*
+ * Match channels to their respective PMT sections, then assign the
+ * streams
+ */
 static void
 vidtv_channel_pmt_match_sections(struct vidtv_channel *channels,
                                 struct vidtv_psi_table_pmt **sections,
                                 u32 nsections)
 {
-       /*
-        * Match channels to their respective PMT sections, then assign the
-        * streams
-        */
        struct vidtv_psi_table_pmt *curr_section = NULL;
-       struct vidtv_channel *cur_chnl = channels;
-
-       struct vidtv_psi_table_pmt_stream *s = NULL;
        struct vidtv_psi_table_pmt_stream *head = NULL;
        struct vidtv_psi_table_pmt_stream *tail = NULL;
-
+       struct vidtv_psi_table_pmt_stream *s = NULL;
+       struct vidtv_channel *cur_chnl = channels;
        struct vidtv_psi_desc *desc = NULL;
-       u32 j;
-       u16 curr_id;
        u16 e_pid; /* elementary stream pid */
+       u16 curr_id;
+       u32 j;
 
        while (cur_chnl) {
                for (j = 0; j < nsections; ++j) {
@@ -232,7 +346,8 @@ vidtv_channel_pmt_match_sections(struct vidtv_channel *channels,
                                                head = tail;
 
                                        desc = vidtv_psi_desc_clone(s->descriptor);
-                                       vidtv_psi_desc_assign(&tail->descriptor, desc);
+                                       vidtv_psi_desc_assign(&tail->descriptor,
+                                                             desc);
 
                                        s = s->next;
                                }
@@ -246,17 +361,103 @@ vidtv_channel_pmt_match_sections(struct vidtv_channel *channels,
        }
 }
 
-void vidtv_channel_si_init(struct vidtv_mux *m)
+static void
+vidtv_channel_destroy_service_list(struct vidtv_psi_desc_service_list_entry *e)
+{
+       struct vidtv_psi_desc_service_list_entry *tmp;
+
+       while (e) {
+               tmp = e;
+               e = e->next;
+               kfree(tmp);
+       }
+}
+
+static struct vidtv_psi_desc_service_list_entry
+*vidtv_channel_build_service_list(struct vidtv_psi_table_sdt_service *s)
+{
+       struct vidtv_psi_desc_service_list_entry *curr_e = NULL;
+       struct vidtv_psi_desc_service_list_entry *head_e = NULL;
+       struct vidtv_psi_desc_service_list_entry *prev_e = NULL;
+       struct vidtv_psi_desc *desc = s->descriptor;
+       struct vidtv_psi_desc_service *s_desc;
+
+       while (s) {
+               while (desc) {
+                       if (s->descriptor->type != SERVICE_DESCRIPTOR)
+                               goto next_desc;
+
+                       s_desc = (struct vidtv_psi_desc_service *)desc;
+
+                       curr_e = kzalloc(sizeof(*curr_e), GFP_KERNEL);
+                       if (!curr_e) {
+                               vidtv_channel_destroy_service_list(head_e);
+                               return NULL;
+                       }
+
+                       curr_e->service_id = s->service_id;
+                       curr_e->service_type = s_desc->service_type;
+
+                       if (!head_e)
+                               head_e = curr_e;
+                       if (prev_e)
+                               prev_e->next = curr_e;
+
+                       prev_e = curr_e;
+
+next_desc:
+                       desc = desc->next;
+               }
+               s = s->next;
+       }
+       return head_e;
+}
+
+int vidtv_channel_si_init(struct vidtv_mux *m)
 {
+       struct vidtv_psi_desc_service_list_entry *service_list = NULL;
        struct vidtv_psi_table_pat_program *programs = NULL;
        struct vidtv_psi_table_sdt_service *services = NULL;
+       struct vidtv_psi_table_eit_event *events = NULL;
 
        m->si.pat = vidtv_psi_pat_table_init(m->transport_stream_id);
+       if (!m->si.pat)
+               return -ENOMEM;
 
-       m->si.sdt = vidtv_psi_sdt_table_init(m->transport_stream_id);
+       m->si.sdt = vidtv_psi_sdt_table_init(m->network_id,
+                                            m->transport_stream_id);
+       if (!m->si.sdt)
+               goto free_pat;
 
        programs = vidtv_channel_pat_prog_cat_into_new(m);
+       if (!programs)
+               goto free_sdt;
        services = vidtv_channel_sdt_serv_cat_into_new(m);
+       if (!services)
+               goto free_programs;
+
+       events = vidtv_channel_eit_event_cat_into_new(m);
+       if (!events)
+               goto free_services;
+
+       /* look for a service descriptor for every service */
+       service_list = vidtv_channel_build_service_list(services);
+       if (!service_list)
+               goto free_events;
+
+       /* use these descriptors to build the NIT */
+       m->si.nit = vidtv_psi_nit_table_init(m->network_id,
+                                            m->transport_stream_id,
+                                            m->network_name,
+                                            service_list);
+       if (!m->si.nit)
+               goto free_service_list;
+
+       m->si.eit = vidtv_psi_eit_table_init(m->network_id,
+                                            m->transport_stream_id,
+                                            programs->service_id);
+       if (!m->si.eit)
+               goto free_nit;
 
        /* assemble all programs and assign to PAT */
        vidtv_psi_pat_program_assign(m->si.pat, programs);
@@ -264,31 +465,65 @@ void vidtv_channel_si_init(struct vidtv_mux *m)
        /* assemble all services and assign to SDT */
        vidtv_psi_sdt_service_assign(m->si.sdt, services);
 
-       m->si.pmt_secs = vidtv_psi_pmt_create_sec_for_each_pat_entry(m->si.pat, m->pcr_pid);
+       /* assemble all events and assign to EIT */
+       vidtv_psi_eit_event_assign(m->si.eit, events);
+
+       m->si.pmt_secs = vidtv_psi_pmt_create_sec_for_each_pat_entry(m->si.pat,
+                                                                    m->pcr_pid);
+       if (!m->si.pmt_secs)
+               goto free_eit;
 
        vidtv_channel_pmt_match_sections(m->channels,
                                         m->si.pmt_secs,
-                                        m->si.pat->programs);
+                                        m->si.pat->num_pmt);
+
+       vidtv_channel_destroy_service_list(service_list);
+
+       return 0;
+
+free_eit:
+       vidtv_psi_eit_table_destroy(m->si.eit);
+free_nit:
+       vidtv_psi_nit_table_destroy(m->si.nit);
+free_service_list:
+       vidtv_channel_destroy_service_list(service_list);
+free_events:
+       vidtv_psi_eit_event_destroy(events);
+free_services:
+       vidtv_psi_sdt_service_destroy(services);
+free_programs:
+       vidtv_psi_pat_program_destroy(programs);
+free_sdt:
+       vidtv_psi_sdt_table_destroy(m->si.sdt);
+free_pat:
+       vidtv_psi_pat_table_destroy(m->si.pat);
+       return 0;
 }
 
 void vidtv_channel_si_destroy(struct vidtv_mux *m)
 {
        u32 i;
-       u16 num_programs = m->si.pat->programs;
 
        vidtv_psi_pat_table_destroy(m->si.pat);
 
-       for (i = 0; i < num_programs; ++i)
+       for (i = 0; i < m->si.pat->num_pmt; ++i)
                vidtv_psi_pmt_table_destroy(m->si.pmt_secs[i]);
 
        kfree(m->si.pmt_secs);
        vidtv_psi_sdt_table_destroy(m->si.sdt);
+       vidtv_psi_nit_table_destroy(m->si.nit);
+       vidtv_psi_eit_table_destroy(m->si.eit);
 }
 
-void vidtv_channels_init(struct vidtv_mux *m)
+int vidtv_channels_init(struct vidtv_mux *m)
 {
        /* this is the place to add new 'channels' for vidtv */
        m->channels = vidtv_channel_s302m_init(NULL, m->transport_stream_id);
+
+       if (!m->channels)
+               return -ENOMEM;
+
+       return 0;
 }
 
 void vidtv_channels_destroy(struct vidtv_mux *m)
@@ -302,6 +537,7 @@ void vidtv_channels_destroy(struct vidtv_mux *m)
                vidtv_psi_pat_program_destroy(curr->program);
                vidtv_psi_pmt_stream_destroy(curr->streams);
                vidtv_channel_encoder_destroy(curr->encoders);
+               vidtv_psi_eit_event_destroy(curr->events);
 
                tmp = curr;
                curr = curr->next;
index 2c3cba4313b0b0a0d399e771bb420391fa8f1933..fff2e501d375d2b9caf2335e87e7bb734a27e818 100644 (file)
@@ -9,6 +9,7 @@
  * When vidtv boots, it will create some hardcoded channels.
  * Their services will be concatenated to populate the SDT.
  * Their programs will be concatenated to populate the PAT
+ * Their events will be concatenated to populate the EIT
  * For each program in the PAT, a PMT section will be created
  * The PMT section for a channel will be assigned its streams.
  * Every stream will have its corresponding encoder polled to produce TS packets
 #define VIDTV_CHANNEL_H
 
 #include <linux/types.h>
-#include "vidtv_psi.h"
+
 #include "vidtv_encoder.h"
 #include "vidtv_mux.h"
+#include "vidtv_psi.h"
 
 /**
  * struct vidtv_channel - A 'channel' abstraction
@@ -37,6 +39,7 @@
  * Every stream will have its corresponding encoder polled to produce TS packets
  * These packets may be interleaved by the mux and then delivered to the bridge
  *
+ * @name: name of the channel
  * @transport_stream_id: a number to identify the TS, chosen at will.
  * @service: A _single_ service. Will be concatenated into the SDT.
  * @program_num: The link between PAT, PMT and SDT.
@@ -44,6 +47,7 @@
  * Will be concatenated into the PAT.
  * @streams: A stream loop used to populate the PMT section for 'program'
  * @encoders: A encoder loop. There must be one encoder for each stream.
+ * @events: Optional event information. This will feed into the EIT.
  * @next: Optionally chain this channel.
  */
 struct vidtv_channel {
@@ -54,6 +58,7 @@ struct vidtv_channel {
        struct vidtv_psi_table_pat_program *program;
        struct vidtv_psi_table_pmt_stream *streams;
        struct vidtv_encoder *encoders;
+       struct vidtv_psi_table_eit_event *events;
        struct vidtv_channel *next;
 };
 
@@ -61,14 +66,14 @@ struct vidtv_channel {
  * vidtv_channel_si_init - Init the PSI tables from the channels in the mux
  * @m: The mux containing the channels.
  */
-void vidtv_channel_si_init(struct vidtv_mux *m);
+int vidtv_channel_si_init(struct vidtv_mux *m);
 void vidtv_channel_si_destroy(struct vidtv_mux *m);
 
 /**
  * vidtv_channels_init - Init hardcoded, fake 'channels'.
  * @m: The mux to store the channels into.
  */
-void vidtv_channels_init(struct vidtv_mux *m);
+int vidtv_channels_init(struct vidtv_mux *m);
 struct vidtv_channel
 *vidtv_channel_s302m_init(struct vidtv_channel *head, u16 transport_stream_id);
 void vidtv_channels_destroy(struct vidtv_mux *m);
index 818e7f2b9ec50a0e70e4a670f74d4b4b932dd428..42f63fdee681cbe60741a6670509864bb106c190 100644 (file)
@@ -16,7 +16,6 @@
 #define CLOCK_UNIT_27MHZ 27000000
 #define VIDTV_SLEEP_USECS 10000
 #define VIDTV_MAX_SLEEP_USECS (2 * VIDTV_SLEEP_USECS)
-#define VIDTV_DEFAULT_TS_ID 0x744
 
 u32 vidtv_memcpy(void *to,
                 size_t to_offset,
index eba7fe1a1b489c0fea5b20a331e36d24f948c7e8..b7823d97b30d5e1f3d2afcd7bff5a7c8bc3c3149 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/workqueue.h>
+
 #include <media/dvb_frontend.h>
 
 #include "vidtv_demod.h"
@@ -192,7 +193,6 @@ static void vidtv_demod_update_stats(struct dvb_frontend *fe)
 
        c->cnr.stat[0].svalue = state->tuner_cnr;
        c->cnr.stat[0].svalue -= prandom_u32_max(state->tuner_cnr / 50);
-
 }
 
 static int vidtv_demod_read_status(struct dvb_frontend *fe,
index 87651b0193e6ffd35cef5bda82869cb001f43f47..2b8404661348a98852e619ef27c13ac773b101c2 100644 (file)
@@ -12,6 +12,7 @@
 #define VIDTV_DEMOD_H
 
 #include <linux/dvb/frontend.h>
+
 #include <media/dvb_frontend.h>
 
 /**
@@ -19,6 +20,9 @@
  * modulation and fec_inner
  * @modulation: see enum fe_modulation
  * @fec: see enum fe_fec_rate
+ * @cnr_ok: S/N threshold to consider the signal as OK. Below that, there's
+ *          a chance of losing sync.
+ * @cnr_good: S/N threshold to consider the signal strong.
  *
  * This struct matches values for 'good' and 'ok' CNRs given the combination
  * of modulation and fec_inner in use. We might simulate some noise if the
@@ -52,13 +56,8 @@ struct vidtv_demod_config {
  * struct vidtv_demod_state - The demodulator state
  * @frontend: The frontend structure allocated by the demod.
  * @config: The config used to init the demod.
- * @poll_snr: The task responsible for periodically checking the simulated
- * signal quality, eventually dropping or reacquiring the TS lock.
  * @status: the demod status.
- * @cold_start: Whether the demod has not been init yet.
- * @poll_snr_thread_running: Whether the task responsible for periodically
- * checking the simulated signal quality is running.
- * @poll_snr_thread_restart: Whether we should restart the poll_snr task.
+ * @tuner_cnr: current S/N ratio for the signal carrier
  */
 struct vidtv_demod_state {
        struct dvb_frontend frontend;
index 65d81daef4c3edf8ce5a7ada65377b60b616fb51..50e3cf4eb4eb116b2f4d2b9ab96af28da0496ef3 100644 (file)
@@ -28,7 +28,7 @@ struct vidtv_access_unit {
        struct vidtv_access_unit *next;
 };
 
-/* Some musical notes, used by a tone generator */
+/* Some musical notes, used by a tone generator. Values are in Hz */
 enum musical_notes {
        NOTE_SILENT = 0,
 
@@ -103,14 +103,16 @@ enum musical_notes {
  * @encoder_buf_sz: The encoder buffer size, in bytes
  * @encoder_buf_offset: Our byte position in the encoder buffer.
  * @sample_count: How many samples we have encoded in total.
+ * @access_units: encoder payload units, used for clock references
  * @src_buf: The source of raw data to be encoded, encoder might set a
  * default if null.
+ * @src_buf_sz: size of @src_buf.
  * @src_buf_offset: Our position in the source buffer.
  * @is_video_encoder: Whether this a video encoder (as opposed to audio)
  * @ctx: Encoder-specific state.
  * @stream_id: Examples: Audio streams (0xc0-0xdf), Video streams
  * (0xe0-0xef).
- * @es_id: The TS PID to use for the elementary stream in this encoder.
+ * @es_pid: The TS PID to use for the elementary stream in this encoder.
  * @encode: Prepare enough AUs for the given amount of time.
  * @clear: Clear the encoder output.
  * @sync: Attempt to synchronize with this encoder.
@@ -131,9 +133,6 @@ struct vidtv_encoder {
        u32 encoder_buf_offset;
 
        u64 sample_count;
-       int last_duration;
-       int note_offset;
-       enum musical_notes last_tone;
 
        struct vidtv_access_unit *access_units;
 
index 082740ae9d445159e108e6e9006431f3c9a5a978..b51e6a3b8cbeb5652752f8def1dcc01fe7e9efc4 100644 (file)
  * Copyright (C) 2020 Daniel W. S. Almeida
  */
 
-#include <linux/types.h>
-#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/dev_printk.h>
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
-#include <linux/dev_printk.h>
+#include <linux/math64.h>
 #include <linux/ratelimit.h>
-#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/types.h>
 #include <linux/vmalloc.h>
-#include <linux/math64.h>
 
-#include "vidtv_mux.h"
-#include "vidtv_ts.h"
-#include "vidtv_pes.h"
-#include "vidtv_encoder.h"
 #include "vidtv_channel.h"
 #include "vidtv_common.h"
+#include "vidtv_encoder.h"
+#include "vidtv_mux.h"
+#include "vidtv_pes.h"
 #include "vidtv_psi.h"
+#include "vidtv_ts.h"
 
 static struct vidtv_mux_pid_ctx
 *vidtv_mux_get_pid_ctx(struct vidtv_mux *m, u16 pid)
@@ -47,33 +47,56 @@ static struct vidtv_mux_pid_ctx
        struct vidtv_mux_pid_ctx *ctx;
 
        ctx = vidtv_mux_get_pid_ctx(m, pid);
-
        if (ctx)
-               goto end;
+               return ctx;
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return NULL;
 
-       ctx      = kzalloc(sizeof(*ctx), GFP_KERNEL);
        ctx->pid = pid;
        ctx->cc  = 0;
        hash_add(m->pid_ctx, &ctx->h, pid);
 
-end:
        return ctx;
 }
 
-static void vidtv_mux_pid_ctx_init(struct vidtv_mux *m)
+static void vidtv_mux_pid_ctx_destroy(struct vidtv_mux *m)
+{
+       struct vidtv_mux_pid_ctx *ctx;
+       struct hlist_node *tmp;
+       int bkt;
+
+       hash_for_each_safe(m->pid_ctx, bkt, tmp, ctx, h) {
+               hash_del(&ctx->h);
+               kfree(ctx);
+       }
+}
+
+static int vidtv_mux_pid_ctx_init(struct vidtv_mux *m)
 {
        struct vidtv_psi_table_pat_program *p = m->si.pat->program;
        u16 pid;
 
        hash_init(m->pid_ctx);
        /* push the pcr pid ctx */
-       vidtv_mux_create_pid_ctx_once(m, m->pcr_pid);
-       /* push the null packet pid ctx */
-       vidtv_mux_create_pid_ctx_once(m, TS_NULL_PACKET_PID);
+       if (!vidtv_mux_create_pid_ctx_once(m, m->pcr_pid))
+               return -ENOMEM;
+       /* push the NULL packet pid ctx */
+       if (!vidtv_mux_create_pid_ctx_once(m, TS_NULL_PACKET_PID))
+               goto free;
        /* push the PAT pid ctx */
-       vidtv_mux_create_pid_ctx_once(m, VIDTV_PAT_PID);
+       if (!vidtv_mux_create_pid_ctx_once(m, VIDTV_PAT_PID))
+               goto free;
        /* push the SDT pid ctx */
-       vidtv_mux_create_pid_ctx_once(m, VIDTV_SDT_PID);
+       if (!vidtv_mux_create_pid_ctx_once(m, VIDTV_SDT_PID))
+               goto free;
+       /* push the NIT pid ctx */
+       if (!vidtv_mux_create_pid_ctx_once(m, VIDTV_NIT_PID))
+               goto free;
+       /* push the EIT pid ctx */
+       if (!vidtv_mux_create_pid_ctx_once(m, VIDTV_EIT_PID))
+               goto free;
 
        /* add a ctx for all PMT sections */
        while (p) {
@@ -81,18 +104,12 @@ static void vidtv_mux_pid_ctx_init(struct vidtv_mux *m)
                vidtv_mux_create_pid_ctx_once(m, pid);
                p = p->next;
        }
-}
 
-static void vidtv_mux_pid_ctx_destroy(struct vidtv_mux *m)
-{
-       int bkt;
-       struct vidtv_mux_pid_ctx *ctx;
-       struct hlist_node *tmp;
+       return 0;
 
-       hash_for_each_safe(m->pid_ctx, bkt, tmp, ctx, h) {
-               hash_del(&ctx->h);
-               kfree(ctx);
-       }
+free:
+       vidtv_mux_pid_ctx_destroy(m);
+       return -ENOMEM;
 }
 
 static void vidtv_mux_update_clk(struct vidtv_mux *m)
@@ -112,32 +129,53 @@ static void vidtv_mux_update_clk(struct vidtv_mux *m)
 
 static u32 vidtv_mux_push_si(struct vidtv_mux *m)
 {
+       struct vidtv_psi_pat_write_args pat_args = {
+               .buf                = m->mux_buf,
+               .buf_sz             = m->mux_buf_sz,
+               .pat                = m->si.pat,
+       };
+       struct vidtv_psi_pmt_write_args pmt_args = {
+               .buf                = m->mux_buf,
+               .buf_sz             = m->mux_buf_sz,
+               .pcr_pid            = m->pcr_pid,
+       };
+       struct vidtv_psi_sdt_write_args sdt_args = {
+               .buf                = m->mux_buf,
+               .buf_sz             = m->mux_buf_sz,
+               .sdt                = m->si.sdt,
+       };
+       struct vidtv_psi_nit_write_args nit_args = {
+               .buf                = m->mux_buf,
+               .buf_sz             = m->mux_buf_sz,
+               .nit                = m->si.nit,
+
+       };
+       struct vidtv_psi_eit_write_args eit_args = {
+               .buf                = m->mux_buf,
+               .buf_sz             = m->mux_buf_sz,
+               .eit                = m->si.eit,
+       };
        u32 initial_offset = m->mux_buf_offset;
-
        struct vidtv_mux_pid_ctx *pat_ctx;
        struct vidtv_mux_pid_ctx *pmt_ctx;
        struct vidtv_mux_pid_ctx *sdt_ctx;
-
-       struct vidtv_psi_pat_write_args pat_args = {};
-       struct vidtv_psi_pmt_write_args pmt_args = {};
-       struct vidtv_psi_sdt_write_args sdt_args = {};
-
-       u32 nbytes; /* the number of bytes written by this function */
+       struct vidtv_mux_pid_ctx *nit_ctx;
+       struct vidtv_mux_pid_ctx *eit_ctx;
+       u32 nbytes;
        u16 pmt_pid;
        u32 i;
 
        pat_ctx = vidtv_mux_get_pid_ctx(m, VIDTV_PAT_PID);
        sdt_ctx = vidtv_mux_get_pid_ctx(m, VIDTV_SDT_PID);
+       nit_ctx = vidtv_mux_get_pid_ctx(m, VIDTV_NIT_PID);
+       eit_ctx = vidtv_mux_get_pid_ctx(m, VIDTV_EIT_PID);
 
-       pat_args.buf                = m->mux_buf;
        pat_args.offset             = m->mux_buf_offset;
-       pat_args.pat                = m->si.pat;
-       pat_args.buf_sz             = m->mux_buf_sz;
        pat_args.continuity_counter = &pat_ctx->cc;
 
-       m->mux_buf_offset += vidtv_psi_pat_write_into(pat_args);
+       m->mux_buf_offset += vidtv_psi_pat_write_into(&pat_args);
 
-       for (i = 0; i < m->si.pat->programs; ++i) {
+       for (i = 0; i < m->si.pat->num_pmt; ++i) {
                pmt_pid = vidtv_psi_pmt_get_pid(m->si.pmt_secs[i],
                                                m->si.pat);
 
@@ -149,25 +187,29 @@ static u32 vidtv_mux_push_si(struct vidtv_mux *m)
 
                pmt_ctx = vidtv_mux_get_pid_ctx(m, pmt_pid);
 
-               pmt_args.buf                = m->mux_buf;
                pmt_args.offset             = m->mux_buf_offset;
                pmt_args.pmt                = m->si.pmt_secs[i];
                pmt_args.pid                = pmt_pid;
-               pmt_args.buf_sz             = m->mux_buf_sz;
                pmt_args.continuity_counter = &pmt_ctx->cc;
-               pmt_args.pcr_pid            = m->pcr_pid;
 
                /* write each section into buffer */
-               m->mux_buf_offset += vidtv_psi_pmt_write_into(pmt_args);
+               m->mux_buf_offset += vidtv_psi_pmt_write_into(&pmt_args);
        }
 
-       sdt_args.buf                = m->mux_buf;
        sdt_args.offset             = m->mux_buf_offset;
-       sdt_args.sdt                = m->si.sdt;
-       sdt_args.buf_sz             = m->mux_buf_sz;
        sdt_args.continuity_counter = &sdt_ctx->cc;
 
-       m->mux_buf_offset += vidtv_psi_sdt_write_into(sdt_args);
+       m->mux_buf_offset += vidtv_psi_sdt_write_into(&sdt_args);
+
+       nit_args.offset             = m->mux_buf_offset;
+       nit_args.continuity_counter = &nit_ctx->cc;
+
+       m->mux_buf_offset += vidtv_psi_nit_write_into(&nit_args);
+
+       eit_args.offset             = m->mux_buf_offset;
+       eit_args.continuity_counter = &eit_ctx->cc;
+
+       m->mux_buf_offset += vidtv_psi_eit_write_into(&eit_args);
 
        nbytes = m->mux_buf_offset - initial_offset;
 
@@ -230,23 +272,29 @@ static bool vidtv_mux_should_push_si(struct vidtv_mux *m)
 static u32 vidtv_mux_packetize_access_units(struct vidtv_mux *m,
                                            struct vidtv_encoder *e)
 {
-       u32 nbytes = 0;
-
-       struct pes_write_args args = {};
-       u32 initial_offset = m->mux_buf_offset;
+       struct pes_write_args args = {
+               .dest_buf           = m->mux_buf,
+               .dest_buf_sz        = m->mux_buf_sz,
+               .pid                = be16_to_cpu(e->es_pid),
+               .encoder_id         = e->id,
+               .stream_id          = be16_to_cpu(e->stream_id),
+               .send_pts           = true,  /* forbidden value '01'... */
+               .send_dts           = false, /* ...for PTS_DTS flags    */
+       };
        struct vidtv_access_unit *au = e->access_units;
-
+       u32 initial_offset = m->mux_buf_offset;
+       struct vidtv_mux_pid_ctx *pid_ctx;
+       u32 nbytes = 0;
        u8 *buf = NULL;
-       struct vidtv_mux_pid_ctx *pid_ctx = vidtv_mux_create_pid_ctx_once(m,
-                                                                         be16_to_cpu(e->es_pid));
 
-       args.dest_buf           = m->mux_buf;
-       args.dest_buf_sz        = m->mux_buf_sz;
-       args.pid                = be16_to_cpu(e->es_pid);
-       args.encoder_id         = e->id;
+       /* see SMPTE 302M clause 6.4 */
+       if (args.encoder_id == S302M) {
+               args.send_dts = false;
+               args.send_pts = true;
+       }
+
+       pid_ctx = vidtv_mux_create_pid_ctx_once(m, be16_to_cpu(e->es_pid));
        args.continuity_counter = &pid_ctx->cc;
-       args.stream_id          = be16_to_cpu(e->stream_id);
-       args.send_pts           = true;
 
        while (au) {
                buf                  = e->encoder_buf + au->offset;
@@ -256,7 +304,7 @@ static u32 vidtv_mux_packetize_access_units(struct vidtv_mux *m,
                args.pts             = au->pts;
                args.pcr             = m->timing.clk;
 
-               m->mux_buf_offset += vidtv_pes_write_into(args);
+               m->mux_buf_offset += vidtv_pes_write_into(&args);
 
                au = au->next;
        }
@@ -273,10 +321,10 @@ static u32 vidtv_mux_packetize_access_units(struct vidtv_mux *m,
 
 static u32 vidtv_mux_poll_encoders(struct vidtv_mux *m)
 {
-       u32 nbytes = 0;
-       u32 au_nbytes;
        struct vidtv_channel *cur_chnl = m->channels;
        struct vidtv_encoder *e = NULL;
+       u32 nbytes = 0;
+       u32 au_nbytes;
 
        while (cur_chnl) {
                e = cur_chnl->encoders;
@@ -300,18 +348,19 @@ static u32 vidtv_mux_poll_encoders(struct vidtv_mux *m)
 
 static u32 vidtv_mux_pad_with_nulls(struct vidtv_mux *m, u32 npkts)
 {
-       struct null_packet_write_args args = {};
+       struct null_packet_write_args args = {
+               .dest_buf           = m->mux_buf,
+               .buf_sz             = m->mux_buf_sz,
+               .dest_offset        = m->mux_buf_offset,
+       };
        u32 initial_offset = m->mux_buf_offset;
-       u32 nbytes; /* the number of bytes written by this function */
-       u32 i;
        struct vidtv_mux_pid_ctx *ctx;
+       u32 nbytes;
+       u32 i;
 
        ctx = vidtv_mux_get_pid_ctx(m, TS_NULL_PACKET_PID);
 
-       args.dest_buf           = m->mux_buf;
-       args.buf_sz             = m->mux_buf_sz;
        args.continuity_counter = &ctx->cc;
-       args.dest_offset        = m->mux_buf_offset;
 
        for (i = 0; i < npkts; ++i) {
                m->mux_buf_offset += vidtv_ts_null_write_into(args);
@@ -343,9 +392,9 @@ static void vidtv_mux_tick(struct work_struct *work)
                                           struct vidtv_mux,
                                           mpeg_thread);
        struct dtv_frontend_properties *c = &m->fe->dtv_property_cache;
+       u32 tot_bits = 0;
        u32 nbytes;
        u32 npkts;
-       u32 tot_bits = 0;
 
        while (m->streaming) {
                nbytes = 0;
@@ -427,40 +476,62 @@ void vidtv_mux_stop_thread(struct vidtv_mux *m)
 
 struct vidtv_mux *vidtv_mux_init(struct dvb_frontend *fe,
                                 struct device *dev,
-                                struct vidtv_mux_init_args args)
+                                struct vidtv_mux_init_args *args)
 {
-       struct vidtv_mux *m = kzalloc(sizeof(*m), GFP_KERNEL);
+       struct vidtv_mux *m;
+
+       m = kzalloc(sizeof(*m), GFP_KERNEL);
+       if (!m)
+               return NULL;
 
        m->dev = dev;
        m->fe = fe;
-       m->timing.pcr_period_usecs = args.pcr_period_usecs;
-       m->timing.si_period_usecs  = args.si_period_usecs;
+       m->timing.pcr_period_usecs = args->pcr_period_usecs;
+       m->timing.si_period_usecs  = args->si_period_usecs;
+
+       m->mux_rate_kbytes_sec = args->mux_rate_kbytes_sec;
 
-       m->mux_rate_kbytes_sec = args.mux_rate_kbytes_sec;
+       m->on_new_packets_available_cb = args->on_new_packets_available_cb;
 
-       m->on_new_packets_available_cb = args.on_new_packets_available_cb;
+       m->mux_buf = vzalloc(args->mux_buf_sz);
+       if (!m->mux_buf)
+               goto free_mux;
 
-       m->mux_buf = vzalloc(args.mux_buf_sz);
-       m->mux_buf_sz = args.mux_buf_sz;
+       m->mux_buf_sz = args->mux_buf_sz;
 
-       m->pcr_pid = args.pcr_pid;
-       m->transport_stream_id = args.transport_stream_id;
-       m->priv = args.priv;
+       m->pcr_pid = args->pcr_pid;
+       m->transport_stream_id = args->transport_stream_id;
+       m->priv = args->priv;
+       m->network_id = args->network_id;
+       m->network_name = kstrdup(args->network_name, GFP_KERNEL);
        m->timing.current_jiffies = get_jiffies_64();
 
-       if (args.channels)
-               m->channels = args.channels;
+       if (args->channels)
+               m->channels = args->channels;
        else
-               vidtv_channels_init(m);
+               if (vidtv_channels_init(m) < 0)
+                       goto free_mux_buf;
 
        /* will alloc data for pmt_sections after initializing pat */
-       vidtv_channel_si_init(m);
+       if (vidtv_channel_si_init(m) < 0)
+               goto free_channels;
 
        INIT_WORK(&m->mpeg_thread, vidtv_mux_tick);
 
-       vidtv_mux_pid_ctx_init(m);
+       if (vidtv_mux_pid_ctx_init(m) < 0)
+               goto free_channel_si;
 
        return m;
+
+free_channel_si:
+       vidtv_channel_si_destroy(m);
+free_channels:
+       vidtv_channels_destroy(m);
+free_mux_buf:
+       vfree(m->mux_buf);
+free_mux:
+       kfree(m);
+       return NULL;
 }
 
 void vidtv_mux_destroy(struct vidtv_mux *m)
@@ -469,6 +540,7 @@ void vidtv_mux_destroy(struct vidtv_mux *m)
        vidtv_mux_pid_ctx_destroy(m);
        vidtv_channel_si_destroy(m);
        vidtv_channels_destroy(m);
+       kfree(m->network_name);
        vfree(m->mux_buf);
        kfree(m);
 }
index 2caa60623e971edb8591596daa2d88fa42d9f829..ad82eb72b8412eb19f3d2014cbfcdf67a20e664f 100644 (file)
 #ifndef VIDTV_MUX_H
 #define VIDTV_MUX_H
 
-#include <linux/types.h>
 #include <linux/hashtable.h>
+#include <linux/types.h>
 #include <linux/workqueue.h>
+
 #include <media/dvb_frontend.h>
 
 #include "vidtv_psi.h"
@@ -58,12 +59,16 @@ struct vidtv_mux_timing {
  * @pat: The PAT in use by the muxer.
  * @pmt_secs: The PMT sections in use by the muxer. One for each program in the PAT.
  * @sdt: The SDT in use by the muxer.
+ * @nit: The NIT in use by the muxer.
+ * @eit: the EIT in use by the muxer.
  */
 struct vidtv_mux_si {
        /* the SI tables */
        struct vidtv_psi_table_pat *pat;
        struct vidtv_psi_table_pmt **pmt_secs; /* the PMT sections */
        struct vidtv_psi_table_sdt *sdt;
+       struct vidtv_psi_table_nit *nit;
+       struct vidtv_psi_table_eit *eit;
 };
 
 /**
@@ -82,8 +87,10 @@ struct vidtv_mux_pid_ctx {
 
 /**
  * struct vidtv_mux - A muxer abstraction loosely based in libavcodec/mpegtsenc.c
- * @mux_rate_kbytes_sec: The bit rate for the TS, in kbytes.
+ * @fe: The frontend structure allocated by the muxer.
+ * @dev: pointer to struct device.
  * @timing: Keeps track of timing related information.
+ * @mux_rate_kbytes_sec: The bit rate for the TS, in kbytes.
  * @pid_ctx: A hash table to keep track of per-PID metadata.
  * @on_new_packets_available_cb: A callback to inform of new TS packets ready.
  * @mux_buf: A pointer to a buffer for this muxer. TS packets are stored there
@@ -99,6 +106,8 @@ struct vidtv_mux_pid_ctx {
  * @pcr_pid: The TS PID used for the PSI packets. All channels will share the
  * same PCR.
  * @transport_stream_id: The transport stream ID
+ * @network_id: The network ID
+ * @network_name: The network name
  * @priv: Private data.
  */
 struct vidtv_mux {
@@ -128,6 +137,8 @@ struct vidtv_mux {
 
        u16 pcr_pid;
        u16 transport_stream_id;
+       u16 network_id;
+       char *network_name;
        void *priv;
 };
 
@@ -142,6 +153,8 @@ struct vidtv_mux {
  * same PCR.
  * @transport_stream_id: The transport stream ID
  * @channels: an optional list of channels to use
+ * @network_id: The network ID
+ * @network_name: The network name
  * @priv: Private data.
  */
 struct vidtv_mux_init_args {
@@ -153,12 +166,14 @@ struct vidtv_mux_init_args {
        u16 pcr_pid;
        u16 transport_stream_id;
        struct vidtv_channel *channels;
+       u16 network_id;
+       char *network_name;
        void *priv;
 };
 
 struct vidtv_mux *vidtv_mux_init(struct dvb_frontend *fe,
                                 struct device *dev,
-                                struct vidtv_mux_init_args args);
+                                struct vidtv_mux_init_args *args);
 void vidtv_mux_destroy(struct vidtv_mux *m);
 
 void vidtv_mux_start_thread(struct vidtv_mux *m);
index 1c75f88070e9695107dc8edf7c2853e4295436e3..782e5e7fbb020ce2fb5b98505875605e3dd8f028 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/types.h>
 #include <linux/printk.h>
 #include <linux/ratelimit.h>
-#include <asm/byteorder.h>
 
 #include "vidtv_pes.h"
 #include "vidtv_common.h"
@@ -57,7 +56,7 @@ static u32 vidtv_pes_h_get_len(bool send_pts, bool send_dts)
        return len;
 }
 
-static u32 vidtv_pes_write_header_stuffing(struct pes_header_write_args args)
+static u32 vidtv_pes_write_header_stuffing(struct pes_header_write_args *args)
 {
        /*
         * This is a fixed 8-bit value equal to '0xFF' that can be inserted
@@ -65,20 +64,20 @@ static u32 vidtv_pes_write_header_stuffing(struct pes_header_write_args args)
         * It is discarded by the decoder. No more than 32 stuffing bytes shall
         * be present in one PES packet header.
         */
-       if (args.n_pes_h_s_bytes > PES_HEADER_MAX_STUFFING_BYTES) {
+       if (args->n_pes_h_s_bytes > PES_HEADER_MAX_STUFFING_BYTES) {
                pr_warn_ratelimited("More than %d stuffing bytes in PES packet header\n",
                                    PES_HEADER_MAX_STUFFING_BYTES);
-               args.n_pes_h_s_bytes = PES_HEADER_MAX_STUFFING_BYTES;
+               args->n_pes_h_s_bytes = PES_HEADER_MAX_STUFFING_BYTES;
        }
 
-       return vidtv_memset(args.dest_buf,
-                           args.dest_offset,
-                           args.dest_buf_sz,
+       return vidtv_memset(args->dest_buf,
+                           args->dest_offset,
+                           args->dest_buf_sz,
                            TS_FILL_BYTE,
-                           args.n_pes_h_s_bytes);
+                           args->n_pes_h_s_bytes);
 }
 
-static u32 vidtv_pes_write_pts_dts(struct pes_header_write_args args)
+static u32 vidtv_pes_write_pts_dts(struct pes_header_write_args *args)
 {
        u32 nbytes = 0;  /* the number of bytes written by this function */
 
@@ -90,7 +89,7 @@ static u32 vidtv_pes_write_pts_dts(struct pes_header_write_args args)
        u64 mask2;
        u64 mask3;
 
-       if (!args.send_pts && args.send_dts)
+       if (!args->send_pts && args->send_dts)
                return 0;
 
        mask1 = GENMASK_ULL(32, 30);
@@ -98,80 +97,81 @@ static u32 vidtv_pes_write_pts_dts(struct pes_header_write_args args)
        mask3 = GENMASK_ULL(14, 0);
 
        /* see ISO/IEC 13818-1 : 2000 p. 32 */
-       if (args.send_pts && args.send_dts) {
-               pts_dts.pts1 = (0x3 << 4) | ((args.pts & mask1) >> 29) | 0x1;
-               pts_dts.pts2 = cpu_to_be16(((args.pts & mask2) >> 14) | 0x1);
-               pts_dts.pts3 = cpu_to_be16(((args.pts & mask3) << 1) | 0x1);
+       if (args->send_pts && args->send_dts) {
+               pts_dts.pts1 = (0x3 << 4) | ((args->pts & mask1) >> 29) | 0x1;
+               pts_dts.pts2 = cpu_to_be16(((args->pts & mask2) >> 14) | 0x1);
+               pts_dts.pts3 = cpu_to_be16(((args->pts & mask3) << 1) | 0x1);
 
-               pts_dts.dts1 = (0x1 << 4) | ((args.dts & mask1) >> 29) | 0x1;
-               pts_dts.dts2 = cpu_to_be16(((args.dts & mask2) >> 14) | 0x1);
-               pts_dts.dts3 = cpu_to_be16(((args.dts & mask3) << 1) | 0x1);
+               pts_dts.dts1 = (0x1 << 4) | ((args->dts & mask1) >> 29) | 0x1;
+               pts_dts.dts2 = cpu_to_be16(((args->dts & mask2) >> 14) | 0x1);
+               pts_dts.dts3 = cpu_to_be16(((args->dts & mask3) << 1) | 0x1);
 
                op = &pts_dts;
                op_sz = sizeof(pts_dts);
 
-       } else if (args.send_pts) {
-               pts.pts1 = (0x1 << 5) | ((args.pts & mask1) >> 29) | 0x1;
-               pts.pts2 = cpu_to_be16(((args.pts & mask2) >> 14) | 0x1);
-               pts.pts3 = cpu_to_be16(((args.pts & mask3) << 1) | 0x1);
+       } else if (args->send_pts) {
+               pts.pts1 = (0x1 << 5) | ((args->pts & mask1) >> 29) | 0x1;
+               pts.pts2 = cpu_to_be16(((args->pts & mask2) >> 14) | 0x1);
+               pts.pts3 = cpu_to_be16(((args->pts & mask3) << 1) | 0x1);
 
                op = &pts;
                op_sz = sizeof(pts);
        }
 
        /* copy PTS/DTS optional */
-       nbytes += vidtv_memcpy(args.dest_buf,
-                              args.dest_offset + nbytes,
-                              args.dest_buf_sz,
+       nbytes += vidtv_memcpy(args->dest_buf,
+                              args->dest_offset + nbytes,
+                              args->dest_buf_sz,
                               op,
                               op_sz);
 
        return nbytes;
 }
 
-static u32 vidtv_pes_write_h(struct pes_header_write_args args)
+static u32 vidtv_pes_write_h(struct pes_header_write_args *args)
 {
        u32 nbytes = 0;  /* the number of bytes written by this function */
 
        struct vidtv_mpeg_pes pes_header          = {};
        struct vidtv_pes_optional pes_optional    = {};
-       struct pes_header_write_args pts_dts_args = args;
-       u32 stream_id = (args.encoder_id == S302M) ? PRIVATE_STREAM_1_ID : args.stream_id;
+       struct pes_header_write_args pts_dts_args;
+       u32 stream_id = (args->encoder_id == S302M) ? PRIVATE_STREAM_1_ID : args->stream_id;
        u16 pes_opt_bitfield = 0x01 << 15;
 
        pes_header.bitfield = cpu_to_be32((PES_START_CODE_PREFIX << 8) | stream_id);
 
-       pes_header.length = cpu_to_be16(vidtv_pes_op_get_len(args.send_pts,
-                                                            args.send_dts) +
-                                                            args.access_unit_len);
+       pes_header.length = cpu_to_be16(vidtv_pes_op_get_len(args->send_pts,
+                                                            args->send_dts) +
+                                                            args->access_unit_len);
 
-       if (args.send_pts && args.send_dts)
+       if (args->send_pts && args->send_dts)
                pes_opt_bitfield |= (0x3 << 6);
-       else if (args.send_pts)
+       else if (args->send_pts)
                pes_opt_bitfield |= (0x1 << 7);
 
        pes_optional.bitfield = cpu_to_be16(pes_opt_bitfield);
-       pes_optional.length = vidtv_pes_op_get_len(args.send_pts, args.send_dts) +
-                             args.n_pes_h_s_bytes -
+       pes_optional.length = vidtv_pes_op_get_len(args->send_pts, args->send_dts) +
+                             args->n_pes_h_s_bytes -
                              sizeof(struct vidtv_pes_optional);
 
        /* copy header */
-       nbytes += vidtv_memcpy(args.dest_buf,
-                              args.dest_offset + nbytes,
-                              args.dest_buf_sz,
+       nbytes += vidtv_memcpy(args->dest_buf,
+                              args->dest_offset + nbytes,
+                              args->dest_buf_sz,
                               &pes_header,
                               sizeof(pes_header));
 
        /* copy optional header bits */
-       nbytes += vidtv_memcpy(args.dest_buf,
-                              args.dest_offset + nbytes,
-                              args.dest_buf_sz,
+       nbytes += vidtv_memcpy(args->dest_buf,
+                              args->dest_offset + nbytes,
+                              args->dest_buf_sz,
                               &pes_optional,
                               sizeof(pes_optional));
 
        /* copy the timing information */
-       pts_dts_args.dest_offset = args.dest_offset + nbytes;
-       nbytes += vidtv_pes_write_pts_dts(pts_dts_args);
+       pts_dts_args = *args;
+       pts_dts_args.dest_offset = args->dest_offset + nbytes;
+       nbytes += vidtv_pes_write_pts_dts(&pts_dts_args);
 
        /* write any PES header stuffing */
        nbytes += vidtv_pes_write_header_stuffing(args);
@@ -300,14 +300,31 @@ static u32 vidtv_pes_write_ts_h(struct pes_ts_header_write_args args,
        return nbytes;
 }
 
-u32 vidtv_pes_write_into(struct pes_write_args args)
+u32 vidtv_pes_write_into(struct pes_write_args *args)
 {
-       u32 unaligned_bytes = (args.dest_offset % TS_PACKET_LEN);
-       struct pes_ts_header_write_args ts_header_args = {};
-       struct pes_header_write_args pes_header_args = {};
-       u32 remaining_len = args.access_unit_len;
+       u32 unaligned_bytes = (args->dest_offset % TS_PACKET_LEN);
+       struct pes_ts_header_write_args ts_header_args = {
+               .dest_buf               = args->dest_buf,
+               .dest_buf_sz            = args->dest_buf_sz,
+               .pid                    = args->pid,
+               .pcr                    = args->pcr,
+               .continuity_counter     = args->continuity_counter,
+       };
+       struct pes_header_write_args pes_header_args = {
+               .dest_buf               = args->dest_buf,
+               .dest_buf_sz            = args->dest_buf_sz,
+               .encoder_id             = args->encoder_id,
+               .send_pts               = args->send_pts,
+               .pts                    = args->pts,
+               .send_dts               = args->send_dts,
+               .dts                    = args->dts,
+               .stream_id              = args->stream_id,
+               .n_pes_h_s_bytes        = args->n_pes_h_s_bytes,
+               .access_unit_len        = args->access_unit_len,
+       };
+       u32 remaining_len = args->access_unit_len;
        bool wrote_pes_header = false;
-       u64 last_pcr = args.pcr;
+       u64 last_pcr = args->pcr;
        bool need_pcr = true;
        u32 available_space;
        u32 payload_size;
@@ -318,25 +335,13 @@ u32 vidtv_pes_write_into(struct pes_write_args args)
                pr_warn_ratelimited("buffer is misaligned, while starting PES\n");
 
                /* forcibly align and hope for the best */
-               nbytes += vidtv_memset(args.dest_buf,
-                                      args.dest_offset + nbytes,
-                                      args.dest_buf_sz,
+               nbytes += vidtv_memset(args->dest_buf,
+                                      args->dest_offset + nbytes,
+                                      args->dest_buf_sz,
                                       TS_FILL_BYTE,
                                       TS_PACKET_LEN - unaligned_bytes);
        }
 
-       if (args.send_dts && !args.send_pts) {
-               pr_warn_ratelimited("forbidden value '01' for PTS_DTS flags\n");
-               args.send_pts = true;
-               args.pts      = args.dts;
-       }
-
-       /* see SMPTE 302M clause 6.4 */
-       if (args.encoder_id == S302M) {
-               args.send_dts = false;
-               args.send_pts = true;
-       }
-
        while (remaining_len) {
                available_space = TS_PAYLOAD_LEN;
                /*
@@ -345,14 +350,14 @@ u32 vidtv_pes_write_into(struct pes_write_args args)
                 * the space needed for the TS header _and_ for the PES header
                 */
                if (!wrote_pes_header)
-                       available_space -= vidtv_pes_h_get_len(args.send_pts,
-                                                              args.send_dts);
+                       available_space -= vidtv_pes_h_get_len(args->send_pts,
+                                                              args->send_dts);
 
                /*
                 * if the encoder has inserted stuffing bytes in the PES
                 * header, account for them.
                 */
-               available_space -= args.n_pes_h_s_bytes;
+               available_space -= args->n_pes_h_s_bytes;
 
                /* Take the extra adaptation into account if need to send PCR */
                if (need_pcr) {
@@ -387,14 +392,9 @@ u32 vidtv_pes_write_into(struct pes_write_args args)
                }
 
                /* write ts header */
-               ts_header_args.dest_buf           = args.dest_buf;
-               ts_header_args.dest_offset        = args.dest_offset + nbytes;
-               ts_header_args.dest_buf_sz        = args.dest_buf_sz;
-               ts_header_args.pid                = args.pid;
-               ts_header_args.pcr                = args.pcr;
-               ts_header_args.continuity_counter = args.continuity_counter;
-               ts_header_args.wrote_pes_header   = wrote_pes_header;
-               ts_header_args.n_stuffing_bytes   = stuff_bytes;
+               ts_header_args.dest_offset = args->dest_offset + nbytes;
+               ts_header_args.wrote_pes_header = wrote_pes_header;
+               ts_header_args.n_stuffing_bytes = stuff_bytes;
 
                nbytes += vidtv_pes_write_ts_h(ts_header_args, need_pcr,
                                               &last_pcr);
@@ -403,33 +403,20 @@ u32 vidtv_pes_write_into(struct pes_write_args args)
 
                if (!wrote_pes_header) {
                        /* write the PES header only once */
-                       pes_header_args.dest_buf        = args.dest_buf;
-
-                       pes_header_args.dest_offset     = args.dest_offset +
-                                                         nbytes;
-
-                       pes_header_args.dest_buf_sz     = args.dest_buf_sz;
-                       pes_header_args.encoder_id      = args.encoder_id;
-                       pes_header_args.send_pts        = args.send_pts;
-                       pes_header_args.pts             = args.pts;
-                       pes_header_args.send_dts        = args.send_dts;
-                       pes_header_args.dts             = args.dts;
-                       pes_header_args.stream_id       = args.stream_id;
-                       pes_header_args.n_pes_h_s_bytes = args.n_pes_h_s_bytes;
-                       pes_header_args.access_unit_len = args.access_unit_len;
-
-                       nbytes           += vidtv_pes_write_h(pes_header_args);
-                       wrote_pes_header  = true;
+                       pes_header_args.dest_offset = args->dest_offset +
+                                                     nbytes;
+                       nbytes += vidtv_pes_write_h(&pes_header_args);
+                       wrote_pes_header = true;
                }
 
                /* write as much of the payload as we possibly can */
-               nbytes += vidtv_memcpy(args.dest_buf,
-                                      args.dest_offset + nbytes,
-                                      args.dest_buf_sz,
-                                      args.from,
+               nbytes += vidtv_memcpy(args->dest_buf,
+                                      args->dest_offset + nbytes,
+                                      args->dest_buf_sz,
+                                      args->from,
                                       payload_size);
 
-               args.from += payload_size;
+               args->from += payload_size;
 
                remaining_len -= payload_size;
        }
index 0ea9e863024d6163bbfa80704dfcaaaaa6d51964..963c59155e725e6b42eea61a4e40c1b2554ff021 100644 (file)
@@ -14,7 +14,6 @@
 #ifndef VIDTV_PES_H
 #define VIDTV_PES_H
 
-#include <asm/byteorder.h>
 #include <linux/types.h>
 
 #include "vidtv_common.h"
@@ -114,8 +113,10 @@ struct pes_header_write_args {
  * @dest_buf_sz: The size of the dest_buffer
  * @pid: The PID to use for the TS packets.
  * @continuity_counter: Incremented on every new TS packet.
- * @n_pes_h_s_bytes: Padding bytes. Might be used by an encoder if needed, gets
+ * @wrote_pes_header: Flag to indicate that the PES header was written
+ * @n_stuffing_bytes: Padding bytes. Might be used by an encoder if needed, gets
  * discarded by the decoder.
+ * @pcr: counter driven by a 27Mhz clock.
  */
 struct pes_ts_header_write_args {
        void *dest_buf;
@@ -146,6 +147,7 @@ struct pes_ts_header_write_args {
  * @dts: DTS value to send.
  * @n_pes_h_s_bytes: Padding bytes. Might be used by an encoder if needed, gets
  * discarded by the decoder.
+ * @pcr: counter driven by a 27Mhz clock.
  */
 struct pes_write_args {
        void *dest_buf;
@@ -186,6 +188,6 @@ struct pes_write_args {
  * equal to the size of the access unit, since we need space for PES headers, TS headers
  * and padding bytes, if any.
  */
-u32 vidtv_pes_write_into(struct pes_write_args args);
+u32 vidtv_pes_write_into(struct pes_write_args *args);
 
 #endif // VIDTV_PES_H
index 82cf67dd27c015d927da3d4991feff394a544394..4511a2a98405d914d697248f91ab34d35d82ed13 100644 (file)
@@ -6,31 +6,31 @@
  * technically be broken into one or more sections, we do not do this here,
  * hence 'table' and 'section' are interchangeable for vidtv.
  *
- * This code currently supports three tables: PAT, PMT and SDT. These are the
- * bare minimum to get userspace to recognize our MPEG transport stream. It can
- * be extended to support more PSI tables in the future.
- *
  * Copyright (C) 2020 Daniel W. S. Almeida
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ":%s, %d: " fmt, __func__, __LINE__
 
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/slab.h>
+#include <linux/bcd.h>
 #include <linux/crc32.h>
-#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ktime.h>
 #include <linux/printk.h>
 #include <linux/ratelimit.h>
+#include <linux/slab.h>
 #include <linux/string.h>
-#include <asm/byteorder.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <linux/types.h>
 
-#include "vidtv_psi.h"
 #include "vidtv_common.h"
+#include "vidtv_psi.h"
 #include "vidtv_ts.h"
 
 #define CRC_SIZE_IN_BYTES 4
 #define MAX_VERSION_NUM 32
+#define INITIAL_CRC 0xffffffff
+#define ISO_LANGUAGE_CODE_LEN 3
 
 static const u32 CRC_LUT[256] = {
        /* from libdvbv5 */
@@ -79,7 +79,7 @@ static const u32 CRC_LUT[256] = {
        0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
 };
 
-static inline u32 dvb_crc32(u32 crc, u8 *data, u32 len)
+static u32 dvb_crc32(u32 crc, u8 *data, u32 len)
 {
        /* from libdvbv5 */
        while (len--)
@@ -92,40 +92,7 @@ static void vidtv_psi_update_version_num(struct vidtv_psi_table_header *h)
        h->version++;
 }
 
-static inline u16 vidtv_psi_sdt_serv_get_desc_loop_len(struct vidtv_psi_table_sdt_service *s)
-{
-       u16 mask;
-       u16 ret;
-
-       mask = GENMASK(11, 0);
-
-       ret = be16_to_cpu(s->bitfield) & mask;
-       return ret;
-}
-
-static inline u16 vidtv_psi_pmt_stream_get_desc_loop_len(struct vidtv_psi_table_pmt_stream *s)
-{
-       u16 mask;
-       u16 ret;
-
-       mask = GENMASK(9, 0);
-
-       ret = be16_to_cpu(s->bitfield2) & mask;
-       return ret;
-}
-
-static inline u16 vidtv_psi_pmt_get_desc_loop_len(struct vidtv_psi_table_pmt *p)
-{
-       u16 mask;
-       u16 ret;
-
-       mask = GENMASK(9, 0);
-
-       ret = be16_to_cpu(p->bitfield2) & mask;
-       return ret;
-}
-
-static inline u16 vidtv_psi_get_sec_len(struct vidtv_psi_table_header *h)
+static u16 vidtv_psi_get_sec_len(struct vidtv_psi_table_header *h)
 {
        u16 mask;
        u16 ret;
@@ -136,7 +103,7 @@ static inline u16 vidtv_psi_get_sec_len(struct vidtv_psi_table_header *h)
        return ret;
 }
 
-inline u16 vidtv_psi_get_pat_program_pid(struct vidtv_psi_table_pat_program *p)
+u16 vidtv_psi_get_pat_program_pid(struct vidtv_psi_table_pat_program *p)
 {
        u16 mask;
        u16 ret;
@@ -147,7 +114,7 @@ inline u16 vidtv_psi_get_pat_program_pid(struct vidtv_psi_table_pat_program *p)
        return ret;
 }
 
-inline u16 vidtv_psi_pmt_stream_get_elem_pid(struct vidtv_psi_table_pmt_stream *s)
+u16 vidtv_psi_pmt_stream_get_elem_pid(struct vidtv_psi_table_pmt_stream *s)
 {
        u16 mask;
        u16 ret;
@@ -158,10 +125,11 @@ inline u16 vidtv_psi_pmt_stream_get_elem_pid(struct vidtv_psi_table_pmt_stream *
        return ret;
 }
 
-static inline void vidtv_psi_set_desc_loop_len(__be16 *bitfield, u16 new_len, u8 desc_len_nbits)
+static void vidtv_psi_set_desc_loop_len(__be16 *bitfield, u16 new_len,
+                                       u8 desc_len_nbits)
 {
-       u16 mask;
        __be16 new;
+       u16 mask;
 
        mask = GENMASK(15, desc_len_nbits);
 
@@ -188,90 +156,81 @@ static void vidtv_psi_set_sec_len(struct vidtv_psi_table_header *h, u16 new_len)
        h->bitfield = new;
 }
 
-static u32 vidtv_psi_ts_psi_write_into(struct psi_write_args args)
+/*
+ * Packetize PSI sections into TS packets:
+ * push a TS header (4bytes) every 184 bytes
+ * manage the continuity_counter
+ * add stuffing (i.e. padding bytes) after the CRC
+ */
+static u32 vidtv_psi_ts_psi_write_into(struct psi_write_args *args)
 {
-       /*
-        * Packetize PSI sections into TS packets:
-        * push a TS header (4bytes) every 184 bytes
-        * manage the continuity_counter
-        * add stuffing (i.e. padding bytes) after the CRC
-        */
-
-       u32 nbytes_past_boundary = (args.dest_offset % TS_PACKET_LEN);
+       struct vidtv_mpeg_ts ts_header = {
+               .sync_byte = TS_SYNC_BYTE,
+               .bitfield = cpu_to_be16((args->new_psi_section << 14) | args->pid),
+               .scrambling = 0,
+               .payload = 1,
+               .adaptation_field = 0, /* no adaptation field */
+       };
+       u32 nbytes_past_boundary = (args->dest_offset % TS_PACKET_LEN);
        bool aligned = (nbytes_past_boundary == 0);
-       struct vidtv_mpeg_ts ts_header = {};
-
-       /* number of bytes written by this function */
-       u32 nbytes = 0;
-       /* how much there is left to write */
-       u32 remaining_len = args.len;
-       /* how much we can be written in this packet */
+       u32 remaining_len = args->len;
        u32 payload_write_len = 0;
-       /* where we are in the source */
        u32 payload_offset = 0;
+       u32 nbytes = 0;
 
-       const u16 PAYLOAD_START = args.new_psi_section;
-
-       if (!args.crc && !args.is_crc)
+       if (!args->crc && !args->is_crc)
                pr_warn_ratelimited("Missing CRC for chunk\n");
 
-       if (args.crc)
-               *args.crc = dvb_crc32(*args.crc, args.from, args.len);
+       if (args->crc)
+               *args->crc = dvb_crc32(*args->crc, args->from, args->len);
 
-       if (args.new_psi_section && !aligned) {
+       if (args->new_psi_section && !aligned) {
                pr_warn_ratelimited("Cannot write a new PSI section in a misaligned buffer\n");
 
                /* forcibly align and hope for the best */
-               nbytes += vidtv_memset(args.dest_buf,
-                                      args.dest_offset + nbytes,
-                                      args.dest_buf_sz,
+               nbytes += vidtv_memset(args->dest_buf,
+                                      args->dest_offset + nbytes,
+                                      args->dest_buf_sz,
                                       TS_FILL_BYTE,
                                       TS_PACKET_LEN - nbytes_past_boundary);
        }
 
        while (remaining_len) {
-               nbytes_past_boundary = (args.dest_offset + nbytes) % TS_PACKET_LEN;
+               nbytes_past_boundary = (args->dest_offset + nbytes) % TS_PACKET_LEN;
                aligned = (nbytes_past_boundary == 0);
 
                if (aligned) {
                        /* if at a packet boundary, write a new TS header */
-                       ts_header.sync_byte = TS_SYNC_BYTE;
-                       ts_header.bitfield = cpu_to_be16((PAYLOAD_START << 14) | args.pid);
-                       ts_header.scrambling = 0;
-                       ts_header.continuity_counter = *args.continuity_counter;
-                       ts_header.payload = 1;
-                       /* no adaptation field */
-                       ts_header.adaptation_field = 0;
-
-                       /* copy the header */
-                       nbytes += vidtv_memcpy(args.dest_buf,
-                                              args.dest_offset + nbytes,
-                                              args.dest_buf_sz,
+                       ts_header.continuity_counter = *args->continuity_counter;
+
+                       nbytes += vidtv_memcpy(args->dest_buf,
+                                              args->dest_offset + nbytes,
+                                              args->dest_buf_sz,
                                               &ts_header,
                                               sizeof(ts_header));
                        /*
                         * This will trigger a discontinuity if the buffer is full,
                         * effectively dropping the packet.
                         */
-                       vidtv_ts_inc_cc(args.continuity_counter);
+                       vidtv_ts_inc_cc(args->continuity_counter);
                }
 
                /* write the pointer_field in the first byte of the payload */
-               if (args.new_psi_section)
-                       nbytes += vidtv_memset(args.dest_buf,
-                                              args.dest_offset + nbytes,
-                                              args.dest_buf_sz,
+               if (args->new_psi_section)
+                       nbytes += vidtv_memset(args->dest_buf,
+                                              args->dest_offset + nbytes,
+                                              args->dest_buf_sz,
                                               0x0,
                                               1);
 
                /* write as much of the payload as possible */
-               nbytes_past_boundary = (args.dest_offset + nbytes) % TS_PACKET_LEN;
+               nbytes_past_boundary = (args->dest_offset + nbytes) % TS_PACKET_LEN;
                payload_write_len = min(TS_PACKET_LEN - nbytes_past_boundary, remaining_len);
 
-               nbytes += vidtv_memcpy(args.dest_buf,
-                                      args.dest_offset + nbytes,
-                                      args.dest_buf_sz,
-                                      args.from + payload_offset,
+               nbytes += vidtv_memcpy(args->dest_buf,
+                                      args->dest_offset + nbytes,
+                                      args->dest_buf_sz,
+                                      args->from + payload_offset,
                                       payload_write_len);
 
                /* 'payload_write_len' written from a total of 'len' requested*/
@@ -283,37 +242,45 @@ static u32 vidtv_psi_ts_psi_write_into(struct psi_write_args args)
         * fill the rest of the packet if there is any remaining space unused
         */
 
-       nbytes_past_boundary = (args.dest_offset + nbytes) % TS_PACKET_LEN;
+       nbytes_past_boundary = (args->dest_offset + nbytes) % TS_PACKET_LEN;
 
-       if (args.is_crc)
-               nbytes += vidtv_memset(args.dest_buf,
-                                      args.dest_offset + nbytes,
-                                      args.dest_buf_sz,
+       if (args->is_crc)
+               nbytes += vidtv_memset(args->dest_buf,
+                                      args->dest_offset + nbytes,
+                                      args->dest_buf_sz,
                                       TS_FILL_BYTE,
                                       TS_PACKET_LEN - nbytes_past_boundary);
 
        return nbytes;
 }
 
-static u32 table_section_crc32_write_into(struct crc32_write_args args)
+static u32 table_section_crc32_write_into(struct crc32_write_args *args)
 {
+       struct psi_write_args psi_args = {
+               .dest_buf           = args->dest_buf,
+               .from               = &args->crc,
+               .len                = CRC_SIZE_IN_BYTES,
+               .dest_offset        = args->dest_offset,
+               .pid                = args->pid,
+               .new_psi_section    = false,
+               .continuity_counter = args->continuity_counter,
+               .is_crc             = true,
+               .dest_buf_sz        = args->dest_buf_sz,
+       };
+
        /* the CRC is the last entry in the section */
-       u32 nbytes = 0;
-       struct psi_write_args psi_args = {};
 
-       psi_args.dest_buf           = args.dest_buf;
-       psi_args.from               = &args.crc;
-       psi_args.len                = CRC_SIZE_IN_BYTES;
-       psi_args.dest_offset        = args.dest_offset;
-       psi_args.pid                = args.pid;
-       psi_args.new_psi_section    = false;
-       psi_args.continuity_counter = args.continuity_counter;
-       psi_args.is_crc             = true;
-       psi_args.dest_buf_sz        = args.dest_buf_sz;
+       return vidtv_psi_ts_psi_write_into(&psi_args);
+}
 
-       nbytes += vidtv_psi_ts_psi_write_into(psi_args);
+static void vidtv_psi_desc_chain(struct vidtv_psi_desc *head, struct vidtv_psi_desc *desc)
+{
+       if (head) {
+               while (head->next)
+                       head = head->next;
 
-       return nbytes;
+               head->next = desc;
+       }
 }
 
 struct vidtv_psi_desc_service *vidtv_psi_service_desc_init(struct vidtv_psi_desc *head,
@@ -326,6 +293,8 @@ struct vidtv_psi_desc_service *vidtv_psi_service_desc_init(struct vidtv_psi_desc
        u32 provider_name_len = provider_name ? strlen(provider_name) : 0;
 
        desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+       if (!desc)
+               return NULL;
 
        desc->type = SERVICE_DESCRIPTOR;
 
@@ -347,12 +316,7 @@ struct vidtv_psi_desc_service *vidtv_psi_service_desc_init(struct vidtv_psi_desc
        if (provider_name && provider_name_len)
                desc->provider_name = kstrdup(provider_name, GFP_KERNEL);
 
-       if (head) {
-               while (head->next)
-                       head = head->next;
-
-               head->next = (struct vidtv_psi_desc *)desc;
-       }
+       vidtv_psi_desc_chain(head, (struct vidtv_psi_desc *)desc);
        return desc;
 }
 
@@ -365,6 +329,8 @@ struct vidtv_psi_desc_registration
        struct vidtv_psi_desc_registration *desc;
 
        desc = kzalloc(sizeof(*desc) + sizeof(format_id) + additional_info_len, GFP_KERNEL);
+       if (!desc)
+               return NULL;
 
        desc->type = REGISTRATION_DESCRIPTOR;
 
@@ -378,44 +344,178 @@ struct vidtv_psi_desc_registration
                       additional_ident_info,
                       additional_info_len);
 
-       if (head) {
-               while (head->next)
-                       head = head->next;
+       vidtv_psi_desc_chain(head, (struct vidtv_psi_desc *)desc);
+       return desc;
+}
 
-               head->next = (struct vidtv_psi_desc *)desc;
+struct vidtv_psi_desc_network_name
+*vidtv_psi_network_name_desc_init(struct vidtv_psi_desc *head, char *network_name)
+{
+       u32 network_name_len = network_name ? strlen(network_name) : 0;
+       struct vidtv_psi_desc_network_name *desc;
+
+       desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+       if (!desc)
+               return NULL;
+
+       desc->type = NETWORK_NAME_DESCRIPTOR;
+
+       desc->length = network_name_len;
+
+       if (network_name && network_name_len)
+               desc->network_name = kstrdup(network_name, GFP_KERNEL);
+
+       vidtv_psi_desc_chain(head, (struct vidtv_psi_desc *)desc);
+       return desc;
+}
+
+struct vidtv_psi_desc_service_list
+*vidtv_psi_service_list_desc_init(struct vidtv_psi_desc *head,
+                                 struct vidtv_psi_desc_service_list_entry *entry)
+{
+       struct vidtv_psi_desc_service_list_entry *curr_e = NULL;
+       struct vidtv_psi_desc_service_list_entry *head_e = NULL;
+       struct vidtv_psi_desc_service_list_entry *prev_e = NULL;
+       struct vidtv_psi_desc_service_list *desc;
+       u16 length = 0;
+
+       desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+       if (!desc)
+               return NULL;
+
+       desc->type = SERVICE_LIST_DESCRIPTOR;
+
+       while (entry) {
+               curr_e = kzalloc(sizeof(*curr_e), GFP_KERNEL);
+               if (!curr_e) {
+                       while (head_e) {
+                               curr_e = head_e;
+                               head_e = head_e->next;
+                               kfree(curr_e);
+                       }
+                       kfree(desc);
+                       return NULL;
+               }
+
+               curr_e->service_id = entry->service_id;
+               curr_e->service_type = entry->service_type;
+
+               length += sizeof(struct vidtv_psi_desc_service_list_entry) -
+                         sizeof(struct vidtv_psi_desc_service_list_entry *);
+
+               if (!head_e)
+                       head_e = curr_e;
+               if (prev_e)
+                       prev_e->next = curr_e;
+
+               prev_e = curr_e;
+               entry = entry->next;
        }
 
+       desc->length = length;
+       desc->service_list = head_e;
+
+       vidtv_psi_desc_chain(head, (struct vidtv_psi_desc *)desc);
+       return desc;
+}
+
+struct vidtv_psi_desc_short_event
+*vidtv_psi_short_event_desc_init(struct vidtv_psi_desc *head,
+                                char *iso_language_code,
+                                char *event_name,
+                                char *text)
+{
+       u32 iso_len =  iso_language_code ? strlen(iso_language_code) : 0;
+       u32 event_name_len = event_name ? strlen(event_name) : 0;
+       struct vidtv_psi_desc_short_event *desc;
+       u32 text_len =  text ? strlen(text) : 0;
+
+       desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+       if (!desc)
+               return NULL;
+
+       desc->type = SHORT_EVENT_DESCRIPTOR;
+
+       desc->length = ISO_LANGUAGE_CODE_LEN +
+                      sizeof_field(struct vidtv_psi_desc_short_event, event_name_len) +
+                      event_name_len +
+                      sizeof_field(struct vidtv_psi_desc_short_event, text_len) +
+                      text_len;
+
+       desc->event_name_len = event_name_len;
+       desc->text_len = text_len;
+
+       if (iso_len != ISO_LANGUAGE_CODE_LEN)
+               iso_language_code = "eng";
+
+       desc->iso_language_code = kstrdup(iso_language_code, GFP_KERNEL);
+
+       if (event_name && event_name_len)
+               desc->event_name = kstrdup(event_name, GFP_KERNEL);
+
+       if (text && text_len)
+               desc->text = kstrdup(text, GFP_KERNEL);
+
+       vidtv_psi_desc_chain(head, (struct vidtv_psi_desc *)desc);
        return desc;
 }
 
 struct vidtv_psi_desc *vidtv_psi_desc_clone(struct vidtv_psi_desc *desc)
 {
+       struct vidtv_psi_desc_network_name *desc_network_name;
+       struct vidtv_psi_desc_service_list *desc_service_list;
+       struct vidtv_psi_desc_short_event  *desc_short_event;
+       struct vidtv_psi_desc_service *service;
        struct vidtv_psi_desc *head = NULL;
        struct vidtv_psi_desc *prev = NULL;
        struct vidtv_psi_desc *curr = NULL;
 
-       struct vidtv_psi_desc_service *service;
-
        while (desc) {
                switch (desc->type) {
                case SERVICE_DESCRIPTOR:
                        service = (struct vidtv_psi_desc_service *)desc;
                        curr = (struct vidtv_psi_desc *)
-                               vidtv_psi_service_desc_init(head,
-                                                           service->service_type,
-                                                           service->service_name,
-                                                           service->provider_name);
+                              vidtv_psi_service_desc_init(head,
+                                                          service->service_type,
+                                                          service->service_name,
+                                                          service->provider_name);
+               break;
+
+               case NETWORK_NAME_DESCRIPTOR:
+                       desc_network_name = (struct vidtv_psi_desc_network_name *)desc;
+                       curr = (struct vidtv_psi_desc *)
+                              vidtv_psi_network_name_desc_init(head,
+                                                               desc_network_name->network_name);
+               break;
+
+               case SERVICE_LIST_DESCRIPTOR:
+                       desc_service_list = (struct vidtv_psi_desc_service_list *)desc;
+                       curr = (struct vidtv_psi_desc *)
+                              vidtv_psi_service_list_desc_init(head,
+                                                               desc_service_list->service_list);
+               break;
+
+               case SHORT_EVENT_DESCRIPTOR:
+                       desc_short_event = (struct vidtv_psi_desc_short_event *)desc;
+                       curr = (struct vidtv_psi_desc *)
+                              vidtv_psi_short_event_desc_init(head,
+                                                              desc_short_event->iso_language_code,
+                                                              desc_short_event->event_name,
+                                                              desc_short_event->text);
                break;
 
                case REGISTRATION_DESCRIPTOR:
                default:
                        curr = kzalloc(sizeof(*desc) + desc->length, GFP_KERNEL);
+                       if (!curr)
+                               return NULL;
                        memcpy(curr, desc, sizeof(*desc) + desc->length);
-               break;
-       }
+               }
 
-               if (curr)
-                       curr->next = NULL;
+               if (!curr)
+                       return NULL;
+
+               curr->next = NULL;
                if (!head)
                        head = curr;
                if (prev)
@@ -430,6 +530,8 @@ struct vidtv_psi_desc *vidtv_psi_desc_clone(struct vidtv_psi_desc *desc)
 
 void vidtv_psi_desc_destroy(struct vidtv_psi_desc *desc)
 {
+       struct vidtv_psi_desc_service_list_entry *sl_entry_tmp = NULL;
+       struct vidtv_psi_desc_service_list_entry *sl_entry = NULL;
        struct vidtv_psi_desc *curr = desc;
        struct vidtv_psi_desc *tmp  = NULL;
 
@@ -447,6 +549,25 @@ void vidtv_psi_desc_destroy(struct vidtv_psi_desc *desc)
                        /* nothing to do */
                        break;
 
+               case NETWORK_NAME_DESCRIPTOR:
+                       kfree(((struct vidtv_psi_desc_network_name *)tmp)->network_name);
+                       break;
+
+               case SERVICE_LIST_DESCRIPTOR:
+                       sl_entry = ((struct vidtv_psi_desc_service_list *)tmp)->service_list;
+                       while (sl_entry) {
+                               sl_entry_tmp = sl_entry;
+                               sl_entry = sl_entry->next;
+                               kfree(sl_entry_tmp);
+                       }
+                       break;
+
+               case SHORT_EVENT_DESCRIPTOR:
+                       kfree(((struct vidtv_psi_desc_short_event *)tmp)->iso_language_code);
+                       kfree(((struct vidtv_psi_desc_short_event *)tmp)->event_name);
+                       kfree(((struct vidtv_psi_desc_short_event *)tmp)->text);
+               break;
+
                default:
                        pr_warn_ratelimited("Possible leak: not handling descriptor type %d\n",
                                            tmp->type);
@@ -513,63 +634,119 @@ void vidtv_sdt_desc_assign(struct vidtv_psi_table_sdt *sdt,
        vidtv_psi_update_version_num(&sdt->header);
 }
 
-static u32 vidtv_psi_desc_write_into(struct desc_write_args args)
+static u32 vidtv_psi_desc_write_into(struct desc_write_args *args)
 {
-       /* the number of bytes written by this function */
+       struct psi_write_args psi_args = {
+               .dest_buf           = args->dest_buf,
+               .from               = &args->desc->type,
+               .pid                = args->pid,
+               .new_psi_section    = false,
+               .continuity_counter = args->continuity_counter,
+               .is_crc             = false,
+               .dest_buf_sz        = args->dest_buf_sz,
+               .crc                = args->crc,
+               .len                = sizeof_field(struct vidtv_psi_desc, type) +
+                                     sizeof_field(struct vidtv_psi_desc, length),
+       };
+       struct vidtv_psi_desc_service_list_entry *serv_list_entry = NULL;
        u32 nbytes = 0;
-       struct psi_write_args psi_args = {};
-
-       psi_args.dest_buf = args.dest_buf;
-       psi_args.from     = &args.desc->type;
 
-       psi_args.len = sizeof_field(struct vidtv_psi_desc, type) +
-                      sizeof_field(struct vidtv_psi_desc, length);
+       psi_args.dest_offset        = args->dest_offset + nbytes;
 
-       psi_args.dest_offset        = args.dest_offset + nbytes;
-       psi_args.pid                = args.pid;
-       psi_args.new_psi_section    = false;
-       psi_args.continuity_counter = args.continuity_counter;
-       psi_args.is_crc             = false;
-       psi_args.dest_buf_sz        = args.dest_buf_sz;
-       psi_args.crc                = args.crc;
+       nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
 
-       nbytes += vidtv_psi_ts_psi_write_into(psi_args);
-
-       switch (args.desc->type) {
+       switch (args->desc->type) {
        case SERVICE_DESCRIPTOR:
-               psi_args.dest_offset = args.dest_offset + nbytes;
+               psi_args.dest_offset = args->dest_offset + nbytes;
                psi_args.len = sizeof_field(struct vidtv_psi_desc_service, service_type) +
                               sizeof_field(struct vidtv_psi_desc_service, provider_name_len);
-               psi_args.from = &((struct vidtv_psi_desc_service *)args.desc)->service_type;
+               psi_args.from = &((struct vidtv_psi_desc_service *)args->desc)->service_type;
 
-               nbytes += vidtv_psi_ts_psi_write_into(psi_args);
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
 
-               psi_args.dest_offset = args.dest_offset + nbytes;
-               psi_args.len = ((struct vidtv_psi_desc_service *)args.desc)->provider_name_len;
-               psi_args.from = ((struct vidtv_psi_desc_service *)args.desc)->provider_name;
+               psi_args.dest_offset = args->dest_offset + nbytes;
+               psi_args.len = ((struct vidtv_psi_desc_service *)args->desc)->provider_name_len;
+               psi_args.from = ((struct vidtv_psi_desc_service *)args->desc)->provider_name;
 
-               nbytes += vidtv_psi_ts_psi_write_into(psi_args);
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
 
-               psi_args.dest_offset = args.dest_offset + nbytes;
+               psi_args.dest_offset = args->dest_offset + nbytes;
                psi_args.len = sizeof_field(struct vidtv_psi_desc_service, service_name_len);
-               psi_args.from = &((struct vidtv_psi_desc_service *)args.desc)->service_name_len;
+               psi_args.from = &((struct vidtv_psi_desc_service *)args->desc)->service_name_len;
 
-               nbytes += vidtv_psi_ts_psi_write_into(psi_args);
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
 
-               psi_args.dest_offset = args.dest_offset + nbytes;
-               psi_args.len = ((struct vidtv_psi_desc_service *)args.desc)->service_name_len;
-               psi_args.from = ((struct vidtv_psi_desc_service *)args.desc)->service_name;
+               psi_args.dest_offset = args->dest_offset + nbytes;
+               psi_args.len = ((struct vidtv_psi_desc_service *)args->desc)->service_name_len;
+               psi_args.from = ((struct vidtv_psi_desc_service *)args->desc)->service_name;
+
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
+               break;
+
+       case NETWORK_NAME_DESCRIPTOR:
+               psi_args.dest_offset = args->dest_offset + nbytes;
+               psi_args.len = args->desc->length;
+               psi_args.from = ((struct vidtv_psi_desc_network_name *)args->desc)->network_name;
+
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
+               break;
+
+       case SERVICE_LIST_DESCRIPTOR:
+               serv_list_entry = ((struct vidtv_psi_desc_service_list *)args->desc)->service_list;
+               while (serv_list_entry) {
+                       psi_args.dest_offset = args->dest_offset + nbytes;
+                       psi_args.len = sizeof(struct vidtv_psi_desc_service_list_entry) -
+                                      sizeof(struct vidtv_psi_desc_service_list_entry *);
+                       psi_args.from = serv_list_entry;
+
+                       nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
+
+                       serv_list_entry = serv_list_entry->next;
+               }
+               break;
+
+       case SHORT_EVENT_DESCRIPTOR:
+               psi_args.dest_offset = args->dest_offset + nbytes;
+               psi_args.len = ISO_LANGUAGE_CODE_LEN;
+               psi_args.from = ((struct vidtv_psi_desc_short_event *)
+                                 args->desc)->iso_language_code;
+
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
+
+               psi_args.dest_offset = args->dest_offset + nbytes;
+               psi_args.len = sizeof_field(struct vidtv_psi_desc_short_event, event_name_len);
+               psi_args.from = &((struct vidtv_psi_desc_short_event *)
+                                 args->desc)->event_name_len;
+
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
+
+               psi_args.dest_offset = args->dest_offset + nbytes;
+               psi_args.len = ((struct vidtv_psi_desc_short_event *)args->desc)->event_name_len;
+               psi_args.from = ((struct vidtv_psi_desc_short_event *)args->desc)->event_name;
+
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
+
+               psi_args.dest_offset = args->dest_offset + nbytes;
+               psi_args.len = sizeof_field(struct vidtv_psi_desc_short_event, text_len);
+               psi_args.from = &((struct vidtv_psi_desc_short_event *)args->desc)->text_len;
+
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
+
+               psi_args.dest_offset = args->dest_offset + nbytes;
+               psi_args.len = ((struct vidtv_psi_desc_short_event *)args->desc)->text_len;
+               psi_args.from = ((struct vidtv_psi_desc_short_event *)args->desc)->text;
+
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
 
-               nbytes += vidtv_psi_ts_psi_write_into(psi_args);
                break;
 
        case REGISTRATION_DESCRIPTOR:
        default:
-               psi_args.dest_offset = args.dest_offset + nbytes;
-               psi_args.len = args.desc->length;
-               psi_args.from = &args.desc->data;
+               psi_args.dest_offset = args->dest_offset + nbytes;
+               psi_args.len = args->desc->length;
+               psi_args.from = &args->desc->data;
 
-               nbytes += vidtv_psi_ts_psi_write_into(psi_args);
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
                break;
        }
 
@@ -577,40 +754,37 @@ static u32 vidtv_psi_desc_write_into(struct desc_write_args args)
 }
 
 static u32
-vidtv_psi_table_header_write_into(struct header_write_args args)
+vidtv_psi_table_header_write_into(struct header_write_args *args)
 {
-       /* the number of bytes written by this function */
-       u32 nbytes = 0;
-       struct psi_write_args psi_args = {};
-
-       psi_args.dest_buf           = args.dest_buf;
-       psi_args.from               = args.h;
-       psi_args.len                = sizeof(struct vidtv_psi_table_header);
-       psi_args.dest_offset        = args.dest_offset;
-       psi_args.pid                = args.pid;
-       psi_args.new_psi_section    = true;
-       psi_args.continuity_counter = args.continuity_counter;
-       psi_args.is_crc             = false;
-       psi_args.dest_buf_sz        = args.dest_buf_sz;
-       psi_args.crc                = args.crc;
-
-       nbytes += vidtv_psi_ts_psi_write_into(psi_args);
-
-       return nbytes;
+       struct psi_write_args psi_args = {
+               .dest_buf           = args->dest_buf,
+               .from               = args->h,
+               .len                = sizeof(struct vidtv_psi_table_header),
+               .dest_offset        = args->dest_offset,
+               .pid                = args->pid,
+               .new_psi_section    = true,
+               .continuity_counter = args->continuity_counter,
+               .is_crc             = false,
+               .dest_buf_sz        = args->dest_buf_sz,
+               .crc                = args->crc,
+       };
+
+       return vidtv_psi_ts_psi_write_into(&psi_args);
 }
 
 void
 vidtv_psi_pat_table_update_sec_len(struct vidtv_psi_table_pat *pat)
 {
-       /* see ISO/IEC 13818-1 : 2000 p.43 */
        u16 length = 0;
        u32 i;
 
+       /* see ISO/IEC 13818-1 : 2000 p.43 */
+
        /* from immediately after 'section_length' until 'last_section_number'*/
        length += PAT_LEN_UNTIL_LAST_SECTION_NUMBER;
 
        /* do not count the pointer */
-       for (i = 0; i < pat->programs; ++i)
+       for (i = 0; i < pat->num_pat; ++i)
                length += sizeof(struct vidtv_psi_table_pat_program) -
                          sizeof(struct vidtv_psi_table_pat_program *);
 
@@ -621,10 +795,11 @@ vidtv_psi_pat_table_update_sec_len(struct vidtv_psi_table_pat *pat)
 
 void vidtv_psi_pmt_table_update_sec_len(struct vidtv_psi_table_pmt *pmt)
 {
-       /* see ISO/IEC 13818-1 : 2000 p.46 */
-       u16 length = 0;
        struct vidtv_psi_table_pmt_stream *s = pmt->stream;
        u16 desc_loop_len;
+       u16 length = 0;
+
+       /* see ISO/IEC 13818-1 : 2000 p.46 */
 
        /* from immediately after 'section_length' until 'program_info_length'*/
        length += PMT_LEN_UNTIL_PROGRAM_INFO_LENGTH;
@@ -655,10 +830,11 @@ void vidtv_psi_pmt_table_update_sec_len(struct vidtv_psi_table_pmt *pmt)
 
 void vidtv_psi_sdt_table_update_sec_len(struct vidtv_psi_table_sdt *sdt)
 {
-       /* see ETSI EN 300 468 V 1.10.1 p.24 */
-       u16 length = 0;
        struct vidtv_psi_table_sdt_service *s = sdt->service;
        u16 desc_loop_len;
+       u16 length = 0;
+
+       /* see ETSI EN 300 468 V 1.10.1 p.24 */
 
        /*
         * from immediately after 'section_length' until
@@ -681,7 +857,6 @@ void vidtv_psi_sdt_table_update_sec_len(struct vidtv_psi_table_sdt *sdt)
        }
 
        length += CRC_SIZE_IN_BYTES;
-
        vidtv_psi_set_sec_len(&sdt->header, length);
 }
 
@@ -694,6 +869,8 @@ vidtv_psi_pat_program_init(struct vidtv_psi_table_pat_program *head,
        const u16 RESERVED = 0x07;
 
        program = kzalloc(sizeof(*program), GFP_KERNEL);
+       if (!program)
+               return NULL;
 
        program->service_id = cpu_to_be16(service_id);
 
@@ -714,8 +891,8 @@ vidtv_psi_pat_program_init(struct vidtv_psi_table_pat_program *head,
 void
 vidtv_psi_pat_program_destroy(struct vidtv_psi_table_pat_program *p)
 {
-       struct vidtv_psi_table_pat_program *curr = p;
        struct vidtv_psi_table_pat_program *tmp  = NULL;
+       struct vidtv_psi_table_pat_program *curr = p;
 
        while (curr) {
                tmp  = curr;
@@ -724,42 +901,49 @@ vidtv_psi_pat_program_destroy(struct vidtv_psi_table_pat_program *p)
        }
 }
 
+/* This function transfers ownership of p to the table */
 void
 vidtv_psi_pat_program_assign(struct vidtv_psi_table_pat *pat,
                             struct vidtv_psi_table_pat_program *p)
 {
-       /* This function transfers ownership of p to the table */
+       struct vidtv_psi_table_pat_program *program;
+       u16 program_count;
 
-       u16 program_count = 0;
-       struct vidtv_psi_table_pat_program *program = p;
+       do {
+               program_count = 0;
+               program = p;
 
-       if (p == pat->program)
-               return;
+               if (p == pat->program)
+                       return;
 
-       while (program) {
-               ++program_count;
-               program = program->next;
-       }
+               while (program) {
+                       ++program_count;
+                       program = program->next;
+               }
 
-       pat->programs = program_count;
-       pat->program  = p;
+               pat->num_pat = program_count;
+               pat->program  = p;
 
-       /* Recompute section length */
-       vidtv_psi_pat_table_update_sec_len(pat);
+               /* Recompute section length */
+               vidtv_psi_pat_table_update_sec_len(pat);
 
-       if (vidtv_psi_get_sec_len(&pat->header) > MAX_SECTION_LEN)
-               vidtv_psi_pat_program_assign(pat, NULL);
+               p = NULL;
+       } while (vidtv_psi_get_sec_len(&pat->header) > MAX_SECTION_LEN);
 
        vidtv_psi_update_version_num(&pat->header);
 }
 
 struct vidtv_psi_table_pat *vidtv_psi_pat_table_init(u16 transport_stream_id)
 {
-       struct vidtv_psi_table_pat *pat = kzalloc(sizeof(*pat), GFP_KERNEL);
+       struct vidtv_psi_table_pat *pat;
        const u16 SYNTAX = 0x1;
        const u16 ZERO = 0x0;
        const u16 ONES = 0x03;
 
+       pat = kzalloc(sizeof(*pat), GFP_KERNEL);
+       if (!pat)
+               return NULL;
+
        pat->header.table_id = 0x0;
 
        pat->header.bitfield = cpu_to_be16((SYNTAX << 15) | (ZERO << 14) | (ONES << 12));
@@ -772,70 +956,68 @@ struct vidtv_psi_table_pat *vidtv_psi_pat_table_init(u16 transport_stream_id)
        pat->header.section_id   = 0x0;
        pat->header.last_section = 0x0;
 
-       pat->programs = 0;
-
        vidtv_psi_pat_table_update_sec_len(pat);
 
        return pat;
 }
 
-u32 vidtv_psi_pat_write_into(struct vidtv_psi_pat_write_args args)
+u32 vidtv_psi_pat_write_into(struct vidtv_psi_pat_write_args *args)
 {
-       /* the number of bytes written by this function */
+       struct vidtv_psi_table_pat_program *p = args->pat->program;
+       struct header_write_args h_args       = {
+               .dest_buf           = args->buf,
+               .dest_offset        = args->offset,
+               .pid                = VIDTV_PAT_PID,
+               .h                  = &args->pat->header,
+               .continuity_counter = args->continuity_counter,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       struct psi_write_args psi_args        = {
+               .dest_buf           = args->buf,
+               .pid                = VIDTV_PAT_PID,
+               .new_psi_section    = false,
+               .continuity_counter = args->continuity_counter,
+               .is_crc             = false,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       struct crc32_write_args c_args        = {
+               .dest_buf           = args->buf,
+               .pid                = VIDTV_PAT_PID,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       u32 crc = INITIAL_CRC;
        u32 nbytes = 0;
-       const u16 pat_pid = VIDTV_PAT_PID;
-       u32 crc = 0xffffffff;
-
-       struct vidtv_psi_table_pat_program *p = args.pat->program;
 
-       struct header_write_args h_args       = {};
-       struct psi_write_args psi_args            = {};
-       struct crc32_write_args c_args        = {};
+       vidtv_psi_pat_table_update_sec_len(args->pat);
 
-       vidtv_psi_pat_table_update_sec_len(args.pat);
-
-       h_args.dest_buf           = args.buf;
-       h_args.dest_offset        = args.offset;
-       h_args.h                  = &args.pat->header;
-       h_args.pid                = pat_pid;
-       h_args.continuity_counter = args.continuity_counter;
-       h_args.dest_buf_sz        = args.buf_sz;
        h_args.crc = &crc;
 
-       nbytes += vidtv_psi_table_header_write_into(h_args);
+       nbytes += vidtv_psi_table_header_write_into(&h_args);
 
        /* note that the field 'u16 programs' is not really part of the PAT */
 
-       psi_args.dest_buf           = args.buf;
-       psi_args.pid                = pat_pid;
-       psi_args.new_psi_section    = false;
-       psi_args.continuity_counter = args.continuity_counter;
-       psi_args.is_crc             = false;
-       psi_args.dest_buf_sz        = args.buf_sz;
-       psi_args.crc                = &crc;
+       psi_args.crc = &crc;
 
        while (p) {
                /* copy the PAT programs */
                psi_args.from = p;
                /* skip the pointer */
                psi_args.len = sizeof(*p) -
-                          sizeof(struct vidtv_psi_table_pat_program *);
-               psi_args.dest_offset = args.offset + nbytes;
+                              sizeof(struct vidtv_psi_table_pat_program *);
+               psi_args.dest_offset = args->offset + nbytes;
+               psi_args.continuity_counter = args->continuity_counter;
 
-               nbytes += vidtv_psi_ts_psi_write_into(psi_args);
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
 
                p = p->next;
        }
 
-       c_args.dest_buf           = args.buf;
-       c_args.dest_offset        = args.offset + nbytes;
+       c_args.dest_offset        = args->offset + nbytes;
+       c_args.continuity_counter = args->continuity_counter;
        c_args.crc                = cpu_to_be32(crc);
-       c_args.pid                = pat_pid;
-       c_args.continuity_counter = args.continuity_counter;
-       c_args.dest_buf_sz        = args.buf_sz;
 
        /* Write the CRC32 at the end */
-       nbytes += table_section_crc32_write_into(c_args);
+       nbytes += table_section_crc32_write_into(&c_args);
 
        return nbytes;
 }
@@ -859,6 +1041,8 @@ vidtv_psi_pmt_stream_init(struct vidtv_psi_table_pmt_stream *head,
        u16 desc_loop_len;
 
        stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+       if (!stream)
+               return NULL;
 
        stream->type = stream_type;
 
@@ -883,8 +1067,8 @@ vidtv_psi_pmt_stream_init(struct vidtv_psi_table_pmt_stream *head,
 
 void vidtv_psi_pmt_stream_destroy(struct vidtv_psi_table_pmt_stream *s)
 {
-       struct vidtv_psi_table_pmt_stream *curr_stream = s;
        struct vidtv_psi_table_pmt_stream *tmp_stream  = NULL;
+       struct vidtv_psi_table_pmt_stream *curr_stream = s;
 
        while (curr_stream) {
                tmp_stream  = curr_stream;
@@ -897,15 +1081,16 @@ void vidtv_psi_pmt_stream_destroy(struct vidtv_psi_table_pmt_stream *s)
 void vidtv_psi_pmt_stream_assign(struct vidtv_psi_table_pmt *pmt,
                                 struct vidtv_psi_table_pmt_stream *s)
 {
-       /* This function transfers ownership of s to the table */
-       if (s == pmt->stream)
-               return;
+       do {
+               /* This function transfers ownership of s to the table */
+               if (s == pmt->stream)
+                       return;
 
-       pmt->stream = s;
-       vidtv_psi_pmt_table_update_sec_len(pmt);
+               pmt->stream = s;
+               vidtv_psi_pmt_table_update_sec_len(pmt);
 
-       if (vidtv_psi_get_sec_len(&pmt->header) > MAX_SECTION_LEN)
-               vidtv_psi_pmt_stream_assign(pmt, NULL);
+               s = NULL;
+       } while (vidtv_psi_get_sec_len(&pmt->header) > MAX_SECTION_LEN);
 
        vidtv_psi_update_version_num(&pmt->header);
 }
@@ -933,14 +1118,18 @@ u16 vidtv_psi_pmt_get_pid(struct vidtv_psi_table_pmt *section,
 struct vidtv_psi_table_pmt *vidtv_psi_pmt_table_init(u16 program_number,
                                                     u16 pcr_pid)
 {
-       struct vidtv_psi_table_pmt *pmt = kzalloc(sizeof(*pmt), GFP_KERNEL);
-       const u16 SYNTAX = 0x1;
-       const u16 ZERO = 0x0;
-       const u16 ONES = 0x03;
+       struct vidtv_psi_table_pmt *pmt;
        const u16 RESERVED1 = 0x07;
        const u16 RESERVED2 = 0x0f;
+       const u16 SYNTAX = 0x1;
+       const u16 ONES = 0x03;
+       const u16 ZERO = 0x0;
        u16 desc_loop_len;
 
+       pmt = kzalloc(sizeof(*pmt), GFP_KERNEL);
+       if (!pmt)
+               return NULL;
+
        if (!pcr_pid)
                pcr_pid = 0x1fff;
 
@@ -970,87 +1159,84 @@ struct vidtv_psi_table_pmt *vidtv_psi_pmt_table_init(u16 program_number,
        return pmt;
 }
 
-u32 vidtv_psi_pmt_write_into(struct vidtv_psi_pmt_write_args args)
+u32 vidtv_psi_pmt_write_into(struct vidtv_psi_pmt_write_args *args)
 {
-       /* the number of bytes written by this function */
+       struct vidtv_psi_desc *table_descriptor   = args->pmt->descriptor;
+       struct vidtv_psi_table_pmt_stream *stream = args->pmt->stream;
+       struct vidtv_psi_desc *stream_descriptor;
+       struct header_write_args h_args = {
+               .dest_buf           = args->buf,
+               .dest_offset        = args->offset,
+               .h                  = &args->pmt->header,
+               .pid                = args->pid,
+               .continuity_counter = args->continuity_counter,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       struct psi_write_args psi_args  = {
+               .dest_buf = args->buf,
+               .from     = &args->pmt->bitfield,
+               .len      = sizeof_field(struct vidtv_psi_table_pmt, bitfield) +
+                           sizeof_field(struct vidtv_psi_table_pmt, bitfield2),
+               .pid                = args->pid,
+               .new_psi_section    = false,
+               .is_crc             = false,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       struct desc_write_args d_args   = {
+               .dest_buf           = args->buf,
+               .desc               = table_descriptor,
+               .pid                = args->pid,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       struct crc32_write_args c_args  = {
+               .dest_buf           = args->buf,
+               .pid                = args->pid,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       u32 crc = INITIAL_CRC;
        u32 nbytes = 0;
-       u32 crc = 0xffffffff;
-
-       struct vidtv_psi_desc *table_descriptor   = args.pmt->descriptor;
-       struct vidtv_psi_table_pmt_stream *stream = args.pmt->stream;
-       struct vidtv_psi_desc *stream_descriptor  = (stream) ?
-                                                   args.pmt->stream->descriptor :
-                                                   NULL;
-
-       struct header_write_args h_args = {};
-       struct psi_write_args psi_args  = {};
-       struct desc_write_args d_args   = {};
-       struct crc32_write_args c_args  = {};
-
-       vidtv_psi_pmt_table_update_sec_len(args.pmt);
-
-       h_args.dest_buf           = args.buf;
-       h_args.dest_offset        = args.offset;
-       h_args.h                  = &args.pmt->header;
-       h_args.pid                = args.pid;
-       h_args.continuity_counter = args.continuity_counter;
-       h_args.dest_buf_sz        = args.buf_sz;
+
+       vidtv_psi_pmt_table_update_sec_len(args->pmt);
+
        h_args.crc                = &crc;
 
-       nbytes += vidtv_psi_table_header_write_into(h_args);
+       nbytes += vidtv_psi_table_header_write_into(&h_args);
 
        /* write the two bitfields */
-       psi_args.dest_buf = args.buf;
-       psi_args.from     = &args.pmt->bitfield;
-       psi_args.len      = sizeof_field(struct vidtv_psi_table_pmt, bitfield) +
-                           sizeof_field(struct vidtv_psi_table_pmt, bitfield2);
-
-       psi_args.dest_offset        = args.offset + nbytes;
-       psi_args.pid                = args.pid;
-       psi_args.new_psi_section    = false;
-       psi_args.continuity_counter = args.continuity_counter;
-       psi_args.is_crc             = false;
-       psi_args.dest_buf_sz        = args.buf_sz;
-       psi_args.crc                = &crc;
-
-       nbytes += vidtv_psi_ts_psi_write_into(psi_args);
+       psi_args.dest_offset        = args->offset + nbytes;
+       psi_args.continuity_counter = args->continuity_counter;
+       nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
 
        while (table_descriptor) {
                /* write the descriptors, if any */
-               d_args.dest_buf           = args.buf;
-               d_args.dest_offset        = args.offset + nbytes;
-               d_args.desc               = table_descriptor;
-               d_args.pid                = args.pid;
-               d_args.continuity_counter = args.continuity_counter;
-               d_args.dest_buf_sz        = args.buf_sz;
+               d_args.dest_offset        = args->offset + nbytes;
+               d_args.continuity_counter = args->continuity_counter;
                d_args.crc                = &crc;
 
-               nbytes += vidtv_psi_desc_write_into(d_args);
+               nbytes += vidtv_psi_desc_write_into(&d_args);
 
                table_descriptor = table_descriptor->next;
        }
 
+       psi_args.len += sizeof_field(struct vidtv_psi_table_pmt_stream, type);
        while (stream) {
                /* write the streams, if any */
                psi_args.from = stream;
-               psi_args.len  = sizeof_field(struct vidtv_psi_table_pmt_stream, type) +
-                               sizeof_field(struct vidtv_psi_table_pmt_stream, bitfield) +
-                               sizeof_field(struct vidtv_psi_table_pmt_stream, bitfield2);
-               psi_args.dest_offset = args.offset + nbytes;
+               psi_args.dest_offset = args->offset + nbytes;
+               psi_args.continuity_counter = args->continuity_counter;
+
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
 
-               nbytes += vidtv_psi_ts_psi_write_into(psi_args);
+               stream_descriptor = stream->descriptor;
 
                while (stream_descriptor) {
                        /* write the stream descriptors, if any */
-                       d_args.dest_buf           = args.buf;
-                       d_args.dest_offset        = args.offset + nbytes;
+                       d_args.dest_offset        = args->offset + nbytes;
                        d_args.desc               = stream_descriptor;
-                       d_args.pid                = args.pid;
-                       d_args.continuity_counter = args.continuity_counter;
-                       d_args.dest_buf_sz        = args.buf_sz;
+                       d_args.continuity_counter = args->continuity_counter;
                        d_args.crc                = &crc;
 
-                       nbytes += vidtv_psi_desc_write_into(d_args);
+                       nbytes += vidtv_psi_desc_write_into(&d_args);
 
                        stream_descriptor = stream_descriptor->next;
                }
@@ -1058,15 +1244,12 @@ u32 vidtv_psi_pmt_write_into(struct vidtv_psi_pmt_write_args args)
                stream = stream->next;
        }
 
-       c_args.dest_buf           = args.buf;
-       c_args.dest_offset        = args.offset + nbytes;
+       c_args.dest_offset        = args->offset + nbytes;
        c_args.crc                = cpu_to_be32(crc);
-       c_args.pid                = args.pid;
-       c_args.continuity_counter = args.continuity_counter;
-       c_args.dest_buf_sz        = args.buf_sz;
+       c_args.continuity_counter = args->continuity_counter;
 
        /* Write the CRC32 at the end */
-       nbytes += table_section_crc32_write_into(c_args);
+       nbytes += table_section_crc32_write_into(&c_args);
 
        return nbytes;
 }
@@ -1078,16 +1261,20 @@ void vidtv_psi_pmt_table_destroy(struct vidtv_psi_table_pmt *pmt)
        kfree(pmt);
 }
 
-struct vidtv_psi_table_sdt *vidtv_psi_sdt_table_init(u16 transport_stream_id)
+struct vidtv_psi_table_sdt *vidtv_psi_sdt_table_init(u16 network_id,
+                                                    u16 transport_stream_id)
 {
-       struct vidtv_psi_table_sdt *sdt = kzalloc(sizeof(*sdt), GFP_KERNEL);
+       struct vidtv_psi_table_sdt *sdt;
+       const u16 RESERVED = 0xff;
        const u16 SYNTAX = 0x1;
-       const u16 ONE = 0x1;
        const u16 ONES = 0x03;
-       const u16 RESERVED = 0xff;
+       const u16 ONE = 0x1;
 
-       sdt->header.table_id = 0x42;
+       sdt  = kzalloc(sizeof(*sdt), GFP_KERNEL);
+       if (!sdt)
+               return NULL;
 
+       sdt->header.table_id = 0x42;
        sdt->header.bitfield = cpu_to_be16((SYNTAX << 15) | (ONE << 14) | (ONES << 12));
 
        /*
@@ -1111,7 +1298,7 @@ struct vidtv_psi_table_sdt *vidtv_psi_sdt_table_init(u16 transport_stream_id)
         * This can be changed to something more useful, when support for
         * NIT gets added
         */
-       sdt->network_id = cpu_to_be16(0xff01);
+       sdt->network_id = cpu_to_be16(network_id);
        sdt->reserved = RESERVED;
 
        vidtv_psi_sdt_table_update_sec_len(sdt);
@@ -1119,74 +1306,79 @@ struct vidtv_psi_table_sdt *vidtv_psi_sdt_table_init(u16 transport_stream_id)
        return sdt;
 }
 
-u32 vidtv_psi_sdt_write_into(struct vidtv_psi_sdt_write_args args)
+u32 vidtv_psi_sdt_write_into(struct vidtv_psi_sdt_write_args *args)
 {
+       struct header_write_args h_args = {
+               .dest_buf           = args->buf,
+               .dest_offset        = args->offset,
+               .h                  = &args->sdt->header,
+               .pid                = VIDTV_SDT_PID,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       struct psi_write_args psi_args  = {
+               .dest_buf = args->buf,
+               .len = sizeof_field(struct vidtv_psi_table_sdt, network_id) +
+                      sizeof_field(struct vidtv_psi_table_sdt, reserved),
+               .pid                = VIDTV_SDT_PID,
+               .new_psi_section    = false,
+               .is_crc             = false,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       struct desc_write_args d_args   = {
+               .dest_buf           = args->buf,
+               .pid                = VIDTV_SDT_PID,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       struct crc32_write_args c_args  = {
+               .dest_buf           = args->buf,
+               .pid                = VIDTV_SDT_PID,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       struct vidtv_psi_table_sdt_service *service = args->sdt->service;
+       struct vidtv_psi_desc *service_desc;
        u32 nbytes  = 0;
-       u16 sdt_pid = VIDTV_SDT_PID;  /* see ETSI EN 300 468 v1.15.1 p. 11 */
+       u32 crc = INITIAL_CRC;
 
-       u32 crc = 0xffffffff;
+       /* see ETSI EN 300 468 v1.15.1 p. 11 */
 
-       struct vidtv_psi_table_sdt_service *service = args.sdt->service;
-       struct vidtv_psi_desc *service_desc = (args.sdt->service) ?
-                                             args.sdt->service->descriptor :
-                                             NULL;
+       vidtv_psi_sdt_table_update_sec_len(args->sdt);
 
-       struct header_write_args h_args = {};
-       struct psi_write_args psi_args  = {};
-       struct desc_write_args d_args   = {};
-       struct crc32_write_args c_args  = {};
-
-       vidtv_psi_sdt_table_update_sec_len(args.sdt);
-
-       h_args.dest_buf           = args.buf;
-       h_args.dest_offset        = args.offset;
-       h_args.h                  = &args.sdt->header;
-       h_args.pid                = sdt_pid;
-       h_args.continuity_counter = args.continuity_counter;
-       h_args.dest_buf_sz        = args.buf_sz;
+       h_args.continuity_counter = args->continuity_counter;
        h_args.crc                = &crc;
 
-       nbytes += vidtv_psi_table_header_write_into(h_args);
-
-       psi_args.dest_buf = args.buf;
-       psi_args.from     = &args.sdt->network_id;
+       nbytes += vidtv_psi_table_header_write_into(&h_args);
 
-       psi_args.len = sizeof_field(struct vidtv_psi_table_sdt, network_id) +
-                      sizeof_field(struct vidtv_psi_table_sdt, reserved);
-
-       psi_args.dest_offset        = args.offset + nbytes;
-       psi_args.pid                = sdt_pid;
-       psi_args.new_psi_section    = false;
-       psi_args.continuity_counter = args.continuity_counter;
-       psi_args.is_crc             = false;
-       psi_args.dest_buf_sz        = args.buf_sz;
+       psi_args.from               = &args->sdt->network_id;
+       psi_args.dest_offset        = args->offset + nbytes;
+       psi_args.continuity_counter = args->continuity_counter;
        psi_args.crc                = &crc;
 
        /* copy u16 network_id + u8 reserved)*/
-       nbytes += vidtv_psi_ts_psi_write_into(psi_args);
+       nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
+
+       /* skip both pointers at the end */
+       psi_args.len = sizeof(struct vidtv_psi_table_sdt_service) -
+                      sizeof(struct vidtv_psi_desc *) -
+                      sizeof(struct vidtv_psi_table_sdt_service *);
 
        while (service) {
                /* copy the services, if any */
                psi_args.from = service;
-               /* skip both pointers at the end */
-               psi_args.len = sizeof(struct vidtv_psi_table_sdt_service) -
-                              sizeof(struct vidtv_psi_desc *) -
-                              sizeof(struct vidtv_psi_table_sdt_service *);
-               psi_args.dest_offset = args.offset + nbytes;
+               psi_args.dest_offset = args->offset + nbytes;
+               psi_args.continuity_counter = args->continuity_counter;
+
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
 
-               nbytes += vidtv_psi_ts_psi_write_into(psi_args);
+               service_desc = service->descriptor;
 
                while (service_desc) {
                        /* copy the service descriptors, if any */
-                       d_args.dest_buf           = args.buf;
-                       d_args.dest_offset        = args.offset + nbytes;
+                       d_args.dest_offset        = args->offset + nbytes;
                        d_args.desc               = service_desc;
-                       d_args.pid                = sdt_pid;
-                       d_args.continuity_counter = args.continuity_counter;
-                       d_args.dest_buf_sz        = args.buf_sz;
+                       d_args.continuity_counter = args->continuity_counter;
                        d_args.crc                = &crc;
 
-                       nbytes += vidtv_psi_desc_write_into(d_args);
+                       nbytes += vidtv_psi_desc_write_into(&d_args);
 
                        service_desc = service_desc->next;
                }
@@ -1194,15 +1386,12 @@ u32 vidtv_psi_sdt_write_into(struct vidtv_psi_sdt_write_args args)
                service = service->next;
        }
 
-       c_args.dest_buf           = args.buf;
-       c_args.dest_offset        = args.offset + nbytes;
+       c_args.dest_offset        = args->offset + nbytes;
        c_args.crc                = cpu_to_be32(crc);
-       c_args.pid                = sdt_pid;
-       c_args.continuity_counter = args.continuity_counter;
-       c_args.dest_buf_sz        = args.buf_sz;
+       c_args.continuity_counter = args->continuity_counter;
 
        /* Write the CRC at the end */
-       nbytes += table_section_crc32_write_into(c_args);
+       nbytes += table_section_crc32_write_into(&c_args);
 
        return nbytes;
 }
@@ -1215,11 +1404,15 @@ void vidtv_psi_sdt_table_destroy(struct vidtv_psi_table_sdt *sdt)
 
 struct vidtv_psi_table_sdt_service
 *vidtv_psi_sdt_service_init(struct vidtv_psi_table_sdt_service *head,
-                           u16 service_id)
+                           u16 service_id,
+                           bool eit_schedule,
+                           bool eit_present_following)
 {
        struct vidtv_psi_table_sdt_service *service;
 
        service = kzalloc(sizeof(*service), GFP_KERNEL);
+       if (!service)
+               return NULL;
 
        /*
         * ETSI 300 468: this is a 16bit field which serves as a label to
@@ -1228,8 +1421,8 @@ struct vidtv_psi_table_sdt_service
         * corresponding program_map_section
         */
        service->service_id            = cpu_to_be16(service_id);
-       service->EIT_schedule          = 0x0;
-       service->EIT_present_following = 0x0;
+       service->EIT_schedule          = eit_schedule;
+       service->EIT_present_following = eit_present_following;
        service->reserved              = 0x3f;
 
        service->bitfield = cpu_to_be16(RUNNING << 13);
@@ -1262,53 +1455,78 @@ void
 vidtv_psi_sdt_service_assign(struct vidtv_psi_table_sdt *sdt,
                             struct vidtv_psi_table_sdt_service *service)
 {
-       if (service == sdt->service)
-               return;
+       do {
+               if (service == sdt->service)
+                       return;
 
-       sdt->service = service;
+               sdt->service = service;
 
-       /* recompute section length */
-       vidtv_psi_sdt_table_update_sec_len(sdt);
+               /* recompute section length */
+               vidtv_psi_sdt_table_update_sec_len(sdt);
 
-       if (vidtv_psi_get_sec_len(&sdt->header) > MAX_SECTION_LEN)
-               vidtv_psi_sdt_service_assign(sdt, NULL);
+               service = NULL;
+       } while (vidtv_psi_get_sec_len(&sdt->header) > MAX_SECTION_LEN);
 
        vidtv_psi_update_version_num(&sdt->header);
 }
 
+/*
+ * PMTs contain information about programs. For each program,
+ * there is one PMT section. This function will create a section
+ * for each program found in the PAT
+ */
 struct vidtv_psi_table_pmt**
-vidtv_psi_pmt_create_sec_for_each_pat_entry(struct vidtv_psi_table_pat *pat, u16 pcr_pid)
+vidtv_psi_pmt_create_sec_for_each_pat_entry(struct vidtv_psi_table_pat *pat,
+                                           u16 pcr_pid)
 
 {
+       struct vidtv_psi_table_pat_program *program;
+       struct vidtv_psi_table_pmt **pmt_secs;
+       u32 i = 0, num_pmt = 0;
+
        /*
-        * PMTs contain information about programs. For each program,
-        * there is one PMT section. This function will create a section
-        * for each program found in the PAT
+        * The number of PMT entries is the number of PAT entries
+        * that contain service_id. That exclude special tables, like NIT
         */
-       struct vidtv_psi_table_pat_program *program = pat->program;
-       struct vidtv_psi_table_pmt **pmt_secs;
-       u32 i = 0;
+       program = pat->program;
+       while (program) {
+               if (program->service_id)
+                       num_pmt++;
+               program = program->next;
+       }
 
-       /* a section for each program_id */
-       pmt_secs = kcalloc(pat->programs,
+       pmt_secs = kcalloc(num_pmt,
                           sizeof(struct vidtv_psi_table_pmt *),
                           GFP_KERNEL);
-
-       while (program) {
-               pmt_secs[i] = vidtv_psi_pmt_table_init(be16_to_cpu(program->service_id), pcr_pid);
-               ++i;
-               program = program->next;
+       if (!pmt_secs)
+               return NULL;
+
+       for (program = pat->program; program; program = program->next) {
+               if (!program->service_id)
+                       continue;
+               pmt_secs[i] = vidtv_psi_pmt_table_init(be16_to_cpu(program->service_id),
+                                                      pcr_pid);
+
+               if (!pmt_secs[i]) {
+                       while (i > 0) {
+                               i--;
+                               vidtv_psi_pmt_table_destroy(pmt_secs[i]);
+                       }
+                       return NULL;
+               }
+               i++;
        }
+       pat->num_pmt = num_pmt;
 
        return pmt_secs;
 }
 
+/* find the PMT section associated with 'program_num' */
 struct vidtv_psi_table_pmt
 *vidtv_psi_find_pmt_sec(struct vidtv_psi_table_pmt **pmt_sections,
                        u16 nsections,
                        u16 program_num)
 {
-       /* find the PMT section associated with 'program_num' */
        struct vidtv_psi_table_pmt *sec = NULL;
        u32 i;
 
@@ -1320,3 +1538,488 @@ struct vidtv_psi_table_pmt
 
        return NULL; /* not found */
 }
+
+static void vidtv_psi_nit_table_update_sec_len(struct vidtv_psi_table_nit *nit)
+{
+       u16 length = 0;
+       struct vidtv_psi_table_transport *t = nit->transport;
+       u16 desc_loop_len;
+       u16 transport_loop_len = 0;
+
+       /*
+        * from immediately after 'section_length' until
+        * 'network_descriptor_length'
+        */
+       length += NIT_LEN_UNTIL_NETWORK_DESCRIPTOR_LEN;
+
+       desc_loop_len = vidtv_psi_desc_comp_loop_len(nit->descriptor);
+       vidtv_psi_set_desc_loop_len(&nit->bitfield, desc_loop_len, 12);
+
+       length += desc_loop_len;
+
+       length += sizeof_field(struct vidtv_psi_table_nit, bitfield2);
+
+       while (t) {
+               /* skip both pointers at the end */
+               transport_loop_len += sizeof(struct vidtv_psi_table_transport) -
+                                     sizeof(struct vidtv_psi_desc *) -
+                                     sizeof(struct vidtv_psi_table_transport *);
+
+               length += transport_loop_len;
+
+               desc_loop_len = vidtv_psi_desc_comp_loop_len(t->descriptor);
+               vidtv_psi_set_desc_loop_len(&t->bitfield, desc_loop_len, 12);
+
+               length += desc_loop_len;
+
+               t = t->next;
+       }
+
+       // Actually sets the transport stream loop len, maybe rename this function later
+       vidtv_psi_set_desc_loop_len(&nit->bitfield2, transport_loop_len, 12);
+       length += CRC_SIZE_IN_BYTES;
+
+       vidtv_psi_set_sec_len(&nit->header, length);
+}
+
+struct vidtv_psi_table_nit
+*vidtv_psi_nit_table_init(u16 network_id,
+                         u16 transport_stream_id,
+                         char *network_name,
+                         struct vidtv_psi_desc_service_list_entry *service_list)
+{
+       struct vidtv_psi_table_transport *transport;
+       struct vidtv_psi_table_nit *nit;
+       const u16 SYNTAX = 0x1;
+       const u16 ONES = 0x03;
+       const u16 ONE = 0x1;
+
+       nit = kzalloc(sizeof(*nit), GFP_KERNEL);
+       if (!nit)
+               return NULL;
+
+       transport = kzalloc(sizeof(*transport), GFP_KERNEL);
+       if (!transport)
+               goto free_nit;
+
+       nit->header.table_id = 0x40; // ACTUAL_NETWORK
+
+       nit->header.bitfield = cpu_to_be16((SYNTAX << 15) | (ONE << 14) | (ONES << 12));
+
+       nit->header.id = cpu_to_be16(network_id);
+       nit->header.current_next = ONE;
+
+       nit->header.version = 0x1f;
+
+       nit->header.one2  = ONES;
+       nit->header.section_id   = 0;
+       nit->header.last_section = 0;
+
+       nit->bitfield = cpu_to_be16(0xf);
+       nit->bitfield2 = cpu_to_be16(0xf);
+
+       nit->descriptor = (struct vidtv_psi_desc *)
+                         vidtv_psi_network_name_desc_init(NULL, network_name);
+       if (!nit->descriptor)
+               goto free_transport;
+
+       transport->transport_id = cpu_to_be16(transport_stream_id);
+       transport->network_id = cpu_to_be16(network_id);
+       transport->bitfield = cpu_to_be16(0xf);
+       transport->descriptor = (struct vidtv_psi_desc *)
+                               vidtv_psi_service_list_desc_init(NULL, service_list);
+       if (!transport->descriptor)
+               goto free_nit_desc;
+
+       nit->transport = transport;
+
+       vidtv_psi_nit_table_update_sec_len(nit);
+
+       return nit;
+
+free_nit_desc:
+       vidtv_psi_desc_destroy((struct vidtv_psi_desc *)nit->descriptor);
+
+free_transport:
+       kfree(transport);
+free_nit:
+       kfree(nit);
+       return NULL;
+}
+
+u32 vidtv_psi_nit_write_into(struct vidtv_psi_nit_write_args *args)
+{
+       struct header_write_args h_args = {
+               .dest_buf           = args->buf,
+               .dest_offset        = args->offset,
+               .h                  = &args->nit->header,
+               .pid                = VIDTV_NIT_PID,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       struct psi_write_args psi_args  = {
+               .dest_buf           = args->buf,
+               .from               = &args->nit->bitfield,
+               .len                = sizeof_field(struct vidtv_psi_table_nit, bitfield),
+               .pid                = VIDTV_NIT_PID,
+               .new_psi_section    = false,
+               .is_crc             = false,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       struct desc_write_args d_args   = {
+               .dest_buf           = args->buf,
+               .pid                = VIDTV_NIT_PID,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       struct crc32_write_args c_args  = {
+               .dest_buf           = args->buf,
+               .pid                = VIDTV_NIT_PID,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       struct vidtv_psi_desc *table_descriptor     = args->nit->descriptor;
+       struct vidtv_psi_table_transport *transport = args->nit->transport;
+       struct vidtv_psi_desc *transport_descriptor;
+       u32 crc = INITIAL_CRC;
+       u32 nbytes = 0;
+
+       vidtv_psi_nit_table_update_sec_len(args->nit);
+
+       h_args.continuity_counter = args->continuity_counter;
+       h_args.crc                = &crc;
+
+       nbytes += vidtv_psi_table_header_write_into(&h_args);
+
+       /* write the bitfield */
+
+       psi_args.dest_offset        = args->offset + nbytes;
+       psi_args.continuity_counter = args->continuity_counter;
+       psi_args.crc                = &crc;
+
+       nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
+
+       while (table_descriptor) {
+               /* write the descriptors, if any */
+               d_args.dest_offset        = args->offset + nbytes;
+               d_args.desc               = table_descriptor;
+               d_args.continuity_counter = args->continuity_counter;
+               d_args.crc                = &crc;
+
+               nbytes += vidtv_psi_desc_write_into(&d_args);
+
+               table_descriptor = table_descriptor->next;
+       }
+
+       /* write the second bitfield */
+       psi_args.from = &args->nit->bitfield2;
+       psi_args.len = sizeof_field(struct vidtv_psi_table_nit, bitfield2);
+       psi_args.dest_offset = args->offset + nbytes;
+
+       nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
+
+       psi_args.len  = sizeof_field(struct vidtv_psi_table_transport, transport_id) +
+                       sizeof_field(struct vidtv_psi_table_transport, network_id)   +
+                       sizeof_field(struct vidtv_psi_table_transport, bitfield);
+       while (transport) {
+               /* write the transport sections, if any */
+               psi_args.from = transport;
+               psi_args.dest_offset = args->offset + nbytes;
+
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
+
+               transport_descriptor = transport->descriptor;
+
+               while (transport_descriptor) {
+                       /* write the transport descriptors, if any */
+                       d_args.dest_offset        = args->offset + nbytes;
+                       d_args.desc               = transport_descriptor;
+                       d_args.continuity_counter = args->continuity_counter;
+                       d_args.crc                = &crc;
+
+                       nbytes += vidtv_psi_desc_write_into(&d_args);
+
+                       transport_descriptor = transport_descriptor->next;
+               }
+
+               transport = transport->next;
+       }
+
+       c_args.dest_offset        = args->offset + nbytes;
+       c_args.crc                = cpu_to_be32(crc);
+       c_args.continuity_counter = args->continuity_counter;
+
+       /* Write the CRC32 at the end */
+       nbytes += table_section_crc32_write_into(&c_args);
+
+       return nbytes;
+}
+
+static void vidtv_psi_transport_destroy(struct vidtv_psi_table_transport *t)
+{
+       struct vidtv_psi_table_transport *tmp_t  = NULL;
+       struct vidtv_psi_table_transport *curr_t = t;
+
+       while (curr_t) {
+               tmp_t  = curr_t;
+               curr_t = curr_t->next;
+               vidtv_psi_desc_destroy(tmp_t->descriptor);
+               kfree(tmp_t);
+       }
+}
+
+void vidtv_psi_nit_table_destroy(struct vidtv_psi_table_nit *nit)
+{
+       vidtv_psi_desc_destroy(nit->descriptor);
+       vidtv_psi_transport_destroy(nit->transport);
+       kfree(nit);
+}
+
+void vidtv_psi_eit_table_update_sec_len(struct vidtv_psi_table_eit *eit)
+{
+       struct vidtv_psi_table_eit_event *e = eit->event;
+       u16 desc_loop_len;
+       u16 length = 0;
+
+       /*
+        * from immediately after 'section_length' until
+        * 'last_table_id'
+        */
+       length += EIT_LEN_UNTIL_LAST_TABLE_ID;
+
+       while (e) {
+               /* skip both pointers at the end */
+               length += sizeof(struct vidtv_psi_table_eit_event) -
+                         sizeof(struct vidtv_psi_desc *) -
+                         sizeof(struct vidtv_psi_table_eit_event *);
+
+               desc_loop_len = vidtv_psi_desc_comp_loop_len(e->descriptor);
+               vidtv_psi_set_desc_loop_len(&e->bitfield, desc_loop_len, 12);
+
+               length += desc_loop_len;
+
+               e = e->next;
+       }
+
+       length += CRC_SIZE_IN_BYTES;
+
+       vidtv_psi_set_sec_len(&eit->header, length);
+}
+
+void vidtv_psi_eit_event_assign(struct vidtv_psi_table_eit *eit,
+                               struct vidtv_psi_table_eit_event *e)
+{
+       do {
+               if (e == eit->event)
+                       return;
+
+               eit->event = e;
+               vidtv_psi_eit_table_update_sec_len(eit);
+
+               e = NULL;
+       } while (vidtv_psi_get_sec_len(&eit->header) > EIT_MAX_SECTION_LEN);
+
+       vidtv_psi_update_version_num(&eit->header);
+}
+
+struct vidtv_psi_table_eit
+*vidtv_psi_eit_table_init(u16 network_id,
+                         u16 transport_stream_id,
+                         __be16 service_id)
+{
+       struct vidtv_psi_table_eit *eit;
+       const u16 SYNTAX = 0x1;
+       const u16 ONE = 0x1;
+       const u16 ONES = 0x03;
+
+       eit = kzalloc(sizeof(*eit), GFP_KERNEL);
+       if (!eit)
+               return NULL;
+
+       eit->header.table_id = 0x4e; //actual_transport_stream: present/following
+
+       eit->header.bitfield = cpu_to_be16((SYNTAX << 15) | (ONE << 14) | (ONES << 12));
+
+       eit->header.id = service_id;
+       eit->header.current_next = ONE;
+
+       eit->header.version = 0x1f;
+
+       eit->header.one2  = ONES;
+       eit->header.section_id   = 0;
+       eit->header.last_section = 0;
+
+       eit->transport_id = cpu_to_be16(transport_stream_id);
+       eit->network_id = cpu_to_be16(network_id);
+
+       eit->last_segment = eit->header.last_section; /* not implemented */
+       eit->last_table_id = eit->header.table_id; /* not implemented */
+
+       vidtv_psi_eit_table_update_sec_len(eit);
+
+       return eit;
+}
+
+u32 vidtv_psi_eit_write_into(struct vidtv_psi_eit_write_args *args)
+{
+       struct header_write_args h_args = {
+               .dest_buf        = args->buf,
+               .dest_offset     = args->offset,
+               .h               = &args->eit->header,
+               .pid             = VIDTV_EIT_PID,
+               .dest_buf_sz     = args->buf_sz,
+       };
+       struct psi_write_args psi_args  = {
+               .dest_buf        = args->buf,
+               .len             = sizeof_field(struct vidtv_psi_table_eit, transport_id) +
+                                  sizeof_field(struct vidtv_psi_table_eit, network_id)   +
+                                  sizeof_field(struct vidtv_psi_table_eit, last_segment) +
+                                  sizeof_field(struct vidtv_psi_table_eit, last_table_id),
+               .pid             = VIDTV_EIT_PID,
+               .new_psi_section = false,
+               .is_crc          = false,
+               .dest_buf_sz     = args->buf_sz,
+       };
+       struct desc_write_args d_args   = {
+               .dest_buf           = args->buf,
+               .pid                = VIDTV_EIT_PID,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       struct crc32_write_args c_args  = {
+               .dest_buf           = args->buf,
+               .pid                = VIDTV_EIT_PID,
+               .dest_buf_sz        = args->buf_sz,
+       };
+       struct vidtv_psi_table_eit_event *event = args->eit->event;
+       struct vidtv_psi_desc *event_descriptor;
+       u32 crc = INITIAL_CRC;
+       u32 nbytes  = 0;
+
+       vidtv_psi_eit_table_update_sec_len(args->eit);
+
+       h_args.continuity_counter = args->continuity_counter;
+       h_args.crc                = &crc;
+
+       nbytes += vidtv_psi_table_header_write_into(&h_args);
+
+       psi_args.from               = &args->eit->transport_id;
+       psi_args.dest_offset        = args->offset + nbytes;
+       psi_args.continuity_counter = args->continuity_counter;
+       psi_args.crc                = &crc;
+
+       nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
+
+       /* skip both pointers at the end */
+       psi_args.len = sizeof(struct vidtv_psi_table_eit_event) -
+                      sizeof(struct vidtv_psi_desc *) -
+                      sizeof(struct vidtv_psi_table_eit_event *);
+       while (event) {
+               /* copy the events, if any */
+               psi_args.from = event;
+               psi_args.dest_offset = args->offset + nbytes;
+
+               nbytes += vidtv_psi_ts_psi_write_into(&psi_args);
+
+               event_descriptor = event->descriptor;
+
+               while (event_descriptor) {
+                       /* copy the event descriptors, if any */
+                       d_args.dest_offset        = args->offset + nbytes;
+                       d_args.desc               = event_descriptor;
+                       d_args.continuity_counter = args->continuity_counter;
+                       d_args.crc                = &crc;
+
+                       nbytes += vidtv_psi_desc_write_into(&d_args);
+
+                       event_descriptor = event_descriptor->next;
+               }
+
+               event = event->next;
+       }
+
+       c_args.dest_offset        = args->offset + nbytes;
+       c_args.crc                = cpu_to_be32(crc);
+       c_args.continuity_counter = args->continuity_counter;
+
+       /* Write the CRC at the end */
+       nbytes += table_section_crc32_write_into(&c_args);
+
+       return nbytes;
+}
+
+struct vidtv_psi_table_eit_event
+*vidtv_psi_eit_event_init(struct vidtv_psi_table_eit_event *head, u16 event_id)
+{
+       const u8 DURATION[] = {0x23, 0x59, 0x59}; /* BCD encoded */
+       struct vidtv_psi_table_eit_event *e;
+       struct timespec64 ts;
+       struct tm time;
+       int mjd, l;
+       __be16 mjd_be;
+
+       e = kzalloc(sizeof(*e), GFP_KERNEL);
+       if (!e)
+               return NULL;
+
+       e->event_id = cpu_to_be16(event_id);
+
+       ts = ktime_to_timespec64(ktime_get_real());
+       time64_to_tm(ts.tv_sec, 0, &time);
+
+       /* Convert date to Modified Julian Date - per EN 300 468 Annex C */
+       if (time.tm_mon < 2)
+               l = 1;
+       else
+               l = 0;
+
+       mjd = 14956 + time.tm_mday;
+       mjd += (time.tm_year - l) * 36525 / 100;
+       mjd += (time.tm_mon + 2 + l * 12) * 306001 / 10000;
+       mjd_be = cpu_to_be16(mjd);
+
+       /*
+        * Store MJD and hour/min/sec to the event.
+        *
+        * Let's make the event to start on a full hour
+        */
+       memcpy(e->start_time, &mjd_be, sizeof(mjd_be));
+       e->start_time[2] = bin2bcd(time.tm_hour);
+       e->start_time[3] = 0;
+       e->start_time[4] = 0;
+
+       /*
+        * TODO: for now, the event will last for a day. Should be
+        * enough for testing purposes, but if one runs the driver
+        * for more than that, the current event will become invalid.
+        * So, we need a better code here in order to change the start
+        * time once the event expires.
+        */
+       memcpy(e->duration, DURATION, sizeof(e->duration));
+
+       e->bitfield = cpu_to_be16(RUNNING << 13);
+
+       if (head) {
+               while (head->next)
+                       head = head->next;
+
+               head->next = e;
+       }
+
+       return e;
+}
+
+void vidtv_psi_eit_event_destroy(struct vidtv_psi_table_eit_event *e)
+{
+       struct vidtv_psi_table_eit_event *tmp_e  = NULL;
+       struct vidtv_psi_table_eit_event *curr_e = e;
+
+       while (curr_e) {
+               tmp_e  = curr_e;
+               curr_e = curr_e->next;
+               vidtv_psi_desc_destroy(tmp_e->descriptor);
+               kfree(tmp_e);
+       }
+}
+
+void vidtv_psi_eit_table_destroy(struct vidtv_psi_table_eit *eit)
+{
+       vidtv_psi_eit_event_destroy(eit->event);
+       kfree(eit);
+}
index 3f962cc78278561094f344c7cf152243078f45f7..340c9fb8d583e20fe4695411ee62f4c325805f7e 100644 (file)
@@ -6,10 +6,6 @@
  * technically be broken into one or more sections, we do not do this here,
  * hence 'table' and 'section' are interchangeable for vidtv.
  *
- * This code currently supports three tables: PAT, PMT and SDT. These are the
- * bare minimum to get userspace to recognize our MPEG transport stream. It can
- * be extended to support more PSI tables in the future.
- *
  * Copyright (C) 2020 Daniel W. S. Almeida
  */
 
@@ -17,7 +13,6 @@
 #define VIDTV_PSI_H
 
 #include <linux/types.h>
-#include <asm/byteorder.h>
 
 /*
  * all section lengths start immediately after the 'section_length' field
 #define PAT_LEN_UNTIL_LAST_SECTION_NUMBER 5
 #define PMT_LEN_UNTIL_PROGRAM_INFO_LENGTH 9
 #define SDT_LEN_UNTIL_RESERVED_FOR_FUTURE_USE 8
+#define NIT_LEN_UNTIL_NETWORK_DESCRIPTOR_LEN 7
+#define EIT_LEN_UNTIL_LAST_TABLE_ID 11
 #define MAX_SECTION_LEN 1021
+#define EIT_MAX_SECTION_LEN 4093 /* see ETSI 300 468 v.1.10.1 p. 26 */
 #define VIDTV_PAT_PID 0 /* mandated by the specs */
 #define VIDTV_SDT_PID 0x0011 /* mandated by the specs */
+#define VIDTV_NIT_PID 0x0010 /* mandated by the specs */
+#define VIDTV_EIT_PID 0x0012 /*mandated by the specs */
 
 enum vidtv_psi_descriptors {
        REGISTRATION_DESCRIPTOR = 0x05, /* See ISO/IEC 13818-1 section 2.6.8 */
+       NETWORK_NAME_DESCRIPTOR = 0x40, /* See ETSI EN 300 468 section 6.2.27 */
+       SERVICE_LIST_DESCRIPTOR = 0x41, /* See ETSI EN 300 468 section 6.2.35 */
        SERVICE_DESCRIPTOR = 0x48, /* See ETSI EN 300 468 section 6.2.33 */
+       SHORT_EVENT_DESCRIPTOR = 0x4d, /* See ETSI EN 300 468 section 6.2.37 */
 };
 
 enum vidtv_psi_stream_types {
        STREAM_PRIVATE_DATA = 0x06, /* see ISO/IEC 13818-1 2000 p. 48 */
 };
 
-/**
+/*
  * struct vidtv_psi_desc - A generic PSI descriptor type.
  * The descriptor length is an 8-bit field specifying the total number of bytes of the data portion
  * of the descriptor following the byte defining the value of this field.
@@ -52,7 +55,7 @@ struct vidtv_psi_desc {
        u8 data[];
 } __packed;
 
-/**
+/*
  * struct vidtv_psi_desc_service - Service descriptor.
  * See ETSI EN 300 468 section 6.2.33.
  */
@@ -68,7 +71,7 @@ struct vidtv_psi_desc_service {
        char *service_name;
 } __packed;
 
-/**
+/*
  * struct vidtv_psi_desc_registration - A registration descriptor.
  * See ISO/IEC 13818-1 section 2.6.8
  */
@@ -90,7 +93,56 @@ struct vidtv_psi_desc_registration {
        u8 additional_identification_info[];
 } __packed;
 
-/**
+/*
+ * struct vidtv_psi_desc_network_name - A network name descriptor
+ * see ETSI EN 300 468 v1.15.1 section 6.2.27
+ */
+struct vidtv_psi_desc_network_name {
+       struct vidtv_psi_desc *next;
+       u8 type;
+       u8 length;
+       char *network_name;
+} __packed;
+
+struct vidtv_psi_desc_service_list_entry {
+       __be16 service_id;
+       u8 service_type;
+       struct vidtv_psi_desc_service_list_entry *next;
+} __packed;
+
+/*
+ * struct vidtv_psi_desc_service_list - A service list descriptor
+ * see ETSI EN 300 468 v1.15.1 section 6.2.35
+ */
+struct vidtv_psi_desc_service_list {
+       struct vidtv_psi_desc *next;
+       u8 type;
+       u8 length;
+       struct vidtv_psi_desc_service_list_entry *service_list;
+} __packed;
+
+/*
+ * struct vidtv_psi_desc_short_event - A short event descriptor
+ * see ETSI EN 300 468 v1.15.1 section 6.2.37
+ */
+struct vidtv_psi_desc_short_event {
+       struct vidtv_psi_desc *next;
+       u8 type;
+       u8 length;
+       char *iso_language_code;
+       u8 event_name_len;
+       char *event_name;
+       u8 text_len;
+       char *text;
+} __packed;
+
+struct vidtv_psi_desc_short_event
+*vidtv_psi_short_event_desc_init(struct vidtv_psi_desc *head,
+                                char *iso_language_code,
+                                char *event_name,
+                                char *text);
+
+/*
  * struct vidtv_psi_table_header - A header that is present for all PSI tables.
  */
 struct vidtv_psi_table_header {
@@ -106,7 +158,7 @@ struct vidtv_psi_table_header {
        u8  last_section; /* last_section_number */
 } __packed;
 
-/**
+/*
  * struct vidtv_psi_table_pat_program - A single program in the PAT
  * See ISO/IEC 13818-1 : 2000 p.43
  */
@@ -116,17 +168,18 @@ struct vidtv_psi_table_pat_program {
        struct vidtv_psi_table_pat_program *next;
 } __packed;
 
-/**
+/*
  * struct vidtv_psi_table_pat - The Program Allocation Table (PAT)
  * See ISO/IEC 13818-1 : 2000 p.43
  */
 struct vidtv_psi_table_pat {
        struct vidtv_psi_table_header header;
-       u16 programs; /* Included by libdvbv5, not part of the table and not actually serialized */
+       u16 num_pat;
+       u16 num_pmt;
        struct vidtv_psi_table_pat_program *program;
 } __packed;
 
-/**
+/*
  * struct vidtv_psi_table_sdt_service - Represents a service in the SDT.
  * see ETSI EN 300 468 v1.15.1 section 5.2.3.
  */
@@ -140,7 +193,7 @@ struct vidtv_psi_table_sdt_service {
        struct vidtv_psi_table_sdt_service *next;
 } __packed;
 
-/**
+/*
  * struct vidtv_psi_table_sdt - Represents the Service Description Table
  * see ETSI EN 300 468 v1.15.1 section 5.2.3.
  */
@@ -152,7 +205,7 @@ struct vidtv_psi_table_sdt {
        struct vidtv_psi_table_sdt_service *service;
 } __packed;
 
-/**
+/*
  * enum service_running_status - Status of a SDT service.
  * see ETSI EN 300 468 v1.15.1 section 5.2.3 table 6.
  */
@@ -160,16 +213,17 @@ enum service_running_status {
        RUNNING = 0x4,
 };
 
-/**
+/*
  * enum service_type - The type of a SDT service.
  * see ETSI EN 300 468 v1.15.1 section 6.2.33, table 81.
  */
 enum service_type {
        /* see ETSI EN 300 468 v1.15.1 p. 77 */
        DIGITAL_TELEVISION_SERVICE = 0x1,
+       DIGITAL_RADIO_SOUND_SERVICE = 0X2,
 };
 
-/**
+/*
  * struct vidtv_psi_table_pmt_stream - A single stream in the PMT.
  * See ISO/IEC 13818-1 : 2000 p.46.
  */
@@ -181,7 +235,7 @@ struct vidtv_psi_table_pmt_stream {
        struct vidtv_psi_table_pmt_stream *next;
 } __packed;
 
-/**
+/*
  * struct vidtv_psi_table_pmt - The Program Map Table (PMT).
  * See ISO/IEC 13818-1 : 2000 p.46.
  */
@@ -290,6 +344,13 @@ struct vidtv_psi_desc_registration
                                  u8 *additional_ident_info,
                                  u32 additional_info_len);
 
+struct vidtv_psi_desc_network_name
+*vidtv_psi_network_name_desc_init(struct vidtv_psi_desc *head, char *network_name);
+
+struct vidtv_psi_desc_service_list
+*vidtv_psi_service_list_desc_init(struct vidtv_psi_desc *head,
+                                 struct vidtv_psi_desc_service_list_entry *entry);
+
 struct vidtv_psi_table_pat_program
 *vidtv_psi_pat_program_init(struct vidtv_psi_table_pat_program *head,
                            u16 service_id,
@@ -305,11 +366,14 @@ struct vidtv_psi_table_pat *vidtv_psi_pat_table_init(u16 transport_stream_id);
 struct vidtv_psi_table_pmt *vidtv_psi_pmt_table_init(u16 program_number,
                                                     u16 pcr_pid);
 
-struct vidtv_psi_table_sdt *vidtv_psi_sdt_table_init(u16 transport_stream_id);
+struct vidtv_psi_table_sdt *vidtv_psi_sdt_table_init(u16 network_id,
+                                                    u16 transport_stream_id);
 
 struct vidtv_psi_table_sdt_service*
 vidtv_psi_sdt_service_init(struct vidtv_psi_table_sdt_service *head,
-                          u16 service_id);
+                          u16 service_id,
+                          bool eit_schedule,
+                          bool eit_present_following);
 
 void
 vidtv_psi_desc_destroy(struct vidtv_psi_desc *desc);
@@ -413,7 +477,6 @@ struct vidtv_psi_desc *vidtv_psi_desc_clone(struct vidtv_psi_desc *desc);
  * vidtv_psi_create_sec_for_each_pat_entry - Create a PMT section for each
  * program found in the PAT
  * @pat: The PAT to look for programs.
- * @s: The stream loop (one or more streams)
  * @pcr_pid: packet ID for the PCR to be used for the program described in this
  * PMT section
  */
@@ -492,7 +555,7 @@ struct vidtv_psi_pat_write_args {
  * equal to the size of the PAT, since more space is needed for TS headers during TS
  * encapsulation.
  */
-u32 vidtv_psi_pat_write_into(struct vidtv_psi_pat_write_args args);
+u32 vidtv_psi_pat_write_into(struct vidtv_psi_pat_write_args *args);
 
 /**
  * struct vidtv_psi_sdt_write_args - Arguments for writing a SDT table
@@ -524,16 +587,18 @@ struct vidtv_psi_sdt_write_args {
  * equal to the size of the SDT, since more space is needed for TS headers during TS
  * encapsulation.
  */
-u32 vidtv_psi_sdt_write_into(struct vidtv_psi_sdt_write_args args);
+u32 vidtv_psi_sdt_write_into(struct vidtv_psi_sdt_write_args *args);
 
 /**
  * struct vidtv_psi_pmt_write_args - Arguments for writing a PMT section
  * @buf: The destination buffer.
  * @offset: The offset into the destination buffer.
  * @pmt: A pointer to the PMT.
+ * @pid: Program ID
  * @buf_sz: The size of the destination buffer.
  * @continuity_counter: A pointer to the CC. Incremented on every new packet.
- *
+ * @pcr_pid: The TS PID used for the PSI packets. All channels will share the
+ * same PCR.
  */
 struct vidtv_psi_pmt_write_args {
        char *buf;
@@ -557,7 +622,7 @@ struct vidtv_psi_pmt_write_args {
  * equal to the size of the PMT section, since more space is needed for TS headers
  * during TS encapsulation.
  */
-u32 vidtv_psi_pmt_write_into(struct vidtv_psi_pmt_write_args args);
+u32 vidtv_psi_pmt_write_into(struct vidtv_psi_pmt_write_args *args);
 
 /**
  * vidtv_psi_find_pmt_sec - Finds the PMT section for 'program_num'
@@ -574,4 +639,171 @@ struct vidtv_psi_table_pmt *vidtv_psi_find_pmt_sec(struct vidtv_psi_table_pmt **
 u16 vidtv_psi_get_pat_program_pid(struct vidtv_psi_table_pat_program *p);
 u16 vidtv_psi_pmt_stream_get_elem_pid(struct vidtv_psi_table_pmt_stream *s);
 
+/**
+ * struct vidtv_psi_table_transport - A entry in the TS loop for the NIT and/or other tables.
+ * See ETSI 300 468 section 5.2.1
+ * @transport_id: The TS ID being described
+ * @network_id: The network_id that contains the TS ID
+ * @bitfield: Contains the descriptor loop length
+ * @descriptor: A descriptor loop
+ * @next: Pointer to the next entry
+ *
+ */
+struct vidtv_psi_table_transport {
+       __be16 transport_id;
+       __be16 network_id;
+       __be16 bitfield; /* desc_len: 12, reserved: 4 */
+       struct vidtv_psi_desc *descriptor;
+       struct vidtv_psi_table_transport *next;
+} __packed;
+
+/**
+ * struct vidtv_psi_table_nit - A Network Information Table (NIT). See ETSI 300
+ * 468 section 5.2.1
+ * @header: A PSI table header
+ * @bitfield: Contains the network descriptor length
+ * @descriptor: A descriptor loop describing the network
+ * @bitfield2: Contains the transport stream loop length
+ * @transport: The transport stream loop
+ *
+ */
+struct vidtv_psi_table_nit {
+       struct vidtv_psi_table_header header;
+       __be16 bitfield; /* network_desc_len: 12, reserved:4 */
+       struct vidtv_psi_desc *descriptor;
+       __be16 bitfield2; /* ts_loop_len: 12, reserved: 4 */
+       struct vidtv_psi_table_transport *transport;
+} __packed;
+
+struct vidtv_psi_table_nit
+*vidtv_psi_nit_table_init(u16 network_id,
+                         u16 transport_stream_id,
+                         char *network_name,
+                         struct vidtv_psi_desc_service_list_entry *service_list);
+
+/**
+ * struct vidtv_psi_nit_write_args - Arguments for writing a NIT section
+ * @buf: The destination buffer.
+ * @offset: The offset into the destination buffer.
+ * @nit: A pointer to the NIT
+ * @buf_sz: The size of the destination buffer.
+ * @continuity_counter: A pointer to the CC. Incremented on every new packet.
+ *
+ */
+struct vidtv_psi_nit_write_args {
+       char *buf;
+       u32 offset;
+       struct vidtv_psi_table_nit *nit;
+       u32 buf_sz;
+       u8 *continuity_counter;
+};
+
+/**
+ * vidtv_psi_nit_write_into - Write NIT as MPEG-TS packets into a buffer.
+ * @args: an instance of struct vidtv_psi_nit_write_args
+ *
+ * This function writes the MPEG TS packets for a NIT table into a buffer.
+ * Calling code will usually generate the NIT via a call to its init function
+ * and thus is responsible for freeing it.
+ *
+ * Return: The number of bytes written into the buffer. This is NOT
+ * equal to the size of the NIT, since more space is needed for TS headers during TS
+ * encapsulation.
+ */
+u32 vidtv_psi_nit_write_into(struct vidtv_psi_nit_write_args *args);
+
+void vidtv_psi_nit_table_destroy(struct vidtv_psi_table_nit *nit);
+
+/*
+ * struct vidtv_psi_desc_short_event - A short event descriptor
+ * see ETSI EN 300 468 v1.15.1 section 6.2.37
+ */
+struct vidtv_psi_table_eit_event {
+       __be16 event_id;
+       u8 start_time[5];
+       u8 duration[3];
+       __be16 bitfield; /* desc_length: 12, free_CA_mode: 1, running_status: 1 */
+       struct vidtv_psi_desc *descriptor;
+       struct vidtv_psi_table_eit_event *next;
+} __packed;
+
+/*
+ * struct vidtv_psi_table_eit - A Event Information Table (EIT)
+ * See ETSI 300 468 section 5.2.4
+ */
+struct vidtv_psi_table_eit {
+       struct vidtv_psi_table_header header;
+       __be16 transport_id;
+       __be16 network_id;
+       u8 last_segment;
+       u8 last_table_id;
+       struct vidtv_psi_table_eit_event *event;
+} __packed;
+
+struct vidtv_psi_table_eit
+*vidtv_psi_eit_table_init(u16 network_id,
+                         u16 transport_stream_id,
+                         u16 service_id);
+
+/**
+ * struct vidtv_psi_eit_write_args - Arguments for writing an EIT section
+ * @buf: The destination buffer.
+ * @offset: The offset into the destination buffer.
+ * @eit: A pointer to the EIT
+ * @buf_sz: The size of the destination buffer.
+ * @continuity_counter: A pointer to the CC. Incremented on every new packet.
+ *
+ */
+struct vidtv_psi_eit_write_args {
+       char *buf;
+       u32 offset;
+       struct vidtv_psi_table_eit *eit;
+       u32 buf_sz;
+       u8 *continuity_counter;
+};
+
+/**
+ * vidtv_psi_eit_write_into - Write EIT as MPEG-TS packets into a buffer.
+ * @args: an instance of struct vidtv_psi_nit_write_args
+ *
+ * This function writes the MPEG TS packets for a EIT table into a buffer.
+ * Calling code will usually generate the EIT via a call to its init function
+ * and thus is responsible for freeing it.
+ *
+ * Return: The number of bytes written into the buffer. This is NOT
+ * equal to the size of the EIT, since more space is needed for TS headers during TS
+ * encapsulation.
+ */
+u32 vidtv_psi_eit_write_into(struct vidtv_psi_eit_write_args *args);
+
+void vidtv_psi_eit_table_destroy(struct vidtv_psi_table_eit *eit);
+
+/**
+ * vidtv_psi_eit_table_update_sec_len - Recompute and update the EIT section length.
+ * @eit: The EIT whose length is to be updated.
+ *
+ * This will traverse the table and accumulate the length of its components,
+ * which is then used to replace the 'section_length' field.
+ *
+ * If section_length > EIT_MAX_SECTION_LEN, the operation fails.
+ */
+void vidtv_psi_eit_table_update_sec_len(struct vidtv_psi_table_eit *eit);
+
+/**
+ * vidtv_psi_eit_event_assign - Assigns the event loop to the EIT.
+ * @eit: The EIT to assign to.
+ * @e: The event loop
+ *
+ * This will free the previous event loop in the table.
+ * This will assign ownership of the stream loop to the table, i.e. the table
+ * will free this stream loop when a call to its destroy function is made.
+ */
+void vidtv_psi_eit_event_assign(struct vidtv_psi_table_eit *eit,
+                               struct vidtv_psi_table_eit_event *e);
+
+struct vidtv_psi_table_eit_event
+*vidtv_psi_eit_event_init(struct vidtv_psi_table_eit_event *head, u16 event_id);
+
+void vidtv_psi_eit_event_destroy(struct vidtv_psi_table_eit_event *e);
+
 #endif // VIDTV_PSI_H
index a447ccbd68d5b595f29304b5ae1e6a1c21a52be2..ce7dd6cafc8b778da072821586b443afff7f1467 100644 (file)
 
 #define pr_fmt(fmt) KBUILD_MODNAME ":%s, %d: " fmt, __func__, __LINE__
 
-#include <linux/types.h>
-#include <linux/slab.h>
+#include <linux/bug.h>
 #include <linux/crc32.h>
-#include <linux/vmalloc.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
+#include <linux/fixp-arith.h>
 #include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
 #include <linux/printk.h>
 #include <linux/ratelimit.h>
-#include <linux/fixp-arith.h>
-
-#include <linux/math64.h>
-#include <asm/byteorder.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
 
-#include "vidtv_s302m.h"
-#include "vidtv_encoder.h"
 #include "vidtv_common.h"
+#include "vidtv_encoder.h"
+#include "vidtv_s302m.h"
 
 #define S302M_SAMPLING_RATE_HZ 48000
 #define PES_PRIVATE_STREAM_1 0xbd  /* PES: private_stream_1 */
@@ -79,8 +78,9 @@ struct tone_duration {
        int duration;
 };
 
-#define COMPASS 120            /* beats per minute (Allegro) */
-static const struct tone_duration beethoven_5th_symphony[] = {
+#define COMPASS 100 /* beats per minute */
+static const struct tone_duration beethoven_fur_elise[] = {
+       { NOTE_SILENT, 512},
        { NOTE_E_6, 128},  { NOTE_DS_6, 128}, { NOTE_E_6, 128},
        { NOTE_DS_6, 128}, { NOTE_E_6, 128},  { NOTE_B_5, 128},
        { NOTE_D_6, 128},  { NOTE_C_6, 128},  { NOTE_A_3, 128},
@@ -121,31 +121,36 @@ static const struct tone_duration beethoven_5th_symphony[] = {
        { NOTE_E_5, 128},  { NOTE_D_5, 128},  { NOTE_A_3, 128},
        { NOTE_E_4, 128},  { NOTE_A_4, 128},  { NOTE_E_4, 128},
        { NOTE_D_5, 128},  { NOTE_C_5, 128},  { NOTE_E_3, 128},
-       { NOTE_E_4, 128},  { NOTE_E_5, 255},  { NOTE_E_6, 128},
-       { NOTE_E_5, 128},  { NOTE_E_6, 128},  { NOTE_E_5, 255},
+       { NOTE_E_4, 128},  { NOTE_E_5, 128},  { NOTE_E_5, 128},
+       { NOTE_E_6, 128},  { NOTE_E_5, 128},  { NOTE_E_6, 128},
+       { NOTE_E_5, 128},  { NOTE_E_5, 128},  { NOTE_DS_5, 128},
+       { NOTE_E_5, 128},  { NOTE_DS_6, 128}, { NOTE_E_6, 128},
        { NOTE_DS_5, 128}, { NOTE_E_5, 128},  { NOTE_DS_6, 128},
-       { NOTE_E_6, 128},  { NOTE_DS_5, 128}, { NOTE_E_5, 128},
-       { NOTE_DS_6, 128}, { NOTE_E_6, 128},  { NOTE_DS_6, 128},
        { NOTE_E_6, 128},  { NOTE_DS_6, 128}, { NOTE_E_6, 128},
-       { NOTE_B_5, 128},  { NOTE_D_6, 128},  { NOTE_C_6, 128},
-       { NOTE_A_3, 128},  { NOTE_E_4, 128},  { NOTE_A_4, 128},
-       { NOTE_C_5, 128},  { NOTE_E_5, 128},  { NOTE_A_5, 128},
-       { NOTE_E_3, 128},  { NOTE_E_4, 128},  { NOTE_GS_4, 128},
-       { NOTE_E_5, 128},  { NOTE_GS_5, 128}, { NOTE_B_5, 128},
-       { NOTE_A_3, 128},  { NOTE_E_4, 128},  { NOTE_A_4, 128},
-       { NOTE_E_5, 128},  { NOTE_E_6, 128},  { NOTE_DS_6, 128},
+       { NOTE_DS_6, 128}, { NOTE_E_6, 128},  { NOTE_B_5, 128},
+       { NOTE_D_6, 128},  { NOTE_C_6, 128},  { NOTE_A_3, 128},
+       { NOTE_E_4, 128},  { NOTE_A_4, 128},  { NOTE_C_5, 128},
+       { NOTE_E_5, 128},  { NOTE_A_5, 128},  { NOTE_E_3, 128},
+       { NOTE_E_4, 128},  { NOTE_GS_4, 128}, { NOTE_E_5, 128},
+       { NOTE_GS_5, 128}, { NOTE_B_5, 128},  { NOTE_A_3, 128},
+       { NOTE_E_4, 128},  { NOTE_A_4, 128},  { NOTE_E_5, 128},
        { NOTE_E_6, 128},  { NOTE_DS_6, 128}, { NOTE_E_6, 128},
-       { NOTE_B_5, 128},  { NOTE_D_6, 128},  { NOTE_C_6, 128},
-       { NOTE_A_3, 128},  { NOTE_E_4, 128},  { NOTE_A_4, 128},
-       { NOTE_C_5, 128},  { NOTE_E_5, 128},  { NOTE_A_5, 128},
-       { NOTE_E_3, 128},  { NOTE_E_4, 128},  { NOTE_GS_4, 128},
-       { NOTE_E_5, 128},  { NOTE_C_6, 128},  { NOTE_B_5, 128},
-       { NOTE_C_5, 255},  { NOTE_C_5, 255},  { NOTE_SILENT, 512},
+       { NOTE_DS_6, 128}, { NOTE_E_6, 128},  { NOTE_B_5, 128},
+       { NOTE_D_6, 128},  { NOTE_C_6, 128},  { NOTE_A_3, 128},
+       { NOTE_E_4, 128},  { NOTE_A_4, 128},  { NOTE_C_5, 128},
+       { NOTE_E_5, 128},  { NOTE_A_5, 128},  { NOTE_E_3, 128},
+       { NOTE_E_4, 128},  { NOTE_GS_4, 128}, { NOTE_E_5, 128},
+       { NOTE_C_6, 128},  { NOTE_B_5, 128},  { NOTE_A_5, 512},
+       { NOTE_SILENT, 256},
 };
 
 static struct vidtv_access_unit *vidtv_s302m_access_unit_init(struct vidtv_access_unit *head)
 {
-       struct vidtv_access_unit *au = kzalloc(sizeof(*au), GFP_KERNEL);
+       struct vidtv_access_unit *au;
+
+       au = kzalloc(sizeof(*au), GFP_KERNEL);
+       if (!au)
+               return NULL;
 
        if (head) {
                while (head->next)
@@ -196,10 +201,10 @@ static void vidtv_s302m_alloc_au(struct vidtv_encoder *e)
 static void
 vidtv_s302m_compute_sample_count_from_video(struct vidtv_encoder *e)
 {
-       struct vidtv_access_unit *au = e->access_units;
        struct vidtv_access_unit *sync_au = e->sync->access_units;
-       u32 vau_duration_usecs;
+       struct vidtv_access_unit *au = e->access_units;
        u32 sample_duration_usecs;
+       u32 vau_duration_usecs;
        u32 s;
 
        vau_duration_usecs    = USEC_PER_SEC / e->sync->sampling_rate_hz;
@@ -230,36 +235,32 @@ static u16 vidtv_s302m_get_sample(struct vidtv_encoder *e)
 {
        u16 sample;
        int pos;
+       struct vidtv_s302m_ctx *ctx = e->ctx;
 
        if (!e->src_buf) {
                /*
                 * Simple tone generator: play the tones at the
-                * beethoven_5th_symphony array.
+                * beethoven_fur_elise array.
                 */
-               if (e->last_duration <= 0) {
-                       if (e->src_buf_offset >= ARRAY_SIZE(beethoven_5th_symphony))
+               if (ctx->last_duration <= 0) {
+                       if (e->src_buf_offset >= ARRAY_SIZE(beethoven_fur_elise))
                                e->src_buf_offset = 0;
 
-                       e->last_tone = beethoven_5th_symphony[e->src_buf_offset].note;
-                       e->last_duration = beethoven_5th_symphony[e->src_buf_offset].duration * S302M_SAMPLING_RATE_HZ / COMPASS / 5;
+                       ctx->last_tone = beethoven_fur_elise[e->src_buf_offset].note;
+                       ctx->last_duration = beethoven_fur_elise[e->src_buf_offset].duration *
+                                            S302M_SAMPLING_RATE_HZ / COMPASS / 5;
                        e->src_buf_offset++;
-                       e->note_offset = 0;
+                       ctx->note_offset = 0;
                } else {
-                       e->last_duration--;
+                       ctx->last_duration--;
                }
 
-               /* Handle silent */
-               if (!e->last_tone) {
-                       e->src_buf_offset = 0;
+               /* Handle pause notes */
+               if (!ctx->last_tone)
                        return 0x8000;
-               }
 
-               pos = (2 * PI * e->note_offset * e->last_tone / S302M_SAMPLING_RATE_HZ);
-
-               if (pos == 360)
-                       e->note_offset = 0;
-               else
-                       e->note_offset++;
+               pos = (2 * PI * ctx->note_offset * ctx->last_tone) / S302M_SAMPLING_RATE_HZ;
+               ctx->note_offset++;
 
                return (fixp_sin32(pos % (2 * PI)) >> 16) + 0x8000;
        }
@@ -289,9 +290,9 @@ static u16 vidtv_s302m_get_sample(struct vidtv_encoder *e)
 static u32 vidtv_s302m_write_frame(struct vidtv_encoder *e,
                                   u16 sample)
 {
-       u32 nbytes = 0;
-       struct vidtv_s302m_frame_16 f = {};
        struct vidtv_s302m_ctx *ctx = e->ctx;
+       struct vidtv_s302m_frame_16 f = {};
+       u32 nbytes = 0;
 
        /* from ffmpeg: see s302enc.c */
 
@@ -388,6 +389,8 @@ static void vidtv_s302m_write_frames(struct vidtv_encoder *e)
 
 static void *vidtv_s302m_encode(struct vidtv_encoder *e)
 {
+       struct vidtv_s302m_ctx *ctx = e->ctx;
+
        /*
         * According to SMPTE 302M, an audio access unit is specified as those
         * AES3 words that are associated with a corresponding video frame.
@@ -401,8 +404,6 @@ static void *vidtv_s302m_encode(struct vidtv_encoder *e)
         * ffmpeg
         */
 
-       struct vidtv_s302m_ctx *ctx = e->ctx;
-
        vidtv_s302m_access_unit_destroy(e);
        vidtv_s302m_alloc_au(e);
 
@@ -440,8 +441,13 @@ static u32 vidtv_s302m_clear(struct vidtv_encoder *e)
 struct vidtv_encoder
 *vidtv_s302m_encoder_init(struct vidtv_s302m_encoder_init_args args)
 {
-       struct vidtv_encoder *e = kzalloc(sizeof(*e), GFP_KERNEL);
        u32 priv_sz = sizeof(struct vidtv_s302m_ctx);
+       struct vidtv_s302m_ctx *ctx;
+       struct vidtv_encoder *e;
+
+       e = kzalloc(sizeof(*e), GFP_KERNEL);
+       if (!e)
+               return NULL;
 
        e->id = S302M;
 
@@ -453,14 +459,19 @@ struct vidtv_encoder
        e->encoder_buf_offset = 0;
 
        e->sample_count = 0;
-       e->last_duration = 0;
 
        e->src_buf = (args.src_buf) ? args.src_buf : NULL;
        e->src_buf_sz = (args.src_buf) ? args.src_buf_sz : 0;
        e->src_buf_offset = 0;
 
        e->is_video_encoder = false;
-       e->ctx = kzalloc(priv_sz, GFP_KERNEL);
+
+       ctx = kzalloc(priv_sz, GFP_KERNEL);
+       if (!ctx)
+               return NULL;
+
+       e->ctx = ctx;
+       ctx->last_duration = 0;
 
        e->encode = vidtv_s302m_encode;
        e->clear = vidtv_s302m_clear;
index eca5e3150ede081c1b77fdf5f9ec040d3c1abf2e..9cc94e4a8924b22f2f0c85939afe2d5160e786f7 100644 (file)
@@ -19,7 +19,6 @@
 #define VIDTV_S302M_H
 
 #include <linux/types.h>
-#include <asm/byteorder.h>
 
 #include "vidtv_encoder.h"
 
  * @enc: A pointer to the containing encoder structure.
  * @frame_index: The current frame in a block
  * @au_count: The total number of access units encoded up to now
+ * @last_duration: Duration of the tone currently being played
+ * @note_offset: Position at the music tone array
+ * @last_tone: Tone currently being played
  */
 struct vidtv_s302m_ctx {
        struct vidtv_encoder *enc;
        u32 frame_index;
        u32 au_count;
+       int last_duration;
+       unsigned int note_offset;
+       enum musical_notes last_tone;
 };
 
-/**
+/*
  * struct vidtv_smpte_s302m_es - s302m MPEG Elementary Stream header.
  *
  * See SMPTE 302M 2007 table 1.
index 190b9e4438dc61435b0767e0f3d69d78304dc172..ca4bb9c40b78ef12e6116965942cc36c3f536408 100644 (file)
@@ -9,14 +9,13 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ":%s, %d: " fmt, __func__, __LINE__
 
+#include <linux/math64.h>
 #include <linux/printk.h>
 #include <linux/ratelimit.h>
 #include <linux/types.h>
-#include <linux/math64.h>
-#include <asm/byteorder.h>
 
-#include "vidtv_ts.h"
 #include "vidtv_common.h"
+#include "vidtv_ts.h"
 
 static u32 vidtv_ts_write_pcr_bits(u8 *to, u32 to_offset, u64 pcr)
 {
index 83dcc9183b453948265ee62e3348c2d334d7fc2a..10838a2b8389d018dec14ae10828c0d008a73f1c 100644 (file)
@@ -11,7 +11,6 @@
 #define VIDTV_TS_H
 
 #include <linux/types.h>
-#include <asm/byteorder.h>
 
 #define TS_SYNC_BYTE 0x47
 #define TS_PACKET_LEN 188
@@ -54,7 +53,7 @@ struct vidtv_mpeg_ts {
  * @dest_offset: The byte offset into the buffer.
  * @pid: The TS PID for the PCR packets.
  * @buf_sz: The size of the buffer in bytes.
- * @countinuity_counter: The TS continuity_counter.
+ * @continuity_counter: The TS continuity_counter.
  * @pcr: A sample from the system clock.
  */
 struct pcr_write_args {
@@ -71,7 +70,7 @@ struct pcr_write_args {
  * @dest_buf: The buffer to write into.
  * @dest_offset: The byte offset into the buffer.
  * @buf_sz: The size of the buffer in bytes.
- * @countinuity_counter: The TS continuity_counter.
+ * @continuity_counter: The TS continuity_counter.
  */
 struct null_packet_write_args {
        void *dest_buf;
index 9bc49e099f6533be135aaee195ad3e426284a26b..14b6bc902ee13e2a54f88fcc41a76ec4922291de 100644 (file)
 #include <linux/errno.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
 #include <linux/slab.h>
 #include <linux/types.h>
+
 #include <media/dvb_frontend.h>
-#include <linux/printk.h>
-#include <linux/ratelimit.h>
 
 #include "vidtv_tuner.h"
 
index 8455b2d564b336bcd1e7d6c350725e6f06e0292a..fd55346a5c876a626484ea46c1af5269642b228b 100644 (file)
@@ -11,6 +11,7 @@
 #define VIDTV_TUNER_H
 
 #include <linux/types.h>
+
 #include <media/dvb_frontend.h>
 
 #define NUM_VALID_TUNER_FREQS 8
index a5ef9faf71c7d4f5a03ba7487ceb6c2d27198517..e7f0d4ae0f9601cbddc68d5667572b6ef4ca769b 100644 (file)
@@ -1176,8 +1176,10 @@ mptscsih_remove(struct pci_dev *pdev)
        MPT_SCSI_HOST           *hd;
        int sz1;
 
-       if((hd = shost_priv(host)) == NULL)
-               return;
+       if (host == NULL)
+               hd = NULL;
+       else
+               hd = shost_priv(host);
 
        mptscsih_shutdown(pdev);
 
@@ -1193,14 +1195,15 @@ mptscsih_remove(struct pci_dev *pdev)
            "Free'd ScsiLookup (%d) memory\n",
            ioc->name, sz1));
 
-       kfree(hd->info_kbuf);
+       if (hd)
+               kfree(hd->info_kbuf);
 
        /* NULL the Scsi_Host pointer
         */
        ioc->sh = NULL;
 
-       scsi_host_put(host);
-
+       if (host)
+               scsi_host_put(host);
        mpt_detach(pdev);
 
 }
index d5ce8082b0a0ac28a35310fb1a2705d586428d99..fafa8b0d809960e7867d6e60201f33d0a86a65d3 100644 (file)
@@ -474,7 +474,6 @@ source "drivers/misc/lis3lv02d/Kconfig"
 source "drivers/misc/altera-stapl/Kconfig"
 source "drivers/misc/mei/Kconfig"
 source "drivers/misc/vmw_vmci/Kconfig"
-source "drivers/misc/mic/Kconfig"
 source "drivers/misc/genwqe/Kconfig"
 source "drivers/misc/echo/Kconfig"
 source "drivers/misc/cxl/Kconfig"
index 2521359e8ef7b5f82498dba5c4329495b12ca98c..d23231e73330373cf13f81eff6ff4e5ce7ef4769 100644 (file)
@@ -46,7 +46,6 @@ obj-$(CONFIG_VMWARE_VMCI)     += vmw_vmci/
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)      += lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)             += sram.o
 obj-$(CONFIG_SRAM_EXEC)                += sram-exec.o
-obj-y                          += mic/
 obj-$(CONFIG_GENWQE)           += genwqe/
 obj-$(CONFIG_ECHO)             += echo/
 obj-$(CONFIG_CXL_BASE)         += cxl/
index 901e213daf40bac66b1491c1d52003e822328902..ada570f35a41acbfa9213f61f4194eb51776e9b9 100644 (file)
@@ -142,11 +142,10 @@ static void cb_fini(struct hl_device *hdev, struct hl_cb *cb)
 {
        if (cb->is_internal)
                gen_pool_free(hdev->internal_cb_pool,
-                               cb->kernel_address, cb->size);
+                               (uintptr_t)cb->kernel_address, cb->size);
        else
                hdev->asic_funcs->asic_dma_free_coherent(hdev, cb->size,
-                               (void *) (uintptr_t) cb->kernel_address,
-                               cb->bus_address);
+                               cb->kernel_address, cb->bus_address);
 
        kfree(cb);
 }
@@ -230,7 +229,7 @@ static struct hl_cb *hl_cb_alloc(struct hl_device *hdev, u32 cb_size,
                return NULL;
        }
 
-       cb->kernel_address = (u64) (uintptr_t) p;
+       cb->kernel_address = p;
        cb->size = cb_size;
 
        return cb;
@@ -509,7 +508,7 @@ int hl_cb_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma)
 
        vma->vm_private_data = cb;
 
-       rc = hdev->asic_funcs->cb_mmap(hdev, vma, (void *) cb->kernel_address,
+       rc = hdev->asic_funcs->cb_mmap(hdev, vma, cb->kernel_address,
                                        cb->bus_address, cb->size);
        if (rc) {
                spin_lock(&cb->lock);
index 20572224099a00342e85cb8ecee94566bc199162..783bbdcb1e6183f48c2370dd4efe239ef481a15e 100644 (file)
@@ -231,16 +231,16 @@ delete_cdev_device:
 
 static void device_cdev_sysfs_del(struct hl_device *hdev)
 {
-       /* device_release() won't be called so must free devices explicitly */
-       if (!hdev->cdev_sysfs_created) {
-               kfree(hdev->dev_ctrl);
-               kfree(hdev->dev);
-               return;
-       }
+       if (!hdev->cdev_sysfs_created)
+               goto put_devices;
 
        hl_sysfs_fini(hdev);
        cdev_device_del(&hdev->cdev_ctrl, hdev->dev_ctrl);
        cdev_device_del(&hdev->cdev, hdev->dev);
+
+put_devices:
+       put_device(hdev->dev);
+       put_device(hdev->dev_ctrl);
 }
 
 /*
@@ -1371,9 +1371,9 @@ sw_fini:
 early_fini:
        device_early_fini(hdev);
 free_dev_ctrl:
-       kfree(hdev->dev_ctrl);
+       put_device(hdev->dev_ctrl);
 free_dev:
-       kfree(hdev->dev);
+       put_device(hdev->dev);
 out_disabled:
        hdev->disabled = true;
        if (add_cdev_sysfs_on_err)
index 80d4d7385ffe7fb1443cad0b103f4cc0a2b21249..6ed974d2def0e6f8098622f132e092aeafcc6dfe 100644 (file)
@@ -452,7 +452,7 @@ struct hl_cb {
        struct list_head        pool_list;
        struct list_head        va_block_list;
        u64                     id;
-       u64                     kernel_address;
+       void                    *kernel_address;
        dma_addr_t              bus_address;
        u32                     mmap_size;
        u32                     size;
@@ -515,7 +515,7 @@ struct hl_hw_queue {
        struct hl_hw_sob        hw_sob[HL_RSVD_SOBS];
        struct hl_cs_job        **shadow_queue;
        enum hl_queue_type      queue_type;
-       u64                     kernel_address;
+       void                    *kernel_address;
        dma_addr_t              bus_address;
        u32                     pi;
        atomic_t                ci;
@@ -544,7 +544,7 @@ struct hl_hw_queue {
  */
 struct hl_cq {
        struct hl_device        *hdev;
-       u64                     kernel_address;
+       void                    *kernel_address;
        dma_addr_t              bus_address;
        u32                     cq_idx;
        u32                     hw_queue_id;
@@ -562,7 +562,7 @@ struct hl_cq {
  */
 struct hl_eq {
        struct hl_device        *hdev;
-       u64                     kernel_address;
+       void                    *kernel_address;
        dma_addr_t              bus_address;
        u32                     ci;
 };
@@ -757,7 +757,7 @@ struct hl_asic_funcs {
        u32 (*get_dma_desc_list_size)(struct hl_device *hdev,
                                        struct sg_table *sgt);
        void (*add_end_of_cb_packets)(struct hl_device *hdev,
-                                       u64 kernel_address, u32 len,
+                                       void *kernel_address, u32 len,
                                        u64 cq_addr, u32 cq_val, u32 msix_num,
                                        bool eb);
        void (*update_eq_ci)(struct hl_device *hdev, u32 val);
@@ -1382,13 +1382,13 @@ void hl_wreg(struct hl_device *hdev, u32 reg, u32 val);
        for (;;) { \
                /* Verify we read updates done by other cores or by device */ \
                mb(); \
-               (val) = *((u32 *) (uintptr_t) (addr)); \
+               (val) = *((u32 *)(addr)); \
                if (mem_written_by_device) \
                        (val) = le32_to_cpu(*(__le32 *) &(val)); \
                if (cond) \
                        break; \
                if (timeout_us && ktime_compare(ktime_get(), __timeout) > 0) { \
-                       (val) = *((u32 *) (uintptr_t) (addr)); \
+                       (val) = *((u32 *)(addr)); \
                        if (mem_written_by_device) \
                                (val) = le32_to_cpu(*(__le32 *) &(val)); \
                        break; \
index 5e66c98fb0d35bd8c86d4d2cbcbbfe3218ef329e..250cf9cefc060c505bd82b85585a2eec59d41ec3 100644 (file)
@@ -75,7 +75,7 @@ static void ext_and_hw_queue_submit_bd(struct hl_device *hdev,
 {
        struct hl_bd *bd;
 
-       bd = (struct hl_bd *) (uintptr_t) q->kernel_address;
+       bd = q->kernel_address;
        bd += hl_pi_2_offset(q->pi);
        bd->ctl = cpu_to_le32(ctl);
        bd->len = cpu_to_le32(len);
@@ -335,8 +335,7 @@ static void int_queue_schedule_job(struct hl_cs_job *job)
        bd.len = cpu_to_le32(job->job_cb_size);
        bd.ptr = cpu_to_le64((u64) (uintptr_t) job->user_cb);
 
-       pi = (__le64 *) (uintptr_t) (q->kernel_address +
-               ((q->pi & (q->int_queue_len - 1)) * sizeof(bd)));
+       pi = q->kernel_address + (q->pi & (q->int_queue_len - 1)) * sizeof(bd);
 
        q->pi++;
        q->pi &= ((q->int_queue_len << 1) - 1);
@@ -630,7 +629,7 @@ static int ext_and_cpu_queue_init(struct hl_device *hdev, struct hl_hw_queue *q,
        if (!p)
                return -ENOMEM;
 
-       q->kernel_address = (u64) (uintptr_t) p;
+       q->kernel_address = p;
 
        q->shadow_queue = kmalloc_array(HL_QUEUE_LENGTH,
                                        sizeof(*q->shadow_queue),
@@ -653,11 +652,11 @@ free_queue:
        if (is_cpu_queue)
                hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev,
                                        HL_QUEUE_SIZE_IN_BYTES,
-                                       (void *) (uintptr_t) q->kernel_address);
+                                       q->kernel_address);
        else
                hdev->asic_funcs->asic_dma_free_coherent(hdev,
                                        HL_QUEUE_SIZE_IN_BYTES,
-                                       (void *) (uintptr_t) q->kernel_address,
+                                       q->kernel_address,
                                        q->bus_address);
 
        return rc;
@@ -676,7 +675,7 @@ static int int_queue_init(struct hl_device *hdev, struct hl_hw_queue *q)
                return -EFAULT;
        }
 
-       q->kernel_address = (u64) (uintptr_t) p;
+       q->kernel_address = p;
        q->pi = 0;
        atomic_set(&q->ci, 0);
 
@@ -704,7 +703,7 @@ static int hw_queue_init(struct hl_device *hdev, struct hl_hw_queue *q)
        if (!p)
                return -ENOMEM;
 
-       q->kernel_address = (u64) (uintptr_t) p;
+       q->kernel_address = p;
 
        /* Make sure read/write pointers are initialized to start of queue */
        atomic_set(&q->ci, 0);
@@ -839,11 +838,11 @@ static void queue_fini(struct hl_device *hdev, struct hl_hw_queue *q)
        if (q->queue_type == QUEUE_TYPE_CPU)
                hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev,
                                        HL_QUEUE_SIZE_IN_BYTES,
-                                       (void *) (uintptr_t) q->kernel_address);
+                                       q->kernel_address);
        else
                hdev->asic_funcs->asic_dma_free_coherent(hdev,
                                        HL_QUEUE_SIZE_IN_BYTES,
-                                       (void *) (uintptr_t) q->kernel_address,
+                                       q->kernel_address,
                                        q->bus_address);
 }
 
index d20e40a53d70666954845bcd22f176a31d09fa40..de53fb5f978a8a026d2172794f85ab1343b3af06 100644 (file)
@@ -90,7 +90,7 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg)
                return IRQ_HANDLED;
        }
 
-       cq_base = (struct hl_cq_entry *) (uintptr_t) cq->kernel_address;
+       cq_base = cq->kernel_address;
 
        while (1) {
                bool entry_ready = ((le32_to_cpu(cq_base[cq->ci].data) &
@@ -152,7 +152,7 @@ irqreturn_t hl_irq_handler_eq(int irq, void *arg)
        struct hl_eq_entry *eq_base;
        struct hl_eqe_work *handle_eqe_work;
 
-       eq_base = (struct hl_eq_entry *) (uintptr_t) eq->kernel_address;
+       eq_base = eq->kernel_address;
 
        while (1) {
                bool entry_ready =
@@ -221,7 +221,7 @@ int hl_cq_init(struct hl_device *hdev, struct hl_cq *q, u32 hw_queue_id)
                return -ENOMEM;
 
        q->hdev = hdev;
-       q->kernel_address = (u64) (uintptr_t) p;
+       q->kernel_address = p;
        q->hw_queue_id = hw_queue_id;
        q->ci = 0;
        q->pi = 0;
@@ -242,7 +242,8 @@ int hl_cq_init(struct hl_device *hdev, struct hl_cq *q, u32 hw_queue_id)
 void hl_cq_fini(struct hl_device *hdev, struct hl_cq *q)
 {
        hdev->asic_funcs->asic_dma_free_coherent(hdev, HL_CQ_SIZE_IN_BYTES,
-                       (void *) (uintptr_t) q->kernel_address, q->bus_address);
+                                                q->kernel_address,
+                                                q->bus_address);
 }
 
 void hl_cq_reset(struct hl_device *hdev, struct hl_cq *q)
@@ -259,7 +260,7 @@ void hl_cq_reset(struct hl_device *hdev, struct hl_cq *q)
         * when the device is operational again
         */
 
-       memset((void *) (uintptr_t) q->kernel_address, 0, HL_CQ_SIZE_IN_BYTES);
+       memset(q->kernel_address, 0, HL_CQ_SIZE_IN_BYTES);
 }
 
 /**
@@ -282,7 +283,7 @@ int hl_eq_init(struct hl_device *hdev, struct hl_eq *q)
                return -ENOMEM;
 
        q->hdev = hdev;
-       q->kernel_address = (u64) (uintptr_t) p;
+       q->kernel_address = p;
        q->ci = 0;
 
        return 0;
@@ -302,7 +303,7 @@ void hl_eq_fini(struct hl_device *hdev, struct hl_eq *q)
 
        hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev,
                                        HL_EQ_SIZE_IN_BYTES,
-                                       (void *) (uintptr_t) q->kernel_address);
+                                       q->kernel_address);
 }
 
 void hl_eq_reset(struct hl_device *hdev, struct hl_eq *q)
@@ -316,5 +317,5 @@ void hl_eq_reset(struct hl_device *hdev, struct hl_eq *q)
         * when the device is operational again
         */
 
-       memset((void *) (uintptr_t) q->kernel_address, 0, HL_EQ_SIZE_IN_BYTES);
+       memset(q->kernel_address, 0, HL_EQ_SIZE_IN_BYTES);
 }
index 84227819e4d14d5d71064d902f20ae4e0dd876de..bfe223abf142672de217cdb6eaaccaeeaaf82f74 100644 (file)
@@ -1626,6 +1626,7 @@ static int vm_ctx_init_with_ranges(struct hl_ctx *ctx,
                        goto host_hpage_range_err;
                }
        } else {
+               kfree(ctx->host_huge_va_range);
                ctx->host_huge_va_range = ctx->host_va_range;
        }
 
index 5f65a1691551cd1bb5d815f36f82680a6a51835b..7ea6b4368a913319783be3dfd9094a5bdd576c86 100644 (file)
@@ -680,8 +680,7 @@ static int _gaudi_init_tpc_mem(struct hl_device *hdev,
        if (!cb)
                return -EFAULT;
 
-       init_tpc_mem_pkt = (struct packet_lin_dma *) (uintptr_t)
-                                       cb->kernel_address;
+       init_tpc_mem_pkt = cb->kernel_address;
        cb_size = sizeof(*init_tpc_mem_pkt);
        memset(init_tpc_mem_pkt, 0, cb_size);
 
@@ -3811,8 +3810,7 @@ static int gaudi_validate_cb(struct hl_device *hdev,
                u16 pkt_size;
                struct gaudi_packet *user_pkt;
 
-               user_pkt = (struct gaudi_packet *) (uintptr_t)
-                       (parser->user_cb->kernel_address + cb_parsed_length);
+               user_pkt = parser->user_cb->kernel_address + cb_parsed_length;
 
                pkt_id = (enum packet_id) (
                                (le64_to_cpu(user_pkt->header) &
@@ -4035,11 +4033,9 @@ static int gaudi_patch_cb(struct hl_device *hdev,
                u32 new_pkt_size = 0;
                struct gaudi_packet *user_pkt, *kernel_pkt;
 
-               user_pkt = (struct gaudi_packet *) (uintptr_t)
-                       (parser->user_cb->kernel_address + cb_parsed_length);
-               kernel_pkt = (struct gaudi_packet *) (uintptr_t)
-                       (parser->patched_cb->kernel_address +
-                                       cb_patched_cur_length);
+               user_pkt = parser->user_cb->kernel_address + cb_parsed_length;
+               kernel_pkt = parser->patched_cb->kernel_address +
+                                       cb_patched_cur_length;
 
                pkt_id = (enum packet_id) (
                                (le64_to_cpu(user_pkt->header) &
@@ -4155,8 +4151,8 @@ static int gaudi_parse_cb_mmu(struct hl_device *hdev,
         * The check that parser->user_cb_size <= parser->user_cb->size was done
         * in validate_queue_index().
         */
-       memcpy((void *) (uintptr_t) parser->patched_cb->kernel_address,
-               (void *) (uintptr_t) parser->user_cb->kernel_address,
+       memcpy(parser->patched_cb->kernel_address,
+               parser->user_cb->kernel_address,
                parser->user_cb_size);
 
        patched_cb_size = parser->patched_cb_size;
@@ -4290,7 +4286,7 @@ static int gaudi_cs_parser(struct hl_device *hdev, struct hl_cs_parser *parser)
 }
 
 static void gaudi_add_end_of_cb_packets(struct hl_device *hdev,
-                                       u64 kernel_address, u32 len,
+                                       void *kernel_address, u32 len,
                                        u64 cq_addr, u32 cq_val, u32 msi_vec,
                                        bool eb)
 {
@@ -4298,8 +4294,7 @@ static void gaudi_add_end_of_cb_packets(struct hl_device *hdev,
        struct packet_msg_prot *cq_pkt;
        u32 tmp;
 
-       cq_pkt = (struct packet_msg_prot *) (uintptr_t)
-               (kernel_address + len - (sizeof(struct packet_msg_prot) * 2));
+       cq_pkt = kernel_address + len - (sizeof(struct packet_msg_prot) * 2);
 
        tmp = FIELD_PREP(GAUDI_PKT_CTL_OPCODE_MASK, PACKET_MSG_PROT);
        tmp |= FIELD_PREP(GAUDI_PKT_CTL_MB_MASK, 1);
@@ -4342,7 +4337,7 @@ static int gaudi_memset_device_memory(struct hl_device *hdev, u64 addr,
        if (!cb)
                return -EFAULT;
 
-       lin_dma_pkt = (struct packet_lin_dma *) (uintptr_t) cb->kernel_address;
+       lin_dma_pkt = cb->kernel_address;
        memset(lin_dma_pkt, 0, sizeof(*lin_dma_pkt));
        cb_size = sizeof(*lin_dma_pkt);
 
@@ -4747,7 +4742,7 @@ static void gaudi_write_pte(struct hl_device *hdev, u64 addr, u64 val)
                        (addr - gaudi->hbm_bar_cur_addr));
 }
 
-static void gaudi_mmu_prepare_reg(struct hl_device *hdev, u64 reg, u32 asid)
+void gaudi_mmu_prepare_reg(struct hl_device *hdev, u64 reg, u32 asid)
 {
        /* mask to zero the MMBP and ASID bits */
        WREG32_AND(reg, ~0x7FF);
@@ -4915,9 +4910,6 @@ static void gaudi_mmu_prepare(struct hl_device *hdev, u32 asid)
        gaudi_mmu_prepare_reg(hdev, mmMME2_ACC_WBC, asid);
        gaudi_mmu_prepare_reg(hdev, mmMME3_ACC_WBC, asid);
 
-       gaudi_mmu_prepare_reg(hdev, mmPSOC_GLOBAL_CONF_TRACE_ARUSER, asid);
-       gaudi_mmu_prepare_reg(hdev, mmPSOC_GLOBAL_CONF_TRACE_AWUSER, asid);
-
        hdev->asic_funcs->set_clock_gating(hdev);
 
        mutex_unlock(&gaudi->clk_gate_mutex);
@@ -4954,8 +4946,8 @@ static int gaudi_send_job_on_qman0(struct hl_device *hdev,
 
        cb = job->patched_cb;
 
-       fence_pkt = (struct packet_msg_prot *) (uintptr_t) (cb->kernel_address +
-                       job->job_cb_size - sizeof(struct packet_msg_prot));
+       fence_pkt = cb->kernel_address +
+                       job->job_cb_size - sizeof(struct packet_msg_prot);
 
        tmp = FIELD_PREP(GAUDI_PKT_CTL_OPCODE_MASK, PACKET_MSG_PROT);
        tmp |= FIELD_PREP(GAUDI_PKT_CTL_EB_MASK, 1);
@@ -5444,6 +5436,8 @@ static void gaudi_handle_ecc_event(struct hl_device *hdev, u16 event_type,
                params.num_memories = 33;
                params.derr = true;
                params.disable_clock_gating = true;
+               extract_info_from_fw = false;
+               break;
        default:
                return;
        }
@@ -6386,7 +6380,7 @@ static void gaudi_gen_signal_cb(struct hl_device *hdev, void *data, u16 sob_id)
        struct packet_msg_short *pkt;
        u32 value, ctl;
 
-       pkt = (struct packet_msg_short *) (uintptr_t) cb->kernel_address;
+       pkt = cb->kernel_address;
        memset(pkt, 0, sizeof(*pkt));
 
        /* Inc by 1, Mode ADD */
@@ -6478,7 +6472,7 @@ static void gaudi_gen_wait_cb(struct hl_device *hdev, void *data, u16 sob_id,
                        u16 sob_val, u16 mon_id, u32 q_idx)
 {
        struct hl_cb *cb = (struct hl_cb *) data;
-       void *buf = (void *) (uintptr_t) cb->kernel_address;
+       void *buf = cb->kernel_address;
        u64 monitor_base, fence_addr = 0;
        u32 size = 0;
        u16 msg_addr_offset;
index 83ad2b0a3a617c16575452ff7f3ac6f0d71eb927..8eb598db81b298e745a96756feb9e97ab79c3339 100644 (file)
@@ -271,5 +271,6 @@ void gaudi_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq);
 int gaudi_debug_coresight(struct hl_device *hdev, void *data);
 void gaudi_halt_coresight(struct hl_device *hdev);
 int gaudi_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk);
+void gaudi_mmu_prepare_reg(struct hl_device *hdev, u64 reg, u32 asid);
 
 #endif /* GAUDIP_H_ */
index 881531d4d9da8540ecf32f4cca6f92f742c78a72..3d2b0f0f46507bc39560bc75ffa7ccabb26b6171 100644 (file)
@@ -623,6 +623,11 @@ static int gaudi_config_etr(struct hl_device *hdev,
                        return -EINVAL;
                }
 
+               gaudi_mmu_prepare_reg(hdev, mmPSOC_GLOBAL_CONF_TRACE_ARUSER,
+                                               hdev->compute_ctx->asid);
+               gaudi_mmu_prepare_reg(hdev, mmPSOC_GLOBAL_CONF_TRACE_AWUSER,
+                                               hdev->compute_ctx->asid);
+
                msb = upper_32_bits(input->buffer_address) >> 8;
                msb &= PSOC_GLOBAL_CONF_TRACE_ADDR_MSB_MASK;
                WREG32(mmPSOC_GLOBAL_CONF_TRACE_ADDR, msb);
index 5db52064ed9efdf8d5863e4b6d8b0853ba81d731..235d47b2420f5beb7f567d040abd1aad375f33bc 100644 (file)
@@ -2882,8 +2882,8 @@ static int goya_send_job_on_qman0(struct hl_device *hdev, struct hl_cs_job *job)
 
        cb = job->patched_cb;
 
-       fence_pkt = (struct packet_msg_prot *) (uintptr_t) (cb->kernel_address +
-                       job->job_cb_size - sizeof(struct packet_msg_prot));
+       fence_pkt = cb->kernel_address +
+                       job->job_cb_size - sizeof(struct packet_msg_prot);
 
        tmp = (PACKET_MSG_PROT << GOYA_PKT_CTL_OPCODE_SHIFT) |
                        (1 << GOYA_PKT_CTL_EB_SHIFT) |
@@ -3475,8 +3475,7 @@ static int goya_validate_cb(struct hl_device *hdev,
                u16 pkt_size;
                struct goya_packet *user_pkt;
 
-               user_pkt = (struct goya_packet *) (uintptr_t)
-                       (parser->user_cb->kernel_address + cb_parsed_length);
+               user_pkt = parser->user_cb->kernel_address + cb_parsed_length;
 
                pkt_id = (enum packet_id) (
                                (le64_to_cpu(user_pkt->header) &
@@ -3713,11 +3712,9 @@ static int goya_patch_cb(struct hl_device *hdev,
                u32 new_pkt_size = 0;
                struct goya_packet *user_pkt, *kernel_pkt;
 
-               user_pkt = (struct goya_packet *) (uintptr_t)
-                       (parser->user_cb->kernel_address + cb_parsed_length);
-               kernel_pkt = (struct goya_packet *) (uintptr_t)
-                       (parser->patched_cb->kernel_address +
-                                       cb_patched_cur_length);
+               user_pkt = parser->user_cb->kernel_address + cb_parsed_length;
+               kernel_pkt = parser->patched_cb->kernel_address +
+                                       cb_patched_cur_length;
 
                pkt_id = (enum packet_id) (
                                (le64_to_cpu(user_pkt->header) &
@@ -3841,8 +3838,8 @@ static int goya_parse_cb_mmu(struct hl_device *hdev,
         * The check that parser->user_cb_size <= parser->user_cb->size was done
         * in validate_queue_index().
         */
-       memcpy((void *) (uintptr_t) parser->patched_cb->kernel_address,
-               (void *) (uintptr_t) parser->user_cb->kernel_address,
+       memcpy(parser->patched_cb->kernel_address,
+               parser->user_cb->kernel_address,
                parser->user_cb_size);
 
        patched_cb_size = parser->patched_cb_size;
@@ -3974,15 +3971,14 @@ int goya_cs_parser(struct hl_device *hdev, struct hl_cs_parser *parser)
                return goya_parse_cb_no_mmu(hdev, parser);
 }
 
-void goya_add_end_of_cb_packets(struct hl_device *hdev, u64 kernel_address,
+void goya_add_end_of_cb_packets(struct hl_device *hdev, void *kernel_address,
                                u32 len, u64 cq_addr, u32 cq_val, u32 msix_vec,
                                bool eb)
 {
        struct packet_msg_prot *cq_pkt;
        u32 tmp;
 
-       cq_pkt = (struct packet_msg_prot *) (uintptr_t)
-               (kernel_address + len - (sizeof(struct packet_msg_prot) * 2));
+       cq_pkt = kernel_address + len - (sizeof(struct packet_msg_prot) * 2);
 
        tmp = (PACKET_MSG_PROT << GOYA_PKT_CTL_OPCODE_SHIFT) |
                        (1 << GOYA_PKT_CTL_EB_SHIFT) |
@@ -4746,7 +4742,7 @@ static int goya_memset_device_memory(struct hl_device *hdev, u64 addr, u64 size,
        if (!cb)
                return -ENOMEM;
 
-       lin_dma_pkt = (struct packet_lin_dma *) (uintptr_t) cb->kernel_address;
+       lin_dma_pkt = cb->kernel_address;
 
        do {
                memset(lin_dma_pkt, 0, sizeof(*lin_dma_pkt));
index 09b4006d4dc3397d2d766c0ba3985a672547c026..def86c75e0350b5903892b83cac8414bbb97628b 100644 (file)
@@ -217,7 +217,7 @@ int goya_resume(struct hl_device *hdev);
 void goya_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_entry);
 void *goya_get_events_stat(struct hl_device *hdev, bool aggregate, u32 *size);
 
-void goya_add_end_of_cb_packets(struct hl_device *hdev, u64 kernel_address,
+void goya_add_end_of_cb_packets(struct hl_device *hdev, void *kernel_address,
                                u32 len, u64 cq_addr, u32 cq_val, u32 msix_vec,
                                bool eb);
 int goya_cs_parser(struct hl_device *hdev, struct hl_cs_parser *parser);
index f395721060bd6b4cbe4e5fd607916375ae5ec862..46aed13f16b199d0964b8d13b959ee589bf64fe1 100644 (file)
@@ -421,7 +421,6 @@ enum axi_id {
 
 #define QM_ARB_ERR_MSG_EN_MASK         (\
                                        QM_ARB_ERR_MSG_EN_CHOISE_OVF_MASK |\
-                                       QM_ARB_ERR_MSG_EN_CHOISE_WDT_MASK |\
                                        QM_ARB_ERR_MSG_EN_AXI_LBW_ERR_MASK)
 
 #define PCIE_AUX_FLR_CTRL_HW_CTRL_MASK                               0x1
index c06581ffa7bd45dd9b7aa5b9c660aeb3d443a4e1..f5fd5b78660730ff2804477b16921fa1b8f80d94 100644 (file)
@@ -46,14 +46,4 @@ config INTEL_MEI_TXE
          Supported SoCs:
          Intel Bay Trail
 
-config INTEL_MEI_VIRTIO
-       tristate "Intel MEI interface emulation with virtio framework"
-       select INTEL_MEI
-       depends on X86 && PCI && VIRTIO_PCI
-       help
-         This module implements mei hw emulation over virtio transport.
-         The module will be called mei_virtio.
-         Enable this if your virtual machine supports virtual mei
-         device over virtio.
-
 source "drivers/misc/mei/hdcp/Kconfig"
index 52aefaab5c1b41e7744f760d78280b64d22a9526..f1c76f7ee8042ad792de183ae74cd4204d9a1be7 100644 (file)
@@ -22,9 +22,6 @@ obj-$(CONFIG_INTEL_MEI_TXE) += mei-txe.o
 mei-txe-objs := pci-txe.o
 mei-txe-objs += hw-txe.o
 
-obj-$(CONFIG_INTEL_MEI_VIRTIO) += mei-virtio.o
-mei-virtio-objs := hw-virtio.o
-
 mei-$(CONFIG_EVENT_TRACING) += mei-trace.o
 CFLAGS_mei-trace.o = -I$(src)
 
index 64143d4ec75830be59e3e7b4353a1fed3f44c595..9e08a9843bba49e9f0b1cd62fca4c143e8f109f0 100644 (file)
@@ -182,11 +182,11 @@ static inline u8 mei_cl_me_id(const struct mei_cl *cl)
  *
  * @cl: host client
  *
- * Return: mtu
+ * Return: mtu or 0 if client is not connected
  */
 static inline size_t mei_cl_mtu(const struct mei_cl *cl)
 {
-       return cl->me_cl->props.max_msg_length;
+       return cl->me_cl ? cl->me_cl->props.max_msg_length : 0;
 }
 
 /**
diff --git a/drivers/misc/mei/hw-virtio.c b/drivers/misc/mei/hw-virtio.c
deleted file mode 100644 (file)
index 899dc1c..0000000
+++ /dev/null
@@ -1,874 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Intel Management Engine Interface (Intel MEI) Linux driver
- * Copyright (c) 2018-2020, Intel Corporation.
- */
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/pm_runtime.h>
-#include <linux/scatterlist.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/virtio.h>
-#include <linux/virtio_config.h>
-#include <linux/virtio_ids.h>
-#include <linux/atomic.h>
-
-#include "mei_dev.h"
-#include "hbm.h"
-#include "client.h"
-
-#define MEI_VIRTIO_RPM_TIMEOUT 500
-/* ACRN virtio device types */
-#ifndef VIRTIO_ID_MEI
-#define VIRTIO_ID_MEI 0xFFFE /* virtio mei */
-#endif
-
-/**
- * struct mei_virtio_cfg - settings passed from the virtio backend
- * @buf_depth: read buffer depth in slots (4bytes)
- * @hw_ready: hw is ready for operation
- * @host_reset: synchronize reset with virtio backend
- * @reserved: reserved for alignment
- * @fw_status: FW status
- */
-struct mei_virtio_cfg {
-       u32 buf_depth;
-       u8 hw_ready;
-       u8 host_reset;
-       u8 reserved[2];
-       u32 fw_status[MEI_FW_STATUS_MAX];
-} __packed;
-
-struct mei_virtio_hw {
-       struct mei_device mdev;
-       char name[32];
-
-       struct virtqueue *in;
-       struct virtqueue *out;
-
-       bool host_ready;
-       struct work_struct intr_handler;
-
-       u32 *recv_buf;
-       u8 recv_rdy;
-       size_t recv_sz;
-       u32 recv_idx;
-       u32 recv_len;
-
-       /* send buffer */
-       atomic_t hbuf_ready;
-       const void *send_hdr;
-       const void *send_buf;
-
-       struct mei_virtio_cfg cfg;
-};
-
-#define to_virtio_hw(_dev) container_of(_dev, struct mei_virtio_hw, mdev)
-
-/**
- * mei_virtio_fw_status() - read status register of mei
- * @dev: mei device
- * @fw_status: fw status register values
- *
- * Return: always 0
- */
-static int mei_virtio_fw_status(struct mei_device *dev,
-                               struct mei_fw_status *fw_status)
-{
-       struct virtio_device *vdev = dev_to_virtio(dev->dev);
-
-       fw_status->count = MEI_FW_STATUS_MAX;
-       virtio_cread_bytes(vdev, offsetof(struct mei_virtio_cfg, fw_status),
-                          fw_status->status, sizeof(fw_status->status));
-       return 0;
-}
-
-/**
- * mei_virtio_pg_state() - translate internal pg state
- *   to the mei power gating state
- *   There is no power management in ACRN mode always return OFF
- * @dev: mei device
- *
- * Return:
- * * MEI_PG_OFF - if aliveness is on (always)
- * * MEI_PG_ON  - (never)
- */
-static inline enum mei_pg_state mei_virtio_pg_state(struct mei_device *dev)
-{
-       return MEI_PG_OFF;
-}
-
-/**
- * mei_virtio_hw_config() - configure hw dependent settings
- *
- * @dev: mei device
- *
- * Return: always 0
- */
-static int mei_virtio_hw_config(struct mei_device *dev)
-{
-       return 0;
-}
-
-/**
- * mei_virtio_hbuf_empty_slots() - counts write empty slots.
- * @dev: the device structure
- *
- * Return: always return frontend buf size if buffer is ready, 0 otherwise
- */
-static int mei_virtio_hbuf_empty_slots(struct mei_device *dev)
-{
-       struct mei_virtio_hw *hw = to_virtio_hw(dev);
-
-       return (atomic_read(&hw->hbuf_ready) == 1) ? hw->cfg.buf_depth : 0;
-}
-
-/**
- * mei_virtio_hbuf_is_ready() - checks if write buffer is ready
- * @dev: the device structure
- *
- * Return: true if hbuf is ready
- */
-static bool mei_virtio_hbuf_is_ready(struct mei_device *dev)
-{
-       struct mei_virtio_hw *hw = to_virtio_hw(dev);
-
-       return atomic_read(&hw->hbuf_ready) == 1;
-}
-
-/**
- * mei_virtio_hbuf_max_depth() - returns depth of FE write buffer.
- * @dev: the device structure
- *
- * Return: size of frontend write buffer in bytes
- */
-static u32 mei_virtio_hbuf_depth(const struct mei_device *dev)
-{
-       struct mei_virtio_hw *hw = to_virtio_hw(dev);
-
-       return hw->cfg.buf_depth;
-}
-
-/**
- * mei_virtio_intr_clear() - clear and stop interrupts
- * @dev: the device structure
- */
-static void mei_virtio_intr_clear(struct mei_device *dev)
-{
-       /*
-        * In our virtio solution, there are two types of interrupts,
-        * vq interrupt and config change interrupt.
-        *   1) start/reset rely on virtio config changed interrupt;
-        *   2) send/recv rely on virtio virtqueue interrupts.
-        * They are all virtual interrupts. So, we don't have corresponding
-        * operation to do here.
-        */
-}
-
-/**
- * mei_virtio_intr_enable() - enables mei BE virtqueues callbacks
- * @dev: the device structure
- */
-static void mei_virtio_intr_enable(struct mei_device *dev)
-{
-       struct mei_virtio_hw *hw = to_virtio_hw(dev);
-       struct virtio_device *vdev = dev_to_virtio(dev->dev);
-
-       virtio_config_enable(vdev);
-
-       virtqueue_enable_cb(hw->in);
-       virtqueue_enable_cb(hw->out);
-}
-
-/**
- * mei_virtio_intr_disable() - disables mei BE virtqueues callbacks
- *
- * @dev: the device structure
- */
-static void mei_virtio_intr_disable(struct mei_device *dev)
-{
-       struct mei_virtio_hw *hw = to_virtio_hw(dev);
-       struct virtio_device *vdev = dev_to_virtio(dev->dev);
-
-       virtio_config_disable(vdev);
-
-       virtqueue_disable_cb(hw->in);
-       virtqueue_disable_cb(hw->out);
-}
-
-/**
- * mei_virtio_synchronize_irq() - wait for pending IRQ handlers for all
- *     virtqueue
- * @dev: the device structure
- */
-static void mei_virtio_synchronize_irq(struct mei_device *dev)
-{
-       struct mei_virtio_hw *hw = to_virtio_hw(dev);
-
-       /*
-        * Now, all IRQ handlers are converted to workqueue.
-        * Change synchronize irq to flush this work.
-        */
-       flush_work(&hw->intr_handler);
-}
-
-static void mei_virtio_free_outbufs(struct mei_virtio_hw *hw)
-{
-       kfree(hw->send_hdr);
-       kfree(hw->send_buf);
-       hw->send_hdr = NULL;
-       hw->send_buf = NULL;
-}
-
-/**
- * mei_virtio_write_message() - writes a message to mei virtio back-end service.
- * @dev: the device structure
- * @hdr: mei header of message
- * @hdr_len: header length
- * @data: message payload will be written
- * @data_len: message payload length
- *
- * Return:
- * *  0: on success
- * * -EIO: if write has failed
- * * -ENOMEM: on memory allocation failure
- */
-static int mei_virtio_write_message(struct mei_device *dev,
-                                   const void *hdr, size_t hdr_len,
-                                   const void *data, size_t data_len)
-{
-       struct mei_virtio_hw *hw = to_virtio_hw(dev);
-       struct scatterlist sg[2];
-       const void *hbuf, *dbuf;
-       int ret;
-
-       if (WARN_ON(!atomic_add_unless(&hw->hbuf_ready, -1, 0)))
-               return -EIO;
-
-       hbuf = kmemdup(hdr, hdr_len, GFP_KERNEL);
-       hw->send_hdr = hbuf;
-
-       dbuf = kmemdup(data, data_len, GFP_KERNEL);
-       hw->send_buf = dbuf;
-
-       if (!hbuf || !dbuf) {
-               ret = -ENOMEM;
-               goto fail;
-       }
-
-       sg_init_table(sg, 2);
-       sg_set_buf(&sg[0], hbuf, hdr_len);
-       sg_set_buf(&sg[1], dbuf, data_len);
-
-       ret = virtqueue_add_outbuf(hw->out, sg, 2, hw, GFP_KERNEL);
-       if (ret) {
-               dev_err(dev->dev, "failed to add outbuf\n");
-               goto fail;
-       }
-
-       virtqueue_kick(hw->out);
-       return 0;
-fail:
-
-       mei_virtio_free_outbufs(hw);
-
-       return ret;
-}
-
-/**
- * mei_virtio_count_full_read_slots() - counts read full slots.
- * @dev: the device structure
- *
- * Return: -EOVERFLOW if overflow, otherwise filled slots count
- */
-static int mei_virtio_count_full_read_slots(struct mei_device *dev)
-{
-       struct mei_virtio_hw *hw = to_virtio_hw(dev);
-
-       if (hw->recv_idx > hw->recv_len)
-               return -EOVERFLOW;
-
-       return hw->recv_len - hw->recv_idx;
-}
-
-/**
- * mei_virtio_read_hdr() - Reads 32bit dword from mei virtio receive buffer
- *
- * @dev: the device structure
- *
- * Return: 32bit dword of receive buffer (u32)
- */
-static inline u32 mei_virtio_read_hdr(const struct mei_device *dev)
-{
-       struct mei_virtio_hw *hw = to_virtio_hw(dev);
-
-       WARN_ON(hw->cfg.buf_depth < hw->recv_idx + 1);
-
-       return hw->recv_buf[hw->recv_idx++];
-}
-
-static int mei_virtio_read(struct mei_device *dev, unsigned char *buffer,
-                          unsigned long len)
-{
-       struct mei_virtio_hw *hw = to_virtio_hw(dev);
-       u32 slots = mei_data2slots(len);
-
-       if (WARN_ON(hw->cfg.buf_depth < hw->recv_idx + slots))
-               return -EOVERFLOW;
-
-       /*
-        * Assumption: There is only one MEI message in recv_buf each time.
-        * Backend service need follow this rule too.
-        */
-       memcpy(buffer, hw->recv_buf + hw->recv_idx, len);
-       hw->recv_idx += slots;
-
-       return 0;
-}
-
-static bool mei_virtio_pg_is_enabled(struct mei_device *dev)
-{
-       return false;
-}
-
-static bool mei_virtio_pg_in_transition(struct mei_device *dev)
-{
-       return false;
-}
-
-static void mei_virtio_add_recv_buf(struct mei_virtio_hw *hw)
-{
-       struct scatterlist sg;
-
-       if (hw->recv_rdy) /* not needed */
-               return;
-
-       /* refill the recv_buf to IN virtqueue to get next message */
-       sg_init_one(&sg, hw->recv_buf, mei_slots2data(hw->cfg.buf_depth));
-       hw->recv_len = 0;
-       hw->recv_idx = 0;
-       hw->recv_rdy = 1;
-       virtqueue_add_inbuf(hw->in, &sg, 1, hw->recv_buf, GFP_KERNEL);
-       virtqueue_kick(hw->in);
-}
-
-/**
- * mei_virtio_hw_is_ready() - check whether the BE(hw) has turned ready
- * @dev: mei device
- * Return: bool
- */
-static bool mei_virtio_hw_is_ready(struct mei_device *dev)
-{
-       struct mei_virtio_hw *hw = to_virtio_hw(dev);
-       struct virtio_device *vdev = dev_to_virtio(dev->dev);
-
-       virtio_cread(vdev, struct mei_virtio_cfg,
-                    hw_ready, &hw->cfg.hw_ready);
-
-       dev_dbg(dev->dev, "hw ready %d\n", hw->cfg.hw_ready);
-
-       return hw->cfg.hw_ready;
-}
-
-/**
- * mei_virtio_hw_reset - resets virtio hw.
- *
- * @dev: the device structure
- * @intr_enable: virtio use data/config callbacks
- *
- * Return: 0 on success an error code otherwise
- */
-static int mei_virtio_hw_reset(struct mei_device *dev, bool intr_enable)
-{
-       struct mei_virtio_hw *hw = to_virtio_hw(dev);
-       struct virtio_device *vdev = dev_to_virtio(dev->dev);
-
-       dev_dbg(dev->dev, "hw reset\n");
-
-       dev->recvd_hw_ready = false;
-       hw->host_ready = false;
-       atomic_set(&hw->hbuf_ready, 0);
-       hw->recv_len = 0;
-       hw->recv_idx = 0;
-
-       hw->cfg.host_reset = 1;
-       virtio_cwrite(vdev, struct mei_virtio_cfg,
-                     host_reset, &hw->cfg.host_reset);
-
-       mei_virtio_hw_is_ready(dev);
-
-       if (intr_enable)
-               mei_virtio_intr_enable(dev);
-
-       return 0;
-}
-
-/**
- * mei_virtio_hw_reset_release() - release device from the reset
- * @dev: the device structure
- */
-static void mei_virtio_hw_reset_release(struct mei_device *dev)
-{
-       struct mei_virtio_hw *hw = to_virtio_hw(dev);
-       struct virtio_device *vdev = dev_to_virtio(dev->dev);
-
-       dev_dbg(dev->dev, "hw reset release\n");
-       hw->cfg.host_reset = 0;
-       virtio_cwrite(vdev, struct mei_virtio_cfg,
-                     host_reset, &hw->cfg.host_reset);
-}
-
-/**
- * mei_virtio_hw_ready_wait() - wait until the virtio(hw) has turned ready
- *  or timeout is reached
- * @dev: mei device
- *
- * Return: 0 on success, error otherwise
- */
-static int mei_virtio_hw_ready_wait(struct mei_device *dev)
-{
-       mutex_unlock(&dev->device_lock);
-       wait_event_timeout(dev->wait_hw_ready,
-                          dev->recvd_hw_ready,
-                          mei_secs_to_jiffies(MEI_HW_READY_TIMEOUT));
-       mutex_lock(&dev->device_lock);
-       if (!dev->recvd_hw_ready) {
-               dev_err(dev->dev, "wait hw ready failed\n");
-               return -ETIMEDOUT;
-       }
-
-       dev->recvd_hw_ready = false;
-       return 0;
-}
-
-/**
- * mei_virtio_hw_start() - hw start routine
- * @dev: mei device
- *
- * Return: 0 on success, error otherwise
- */
-static int mei_virtio_hw_start(struct mei_device *dev)
-{
-       struct mei_virtio_hw *hw = to_virtio_hw(dev);
-       int ret;
-
-       dev_dbg(dev->dev, "hw start\n");
-       mei_virtio_hw_reset_release(dev);
-
-       ret = mei_virtio_hw_ready_wait(dev);
-       if (ret)
-               return ret;
-
-       mei_virtio_add_recv_buf(hw);
-       atomic_set(&hw->hbuf_ready, 1);
-       dev_dbg(dev->dev, "hw is ready\n");
-       hw->host_ready = true;
-
-       return 0;
-}
-
-/**
- * mei_virtio_host_is_ready() - check whether the FE has turned ready
- * @dev: mei device
- *
- * Return: bool
- */
-static bool mei_virtio_host_is_ready(struct mei_device *dev)
-{
-       struct mei_virtio_hw *hw = to_virtio_hw(dev);
-
-       dev_dbg(dev->dev, "host ready %d\n", hw->host_ready);
-
-       return hw->host_ready;
-}
-
-/**
- * mei_virtio_data_in() - The callback of recv virtqueue of virtio mei
- * @vq: receiving virtqueue
- */
-static void mei_virtio_data_in(struct virtqueue *vq)
-{
-       struct mei_virtio_hw *hw = vq->vdev->priv;
-
-       /* disable interrupts (enabled again from in the interrupt worker) */
-       virtqueue_disable_cb(hw->in);
-
-       schedule_work(&hw->intr_handler);
-}
-
-/**
- * mei_virtio_data_out() - The callback of send virtqueue of virtio mei
- * @vq: transmitting virtqueue
- */
-static void mei_virtio_data_out(struct virtqueue *vq)
-{
-       struct mei_virtio_hw *hw = vq->vdev->priv;
-
-       schedule_work(&hw->intr_handler);
-}
-
-static void mei_virtio_intr_handler(struct work_struct *work)
-{
-       struct mei_virtio_hw *hw =
-               container_of(work, struct mei_virtio_hw, intr_handler);
-       struct mei_device *dev = &hw->mdev;
-       LIST_HEAD(complete_list);
-       s32 slots;
-       int rets = 0;
-       void *data;
-       unsigned int len;
-
-       mutex_lock(&dev->device_lock);
-
-       if (dev->dev_state == MEI_DEV_DISABLED) {
-               dev_warn(dev->dev, "Interrupt in disabled state.\n");
-               mei_virtio_intr_disable(dev);
-               goto end;
-       }
-
-       /* check if ME wants a reset */
-       if (!mei_hw_is_ready(dev) && dev->dev_state != MEI_DEV_RESETTING) {
-               dev_warn(dev->dev, "BE service not ready: resetting.\n");
-               schedule_work(&dev->reset_work);
-               goto end;
-       }
-
-       /* check if we need to start the dev */
-       if (!mei_host_is_ready(dev)) {
-               if (mei_hw_is_ready(dev)) {
-                       dev_dbg(dev->dev, "we need to start the dev.\n");
-                       dev->recvd_hw_ready = true;
-                       wake_up(&dev->wait_hw_ready);
-               } else {
-                       dev_warn(dev->dev, "Spurious Interrupt\n");
-               }
-               goto end;
-       }
-
-       /* read */
-       if (hw->recv_rdy) {
-               data = virtqueue_get_buf(hw->in, &len);
-               if (!data || !len) {
-                       dev_dbg(dev->dev, "No data %d", len);
-               } else {
-                       dev_dbg(dev->dev, "data_in %d\n", len);
-                       WARN_ON(data != hw->recv_buf);
-                       hw->recv_len = mei_data2slots(len);
-                       hw->recv_rdy = 0;
-               }
-       }
-
-       /* write */
-       if (!atomic_read(&hw->hbuf_ready)) {
-               if (!virtqueue_get_buf(hw->out, &len)) {
-                       dev_warn(dev->dev, "Failed to getbuf\n");
-               } else {
-                       mei_virtio_free_outbufs(hw);
-                       atomic_inc(&hw->hbuf_ready);
-               }
-       }
-
-       /* check slots available for reading */
-       slots = mei_count_full_read_slots(dev);
-       while (slots > 0) {
-               dev_dbg(dev->dev, "slots to read = %08x\n", slots);
-               rets = mei_irq_read_handler(dev, &complete_list, &slots);
-
-               if (rets &&
-                   (dev->dev_state != MEI_DEV_RESETTING &&
-                    dev->dev_state != MEI_DEV_POWER_DOWN)) {
-                       dev_err(dev->dev, "mei_irq_read_handler ret = %d.\n",
-                               rets);
-                       schedule_work(&dev->reset_work);
-                       goto end;
-               }
-       }
-
-       dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
-
-       mei_irq_write_handler(dev, &complete_list);
-
-       dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
-
-       mei_irq_compl_handler(dev, &complete_list);
-
-       mei_virtio_add_recv_buf(hw);
-
-end:
-       if (dev->dev_state != MEI_DEV_DISABLED) {
-               if (!virtqueue_enable_cb(hw->in))
-                       schedule_work(&hw->intr_handler);
-       }
-
-       mutex_unlock(&dev->device_lock);
-}
-
-static void mei_virtio_config_changed(struct virtio_device *vdev)
-{
-       struct mei_virtio_hw *hw = vdev->priv;
-       struct mei_device *dev = &hw->mdev;
-
-       virtio_cread(vdev, struct mei_virtio_cfg,
-                    hw_ready, &hw->cfg.hw_ready);
-
-       if (dev->dev_state == MEI_DEV_DISABLED) {
-               dev_dbg(dev->dev, "disabled state don't start\n");
-               return;
-       }
-
-       /* Run intr handler once to handle reset notify */
-       schedule_work(&hw->intr_handler);
-}
-
-static void mei_virtio_remove_vqs(struct virtio_device *vdev)
-{
-       struct mei_virtio_hw *hw = vdev->priv;
-
-       virtqueue_detach_unused_buf(hw->in);
-       hw->recv_len = 0;
-       hw->recv_idx = 0;
-       hw->recv_rdy = 0;
-
-       virtqueue_detach_unused_buf(hw->out);
-
-       mei_virtio_free_outbufs(hw);
-
-       vdev->config->del_vqs(vdev);
-}
-
-/*
- * There are two virtqueues, one is for send and another is for recv.
- */
-static int mei_virtio_init_vqs(struct mei_virtio_hw *hw,
-                              struct virtio_device *vdev)
-{
-       struct virtqueue *vqs[2];
-
-       vq_callback_t *cbs[] = {
-               mei_virtio_data_in,
-               mei_virtio_data_out,
-       };
-       static const char * const names[] = {
-               "in",
-               "out",
-       };
-       int ret;
-
-       ret = virtio_find_vqs(vdev, 2, vqs, cbs, names, NULL);
-       if (ret)
-               return ret;
-
-       hw->in = vqs[0];
-       hw->out = vqs[1];
-
-       return 0;
-}
-
-static const struct mei_hw_ops mei_virtio_ops = {
-       .fw_status = mei_virtio_fw_status,
-       .pg_state  = mei_virtio_pg_state,
-
-       .host_is_ready = mei_virtio_host_is_ready,
-
-       .hw_is_ready = mei_virtio_hw_is_ready,
-       .hw_reset = mei_virtio_hw_reset,
-       .hw_config = mei_virtio_hw_config,
-       .hw_start = mei_virtio_hw_start,
-
-       .pg_in_transition = mei_virtio_pg_in_transition,
-       .pg_is_enabled = mei_virtio_pg_is_enabled,
-
-       .intr_clear = mei_virtio_intr_clear,
-       .intr_enable = mei_virtio_intr_enable,
-       .intr_disable = mei_virtio_intr_disable,
-       .synchronize_irq = mei_virtio_synchronize_irq,
-
-       .hbuf_free_slots = mei_virtio_hbuf_empty_slots,
-       .hbuf_is_ready = mei_virtio_hbuf_is_ready,
-       .hbuf_depth = mei_virtio_hbuf_depth,
-
-       .write = mei_virtio_write_message,
-
-       .rdbuf_full_slots = mei_virtio_count_full_read_slots,
-       .read_hdr = mei_virtio_read_hdr,
-       .read = mei_virtio_read,
-};
-
-static int mei_virtio_probe(struct virtio_device *vdev)
-{
-       struct mei_virtio_hw *hw;
-       int ret;
-
-       hw = devm_kzalloc(&vdev->dev, sizeof(*hw), GFP_KERNEL);
-       if (!hw)
-               return -ENOMEM;
-
-       vdev->priv = hw;
-
-       INIT_WORK(&hw->intr_handler, mei_virtio_intr_handler);
-
-       ret = mei_virtio_init_vqs(hw, vdev);
-       if (ret)
-               goto vqs_failed;
-
-       virtio_cread(vdev, struct mei_virtio_cfg,
-                    buf_depth, &hw->cfg.buf_depth);
-
-       hw->recv_buf = kzalloc(mei_slots2data(hw->cfg.buf_depth), GFP_KERNEL);
-       if (!hw->recv_buf) {
-               ret = -ENOMEM;
-               goto hbuf_failed;
-       }
-       atomic_set(&hw->hbuf_ready, 0);
-
-       virtio_device_ready(vdev);
-
-       mei_device_init(&hw->mdev, &vdev->dev, &mei_virtio_ops);
-
-       pm_runtime_get_noresume(&vdev->dev);
-       pm_runtime_set_active(&vdev->dev);
-       pm_runtime_enable(&vdev->dev);
-
-       ret = mei_start(&hw->mdev);
-       if (ret)
-               goto mei_start_failed;
-
-       pm_runtime_set_autosuspend_delay(&vdev->dev, MEI_VIRTIO_RPM_TIMEOUT);
-       pm_runtime_use_autosuspend(&vdev->dev);
-
-       ret = mei_register(&hw->mdev, &vdev->dev);
-       if (ret)
-               goto mei_failed;
-
-       pm_runtime_put(&vdev->dev);
-
-       return 0;
-
-mei_failed:
-       mei_stop(&hw->mdev);
-mei_start_failed:
-       mei_cancel_work(&hw->mdev);
-       mei_disable_interrupts(&hw->mdev);
-       kfree(hw->recv_buf);
-hbuf_failed:
-       vdev->config->del_vqs(vdev);
-vqs_failed:
-       return ret;
-}
-
-static int __maybe_unused mei_virtio_pm_runtime_idle(struct device *device)
-{
-       struct virtio_device *vdev = dev_to_virtio(device);
-       struct mei_virtio_hw *hw = vdev->priv;
-
-       dev_dbg(&vdev->dev, "rpm: mei_virtio : runtime_idle\n");
-
-       if (!hw)
-               return -ENODEV;
-
-       if (mei_write_is_idle(&hw->mdev))
-               pm_runtime_autosuspend(device);
-
-       return -EBUSY;
-}
-
-static int __maybe_unused mei_virtio_pm_runtime_suspend(struct device *device)
-{
-       return 0;
-}
-
-static int __maybe_unused mei_virtio_pm_runtime_resume(struct device *device)
-{
-       return 0;
-}
-
-static int __maybe_unused mei_virtio_freeze(struct virtio_device *vdev)
-{
-       struct mei_virtio_hw *hw = vdev->priv;
-
-       dev_dbg(&vdev->dev, "freeze\n");
-
-       if (!hw)
-               return -ENODEV;
-
-       mei_stop(&hw->mdev);
-       mei_disable_interrupts(&hw->mdev);
-       cancel_work_sync(&hw->intr_handler);
-       vdev->config->reset(vdev);
-       mei_virtio_remove_vqs(vdev);
-
-       return 0;
-}
-
-static int __maybe_unused mei_virtio_restore(struct virtio_device *vdev)
-{
-       struct mei_virtio_hw *hw = vdev->priv;
-       int ret;
-
-       dev_dbg(&vdev->dev, "restore\n");
-
-       if (!hw)
-               return -ENODEV;
-
-       ret = mei_virtio_init_vqs(hw, vdev);
-       if (ret)
-               return ret;
-
-       virtio_device_ready(vdev);
-
-       ret = mei_restart(&hw->mdev);
-       if (ret)
-               return ret;
-
-       /* Start timer if stopped in suspend */
-       schedule_delayed_work(&hw->mdev.timer_work, HZ);
-
-       return 0;
-}
-
-static const struct dev_pm_ops mei_virtio_pm_ops = {
-       SET_RUNTIME_PM_OPS(mei_virtio_pm_runtime_suspend,
-                          mei_virtio_pm_runtime_resume,
-                          mei_virtio_pm_runtime_idle)
-};
-
-static void mei_virtio_remove(struct virtio_device *vdev)
-{
-       struct mei_virtio_hw *hw = vdev->priv;
-
-       mei_stop(&hw->mdev);
-       mei_disable_interrupts(&hw->mdev);
-       cancel_work_sync(&hw->intr_handler);
-       mei_deregister(&hw->mdev);
-       vdev->config->reset(vdev);
-       mei_virtio_remove_vqs(vdev);
-       kfree(hw->recv_buf);
-       pm_runtime_disable(&vdev->dev);
-}
-
-static struct virtio_device_id id_table[] = {
-       { VIRTIO_ID_MEI, VIRTIO_DEV_ANY_ID },
-       { }
-};
-
-static struct virtio_driver mei_virtio_driver = {
-       .id_table = id_table,
-       .probe = mei_virtio_probe,
-       .remove = mei_virtio_remove,
-       .config_changed = mei_virtio_config_changed,
-       .driver = {
-               .name = KBUILD_MODNAME,
-               .owner = THIS_MODULE,
-               .pm = &mei_virtio_pm_ops,
-       },
-#ifdef CONFIG_PM_SLEEP
-       .freeze = mei_virtio_freeze,
-       .restore = mei_virtio_restore,
-#endif
-};
-
-module_virtio_driver(mei_virtio_driver);
-MODULE_DEVICE_TABLE(virtio, id_table);
-MODULE_DESCRIPTION("Virtio MEI frontend driver");
-MODULE_LICENSE("GPL v2");
index 8bac86c4d86b778a4554f5a6c3ecc34a7fe5f587..df2fb9520dd8d03cdbc422243f37f5f737e4ba0a 100644 (file)
@@ -224,7 +224,7 @@ struct mei_ext_hdr {
        u8 type;
        u8 length;
        u8 ext_payload[2];
-       u8 hdr[0];
+       u8 hdr[];
 };
 
 /**
@@ -238,7 +238,7 @@ struct mei_ext_meta_hdr {
        u8 count;
        u8 size;
        u8 reserved[2];
-       struct mei_ext_hdr hdrs[0];
+       struct mei_ext_hdr hdrs[];
 };
 
 /*
@@ -308,7 +308,7 @@ struct mei_msg_hdr {
        u32 dma_ring:1;
        u32 internal:1;
        u32 msg_complete:1;
-       u32 extension[0];
+       u32 extension[];
 } __packed;
 
 /* The length is up to 9 bits */
diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig
deleted file mode 100644 (file)
index 8a7c2c5..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-menu "Intel MIC & related support"
-
-config INTEL_MIC_BUS
-       tristate "Intel MIC Bus Driver"
-       depends on 64BIT && PCI && X86
-       select DMA_OPS
-       help
-         This option is selected by any driver which registers a
-         device or driver on the MIC Bus, such as CONFIG_INTEL_MIC_HOST,
-         CONFIG_INTEL_MIC_CARD, CONFIG_INTEL_MIC_X100_DMA etc.
-
-         If you are building a host/card kernel with an Intel MIC device
-         then say M (recommended) or Y, else say N. If unsure say N.
-
-         More information about the Intel MIC family as well as the Linux
-         OS and tools for MIC to use with this driver are available from
-         <http://software.intel.com/en-us/mic-developer>.
-
-config SCIF_BUS
-       tristate "SCIF Bus Driver"
-       depends on 64BIT && PCI && X86
-       select DMA_OPS
-       help
-         This option is selected by any driver which registers a
-         device or driver on the SCIF Bus, such as CONFIG_INTEL_MIC_HOST
-         and CONFIG_INTEL_MIC_CARD.
-
-         If you are building a host/card kernel with an Intel MIC device
-         then say M (recommended) or Y, else say N. If unsure say N.
-
-         More information about the Intel MIC family as well as the Linux
-         OS and tools for MIC to use with this driver are available from
-         <http://software.intel.com/en-us/mic-developer>.
-
-config VOP_BUS
-       tristate "VOP Bus Driver"
-       depends on HAS_DMA
-       select DMA_OPS
-       help
-         This option is selected by any driver which registers a
-         device or driver on the VOP Bus, such as CONFIG_INTEL_MIC_HOST
-         and CONFIG_INTEL_MIC_CARD.
-
-         If you are building a host/card kernel with an Intel MIC device
-         then say M (recommended) or Y, else say N. If unsure say N.
-
-         More information about the Intel MIC family as well as the Linux
-         OS and tools for MIC to use with this driver are available from
-         <http://software.intel.com/en-us/mic-developer>.
-
-config INTEL_MIC_HOST
-       tristate "Intel MIC Host Driver"
-       depends on 64BIT && PCI && X86
-       depends on INTEL_MIC_BUS && SCIF_BUS && MIC_COSM && VOP_BUS
-       select DMA_OPS
-       help
-         This enables Host Driver support for the Intel Many Integrated
-         Core (MIC) family of PCIe form factor coprocessor devices that
-         run a 64 bit Linux OS. The driver manages card OS state and
-         enables communication between host and card. Intel MIC X100
-         devices are currently supported.
-
-         If you are building a host kernel with an Intel MIC device then
-         say M (recommended) or Y, else say N. If unsure say N.
-
-         More information about the Intel MIC family as well as the Linux
-         OS and tools for MIC to use with this driver are available from
-         <http://software.intel.com/en-us/mic-developer>.
-
-config INTEL_MIC_CARD
-       tristate "Intel MIC Card Driver"
-       depends on 64BIT && X86
-       depends on INTEL_MIC_BUS && SCIF_BUS && MIC_COSM && VOP_BUS
-       select VIRTIO
-       help
-         This enables card driver support for the Intel Many Integrated
-         Core (MIC) device family. The card driver communicates shutdown/
-         crash events to the host and allows registration/configuration of
-         virtio devices. Intel MIC X100 devices are currently supported.
-
-         If you are building a card kernel for an Intel MIC device then
-         say M (recommended) or Y, else say N. If unsure say N.
-
-         For more information see
-         <http://software.intel.com/en-us/mic-developer>.
-
-config SCIF
-       tristate "SCIF Driver"
-       depends on 64BIT && PCI && X86 && SCIF_BUS && IOMMU_SUPPORT
-       select IOMMU_IOVA
-       help
-         This enables SCIF Driver support for the Intel Many Integrated
-         Core (MIC) family of PCIe form factor coprocessor devices that
-         run a 64 bit Linux OS. The Symmetric Communication Interface
-         (SCIF (pronounced as skiff)) is a low level communications API
-         across PCIe currently implemented for MIC.
-
-         If you are building a host kernel with an Intel MIC device then
-         say M (recommended) or Y, else say N. If unsure say N.
-
-         More information about the Intel MIC family as well as the Linux
-         OS and tools for MIC to use with this driver are available from
-         <http://software.intel.com/en-us/mic-developer>.
-
-config MIC_COSM
-       tristate "Intel MIC Coprocessor State Management (COSM) Drivers"
-       depends on 64BIT && PCI && X86 && SCIF
-       help
-         This enables COSM driver support for the Intel Many
-         Integrated Core (MIC) family of PCIe form factor coprocessor
-         devices. COSM drivers implement functions such as boot,
-         shutdown, reset and reboot of MIC devices.
-
-         If you are building a host kernel with an Intel MIC device then
-         say M (recommended) or Y, else say N. If unsure say N.
-
-         More information about the Intel MIC family as well as the Linux
-         OS and tools for MIC to use with this driver are available from
-         <http://software.intel.com/en-us/mic-developer>.
-
-config VOP
-       tristate "VOP Driver"
-       depends on VOP_BUS
-       select VHOST_RING
-       select VIRTIO
-       help
-         This enables VOP (Virtio over PCIe) Driver support for the Intel
-         Many Integrated Core (MIC) family of PCIe form factor coprocessor
-         devices. The VOP driver allows virtio drivers, e.g. net, console
-         and block drivers, on the card connect to user space virtio
-         devices on the host.
-
-         If you are building a host kernel with an Intel MIC device then
-         say M (recommended) or Y, else say N. If unsure say N.
-
-         More information about the Intel MIC family as well as the Linux
-         OS and tools for MIC to use with this driver are available from
-         <http://software.intel.com/en-us/mic-developer>.
-
-endmenu
diff --git a/drivers/misc/mic/Makefile b/drivers/misc/mic/Makefile
deleted file mode 100644 (file)
index 1a43622..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile - Intel MIC Linux driver.
-# Copyright(c) 2013, Intel Corporation.
-#
-obj-$(CONFIG_INTEL_MIC_HOST) += host/
-obj-$(CONFIG_INTEL_MIC_CARD) += card/
-obj-y += bus/
-obj-$(CONFIG_SCIF) += scif/
-obj-$(CONFIG_MIC_COSM) += cosm/
-obj-$(CONFIG_MIC_COSM) += cosm_client/
-obj-$(CONFIG_VOP) += vop/
diff --git a/drivers/misc/mic/bus/Makefile b/drivers/misc/mic/bus/Makefile
deleted file mode 100644 (file)
index 0a6aa21..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile - Intel MIC Linux driver.
-# Copyright(c) 2014, Intel Corporation.
-#
-obj-$(CONFIG_INTEL_MIC_BUS) += mic_bus.o
-obj-$(CONFIG_SCIF_BUS) += scif_bus.o
-obj-$(CONFIG_MIC_COSM) += cosm_bus.o
-obj-$(CONFIG_VOP_BUS) += vop_bus.o
diff --git a/drivers/misc/mic/bus/cosm_bus.c b/drivers/misc/mic/bus/cosm_bus.c
deleted file mode 100644 (file)
index 5f2141c..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * Intel MIC COSM Bus Driver
- */
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/idr.h>
-#include "cosm_bus.h"
-
-/* Unique numbering for cosm devices. */
-static DEFINE_IDA(cosm_index_ida);
-
-static int cosm_dev_probe(struct device *d)
-{
-       struct cosm_device *dev = dev_to_cosm(d);
-       struct cosm_driver *drv = drv_to_cosm(dev->dev.driver);
-
-       return drv->probe(dev);
-}
-
-static int cosm_dev_remove(struct device *d)
-{
-       struct cosm_device *dev = dev_to_cosm(d);
-       struct cosm_driver *drv = drv_to_cosm(dev->dev.driver);
-
-       drv->remove(dev);
-       return 0;
-}
-
-static struct bus_type cosm_bus = {
-       .name  = "cosm_bus",
-       .probe = cosm_dev_probe,
-       .remove = cosm_dev_remove,
-};
-
-int cosm_register_driver(struct cosm_driver *driver)
-{
-       driver->driver.bus = &cosm_bus;
-       return driver_register(&driver->driver);
-}
-EXPORT_SYMBOL_GPL(cosm_register_driver);
-
-void cosm_unregister_driver(struct cosm_driver *driver)
-{
-       driver_unregister(&driver->driver);
-}
-EXPORT_SYMBOL_GPL(cosm_unregister_driver);
-
-static inline void cosm_release_dev(struct device *d)
-{
-       struct cosm_device *cdev = dev_to_cosm(d);
-
-       kfree(cdev);
-}
-
-struct cosm_device *
-cosm_register_device(struct device *pdev, struct cosm_hw_ops *hw_ops)
-{
-       struct cosm_device *cdev;
-       int ret;
-
-       cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
-       if (!cdev)
-               return ERR_PTR(-ENOMEM);
-
-       cdev->dev.parent = pdev;
-       cdev->dev.release = cosm_release_dev;
-       cdev->hw_ops = hw_ops;
-       dev_set_drvdata(&cdev->dev, cdev);
-       cdev->dev.bus = &cosm_bus;
-
-       /* Assign a unique device index and hence name */
-       ret = ida_simple_get(&cosm_index_ida, 0, 0, GFP_KERNEL);
-       if (ret < 0)
-               goto free_cdev;
-
-       cdev->index = ret;
-       cdev->dev.id = ret;
-       dev_set_name(&cdev->dev, "cosm-dev%u", cdev->index);
-
-       ret = device_register(&cdev->dev);
-       if (ret)
-               goto ida_remove;
-       return cdev;
-ida_remove:
-       ida_simple_remove(&cosm_index_ida, cdev->index);
-free_cdev:
-       put_device(&cdev->dev);
-       return ERR_PTR(ret);
-}
-EXPORT_SYMBOL_GPL(cosm_register_device);
-
-void cosm_unregister_device(struct cosm_device *dev)
-{
-       int index = dev->index; /* save for after device release */
-
-       device_unregister(&dev->dev);
-       ida_simple_remove(&cosm_index_ida, index);
-}
-EXPORT_SYMBOL_GPL(cosm_unregister_device);
-
-struct cosm_device *cosm_find_cdev_by_id(int id)
-{
-       struct device *dev = subsys_find_device_by_id(&cosm_bus, id, NULL);
-
-       return dev ? container_of(dev, struct cosm_device, dev) : NULL;
-}
-EXPORT_SYMBOL_GPL(cosm_find_cdev_by_id);
-
-static int __init cosm_init(void)
-{
-       return bus_register(&cosm_bus);
-}
-
-static void __exit cosm_exit(void)
-{
-       bus_unregister(&cosm_bus);
-       ida_destroy(&cosm_index_ida);
-}
-
-core_initcall(cosm_init);
-module_exit(cosm_exit);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Intel(R) MIC card OS state management bus driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/bus/cosm_bus.h b/drivers/misc/mic/bus/cosm_bus.h
deleted file mode 100644 (file)
index d50d7ae..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * Intel MIC COSM Bus Driver
- */
-#ifndef _COSM_BUS_H_
-#define _COSM_BUS_H_
-
-#include <linux/scif.h>
-#include <linux/mic_common.h>
-#include "../common/mic_dev.h"
-
-/**
- * cosm_device - representation of a cosm device
- *
- * @attr_group: Pointer to list of sysfs attribute groups.
- * @sdev: Device for sysfs entries.
- * @state: MIC state.
- * @prev_state: MIC state previous to MIC_RESETTING
- * @shutdown_status: MIC status reported by card for shutdown/crashes.
- * @shutdown_status_int: Internal shutdown status maintained by the driver
- * @cosm_mutex: Mutex for synchronizing access to data structures.
- * @reset_trigger_work: Work for triggering reset requests.
- * @scif_work: Work for handling per device SCIF connections
- * @cmdline: Kernel command line.
- * @firmware: Firmware file name.
- * @ramdisk: Ramdisk file name.
- * @bootmode: Boot mode i.e. "linux" or "elf" for flash updates.
- * @log_buf_addr: Log buffer address for MIC.
- * @log_buf_len: Log buffer length address for MIC.
- * @state_sysfs: Sysfs dirent for notifying ring 3 about MIC state changes.
- * @hw_ops: the hardware bus ops for this device.
- * @dev: underlying device.
- * @index: unique position on the cosm bus
- * @dbg_dir: debug fs directory
- * @newepd: new endpoint from scif accept to be assigned to this cdev
- * @epd: SCIF endpoint for this cdev
- * @heartbeat_watchdog_enable: if heartbeat watchdog is enabled for this cdev
- * @sysfs_heartbeat_enable: sysfs setting for disabling heartbeat notification
- */
-struct cosm_device {
-       const struct attribute_group **attr_group;
-       struct device *sdev;
-       u8 state;
-       u8 prev_state;
-       u8 shutdown_status;
-       u8 shutdown_status_int;
-       struct mutex cosm_mutex;
-       struct work_struct reset_trigger_work;
-       struct work_struct scif_work;
-       char *cmdline;
-       char *firmware;
-       char *ramdisk;
-       char *bootmode;
-       void *log_buf_addr;
-       int *log_buf_len;
-       struct kernfs_node *state_sysfs;
-       struct cosm_hw_ops *hw_ops;
-       struct device dev;
-       int index;
-       struct dentry *dbg_dir;
-       scif_epd_t newepd;
-       scif_epd_t epd;
-       bool heartbeat_watchdog_enable;
-       bool sysfs_heartbeat_enable;
-};
-
-/**
- * cosm_driver - operations for a cosm driver
- *
- * @driver: underlying device driver (populate name and owner).
- * @probe: the function to call when a device is found.  Returns 0 or -errno.
- * @remove: the function to call when a device is removed.
- */
-struct cosm_driver {
-       struct device_driver driver;
-       int (*probe)(struct cosm_device *dev);
-       void (*remove)(struct cosm_device *dev);
-};
-
-/**
- * cosm_hw_ops - cosm bus ops
- *
- * @reset: trigger MIC reset
- * @force_reset: force MIC reset
- * @post_reset: inform MIC reset is complete
- * @ready: is MIC ready for OS download
- * @start: boot MIC
- * @stop: prepare MIC for reset
- * @family: return MIC HW family string
- * @stepping: return MIC HW stepping string
- * @aper: return MIC PCIe aperture
- */
-struct cosm_hw_ops {
-       void (*reset)(struct cosm_device *cdev);
-       void (*force_reset)(struct cosm_device *cdev);
-       void (*post_reset)(struct cosm_device *cdev, enum mic_states state);
-       bool (*ready)(struct cosm_device *cdev);
-       int (*start)(struct cosm_device *cdev, int id);
-       void (*stop)(struct cosm_device *cdev, bool force);
-       ssize_t (*family)(struct cosm_device *cdev, char *buf);
-       ssize_t (*stepping)(struct cosm_device *cdev, char *buf);
-       struct mic_mw *(*aper)(struct cosm_device *cdev);
-};
-
-struct cosm_device *
-cosm_register_device(struct device *pdev, struct cosm_hw_ops *hw_ops);
-void cosm_unregister_device(struct cosm_device *dev);
-int cosm_register_driver(struct cosm_driver *drv);
-void cosm_unregister_driver(struct cosm_driver *drv);
-struct cosm_device *cosm_find_cdev_by_id(int id);
-
-static inline struct cosm_device *dev_to_cosm(struct device *dev)
-{
-       return container_of(dev, struct cosm_device, dev);
-}
-
-static inline struct cosm_driver *drv_to_cosm(struct device_driver *drv)
-{
-       return container_of(drv, struct cosm_driver, driver);
-}
-#endif /* _COSM_BUS_H */
diff --git a/drivers/misc/mic/bus/mic_bus.c b/drivers/misc/mic/bus/mic_bus.c
deleted file mode 100644 (file)
index a08cb29..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel MIC Bus driver.
- *
- * This implementation is very similar to the the virtio bus driver
- * implementation @ drivers/virtio/virtio.c
- */
-#include <linux/dma-map-ops.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/idr.h>
-#include <linux/mic_bus.h>
-
-static ssize_t device_show(struct device *d,
-                          struct device_attribute *attr, char *buf)
-{
-       struct mbus_device *dev = dev_to_mbus(d);
-       return sprintf(buf, "0x%04x\n", dev->id.device);
-}
-static DEVICE_ATTR_RO(device);
-
-static ssize_t vendor_show(struct device *d,
-                          struct device_attribute *attr, char *buf)
-{
-       struct mbus_device *dev = dev_to_mbus(d);
-       return sprintf(buf, "0x%04x\n", dev->id.vendor);
-}
-static DEVICE_ATTR_RO(vendor);
-
-static ssize_t modalias_show(struct device *d,
-                            struct device_attribute *attr, char *buf)
-{
-       struct mbus_device *dev = dev_to_mbus(d);
-       return sprintf(buf, "mbus:d%08Xv%08X\n",
-                      dev->id.device, dev->id.vendor);
-}
-static DEVICE_ATTR_RO(modalias);
-
-static struct attribute *mbus_dev_attrs[] = {
-       &dev_attr_device.attr,
-       &dev_attr_vendor.attr,
-       &dev_attr_modalias.attr,
-       NULL,
-};
-ATTRIBUTE_GROUPS(mbus_dev);
-
-static inline int mbus_id_match(const struct mbus_device *dev,
-                               const struct mbus_device_id *id)
-{
-       if (id->device != dev->id.device && id->device != MBUS_DEV_ANY_ID)
-               return 0;
-
-       return id->vendor == MBUS_DEV_ANY_ID || id->vendor == dev->id.vendor;
-}
-
-/*
- * This looks through all the IDs a driver claims to support.  If any of them
- * match, we return 1 and the kernel will call mbus_dev_probe().
- */
-static int mbus_dev_match(struct device *dv, struct device_driver *dr)
-{
-       unsigned int i;
-       struct mbus_device *dev = dev_to_mbus(dv);
-       const struct mbus_device_id *ids;
-
-       ids = drv_to_mbus(dr)->id_table;
-       for (i = 0; ids[i].device; i++)
-               if (mbus_id_match(dev, &ids[i]))
-                       return 1;
-       return 0;
-}
-
-static int mbus_uevent(struct device *dv, struct kobj_uevent_env *env)
-{
-       struct mbus_device *dev = dev_to_mbus(dv);
-
-       return add_uevent_var(env, "MODALIAS=mbus:d%08Xv%08X",
-                             dev->id.device, dev->id.vendor);
-}
-
-static int mbus_dev_probe(struct device *d)
-{
-       int err;
-       struct mbus_device *dev = dev_to_mbus(d);
-       struct mbus_driver *drv = drv_to_mbus(dev->dev.driver);
-
-       err = drv->probe(dev);
-       if (!err)
-               if (drv->scan)
-                       drv->scan(dev);
-       return err;
-}
-
-static int mbus_dev_remove(struct device *d)
-{
-       struct mbus_device *dev = dev_to_mbus(d);
-       struct mbus_driver *drv = drv_to_mbus(dev->dev.driver);
-
-       drv->remove(dev);
-       return 0;
-}
-
-static struct bus_type mic_bus = {
-       .name  = "mic_bus",
-       .match = mbus_dev_match,
-       .dev_groups = mbus_dev_groups,
-       .uevent = mbus_uevent,
-       .probe = mbus_dev_probe,
-       .remove = mbus_dev_remove,
-};
-
-int mbus_register_driver(struct mbus_driver *driver)
-{
-       driver->driver.bus = &mic_bus;
-       return driver_register(&driver->driver);
-}
-EXPORT_SYMBOL_GPL(mbus_register_driver);
-
-void mbus_unregister_driver(struct mbus_driver *driver)
-{
-       driver_unregister(&driver->driver);
-}
-EXPORT_SYMBOL_GPL(mbus_unregister_driver);
-
-static void mbus_release_dev(struct device *d)
-{
-       struct mbus_device *mbdev = dev_to_mbus(d);
-       kfree(mbdev);
-}
-
-struct mbus_device *
-mbus_register_device(struct device *pdev, int id, const struct dma_map_ops *dma_ops,
-                    struct mbus_hw_ops *hw_ops, int index,
-                    void __iomem *mmio_va)
-{
-       int ret;
-       struct mbus_device *mbdev;
-
-       mbdev = kzalloc(sizeof(*mbdev), GFP_KERNEL);
-       if (!mbdev)
-               return ERR_PTR(-ENOMEM);
-
-       mbdev->mmio_va = mmio_va;
-       mbdev->dev.parent = pdev;
-       mbdev->id.device = id;
-       mbdev->id.vendor = MBUS_DEV_ANY_ID;
-       mbdev->dev.dma_ops = dma_ops;
-       mbdev->dev.dma_mask = &mbdev->dev.coherent_dma_mask;
-       dma_set_mask(&mbdev->dev, DMA_BIT_MASK(64));
-       mbdev->dev.release = mbus_release_dev;
-       mbdev->hw_ops = hw_ops;
-       mbdev->dev.bus = &mic_bus;
-       mbdev->index = index;
-       dev_set_name(&mbdev->dev, "mbus-dev%u", mbdev->index);
-       /*
-        * device_register() causes the bus infrastructure to look for a
-        * matching driver.
-        */
-       ret = device_register(&mbdev->dev);
-       if (ret)
-               goto free_mbdev;
-       return mbdev;
-free_mbdev:
-       put_device(&mbdev->dev);
-       return ERR_PTR(ret);
-}
-EXPORT_SYMBOL_GPL(mbus_register_device);
-
-void mbus_unregister_device(struct mbus_device *mbdev)
-{
-       device_unregister(&mbdev->dev);
-}
-EXPORT_SYMBOL_GPL(mbus_unregister_device);
-
-static int __init mbus_init(void)
-{
-       return bus_register(&mic_bus);
-}
-
-static void __exit mbus_exit(void)
-{
-       bus_unregister(&mic_bus);
-}
-
-core_initcall(mbus_init);
-module_exit(mbus_exit);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Intel(R) MIC Bus driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/bus/scif_bus.c b/drivers/misc/mic/bus/scif_bus.c
deleted file mode 100644 (file)
index ad7c360..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel Symmetric Communications Interface Bus driver.
- */
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/idr.h>
-#include <linux/dma-map-ops.h>
-
-#include "scif_bus.h"
-
-static ssize_t device_show(struct device *d,
-                          struct device_attribute *attr, char *buf)
-{
-       struct scif_hw_dev *dev = dev_to_scif(d);
-
-       return sprintf(buf, "0x%04x\n", dev->id.device);
-}
-static DEVICE_ATTR_RO(device);
-
-static ssize_t vendor_show(struct device *d,
-                          struct device_attribute *attr, char *buf)
-{
-       struct scif_hw_dev *dev = dev_to_scif(d);
-
-       return sprintf(buf, "0x%04x\n", dev->id.vendor);
-}
-static DEVICE_ATTR_RO(vendor);
-
-static ssize_t modalias_show(struct device *d,
-                            struct device_attribute *attr, char *buf)
-{
-       struct scif_hw_dev *dev = dev_to_scif(d);
-
-       return sprintf(buf, "scif:d%08Xv%08X\n",
-                      dev->id.device, dev->id.vendor);
-}
-static DEVICE_ATTR_RO(modalias);
-
-static struct attribute *scif_dev_attrs[] = {
-       &dev_attr_device.attr,
-       &dev_attr_vendor.attr,
-       &dev_attr_modalias.attr,
-       NULL,
-};
-ATTRIBUTE_GROUPS(scif_dev);
-
-static inline int scif_id_match(const struct scif_hw_dev *dev,
-                               const struct scif_hw_dev_id *id)
-{
-       if (id->device != dev->id.device && id->device != SCIF_DEV_ANY_ID)
-               return 0;
-
-       return id->vendor == SCIF_DEV_ANY_ID || id->vendor == dev->id.vendor;
-}
-
-/*
- * This looks through all the IDs a driver claims to support.  If any of them
- * match, we return 1 and the kernel will call scif_dev_probe().
- */
-static int scif_dev_match(struct device *dv, struct device_driver *dr)
-{
-       unsigned int i;
-       struct scif_hw_dev *dev = dev_to_scif(dv);
-       const struct scif_hw_dev_id *ids;
-
-       ids = drv_to_scif(dr)->id_table;
-       for (i = 0; ids[i].device; i++)
-               if (scif_id_match(dev, &ids[i]))
-                       return 1;
-       return 0;
-}
-
-static int scif_uevent(struct device *dv, struct kobj_uevent_env *env)
-{
-       struct scif_hw_dev *dev = dev_to_scif(dv);
-
-       return add_uevent_var(env, "MODALIAS=scif:d%08Xv%08X",
-                             dev->id.device, dev->id.vendor);
-}
-
-static int scif_dev_probe(struct device *d)
-{
-       struct scif_hw_dev *dev = dev_to_scif(d);
-       struct scif_driver *drv = drv_to_scif(dev->dev.driver);
-
-       return drv->probe(dev);
-}
-
-static int scif_dev_remove(struct device *d)
-{
-       struct scif_hw_dev *dev = dev_to_scif(d);
-       struct scif_driver *drv = drv_to_scif(dev->dev.driver);
-
-       drv->remove(dev);
-       return 0;
-}
-
-static struct bus_type scif_bus = {
-       .name  = "scif_bus",
-       .match = scif_dev_match,
-       .dev_groups = scif_dev_groups,
-       .uevent = scif_uevent,
-       .probe = scif_dev_probe,
-       .remove = scif_dev_remove,
-};
-
-int scif_register_driver(struct scif_driver *driver)
-{
-       driver->driver.bus = &scif_bus;
-       return driver_register(&driver->driver);
-}
-EXPORT_SYMBOL_GPL(scif_register_driver);
-
-void scif_unregister_driver(struct scif_driver *driver)
-{
-       driver_unregister(&driver->driver);
-}
-EXPORT_SYMBOL_GPL(scif_unregister_driver);
-
-static void scif_release_dev(struct device *d)
-{
-       struct scif_hw_dev *sdev = dev_to_scif(d);
-
-       kfree(sdev);
-}
-
-struct scif_hw_dev *
-scif_register_device(struct device *pdev, int id, const struct dma_map_ops *dma_ops,
-                    struct scif_hw_ops *hw_ops, u8 dnode, u8 snode,
-                    struct mic_mw *mmio, struct mic_mw *aper, void *dp,
-                    void __iomem *rdp, struct dma_chan **chan, int num_chan,
-                    bool card_rel_da)
-{
-       int ret;
-       struct scif_hw_dev *sdev;
-
-       sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
-       if (!sdev)
-               return ERR_PTR(-ENOMEM);
-
-       sdev->dev.parent = pdev;
-       sdev->id.device = id;
-       sdev->id.vendor = SCIF_DEV_ANY_ID;
-       sdev->dev.dma_ops = dma_ops;
-       sdev->dev.release = scif_release_dev;
-       sdev->hw_ops = hw_ops;
-       sdev->dnode = dnode;
-       sdev->snode = snode;
-       dev_set_drvdata(&sdev->dev, sdev);
-       sdev->dev.bus = &scif_bus;
-       sdev->mmio = mmio;
-       sdev->aper = aper;
-       sdev->dp = dp;
-       sdev->rdp = rdp;
-       sdev->dev.dma_mask = &sdev->dev.coherent_dma_mask;
-       dma_set_mask(&sdev->dev, DMA_BIT_MASK(64));
-       sdev->dma_ch = chan;
-       sdev->num_dma_ch = num_chan;
-       sdev->card_rel_da = card_rel_da;
-       dev_set_name(&sdev->dev, "scif-dev%u", sdev->dnode);
-       /*
-        * device_register() causes the bus infrastructure to look for a
-        * matching driver.
-        */
-       ret = device_register(&sdev->dev);
-       if (ret)
-               goto free_sdev;
-       return sdev;
-free_sdev:
-       put_device(&sdev->dev);
-       return ERR_PTR(ret);
-}
-EXPORT_SYMBOL_GPL(scif_register_device);
-
-void scif_unregister_device(struct scif_hw_dev *sdev)
-{
-       device_unregister(&sdev->dev);
-}
-EXPORT_SYMBOL_GPL(scif_unregister_device);
-
-static int __init scif_init(void)
-{
-       return bus_register(&scif_bus);
-}
-
-static void __exit scif_exit(void)
-{
-       bus_unregister(&scif_bus);
-}
-
-core_initcall(scif_init);
-module_exit(scif_exit);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Intel(R) SCIF Bus driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/bus/scif_bus.h b/drivers/misc/mic/bus/scif_bus.h
deleted file mode 100644 (file)
index 4981eb5..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel Symmetric Communications Interface Bus driver.
- */
-#ifndef _SCIF_BUS_H_
-#define _SCIF_BUS_H_
-/*
- * Everything a scif driver needs to work with any particular scif
- * hardware abstraction layer.
- */
-#include <linux/dma-map-ops.h>
-
-#include <linux/mic_common.h>
-#include "../common/mic_dev.h"
-
-struct scif_hw_dev_id {
-       u32 device;
-       u32 vendor;
-};
-
-#define MIC_SCIF_DEV 1
-#define SCIF_DEV_ANY_ID 0xffffffff
-
-/**
- * scif_hw_dev - representation of a hardware device abstracted for scif
- * @hw_ops: the hardware ops supported by this device
- * @id: the device type identification (used to match it with a driver)
- * @mmio: MMIO memory window
- * @aper: Aperture memory window
- * @dev: underlying device
- * @dnode - The destination node which this device will communicate with.
- * @snode - The source node for this device.
- * @dp - Self device page
- * @rdp - Remote device page
- * @dma_ch - Array of DMA channels
- * @num_dma_ch - Number of DMA channels available
- * @card_rel_da - Set to true if DMA addresses programmed in the DMA engine
- *             are relative to the card point of view
- */
-struct scif_hw_dev {
-       struct scif_hw_ops *hw_ops;
-       struct scif_hw_dev_id id;
-       struct mic_mw *mmio;
-       struct mic_mw *aper;
-       struct device dev;
-       u8 dnode;
-       u8 snode;
-       void *dp;
-       void __iomem *rdp;
-       struct dma_chan **dma_ch;
-       int num_dma_ch;
-       bool card_rel_da;
-};
-
-/**
- * scif_driver - operations for a scif I/O driver
- * @driver: underlying device driver (populate name and owner).
- * @id_table: the ids serviced by this driver.
- * @probe: the function to call when a device is found.  Returns 0 or -errno.
- * @remove: the function to call when a device is removed.
- */
-struct scif_driver {
-       struct device_driver driver;
-       const struct scif_hw_dev_id *id_table;
-       int (*probe)(struct scif_hw_dev *dev);
-       void (*remove)(struct scif_hw_dev *dev);
-};
-
-/**
- * scif_hw_ops - Hardware operations for accessing a SCIF device on the SCIF bus.
- *
- * @next_db: Obtain the next available doorbell.
- * @request_irq: Request an interrupt on a particular doorbell.
- * @free_irq: Free an interrupt requested previously.
- * @ack_interrupt: acknowledge an interrupt in the ISR.
- * @send_intr: Send an interrupt to the remote node on a specified doorbell.
- * @send_p2p_intr: Send an interrupt to the peer node on a specified doorbell
- * which is specifically targeted for a peer to peer node.
- * @remap: Map a buffer with the specified physical address and length.
- * @unmap: Unmap a buffer previously mapped.
- */
-struct scif_hw_ops {
-       int (*next_db)(struct scif_hw_dev *sdev);
-       struct mic_irq * (*request_irq)(struct scif_hw_dev *sdev,
-                                       irqreturn_t (*func)(int irq,
-                                                           void *data),
-                                       const char *name, void *data,
-                                       int db);
-       void (*free_irq)(struct scif_hw_dev *sdev,
-                        struct mic_irq *cookie, void *data);
-       void (*ack_interrupt)(struct scif_hw_dev *sdev, int num);
-       void (*send_intr)(struct scif_hw_dev *sdev, int db);
-       void (*send_p2p_intr)(struct scif_hw_dev *sdev, int db,
-                             struct mic_mw *mw);
-       void __iomem * (*remap)(struct scif_hw_dev *sdev,
-                                 phys_addr_t pa, size_t len);
-       void (*unmap)(struct scif_hw_dev *sdev, void __iomem *va);
-};
-
-int scif_register_driver(struct scif_driver *driver);
-void scif_unregister_driver(struct scif_driver *driver);
-struct scif_hw_dev *
-scif_register_device(struct device *pdev, int id,
-                    const struct dma_map_ops *dma_ops,
-                    struct scif_hw_ops *hw_ops, u8 dnode, u8 snode,
-                    struct mic_mw *mmio, struct mic_mw *aper,
-                    void *dp, void __iomem *rdp,
-                    struct dma_chan **chan, int num_chan,
-                    bool card_rel_da);
-void scif_unregister_device(struct scif_hw_dev *sdev);
-
-static inline struct scif_hw_dev *dev_to_scif(struct device *dev)
-{
-       return container_of(dev, struct scif_hw_dev, dev);
-}
-
-static inline struct scif_driver *drv_to_scif(struct device_driver *drv)
-{
-       return container_of(drv, struct scif_driver, driver);
-}
-#endif /* _SCIF_BUS_H */
diff --git a/drivers/misc/mic/bus/vop_bus.c b/drivers/misc/mic/bus/vop_bus.c
deleted file mode 100644 (file)
index 6935ddc..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2016 Intel Corporation.
- *
- * Intel Virtio Over PCIe (VOP) Bus driver.
- */
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/idr.h>
-#include <linux/dma-map-ops.h>
-
-#include "vop_bus.h"
-
-static ssize_t device_show(struct device *d,
-                          struct device_attribute *attr, char *buf)
-{
-       struct vop_device *dev = dev_to_vop(d);
-
-       return sprintf(buf, "0x%04x\n", dev->id.device);
-}
-static DEVICE_ATTR_RO(device);
-
-static ssize_t vendor_show(struct device *d,
-                          struct device_attribute *attr, char *buf)
-{
-       struct vop_device *dev = dev_to_vop(d);
-
-       return sprintf(buf, "0x%04x\n", dev->id.vendor);
-}
-static DEVICE_ATTR_RO(vendor);
-
-static ssize_t modalias_show(struct device *d,
-                            struct device_attribute *attr, char *buf)
-{
-       struct vop_device *dev = dev_to_vop(d);
-
-       return sprintf(buf, "vop:d%08Xv%08X\n",
-                      dev->id.device, dev->id.vendor);
-}
-static DEVICE_ATTR_RO(modalias);
-
-static struct attribute *vop_dev_attrs[] = {
-       &dev_attr_device.attr,
-       &dev_attr_vendor.attr,
-       &dev_attr_modalias.attr,
-       NULL,
-};
-ATTRIBUTE_GROUPS(vop_dev);
-
-static inline int vop_id_match(const struct vop_device *dev,
-                              const struct vop_device_id *id)
-{
-       if (id->device != dev->id.device && id->device != VOP_DEV_ANY_ID)
-               return 0;
-
-       return id->vendor == VOP_DEV_ANY_ID || id->vendor == dev->id.vendor;
-}
-
-/*
- * This looks through all the IDs a driver claims to support.  If any of them
- * match, we return 1 and the kernel will call vop_dev_probe().
- */
-static int vop_dev_match(struct device *dv, struct device_driver *dr)
-{
-       unsigned int i;
-       struct vop_device *dev = dev_to_vop(dv);
-       const struct vop_device_id *ids;
-
-       ids = drv_to_vop(dr)->id_table;
-       for (i = 0; ids[i].device; i++)
-               if (vop_id_match(dev, &ids[i]))
-                       return 1;
-       return 0;
-}
-
-static int vop_uevent(struct device *dv, struct kobj_uevent_env *env)
-{
-       struct vop_device *dev = dev_to_vop(dv);
-
-       return add_uevent_var(env, "MODALIAS=vop:d%08Xv%08X",
-                             dev->id.device, dev->id.vendor);
-}
-
-static int vop_dev_probe(struct device *d)
-{
-       struct vop_device *dev = dev_to_vop(d);
-       struct vop_driver *drv = drv_to_vop(dev->dev.driver);
-
-       return drv->probe(dev);
-}
-
-static int vop_dev_remove(struct device *d)
-{
-       struct vop_device *dev = dev_to_vop(d);
-       struct vop_driver *drv = drv_to_vop(dev->dev.driver);
-
-       drv->remove(dev);
-       return 0;
-}
-
-static struct bus_type vop_bus = {
-       .name  = "vop_bus",
-       .match = vop_dev_match,
-       .dev_groups = vop_dev_groups,
-       .uevent = vop_uevent,
-       .probe = vop_dev_probe,
-       .remove = vop_dev_remove,
-};
-
-int vop_register_driver(struct vop_driver *driver)
-{
-       driver->driver.bus = &vop_bus;
-       return driver_register(&driver->driver);
-}
-EXPORT_SYMBOL_GPL(vop_register_driver);
-
-void vop_unregister_driver(struct vop_driver *driver)
-{
-       driver_unregister(&driver->driver);
-}
-EXPORT_SYMBOL_GPL(vop_unregister_driver);
-
-static void vop_release_dev(struct device *d)
-{
-       struct vop_device *dev = dev_to_vop(d);
-
-       kfree(dev);
-}
-
-struct vop_device *
-vop_register_device(struct device *pdev, int id,
-                   const struct dma_map_ops *dma_ops,
-                   struct vop_hw_ops *hw_ops, u8 dnode, struct mic_mw *aper,
-                   struct dma_chan *chan)
-{
-       int ret;
-       struct vop_device *vdev;
-
-       vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
-       if (!vdev)
-               return ERR_PTR(-ENOMEM);
-
-       vdev->dev.parent = pdev;
-       vdev->id.device = id;
-       vdev->id.vendor = VOP_DEV_ANY_ID;
-       vdev->dev.dma_ops = dma_ops;
-       vdev->dev.dma_mask = &vdev->dev.coherent_dma_mask;
-       dma_set_mask(&vdev->dev, DMA_BIT_MASK(64));
-       vdev->dev.release = vop_release_dev;
-       vdev->hw_ops = hw_ops;
-       vdev->dev.bus = &vop_bus;
-       vdev->dnode = dnode;
-       vdev->aper = aper;
-       vdev->dma_ch = chan;
-       vdev->index = dnode - 1;
-       dev_set_name(&vdev->dev, "vop-dev%u", vdev->index);
-       /*
-        * device_register() causes the bus infrastructure to look for a
-        * matching driver.
-        */
-       ret = device_register(&vdev->dev);
-       if (ret)
-               goto free_vdev;
-       return vdev;
-free_vdev:
-       put_device(&vdev->dev);
-       return ERR_PTR(ret);
-}
-EXPORT_SYMBOL_GPL(vop_register_device);
-
-void vop_unregister_device(struct vop_device *dev)
-{
-       device_unregister(&dev->dev);
-}
-EXPORT_SYMBOL_GPL(vop_unregister_device);
-
-static int __init vop_init(void)
-{
-       return bus_register(&vop_bus);
-}
-
-static void __exit vop_exit(void)
-{
-       bus_unregister(&vop_bus);
-}
-
-core_initcall(vop_init);
-module_exit(vop_exit);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Intel(R) VOP Bus driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/bus/vop_bus.h b/drivers/misc/mic/bus/vop_bus.h
deleted file mode 100644 (file)
index 4fa0280..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2016 Intel Corporation.
- *
- * Intel Virtio over PCIe Bus driver.
- */
-#ifndef _VOP_BUS_H_
-#define _VOP_BUS_H_
-/*
- * Everything a vop driver needs to work with any particular vop
- * implementation.
- */
-#include <linux/dmaengine.h>
-#include <linux/interrupt.h>
-
-#include "../common/mic_dev.h"
-
-struct vop_device_id {
-       u32 device;
-       u32 vendor;
-};
-
-#define VOP_DEV_TRNSP 1
-#define VOP_DEV_ANY_ID 0xffffffff
-/*
- * Size of the internal buffer used during DMA's as an intermediate buffer
- * for copy to/from user. Must be an integral number of pages.
- */
-#define VOP_INT_DMA_BUF_SIZE PAGE_ALIGN(64 * 1024ULL)
-
-/**
- * vop_device - representation of a device using vop
- * @hw_ops: the hardware ops supported by this device.
- * @id: the device type identification (used to match it with a driver).
- * @dev: underlying device.
- * @dnode - The destination node which this device will communicate with.
- * @aper: Aperture memory window
- * @dma_ch - DMA channel
- * @index: unique position on the vop bus
- */
-struct vop_device {
-       struct vop_hw_ops *hw_ops;
-       struct vop_device_id id;
-       struct device dev;
-       u8 dnode;
-       struct mic_mw *aper;
-       struct dma_chan *dma_ch;
-       int index;
-};
-
-/**
- * vop_driver - operations for a vop I/O driver
- * @driver: underlying device driver (populate name and owner).
- * @id_table: the ids serviced by this driver.
- * @probe: the function to call when a device is found.  Returns 0 or -errno.
- * @remove: the function to call when a device is removed.
- */
-struct vop_driver {
-       struct device_driver driver;
-       const struct vop_device_id *id_table;
-       int (*probe)(struct vop_device *dev);
-       void (*remove)(struct vop_device *dev);
-};
-
-/**
- * vop_hw_ops - Hardware operations for accessing a VOP device on the VOP bus.
- *
- * @next_db: Obtain the next available doorbell.
- * @request_irq: Request an interrupt on a particular doorbell.
- * @free_irq: Free an interrupt requested previously.
- * @ack_interrupt: acknowledge an interrupt in the ISR.
- * @get_remote_dp: Get access to the virtio device page used by the remote
- *                 node to add/remove/configure virtio devices.
- * @get_dp: Get access to the virtio device page used by the self
- *          node to add/remove/configure virtio devices.
- * @send_intr: Send an interrupt to the peer node on a specified doorbell.
- * @remap: Map a buffer with the specified DMA address and length.
- * @unmap: Unmap a buffer previously mapped.
- * @dma_filter: The DMA filter function to use for obtaining access to
- *             a DMA channel on the peer node.
- */
-struct vop_hw_ops {
-       int (*next_db)(struct vop_device *vpdev);
-       struct mic_irq *(*request_irq)(struct vop_device *vpdev,
-                                      irqreturn_t (*func)(int irq, void *data),
-                                      const char *name, void *data,
-                                      int intr_src);
-       void (*free_irq)(struct vop_device *vpdev,
-                        struct mic_irq *cookie, void *data);
-       void (*ack_interrupt)(struct vop_device *vpdev, int num);
-       void __iomem * (*get_remote_dp)(struct vop_device *vpdev);
-       void * (*get_dp)(struct vop_device *vpdev);
-       void (*send_intr)(struct vop_device *vpdev, int db);
-       void __iomem * (*remap)(struct vop_device *vpdev,
-                                 dma_addr_t pa, size_t len);
-       void (*unmap)(struct vop_device *vpdev, void __iomem *va);
-};
-
-struct vop_device *
-vop_register_device(struct device *pdev, int id,
-                   const struct dma_map_ops *dma_ops,
-                   struct vop_hw_ops *hw_ops, u8 dnode, struct mic_mw *aper,
-                   struct dma_chan *chan);
-void vop_unregister_device(struct vop_device *dev);
-int vop_register_driver(struct vop_driver *drv);
-void vop_unregister_driver(struct vop_driver *drv);
-
-/*
- * module_vop_driver() - Helper macro for drivers that don't do
- * anything special in module init/exit.  This eliminates a lot of
- * boilerplate.  Each module may only use this macro once, and
- * calling it replaces module_init() and module_exit()
- */
-#define module_vop_driver(__vop_driver) \
-       module_driver(__vop_driver, vop_register_driver, \
-                       vop_unregister_driver)
-
-static inline struct vop_device *dev_to_vop(struct device *dev)
-{
-       return container_of(dev, struct vop_device, dev);
-}
-
-static inline struct vop_driver *drv_to_vop(struct device_driver *drv)
-{
-       return container_of(drv, struct vop_driver, driver);
-}
-#endif /* _VOP_BUS_H */
diff --git a/drivers/misc/mic/card/Makefile b/drivers/misc/mic/card/Makefile
deleted file mode 100644 (file)
index 921a7e7..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile - Intel MIC Linux driver.
-# Copyright(c) 2013, Intel Corporation.
-#
-ccflags-y += -DINTEL_MIC_CARD
-
-obj-$(CONFIG_INTEL_MIC_CARD) += mic_card.o
-mic_card-y += mic_x100.o
-mic_card-y += mic_device.o
-mic_card-y += mic_debugfs.o
diff --git a/drivers/misc/mic/card/mic_debugfs.c b/drivers/misc/mic/card/mic_debugfs.c
deleted file mode 100644 (file)
index 4c326e8..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Disclaimer: The codes contained in these modules may be specific to
- * the Intel Software Development Platform codenamed: Knights Ferry, and
- * the Intel product codenamed: Knights Corner, and are not backward
- * compatible with other Intel products. Additionally, Intel will NOT
- * support the codes or instruction set in future products.
- *
- * Intel MIC Card driver.
- */
-#include <linux/debugfs.h>
-#include <linux/delay.h>
-#include <linux/seq_file.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-
-#include "../common/mic_dev.h"
-#include "mic_device.h"
-
-/* Debugfs parent dir */
-static struct dentry *mic_dbg;
-
-/*
- * mic_intr_show - Send interrupts to host.
- */
-static int mic_intr_show(struct seq_file *s, void *unused)
-{
-       struct mic_driver *mdrv = s->private;
-       struct mic_device *mdev = &mdrv->mdev;
-
-       mic_send_intr(mdev, 0);
-       msleep(1000);
-       mic_send_intr(mdev, 1);
-       msleep(1000);
-       mic_send_intr(mdev, 2);
-       msleep(1000);
-       mic_send_intr(mdev, 3);
-       msleep(1000);
-
-       return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(mic_intr);
-
-/*
- * mic_create_card_debug_dir - Initialize MIC debugfs entries.
- */
-void __init mic_create_card_debug_dir(struct mic_driver *mdrv)
-{
-       if (!mic_dbg)
-               return;
-
-       mdrv->dbg_dir = debugfs_create_dir(mdrv->name, mic_dbg);
-
-       debugfs_create_file("intr_test", 0444, mdrv->dbg_dir, mdrv,
-                           &mic_intr_fops);
-}
-
-/*
- * mic_delete_card_debug_dir - Uninitialize MIC debugfs entries.
- */
-void mic_delete_card_debug_dir(struct mic_driver *mdrv)
-{
-       debugfs_remove_recursive(mdrv->dbg_dir);
-}
-
-/*
- * mic_init_card_debugfs - Initialize global debugfs entry.
- */
-void __init mic_init_card_debugfs(void)
-{
-       mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
-}
-
-/*
- * mic_exit_card_debugfs - Uninitialize global debugfs entry
- */
-void mic_exit_card_debugfs(void)
-{
-       debugfs_remove(mic_dbg);
-}
diff --git a/drivers/misc/mic/card/mic_device.c b/drivers/misc/mic/card/mic_device.c
deleted file mode 100644 (file)
index a156062..0000000
+++ /dev/null
@@ -1,417 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Disclaimer: The codes contained in these modules may be specific to
- * the Intel Software Development Platform codenamed: Knights Ferry, and
- * the Intel product codenamed: Knights Corner, and are not backward
- * compatible with other Intel products. Additionally, Intel will NOT
- * support the codes or instruction set in future products.
- *
- * Intel MIC Card driver.
- */
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/dmaengine.h>
-#include <linux/kmod.h>
-
-#include <linux/mic_common.h>
-#include "../common/mic_dev.h"
-#include "mic_device.h"
-
-static struct mic_driver *g_drv;
-
-static int __init mic_dp_init(void)
-{
-       struct mic_driver *mdrv = g_drv;
-       struct mic_device *mdev = &mdrv->mdev;
-       struct mic_bootparam __iomem *bootparam;
-       u64 lo, hi, dp_dma_addr;
-       u32 magic;
-
-       lo = mic_read_spad(&mdrv->mdev, MIC_DPLO_SPAD);
-       hi = mic_read_spad(&mdrv->mdev, MIC_DPHI_SPAD);
-
-       dp_dma_addr = lo | (hi << 32);
-       mdrv->dp = mic_card_map(mdev, dp_dma_addr, MIC_DP_SIZE);
-       if (!mdrv->dp) {
-               dev_err(mdrv->dev, "Cannot remap Aperture BAR\n");
-               return -ENOMEM;
-       }
-       bootparam = mdrv->dp;
-       magic = ioread32(&bootparam->magic);
-       if (MIC_MAGIC != magic) {
-               dev_err(mdrv->dev, "bootparam magic mismatch 0x%x\n", magic);
-               return -EIO;
-       }
-       return 0;
-}
-
-/* Uninitialize the device page */
-static void mic_dp_uninit(void)
-{
-       mic_card_unmap(&g_drv->mdev, g_drv->dp);
-}
-
-/**
- * mic_request_card_irq - request an irq.
- *
- * @handler: interrupt handler passed to request_threaded_irq.
- * @thread_fn: thread fn. passed to request_threaded_irq.
- * @name: The ASCII name of the callee requesting the irq.
- * @data: private data that is returned back when calling the
- * function handler.
- * @index: The doorbell index of the requester.
- *
- * returns: The cookie that is transparent to the caller. Passed
- * back when calling mic_free_irq. An appropriate error code
- * is returned on failure. Caller needs to use IS_ERR(return_val)
- * to check for failure and PTR_ERR(return_val) to obtained the
- * error code.
- *
- */
-struct mic_irq *
-mic_request_card_irq(irq_handler_t handler,
-                    irq_handler_t thread_fn, const char *name,
-                    void *data, int index)
-{
-       int rc = 0;
-       unsigned long cookie;
-       struct mic_driver *mdrv = g_drv;
-
-       rc  = request_threaded_irq(mic_db_to_irq(mdrv, index), handler,
-                                  thread_fn, 0, name, data);
-       if (rc) {
-               dev_err(mdrv->dev, "request_threaded_irq failed rc = %d\n", rc);
-               goto err;
-       }
-       mdrv->irq_info.irq_usage_count[index]++;
-       cookie = index;
-       return (struct mic_irq *)cookie;
-err:
-       return ERR_PTR(rc);
-}
-
-/**
- * mic_free_card_irq - free irq.
- *
- * @cookie: cookie obtained during a successful call to mic_request_threaded_irq
- * @data: private data specified by the calling function during the
- * mic_request_threaded_irq
- *
- * returns: none.
- */
-void mic_free_card_irq(struct mic_irq *cookie, void *data)
-{
-       int index;
-       struct mic_driver *mdrv = g_drv;
-
-       index = (unsigned long)cookie & 0xFFFFU;
-       free_irq(mic_db_to_irq(mdrv, index), data);
-       mdrv->irq_info.irq_usage_count[index]--;
-}
-
-/**
- * mic_next_card_db - Get the doorbell with minimum usage count.
- *
- * Returns the irq index.
- */
-int mic_next_card_db(void)
-{
-       int i;
-       int index = 0;
-       struct mic_driver *mdrv = g_drv;
-
-       for (i = 0; i < mdrv->intr_info.num_intr; i++) {
-               if (mdrv->irq_info.irq_usage_count[i] <
-                       mdrv->irq_info.irq_usage_count[index])
-                       index = i;
-       }
-
-       return index;
-}
-
-/**
- * mic_init_irq - Initialize irq information.
- *
- * Returns 0 in success. Appropriate error code on failure.
- */
-static int mic_init_irq(void)
-{
-       struct mic_driver *mdrv = g_drv;
-
-       mdrv->irq_info.irq_usage_count = kzalloc((sizeof(u32) *
-                       mdrv->intr_info.num_intr),
-                       GFP_KERNEL);
-       if (!mdrv->irq_info.irq_usage_count)
-               return -ENOMEM;
-       return 0;
-}
-
-/**
- * mic_uninit_irq - Uninitialize irq information.
- *
- * None.
- */
-static void mic_uninit_irq(void)
-{
-       struct mic_driver *mdrv = g_drv;
-
-       kfree(mdrv->irq_info.irq_usage_count);
-}
-
-static inline struct mic_driver *scdev_to_mdrv(struct scif_hw_dev *scdev)
-{
-       return dev_get_drvdata(scdev->dev.parent);
-}
-
-static struct mic_irq *
-___mic_request_irq(struct scif_hw_dev *scdev,
-                  irqreturn_t (*func)(int irq, void *data),
-                                      const char *name, void *data,
-                                      int db)
-{
-       return mic_request_card_irq(func, NULL, name, data, db);
-}
-
-static void
-___mic_free_irq(struct scif_hw_dev *scdev,
-               struct mic_irq *cookie, void *data)
-{
-       return mic_free_card_irq(cookie, data);
-}
-
-static void ___mic_ack_interrupt(struct scif_hw_dev *scdev, int num)
-{
-       struct mic_driver *mdrv = scdev_to_mdrv(scdev);
-
-       mic_ack_interrupt(&mdrv->mdev);
-}
-
-static int ___mic_next_db(struct scif_hw_dev *scdev)
-{
-       return mic_next_card_db();
-}
-
-static void ___mic_send_intr(struct scif_hw_dev *scdev, int db)
-{
-       struct mic_driver *mdrv = scdev_to_mdrv(scdev);
-
-       mic_send_intr(&mdrv->mdev, db);
-}
-
-static void ___mic_send_p2p_intr(struct scif_hw_dev *scdev, int db,
-                                struct mic_mw *mw)
-{
-       mic_send_p2p_intr(db, mw);
-}
-
-static void __iomem *
-___mic_ioremap(struct scif_hw_dev *scdev,
-              phys_addr_t pa, size_t len)
-{
-       struct mic_driver *mdrv = scdev_to_mdrv(scdev);
-
-       return mic_card_map(&mdrv->mdev, pa, len);
-}
-
-static void ___mic_iounmap(struct scif_hw_dev *scdev, void __iomem *va)
-{
-       struct mic_driver *mdrv = scdev_to_mdrv(scdev);
-
-       mic_card_unmap(&mdrv->mdev, va);
-}
-
-static struct scif_hw_ops scif_hw_ops = {
-       .request_irq = ___mic_request_irq,
-       .free_irq = ___mic_free_irq,
-       .ack_interrupt = ___mic_ack_interrupt,
-       .next_db = ___mic_next_db,
-       .send_intr = ___mic_send_intr,
-       .send_p2p_intr = ___mic_send_p2p_intr,
-       .remap = ___mic_ioremap,
-       .unmap = ___mic_iounmap,
-};
-
-static inline struct mic_driver *vpdev_to_mdrv(struct vop_device *vpdev)
-{
-       return dev_get_drvdata(vpdev->dev.parent);
-}
-
-static struct mic_irq *
-__mic_request_irq(struct vop_device *vpdev,
-                 irqreturn_t (*func)(int irq, void *data),
-                  const char *name, void *data, int intr_src)
-{
-       return mic_request_card_irq(func, NULL, name, data, intr_src);
-}
-
-static void __mic_free_irq(struct vop_device *vpdev,
-                          struct mic_irq *cookie, void *data)
-{
-       return mic_free_card_irq(cookie, data);
-}
-
-static void __mic_ack_interrupt(struct vop_device *vpdev, int num)
-{
-       struct mic_driver *mdrv = vpdev_to_mdrv(vpdev);
-
-       mic_ack_interrupt(&mdrv->mdev);
-}
-
-static int __mic_next_db(struct vop_device *vpdev)
-{
-       return mic_next_card_db();
-}
-
-static void __iomem *__mic_get_remote_dp(struct vop_device *vpdev)
-{
-       struct mic_driver *mdrv = vpdev_to_mdrv(vpdev);
-
-       return mdrv->dp;
-}
-
-static void __mic_send_intr(struct vop_device *vpdev, int db)
-{
-       struct mic_driver *mdrv = vpdev_to_mdrv(vpdev);
-
-       mic_send_intr(&mdrv->mdev, db);
-}
-
-static void __iomem *__mic_ioremap(struct vop_device *vpdev,
-                                  dma_addr_t pa, size_t len)
-{
-       struct mic_driver *mdrv = vpdev_to_mdrv(vpdev);
-
-       return mic_card_map(&mdrv->mdev, pa, len);
-}
-
-static void __mic_iounmap(struct vop_device *vpdev, void __iomem *va)
-{
-       struct mic_driver *mdrv = vpdev_to_mdrv(vpdev);
-
-       mic_card_unmap(&mdrv->mdev, va);
-}
-
-static struct vop_hw_ops vop_hw_ops = {
-       .request_irq = __mic_request_irq,
-       .free_irq = __mic_free_irq,
-       .ack_interrupt = __mic_ack_interrupt,
-       .next_db = __mic_next_db,
-       .get_remote_dp = __mic_get_remote_dp,
-       .send_intr = __mic_send_intr,
-       .remap = __mic_ioremap,
-       .unmap = __mic_iounmap,
-};
-
-static int mic_request_dma_chans(struct mic_driver *mdrv)
-{
-       dma_cap_mask_t mask;
-       struct dma_chan *chan;
-
-       dma_cap_zero(mask);
-       dma_cap_set(DMA_MEMCPY, mask);
-
-       do {
-               chan = dma_request_channel(mask, NULL, NULL);
-               if (chan) {
-                       mdrv->dma_ch[mdrv->num_dma_ch++] = chan;
-                       if (mdrv->num_dma_ch >= MIC_MAX_DMA_CHAN)
-                               break;
-               }
-       } while (chan);
-       dev_info(mdrv->dev, "DMA channels # %d\n", mdrv->num_dma_ch);
-       return mdrv->num_dma_ch;
-}
-
-static void mic_free_dma_chans(struct mic_driver *mdrv)
-{
-       int i = 0;
-
-       for (i = 0; i < mdrv->num_dma_ch; i++) {
-               dma_release_channel(mdrv->dma_ch[i]);
-               mdrv->dma_ch[i] = NULL;
-       }
-       mdrv->num_dma_ch = 0;
-}
-
-/*
- * mic_driver_init - MIC driver initialization tasks.
- *
- * Returns 0 in success. Appropriate error code on failure.
- */
-int __init mic_driver_init(struct mic_driver *mdrv)
-{
-       int rc;
-       struct mic_bootparam __iomem *bootparam;
-       u8 node_id;
-
-       g_drv = mdrv;
-       /* Unloading the card module is not supported. */
-       if (!try_module_get(mdrv->dev->driver->owner)) {
-               rc = -ENODEV;
-               goto done;
-       }
-       rc = mic_dp_init();
-       if (rc)
-               goto put;
-       rc = mic_init_irq();
-       if (rc)
-               goto dp_uninit;
-       if (!mic_request_dma_chans(mdrv)) {
-               rc = -ENODEV;
-               goto irq_uninit;
-       }
-       mdrv->vpdev = vop_register_device(mdrv->dev, VOP_DEV_TRNSP,
-                                         NULL, &vop_hw_ops, 0,
-                                         NULL, mdrv->dma_ch[0]);
-       if (IS_ERR(mdrv->vpdev)) {
-               rc = PTR_ERR(mdrv->vpdev);
-               goto dma_free;
-       }
-       bootparam = mdrv->dp;
-       node_id = ioread8(&bootparam->node_id);
-       mdrv->scdev = scif_register_device(mdrv->dev, MIC_SCIF_DEV,
-                                          NULL, &scif_hw_ops,
-                                          0, node_id, &mdrv->mdev.mmio, NULL,
-                                          NULL, mdrv->dp, mdrv->dma_ch,
-                                          mdrv->num_dma_ch, true);
-       if (IS_ERR(mdrv->scdev)) {
-               rc = PTR_ERR(mdrv->scdev);
-               goto vop_remove;
-       }
-       mic_create_card_debug_dir(mdrv);
-done:
-       return rc;
-vop_remove:
-       vop_unregister_device(mdrv->vpdev);
-dma_free:
-       mic_free_dma_chans(mdrv);
-irq_uninit:
-       mic_uninit_irq();
-dp_uninit:
-       mic_dp_uninit();
-put:
-       module_put(mdrv->dev->driver->owner);
-       return rc;
-}
-
-/*
- * mic_driver_uninit - MIC driver uninitialization tasks.
- *
- * Returns None
- */
-void mic_driver_uninit(struct mic_driver *mdrv)
-{
-       mic_delete_card_debug_dir(mdrv);
-       scif_unregister_device(mdrv->scdev);
-       vop_unregister_device(mdrv->vpdev);
-       mic_free_dma_chans(mdrv);
-       mic_uninit_irq();
-       mic_dp_uninit();
-       module_put(mdrv->dev->driver->owner);
-}
diff --git a/drivers/misc/mic/card/mic_device.h b/drivers/misc/mic/card/mic_device.h
deleted file mode 100644 (file)
index d6cc69a..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Disclaimer: The codes contained in these modules may be specific to
- * the Intel Software Development Platform codenamed: Knights Ferry, and
- * the Intel product codenamed: Knights Corner, and are not backward
- * compatible with other Intel products. Additionally, Intel will NOT
- * support the codes or instruction set in future products.
- *
- * Intel MIC Card driver.
- */
-#ifndef _MIC_CARD_DEVICE_H_
-#define _MIC_CARD_DEVICE_H_
-
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/mic_bus.h>
-#include "../bus/scif_bus.h"
-#include "../bus/vop_bus.h"
-
-/**
- * struct mic_intr_info - Contains h/w specific interrupt sources info
- *
- * @num_intr: The number of irqs available
- */
-struct mic_intr_info {
-       u32 num_intr;
-};
-
-/**
- * struct mic_irq_info - OS specific irq information
- *
- * @irq_usage_count: usage count array tracking the number of sources
- * assigned for each irq.
- */
-struct mic_irq_info {
-       int *irq_usage_count;
-};
-
-/**
- * struct mic_device -  MIC device information.
- *
- * @mmio: MMIO bar information.
- */
-struct mic_device {
-       struct mic_mw mmio;
-};
-
-/**
- * struct mic_driver - MIC card driver information.
- *
- * @name: Name for MIC driver.
- * @dbg_dir: debugfs directory of this MIC device.
- * @dev: The device backing this MIC.
- * @dp: The pointer to the virtio device page.
- * @mdev: MIC device information for the host.
- * @hotplug_work: Hot plug work for adding/removing virtio devices.
- * @irq_info: The OS specific irq information
- * @intr_info: H/W specific interrupt information.
- * @dma_mbdev: dma device on the MIC virtual bus.
- * @dma_ch - Array of DMA channels
- * @num_dma_ch - Number of DMA channels available
- * @scdev: SCIF device on the SCIF virtual bus.
- * @vpdev: Virtio over PCIe device on the VOP virtual bus.
- */
-struct mic_driver {
-       char name[20];
-       struct dentry *dbg_dir;
-       struct device *dev;
-       void __iomem *dp;
-       struct mic_device mdev;
-       struct work_struct hotplug_work;
-       struct mic_irq_info irq_info;
-       struct mic_intr_info intr_info;
-       struct mbus_device *dma_mbdev;
-       struct dma_chan *dma_ch[MIC_MAX_DMA_CHAN];
-       int num_dma_ch;
-       struct scif_hw_dev *scdev;
-       struct vop_device *vpdev;
-};
-
-/**
- * struct mic_irq - opaque pointer used as cookie
- */
-struct mic_irq;
-
-/**
- * mic_mmio_read - read from an MMIO register.
- * @mw: MMIO register base virtual address.
- * @offset: register offset.
- *
- * RETURNS: register value.
- */
-static inline u32 mic_mmio_read(struct mic_mw *mw, u32 offset)
-{
-       return ioread32(mw->va + offset);
-}
-
-/**
- * mic_mmio_write - write to an MMIO register.
- * @mw: MMIO register base virtual address.
- * @val: the data value to put into the register
- * @offset: register offset.
- *
- * RETURNS: none.
- */
-static inline void
-mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset)
-{
-       iowrite32(val, mw->va + offset);
-}
-
-int mic_driver_init(struct mic_driver *mdrv);
-void mic_driver_uninit(struct mic_driver *mdrv);
-int mic_next_card_db(void);
-struct mic_irq *
-mic_request_card_irq(irq_handler_t handler, irq_handler_t thread_fn,
-                    const char *name, void *data, int db);
-void mic_free_card_irq(struct mic_irq *cookie, void *data);
-u32 mic_read_spad(struct mic_device *mdev, unsigned int idx);
-void mic_send_intr(struct mic_device *mdev, int doorbell);
-void mic_send_p2p_intr(int doorbell, struct mic_mw *mw);
-int mic_db_to_irq(struct mic_driver *mdrv, int db);
-u32 mic_ack_interrupt(struct mic_device *mdev);
-void mic_hw_intr_init(struct mic_driver *mdrv);
-void __iomem *
-mic_card_map(struct mic_device *mdev, dma_addr_t addr, size_t size);
-void mic_card_unmap(struct mic_device *mdev, void __iomem *addr);
-void __init mic_create_card_debug_dir(struct mic_driver *mdrv);
-void mic_delete_card_debug_dir(struct mic_driver *mdrv);
-void __init mic_init_card_debugfs(void);
-void mic_exit_card_debugfs(void);
-#endif
diff --git a/drivers/misc/mic/card/mic_x100.c b/drivers/misc/mic/card/mic_x100.c
deleted file mode 100644 (file)
index c8bff29..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Disclaimer: The codes contained in these modules may be specific to
- * the Intel Software Development Platform codenamed: Knights Ferry, and
- * the Intel product codenamed: Knights Corner, and are not backward
- * compatible with other Intel products. Additionally, Intel will NOT
- * support the codes or instruction set in future products.
- *
- * Intel MIC Card driver.
- */
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-
-#include "../common/mic_dev.h"
-#include "mic_device.h"
-#include "mic_x100.h"
-
-static const char mic_driver_name[] = "mic";
-
-static struct mic_driver g_drv;
-
-/**
- * mic_read_spad - read from the scratchpad register
- * @mdev: pointer to mic_device instance
- * @idx: index to scratchpad register, 0 based
- *
- * This function allows reading of the 32bit scratchpad register.
- *
- * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
- */
-u32 mic_read_spad(struct mic_device *mdev, unsigned int idx)
-{
-       return mic_mmio_read(&mdev->mmio,
-               MIC_X100_SBOX_BASE_ADDRESS +
-               MIC_X100_SBOX_SPAD0 + idx * 4);
-}
-
-/**
- * __mic_send_intr - Send interrupt to Host.
- * @mdev: pointer to mic_device instance
- * @doorbell: Doorbell number.
- */
-void mic_send_intr(struct mic_device *mdev, int doorbell)
-{
-       struct mic_mw *mw = &mdev->mmio;
-
-       if (doorbell > MIC_X100_MAX_DOORBELL_IDX)
-               return;
-       /* Ensure that the interrupt is ordered w.r.t previous stores. */
-       wmb();
-       mic_mmio_write(mw, MIC_X100_SBOX_SDBIC0_DBREQ_BIT,
-                      MIC_X100_SBOX_BASE_ADDRESS +
-                      (MIC_X100_SBOX_SDBIC0 + (4 * doorbell)));
-}
-
-/*
- * mic_x100_send_sbox_intr - Send an MIC_X100_SBOX interrupt to MIC.
- */
-static void mic_x100_send_sbox_intr(struct mic_mw *mw, int doorbell)
-{
-       u64 apic_icr_offset = MIC_X100_SBOX_APICICR0 + doorbell * 8;
-       u32 apicicr_low = mic_mmio_read(mw, MIC_X100_SBOX_BASE_ADDRESS +
-                                       apic_icr_offset);
-
-       /* for MIC we need to make sure we "hit" the send_icr bit (13) */
-       apicicr_low = (apicicr_low | (1 << 13));
-       /*
-        * Ensure that the interrupt is ordered w.r.t. previous stores
-        * to main memory. Fence instructions are not implemented in X100
-        * since execution is in order but a compiler barrier is still
-        * required.
-        */
-       wmb();
-       mic_mmio_write(mw, apicicr_low,
-                      MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
-}
-
-static void mic_x100_send_rdmasr_intr(struct mic_mw *mw, int doorbell)
-{
-       int rdmasr_offset = MIC_X100_SBOX_RDMASR0 + (doorbell << 2);
-       /*
-        * Ensure that the interrupt is ordered w.r.t. previous stores
-        * to main memory. Fence instructions are not implemented in X100
-        * since execution is in order but a compiler barrier is still
-        * required.
-        */
-       wmb();
-       mic_mmio_write(mw, 0, MIC_X100_SBOX_BASE_ADDRESS + rdmasr_offset);
-}
-
-/**
- * mic_ack_interrupt - Device specific interrupt handling.
- * @mdev: pointer to mic_device instance
- *
- * Returns: bitmask of doorbell events triggered.
- */
-u32 mic_ack_interrupt(struct mic_device *mdev)
-{
-       return 0;
-}
-
-static inline int mic_get_sbox_irq(int db)
-{
-       return MIC_X100_IRQ_BASE + db;
-}
-
-static inline int mic_get_rdmasr_irq(int index)
-{
-       return  MIC_X100_RDMASR_IRQ_BASE + index;
-}
-
-void mic_send_p2p_intr(int db, struct mic_mw *mw)
-{
-       int rdmasr_index;
-
-       if (db < MIC_X100_NUM_SBOX_IRQ) {
-               mic_x100_send_sbox_intr(mw, db);
-       } else {
-               rdmasr_index = db - MIC_X100_NUM_SBOX_IRQ;
-               mic_x100_send_rdmasr_intr(mw, rdmasr_index);
-       }
-}
-
-/**
- * mic_hw_intr_init - Initialize h/w specific interrupt
- * information.
- * @mdrv: pointer to mic_driver
- */
-void mic_hw_intr_init(struct mic_driver *mdrv)
-{
-       mdrv->intr_info.num_intr = MIC_X100_NUM_SBOX_IRQ +
-                               MIC_X100_NUM_RDMASR_IRQ;
-}
-
-/**
- * mic_db_to_irq - Retrieve irq number corresponding to a doorbell.
- * @mdrv: pointer to mic_driver
- * @db: The doorbell obtained for which the irq is needed. Doorbell
- * may correspond to an sbox doorbell or an rdmasr index.
- *
- * Returns the irq corresponding to the doorbell.
- */
-int mic_db_to_irq(struct mic_driver *mdrv, int db)
-{
-       int rdmasr_index;
-
-       /*
-        * The total number of doorbell interrupts on the card are 16. Indices
-        * 0-8 falls in the SBOX category and 8-15 fall in the RDMASR category.
-        */
-       if (db < MIC_X100_NUM_SBOX_IRQ) {
-               return mic_get_sbox_irq(db);
-       } else {
-               rdmasr_index = db - MIC_X100_NUM_SBOX_IRQ;
-               return mic_get_rdmasr_irq(rdmasr_index);
-       }
-}
-
-/*
- * mic_card_map - Allocate virtual address for a remote memory region.
- * @mdev: pointer to mic_device instance.
- * @addr: Remote DMA address.
- * @size: Size of the region.
- *
- * Returns: Virtual address backing the remote memory region.
- */
-void __iomem *
-mic_card_map(struct mic_device *mdev, dma_addr_t addr, size_t size)
-{
-       return ioremap(addr, size);
-}
-
-/*
- * mic_card_unmap - Unmap the virtual address for a remote memory region.
- * @mdev: pointer to mic_device instance.
- * @addr: Virtual address for remote memory region.
- *
- * Returns: None.
- */
-void mic_card_unmap(struct mic_device *mdev, void __iomem *addr)
-{
-       iounmap(addr);
-}
-
-static inline struct mic_driver *mbdev_to_mdrv(struct mbus_device *mbdev)
-{
-       return dev_get_drvdata(mbdev->dev.parent);
-}
-
-static struct mic_irq *
-_mic_request_threaded_irq(struct mbus_device *mbdev,
-                         irq_handler_t handler, irq_handler_t thread_fn,
-                         const char *name, void *data, int intr_src)
-{
-       int rc = 0;
-       unsigned int irq = intr_src;
-       unsigned long cookie = irq;
-
-       rc  = request_threaded_irq(irq, handler, thread_fn, 0, name, data);
-       if (rc) {
-               dev_err(mbdev_to_mdrv(mbdev)->dev,
-                       "request_threaded_irq failed rc = %d\n", rc);
-               return ERR_PTR(rc);
-       }
-       return (struct mic_irq *)cookie;
-}
-
-static void _mic_free_irq(struct mbus_device *mbdev,
-                         struct mic_irq *cookie, void *data)
-{
-       unsigned long irq = (unsigned long)cookie;
-       free_irq(irq, data);
-}
-
-static void _mic_ack_interrupt(struct mbus_device *mbdev, int num)
-{
-       mic_ack_interrupt(&mbdev_to_mdrv(mbdev)->mdev);
-}
-
-static struct mbus_hw_ops mbus_hw_ops = {
-       .request_threaded_irq = _mic_request_threaded_irq,
-       .free_irq = _mic_free_irq,
-       .ack_interrupt = _mic_ack_interrupt,
-};
-
-static int __init mic_probe(struct platform_device *pdev)
-{
-       struct mic_driver *mdrv = &g_drv;
-       struct mic_device *mdev = &mdrv->mdev;
-       int rc = 0;
-
-       mdrv->dev = &pdev->dev;
-       snprintf(mdrv->name, sizeof(mic_driver_name), mic_driver_name);
-
-       /* FIXME: use dma_set_mask_and_coherent() and check result */
-       dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
-
-       mdev->mmio.pa = MIC_X100_MMIO_BASE;
-       mdev->mmio.len = MIC_X100_MMIO_LEN;
-       mdev->mmio.va = devm_ioremap(&pdev->dev, MIC_X100_MMIO_BASE,
-                                    MIC_X100_MMIO_LEN);
-       if (!mdev->mmio.va) {
-               dev_err(&pdev->dev, "Cannot remap MMIO BAR\n");
-               rc = -EIO;
-               goto done;
-       }
-       mic_hw_intr_init(mdrv);
-       platform_set_drvdata(pdev, mdrv);
-       mdrv->dma_mbdev = mbus_register_device(mdrv->dev, MBUS_DEV_DMA_MIC,
-                                              NULL, &mbus_hw_ops, 0,
-                                              mdrv->mdev.mmio.va);
-       if (IS_ERR(mdrv->dma_mbdev)) {
-               rc = PTR_ERR(mdrv->dma_mbdev);
-               dev_err(&pdev->dev, "mbus_add_device failed rc %d\n", rc);
-               goto done;
-       }
-       rc = mic_driver_init(mdrv);
-       if (rc) {
-               dev_err(&pdev->dev, "mic_driver_init failed rc %d\n", rc);
-               goto remove_dma;
-       }
-done:
-       return rc;
-remove_dma:
-       mbus_unregister_device(mdrv->dma_mbdev);
-       return rc;
-}
-
-static int mic_remove(struct platform_device *pdev)
-{
-       struct mic_driver *mdrv = &g_drv;
-
-       mic_driver_uninit(mdrv);
-       mbus_unregister_device(mdrv->dma_mbdev);
-       return 0;
-}
-
-static void mic_platform_shutdown(struct platform_device *pdev)
-{
-       mic_remove(pdev);
-}
-
-static struct platform_driver __refdata mic_platform_driver = {
-       .probe = mic_probe,
-       .remove = mic_remove,
-       .shutdown = mic_platform_shutdown,
-       .driver         = {
-               .name   = mic_driver_name,
-       },
-};
-
-static struct platform_device *mic_platform_dev;
-
-static int __init mic_init(void)
-{
-       int ret;
-       struct cpuinfo_x86 *c = &cpu_data(0);
-
-       if (!(c->x86 == 11 && c->x86_model == 1)) {
-               ret = -ENODEV;
-               pr_err("%s not running on X100 ret %d\n", __func__, ret);
-               goto done;
-       }
-
-       request_module("mic_x100_dma");
-       mic_init_card_debugfs();
-
-       mic_platform_dev = platform_device_register_simple(mic_driver_name,
-                                                          0, NULL, 0);
-       ret = PTR_ERR_OR_ZERO(mic_platform_dev);
-       if (ret) {
-               pr_err("platform_device_register_full ret %d\n", ret);
-               goto cleanup_debugfs;
-       }
-       ret = platform_driver_register(&mic_platform_driver);
-       if (ret) {
-               pr_err("platform_driver_register ret %d\n", ret);
-               goto device_unregister;
-       }
-       return ret;
-
-device_unregister:
-       platform_device_unregister(mic_platform_dev);
-cleanup_debugfs:
-       mic_exit_card_debugfs();
-done:
-       return ret;
-}
-
-static void __exit mic_exit(void)
-{
-       platform_driver_unregister(&mic_platform_driver);
-       platform_device_unregister(mic_platform_dev);
-       mic_exit_card_debugfs();
-}
-
-module_init(mic_init);
-module_exit(mic_exit);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Intel(R) MIC X100 Card driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/card/mic_x100.h b/drivers/misc/mic/card/mic_x100.h
deleted file mode 100644 (file)
index 46644dd..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Disclaimer: The codes contained in these modules may be specific to
- * the Intel Software Development Platform codenamed: Knights Ferry, and
- * the Intel product codenamed: Knights Corner, and are not backward
- * compatible with other Intel products. Additionally, Intel will NOT
- * support the codes or instruction set in future products.
- *
- * Intel MIC Card driver.
- */
-#ifndef _MIC_X100_CARD_H_
-#define _MIC_X100_CARD_H_
-
-#define MIC_X100_MMIO_BASE 0x08007C0000ULL
-#define MIC_X100_MMIO_LEN 0x00020000ULL
-#define MIC_X100_SBOX_BASE_ADDRESS 0x00010000ULL
-
-#define MIC_X100_SBOX_SPAD0 0x0000AB20
-#define MIC_X100_SBOX_SDBIC0 0x0000CC90
-#define MIC_X100_SBOX_SDBIC0_DBREQ_BIT 0x80000000
-#define MIC_X100_SBOX_RDMASR0  0x0000B180
-#define MIC_X100_SBOX_APICICR0 0x0000A9D0
-
-#define MIC_X100_MAX_DOORBELL_IDX 8
-
-#define MIC_X100_NUM_SBOX_IRQ 8
-#define MIC_X100_NUM_RDMASR_IRQ 8
-#define MIC_X100_SBOX_IRQ_BASE 0
-#define MIC_X100_RDMASR_IRQ_BASE 17
-
-#define MIC_X100_IRQ_BASE 26
-
-#endif
diff --git a/drivers/misc/mic/common/mic_dev.h b/drivers/misc/mic/common/mic_dev.h
deleted file mode 100644 (file)
index f94f08d..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Intel MIC driver.
- */
-#ifndef __MIC_DEV_H__
-#define __MIC_DEV_H__
-
-/* The maximum number of MIC devices supported in a single host system. */
-#define MIC_MAX_NUM_DEVS 128
-
-/**
- * enum mic_hw_family - The hardware family to which a device belongs.
- */
-enum mic_hw_family {
-       MIC_FAMILY_X100 = 0,
-       MIC_FAMILY_X200,
-       MIC_FAMILY_UNKNOWN,
-       MIC_FAMILY_LAST
-};
-
-/**
- * struct mic_mw - MIC memory window
- *
- * @pa: Base physical address.
- * @va: Base ioremap'd virtual address.
- * @len: Size of the memory window.
- */
-struct mic_mw {
-       phys_addr_t pa;
-       void __iomem *va;
-       resource_size_t len;
-};
-
-/*
- * Scratch pad register offsets used by the host to communicate
- * device page DMA address to the card.
- */
-#define MIC_DPLO_SPAD 14
-#define MIC_DPHI_SPAD 15
-
-/*
- * These values are supposed to be in the config_change field of the
- * device page when the host sends a config change interrupt to the card.
- */
-#define MIC_VIRTIO_PARAM_DEV_REMOVE 0x1
-#define MIC_VIRTIO_PARAM_CONFIG_CHANGED 0x2
-
-/* Maximum number of DMA channels */
-#define MIC_MAX_DMA_CHAN 4
-
-#endif
diff --git a/drivers/misc/mic/cosm/Makefile b/drivers/misc/mic/cosm/Makefile
deleted file mode 100644 (file)
index 97d74cb..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile - Intel MIC Coprocessor State Management (COSM) Driver
-# Copyright(c) 2015, Intel Corporation.
-#
-obj-$(CONFIG_MIC_COSM) += mic_cosm.o
-
-mic_cosm-objs := cosm_main.o
-mic_cosm-objs += cosm_debugfs.o
-mic_cosm-objs += cosm_sysfs.o
-mic_cosm-objs += cosm_scif_server.o
diff --git a/drivers/misc/mic/cosm/cosm_debugfs.c b/drivers/misc/mic/cosm/cosm_debugfs.c
deleted file mode 100644 (file)
index cb55653..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * Intel MIC Coprocessor State Management (COSM) Driver
- */
-
-#include <linux/debugfs.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include "cosm_main.h"
-
-/* Debugfs parent dir */
-static struct dentry *cosm_dbg;
-
-/*
- * log_buf_show - Display MIC kernel log buffer
- *
- * log_buf addr/len is read from System.map by user space
- * and populated in sysfs entries.
- */
-static int log_buf_show(struct seq_file *s, void *unused)
-{
-       void __iomem *log_buf_va;
-       int __iomem *log_buf_len_va;
-       struct cosm_device *cdev = s->private;
-       void *kva;
-       int size;
-       u64 aper_offset;
-
-       if (!cdev || !cdev->log_buf_addr || !cdev->log_buf_len)
-               goto done;
-
-       mutex_lock(&cdev->cosm_mutex);
-       switch (cdev->state) {
-       case MIC_BOOTING:
-       case MIC_ONLINE:
-       case MIC_SHUTTING_DOWN:
-               break;
-       default:
-               goto unlock;
-       }
-
-       /*
-        * Card kernel will never be relocated and any kernel text/data mapping
-        * can be translated to phys address by subtracting __START_KERNEL_map.
-        */
-       aper_offset = (u64)cdev->log_buf_len - __START_KERNEL_map;
-       log_buf_len_va = cdev->hw_ops->aper(cdev)->va + aper_offset;
-       aper_offset = (u64)cdev->log_buf_addr - __START_KERNEL_map;
-       log_buf_va = cdev->hw_ops->aper(cdev)->va + aper_offset;
-
-       size = ioread32(log_buf_len_va);
-       kva = kmalloc(size, GFP_KERNEL);
-       if (!kva)
-               goto unlock;
-
-       memcpy_fromio(kva, log_buf_va, size);
-       seq_write(s, kva, size);
-       kfree(kva);
-unlock:
-       mutex_unlock(&cdev->cosm_mutex);
-done:
-       return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(log_buf);
-
-/*
- * force_reset_show - Force MIC reset
- *
- * Invokes the force_reset COSM bus op instead of the standard reset
- * op in case a force reset of the MIC device is required
- */
-static int force_reset_show(struct seq_file *s, void *pos)
-{
-       struct cosm_device *cdev = s->private;
-
-       cosm_stop(cdev, true);
-       return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(force_reset);
-
-void cosm_create_debug_dir(struct cosm_device *cdev)
-{
-       char name[16];
-
-       if (!cosm_dbg)
-               return;
-
-       scnprintf(name, sizeof(name), "mic%d", cdev->index);
-       cdev->dbg_dir = debugfs_create_dir(name, cosm_dbg);
-
-       debugfs_create_file("log_buf", 0444, cdev->dbg_dir, cdev,
-                           &log_buf_fops);
-       debugfs_create_file("force_reset", 0444, cdev->dbg_dir, cdev,
-                           &force_reset_fops);
-}
-
-void cosm_delete_debug_dir(struct cosm_device *cdev)
-{
-       debugfs_remove_recursive(cdev->dbg_dir);
-}
-
-void cosm_init_debugfs(void)
-{
-       cosm_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
-}
-
-void cosm_exit_debugfs(void)
-{
-       debugfs_remove(cosm_dbg);
-}
diff --git a/drivers/misc/mic/cosm/cosm_main.c b/drivers/misc/mic/cosm/cosm_main.c
deleted file mode 100644 (file)
index ebb0eac..0000000
+++ /dev/null
@@ -1,382 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * Intel MIC Coprocessor State Management (COSM) Driver
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/idr.h>
-#include <linux/slab.h>
-#include <linux/cred.h>
-#include "cosm_main.h"
-
-static const char cosm_driver_name[] = "mic";
-
-/* COSM ID allocator */
-static struct ida g_cosm_ida;
-/* Class of MIC devices for sysfs accessibility. */
-static struct class *g_cosm_class;
-/* Number of MIC devices */
-static atomic_t g_num_dev;
-
-/**
- * cosm_hw_reset - Issue a HW reset for the MIC device
- * @cdev: pointer to cosm_device instance
- * @force: force a MIC to reset even if it is already reset and ready
- */
-static void cosm_hw_reset(struct cosm_device *cdev, bool force)
-{
-       int i;
-
-#define MIC_RESET_TO (45)
-       if (force && cdev->hw_ops->force_reset)
-               cdev->hw_ops->force_reset(cdev);
-       else
-               cdev->hw_ops->reset(cdev);
-
-       for (i = 0; i < MIC_RESET_TO; i++) {
-               if (cdev->hw_ops->ready(cdev)) {
-                       cosm_set_state(cdev, MIC_READY);
-                       return;
-               }
-               /*
-                * Resets typically take 10s of seconds to complete.
-                * Since an MMIO read is required to check if the
-                * firmware is ready or not, a 1 second delay works nicely.
-                */
-               msleep(1000);
-       }
-       cosm_set_state(cdev, MIC_RESET_FAILED);
-}
-
-/**
- * cosm_start - Start the MIC
- * @cdev: pointer to cosm_device instance
- *
- * This function prepares an MIC for boot and initiates boot.
- * RETURNS: An appropriate -ERRNO error value on error, or 0 for success.
- */
-int cosm_start(struct cosm_device *cdev)
-{
-       const struct cred *orig_cred;
-       struct cred *override_cred;
-       int rc;
-
-       mutex_lock(&cdev->cosm_mutex);
-       if (!cdev->bootmode) {
-               dev_err(&cdev->dev, "%s %d bootmode not set\n",
-                       __func__, __LINE__);
-               rc = -EINVAL;
-               goto unlock_ret;
-       }
-retry:
-       if (cdev->state != MIC_READY) {
-               dev_err(&cdev->dev, "%s %d MIC state not READY\n",
-                       __func__, __LINE__);
-               rc = -EINVAL;
-               goto unlock_ret;
-       }
-       if (!cdev->hw_ops->ready(cdev)) {
-               cosm_hw_reset(cdev, false);
-               /*
-                * The state will either be MIC_READY if the reset succeeded
-                * or MIC_RESET_FAILED if the firmware reset failed.
-                */
-               goto retry;
-       }
-
-       /*
-        * Set credentials to root to allow non-root user to download initramsfs
-        * with 600 permissions
-        */
-       override_cred = prepare_creds();
-       if (!override_cred) {
-               dev_err(&cdev->dev, "%s %d prepare_creds failed\n",
-                       __func__, __LINE__);
-               rc = -ENOMEM;
-               goto unlock_ret;
-       }
-       override_cred->fsuid = GLOBAL_ROOT_UID;
-       orig_cred = override_creds(override_cred);
-
-       rc = cdev->hw_ops->start(cdev, cdev->index);
-
-       revert_creds(orig_cred);
-       put_cred(override_cred);
-       if (rc)
-               goto unlock_ret;
-
-       /*
-        * If linux is being booted, card is treated 'online' only
-        * when the scif interface in the card is up. If anything else
-        * is booted, we set card to 'online' immediately.
-        */
-       if (!strcmp(cdev->bootmode, "linux"))
-               cosm_set_state(cdev, MIC_BOOTING);
-       else
-               cosm_set_state(cdev, MIC_ONLINE);
-unlock_ret:
-       mutex_unlock(&cdev->cosm_mutex);
-       if (rc)
-               dev_err(&cdev->dev, "cosm_start failed rc %d\n", rc);
-       return rc;
-}
-
-/**
- * cosm_stop - Prepare the MIC for reset and trigger reset
- * @cdev: pointer to cosm_device instance
- * @force: force a MIC to reset even if it is already reset and ready.
- *
- * RETURNS: None
- */
-void cosm_stop(struct cosm_device *cdev, bool force)
-{
-       mutex_lock(&cdev->cosm_mutex);
-       if (cdev->state != MIC_READY || force) {
-               /*
-                * Don't call hw_ops if they have been called previously.
-                * stop(..) calls device_unregister and will crash the system if
-                * called multiple times.
-                */
-               u8 state = cdev->state == MIC_RESETTING ?
-                                       cdev->prev_state : cdev->state;
-               bool call_hw_ops = state != MIC_RESET_FAILED &&
-                                       state != MIC_READY;
-
-               if (cdev->state != MIC_RESETTING)
-                       cosm_set_state(cdev, MIC_RESETTING);
-               cdev->heartbeat_watchdog_enable = false;
-               if (call_hw_ops)
-                       cdev->hw_ops->stop(cdev, force);
-               cosm_hw_reset(cdev, force);
-               cosm_set_shutdown_status(cdev, MIC_NOP);
-               if (call_hw_ops && cdev->hw_ops->post_reset)
-                       cdev->hw_ops->post_reset(cdev, cdev->state);
-       }
-       mutex_unlock(&cdev->cosm_mutex);
-       flush_work(&cdev->scif_work);
-}
-
-/**
- * cosm_reset_trigger_work - Trigger MIC reset
- * @work: The work structure
- *
- * This work is scheduled whenever the host wants to reset the MIC.
- */
-static void cosm_reset_trigger_work(struct work_struct *work)
-{
-       struct cosm_device *cdev = container_of(work, struct cosm_device,
-                                               reset_trigger_work);
-       cosm_stop(cdev, false);
-}
-
-/**
- * cosm_reset - Schedule MIC reset
- * @cdev: pointer to cosm_device instance
- *
- * RETURNS: An -EINVAL if the card is already READY or 0 for success.
- */
-int cosm_reset(struct cosm_device *cdev)
-{
-       int rc = 0;
-
-       mutex_lock(&cdev->cosm_mutex);
-       if (cdev->state != MIC_READY) {
-               if (cdev->state != MIC_RESETTING) {
-                       cdev->prev_state = cdev->state;
-                       cosm_set_state(cdev, MIC_RESETTING);
-                       schedule_work(&cdev->reset_trigger_work);
-               }
-       } else {
-               dev_err(&cdev->dev, "%s %d MIC is READY\n", __func__, __LINE__);
-               rc = -EINVAL;
-       }
-       mutex_unlock(&cdev->cosm_mutex);
-       return rc;
-}
-
-/**
- * cosm_shutdown - Initiate MIC shutdown.
- * @cdev: pointer to cosm_device instance
- *
- * RETURNS: None
- */
-int cosm_shutdown(struct cosm_device *cdev)
-{
-       struct cosm_msg msg = { .id = COSM_MSG_SHUTDOWN };
-       int rc = 0;
-
-       mutex_lock(&cdev->cosm_mutex);
-       if (cdev->state != MIC_ONLINE) {
-               rc = -EINVAL;
-               dev_err(&cdev->dev, "%s %d skipping shutdown in state: %s\n",
-                       __func__, __LINE__, cosm_state_string[cdev->state]);
-               goto err;
-       }
-
-       if (!cdev->epd) {
-               rc = -ENOTCONN;
-               dev_err(&cdev->dev, "%s %d scif endpoint not connected rc %d\n",
-                       __func__, __LINE__, rc);
-               goto err;
-       }
-
-       rc = scif_send(cdev->epd, &msg, sizeof(msg), SCIF_SEND_BLOCK);
-       if (rc < 0) {
-               dev_err(&cdev->dev, "%s %d scif_send failed rc %d\n",
-                       __func__, __LINE__, rc);
-               goto err;
-       }
-       cdev->heartbeat_watchdog_enable = false;
-       cosm_set_state(cdev, MIC_SHUTTING_DOWN);
-       rc = 0;
-err:
-       mutex_unlock(&cdev->cosm_mutex);
-       return rc;
-}
-
-static int cosm_driver_probe(struct cosm_device *cdev)
-{
-       int rc;
-
-       /* Initialize SCIF server at first probe */
-       if (atomic_add_return(1, &g_num_dev) == 1) {
-               rc = cosm_scif_init();
-               if (rc)
-                       goto scif_exit;
-       }
-       mutex_init(&cdev->cosm_mutex);
-       INIT_WORK(&cdev->reset_trigger_work, cosm_reset_trigger_work);
-       INIT_WORK(&cdev->scif_work, cosm_scif_work);
-       cdev->sysfs_heartbeat_enable = true;
-       cosm_sysfs_init(cdev);
-       cdev->sdev = device_create_with_groups(g_cosm_class, cdev->dev.parent,
-                              MKDEV(0, cdev->index), cdev, cdev->attr_group,
-                              "mic%d", cdev->index);
-       if (IS_ERR(cdev->sdev)) {
-               rc = PTR_ERR(cdev->sdev);
-               dev_err(&cdev->dev, "device_create_with_groups failed rc %d\n",
-                       rc);
-               goto scif_exit;
-       }
-
-       cdev->state_sysfs = sysfs_get_dirent(cdev->sdev->kobj.sd,
-               "state");
-       if (!cdev->state_sysfs) {
-               rc = -ENODEV;
-               dev_err(&cdev->dev, "sysfs_get_dirent failed rc %d\n", rc);
-               goto destroy_device;
-       }
-       cosm_create_debug_dir(cdev);
-       return 0;
-destroy_device:
-       device_destroy(g_cosm_class, MKDEV(0, cdev->index));
-scif_exit:
-       if (atomic_dec_and_test(&g_num_dev))
-               cosm_scif_exit();
-       return rc;
-}
-
-static void cosm_driver_remove(struct cosm_device *cdev)
-{
-       cosm_delete_debug_dir(cdev);
-       sysfs_put(cdev->state_sysfs);
-       device_destroy(g_cosm_class, MKDEV(0, cdev->index));
-       flush_work(&cdev->reset_trigger_work);
-       cosm_stop(cdev, false);
-       if (atomic_dec_and_test(&g_num_dev))
-               cosm_scif_exit();
-
-       /* These sysfs entries might have allocated */
-       kfree(cdev->cmdline);
-       kfree(cdev->firmware);
-       kfree(cdev->ramdisk);
-       kfree(cdev->bootmode);
-}
-
-static int cosm_suspend(struct device *dev)
-{
-       struct cosm_device *cdev = dev_to_cosm(dev);
-
-       mutex_lock(&cdev->cosm_mutex);
-       switch (cdev->state) {
-       /**
-        * Suspend/freeze hooks in userspace have already shutdown the card.
-        * Card should be 'ready' in most cases. It is however possible that
-        * some userspace application initiated a boot. In those cases, we
-        * simply reset the card.
-        */
-       case MIC_ONLINE:
-       case MIC_BOOTING:
-       case MIC_SHUTTING_DOWN:
-               mutex_unlock(&cdev->cosm_mutex);
-               cosm_stop(cdev, false);
-               break;
-       default:
-               mutex_unlock(&cdev->cosm_mutex);
-               break;
-       }
-       return 0;
-}
-
-static const struct dev_pm_ops cosm_pm_ops = {
-       .suspend = cosm_suspend,
-       .freeze = cosm_suspend
-};
-
-static struct cosm_driver cosm_driver = {
-       .driver = {
-               .name =  KBUILD_MODNAME,
-               .owner = THIS_MODULE,
-               .pm = &cosm_pm_ops,
-       },
-       .probe = cosm_driver_probe,
-       .remove = cosm_driver_remove
-};
-
-static int __init cosm_init(void)
-{
-       int ret;
-
-       cosm_init_debugfs();
-
-       g_cosm_class = class_create(THIS_MODULE, cosm_driver_name);
-       if (IS_ERR(g_cosm_class)) {
-               ret = PTR_ERR(g_cosm_class);
-               pr_err("class_create failed ret %d\n", ret);
-               goto cleanup_debugfs;
-       }
-
-       ida_init(&g_cosm_ida);
-       ret = cosm_register_driver(&cosm_driver);
-       if (ret) {
-               pr_err("cosm_register_driver failed ret %d\n", ret);
-               goto ida_destroy;
-       }
-       return 0;
-ida_destroy:
-       ida_destroy(&g_cosm_ida);
-       class_destroy(g_cosm_class);
-cleanup_debugfs:
-       cosm_exit_debugfs();
-       return ret;
-}
-
-static void __exit cosm_exit(void)
-{
-       cosm_unregister_driver(&cosm_driver);
-       ida_destroy(&g_cosm_ida);
-       class_destroy(g_cosm_class);
-       cosm_exit_debugfs();
-}
-
-module_init(cosm_init);
-module_exit(cosm_exit);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Intel(R) MIC Coprocessor State Management (COSM) Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/cosm/cosm_main.h b/drivers/misc/mic/cosm/cosm_main.h
deleted file mode 100644 (file)
index 5188ad2..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * Intel MIC Coprocessor State Management (COSM) Driver
- */
-#ifndef _COSM_COSM_H_
-#define _COSM_COSM_H_
-
-#include <linux/scif.h>
-#include "../bus/cosm_bus.h"
-
-#define COSM_HEARTBEAT_SEND_SEC 30
-#define SCIF_COSM_LISTEN_PORT  201
-
-/**
- * enum COSM msg id's
- * @COSM_MSG_SHUTDOWN: host->card trigger shutdown
- * @COSM_MSG_SYNC_TIME: host->card send host time to card to sync time
- * @COSM_MSG_HEARTBEAT: card->host heartbeat
- * @COSM_MSG_SHUTDOWN_STATUS: card->host with shutdown status as payload
- */
-enum cosm_msg_id {
-       COSM_MSG_SHUTDOWN,
-       COSM_MSG_SYNC_TIME,
-       COSM_MSG_HEARTBEAT,
-       COSM_MSG_SHUTDOWN_STATUS,
-};
-
-struct cosm_msg {
-       u64 id;
-       union {
-               u64 shutdown_status;
-               struct {
-                       u64 tv_sec;
-                       u64 tv_nsec;
-               } timespec;
-       };
-};
-
-extern const char * const cosm_state_string[];
-extern const char * const cosm_shutdown_status_string[];
-
-void cosm_sysfs_init(struct cosm_device *cdev);
-int cosm_start(struct cosm_device *cdev);
-void cosm_stop(struct cosm_device *cdev, bool force);
-int cosm_reset(struct cosm_device *cdev);
-int cosm_shutdown(struct cosm_device *cdev);
-void cosm_set_state(struct cosm_device *cdev, u8 state);
-void cosm_set_shutdown_status(struct cosm_device *cdev, u8 status);
-void cosm_init_debugfs(void);
-void cosm_exit_debugfs(void);
-void cosm_create_debug_dir(struct cosm_device *cdev);
-void cosm_delete_debug_dir(struct cosm_device *cdev);
-int cosm_scif_init(void);
-void cosm_scif_exit(void);
-void cosm_scif_work(struct work_struct *work);
-
-#endif
diff --git a/drivers/misc/mic/cosm/cosm_scif_server.c b/drivers/misc/mic/cosm/cosm_scif_server.c
deleted file mode 100644 (file)
index 7baec9f..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * Intel MIC Coprocessor State Management (COSM) Driver
- */
-#include <linux/kthread.h>
-#include <linux/sched/signal.h>
-
-#include "cosm_main.h"
-
-/*
- * The COSM driver uses SCIF to communicate between the management node and the
- * MIC cards. SCIF is used to (a) Send a shutdown command to the card (b)
- * receive a shutdown status back from the card upon completion of shutdown and
- * (c) receive periodic heartbeat messages from the card used to deduce if the
- * card has crashed.
- *
- * A COSM server consisting of a SCIF listening endpoint waits for incoming
- * connections from the card. Upon acceptance of the connection, a separate
- * work-item is scheduled to handle SCIF message processing for that card. The
- * life-time of this work-item is therefore the time from which the connection
- * from a card is accepted to the time at which the connection is closed. A new
- * work-item starts each time the card boots and is alive till the card (a)
- * shuts down (b) is reset (c) crashes (d) cosm_client driver on the card is
- * unloaded.
- *
- * From the point of view of COSM interactions with SCIF during card
- * shutdown, reset and crash are as follows:
- *
- * Card shutdown
- * -------------
- * 1. COSM client on the card invokes orderly_poweroff() in response to SHUTDOWN
- *    message from the host.
- * 2. Card driver shutdown callback invokes scif_unregister_device(..) resulting
- *    in scif_remove(..) getting called on the card
- * 3. scif_remove -> scif_stop -> scif_handle_remove_node ->
- *    scif_peer_unregister_device -> device_unregister for the host peer device
- * 4. During device_unregister remove(..) method of cosm_client is invoked which
- *    closes the COSM SCIF endpoint on the card. This results in a SCIF_DISCNCT
- *    message being sent to host SCIF. SCIF_DISCNCT message processing on the
- *    host SCIF sets the host COSM SCIF endpoint state to DISCONNECTED and wakes
- *    up the host COSM thread blocked in scif_poll(..) resulting in
- *    scif_poll(..)  returning EPOLLHUP.
- * 5. On the card, scif_peer_release_dev is next called which results in an
- *    SCIF_EXIT message being sent to the host and after receiving the
- *    SCIF_EXIT_ACK from the host the peer device teardown on the card is
- *    complete.
- * 6. As part of the SCIF_EXIT message processing on the host, host sends a
- *    SCIF_REMOVE_NODE to itself corresponding to the card being removed. This
- *    starts a similar SCIF peer device teardown sequence on the host
- *    corresponding to the card being shut down.
- *
- * Card reset
- * ----------
- * The case of interest here is when the card has not been previously shut down
- * since most of the steps below are skipped in that case:
-
- * 1. cosm_stop(..) invokes hw_ops->stop(..) method of the base PCIe driver
- *    which unregisters the SCIF HW device resulting in scif_remove(..) being
- *    called on the host.
- * 2. scif_remove(..) calls scif_disconnect_node(..) which results in a
- *    SCIF_EXIT message being sent to the card.
- * 3. The card executes scif_stop() as part of SCIF_EXIT message
- *    processing. This results in the COSM endpoint on the card being closed and
- *    the SCIF host peer device on the card getting unregistered similar to
- *    steps 3, 4 and 5 for the card shutdown case above. scif_poll(..) on the
- *    host returns EPOLLHUP as a result.
- * 4. On the host, card peer device unregister and SCIF HW remove(..) also
- *    subsequently complete.
- *
- * Card crash
- * ----------
- * If a reset is issued after the card has crashed, there is no SCIF_DISCNT
- * message from the card which would result in scif_poll(..) returning
- * EPOLLHUP. In this case when the host SCIF driver sends a SCIF_REMOVE_NODE
- * message to itself resulting in the card SCIF peer device being unregistered,
- * this results in a scif_peer_release_dev -> scif_cleanup_scifdev->
- * scif_invalidate_ep call sequence which sets the endpoint state to
- * DISCONNECTED and results in scif_poll(..) returning EPOLLHUP.
- */
-
-#define COSM_SCIF_BACKLOG 16
-#define COSM_HEARTBEAT_CHECK_DELTA_SEC 10
-#define COSM_HEARTBEAT_TIMEOUT_SEC \
-               (COSM_HEARTBEAT_SEND_SEC + COSM_HEARTBEAT_CHECK_DELTA_SEC)
-#define COSM_HEARTBEAT_TIMEOUT_MSEC (COSM_HEARTBEAT_TIMEOUT_SEC * MSEC_PER_SEC)
-
-static struct task_struct *server_thread;
-static scif_epd_t listen_epd;
-
-/* Publish MIC card's shutdown status to user space MIC daemon */
-static void cosm_update_mic_status(struct cosm_device *cdev)
-{
-       if (cdev->shutdown_status_int != MIC_NOP) {
-               cosm_set_shutdown_status(cdev, cdev->shutdown_status_int);
-               cdev->shutdown_status_int = MIC_NOP;
-       }
-}
-
-/* Store MIC card's shutdown status internally when it is received */
-static void cosm_shutdown_status_int(struct cosm_device *cdev,
-                                    enum mic_status shutdown_status)
-{
-       switch (shutdown_status) {
-       case MIC_HALTED:
-       case MIC_POWER_OFF:
-       case MIC_RESTART:
-       case MIC_CRASHED:
-               break;
-       default:
-               dev_err(&cdev->dev, "%s %d Unexpected shutdown_status %d\n",
-                       __func__, __LINE__, shutdown_status);
-               return;
-       };
-       cdev->shutdown_status_int = shutdown_status;
-       cdev->heartbeat_watchdog_enable = false;
-
-       if (cdev->state != MIC_SHUTTING_DOWN)
-               cosm_set_state(cdev, MIC_SHUTTING_DOWN);
-}
-
-/* Non-blocking recv. Read and process all available messages */
-static void cosm_scif_recv(struct cosm_device *cdev)
-{
-       struct cosm_msg msg;
-       int rc;
-
-       while (1) {
-               rc = scif_recv(cdev->epd, &msg, sizeof(msg), 0);
-               if (!rc) {
-                       break;
-               } else if (rc < 0) {
-                       dev_dbg(&cdev->dev, "%s: %d rc %d\n",
-                               __func__, __LINE__, rc);
-                       break;
-               }
-               dev_dbg(&cdev->dev, "%s: %d rc %d id 0x%llx\n",
-                       __func__, __LINE__, rc, msg.id);
-
-               switch (msg.id) {
-               case COSM_MSG_SHUTDOWN_STATUS:
-                       cosm_shutdown_status_int(cdev, msg.shutdown_status);
-                       break;
-               case COSM_MSG_HEARTBEAT:
-                       /* Nothing to do, heartbeat only unblocks scif_poll */
-                       break;
-               default:
-                       dev_err(&cdev->dev, "%s: %d unknown msg.id %lld\n",
-                               __func__, __LINE__, msg.id);
-                       break;
-               }
-       }
-}
-
-/* Publish crashed status for this MIC card */
-static void cosm_set_crashed(struct cosm_device *cdev)
-{
-       dev_err(&cdev->dev, "node alive timeout\n");
-       cosm_shutdown_status_int(cdev, MIC_CRASHED);
-       cosm_update_mic_status(cdev);
-}
-
-/* Send host time to the MIC card to sync system time between host and MIC */
-static void cosm_send_time(struct cosm_device *cdev)
-{
-       struct cosm_msg msg = { .id = COSM_MSG_SYNC_TIME };
-       struct timespec64 ts;
-       int rc;
-
-       ktime_get_real_ts64(&ts);
-       msg.timespec.tv_sec = ts.tv_sec;
-       msg.timespec.tv_nsec = ts.tv_nsec;
-
-       rc = scif_send(cdev->epd, &msg, sizeof(msg), SCIF_SEND_BLOCK);
-       if (rc < 0)
-               dev_err(&cdev->dev, "%s %d scif_send failed rc %d\n",
-                       __func__, __LINE__, rc);
-}
-
-/*
- * Close this cosm_device's endpoint after its peer endpoint on the card has
- * been closed. In all cases except MIC card crash EPOLLHUP on the host is
- * triggered by the client's endpoint being closed.
- */
-static void cosm_scif_close(struct cosm_device *cdev)
-{
-       /*
-        * Because SHUTDOWN_STATUS message is sent by the MIC cards in the
-        * reboot notifier when shutdown is still not complete, we notify mpssd
-        * to reset the card when SCIF endpoint is closed.
-        */
-       cosm_update_mic_status(cdev);
-       scif_close(cdev->epd);
-       cdev->epd = NULL;
-       dev_dbg(&cdev->dev, "%s %d\n", __func__, __LINE__);
-}
-
-/*
- * Set card state to ONLINE when a new SCIF connection from a MIC card is
- * received. Normally the state is BOOTING when the connection comes in, but can
- * be ONLINE if cosm_client driver on the card was unloaded and then reloaded.
- */
-static int cosm_set_online(struct cosm_device *cdev)
-{
-       int rc = 0;
-
-       if (MIC_BOOTING == cdev->state || MIC_ONLINE == cdev->state) {
-               cdev->heartbeat_watchdog_enable = cdev->sysfs_heartbeat_enable;
-               cdev->epd = cdev->newepd;
-               if (cdev->state == MIC_BOOTING)
-                       cosm_set_state(cdev, MIC_ONLINE);
-               cosm_send_time(cdev);
-               dev_dbg(&cdev->dev, "%s %d\n", __func__, __LINE__);
-       } else {
-               dev_warn(&cdev->dev, "%s %d not going online in state: %s\n",
-                        __func__, __LINE__, cosm_state_string[cdev->state]);
-               rc = -EINVAL;
-       }
-       /* Drop reference acquired by bus_find_device in the server thread */
-       put_device(&cdev->dev);
-       return rc;
-}
-
-/*
- * Work function for handling work for a SCIF connection from a particular MIC
- * card. It first sets the card state to ONLINE and then calls scif_poll to
- * block on activity such as incoming messages on the SCIF endpoint. When the
- * endpoint is closed, the work function exits, completing its life cycle, from
- * MIC card boot to card shutdown/reset/crash.
- */
-void cosm_scif_work(struct work_struct *work)
-{
-       struct cosm_device *cdev = container_of(work, struct cosm_device,
-                                               scif_work);
-       struct scif_pollepd pollepd;
-       int rc;
-
-       mutex_lock(&cdev->cosm_mutex);
-       if (cosm_set_online(cdev))
-               goto exit;
-
-       while (1) {
-               pollepd.epd = cdev->epd;
-               pollepd.events = EPOLLIN;
-
-               /* Drop the mutex before blocking in scif_poll(..) */
-               mutex_unlock(&cdev->cosm_mutex);
-               /* poll(..) with timeout on our endpoint */
-               rc = scif_poll(&pollepd, 1, COSM_HEARTBEAT_TIMEOUT_MSEC);
-               mutex_lock(&cdev->cosm_mutex);
-               if (rc < 0) {
-                       dev_err(&cdev->dev, "%s %d scif_poll rc %d\n",
-                               __func__, __LINE__, rc);
-                       continue;
-               }
-
-               /* There is a message from the card */
-               if (pollepd.revents & EPOLLIN)
-                       cosm_scif_recv(cdev);
-
-               /* The peer endpoint is closed or this endpoint disconnected */
-               if (pollepd.revents & EPOLLHUP) {
-                       cosm_scif_close(cdev);
-                       break;
-               }
-
-               /* Did we timeout from poll? */
-               if (!rc && cdev->heartbeat_watchdog_enable)
-                       cosm_set_crashed(cdev);
-       }
-exit:
-       dev_dbg(&cdev->dev, "%s %d exiting\n", __func__, __LINE__);
-       mutex_unlock(&cdev->cosm_mutex);
-}
-
-/*
- * COSM SCIF server thread function. Accepts incoming SCIF connections from MIC
- * cards, finds the correct cosm_device to associate that connection with and
- * schedules individual work items for each MIC card.
- */
-static int cosm_scif_server(void *unused)
-{
-       struct cosm_device *cdev;
-       scif_epd_t newepd;
-       struct scif_port_id port_id;
-       int rc;
-
-       allow_signal(SIGKILL);
-
-       while (!kthread_should_stop()) {
-               rc = scif_accept(listen_epd, &port_id, &newepd,
-                                SCIF_ACCEPT_SYNC);
-               if (rc < 0) {
-                       if (-ERESTARTSYS != rc)
-                               pr_err("%s %d rc %d\n", __func__, __LINE__, rc);
-                       continue;
-               }
-
-               /*
-                * Associate the incoming connection with a particular
-                * cosm_device, COSM device ID == SCIF node ID - 1
-                */
-               cdev = cosm_find_cdev_by_id(port_id.node - 1);
-               if (!cdev)
-                       continue;
-               cdev->newepd = newepd;
-               schedule_work(&cdev->scif_work);
-       }
-
-       pr_debug("%s %d Server thread stopped\n", __func__, __LINE__);
-       return 0;
-}
-
-static int cosm_scif_listen(void)
-{
-       int rc;
-
-       listen_epd = scif_open();
-       if (!listen_epd) {
-               pr_err("%s %d scif_open failed\n", __func__, __LINE__);
-               return -ENOMEM;
-       }
-
-       rc = scif_bind(listen_epd, SCIF_COSM_LISTEN_PORT);
-       if (rc < 0) {
-               pr_err("%s %d scif_bind failed rc %d\n",
-                      __func__, __LINE__, rc);
-               goto err;
-       }
-
-       rc = scif_listen(listen_epd, COSM_SCIF_BACKLOG);
-       if (rc < 0) {
-               pr_err("%s %d scif_listen rc %d\n", __func__, __LINE__, rc);
-               goto err;
-       }
-       pr_debug("%s %d listen_epd set up\n", __func__, __LINE__);
-       return 0;
-err:
-       scif_close(listen_epd);
-       listen_epd = NULL;
-       return rc;
-}
-
-static void cosm_scif_listen_exit(void)
-{
-       pr_debug("%s %d closing listen_epd\n", __func__, __LINE__);
-       if (listen_epd) {
-               scif_close(listen_epd);
-               listen_epd = NULL;
-       }
-}
-
-/*
- * Create a listening SCIF endpoint and a server kthread which accepts incoming
- * SCIF connections from MIC cards
- */
-int cosm_scif_init(void)
-{
-       int rc = cosm_scif_listen();
-
-       if (rc) {
-               pr_err("%s %d cosm_scif_listen rc %d\n",
-                      __func__, __LINE__, rc);
-               goto err;
-       }
-
-       server_thread = kthread_run(cosm_scif_server, NULL, "cosm_server");
-       if (IS_ERR(server_thread)) {
-               rc = PTR_ERR(server_thread);
-               pr_err("%s %d kthread_run rc %d\n", __func__, __LINE__, rc);
-               goto listen_exit;
-       }
-       return 0;
-listen_exit:
-       cosm_scif_listen_exit();
-err:
-       return rc;
-}
-
-/* Stop the running server thread and close the listening SCIF endpoint */
-void cosm_scif_exit(void)
-{
-       int rc;
-
-       if (!IS_ERR_OR_NULL(server_thread)) {
-               rc = send_sig(SIGKILL, server_thread, 0);
-               if (rc) {
-                       pr_err("%s %d send_sig rc %d\n",
-                              __func__, __LINE__, rc);
-                       return;
-               }
-               kthread_stop(server_thread);
-       }
-
-       cosm_scif_listen_exit();
-}
diff --git a/drivers/misc/mic/cosm/cosm_sysfs.c b/drivers/misc/mic/cosm/cosm_sysfs.c
deleted file mode 100644 (file)
index e6dac96..0000000
+++ /dev/null
@@ -1,449 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * Intel MIC Coprocessor State Management (COSM) Driver
- */
-#include <linux/slab.h>
-#include "cosm_main.h"
-
-/*
- * A state-to-string lookup table, for exposing a human readable state
- * via sysfs. Always keep in sync with enum cosm_states
- */
-const char * const cosm_state_string[] = {
-       [MIC_READY] = "ready",
-       [MIC_BOOTING] = "booting",
-       [MIC_ONLINE] = "online",
-       [MIC_SHUTTING_DOWN] = "shutting_down",
-       [MIC_RESETTING] = "resetting",
-       [MIC_RESET_FAILED] = "reset_failed",
-};
-
-/*
- * A shutdown-status-to-string lookup table, for exposing a human
- * readable state via sysfs. Always keep in sync with enum cosm_shutdown_status
- */
-const char * const cosm_shutdown_status_string[] = {
-       [MIC_NOP] = "nop",
-       [MIC_CRASHED] = "crashed",
-       [MIC_HALTED] = "halted",
-       [MIC_POWER_OFF] = "poweroff",
-       [MIC_RESTART] = "restart",
-};
-
-void cosm_set_shutdown_status(struct cosm_device *cdev, u8 shutdown_status)
-{
-       dev_dbg(&cdev->dev, "Shutdown Status %s -> %s\n",
-               cosm_shutdown_status_string[cdev->shutdown_status],
-               cosm_shutdown_status_string[shutdown_status]);
-       cdev->shutdown_status = shutdown_status;
-}
-
-void cosm_set_state(struct cosm_device *cdev, u8 state)
-{
-       dev_dbg(&cdev->dev, "State %s -> %s\n",
-               cosm_state_string[cdev->state],
-               cosm_state_string[state]);
-       cdev->state = state;
-       sysfs_notify_dirent(cdev->state_sysfs);
-}
-
-static ssize_t
-family_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-
-       if (!cdev)
-               return -EINVAL;
-
-       return cdev->hw_ops->family(cdev, buf);
-}
-static DEVICE_ATTR_RO(family);
-
-static ssize_t
-stepping_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-
-       if (!cdev)
-               return -EINVAL;
-
-       return cdev->hw_ops->stepping(cdev, buf);
-}
-static DEVICE_ATTR_RO(stepping);
-
-static ssize_t
-state_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-
-       if (!cdev || cdev->state >= MIC_LAST)
-               return -EINVAL;
-
-       return scnprintf(buf, PAGE_SIZE, "%s\n",
-               cosm_state_string[cdev->state]);
-}
-
-static ssize_t
-state_store(struct device *dev, struct device_attribute *attr,
-           const char *buf, size_t count)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-       int rc;
-
-       if (!cdev)
-               return -EINVAL;
-
-       if (sysfs_streq(buf, "boot")) {
-               rc = cosm_start(cdev);
-               goto done;
-       }
-       if (sysfs_streq(buf, "reset")) {
-               rc = cosm_reset(cdev);
-               goto done;
-       }
-
-       if (sysfs_streq(buf, "shutdown")) {
-               rc = cosm_shutdown(cdev);
-               goto done;
-       }
-       rc = -EINVAL;
-done:
-       if (rc)
-               count = rc;
-       return count;
-}
-static DEVICE_ATTR_RW(state);
-
-static ssize_t shutdown_status_show(struct device *dev,
-                                   struct device_attribute *attr, char *buf)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-
-       if (!cdev || cdev->shutdown_status >= MIC_STATUS_LAST)
-               return -EINVAL;
-
-       return scnprintf(buf, PAGE_SIZE, "%s\n",
-               cosm_shutdown_status_string[cdev->shutdown_status]);
-}
-static DEVICE_ATTR_RO(shutdown_status);
-
-static ssize_t
-heartbeat_enable_show(struct device *dev,
-                     struct device_attribute *attr, char *buf)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-
-       if (!cdev)
-               return -EINVAL;
-
-       return scnprintf(buf, PAGE_SIZE, "%d\n", cdev->sysfs_heartbeat_enable);
-}
-
-static ssize_t
-heartbeat_enable_store(struct device *dev,
-                      struct device_attribute *attr,
-                      const char *buf, size_t count)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-       int enable;
-       int ret;
-
-       if (!cdev)
-               return -EINVAL;
-
-       mutex_lock(&cdev->cosm_mutex);
-       ret = kstrtoint(buf, 10, &enable);
-       if (ret)
-               goto unlock;
-
-       cdev->sysfs_heartbeat_enable = enable;
-       /* if state is not online, cdev->heartbeat_watchdog_enable is 0 */
-       if (cdev->state == MIC_ONLINE)
-               cdev->heartbeat_watchdog_enable = enable;
-       ret = count;
-unlock:
-       mutex_unlock(&cdev->cosm_mutex);
-       return ret;
-}
-static DEVICE_ATTR_RW(heartbeat_enable);
-
-static ssize_t
-cmdline_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-       char *cmdline;
-
-       if (!cdev)
-               return -EINVAL;
-
-       cmdline = cdev->cmdline;
-
-       if (cmdline)
-               return scnprintf(buf, PAGE_SIZE, "%s\n", cmdline);
-       return 0;
-}
-
-static ssize_t
-cmdline_store(struct device *dev, struct device_attribute *attr,
-             const char *buf, size_t count)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-
-       if (!cdev)
-               return -EINVAL;
-
-       mutex_lock(&cdev->cosm_mutex);
-       kfree(cdev->cmdline);
-
-       cdev->cmdline = kmalloc(count + 1, GFP_KERNEL);
-       if (!cdev->cmdline) {
-               count = -ENOMEM;
-               goto unlock;
-       }
-
-       strncpy(cdev->cmdline, buf, count);
-
-       if (cdev->cmdline[count - 1] == '\n')
-               cdev->cmdline[count - 1] = '\0';
-       else
-               cdev->cmdline[count] = '\0';
-unlock:
-       mutex_unlock(&cdev->cosm_mutex);
-       return count;
-}
-static DEVICE_ATTR_RW(cmdline);
-
-static ssize_t
-firmware_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-       char *firmware;
-
-       if (!cdev)
-               return -EINVAL;
-
-       firmware = cdev->firmware;
-
-       if (firmware)
-               return scnprintf(buf, PAGE_SIZE, "%s\n", firmware);
-       return 0;
-}
-
-static ssize_t
-firmware_store(struct device *dev, struct device_attribute *attr,
-              const char *buf, size_t count)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-
-       if (!cdev)
-               return -EINVAL;
-
-       mutex_lock(&cdev->cosm_mutex);
-       kfree(cdev->firmware);
-
-       cdev->firmware = kmalloc(count + 1, GFP_KERNEL);
-       if (!cdev->firmware) {
-               count = -ENOMEM;
-               goto unlock;
-       }
-       strncpy(cdev->firmware, buf, count);
-
-       if (cdev->firmware[count - 1] == '\n')
-               cdev->firmware[count - 1] = '\0';
-       else
-               cdev->firmware[count] = '\0';
-unlock:
-       mutex_unlock(&cdev->cosm_mutex);
-       return count;
-}
-static DEVICE_ATTR_RW(firmware);
-
-static ssize_t
-ramdisk_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-       char *ramdisk;
-
-       if (!cdev)
-               return -EINVAL;
-
-       ramdisk = cdev->ramdisk;
-
-       if (ramdisk)
-               return scnprintf(buf, PAGE_SIZE, "%s\n", ramdisk);
-       return 0;
-}
-
-static ssize_t
-ramdisk_store(struct device *dev, struct device_attribute *attr,
-             const char *buf, size_t count)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-
-       if (!cdev)
-               return -EINVAL;
-
-       mutex_lock(&cdev->cosm_mutex);
-       kfree(cdev->ramdisk);
-
-       cdev->ramdisk = kmalloc(count + 1, GFP_KERNEL);
-       if (!cdev->ramdisk) {
-               count = -ENOMEM;
-               goto unlock;
-       }
-
-       strncpy(cdev->ramdisk, buf, count);
-
-       if (cdev->ramdisk[count - 1] == '\n')
-               cdev->ramdisk[count - 1] = '\0';
-       else
-               cdev->ramdisk[count] = '\0';
-unlock:
-       mutex_unlock(&cdev->cosm_mutex);
-       return count;
-}
-static DEVICE_ATTR_RW(ramdisk);
-
-static ssize_t
-bootmode_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-       char *bootmode;
-
-       if (!cdev)
-               return -EINVAL;
-
-       bootmode = cdev->bootmode;
-
-       if (bootmode)
-               return scnprintf(buf, PAGE_SIZE, "%s\n", bootmode);
-       return 0;
-}
-
-static ssize_t
-bootmode_store(struct device *dev, struct device_attribute *attr,
-              const char *buf, size_t count)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-
-       if (!cdev)
-               return -EINVAL;
-
-       if (!sysfs_streq(buf, "linux") && !sysfs_streq(buf, "flash"))
-               return -EINVAL;
-
-       mutex_lock(&cdev->cosm_mutex);
-       kfree(cdev->bootmode);
-
-       cdev->bootmode = kmalloc(count + 1, GFP_KERNEL);
-       if (!cdev->bootmode) {
-               count = -ENOMEM;
-               goto unlock;
-       }
-
-       strncpy(cdev->bootmode, buf, count);
-
-       if (cdev->bootmode[count - 1] == '\n')
-               cdev->bootmode[count - 1] = '\0';
-       else
-               cdev->bootmode[count] = '\0';
-unlock:
-       mutex_unlock(&cdev->cosm_mutex);
-       return count;
-}
-static DEVICE_ATTR_RW(bootmode);
-
-static ssize_t
-log_buf_addr_show(struct device *dev, struct device_attribute *attr,
-                 char *buf)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-
-       if (!cdev)
-               return -EINVAL;
-
-       return scnprintf(buf, PAGE_SIZE, "%p\n", cdev->log_buf_addr);
-}
-
-static ssize_t
-log_buf_addr_store(struct device *dev, struct device_attribute *attr,
-                  const char *buf, size_t count)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-       int ret;
-       unsigned long addr;
-
-       if (!cdev)
-               return -EINVAL;
-
-       ret = kstrtoul(buf, 16, &addr);
-       if (ret)
-               goto exit;
-
-       cdev->log_buf_addr = (void *)addr;
-       ret = count;
-exit:
-       return ret;
-}
-static DEVICE_ATTR_RW(log_buf_addr);
-
-static ssize_t
-log_buf_len_show(struct device *dev, struct device_attribute *attr,
-                char *buf)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-
-       if (!cdev)
-               return -EINVAL;
-
-       return scnprintf(buf, PAGE_SIZE, "%p\n", cdev->log_buf_len);
-}
-
-static ssize_t
-log_buf_len_store(struct device *dev, struct device_attribute *attr,
-                 const char *buf, size_t count)
-{
-       struct cosm_device *cdev = dev_get_drvdata(dev);
-       int ret;
-       unsigned long addr;
-
-       if (!cdev)
-               return -EINVAL;
-
-       ret = kstrtoul(buf, 16, &addr);
-       if (ret)
-               goto exit;
-
-       cdev->log_buf_len = (int *)addr;
-       ret = count;
-exit:
-       return ret;
-}
-static DEVICE_ATTR_RW(log_buf_len);
-
-static struct attribute *cosm_default_attrs[] = {
-       &dev_attr_family.attr,
-       &dev_attr_stepping.attr,
-       &dev_attr_state.attr,
-       &dev_attr_shutdown_status.attr,
-       &dev_attr_heartbeat_enable.attr,
-       &dev_attr_cmdline.attr,
-       &dev_attr_firmware.attr,
-       &dev_attr_ramdisk.attr,
-       &dev_attr_bootmode.attr,
-       &dev_attr_log_buf_addr.attr,
-       &dev_attr_log_buf_len.attr,
-
-       NULL
-};
-
-ATTRIBUTE_GROUPS(cosm_default);
-
-void cosm_sysfs_init(struct cosm_device *cdev)
-{
-       cdev->attr_group = cosm_default_groups;
-}
diff --git a/drivers/misc/mic/cosm_client/Makefile b/drivers/misc/mic/cosm_client/Makefile
deleted file mode 100644 (file)
index 5b62270..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile - Intel MIC COSM Client Driver
-# Copyright(c) 2015, Intel Corporation.
-#
-obj-$(CONFIG_MIC_COSM) += cosm_client.o
-
-cosm_client-objs += cosm_scif_client.o
diff --git a/drivers/misc/mic/cosm_client/cosm_scif_client.c b/drivers/misc/mic/cosm_client/cosm_scif_client.c
deleted file mode 100644 (file)
index a03213d..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * Intel MIC COSM Client Driver
- */
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/reboot.h>
-#include <linux/kthread.h>
-#include <linux/sched/signal.h>
-
-#include "../cosm/cosm_main.h"
-
-#define COSM_SCIF_MAX_RETRIES 10
-#define COSM_HEARTBEAT_SEND_MSEC (COSM_HEARTBEAT_SEND_SEC * MSEC_PER_SEC)
-
-static struct task_struct *client_thread;
-static scif_epd_t client_epd;
-static struct scif_peer_dev *client_spdev;
-
-/*
- * Reboot notifier: receives shutdown status from the OS and communicates it
- * back to the COSM process on the host
- */
-static int cosm_reboot_event(struct notifier_block *this, unsigned long event,
-                            void *ptr)
-{
-       struct cosm_msg msg = { .id = COSM_MSG_SHUTDOWN_STATUS };
-       int rc;
-
-       event = (event == SYS_RESTART) ? SYSTEM_RESTART : event;
-       dev_info(&client_spdev->dev, "%s %d received event %ld\n",
-                __func__, __LINE__, event);
-
-       msg.shutdown_status = event;
-       rc = scif_send(client_epd, &msg, sizeof(msg), SCIF_SEND_BLOCK);
-       if (rc < 0)
-               dev_err(&client_spdev->dev, "%s %d scif_send rc %d\n",
-                       __func__, __LINE__, rc);
-
-       return NOTIFY_DONE;
-}
-
-static struct notifier_block cosm_reboot = {
-       .notifier_call  = cosm_reboot_event,
-};
-
-/* Set system time from timespec value received from the host */
-static void cosm_set_time(struct cosm_msg *msg)
-{
-       struct timespec64 ts = {
-               .tv_sec = msg->timespec.tv_sec,
-               .tv_nsec = msg->timespec.tv_nsec,
-       };
-       int rc = do_settimeofday64(&ts);
-
-       if (rc)
-               dev_err(&client_spdev->dev, "%s: %d settimeofday rc %d\n",
-                       __func__, __LINE__, rc);
-}
-
-/* COSM client receive message processing */
-static void cosm_client_recv(void)
-{
-       struct cosm_msg msg;
-       int rc;
-
-       while (1) {
-               rc = scif_recv(client_epd, &msg, sizeof(msg), 0);
-               if (!rc) {
-                       return;
-               } else if (rc < 0) {
-                       dev_err(&client_spdev->dev, "%s: %d rc %d\n",
-                               __func__, __LINE__, rc);
-                       return;
-               }
-
-               dev_dbg(&client_spdev->dev, "%s: %d rc %d id 0x%llx\n",
-                       __func__, __LINE__, rc, msg.id);
-
-               switch (msg.id) {
-               case COSM_MSG_SYNC_TIME:
-                       cosm_set_time(&msg);
-                       break;
-               case COSM_MSG_SHUTDOWN:
-                       orderly_poweroff(true);
-                       break;
-               default:
-                       dev_err(&client_spdev->dev, "%s: %d unknown id %lld\n",
-                               __func__, __LINE__, msg.id);
-                       break;
-               }
-       }
-}
-
-/* Initiate connection to the COSM server on the host */
-static int cosm_scif_connect(void)
-{
-       struct scif_port_id port_id;
-       int i, rc;
-
-       client_epd = scif_open();
-       if (!client_epd) {
-               dev_err(&client_spdev->dev, "%s %d scif_open failed\n",
-                       __func__, __LINE__);
-               return -ENOMEM;
-       }
-
-       port_id.node = 0;
-       port_id.port = SCIF_COSM_LISTEN_PORT;
-
-       for (i = 0; i < COSM_SCIF_MAX_RETRIES; i++) {
-               rc = scif_connect(client_epd, &port_id);
-               if (rc < 0)
-                       msleep(1000);
-               else
-                       break;
-       }
-
-       if (rc < 0) {
-               dev_err(&client_spdev->dev, "%s %d scif_connect rc %d\n",
-                       __func__, __LINE__, rc);
-               scif_close(client_epd);
-               client_epd = NULL;
-       }
-       return rc < 0 ? rc : 0;
-}
-
-/* Close host SCIF connection */
-static void cosm_scif_connect_exit(void)
-{
-       if (client_epd) {
-               scif_close(client_epd);
-               client_epd = NULL;
-       }
-}
-
-/*
- * COSM SCIF client thread function: waits for messages from the host and sends
- * a heartbeat to the host
- */
-static int cosm_scif_client(void *unused)
-{
-       struct cosm_msg msg = { .id = COSM_MSG_HEARTBEAT };
-       struct scif_pollepd pollepd;
-       int rc;
-
-       allow_signal(SIGKILL);
-
-       while (!kthread_should_stop()) {
-               pollepd.epd = client_epd;
-               pollepd.events = EPOLLIN;
-
-               rc = scif_poll(&pollepd, 1, COSM_HEARTBEAT_SEND_MSEC);
-               if (rc < 0) {
-                       if (-EINTR != rc)
-                               dev_err(&client_spdev->dev,
-                                       "%s %d scif_poll rc %d\n",
-                                       __func__, __LINE__, rc);
-                       continue;
-               }
-
-               if (pollepd.revents & EPOLLIN)
-                       cosm_client_recv();
-
-               msg.id = COSM_MSG_HEARTBEAT;
-               rc = scif_send(client_epd, &msg, sizeof(msg), SCIF_SEND_BLOCK);
-               if (rc < 0)
-                       dev_err(&client_spdev->dev, "%s %d scif_send rc %d\n",
-                               __func__, __LINE__, rc);
-       }
-
-       dev_dbg(&client_spdev->dev, "%s %d Client thread stopped\n",
-               __func__, __LINE__);
-       return 0;
-}
-
-static void cosm_scif_probe(struct scif_peer_dev *spdev)
-{
-       int rc;
-
-       dev_dbg(&spdev->dev, "%s %d: dnode %d\n",
-               __func__, __LINE__, spdev->dnode);
-
-       /* We are only interested in the host with spdev->dnode == 0 */
-       if (spdev->dnode)
-               return;
-
-       client_spdev = spdev;
-       rc = cosm_scif_connect();
-       if (rc)
-               goto exit;
-
-       rc = register_reboot_notifier(&cosm_reboot);
-       if (rc) {
-               dev_err(&spdev->dev,
-                       "reboot notifier registration failed rc %d\n", rc);
-               goto connect_exit;
-       }
-
-       client_thread = kthread_run(cosm_scif_client, NULL, "cosm_client");
-       if (IS_ERR(client_thread)) {
-               rc = PTR_ERR(client_thread);
-               dev_err(&spdev->dev, "%s %d kthread_run rc %d\n",
-                       __func__, __LINE__, rc);
-               goto unreg_reboot;
-       }
-       return;
-unreg_reboot:
-       unregister_reboot_notifier(&cosm_reboot);
-connect_exit:
-       cosm_scif_connect_exit();
-exit:
-       client_spdev = NULL;
-}
-
-static void cosm_scif_remove(struct scif_peer_dev *spdev)
-{
-       int rc;
-
-       dev_dbg(&spdev->dev, "%s %d: dnode %d\n",
-               __func__, __LINE__, spdev->dnode);
-
-       if (spdev->dnode)
-               return;
-
-       if (!IS_ERR_OR_NULL(client_thread)) {
-               rc = send_sig(SIGKILL, client_thread, 0);
-               if (rc) {
-                       pr_err("%s %d send_sig rc %d\n",
-                              __func__, __LINE__, rc);
-                       return;
-               }
-               kthread_stop(client_thread);
-       }
-       unregister_reboot_notifier(&cosm_reboot);
-       cosm_scif_connect_exit();
-       client_spdev = NULL;
-}
-
-static struct scif_client scif_client_cosm = {
-       .name = KBUILD_MODNAME,
-       .probe = cosm_scif_probe,
-       .remove = cosm_scif_remove,
-};
-
-static int __init cosm_client_init(void)
-{
-       int rc = scif_client_register(&scif_client_cosm);
-
-       if (rc)
-               pr_err("scif_client_register failed rc %d\n", rc);
-       return rc;
-}
-
-static void __exit cosm_client_exit(void)
-{
-       scif_client_unregister(&scif_client_cosm);
-}
-
-module_init(cosm_client_init);
-module_exit(cosm_client_exit);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Intel(R) MIC card OS state management client driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/host/Makefile b/drivers/misc/mic/host/Makefile
deleted file mode 100644 (file)
index 25f1533..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile - Intel MIC Linux driver.
-# Copyright(c) 2013, Intel Corporation.
-#
-obj-$(CONFIG_INTEL_MIC_HOST) += mic_host.o
-mic_host-objs := mic_main.o
-mic_host-objs += mic_x100.o
-mic_host-objs += mic_smpt.o
-mic_host-objs += mic_intr.o
-mic_host-objs += mic_boot.o
-mic_host-objs += mic_debugfs.o
diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c
deleted file mode 100644 (file)
index 8cb85b8..0000000
+++ /dev/null
@@ -1,588 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Intel MIC Host driver.
- */
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/pci.h>
-#include <linux/kmod.h>
-#include <linux/dma-map-ops.h>
-#include <linux/mic_common.h>
-#include <linux/mic_bus.h>
-#include "../bus/scif_bus.h"
-#include "../bus/vop_bus.h"
-#include "../common/mic_dev.h"
-#include "mic_device.h"
-#include "mic_smpt.h"
-
-static inline struct mic_device *vpdev_to_mdev(struct device *dev)
-{
-       return dev_get_drvdata(dev->parent);
-}
-
-static dma_addr_t
-_mic_dma_map_page(struct device *dev, struct page *page,
-                 unsigned long offset, size_t size,
-                 enum dma_data_direction dir, unsigned long attrs)
-{
-       void *va = phys_to_virt(page_to_phys(page)) + offset;
-       struct mic_device *mdev = vpdev_to_mdev(dev);
-
-       return mic_map_single(mdev, va, size);
-}
-
-static void _mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
-                               size_t size, enum dma_data_direction dir,
-                               unsigned long attrs)
-{
-       struct mic_device *mdev = vpdev_to_mdev(dev);
-
-       mic_unmap_single(mdev, dma_addr, size);
-}
-
-static const struct dma_map_ops _mic_dma_ops = {
-       .map_page = _mic_dma_map_page,
-       .unmap_page = _mic_dma_unmap_page,
-};
-
-static struct mic_irq *
-__mic_request_irq(struct vop_device *vpdev,
-                 irqreturn_t (*func)(int irq, void *data),
-                 const char *name, void *data, int intr_src)
-{
-       struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
-
-       return mic_request_threaded_irq(mdev, func, NULL, name, data,
-                                       intr_src, MIC_INTR_DB);
-}
-
-static void __mic_free_irq(struct vop_device *vpdev,
-                          struct mic_irq *cookie, void *data)
-{
-       struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
-
-       mic_free_irq(mdev, cookie, data);
-}
-
-static void __mic_ack_interrupt(struct vop_device *vpdev, int num)
-{
-       struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
-
-       mdev->ops->intr_workarounds(mdev);
-}
-
-static int __mic_next_db(struct vop_device *vpdev)
-{
-       struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
-
-       return mic_next_db(mdev);
-}
-
-static void *__mic_get_dp(struct vop_device *vpdev)
-{
-       struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
-
-       return mdev->dp;
-}
-
-static void __iomem *__mic_get_remote_dp(struct vop_device *vpdev)
-{
-       return NULL;
-}
-
-static void __mic_send_intr(struct vop_device *vpdev, int db)
-{
-       struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
-
-       mdev->ops->send_intr(mdev, db);
-}
-
-static void __iomem *__mic_ioremap(struct vop_device *vpdev,
-                                  dma_addr_t pa, size_t len)
-{
-       struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
-
-       return mdev->aper.va + pa;
-}
-
-static void __mic_iounmap(struct vop_device *vpdev, void __iomem *va)
-{
-       /* nothing to do */
-}
-
-static struct vop_hw_ops vop_hw_ops = {
-       .request_irq = __mic_request_irq,
-       .free_irq = __mic_free_irq,
-       .ack_interrupt = __mic_ack_interrupt,
-       .next_db = __mic_next_db,
-       .get_dp = __mic_get_dp,
-       .get_remote_dp = __mic_get_remote_dp,
-       .send_intr = __mic_send_intr,
-       .remap = __mic_ioremap,
-       .unmap = __mic_iounmap,
-};
-
-static inline struct mic_device *scdev_to_mdev(struct scif_hw_dev *scdev)
-{
-       return dev_get_drvdata(scdev->dev.parent);
-}
-
-static void *__mic_dma_alloc(struct device *dev, size_t size,
-                            dma_addr_t *dma_handle, gfp_t gfp,
-                            unsigned long attrs)
-{
-       struct scif_hw_dev *scdev = dev_get_drvdata(dev);
-       struct mic_device *mdev = scdev_to_mdev(scdev);
-       dma_addr_t tmp;
-       void *va = kzalloc(size, gfp);
-
-       if (va) {
-               tmp = mic_map_single(mdev, va, size);
-               if (dma_mapping_error(dev, tmp)) {
-                       kfree(va);
-                       va = NULL;
-               } else {
-                       *dma_handle = tmp;
-               }
-       }
-       return va;
-}
-
-static void __mic_dma_free(struct device *dev, size_t size, void *vaddr,
-                          dma_addr_t dma_handle, unsigned long attrs)
-{
-       struct scif_hw_dev *scdev = dev_get_drvdata(dev);
-       struct mic_device *mdev = scdev_to_mdev(scdev);
-
-       mic_unmap_single(mdev, dma_handle, size);
-       kfree(vaddr);
-}
-
-static dma_addr_t
-__mic_dma_map_page(struct device *dev, struct page *page, unsigned long offset,
-                  size_t size, enum dma_data_direction dir,
-                  unsigned long attrs)
-{
-       void *va = phys_to_virt(page_to_phys(page)) + offset;
-       struct scif_hw_dev *scdev = dev_get_drvdata(dev);
-       struct mic_device *mdev = scdev_to_mdev(scdev);
-
-       return mic_map_single(mdev, va, size);
-}
-
-static void
-__mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
-                    size_t size, enum dma_data_direction dir,
-                    unsigned long attrs)
-{
-       struct scif_hw_dev *scdev = dev_get_drvdata(dev);
-       struct mic_device *mdev = scdev_to_mdev(scdev);
-
-       mic_unmap_single(mdev, dma_addr, size);
-}
-
-static int __mic_dma_map_sg(struct device *dev, struct scatterlist *sg,
-                           int nents, enum dma_data_direction dir,
-                           unsigned long attrs)
-{
-       struct scif_hw_dev *scdev = dev_get_drvdata(dev);
-       struct mic_device *mdev = scdev_to_mdev(scdev);
-       struct scatterlist *s;
-       int i, j, ret;
-       dma_addr_t da;
-
-       ret = dma_map_sg(&mdev->pdev->dev, sg, nents, dir);
-       if (ret <= 0)
-               return 0;
-
-       for_each_sg(sg, s, nents, i) {
-               da = mic_map(mdev, sg_dma_address(s) + s->offset, s->length);
-               if (!da)
-                       goto err;
-               sg_dma_address(s) = da;
-       }
-       return nents;
-err:
-       for_each_sg(sg, s, i, j) {
-               mic_unmap(mdev, sg_dma_address(s), s->length);
-               sg_dma_address(s) = mic_to_dma_addr(mdev, sg_dma_address(s));
-       }
-       dma_unmap_sg(&mdev->pdev->dev, sg, nents, dir);
-       return 0;
-}
-
-static void __mic_dma_unmap_sg(struct device *dev,
-                              struct scatterlist *sg, int nents,
-                              enum dma_data_direction dir,
-                              unsigned long attrs)
-{
-       struct scif_hw_dev *scdev = dev_get_drvdata(dev);
-       struct mic_device *mdev = scdev_to_mdev(scdev);
-       struct scatterlist *s;
-       dma_addr_t da;
-       int i;
-
-       for_each_sg(sg, s, nents, i) {
-               da = mic_to_dma_addr(mdev, sg_dma_address(s));
-               mic_unmap(mdev, sg_dma_address(s), s->length);
-               sg_dma_address(s) = da;
-       }
-       dma_unmap_sg(&mdev->pdev->dev, sg, nents, dir);
-}
-
-static const struct dma_map_ops __mic_dma_ops = {
-       .alloc = __mic_dma_alloc,
-       .free = __mic_dma_free,
-       .map_page = __mic_dma_map_page,
-       .unmap_page = __mic_dma_unmap_page,
-       .map_sg = __mic_dma_map_sg,
-       .unmap_sg = __mic_dma_unmap_sg,
-};
-
-static struct mic_irq *
-___mic_request_irq(struct scif_hw_dev *scdev,
-                  irqreturn_t (*func)(int irq, void *data),
-                                      const char *name,
-                                      void *data, int db)
-{
-       struct mic_device *mdev = scdev_to_mdev(scdev);
-
-       return mic_request_threaded_irq(mdev, func, NULL, name, data,
-                                       db, MIC_INTR_DB);
-}
-
-static void
-___mic_free_irq(struct scif_hw_dev *scdev,
-               struct mic_irq *cookie, void *data)
-{
-       struct mic_device *mdev = scdev_to_mdev(scdev);
-
-       mic_free_irq(mdev, cookie, data);
-}
-
-static void ___mic_ack_interrupt(struct scif_hw_dev *scdev, int num)
-{
-       struct mic_device *mdev = scdev_to_mdev(scdev);
-
-       mdev->ops->intr_workarounds(mdev);
-}
-
-static int ___mic_next_db(struct scif_hw_dev *scdev)
-{
-       struct mic_device *mdev = scdev_to_mdev(scdev);
-
-       return mic_next_db(mdev);
-}
-
-static void ___mic_send_intr(struct scif_hw_dev *scdev, int db)
-{
-       struct mic_device *mdev = scdev_to_mdev(scdev);
-
-       mdev->ops->send_intr(mdev, db);
-}
-
-static void __iomem *___mic_ioremap(struct scif_hw_dev *scdev,
-                                   phys_addr_t pa, size_t len)
-{
-       struct mic_device *mdev = scdev_to_mdev(scdev);
-
-       return mdev->aper.va + pa;
-}
-
-static void ___mic_iounmap(struct scif_hw_dev *scdev, void __iomem *va)
-{
-       /* nothing to do */
-}
-
-static struct scif_hw_ops scif_hw_ops = {
-       .request_irq = ___mic_request_irq,
-       .free_irq = ___mic_free_irq,
-       .ack_interrupt = ___mic_ack_interrupt,
-       .next_db = ___mic_next_db,
-       .send_intr = ___mic_send_intr,
-       .remap = ___mic_ioremap,
-       .unmap = ___mic_iounmap,
-};
-
-static inline struct mic_device *mbdev_to_mdev(struct mbus_device *mbdev)
-{
-       return dev_get_drvdata(mbdev->dev.parent);
-}
-
-static dma_addr_t
-mic_dma_map_page(struct device *dev, struct page *page,
-                unsigned long offset, size_t size, enum dma_data_direction dir,
-                unsigned long attrs)
-{
-       void *va = phys_to_virt(page_to_phys(page)) + offset;
-       struct mic_device *mdev = dev_get_drvdata(dev->parent);
-
-       return mic_map_single(mdev, va, size);
-}
-
-static void
-mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
-                  size_t size, enum dma_data_direction dir,
-                  unsigned long attrs)
-{
-       struct mic_device *mdev = dev_get_drvdata(dev->parent);
-       mic_unmap_single(mdev, dma_addr, size);
-}
-
-static const struct dma_map_ops mic_dma_ops = {
-       .map_page = mic_dma_map_page,
-       .unmap_page = mic_dma_unmap_page,
-};
-
-static struct mic_irq *
-_mic_request_threaded_irq(struct mbus_device *mbdev,
-                         irq_handler_t handler, irq_handler_t thread_fn,
-                         const char *name, void *data, int intr_src)
-{
-       return mic_request_threaded_irq(mbdev_to_mdev(mbdev), handler,
-                                       thread_fn, name, data,
-                                       intr_src, MIC_INTR_DMA);
-}
-
-static void _mic_free_irq(struct mbus_device *mbdev,
-                         struct mic_irq *cookie, void *data)
-{
-       mic_free_irq(mbdev_to_mdev(mbdev), cookie, data);
-}
-
-static void _mic_ack_interrupt(struct mbus_device *mbdev, int num)
-{
-       struct mic_device *mdev = mbdev_to_mdev(mbdev);
-       mdev->ops->intr_workarounds(mdev);
-}
-
-static struct mbus_hw_ops mbus_hw_ops = {
-       .request_threaded_irq = _mic_request_threaded_irq,
-       .free_irq = _mic_free_irq,
-       .ack_interrupt = _mic_ack_interrupt,
-};
-
-/* Initialize the MIC bootparams */
-void mic_bootparam_init(struct mic_device *mdev)
-{
-       struct mic_bootparam *bootparam = mdev->dp;
-
-       bootparam->magic = cpu_to_le32(MIC_MAGIC);
-       bootparam->h2c_config_db = -1;
-       bootparam->node_id = mdev->id + 1;
-       bootparam->scif_host_dma_addr = 0x0;
-       bootparam->scif_card_dma_addr = 0x0;
-       bootparam->c2h_scif_db = -1;
-       bootparam->h2c_scif_db = -1;
-}
-
-static inline struct mic_device *cosmdev_to_mdev(struct cosm_device *cdev)
-{
-       return dev_get_drvdata(cdev->dev.parent);
-}
-
-static void _mic_reset(struct cosm_device *cdev)
-{
-       struct mic_device *mdev = cosmdev_to_mdev(cdev);
-
-       mdev->ops->reset_fw_ready(mdev);
-       mdev->ops->reset(mdev);
-}
-
-static bool _mic_ready(struct cosm_device *cdev)
-{
-       struct mic_device *mdev = cosmdev_to_mdev(cdev);
-
-       return mdev->ops->is_fw_ready(mdev);
-}
-
-/**
- * mic_request_dma_chans - Request DMA channels
- * @mdev: pointer to mic_device instance
- *
- * returns number of DMA channels acquired
- */
-static int mic_request_dma_chans(struct mic_device *mdev)
-{
-       dma_cap_mask_t mask;
-       struct dma_chan *chan;
-
-       dma_cap_zero(mask);
-       dma_cap_set(DMA_MEMCPY, mask);
-
-       do {
-               chan = dma_request_channel(mask, mdev->ops->dma_filter,
-                                          &mdev->pdev->dev);
-               if (chan) {
-                       mdev->dma_ch[mdev->num_dma_ch++] = chan;
-                       if (mdev->num_dma_ch >= MIC_MAX_DMA_CHAN)
-                               break;
-               }
-       } while (chan);
-       dev_info(&mdev->pdev->dev, "DMA channels # %d\n", mdev->num_dma_ch);
-       return mdev->num_dma_ch;
-}
-
-/**
- * mic_free_dma_chans - release DMA channels
- * @mdev: pointer to mic_device instance
- *
- * returns none
- */
-static void mic_free_dma_chans(struct mic_device *mdev)
-{
-       int i = 0;
-
-       for (i = 0; i < mdev->num_dma_ch; i++) {
-               dma_release_channel(mdev->dma_ch[i]);
-               mdev->dma_ch[i] = NULL;
-       }
-       mdev->num_dma_ch = 0;
-}
-
-/**
- * _mic_start - Start the MIC.
- * @cdev: pointer to cosm_device instance
- * @id: MIC device id/index provided by COSM used in other drivers like SCIF
- *
- * This function prepares an MIC for boot and initiates boot.
- * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
- *
- * For all cosm_hw_ops the caller holds a mutex to ensure serialization.
- */
-static int _mic_start(struct cosm_device *cdev, int id)
-{
-       struct mic_device *mdev = cosmdev_to_mdev(cdev);
-       int rc;
-
-       mic_bootparam_init(mdev);
-       mdev->dma_mbdev = mbus_register_device(&mdev->pdev->dev,
-                                              MBUS_DEV_DMA_HOST, &mic_dma_ops,
-                                              &mbus_hw_ops, id, mdev->mmio.va);
-       if (IS_ERR(mdev->dma_mbdev)) {
-               rc = PTR_ERR(mdev->dma_mbdev);
-               goto unlock_ret;
-       }
-       if (!mic_request_dma_chans(mdev)) {
-               rc = -ENODEV;
-               goto dma_remove;
-       }
-       mdev->scdev = scif_register_device(&mdev->pdev->dev, MIC_SCIF_DEV,
-                                          &__mic_dma_ops, &scif_hw_ops,
-                                          id + 1, 0, &mdev->mmio,
-                                          &mdev->aper, mdev->dp, NULL,
-                                          mdev->dma_ch, mdev->num_dma_ch,
-                                          true);
-       if (IS_ERR(mdev->scdev)) {
-               rc = PTR_ERR(mdev->scdev);
-               goto dma_free;
-       }
-
-       mdev->vpdev = vop_register_device(&mdev->pdev->dev,
-                                         VOP_DEV_TRNSP, &_mic_dma_ops,
-                                         &vop_hw_ops, id + 1, &mdev->aper,
-                                         mdev->dma_ch[0]);
-       if (IS_ERR(mdev->vpdev)) {
-               rc = PTR_ERR(mdev->vpdev);
-               goto scif_remove;
-       }
-
-       rc = mdev->ops->load_mic_fw(mdev, NULL);
-       if (rc)
-               goto vop_remove;
-       mic_smpt_restore(mdev);
-       mic_intr_restore(mdev);
-       mdev->intr_ops->enable_interrupts(mdev);
-       mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr);
-       mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
-       mdev->ops->send_firmware_intr(mdev);
-       goto unlock_ret;
-vop_remove:
-       vop_unregister_device(mdev->vpdev);
-scif_remove:
-       scif_unregister_device(mdev->scdev);
-dma_free:
-       mic_free_dma_chans(mdev);
-dma_remove:
-       mbus_unregister_device(mdev->dma_mbdev);
-unlock_ret:
-       return rc;
-}
-
-/**
- * _mic_stop - Prepare the MIC for reset and trigger reset.
- * @cdev: pointer to cosm_device instance
- * @force: force a MIC to reset even if it is already offline.
- *
- * RETURNS: None.
- */
-static void _mic_stop(struct cosm_device *cdev, bool force)
-{
-       struct mic_device *mdev = cosmdev_to_mdev(cdev);
-
-       /*
-        * Since SCIF handles card shutdown and reset (using COSM), it will
-        * will be the first to be registered and the last to be
-        * unregistered.
-        */
-       vop_unregister_device(mdev->vpdev);
-       scif_unregister_device(mdev->scdev);
-       mic_free_dma_chans(mdev);
-       mbus_unregister_device(mdev->dma_mbdev);
-       mic_bootparam_init(mdev);
-}
-
-static ssize_t _mic_family(struct cosm_device *cdev, char *buf)
-{
-       struct mic_device *mdev = cosmdev_to_mdev(cdev);
-       static const char *family[MIC_FAMILY_LAST] = { "x100", "Unknown" };
-
-       return scnprintf(buf, PAGE_SIZE, "%s\n", family[mdev->family]);
-}
-
-static ssize_t _mic_stepping(struct cosm_device *cdev, char *buf)
-{
-       struct mic_device *mdev = cosmdev_to_mdev(cdev);
-       const char *string = "??";
-
-       switch (mdev->stepping) {
-       case MIC_A0_STEP:
-               string = "A0";
-               break;
-       case MIC_B0_STEP:
-               string = "B0";
-               break;
-       case MIC_B1_STEP:
-               string = "B1";
-               break;
-       case MIC_C0_STEP:
-               string = "C0";
-               break;
-       default:
-               break;
-       }
-       return scnprintf(buf, PAGE_SIZE, "%s\n", string);
-}
-
-static struct mic_mw *_mic_aper(struct cosm_device *cdev)
-{
-       struct mic_device *mdev = cosmdev_to_mdev(cdev);
-
-       return &mdev->aper;
-}
-
-struct cosm_hw_ops cosm_hw_ops = {
-       .reset = _mic_reset,
-       .force_reset = _mic_reset,
-       .post_reset = NULL,
-       .ready = _mic_ready,
-       .start = _mic_start,
-       .stop = _mic_stop,
-       .family = _mic_family,
-       .stepping = _mic_stepping,
-       .aper = _mic_aper,
-};
diff --git a/drivers/misc/mic/host/mic_debugfs.c b/drivers/misc/mic/host/mic_debugfs.c
deleted file mode 100644 (file)
index ffda740..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Intel MIC Host driver.
- */
-#include <linux/debugfs.h>
-#include <linux/pci.h>
-#include <linux/seq_file.h>
-
-#include <linux/mic_common.h>
-#include "../common/mic_dev.h"
-#include "mic_device.h"
-#include "mic_smpt.h"
-
-/* Debugfs parent dir */
-static struct dentry *mic_dbg;
-
-static int mic_smpt_show(struct seq_file *s, void *pos)
-{
-       int i;
-       struct mic_device *mdev = s->private;
-       unsigned long flags;
-
-       seq_printf(s, "MIC %-2d |%-10s| %-14s %-10s\n",
-                  mdev->id, "SMPT entry", "SW DMA addr", "RefCount");
-       seq_puts(s, "====================================================\n");
-
-       if (mdev->smpt) {
-               struct mic_smpt_info *smpt_info = mdev->smpt;
-               spin_lock_irqsave(&smpt_info->smpt_lock, flags);
-               for (i = 0; i < smpt_info->info.num_reg; i++) {
-                       seq_printf(s, "%9s|%-10d| %-#14llx %-10lld\n",
-                                  " ",  i, smpt_info->entry[i].dma_addr,
-                                  smpt_info->entry[i].ref_count);
-               }
-               spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
-       }
-       seq_puts(s, "====================================================\n");
-       return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(mic_smpt);
-
-static int mic_post_code_show(struct seq_file *s, void *pos)
-{
-       struct mic_device *mdev = s->private;
-       u32 reg = mdev->ops->get_postcode(mdev);
-
-       seq_printf(s, "%c%c", reg & 0xff, (reg >> 8) & 0xff);
-       return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(mic_post_code);
-
-static int mic_msi_irq_info_show(struct seq_file *s, void *pos)
-{
-       struct mic_device *mdev  = s->private;
-       int reg;
-       int i, j;
-       u16 entry;
-       u16 vector;
-       struct pci_dev *pdev = mdev->pdev;
-
-       if (pci_dev_msi_enabled(pdev)) {
-               for (i = 0; i < mdev->irq_info.num_vectors; i++) {
-                       if (pdev->msix_enabled) {
-                               entry = mdev->irq_info.msix_entries[i].entry;
-                               vector = mdev->irq_info.msix_entries[i].vector;
-                       } else {
-                               entry = 0;
-                               vector = pdev->irq;
-                       }
-
-                       reg = mdev->intr_ops->read_msi_to_src_map(mdev, entry);
-
-                       seq_printf(s, "%s %-10d %s %-10d MXAR[%d]: %08X\n",
-                                  "IRQ:", vector, "Entry:", entry, i, reg);
-
-                       seq_printf(s, "%-10s", "offset:");
-                       for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--)
-                               seq_printf(s, "%4d ", j);
-                       seq_puts(s, "\n");
-
-
-                       seq_printf(s, "%-10s", "count:");
-                       for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--)
-                               seq_printf(s, "%4d ",
-                                          (mdev->irq_info.mic_msi_map[i] &
-                                          BIT(j)) ? 1 : 0);
-                       seq_puts(s, "\n\n");
-               }
-       } else {
-               seq_puts(s, "MSI/MSIx interrupts not enabled\n");
-       }
-
-       return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(mic_msi_irq_info);
-
-/*
- * mic_create_debug_dir - Initialize MIC debugfs entries.
- */
-void mic_create_debug_dir(struct mic_device *mdev)
-{
-       char name[16];
-
-       if (!mic_dbg)
-               return;
-
-       scnprintf(name, sizeof(name), "mic%d", mdev->id);
-       mdev->dbg_dir = debugfs_create_dir(name, mic_dbg);
-
-       debugfs_create_file("smpt", 0444, mdev->dbg_dir, mdev,
-                           &mic_smpt_fops);
-
-       debugfs_create_file("post_code", 0444, mdev->dbg_dir, mdev,
-                           &mic_post_code_fops);
-
-       debugfs_create_file("msi_irq_info", 0444, mdev->dbg_dir, mdev,
-                           &mic_msi_irq_info_fops);
-}
-
-/*
- * mic_delete_debug_dir - Uninitialize MIC debugfs entries.
- */
-void mic_delete_debug_dir(struct mic_device *mdev)
-{
-       debugfs_remove_recursive(mdev->dbg_dir);
-}
-
-/*
- * mic_init_debugfs - Initialize global debugfs entry.
- */
-void __init mic_init_debugfs(void)
-{
-       mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
-}
-
-/*
- * mic_exit_debugfs - Uninitialize global debugfs entry
- */
-void mic_exit_debugfs(void)
-{
-       debugfs_remove(mic_dbg);
-}
diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h
deleted file mode 100644 (file)
index 41bcd30..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Intel MIC Host driver.
- */
-#ifndef _MIC_DEVICE_H_
-#define _MIC_DEVICE_H_
-
-#include <linux/cdev.h>
-#include <linux/idr.h>
-#include <linux/notifier.h>
-#include <linux/irqreturn.h>
-#include <linux/dmaengine.h>
-#include <linux/miscdevice.h>
-#include <linux/mic_bus.h>
-#include "../bus/scif_bus.h"
-#include "../bus/vop_bus.h"
-#include "../bus/cosm_bus.h"
-#include "mic_intr.h"
-
-/**
- * enum mic_stepping - MIC stepping ids.
- */
-enum mic_stepping {
-       MIC_A0_STEP = 0x0,
-       MIC_B0_STEP = 0x10,
-       MIC_B1_STEP = 0x11,
-       MIC_C0_STEP = 0x20,
-};
-
-extern struct cosm_hw_ops cosm_hw_ops;
-
-/**
- * struct mic_device -  MIC device information for each card.
- *
- * @mmio: MMIO bar information.
- * @aper: Aperture bar information.
- * @family: The MIC family to which this device belongs.
- * @ops: MIC HW specific operations.
- * @id: The unique device id for this MIC device.
- * @stepping: Stepping ID.
- * @pdev: Underlying PCI device.
- * @mic_mutex: Mutex for synchronizing access to mic_device.
- * @intr_ops: HW specific interrupt operations.
- * @smpt_ops: Hardware specific SMPT operations.
- * @smpt: MIC SMPT information.
- * @intr_info: H/W specific interrupt information.
- * @irq_info: The OS specific irq information
- * @dbg_dir: debugfs directory of this MIC device.
- * @bootaddr: MIC boot address.
- * @dp: virtio device page
- * @dp_dma_addr: virtio device page DMA address.
- * @dma_mbdev: MIC BUS DMA device.
- * @dma_ch - Array of DMA channels
- * @num_dma_ch - Number of DMA channels available
- * @scdev: SCIF device on the SCIF virtual bus.
- * @vpdev: Virtio over PCIe device on the VOP virtual bus.
- * @cosm_dev: COSM device
- */
-struct mic_device {
-       struct mic_mw mmio;
-       struct mic_mw aper;
-       enum mic_hw_family family;
-       struct mic_hw_ops *ops;
-       int id;
-       enum mic_stepping stepping;
-       struct pci_dev *pdev;
-       struct mutex mic_mutex;
-       struct mic_hw_intr_ops *intr_ops;
-       struct mic_smpt_ops *smpt_ops;
-       struct mic_smpt_info *smpt;
-       struct mic_intr_info *intr_info;
-       struct mic_irq_info irq_info;
-       struct dentry *dbg_dir;
-       u32 bootaddr;
-       void *dp;
-       dma_addr_t dp_dma_addr;
-       struct mbus_device *dma_mbdev;
-       struct dma_chan *dma_ch[MIC_MAX_DMA_CHAN];
-       int num_dma_ch;
-       struct scif_hw_dev *scdev;
-       struct vop_device *vpdev;
-       struct cosm_device *cosm_dev;
-};
-
-/**
- * struct mic_hw_ops - MIC HW specific operations.
- * @aper_bar: Aperture bar resource number.
- * @mmio_bar: MMIO bar resource number.
- * @read_spad: Read from scratch pad register.
- * @write_spad: Write to scratch pad register.
- * @send_intr: Send an interrupt for a particular doorbell on the card.
- * @ack_interrupt: Hardware specific operations to ack the h/w on
- * receipt of an interrupt.
- * @intr_workarounds: Hardware specific workarounds needed after
- * handling an interrupt.
- * @reset: Reset the remote processor.
- * @reset_fw_ready: Reset firmware ready field.
- * @is_fw_ready: Check if firmware is ready for OS download.
- * @send_firmware_intr: Send an interrupt to the card firmware.
- * @load_mic_fw: Load firmware segments required to boot the card
- * into card memory. This includes the kernel, command line, ramdisk etc.
- * @get_postcode: Get post code status from firmware.
- * @dma_filter: DMA filter function to be used.
- */
-struct mic_hw_ops {
-       u8 aper_bar;
-       u8 mmio_bar;
-       u32 (*read_spad)(struct mic_device *mdev, unsigned int idx);
-       void (*write_spad)(struct mic_device *mdev, unsigned int idx, u32 val);
-       void (*send_intr)(struct mic_device *mdev, int doorbell);
-       u32 (*ack_interrupt)(struct mic_device *mdev);
-       void (*intr_workarounds)(struct mic_device *mdev);
-       void (*reset)(struct mic_device *mdev);
-       void (*reset_fw_ready)(struct mic_device *mdev);
-       bool (*is_fw_ready)(struct mic_device *mdev);
-       void (*send_firmware_intr)(struct mic_device *mdev);
-       int (*load_mic_fw)(struct mic_device *mdev, const char *buf);
-       u32 (*get_postcode)(struct mic_device *mdev);
-       bool (*dma_filter)(struct dma_chan *chan, void *param);
-};
-
-/**
- * mic_mmio_read - read from an MMIO register.
- * @mw: MMIO register base virtual address.
- * @offset: register offset.
- *
- * RETURNS: register value.
- */
-static inline u32 mic_mmio_read(struct mic_mw *mw, u32 offset)
-{
-       return ioread32(mw->va + offset);
-}
-
-/**
- * mic_mmio_write - write to an MMIO register.
- * @mw: MMIO register base virtual address.
- * @val: the data value to put into the register
- * @offset: register offset.
- *
- * RETURNS: none.
- */
-static inline void
-mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset)
-{
-       iowrite32(val, mw->va + offset);
-}
-
-void mic_bootparam_init(struct mic_device *mdev);
-void mic_create_debug_dir(struct mic_device *dev);
-void mic_delete_debug_dir(struct mic_device *dev);
-void __init mic_init_debugfs(void);
-void mic_exit_debugfs(void);
-#endif
diff --git a/drivers/misc/mic/host/mic_intr.c b/drivers/misc/mic/host/mic_intr.c
deleted file mode 100644 (file)
index 85b3221..0000000
+++ /dev/null
@@ -1,635 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Intel MIC Host driver.
- */
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-
-#include "../common/mic_dev.h"
-#include "mic_device.h"
-
-static irqreturn_t mic_thread_fn(int irq, void *dev)
-{
-       struct mic_device *mdev = dev;
-       struct mic_intr_info *intr_info = mdev->intr_info;
-       struct mic_irq_info *irq_info = &mdev->irq_info;
-       struct mic_intr_cb *intr_cb;
-       struct pci_dev *pdev = mdev->pdev;
-       int i;
-
-       spin_lock(&irq_info->mic_thread_lock);
-       for (i = intr_info->intr_start_idx[MIC_INTR_DB];
-                       i < intr_info->intr_len[MIC_INTR_DB]; i++)
-               if (test_and_clear_bit(i, &irq_info->mask)) {
-                       list_for_each_entry(intr_cb, &irq_info->cb_list[i],
-                                           list)
-                               if (intr_cb->thread_fn)
-                                       intr_cb->thread_fn(pdev->irq,
-                                                        intr_cb->data);
-               }
-       spin_unlock(&irq_info->mic_thread_lock);
-       return IRQ_HANDLED;
-}
-/**
- * mic_interrupt - Generic interrupt handler for
- * MSI and INTx based interrupts.
- * @irq:  interrupt to handle (unused)
- * @dev: pointer to the mic_device instance
- */
-static irqreturn_t mic_interrupt(int irq, void *dev)
-{
-       struct mic_device *mdev = dev;
-       struct mic_intr_info *intr_info = mdev->intr_info;
-       struct mic_irq_info *irq_info = &mdev->irq_info;
-       struct mic_intr_cb *intr_cb;
-       struct pci_dev *pdev = mdev->pdev;
-       u32 mask;
-       int i;
-
-       mask = mdev->ops->ack_interrupt(mdev);
-       if (!mask)
-               return IRQ_NONE;
-
-       spin_lock(&irq_info->mic_intr_lock);
-       for (i = intr_info->intr_start_idx[MIC_INTR_DB];
-                       i < intr_info->intr_len[MIC_INTR_DB]; i++)
-               if (mask & BIT(i)) {
-                       list_for_each_entry(intr_cb, &irq_info->cb_list[i],
-                                           list)
-                               if (intr_cb->handler)
-                                       intr_cb->handler(pdev->irq,
-                                                        intr_cb->data);
-                       set_bit(i, &irq_info->mask);
-               }
-       spin_unlock(&irq_info->mic_intr_lock);
-       return IRQ_WAKE_THREAD;
-}
-
-/* Return the interrupt offset from the index. Index is 0 based. */
-static u16 mic_map_src_to_offset(struct mic_device *mdev,
-                                int intr_src, enum mic_intr_type type)
-{
-       if (type >= MIC_NUM_INTR_TYPES)
-               return MIC_NUM_OFFSETS;
-       if (intr_src >= mdev->intr_info->intr_len[type])
-               return MIC_NUM_OFFSETS;
-
-       return mdev->intr_info->intr_start_idx[type] + intr_src;
-}
-
-/* Return next available msix_entry. */
-static struct msix_entry *mic_get_available_vector(struct mic_device *mdev)
-{
-       int i;
-       struct mic_irq_info *info = &mdev->irq_info;
-
-       for (i = 0; i < info->num_vectors; i++)
-               if (!info->mic_msi_map[i])
-                       return &info->msix_entries[i];
-       return NULL;
-}
-
-/**
- * mic_register_intr_callback - Register a callback handler for the
- * given source id.
- *
- * @mdev: pointer to the mic_device instance
- * @idx: The source id to be registered.
- * @handler: The function to be called when the source id receives
- * the interrupt.
- * @thread_fn: thread fn. corresponding to the handler
- * @data: Private data of the requester.
- * Return the callback structure that was registered or an
- * appropriate error on failure.
- */
-static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev,
-                       u8 idx, irq_handler_t handler, irq_handler_t thread_fn,
-                       void *data)
-{
-       struct mic_intr_cb *intr_cb;
-       unsigned long flags;
-       int rc;
-       intr_cb = kmalloc(sizeof(*intr_cb), GFP_KERNEL);
-
-       if (!intr_cb)
-               return ERR_PTR(-ENOMEM);
-
-       intr_cb->handler = handler;
-       intr_cb->thread_fn = thread_fn;
-       intr_cb->data = data;
-       intr_cb->cb_id = ida_simple_get(&mdev->irq_info.cb_ida,
-               0, 0, GFP_KERNEL);
-       if (intr_cb->cb_id < 0) {
-               rc = intr_cb->cb_id;
-               goto ida_fail;
-       }
-
-       spin_lock(&mdev->irq_info.mic_thread_lock);
-       spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
-       list_add_tail(&intr_cb->list, &mdev->irq_info.cb_list[idx]);
-       spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
-       spin_unlock(&mdev->irq_info.mic_thread_lock);
-
-       return intr_cb;
-ida_fail:
-       kfree(intr_cb);
-       return ERR_PTR(rc);
-}
-
-/**
- * mic_unregister_intr_callback - Unregister the callback handler
- * identified by its callback id.
- *
- * @mdev: pointer to the mic_device instance
- * @idx: The callback structure id to be unregistered.
- * Return the source id that was unregistered or MIC_NUM_OFFSETS if no
- * such callback handler was found.
- */
-static u8 mic_unregister_intr_callback(struct mic_device *mdev, u32 idx)
-{
-       struct list_head *pos, *tmp;
-       struct mic_intr_cb *intr_cb;
-       unsigned long flags;
-       int i;
-
-       spin_lock(&mdev->irq_info.mic_thread_lock);
-       spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
-       for (i = 0;  i < MIC_NUM_OFFSETS; i++) {
-               list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
-                       intr_cb = list_entry(pos, struct mic_intr_cb, list);
-                       if (intr_cb->cb_id == idx) {
-                               list_del(pos);
-                               ida_simple_remove(&mdev->irq_info.cb_ida,
-                                                 intr_cb->cb_id);
-                               kfree(intr_cb);
-                               spin_unlock_irqrestore(
-                                       &mdev->irq_info.mic_intr_lock, flags);
-                               spin_unlock(&mdev->irq_info.mic_thread_lock);
-                               return i;
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
-       spin_unlock(&mdev->irq_info.mic_thread_lock);
-       return MIC_NUM_OFFSETS;
-}
-
-/**
- * mic_setup_msix - Initializes MSIx interrupts.
- *
- * @mdev: pointer to mic_device instance
- * @pdev: PCI device structure
- *
- * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
- */
-static int mic_setup_msix(struct mic_device *mdev, struct pci_dev *pdev)
-{
-       int rc, i;
-       int entry_size = sizeof(*mdev->irq_info.msix_entries);
-
-       mdev->irq_info.msix_entries = kmalloc_array(MIC_MIN_MSIX,
-                                                   entry_size, GFP_KERNEL);
-       if (!mdev->irq_info.msix_entries) {
-               rc = -ENOMEM;
-               goto err_nomem1;
-       }
-
-       for (i = 0; i < MIC_MIN_MSIX; i++)
-               mdev->irq_info.msix_entries[i].entry = i;
-
-       rc = pci_enable_msix_exact(pdev, mdev->irq_info.msix_entries,
-                                  MIC_MIN_MSIX);
-       if (rc) {
-               dev_dbg(&pdev->dev, "Error enabling MSIx. rc = %d\n", rc);
-               goto err_enable_msix;
-       }
-
-       mdev->irq_info.num_vectors = MIC_MIN_MSIX;
-       mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
-               mdev->irq_info.num_vectors), GFP_KERNEL);
-
-       if (!mdev->irq_info.mic_msi_map) {
-               rc = -ENOMEM;
-               goto err_nomem2;
-       }
-
-       dev_dbg(&mdev->pdev->dev,
-               "%d MSIx irqs setup\n", mdev->irq_info.num_vectors);
-       return 0;
-err_nomem2:
-       pci_disable_msix(pdev);
-err_enable_msix:
-       kfree(mdev->irq_info.msix_entries);
-err_nomem1:
-       mdev->irq_info.num_vectors = 0;
-       return rc;
-}
-
-/**
- * mic_setup_callbacks - Initialize data structures needed
- * to handle callbacks.
- *
- * @mdev: pointer to mic_device instance
- */
-static int mic_setup_callbacks(struct mic_device *mdev)
-{
-       int i;
-
-       mdev->irq_info.cb_list = kmalloc_array(MIC_NUM_OFFSETS,
-                                              sizeof(*mdev->irq_info.cb_list),
-                                              GFP_KERNEL);
-       if (!mdev->irq_info.cb_list)
-               return -ENOMEM;
-
-       for (i = 0; i < MIC_NUM_OFFSETS; i++)
-               INIT_LIST_HEAD(&mdev->irq_info.cb_list[i]);
-       ida_init(&mdev->irq_info.cb_ida);
-       spin_lock_init(&mdev->irq_info.mic_intr_lock);
-       spin_lock_init(&mdev->irq_info.mic_thread_lock);
-       return 0;
-}
-
-/**
- * mic_release_callbacks - Uninitialize data structures needed
- * to handle callbacks.
- *
- * @mdev: pointer to mic_device instance
- */
-static void mic_release_callbacks(struct mic_device *mdev)
-{
-       unsigned long flags;
-       struct list_head *pos, *tmp;
-       struct mic_intr_cb *intr_cb;
-       int i;
-
-       spin_lock(&mdev->irq_info.mic_thread_lock);
-       spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
-       for (i = 0; i < MIC_NUM_OFFSETS; i++) {
-               if (list_empty(&mdev->irq_info.cb_list[i]))
-                       break;
-
-               list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
-                       intr_cb = list_entry(pos, struct mic_intr_cb, list);
-                       list_del(pos);
-                       ida_simple_remove(&mdev->irq_info.cb_ida,
-                                         intr_cb->cb_id);
-                       kfree(intr_cb);
-               }
-       }
-       spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
-       spin_unlock(&mdev->irq_info.mic_thread_lock);
-       ida_destroy(&mdev->irq_info.cb_ida);
-       kfree(mdev->irq_info.cb_list);
-}
-
-/**
- * mic_setup_msi - Initializes MSI interrupts.
- *
- * @mdev: pointer to mic_device instance
- * @pdev: PCI device structure
- *
- * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
- */
-static int mic_setup_msi(struct mic_device *mdev, struct pci_dev *pdev)
-{
-       int rc;
-
-       rc = pci_enable_msi(pdev);
-       if (rc) {
-               dev_dbg(&pdev->dev, "Error enabling MSI. rc = %d\n", rc);
-               return rc;
-       }
-
-       mdev->irq_info.num_vectors = 1;
-       mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
-               mdev->irq_info.num_vectors), GFP_KERNEL);
-
-       if (!mdev->irq_info.mic_msi_map) {
-               rc = -ENOMEM;
-               goto err_nomem1;
-       }
-
-       rc = mic_setup_callbacks(mdev);
-       if (rc) {
-               dev_err(&pdev->dev, "Error setting up callbacks\n");
-               goto err_nomem2;
-       }
-
-       rc = request_threaded_irq(pdev->irq, mic_interrupt, mic_thread_fn,
-                                 0, "mic-msi", mdev);
-       if (rc) {
-               dev_err(&pdev->dev, "Error allocating MSI interrupt\n");
-               goto err_irq_req_fail;
-       }
-
-       dev_dbg(&pdev->dev, "%d MSI irqs setup\n", mdev->irq_info.num_vectors);
-       return 0;
-err_irq_req_fail:
-       mic_release_callbacks(mdev);
-err_nomem2:
-       kfree(mdev->irq_info.mic_msi_map);
-err_nomem1:
-       pci_disable_msi(pdev);
-       mdev->irq_info.num_vectors = 0;
-       return rc;
-}
-
-/**
- * mic_setup_intx - Initializes legacy interrupts.
- *
- * @mdev: pointer to mic_device instance
- * @pdev: PCI device structure
- *
- * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
- */
-static int mic_setup_intx(struct mic_device *mdev, struct pci_dev *pdev)
-{
-       int rc;
-
-       /* Enable intx */
-       pci_intx(pdev, 1);
-       rc = mic_setup_callbacks(mdev);
-       if (rc) {
-               dev_err(&pdev->dev, "Error setting up callbacks\n");
-               goto err_nomem;
-       }
-
-       rc = request_threaded_irq(pdev->irq, mic_interrupt, mic_thread_fn,
-                                 IRQF_SHARED, "mic-intx", mdev);
-       if (rc)
-               goto err;
-
-       dev_dbg(&pdev->dev, "intx irq setup\n");
-       return 0;
-err:
-       mic_release_callbacks(mdev);
-err_nomem:
-       return rc;
-}
-
-/**
- * mic_next_db - Retrieve the next doorbell interrupt source id.
- * The id is picked sequentially from the available pool of
- * doorlbell ids.
- *
- * @mdev: pointer to the mic_device instance.
- *
- * Returns the next doorbell interrupt source.
- */
-int mic_next_db(struct mic_device *mdev)
-{
-       int next_db;
-
-       next_db = mdev->irq_info.next_avail_src %
-               mdev->intr_info->intr_len[MIC_INTR_DB];
-       mdev->irq_info.next_avail_src++;
-       return next_db;
-}
-
-#define COOKIE_ID_SHIFT 16
-#define GET_ENTRY(cookie) ((cookie) & 0xFFFF)
-#define GET_OFFSET(cookie) ((cookie) >> COOKIE_ID_SHIFT)
-#define MK_COOKIE(x, y) ((x) | (y) << COOKIE_ID_SHIFT)
-
-/**
- * mic_request_threaded_irq - request an irq. mic_mutex needs
- * to be held before calling this function.
- *
- * @mdev: pointer to mic_device instance
- * @handler: The callback function that handles the interrupt.
- * The function needs to call ack_interrupts
- * (mdev->ops->ack_interrupt(mdev)) when handling the interrupts.
- * @thread_fn: thread fn required by request_threaded_irq.
- * @name: The ASCII name of the callee requesting the irq.
- * @data: private data that is returned back when calling the
- * function handler.
- * @intr_src: The source id of the requester. Its the doorbell id
- * for Doorbell interrupts and DMA channel id for DMA interrupts.
- * @type: The type of interrupt. Values defined in mic_intr_type
- *
- * returns: The cookie that is transparent to the caller. Passed
- * back when calling mic_free_irq. An appropriate error code
- * is returned on failure. Caller needs to use IS_ERR(return_val)
- * to check for failure and PTR_ERR(return_val) to obtained the
- * error code.
- *
- */
-struct mic_irq *
-mic_request_threaded_irq(struct mic_device *mdev,
-                        irq_handler_t handler, irq_handler_t thread_fn,
-                        const char *name, void *data, int intr_src,
-                        enum mic_intr_type type)
-{
-       u16 offset;
-       int rc = 0;
-       struct msix_entry *msix = NULL;
-       unsigned long cookie = 0;
-       u16 entry;
-       struct mic_intr_cb *intr_cb;
-       struct pci_dev *pdev = mdev->pdev;
-
-       offset = mic_map_src_to_offset(mdev, intr_src, type);
-       if (offset >= MIC_NUM_OFFSETS) {
-               dev_err(&mdev->pdev->dev,
-                       "Error mapping index %d to a valid source id.\n",
-                       intr_src);
-               rc = -EINVAL;
-               goto err;
-       }
-
-       if (mdev->irq_info.num_vectors > 1) {
-               msix = mic_get_available_vector(mdev);
-               if (!msix) {
-                       dev_err(&mdev->pdev->dev,
-                               "No MSIx vectors available for use.\n");
-                       rc = -ENOSPC;
-                       goto err;
-               }
-
-               rc = request_threaded_irq(msix->vector, handler, thread_fn,
-                                         0, name, data);
-               if (rc) {
-                       dev_dbg(&mdev->pdev->dev,
-                               "request irq failed rc = %d\n", rc);
-                       goto err;
-               }
-               entry = msix->entry;
-               mdev->irq_info.mic_msi_map[entry] |= BIT(offset);
-               mdev->intr_ops->program_msi_to_src_map(mdev,
-                               entry, offset, true);
-               cookie = MK_COOKIE(entry, offset);
-               dev_dbg(&mdev->pdev->dev, "irq: %d assigned for src: %d\n",
-                       msix->vector, intr_src);
-       } else {
-               intr_cb = mic_register_intr_callback(mdev, offset, handler,
-                                                    thread_fn, data);
-               if (IS_ERR(intr_cb)) {
-                       dev_err(&mdev->pdev->dev,
-                               "No available callback entries for use\n");
-                       rc = PTR_ERR(intr_cb);
-                       goto err;
-               }
-
-               entry = 0;
-               if (pci_dev_msi_enabled(pdev)) {
-                       mdev->irq_info.mic_msi_map[entry] |= (1 << offset);
-                       mdev->intr_ops->program_msi_to_src_map(mdev,
-                               entry, offset, true);
-               }
-               cookie = MK_COOKIE(entry, intr_cb->cb_id);
-               dev_dbg(&mdev->pdev->dev, "callback %d registered for src: %d\n",
-                       intr_cb->cb_id, intr_src);
-       }
-       return (struct mic_irq *)cookie;
-err:
-       return ERR_PTR(rc);
-}
-
-/**
- * mic_free_irq - free irq. mic_mutex
- *  needs to be held before calling this function.
- *
- * @mdev: pointer to mic_device instance
- * @cookie: cookie obtained during a successful call to mic_request_threaded_irq
- * @data: private data specified by the calling function during the
- * mic_request_threaded_irq
- *
- * returns: none.
- */
-void mic_free_irq(struct mic_device *mdev,
-                 struct mic_irq *cookie, void *data)
-{
-       u32 offset;
-       u32 entry;
-       u8 src_id;
-       unsigned int irq;
-       struct pci_dev *pdev = mdev->pdev;
-
-       entry = GET_ENTRY((unsigned long)cookie);
-       offset = GET_OFFSET((unsigned long)cookie);
-       if (mdev->irq_info.num_vectors > 1) {
-               if (entry >= mdev->irq_info.num_vectors) {
-                       dev_warn(&mdev->pdev->dev,
-                                "entry %d should be < num_irq %d\n",
-                               entry, mdev->irq_info.num_vectors);
-                       return;
-               }
-               irq = mdev->irq_info.msix_entries[entry].vector;
-               free_irq(irq, data);
-               mdev->irq_info.mic_msi_map[entry] &= ~(BIT(offset));
-               mdev->intr_ops->program_msi_to_src_map(mdev,
-                       entry, offset, false);
-
-               dev_dbg(&mdev->pdev->dev, "irq: %d freed\n", irq);
-       } else {
-               irq = pdev->irq;
-               src_id = mic_unregister_intr_callback(mdev, offset);
-               if (src_id >= MIC_NUM_OFFSETS) {
-                       dev_warn(&mdev->pdev->dev, "Error unregistering callback\n");
-                       return;
-               }
-               if (pci_dev_msi_enabled(pdev)) {
-                       mdev->irq_info.mic_msi_map[entry] &= ~(BIT(src_id));
-                       mdev->intr_ops->program_msi_to_src_map(mdev,
-                               entry, src_id, false);
-               }
-               dev_dbg(&mdev->pdev->dev, "callback %d unregistered for src: %d\n",
-                       offset, src_id);
-       }
-}
-
-/**
- * mic_setup_interrupts - Initializes interrupts.
- *
- * @mdev: pointer to mic_device instance
- * @pdev: PCI device structure
- *
- * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
- */
-int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
-{
-       int rc;
-
-       rc = mic_setup_msix(mdev, pdev);
-       if (!rc)
-               goto done;
-
-       rc = mic_setup_msi(mdev, pdev);
-       if (!rc)
-               goto done;
-
-       rc = mic_setup_intx(mdev, pdev);
-       if (rc) {
-               dev_err(&mdev->pdev->dev, "no usable interrupts\n");
-               return rc;
-       }
-done:
-       mdev->intr_ops->enable_interrupts(mdev);
-       return 0;
-}
-
-/**
- * mic_free_interrupts - Frees interrupts setup by mic_setup_interrupts
- *
- * @mdev: pointer to mic_device instance
- * @pdev: PCI device structure
- *
- * returns none.
- */
-void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
-{
-       int i;
-
-       mdev->intr_ops->disable_interrupts(mdev);
-       if (mdev->irq_info.num_vectors > 1) {
-               for (i = 0; i < mdev->irq_info.num_vectors; i++) {
-                       if (mdev->irq_info.mic_msi_map[i])
-                               dev_warn(&pdev->dev, "irq %d may still be in use.\n",
-                                        mdev->irq_info.msix_entries[i].vector);
-               }
-               kfree(mdev->irq_info.mic_msi_map);
-               kfree(mdev->irq_info.msix_entries);
-               pci_disable_msix(pdev);
-       } else {
-               if (pci_dev_msi_enabled(pdev)) {
-                       free_irq(pdev->irq, mdev);
-                       kfree(mdev->irq_info.mic_msi_map);
-                       pci_disable_msi(pdev);
-               } else {
-                       free_irq(pdev->irq, mdev);
-               }
-               mic_release_callbacks(mdev);
-       }
-}
-
-/**
- * mic_intr_restore - Restore MIC interrupt registers.
- *
- * @mdev: pointer to mic_device instance.
- *
- * Restore the interrupt registers to values previously
- * stored in the SW data structures. mic_mutex needs to
- * be held before calling this function.
- *
- * returns None.
- */
-void mic_intr_restore(struct mic_device *mdev)
-{
-       int entry, offset;
-       struct pci_dev *pdev = mdev->pdev;
-
-       if (!pci_dev_msi_enabled(pdev))
-               return;
-
-       for (entry = 0; entry < mdev->irq_info.num_vectors; entry++) {
-               for (offset = 0; offset < MIC_NUM_OFFSETS; offset++) {
-                       if (mdev->irq_info.mic_msi_map[entry] & BIT(offset))
-                               mdev->intr_ops->program_msi_to_src_map(mdev,
-                                       entry, offset, true);
-               }
-       }
-}
diff --git a/drivers/misc/mic/host/mic_intr.h b/drivers/misc/mic/host/mic_intr.h
deleted file mode 100644 (file)
index b14ba81..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Intel MIC Host driver.
- */
-#ifndef _MIC_INTR_H_
-#define _MIC_INTR_H_
-
-#include <linux/bitops.h>
-#include <linux/interrupt.h>
-/*
- * The minimum number of msix vectors required for normal operation.
- * 3 for virtio network, console and block devices.
- * 1 for card shutdown notifications.
- * 4 for host owned DMA channels.
- * 1 for SCIF
- */
-#define MIC_MIN_MSIX 9
-#define MIC_NUM_OFFSETS 32
-
-/**
- * mic_intr_source - The type of source that will generate
- * the interrupt.The number of types needs to be in sync with
- * MIC_NUM_INTR_TYPES
- *
- * MIC_INTR_DB: The source is a doorbell
- * MIC_INTR_DMA: The source is a DMA channel
- * MIC_INTR_ERR: The source is an error interrupt e.g. SBOX ERR
- * MIC_NUM_INTR_TYPES: Total number of interrupt sources.
- */
-enum mic_intr_type {
-       MIC_INTR_DB = 0,
-       MIC_INTR_DMA,
-       MIC_INTR_ERR,
-       MIC_NUM_INTR_TYPES
-};
-
-/**
- * struct mic_intr_info - Contains h/w specific interrupt sources
- * information.
- *
- * @intr_start_idx: Contains the starting indexes of the
- * interrupt types.
- * @intr_len: Contains the length of the interrupt types.
- */
-struct mic_intr_info {
-       u16 intr_start_idx[MIC_NUM_INTR_TYPES];
-       u16 intr_len[MIC_NUM_INTR_TYPES];
-};
-
-/**
- * struct mic_irq_info - OS specific irq information
- *
- * @next_avail_src: next available doorbell that can be assigned.
- * @msix_entries: msix entries allocated while setting up MSI-x
- * @mic_msi_map: The MSI/MSI-x mapping information.
- * @num_vectors: The number of MSI/MSI-x vectors that have been allocated.
- * @cb_ida: callback ID allocator to track the callbacks registered.
- * @mic_intr_lock: spinlock to protect the interrupt callback list.
- * @mic_thread_lock: spinlock to protect the thread callback list.
- *                This lock is used to protect against thread_fn while
- *                mic_intr_lock is used to protect against interrupt handler.
- * @cb_list: Array of callback lists one for each source.
- * @mask: Mask used by the main thread fn to call the underlying thread fns.
- */
-struct mic_irq_info {
-       int next_avail_src;
-       struct msix_entry *msix_entries;
-       u32 *mic_msi_map;
-       u16 num_vectors;
-       struct ida cb_ida;
-       spinlock_t mic_intr_lock;
-       spinlock_t mic_thread_lock;
-       struct list_head *cb_list;
-       unsigned long mask;
-};
-
-/**
- * struct mic_intr_cb - Interrupt callback structure.
- *
- * @handler: The callback function
- * @thread_fn: The thread_fn.
- * @data: Private data of the requester.
- * @cb_id: The callback id. Identifies this callback.
- * @list: list head pointing to the next callback structure.
- */
-struct mic_intr_cb {
-       irq_handler_t handler;
-       irq_handler_t thread_fn;
-       void *data;
-       int cb_id;
-       struct list_head list;
-};
-
-/**
- * struct mic_irq - opaque pointer used as cookie
- */
-struct mic_irq;
-
-/* Forward declaration */
-struct mic_device;
-
-/**
- * struct mic_hw_intr_ops: MIC HW specific interrupt operations
- * @intr_init: Initialize H/W specific interrupt information.
- * @enable_interrupts: Enable interrupts from the hardware.
- * @disable_interrupts: Disable interrupts from the hardware.
- * @program_msi_to_src_map: Update MSI mapping registers with
- * irq information.
- * @read_msi_to_src_map: Read MSI mapping registers containing
- * irq information.
- */
-struct mic_hw_intr_ops {
-       void (*intr_init)(struct mic_device *mdev);
-       void (*enable_interrupts)(struct mic_device *mdev);
-       void (*disable_interrupts)(struct mic_device *mdev);
-       void (*program_msi_to_src_map) (struct mic_device *mdev,
-                       int idx, int intr_src, bool set);
-       u32 (*read_msi_to_src_map) (struct mic_device *mdev,
-                       int idx);
-};
-
-int mic_next_db(struct mic_device *mdev);
-struct mic_irq *
-mic_request_threaded_irq(struct mic_device *mdev,
-                        irq_handler_t handler, irq_handler_t thread_fn,
-                        const char *name, void *data, int intr_src,
-                        enum mic_intr_type type);
-void mic_free_irq(struct mic_device *mdev,
-               struct mic_irq *cookie, void *data);
-int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev);
-void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev);
-void mic_intr_restore(struct mic_device *mdev);
-#endif
diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c
deleted file mode 100644 (file)
index ea46085..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Intel MIC Host driver.
- */
-#include <linux/fs.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/poll.h>
-
-#include <linux/mic_common.h>
-#include "../common/mic_dev.h"
-#include "mic_device.h"
-#include "mic_x100.h"
-#include "mic_smpt.h"
-
-static const char mic_driver_name[] = "mic";
-
-static const struct pci_device_id mic_pci_tbl[] = {
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2250)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2251)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2252)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2253)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2254)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2255)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2256)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2257)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2258)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2259)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225a)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225b)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225c)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225d)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225e)},
-
-       /* required last entry */
-       { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, mic_pci_tbl);
-
-/* ID allocator for MIC devices */
-static struct ida g_mic_ida;
-
-/* Initialize the device page */
-static int mic_dp_init(struct mic_device *mdev)
-{
-       mdev->dp = kzalloc(MIC_DP_SIZE, GFP_KERNEL);
-       if (!mdev->dp)
-               return -ENOMEM;
-
-       mdev->dp_dma_addr = mic_map_single(mdev,
-               mdev->dp, MIC_DP_SIZE);
-       if (mic_map_error(mdev->dp_dma_addr)) {
-               kfree(mdev->dp);
-               dev_err(&mdev->pdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, -ENOMEM);
-               return -ENOMEM;
-       }
-       mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr);
-       mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
-       return 0;
-}
-
-/* Uninitialize the device page */
-static void mic_dp_uninit(struct mic_device *mdev)
-{
-       mic_unmap_single(mdev, mdev->dp_dma_addr, MIC_DP_SIZE);
-       kfree(mdev->dp);
-}
-
-/**
- * mic_ops_init: Initialize HW specific operation tables.
- *
- * @mdev: pointer to mic_device instance
- *
- * returns none.
- */
-static void mic_ops_init(struct mic_device *mdev)
-{
-       switch (mdev->family) {
-       case MIC_FAMILY_X100:
-               mdev->ops = &mic_x100_ops;
-               mdev->intr_ops = &mic_x100_intr_ops;
-               mdev->smpt_ops = &mic_x100_smpt_ops;
-               break;
-       default:
-               break;
-       }
-}
-
-/**
- * mic_get_family - Determine hardware family to which this MIC belongs.
- *
- * @pdev: The pci device structure
- *
- * returns family.
- */
-static enum mic_hw_family mic_get_family(struct pci_dev *pdev)
-{
-       enum mic_hw_family family;
-
-       switch (pdev->device) {
-       case MIC_X100_PCI_DEVICE_2250:
-       case MIC_X100_PCI_DEVICE_2251:
-       case MIC_X100_PCI_DEVICE_2252:
-       case MIC_X100_PCI_DEVICE_2253:
-       case MIC_X100_PCI_DEVICE_2254:
-       case MIC_X100_PCI_DEVICE_2255:
-       case MIC_X100_PCI_DEVICE_2256:
-       case MIC_X100_PCI_DEVICE_2257:
-       case MIC_X100_PCI_DEVICE_2258:
-       case MIC_X100_PCI_DEVICE_2259:
-       case MIC_X100_PCI_DEVICE_225a:
-       case MIC_X100_PCI_DEVICE_225b:
-       case MIC_X100_PCI_DEVICE_225c:
-       case MIC_X100_PCI_DEVICE_225d:
-       case MIC_X100_PCI_DEVICE_225e:
-               family = MIC_FAMILY_X100;
-               break;
-       default:
-               family = MIC_FAMILY_UNKNOWN;
-               break;
-       }
-       return family;
-}
-
-/**
- * mic_device_init - Allocates and initializes the MIC device structure
- *
- * @mdev: pointer to mic_device instance
- * @pdev: The pci device structure
- *
- * returns none.
- */
-static void
-mic_device_init(struct mic_device *mdev, struct pci_dev *pdev)
-{
-       mdev->pdev = pdev;
-       mdev->family = mic_get_family(pdev);
-       mdev->stepping = pdev->revision;
-       mic_ops_init(mdev);
-       mutex_init(&mdev->mic_mutex);
-       mdev->irq_info.next_avail_src = 0;
-}
-
-/**
- * mic_probe - Device Initialization Routine
- *
- * @pdev: PCI device structure
- * @ent: entry in mic_pci_tbl
- *
- * returns 0 on success, < 0 on failure.
- */
-static int mic_probe(struct pci_dev *pdev,
-                    const struct pci_device_id *ent)
-{
-       int rc;
-       struct mic_device *mdev;
-
-       mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
-       if (!mdev) {
-               rc = -ENOMEM;
-               goto mdev_alloc_fail;
-       }
-       mdev->id = ida_simple_get(&g_mic_ida, 0, MIC_MAX_NUM_DEVS, GFP_KERNEL);
-       if (mdev->id < 0) {
-               rc = mdev->id;
-               dev_err(&pdev->dev, "ida_simple_get failed rc %d\n", rc);
-               goto ida_fail;
-       }
-
-       mic_device_init(mdev, pdev);
-
-       rc = pci_enable_device(pdev);
-       if (rc) {
-               dev_err(&pdev->dev, "failed to enable pci device.\n");
-               goto ida_remove;
-       }
-
-       pci_set_master(pdev);
-
-       rc = pci_request_regions(pdev, mic_driver_name);
-       if (rc) {
-               dev_err(&pdev->dev, "failed to get pci regions.\n");
-               goto disable_device;
-       }
-
-       rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
-       if (rc) {
-               dev_err(&pdev->dev, "Cannot set DMA mask\n");
-               goto release_regions;
-       }
-
-       mdev->mmio.pa = pci_resource_start(pdev, mdev->ops->mmio_bar);
-       mdev->mmio.len = pci_resource_len(pdev, mdev->ops->mmio_bar);
-       mdev->mmio.va = pci_ioremap_bar(pdev, mdev->ops->mmio_bar);
-       if (!mdev->mmio.va) {
-               dev_err(&pdev->dev, "Cannot remap MMIO BAR\n");
-               rc = -EIO;
-               goto release_regions;
-       }
-
-       mdev->aper.pa = pci_resource_start(pdev, mdev->ops->aper_bar);
-       mdev->aper.len = pci_resource_len(pdev, mdev->ops->aper_bar);
-       mdev->aper.va = ioremap_wc(mdev->aper.pa, mdev->aper.len);
-       if (!mdev->aper.va) {
-               dev_err(&pdev->dev, "Cannot remap Aperture BAR\n");
-               rc = -EIO;
-               goto unmap_mmio;
-       }
-
-       mdev->intr_ops->intr_init(mdev);
-       rc = mic_setup_interrupts(mdev, pdev);
-       if (rc) {
-               dev_err(&pdev->dev, "mic_setup_interrupts failed %d\n", rc);
-               goto unmap_aper;
-       }
-       rc = mic_smpt_init(mdev);
-       if (rc) {
-               dev_err(&pdev->dev, "smpt_init failed %d\n", rc);
-               goto free_interrupts;
-       }
-
-       pci_set_drvdata(pdev, mdev);
-
-       rc = mic_dp_init(mdev);
-       if (rc) {
-               dev_err(&pdev->dev, "mic_dp_init failed rc %d\n", rc);
-               goto smpt_uninit;
-       }
-       mic_bootparam_init(mdev);
-       mic_create_debug_dir(mdev);
-
-       mdev->cosm_dev = cosm_register_device(&mdev->pdev->dev, &cosm_hw_ops);
-       if (IS_ERR(mdev->cosm_dev)) {
-               rc = PTR_ERR(mdev->cosm_dev);
-               dev_err(&pdev->dev, "cosm_add_device failed rc %d\n", rc);
-               goto cleanup_debug_dir;
-       }
-       return 0;
-cleanup_debug_dir:
-       mic_delete_debug_dir(mdev);
-       mic_dp_uninit(mdev);
-smpt_uninit:
-       mic_smpt_uninit(mdev);
-free_interrupts:
-       mic_free_interrupts(mdev, pdev);
-unmap_aper:
-       iounmap(mdev->aper.va);
-unmap_mmio:
-       iounmap(mdev->mmio.va);
-release_regions:
-       pci_release_regions(pdev);
-disable_device:
-       pci_disable_device(pdev);
-ida_remove:
-       ida_simple_remove(&g_mic_ida, mdev->id);
-ida_fail:
-       kfree(mdev);
-mdev_alloc_fail:
-       dev_err(&pdev->dev, "Probe failed rc %d\n", rc);
-       return rc;
-}
-
-/**
- * mic_remove - Device Removal Routine
- * mic_remove is called by the PCI subsystem to alert the driver
- * that it should release a PCI device.
- *
- * @pdev: PCI device structure
- */
-static void mic_remove(struct pci_dev *pdev)
-{
-       struct mic_device *mdev;
-
-       mdev = pci_get_drvdata(pdev);
-       if (!mdev)
-               return;
-
-       cosm_unregister_device(mdev->cosm_dev);
-       mic_delete_debug_dir(mdev);
-       mic_dp_uninit(mdev);
-       mic_smpt_uninit(mdev);
-       mic_free_interrupts(mdev, pdev);
-       iounmap(mdev->aper.va);
-       iounmap(mdev->mmio.va);
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-       ida_simple_remove(&g_mic_ida, mdev->id);
-       kfree(mdev);
-}
-
-static struct pci_driver mic_driver = {
-       .name = mic_driver_name,
-       .id_table = mic_pci_tbl,
-       .probe = mic_probe,
-       .remove = mic_remove
-};
-
-static int __init mic_init(void)
-{
-       int ret;
-
-       request_module("mic_x100_dma");
-       mic_init_debugfs();
-       ida_init(&g_mic_ida);
-       ret = pci_register_driver(&mic_driver);
-       if (ret) {
-               pr_err("pci_register_driver failed ret %d\n", ret);
-               goto cleanup_debugfs;
-       }
-       return 0;
-cleanup_debugfs:
-       ida_destroy(&g_mic_ida);
-       mic_exit_debugfs();
-       return ret;
-}
-
-static void __exit mic_exit(void)
-{
-       pci_unregister_driver(&mic_driver);
-       ida_destroy(&g_mic_ida);
-       mic_exit_debugfs();
-}
-
-module_init(mic_init);
-module_exit(mic_exit);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Intel(R) MIC X100 Host driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/host/mic_smpt.c b/drivers/misc/mic/host/mic_smpt.c
deleted file mode 100644 (file)
index 50d1beb..0000000
+++ /dev/null
@@ -1,427 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Intel MIC Host driver.
- */
-#include <linux/pci.h>
-
-#include "../common/mic_dev.h"
-#include "mic_device.h"
-#include "mic_smpt.h"
-
-static inline u64 mic_system_page_mask(struct mic_device *mdev)
-{
-       return (1ULL << mdev->smpt->info.page_shift) - 1ULL;
-}
-
-static inline u8 mic_sys_addr_to_smpt(struct mic_device *mdev, dma_addr_t pa)
-{
-       return (pa - mdev->smpt->info.base) >> mdev->smpt->info.page_shift;
-}
-
-static inline u64 mic_smpt_to_pa(struct mic_device *mdev, u8 index)
-{
-       return mdev->smpt->info.base + (index * mdev->smpt->info.page_size);
-}
-
-static inline u64 mic_smpt_offset(struct mic_device *mdev, dma_addr_t pa)
-{
-       return pa & mic_system_page_mask(mdev);
-}
-
-static inline u64 mic_smpt_align_low(struct mic_device *mdev, dma_addr_t pa)
-{
-       return ALIGN(pa - mic_system_page_mask(mdev),
-               mdev->smpt->info.page_size);
-}
-
-static inline u64 mic_smpt_align_high(struct mic_device *mdev, dma_addr_t pa)
-{
-       return ALIGN(pa, mdev->smpt->info.page_size);
-}
-
-/* Total Cumulative system memory accessible by MIC across all SMPT entries */
-static inline u64 mic_max_system_memory(struct mic_device *mdev)
-{
-       return mdev->smpt->info.num_reg * mdev->smpt->info.page_size;
-}
-
-/* Maximum system memory address accessible by MIC */
-static inline u64 mic_max_system_addr(struct mic_device *mdev)
-{
-       return mdev->smpt->info.base + mic_max_system_memory(mdev) - 1ULL;
-}
-
-/* Check if the DMA address is a MIC system memory address */
-static inline bool
-mic_is_system_addr(struct mic_device *mdev, dma_addr_t pa)
-{
-       return pa >= mdev->smpt->info.base && pa <= mic_max_system_addr(mdev);
-}
-
-/* Populate an SMPT entry and update the reference counts. */
-static void mic_add_smpt_entry(int spt, s64 *ref, u64 addr,
-                              int entries, struct mic_device *mdev)
-{
-       struct mic_smpt_info *smpt_info = mdev->smpt;
-       int i;
-
-       for (i = spt; i < spt + entries; i++,
-               addr += smpt_info->info.page_size) {
-               if (!smpt_info->entry[i].ref_count &&
-                   (smpt_info->entry[i].dma_addr != addr)) {
-                       mdev->smpt_ops->set(mdev, addr, i);
-                       smpt_info->entry[i].dma_addr = addr;
-               }
-               smpt_info->entry[i].ref_count += ref[i - spt];
-       }
-}
-
-/*
- * Find an available MIC address in MIC SMPT address space
- * for a given DMA address and size.
- */
-static dma_addr_t mic_smpt_op(struct mic_device *mdev, u64 dma_addr,
-                             int entries, s64 *ref, size_t size)
-{
-       int spt;
-       int ae = 0;
-       int i;
-       unsigned long flags;
-       dma_addr_t mic_addr = 0;
-       dma_addr_t addr = dma_addr;
-       struct mic_smpt_info *smpt_info = mdev->smpt;
-
-       spin_lock_irqsave(&smpt_info->smpt_lock, flags);
-
-       /* find existing entries */
-       for (i = 0; i < smpt_info->info.num_reg; i++) {
-               if (smpt_info->entry[i].dma_addr == addr) {
-                       ae++;
-                       addr += smpt_info->info.page_size;
-               } else if (ae) /* cannot find contiguous entries */
-                       goto not_found;
-
-               if (ae == entries)
-                       goto found;
-       }
-
-       /* find free entry */
-       for (ae = 0, i = 0; i < smpt_info->info.num_reg; i++) {
-               ae = (smpt_info->entry[i].ref_count == 0) ? ae + 1 : 0;
-               if (ae == entries)
-                       goto found;
-       }
-
-not_found:
-       spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
-       return mic_addr;
-
-found:
-       spt = i - entries + 1;
-       mic_addr = mic_smpt_to_pa(mdev, spt);
-       mic_add_smpt_entry(spt, ref, dma_addr, entries, mdev);
-       smpt_info->map_count++;
-       smpt_info->ref_count += (s64)size;
-       spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
-       return mic_addr;
-}
-
-/*
- * Returns number of smpt entries needed for dma_addr to dma_addr + size
- * also returns the reference count array for each of those entries
- * and the starting smpt address
- */
-static int mic_get_smpt_ref_count(struct mic_device *mdev, dma_addr_t dma_addr,
-                                 size_t size, s64 *ref,  u64 *smpt_start)
-{
-       u64 start =  dma_addr;
-       u64 end = dma_addr + size;
-       int i = 0;
-
-       while (start < end) {
-               ref[i++] = min(mic_smpt_align_high(mdev, start + 1),
-                       end) - start;
-               start = mic_smpt_align_high(mdev, start + 1);
-       }
-
-       if (smpt_start)
-               *smpt_start = mic_smpt_align_low(mdev, dma_addr);
-
-       return i;
-}
-
-/*
- * mic_to_dma_addr - Converts a MIC address to a DMA address.
- *
- * @mdev: pointer to mic_device instance.
- * @mic_addr: MIC address.
- *
- * returns a DMA address.
- */
-dma_addr_t mic_to_dma_addr(struct mic_device *mdev, dma_addr_t mic_addr)
-{
-       struct mic_smpt_info *smpt_info = mdev->smpt;
-       int spt;
-       dma_addr_t dma_addr;
-
-       if (!mic_is_system_addr(mdev, mic_addr)) {
-               dev_err(&mdev->pdev->dev,
-                       "mic_addr is invalid. mic_addr = 0x%llx\n", mic_addr);
-               return -EINVAL;
-       }
-       spt = mic_sys_addr_to_smpt(mdev, mic_addr);
-       dma_addr = smpt_info->entry[spt].dma_addr +
-               mic_smpt_offset(mdev, mic_addr);
-       return dma_addr;
-}
-
-/**
- * mic_map - Maps a DMA address to a MIC physical address.
- *
- * @mdev: pointer to mic_device instance.
- * @dma_addr: DMA address.
- * @size: Size of the region to be mapped.
- *
- * This API converts the DMA address provided to a DMA address understood
- * by MIC. Caller should check for errors by calling mic_map_error(..).
- *
- * returns DMA address as required by MIC.
- */
-dma_addr_t mic_map(struct mic_device *mdev, dma_addr_t dma_addr, size_t size)
-{
-       dma_addr_t mic_addr = 0;
-       int num_entries;
-       s64 *ref;
-       u64 smpt_start;
-
-       if (!size || size > mic_max_system_memory(mdev))
-               return mic_addr;
-
-       ref = kmalloc_array(mdev->smpt->info.num_reg, sizeof(s64), GFP_ATOMIC);
-       if (!ref)
-               return mic_addr;
-
-       num_entries = mic_get_smpt_ref_count(mdev, dma_addr, size,
-                                            ref, &smpt_start);
-
-       /* Set the smpt table appropriately and get 16G aligned mic address */
-       mic_addr = mic_smpt_op(mdev, smpt_start, num_entries, ref, size);
-
-       kfree(ref);
-
-       /*
-        * If mic_addr is zero then its an error case
-        * since mic_addr can never be zero.
-        * else generate mic_addr by adding the 16G offset in dma_addr
-        */
-       if (!mic_addr && MIC_FAMILY_X100 == mdev->family) {
-               dev_err(&mdev->pdev->dev,
-                       "mic_map failed dma_addr 0x%llx size 0x%lx\n",
-                       dma_addr, size);
-               return mic_addr;
-       } else {
-               return mic_addr + mic_smpt_offset(mdev, dma_addr);
-       }
-}
-
-/**
- * mic_unmap - Unmaps a MIC physical address.
- *
- * @mdev: pointer to mic_device instance.
- * @mic_addr: MIC physical address.
- * @size: Size of the region to be unmapped.
- *
- * This API unmaps the mappings created by mic_map(..).
- *
- * returns None.
- */
-void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
-{
-       struct mic_smpt_info *smpt_info = mdev->smpt;
-       s64 *ref;
-       int num_smpt;
-       int spt;
-       int i;
-       unsigned long flags;
-
-       if (!size)
-               return;
-
-       if (!mic_is_system_addr(mdev, mic_addr)) {
-               dev_err(&mdev->pdev->dev,
-                       "invalid address: 0x%llx\n", mic_addr);
-               return;
-       }
-
-       spt = mic_sys_addr_to_smpt(mdev, mic_addr);
-       ref = kmalloc_array(mdev->smpt->info.num_reg, sizeof(s64), GFP_ATOMIC);
-       if (!ref)
-               return;
-
-       /* Get number of smpt entries to be mapped, ref count array */
-       num_smpt = mic_get_smpt_ref_count(mdev, mic_addr, size, ref, NULL);
-
-       spin_lock_irqsave(&smpt_info->smpt_lock, flags);
-       smpt_info->unmap_count++;
-       smpt_info->ref_count -= (s64)size;
-
-       for (i = spt; i < spt + num_smpt; i++) {
-               smpt_info->entry[i].ref_count -= ref[i - spt];
-               if (smpt_info->entry[i].ref_count < 0)
-                       dev_warn(&mdev->pdev->dev,
-                                "ref count for entry %d is negative\n", i);
-       }
-       spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
-       kfree(ref);
-}
-
-/**
- * mic_map_single - Maps a virtual address to a MIC physical address.
- *
- * @mdev: pointer to mic_device instance.
- * @va: Kernel direct mapped virtual address.
- * @size: Size of the region to be mapped.
- *
- * This API calls pci_map_single(..) for the direct mapped virtual address
- * and then converts the DMA address provided to a DMA address understood
- * by MIC. Caller should check for errors by calling mic_map_error(..).
- *
- * returns DMA address as required by MIC.
- */
-dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size)
-{
-       dma_addr_t mic_addr = 0;
-       struct pci_dev *pdev = mdev->pdev;
-       dma_addr_t dma_addr =
-               pci_map_single(pdev, va, size, PCI_DMA_BIDIRECTIONAL);
-
-       if (!pci_dma_mapping_error(pdev, dma_addr)) {
-               mic_addr = mic_map(mdev, dma_addr, size);
-               if (!mic_addr) {
-                       dev_err(&mdev->pdev->dev,
-                               "mic_map failed dma_addr 0x%llx size 0x%lx\n",
-                               dma_addr, size);
-                       pci_unmap_single(pdev, dma_addr,
-                                        size, PCI_DMA_BIDIRECTIONAL);
-               }
-       }
-       return mic_addr;
-}
-
-/**
- * mic_unmap_single - Unmaps a MIC physical address.
- *
- * @mdev: pointer to mic_device instance.
- * @mic_addr: MIC physical address.
- * @size: Size of the region to be unmapped.
- *
- * This API unmaps the mappings created by mic_map_single(..).
- *
- * returns None.
- */
-void
-mic_unmap_single(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
-{
-       struct pci_dev *pdev = mdev->pdev;
-       dma_addr_t dma_addr = mic_to_dma_addr(mdev, mic_addr);
-       mic_unmap(mdev, mic_addr, size);
-       pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
-}
-
-/**
- * mic_smpt_init - Initialize MIC System Memory Page Tables.
- *
- * @mdev: pointer to mic_device instance.
- *
- * returns 0 for success and -errno for error.
- */
-int mic_smpt_init(struct mic_device *mdev)
-{
-       int i, err = 0;
-       dma_addr_t dma_addr;
-       struct mic_smpt_info *smpt_info;
-
-       mdev->smpt = kmalloc(sizeof(*mdev->smpt), GFP_KERNEL);
-       if (!mdev->smpt)
-               return -ENOMEM;
-
-       smpt_info = mdev->smpt;
-       mdev->smpt_ops->init(mdev);
-       smpt_info->entry = kmalloc_array(smpt_info->info.num_reg,
-                                        sizeof(*smpt_info->entry), GFP_KERNEL);
-       if (!smpt_info->entry) {
-               err = -ENOMEM;
-               goto free_smpt;
-       }
-       spin_lock_init(&smpt_info->smpt_lock);
-       for (i = 0; i < smpt_info->info.num_reg; i++) {
-               dma_addr = i * smpt_info->info.page_size;
-               smpt_info->entry[i].dma_addr = dma_addr;
-               smpt_info->entry[i].ref_count = 0;
-               mdev->smpt_ops->set(mdev, dma_addr, i);
-       }
-       smpt_info->ref_count = 0;
-       smpt_info->map_count = 0;
-       smpt_info->unmap_count = 0;
-       return 0;
-free_smpt:
-       kfree(smpt_info);
-       return err;
-}
-
-/**
- * mic_smpt_uninit - UnInitialize MIC System Memory Page Tables.
- *
- * @mdev: pointer to mic_device instance.
- *
- * returns None.
- */
-void mic_smpt_uninit(struct mic_device *mdev)
-{
-       struct mic_smpt_info *smpt_info = mdev->smpt;
-       int i;
-
-       dev_dbg(&mdev->pdev->dev,
-               "nodeid %d SMPT ref count %lld map %lld unmap %lld\n",
-               mdev->id, smpt_info->ref_count,
-               smpt_info->map_count, smpt_info->unmap_count);
-
-       for (i = 0; i < smpt_info->info.num_reg; i++) {
-               dev_dbg(&mdev->pdev->dev,
-                       "SMPT entry[%d] dma_addr = 0x%llx ref_count = %lld\n",
-                       i, smpt_info->entry[i].dma_addr,
-                       smpt_info->entry[i].ref_count);
-               if (smpt_info->entry[i].ref_count)
-                       dev_warn(&mdev->pdev->dev,
-                                "ref count for entry %d is not zero\n", i);
-       }
-       kfree(smpt_info->entry);
-       kfree(smpt_info);
-}
-
-/**
- * mic_smpt_restore - Restore MIC System Memory Page Tables.
- *
- * @mdev: pointer to mic_device instance.
- *
- * Restore the SMPT registers to values previously stored in the
- * SW data structures. Some MIC steppings lose register state
- * across resets and this API should be called for performing
- * a restore operation if required.
- *
- * returns None.
- */
-void mic_smpt_restore(struct mic_device *mdev)
-{
-       int i;
-       dma_addr_t dma_addr;
-
-       for (i = 0; i < mdev->smpt->info.num_reg; i++) {
-               dma_addr = mdev->smpt->entry[i].dma_addr;
-               mdev->smpt_ops->set(mdev, dma_addr, i);
-       }
-}
diff --git a/drivers/misc/mic/host/mic_smpt.h b/drivers/misc/mic/host/mic_smpt.h
deleted file mode 100644 (file)
index 3b1ec14..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Intel MIC Host driver.
- */
-#ifndef MIC_SMPT_H
-#define MIC_SMPT_H
-/**
- * struct mic_smpt_ops - MIC HW specific SMPT operations.
- * @init: Initialize hardware specific SMPT information in mic_smpt_hw_info.
- * @set: Set the value for a particular SMPT entry.
- */
-struct mic_smpt_ops {
-       void (*init)(struct mic_device *mdev);
-       void (*set)(struct mic_device *mdev, dma_addr_t dma_addr, u8 index);
-};
-
-/**
- * struct mic_smpt - MIC SMPT entry information.
- * @dma_addr: Base DMA address for this SMPT entry.
- * @ref_count: Number of active mappings for this SMPT entry in bytes.
- */
-struct mic_smpt {
-       dma_addr_t dma_addr;
-       s64 ref_count;
-};
-
-/**
- * struct mic_smpt_hw_info - MIC SMPT hardware specific information.
- * @num_reg: Number of SMPT registers.
- * @page_shift: System memory page shift.
- * @page_size: System memory page size.
- * @base: System address base.
- */
-struct mic_smpt_hw_info {
-       u8 num_reg;
-       u8 page_shift;
-       u64 page_size;
-       u64 base;
-};
-
-/**
- * struct mic_smpt_info - MIC SMPT information.
- * @entry: Array of SMPT entries.
- * @smpt_lock: Spin lock protecting access to SMPT data structures.
- * @info: Hardware specific SMPT information.
- * @ref_count: Number of active SMPT mappings (for debug).
- * @map_count: Number of SMPT mappings created (for debug).
- * @unmap_count: Number of SMPT mappings destroyed (for debug).
- */
-struct mic_smpt_info {
-       struct mic_smpt *entry;
-       spinlock_t smpt_lock;
-       struct mic_smpt_hw_info info;
-       s64 ref_count;
-       s64 map_count;
-       s64 unmap_count;
-};
-
-dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size);
-void mic_unmap_single(struct mic_device *mdev,
-       dma_addr_t mic_addr, size_t size);
-dma_addr_t mic_map(struct mic_device *mdev,
-       dma_addr_t dma_addr, size_t size);
-void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size);
-dma_addr_t mic_to_dma_addr(struct mic_device *mdev, dma_addr_t mic_addr);
-
-/**
- * mic_map_error - Check a MIC address for errors.
- *
- * @mdev: pointer to mic_device instance.
- *
- * returns Whether there was an error during mic_map..(..) APIs.
- */
-static inline bool mic_map_error(dma_addr_t mic_addr)
-{
-       return !mic_addr;
-}
-
-int mic_smpt_init(struct mic_device *mdev);
-void mic_smpt_uninit(struct mic_device *mdev);
-void mic_smpt_restore(struct mic_device *mdev);
-
-#endif
diff --git a/drivers/misc/mic/host/mic_x100.c b/drivers/misc/mic/host/mic_x100.c
deleted file mode 100644 (file)
index f5536c1..0000000
+++ /dev/null
@@ -1,585 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Intel MIC Host driver.
- */
-#include <linux/fs.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/firmware.h>
-#include <linux/delay.h>
-
-#include "../common/mic_dev.h"
-#include "mic_device.h"
-#include "mic_x100.h"
-#include "mic_smpt.h"
-
-static const u16 mic_x100_intr_init[] = {
-               MIC_X100_DOORBELL_IDX_START,
-               MIC_X100_DMA_IDX_START,
-               MIC_X100_ERR_IDX_START,
-               MIC_X100_NUM_DOORBELL,
-               MIC_X100_NUM_DMA,
-               MIC_X100_NUM_ERR,
-};
-
-/**
- * mic_x100_write_spad - write to the scratchpad register
- * @mdev: pointer to mic_device instance
- * @idx: index to the scratchpad register, 0 based
- * @val: the data value to put into the register
- *
- * This function allows writing of a 32bit value to the indexed scratchpad
- * register.
- *
- * RETURNS: none.
- */
-static void
-mic_x100_write_spad(struct mic_device *mdev, unsigned int idx, u32 val)
-{
-       dev_dbg(&mdev->pdev->dev, "Writing 0x%x to scratch pad index %d\n",
-               val, idx);
-       mic_mmio_write(&mdev->mmio, val,
-                      MIC_X100_SBOX_BASE_ADDRESS +
-                      MIC_X100_SBOX_SPAD0 + idx * 4);
-}
-
-/**
- * mic_x100_read_spad - read from the scratchpad register
- * @mdev: pointer to mic_device instance
- * @idx: index to scratchpad register, 0 based
- *
- * This function allows reading of the 32bit scratchpad register.
- *
- * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
- */
-static u32
-mic_x100_read_spad(struct mic_device *mdev, unsigned int idx)
-{
-       u32 val = mic_mmio_read(&mdev->mmio,
-               MIC_X100_SBOX_BASE_ADDRESS +
-               MIC_X100_SBOX_SPAD0 + idx * 4);
-
-       dev_dbg(&mdev->pdev->dev,
-               "Reading 0x%x from scratch pad index %d\n", val, idx);
-       return val;
-}
-
-/**
- * mic_x100_enable_interrupts - Enable interrupts.
- * @mdev: pointer to mic_device instance
- */
-static void mic_x100_enable_interrupts(struct mic_device *mdev)
-{
-       u32 reg;
-       struct mic_mw *mw = &mdev->mmio;
-       u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICE0;
-       u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SIAC0;
-
-       reg = mic_mmio_read(mw, sice0);
-       reg |= MIC_X100_SBOX_DBR_BITS(0xf) | MIC_X100_SBOX_DMA_BITS(0xff);
-       mic_mmio_write(mw, reg, sice0);
-
-       /*
-        * Enable auto-clear when enabling interrupts. Applicable only for
-        * MSI-x. Legacy and MSI mode cannot have auto-clear enabled.
-        */
-       if (mdev->irq_info.num_vectors > 1) {
-               reg = mic_mmio_read(mw, siac0);
-               reg |= MIC_X100_SBOX_DBR_BITS(0xf) |
-                       MIC_X100_SBOX_DMA_BITS(0xff);
-               mic_mmio_write(mw, reg, siac0);
-       }
-}
-
-/**
- * mic_x100_disable_interrupts - Disable interrupts.
- * @mdev: pointer to mic_device instance
- */
-static void mic_x100_disable_interrupts(struct mic_device *mdev)
-{
-       u32 reg;
-       struct mic_mw *mw = &mdev->mmio;
-       u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICE0;
-       u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SIAC0;
-       u32 sicc0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICC0;
-
-       reg = mic_mmio_read(mw, sice0);
-       mic_mmio_write(mw, reg, sicc0);
-
-       if (mdev->irq_info.num_vectors > 1) {
-               reg = mic_mmio_read(mw, siac0);
-               reg &= ~(MIC_X100_SBOX_DBR_BITS(0xf) |
-                       MIC_X100_SBOX_DMA_BITS(0xff));
-               mic_mmio_write(mw, reg, siac0);
-       }
-}
-
-/**
- * mic_x100_send_sbox_intr - Send an MIC_X100_SBOX interrupt to MIC.
- * @mdev: pointer to mic_device instance
- * @doorbell: doorbell number
- */
-static void mic_x100_send_sbox_intr(struct mic_device *mdev,
-                                   int doorbell)
-{
-       struct mic_mw *mw = &mdev->mmio;
-       u64 apic_icr_offset = MIC_X100_SBOX_APICICR0 + doorbell * 8;
-       u32 apicicr_low = mic_mmio_read(mw, MIC_X100_SBOX_BASE_ADDRESS +
-                                       apic_icr_offset);
-
-       /* for MIC we need to make sure we "hit" the send_icr bit (13) */
-       apicicr_low = (apicicr_low | (1 << 13));
-
-       /* Ensure that the interrupt is ordered w.r.t. previous stores. */
-       wmb();
-       mic_mmio_write(mw, apicicr_low,
-                      MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
-}
-
-/**
- * mic_x100_send_rdmasr_intr - Send an RDMASR interrupt to MIC.
- * @mdev: pointer to mic_device instance
- * @doorbell: doorbell number
- */
-static void mic_x100_send_rdmasr_intr(struct mic_device *mdev,
-                                     int doorbell)
-{
-       int rdmasr_offset = MIC_X100_SBOX_RDMASR0 + (doorbell << 2);
-       /* Ensure that the interrupt is ordered w.r.t. previous stores. */
-       wmb();
-       mic_mmio_write(&mdev->mmio, 0,
-                      MIC_X100_SBOX_BASE_ADDRESS + rdmasr_offset);
-}
-
-/**
- * __mic_x100_send_intr - Send interrupt to MIC.
- * @mdev: pointer to mic_device instance
- * @doorbell: doorbell number.
- */
-static void mic_x100_send_intr(struct mic_device *mdev, int doorbell)
-{
-       int rdmasr_db;
-       if (doorbell < MIC_X100_NUM_SBOX_IRQ) {
-               mic_x100_send_sbox_intr(mdev, doorbell);
-       } else {
-               rdmasr_db = doorbell - MIC_X100_NUM_SBOX_IRQ;
-               mic_x100_send_rdmasr_intr(mdev, rdmasr_db);
-       }
-}
-
-/**
- * mic_x100_ack_interrupt - Read the interrupt sources register and
- * clear it. This function will be called in the MSI/INTx case.
- * @mdev: Pointer to mic_device instance.
- *
- * Returns: bitmask of interrupt sources triggered.
- */
-static u32 mic_x100_ack_interrupt(struct mic_device *mdev)
-{
-       u32 sicr0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICR0;
-       u32 reg = mic_mmio_read(&mdev->mmio, sicr0);
-       mic_mmio_write(&mdev->mmio, reg, sicr0);
-       return reg;
-}
-
-/**
- * mic_x100_intr_workarounds - These hardware specific workarounds are
- * to be invoked everytime an interrupt is handled.
- * @mdev: Pointer to mic_device instance.
- *
- * Returns: none
- */
-static void mic_x100_intr_workarounds(struct mic_device *mdev)
-{
-       struct mic_mw *mw = &mdev->mmio;
-
-       /* Clear pending bit array. */
-       if (MIC_A0_STEP == mdev->stepping)
-               mic_mmio_write(mw, 1, MIC_X100_SBOX_BASE_ADDRESS +
-                       MIC_X100_SBOX_MSIXPBACR);
-
-       if (mdev->stepping >= MIC_B0_STEP)
-               mdev->intr_ops->enable_interrupts(mdev);
-}
-
-/**
- * mic_x100_hw_intr_init - Initialize h/w specific interrupt
- * information.
- * @mdev: pointer to mic_device instance
- */
-static void mic_x100_hw_intr_init(struct mic_device *mdev)
-{
-       mdev->intr_info = (struct mic_intr_info *)mic_x100_intr_init;
-}
-
-/**
- * mic_x100_read_msi_to_src_map - read from the MSI mapping registers
- * @mdev: pointer to mic_device instance
- * @idx: index to the mapping register, 0 based
- *
- * This function allows reading of the 32bit MSI mapping register.
- *
- * RETURNS: The value in the register.
- */
-static u32
-mic_x100_read_msi_to_src_map(struct mic_device *mdev, int idx)
-{
-       return mic_mmio_read(&mdev->mmio,
-               MIC_X100_SBOX_BASE_ADDRESS +
-               MIC_X100_SBOX_MXAR0 + idx * 4);
-}
-
-/**
- * mic_x100_program_msi_to_src_map - program the MSI mapping registers
- * @mdev: pointer to mic_device instance
- * @idx: index to the mapping register, 0 based
- * @offset: The bit offset in the register that needs to be updated.
- * @set: boolean specifying if the bit in the specified offset needs
- * to be set or cleared.
- *
- * RETURNS: None.
- */
-static void
-mic_x100_program_msi_to_src_map(struct mic_device *mdev,
-                               int idx, int offset, bool set)
-{
-       unsigned long reg;
-       struct mic_mw *mw = &mdev->mmio;
-       u32 mxar = MIC_X100_SBOX_BASE_ADDRESS +
-               MIC_X100_SBOX_MXAR0 + idx * 4;
-
-       reg = mic_mmio_read(mw, mxar);
-       if (set)
-               __set_bit(offset, &reg);
-       else
-               __clear_bit(offset, &reg);
-       mic_mmio_write(mw, reg, mxar);
-}
-
-/*
- * mic_x100_reset_fw_ready - Reset Firmware ready status field.
- * @mdev: pointer to mic_device instance
- */
-static void mic_x100_reset_fw_ready(struct mic_device *mdev)
-{
-       mdev->ops->write_spad(mdev, MIC_X100_DOWNLOAD_INFO, 0);
-}
-
-/*
- * mic_x100_is_fw_ready - Check if firmware is ready.
- * @mdev: pointer to mic_device instance
- */
-static bool mic_x100_is_fw_ready(struct mic_device *mdev)
-{
-       u32 scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO);
-       return MIC_X100_SPAD2_DOWNLOAD_STATUS(scratch2) ? true : false;
-}
-
-/**
- * mic_x100_get_apic_id - Get bootstrap APIC ID.
- * @mdev: pointer to mic_device instance
- */
-static u32 mic_x100_get_apic_id(struct mic_device *mdev)
-{
-       u32 scratch2 = 0;
-
-       scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO);
-       return MIC_X100_SPAD2_APIC_ID(scratch2);
-}
-
-/**
- * mic_x100_send_firmware_intr - Send an interrupt to the firmware on MIC.
- * @mdev: pointer to mic_device instance
- */
-static void mic_x100_send_firmware_intr(struct mic_device *mdev)
-{
-       u32 apicicr_low;
-       u64 apic_icr_offset = MIC_X100_SBOX_APICICR7;
-       int vector = MIC_X100_BSP_INTERRUPT_VECTOR;
-       struct mic_mw *mw = &mdev->mmio;
-
-       /*
-        * For MIC we need to make sure we "hit"
-        * the send_icr bit (13).
-        */
-       apicicr_low = (vector | (1 << 13));
-
-       mic_mmio_write(mw, mic_x100_get_apic_id(mdev),
-                      MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset + 4);
-
-       /* Ensure that the interrupt is ordered w.r.t. previous stores. */
-       wmb();
-       mic_mmio_write(mw, apicicr_low,
-                      MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
-}
-
-/**
- * mic_x100_hw_reset - Reset the MIC device.
- * @mdev: pointer to mic_device instance
- */
-static void mic_x100_hw_reset(struct mic_device *mdev)
-{
-       u32 reset_reg;
-       u32 rgcr = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_RGCR;
-       struct mic_mw *mw = &mdev->mmio;
-
-       /* Ensure that the reset is ordered w.r.t. previous loads and stores */
-       mb();
-       /* Trigger reset */
-       reset_reg = mic_mmio_read(mw, rgcr);
-       reset_reg |= 0x1;
-       mic_mmio_write(mw, reset_reg, rgcr);
-       /*
-        * It seems we really want to delay at least 1 second
-        * after touching reset to prevent a lot of problems.
-        */
-       msleep(1000);
-}
-
-/**
- * mic_x100_load_command_line - Load command line to MIC.
- * @mdev: pointer to mic_device instance
- * @fw: the firmware image
- *
- * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
- */
-static int
-mic_x100_load_command_line(struct mic_device *mdev, const struct firmware *fw)
-{
-       u32 len = 0;
-       u32 boot_mem;
-       char *buf;
-       void __iomem *cmd_line_va = mdev->aper.va + mdev->bootaddr + fw->size;
-#define CMDLINE_SIZE 2048
-
-       boot_mem = mdev->aper.len >> 20;
-       buf = kzalloc(CMDLINE_SIZE, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       len += scnprintf(buf, CMDLINE_SIZE - len,
-               " mem=%dM", boot_mem);
-       if (mdev->cosm_dev->cmdline)
-               scnprintf(buf + len, CMDLINE_SIZE - len, " %s",
-                        mdev->cosm_dev->cmdline);
-       memcpy_toio(cmd_line_va, buf, strlen(buf) + 1);
-       kfree(buf);
-       return 0;
-}
-
-/**
- * mic_x100_load_ramdisk - Load ramdisk to MIC.
- * @mdev: pointer to mic_device instance
- *
- * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
- */
-static int
-mic_x100_load_ramdisk(struct mic_device *mdev)
-{
-       const struct firmware *fw;
-       int rc;
-       struct boot_params __iomem *bp = mdev->aper.va + mdev->bootaddr;
-
-       rc = request_firmware(&fw, mdev->cosm_dev->ramdisk, &mdev->pdev->dev);
-       if (rc < 0) {
-               dev_err(&mdev->pdev->dev,
-                       "ramdisk request_firmware failed: %d %s\n",
-                       rc, mdev->cosm_dev->ramdisk);
-               goto error;
-       }
-       /*
-        * Typically the bootaddr for card OS is 64M
-        * so copy over the ramdisk @ 128M.
-        */
-       memcpy_toio(mdev->aper.va + (mdev->bootaddr << 1), fw->data, fw->size);
-       iowrite32(mdev->bootaddr << 1, &bp->hdr.ramdisk_image);
-       iowrite32(fw->size, &bp->hdr.ramdisk_size);
-       release_firmware(fw);
-error:
-       return rc;
-}
-
-/**
- * mic_x100_get_boot_addr - Get MIC boot address.
- * @mdev: pointer to mic_device instance
- *
- * This function is called during firmware load to determine
- * the address at which the OS should be downloaded in card
- * memory i.e. GDDR.
- * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
- */
-static int
-mic_x100_get_boot_addr(struct mic_device *mdev)
-{
-       u32 scratch2, boot_addr;
-       int rc = 0;
-
-       scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO);
-       boot_addr = MIC_X100_SPAD2_DOWNLOAD_ADDR(scratch2);
-       dev_dbg(&mdev->pdev->dev, "%s %d boot_addr 0x%x\n",
-               __func__, __LINE__, boot_addr);
-       if (boot_addr > (1 << 31)) {
-               dev_err(&mdev->pdev->dev,
-                       "incorrect bootaddr 0x%x\n",
-                       boot_addr);
-               rc = -EINVAL;
-               goto error;
-       }
-       mdev->bootaddr = boot_addr;
-error:
-       return rc;
-}
-
-/**
- * mic_x100_load_firmware - Load firmware to MIC.
- * @mdev: pointer to mic_device instance
- * @buf: buffer containing boot string including firmware/ramdisk path.
- *
- * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
- */
-static int
-mic_x100_load_firmware(struct mic_device *mdev, const char *buf)
-{
-       int rc;
-       const struct firmware *fw;
-
-       rc = mic_x100_get_boot_addr(mdev);
-       if (rc)
-               return rc;
-       /* load OS */
-       rc = request_firmware(&fw, mdev->cosm_dev->firmware, &mdev->pdev->dev);
-       if (rc < 0) {
-               dev_err(&mdev->pdev->dev,
-                       "ramdisk request_firmware failed: %d %s\n",
-                       rc, mdev->cosm_dev->firmware);
-               return rc;
-       }
-       if (mdev->bootaddr > mdev->aper.len - fw->size) {
-               rc = -EINVAL;
-               dev_err(&mdev->pdev->dev, "%s %d rc %d bootaddr 0x%x\n",
-                       __func__, __LINE__, rc, mdev->bootaddr);
-               goto error;
-       }
-       memcpy_toio(mdev->aper.va + mdev->bootaddr, fw->data, fw->size);
-       mdev->ops->write_spad(mdev, MIC_X100_FW_SIZE, fw->size);
-       if (!strcmp(mdev->cosm_dev->bootmode, "flash")) {
-               rc = -EINVAL;
-               dev_err(&mdev->pdev->dev, "%s %d rc %d\n",
-                       __func__, __LINE__, rc);
-               goto error;
-       }
-       /* load command line */
-       rc = mic_x100_load_command_line(mdev, fw);
-       if (rc) {
-               dev_err(&mdev->pdev->dev, "%s %d rc %d\n",
-                       __func__, __LINE__, rc);
-               goto error;
-       }
-       release_firmware(fw);
-       /* load ramdisk */
-       if (mdev->cosm_dev->ramdisk)
-               rc = mic_x100_load_ramdisk(mdev);
-
-       return rc;
-
-error:
-       release_firmware(fw);
-       return rc;
-}
-
-/**
- * mic_x100_get_postcode - Get postcode status from firmware.
- * @mdev: pointer to mic_device instance
- *
- * RETURNS: postcode.
- */
-static u32 mic_x100_get_postcode(struct mic_device *mdev)
-{
-       return mic_mmio_read(&mdev->mmio, MIC_X100_POSTCODE);
-}
-
-/**
- * mic_x100_smpt_set - Update an SMPT entry with a DMA address.
- * @mdev: pointer to mic_device instance
- * @dma_addr: DMA address to use
- * @index: entry to write to
- *
- * RETURNS: none.
- */
-static void
-mic_x100_smpt_set(struct mic_device *mdev, dma_addr_t dma_addr, u8 index)
-{
-#define SNOOP_ON       (0 << 0)
-#define SNOOP_OFF      (1 << 0)
-/*
- * Sbox Smpt Reg Bits:
- * Bits        31:2    Host address
- * Bits        1       RSVD
- * Bits        0       No snoop
- */
-#define BUILD_SMPT(NO_SNOOP, HOST_ADDR)  \
-       (u32)(((HOST_ADDR) << 2) | ((NO_SNOOP) & 0x01))
-
-       uint32_t smpt_reg_val = BUILD_SMPT(SNOOP_ON,
-                       dma_addr >> mdev->smpt->info.page_shift);
-       mic_mmio_write(&mdev->mmio, smpt_reg_val,
-                      MIC_X100_SBOX_BASE_ADDRESS +
-                      MIC_X100_SBOX_SMPT00 + (4 * index));
-}
-
-/**
- * mic_x100_smpt_hw_init - Initialize SMPT X100 specific fields.
- * @mdev: pointer to mic_device instance
- *
- * RETURNS: none.
- */
-static void mic_x100_smpt_hw_init(struct mic_device *mdev)
-{
-       struct mic_smpt_hw_info *info = &mdev->smpt->info;
-
-       info->num_reg = 32;
-       info->page_shift = 34;
-       info->page_size = (1ULL << info->page_shift);
-       info->base = 0x8000000000ULL;
-}
-
-struct mic_smpt_ops mic_x100_smpt_ops = {
-       .init = mic_x100_smpt_hw_init,
-       .set = mic_x100_smpt_set,
-};
-
-static bool mic_x100_dma_filter(struct dma_chan *chan, void *param)
-{
-       if (chan->device->dev->parent == (struct device *)param)
-               return true;
-       return false;
-}
-
-struct mic_hw_ops mic_x100_ops = {
-       .aper_bar = MIC_X100_APER_BAR,
-       .mmio_bar = MIC_X100_MMIO_BAR,
-       .read_spad = mic_x100_read_spad,
-       .write_spad = mic_x100_write_spad,
-       .send_intr = mic_x100_send_intr,
-       .ack_interrupt = mic_x100_ack_interrupt,
-       .intr_workarounds = mic_x100_intr_workarounds,
-       .reset = mic_x100_hw_reset,
-       .reset_fw_ready = mic_x100_reset_fw_ready,
-       .is_fw_ready = mic_x100_is_fw_ready,
-       .send_firmware_intr = mic_x100_send_firmware_intr,
-       .load_mic_fw = mic_x100_load_firmware,
-       .get_postcode = mic_x100_get_postcode,
-       .dma_filter = mic_x100_dma_filter,
-};
-
-struct mic_hw_intr_ops mic_x100_intr_ops = {
-       .intr_init = mic_x100_hw_intr_init,
-       .enable_interrupts = mic_x100_enable_interrupts,
-       .disable_interrupts = mic_x100_disable_interrupts,
-       .program_msi_to_src_map = mic_x100_program_msi_to_src_map,
-       .read_msi_to_src_map = mic_x100_read_msi_to_src_map,
-};
diff --git a/drivers/misc/mic/host/mic_x100.h b/drivers/misc/mic/host/mic_x100.h
deleted file mode 100644 (file)
index aebcaed..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Intel MIC Host driver.
- */
-#ifndef _MIC_X100_HW_H_
-#define _MIC_X100_HW_H_
-
-#define MIC_X100_PCI_DEVICE_2250 0x2250
-#define MIC_X100_PCI_DEVICE_2251 0x2251
-#define MIC_X100_PCI_DEVICE_2252 0x2252
-#define MIC_X100_PCI_DEVICE_2253 0x2253
-#define MIC_X100_PCI_DEVICE_2254 0x2254
-#define MIC_X100_PCI_DEVICE_2255 0x2255
-#define MIC_X100_PCI_DEVICE_2256 0x2256
-#define MIC_X100_PCI_DEVICE_2257 0x2257
-#define MIC_X100_PCI_DEVICE_2258 0x2258
-#define MIC_X100_PCI_DEVICE_2259 0x2259
-#define MIC_X100_PCI_DEVICE_225a 0x225a
-#define MIC_X100_PCI_DEVICE_225b 0x225b
-#define MIC_X100_PCI_DEVICE_225c 0x225c
-#define MIC_X100_PCI_DEVICE_225d 0x225d
-#define MIC_X100_PCI_DEVICE_225e 0x225e
-
-#define MIC_X100_APER_BAR 0
-#define MIC_X100_MMIO_BAR 4
-
-#define MIC_X100_SBOX_BASE_ADDRESS 0x00010000
-#define MIC_X100_SBOX_SPAD0 0x0000AB20
-#define MIC_X100_SBOX_SICR0_DBR(x) ((x) & 0xf)
-#define MIC_X100_SBOX_SICR0_DMA(x) (((x) >> 8) & 0xff)
-#define MIC_X100_SBOX_SICE0_DBR(x) ((x) & 0xf)
-#define MIC_X100_SBOX_DBR_BITS(x) ((x) & 0xf)
-#define MIC_X100_SBOX_SICE0_DMA(x) (((x) >> 8) & 0xff)
-#define MIC_X100_SBOX_DMA_BITS(x) (((x) & 0xff) << 8)
-
-#define MIC_X100_SBOX_APICICR0 0x0000A9D0
-#define MIC_X100_SBOX_SICR0 0x00009004
-#define MIC_X100_SBOX_SICE0 0x0000900C
-#define MIC_X100_SBOX_SICC0 0x00009010
-#define MIC_X100_SBOX_SIAC0 0x00009014
-#define MIC_X100_SBOX_MSIXPBACR 0x00009084
-#define MIC_X100_SBOX_MXAR0 0x00009044
-#define MIC_X100_SBOX_SMPT00 0x00003100
-#define MIC_X100_SBOX_RDMASR0 0x0000B180
-
-#define MIC_X100_DOORBELL_IDX_START 0
-#define MIC_X100_NUM_DOORBELL 4
-#define MIC_X100_DMA_IDX_START 8
-#define MIC_X100_NUM_DMA 8
-#define MIC_X100_ERR_IDX_START 30
-#define MIC_X100_NUM_ERR 1
-
-#define MIC_X100_NUM_SBOX_IRQ 8
-#define MIC_X100_NUM_RDMASR_IRQ 8
-#define MIC_X100_RDMASR_IRQ_BASE 17
-#define MIC_X100_SPAD2_DOWNLOAD_STATUS(x) ((x) & 0x1)
-#define MIC_X100_SPAD2_APIC_ID(x)      (((x) >> 1) & 0x1ff)
-#define MIC_X100_SPAD2_DOWNLOAD_ADDR(x) ((x) & 0xfffff000)
-#define MIC_X100_SBOX_APICICR7 0x0000AA08
-#define MIC_X100_SBOX_RGCR 0x00004010
-#define MIC_X100_SBOX_SDBIC0 0x0000CC90
-#define MIC_X100_DOWNLOAD_INFO 2
-#define MIC_X100_FW_SIZE 5
-#define MIC_X100_POSTCODE 0x242c
-
-/* Host->Card(bootstrap) Interrupt Vector */
-#define MIC_X100_BSP_INTERRUPT_VECTOR 229
-
-extern struct mic_hw_ops mic_x100_ops;
-extern struct mic_smpt_ops mic_x100_smpt_ops;
-extern struct mic_hw_intr_ops mic_x100_intr_ops;
-
-#endif
diff --git a/drivers/misc/mic/scif/Makefile b/drivers/misc/mic/scif/Makefile
deleted file mode 100644 (file)
index ff37255..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile - SCIF driver.
-# Copyright(c) 2014, Intel Corporation.
-#
-obj-$(CONFIG_SCIF) += scif.o
-scif-objs := scif_main.o
-scif-objs += scif_peer_bus.o
-scif-objs += scif_ports.o
-scif-objs += scif_debugfs.o
-scif-objs += scif_fd.o
-scif-objs += scif_api.o
-scif-objs += scif_epd.o
-scif-objs += scif_rb.o
-scif-objs += scif_nodeqp.o
-scif-objs += scif_nm.o
-scif-objs += scif_dma.o
-scif-objs += scif_fence.o
-scif-objs += scif_mmap.o
-scif-objs += scif_rma.o
-scif-objs += scif_rma_list.o
diff --git a/drivers/misc/mic/scif/scif_api.c b/drivers/misc/mic/scif/scif_api.c
deleted file mode 100644 (file)
index 304d6c8..0000000
+++ /dev/null
@@ -1,1485 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#include <linux/scif.h>
-#include "scif_main.h"
-#include "scif_map.h"
-
-static const char * const scif_ep_states[] = {
-       "Unbound",
-       "Bound",
-       "Listening",
-       "Connected",
-       "Connecting",
-       "Mapping",
-       "Closing",
-       "Close Listening",
-       "Disconnected",
-       "Zombie"};
-
-enum conn_async_state {
-       ASYNC_CONN_IDLE = 1,    /* ep setup for async connect */
-       ASYNC_CONN_INPROGRESS,  /* async connect in progress */
-       ASYNC_CONN_FLUSH_WORK   /* async work flush in progress  */
-};
-
-/*
- * File operations for anonymous inode file associated with a SCIF endpoint,
- * used in kernel mode SCIF poll. Kernel mode SCIF poll calls portions of the
- * poll API in the kernel and these take in a struct file *. Since a struct
- * file is not available to kernel mode SCIF, it uses an anonymous file for
- * this purpose.
- */
-const struct file_operations scif_anon_fops = {
-       .owner = THIS_MODULE,
-};
-
-scif_epd_t scif_open(void)
-{
-       struct scif_endpt *ep;
-       int err;
-
-       might_sleep();
-       ep = kzalloc(sizeof(*ep), GFP_KERNEL);
-       if (!ep)
-               goto err_ep_alloc;
-
-       ep->qp_info.qp = kzalloc(sizeof(*ep->qp_info.qp), GFP_KERNEL);
-       if (!ep->qp_info.qp)
-               goto err_qp_alloc;
-
-       err = scif_anon_inode_getfile(ep);
-       if (err)
-               goto err_anon_inode;
-
-       spin_lock_init(&ep->lock);
-       mutex_init(&ep->sendlock);
-       mutex_init(&ep->recvlock);
-
-       scif_rma_ep_init(ep);
-       ep->state = SCIFEP_UNBOUND;
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI open: ep %p success\n", ep);
-       return ep;
-
-err_anon_inode:
-       kfree(ep->qp_info.qp);
-err_qp_alloc:
-       kfree(ep);
-err_ep_alloc:
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(scif_open);
-
-/*
- * scif_disconnect_ep - Disconnects the endpoint if found
- * @epd: The end point returned from scif_open()
- */
-static struct scif_endpt *scif_disconnect_ep(struct scif_endpt *ep)
-{
-       struct scifmsg msg;
-       struct scif_endpt *fep = NULL;
-       struct scif_endpt *tmpep;
-       struct list_head *pos, *tmpq;
-       int err;
-
-       /*
-        * Wake up any threads blocked in send()/recv() before closing
-        * out the connection. Grabbing and releasing the send/recv lock
-        * will ensure that any blocked senders/receivers have exited for
-        * Ring 0 endpoints. It is a Ring 0 bug to call send/recv after
-        * close. Ring 3 endpoints are not affected since close will not
-        * be called while there are IOCTLs executing.
-        */
-       wake_up_interruptible(&ep->sendwq);
-       wake_up_interruptible(&ep->recvwq);
-       mutex_lock(&ep->sendlock);
-       mutex_unlock(&ep->sendlock);
-       mutex_lock(&ep->recvlock);
-       mutex_unlock(&ep->recvlock);
-
-       /* Remove from the connected list */
-       mutex_lock(&scif_info.connlock);
-       list_for_each_safe(pos, tmpq, &scif_info.connected) {
-               tmpep = list_entry(pos, struct scif_endpt, list);
-               if (tmpep == ep) {
-                       list_del(pos);
-                       fep = tmpep;
-                       spin_lock(&ep->lock);
-                       break;
-               }
-       }
-
-       if (!fep) {
-               /*
-                * The other side has completed the disconnect before
-                * the end point can be removed from the list. Therefore
-                * the ep lock is not locked, traverse the disconnected
-                * list to find the endpoint and release the conn lock.
-                */
-               list_for_each_safe(pos, tmpq, &scif_info.disconnected) {
-                       tmpep = list_entry(pos, struct scif_endpt, list);
-                       if (tmpep == ep) {
-                               list_del(pos);
-                               break;
-                       }
-               }
-               mutex_unlock(&scif_info.connlock);
-               return NULL;
-       }
-
-       init_completion(&ep->discon);
-       msg.uop = SCIF_DISCNCT;
-       msg.src = ep->port;
-       msg.dst = ep->peer;
-       msg.payload[0] = (u64)ep;
-       msg.payload[1] = ep->remote_ep;
-
-       err = scif_nodeqp_send(ep->remote_dev, &msg);
-       spin_unlock(&ep->lock);
-       mutex_unlock(&scif_info.connlock);
-
-       if (!err)
-               /* Wait for the remote node to respond with SCIF_DISCNT_ACK */
-               wait_for_completion_timeout(&ep->discon,
-                                           SCIF_NODE_ALIVE_TIMEOUT);
-       return ep;
-}
-
-int scif_close(scif_epd_t epd)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       struct scif_endpt *tmpep;
-       struct list_head *pos, *tmpq;
-       enum scif_epd_state oldstate;
-       bool flush_conn;
-
-       dev_dbg(scif_info.mdev.this_device, "SCIFAPI close: ep %p %s\n",
-               ep, scif_ep_states[ep->state]);
-       might_sleep();
-       spin_lock(&ep->lock);
-       flush_conn = (ep->conn_async_state == ASYNC_CONN_INPROGRESS);
-       spin_unlock(&ep->lock);
-
-       if (flush_conn)
-               flush_work(&scif_info.conn_work);
-
-       spin_lock(&ep->lock);
-       oldstate = ep->state;
-
-       ep->state = SCIFEP_CLOSING;
-
-       switch (oldstate) {
-       case SCIFEP_ZOMBIE:
-               dev_err(scif_info.mdev.this_device,
-                       "SCIFAPI close: zombie state unexpected\n");
-               fallthrough;
-       case SCIFEP_DISCONNECTED:
-               spin_unlock(&ep->lock);
-               scif_unregister_all_windows(epd);
-               /* Remove from the disconnected list */
-               mutex_lock(&scif_info.connlock);
-               list_for_each_safe(pos, tmpq, &scif_info.disconnected) {
-                       tmpep = list_entry(pos, struct scif_endpt, list);
-                       if (tmpep == ep) {
-                               list_del(pos);
-                               break;
-                       }
-               }
-               mutex_unlock(&scif_info.connlock);
-               break;
-       case SCIFEP_UNBOUND:
-       case SCIFEP_BOUND:
-       case SCIFEP_CONNECTING:
-               spin_unlock(&ep->lock);
-               break;
-       case SCIFEP_MAPPING:
-       case SCIFEP_CONNECTED:
-       case SCIFEP_CLOSING:
-       {
-               spin_unlock(&ep->lock);
-               scif_unregister_all_windows(epd);
-               scif_disconnect_ep(ep);
-               break;
-       }
-       case SCIFEP_LISTENING:
-       case SCIFEP_CLLISTEN:
-       {
-               struct scif_conreq *conreq;
-               struct scifmsg msg;
-               struct scif_endpt *aep;
-
-               spin_unlock(&ep->lock);
-               mutex_lock(&scif_info.eplock);
-
-               /* remove from listen list */
-               list_for_each_safe(pos, tmpq, &scif_info.listen) {
-                       tmpep = list_entry(pos, struct scif_endpt, list);
-                       if (tmpep == ep)
-                               list_del(pos);
-               }
-               /* Remove any dangling accepts */
-               while (ep->acceptcnt) {
-                       aep = list_first_entry(&ep->li_accept,
-                                              struct scif_endpt, liacceptlist);
-                       list_del(&aep->liacceptlist);
-                       scif_put_port(aep->port.port);
-                       list_for_each_safe(pos, tmpq, &scif_info.uaccept) {
-                               tmpep = list_entry(pos, struct scif_endpt,
-                                                  miacceptlist);
-                               if (tmpep == aep) {
-                                       list_del(pos);
-                                       break;
-                               }
-                       }
-                       mutex_unlock(&scif_info.eplock);
-                       mutex_lock(&scif_info.connlock);
-                       list_for_each_safe(pos, tmpq, &scif_info.connected) {
-                               tmpep = list_entry(pos,
-                                                  struct scif_endpt, list);
-                               if (tmpep == aep) {
-                                       list_del(pos);
-                                       break;
-                               }
-                       }
-                       list_for_each_safe(pos, tmpq, &scif_info.disconnected) {
-                               tmpep = list_entry(pos,
-                                                  struct scif_endpt, list);
-                               if (tmpep == aep) {
-                                       list_del(pos);
-                                       break;
-                               }
-                       }
-                       mutex_unlock(&scif_info.connlock);
-                       scif_teardown_ep(aep);
-                       mutex_lock(&scif_info.eplock);
-                       scif_add_epd_to_zombie_list(aep, SCIF_EPLOCK_HELD);
-                       ep->acceptcnt--;
-               }
-
-               spin_lock(&ep->lock);
-               mutex_unlock(&scif_info.eplock);
-
-               /* Remove and reject any pending connection requests. */
-               while (ep->conreqcnt) {
-                       conreq = list_first_entry(&ep->conlist,
-                                                 struct scif_conreq, list);
-                       list_del(&conreq->list);
-
-                       msg.uop = SCIF_CNCT_REJ;
-                       msg.dst.node = conreq->msg.src.node;
-                       msg.dst.port = conreq->msg.src.port;
-                       msg.payload[0] = conreq->msg.payload[0];
-                       msg.payload[1] = conreq->msg.payload[1];
-                       /*
-                        * No Error Handling on purpose for scif_nodeqp_send().
-                        * If the remote node is lost we still want free the
-                        * connection requests on the self node.
-                        */
-                       scif_nodeqp_send(&scif_dev[conreq->msg.src.node],
-                                        &msg);
-                       ep->conreqcnt--;
-                       kfree(conreq);
-               }
-
-               spin_unlock(&ep->lock);
-               /* If a kSCIF accept is waiting wake it up */
-               wake_up_interruptible(&ep->conwq);
-               break;
-       }
-       }
-       scif_put_port(ep->port.port);
-       scif_anon_inode_fput(ep);
-       scif_teardown_ep(ep);
-       scif_add_epd_to_zombie_list(ep, !SCIF_EPLOCK_HELD);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(scif_close);
-
-/**
- * scif_flush() - Wakes up any blocking accepts. The endpoint will no longer
- *                     accept new connections.
- * @epd: The end point returned from scif_open()
- */
-int __scif_flush(scif_epd_t epd)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-
-       switch (ep->state) {
-       case SCIFEP_LISTENING:
-       {
-               ep->state = SCIFEP_CLLISTEN;
-
-               /* If an accept is waiting wake it up */
-               wake_up_interruptible(&ep->conwq);
-               break;
-       }
-       default:
-               break;
-       }
-       return 0;
-}
-
-int scif_bind(scif_epd_t epd, u16 pn)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       int ret = 0;
-       int tmp;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI bind: ep %p %s requested port number %d\n",
-               ep, scif_ep_states[ep->state], pn);
-       if (pn) {
-               /*
-                * Similar to IETF RFC 1700, SCIF ports below
-                * SCIF_ADMIN_PORT_END can only be bound by system (or root)
-                * processes or by processes executed by privileged users.
-                */
-               if (pn < SCIF_ADMIN_PORT_END && !capable(CAP_SYS_ADMIN)) {
-                       ret = -EACCES;
-                       goto scif_bind_admin_exit;
-               }
-       }
-
-       spin_lock(&ep->lock);
-       if (ep->state == SCIFEP_BOUND) {
-               ret = -EINVAL;
-               goto scif_bind_exit;
-       } else if (ep->state != SCIFEP_UNBOUND) {
-               ret = -EISCONN;
-               goto scif_bind_exit;
-       }
-
-       if (pn) {
-               tmp = scif_rsrv_port(pn);
-               if (tmp != pn) {
-                       ret = -EINVAL;
-                       goto scif_bind_exit;
-               }
-       } else {
-               ret = scif_get_new_port();
-               if (ret < 0)
-                       goto scif_bind_exit;
-               pn = ret;
-       }
-
-       ep->state = SCIFEP_BOUND;
-       ep->port.node = scif_info.nodeid;
-       ep->port.port = pn;
-       ep->conn_async_state = ASYNC_CONN_IDLE;
-       ret = pn;
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI bind: bound to port number %d\n", pn);
-scif_bind_exit:
-       spin_unlock(&ep->lock);
-scif_bind_admin_exit:
-       return ret;
-}
-EXPORT_SYMBOL_GPL(scif_bind);
-
-int scif_listen(scif_epd_t epd, int backlog)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI listen: ep %p %s\n", ep, scif_ep_states[ep->state]);
-       spin_lock(&ep->lock);
-       switch (ep->state) {
-       case SCIFEP_ZOMBIE:
-       case SCIFEP_CLOSING:
-       case SCIFEP_CLLISTEN:
-       case SCIFEP_UNBOUND:
-       case SCIFEP_DISCONNECTED:
-               spin_unlock(&ep->lock);
-               return -EINVAL;
-       case SCIFEP_LISTENING:
-       case SCIFEP_CONNECTED:
-       case SCIFEP_CONNECTING:
-       case SCIFEP_MAPPING:
-               spin_unlock(&ep->lock);
-               return -EISCONN;
-       case SCIFEP_BOUND:
-               break;
-       }
-
-       ep->state = SCIFEP_LISTENING;
-       ep->backlog = backlog;
-
-       ep->conreqcnt = 0;
-       ep->acceptcnt = 0;
-       INIT_LIST_HEAD(&ep->conlist);
-       init_waitqueue_head(&ep->conwq);
-       INIT_LIST_HEAD(&ep->li_accept);
-       spin_unlock(&ep->lock);
-
-       /*
-        * Listen status is complete so delete the qp information not needed
-        * on a listen before placing on the list of listening ep's
-        */
-       scif_teardown_ep(ep);
-       ep->qp_info.qp = NULL;
-
-       mutex_lock(&scif_info.eplock);
-       list_add_tail(&ep->list, &scif_info.listen);
-       mutex_unlock(&scif_info.eplock);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(scif_listen);
-
-/*
- ************************************************************************
- * SCIF connection flow:
- *
- * 1) A SCIF listening endpoint can call scif_accept(..) to wait for SCIF
- *     connections via a SCIF_CNCT_REQ message
- * 2) A SCIF endpoint can initiate a SCIF connection by calling
- *     scif_connect(..) which calls scif_setup_qp_connect(..) which
- *     allocates the local qp for the endpoint ring buffer and then sends
- *     a SCIF_CNCT_REQ to the remote node and waits for a SCIF_CNCT_GNT or
- *     a SCIF_CNCT_REJ message
- * 3) The peer node handles a SCIF_CNCT_REQ via scif_cnctreq_resp(..) which
- *     wakes up any threads blocked in step 1 or sends a SCIF_CNCT_REJ
- *     message otherwise
- * 4) A thread blocked waiting for incoming connections allocates its local
- *     endpoint QP and ring buffer following which it sends a SCIF_CNCT_GNT
- *     and waits for a SCIF_CNCT_GNT(N)ACK. If the allocation fails then
- *     the node sends a SCIF_CNCT_REJ message
- * 5) Upon receipt of a SCIF_CNCT_GNT or a SCIF_CNCT_REJ message the
- *     connecting endpoint is woken up as part of handling
- *     scif_cnctgnt_resp(..) following which it maps the remote endpoints'
- *     QP, updates its outbound QP and sends a SCIF_CNCT_GNTACK message on
- *     success or a SCIF_CNCT_GNTNACK message on failure and completes
- *     the scif_connect(..) API
- * 6) Upon receipt of a SCIF_CNCT_GNT(N)ACK the accepting endpoint blocked
- *     in step 4 is woken up and completes the scif_accept(..) API
- * 7) The SCIF connection is now established between the two SCIF endpoints.
- */
-static int scif_conn_func(struct scif_endpt *ep)
-{
-       int err = 0;
-       struct scifmsg msg;
-       struct device *spdev;
-
-       err = scif_reserve_dma_chan(ep);
-       if (err) {
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-               ep->state = SCIFEP_BOUND;
-               goto connect_error_simple;
-       }
-       /* Initiate the first part of the endpoint QP setup */
-       err = scif_setup_qp_connect(ep->qp_info.qp, &ep->qp_info.qp_offset,
-                                   SCIF_ENDPT_QP_SIZE, ep->remote_dev);
-       if (err) {
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s err %d qp_offset 0x%llx\n",
-                       __func__, err, ep->qp_info.qp_offset);
-               ep->state = SCIFEP_BOUND;
-               goto connect_error_simple;
-       }
-
-       spdev = scif_get_peer_dev(ep->remote_dev);
-       if (IS_ERR(spdev)) {
-               err = PTR_ERR(spdev);
-               goto cleanup_qp;
-       }
-       /* Format connect message and send it */
-       msg.src = ep->port;
-       msg.dst = ep->conn_port;
-       msg.uop = SCIF_CNCT_REQ;
-       msg.payload[0] = (u64)ep;
-       msg.payload[1] = ep->qp_info.qp_offset;
-       err = _scif_nodeqp_send(ep->remote_dev, &msg);
-       if (err)
-               goto connect_error_dec;
-       scif_put_peer_dev(spdev);
-       /*
-        * Wait for the remote node to respond with SCIF_CNCT_GNT or
-        * SCIF_CNCT_REJ message.
-        */
-       err = wait_event_timeout(ep->conwq, ep->state != SCIFEP_CONNECTING,
-                                SCIF_NODE_ALIVE_TIMEOUT);
-       if (!err) {
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d timeout\n", __func__, __LINE__);
-               ep->state = SCIFEP_BOUND;
-       }
-       spdev = scif_get_peer_dev(ep->remote_dev);
-       if (IS_ERR(spdev)) {
-               err = PTR_ERR(spdev);
-               goto cleanup_qp;
-       }
-       if (ep->state == SCIFEP_MAPPING) {
-               err = scif_setup_qp_connect_response(ep->remote_dev,
-                                                    ep->qp_info.qp,
-                                                    ep->qp_info.gnt_pld);
-               /*
-                * If the resource to map the queue are not available then
-                * we need to tell the other side to terminate the accept
-                */
-               if (err) {
-                       dev_err(&ep->remote_dev->sdev->dev,
-                               "%s %d err %d\n", __func__, __LINE__, err);
-                       msg.uop = SCIF_CNCT_GNTNACK;
-                       msg.payload[0] = ep->remote_ep;
-                       _scif_nodeqp_send(ep->remote_dev, &msg);
-                       ep->state = SCIFEP_BOUND;
-                       goto connect_error_dec;
-               }
-
-               msg.uop = SCIF_CNCT_GNTACK;
-               msg.payload[0] = ep->remote_ep;
-               err = _scif_nodeqp_send(ep->remote_dev, &msg);
-               if (err) {
-                       ep->state = SCIFEP_BOUND;
-                       goto connect_error_dec;
-               }
-               ep->state = SCIFEP_CONNECTED;
-               mutex_lock(&scif_info.connlock);
-               list_add_tail(&ep->list, &scif_info.connected);
-               mutex_unlock(&scif_info.connlock);
-               dev_dbg(&ep->remote_dev->sdev->dev,
-                       "SCIFAPI connect: ep %p connected\n", ep);
-       } else if (ep->state == SCIFEP_BOUND) {
-               dev_dbg(&ep->remote_dev->sdev->dev,
-                       "SCIFAPI connect: ep %p connection refused\n", ep);
-               err = -ECONNREFUSED;
-               goto connect_error_dec;
-       }
-       scif_put_peer_dev(spdev);
-       return err;
-connect_error_dec:
-       scif_put_peer_dev(spdev);
-cleanup_qp:
-       scif_cleanup_ep_qp(ep);
-connect_error_simple:
-       return err;
-}
-
-/*
- * scif_conn_handler:
- *
- * Workqueue handler for servicing non-blocking SCIF connect
- *
- */
-void scif_conn_handler(struct work_struct *work)
-{
-       struct scif_endpt *ep;
-
-       do {
-               ep = NULL;
-               spin_lock(&scif_info.nb_connect_lock);
-               if (!list_empty(&scif_info.nb_connect_list)) {
-                       ep = list_first_entry(&scif_info.nb_connect_list,
-                                             struct scif_endpt, conn_list);
-                       list_del(&ep->conn_list);
-               }
-               spin_unlock(&scif_info.nb_connect_lock);
-               if (ep) {
-                       ep->conn_err = scif_conn_func(ep);
-                       wake_up_interruptible(&ep->conn_pend_wq);
-               }
-       } while (ep);
-}
-
-int __scif_connect(scif_epd_t epd, struct scif_port_id *dst, bool non_block)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       int err = 0;
-       struct scif_dev *remote_dev;
-       struct device *spdev;
-
-       dev_dbg(scif_info.mdev.this_device, "SCIFAPI connect: ep %p %s\n", ep,
-               scif_ep_states[ep->state]);
-
-       if (!scif_dev || dst->node > scif_info.maxid)
-               return -ENODEV;
-
-       might_sleep();
-
-       remote_dev = &scif_dev[dst->node];
-       spdev = scif_get_peer_dev(remote_dev);
-       if (IS_ERR(spdev)) {
-               err = PTR_ERR(spdev);
-               return err;
-       }
-
-       spin_lock(&ep->lock);
-       switch (ep->state) {
-       case SCIFEP_ZOMBIE:
-       case SCIFEP_CLOSING:
-               err = -EINVAL;
-               break;
-       case SCIFEP_DISCONNECTED:
-               if (ep->conn_async_state == ASYNC_CONN_INPROGRESS)
-                       ep->conn_async_state = ASYNC_CONN_FLUSH_WORK;
-               else
-                       err = -EINVAL;
-               break;
-       case SCIFEP_LISTENING:
-       case SCIFEP_CLLISTEN:
-               err = -EOPNOTSUPP;
-               break;
-       case SCIFEP_CONNECTING:
-       case SCIFEP_MAPPING:
-               if (ep->conn_async_state == ASYNC_CONN_INPROGRESS)
-                       err = -EINPROGRESS;
-               else
-                       err = -EISCONN;
-               break;
-       case SCIFEP_CONNECTED:
-               if (ep->conn_async_state == ASYNC_CONN_INPROGRESS)
-                       ep->conn_async_state = ASYNC_CONN_FLUSH_WORK;
-               else
-                       err = -EISCONN;
-               break;
-       case SCIFEP_UNBOUND:
-               err = scif_get_new_port();
-               if (err < 0)
-                       break;
-               ep->port.port = err;
-               ep->port.node = scif_info.nodeid;
-               ep->conn_async_state = ASYNC_CONN_IDLE;
-               fallthrough;
-       case SCIFEP_BOUND:
-               /*
-                * If a non-blocking connect has been already initiated
-                * (conn_async_state is either ASYNC_CONN_INPROGRESS or
-                * ASYNC_CONN_FLUSH_WORK), the end point could end up in
-                * SCIF_BOUND due an error in the connection process
-                * (e.g., connection refused) If conn_async_state is
-                * ASYNC_CONN_INPROGRESS - transition to ASYNC_CONN_FLUSH_WORK
-                * so that the error status can be collected. If the state is
-                * already ASYNC_CONN_FLUSH_WORK - then set the error to
-                * EINPROGRESS since some other thread is waiting to collect
-                * error status.
-                */
-               if (ep->conn_async_state == ASYNC_CONN_INPROGRESS) {
-                       ep->conn_async_state = ASYNC_CONN_FLUSH_WORK;
-               } else if (ep->conn_async_state == ASYNC_CONN_FLUSH_WORK) {
-                       err = -EINPROGRESS;
-               } else {
-                       ep->conn_port = *dst;
-                       init_waitqueue_head(&ep->sendwq);
-                       init_waitqueue_head(&ep->recvwq);
-                       init_waitqueue_head(&ep->conwq);
-                       ep->conn_async_state = 0;
-
-                       if (unlikely(non_block))
-                               ep->conn_async_state = ASYNC_CONN_INPROGRESS;
-               }
-               break;
-       }
-
-       if (err || ep->conn_async_state == ASYNC_CONN_FLUSH_WORK)
-                       goto connect_simple_unlock1;
-
-       ep->state = SCIFEP_CONNECTING;
-       ep->remote_dev = &scif_dev[dst->node];
-       ep->qp_info.qp->magic = SCIFEP_MAGIC;
-       if (ep->conn_async_state == ASYNC_CONN_INPROGRESS) {
-               init_waitqueue_head(&ep->conn_pend_wq);
-               spin_lock(&scif_info.nb_connect_lock);
-               list_add_tail(&ep->conn_list, &scif_info.nb_connect_list);
-               spin_unlock(&scif_info.nb_connect_lock);
-               err = -EINPROGRESS;
-               schedule_work(&scif_info.conn_work);
-       }
-connect_simple_unlock1:
-       spin_unlock(&ep->lock);
-       scif_put_peer_dev(spdev);
-       if (err) {
-               return err;
-       } else if (ep->conn_async_state == ASYNC_CONN_FLUSH_WORK) {
-               flush_work(&scif_info.conn_work);
-               err = ep->conn_err;
-               spin_lock(&ep->lock);
-               ep->conn_async_state = ASYNC_CONN_IDLE;
-               spin_unlock(&ep->lock);
-       } else {
-               err = scif_conn_func(ep);
-       }
-       return err;
-}
-
-int scif_connect(scif_epd_t epd, struct scif_port_id *dst)
-{
-       return __scif_connect(epd, dst, false);
-}
-EXPORT_SYMBOL_GPL(scif_connect);
-
-/*
- * scif_accept() - Accept a connection request from the remote node
- *
- * The function accepts a connection request from the remote node.  Successful
- * complete is indicate by a new end point being created and passed back
- * to the caller for future reference.
- *
- * Upon successful complete a zero will be returned and the peer information
- * will be filled in.
- *
- * If the end point is not in the listening state -EINVAL will be returned.
- *
- * If during the connection sequence resource allocation fails the -ENOMEM
- * will be returned.
- *
- * If the function is called with the ASYNC flag set and no connection requests
- * are pending it will return -EAGAIN.
- *
- * If the remote side is not sending any connection requests the caller may
- * terminate this function with a signal.  If so a -EINTR will be returned.
- */
-int scif_accept(scif_epd_t epd, struct scif_port_id *peer,
-               scif_epd_t *newepd, int flags)
-{
-       struct scif_endpt *lep = (struct scif_endpt *)epd;
-       struct scif_endpt *cep;
-       struct scif_conreq *conreq;
-       struct scifmsg msg;
-       int err;
-       struct device *spdev;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI accept: ep %p %s\n", lep, scif_ep_states[lep->state]);
-
-       if (flags & ~SCIF_ACCEPT_SYNC)
-               return -EINVAL;
-
-       if (!peer || !newepd)
-               return -EINVAL;
-
-       might_sleep();
-       spin_lock(&lep->lock);
-       if (lep->state != SCIFEP_LISTENING) {
-               spin_unlock(&lep->lock);
-               return -EINVAL;
-       }
-
-       if (!lep->conreqcnt && !(flags & SCIF_ACCEPT_SYNC)) {
-               /* No connection request present and we do not want to wait */
-               spin_unlock(&lep->lock);
-               return -EAGAIN;
-       }
-
-       lep->files = current->files;
-retry_connection:
-       spin_unlock(&lep->lock);
-       /* Wait for the remote node to send us a SCIF_CNCT_REQ */
-       err = wait_event_interruptible(lep->conwq,
-                                      (lep->conreqcnt ||
-                                      (lep->state != SCIFEP_LISTENING)));
-       if (err)
-               return err;
-
-       if (lep->state != SCIFEP_LISTENING)
-               return -EINTR;
-
-       spin_lock(&lep->lock);
-
-       if (!lep->conreqcnt)
-               goto retry_connection;
-
-       /* Get the first connect request off the list */
-       conreq = list_first_entry(&lep->conlist, struct scif_conreq, list);
-       list_del(&conreq->list);
-       lep->conreqcnt--;
-       spin_unlock(&lep->lock);
-
-       /* Fill in the peer information */
-       peer->node = conreq->msg.src.node;
-       peer->port = conreq->msg.src.port;
-
-       cep = kzalloc(sizeof(*cep), GFP_KERNEL);
-       if (!cep) {
-               err = -ENOMEM;
-               goto scif_accept_error_epalloc;
-       }
-       spin_lock_init(&cep->lock);
-       mutex_init(&cep->sendlock);
-       mutex_init(&cep->recvlock);
-       cep->state = SCIFEP_CONNECTING;
-       cep->remote_dev = &scif_dev[peer->node];
-       cep->remote_ep = conreq->msg.payload[0];
-
-       scif_rma_ep_init(cep);
-
-       err = scif_reserve_dma_chan(cep);
-       if (err) {
-               dev_err(scif_info.mdev.this_device,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-               goto scif_accept_error_qpalloc;
-       }
-
-       cep->qp_info.qp = kzalloc(sizeof(*cep->qp_info.qp), GFP_KERNEL);
-       if (!cep->qp_info.qp) {
-               err = -ENOMEM;
-               goto scif_accept_error_qpalloc;
-       }
-
-       err = scif_anon_inode_getfile(cep);
-       if (err)
-               goto scif_accept_error_anon_inode;
-
-       cep->qp_info.qp->magic = SCIFEP_MAGIC;
-       spdev = scif_get_peer_dev(cep->remote_dev);
-       if (IS_ERR(spdev)) {
-               err = PTR_ERR(spdev);
-               goto scif_accept_error_map;
-       }
-       err = scif_setup_qp_accept(cep->qp_info.qp, &cep->qp_info.qp_offset,
-                                  conreq->msg.payload[1], SCIF_ENDPT_QP_SIZE,
-                                  cep->remote_dev);
-       if (err) {
-               dev_dbg(&cep->remote_dev->sdev->dev,
-                       "SCIFAPI accept: ep %p new %p scif_setup_qp_accept %d qp_offset 0x%llx\n",
-                       lep, cep, err, cep->qp_info.qp_offset);
-               scif_put_peer_dev(spdev);
-               goto scif_accept_error_map;
-       }
-
-       cep->port.node = lep->port.node;
-       cep->port.port = lep->port.port;
-       cep->peer.node = peer->node;
-       cep->peer.port = peer->port;
-       init_waitqueue_head(&cep->sendwq);
-       init_waitqueue_head(&cep->recvwq);
-       init_waitqueue_head(&cep->conwq);
-
-       msg.uop = SCIF_CNCT_GNT;
-       msg.src = cep->port;
-       msg.payload[0] = cep->remote_ep;
-       msg.payload[1] = cep->qp_info.qp_offset;
-       msg.payload[2] = (u64)cep;
-
-       err = _scif_nodeqp_send(cep->remote_dev, &msg);
-       scif_put_peer_dev(spdev);
-       if (err)
-               goto scif_accept_error_map;
-retry:
-       /* Wait for the remote node to respond with SCIF_CNCT_GNT(N)ACK */
-       err = wait_event_timeout(cep->conwq, cep->state != SCIFEP_CONNECTING,
-                                SCIF_NODE_ACCEPT_TIMEOUT);
-       if (!err && scifdev_alive(cep))
-               goto retry;
-       err = !err ? -ENODEV : 0;
-       if (err)
-               goto scif_accept_error_map;
-       kfree(conreq);
-
-       spin_lock(&cep->lock);
-
-       if (cep->state == SCIFEP_CLOSING) {
-               /*
-                * Remote failed to allocate resources and NAKed the grant.
-                * There is at this point nothing referencing the new end point.
-                */
-               spin_unlock(&cep->lock);
-               scif_teardown_ep(cep);
-               kfree(cep);
-
-               /* If call with sync flag then go back and wait. */
-               if (flags & SCIF_ACCEPT_SYNC) {
-                       spin_lock(&lep->lock);
-                       goto retry_connection;
-               }
-               return -EAGAIN;
-       }
-
-       scif_get_port(cep->port.port);
-       *newepd = (scif_epd_t)cep;
-       spin_unlock(&cep->lock);
-       return 0;
-scif_accept_error_map:
-       scif_anon_inode_fput(cep);
-scif_accept_error_anon_inode:
-       scif_teardown_ep(cep);
-scif_accept_error_qpalloc:
-       kfree(cep);
-scif_accept_error_epalloc:
-       msg.uop = SCIF_CNCT_REJ;
-       msg.dst.node = conreq->msg.src.node;
-       msg.dst.port = conreq->msg.src.port;
-       msg.payload[0] = conreq->msg.payload[0];
-       msg.payload[1] = conreq->msg.payload[1];
-       scif_nodeqp_send(&scif_dev[conreq->msg.src.node], &msg);
-       kfree(conreq);
-       return err;
-}
-EXPORT_SYMBOL_GPL(scif_accept);
-
-/*
- * scif_msg_param_check:
- * @epd: The end point returned from scif_open()
- * @len: Length to receive
- * @flags: blocking or non blocking
- *
- * Validate parameters for messaging APIs scif_send(..)/scif_recv(..).
- */
-static inline int scif_msg_param_check(scif_epd_t epd, int len, int flags)
-{
-       int ret = -EINVAL;
-
-       if (len < 0)
-               goto err_ret;
-       if (flags && (!(flags & SCIF_RECV_BLOCK)))
-               goto err_ret;
-       ret = 0;
-err_ret:
-       return ret;
-}
-
-static int _scif_send(scif_epd_t epd, void *msg, int len, int flags)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       struct scifmsg notif_msg;
-       int curr_xfer_len = 0, sent_len = 0, write_count;
-       int ret = 0;
-       struct scif_qp *qp = ep->qp_info.qp;
-
-       if (flags & SCIF_SEND_BLOCK)
-               might_sleep();
-
-       spin_lock(&ep->lock);
-       while (sent_len != len && SCIFEP_CONNECTED == ep->state) {
-               write_count = scif_rb_space(&qp->outbound_q);
-               if (write_count) {
-                       /* Best effort to send as much data as possible */
-                       curr_xfer_len = min(len - sent_len, write_count);
-                       ret = scif_rb_write(&qp->outbound_q, msg,
-                                           curr_xfer_len);
-                       if (ret < 0)
-                               break;
-                       /* Success. Update write pointer */
-                       scif_rb_commit(&qp->outbound_q);
-                       /*
-                        * Send a notification to the peer about the
-                        * produced data message.
-                        */
-                       notif_msg.src = ep->port;
-                       notif_msg.uop = SCIF_CLIENT_SENT;
-                       notif_msg.payload[0] = ep->remote_ep;
-                       ret = _scif_nodeqp_send(ep->remote_dev, &notif_msg);
-                       if (ret)
-                               break;
-                       sent_len += curr_xfer_len;
-                       msg = msg + curr_xfer_len;
-                       continue;
-               }
-               curr_xfer_len = min(len - sent_len, SCIF_ENDPT_QP_SIZE - 1);
-               /* Not enough RB space. return for the Non Blocking case */
-               if (!(flags & SCIF_SEND_BLOCK))
-                       break;
-
-               spin_unlock(&ep->lock);
-               /* Wait for a SCIF_CLIENT_RCVD message in the Blocking case */
-               ret =
-               wait_event_interruptible(ep->sendwq,
-                                        (SCIFEP_CONNECTED != ep->state) ||
-                                        (scif_rb_space(&qp->outbound_q) >=
-                                        curr_xfer_len));
-               spin_lock(&ep->lock);
-               if (ret)
-                       break;
-       }
-       if (sent_len)
-               ret = sent_len;
-       else if (!ret && SCIFEP_CONNECTED != ep->state)
-               ret = SCIFEP_DISCONNECTED == ep->state ?
-                       -ECONNRESET : -ENOTCONN;
-       spin_unlock(&ep->lock);
-       return ret;
-}
-
-static int _scif_recv(scif_epd_t epd, void *msg, int len, int flags)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       struct scifmsg notif_msg;
-       int curr_recv_len = 0, remaining_len = len, read_count;
-       int ret = 0;
-       struct scif_qp *qp = ep->qp_info.qp;
-
-       if (flags & SCIF_RECV_BLOCK)
-               might_sleep();
-       spin_lock(&ep->lock);
-       while (remaining_len && (SCIFEP_CONNECTED == ep->state ||
-                                SCIFEP_DISCONNECTED == ep->state)) {
-               read_count = scif_rb_count(&qp->inbound_q, remaining_len);
-               if (read_count) {
-                       /*
-                        * Best effort to recv as much data as there
-                        * are bytes to read in the RB particularly
-                        * important for the Non Blocking case.
-                        */
-                       curr_recv_len = min(remaining_len, read_count);
-                       scif_rb_get_next(&qp->inbound_q, msg, curr_recv_len);
-                       if (ep->state == SCIFEP_CONNECTED) {
-                               /*
-                                * Update the read pointer only if the endpoint
-                                * is still connected else the read pointer
-                                * might no longer exist since the peer has
-                                * freed resources!
-                                */
-                               scif_rb_update_read_ptr(&qp->inbound_q);
-                               /*
-                                * Send a notification to the peer about the
-                                * consumed data message only if the EP is in
-                                * SCIFEP_CONNECTED state.
-                                */
-                               notif_msg.src = ep->port;
-                               notif_msg.uop = SCIF_CLIENT_RCVD;
-                               notif_msg.payload[0] = ep->remote_ep;
-                               ret = _scif_nodeqp_send(ep->remote_dev,
-                                                       &notif_msg);
-                               if (ret)
-                                       break;
-                       }
-                       remaining_len -= curr_recv_len;
-                       msg = msg + curr_recv_len;
-                       continue;
-               }
-               /*
-                * Bail out now if the EP is in SCIFEP_DISCONNECTED state else
-                * we will keep looping forever.
-                */
-               if (ep->state == SCIFEP_DISCONNECTED)
-                       break;
-               /*
-                * Return in the Non Blocking case if there is no data
-                * to read in this iteration.
-                */
-               if (!(flags & SCIF_RECV_BLOCK))
-                       break;
-               curr_recv_len = min(remaining_len, SCIF_ENDPT_QP_SIZE - 1);
-               spin_unlock(&ep->lock);
-               /*
-                * Wait for a SCIF_CLIENT_SEND message in the blocking case
-                * or until other side disconnects.
-                */
-               ret =
-               wait_event_interruptible(ep->recvwq,
-                                        SCIFEP_CONNECTED != ep->state ||
-                                        scif_rb_count(&qp->inbound_q,
-                                                      curr_recv_len)
-                                        >= curr_recv_len);
-               spin_lock(&ep->lock);
-               if (ret)
-                       break;
-       }
-       if (len - remaining_len)
-               ret = len - remaining_len;
-       else if (!ret && ep->state != SCIFEP_CONNECTED)
-               ret = ep->state == SCIFEP_DISCONNECTED ?
-                       -ECONNRESET : -ENOTCONN;
-       spin_unlock(&ep->lock);
-       return ret;
-}
-
-/**
- * scif_user_send() - Send data to connection queue
- * @epd: The end point returned from scif_open()
- * @msg: Address to place data
- * @len: Length to receive
- * @flags: blocking or non blocking
- *
- * This function is called from the driver IOCTL entry point
- * only and is a wrapper for _scif_send().
- */
-int scif_user_send(scif_epd_t epd, void __user *msg, int len, int flags)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       int err = 0;
-       int sent_len = 0;
-       char *tmp;
-       int loop_len;
-       int chunk_len = min(len, (1 << (MAX_ORDER + PAGE_SHIFT - 1)));
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI send (U): ep %p %s\n", ep, scif_ep_states[ep->state]);
-       if (!len)
-               return 0;
-
-       err = scif_msg_param_check(epd, len, flags);
-       if (err)
-               goto send_err;
-
-       tmp = kmalloc(chunk_len, GFP_KERNEL);
-       if (!tmp) {
-               err = -ENOMEM;
-               goto send_err;
-       }
-       /*
-        * Grabbing the lock before breaking up the transfer in
-        * multiple chunks is required to ensure that messages do
-        * not get fragmented and reordered.
-        */
-       mutex_lock(&ep->sendlock);
-       while (sent_len != len) {
-               loop_len = len - sent_len;
-               loop_len = min(chunk_len, loop_len);
-               if (copy_from_user(tmp, msg, loop_len)) {
-                       err = -EFAULT;
-                       goto send_free_err;
-               }
-               err = _scif_send(epd, tmp, loop_len, flags);
-               if (err < 0)
-                       goto send_free_err;
-               sent_len += err;
-               msg += err;
-               if (err != loop_len)
-                       goto send_free_err;
-       }
-send_free_err:
-       mutex_unlock(&ep->sendlock);
-       kfree(tmp);
-send_err:
-       return err < 0 ? err : sent_len;
-}
-
-/**
- * scif_user_recv() - Receive data from connection queue
- * @epd: The end point returned from scif_open()
- * @msg: Address to place data
- * @len: Length to receive
- * @flags: blocking or non blocking
- *
- * This function is called from the driver IOCTL entry point
- * only and is a wrapper for _scif_recv().
- */
-int scif_user_recv(scif_epd_t epd, void __user *msg, int len, int flags)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       int err = 0;
-       int recv_len = 0;
-       char *tmp;
-       int loop_len;
-       int chunk_len = min(len, (1 << (MAX_ORDER + PAGE_SHIFT - 1)));
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI recv (U): ep %p %s\n", ep, scif_ep_states[ep->state]);
-       if (!len)
-               return 0;
-
-       err = scif_msg_param_check(epd, len, flags);
-       if (err)
-               goto recv_err;
-
-       tmp = kmalloc(chunk_len, GFP_KERNEL);
-       if (!tmp) {
-               err = -ENOMEM;
-               goto recv_err;
-       }
-       /*
-        * Grabbing the lock before breaking up the transfer in
-        * multiple chunks is required to ensure that messages do
-        * not get fragmented and reordered.
-        */
-       mutex_lock(&ep->recvlock);
-       while (recv_len != len) {
-               loop_len = len - recv_len;
-               loop_len = min(chunk_len, loop_len);
-               err = _scif_recv(epd, tmp, loop_len, flags);
-               if (err < 0)
-                       goto recv_free_err;
-               if (copy_to_user(msg, tmp, err)) {
-                       err = -EFAULT;
-                       goto recv_free_err;
-               }
-               recv_len += err;
-               msg += err;
-               if (err != loop_len)
-                       goto recv_free_err;
-       }
-recv_free_err:
-       mutex_unlock(&ep->recvlock);
-       kfree(tmp);
-recv_err:
-       return err < 0 ? err : recv_len;
-}
-
-/**
- * scif_send() - Send data to connection queue
- * @epd: The end point returned from scif_open()
- * @msg: Address to place data
- * @len: Length to receive
- * @flags: blocking or non blocking
- *
- * This function is called from the kernel mode only and is
- * a wrapper for _scif_send().
- */
-int scif_send(scif_epd_t epd, void *msg, int len, int flags)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       int ret;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI send (K): ep %p %s\n", ep, scif_ep_states[ep->state]);
-       if (!len)
-               return 0;
-
-       ret = scif_msg_param_check(epd, len, flags);
-       if (ret)
-               return ret;
-       if (!ep->remote_dev)
-               return -ENOTCONN;
-       /*
-        * Grab the mutex lock in the blocking case only
-        * to ensure messages do not get fragmented/reordered.
-        * The non blocking mode is protected using spin locks
-        * in _scif_send().
-        */
-       if (flags & SCIF_SEND_BLOCK)
-               mutex_lock(&ep->sendlock);
-
-       ret = _scif_send(epd, msg, len, flags);
-
-       if (flags & SCIF_SEND_BLOCK)
-               mutex_unlock(&ep->sendlock);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(scif_send);
-
-/**
- * scif_recv() - Receive data from connection queue
- * @epd: The end point returned from scif_open()
- * @msg: Address to place data
- * @len: Length to receive
- * @flags: blocking or non blocking
- *
- * This function is called from the kernel mode only and is
- * a wrapper for _scif_recv().
- */
-int scif_recv(scif_epd_t epd, void *msg, int len, int flags)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       int ret;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI recv (K): ep %p %s\n", ep, scif_ep_states[ep->state]);
-       if (!len)
-               return 0;
-
-       ret = scif_msg_param_check(epd, len, flags);
-       if (ret)
-               return ret;
-       /*
-        * Grab the mutex lock in the blocking case only
-        * to ensure messages do not get fragmented/reordered.
-        * The non blocking mode is protected using spin locks
-        * in _scif_send().
-        */
-       if (flags & SCIF_RECV_BLOCK)
-               mutex_lock(&ep->recvlock);
-
-       ret = _scif_recv(epd, msg, len, flags);
-
-       if (flags & SCIF_RECV_BLOCK)
-               mutex_unlock(&ep->recvlock);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(scif_recv);
-
-static inline void _scif_poll_wait(struct file *f, wait_queue_head_t *wq,
-                                  poll_table *p, struct scif_endpt *ep)
-{
-       /*
-        * Because poll_wait makes a GFP_KERNEL allocation, give up the lock
-        * and regrab it afterwards. Because the endpoint state might have
-        * changed while the lock was given up, the state must be checked
-        * again after re-acquiring the lock. The code in __scif_pollfd(..)
-        * does this.
-        */
-       spin_unlock(&ep->lock);
-       poll_wait(f, wq, p);
-       spin_lock(&ep->lock);
-}
-
-__poll_t
-__scif_pollfd(struct file *f, poll_table *wait, struct scif_endpt *ep)
-{
-       __poll_t mask = 0;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI pollfd: ep %p %s\n", ep, scif_ep_states[ep->state]);
-
-       spin_lock(&ep->lock);
-
-       /* Endpoint is waiting for a non-blocking connect to complete */
-       if (ep->conn_async_state == ASYNC_CONN_INPROGRESS) {
-               _scif_poll_wait(f, &ep->conn_pend_wq, wait, ep);
-               if (ep->conn_async_state == ASYNC_CONN_INPROGRESS) {
-                       if (ep->state == SCIFEP_CONNECTED ||
-                           ep->state == SCIFEP_DISCONNECTED ||
-                           ep->conn_err)
-                               mask |= EPOLLOUT;
-                       goto exit;
-               }
-       }
-
-       /* Endpoint is listening for incoming connection requests */
-       if (ep->state == SCIFEP_LISTENING) {
-               _scif_poll_wait(f, &ep->conwq, wait, ep);
-               if (ep->state == SCIFEP_LISTENING) {
-                       if (ep->conreqcnt)
-                               mask |= EPOLLIN;
-                       goto exit;
-               }
-       }
-
-       /* Endpoint is connected or disconnected */
-       if (ep->state == SCIFEP_CONNECTED || ep->state == SCIFEP_DISCONNECTED) {
-               if (poll_requested_events(wait) & EPOLLIN)
-                       _scif_poll_wait(f, &ep->recvwq, wait, ep);
-               if (poll_requested_events(wait) & EPOLLOUT)
-                       _scif_poll_wait(f, &ep->sendwq, wait, ep);
-               if (ep->state == SCIFEP_CONNECTED ||
-                   ep->state == SCIFEP_DISCONNECTED) {
-                       /* Data can be read without blocking */
-                       if (scif_rb_count(&ep->qp_info.qp->inbound_q, 1))
-                               mask |= EPOLLIN;
-                       /* Data can be written without blocking */
-                       if (scif_rb_space(&ep->qp_info.qp->outbound_q))
-                               mask |= EPOLLOUT;
-                       /* Return EPOLLHUP if endpoint is disconnected */
-                       if (ep->state == SCIFEP_DISCONNECTED)
-                               mask |= EPOLLHUP;
-                       goto exit;
-               }
-       }
-
-       /* Return EPOLLERR if the endpoint is in none of the above states */
-       mask |= EPOLLERR;
-exit:
-       spin_unlock(&ep->lock);
-       return mask;
-}
-
-/**
- * scif_poll() - Kernel mode SCIF poll
- * @ufds: Array of scif_pollepd structures containing the end points
- *       and events to poll on
- * @nfds: Size of the ufds array
- * @timeout_msecs: Timeout in msecs, -ve implies infinite timeout
- *
- * The code flow in this function is based on do_poll(..) in select.c
- *
- * Returns the number of endpoints which have pending events or 0 in
- * the event of a timeout. If a signal is used for wake up, -EINTR is
- * returned.
- */
-int
-scif_poll(struct scif_pollepd *ufds, unsigned int nfds, long timeout_msecs)
-{
-       struct poll_wqueues table;
-       poll_table *pt;
-       int i, count = 0, timed_out = timeout_msecs == 0;
-       __poll_t mask;
-       u64 timeout = timeout_msecs < 0 ? MAX_SCHEDULE_TIMEOUT
-               : msecs_to_jiffies(timeout_msecs);
-
-       poll_initwait(&table);
-       pt = &table.pt;
-       while (1) {
-               for (i = 0; i < nfds; i++) {
-                       pt->_key = ufds[i].events | EPOLLERR | EPOLLHUP;
-                       mask = __scif_pollfd(ufds[i].epd->anon,
-                                            pt, ufds[i].epd);
-                       mask &= ufds[i].events | EPOLLERR | EPOLLHUP;
-                       if (mask) {
-                               count++;
-                               pt->_qproc = NULL;
-                       }
-                       ufds[i].revents = mask;
-               }
-               pt->_qproc = NULL;
-               if (!count) {
-                       count = table.error;
-                       if (signal_pending(current))
-                               count = -EINTR;
-               }
-               if (count || timed_out)
-                       break;
-
-               if (!schedule_timeout_interruptible(timeout))
-                       timed_out = 1;
-       }
-       poll_freewait(&table);
-       return count;
-}
-EXPORT_SYMBOL_GPL(scif_poll);
-
-int scif_get_node_ids(u16 *nodes, int len, u16 *self)
-{
-       int online = 0;
-       int offset = 0;
-       int node;
-
-       if (!scif_is_mgmt_node())
-               scif_get_node_info();
-
-       *self = scif_info.nodeid;
-       mutex_lock(&scif_info.conflock);
-       len = min_t(int, len, scif_info.total);
-       for (node = 0; node <= scif_info.maxid; node++) {
-               if (_scifdev_alive(&scif_dev[node])) {
-                       online++;
-                       if (offset < len)
-                               nodes[offset++] = node;
-               }
-       }
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI get_node_ids total %d online %d filled in %d nodes\n",
-               scif_info.total, online, offset);
-       mutex_unlock(&scif_info.conflock);
-
-       return online;
-}
-EXPORT_SYMBOL_GPL(scif_get_node_ids);
-
-static int scif_add_client_dev(struct device *dev, struct subsys_interface *si)
-{
-       struct scif_client *client =
-               container_of(si, struct scif_client, si);
-       struct scif_peer_dev *spdev =
-               container_of(dev, struct scif_peer_dev, dev);
-
-       if (client->probe)
-               client->probe(spdev);
-       return 0;
-}
-
-static void scif_remove_client_dev(struct device *dev,
-                                  struct subsys_interface *si)
-{
-       struct scif_client *client =
-               container_of(si, struct scif_client, si);
-       struct scif_peer_dev *spdev =
-               container_of(dev, struct scif_peer_dev, dev);
-
-       if (client->remove)
-               client->remove(spdev);
-}
-
-void scif_client_unregister(struct scif_client *client)
-{
-       subsys_interface_unregister(&client->si);
-}
-EXPORT_SYMBOL_GPL(scif_client_unregister);
-
-int scif_client_register(struct scif_client *client)
-{
-       struct subsys_interface *si = &client->si;
-
-       si->name = client->name;
-       si->subsys = &scif_peer_bus;
-       si->add_dev = scif_add_client_dev;
-       si->remove_dev = scif_remove_client_dev;
-
-       return subsys_interface_register(&client->si);
-}
-EXPORT_SYMBOL_GPL(scif_client_register);
diff --git a/drivers/misc/mic/scif/scif_debugfs.c b/drivers/misc/mic/scif/scif_debugfs.c
deleted file mode 100644 (file)
index 8fe38e7..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-#include "../common/mic_dev.h"
-#include "scif_main.h"
-
-/* Debugfs parent dir */
-static struct dentry *scif_dbg;
-
-static int scif_dev_show(struct seq_file *s, void *unused)
-{
-       int node;
-
-       seq_printf(s, "Total Nodes %d Self Node Id %d Maxid %d\n",
-                  scif_info.total, scif_info.nodeid,
-                  scif_info.maxid);
-
-       if (!scif_dev)
-               return 0;
-
-       seq_printf(s, "%-16s\t%-16s\n", "node_id", "state");
-
-       for (node = 0; node <= scif_info.maxid; node++)
-               seq_printf(s, "%-16d\t%-16s\n", scif_dev[node].node,
-                          _scifdev_alive(&scif_dev[node]) ?
-                          "Running" : "Offline");
-       return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(scif_dev);
-
-static void scif_display_window(struct scif_window *window, struct seq_file *s)
-{
-       int j;
-       struct scatterlist *sg;
-       scif_pinned_pages_t pin = window->pinned_pages;
-
-       seq_printf(s, "window %p type %d temp %d offset 0x%llx ",
-                  window, window->type, window->temp, window->offset);
-       seq_printf(s, "nr_pages 0x%llx nr_contig_chunks 0x%x prot %d ",
-                  window->nr_pages, window->nr_contig_chunks, window->prot);
-       seq_printf(s, "ref_count %d magic 0x%llx peer_window 0x%llx ",
-                  window->ref_count, window->magic, window->peer_window);
-       seq_printf(s, "unreg_state 0x%x va_for_temp 0x%lx\n",
-                  window->unreg_state, window->va_for_temp);
-
-       for (j = 0; j < window->nr_contig_chunks; j++)
-               seq_printf(s, "page[%d] dma_addr 0x%llx num_pages 0x%llx\n", j,
-                          window->dma_addr[j], window->num_pages[j]);
-
-       if (window->type == SCIF_WINDOW_SELF && pin)
-               for (j = 0; j < window->nr_pages; j++)
-                       seq_printf(s, "page[%d] = pinned_pages %p address %p\n",
-                                  j, pin->pages[j],
-                                  page_address(pin->pages[j]));
-
-       if (window->st)
-               for_each_sg(window->st->sgl, sg, window->st->nents, j)
-                       seq_printf(s, "sg[%d] dma addr 0x%llx length 0x%x\n",
-                                  j, sg_dma_address(sg), sg_dma_len(sg));
-}
-
-static void scif_display_all_windows(struct list_head *head, struct seq_file *s)
-{
-       struct list_head *item;
-       struct scif_window *window;
-
-       list_for_each(item, head) {
-               window = list_entry(item, struct scif_window, list);
-               scif_display_window(window, s);
-       }
-}
-
-static int scif_rma_show(struct seq_file *s, void *unused)
-{
-       struct scif_endpt *ep;
-       struct list_head *pos;
-
-       mutex_lock(&scif_info.connlock);
-       list_for_each(pos, &scif_info.connected) {
-               ep = list_entry(pos, struct scif_endpt, list);
-               seq_printf(s, "ep %p self windows\n", ep);
-               mutex_lock(&ep->rma_info.rma_lock);
-               scif_display_all_windows(&ep->rma_info.reg_list, s);
-               seq_printf(s, "ep %p remote windows\n", ep);
-               scif_display_all_windows(&ep->rma_info.remote_reg_list, s);
-               mutex_unlock(&ep->rma_info.rma_lock);
-       }
-       mutex_unlock(&scif_info.connlock);
-       return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(scif_rma);
-
-void __init scif_init_debugfs(void)
-{
-       scif_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
-
-       debugfs_create_file("scif_dev", 0444, scif_dbg, NULL, &scif_dev_fops);
-       debugfs_create_file("scif_rma", 0444, scif_dbg, NULL, &scif_rma_fops);
-       debugfs_create_u8("en_msg_log", 0666, scif_dbg, &scif_info.en_msg_log);
-       debugfs_create_u8("p2p_enable", 0666, scif_dbg, &scif_info.p2p_enable);
-}
-
-void scif_exit_debugfs(void)
-{
-       debugfs_remove_recursive(scif_dbg);
-}
diff --git a/drivers/misc/mic/scif/scif_dma.c b/drivers/misc/mic/scif/scif_dma.c
deleted file mode 100644 (file)
index 401b98e..0000000
+++ /dev/null
@@ -1,1940 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#include "scif_main.h"
-#include "scif_map.h"
-
-/*
- * struct scif_dma_comp_cb - SCIF DMA completion callback
- *
- * @dma_completion_func: DMA completion callback
- * @cb_cookie: DMA completion callback cookie
- * @temp_buf: Temporary buffer
- * @temp_buf_to_free: Temporary buffer to be freed
- * @is_cache: Is a kmem_cache allocated buffer
- * @dst_offset: Destination registration offset
- * @dst_window: Destination registration window
- * @len: Length of the temp buffer
- * @temp_phys: DMA address of the temp buffer
- * @sdev: The SCIF device
- * @header_padding: padding for cache line alignment
- */
-struct scif_dma_comp_cb {
-       void (*dma_completion_func)(void *cookie);
-       void *cb_cookie;
-       u8 *temp_buf;
-       u8 *temp_buf_to_free;
-       bool is_cache;
-       s64 dst_offset;
-       struct scif_window *dst_window;
-       size_t len;
-       dma_addr_t temp_phys;
-       struct scif_dev *sdev;
-       int header_padding;
-};
-
-/**
- * struct scif_copy_work - Work for DMA copy
- *
- * @src_offset: Starting source offset
- * @dst_offset: Starting destination offset
- * @src_window: Starting src registered window
- * @dst_window: Starting dst registered window
- * @loopback: true if this is a loopback DMA transfer
- * @len: Length of the transfer
- * @comp_cb: DMA copy completion callback
- * @remote_dev: The remote SCIF peer device
- * @fence_type: polling or interrupt based
- * @ordered: is this a tail byte ordered DMA transfer
- */
-struct scif_copy_work {
-       s64 src_offset;
-       s64 dst_offset;
-       struct scif_window *src_window;
-       struct scif_window *dst_window;
-       int loopback;
-       size_t len;
-       struct scif_dma_comp_cb   *comp_cb;
-       struct scif_dev *remote_dev;
-       int fence_type;
-       bool ordered;
-};
-
-/**
- * scif_reserve_dma_chan:
- * @ep: Endpoint Descriptor.
- *
- * This routine reserves a DMA channel for a particular
- * endpoint. All DMA transfers for an endpoint are always
- * programmed on the same DMA channel.
- */
-int scif_reserve_dma_chan(struct scif_endpt *ep)
-{
-       int err = 0;
-       struct scif_dev *scifdev;
-       struct scif_hw_dev *sdev;
-       struct dma_chan *chan;
-
-       /* Loopback DMAs are not supported on the management node */
-       if (!scif_info.nodeid && scifdev_self(ep->remote_dev))
-               return 0;
-       if (scif_info.nodeid)
-               scifdev = &scif_dev[0];
-       else
-               scifdev = ep->remote_dev;
-       sdev = scifdev->sdev;
-       if (!sdev->num_dma_ch)
-               return -ENODEV;
-       chan = sdev->dma_ch[scifdev->dma_ch_idx];
-       scifdev->dma_ch_idx = (scifdev->dma_ch_idx + 1) % sdev->num_dma_ch;
-       mutex_lock(&ep->rma_info.rma_lock);
-       ep->rma_info.dma_chan = chan;
-       mutex_unlock(&ep->rma_info.rma_lock);
-       return err;
-}
-
-#ifdef CONFIG_MMU_NOTIFIER
-/*
- * scif_rma_destroy_tcw:
- *
- * This routine destroys temporary cached windows
- */
-static
-void __scif_rma_destroy_tcw(struct scif_mmu_notif *mmn,
-                           u64 start, u64 len)
-{
-       struct list_head *item, *tmp;
-       struct scif_window *window;
-       u64 start_va, end_va;
-       u64 end = start + len;
-
-       if (end <= start)
-               return;
-
-       list_for_each_safe(item, tmp, &mmn->tc_reg_list) {
-               window = list_entry(item, struct scif_window, list);
-               if (!len)
-                       break;
-               start_va = window->va_for_temp;
-               end_va = start_va + (window->nr_pages << PAGE_SHIFT);
-               if (start < start_va && end <= start_va)
-                       break;
-               if (start >= end_va)
-                       continue;
-               __scif_rma_destroy_tcw_helper(window);
-       }
-}
-
-static void scif_rma_destroy_tcw(struct scif_mmu_notif *mmn, u64 start, u64 len)
-{
-       struct scif_endpt *ep = mmn->ep;
-
-       spin_lock(&ep->rma_info.tc_lock);
-       __scif_rma_destroy_tcw(mmn, start, len);
-       spin_unlock(&ep->rma_info.tc_lock);
-}
-
-static void scif_rma_destroy_tcw_ep(struct scif_endpt *ep)
-{
-       struct list_head *item, *tmp;
-       struct scif_mmu_notif *mmn;
-
-       list_for_each_safe(item, tmp, &ep->rma_info.mmn_list) {
-               mmn = list_entry(item, struct scif_mmu_notif, list);
-               scif_rma_destroy_tcw(mmn, 0, ULONG_MAX);
-       }
-}
-
-static void __scif_rma_destroy_tcw_ep(struct scif_endpt *ep)
-{
-       struct list_head *item, *tmp;
-       struct scif_mmu_notif *mmn;
-
-       spin_lock(&ep->rma_info.tc_lock);
-       list_for_each_safe(item, tmp, &ep->rma_info.mmn_list) {
-               mmn = list_entry(item, struct scif_mmu_notif, list);
-               __scif_rma_destroy_tcw(mmn, 0, ULONG_MAX);
-       }
-       spin_unlock(&ep->rma_info.tc_lock);
-}
-
-static bool scif_rma_tc_can_cache(struct scif_endpt *ep, size_t cur_bytes)
-{
-       if ((cur_bytes >> PAGE_SHIFT) > scif_info.rma_tc_limit)
-               return false;
-       if ((atomic_read(&ep->rma_info.tcw_total_pages)
-                       + (cur_bytes >> PAGE_SHIFT)) >
-                       scif_info.rma_tc_limit) {
-               dev_info(scif_info.mdev.this_device,
-                        "%s %d total=%d, current=%zu reached max\n",
-                        __func__, __LINE__,
-                        atomic_read(&ep->rma_info.tcw_total_pages),
-                        (1 + (cur_bytes >> PAGE_SHIFT)));
-               scif_rma_destroy_tcw_invalid();
-               __scif_rma_destroy_tcw_ep(ep);
-       }
-       return true;
-}
-
-static void scif_mmu_notifier_release(struct mmu_notifier *mn,
-                                     struct mm_struct *mm)
-{
-       struct scif_mmu_notif   *mmn;
-
-       mmn = container_of(mn, struct scif_mmu_notif, ep_mmu_notifier);
-       scif_rma_destroy_tcw(mmn, 0, ULONG_MAX);
-       schedule_work(&scif_info.misc_work);
-}
-
-static int scif_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
-                                       const struct mmu_notifier_range *range)
-{
-       struct scif_mmu_notif   *mmn;
-
-       mmn = container_of(mn, struct scif_mmu_notif, ep_mmu_notifier);
-       scif_rma_destroy_tcw(mmn, range->start, range->end - range->start);
-
-       return 0;
-}
-
-static void scif_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
-                       const struct mmu_notifier_range *range)
-{
-       /*
-        * Nothing to do here, everything needed was done in
-        * invalidate_range_start.
-        */
-}
-
-static const struct mmu_notifier_ops scif_mmu_notifier_ops = {
-       .release = scif_mmu_notifier_release,
-       .clear_flush_young = NULL,
-       .invalidate_range_start = scif_mmu_notifier_invalidate_range_start,
-       .invalidate_range_end = scif_mmu_notifier_invalidate_range_end};
-
-static void scif_ep_unregister_mmu_notifier(struct scif_endpt *ep)
-{
-       struct scif_endpt_rma_info *rma = &ep->rma_info;
-       struct scif_mmu_notif *mmn = NULL;
-       struct list_head *item, *tmp;
-
-       mutex_lock(&ep->rma_info.mmn_lock);
-       list_for_each_safe(item, tmp, &rma->mmn_list) {
-               mmn = list_entry(item, struct scif_mmu_notif, list);
-               mmu_notifier_unregister(&mmn->ep_mmu_notifier, mmn->mm);
-               list_del(item);
-               kfree(mmn);
-       }
-       mutex_unlock(&ep->rma_info.mmn_lock);
-}
-
-static void scif_init_mmu_notifier(struct scif_mmu_notif *mmn,
-                                  struct mm_struct *mm, struct scif_endpt *ep)
-{
-       mmn->ep = ep;
-       mmn->mm = mm;
-       mmn->ep_mmu_notifier.ops = &scif_mmu_notifier_ops;
-       INIT_LIST_HEAD(&mmn->list);
-       INIT_LIST_HEAD(&mmn->tc_reg_list);
-}
-
-static struct scif_mmu_notif *
-scif_find_mmu_notifier(struct mm_struct *mm, struct scif_endpt_rma_info *rma)
-{
-       struct scif_mmu_notif *mmn;
-
-       list_for_each_entry(mmn, &rma->mmn_list, list)
-               if (mmn->mm == mm)
-                       return mmn;
-       return NULL;
-}
-
-static struct scif_mmu_notif *
-scif_add_mmu_notifier(struct mm_struct *mm, struct scif_endpt *ep)
-{
-       struct scif_mmu_notif *mmn
-                = kzalloc(sizeof(*mmn), GFP_KERNEL);
-
-       if (!mmn)
-               return ERR_PTR(-ENOMEM);
-
-       scif_init_mmu_notifier(mmn, current->mm, ep);
-       if (mmu_notifier_register(&mmn->ep_mmu_notifier, current->mm)) {
-               kfree(mmn);
-               return ERR_PTR(-EBUSY);
-       }
-       list_add(&mmn->list, &ep->rma_info.mmn_list);
-       return mmn;
-}
-
-/*
- * Called from the misc thread to destroy temporary cached windows and
- * unregister the MMU notifier for the SCIF endpoint.
- */
-void scif_mmu_notif_handler(struct work_struct *work)
-{
-       struct list_head *pos, *tmpq;
-       struct scif_endpt *ep;
-restart:
-       scif_rma_destroy_tcw_invalid();
-       spin_lock(&scif_info.rmalock);
-       list_for_each_safe(pos, tmpq, &scif_info.mmu_notif_cleanup) {
-               ep = list_entry(pos, struct scif_endpt, mmu_list);
-               list_del(&ep->mmu_list);
-               spin_unlock(&scif_info.rmalock);
-               scif_rma_destroy_tcw_ep(ep);
-               scif_ep_unregister_mmu_notifier(ep);
-               goto restart;
-       }
-       spin_unlock(&scif_info.rmalock);
-}
-
-static bool scif_is_set_reg_cache(int flags)
-{
-       return !!(flags & SCIF_RMA_USECACHE);
-}
-#else
-static struct scif_mmu_notif *
-scif_find_mmu_notifier(struct mm_struct *mm,
-                      struct scif_endpt_rma_info *rma)
-{
-       return NULL;
-}
-
-static struct scif_mmu_notif *
-scif_add_mmu_notifier(struct mm_struct *mm, struct scif_endpt *ep)
-{
-       return NULL;
-}
-
-void scif_mmu_notif_handler(struct work_struct *work)
-{
-}
-
-static bool scif_is_set_reg_cache(int flags)
-{
-       return false;
-}
-
-static bool scif_rma_tc_can_cache(struct scif_endpt *ep, size_t cur_bytes)
-{
-       return false;
-}
-#endif
-
-/**
- * scif_register_temp:
- * @epd: End Point Descriptor.
- * @addr: virtual address to/from which to copy
- * @len: length of range to copy
- * @prot: read/write protection
- * @out_offset: computed offset returned by reference.
- * @out_window: allocated registered window returned by reference.
- *
- * Create a temporary registered window. The peer will not know about this
- * window. This API is used for scif_vreadfrom()/scif_vwriteto() API's.
- */
-static int
-scif_register_temp(scif_epd_t epd, unsigned long addr, size_t len, int prot,
-                  off_t *out_offset, struct scif_window **out_window)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       int err;
-       scif_pinned_pages_t pinned_pages;
-       size_t aligned_len;
-
-       aligned_len = ALIGN(len, PAGE_SIZE);
-
-       err = __scif_pin_pages((void *)(addr & PAGE_MASK),
-                              aligned_len, &prot, 0, &pinned_pages);
-       if (err)
-               return err;
-
-       pinned_pages->prot = prot;
-
-       /* Compute the offset for this registration */
-       err = scif_get_window_offset(ep, 0, 0,
-                                    aligned_len >> PAGE_SHIFT,
-                                    (s64 *)out_offset);
-       if (err)
-               goto error_unpin;
-
-       /* Allocate and prepare self registration window */
-       *out_window = scif_create_window(ep, aligned_len >> PAGE_SHIFT,
-                                       *out_offset, true);
-       if (!*out_window) {
-               scif_free_window_offset(ep, NULL, *out_offset);
-               err = -ENOMEM;
-               goto error_unpin;
-       }
-
-       (*out_window)->pinned_pages = pinned_pages;
-       (*out_window)->nr_pages = pinned_pages->nr_pages;
-       (*out_window)->prot = pinned_pages->prot;
-
-       (*out_window)->va_for_temp = addr & PAGE_MASK;
-       err = scif_map_window(ep->remote_dev, *out_window);
-       if (err) {
-               /* Something went wrong! Rollback */
-               scif_destroy_window(ep, *out_window);
-               *out_window = NULL;
-       } else {
-               *out_offset |= (addr - (*out_window)->va_for_temp);
-       }
-       return err;
-error_unpin:
-       if (err)
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-       scif_unpin_pages(pinned_pages);
-       return err;
-}
-
-#define SCIF_DMA_TO (3 * HZ)
-
-/*
- * scif_sync_dma - Program a DMA without an interrupt descriptor
- *
- * @dev - The address of the pointer to the device instance used
- * for DMA registration.
- * @chan - DMA channel to be used.
- * @sync_wait: Wait for DMA to complete?
- *
- * Return 0 on success and -errno on error.
- */
-static int scif_sync_dma(struct scif_hw_dev *sdev, struct dma_chan *chan,
-                        bool sync_wait)
-{
-       int err = 0;
-       struct dma_async_tx_descriptor *tx = NULL;
-       enum dma_ctrl_flags flags = DMA_PREP_FENCE;
-       dma_cookie_t cookie;
-       struct dma_device *ddev;
-
-       if (!chan) {
-               err = -EIO;
-               dev_err(&sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               return err;
-       }
-       ddev = chan->device;
-
-       tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, flags);
-       if (!tx) {
-               err = -ENOMEM;
-               dev_err(&sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               goto release;
-       }
-       cookie = tx->tx_submit(tx);
-
-       if (dma_submit_error(cookie)) {
-               err = -ENOMEM;
-               dev_err(&sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               goto release;
-       }
-       if (!sync_wait) {
-               dma_async_issue_pending(chan);
-       } else {
-               if (dma_sync_wait(chan, cookie) == DMA_COMPLETE) {
-                       err = 0;
-               } else {
-                       err = -EIO;
-                       dev_err(&sdev->dev, "%s %d err %d\n",
-                               __func__, __LINE__, err);
-               }
-       }
-release:
-       return err;
-}
-
-static void scif_dma_callback(void *arg)
-{
-       struct completion *done = (struct completion *)arg;
-
-       complete(done);
-}
-
-#define SCIF_DMA_SYNC_WAIT true
-#define SCIF_DMA_POLL BIT(0)
-#define SCIF_DMA_INTR BIT(1)
-
-/*
- * scif_async_dma - Program a DMA with an interrupt descriptor
- *
- * @dev - The address of the pointer to the device instance used
- * for DMA registration.
- * @chan - DMA channel to be used.
- * Return 0 on success and -errno on error.
- */
-static int scif_async_dma(struct scif_hw_dev *sdev, struct dma_chan *chan)
-{
-       int err = 0;
-       struct dma_device *ddev;
-       struct dma_async_tx_descriptor *tx = NULL;
-       enum dma_ctrl_flags flags = DMA_PREP_INTERRUPT | DMA_PREP_FENCE;
-       DECLARE_COMPLETION_ONSTACK(done_wait);
-       dma_cookie_t cookie;
-       enum dma_status status;
-
-       if (!chan) {
-               err = -EIO;
-               dev_err(&sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               return err;
-       }
-       ddev = chan->device;
-
-       tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, flags);
-       if (!tx) {
-               err = -ENOMEM;
-               dev_err(&sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               goto release;
-       }
-       reinit_completion(&done_wait);
-       tx->callback = scif_dma_callback;
-       tx->callback_param = &done_wait;
-       cookie = tx->tx_submit(tx);
-
-       if (dma_submit_error(cookie)) {
-               err = -ENOMEM;
-               dev_err(&sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               goto release;
-       }
-       dma_async_issue_pending(chan);
-
-       err = wait_for_completion_timeout(&done_wait, SCIF_DMA_TO);
-       if (!err) {
-               err = -EIO;
-               dev_err(&sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               goto release;
-       }
-       err = 0;
-       status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
-       if (status != DMA_COMPLETE) {
-               err = -EIO;
-               dev_err(&sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               goto release;
-       }
-release:
-       return err;
-}
-
-/*
- * scif_drain_dma_poll - Drain all outstanding DMA operations for a particular
- * DMA channel via polling.
- *
- * @sdev - The SCIF device
- * @chan - DMA channel
- * Return 0 on success and -errno on error.
- */
-static int scif_drain_dma_poll(struct scif_hw_dev *sdev, struct dma_chan *chan)
-{
-       if (!chan)
-               return -EINVAL;
-       return scif_sync_dma(sdev, chan, SCIF_DMA_SYNC_WAIT);
-}
-
-/*
- * scif_drain_dma_intr - Drain all outstanding DMA operations for a particular
- * DMA channel via interrupt based blocking wait.
- *
- * @sdev - The SCIF device
- * @chan - DMA channel
- * Return 0 on success and -errno on error.
- */
-int scif_drain_dma_intr(struct scif_hw_dev *sdev, struct dma_chan *chan)
-{
-       if (!chan)
-               return -EINVAL;
-       return scif_async_dma(sdev, chan);
-}
-
-/**
- * scif_rma_destroy_windows:
- *
- * This routine destroys all windows queued for cleanup
- */
-void scif_rma_destroy_windows(void)
-{
-       struct list_head *item, *tmp;
-       struct scif_window *window;
-       struct scif_endpt *ep;
-       struct dma_chan *chan;
-
-       might_sleep();
-restart:
-       spin_lock(&scif_info.rmalock);
-       list_for_each_safe(item, tmp, &scif_info.rma) {
-               window = list_entry(item, struct scif_window,
-                                   list);
-               ep = (struct scif_endpt *)window->ep;
-               chan = ep->rma_info.dma_chan;
-
-               list_del_init(&window->list);
-               spin_unlock(&scif_info.rmalock);
-               if (!chan || !scifdev_alive(ep) ||
-                   !scif_drain_dma_intr(ep->remote_dev->sdev,
-                                        ep->rma_info.dma_chan))
-                       /* Remove window from global list */
-                       window->unreg_state = OP_COMPLETED;
-               else
-                       dev_warn(&ep->remote_dev->sdev->dev,
-                                "DMA engine hung?\n");
-               if (window->unreg_state == OP_COMPLETED) {
-                       if (window->type == SCIF_WINDOW_SELF)
-                               scif_destroy_window(ep, window);
-                       else
-                               scif_destroy_remote_window(window);
-                       atomic_dec(&ep->rma_info.tw_refcount);
-               }
-               goto restart;
-       }
-       spin_unlock(&scif_info.rmalock);
-}
-
-/**
- * scif_rma_destroy_tcw:
- *
- * This routine destroys temporary cached registered windows
- * which have been queued for cleanup.
- */
-void scif_rma_destroy_tcw_invalid(void)
-{
-       struct list_head *item, *tmp;
-       struct scif_window *window;
-       struct scif_endpt *ep;
-       struct dma_chan *chan;
-
-       might_sleep();
-restart:
-       spin_lock(&scif_info.rmalock);
-       list_for_each_safe(item, tmp, &scif_info.rma_tc) {
-               window = list_entry(item, struct scif_window, list);
-               ep = (struct scif_endpt *)window->ep;
-               chan = ep->rma_info.dma_chan;
-               list_del_init(&window->list);
-               spin_unlock(&scif_info.rmalock);
-               mutex_lock(&ep->rma_info.rma_lock);
-               if (!chan || !scifdev_alive(ep) ||
-                   !scif_drain_dma_intr(ep->remote_dev->sdev,
-                                        ep->rma_info.dma_chan)) {
-                       atomic_sub(window->nr_pages,
-                                  &ep->rma_info.tcw_total_pages);
-                       scif_destroy_window(ep, window);
-                       atomic_dec(&ep->rma_info.tcw_refcount);
-               } else {
-                       dev_warn(&ep->remote_dev->sdev->dev,
-                                "DMA engine hung?\n");
-               }
-               mutex_unlock(&ep->rma_info.rma_lock);
-               goto restart;
-       }
-       spin_unlock(&scif_info.rmalock);
-}
-
-static inline
-void *_get_local_va(off_t off, struct scif_window *window, size_t len)
-{
-       int page_nr = (off - window->offset) >> PAGE_SHIFT;
-       off_t page_off = off & ~PAGE_MASK;
-       void *va = NULL;
-
-       if (window->type == SCIF_WINDOW_SELF) {
-               struct page **pages = window->pinned_pages->pages;
-
-               va = page_address(pages[page_nr]) + page_off;
-       }
-       return va;
-}
-
-static inline
-void *ioremap_remote(off_t off, struct scif_window *window,
-                    size_t len, struct scif_dev *dev,
-                    struct scif_window_iter *iter)
-{
-       dma_addr_t phys = scif_off_to_dma_addr(window, off, NULL, iter);
-
-       /*
-        * If the DMA address is not card relative then we need the DMA
-        * addresses to be an offset into the bar. The aperture base was already
-        * added so subtract it here since scif_ioremap is going to add it again
-        */
-       if (!scifdev_self(dev) && window->type == SCIF_WINDOW_PEER &&
-           dev->sdev->aper && !dev->sdev->card_rel_da)
-               phys = phys - dev->sdev->aper->pa;
-       return scif_ioremap(phys, len, dev);
-}
-
-static inline void
-iounmap_remote(void *virt, size_t size, struct scif_copy_work *work)
-{
-       scif_iounmap(virt, size, work->remote_dev);
-}
-
-/*
- * Takes care of ordering issue caused by
- * 1. Hardware:  Only in the case of cpu copy from mgmt node to card
- * because of WC memory.
- * 2. Software: If memcpy reorders copy instructions for optimization.
- * This could happen at both mgmt node and card.
- */
-static inline void
-scif_ordered_memcpy_toio(char *dst, const char *src, size_t count)
-{
-       if (!count)
-               return;
-
-       memcpy_toio((void __iomem __force *)dst, src, --count);
-       /* Order the last byte with the previous stores */
-       wmb();
-       *(dst + count) = *(src + count);
-}
-
-static inline void scif_unaligned_cpy_toio(char *dst, const char *src,
-                                          size_t count, bool ordered)
-{
-       if (ordered)
-               scif_ordered_memcpy_toio(dst, src, count);
-       else
-               memcpy_toio((void __iomem __force *)dst, src, count);
-}
-
-static inline
-void scif_ordered_memcpy_fromio(char *dst, const char *src, size_t count)
-{
-       if (!count)
-               return;
-
-       memcpy_fromio(dst, (void __iomem __force *)src, --count);
-       /* Order the last byte with the previous loads */
-       rmb();
-       *(dst + count) = *(src + count);
-}
-
-static inline void scif_unaligned_cpy_fromio(char *dst, const char *src,
-                                            size_t count, bool ordered)
-{
-       if (ordered)
-               scif_ordered_memcpy_fromio(dst, src, count);
-       else
-               memcpy_fromio(dst, (void __iomem __force *)src, count);
-}
-
-#define SCIF_RMA_ERROR_CODE (~(dma_addr_t)0x0)
-
-/*
- * scif_off_to_dma_addr:
- * Obtain the dma_addr given the window and the offset.
- * @window: Registered window.
- * @off: Window offset.
- * @nr_bytes: Return the number of contiguous bytes till next DMA addr index.
- * @index: Return the index of the dma_addr array found.
- * @start_off: start offset of index of the dma addr array found.
- * The nr_bytes provides the callee an estimate of the maximum possible
- * DMA xfer possible while the index/start_off provide faster lookups
- * for the next iteration.
- */
-dma_addr_t scif_off_to_dma_addr(struct scif_window *window, s64 off,
-                               size_t *nr_bytes, struct scif_window_iter *iter)
-{
-       int i, page_nr;
-       s64 start, end;
-       off_t page_off;
-
-       if (window->nr_pages == window->nr_contig_chunks) {
-               page_nr = (off - window->offset) >> PAGE_SHIFT;
-               page_off = off & ~PAGE_MASK;
-
-               if (nr_bytes)
-                       *nr_bytes = PAGE_SIZE - page_off;
-               return window->dma_addr[page_nr] | page_off;
-       }
-       if (iter) {
-               i = iter->index;
-               start = iter->offset;
-       } else {
-               i =  0;
-               start =  window->offset;
-       }
-       for (; i < window->nr_contig_chunks; i++) {
-               end = start + (window->num_pages[i] << PAGE_SHIFT);
-               if (off >= start && off < end) {
-                       if (iter) {
-                               iter->index = i;
-                               iter->offset = start;
-                       }
-                       if (nr_bytes)
-                               *nr_bytes = end - off;
-                       return (window->dma_addr[i] + (off - start));
-               }
-               start += (window->num_pages[i] << PAGE_SHIFT);
-       }
-       dev_err(scif_info.mdev.this_device,
-               "%s %d BUG. Addr not found? window %p off 0x%llx\n",
-               __func__, __LINE__, window, off);
-       return SCIF_RMA_ERROR_CODE;
-}
-
-/*
- * Copy between rma window and temporary buffer
- */
-static void scif_rma_local_cpu_copy(s64 offset, struct scif_window *window,
-                                   u8 *temp, size_t rem_len, bool to_temp)
-{
-       void *window_virt;
-       size_t loop_len;
-       int offset_in_page;
-       s64 end_offset;
-
-       offset_in_page = offset & ~PAGE_MASK;
-       loop_len = PAGE_SIZE - offset_in_page;
-
-       if (rem_len < loop_len)
-               loop_len = rem_len;
-
-       window_virt = _get_local_va(offset, window, loop_len);
-       if (!window_virt)
-               return;
-       if (to_temp)
-               memcpy(temp, window_virt, loop_len);
-       else
-               memcpy(window_virt, temp, loop_len);
-
-       offset += loop_len;
-       temp += loop_len;
-       rem_len -= loop_len;
-
-       end_offset = window->offset +
-               (window->nr_pages << PAGE_SHIFT);
-       while (rem_len) {
-               if (offset == end_offset) {
-                       window = list_next_entry(window, list);
-                       end_offset = window->offset +
-                               (window->nr_pages << PAGE_SHIFT);
-               }
-               loop_len = min(PAGE_SIZE, rem_len);
-               window_virt = _get_local_va(offset, window, loop_len);
-               if (!window_virt)
-                       return;
-               if (to_temp)
-                       memcpy(temp, window_virt, loop_len);
-               else
-                       memcpy(window_virt, temp, loop_len);
-               offset  += loop_len;
-               temp    += loop_len;
-               rem_len -= loop_len;
-       }
-}
-
-/**
- * scif_rma_completion_cb:
- * @data: RMA cookie
- *
- * RMA interrupt completion callback.
- */
-static void scif_rma_completion_cb(void *data)
-{
-       struct scif_dma_comp_cb *comp_cb = data;
-
-       /* Free DMA Completion CB. */
-       if (comp_cb->dst_window)
-               scif_rma_local_cpu_copy(comp_cb->dst_offset,
-                                       comp_cb->dst_window,
-                                       comp_cb->temp_buf +
-                                       comp_cb->header_padding,
-                                       comp_cb->len, false);
-       scif_unmap_single(comp_cb->temp_phys, comp_cb->sdev,
-                         SCIF_KMEM_UNALIGNED_BUF_SIZE);
-       if (comp_cb->is_cache)
-               kmem_cache_free(unaligned_cache,
-                               comp_cb->temp_buf_to_free);
-       else
-               kfree(comp_cb->temp_buf_to_free);
-}
-
-/* Copies between temporary buffer and offsets provided in work */
-static int
-scif_rma_list_dma_copy_unaligned(struct scif_copy_work *work,
-                                u8 *temp, struct dma_chan *chan,
-                                bool src_local)
-{
-       struct scif_dma_comp_cb *comp_cb = work->comp_cb;
-       dma_addr_t window_dma_addr, temp_dma_addr;
-       dma_addr_t temp_phys = comp_cb->temp_phys;
-       size_t loop_len, nr_contig_bytes = 0, remaining_len = work->len;
-       int offset_in_ca, ret = 0;
-       s64 end_offset, offset;
-       struct scif_window *window;
-       void *window_virt_addr;
-       size_t tail_len;
-       struct dma_async_tx_descriptor *tx;
-       struct dma_device *dev = chan->device;
-       dma_cookie_t cookie;
-
-       if (src_local) {
-               offset = work->dst_offset;
-               window = work->dst_window;
-       } else {
-               offset = work->src_offset;
-               window = work->src_window;
-       }
-
-       offset_in_ca = offset & (L1_CACHE_BYTES - 1);
-       if (offset_in_ca) {
-               loop_len = L1_CACHE_BYTES - offset_in_ca;
-               loop_len = min(loop_len, remaining_len);
-               window_virt_addr = ioremap_remote(offset, window,
-                                                 loop_len,
-                                                 work->remote_dev,
-                                                 NULL);
-               if (!window_virt_addr)
-                       return -ENOMEM;
-               if (src_local)
-                       scif_unaligned_cpy_toio(window_virt_addr, temp,
-                                               loop_len,
-                                               work->ordered &&
-                                               !(remaining_len - loop_len));
-               else
-                       scif_unaligned_cpy_fromio(temp, window_virt_addr,
-                                                 loop_len, work->ordered &&
-                                                 !(remaining_len - loop_len));
-               iounmap_remote(window_virt_addr, loop_len, work);
-
-               offset += loop_len;
-               temp += loop_len;
-               temp_phys += loop_len;
-               remaining_len -= loop_len;
-       }
-
-       offset_in_ca = offset & ~PAGE_MASK;
-       end_offset = window->offset +
-               (window->nr_pages << PAGE_SHIFT);
-
-       tail_len = remaining_len & (L1_CACHE_BYTES - 1);
-       remaining_len -= tail_len;
-       while (remaining_len) {
-               if (offset == end_offset) {
-                       window = list_next_entry(window, list);
-                       end_offset = window->offset +
-                               (window->nr_pages << PAGE_SHIFT);
-               }
-               if (scif_is_mgmt_node())
-                       temp_dma_addr = temp_phys;
-               else
-                       /* Fix if we ever enable IOMMU on the card */
-                       temp_dma_addr = (dma_addr_t)virt_to_phys(temp);
-               window_dma_addr = scif_off_to_dma_addr(window, offset,
-                                                      &nr_contig_bytes,
-                                                      NULL);
-               loop_len = min(nr_contig_bytes, remaining_len);
-               if (src_local) {
-                       if (work->ordered && !tail_len &&
-                           !(remaining_len - loop_len) &&
-                           loop_len != L1_CACHE_BYTES) {
-                               /*
-                                * Break up the last chunk of the transfer into
-                                * two steps. if there is no tail to guarantee
-                                * DMA ordering. SCIF_DMA_POLLING inserts
-                                * a status update descriptor in step 1 which
-                                * acts as a double sided synchronization fence
-                                * for the DMA engine to ensure that the last
-                                * cache line in step 2 is updated last.
-                                */
-                               /* Step 1) DMA: Body Length - L1_CACHE_BYTES. */
-                               tx =
-                               dev->device_prep_dma_memcpy(chan,
-                                                           window_dma_addr,
-                                                           temp_dma_addr,
-                                                           loop_len -
-                                                           L1_CACHE_BYTES,
-                                                           DMA_PREP_FENCE);
-                               if (!tx) {
-                                       ret = -ENOMEM;
-                                       goto err;
-                               }
-                               cookie = tx->tx_submit(tx);
-                               if (dma_submit_error(cookie)) {
-                                       ret = -ENOMEM;
-                                       goto err;
-                               }
-                               dma_async_issue_pending(chan);
-                               offset += (loop_len - L1_CACHE_BYTES);
-                               temp_dma_addr += (loop_len - L1_CACHE_BYTES);
-                               window_dma_addr += (loop_len - L1_CACHE_BYTES);
-                               remaining_len -= (loop_len - L1_CACHE_BYTES);
-                               loop_len = remaining_len;
-
-                               /* Step 2) DMA: L1_CACHE_BYTES */
-                               tx =
-                               dev->device_prep_dma_memcpy(chan,
-                                                           window_dma_addr,
-                                                           temp_dma_addr,
-                                                           loop_len, 0);
-                               if (!tx) {
-                                       ret = -ENOMEM;
-                                       goto err;
-                               }
-                               cookie = tx->tx_submit(tx);
-                               if (dma_submit_error(cookie)) {
-                                       ret = -ENOMEM;
-                                       goto err;
-                               }
-                               dma_async_issue_pending(chan);
-                       } else {
-                               tx =
-                               dev->device_prep_dma_memcpy(chan,
-                                                           window_dma_addr,
-                                                           temp_dma_addr,
-                                                           loop_len, 0);
-                               if (!tx) {
-                                       ret = -ENOMEM;
-                                       goto err;
-                               }
-                               cookie = tx->tx_submit(tx);
-                               if (dma_submit_error(cookie)) {
-                                       ret = -ENOMEM;
-                                       goto err;
-                               }
-                               dma_async_issue_pending(chan);
-                       }
-               } else {
-                       tx = dev->device_prep_dma_memcpy(chan, temp_dma_addr,
-                                       window_dma_addr, loop_len, 0);
-                       if (!tx) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-                       cookie = tx->tx_submit(tx);
-                       if (dma_submit_error(cookie)) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-                       dma_async_issue_pending(chan);
-               }
-               offset += loop_len;
-               temp += loop_len;
-               temp_phys += loop_len;
-               remaining_len -= loop_len;
-               offset_in_ca = 0;
-       }
-       if (tail_len) {
-               if (offset == end_offset) {
-                       window = list_next_entry(window, list);
-                       end_offset = window->offset +
-                               (window->nr_pages << PAGE_SHIFT);
-               }
-               window_virt_addr = ioremap_remote(offset, window, tail_len,
-                                                 work->remote_dev,
-                                                 NULL);
-               if (!window_virt_addr)
-                       return -ENOMEM;
-               /*
-                * The CPU copy for the tail bytes must be initiated only once
-                * previous DMA transfers for this endpoint have completed
-                * to guarantee ordering.
-                */
-               if (work->ordered) {
-                       struct scif_dev *rdev = work->remote_dev;
-
-                       ret = scif_drain_dma_intr(rdev->sdev, chan);
-                       if (ret)
-                               return ret;
-               }
-               if (src_local)
-                       scif_unaligned_cpy_toio(window_virt_addr, temp,
-                                               tail_len, work->ordered);
-               else
-                       scif_unaligned_cpy_fromio(temp, window_virt_addr,
-                                                 tail_len, work->ordered);
-               iounmap_remote(window_virt_addr, tail_len, work);
-       }
-       tx = dev->device_prep_dma_memcpy(chan, 0, 0, 0, DMA_PREP_INTERRUPT);
-       if (!tx) {
-               ret = -ENOMEM;
-               return ret;
-       }
-       tx->callback = &scif_rma_completion_cb;
-       tx->callback_param = comp_cb;
-       cookie = tx->tx_submit(tx);
-
-       if (dma_submit_error(cookie)) {
-               ret = -ENOMEM;
-               return ret;
-       }
-       dma_async_issue_pending(chan);
-       return 0;
-err:
-       dev_err(scif_info.mdev.this_device,
-               "%s %d Desc Prog Failed ret %d\n",
-               __func__, __LINE__, ret);
-       return ret;
-}
-
-/*
- * _scif_rma_list_dma_copy_aligned:
- *
- * Traverse all the windows and perform DMA copy.
- */
-static int _scif_rma_list_dma_copy_aligned(struct scif_copy_work *work,
-                                          struct dma_chan *chan)
-{
-       dma_addr_t src_dma_addr, dst_dma_addr;
-       size_t loop_len, remaining_len, src_contig_bytes = 0;
-       size_t dst_contig_bytes = 0;
-       struct scif_window_iter src_win_iter;
-       struct scif_window_iter dst_win_iter;
-       s64 end_src_offset, end_dst_offset;
-       struct scif_window *src_window = work->src_window;
-       struct scif_window *dst_window = work->dst_window;
-       s64 src_offset = work->src_offset, dst_offset = work->dst_offset;
-       int ret = 0;
-       struct dma_async_tx_descriptor *tx;
-       struct dma_device *dev = chan->device;
-       dma_cookie_t cookie;
-
-       remaining_len = work->len;
-
-       scif_init_window_iter(src_window, &src_win_iter);
-       scif_init_window_iter(dst_window, &dst_win_iter);
-       end_src_offset = src_window->offset +
-               (src_window->nr_pages << PAGE_SHIFT);
-       end_dst_offset = dst_window->offset +
-               (dst_window->nr_pages << PAGE_SHIFT);
-       while (remaining_len) {
-               if (src_offset == end_src_offset) {
-                       src_window = list_next_entry(src_window, list);
-                       end_src_offset = src_window->offset +
-                               (src_window->nr_pages << PAGE_SHIFT);
-                       scif_init_window_iter(src_window, &src_win_iter);
-               }
-               if (dst_offset == end_dst_offset) {
-                       dst_window = list_next_entry(dst_window, list);
-                       end_dst_offset = dst_window->offset +
-                               (dst_window->nr_pages << PAGE_SHIFT);
-                       scif_init_window_iter(dst_window, &dst_win_iter);
-               }
-
-               /* compute dma addresses for transfer */
-               src_dma_addr = scif_off_to_dma_addr(src_window, src_offset,
-                                                   &src_contig_bytes,
-                                                   &src_win_iter);
-               dst_dma_addr = scif_off_to_dma_addr(dst_window, dst_offset,
-                                                   &dst_contig_bytes,
-                                                   &dst_win_iter);
-               loop_len = min(src_contig_bytes, dst_contig_bytes);
-               loop_len = min(loop_len, remaining_len);
-               if (work->ordered && !(remaining_len - loop_len)) {
-                       /*
-                        * Break up the last chunk of the transfer into two
-                        * steps to ensure that the last byte in step 2 is
-                        * updated last.
-                        */
-                       /* Step 1) DMA: Body Length - 1 */
-                       tx = dev->device_prep_dma_memcpy(chan, dst_dma_addr,
-                                                        src_dma_addr,
-                                                        loop_len - 1,
-                                                        DMA_PREP_FENCE);
-                       if (!tx) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-                       cookie = tx->tx_submit(tx);
-                       if (dma_submit_error(cookie)) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-                       src_offset += (loop_len - 1);
-                       dst_offset += (loop_len - 1);
-                       src_dma_addr += (loop_len - 1);
-                       dst_dma_addr += (loop_len - 1);
-                       remaining_len -= (loop_len - 1);
-                       loop_len = remaining_len;
-
-                       /* Step 2) DMA: 1 BYTES */
-                       tx = dev->device_prep_dma_memcpy(chan, dst_dma_addr,
-                                       src_dma_addr, loop_len, 0);
-                       if (!tx) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-                       cookie = tx->tx_submit(tx);
-                       if (dma_submit_error(cookie)) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-                       dma_async_issue_pending(chan);
-               } else {
-                       tx = dev->device_prep_dma_memcpy(chan, dst_dma_addr,
-                                       src_dma_addr, loop_len, 0);
-                       if (!tx) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-                       cookie = tx->tx_submit(tx);
-                       if (dma_submit_error(cookie)) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-               }
-               src_offset += loop_len;
-               dst_offset += loop_len;
-               remaining_len -= loop_len;
-       }
-       return ret;
-err:
-       dev_err(scif_info.mdev.this_device,
-               "%s %d Desc Prog Failed ret %d\n",
-               __func__, __LINE__, ret);
-       return ret;
-}
-
-/*
- * scif_rma_list_dma_copy_aligned:
- *
- * Traverse all the windows and perform DMA copy.
- */
-static int scif_rma_list_dma_copy_aligned(struct scif_copy_work *work,
-                                         struct dma_chan *chan)
-{
-       dma_addr_t src_dma_addr, dst_dma_addr;
-       size_t loop_len, remaining_len, tail_len, src_contig_bytes = 0;
-       size_t dst_contig_bytes = 0;
-       int src_cache_off;
-       s64 end_src_offset, end_dst_offset;
-       struct scif_window_iter src_win_iter;
-       struct scif_window_iter dst_win_iter;
-       void *src_virt, *dst_virt;
-       struct scif_window *src_window = work->src_window;
-       struct scif_window *dst_window = work->dst_window;
-       s64 src_offset = work->src_offset, dst_offset = work->dst_offset;
-       int ret = 0;
-       struct dma_async_tx_descriptor *tx;
-       struct dma_device *dev = chan->device;
-       dma_cookie_t cookie;
-
-       remaining_len = work->len;
-       scif_init_window_iter(src_window, &src_win_iter);
-       scif_init_window_iter(dst_window, &dst_win_iter);
-
-       src_cache_off = src_offset & (L1_CACHE_BYTES - 1);
-       if (src_cache_off != 0) {
-               /* Head */
-               loop_len = L1_CACHE_BYTES - src_cache_off;
-               loop_len = min(loop_len, remaining_len);
-               src_dma_addr = __scif_off_to_dma_addr(src_window, src_offset);
-               dst_dma_addr = __scif_off_to_dma_addr(dst_window, dst_offset);
-               if (src_window->type == SCIF_WINDOW_SELF)
-                       src_virt = _get_local_va(src_offset, src_window,
-                                                loop_len);
-               else
-                       src_virt = ioremap_remote(src_offset, src_window,
-                                                 loop_len,
-                                                 work->remote_dev, NULL);
-               if (!src_virt)
-                       return -ENOMEM;
-               if (dst_window->type == SCIF_WINDOW_SELF)
-                       dst_virt = _get_local_va(dst_offset, dst_window,
-                                                loop_len);
-               else
-                       dst_virt = ioremap_remote(dst_offset, dst_window,
-                                                 loop_len,
-                                                 work->remote_dev, NULL);
-               if (!dst_virt) {
-                       if (src_window->type != SCIF_WINDOW_SELF)
-                               iounmap_remote(src_virt, loop_len, work);
-                       return -ENOMEM;
-               }
-               if (src_window->type == SCIF_WINDOW_SELF)
-                       scif_unaligned_cpy_toio(dst_virt, src_virt, loop_len,
-                                               remaining_len == loop_len ?
-                                               work->ordered : false);
-               else
-                       scif_unaligned_cpy_fromio(dst_virt, src_virt, loop_len,
-                                                 remaining_len == loop_len ?
-                                                 work->ordered : false);
-               if (src_window->type != SCIF_WINDOW_SELF)
-                       iounmap_remote(src_virt, loop_len, work);
-               if (dst_window->type != SCIF_WINDOW_SELF)
-                       iounmap_remote(dst_virt, loop_len, work);
-               src_offset += loop_len;
-               dst_offset += loop_len;
-               remaining_len -= loop_len;
-       }
-
-       end_src_offset = src_window->offset +
-               (src_window->nr_pages << PAGE_SHIFT);
-       end_dst_offset = dst_window->offset +
-               (dst_window->nr_pages << PAGE_SHIFT);
-       tail_len = remaining_len & (L1_CACHE_BYTES - 1);
-       remaining_len -= tail_len;
-       while (remaining_len) {
-               if (src_offset == end_src_offset) {
-                       src_window = list_next_entry(src_window, list);
-                       end_src_offset = src_window->offset +
-                               (src_window->nr_pages << PAGE_SHIFT);
-                       scif_init_window_iter(src_window, &src_win_iter);
-               }
-               if (dst_offset == end_dst_offset) {
-                       dst_window = list_next_entry(dst_window, list);
-                       end_dst_offset = dst_window->offset +
-                               (dst_window->nr_pages << PAGE_SHIFT);
-                       scif_init_window_iter(dst_window, &dst_win_iter);
-               }
-
-               /* compute dma addresses for transfer */
-               src_dma_addr = scif_off_to_dma_addr(src_window, src_offset,
-                                                   &src_contig_bytes,
-                                                   &src_win_iter);
-               dst_dma_addr = scif_off_to_dma_addr(dst_window, dst_offset,
-                                                   &dst_contig_bytes,
-                                                   &dst_win_iter);
-               loop_len = min(src_contig_bytes, dst_contig_bytes);
-               loop_len = min(loop_len, remaining_len);
-               if (work->ordered && !tail_len &&
-                   !(remaining_len - loop_len)) {
-                       /*
-                        * Break up the last chunk of the transfer into two
-                        * steps. if there is no tail to gurantee DMA ordering.
-                        * Passing SCIF_DMA_POLLING inserts a status update
-                        * descriptor in step 1 which acts as a double sided
-                        * synchronization fence for the DMA engine to ensure
-                        * that the last cache line in step 2 is updated last.
-                        */
-                       /* Step 1) DMA: Body Length - L1_CACHE_BYTES. */
-                       tx = dev->device_prep_dma_memcpy(chan, dst_dma_addr,
-                                                        src_dma_addr,
-                                                        loop_len -
-                                                        L1_CACHE_BYTES,
-                                                        DMA_PREP_FENCE);
-                       if (!tx) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-                       cookie = tx->tx_submit(tx);
-                       if (dma_submit_error(cookie)) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-                       dma_async_issue_pending(chan);
-                       src_offset += (loop_len - L1_CACHE_BYTES);
-                       dst_offset += (loop_len - L1_CACHE_BYTES);
-                       src_dma_addr += (loop_len - L1_CACHE_BYTES);
-                       dst_dma_addr += (loop_len - L1_CACHE_BYTES);
-                       remaining_len -= (loop_len - L1_CACHE_BYTES);
-                       loop_len = remaining_len;
-
-                       /* Step 2) DMA: L1_CACHE_BYTES */
-                       tx = dev->device_prep_dma_memcpy(chan, dst_dma_addr,
-                                                        src_dma_addr,
-                                                        loop_len, 0);
-                       if (!tx) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-                       cookie = tx->tx_submit(tx);
-                       if (dma_submit_error(cookie)) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-                       dma_async_issue_pending(chan);
-               } else {
-                       tx = dev->device_prep_dma_memcpy(chan, dst_dma_addr,
-                                                        src_dma_addr,
-                                                        loop_len, 0);
-                       if (!tx) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-                       cookie = tx->tx_submit(tx);
-                       if (dma_submit_error(cookie)) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-                       dma_async_issue_pending(chan);
-               }
-               src_offset += loop_len;
-               dst_offset += loop_len;
-               remaining_len -= loop_len;
-       }
-       remaining_len = tail_len;
-       if (remaining_len) {
-               loop_len = remaining_len;
-               if (src_offset == end_src_offset)
-                       src_window = list_next_entry(src_window, list);
-               if (dst_offset == end_dst_offset)
-                       dst_window = list_next_entry(dst_window, list);
-
-               src_dma_addr = __scif_off_to_dma_addr(src_window, src_offset);
-               dst_dma_addr = __scif_off_to_dma_addr(dst_window, dst_offset);
-               /*
-                * The CPU copy for the tail bytes must be initiated only once
-                * previous DMA transfers for this endpoint have completed to
-                * guarantee ordering.
-                */
-               if (work->ordered) {
-                       struct scif_dev *rdev = work->remote_dev;
-
-                       ret = scif_drain_dma_poll(rdev->sdev, chan);
-                       if (ret)
-                               return ret;
-               }
-               if (src_window->type == SCIF_WINDOW_SELF)
-                       src_virt = _get_local_va(src_offset, src_window,
-                                                loop_len);
-               else
-                       src_virt = ioremap_remote(src_offset, src_window,
-                                                 loop_len,
-                                                 work->remote_dev, NULL);
-               if (!src_virt)
-                       return -ENOMEM;
-
-               if (dst_window->type == SCIF_WINDOW_SELF)
-                       dst_virt = _get_local_va(dst_offset, dst_window,
-                                                loop_len);
-               else
-                       dst_virt = ioremap_remote(dst_offset, dst_window,
-                                                 loop_len,
-                                                 work->remote_dev, NULL);
-               if (!dst_virt) {
-                       if (src_window->type != SCIF_WINDOW_SELF)
-                               iounmap_remote(src_virt, loop_len, work);
-                       return -ENOMEM;
-               }
-
-               if (src_window->type == SCIF_WINDOW_SELF)
-                       scif_unaligned_cpy_toio(dst_virt, src_virt, loop_len,
-                                               work->ordered);
-               else
-                       scif_unaligned_cpy_fromio(dst_virt, src_virt,
-                                                 loop_len, work->ordered);
-               if (src_window->type != SCIF_WINDOW_SELF)
-                       iounmap_remote(src_virt, loop_len, work);
-
-               if (dst_window->type != SCIF_WINDOW_SELF)
-                       iounmap_remote(dst_virt, loop_len, work);
-               remaining_len -= loop_len;
-       }
-       return ret;
-err:
-       dev_err(scif_info.mdev.this_device,
-               "%s %d Desc Prog Failed ret %d\n",
-               __func__, __LINE__, ret);
-       return ret;
-}
-
-/*
- * scif_rma_list_cpu_copy:
- *
- * Traverse all the windows and perform CPU copy.
- */
-static int scif_rma_list_cpu_copy(struct scif_copy_work *work)
-{
-       void *src_virt, *dst_virt;
-       size_t loop_len, remaining_len;
-       int src_page_off, dst_page_off;
-       s64 src_offset = work->src_offset, dst_offset = work->dst_offset;
-       struct scif_window *src_window = work->src_window;
-       struct scif_window *dst_window = work->dst_window;
-       s64 end_src_offset, end_dst_offset;
-       int ret = 0;
-       struct scif_window_iter src_win_iter;
-       struct scif_window_iter dst_win_iter;
-
-       remaining_len = work->len;
-
-       scif_init_window_iter(src_window, &src_win_iter);
-       scif_init_window_iter(dst_window, &dst_win_iter);
-       while (remaining_len) {
-               src_page_off = src_offset & ~PAGE_MASK;
-               dst_page_off = dst_offset & ~PAGE_MASK;
-               loop_len = min(PAGE_SIZE -
-                              max(src_page_off, dst_page_off),
-                              remaining_len);
-
-               if (src_window->type == SCIF_WINDOW_SELF)
-                       src_virt = _get_local_va(src_offset, src_window,
-                                                loop_len);
-               else
-                       src_virt = ioremap_remote(src_offset, src_window,
-                                                 loop_len,
-                                                 work->remote_dev,
-                                                 &src_win_iter);
-               if (!src_virt) {
-                       ret = -ENOMEM;
-                       goto error;
-               }
-
-               if (dst_window->type == SCIF_WINDOW_SELF)
-                       dst_virt = _get_local_va(dst_offset, dst_window,
-                                                loop_len);
-               else
-                       dst_virt = ioremap_remote(dst_offset, dst_window,
-                                                 loop_len,
-                                                 work->remote_dev,
-                                                 &dst_win_iter);
-               if (!dst_virt) {
-                       if (src_window->type == SCIF_WINDOW_PEER)
-                               iounmap_remote(src_virt, loop_len, work);
-                       ret = -ENOMEM;
-                       goto error;
-               }
-
-               if (work->loopback) {
-                       memcpy(dst_virt, src_virt, loop_len);
-               } else {
-                       if (src_window->type == SCIF_WINDOW_SELF)
-                               memcpy_toio((void __iomem __force *)dst_virt,
-                                           src_virt, loop_len);
-                       else
-                               memcpy_fromio(dst_virt,
-                                             (void __iomem __force *)src_virt,
-                                             loop_len);
-               }
-               if (src_window->type == SCIF_WINDOW_PEER)
-                       iounmap_remote(src_virt, loop_len, work);
-
-               if (dst_window->type == SCIF_WINDOW_PEER)
-                       iounmap_remote(dst_virt, loop_len, work);
-
-               src_offset += loop_len;
-               dst_offset += loop_len;
-               remaining_len -= loop_len;
-               if (remaining_len) {
-                       end_src_offset = src_window->offset +
-                               (src_window->nr_pages << PAGE_SHIFT);
-                       end_dst_offset = dst_window->offset +
-                               (dst_window->nr_pages << PAGE_SHIFT);
-                       if (src_offset == end_src_offset) {
-                               src_window = list_next_entry(src_window, list);
-                               scif_init_window_iter(src_window,
-                                                     &src_win_iter);
-                       }
-                       if (dst_offset == end_dst_offset) {
-                               dst_window = list_next_entry(dst_window, list);
-                               scif_init_window_iter(dst_window,
-                                                     &dst_win_iter);
-                       }
-               }
-       }
-error:
-       return ret;
-}
-
-static int scif_rma_list_dma_copy_wrapper(struct scif_endpt *epd,
-                                         struct scif_copy_work *work,
-                                         struct dma_chan *chan, off_t loffset)
-{
-       int src_cache_off, dst_cache_off;
-       s64 src_offset = work->src_offset, dst_offset = work->dst_offset;
-       u8 *temp = NULL;
-       bool src_local = true;
-       struct scif_dma_comp_cb *comp_cb;
-       int err;
-
-       if (is_dma_copy_aligned(chan->device, 1, 1, 1))
-               return _scif_rma_list_dma_copy_aligned(work, chan);
-
-       src_cache_off = src_offset & (L1_CACHE_BYTES - 1);
-       dst_cache_off = dst_offset & (L1_CACHE_BYTES - 1);
-
-       if (dst_cache_off == src_cache_off)
-               return scif_rma_list_dma_copy_aligned(work, chan);
-
-       if (work->loopback)
-               return scif_rma_list_cpu_copy(work);
-       src_local = work->src_window->type == SCIF_WINDOW_SELF;
-
-       /* Allocate dma_completion cb */
-       comp_cb = kzalloc(sizeof(*comp_cb), GFP_KERNEL);
-       if (!comp_cb)
-               goto error;
-
-       work->comp_cb = comp_cb;
-       comp_cb->cb_cookie = comp_cb;
-       comp_cb->dma_completion_func = &scif_rma_completion_cb;
-
-       if (work->len + (L1_CACHE_BYTES << 1) < SCIF_KMEM_UNALIGNED_BUF_SIZE) {
-               comp_cb->is_cache = false;
-               /* Allocate padding bytes to align to a cache line */
-               temp = kmalloc(work->len + (L1_CACHE_BYTES << 1),
-                              GFP_KERNEL);
-               if (!temp)
-                       goto free_comp_cb;
-               comp_cb->temp_buf_to_free = temp;
-               /* kmalloc(..) does not guarantee cache line alignment */
-               if (!IS_ALIGNED((u64)temp, L1_CACHE_BYTES))
-                       temp = PTR_ALIGN(temp, L1_CACHE_BYTES);
-       } else {
-               comp_cb->is_cache = true;
-               temp = kmem_cache_alloc(unaligned_cache, GFP_KERNEL);
-               if (!temp)
-                       goto free_comp_cb;
-               comp_cb->temp_buf_to_free = temp;
-       }
-
-       if (src_local) {
-               temp += dst_cache_off;
-               scif_rma_local_cpu_copy(work->src_offset, work->src_window,
-                                       temp, work->len, true);
-       } else {
-               comp_cb->dst_window = work->dst_window;
-               comp_cb->dst_offset = work->dst_offset;
-               work->src_offset = work->src_offset - src_cache_off;
-               comp_cb->len = work->len;
-               work->len = ALIGN(work->len + src_cache_off, L1_CACHE_BYTES);
-               comp_cb->header_padding = src_cache_off;
-       }
-       comp_cb->temp_buf = temp;
-
-       err = scif_map_single(&comp_cb->temp_phys, temp,
-                             work->remote_dev, SCIF_KMEM_UNALIGNED_BUF_SIZE);
-       if (err)
-               goto free_temp_buf;
-       comp_cb->sdev = work->remote_dev;
-       if (scif_rma_list_dma_copy_unaligned(work, temp, chan, src_local) < 0)
-               goto free_temp_buf;
-       if (!src_local)
-               work->fence_type = SCIF_DMA_INTR;
-       return 0;
-free_temp_buf:
-       if (comp_cb->is_cache)
-               kmem_cache_free(unaligned_cache, comp_cb->temp_buf_to_free);
-       else
-               kfree(comp_cb->temp_buf_to_free);
-free_comp_cb:
-       kfree(comp_cb);
-error:
-       return -ENOMEM;
-}
-
-/**
- * scif_rma_copy:
- * @epd: end point descriptor.
- * @loffset: offset in local registered address space to/from which to copy
- * @addr: user virtual address to/from which to copy
- * @len: length of range to copy
- * @roffset: offset in remote registered address space to/from which to copy
- * @flags: flags
- * @dir: LOCAL->REMOTE or vice versa.
- * @last_chunk: true if this is the last chunk of a larger transfer
- *
- * Validate parameters, check if src/dst registered ranges requested for copy
- * are valid and initiate either CPU or DMA copy.
- */
-static int scif_rma_copy(scif_epd_t epd, off_t loffset, unsigned long addr,
-                        size_t len, off_t roffset, int flags,
-                        enum scif_rma_dir dir, bool last_chunk)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       struct scif_rma_req remote_req;
-       struct scif_rma_req req;
-       struct scif_window *local_window = NULL;
-       struct scif_window *remote_window = NULL;
-       struct scif_copy_work copy_work;
-       bool loopback;
-       int err = 0;
-       struct dma_chan *chan;
-       struct scif_mmu_notif *mmn = NULL;
-       bool cache = false;
-       struct device *spdev;
-
-       err = scif_verify_epd(ep);
-       if (err)
-               return err;
-
-       if (flags && !(flags & (SCIF_RMA_USECPU | SCIF_RMA_USECACHE |
-                               SCIF_RMA_SYNC | SCIF_RMA_ORDERED)))
-               return -EINVAL;
-
-       loopback = scifdev_self(ep->remote_dev) ? true : false;
-       copy_work.fence_type = ((flags & SCIF_RMA_SYNC) && last_chunk) ?
-                               SCIF_DMA_POLL : 0;
-       copy_work.ordered = !!((flags & SCIF_RMA_ORDERED) && last_chunk);
-
-       /* Use CPU for Mgmt node <-> Mgmt node copies */
-       if (loopback && scif_is_mgmt_node()) {
-               flags |= SCIF_RMA_USECPU;
-               copy_work.fence_type = 0x0;
-       }
-
-       cache = scif_is_set_reg_cache(flags);
-
-       remote_req.out_window = &remote_window;
-       remote_req.offset = roffset;
-       remote_req.nr_bytes = len;
-       /*
-        * If transfer is from local to remote then the remote window
-        * must be writeable and vice versa.
-        */
-       remote_req.prot = dir == SCIF_LOCAL_TO_REMOTE ? VM_WRITE : VM_READ;
-       remote_req.type = SCIF_WINDOW_PARTIAL;
-       remote_req.head = &ep->rma_info.remote_reg_list;
-
-       spdev = scif_get_peer_dev(ep->remote_dev);
-       if (IS_ERR(spdev)) {
-               err = PTR_ERR(spdev);
-               return err;
-       }
-
-       if (addr && cache) {
-               mutex_lock(&ep->rma_info.mmn_lock);
-               mmn = scif_find_mmu_notifier(current->mm, &ep->rma_info);
-               if (!mmn)
-                       mmn = scif_add_mmu_notifier(current->mm, ep);
-               mutex_unlock(&ep->rma_info.mmn_lock);
-               if (IS_ERR(mmn)) {
-                       scif_put_peer_dev(spdev);
-                       return PTR_ERR(mmn);
-               }
-               cache = cache && !scif_rma_tc_can_cache(ep, len);
-       }
-       mutex_lock(&ep->rma_info.rma_lock);
-       if (addr) {
-               req.out_window = &local_window;
-               req.nr_bytes = ALIGN(len + (addr & ~PAGE_MASK),
-                                    PAGE_SIZE);
-               req.va_for_temp = addr & PAGE_MASK;
-               req.prot = (dir == SCIF_LOCAL_TO_REMOTE ?
-                           VM_READ : VM_WRITE | VM_READ);
-               /* Does a valid local window exist? */
-               if (mmn) {
-                       spin_lock(&ep->rma_info.tc_lock);
-                       req.head = &mmn->tc_reg_list;
-                       err = scif_query_tcw(ep, &req);
-                       spin_unlock(&ep->rma_info.tc_lock);
-               }
-               if (!mmn || err) {
-                       err = scif_register_temp(epd, req.va_for_temp,
-                                                req.nr_bytes, req.prot,
-                                                &loffset, &local_window);
-                       if (err) {
-                               mutex_unlock(&ep->rma_info.rma_lock);
-                               goto error;
-                       }
-                       if (!cache)
-                               goto skip_cache;
-                       atomic_inc(&ep->rma_info.tcw_refcount);
-                       atomic_add_return(local_window->nr_pages,
-                                         &ep->rma_info.tcw_total_pages);
-                       if (mmn) {
-                               spin_lock(&ep->rma_info.tc_lock);
-                               scif_insert_tcw(local_window,
-                                               &mmn->tc_reg_list);
-                               spin_unlock(&ep->rma_info.tc_lock);
-                       }
-               }
-skip_cache:
-               loffset = local_window->offset +
-                               (addr - local_window->va_for_temp);
-       } else {
-               req.out_window = &local_window;
-               req.offset = loffset;
-               /*
-                * If transfer is from local to remote then the self window
-                * must be readable and vice versa.
-                */
-               req.prot = dir == SCIF_LOCAL_TO_REMOTE ? VM_READ : VM_WRITE;
-               req.nr_bytes = len;
-               req.type = SCIF_WINDOW_PARTIAL;
-               req.head = &ep->rma_info.reg_list;
-               /* Does a valid local window exist? */
-               err = scif_query_window(&req);
-               if (err) {
-                       mutex_unlock(&ep->rma_info.rma_lock);
-                       goto error;
-               }
-       }
-
-       /* Does a valid remote window exist? */
-       err = scif_query_window(&remote_req);
-       if (err) {
-               mutex_unlock(&ep->rma_info.rma_lock);
-               goto error;
-       }
-
-       /*
-        * Prepare copy_work for submitting work to the DMA kernel thread
-        * or CPU copy routine.
-        */
-       copy_work.len = len;
-       copy_work.loopback = loopback;
-       copy_work.remote_dev = ep->remote_dev;
-       if (dir == SCIF_LOCAL_TO_REMOTE) {
-               copy_work.src_offset = loffset;
-               copy_work.src_window = local_window;
-               copy_work.dst_offset = roffset;
-               copy_work.dst_window = remote_window;
-       } else {
-               copy_work.src_offset = roffset;
-               copy_work.src_window = remote_window;
-               copy_work.dst_offset = loffset;
-               copy_work.dst_window = local_window;
-       }
-
-       if (flags & SCIF_RMA_USECPU) {
-               scif_rma_list_cpu_copy(&copy_work);
-       } else {
-               chan = ep->rma_info.dma_chan;
-               err = scif_rma_list_dma_copy_wrapper(epd, &copy_work,
-                                                    chan, loffset);
-       }
-       if (addr && !cache)
-               atomic_inc(&ep->rma_info.tw_refcount);
-
-       mutex_unlock(&ep->rma_info.rma_lock);
-
-       if (last_chunk) {
-               struct scif_dev *rdev = ep->remote_dev;
-
-               if (copy_work.fence_type == SCIF_DMA_POLL)
-                       err = scif_drain_dma_poll(rdev->sdev,
-                                                 ep->rma_info.dma_chan);
-               else if (copy_work.fence_type == SCIF_DMA_INTR)
-                       err = scif_drain_dma_intr(rdev->sdev,
-                                                 ep->rma_info.dma_chan);
-       }
-
-       if (addr && !cache)
-               scif_queue_for_cleanup(local_window, &scif_info.rma);
-       scif_put_peer_dev(spdev);
-       return err;
-error:
-       if (err) {
-               if (addr && local_window && !cache)
-                       scif_destroy_window(ep, local_window);
-               dev_err(scif_info.mdev.this_device,
-                       "%s %d err %d len 0x%lx\n",
-                       __func__, __LINE__, err, len);
-       }
-       scif_put_peer_dev(spdev);
-       return err;
-}
-
-int scif_readfrom(scif_epd_t epd, off_t loffset, size_t len,
-                 off_t roffset, int flags)
-{
-       int err;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI readfrom: ep %p loffset 0x%lx len 0x%lx offset 0x%lx flags 0x%x\n",
-               epd, loffset, len, roffset, flags);
-       if (scif_unaligned(loffset, roffset)) {
-               while (len > SCIF_MAX_UNALIGNED_BUF_SIZE) {
-                       err = scif_rma_copy(epd, loffset, 0x0,
-                                           SCIF_MAX_UNALIGNED_BUF_SIZE,
-                                           roffset, flags,
-                                           SCIF_REMOTE_TO_LOCAL, false);
-                       if (err)
-                               goto readfrom_err;
-                       loffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
-                       roffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
-                       len -= SCIF_MAX_UNALIGNED_BUF_SIZE;
-               }
-       }
-       err = scif_rma_copy(epd, loffset, 0x0, len,
-                           roffset, flags, SCIF_REMOTE_TO_LOCAL, true);
-readfrom_err:
-       return err;
-}
-EXPORT_SYMBOL_GPL(scif_readfrom);
-
-int scif_writeto(scif_epd_t epd, off_t loffset, size_t len,
-                off_t roffset, int flags)
-{
-       int err;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI writeto: ep %p loffset 0x%lx len 0x%lx roffset 0x%lx flags 0x%x\n",
-               epd, loffset, len, roffset, flags);
-       if (scif_unaligned(loffset, roffset)) {
-               while (len > SCIF_MAX_UNALIGNED_BUF_SIZE) {
-                       err = scif_rma_copy(epd, loffset, 0x0,
-                                           SCIF_MAX_UNALIGNED_BUF_SIZE,
-                                           roffset, flags,
-                                           SCIF_LOCAL_TO_REMOTE, false);
-                       if (err)
-                               goto writeto_err;
-                       loffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
-                       roffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
-                       len -= SCIF_MAX_UNALIGNED_BUF_SIZE;
-               }
-       }
-       err = scif_rma_copy(epd, loffset, 0x0, len,
-                           roffset, flags, SCIF_LOCAL_TO_REMOTE, true);
-writeto_err:
-       return err;
-}
-EXPORT_SYMBOL_GPL(scif_writeto);
-
-int scif_vreadfrom(scif_epd_t epd, void *addr, size_t len,
-                  off_t roffset, int flags)
-{
-       int err;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI vreadfrom: ep %p addr %p len 0x%lx roffset 0x%lx flags 0x%x\n",
-               epd, addr, len, roffset, flags);
-       if (scif_unaligned((off_t __force)addr, roffset)) {
-               if (len > SCIF_MAX_UNALIGNED_BUF_SIZE)
-                       flags &= ~SCIF_RMA_USECACHE;
-
-               while (len > SCIF_MAX_UNALIGNED_BUF_SIZE) {
-                       err = scif_rma_copy(epd, 0, (u64)addr,
-                                           SCIF_MAX_UNALIGNED_BUF_SIZE,
-                                           roffset, flags,
-                                           SCIF_REMOTE_TO_LOCAL, false);
-                       if (err)
-                               goto vreadfrom_err;
-                       addr += SCIF_MAX_UNALIGNED_BUF_SIZE;
-                       roffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
-                       len -= SCIF_MAX_UNALIGNED_BUF_SIZE;
-               }
-       }
-       err = scif_rma_copy(epd, 0, (u64)addr, len,
-                           roffset, flags, SCIF_REMOTE_TO_LOCAL, true);
-vreadfrom_err:
-       return err;
-}
-EXPORT_SYMBOL_GPL(scif_vreadfrom);
-
-int scif_vwriteto(scif_epd_t epd, void *addr, size_t len,
-                 off_t roffset, int flags)
-{
-       int err;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI vwriteto: ep %p addr %p len 0x%lx roffset 0x%lx flags 0x%x\n",
-               epd, addr, len, roffset, flags);
-       if (scif_unaligned((off_t __force)addr, roffset)) {
-               if (len > SCIF_MAX_UNALIGNED_BUF_SIZE)
-                       flags &= ~SCIF_RMA_USECACHE;
-
-               while (len > SCIF_MAX_UNALIGNED_BUF_SIZE) {
-                       err = scif_rma_copy(epd, 0, (u64)addr,
-                                           SCIF_MAX_UNALIGNED_BUF_SIZE,
-                                           roffset, flags,
-                                           SCIF_LOCAL_TO_REMOTE, false);
-                       if (err)
-                               goto vwriteto_err;
-                       addr += SCIF_MAX_UNALIGNED_BUF_SIZE;
-                       roffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
-                       len -= SCIF_MAX_UNALIGNED_BUF_SIZE;
-               }
-       }
-       err = scif_rma_copy(epd, 0, (u64)addr, len,
-                           roffset, flags, SCIF_LOCAL_TO_REMOTE, true);
-vwriteto_err:
-       return err;
-}
-EXPORT_SYMBOL_GPL(scif_vwriteto);
diff --git a/drivers/misc/mic/scif/scif_epd.c b/drivers/misc/mic/scif/scif_epd.c
deleted file mode 100644 (file)
index 426687f..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#include "scif_main.h"
-#include "scif_map.h"
-
-void scif_cleanup_ep_qp(struct scif_endpt *ep)
-{
-       struct scif_qp *qp = ep->qp_info.qp;
-
-       if (qp->outbound_q.rb_base) {
-               scif_iounmap((void *)qp->outbound_q.rb_base,
-                            qp->outbound_q.size, ep->remote_dev);
-               qp->outbound_q.rb_base = NULL;
-       }
-       if (qp->remote_qp) {
-               scif_iounmap((void *)qp->remote_qp,
-                            sizeof(struct scif_qp), ep->remote_dev);
-               qp->remote_qp = NULL;
-       }
-       if (qp->local_qp) {
-               scif_unmap_single(qp->local_qp, ep->remote_dev,
-                                 sizeof(struct scif_qp));
-               qp->local_qp = 0x0;
-       }
-       if (qp->local_buf) {
-               scif_unmap_single(qp->local_buf, ep->remote_dev,
-                                 SCIF_ENDPT_QP_SIZE);
-               qp->local_buf = 0;
-       }
-}
-
-void scif_teardown_ep(void *endpt)
-{
-       struct scif_endpt *ep = endpt;
-       struct scif_qp *qp = ep->qp_info.qp;
-
-       if (qp) {
-               spin_lock(&ep->lock);
-               scif_cleanup_ep_qp(ep);
-               spin_unlock(&ep->lock);
-               kfree(qp->inbound_q.rb_base);
-               kfree(qp);
-       }
-}
-
-/*
- * Enqueue the endpoint to the zombie list for cleanup.
- * The endpoint should not be accessed once this API returns.
- */
-void scif_add_epd_to_zombie_list(struct scif_endpt *ep, bool eplock_held)
-{
-       if (!eplock_held)
-               mutex_lock(&scif_info.eplock);
-       spin_lock(&ep->lock);
-       ep->state = SCIFEP_ZOMBIE;
-       spin_unlock(&ep->lock);
-       list_add_tail(&ep->list, &scif_info.zombie);
-       scif_info.nr_zombies++;
-       if (!eplock_held)
-               mutex_unlock(&scif_info.eplock);
-       schedule_work(&scif_info.misc_work);
-}
-
-static struct scif_endpt *scif_find_listen_ep(u16 port)
-{
-       struct scif_endpt *ep = NULL;
-       struct list_head *pos, *tmpq;
-
-       mutex_lock(&scif_info.eplock);
-       list_for_each_safe(pos, tmpq, &scif_info.listen) {
-               ep = list_entry(pos, struct scif_endpt, list);
-               if (ep->port.port == port) {
-                       mutex_unlock(&scif_info.eplock);
-                       return ep;
-               }
-       }
-       mutex_unlock(&scif_info.eplock);
-       return NULL;
-}
-
-void scif_cleanup_zombie_epd(void)
-{
-       struct list_head *pos, *tmpq;
-       struct scif_endpt *ep;
-
-       mutex_lock(&scif_info.eplock);
-       list_for_each_safe(pos, tmpq, &scif_info.zombie) {
-               ep = list_entry(pos, struct scif_endpt, list);
-               if (scif_rma_ep_can_uninit(ep)) {
-                       list_del(pos);
-                       scif_info.nr_zombies--;
-                       put_iova_domain(&ep->rma_info.iovad);
-                       kfree(ep);
-               }
-       }
-       mutex_unlock(&scif_info.eplock);
-}
-
-/**
- * scif_cnctreq() - Respond to SCIF_CNCT_REQ interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * This message is initiated by the remote node to request a connection
- * to the local node.  This function looks for an end point in the
- * listen state on the requested port id.
- *
- * If it finds a listening port it places the connect request on the
- * listening end points queue and wakes up any pending accept calls.
- *
- * If it does not find a listening end point it sends a connection
- * reject message to the remote node.
- */
-void scif_cnctreq(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = NULL;
-       struct scif_conreq *conreq;
-
-       conreq = kmalloc(sizeof(*conreq), GFP_KERNEL);
-       if (!conreq)
-               /* Lack of resources so reject the request. */
-               goto conreq_sendrej;
-
-       ep = scif_find_listen_ep(msg->dst.port);
-       if (!ep)
-               /*  Send reject due to no listening ports */
-               goto conreq_sendrej_free;
-       else
-               spin_lock(&ep->lock);
-
-       if (ep->backlog <= ep->conreqcnt) {
-               /*  Send reject due to too many pending requests */
-               spin_unlock(&ep->lock);
-               goto conreq_sendrej_free;
-       }
-
-       conreq->msg = *msg;
-       list_add_tail(&conreq->list, &ep->conlist);
-       ep->conreqcnt++;
-       wake_up_interruptible(&ep->conwq);
-       spin_unlock(&ep->lock);
-       return;
-
-conreq_sendrej_free:
-       kfree(conreq);
-conreq_sendrej:
-       msg->uop = SCIF_CNCT_REJ;
-       scif_nodeqp_send(&scif_dev[msg->src.node], msg);
-}
-
-/**
- * scif_cnctgnt() - Respond to SCIF_CNCT_GNT interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * An accept() on the remote node has occurred and sent this message
- * to indicate success.  Place the end point in the MAPPING state and
- * save the remote nodes memory information.  Then wake up the connect
- * request so it can finish.
- */
-void scif_cnctgnt(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
-
-       spin_lock(&ep->lock);
-       if (SCIFEP_CONNECTING == ep->state) {
-               ep->peer.node = msg->src.node;
-               ep->peer.port = msg->src.port;
-               ep->qp_info.gnt_pld = msg->payload[1];
-               ep->remote_ep = msg->payload[2];
-               ep->state = SCIFEP_MAPPING;
-
-               wake_up(&ep->conwq);
-       }
-       spin_unlock(&ep->lock);
-}
-
-/**
- * scif_cnctgnt_ack() - Respond to SCIF_CNCT_GNTACK interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * The remote connection request has finished mapping the local memory.
- * Place the connection in the connected state and wake up the pending
- * accept() call.
- */
-void scif_cnctgnt_ack(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
-
-       mutex_lock(&scif_info.connlock);
-       spin_lock(&ep->lock);
-       /* New ep is now connected with all resources set. */
-       ep->state = SCIFEP_CONNECTED;
-       list_add_tail(&ep->list, &scif_info.connected);
-       wake_up(&ep->conwq);
-       spin_unlock(&ep->lock);
-       mutex_unlock(&scif_info.connlock);
-}
-
-/**
- * scif_cnctgnt_nack() - Respond to SCIF_CNCT_GNTNACK interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * The remote connection request failed to map the local memory it was sent.
- * Place the end point in the CLOSING state to indicate it and wake up
- * the pending accept();
- */
-void scif_cnctgnt_nack(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
-
-       spin_lock(&ep->lock);
-       ep->state = SCIFEP_CLOSING;
-       wake_up(&ep->conwq);
-       spin_unlock(&ep->lock);
-}
-
-/**
- * scif_cnctrej() - Respond to SCIF_CNCT_REJ interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * The remote end has rejected the connection request.  Set the end
- * point back to the bound state and wake up the pending connect().
- */
-void scif_cnctrej(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
-
-       spin_lock(&ep->lock);
-       if (SCIFEP_CONNECTING == ep->state) {
-               ep->state = SCIFEP_BOUND;
-               wake_up(&ep->conwq);
-       }
-       spin_unlock(&ep->lock);
-}
-
-/**
- * scif_discnct() - Respond to SCIF_DISCNCT interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * The remote node has indicated close() has been called on its end
- * point.  Remove the local end point from the connected list, set its
- * state to disconnected and ensure accesses to the remote node are
- * shutdown.
- *
- * When all accesses to the remote end have completed then send a
- * DISCNT_ACK to indicate it can remove its resources and complete
- * the close routine.
- */
-void scif_discnct(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = NULL;
-       struct scif_endpt *tmpep;
-       struct list_head *pos, *tmpq;
-
-       mutex_lock(&scif_info.connlock);
-       list_for_each_safe(pos, tmpq, &scif_info.connected) {
-               tmpep = list_entry(pos, struct scif_endpt, list);
-               /*
-                * The local ep may have sent a disconnect and and been closed
-                * due to a message response time out. It may have been
-                * allocated again and formed a new connection so we want to
-                * check if the remote ep matches
-                */
-               if (((u64)tmpep == msg->payload[1]) &&
-                   ((u64)tmpep->remote_ep == msg->payload[0])) {
-                       list_del(pos);
-                       ep = tmpep;
-                       spin_lock(&ep->lock);
-                       break;
-               }
-       }
-
-       /*
-        * If the terminated end is not found then this side started closing
-        * before the other side sent the disconnect.  If so the ep will no
-        * longer be on the connected list.  Regardless the other side
-        * needs to be acked to let it know close is complete.
-        */
-       if (!ep) {
-               mutex_unlock(&scif_info.connlock);
-               goto discnct_ack;
-       }
-
-       ep->state = SCIFEP_DISCONNECTED;
-       list_add_tail(&ep->list, &scif_info.disconnected);
-
-       wake_up_interruptible(&ep->sendwq);
-       wake_up_interruptible(&ep->recvwq);
-       spin_unlock(&ep->lock);
-       mutex_unlock(&scif_info.connlock);
-
-discnct_ack:
-       msg->uop = SCIF_DISCNT_ACK;
-       scif_nodeqp_send(&scif_dev[msg->src.node], msg);
-}
-
-/**
- * scif_discnct_ack() - Respond to SCIF_DISCNT_ACK interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * Remote side has indicated it has not more references to local resources
- */
-void scif_discnt_ack(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
-
-       spin_lock(&ep->lock);
-       ep->state = SCIFEP_DISCONNECTED;
-       spin_unlock(&ep->lock);
-       complete(&ep->discon);
-}
-
-/**
- * scif_clientsend() - Respond to SCIF_CLIENT_SEND interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * Remote side is confirming send or receive interrupt handling is complete.
- */
-void scif_clientsend(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
-
-       spin_lock(&ep->lock);
-       if (SCIFEP_CONNECTED == ep->state)
-               wake_up_interruptible(&ep->recvwq);
-       spin_unlock(&ep->lock);
-}
-
-/**
- * scif_clientrcvd() - Respond to SCIF_CLIENT_RCVD interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * Remote side is confirming send or receive interrupt handling is complete.
- */
-void scif_clientrcvd(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
-
-       spin_lock(&ep->lock);
-       if (SCIFEP_CONNECTED == ep->state)
-               wake_up_interruptible(&ep->sendwq);
-       spin_unlock(&ep->lock);
-}
diff --git a/drivers/misc/mic/scif/scif_epd.h b/drivers/misc/mic/scif/scif_epd.h
deleted file mode 100644 (file)
index 0b9dfe1..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#ifndef SCIF_EPD_H
-#define SCIF_EPD_H
-
-#include <linux/delay.h>
-#include <linux/scif.h>
-#include <linux/scif_ioctl.h>
-
-#define SCIF_EPLOCK_HELD true
-
-enum scif_epd_state {
-       SCIFEP_UNBOUND,
-       SCIFEP_BOUND,
-       SCIFEP_LISTENING,
-       SCIFEP_CONNECTED,
-       SCIFEP_CONNECTING,
-       SCIFEP_MAPPING,
-       SCIFEP_CLOSING,
-       SCIFEP_CLLISTEN,
-       SCIFEP_DISCONNECTED,
-       SCIFEP_ZOMBIE
-};
-
-/*
- * struct scif_conreq - Data structure added to the connection list.
- *
- * @msg: connection request message received
- * @list: link to list of connection requests
- */
-struct scif_conreq {
-       struct scifmsg msg;
-       struct list_head list;
-};
-
-/* Size of the RB for the Endpoint QP */
-#define SCIF_ENDPT_QP_SIZE 0x1000
-
-/*
- * scif_endpt_qp_info - SCIF endpoint queue pair
- *
- * @qp - Qpair for this endpoint
- * @qp_offset - DMA address of the QP
- * @gnt_pld - Payload in a SCIF_CNCT_GNT message containing the
- * physical address of the remote_qp.
- */
-struct scif_endpt_qp_info {
-       struct scif_qp *qp;
-       dma_addr_t qp_offset;
-       dma_addr_t gnt_pld;
-};
-
-/*
- * struct scif_endpt - The SCIF endpoint data structure
- *
- * @state: end point state
- * @lock: lock synchronizing access to endpoint fields like state etc
- * @port: self port information
- * @peer: peer port information
- * @backlog: maximum pending connection requests
- * @qp_info: Endpoint QP information for SCIF messaging
- * @remote_dev: scifdev used by this endpt to communicate with remote node.
- * @remote_ep: remote endpoint
- * @conreqcnt: Keep track of number of connection requests.
- * @files: Open file information used to match the id passed in with
- *         the flush routine.
- * @conlist: list of connection requests
- * @conwq: waitqueue for connection processing
- * @discon: completion used during disconnection
- * @sendwq: waitqueue used during sending messages
- * @recvwq: waitqueue used during message receipt
- * @sendlock: Synchronize ordering of messages sent
- * @recvlock: Synchronize ordering of messages received
- * @list: link to list of various endpoints like connected, listening etc
- * @li_accept: pending ACCEPTREG
- * @acceptcnt: pending ACCEPTREG cnt
- * @liacceptlist: link to listen accept
- * @miacceptlist: link to uaccept
- * @listenep: associated listen ep
- * @conn_work: Non blocking connect work
- * @conn_port: Connection port
- * @conn_err: Errors during connection
- * @conn_async_state: Async connection
- * @conn_pend_wq: Used by poll while waiting for incoming connections
- * @conn_list: List of async connection requests
- * @rma_info: Information for triggering SCIF RMA and DMA operations
- * @mmu_list: link to list of MMU notifier cleanup work
- * @anon: anonymous file for use in kernel mode scif poll
- */
-struct scif_endpt {
-       enum scif_epd_state state;
-       spinlock_t lock;
-       struct scif_port_id port;
-       struct scif_port_id peer;
-       int backlog;
-       struct scif_endpt_qp_info qp_info;
-       struct scif_dev *remote_dev;
-       u64 remote_ep;
-       int conreqcnt;
-       struct files_struct *files;
-       struct list_head conlist;
-       wait_queue_head_t conwq;
-       struct completion discon;
-       wait_queue_head_t sendwq;
-       wait_queue_head_t recvwq;
-       struct mutex sendlock;
-       struct mutex recvlock;
-       struct list_head list;
-       struct list_head li_accept;
-       int acceptcnt;
-       struct list_head liacceptlist;
-       struct list_head miacceptlist;
-       struct scif_endpt *listenep;
-       struct scif_port_id conn_port;
-       int conn_err;
-       int conn_async_state;
-       wait_queue_head_t conn_pend_wq;
-       struct list_head conn_list;
-       struct scif_endpt_rma_info rma_info;
-       struct list_head mmu_list;
-       struct file *anon;
-};
-
-static inline int scifdev_alive(struct scif_endpt *ep)
-{
-       return _scifdev_alive(ep->remote_dev);
-}
-
-/*
- * scif_verify_epd:
- * ep: SCIF endpoint
- *
- * Checks several generic error conditions and returns the
- * appropriate error.
- */
-static inline int scif_verify_epd(struct scif_endpt *ep)
-{
-       if (ep->state == SCIFEP_DISCONNECTED)
-               return -ECONNRESET;
-
-       if (ep->state != SCIFEP_CONNECTED)
-               return -ENOTCONN;
-
-       if (!scifdev_alive(ep))
-               return -ENODEV;
-
-       return 0;
-}
-
-static inline int scif_anon_inode_getfile(scif_epd_t epd)
-{
-       epd->anon = anon_inode_getfile("scif", &scif_anon_fops, NULL, 0);
-
-       return PTR_ERR_OR_ZERO(epd->anon);
-}
-
-static inline void scif_anon_inode_fput(scif_epd_t epd)
-{
-       if (epd->anon) {
-               fput(epd->anon);
-               epd->anon = NULL;
-       }
-}
-
-void scif_cleanup_zombie_epd(void);
-void scif_teardown_ep(void *endpt);
-void scif_cleanup_ep_qp(struct scif_endpt *ep);
-void scif_add_epd_to_zombie_list(struct scif_endpt *ep, bool eplock_held);
-void scif_get_node_info(void);
-void scif_send_acks(struct scif_dev *dev);
-void scif_conn_handler(struct work_struct *work);
-int scif_rsrv_port(u16 port);
-void scif_get_port(u16 port);
-int scif_get_new_port(void);
-void scif_put_port(u16 port);
-int scif_user_send(scif_epd_t epd, void __user *msg, int len, int flags);
-int scif_user_recv(scif_epd_t epd, void __user *msg, int len, int flags);
-void scif_cnctreq(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_cnctgnt(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_cnctgnt_ack(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_cnctgnt_nack(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_cnctrej(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_discnct(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_discnt_ack(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_clientsend(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_clientrcvd(struct scif_dev *scifdev, struct scifmsg *msg);
-int __scif_connect(scif_epd_t epd, struct scif_port_id *dst, bool non_block);
-int __scif_flush(scif_epd_t epd);
-int scif_mmap(struct vm_area_struct *vma, scif_epd_t epd);
-__poll_t __scif_pollfd(struct file *f, poll_table *wait,
-                          struct scif_endpt *ep);
-int __scif_pin_pages(void *addr, size_t len, int *out_prot,
-                    int map_flags, scif_pinned_pages_t *pages);
-#endif /* SCIF_EPD_H */
diff --git a/drivers/misc/mic/scif/scif_fd.c b/drivers/misc/mic/scif/scif_fd.c
deleted file mode 100644 (file)
index 3f08646..0000000
+++ /dev/null
@@ -1,462 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#include "scif_main.h"
-
-static int scif_fdopen(struct inode *inode, struct file *f)
-{
-       struct scif_endpt *priv = scif_open();
-
-       if (!priv)
-               return -ENOMEM;
-       f->private_data = priv;
-       return 0;
-}
-
-static int scif_fdclose(struct inode *inode, struct file *f)
-{
-       struct scif_endpt *priv = f->private_data;
-
-       return scif_close(priv);
-}
-
-static int scif_fdmmap(struct file *f, struct vm_area_struct *vma)
-{
-       struct scif_endpt *priv = f->private_data;
-
-       return scif_mmap(vma, priv);
-}
-
-static __poll_t scif_fdpoll(struct file *f, poll_table *wait)
-{
-       struct scif_endpt *priv = f->private_data;
-
-       return __scif_pollfd(f, wait, priv);
-}
-
-static int scif_fdflush(struct file *f, fl_owner_t id)
-{
-       struct scif_endpt *ep = f->private_data;
-
-       spin_lock(&ep->lock);
-       /*
-        * The listening endpoint stashes the open file information before
-        * waiting for incoming connections. The release callback would never be
-        * called if the application closed the endpoint, while waiting for
-        * incoming connections from a separate thread since the file descriptor
-        * reference count is bumped up in the accept IOCTL. Call the flush
-        * routine if the id matches the endpoint open file information so that
-        * the listening endpoint can be woken up and the fd released.
-        */
-       if (ep->files == id)
-               __scif_flush(ep);
-       spin_unlock(&ep->lock);
-       return 0;
-}
-
-static __always_inline void scif_err_debug(int err, const char *str)
-{
-       /*
-        * ENOTCONN is a common uninteresting error which is
-        * flooding debug messages to the console unnecessarily.
-        */
-       if (err < 0 && err != -ENOTCONN)
-               dev_dbg(scif_info.mdev.this_device, "%s err %d\n", str, err);
-}
-
-static long scif_fdioctl(struct file *f, unsigned int cmd, unsigned long arg)
-{
-       struct scif_endpt *priv = f->private_data;
-       void __user *argp = (void __user *)arg;
-       int err = 0;
-       struct scifioctl_msg request;
-       bool non_block = false;
-
-       non_block = !!(f->f_flags & O_NONBLOCK);
-
-       switch (cmd) {
-       case SCIF_BIND:
-       {
-               int pn;
-
-               if (copy_from_user(&pn, argp, sizeof(pn)))
-                       return -EFAULT;
-
-               pn = scif_bind(priv, pn);
-               if (pn < 0)
-                       return pn;
-
-               if (copy_to_user(argp, &pn, sizeof(pn)))
-                       return -EFAULT;
-
-               return 0;
-       }
-       case SCIF_LISTEN:
-               return scif_listen(priv, arg);
-       case SCIF_CONNECT:
-       {
-               struct scifioctl_connect req;
-               struct scif_endpt *ep = (struct scif_endpt *)priv;
-
-               if (copy_from_user(&req, argp, sizeof(req)))
-                       return -EFAULT;
-
-               err = __scif_connect(priv, &req.peer, non_block);
-               if (err < 0)
-                       return err;
-
-               req.self.node = ep->port.node;
-               req.self.port = ep->port.port;
-
-               if (copy_to_user(argp, &req, sizeof(req)))
-                       return -EFAULT;
-
-               return 0;
-       }
-       /*
-        * Accept is done in two halves.  The request ioctl does the basic
-        * functionality of accepting the request and returning the information
-        * about it including the internal ID of the end point.  The register
-        * is done with the internal ID on a new file descriptor opened by the
-        * requesting process.
-        */
-       case SCIF_ACCEPTREQ:
-       {
-               struct scifioctl_accept request;
-               scif_epd_t *ep = (scif_epd_t *)&request.endpt;
-
-               if (copy_from_user(&request, argp, sizeof(request)))
-                       return -EFAULT;
-
-               err = scif_accept(priv, &request.peer, ep, request.flags);
-               if (err < 0)
-                       return err;
-
-               if (copy_to_user(argp, &request, sizeof(request))) {
-                       scif_close(*ep);
-                       return -EFAULT;
-               }
-               /*
-                * Add to the list of user mode eps where the second half
-                * of the accept is not yet completed.
-                */
-               mutex_lock(&scif_info.eplock);
-               list_add_tail(&((*ep)->miacceptlist), &scif_info.uaccept);
-               list_add_tail(&((*ep)->liacceptlist), &priv->li_accept);
-               (*ep)->listenep = priv;
-               priv->acceptcnt++;
-               mutex_unlock(&scif_info.eplock);
-
-               return 0;
-       }
-       case SCIF_ACCEPTREG:
-       {
-               struct scif_endpt *priv = f->private_data;
-               struct scif_endpt *newep;
-               struct scif_endpt *lisep;
-               struct scif_endpt *fep = NULL;
-               struct scif_endpt *tmpep;
-               struct list_head *pos, *tmpq;
-
-               /* Finally replace the pointer to the accepted endpoint */
-               if (copy_from_user(&newep, argp, sizeof(void *)))
-                       return -EFAULT;
-
-               /* Remove form the user accept queue */
-               mutex_lock(&scif_info.eplock);
-               list_for_each_safe(pos, tmpq, &scif_info.uaccept) {
-                       tmpep = list_entry(pos,
-                                          struct scif_endpt, miacceptlist);
-                       if (tmpep == newep) {
-                               list_del(pos);
-                               fep = tmpep;
-                               break;
-                       }
-               }
-
-               if (!fep) {
-                       mutex_unlock(&scif_info.eplock);
-                       return -ENOENT;
-               }
-
-               lisep = newep->listenep;
-               list_for_each_safe(pos, tmpq, &lisep->li_accept) {
-                       tmpep = list_entry(pos,
-                                          struct scif_endpt, liacceptlist);
-                       if (tmpep == newep) {
-                               list_del(pos);
-                               lisep->acceptcnt--;
-                               break;
-                       }
-               }
-
-               mutex_unlock(&scif_info.eplock);
-
-               /* Free the resources automatically created from the open. */
-               scif_anon_inode_fput(priv);
-               scif_teardown_ep(priv);
-               scif_add_epd_to_zombie_list(priv, !SCIF_EPLOCK_HELD);
-               f->private_data = newep;
-               return 0;
-       }
-       case SCIF_SEND:
-       {
-               struct scif_endpt *priv = f->private_data;
-
-               if (copy_from_user(&request, argp,
-                                  sizeof(struct scifioctl_msg))) {
-                       err = -EFAULT;
-                       goto send_err;
-               }
-               err = scif_user_send(priv, (void __user *)request.msg,
-                                    request.len, request.flags);
-               if (err < 0)
-                       goto send_err;
-               if (copy_to_user(&
-                                ((struct scifioctl_msg __user *)argp)->out_len,
-                                &err, sizeof(err))) {
-                       err = -EFAULT;
-                       goto send_err;
-               }
-               err = 0;
-send_err:
-               scif_err_debug(err, "scif_send");
-               return err;
-       }
-       case SCIF_RECV:
-       {
-               struct scif_endpt *priv = f->private_data;
-
-               if (copy_from_user(&request, argp,
-                                  sizeof(struct scifioctl_msg))) {
-                       err = -EFAULT;
-                       goto recv_err;
-               }
-
-               err = scif_user_recv(priv, (void __user *)request.msg,
-                                    request.len, request.flags);
-               if (err < 0)
-                       goto recv_err;
-
-               if (copy_to_user(&
-                                ((struct scifioctl_msg __user *)argp)->out_len,
-                       &err, sizeof(err))) {
-                       err = -EFAULT;
-                       goto recv_err;
-               }
-               err = 0;
-recv_err:
-               scif_err_debug(err, "scif_recv");
-               return err;
-       }
-       case SCIF_GET_NODEIDS:
-       {
-               struct scifioctl_node_ids node_ids;
-               int entries;
-               u16 *nodes;
-               void __user *unodes, *uself;
-               u16 self;
-
-               if (copy_from_user(&node_ids, argp, sizeof(node_ids))) {
-                       err = -EFAULT;
-                       goto getnodes_err2;
-               }
-
-               entries = min_t(int, scif_info.maxid, node_ids.len);
-               nodes = kmalloc_array(entries, sizeof(u16), GFP_KERNEL);
-               if (entries && !nodes) {
-                       err = -ENOMEM;
-                       goto getnodes_err2;
-               }
-               node_ids.len = scif_get_node_ids(nodes, entries, &self);
-
-               unodes = (void __user *)node_ids.nodes;
-               if (copy_to_user(unodes, nodes, sizeof(u16) * entries)) {
-                       err = -EFAULT;
-                       goto getnodes_err1;
-               }
-
-               uself = (void __user *)node_ids.self;
-               if (copy_to_user(uself, &self, sizeof(u16))) {
-                       err = -EFAULT;
-                       goto getnodes_err1;
-               }
-
-               if (copy_to_user(argp, &node_ids, sizeof(node_ids))) {
-                       err = -EFAULT;
-                       goto getnodes_err1;
-               }
-getnodes_err1:
-               kfree(nodes);
-getnodes_err2:
-               return err;
-       }
-       case SCIF_REG:
-       {
-               struct scif_endpt *priv = f->private_data;
-               struct scifioctl_reg reg;
-               off_t ret;
-
-               if (copy_from_user(&reg, argp, sizeof(reg))) {
-                       err = -EFAULT;
-                       goto reg_err;
-               }
-               if (reg.flags & SCIF_MAP_KERNEL) {
-                       err = -EINVAL;
-                       goto reg_err;
-               }
-               ret = scif_register(priv, (void *)reg.addr, reg.len,
-                                   reg.offset, reg.prot, reg.flags);
-               if (ret < 0) {
-                       err = (int)ret;
-                       goto reg_err;
-               }
-
-               if (copy_to_user(&((struct scifioctl_reg __user *)argp)
-                                ->out_offset, &ret, sizeof(reg.out_offset))) {
-                       err = -EFAULT;
-                       goto reg_err;
-               }
-               err = 0;
-reg_err:
-               scif_err_debug(err, "scif_register");
-               return err;
-       }
-       case SCIF_UNREG:
-       {
-               struct scif_endpt *priv = f->private_data;
-               struct scifioctl_unreg unreg;
-
-               if (copy_from_user(&unreg, argp, sizeof(unreg))) {
-                       err = -EFAULT;
-                       goto unreg_err;
-               }
-               err = scif_unregister(priv, unreg.offset, unreg.len);
-unreg_err:
-               scif_err_debug(err, "scif_unregister");
-               return err;
-       }
-       case SCIF_READFROM:
-       {
-               struct scif_endpt *priv = f->private_data;
-               struct scifioctl_copy copy;
-
-               if (copy_from_user(&copy, argp, sizeof(copy))) {
-                       err = -EFAULT;
-                       goto readfrom_err;
-               }
-               err = scif_readfrom(priv, copy.loffset, copy.len, copy.roffset,
-                                   copy.flags);
-readfrom_err:
-               scif_err_debug(err, "scif_readfrom");
-               return err;
-       }
-       case SCIF_WRITETO:
-       {
-               struct scif_endpt *priv = f->private_data;
-               struct scifioctl_copy copy;
-
-               if (copy_from_user(&copy, argp, sizeof(copy))) {
-                       err = -EFAULT;
-                       goto writeto_err;
-               }
-               err = scif_writeto(priv, copy.loffset, copy.len, copy.roffset,
-                                  copy.flags);
-writeto_err:
-               scif_err_debug(err, "scif_writeto");
-               return err;
-       }
-       case SCIF_VREADFROM:
-       {
-               struct scif_endpt *priv = f->private_data;
-               struct scifioctl_copy copy;
-
-               if (copy_from_user(&copy, argp, sizeof(copy))) {
-                       err = -EFAULT;
-                       goto vreadfrom_err;
-               }
-               err = scif_vreadfrom(priv, (void __force *)copy.addr, copy.len,
-                                    copy.roffset, copy.flags);
-vreadfrom_err:
-               scif_err_debug(err, "scif_vreadfrom");
-               return err;
-       }
-       case SCIF_VWRITETO:
-       {
-               struct scif_endpt *priv = f->private_data;
-               struct scifioctl_copy copy;
-
-               if (copy_from_user(&copy, argp, sizeof(copy))) {
-                       err = -EFAULT;
-                       goto vwriteto_err;
-               }
-               err = scif_vwriteto(priv, (void __force *)copy.addr, copy.len,
-                                   copy.roffset, copy.flags);
-vwriteto_err:
-               scif_err_debug(err, "scif_vwriteto");
-               return err;
-       }
-       case SCIF_FENCE_MARK:
-       {
-               struct scif_endpt *priv = f->private_data;
-               struct scifioctl_fence_mark mark;
-               int tmp_mark = 0;
-
-               if (copy_from_user(&mark, argp, sizeof(mark))) {
-                       err = -EFAULT;
-                       goto fence_mark_err;
-               }
-               err = scif_fence_mark(priv, mark.flags, &tmp_mark);
-               if (err)
-                       goto fence_mark_err;
-               if (copy_to_user((void __user *)mark.mark, &tmp_mark,
-                                sizeof(tmp_mark))) {
-                       err = -EFAULT;
-                       goto fence_mark_err;
-               }
-fence_mark_err:
-               scif_err_debug(err, "scif_fence_mark");
-               return err;
-       }
-       case SCIF_FENCE_WAIT:
-       {
-               struct scif_endpt *priv = f->private_data;
-
-               err = scif_fence_wait(priv, arg);
-               scif_err_debug(err, "scif_fence_wait");
-               return err;
-       }
-       case SCIF_FENCE_SIGNAL:
-       {
-               struct scif_endpt *priv = f->private_data;
-               struct scifioctl_fence_signal signal;
-
-               if (copy_from_user(&signal, argp, sizeof(signal))) {
-                       err = -EFAULT;
-                       goto fence_signal_err;
-               }
-
-               err = scif_fence_signal(priv, signal.loff, signal.lval,
-                                       signal.roff, signal.rval, signal.flags);
-fence_signal_err:
-               scif_err_debug(err, "scif_fence_signal");
-               return err;
-       }
-       }
-       return -EINVAL;
-}
-
-const struct file_operations scif_fops = {
-       .open = scif_fdopen,
-       .release = scif_fdclose,
-       .unlocked_ioctl = scif_fdioctl,
-       .mmap = scif_fdmmap,
-       .poll = scif_fdpoll,
-       .flush = scif_fdflush,
-       .owner = THIS_MODULE,
-};
diff --git a/drivers/misc/mic/scif/scif_fence.c b/drivers/misc/mic/scif/scif_fence.c
deleted file mode 100644 (file)
index 4fedf61..0000000
+++ /dev/null
@@ -1,783 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-
-#include "scif_main.h"
-
-/**
- * scif_recv_mark: Handle SCIF_MARK request
- * @scifdev:   SCIF device
- * @msg:       Interrupt message
- *
- * The peer has requested a mark.
- */
-void scif_recv_mark(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
-       int mark = 0;
-       int err;
-
-       err = _scif_fence_mark(ep, &mark);
-       if (err)
-               msg->uop = SCIF_MARK_NACK;
-       else
-               msg->uop = SCIF_MARK_ACK;
-       msg->payload[0] = ep->remote_ep;
-       msg->payload[2] = mark;
-       scif_nodeqp_send(ep->remote_dev, msg);
-}
-
-/**
- * scif_recv_mark_resp: Handle SCIF_MARK_(N)ACK messages.
- * @scifdev:   SCIF device
- * @msg:       Interrupt message
- *
- * The peer has responded to a SCIF_MARK message.
- */
-void scif_recv_mark_resp(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
-       struct scif_fence_info *fence_req =
-               (struct scif_fence_info *)msg->payload[1];
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       if (msg->uop == SCIF_MARK_ACK) {
-               fence_req->state = OP_COMPLETED;
-               fence_req->dma_mark = (int)msg->payload[2];
-       } else {
-               fence_req->state = OP_FAILED;
-       }
-       mutex_unlock(&ep->rma_info.rma_lock);
-       complete(&fence_req->comp);
-}
-
-/**
- * scif_recv_wait: Handle SCIF_WAIT request
- * @scifdev:   SCIF device
- * @msg:       Interrupt message
- *
- * The peer has requested waiting on a fence.
- */
-void scif_recv_wait(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
-       struct scif_remote_fence_info *fence;
-
-       /*
-        * Allocate structure for remote fence information and
-        * send a NACK if the allocation failed. The peer will
-        * return ENOMEM upon receiving a NACK.
-        */
-       fence = kmalloc(sizeof(*fence), GFP_KERNEL);
-       if (!fence) {
-               msg->payload[0] = ep->remote_ep;
-               msg->uop = SCIF_WAIT_NACK;
-               scif_nodeqp_send(ep->remote_dev, msg);
-               return;
-       }
-
-       /* Prepare the fence request */
-       memcpy(&fence->msg, msg, sizeof(struct scifmsg));
-       INIT_LIST_HEAD(&fence->list);
-
-       /* Insert to the global remote fence request list */
-       mutex_lock(&scif_info.fencelock);
-       atomic_inc(&ep->rma_info.fence_refcount);
-       list_add_tail(&fence->list, &scif_info.fence);
-       mutex_unlock(&scif_info.fencelock);
-
-       schedule_work(&scif_info.misc_work);
-}
-
-/**
- * scif_recv_wait_resp: Handle SCIF_WAIT_(N)ACK messages.
- * @scifdev:   SCIF device
- * @msg:       Interrupt message
- *
- * The peer has responded to a SCIF_WAIT message.
- */
-void scif_recv_wait_resp(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
-       struct scif_fence_info *fence_req =
-               (struct scif_fence_info *)msg->payload[1];
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       if (msg->uop == SCIF_WAIT_ACK)
-               fence_req->state = OP_COMPLETED;
-       else
-               fence_req->state = OP_FAILED;
-       mutex_unlock(&ep->rma_info.rma_lock);
-       complete(&fence_req->comp);
-}
-
-/**
- * scif_recv_sig_local: Handle SCIF_SIG_LOCAL request
- * @scifdev:   SCIF device
- * @msg:       Interrupt message
- *
- * The peer has requested a signal on a local offset.
- */
-void scif_recv_sig_local(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
-       int err;
-
-       err = scif_prog_signal(ep, msg->payload[1], msg->payload[2],
-                              SCIF_WINDOW_SELF);
-       if (err)
-               msg->uop = SCIF_SIG_NACK;
-       else
-               msg->uop = SCIF_SIG_ACK;
-       msg->payload[0] = ep->remote_ep;
-       scif_nodeqp_send(ep->remote_dev, msg);
-}
-
-/**
- * scif_recv_sig_remote: Handle SCIF_SIGNAL_REMOTE request
- * @scifdev:   SCIF device
- * @msg:       Interrupt message
- *
- * The peer has requested a signal on a remote offset.
- */
-void scif_recv_sig_remote(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
-       int err;
-
-       err = scif_prog_signal(ep, msg->payload[1], msg->payload[2],
-                              SCIF_WINDOW_PEER);
-       if (err)
-               msg->uop = SCIF_SIG_NACK;
-       else
-               msg->uop = SCIF_SIG_ACK;
-       msg->payload[0] = ep->remote_ep;
-       scif_nodeqp_send(ep->remote_dev, msg);
-}
-
-/**
- * scif_recv_sig_resp: Handle SCIF_SIG_(N)ACK messages.
- * @scifdev:   SCIF device
- * @msg:       Interrupt message
- *
- * The peer has responded to a signal request.
- */
-void scif_recv_sig_resp(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
-       struct scif_fence_info *fence_req =
-               (struct scif_fence_info *)msg->payload[3];
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       if (msg->uop == SCIF_SIG_ACK)
-               fence_req->state = OP_COMPLETED;
-       else
-               fence_req->state = OP_FAILED;
-       mutex_unlock(&ep->rma_info.rma_lock);
-       complete(&fence_req->comp);
-}
-
-static inline void *scif_get_local_va(off_t off, struct scif_window *window)
-{
-       struct page **pages = window->pinned_pages->pages;
-       int page_nr = (off - window->offset) >> PAGE_SHIFT;
-       off_t page_off = off & ~PAGE_MASK;
-
-       return page_address(pages[page_nr]) + page_off;
-}
-
-static void scif_prog_signal_cb(void *arg)
-{
-       struct scif_cb_arg *cb_arg = arg;
-
-       dma_pool_free(cb_arg->ep->remote_dev->signal_pool, cb_arg->status,
-                     cb_arg->src_dma_addr);
-       kfree(cb_arg);
-}
-
-static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       struct dma_chan *chan = ep->rma_info.dma_chan;
-       struct dma_device *ddev = chan->device;
-       bool x100 = !is_dma_copy_aligned(chan->device, 1, 1, 1);
-       struct dma_async_tx_descriptor *tx;
-       struct scif_status *status = NULL;
-       struct scif_cb_arg *cb_arg = NULL;
-       dma_addr_t src;
-       dma_cookie_t cookie;
-       int err;
-
-       tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, DMA_PREP_FENCE);
-       if (!tx) {
-               err = -ENOMEM;
-               dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               goto alloc_fail;
-       }
-       cookie = tx->tx_submit(tx);
-       if (dma_submit_error(cookie)) {
-               err = (int)cookie;
-               dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               goto alloc_fail;
-       }
-       dma_async_issue_pending(chan);
-       if (x100) {
-               /*
-                * For X100 use the status descriptor to write the value to
-                * the destination.
-                */
-               tx = ddev->device_prep_dma_imm_data(chan, dst, val, 0);
-       } else {
-               status = dma_pool_alloc(ep->remote_dev->signal_pool, GFP_KERNEL,
-                                       &src);
-               if (!status) {
-                       err = -ENOMEM;
-                       dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
-                               __func__, __LINE__, err);
-                       goto alloc_fail;
-               }
-               status->val = val;
-               status->src_dma_addr = src;
-               status->ep = ep;
-               src += offsetof(struct scif_status, val);
-               tx = ddev->device_prep_dma_memcpy(chan, dst, src, sizeof(val),
-                                                 DMA_PREP_INTERRUPT);
-       }
-       if (!tx) {
-               err = -ENOMEM;
-               dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               goto dma_fail;
-       }
-       if (!x100) {
-               cb_arg = kmalloc(sizeof(*cb_arg), GFP_KERNEL);
-               if (!cb_arg) {
-                       err = -ENOMEM;
-                       goto dma_fail;
-               }
-               cb_arg->src_dma_addr = src;
-               cb_arg->status = status;
-               cb_arg->ep = ep;
-               tx->callback = scif_prog_signal_cb;
-               tx->callback_param = cb_arg;
-       }
-       cookie = tx->tx_submit(tx);
-       if (dma_submit_error(cookie)) {
-               err = -EIO;
-               dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               goto dma_fail;
-       }
-       dma_async_issue_pending(chan);
-       return 0;
-dma_fail:
-       if (!x100) {
-               dma_pool_free(ep->remote_dev->signal_pool, status,
-                             src - offsetof(struct scif_status, val));
-               kfree(cb_arg);
-       }
-alloc_fail:
-       return err;
-}
-
-/**
- * scif_prog_signal:
- * @epd: Endpoint Descriptor
- * @offset: registered address to write @val to
- * @val: Value to be written at @offset
- * @type: Type of the window.
- *
- * Arrange to write a value to the registered offset after ensuring that the
- * offset provided is indeed valid.
- */
-int scif_prog_signal(scif_epd_t epd, off_t offset, u64 val,
-                    enum scif_window_type type)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       struct scif_window *window = NULL;
-       struct scif_rma_req req;
-       dma_addr_t dst_dma_addr;
-       int err;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       req.out_window = &window;
-       req.offset = offset;
-       req.nr_bytes = sizeof(u64);
-       req.prot = SCIF_PROT_WRITE;
-       req.type = SCIF_WINDOW_SINGLE;
-       if (type == SCIF_WINDOW_SELF)
-               req.head = &ep->rma_info.reg_list;
-       else
-               req.head = &ep->rma_info.remote_reg_list;
-       /* Does a valid window exist? */
-       err = scif_query_window(&req);
-       if (err) {
-               dev_err(scif_info.mdev.this_device,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-               goto unlock_ret;
-       }
-
-       if (scif_is_mgmt_node() && scifdev_self(ep->remote_dev)) {
-               u64 *dst_virt;
-
-               if (type == SCIF_WINDOW_SELF)
-                       dst_virt = scif_get_local_va(offset, window);
-               else
-                       dst_virt =
-                       scif_get_local_va(offset, (struct scif_window *)
-                                         window->peer_window);
-               *dst_virt = val;
-       } else {
-               dst_dma_addr = __scif_off_to_dma_addr(window, offset);
-               err = _scif_prog_signal(epd, dst_dma_addr, val);
-       }
-unlock_ret:
-       mutex_unlock(&ep->rma_info.rma_lock);
-       return err;
-}
-
-static int _scif_fence_wait(scif_epd_t epd, int mark)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       dma_cookie_t cookie = mark & ~SCIF_REMOTE_FENCE;
-       int err;
-
-       /* Wait for DMA callback in scif_fence_mark_cb(..) */
-       err = wait_event_interruptible_timeout(ep->rma_info.markwq,
-                                              dma_async_is_tx_complete(
-                                              ep->rma_info.dma_chan,
-                                              cookie, NULL, NULL) ==
-                                              DMA_COMPLETE,
-                                              SCIF_NODE_ALIVE_TIMEOUT);
-       if (!err)
-               err = -ETIMEDOUT;
-       else if (err > 0)
-               err = 0;
-       return err;
-}
-
-/**
- * scif_rma_handle_remote_fences:
- *
- * This routine services remote fence requests.
- */
-void scif_rma_handle_remote_fences(void)
-{
-       struct list_head *item, *tmp;
-       struct scif_remote_fence_info *fence;
-       struct scif_endpt *ep;
-       int mark, err;
-
-       might_sleep();
-       mutex_lock(&scif_info.fencelock);
-       list_for_each_safe(item, tmp, &scif_info.fence) {
-               fence = list_entry(item, struct scif_remote_fence_info,
-                                  list);
-               /* Remove fence from global list */
-               list_del(&fence->list);
-
-               /* Initiate the fence operation */
-               ep = (struct scif_endpt *)fence->msg.payload[0];
-               mark = fence->msg.payload[2];
-               err = _scif_fence_wait(ep, mark);
-               if (err)
-                       fence->msg.uop = SCIF_WAIT_NACK;
-               else
-                       fence->msg.uop = SCIF_WAIT_ACK;
-               fence->msg.payload[0] = ep->remote_ep;
-               scif_nodeqp_send(ep->remote_dev, &fence->msg);
-               kfree(fence);
-               if (!atomic_sub_return(1, &ep->rma_info.fence_refcount))
-                       schedule_work(&scif_info.misc_work);
-       }
-       mutex_unlock(&scif_info.fencelock);
-}
-
-static int _scif_send_fence(scif_epd_t epd, int uop, int mark, int *out_mark)
-{
-       int err;
-       struct scifmsg msg;
-       struct scif_fence_info *fence_req;
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-
-       fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL);
-       if (!fence_req) {
-               err = -ENOMEM;
-               goto error;
-       }
-
-       fence_req->state = OP_IN_PROGRESS;
-       init_completion(&fence_req->comp);
-
-       msg.src = ep->port;
-       msg.uop = uop;
-       msg.payload[0] = ep->remote_ep;
-       msg.payload[1] = (u64)fence_req;
-       if (uop == SCIF_WAIT)
-               msg.payload[2] = mark;
-       spin_lock(&ep->lock);
-       if (ep->state == SCIFEP_CONNECTED)
-               err = scif_nodeqp_send(ep->remote_dev, &msg);
-       else
-               err = -ENOTCONN;
-       spin_unlock(&ep->lock);
-       if (err)
-               goto error_free;
-retry:
-       /* Wait for a SCIF_WAIT_(N)ACK message */
-       err = wait_for_completion_timeout(&fence_req->comp,
-                                         SCIF_NODE_ALIVE_TIMEOUT);
-       if (!err && scifdev_alive(ep))
-               goto retry;
-       if (!err)
-               err = -ENODEV;
-       if (err > 0)
-               err = 0;
-       mutex_lock(&ep->rma_info.rma_lock);
-       if (err < 0) {
-               if (fence_req->state == OP_IN_PROGRESS)
-                       fence_req->state = OP_FAILED;
-       }
-       if (fence_req->state == OP_FAILED && !err)
-               err = -ENOMEM;
-       if (uop == SCIF_MARK && fence_req->state == OP_COMPLETED)
-               *out_mark = SCIF_REMOTE_FENCE | fence_req->dma_mark;
-       mutex_unlock(&ep->rma_info.rma_lock);
-error_free:
-       kfree(fence_req);
-error:
-       return err;
-}
-
-/**
- * scif_send_fence_mark:
- * @epd: end point descriptor.
- * @out_mark: Output DMA mark reported by peer.
- *
- * Send a remote fence mark request.
- */
-static int scif_send_fence_mark(scif_epd_t epd, int *out_mark)
-{
-       return _scif_send_fence(epd, SCIF_MARK, 0, out_mark);
-}
-
-/**
- * scif_send_fence_wait:
- * @epd: end point descriptor.
- * @mark: DMA mark to wait for.
- *
- * Send a remote fence wait request.
- */
-static int scif_send_fence_wait(scif_epd_t epd, int mark)
-{
-       return _scif_send_fence(epd, SCIF_WAIT, mark, NULL);
-}
-
-static int _scif_send_fence_signal_wait(struct scif_endpt *ep,
-                                       struct scif_fence_info *fence_req)
-{
-       int err;
-
-retry:
-       /* Wait for a SCIF_SIG_(N)ACK message */
-       err = wait_for_completion_timeout(&fence_req->comp,
-                                         SCIF_NODE_ALIVE_TIMEOUT);
-       if (!err && scifdev_alive(ep))
-               goto retry;
-       if (!err)
-               err = -ENODEV;
-       if (err > 0)
-               err = 0;
-       if (err < 0) {
-               mutex_lock(&ep->rma_info.rma_lock);
-               if (fence_req->state == OP_IN_PROGRESS)
-                       fence_req->state = OP_FAILED;
-               mutex_unlock(&ep->rma_info.rma_lock);
-       }
-       if (fence_req->state == OP_FAILED && !err)
-               err = -ENXIO;
-       return err;
-}
-
-/**
- * scif_send_fence_signal:
- * @epd: endpoint descriptor
- * @loff: local offset
- * @lval: local value to write to loffset
- * @roff: remote offset
- * @rval: remote value to write to roffset
- * @flags: flags
- *
- * Sends a remote fence signal request
- */
-static int scif_send_fence_signal(scif_epd_t epd, off_t roff, u64 rval,
-                                 off_t loff, u64 lval, int flags)
-{
-       int err = 0;
-       struct scifmsg msg;
-       struct scif_fence_info *fence_req;
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-
-       fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL);
-       if (!fence_req) {
-               err = -ENOMEM;
-               goto error;
-       }
-
-       fence_req->state = OP_IN_PROGRESS;
-       init_completion(&fence_req->comp);
-       msg.src = ep->port;
-       if (flags & SCIF_SIGNAL_LOCAL) {
-               msg.uop = SCIF_SIG_LOCAL;
-               msg.payload[0] = ep->remote_ep;
-               msg.payload[1] = roff;
-               msg.payload[2] = rval;
-               msg.payload[3] = (u64)fence_req;
-               spin_lock(&ep->lock);
-               if (ep->state == SCIFEP_CONNECTED)
-                       err = scif_nodeqp_send(ep->remote_dev, &msg);
-               else
-                       err = -ENOTCONN;
-               spin_unlock(&ep->lock);
-               if (err)
-                       goto error_free;
-               err = _scif_send_fence_signal_wait(ep, fence_req);
-               if (err)
-                       goto error_free;
-       }
-       fence_req->state = OP_IN_PROGRESS;
-
-       if (flags & SCIF_SIGNAL_REMOTE) {
-               msg.uop = SCIF_SIG_REMOTE;
-               msg.payload[0] = ep->remote_ep;
-               msg.payload[1] = loff;
-               msg.payload[2] = lval;
-               msg.payload[3] = (u64)fence_req;
-               spin_lock(&ep->lock);
-               if (ep->state == SCIFEP_CONNECTED)
-                       err = scif_nodeqp_send(ep->remote_dev, &msg);
-               else
-                       err = -ENOTCONN;
-               spin_unlock(&ep->lock);
-               if (err)
-                       goto error_free;
-               err = _scif_send_fence_signal_wait(ep, fence_req);
-       }
-error_free:
-       kfree(fence_req);
-error:
-       return err;
-}
-
-static void scif_fence_mark_cb(void *arg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)arg;
-
-       wake_up_interruptible(&ep->rma_info.markwq);
-       atomic_dec(&ep->rma_info.fence_refcount);
-}
-
-/**
- * _scif_fence_mark:
- * @epd: endpoint descriptor
- * @mark: DMA mark to set-up
- *
- * Set up a mark for this endpoint and return the value of the mark.
- */
-int _scif_fence_mark(scif_epd_t epd, int *mark)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       struct dma_chan *chan = ep->rma_info.dma_chan;
-       struct dma_device *ddev = chan->device;
-       struct dma_async_tx_descriptor *tx;
-       dma_cookie_t cookie;
-       int err;
-
-       tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, DMA_PREP_FENCE);
-       if (!tx) {
-               err = -ENOMEM;
-               dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               return err;
-       }
-       cookie = tx->tx_submit(tx);
-       if (dma_submit_error(cookie)) {
-               err = (int)cookie;
-               dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               return err;
-       }
-       dma_async_issue_pending(chan);
-       tx = ddev->device_prep_dma_interrupt(chan, DMA_PREP_INTERRUPT);
-       if (!tx) {
-               err = -ENOMEM;
-               dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               return err;
-       }
-       tx->callback = scif_fence_mark_cb;
-       tx->callback_param = ep;
-       *mark = cookie = tx->tx_submit(tx);
-       if (dma_submit_error(cookie)) {
-               err = (int)cookie;
-               dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               return err;
-       }
-       atomic_inc(&ep->rma_info.fence_refcount);
-       dma_async_issue_pending(chan);
-       return 0;
-}
-
-#define SCIF_LOOPB_MAGIC_MARK 0xdead
-
-int scif_fence_mark(scif_epd_t epd, int flags, int *mark)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       int err = 0;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI fence_mark: ep %p flags 0x%x mark 0x%x\n",
-               ep, flags, *mark);
-       err = scif_verify_epd(ep);
-       if (err)
-               return err;
-
-       /* Invalid flags? */
-       if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER))
-               return -EINVAL;
-
-       /* At least one of init self or peer RMA should be set */
-       if (!(flags & (SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER)))
-               return -EINVAL;
-
-       /* Exactly one of init self or peer RMA should be set but not both */
-       if ((flags & SCIF_FENCE_INIT_SELF) && (flags & SCIF_FENCE_INIT_PEER))
-               return -EINVAL;
-
-       /*
-        * Management node loopback does not need to use DMA.
-        * Return a valid mark to be symmetric.
-        */
-       if (scifdev_self(ep->remote_dev) && scif_is_mgmt_node()) {
-               *mark = SCIF_LOOPB_MAGIC_MARK;
-               return 0;
-       }
-
-       if (flags & SCIF_FENCE_INIT_SELF)
-               err = _scif_fence_mark(epd, mark);
-       else
-               err = scif_send_fence_mark(ep, mark);
-
-       if (err)
-               dev_err(scif_info.mdev.this_device,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI fence_mark: ep %p flags 0x%x mark 0x%x err %d\n",
-               ep, flags, *mark, err);
-       return err;
-}
-EXPORT_SYMBOL_GPL(scif_fence_mark);
-
-int scif_fence_wait(scif_epd_t epd, int mark)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       int err = 0;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI fence_wait: ep %p mark 0x%x\n",
-               ep, mark);
-       err = scif_verify_epd(ep);
-       if (err)
-               return err;
-       /*
-        * Management node loopback does not need to use DMA.
-        * The only valid mark provided is 0 so simply
-        * return success if the mark is valid.
-        */
-       if (scifdev_self(ep->remote_dev) && scif_is_mgmt_node()) {
-               if (mark == SCIF_LOOPB_MAGIC_MARK)
-                       return 0;
-               else
-                       return -EINVAL;
-       }
-       if (mark & SCIF_REMOTE_FENCE)
-               err = scif_send_fence_wait(epd, mark);
-       else
-               err = _scif_fence_wait(epd, mark);
-       if (err < 0)
-               dev_err(scif_info.mdev.this_device,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-       return err;
-}
-EXPORT_SYMBOL_GPL(scif_fence_wait);
-
-int scif_fence_signal(scif_epd_t epd, off_t loff, u64 lval,
-                     off_t roff, u64 rval, int flags)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       int err = 0;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI fence_signal: ep %p loff 0x%lx lval 0x%llx roff 0x%lx rval 0x%llx flags 0x%x\n",
-               ep, loff, lval, roff, rval, flags);
-       err = scif_verify_epd(ep);
-       if (err)
-               return err;
-
-       /* Invalid flags? */
-       if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER |
-                       SCIF_SIGNAL_LOCAL | SCIF_SIGNAL_REMOTE))
-               return -EINVAL;
-
-       /* At least one of init self or peer RMA should be set */
-       if (!(flags & (SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER)))
-               return -EINVAL;
-
-       /* Exactly one of init self or peer RMA should be set but not both */
-       if ((flags & SCIF_FENCE_INIT_SELF) && (flags & SCIF_FENCE_INIT_PEER))
-               return -EINVAL;
-
-       /* At least one of SCIF_SIGNAL_LOCAL or SCIF_SIGNAL_REMOTE required */
-       if (!(flags & (SCIF_SIGNAL_LOCAL | SCIF_SIGNAL_REMOTE)))
-               return -EINVAL;
-
-       /* Only Dword offsets allowed */
-       if ((flags & SCIF_SIGNAL_LOCAL) && (loff & (sizeof(u32) - 1)))
-               return -EINVAL;
-
-       /* Only Dword aligned offsets allowed */
-       if ((flags & SCIF_SIGNAL_REMOTE) && (roff & (sizeof(u32) - 1)))
-               return -EINVAL;
-
-       if (flags & SCIF_FENCE_INIT_PEER) {
-               err = scif_send_fence_signal(epd, roff, rval, loff,
-                                            lval, flags);
-       } else {
-               /* Local Signal in Local RAS */
-               if (flags & SCIF_SIGNAL_LOCAL) {
-                       err = scif_prog_signal(epd, loff, lval,
-                                              SCIF_WINDOW_SELF);
-                       if (err)
-                               goto error_ret;
-               }
-
-               /* Signal in Remote RAS */
-               if (flags & SCIF_SIGNAL_REMOTE)
-                       err = scif_prog_signal(epd, roff,
-                                              rval, SCIF_WINDOW_PEER);
-       }
-error_ret:
-       if (err)
-               dev_err(scif_info.mdev.this_device,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-       return err;
-}
-EXPORT_SYMBOL_GPL(scif_fence_signal);
diff --git a/drivers/misc/mic/scif/scif_main.c b/drivers/misc/mic/scif/scif_main.c
deleted file mode 100644 (file)
index e2278bf..0000000
+++ /dev/null
@@ -1,351 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#include <linux/module.h>
-#include <linux/idr.h>
-
-#include <linux/mic_common.h>
-#include "../common/mic_dev.h"
-#include "../bus/scif_bus.h"
-#include "scif_peer_bus.h"
-#include "scif_main.h"
-#include "scif_map.h"
-
-struct scif_info scif_info = {
-       .mdev = {
-               .minor = MISC_DYNAMIC_MINOR,
-               .name = "scif",
-               .fops = &scif_fops,
-       }
-};
-
-struct scif_dev *scif_dev;
-struct kmem_cache *unaligned_cache;
-static atomic_t g_loopb_cnt;
-
-/* Runs in the context of intr_wq */
-static void scif_intr_bh_handler(struct work_struct *work)
-{
-       struct scif_dev *scifdev =
-                       container_of(work, struct scif_dev, intr_bh);
-
-       if (scifdev_self(scifdev))
-               scif_loopb_msg_handler(scifdev, scifdev->qpairs);
-       else
-               scif_nodeqp_intrhandler(scifdev, scifdev->qpairs);
-}
-
-int scif_setup_intr_wq(struct scif_dev *scifdev)
-{
-       if (!scifdev->intr_wq) {
-               snprintf(scifdev->intr_wqname, sizeof(scifdev->intr_wqname),
-                        "SCIF INTR %d", scifdev->node);
-               scifdev->intr_wq =
-                       alloc_ordered_workqueue(scifdev->intr_wqname, 0);
-               if (!scifdev->intr_wq)
-                       return -ENOMEM;
-               INIT_WORK(&scifdev->intr_bh, scif_intr_bh_handler);
-       }
-       return 0;
-}
-
-void scif_destroy_intr_wq(struct scif_dev *scifdev)
-{
-       if (scifdev->intr_wq) {
-               destroy_workqueue(scifdev->intr_wq);
-               scifdev->intr_wq = NULL;
-       }
-}
-
-irqreturn_t scif_intr_handler(int irq, void *data)
-{
-       struct scif_dev *scifdev = data;
-       struct scif_hw_dev *sdev = scifdev->sdev;
-
-       sdev->hw_ops->ack_interrupt(sdev, scifdev->db);
-       queue_work(scifdev->intr_wq, &scifdev->intr_bh);
-       return IRQ_HANDLED;
-}
-
-static void scif_qp_setup_handler(struct work_struct *work)
-{
-       struct scif_dev *scifdev = container_of(work, struct scif_dev,
-                                               qp_dwork.work);
-       struct scif_hw_dev *sdev = scifdev->sdev;
-       dma_addr_t da = 0;
-       int err;
-
-       if (scif_is_mgmt_node()) {
-               struct mic_bootparam *bp = sdev->dp;
-
-               da = bp->scif_card_dma_addr;
-               scifdev->rdb = bp->h2c_scif_db;
-       } else {
-               struct mic_bootparam __iomem *bp = sdev->rdp;
-
-               da = readq(&bp->scif_host_dma_addr);
-               scifdev->rdb = ioread8(&bp->c2h_scif_db);
-       }
-       if (da) {
-               err = scif_qp_response(da, scifdev);
-               if (err)
-                       dev_err(&scifdev->sdev->dev,
-                               "scif_qp_response err %d\n", err);
-       } else {
-               schedule_delayed_work(&scifdev->qp_dwork,
-                                     msecs_to_jiffies(1000));
-       }
-}
-
-static int scif_setup_scifdev(void)
-{
-       /* We support a maximum of 129 SCIF nodes including the mgmt node */
-#define MAX_SCIF_NODES 129
-       int i;
-       u8 num_nodes = MAX_SCIF_NODES;
-
-       scif_dev = kcalloc(num_nodes, sizeof(*scif_dev), GFP_KERNEL);
-       if (!scif_dev)
-               return -ENOMEM;
-       for (i = 0; i < num_nodes; i++) {
-               struct scif_dev *scifdev = &scif_dev[i];
-
-               scifdev->node = i;
-               scifdev->exit = OP_IDLE;
-               init_waitqueue_head(&scifdev->disconn_wq);
-               mutex_init(&scifdev->lock);
-               INIT_WORK(&scifdev->peer_add_work, scif_add_peer_device);
-               INIT_DELAYED_WORK(&scifdev->p2p_dwork,
-                                 scif_poll_qp_state);
-               INIT_DELAYED_WORK(&scifdev->qp_dwork,
-                                 scif_qp_setup_handler);
-               INIT_LIST_HEAD(&scifdev->p2p);
-               RCU_INIT_POINTER(scifdev->spdev, NULL);
-       }
-       return 0;
-}
-
-static void scif_destroy_scifdev(void)
-{
-       kfree(scif_dev);
-       scif_dev = NULL;
-}
-
-static int scif_probe(struct scif_hw_dev *sdev)
-{
-       struct scif_dev *scifdev = &scif_dev[sdev->dnode];
-       int rc;
-
-       dev_set_drvdata(&sdev->dev, sdev);
-       scifdev->sdev = sdev;
-
-       if (1 == atomic_add_return(1, &g_loopb_cnt)) {
-               struct scif_dev *loopb_dev = &scif_dev[sdev->snode];
-
-               loopb_dev->sdev = sdev;
-               rc = scif_setup_loopback_qp(loopb_dev);
-               if (rc)
-                       goto exit;
-       }
-
-       rc = scif_setup_intr_wq(scifdev);
-       if (rc)
-               goto destroy_loopb;
-       rc = scif_setup_qp(scifdev);
-       if (rc)
-               goto destroy_intr;
-       scifdev->db = sdev->hw_ops->next_db(sdev);
-       scifdev->cookie = sdev->hw_ops->request_irq(sdev, scif_intr_handler,
-                                                   "SCIF_INTR", scifdev,
-                                                   scifdev->db);
-       if (IS_ERR(scifdev->cookie)) {
-               rc = PTR_ERR(scifdev->cookie);
-               goto free_qp;
-       }
-       if (scif_is_mgmt_node()) {
-               struct mic_bootparam *bp = sdev->dp;
-
-               bp->c2h_scif_db = scifdev->db;
-               bp->scif_host_dma_addr = scifdev->qp_dma_addr;
-       } else {
-               struct mic_bootparam __iomem *bp = sdev->rdp;
-
-               iowrite8(scifdev->db, &bp->h2c_scif_db);
-               writeq(scifdev->qp_dma_addr, &bp->scif_card_dma_addr);
-       }
-       schedule_delayed_work(&scifdev->qp_dwork,
-                             msecs_to_jiffies(1000));
-       return rc;
-free_qp:
-       scif_free_qp(scifdev);
-destroy_intr:
-       scif_destroy_intr_wq(scifdev);
-destroy_loopb:
-       if (atomic_dec_and_test(&g_loopb_cnt))
-               scif_destroy_loopback_qp(&scif_dev[sdev->snode]);
-exit:
-       return rc;
-}
-
-void scif_stop(struct scif_dev *scifdev)
-{
-       struct scif_dev *dev;
-       int i;
-
-       for (i = scif_info.maxid; i >= 0; i--) {
-               dev = &scif_dev[i];
-               if (scifdev_self(dev))
-                       continue;
-               scif_handle_remove_node(i);
-       }
-}
-
-static void scif_remove(struct scif_hw_dev *sdev)
-{
-       struct scif_dev *scifdev = &scif_dev[sdev->dnode];
-
-       if (scif_is_mgmt_node()) {
-               struct mic_bootparam *bp = sdev->dp;
-
-               bp->c2h_scif_db = -1;
-               bp->scif_host_dma_addr = 0x0;
-       } else {
-               struct mic_bootparam __iomem *bp = sdev->rdp;
-
-               iowrite8(-1, &bp->h2c_scif_db);
-               writeq(0x0, &bp->scif_card_dma_addr);
-       }
-       if (scif_is_mgmt_node()) {
-               scif_disconnect_node(scifdev->node, true);
-       } else {
-               scif_info.card_initiated_exit = true;
-               scif_stop(scifdev);
-       }
-       if (atomic_dec_and_test(&g_loopb_cnt))
-               scif_destroy_loopback_qp(&scif_dev[sdev->snode]);
-       if (scifdev->cookie) {
-               sdev->hw_ops->free_irq(sdev, scifdev->cookie, scifdev);
-               scifdev->cookie = NULL;
-       }
-       scif_destroy_intr_wq(scifdev);
-       cancel_delayed_work(&scifdev->qp_dwork);
-       scif_free_qp(scifdev);
-       scifdev->rdb = -1;
-       scifdev->sdev = NULL;
-}
-
-static struct scif_hw_dev_id id_table[] = {
-       { MIC_SCIF_DEV, SCIF_DEV_ANY_ID },
-       { 0 },
-};
-
-static struct scif_driver scif_driver = {
-       .driver.name =  KBUILD_MODNAME,
-       .driver.owner = THIS_MODULE,
-       .id_table = id_table,
-       .probe = scif_probe,
-       .remove = scif_remove,
-};
-
-static int _scif_init(void)
-{
-       int rc;
-
-       mutex_init(&scif_info.eplock);
-       spin_lock_init(&scif_info.rmalock);
-       spin_lock_init(&scif_info.nb_connect_lock);
-       spin_lock_init(&scif_info.port_lock);
-       mutex_init(&scif_info.conflock);
-       mutex_init(&scif_info.connlock);
-       mutex_init(&scif_info.fencelock);
-       INIT_LIST_HEAD(&scif_info.uaccept);
-       INIT_LIST_HEAD(&scif_info.listen);
-       INIT_LIST_HEAD(&scif_info.zombie);
-       INIT_LIST_HEAD(&scif_info.connected);
-       INIT_LIST_HEAD(&scif_info.disconnected);
-       INIT_LIST_HEAD(&scif_info.rma);
-       INIT_LIST_HEAD(&scif_info.rma_tc);
-       INIT_LIST_HEAD(&scif_info.mmu_notif_cleanup);
-       INIT_LIST_HEAD(&scif_info.fence);
-       INIT_LIST_HEAD(&scif_info.nb_connect_list);
-       init_waitqueue_head(&scif_info.exitwq);
-       scif_info.rma_tc_limit = SCIF_RMA_TEMP_CACHE_LIMIT;
-       scif_info.en_msg_log = 0;
-       scif_info.p2p_enable = 1;
-       rc = scif_setup_scifdev();
-       if (rc)
-               goto error;
-       unaligned_cache = kmem_cache_create("Unaligned_DMA",
-                                           SCIF_KMEM_UNALIGNED_BUF_SIZE,
-                                           0, SLAB_HWCACHE_ALIGN, NULL);
-       if (!unaligned_cache) {
-               rc = -ENOMEM;
-               goto free_sdev;
-       }
-       INIT_WORK(&scif_info.misc_work, scif_misc_handler);
-       INIT_WORK(&scif_info.mmu_notif_work, scif_mmu_notif_handler);
-       INIT_WORK(&scif_info.conn_work, scif_conn_handler);
-       idr_init(&scif_ports);
-       return 0;
-free_sdev:
-       scif_destroy_scifdev();
-error:
-       return rc;
-}
-
-static void _scif_exit(void)
-{
-       idr_destroy(&scif_ports);
-       kmem_cache_destroy(unaligned_cache);
-       scif_destroy_scifdev();
-}
-
-static int __init scif_init(void)
-{
-       struct miscdevice *mdev = &scif_info.mdev;
-       int rc;
-
-       _scif_init();
-       iova_cache_get();
-       rc = scif_peer_bus_init();
-       if (rc)
-               goto exit;
-       rc = scif_register_driver(&scif_driver);
-       if (rc)
-               goto peer_bus_exit;
-       rc = misc_register(mdev);
-       if (rc)
-               goto unreg_scif;
-       scif_init_debugfs();
-       return 0;
-unreg_scif:
-       scif_unregister_driver(&scif_driver);
-peer_bus_exit:
-       scif_peer_bus_exit();
-exit:
-       _scif_exit();
-       return rc;
-}
-
-static void __exit scif_exit(void)
-{
-       scif_exit_debugfs();
-       misc_deregister(&scif_info.mdev);
-       scif_unregister_driver(&scif_driver);
-       scif_peer_bus_exit();
-       iova_cache_put();
-       _scif_exit();
-}
-
-module_init(scif_init);
-module_exit(scif_exit);
-
-MODULE_DEVICE_TABLE(scif, id_table);
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Intel(R) SCIF driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/scif/scif_main.h b/drivers/misc/mic/scif/scif_main.h
deleted file mode 100644 (file)
index bb3ab97..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#ifndef SCIF_MAIN_H
-#define SCIF_MAIN_H
-
-#include <linux/sched/signal.h>
-#include <linux/pci.h>
-#include <linux/miscdevice.h>
-#include <linux/dmaengine.h>
-#include <linux/iova.h>
-#include <linux/anon_inodes.h>
-#include <linux/file.h>
-#include <linux/vmalloc.h>
-#include <linux/scif.h>
-#include "../common/mic_dev.h"
-
-#define SCIF_MGMT_NODE 0
-#define SCIF_DEFAULT_WATCHDOG_TO 30
-#define SCIF_NODE_ACCEPT_TIMEOUT (3 * HZ)
-#define SCIF_NODE_ALIVE_TIMEOUT (SCIF_DEFAULT_WATCHDOG_TO * HZ)
-#define SCIF_RMA_TEMP_CACHE_LIMIT 0x20000
-
-/*
- * Generic state used for certain node QP message exchanges
- * like Unregister, Alloc etc.
- */
-enum scif_msg_state {
-       OP_IDLE = 1,
-       OP_IN_PROGRESS,
-       OP_COMPLETED,
-       OP_FAILED
-};
-
-/*
- * struct scif_info - Global SCIF information
- *
- * @nodeid: Node ID this node is to others
- * @maxid: Max known node ID
- * @total: Total number of SCIF nodes
- * @nr_zombies: number of zombie endpoints
- * @eplock: Lock to synchronize listening, zombie endpoint lists
- * @connlock: Lock to synchronize connected and disconnected lists
- * @nb_connect_lock: Synchronize non blocking connect operations
- * @port_lock: Synchronize access to SCIF ports
- * @uaccept: List of user acceptreq waiting for acceptreg
- * @listen: List of listening end points
- * @zombie: List of zombie end points with pending RMA's
- * @connected: List of end points in connected state
- * @disconnected: List of end points in disconnected state
- * @nb_connect_list: List for non blocking connections
- * @misc_work: miscellaneous SCIF tasks
- * @conflock: Lock to synchronize SCIF node configuration changes
- * @en_msg_log: Enable debug message logging
- * @p2p_enable: Enable P2P SCIF network
- * @mdev: The MISC device
- * @conn_work: Work for workqueue handling all connections
- * @exitwq: Wait queue for waiting for an EXIT node QP message response
- * @loopb_dev: Dummy SCIF device used for loopback
- * @loopb_wq: Workqueue used for handling loopback messages
- * @loopb_wqname[16]: Name of loopback workqueue
- * @loopb_work: Used for submitting work to loopb_wq
- * @loopb_recv_q: List of messages received on the loopb_wq
- * @card_initiated_exit: set when the card has initiated the exit
- * @rmalock: Synchronize access to RMA operations
- * @fencelock: Synchronize access to list of remote fences requested.
- * @rma: List of temporary registered windows to be destroyed.
- * @rma_tc: List of temporary registered & cached Windows to be destroyed
- * @fence: List of remote fence requests
- * @mmu_notif_work: Work for registration caching MMU notifier workqueue
- * @mmu_notif_cleanup: List of temporary cached windows for reg cache
- * @rma_tc_limit: RMA temporary cache limit
- */
-struct scif_info {
-       u8 nodeid;
-       u8 maxid;
-       u8 total;
-       u32 nr_zombies;
-       struct mutex eplock;
-       struct mutex connlock;
-       spinlock_t nb_connect_lock;
-       spinlock_t port_lock;
-       struct list_head uaccept;
-       struct list_head listen;
-       struct list_head zombie;
-       struct list_head connected;
-       struct list_head disconnected;
-       struct list_head nb_connect_list;
-       struct work_struct misc_work;
-       struct mutex conflock;
-       u8 en_msg_log;
-       u8 p2p_enable;
-       struct miscdevice mdev;
-       struct work_struct conn_work;
-       wait_queue_head_t exitwq;
-       struct scif_dev *loopb_dev;
-       struct workqueue_struct *loopb_wq;
-       char loopb_wqname[16];
-       struct work_struct loopb_work;
-       struct list_head loopb_recv_q;
-       bool card_initiated_exit;
-       spinlock_t rmalock;
-       struct mutex fencelock;
-       struct list_head rma;
-       struct list_head rma_tc;
-       struct list_head fence;
-       struct work_struct mmu_notif_work;
-       struct list_head mmu_notif_cleanup;
-       unsigned long rma_tc_limit;
-};
-
-/*
- * struct scif_p2p_info - SCIF mapping information used for P2P
- *
- * @ppi_peer_id - SCIF peer node id
- * @ppi_sg - Scatter list for bar information (One for mmio and one for aper)
- * @sg_nentries - Number of entries in the scatterlist
- * @ppi_da: DMA address for MMIO and APER bars
- * @ppi_len: Length of MMIO and APER bars
- * @ppi_list: Link in list of mapping information
- */
-struct scif_p2p_info {
-       u8 ppi_peer_id;
-       struct scatterlist *ppi_sg[2];
-       u64 sg_nentries[2];
-       dma_addr_t ppi_da[2];
-       u64 ppi_len[2];
-#define SCIF_PPI_MMIO 0
-#define SCIF_PPI_APER 1
-       struct list_head ppi_list;
-};
-
-/*
- * struct scif_dev - SCIF remote device specific fields
- *
- * @node: Node id
- * @p2p: List of P2P mapping information
- * @qpairs: The node queue pair for exchanging control messages
- * @intr_wq: Workqueue for handling Node QP messages
- * @intr_wqname: Name of node QP workqueue for handling interrupts
- * @intr_bh: Used for submitting work to intr_wq
- * @lock: Lock used for synchronizing access to the scif device
- * @sdev: SCIF hardware device on the SCIF hardware bus
- * @db: doorbell the peer will trigger to generate an interrupt on self
- * @rdb: Doorbell to trigger on the peer to generate an interrupt on the peer
- * @cookie: Cookie received while registering the interrupt handler
- * @peer_add_work: Work for handling device_add for peer devices
- * @p2p_dwork: Delayed work to enable polling for P2P state
- * @qp_dwork: Delayed work for enabling polling for remote QP information
- * @p2p_retry: Number of times to retry polling of P2P state
- * @base_addr: P2P aperture bar base address
- * @mic_mw mmio: The peer MMIO information used for P2P
- * @spdev: SCIF peer device on the SCIF peer bus
- * @node_remove_ack_pending: True if a node_remove_ack is pending
- * @exit_ack_pending: true if an exit_ack is pending
- * @disconn_wq: Used while waiting for a node remove response
- * @disconn_rescnt: Keeps track of number of node remove requests sent
- * @exit: Status of exit message
- * @qp_dma_addr: Queue pair DMA address passed to the peer
- * @dma_ch_idx: Round robin index for DMA channels
- * @signal_pool: DMA pool used for scheduling scif_fence_signal DMA's
-*/
-struct scif_dev {
-       u8 node;
-       struct list_head p2p;
-       struct scif_qp *qpairs;
-       struct workqueue_struct *intr_wq;
-       char intr_wqname[16];
-       struct work_struct intr_bh;
-       struct mutex lock;
-       struct scif_hw_dev *sdev;
-       int db;
-       int rdb;
-       struct mic_irq *cookie;
-       struct work_struct peer_add_work;
-       struct delayed_work p2p_dwork;
-       struct delayed_work qp_dwork;
-       int p2p_retry;
-       dma_addr_t base_addr;
-       struct mic_mw mmio;
-       struct scif_peer_dev __rcu *spdev;
-       bool node_remove_ack_pending;
-       bool exit_ack_pending;
-       wait_queue_head_t disconn_wq;
-       atomic_t disconn_rescnt;
-       enum scif_msg_state exit;
-       dma_addr_t qp_dma_addr;
-       int dma_ch_idx;
-       struct dma_pool *signal_pool;
-};
-
-extern bool scif_reg_cache_enable;
-extern bool scif_ulimit_check;
-extern struct scif_info scif_info;
-extern struct idr scif_ports;
-extern struct bus_type scif_peer_bus;
-extern struct scif_dev *scif_dev;
-extern const struct file_operations scif_fops;
-extern const struct file_operations scif_anon_fops;
-
-/* Size of the RB for the Node QP */
-#define SCIF_NODE_QP_SIZE 0x10000
-
-#include "scif_nodeqp.h"
-#include "scif_rma.h"
-#include "scif_rma_list.h"
-
-/*
- * scifdev_self:
- * @dev: The remote SCIF Device
- *
- * Returns true if the SCIF Device passed is the self aka Loopback SCIF device.
- */
-static inline int scifdev_self(struct scif_dev *dev)
-{
-       return dev->node == scif_info.nodeid;
-}
-
-static inline bool scif_is_mgmt_node(void)
-{
-       return !scif_info.nodeid;
-}
-
-/*
- * scifdev_is_p2p:
- * @dev: The remote SCIF Device
- *
- * Returns true if the SCIF Device is a MIC Peer to Peer SCIF device.
- */
-static inline bool scifdev_is_p2p(struct scif_dev *dev)
-{
-       if (scif_is_mgmt_node())
-               return false;
-       else
-               return dev != &scif_dev[SCIF_MGMT_NODE] &&
-                       !scifdev_self(dev);
-}
-
-/*
- * scifdev_alive:
- * @scifdev: The remote SCIF Device
- *
- * Returns true if the remote SCIF Device is running or sleeping for
- * this endpoint.
- */
-static inline int _scifdev_alive(struct scif_dev *scifdev)
-{
-       struct scif_peer_dev *spdev;
-
-       rcu_read_lock();
-       spdev = rcu_dereference(scifdev->spdev);
-       rcu_read_unlock();
-       return !!spdev;
-}
-
-#include "scif_epd.h"
-
-void __init scif_init_debugfs(void);
-void scif_exit_debugfs(void);
-int scif_setup_intr_wq(struct scif_dev *scifdev);
-void scif_destroy_intr_wq(struct scif_dev *scifdev);
-void scif_cleanup_scifdev(struct scif_dev *dev);
-void scif_handle_remove_node(int node);
-void scif_disconnect_node(u32 node_id, bool mgmt_initiated);
-void scif_free_qp(struct scif_dev *dev);
-void scif_misc_handler(struct work_struct *work);
-void scif_stop(struct scif_dev *scifdev);
-irqreturn_t scif_intr_handler(int irq, void *data);
-#endif /* SCIF_MAIN_H */
diff --git a/drivers/misc/mic/scif/scif_map.h b/drivers/misc/mic/scif/scif_map.h
deleted file mode 100644 (file)
index 96b7608..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#ifndef SCIF_MAP_H
-#define SCIF_MAP_H
-
-#include "../bus/scif_bus.h"
-
-static __always_inline void *
-scif_alloc_coherent(dma_addr_t *dma_handle,
-                   struct scif_dev *scifdev, size_t size,
-                   gfp_t gfp)
-{
-       void *va;
-
-       if (scifdev_self(scifdev)) {
-               va = kmalloc(size, gfp);
-               if (va)
-                       *dma_handle = virt_to_phys(va);
-       } else {
-               va = dma_alloc_coherent(&scifdev->sdev->dev,
-                                       size, dma_handle, gfp);
-               if (va && scifdev_is_p2p(scifdev))
-                       *dma_handle = *dma_handle + scifdev->base_addr;
-       }
-       return va;
-}
-
-static __always_inline void
-scif_free_coherent(void *va, dma_addr_t local,
-                  struct scif_dev *scifdev, size_t size)
-{
-       if (scifdev_self(scifdev)) {
-               kfree(va);
-       } else {
-               if (scifdev_is_p2p(scifdev) && local > scifdev->base_addr)
-                       local = local - scifdev->base_addr;
-               dma_free_coherent(&scifdev->sdev->dev,
-                                 size, va, local);
-       }
-}
-
-static __always_inline int
-scif_map_single(dma_addr_t *dma_handle,
-               void *local, struct scif_dev *scifdev, size_t size)
-{
-       int err = 0;
-
-       if (scifdev_self(scifdev)) {
-               *dma_handle = virt_to_phys((local));
-       } else {
-               *dma_handle = dma_map_single(&scifdev->sdev->dev,
-                                            local, size, DMA_BIDIRECTIONAL);
-               if (dma_mapping_error(&scifdev->sdev->dev, *dma_handle))
-                       err = -ENOMEM;
-               else if (scifdev_is_p2p(scifdev))
-                       *dma_handle = *dma_handle + scifdev->base_addr;
-       }
-       if (err)
-               *dma_handle = 0;
-       return err;
-}
-
-static __always_inline void
-scif_unmap_single(dma_addr_t local, struct scif_dev *scifdev,
-                 size_t size)
-{
-       if (!scifdev_self(scifdev)) {
-               if (scifdev_is_p2p(scifdev))
-                       local = local - scifdev->base_addr;
-               dma_unmap_single(&scifdev->sdev->dev, local,
-                                size, DMA_BIDIRECTIONAL);
-       }
-}
-
-static __always_inline void *
-scif_ioremap(dma_addr_t phys, size_t size, struct scif_dev *scifdev)
-{
-       void *out_virt;
-       struct scif_hw_dev *sdev = scifdev->sdev;
-
-       if (scifdev_self(scifdev))
-               out_virt = phys_to_virt(phys);
-       else
-               out_virt = (void __force *)
-                          sdev->hw_ops->remap(sdev, phys, size);
-       return out_virt;
-}
-
-static __always_inline void
-scif_iounmap(void *virt, size_t len, struct scif_dev *scifdev)
-{
-       if (!scifdev_self(scifdev)) {
-               struct scif_hw_dev *sdev = scifdev->sdev;
-
-               sdev->hw_ops->unmap(sdev, (void __force __iomem *)virt);
-       }
-}
-
-static __always_inline int
-scif_map_page(dma_addr_t *dma_handle, struct page *page,
-             struct scif_dev *scifdev)
-{
-       int err = 0;
-
-       if (scifdev_self(scifdev)) {
-               *dma_handle = page_to_phys(page);
-       } else {
-               struct scif_hw_dev *sdev = scifdev->sdev;
-               *dma_handle = dma_map_page(&sdev->dev,
-                                          page, 0x0, PAGE_SIZE,
-                                          DMA_BIDIRECTIONAL);
-               if (dma_mapping_error(&sdev->dev, *dma_handle))
-                       err = -ENOMEM;
-               else if (scifdev_is_p2p(scifdev))
-                       *dma_handle = *dma_handle + scifdev->base_addr;
-       }
-       if (err)
-               *dma_handle = 0;
-       return err;
-}
-#endif  /* SCIF_MAP_H */
diff --git a/drivers/misc/mic/scif/scif_mmap.c b/drivers/misc/mic/scif/scif_mmap.c
deleted file mode 100644 (file)
index a151d41..0000000
+++ /dev/null
@@ -1,690 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#include "scif_main.h"
-
-/*
- * struct scif_vma_info - Information about a remote memory mapping
- *                       created via scif_mmap(..)
- * @vma: VM area struct
- * @list: link to list of active vmas
- */
-struct scif_vma_info {
-       struct vm_area_struct *vma;
-       struct list_head list;
-};
-
-void scif_recv_munmap(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_rma_req req;
-       struct scif_window *window = NULL;
-       struct scif_window *recv_window =
-               (struct scif_window *)msg->payload[0];
-       struct scif_endpt *ep;
-
-       ep = (struct scif_endpt *)recv_window->ep;
-       req.out_window = &window;
-       req.offset = recv_window->offset;
-       req.prot = recv_window->prot;
-       req.nr_bytes = recv_window->nr_pages << PAGE_SHIFT;
-       req.type = SCIF_WINDOW_FULL;
-       req.head = &ep->rma_info.reg_list;
-       msg->payload[0] = ep->remote_ep;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       /* Does a valid window exist? */
-       if (scif_query_window(&req)) {
-               dev_err(&scifdev->sdev->dev,
-                       "%s %d -ENXIO\n", __func__, __LINE__);
-               msg->uop = SCIF_UNREGISTER_ACK;
-               goto error;
-       }
-
-       scif_put_window(window, window->nr_pages);
-
-       if (!window->ref_count) {
-               atomic_inc(&ep->rma_info.tw_refcount);
-               ep->rma_info.async_list_del = 1;
-               list_del_init(&window->list);
-               scif_free_window_offset(ep, window, window->offset);
-       }
-error:
-       mutex_unlock(&ep->rma_info.rma_lock);
-       if (window && !window->ref_count)
-               scif_queue_for_cleanup(window, &scif_info.rma);
-}
-
-/*
- * Remove valid remote memory mappings created via scif_mmap(..) from the
- * process address space since the remote node is lost
- */
-static void __scif_zap_mmaps(struct scif_endpt *ep)
-{
-       struct list_head *item;
-       struct scif_vma_info *info;
-       struct vm_area_struct *vma;
-       unsigned long size;
-
-       spin_lock(&ep->lock);
-       list_for_each(item, &ep->rma_info.vma_list) {
-               info = list_entry(item, struct scif_vma_info, list);
-               vma = info->vma;
-               size = vma->vm_end - vma->vm_start;
-               zap_vma_ptes(vma, vma->vm_start, size);
-               dev_dbg(scif_info.mdev.this_device,
-                       "%s ep %p zap vma %p size 0x%lx\n",
-                       __func__, ep, info->vma, size);
-       }
-       spin_unlock(&ep->lock);
-}
-
-/*
- * Traverse the list of endpoints for a particular remote node and
- * zap valid remote memory mappings since the remote node is lost
- */
-static void _scif_zap_mmaps(int node, struct list_head *head)
-{
-       struct scif_endpt *ep;
-       struct list_head *item;
-
-       mutex_lock(&scif_info.connlock);
-       list_for_each(item, head) {
-               ep = list_entry(item, struct scif_endpt, list);
-               if (ep->remote_dev->node == node)
-                       __scif_zap_mmaps(ep);
-       }
-       mutex_unlock(&scif_info.connlock);
-}
-
-/*
- * Wrapper for removing remote memory mappings for a particular node. This API
- * is called by peer nodes as part of handling a lost node.
- */
-void scif_zap_mmaps(int node)
-{
-       _scif_zap_mmaps(node, &scif_info.connected);
-       _scif_zap_mmaps(node, &scif_info.disconnected);
-}
-
-/*
- * This API is only called while handling a lost node:
- * a) Remote node is dead.
- * b) Remote memory mappings have been zapped
- * So we can traverse the remote_reg_list without any locks. Since
- * the window has not yet been unregistered we can drop the ref count
- * and queue it to the cleanup thread.
- */
-static void __scif_cleanup_rma_for_zombies(struct scif_endpt *ep)
-{
-       struct list_head *pos, *tmp;
-       struct scif_window *window;
-
-       list_for_each_safe(pos, tmp, &ep->rma_info.remote_reg_list) {
-               window = list_entry(pos, struct scif_window, list);
-               if (window->ref_count)
-                       scif_put_window(window, window->nr_pages);
-               else
-                       dev_err(scif_info.mdev.this_device,
-                               "%s %d unexpected\n",
-                               __func__, __LINE__);
-               if (!window->ref_count) {
-                       atomic_inc(&ep->rma_info.tw_refcount);
-                       list_del_init(&window->list);
-                       scif_queue_for_cleanup(window, &scif_info.rma);
-               }
-       }
-}
-
-/* Cleanup remote registration lists for zombie endpoints */
-void scif_cleanup_rma_for_zombies(int node)
-{
-       struct scif_endpt *ep;
-       struct list_head *item;
-
-       mutex_lock(&scif_info.eplock);
-       list_for_each(item, &scif_info.zombie) {
-               ep = list_entry(item, struct scif_endpt, list);
-               if (ep->remote_dev && ep->remote_dev->node == node)
-                       __scif_cleanup_rma_for_zombies(ep);
-       }
-       mutex_unlock(&scif_info.eplock);
-       flush_work(&scif_info.misc_work);
-}
-
-/* Insert the VMA into the per endpoint VMA list */
-static int scif_insert_vma(struct scif_endpt *ep, struct vm_area_struct *vma)
-{
-       struct scif_vma_info *info;
-       int err = 0;
-
-       info = kzalloc(sizeof(*info), GFP_KERNEL);
-       if (!info) {
-               err = -ENOMEM;
-               goto done;
-       }
-       info->vma = vma;
-       spin_lock(&ep->lock);
-       list_add_tail(&info->list, &ep->rma_info.vma_list);
-       spin_unlock(&ep->lock);
-done:
-       return err;
-}
-
-/* Delete the VMA from the per endpoint VMA list */
-static void scif_delete_vma(struct scif_endpt *ep, struct vm_area_struct *vma)
-{
-       struct list_head *item;
-       struct scif_vma_info *info;
-
-       spin_lock(&ep->lock);
-       list_for_each(item, &ep->rma_info.vma_list) {
-               info = list_entry(item, struct scif_vma_info, list);
-               if (info->vma == vma) {
-                       list_del(&info->list);
-                       kfree(info);
-                       break;
-               }
-       }
-       spin_unlock(&ep->lock);
-}
-
-static phys_addr_t scif_get_phys(phys_addr_t phys, struct scif_endpt *ep)
-{
-       struct scif_dev *scifdev = (struct scif_dev *)ep->remote_dev;
-       struct scif_hw_dev *sdev = scifdev->sdev;
-       phys_addr_t out_phys, apt_base = 0;
-
-       /*
-        * If the DMA address is card relative then we need to add the
-        * aperture base for mmap to work correctly
-        */
-       if (!scifdev_self(scifdev) && sdev->aper && sdev->card_rel_da)
-               apt_base = sdev->aper->pa;
-       out_phys = apt_base + phys;
-       return out_phys;
-}
-
-int scif_get_pages(scif_epd_t epd, off_t offset, size_t len,
-                  struct scif_range **pages)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       struct scif_rma_req req;
-       struct scif_window *window = NULL;
-       int nr_pages, err, i;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI get_pinned_pages: ep %p offset 0x%lx len 0x%lx\n",
-               ep, offset, len);
-       err = scif_verify_epd(ep);
-       if (err)
-               return err;
-
-       if (!len || (offset < 0) ||
-           (offset + len < offset) ||
-           (ALIGN(offset, PAGE_SIZE) != offset) ||
-           (ALIGN(len, PAGE_SIZE) != len))
-               return -EINVAL;
-
-       nr_pages = len >> PAGE_SHIFT;
-
-       req.out_window = &window;
-       req.offset = offset;
-       req.prot = 0;
-       req.nr_bytes = len;
-       req.type = SCIF_WINDOW_SINGLE;
-       req.head = &ep->rma_info.remote_reg_list;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       /* Does a valid window exist? */
-       err = scif_query_window(&req);
-       if (err) {
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-               goto error;
-       }
-
-       /* Allocate scif_range */
-       *pages = kzalloc(sizeof(**pages), GFP_KERNEL);
-       if (!*pages) {
-               err = -ENOMEM;
-               goto error;
-       }
-
-       /* Allocate phys addr array */
-       (*pages)->phys_addr = scif_zalloc(nr_pages * sizeof(dma_addr_t));
-       if (!((*pages)->phys_addr)) {
-               err = -ENOMEM;
-               goto error;
-       }
-
-       if (scif_is_mgmt_node() && !scifdev_self(ep->remote_dev)) {
-               /* Allocate virtual address array */
-               ((*pages)->va = scif_zalloc(nr_pages * sizeof(void *)));
-               if (!(*pages)->va) {
-                       err = -ENOMEM;
-                       goto error;
-               }
-       }
-       /* Populate the values */
-       (*pages)->cookie = window;
-       (*pages)->nr_pages = nr_pages;
-       (*pages)->prot_flags = window->prot;
-
-       for (i = 0; i < nr_pages; i++) {
-               (*pages)->phys_addr[i] =
-                       __scif_off_to_dma_addr(window, offset +
-                                              (i * PAGE_SIZE));
-               (*pages)->phys_addr[i] = scif_get_phys((*pages)->phys_addr[i],
-                                                       ep);
-               if (scif_is_mgmt_node() && !scifdev_self(ep->remote_dev))
-                       (*pages)->va[i] =
-                               ep->remote_dev->sdev->aper->va +
-                               (*pages)->phys_addr[i] -
-                               ep->remote_dev->sdev->aper->pa;
-       }
-
-       scif_get_window(window, nr_pages);
-error:
-       mutex_unlock(&ep->rma_info.rma_lock);
-       if (err) {
-               if (*pages) {
-                       scif_free((*pages)->phys_addr,
-                                 nr_pages * sizeof(dma_addr_t));
-                       scif_free((*pages)->va,
-                                 nr_pages * sizeof(void *));
-                       kfree(*pages);
-                       *pages = NULL;
-               }
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-       }
-       return err;
-}
-EXPORT_SYMBOL_GPL(scif_get_pages);
-
-int scif_put_pages(struct scif_range *pages)
-{
-       struct scif_endpt *ep;
-       struct scif_window *window;
-       struct scifmsg msg;
-
-       if (!pages || !pages->cookie)
-               return -EINVAL;
-
-       window = pages->cookie;
-
-       if (!window || window->magic != SCIFEP_MAGIC)
-               return -EINVAL;
-
-       ep = (struct scif_endpt *)window->ep;
-       /*
-        * If the state is SCIFEP_CONNECTED or SCIFEP_DISCONNECTED then the
-        * callee should be allowed to release references to the pages,
-        * else the endpoint was not connected in the first place,
-        * hence the ENOTCONN.
-        */
-       if (ep->state != SCIFEP_CONNECTED && ep->state != SCIFEP_DISCONNECTED)
-               return -ENOTCONN;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-
-       scif_put_window(window, pages->nr_pages);
-
-       /* Initiate window destruction if ref count is zero */
-       if (!window->ref_count) {
-               list_del(&window->list);
-               mutex_unlock(&ep->rma_info.rma_lock);
-               scif_drain_dma_intr(ep->remote_dev->sdev,
-                                   ep->rma_info.dma_chan);
-               /* Inform the peer about this window being destroyed. */
-               msg.uop = SCIF_MUNMAP;
-               msg.src = ep->port;
-               msg.payload[0] = window->peer_window;
-               /* No error handling for notification messages */
-               scif_nodeqp_send(ep->remote_dev, &msg);
-               /* Destroy this window from the peer's registered AS */
-               scif_destroy_remote_window(window);
-       } else {
-               mutex_unlock(&ep->rma_info.rma_lock);
-       }
-
-       scif_free(pages->phys_addr, pages->nr_pages * sizeof(dma_addr_t));
-       scif_free(pages->va, pages->nr_pages * sizeof(void *));
-       kfree(pages);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(scif_put_pages);
-
-/*
- * scif_rma_list_mmap:
- *
- * Traverse the remote registration list starting from start_window:
- * 1) Create VtoP mappings via remap_pfn_range(..)
- * 2) Once step 1) and 2) complete successfully then traverse the range of
- *    windows again and bump the reference count.
- * RMA lock must be held.
- */
-static int scif_rma_list_mmap(struct scif_window *start_window, s64 offset,
-                             int nr_pages, struct vm_area_struct *vma)
-{
-       s64 end_offset, loop_offset = offset;
-       struct scif_window *window = start_window;
-       int loop_nr_pages, nr_pages_left = nr_pages;
-       struct scif_endpt *ep = (struct scif_endpt *)start_window->ep;
-       struct list_head *head = &ep->rma_info.remote_reg_list;
-       int i, err = 0;
-       dma_addr_t phys_addr;
-       struct scif_window_iter src_win_iter;
-       size_t contig_bytes = 0;
-
-       might_sleep();
-       list_for_each_entry_from(window, head, list) {
-               end_offset = window->offset +
-                       (window->nr_pages << PAGE_SHIFT);
-               loop_nr_pages = min_t(int,
-                                     (end_offset - loop_offset) >> PAGE_SHIFT,
-                                     nr_pages_left);
-               scif_init_window_iter(window, &src_win_iter);
-               for (i = 0; i < loop_nr_pages; i++) {
-                       phys_addr = scif_off_to_dma_addr(window, loop_offset,
-                                                        &contig_bytes,
-                                                        &src_win_iter);
-                       phys_addr = scif_get_phys(phys_addr, ep);
-                       err = remap_pfn_range(vma,
-                                             vma->vm_start +
-                                             loop_offset - offset,
-                                             phys_addr >> PAGE_SHIFT,
-                                             PAGE_SIZE,
-                                             vma->vm_page_prot);
-                       if (err)
-                               goto error;
-                       loop_offset += PAGE_SIZE;
-               }
-               nr_pages_left -= loop_nr_pages;
-               if (!nr_pages_left)
-                       break;
-       }
-       /*
-        * No more failures expected. Bump up the ref count for all
-        * the windows. Another traversal from start_window required
-        * for handling errors encountered across windows during
-        * remap_pfn_range(..).
-        */
-       loop_offset = offset;
-       nr_pages_left = nr_pages;
-       window = start_window;
-       head = &ep->rma_info.remote_reg_list;
-       list_for_each_entry_from(window, head, list) {
-               end_offset = window->offset +
-                       (window->nr_pages << PAGE_SHIFT);
-               loop_nr_pages = min_t(int,
-                                     (end_offset - loop_offset) >> PAGE_SHIFT,
-                                     nr_pages_left);
-               scif_get_window(window, loop_nr_pages);
-               nr_pages_left -= loop_nr_pages;
-               loop_offset += (loop_nr_pages << PAGE_SHIFT);
-               if (!nr_pages_left)
-                       break;
-       }
-error:
-       if (err)
-               dev_err(scif_info.mdev.this_device,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-       return err;
-}
-
-/*
- * scif_rma_list_munmap:
- *
- * Traverse the remote registration list starting from window:
- * 1) Decrement ref count.
- * 2) If the ref count drops to zero then send a SCIF_MUNMAP message to peer.
- * RMA lock must be held.
- */
-static void scif_rma_list_munmap(struct scif_window *start_window,
-                                s64 offset, int nr_pages)
-{
-       struct scifmsg msg;
-       s64 loop_offset = offset, end_offset;
-       int loop_nr_pages, nr_pages_left = nr_pages;
-       struct scif_endpt *ep = (struct scif_endpt *)start_window->ep;
-       struct list_head *head = &ep->rma_info.remote_reg_list;
-       struct scif_window *window = start_window, *_window;
-
-       msg.uop = SCIF_MUNMAP;
-       msg.src = ep->port;
-       loop_offset = offset;
-       nr_pages_left = nr_pages;
-       list_for_each_entry_safe_from(window, _window, head, list) {
-               end_offset = window->offset +
-                       (window->nr_pages << PAGE_SHIFT);
-               loop_nr_pages = min_t(int,
-                                     (end_offset - loop_offset) >> PAGE_SHIFT,
-                                     nr_pages_left);
-               scif_put_window(window, loop_nr_pages);
-               if (!window->ref_count) {
-                       struct scif_dev *rdev = ep->remote_dev;
-
-                       scif_drain_dma_intr(rdev->sdev,
-                                           ep->rma_info.dma_chan);
-                       /* Inform the peer about this munmap */
-                       msg.payload[0] = window->peer_window;
-                       /* No error handling for Notification messages. */
-                       scif_nodeqp_send(ep->remote_dev, &msg);
-                       list_del(&window->list);
-                       /* Destroy this window from the peer's registered AS */
-                       scif_destroy_remote_window(window);
-               }
-               nr_pages_left -= loop_nr_pages;
-               loop_offset += (loop_nr_pages << PAGE_SHIFT);
-               if (!nr_pages_left)
-                       break;
-       }
-}
-
-/*
- * The private data field of each VMA used to mmap a remote window
- * points to an instance of struct vma_pvt
- */
-struct vma_pvt {
-       struct scif_endpt *ep;  /* End point for remote window */
-       s64 offset;             /* offset within remote window */
-       bool valid_offset;      /* offset is valid only if the original
-                                * mmap request was for a single page
-                                * else the offset within the vma is
-                                * the correct offset
-                                */
-       struct kref ref;
-};
-
-static void vma_pvt_release(struct kref *ref)
-{
-       struct vma_pvt *vmapvt = container_of(ref, struct vma_pvt, ref);
-
-       kfree(vmapvt);
-}
-
-/**
- * scif_vma_open - VMA open driver callback
- * @vma: VMM memory area.
- * The open method is called by the kernel to allow the subsystem implementing
- * the VMA to initialize the area. This method is invoked any time a new
- * reference to the VMA is made (when a process forks, for example).
- * The one exception happens when the VMA is first created by mmap;
- * in this case, the driver's mmap method is called instead.
- * This function is also invoked when an existing VMA is split by the kernel
- * due to a call to munmap on a subset of the VMA resulting in two VMAs.
- * The kernel invokes this function only on one of the two VMAs.
- */
-static void scif_vma_open(struct vm_area_struct *vma)
-{
-       struct vma_pvt *vmapvt = vma->vm_private_data;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI vma open: vma_start 0x%lx vma_end 0x%lx\n",
-               vma->vm_start, vma->vm_end);
-       scif_insert_vma(vmapvt->ep, vma);
-       kref_get(&vmapvt->ref);
-}
-
-/**
- * scif_munmap - VMA close driver callback.
- * @vma: VMM memory area.
- * When an area is destroyed, the kernel calls its close operation.
- * Note that there's no usage count associated with VMA's; the area
- * is opened and closed exactly once by each process that uses it.
- */
-static void scif_munmap(struct vm_area_struct *vma)
-{
-       struct scif_endpt *ep;
-       struct vma_pvt *vmapvt = vma->vm_private_data;
-       int nr_pages = vma_pages(vma);
-       s64 offset;
-       struct scif_rma_req req;
-       struct scif_window *window = NULL;
-       int err;
-
-       might_sleep();
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI munmap: vma_start 0x%lx vma_end 0x%lx\n",
-               vma->vm_start, vma->vm_end);
-       ep = vmapvt->ep;
-       offset = vmapvt->valid_offset ? vmapvt->offset :
-               (vma->vm_pgoff) << PAGE_SHIFT;
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI munmap: ep %p nr_pages 0x%x offset 0x%llx\n",
-               ep, nr_pages, offset);
-       req.out_window = &window;
-       req.offset = offset;
-       req.nr_bytes = vma->vm_end - vma->vm_start;
-       req.prot = vma->vm_flags & (VM_READ | VM_WRITE);
-       req.type = SCIF_WINDOW_PARTIAL;
-       req.head = &ep->rma_info.remote_reg_list;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-
-       err = scif_query_window(&req);
-       if (err)
-               dev_err(scif_info.mdev.this_device,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-       else
-               scif_rma_list_munmap(window, offset, nr_pages);
-
-       mutex_unlock(&ep->rma_info.rma_lock);
-       /*
-        * The kernel probably zeroes these out but we still want
-        * to clean up our own mess just in case.
-        */
-       vma->vm_ops = NULL;
-       vma->vm_private_data = NULL;
-       kref_put(&vmapvt->ref, vma_pvt_release);
-       scif_delete_vma(ep, vma);
-}
-
-static const struct vm_operations_struct scif_vm_ops = {
-       .open = scif_vma_open,
-       .close = scif_munmap,
-};
-
-/**
- * scif_mmap - Map pages in virtual address space to a remote window.
- * @vma: VMM memory area.
- * @epd: endpoint descriptor
- *
- * Return: Upon successful completion, scif_mmap() returns zero
- * else an apt error is returned as documented in scif.h
- */
-int scif_mmap(struct vm_area_struct *vma, scif_epd_t epd)
-{
-       struct scif_rma_req req;
-       struct scif_window *window = NULL;
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       s64 start_offset = vma->vm_pgoff << PAGE_SHIFT;
-       int nr_pages = vma_pages(vma);
-       int err;
-       struct vma_pvt *vmapvt;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI mmap: ep %p start_offset 0x%llx nr_pages 0x%x\n",
-               ep, start_offset, nr_pages);
-       err = scif_verify_epd(ep);
-       if (err)
-               return err;
-
-       might_sleep();
-
-       err = scif_insert_vma(ep, vma);
-       if (err)
-               return err;
-
-       vmapvt = kzalloc(sizeof(*vmapvt), GFP_KERNEL);
-       if (!vmapvt) {
-               scif_delete_vma(ep, vma);
-               return -ENOMEM;
-       }
-
-       vmapvt->ep = ep;
-       kref_init(&vmapvt->ref);
-
-       req.out_window = &window;
-       req.offset = start_offset;
-       req.nr_bytes = vma->vm_end - vma->vm_start;
-       req.prot = vma->vm_flags & (VM_READ | VM_WRITE);
-       req.type = SCIF_WINDOW_PARTIAL;
-       req.head = &ep->rma_info.remote_reg_list;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       /* Does a valid window exist? */
-       err = scif_query_window(&req);
-       if (err) {
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-               goto error_unlock;
-       }
-
-       /* Default prot for loopback */
-       if (!scifdev_self(ep->remote_dev))
-               vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-
-       /*
-        * VM_DONTCOPY - Do not copy this vma on fork
-        * VM_DONTEXPAND - Cannot expand with mremap()
-        * VM_RESERVED - Count as reserved_vm like IO
-        * VM_PFNMAP - Page-ranges managed without "struct page"
-        * VM_IO - Memory mapped I/O or similar
-        *
-        * We do not want to copy this VMA automatically on a fork(),
-        * expand this VMA due to mremap() or swap out these pages since
-        * the VMA is actually backed by physical pages in the remote
-        * node's physical memory and not via a struct page.
-        */
-       vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP;
-
-       if (!scifdev_self(ep->remote_dev))
-               vma->vm_flags |= VM_IO | VM_PFNMAP;
-
-       /* Map this range of windows */
-       err = scif_rma_list_mmap(window, start_offset, nr_pages, vma);
-       if (err) {
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-               goto error_unlock;
-       }
-       /* Set up the driver call back */
-       vma->vm_ops = &scif_vm_ops;
-       vma->vm_private_data = vmapvt;
-error_unlock:
-       mutex_unlock(&ep->rma_info.rma_lock);
-       if (err) {
-               kfree(vmapvt);
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-               scif_delete_vma(ep, vma);
-       }
-       return err;
-}
diff --git a/drivers/misc/mic/scif/scif_nm.c b/drivers/misc/mic/scif/scif_nm.c
deleted file mode 100644 (file)
index c4d9422..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#include "scif_peer_bus.h"
-
-#include "scif_main.h"
-#include "scif_map.h"
-
-/**
- * scif_invalidate_ep() - Set state for all connected endpoints
- * to disconnected and wake up all send/recv waitqueues
- *
- * @node: Node to invalidate
- */
-static void scif_invalidate_ep(int node)
-{
-       struct scif_endpt *ep;
-       struct list_head *pos, *tmpq;
-
-       flush_work(&scif_info.conn_work);
-       mutex_lock(&scif_info.connlock);
-       list_for_each_safe(pos, tmpq, &scif_info.disconnected) {
-               ep = list_entry(pos, struct scif_endpt, list);
-               if (ep->remote_dev->node == node) {
-                       scif_unmap_all_windows(ep);
-                       spin_lock(&ep->lock);
-                       scif_cleanup_ep_qp(ep);
-                       spin_unlock(&ep->lock);
-               }
-       }
-       list_for_each_safe(pos, tmpq, &scif_info.connected) {
-               ep = list_entry(pos, struct scif_endpt, list);
-               if (ep->remote_dev->node == node) {
-                       list_del(pos);
-                       spin_lock(&ep->lock);
-                       ep->state = SCIFEP_DISCONNECTED;
-                       list_add_tail(&ep->list, &scif_info.disconnected);
-                       scif_cleanup_ep_qp(ep);
-                       wake_up_interruptible(&ep->sendwq);
-                       wake_up_interruptible(&ep->recvwq);
-                       spin_unlock(&ep->lock);
-                       scif_unmap_all_windows(ep);
-               }
-       }
-       mutex_unlock(&scif_info.connlock);
-}
-
-void scif_free_qp(struct scif_dev *scifdev)
-{
-       struct scif_qp *qp = scifdev->qpairs;
-
-       if (!qp)
-               return;
-       scif_unmap_single(qp->local_buf, scifdev, qp->inbound_q.size);
-       kfree(qp->inbound_q.rb_base);
-       scif_unmap_single(qp->local_qp, scifdev, sizeof(struct scif_qp));
-       kfree(scifdev->qpairs);
-       scifdev->qpairs = NULL;
-}
-
-static void scif_cleanup_qp(struct scif_dev *dev)
-{
-       struct scif_qp *qp = &dev->qpairs[0];
-
-       if (!qp)
-               return;
-       scif_iounmap((void *)qp->remote_qp, sizeof(struct scif_qp), dev);
-       scif_iounmap((void *)qp->outbound_q.rb_base,
-                    sizeof(struct scif_qp), dev);
-       qp->remote_qp = NULL;
-       qp->local_write = 0;
-       qp->inbound_q.current_write_offset = 0;
-       qp->inbound_q.current_read_offset = 0;
-       if (scifdev_is_p2p(dev))
-               scif_free_qp(dev);
-}
-
-void scif_send_acks(struct scif_dev *dev)
-{
-       struct scifmsg msg;
-
-       if (dev->node_remove_ack_pending) {
-               msg.uop = SCIF_NODE_REMOVE_ACK;
-               msg.src.node = scif_info.nodeid;
-               msg.dst.node = SCIF_MGMT_NODE;
-               msg.payload[0] = dev->node;
-               scif_nodeqp_send(&scif_dev[SCIF_MGMT_NODE], &msg);
-               dev->node_remove_ack_pending = false;
-       }
-       if (dev->exit_ack_pending) {
-               msg.uop = SCIF_EXIT_ACK;
-               msg.src.node = scif_info.nodeid;
-               msg.dst.node = dev->node;
-               scif_nodeqp_send(dev, &msg);
-               dev->exit_ack_pending = false;
-       }
-}
-
-/**
- * scif_cleanup_scifdev - Uninitialize SCIF data structures for remote
- *                        SCIF device.
- * @dev: Remote SCIF device.
- */
-void scif_cleanup_scifdev(struct scif_dev *dev)
-{
-       struct scif_hw_dev *sdev = dev->sdev;
-
-       if (!dev->sdev)
-               return;
-       if (scifdev_is_p2p(dev)) {
-               if (dev->cookie) {
-                       sdev->hw_ops->free_irq(sdev, dev->cookie, dev);
-                       dev->cookie = NULL;
-               }
-               scif_destroy_intr_wq(dev);
-       }
-       flush_work(&scif_info.misc_work);
-       scif_destroy_p2p(dev);
-       scif_invalidate_ep(dev->node);
-       scif_zap_mmaps(dev->node);
-       scif_cleanup_rma_for_zombies(dev->node);
-       flush_work(&scif_info.misc_work);
-       scif_send_acks(dev);
-       if (!dev->node && scif_info.card_initiated_exit) {
-               /*
-                * Send an SCIF_EXIT message which is the last message from MIC
-                * to the Host and wait for a SCIF_EXIT_ACK
-                */
-               scif_send_exit(dev);
-               scif_info.card_initiated_exit = false;
-       }
-       scif_cleanup_qp(dev);
-}
-
-/**
- * scif_remove_node
- *
- * @node: Node to remove
- */
-void scif_handle_remove_node(int node)
-{
-       struct scif_dev *scifdev = &scif_dev[node];
-
-       if (scif_peer_unregister_device(scifdev))
-               scif_send_acks(scifdev);
-}
-
-static int scif_send_rmnode_msg(int node, int remove_node)
-{
-       struct scifmsg notif_msg;
-       struct scif_dev *dev = &scif_dev[node];
-
-       notif_msg.uop = SCIF_NODE_REMOVE;
-       notif_msg.src.node = scif_info.nodeid;
-       notif_msg.dst.node = node;
-       notif_msg.payload[0] = remove_node;
-       return scif_nodeqp_send(dev, &notif_msg);
-}
-
-/**
- * scif_node_disconnect
- *
- * @node_id: source node id [in]
- * @mgmt_initiated: Disconnection initiated from the mgmt node
- *
- * Disconnect a node from the scif network.
- */
-void scif_disconnect_node(u32 node_id, bool mgmt_initiated)
-{
-       int ret;
-       int msg_cnt = 0;
-       u32 i = 0;
-       struct scif_dev *scifdev = &scif_dev[node_id];
-
-       if (!node_id)
-               return;
-
-       atomic_set(&scifdev->disconn_rescnt, 0);
-
-       /* Destroy p2p network */
-       for (i = 1; i <= scif_info.maxid; i++) {
-               if (i == node_id)
-                       continue;
-               ret = scif_send_rmnode_msg(i, node_id);
-               if (!ret)
-                       msg_cnt++;
-       }
-       /* Wait for the remote nodes to respond with SCIF_NODE_REMOVE_ACK */
-       ret = wait_event_timeout(scifdev->disconn_wq,
-                                (atomic_read(&scifdev->disconn_rescnt)
-                                == msg_cnt), SCIF_NODE_ALIVE_TIMEOUT);
-       /* Tell the card to clean up */
-       if (mgmt_initiated && _scifdev_alive(scifdev))
-               /*
-                * Send an SCIF_EXIT message which is the last message from Host
-                * to the MIC and wait for a SCIF_EXIT_ACK
-                */
-               scif_send_exit(scifdev);
-       atomic_set(&scifdev->disconn_rescnt, 0);
-       /* Tell the mgmt node to clean up */
-       ret = scif_send_rmnode_msg(SCIF_MGMT_NODE, node_id);
-       if (!ret)
-               /* Wait for mgmt node to respond with SCIF_NODE_REMOVE_ACK */
-               wait_event_timeout(scifdev->disconn_wq,
-                                  (atomic_read(&scifdev->disconn_rescnt) == 1),
-                                  SCIF_NODE_ALIVE_TIMEOUT);
-}
-
-void scif_get_node_info(void)
-{
-       struct scifmsg msg;
-       DECLARE_COMPLETION_ONSTACK(node_info);
-
-       msg.uop = SCIF_GET_NODE_INFO;
-       msg.src.node = scif_info.nodeid;
-       msg.dst.node = SCIF_MGMT_NODE;
-       msg.payload[3] = (u64)&node_info;
-
-       if ((scif_nodeqp_send(&scif_dev[SCIF_MGMT_NODE], &msg)))
-               return;
-
-       /* Wait for a response with SCIF_GET_NODE_INFO */
-       wait_for_completion(&node_info);
-}
diff --git a/drivers/misc/mic/scif/scif_nodeqp.c b/drivers/misc/mic/scif/scif_nodeqp.c
deleted file mode 100644 (file)
index 384ce08..0000000
+++ /dev/null
@@ -1,1349 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#include "../bus/scif_bus.h"
-#include "scif_peer_bus.h"
-#include "scif_main.h"
-#include "scif_nodeqp.h"
-#include "scif_map.h"
-
-/*
- ************************************************************************
- * SCIF node Queue Pair (QP) setup flow:
- *
- * 1) SCIF driver gets probed with a scif_hw_dev via the scif_hw_bus
- * 2) scif_setup_qp(..) allocates the local qp and calls
- *     scif_setup_qp_connect(..) which allocates and maps the local
- *     buffer for the inbound QP
- * 3) The local node updates the device page with the DMA address of the QP
- * 4) A delayed work is scheduled (qp_dwork) which periodically reads if
- *     the peer node has updated its QP DMA address
- * 5) Once a valid non zero address is found in the QP DMA address field
- *     in the device page, the local node maps the remote node's QP,
- *     updates its outbound QP and sends a SCIF_INIT message to the peer
- * 6) The SCIF_INIT message is received by the peer node QP interrupt bottom
- *     half handler by calling scif_init(..)
- * 7) scif_init(..) registers a new SCIF peer node by calling
- *     scif_peer_register_device(..) which signifies the addition of a new
- *     SCIF node
- * 8) On the mgmt node, P2P network setup/teardown is initiated if all the
- *     remote nodes are online via scif_p2p_setup(..)
- * 9) For P2P setup, the host maps the remote nodes' aperture and memory
- *     bars and sends a SCIF_NODE_ADD message to both nodes
- * 10) As part of scif_nodeadd, both nodes set up their local inbound
- *     QPs and send a SCIF_NODE_ADD_ACK to the mgmt node
- * 11) As part of scif_node_add_ack(..) the mgmt node forwards the
- *     SCIF_NODE_ADD_ACK to the remote nodes
- * 12) As part of scif_node_add_ack(..) the remote nodes update their
- *     outbound QPs, make sure they can access memory on the remote node
- *     and then add a new SCIF peer node by calling
- *     scif_peer_register_device(..) which signifies the addition of a new
- *     SCIF node.
- * 13) The SCIF network is now established across all nodes.
- *
- ************************************************************************
- * SCIF node QP teardown flow (initiated by non mgmt node):
- *
- * 1) SCIF driver gets a remove callback with a scif_hw_dev via the scif_hw_bus
- * 2) The device page QP DMA address field is updated with 0x0
- * 3) A non mgmt node now cleans up all local data structures and sends a
- *     SCIF_EXIT message to the peer and waits for a SCIF_EXIT_ACK
- * 4) As part of scif_exit(..) handling scif_disconnect_node(..) is called
- * 5) scif_disconnect_node(..) sends a SCIF_NODE_REMOVE message to all the
- *     peers and waits for a SCIF_NODE_REMOVE_ACK
- * 6) As part of scif_node_remove(..) a remote node unregisters the peer
- *     node from the SCIF network and sends a SCIF_NODE_REMOVE_ACK
- * 7) When the mgmt node has received all the SCIF_NODE_REMOVE_ACKs
- *     it sends itself a node remove message whose handling cleans up local
- *     data structures and unregisters the peer node from the SCIF network
- * 8) The mgmt node sends a SCIF_EXIT_ACK
- * 9) Upon receipt of the SCIF_EXIT_ACK the node initiating the teardown
- *     completes the SCIF remove routine
- * 10) The SCIF network is now torn down for the node initiating the
- *     teardown sequence
- *
- ************************************************************************
- * SCIF node QP teardown flow (initiated by mgmt node):
- *
- * 1) SCIF driver gets a remove callback with a scif_hw_dev via the scif_hw_bus
- * 2) The device page QP DMA address field is updated with 0x0
- * 3) The mgmt node calls scif_disconnect_node(..)
- * 4) scif_disconnect_node(..) sends a SCIF_NODE_REMOVE message to all the peers
- *     and waits for a SCIF_NODE_REMOVE_ACK
- * 5) As part of scif_node_remove(..) a remote node unregisters the peer
- *     node from the SCIF network and sends a SCIF_NODE_REMOVE_ACK
- * 6) When the mgmt node has received all the SCIF_NODE_REMOVE_ACKs
- *     it unregisters the peer node from the SCIF network
- * 7) The mgmt node sends a SCIF_EXIT message and waits for a SCIF_EXIT_ACK.
- * 8) A non mgmt node upon receipt of a SCIF_EXIT message calls scif_stop(..)
- *     which would clean up local data structures for all SCIF nodes and
- *     then send a SCIF_EXIT_ACK back to the mgmt node
- * 9) Upon receipt of the SCIF_EXIT_ACK the the mgmt node sends itself a node
- *     remove message whose handling cleans up local data structures and
- *     destroys any P2P mappings.
- * 10) The SCIF hardware device for which a remove callback was received is now
- *     disconnected from the SCIF network.
- */
-/*
- * Initializes "local" data structures for the QP. Allocates the QP
- * ring buffer (rb) and initializes the "in bound" queue.
- */
-int scif_setup_qp_connect(struct scif_qp *qp, dma_addr_t *qp_offset,
-                         int local_size, struct scif_dev *scifdev)
-{
-       void *local_q = qp->inbound_q.rb_base;
-       int err = 0;
-       u32 tmp_rd = 0;
-
-       spin_lock_init(&qp->send_lock);
-       spin_lock_init(&qp->recv_lock);
-
-       /* Allocate rb only if not already allocated */
-       if (!local_q) {
-               local_q = kzalloc(local_size, GFP_KERNEL);
-               if (!local_q) {
-                       err = -ENOMEM;
-                       return err;
-               }
-       }
-
-       err = scif_map_single(&qp->local_buf, local_q, scifdev, local_size);
-       if (err)
-               goto kfree;
-       /*
-        * To setup the inbound_q, the buffer lives locally, the read pointer
-        * is remote and the write pointer is local.
-        */
-       scif_rb_init(&qp->inbound_q,
-                    &tmp_rd,
-                    &qp->local_write,
-                    local_q, get_count_order(local_size));
-       /*
-        * The read pointer is NULL initially and it is unsafe to use the ring
-        * buffer til this changes!
-        */
-       qp->inbound_q.read_ptr = NULL;
-       err = scif_map_single(qp_offset, qp,
-                             scifdev, sizeof(struct scif_qp));
-       if (err)
-               goto unmap;
-       qp->local_qp = *qp_offset;
-       return err;
-unmap:
-       scif_unmap_single(qp->local_buf, scifdev, local_size);
-       qp->local_buf = 0;
-kfree:
-       kfree(local_q);
-       return err;
-}
-
-/* When the other side has already done it's allocation, this is called */
-int scif_setup_qp_accept(struct scif_qp *qp, dma_addr_t *qp_offset,
-                        dma_addr_t phys, int local_size,
-                        struct scif_dev *scifdev)
-{
-       void *local_q;
-       void *remote_q;
-       struct scif_qp *remote_qp;
-       int remote_size;
-       int err = 0;
-
-       spin_lock_init(&qp->send_lock);
-       spin_lock_init(&qp->recv_lock);
-       /* Start by figuring out where we need to point */
-       remote_qp = scif_ioremap(phys, sizeof(struct scif_qp), scifdev);
-       if (!remote_qp)
-               return -EIO;
-       qp->remote_qp = remote_qp;
-       if (qp->remote_qp->magic != SCIFEP_MAGIC) {
-               err = -EIO;
-               goto iounmap;
-       }
-       qp->remote_buf = remote_qp->local_buf;
-       remote_size = qp->remote_qp->inbound_q.size;
-       remote_q = scif_ioremap(qp->remote_buf, remote_size, scifdev);
-       if (!remote_q) {
-               err = -EIO;
-               goto iounmap;
-       }
-       qp->remote_qp->local_write = 0;
-       /*
-        * To setup the outbound_q, the buffer lives in remote memory,
-        * the read pointer is local, the write pointer is remote
-        */
-       scif_rb_init(&qp->outbound_q,
-                    &qp->local_read,
-                    &qp->remote_qp->local_write,
-                    remote_q,
-                    get_count_order(remote_size));
-       local_q = kzalloc(local_size, GFP_KERNEL);
-       if (!local_q) {
-               err = -ENOMEM;
-               goto iounmap_1;
-       }
-       err = scif_map_single(&qp->local_buf, local_q, scifdev, local_size);
-       if (err)
-               goto kfree;
-       qp->remote_qp->local_read = 0;
-       /*
-        * To setup the inbound_q, the buffer lives locally, the read pointer
-        * is remote and the write pointer is local
-        */
-       scif_rb_init(&qp->inbound_q,
-                    &qp->remote_qp->local_read,
-                    &qp->local_write,
-                    local_q, get_count_order(local_size));
-       err = scif_map_single(qp_offset, qp, scifdev,
-                             sizeof(struct scif_qp));
-       if (err)
-               goto unmap;
-       qp->local_qp = *qp_offset;
-       return err;
-unmap:
-       scif_unmap_single(qp->local_buf, scifdev, local_size);
-       qp->local_buf = 0;
-kfree:
-       kfree(local_q);
-iounmap_1:
-       scif_iounmap(remote_q, remote_size, scifdev);
-       qp->outbound_q.rb_base = NULL;
-iounmap:
-       scif_iounmap(qp->remote_qp, sizeof(struct scif_qp), scifdev);
-       qp->remote_qp = NULL;
-       return err;
-}
-
-int scif_setup_qp_connect_response(struct scif_dev *scifdev,
-                                  struct scif_qp *qp, u64 payload)
-{
-       int err = 0;
-       void *r_buf;
-       int remote_size;
-       phys_addr_t tmp_phys;
-
-       qp->remote_qp = scif_ioremap(payload, sizeof(struct scif_qp), scifdev);
-
-       if (!qp->remote_qp) {
-               err = -ENOMEM;
-               goto error;
-       }
-
-       if (qp->remote_qp->magic != SCIFEP_MAGIC) {
-               dev_err(&scifdev->sdev->dev,
-                       "SCIFEP_MAGIC mismatch between self %d remote %d\n",
-                       scif_dev[scif_info.nodeid].node, scifdev->node);
-               err = -ENODEV;
-               goto error;
-       }
-
-       tmp_phys = qp->remote_qp->local_buf;
-       remote_size = qp->remote_qp->inbound_q.size;
-       r_buf = scif_ioremap(tmp_phys, remote_size, scifdev);
-
-       if (!r_buf)
-               return -EIO;
-
-       qp->local_read = 0;
-       scif_rb_init(&qp->outbound_q,
-                    &qp->local_read,
-                    &qp->remote_qp->local_write,
-                    r_buf,
-                    get_count_order(remote_size));
-       /*
-        * Because the node QP may already be processing an INIT message, set
-        * the read pointer so the cached read offset isn't lost
-        */
-       qp->remote_qp->local_read = qp->inbound_q.current_read_offset;
-       /*
-        * resetup the inbound_q now that we know where the
-        * inbound_read really is.
-        */
-       scif_rb_init(&qp->inbound_q,
-                    &qp->remote_qp->local_read,
-                    &qp->local_write,
-                    qp->inbound_q.rb_base,
-                    get_count_order(qp->inbound_q.size));
-error:
-       return err;
-}
-
-static __always_inline void
-scif_send_msg_intr(struct scif_dev *scifdev)
-{
-       struct scif_hw_dev *sdev = scifdev->sdev;
-
-       if (scifdev_is_p2p(scifdev))
-               sdev->hw_ops->send_p2p_intr(sdev, scifdev->rdb, &scifdev->mmio);
-       else
-               sdev->hw_ops->send_intr(sdev, scifdev->rdb);
-}
-
-int scif_qp_response(phys_addr_t phys, struct scif_dev *scifdev)
-{
-       int err = 0;
-       struct scifmsg msg;
-
-       err = scif_setup_qp_connect_response(scifdev, scifdev->qpairs, phys);
-       if (!err) {
-               /*
-                * Now that everything is setup and mapped, we're ready
-                * to tell the peer about our queue's location
-                */
-               msg.uop = SCIF_INIT;
-               msg.dst.node = scifdev->node;
-               err = scif_nodeqp_send(scifdev, &msg);
-       }
-       return err;
-}
-
-void scif_send_exit(struct scif_dev *scifdev)
-{
-       struct scifmsg msg;
-       int ret;
-
-       scifdev->exit = OP_IN_PROGRESS;
-       msg.uop = SCIF_EXIT;
-       msg.src.node = scif_info.nodeid;
-       msg.dst.node = scifdev->node;
-       ret = scif_nodeqp_send(scifdev, &msg);
-       if (ret)
-               goto done;
-       /* Wait for a SCIF_EXIT_ACK message */
-       wait_event_timeout(scif_info.exitwq, scifdev->exit == OP_COMPLETED,
-                          SCIF_NODE_ALIVE_TIMEOUT);
-done:
-       scifdev->exit = OP_IDLE;
-}
-
-int scif_setup_qp(struct scif_dev *scifdev)
-{
-       int err = 0;
-       int local_size;
-       struct scif_qp *qp;
-
-       local_size = SCIF_NODE_QP_SIZE;
-
-       qp = kzalloc(sizeof(*qp), GFP_KERNEL);
-       if (!qp) {
-               err = -ENOMEM;
-               return err;
-       }
-       qp->magic = SCIFEP_MAGIC;
-       scifdev->qpairs = qp;
-       err = scif_setup_qp_connect(qp, &scifdev->qp_dma_addr,
-                                   local_size, scifdev);
-       if (err)
-               goto free_qp;
-       /*
-        * We're as setup as we can be. The inbound_q is setup, w/o a usable
-        * outbound q.  When we get a message, the read_ptr will be updated,
-        * and we will pull the message.
-        */
-       return err;
-free_qp:
-       kfree(scifdev->qpairs);
-       scifdev->qpairs = NULL;
-       return err;
-}
-
-static void scif_p2p_freesg(struct scatterlist *sg)
-{
-       kfree(sg);
-}
-
-static struct scatterlist *
-scif_p2p_setsg(phys_addr_t pa, int page_size, int page_cnt)
-{
-       struct scatterlist *sg;
-       struct page *page;
-       int i;
-
-       sg = kmalloc_array(page_cnt, sizeof(struct scatterlist), GFP_KERNEL);
-       if (!sg)
-               return NULL;
-       sg_init_table(sg, page_cnt);
-       for (i = 0; i < page_cnt; i++) {
-               page = pfn_to_page(pa >> PAGE_SHIFT);
-               sg_set_page(&sg[i], page, page_size, 0);
-               pa += page_size;
-       }
-       return sg;
-}
-
-/* Init p2p mappings required to access peerdev from scifdev */
-static struct scif_p2p_info *
-scif_init_p2p_info(struct scif_dev *scifdev, struct scif_dev *peerdev)
-{
-       struct scif_p2p_info *p2p;
-       int num_mmio_pages, num_aper_pages, sg_page_shift, err, num_aper_chunks;
-       struct scif_hw_dev *psdev = peerdev->sdev;
-       struct scif_hw_dev *sdev = scifdev->sdev;
-
-       num_mmio_pages = psdev->mmio->len >> PAGE_SHIFT;
-       num_aper_pages = psdev->aper->len >> PAGE_SHIFT;
-
-       p2p = kzalloc(sizeof(*p2p), GFP_KERNEL);
-       if (!p2p)
-               return NULL;
-       p2p->ppi_sg[SCIF_PPI_MMIO] = scif_p2p_setsg(psdev->mmio->pa,
-                                                   PAGE_SIZE, num_mmio_pages);
-       if (!p2p->ppi_sg[SCIF_PPI_MMIO])
-               goto free_p2p;
-       p2p->sg_nentries[SCIF_PPI_MMIO] = num_mmio_pages;
-       sg_page_shift = get_order(min(psdev->aper->len, (u64)(1 << 30)));
-       num_aper_chunks = num_aper_pages >> (sg_page_shift - PAGE_SHIFT);
-       p2p->ppi_sg[SCIF_PPI_APER] = scif_p2p_setsg(psdev->aper->pa,
-                                                   1 << sg_page_shift,
-                                                   num_aper_chunks);
-       p2p->sg_nentries[SCIF_PPI_APER] = num_aper_chunks;
-       err = dma_map_sg(&sdev->dev, p2p->ppi_sg[SCIF_PPI_MMIO],
-                        num_mmio_pages, PCI_DMA_BIDIRECTIONAL);
-       if (err != num_mmio_pages)
-               goto scif_p2p_free;
-       err = dma_map_sg(&sdev->dev, p2p->ppi_sg[SCIF_PPI_APER],
-                        num_aper_chunks, PCI_DMA_BIDIRECTIONAL);
-       if (err != num_aper_chunks)
-               goto dma_unmap;
-       p2p->ppi_da[SCIF_PPI_MMIO] = sg_dma_address(p2p->ppi_sg[SCIF_PPI_MMIO]);
-       p2p->ppi_da[SCIF_PPI_APER] = sg_dma_address(p2p->ppi_sg[SCIF_PPI_APER]);
-       p2p->ppi_len[SCIF_PPI_MMIO] = num_mmio_pages;
-       p2p->ppi_len[SCIF_PPI_APER] = num_aper_pages;
-       p2p->ppi_peer_id = peerdev->node;
-       return p2p;
-dma_unmap:
-       dma_unmap_sg(&sdev->dev, p2p->ppi_sg[SCIF_PPI_MMIO],
-                    p2p->sg_nentries[SCIF_PPI_MMIO], DMA_BIDIRECTIONAL);
-scif_p2p_free:
-       scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_MMIO]);
-       scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_APER]);
-free_p2p:
-       kfree(p2p);
-       return NULL;
-}
-
-/* Uninitialize and release resources from a p2p mapping */
-static void scif_deinit_p2p_info(struct scif_dev *scifdev,
-                                struct scif_p2p_info *p2p)
-{
-       struct scif_hw_dev *sdev = scifdev->sdev;
-
-       dma_unmap_sg(&sdev->dev, p2p->ppi_sg[SCIF_PPI_MMIO],
-                    p2p->sg_nentries[SCIF_PPI_MMIO], DMA_BIDIRECTIONAL);
-       dma_unmap_sg(&sdev->dev, p2p->ppi_sg[SCIF_PPI_APER],
-                    p2p->sg_nentries[SCIF_PPI_APER], DMA_BIDIRECTIONAL);
-       scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_MMIO]);
-       scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_APER]);
-       kfree(p2p);
-}
-
-/**
- * scif_node_connect: Respond to SCIF_NODE_CONNECT interrupt message
- * @scifdev: SCIF device
- * @dst: Destination node
- *
- * Connect the src and dst node by setting up the p2p connection
- * between them. Management node here acts like a proxy.
- */
-static void scif_node_connect(struct scif_dev *scifdev, int dst)
-{
-       struct scif_dev *dev_j = scifdev;
-       struct scif_dev *dev_i = NULL;
-       struct scif_p2p_info *p2p_ij = NULL;    /* bus addr for j from i */
-       struct scif_p2p_info *p2p_ji = NULL;    /* bus addr for i from j */
-       struct scif_p2p_info *p2p;
-       struct list_head *pos, *tmp;
-       struct scifmsg msg;
-       int err;
-       u64 tmppayload;
-
-       if (dst < 1 || dst > scif_info.maxid)
-               return;
-
-       dev_i = &scif_dev[dst];
-
-       if (!_scifdev_alive(dev_i))
-               return;
-       /*
-        * If the p2p connection is already setup or in the process of setting
-        * up then just ignore this request. The requested node will get
-        * informed by SCIF_NODE_ADD_ACK or SCIF_NODE_ADD_NACK
-        */
-       if (!list_empty(&dev_i->p2p)) {
-               list_for_each_safe(pos, tmp, &dev_i->p2p) {
-                       p2p = list_entry(pos, struct scif_p2p_info, ppi_list);
-                       if (p2p->ppi_peer_id == dev_j->node)
-                               return;
-               }
-       }
-       p2p_ij = scif_init_p2p_info(dev_i, dev_j);
-       if (!p2p_ij)
-               return;
-       p2p_ji = scif_init_p2p_info(dev_j, dev_i);
-       if (!p2p_ji) {
-               scif_deinit_p2p_info(dev_i, p2p_ij);
-               return;
-       }
-       list_add_tail(&p2p_ij->ppi_list, &dev_i->p2p);
-       list_add_tail(&p2p_ji->ppi_list, &dev_j->p2p);
-
-       /*
-        * Send a SCIF_NODE_ADD to dev_i, pass it its bus address
-        * as seen from dev_j
-        */
-       msg.uop = SCIF_NODE_ADD;
-       msg.src.node = dev_j->node;
-       msg.dst.node = dev_i->node;
-
-       msg.payload[0] = p2p_ji->ppi_da[SCIF_PPI_APER];
-       msg.payload[1] = p2p_ij->ppi_da[SCIF_PPI_MMIO];
-       msg.payload[2] = p2p_ij->ppi_da[SCIF_PPI_APER];
-       msg.payload[3] = p2p_ij->ppi_len[SCIF_PPI_APER] << PAGE_SHIFT;
-
-       err = scif_nodeqp_send(dev_i,  &msg);
-       if (err) {
-               dev_err(&scifdev->sdev->dev,
-                       "%s %d error %d\n", __func__, __LINE__, err);
-               return;
-       }
-
-       /* Same as above but to dev_j */
-       msg.uop = SCIF_NODE_ADD;
-       msg.src.node = dev_i->node;
-       msg.dst.node = dev_j->node;
-
-       tmppayload = msg.payload[0];
-       msg.payload[0] = msg.payload[2];
-       msg.payload[2] = tmppayload;
-       msg.payload[1] = p2p_ji->ppi_da[SCIF_PPI_MMIO];
-       msg.payload[3] = p2p_ji->ppi_len[SCIF_PPI_APER] << PAGE_SHIFT;
-
-       scif_nodeqp_send(dev_j, &msg);
-}
-
-static void scif_p2p_setup(void)
-{
-       int i, j;
-
-       if (!scif_info.p2p_enable)
-               return;
-
-       for (i = 1; i <= scif_info.maxid; i++)
-               if (!_scifdev_alive(&scif_dev[i]))
-                       return;
-
-       for (i = 1; i <= scif_info.maxid; i++) {
-               for (j = 1; j <= scif_info.maxid; j++) {
-                       struct scif_dev *scifdev = &scif_dev[i];
-
-                       if (i == j)
-                               continue;
-                       scif_node_connect(scifdev, j);
-               }
-       }
-}
-
-static char *message_types[] = {"BAD",
-                               "INIT",
-                               "EXIT",
-                               "SCIF_EXIT_ACK",
-                               "SCIF_NODE_ADD",
-                               "SCIF_NODE_ADD_ACK",
-                               "SCIF_NODE_ADD_NACK",
-                               "REMOVE_NODE",
-                               "REMOVE_NODE_ACK",
-                               "CNCT_REQ",
-                               "CNCT_GNT",
-                               "CNCT_GNTACK",
-                               "CNCT_GNTNACK",
-                               "CNCT_REJ",
-                               "DISCNCT",
-                               "DISCNT_ACK",
-                               "CLIENT_SENT",
-                               "CLIENT_RCVD",
-                               "SCIF_GET_NODE_INFO",
-                               "REGISTER",
-                               "REGISTER_ACK",
-                               "REGISTER_NACK",
-                               "UNREGISTER",
-                               "UNREGISTER_ACK",
-                               "UNREGISTER_NACK",
-                               "ALLOC_REQ",
-                               "ALLOC_GNT",
-                               "ALLOC_REJ",
-                               "FREE_PHYS",
-                               "FREE_VIRT",
-                               "MUNMAP",
-                               "MARK",
-                               "MARK_ACK",
-                               "MARK_NACK",
-                               "WAIT",
-                               "WAIT_ACK",
-                               "WAIT_NACK",
-                               "SIGNAL_LOCAL",
-                               "SIGNAL_REMOTE",
-                               "SIG_ACK",
-                               "SIG_NACK"};
-
-static void
-scif_display_message(struct scif_dev *scifdev, struct scifmsg *msg,
-                    const char *label)
-{
-       if (!scif_info.en_msg_log)
-               return;
-       if (msg->uop > SCIF_MAX_MSG) {
-               dev_err(&scifdev->sdev->dev,
-                       "%s: unknown msg type %d\n", label, msg->uop);
-               return;
-       }
-       dev_info(&scifdev->sdev->dev,
-                "%s: msg type %s, src %d:%d, dest %d:%d payload 0x%llx:0x%llx:0x%llx:0x%llx\n",
-                label, message_types[msg->uop], msg->src.node, msg->src.port,
-                msg->dst.node, msg->dst.port, msg->payload[0], msg->payload[1],
-                msg->payload[2], msg->payload[3]);
-}
-
-int _scif_nodeqp_send(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_qp *qp = scifdev->qpairs;
-       int err = -ENOMEM, loop_cnt = 0;
-
-       scif_display_message(scifdev, msg, "Sent");
-       if (!qp) {
-               err = -EINVAL;
-               goto error;
-       }
-       spin_lock(&qp->send_lock);
-
-       while ((err = scif_rb_write(&qp->outbound_q,
-                                   msg, sizeof(struct scifmsg)))) {
-               mdelay(1);
-#define SCIF_NODEQP_SEND_TO_MSEC (3 * 1000)
-               if (loop_cnt++ > (SCIF_NODEQP_SEND_TO_MSEC)) {
-                       err = -ENODEV;
-                       break;
-               }
-       }
-       if (!err)
-               scif_rb_commit(&qp->outbound_q);
-       spin_unlock(&qp->send_lock);
-       if (!err) {
-               if (scifdev_self(scifdev))
-                       /*
-                        * For loopback we need to emulate an interrupt by
-                        * queuing work for the queue handling real node
-                        * Qp interrupts.
-                        */
-                       queue_work(scifdev->intr_wq, &scifdev->intr_bh);
-               else
-                       scif_send_msg_intr(scifdev);
-       }
-error:
-       if (err)
-               dev_dbg(&scifdev->sdev->dev,
-                       "%s %d error %d uop %d\n",
-                        __func__, __LINE__, err, msg->uop);
-       return err;
-}
-
-/**
- * scif_nodeqp_send - Send a message on the node queue pair
- * @scifdev: Scif Device.
- * @msg: The message to be sent.
- */
-int scif_nodeqp_send(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       int err;
-       struct device *spdev = NULL;
-
-       if (msg->uop > SCIF_EXIT_ACK) {
-               /* Don't send messages once the exit flow has begun */
-               if (OP_IDLE != scifdev->exit)
-                       return -ENODEV;
-               spdev = scif_get_peer_dev(scifdev);
-               if (IS_ERR(spdev)) {
-                       err = PTR_ERR(spdev);
-                       return err;
-               }
-       }
-       err = _scif_nodeqp_send(scifdev, msg);
-       if (msg->uop > SCIF_EXIT_ACK)
-               scif_put_peer_dev(spdev);
-       return err;
-}
-
-/*
- * scif_misc_handler:
- *
- * Work queue handler for servicing miscellaneous SCIF tasks.
- * Examples include:
- * 1) Remote fence requests.
- * 2) Destruction of temporary registered windows
- *    created during scif_vreadfrom()/scif_vwriteto().
- * 3) Cleanup of zombie endpoints.
- */
-void scif_misc_handler(struct work_struct *work)
-{
-       scif_rma_handle_remote_fences();
-       scif_rma_destroy_windows();
-       scif_rma_destroy_tcw_invalid();
-       scif_cleanup_zombie_epd();
-}
-
-/**
- * scif_init() - Respond to SCIF_INIT interrupt message
- * @scifdev:    Remote SCIF device node
- * @msg:        Interrupt message
- */
-static __always_inline void
-scif_init(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       /*
-        * Allow the thread waiting for device page updates for the peer QP DMA
-        * address to complete initializing the inbound_q.
-        */
-       flush_delayed_work(&scifdev->qp_dwork);
-
-       scif_peer_register_device(scifdev);
-
-       if (scif_is_mgmt_node()) {
-               mutex_lock(&scif_info.conflock);
-               scif_p2p_setup();
-               mutex_unlock(&scif_info.conflock);
-       }
-}
-
-/**
- * scif_exit() - Respond to SCIF_EXIT interrupt message
- * @scifdev:    Remote SCIF device node
- * @unused:     Interrupt message (unused)
- *
- * This function stops the SCIF interface for the node which sent
- * the SCIF_EXIT message and starts waiting for that node to
- * resetup the queue pair again.
- */
-static __always_inline void
-scif_exit(struct scif_dev *scifdev, struct scifmsg *unused)
-{
-       scifdev->exit_ack_pending = true;
-       if (scif_is_mgmt_node())
-               scif_disconnect_node(scifdev->node, false);
-       else
-               scif_stop(scifdev);
-       schedule_delayed_work(&scifdev->qp_dwork,
-                             msecs_to_jiffies(1000));
-}
-
-/**
- * scif_exitack() - Respond to SCIF_EXIT_ACK interrupt message
- * @scifdev:    Remote SCIF device node
- * @unused:     Interrupt message (unused)
- *
- */
-static __always_inline void
-scif_exit_ack(struct scif_dev *scifdev, struct scifmsg *unused)
-{
-       scifdev->exit = OP_COMPLETED;
-       wake_up(&scif_info.exitwq);
-}
-
-/**
- * scif_node_add() - Respond to SCIF_NODE_ADD interrupt message
- * @scifdev:    Remote SCIF device node
- * @msg:        Interrupt message
- *
- * When the mgmt node driver has finished initializing a MIC node queue pair it
- * marks the node as online. It then looks for all currently online MIC cards
- * and send a SCIF_NODE_ADD message to identify the ID of the new card for
- * peer to peer initialization
- *
- * The local node allocates its incoming queue and sends its address in the
- * SCIF_NODE_ADD_ACK message back to the mgmt node, the mgmt node "reflects"
- * this message to the new node
- */
-static __always_inline void
-scif_node_add(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_dev *newdev;
-       dma_addr_t qp_offset;
-       int qp_connect;
-       struct scif_hw_dev *sdev;
-
-       dev_dbg(&scifdev->sdev->dev,
-               "Scifdev %d:%d received NODE_ADD msg for node %d\n",
-               scifdev->node, msg->dst.node, msg->src.node);
-       dev_dbg(&scifdev->sdev->dev,
-               "Remote address for this node's aperture %llx\n",
-               msg->payload[0]);
-       newdev = &scif_dev[msg->src.node];
-       newdev->node = msg->src.node;
-       newdev->sdev = scif_dev[SCIF_MGMT_NODE].sdev;
-       sdev = newdev->sdev;
-
-       if (scif_setup_intr_wq(newdev)) {
-               dev_err(&scifdev->sdev->dev,
-                       "failed to setup interrupts for %d\n", msg->src.node);
-               goto interrupt_setup_error;
-       }
-       newdev->mmio.va = ioremap(msg->payload[1], sdev->mmio->len);
-       if (!newdev->mmio.va) {
-               dev_err(&scifdev->sdev->dev,
-                       "failed to map mmio for %d\n", msg->src.node);
-               goto mmio_map_error;
-       }
-       newdev->qpairs = kzalloc(sizeof(*newdev->qpairs), GFP_KERNEL);
-       if (!newdev->qpairs)
-               goto qp_alloc_error;
-       /*
-        * Set the base address of the remote node's memory since it gets
-        * added to qp_offset
-        */
-       newdev->base_addr = msg->payload[0];
-
-       qp_connect = scif_setup_qp_connect(newdev->qpairs, &qp_offset,
-                                          SCIF_NODE_QP_SIZE, newdev);
-       if (qp_connect) {
-               dev_err(&scifdev->sdev->dev,
-                       "failed to setup qp_connect %d\n", qp_connect);
-               goto qp_connect_error;
-       }
-
-       newdev->db = sdev->hw_ops->next_db(sdev);
-       newdev->cookie = sdev->hw_ops->request_irq(sdev, scif_intr_handler,
-                                                  "SCIF_INTR", newdev,
-                                                  newdev->db);
-       if (IS_ERR(newdev->cookie))
-               goto qp_connect_error;
-       newdev->qpairs->magic = SCIFEP_MAGIC;
-       newdev->qpairs->qp_state = SCIF_QP_OFFLINE;
-
-       msg->uop = SCIF_NODE_ADD_ACK;
-       msg->dst.node = msg->src.node;
-       msg->src.node = scif_info.nodeid;
-       msg->payload[0] = qp_offset;
-       msg->payload[2] = newdev->db;
-       scif_nodeqp_send(&scif_dev[SCIF_MGMT_NODE], msg);
-       return;
-qp_connect_error:
-       kfree(newdev->qpairs);
-       newdev->qpairs = NULL;
-qp_alloc_error:
-       iounmap(newdev->mmio.va);
-       newdev->mmio.va = NULL;
-mmio_map_error:
-interrupt_setup_error:
-       dev_err(&scifdev->sdev->dev,
-               "node add failed for node %d\n", msg->src.node);
-       msg->uop = SCIF_NODE_ADD_NACK;
-       msg->dst.node = msg->src.node;
-       msg->src.node = scif_info.nodeid;
-       scif_nodeqp_send(&scif_dev[SCIF_MGMT_NODE], msg);
-}
-
-void scif_poll_qp_state(struct work_struct *work)
-{
-#define SCIF_NODE_QP_RETRY 100
-#define SCIF_NODE_QP_TIMEOUT 100
-       struct scif_dev *peerdev = container_of(work, struct scif_dev,
-                                                       p2p_dwork.work);
-       struct scif_qp *qp = &peerdev->qpairs[0];
-
-       if (qp->qp_state != SCIF_QP_ONLINE ||
-           qp->remote_qp->qp_state != SCIF_QP_ONLINE) {
-               if (peerdev->p2p_retry++ == SCIF_NODE_QP_RETRY) {
-                       dev_err(&peerdev->sdev->dev,
-                               "Warning: QP check timeout with state %d\n",
-                               qp->qp_state);
-                       goto timeout;
-               }
-               schedule_delayed_work(&peerdev->p2p_dwork,
-                                     msecs_to_jiffies(SCIF_NODE_QP_TIMEOUT));
-               return;
-       }
-       return;
-timeout:
-       dev_err(&peerdev->sdev->dev,
-               "%s %d remote node %d offline,  state = 0x%x\n",
-               __func__, __LINE__, peerdev->node, qp->qp_state);
-       qp->remote_qp->qp_state = SCIF_QP_OFFLINE;
-       scif_peer_unregister_device(peerdev);
-       scif_cleanup_scifdev(peerdev);
-}
-
-/**
- * scif_node_add_ack() - Respond to SCIF_NODE_ADD_ACK interrupt message
- * @scifdev:    Remote SCIF device node
- * @msg:        Interrupt message
- *
- * After a MIC node receives the SCIF_NODE_ADD_ACK message it send this
- * message to the mgmt node to confirm the sequence is finished.
- *
- */
-static __always_inline void
-scif_node_add_ack(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_dev *peerdev;
-       struct scif_qp *qp;
-       struct scif_dev *dst_dev = &scif_dev[msg->dst.node];
-
-       dev_dbg(&scifdev->sdev->dev,
-               "Scifdev %d received SCIF_NODE_ADD_ACK msg src %d dst %d\n",
-               scifdev->node, msg->src.node, msg->dst.node);
-       dev_dbg(&scifdev->sdev->dev,
-               "payload %llx %llx %llx %llx\n", msg->payload[0],
-               msg->payload[1], msg->payload[2], msg->payload[3]);
-       if (scif_is_mgmt_node()) {
-               /*
-                * the lock serializes with scif_qp_response_ack. The mgmt node
-                * is forwarding the NODE_ADD_ACK message from src to dst we
-                * need to make sure that the dst has already received a
-                * NODE_ADD for src and setup its end of the qp to dst
-                */
-               mutex_lock(&scif_info.conflock);
-               msg->payload[1] = scif_info.maxid;
-               scif_nodeqp_send(dst_dev, msg);
-               mutex_unlock(&scif_info.conflock);
-               return;
-       }
-       peerdev = &scif_dev[msg->src.node];
-       peerdev->sdev = scif_dev[SCIF_MGMT_NODE].sdev;
-       peerdev->node = msg->src.node;
-
-       qp = &peerdev->qpairs[0];
-
-       if ((scif_setup_qp_connect_response(peerdev, &peerdev->qpairs[0],
-                                           msg->payload[0])))
-               goto local_error;
-       peerdev->rdb = msg->payload[2];
-       qp->remote_qp->qp_state = SCIF_QP_ONLINE;
-
-       scif_peer_register_device(peerdev);
-
-       schedule_delayed_work(&peerdev->p2p_dwork, 0);
-       return;
-local_error:
-       scif_cleanup_scifdev(peerdev);
-}
-
-/**
- * scif_node_add_nack: Respond to SCIF_NODE_ADD_NACK interrupt message
- * @scifdev:    Remote SCIF device node
- * @msg:        Interrupt message
- *
- * SCIF_NODE_ADD failed, so inform the waiting wq.
- */
-static __always_inline void
-scif_node_add_nack(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       if (scif_is_mgmt_node()) {
-               struct scif_dev *dst_dev = &scif_dev[msg->dst.node];
-
-               dev_dbg(&scifdev->sdev->dev,
-                       "SCIF_NODE_ADD_NACK received from %d\n", scifdev->node);
-               scif_nodeqp_send(dst_dev, msg);
-       }
-}
-
-/**
- * scif_node_remove: Handle SCIF_NODE_REMOVE message
- * @scifdev:    Remote SCIF device node
- * @msg: Interrupt message
- *
- * Handle node removal.
- */
-static __always_inline void
-scif_node_remove(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       int node = msg->payload[0];
-       struct scif_dev *scdev = &scif_dev[node];
-
-       scdev->node_remove_ack_pending = true;
-       scif_handle_remove_node(node);
-}
-
-/**
- * scif_node_remove_ack: Handle SCIF_NODE_REMOVE_ACK message
- * @scifdev:    Remote SCIF device node
- * @msg: Interrupt message
- *
- * The peer has acked a SCIF_NODE_REMOVE message.
- */
-static __always_inline void
-scif_node_remove_ack(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_dev *sdev = &scif_dev[msg->payload[0]];
-
-       atomic_inc(&sdev->disconn_rescnt);
-       wake_up(&sdev->disconn_wq);
-}
-
-/**
- * scif_get_node_info: Respond to SCIF_GET_NODE_INFO interrupt message
- * @scifdev:    Remote SCIF device node
- * @msg:        Interrupt message
- *
- * Retrieve node info i.e maxid and total from the mgmt node.
- */
-static __always_inline void
-scif_get_node_info_resp(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       if (scif_is_mgmt_node()) {
-               swap(msg->dst.node, msg->src.node);
-               mutex_lock(&scif_info.conflock);
-               msg->payload[1] = scif_info.maxid;
-               msg->payload[2] = scif_info.total;
-               mutex_unlock(&scif_info.conflock);
-               scif_nodeqp_send(scifdev, msg);
-       } else {
-               struct completion *node_info =
-                       (struct completion *)msg->payload[3];
-
-               mutex_lock(&scif_info.conflock);
-               scif_info.maxid = msg->payload[1];
-               scif_info.total = msg->payload[2];
-               complete_all(node_info);
-               mutex_unlock(&scif_info.conflock);
-       }
-}
-
-static void
-scif_msg_unknown(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       /* Bogus Node Qp Message? */
-       dev_err(&scifdev->sdev->dev,
-               "Unknown message 0x%xn scifdev->node 0x%x\n",
-               msg->uop, scifdev->node);
-}
-
-static void (*scif_intr_func[SCIF_MAX_MSG + 1])
-           (struct scif_dev *, struct scifmsg *msg) = {
-       scif_msg_unknown,       /* Error */
-       scif_init,              /* SCIF_INIT */
-       scif_exit,              /* SCIF_EXIT */
-       scif_exit_ack,          /* SCIF_EXIT_ACK */
-       scif_node_add,          /* SCIF_NODE_ADD */
-       scif_node_add_ack,      /* SCIF_NODE_ADD_ACK */
-       scif_node_add_nack,     /* SCIF_NODE_ADD_NACK */
-       scif_node_remove,       /* SCIF_NODE_REMOVE */
-       scif_node_remove_ack,   /* SCIF_NODE_REMOVE_ACK */
-       scif_cnctreq,           /* SCIF_CNCT_REQ */
-       scif_cnctgnt,           /* SCIF_CNCT_GNT */
-       scif_cnctgnt_ack,       /* SCIF_CNCT_GNTACK */
-       scif_cnctgnt_nack,      /* SCIF_CNCT_GNTNACK */
-       scif_cnctrej,           /* SCIF_CNCT_REJ */
-       scif_discnct,           /* SCIF_DISCNCT */
-       scif_discnt_ack,        /* SCIF_DISCNT_ACK */
-       scif_clientsend,        /* SCIF_CLIENT_SENT */
-       scif_clientrcvd,        /* SCIF_CLIENT_RCVD */
-       scif_get_node_info_resp,/* SCIF_GET_NODE_INFO */
-       scif_recv_reg,          /* SCIF_REGISTER */
-       scif_recv_reg_ack,      /* SCIF_REGISTER_ACK */
-       scif_recv_reg_nack,     /* SCIF_REGISTER_NACK */
-       scif_recv_unreg,        /* SCIF_UNREGISTER */
-       scif_recv_unreg_ack,    /* SCIF_UNREGISTER_ACK */
-       scif_recv_unreg_nack,   /* SCIF_UNREGISTER_NACK */
-       scif_alloc_req,         /* SCIF_ALLOC_REQ */
-       scif_alloc_gnt_rej,     /* SCIF_ALLOC_GNT */
-       scif_alloc_gnt_rej,     /* SCIF_ALLOC_REJ */
-       scif_free_virt,         /* SCIF_FREE_VIRT */
-       scif_recv_munmap,       /* SCIF_MUNMAP */
-       scif_recv_mark,         /* SCIF_MARK */
-       scif_recv_mark_resp,    /* SCIF_MARK_ACK */
-       scif_recv_mark_resp,    /* SCIF_MARK_NACK */
-       scif_recv_wait,         /* SCIF_WAIT */
-       scif_recv_wait_resp,    /* SCIF_WAIT_ACK */
-       scif_recv_wait_resp,    /* SCIF_WAIT_NACK */
-       scif_recv_sig_local,    /* SCIF_SIG_LOCAL */
-       scif_recv_sig_remote,   /* SCIF_SIG_REMOTE */
-       scif_recv_sig_resp,     /* SCIF_SIG_ACK */
-       scif_recv_sig_resp,     /* SCIF_SIG_NACK */
-};
-
-static int scif_max_msg_id = SCIF_MAX_MSG;
-/**
- * scif_nodeqp_msg_handler() - Common handler for node messages
- * @scifdev: Remote device to respond to
- * @qp: Remote memory pointer
- * @msg: The message to be handled.
- *
- * This routine calls the appropriate routine to handle a Node Qp
- * message receipt
- */
-static void
-scif_nodeqp_msg_handler(struct scif_dev *scifdev,
-                       struct scif_qp *qp, struct scifmsg *msg)
-{
-       scif_display_message(scifdev, msg, "Rcvd");
-
-       if (msg->uop > (u32)scif_max_msg_id) {
-               /* Bogus Node Qp Message? */
-               dev_err(&scifdev->sdev->dev,
-                       "Unknown message 0x%xn scifdev->node 0x%x\n",
-                       msg->uop, scifdev->node);
-               return;
-       }
-
-       scif_intr_func[msg->uop](scifdev, msg);
-}
-
-/**
- * scif_nodeqp_intrhandler() - Interrupt handler for node messages
- * @scifdev:    Remote device to respond to
- * @qp:         Remote memory pointer
- *
- * This routine is triggered by the interrupt mechanism.  It reads
- * messages from the node queue RB and calls the Node QP Message handling
- * routine.
- */
-void scif_nodeqp_intrhandler(struct scif_dev *scifdev, struct scif_qp *qp)
-{
-       struct scifmsg msg;
-       int read_size;
-
-       do {
-               read_size = scif_rb_get_next(&qp->inbound_q, &msg, sizeof(msg));
-               if (!read_size)
-                       break;
-               scif_nodeqp_msg_handler(scifdev, qp, &msg);
-               /*
-                * The node queue pair is unmapped so skip the read pointer
-                * update after receipt of a SCIF_EXIT_ACK
-                */
-               if (SCIF_EXIT_ACK == msg.uop)
-                       break;
-               scif_rb_update_read_ptr(&qp->inbound_q);
-       } while (1);
-}
-
-/**
- * scif_loopb_wq_handler - Loopback Workqueue Handler.
- * @unused: loop back work (unused)
- *
- * This work queue routine is invoked by the loopback work queue handler.
- * It grabs the recv lock, dequeues any available messages from the head
- * of the loopback message list, calls the node QP message handler,
- * waits for it to return, then frees up this message and dequeues more
- * elements of the list if available.
- */
-static void scif_loopb_wq_handler(struct work_struct *unused)
-{
-       struct scif_dev *scifdev = scif_info.loopb_dev;
-       struct scif_qp *qp = scifdev->qpairs;
-       struct scif_loopb_msg *msg;
-
-       do {
-               msg = NULL;
-               spin_lock(&qp->recv_lock);
-               if (!list_empty(&scif_info.loopb_recv_q)) {
-                       msg = list_first_entry(&scif_info.loopb_recv_q,
-                                              struct scif_loopb_msg,
-                                              list);
-                       list_del(&msg->list);
-               }
-               spin_unlock(&qp->recv_lock);
-
-               if (msg) {
-                       scif_nodeqp_msg_handler(scifdev, qp, &msg->msg);
-                       kfree(msg);
-               }
-       } while (msg);
-}
-
-/**
- * scif_loopb_msg_handler() - Workqueue handler for loopback messages.
- * @scifdev: SCIF device
- * @qp: Queue pair.
- *
- * This work queue routine is triggered when a loopback message is received.
- *
- * We need special handling for receiving Node Qp messages on a loopback SCIF
- * device via two workqueues for receiving messages.
- *
- * The reason we need the extra workqueue which is not required with *normal*
- * non-loopback SCIF devices is the potential classic deadlock described below:
- *
- * Thread A tries to send a message on a loopback SCIF device and blocks since
- * there is no space in the RB while it has the send_lock held or another
- * lock called lock X for example.
- *
- * Thread B: The Loopback Node QP message receive workqueue receives the message
- * and tries to send a message (eg an ACK) to the loopback SCIF device. It tries
- * to grab the send lock again or lock X and deadlocks with Thread A. The RB
- * cannot be drained any further due to this classic deadlock.
- *
- * In order to avoid deadlocks as mentioned above we have an extra level of
- * indirection achieved by having two workqueues.
- * 1) The first workqueue whose handler is scif_loopb_msg_handler reads
- * messages from the Node QP RB, adds them to a list and queues work for the
- * second workqueue.
- *
- * 2) The second workqueue whose handler is scif_loopb_wq_handler dequeues
- * messages from the list, handles them, frees up the memory and dequeues
- * more elements from the list if possible.
- */
-int
-scif_loopb_msg_handler(struct scif_dev *scifdev, struct scif_qp *qp)
-{
-       int read_size;
-       struct scif_loopb_msg *msg;
-
-       do {
-               msg = kmalloc(sizeof(*msg), GFP_KERNEL);
-               if (!msg)
-                       return -ENOMEM;
-               read_size = scif_rb_get_next(&qp->inbound_q, &msg->msg,
-                                            sizeof(struct scifmsg));
-               if (read_size != sizeof(struct scifmsg)) {
-                       kfree(msg);
-                       scif_rb_update_read_ptr(&qp->inbound_q);
-                       break;
-               }
-               spin_lock(&qp->recv_lock);
-               list_add_tail(&msg->list, &scif_info.loopb_recv_q);
-               spin_unlock(&qp->recv_lock);
-               queue_work(scif_info.loopb_wq, &scif_info.loopb_work);
-               scif_rb_update_read_ptr(&qp->inbound_q);
-       } while (read_size == sizeof(struct scifmsg));
-       return read_size;
-}
-
-/**
- * scif_setup_loopback_qp - One time setup work for Loopback Node Qp.
- * @scifdev: SCIF device
- *
- * Sets up the required loopback workqueues, queue pairs and ring buffers
- */
-int scif_setup_loopback_qp(struct scif_dev *scifdev)
-{
-       int err = 0;
-       void *local_q;
-       struct scif_qp *qp;
-
-       err = scif_setup_intr_wq(scifdev);
-       if (err)
-               goto exit;
-       INIT_LIST_HEAD(&scif_info.loopb_recv_q);
-       snprintf(scif_info.loopb_wqname, sizeof(scif_info.loopb_wqname),
-                "SCIF LOOPB %d", scifdev->node);
-       scif_info.loopb_wq =
-               alloc_ordered_workqueue(scif_info.loopb_wqname, 0);
-       if (!scif_info.loopb_wq) {
-               err = -ENOMEM;
-               goto destroy_intr;
-       }
-       INIT_WORK(&scif_info.loopb_work, scif_loopb_wq_handler);
-       /* Allocate Self Qpair */
-       scifdev->qpairs = kzalloc(sizeof(*scifdev->qpairs), GFP_KERNEL);
-       if (!scifdev->qpairs) {
-               err = -ENOMEM;
-               goto destroy_loopb_wq;
-       }
-
-       qp = scifdev->qpairs;
-       qp->magic = SCIFEP_MAGIC;
-       spin_lock_init(&qp->send_lock);
-       spin_lock_init(&qp->recv_lock);
-
-       local_q = kzalloc(SCIF_NODE_QP_SIZE, GFP_KERNEL);
-       if (!local_q) {
-               err = -ENOMEM;
-               goto free_qpairs;
-       }
-       /*
-        * For loopback the inbound_q and outbound_q are essentially the same
-        * since the Node sends a message on the loopback interface to the
-        * outbound_q which is then received on the inbound_q.
-        */
-       scif_rb_init(&qp->outbound_q,
-                    &qp->local_read,
-                    &qp->local_write,
-                    local_q, get_count_order(SCIF_NODE_QP_SIZE));
-
-       scif_rb_init(&qp->inbound_q,
-                    &qp->local_read,
-                    &qp->local_write,
-                    local_q, get_count_order(SCIF_NODE_QP_SIZE));
-       scif_info.nodeid = scifdev->node;
-
-       scif_peer_register_device(scifdev);
-
-       scif_info.loopb_dev = scifdev;
-       return err;
-free_qpairs:
-       kfree(scifdev->qpairs);
-destroy_loopb_wq:
-       destroy_workqueue(scif_info.loopb_wq);
-destroy_intr:
-       scif_destroy_intr_wq(scifdev);
-exit:
-       return err;
-}
-
-/**
- * scif_destroy_loopback_qp - One time uninit work for Loopback Node Qp
- * @scifdev: SCIF device
- *
- * Destroys the workqueues and frees up the Ring Buffer and Queue Pair memory.
- */
-int scif_destroy_loopback_qp(struct scif_dev *scifdev)
-{
-       scif_peer_unregister_device(scifdev);
-       destroy_workqueue(scif_info.loopb_wq);
-       scif_destroy_intr_wq(scifdev);
-       kfree(scifdev->qpairs->outbound_q.rb_base);
-       kfree(scifdev->qpairs);
-       scifdev->sdev = NULL;
-       scif_info.loopb_dev = NULL;
-       return 0;
-}
-
-void scif_destroy_p2p(struct scif_dev *scifdev)
-{
-       struct scif_dev *peer_dev;
-       struct scif_p2p_info *p2p;
-       struct list_head *pos, *tmp;
-       int bd;
-
-       mutex_lock(&scif_info.conflock);
-       /* Free P2P mappings in the given node for all its peer nodes */
-       list_for_each_safe(pos, tmp, &scifdev->p2p) {
-               p2p = list_entry(pos, struct scif_p2p_info, ppi_list);
-               dma_unmap_sg(&scifdev->sdev->dev, p2p->ppi_sg[SCIF_PPI_MMIO],
-                            p2p->sg_nentries[SCIF_PPI_MMIO],
-                            DMA_BIDIRECTIONAL);
-               dma_unmap_sg(&scifdev->sdev->dev, p2p->ppi_sg[SCIF_PPI_APER],
-                            p2p->sg_nentries[SCIF_PPI_APER],
-                            DMA_BIDIRECTIONAL);
-               scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_MMIO]);
-               scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_APER]);
-               list_del(pos);
-               kfree(p2p);
-       }
-
-       /* Free P2P mapping created in the peer nodes for the given node */
-       for (bd = SCIF_MGMT_NODE + 1; bd <= scif_info.maxid; bd++) {
-               peer_dev = &scif_dev[bd];
-               list_for_each_safe(pos, tmp, &peer_dev->p2p) {
-                       p2p = list_entry(pos, struct scif_p2p_info, ppi_list);
-                       if (p2p->ppi_peer_id == scifdev->node) {
-                               dma_unmap_sg(&peer_dev->sdev->dev,
-                                            p2p->ppi_sg[SCIF_PPI_MMIO],
-                                            p2p->sg_nentries[SCIF_PPI_MMIO],
-                                            DMA_BIDIRECTIONAL);
-                               dma_unmap_sg(&peer_dev->sdev->dev,
-                                            p2p->ppi_sg[SCIF_PPI_APER],
-                                            p2p->sg_nentries[SCIF_PPI_APER],
-                                            DMA_BIDIRECTIONAL);
-                               scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_MMIO]);
-                               scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_APER]);
-                               list_del(pos);
-                               kfree(p2p);
-                       }
-               }
-       }
-       mutex_unlock(&scif_info.conflock);
-}
diff --git a/drivers/misc/mic/scif/scif_nodeqp.h b/drivers/misc/mic/scif/scif_nodeqp.h
deleted file mode 100644 (file)
index 9589627..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in
- *   the documentation and/or other materials provided with the
- *   distribution.
- * * Neither the name of Intel Corporation nor the names of its
- *   contributors may be used to endorse or promote products derived
- *   from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Intel SCIF driver.
- *
- */
-#ifndef SCIF_NODEQP
-#define SCIF_NODEQP
-
-#include "scif_rb.h"
-#include "scif_peer_bus.h"
-
-#define SCIF_INIT 1  /* First message sent to the peer node for discovery */
-#define SCIF_EXIT 2  /* Last message from the peer informing intent to exit */
-#define SCIF_EXIT_ACK 3 /* Response to SCIF_EXIT message */
-#define SCIF_NODE_ADD 4  /* Tell Online nodes a new node exits */
-#define SCIF_NODE_ADD_ACK 5  /* Confirm to mgmt node sequence is finished */
-#define SCIF_NODE_ADD_NACK 6 /* SCIF_NODE_ADD failed */
-#define SCIF_NODE_REMOVE 7 /* Request to deactivate a SCIF node */
-#define SCIF_NODE_REMOVE_ACK 8 /* Response to a SCIF_NODE_REMOVE message */
-#define SCIF_CNCT_REQ 9  /* Phys addr of Request connection to a port */
-#define SCIF_CNCT_GNT 10  /* Phys addr of new Grant connection request */
-#define SCIF_CNCT_GNTACK 11  /* Error type Reject a connection request */
-#define SCIF_CNCT_GNTNACK 12  /* Error type Reject a connection request */
-#define SCIF_CNCT_REJ 13  /* Error type Reject a connection request */
-#define SCIF_DISCNCT 14 /* Notify peer that connection is being terminated */
-#define SCIF_DISCNT_ACK 15 /* Notify peer that connection is being terminated */
-#define SCIF_CLIENT_SENT 16 /* Notify the peer that data has been written */
-#define SCIF_CLIENT_RCVD 17 /* Notify the peer that data has been read */
-#define SCIF_GET_NODE_INFO 18 /* Get current node mask from the mgmt node*/
-#define SCIF_REGISTER 19 /* Tell peer about a new registered window */
-#define SCIF_REGISTER_ACK 20 /* Notify peer about unregistration success */
-#define SCIF_REGISTER_NACK 21 /* Notify peer about registration success */
-#define SCIF_UNREGISTER 22 /* Tell peer about unregistering a window */
-#define SCIF_UNREGISTER_ACK 23 /* Notify peer about registration failure */
-#define SCIF_UNREGISTER_NACK 24 /* Notify peer about unregistration failure */
-#define SCIF_ALLOC_REQ 25 /* Request a mapped buffer */
-#define SCIF_ALLOC_GNT 26 /* Notify peer about allocation success */
-#define SCIF_ALLOC_REJ 27 /* Notify peer about allocation failure */
-#define SCIF_FREE_VIRT 28 /* Free previously allocated virtual memory */
-#define SCIF_MUNMAP 29 /* Acknowledgment for a SCIF_MMAP request */
-#define SCIF_MARK 30 /* SCIF Remote Fence Mark Request */
-#define SCIF_MARK_ACK 31 /* SCIF Remote Fence Mark Success */
-#define SCIF_MARK_NACK 32 /* SCIF Remote Fence Mark Failure */
-#define SCIF_WAIT 33 /* SCIF Remote Fence Wait Request */
-#define SCIF_WAIT_ACK 34 /* SCIF Remote Fence Wait Success */
-#define SCIF_WAIT_NACK 35 /* SCIF Remote Fence Wait Failure */
-#define SCIF_SIG_LOCAL 36 /* SCIF Remote Fence Local Signal Request */
-#define SCIF_SIG_REMOTE 37 /* SCIF Remote Fence Remote Signal Request */
-#define SCIF_SIG_ACK 38 /* SCIF Remote Fence Remote Signal Success */
-#define SCIF_SIG_NACK 39 /* SCIF Remote Fence Remote Signal Failure */
-#define SCIF_MAX_MSG SCIF_SIG_NACK
-
-/*
- * struct scifmsg - Node QP message format
- *
- * @src: Source information
- * @dst: Destination information
- * @uop: The message opcode
- * @payload: Unique payload format for each message
- */
-struct scifmsg {
-       struct scif_port_id src;
-       struct scif_port_id dst;
-       u32 uop;
-       u64 payload[4];
-} __packed;
-
-/*
- * struct scif_allocmsg - Used with SCIF_ALLOC_REQ to request
- * the remote note to allocate memory
- *
- * phys_addr: Physical address of the buffer
- * vaddr: Virtual address of the buffer
- * size: Size of the buffer
- * state: Current state
- * allocwq: wait queue for status
- */
-struct scif_allocmsg {
-       dma_addr_t phys_addr;
-       unsigned long vaddr;
-       size_t size;
-       enum scif_msg_state state;
-       wait_queue_head_t allocwq;
-};
-
-/*
- * struct scif_qp - Node Queue Pair
- *
- * Interesting structure -- a little difficult because we can only
- * write across the PCIe, so any r/w pointer we need to read is
- * local. We only need to read the read pointer on the inbound_q
- * and read the write pointer in the outbound_q
- *
- * @magic: Magic value to ensure the peer sees the QP correctly
- * @outbound_q: The outbound ring buffer for sending messages
- * @inbound_q: The inbound ring buffer for receiving messages
- * @local_write: Local write index
- * @local_read: Local read index
- * @remote_qp: The remote queue pair
- * @local_buf: DMA address of local ring buffer
- * @local_qp: DMA address of the local queue pair data structure
- * @remote_buf: DMA address of remote ring buffer
- * @qp_state: QP state i.e. online or offline used for P2P
- * @send_lock: synchronize access to outbound queue
- * @recv_lock: Synchronize access to inbound queue
- */
-struct scif_qp {
-       u64 magic;
-#define SCIFEP_MAGIC 0x5c1f000000005c1fULL
-       struct scif_rb outbound_q;
-       struct scif_rb inbound_q;
-
-       u32 local_write __aligned(64);
-       u32 local_read __aligned(64);
-       struct scif_qp *remote_qp;
-       dma_addr_t local_buf;
-       dma_addr_t local_qp;
-       dma_addr_t remote_buf;
-       u32 qp_state;
-#define SCIF_QP_OFFLINE 0xdead
-#define SCIF_QP_ONLINE 0xc0de
-       spinlock_t send_lock;
-       spinlock_t recv_lock;
-};
-
-/*
- * struct scif_loopb_msg - An element in the loopback Node QP message list.
- *
- * @msg - The SCIF node QP message
- * @list - link in the list of messages
- */
-struct scif_loopb_msg {
-       struct scifmsg msg;
-       struct list_head list;
-};
-
-int scif_nodeqp_send(struct scif_dev *scifdev, struct scifmsg *msg);
-int _scif_nodeqp_send(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_nodeqp_intrhandler(struct scif_dev *scifdev, struct scif_qp *qp);
-int scif_loopb_msg_handler(struct scif_dev *scifdev, struct scif_qp *qp);
-int scif_setup_qp(struct scif_dev *scifdev);
-int scif_qp_response(phys_addr_t phys, struct scif_dev *dev);
-int scif_setup_qp_connect(struct scif_qp *qp, dma_addr_t *qp_offset,
-                         int local_size, struct scif_dev *scifdev);
-int scif_setup_qp_accept(struct scif_qp *qp, dma_addr_t *qp_offset,
-                        dma_addr_t phys, int local_size,
-                        struct scif_dev *scifdev);
-int scif_setup_qp_connect_response(struct scif_dev *scifdev,
-                                  struct scif_qp *qp, u64 payload);
-int scif_setup_loopback_qp(struct scif_dev *scifdev);
-int scif_destroy_loopback_qp(struct scif_dev *scifdev);
-void scif_poll_qp_state(struct work_struct *work);
-void scif_destroy_p2p(struct scif_dev *scifdev);
-void scif_send_exit(struct scif_dev *scifdev);
-static inline struct device *scif_get_peer_dev(struct scif_dev *scifdev)
-{
-       struct scif_peer_dev *spdev;
-       struct device *spdev_ret;
-
-       rcu_read_lock();
-       spdev = rcu_dereference(scifdev->spdev);
-       if (spdev)
-               spdev_ret = get_device(&spdev->dev);
-       else
-               spdev_ret = ERR_PTR(-ENODEV);
-       rcu_read_unlock();
-       return spdev_ret;
-}
-
-static inline void scif_put_peer_dev(struct device *dev)
-{
-       put_device(dev);
-}
-#endif  /* SCIF_NODEQP */
diff --git a/drivers/misc/mic/scif/scif_peer_bus.c b/drivers/misc/mic/scif/scif_peer_bus.c
deleted file mode 100644 (file)
index 6d60830..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#include "scif_main.h"
-#include "../bus/scif_bus.h"
-#include "scif_peer_bus.h"
-
-static inline struct scif_peer_dev *
-dev_to_scif_peer(struct device *dev)
-{
-       return container_of(dev, struct scif_peer_dev, dev);
-}
-
-struct bus_type scif_peer_bus = {
-       .name  = "scif_peer_bus",
-};
-
-static void scif_peer_release_dev(struct device *d)
-{
-       struct scif_peer_dev *sdev = dev_to_scif_peer(d);
-       struct scif_dev *scifdev = &scif_dev[sdev->dnode];
-
-       scif_cleanup_scifdev(scifdev);
-       kfree(sdev);
-}
-
-static int scif_peer_initialize_device(struct scif_dev *scifdev)
-{
-       struct scif_peer_dev *spdev;
-       int ret;
-
-       spdev = kzalloc(sizeof(*spdev), GFP_KERNEL);
-       if (!spdev) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       spdev->dev.parent = scifdev->sdev->dev.parent;
-       spdev->dev.release = scif_peer_release_dev;
-       spdev->dnode = scifdev->node;
-       spdev->dev.bus = &scif_peer_bus;
-       dev_set_name(&spdev->dev, "scif_peer-dev%u", spdev->dnode);
-
-       device_initialize(&spdev->dev);
-       get_device(&spdev->dev);
-       rcu_assign_pointer(scifdev->spdev, spdev);
-
-       mutex_lock(&scif_info.conflock);
-       scif_info.total++;
-       scif_info.maxid = max_t(u32, spdev->dnode, scif_info.maxid);
-       mutex_unlock(&scif_info.conflock);
-       return 0;
-err:
-       dev_err(&scifdev->sdev->dev,
-               "dnode %d: initialize_device rc %d\n", scifdev->node, ret);
-       return ret;
-}
-
-static int scif_peer_add_device(struct scif_dev *scifdev)
-{
-       struct scif_peer_dev *spdev = rcu_dereference(scifdev->spdev);
-       char pool_name[16];
-       int ret;
-
-       ret = device_add(&spdev->dev);
-       put_device(&spdev->dev);
-       if (ret) {
-               dev_err(&scifdev->sdev->dev,
-                       "dnode %d: peer device_add failed\n", scifdev->node);
-               goto put_spdev;
-       }
-
-       scnprintf(pool_name, sizeof(pool_name), "scif-%d", spdev->dnode);
-       scifdev->signal_pool = dmam_pool_create(pool_name, &scifdev->sdev->dev,
-                                               sizeof(struct scif_status), 1,
-                                               0);
-       if (!scifdev->signal_pool) {
-               dev_err(&scifdev->sdev->dev,
-                       "dnode %d: dmam_pool_create failed\n", scifdev->node);
-               ret = -ENOMEM;
-               goto del_spdev;
-       }
-       dev_dbg(&spdev->dev, "Added peer dnode %d\n", spdev->dnode);
-       return 0;
-del_spdev:
-       device_del(&spdev->dev);
-put_spdev:
-       RCU_INIT_POINTER(scifdev->spdev, NULL);
-       synchronize_rcu();
-       put_device(&spdev->dev);
-
-       mutex_lock(&scif_info.conflock);
-       scif_info.total--;
-       mutex_unlock(&scif_info.conflock);
-       return ret;
-}
-
-void scif_add_peer_device(struct work_struct *work)
-{
-       struct scif_dev *scifdev = container_of(work, struct scif_dev,
-                                               peer_add_work);
-
-       scif_peer_add_device(scifdev);
-}
-
-/*
- * Peer device registration is split into a device_initialize and a device_add.
- * The reason for doing this is as follows: First, peer device registration
- * itself cannot be done in the message processing thread and must be delegated
- * to another workqueue, otherwise if SCIF client probe, called during peer
- * device registration, calls scif_connect(..), it will block the message
- * processing thread causing a deadlock. Next, device_initialize is done in the
- * "top-half" message processing thread and device_add in the "bottom-half"
- * workqueue. If this is not done, SCIF_CNCT_REQ message processing executing
- * concurrently with SCIF_INIT message processing is unable to get a reference
- * on the peer device, thereby failing the connect request.
- */
-void scif_peer_register_device(struct scif_dev *scifdev)
-{
-       int ret;
-
-       mutex_lock(&scifdev->lock);
-       ret = scif_peer_initialize_device(scifdev);
-       if (ret)
-               goto exit;
-       schedule_work(&scifdev->peer_add_work);
-exit:
-       mutex_unlock(&scifdev->lock);
-}
-
-int scif_peer_unregister_device(struct scif_dev *scifdev)
-{
-       struct scif_peer_dev *spdev;
-
-       mutex_lock(&scifdev->lock);
-       /* Flush work to ensure device register is complete */
-       flush_work(&scifdev->peer_add_work);
-
-       /*
-        * Continue holding scifdev->lock since theoretically unregister_device
-        * can be called simultaneously from multiple threads
-        */
-       spdev = rcu_dereference(scifdev->spdev);
-       if (!spdev) {
-               mutex_unlock(&scifdev->lock);
-               return -ENODEV;
-       }
-
-       RCU_INIT_POINTER(scifdev->spdev, NULL);
-       synchronize_rcu();
-       mutex_unlock(&scifdev->lock);
-
-       dev_dbg(&spdev->dev, "Removing peer dnode %d\n", spdev->dnode);
-       device_unregister(&spdev->dev);
-
-       mutex_lock(&scif_info.conflock);
-       scif_info.total--;
-       mutex_unlock(&scif_info.conflock);
-       return 0;
-}
-
-int scif_peer_bus_init(void)
-{
-       return bus_register(&scif_peer_bus);
-}
-
-void scif_peer_bus_exit(void)
-{
-       bus_unregister(&scif_peer_bus);
-}
diff --git a/drivers/misc/mic/scif/scif_peer_bus.h b/drivers/misc/mic/scif/scif_peer_bus.h
deleted file mode 100644 (file)
index 2ea4c51..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#ifndef _SCIF_PEER_BUS_H_
-#define _SCIF_PEER_BUS_H_
-
-#include <linux/device.h>
-#include <linux/mic_common.h>
-#include <linux/scif.h>
-
-struct scif_dev;
-
-void scif_add_peer_device(struct work_struct *work);
-void scif_peer_register_device(struct scif_dev *sdev);
-int scif_peer_unregister_device(struct scif_dev *scifdev);
-int scif_peer_bus_init(void);
-void scif_peer_bus_exit(void);
-#endif /* _SCIF_PEER_BUS_H */
diff --git a/drivers/misc/mic/scif/scif_ports.c b/drivers/misc/mic/scif/scif_ports.c
deleted file mode 100644 (file)
index 4bdb5ef..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#include <linux/idr.h>
-
-#include "scif_main.h"
-
-#define SCIF_PORT_COUNT        0x10000 /* Ports available */
-
-struct idr scif_ports;
-
-/**
- * struct scif_port - SCIF port information
- *
- * @ref_cnt:  Reference count since there can be multiple endpoints
- *           created via scif_accept(..) simultaneously using a port.
- */
-struct scif_port {
-       int ref_cnt;
-};
-
-/**
- * __scif_get_port - Reserve a specified port # for SCIF and add it
- * to the global list.
- * @start: lowest port # to be reserved (inclusive).
- * @end:   highest port # to be reserved (exclusive).
- *
- * @return : Allocated SCIF port #, or -ENOSPC if port unavailable.
- *             On memory allocation failure, returns -ENOMEM.
- */
-static int __scif_get_port(int start, int end)
-{
-       int id;
-       struct scif_port *port = kzalloc(sizeof(*port), GFP_ATOMIC);
-
-       if (!port)
-               return -ENOMEM;
-       spin_lock(&scif_info.port_lock);
-       id = idr_alloc(&scif_ports, port, start, end, GFP_ATOMIC);
-       if (id >= 0)
-               port->ref_cnt++;
-       spin_unlock(&scif_info.port_lock);
-       return id;
-}
-
-/**
- * scif_rsrv_port - Reserve a specified port # for SCIF.
- * @port : port # to be reserved.
- *
- * @return : Allocated SCIF port #, or -ENOSPC if port unavailable.
- *             On memory allocation failure, returns -ENOMEM.
- */
-int scif_rsrv_port(u16 port)
-{
-       return __scif_get_port(port, port + 1);
-}
-
-/**
- * scif_get_new_port - Get and reserve any port # for SCIF in the range
- *                     SCIF_PORT_RSVD + 1 to SCIF_PORT_COUNT - 1.
- *
- * @return : Allocated SCIF port #, or -ENOSPC if no ports available.
- *             On memory allocation failure, returns -ENOMEM.
- */
-int scif_get_new_port(void)
-{
-       return __scif_get_port(SCIF_PORT_RSVD + 1, SCIF_PORT_COUNT);
-}
-
-/**
- * scif_get_port - Increment the reference count for a SCIF port
- * @id : SCIF port
- *
- * @return : None
- */
-void scif_get_port(u16 id)
-{
-       struct scif_port *port;
-
-       if (!id)
-               return;
-       spin_lock(&scif_info.port_lock);
-       port = idr_find(&scif_ports, id);
-       if (port)
-               port->ref_cnt++;
-       spin_unlock(&scif_info.port_lock);
-}
-
-/**
- * scif_put_port - Release a reserved SCIF port
- * @id : SCIF port to be released.
- *
- * @return : None
- */
-void scif_put_port(u16 id)
-{
-       struct scif_port *port;
-
-       if (!id)
-               return;
-       spin_lock(&scif_info.port_lock);
-       port = idr_find(&scif_ports, id);
-       if (port) {
-               port->ref_cnt--;
-               if (!port->ref_cnt) {
-                       idr_remove(&scif_ports, id);
-                       kfree(port);
-               }
-       }
-       spin_unlock(&scif_info.port_lock);
-}
diff --git a/drivers/misc/mic/scif/scif_rb.c b/drivers/misc/mic/scif/scif_rb.c
deleted file mode 100644 (file)
index e425882..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#include <linux/circ_buf.h>
-#include <linux/types.h>
-#include <linux/io.h>
-#include <linux/errno.h>
-
-#include "scif_rb.h"
-
-#define scif_rb_ring_cnt(head, tail, size) CIRC_CNT(head, tail, size)
-#define scif_rb_ring_space(head, tail, size) CIRC_SPACE(head, tail, size)
-
-/**
- * scif_rb_init - Initializes the ring buffer
- * @rb: ring buffer
- * @read_ptr: A pointer to the read offset
- * @write_ptr: A pointer to the write offset
- * @rb_base: A pointer to the base of the ring buffer
- * @size: The size of the ring buffer in powers of two
- */
-void scif_rb_init(struct scif_rb *rb, u32 *read_ptr, u32 *write_ptr,
-                 void *rb_base, u8 size)
-{
-       rb->rb_base = rb_base;
-       rb->size = (1 << size);
-       rb->read_ptr = read_ptr;
-       rb->write_ptr = write_ptr;
-       rb->current_read_offset = *read_ptr;
-       rb->current_write_offset = *write_ptr;
-}
-
-/* Copies a message to the ring buffer -- handles the wrap around case */
-static void memcpy_torb(struct scif_rb *rb, void *header,
-                       void *msg, u32 size)
-{
-       u32 size1, size2;
-
-       if (header + size >= rb->rb_base + rb->size) {
-               /* Need to call two copies if it wraps around */
-               size1 = (u32)(rb->rb_base + rb->size - header);
-               size2 = size - size1;
-               memcpy_toio((void __iomem __force *)header, msg, size1);
-               memcpy_toio((void __iomem __force *)rb->rb_base,
-                           msg + size1, size2);
-       } else {
-               memcpy_toio((void __iomem __force *)header, msg, size);
-       }
-}
-
-/* Copies a message from the ring buffer -- handles the wrap around case */
-static void memcpy_fromrb(struct scif_rb *rb, void *header,
-                         void *msg, u32 size)
-{
-       u32 size1, size2;
-
-       if (header + size >= rb->rb_base + rb->size) {
-               /* Need to call two copies if it wraps around */
-               size1 = (u32)(rb->rb_base + rb->size - header);
-               size2 = size - size1;
-               memcpy_fromio(msg, (void __iomem __force *)header, size1);
-               memcpy_fromio(msg + size1,
-                             (void __iomem __force *)rb->rb_base, size2);
-       } else {
-               memcpy_fromio(msg, (void __iomem __force *)header, size);
-       }
-}
-
-/**
- * scif_rb_space - Query space available for writing to the RB
- * @rb: ring buffer
- *
- * Return: size available for writing to RB in bytes.
- */
-u32 scif_rb_space(struct scif_rb *rb)
-{
-       rb->current_read_offset = *rb->read_ptr;
-       /*
-        * Update from the HW read pointer only once the peer has exposed the
-        * new empty slot. This barrier is paired with the memory barrier
-        * scif_rb_update_read_ptr()
-        */
-       mb();
-       return scif_rb_ring_space(rb->current_write_offset,
-                                 rb->current_read_offset, rb->size);
-}
-
-/**
- * scif_rb_write - Write a message to the RB
- * @rb: ring buffer
- * @msg: buffer to send the message.  Must be at least size bytes long
- * @size: the size (in bytes) to be copied to the RB
- *
- * This API does not block if there isn't enough space in the RB.
- * Returns: 0 on success or -ENOMEM on failure
- */
-int scif_rb_write(struct scif_rb *rb, void *msg, u32 size)
-{
-       void *header;
-
-       if (scif_rb_space(rb) < size)
-               return -ENOMEM;
-       header = rb->rb_base + rb->current_write_offset;
-       memcpy_torb(rb, header, msg, size);
-       /*
-        * Wait until scif_rb_commit(). Update the local ring
-        * buffer data, not the shared data until commit.
-        */
-       rb->current_write_offset =
-               (rb->current_write_offset + size) & (rb->size - 1);
-       return 0;
-}
-
-/**
- * scif_rb_commit - To submit the message to let the peer fetch it
- * @rb: ring buffer
- */
-void scif_rb_commit(struct scif_rb *rb)
-{
-       /*
-        * We must ensure ordering between the all the data committed
-        * previously before we expose the new message to the peer by
-        * updating the write_ptr. This write barrier is paired with
-        * the read barrier in scif_rb_count(..)
-        */
-       wmb();
-       WRITE_ONCE(*rb->write_ptr, rb->current_write_offset);
-#ifdef CONFIG_INTEL_MIC_CARD
-       /*
-        * X100 Si bug: For the case where a Core is performing an EXT_WR
-        * followed by a Doorbell Write, the Core must perform two EXT_WR to the
-        * same address with the same data before it does the Doorbell Write.
-        * This way, if ordering is violated for the Interrupt Message, it will
-        * fall just behind the first Posted associated with the first EXT_WR.
-        */
-       WRITE_ONCE(*rb->write_ptr, rb->current_write_offset);
-#endif
-}
-
-/**
- * scif_rb_get - To get next message from the ring buffer
- * @rb: ring buffer
- * @size: Number of bytes to be read
- *
- * Return: NULL if no bytes to be read from the ring buffer, otherwise the
- *     pointer to the next byte
- */
-static void *scif_rb_get(struct scif_rb *rb, u32 size)
-{
-       void *header = NULL;
-
-       if (scif_rb_count(rb, size) >= size)
-               header = rb->rb_base + rb->current_read_offset;
-       return header;
-}
-
-/*
- * scif_rb_get_next - Read from ring buffer.
- * @rb: ring buffer
- * @msg: buffer to hold the message.  Must be at least size bytes long
- * @size: Number of bytes to be read
- *
- * Return: number of bytes read if available bytes are >= size, otherwise
- * returns zero.
- */
-u32 scif_rb_get_next(struct scif_rb *rb, void *msg, u32 size)
-{
-       void *header = NULL;
-       int read_size = 0;
-
-       header = scif_rb_get(rb, size);
-       if (header) {
-               u32 next_cmd_offset =
-                       (rb->current_read_offset + size) & (rb->size - 1);
-
-               read_size = size;
-               rb->current_read_offset = next_cmd_offset;
-               memcpy_fromrb(rb, header, msg, size);
-       }
-       return read_size;
-}
-
-/**
- * scif_rb_update_read_ptr
- * @rb: ring buffer
- */
-void scif_rb_update_read_ptr(struct scif_rb *rb)
-{
-       u32 new_offset;
-
-       new_offset = rb->current_read_offset;
-       /*
-        * We must ensure ordering between the all the data committed or read
-        * previously before we expose the empty slot to the peer by updating
-        * the read_ptr. This barrier is paired with the memory barrier in
-        * scif_rb_space(..)
-        */
-       mb();
-       WRITE_ONCE(*rb->read_ptr, new_offset);
-#ifdef CONFIG_INTEL_MIC_CARD
-       /*
-        * X100 Si Bug: For the case where a Core is performing an EXT_WR
-        * followed by a Doorbell Write, the Core must perform two EXT_WR to the
-        * same address with the same data before it does the Doorbell Write.
-        * This way, if ordering is violated for the Interrupt Message, it will
-        * fall just behind the first Posted associated with the first EXT_WR.
-        */
-       WRITE_ONCE(*rb->read_ptr, new_offset);
-#endif
-}
-
-/**
- * scif_rb_count
- * @rb: ring buffer
- * @size: Number of bytes expected to be read
- *
- * Return: number of bytes that can be read from the RB
- */
-u32 scif_rb_count(struct scif_rb *rb, u32 size)
-{
-       if (scif_rb_ring_cnt(rb->current_write_offset,
-                            rb->current_read_offset,
-                            rb->size) < size) {
-               rb->current_write_offset = *rb->write_ptr;
-               /*
-                * Update from the HW write pointer if empty only once the peer
-                * has exposed the new message. This read barrier is paired
-                * with the write barrier in scif_rb_commit(..)
-                */
-               smp_rmb();
-       }
-       return scif_rb_ring_cnt(rb->current_write_offset,
-                               rb->current_read_offset,
-                               rb->size);
-}
diff --git a/drivers/misc/mic/scif/scif_rb.h b/drivers/misc/mic/scif/scif_rb.h
deleted file mode 100644 (file)
index 166dffe..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in
- *   the documentation and/or other materials provided with the
- *   distribution.
- * * Neither the name of Intel Corporation nor the names of its
- *   contributors may be used to endorse or promote products derived
- *   from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Intel SCIF driver.
- */
-#ifndef SCIF_RB_H
-#define SCIF_RB_H
-/*
- * This file describes a general purpose, byte based ring buffer. Writers to the
- * ring buffer need to synchronize using a lock. The same is true for readers,
- * although in practice, the ring buffer has a single reader. It is lockless
- * between producer and consumer so it can handle being used across the PCIe
- * bus. The ring buffer ensures that there are no reads across the PCIe bus for
- * performance reasons. Two of these are used to form a single bidirectional
- * queue-pair across PCIe.
- */
-/*
- * struct scif_rb - SCIF Ring Buffer
- *
- * @rb_base: The base of the memory used for storing RB messages
- * @read_ptr: Pointer to the read offset
- * @write_ptr: Pointer to the write offset
- * @size: Size of the memory in rb_base
- * @current_read_offset: Cached read offset for performance
- * @current_write_offset: Cached write offset for performance
- */
-struct scif_rb {
-       void *rb_base;
-       u32 *read_ptr;
-       u32 *write_ptr;
-       u32 size;
-       u32 current_read_offset;
-       u32 current_write_offset;
-};
-
-/* methods used by both */
-void scif_rb_init(struct scif_rb *rb, u32 *read_ptr, u32 *write_ptr,
-                 void *rb_base, u8 size);
-/* writer only methods */
-/* write a new command, then scif_rb_commit() */
-int scif_rb_write(struct scif_rb *rb, void *msg, u32 size);
-/* after write(), then scif_rb_commit() */
-void scif_rb_commit(struct scif_rb *rb);
-/* query space available for writing to a RB. */
-u32 scif_rb_space(struct scif_rb *rb);
-
-/* reader only methods */
-/* read a new message from the ring buffer of size bytes */
-u32 scif_rb_get_next(struct scif_rb *rb, void *msg, u32 size);
-/* update the read pointer so that the space can be reused */
-void scif_rb_update_read_ptr(struct scif_rb *rb);
-/* count the number of bytes that can be read */
-u32 scif_rb_count(struct scif_rb *rb, u32 size);
-#endif
diff --git a/drivers/misc/mic/scif/scif_rma.c b/drivers/misc/mic/scif/scif_rma.c
deleted file mode 100644 (file)
index 18fb9d8..0000000
+++ /dev/null
@@ -1,1760 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#include <linux/intel-iommu.h>
-#include <linux/pagemap.h>
-#include <linux/sched/mm.h>
-#include <linux/sched/signal.h>
-
-#include "scif_main.h"
-#include "scif_map.h"
-
-/* Used to skip ulimit checks for registrations with SCIF_MAP_KERNEL flag */
-#define SCIF_MAP_ULIMIT 0x40
-
-bool scif_ulimit_check = 1;
-
-/**
- * scif_rma_ep_init:
- * @ep: end point
- *
- * Initialize RMA per EP data structures.
- */
-void scif_rma_ep_init(struct scif_endpt *ep)
-{
-       struct scif_endpt_rma_info *rma = &ep->rma_info;
-
-       mutex_init(&rma->rma_lock);
-       init_iova_domain(&rma->iovad, PAGE_SIZE, SCIF_IOVA_START_PFN);
-       spin_lock_init(&rma->tc_lock);
-       mutex_init(&rma->mmn_lock);
-       INIT_LIST_HEAD(&rma->reg_list);
-       INIT_LIST_HEAD(&rma->remote_reg_list);
-       atomic_set(&rma->tw_refcount, 0);
-       atomic_set(&rma->tcw_refcount, 0);
-       atomic_set(&rma->tcw_total_pages, 0);
-       atomic_set(&rma->fence_refcount, 0);
-
-       rma->async_list_del = 0;
-       rma->dma_chan = NULL;
-       INIT_LIST_HEAD(&rma->mmn_list);
-       INIT_LIST_HEAD(&rma->vma_list);
-       init_waitqueue_head(&rma->markwq);
-}
-
-/**
- * scif_rma_ep_can_uninit:
- * @ep: end point
- *
- * Returns 1 if an endpoint can be uninitialized and 0 otherwise.
- */
-int scif_rma_ep_can_uninit(struct scif_endpt *ep)
-{
-       int ret = 0;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       /* Destroy RMA Info only if both lists are empty */
-       if (list_empty(&ep->rma_info.reg_list) &&
-           list_empty(&ep->rma_info.remote_reg_list) &&
-           list_empty(&ep->rma_info.mmn_list) &&
-           !atomic_read(&ep->rma_info.tw_refcount) &&
-           !atomic_read(&ep->rma_info.tcw_refcount) &&
-           !atomic_read(&ep->rma_info.fence_refcount))
-               ret = 1;
-       mutex_unlock(&ep->rma_info.rma_lock);
-       return ret;
-}
-
-/**
- * scif_create_pinned_pages:
- * @nr_pages: number of pages in window
- * @prot: read/write protection
- *
- * Allocate and prepare a set of pinned pages.
- */
-static struct scif_pinned_pages *
-scif_create_pinned_pages(int nr_pages, int prot)
-{
-       struct scif_pinned_pages *pin;
-
-       might_sleep();
-       pin = scif_zalloc(sizeof(*pin));
-       if (!pin)
-               goto error;
-
-       pin->pages = scif_zalloc(nr_pages * sizeof(*pin->pages));
-       if (!pin->pages)
-               goto error_free_pinned_pages;
-
-       pin->prot = prot;
-       pin->magic = SCIFEP_MAGIC;
-       return pin;
-
-error_free_pinned_pages:
-       scif_free(pin, sizeof(*pin));
-error:
-       return NULL;
-}
-
-/**
- * scif_destroy_pinned_pages:
- * @pin: A set of pinned pages.
- *
- * Deallocate resources for pinned pages.
- */
-static int scif_destroy_pinned_pages(struct scif_pinned_pages *pin)
-{
-       int j;
-       int writeable = pin->prot & SCIF_PROT_WRITE;
-       int kernel = SCIF_MAP_KERNEL & pin->map_flags;
-
-       if (kernel) {
-               for (j = 0; j < pin->nr_pages; j++) {
-                       if (pin->pages[j] && !kernel) {
-                               if (writeable)
-                                       set_page_dirty_lock(pin->pages[j]);
-                               put_page(pin->pages[j]);
-                       }
-               }
-       } else
-               unpin_user_pages_dirty_lock(pin->pages, pin->nr_pages,
-                                           writeable);
-       scif_free(pin->pages,
-                 pin->nr_pages * sizeof(*pin->pages));
-       scif_free(pin, sizeof(*pin));
-       return 0;
-}
-
-/*
- * scif_create_window:
- * @ep: end point
- * @nr_pages: number of pages
- * @offset: registration offset
- * @temp: true if a temporary window is being created
- *
- * Allocate and prepare a self registration window.
- */
-struct scif_window *scif_create_window(struct scif_endpt *ep, int nr_pages,
-                                      s64 offset, bool temp)
-{
-       struct scif_window *window;
-
-       might_sleep();
-       window = scif_zalloc(sizeof(*window));
-       if (!window)
-               goto error;
-
-       window->dma_addr = scif_zalloc(nr_pages * sizeof(*window->dma_addr));
-       if (!window->dma_addr)
-               goto error_free_window;
-
-       window->num_pages = scif_zalloc(nr_pages * sizeof(*window->num_pages));
-       if (!window->num_pages)
-               goto error_free_window;
-
-       window->offset = offset;
-       window->ep = (u64)ep;
-       window->magic = SCIFEP_MAGIC;
-       window->reg_state = OP_IDLE;
-       init_waitqueue_head(&window->regwq);
-       window->unreg_state = OP_IDLE;
-       init_waitqueue_head(&window->unregwq);
-       INIT_LIST_HEAD(&window->list);
-       window->type = SCIF_WINDOW_SELF;
-       window->temp = temp;
-       return window;
-
-error_free_window:
-       scif_free(window->dma_addr,
-                 nr_pages * sizeof(*window->dma_addr));
-       scif_free(window, sizeof(*window));
-error:
-       return NULL;
-}
-
-/**
- * scif_destroy_incomplete_window:
- * @ep: end point
- * @window: registration window
- *
- * Deallocate resources for self window.
- */
-static void scif_destroy_incomplete_window(struct scif_endpt *ep,
-                                          struct scif_window *window)
-{
-       int err;
-       int nr_pages = window->nr_pages;
-       struct scif_allocmsg *alloc = &window->alloc_handle;
-       struct scifmsg msg;
-
-retry:
-       /* Wait for a SCIF_ALLOC_GNT/REJ message */
-       err = wait_event_timeout(alloc->allocwq,
-                                alloc->state != OP_IN_PROGRESS,
-                                SCIF_NODE_ALIVE_TIMEOUT);
-       if (!err && scifdev_alive(ep))
-               goto retry;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       if (alloc->state == OP_COMPLETED) {
-               msg.uop = SCIF_FREE_VIRT;
-               msg.src = ep->port;
-               msg.payload[0] = ep->remote_ep;
-               msg.payload[1] = window->alloc_handle.vaddr;
-               msg.payload[2] = (u64)window;
-               msg.payload[3] = SCIF_REGISTER;
-               _scif_nodeqp_send(ep->remote_dev, &msg);
-       }
-       mutex_unlock(&ep->rma_info.rma_lock);
-
-       scif_free_window_offset(ep, window, window->offset);
-       scif_free(window->dma_addr, nr_pages * sizeof(*window->dma_addr));
-       scif_free(window->num_pages, nr_pages * sizeof(*window->num_pages));
-       scif_free(window, sizeof(*window));
-}
-
-/**
- * scif_unmap_window:
- * @remote_dev: SCIF remote device
- * @window: registration window
- *
- * Delete any DMA mappings created for a registered self window
- */
-void scif_unmap_window(struct scif_dev *remote_dev, struct scif_window *window)
-{
-       int j;
-
-       if (scif_is_iommu_enabled() && !scifdev_self(remote_dev)) {
-               if (window->st) {
-                       dma_unmap_sg(&remote_dev->sdev->dev,
-                                    window->st->sgl, window->st->nents,
-                                    DMA_BIDIRECTIONAL);
-                       sg_free_table(window->st);
-                       kfree(window->st);
-                       window->st = NULL;
-               }
-       } else {
-               for (j = 0; j < window->nr_contig_chunks; j++) {
-                       if (window->dma_addr[j]) {
-                               scif_unmap_single(window->dma_addr[j],
-                                                 remote_dev,
-                                                 window->num_pages[j] <<
-                                                 PAGE_SHIFT);
-                               window->dma_addr[j] = 0x0;
-                       }
-               }
-       }
-}
-
-static inline struct mm_struct *__scif_acquire_mm(void)
-{
-       if (scif_ulimit_check)
-               return get_task_mm(current);
-       return NULL;
-}
-
-static inline void __scif_release_mm(struct mm_struct *mm)
-{
-       if (mm)
-               mmput(mm);
-}
-
-static inline int
-__scif_dec_pinned_vm_lock(struct mm_struct *mm,
-                         int nr_pages)
-{
-       if (!mm || !nr_pages || !scif_ulimit_check)
-               return 0;
-
-       atomic64_sub(nr_pages, &mm->pinned_vm);
-       return 0;
-}
-
-static inline int __scif_check_inc_pinned_vm(struct mm_struct *mm,
-                                            int nr_pages)
-{
-       unsigned long locked, lock_limit;
-
-       if (!mm || !nr_pages || !scif_ulimit_check)
-               return 0;
-
-       lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
-       locked = atomic64_add_return(nr_pages, &mm->pinned_vm);
-
-       if ((locked > lock_limit) && !capable(CAP_IPC_LOCK)) {
-               atomic64_sub(nr_pages, &mm->pinned_vm);
-               dev_err(scif_info.mdev.this_device,
-                       "locked(%lu) > lock_limit(%lu)\n",
-                       locked, lock_limit);
-               return -ENOMEM;
-       }
-       return 0;
-}
-
-/**
- * scif_destroy_window:
- * @ep: end point
- * @window: registration window
- *
- * Deallocate resources for self window.
- */
-int scif_destroy_window(struct scif_endpt *ep, struct scif_window *window)
-{
-       int j;
-       struct scif_pinned_pages *pinned_pages = window->pinned_pages;
-       int nr_pages = window->nr_pages;
-
-       might_sleep();
-       if (!window->temp && window->mm) {
-               __scif_dec_pinned_vm_lock(window->mm, window->nr_pages);
-               __scif_release_mm(window->mm);
-               window->mm = NULL;
-       }
-
-       scif_free_window_offset(ep, window, window->offset);
-       scif_unmap_window(ep->remote_dev, window);
-       /*
-        * Decrement references for this set of pinned pages from
-        * this window.
-        */
-       j = atomic_sub_return(1, &pinned_pages->ref_count);
-       if (j < 0)
-               dev_err(scif_info.mdev.this_device,
-                       "%s %d incorrect ref count %d\n",
-                       __func__, __LINE__, j);
-       /*
-        * If the ref count for pinned_pages is zero then someone
-        * has already called scif_unpin_pages() for it and we should
-        * destroy the page cache.
-        */
-       if (!j)
-               scif_destroy_pinned_pages(window->pinned_pages);
-       scif_free(window->dma_addr, nr_pages * sizeof(*window->dma_addr));
-       scif_free(window->num_pages, nr_pages * sizeof(*window->num_pages));
-       window->magic = 0;
-       scif_free(window, sizeof(*window));
-       return 0;
-}
-
-/**
- * scif_create_remote_lookup:
- * @remote_dev: SCIF remote device
- * @window: remote window
- *
- * Allocate and prepare lookup entries for the remote
- * end to copy over the physical addresses.
- * Returns 0 on success and appropriate errno on failure.
- */
-static int scif_create_remote_lookup(struct scif_dev *remote_dev,
-                                    struct scif_window *window)
-{
-       int i, j, err = 0;
-       int nr_pages = window->nr_pages;
-       bool vmalloc_dma_phys, vmalloc_num_pages;
-
-       might_sleep();
-       /* Map window */
-       err = scif_map_single(&window->mapped_offset,
-                             window, remote_dev, sizeof(*window));
-       if (err)
-               goto error_window;
-
-       /* Compute the number of lookup entries. 21 == 2MB Shift */
-       window->nr_lookup = ALIGN(nr_pages * PAGE_SIZE,
-                                       ((2) * 1024 * 1024)) >> 21;
-
-       window->dma_addr_lookup.lookup =
-               scif_alloc_coherent(&window->dma_addr_lookup.offset,
-                                   remote_dev, window->nr_lookup *
-                                   sizeof(*window->dma_addr_lookup.lookup),
-                                   GFP_KERNEL | __GFP_ZERO);
-       if (!window->dma_addr_lookup.lookup) {
-               err = -ENOMEM;
-               goto error_window;
-       }
-
-       window->num_pages_lookup.lookup =
-               scif_alloc_coherent(&window->num_pages_lookup.offset,
-                                   remote_dev, window->nr_lookup *
-                                   sizeof(*window->num_pages_lookup.lookup),
-                                   GFP_KERNEL | __GFP_ZERO);
-       if (!window->num_pages_lookup.lookup) {
-               err = -ENOMEM;
-               goto error_window;
-       }
-
-       vmalloc_dma_phys = is_vmalloc_addr(&window->dma_addr[0]);
-       vmalloc_num_pages = is_vmalloc_addr(&window->num_pages[0]);
-
-       /* Now map each of the pages containing physical addresses */
-       for (i = 0, j = 0; i < nr_pages; i += SCIF_NR_ADDR_IN_PAGE, j++) {
-               err = scif_map_page(&window->dma_addr_lookup.lookup[j],
-                                   vmalloc_dma_phys ?
-                                   vmalloc_to_page(&window->dma_addr[i]) :
-                                   virt_to_page(&window->dma_addr[i]),
-                                   remote_dev);
-               if (err)
-                       goto error_window;
-               err = scif_map_page(&window->num_pages_lookup.lookup[j],
-                                   vmalloc_num_pages ?
-                                   vmalloc_to_page(&window->num_pages[i]) :
-                                   virt_to_page(&window->num_pages[i]),
-                                   remote_dev);
-               if (err)
-                       goto error_window;
-       }
-       return 0;
-error_window:
-       return err;
-}
-
-/**
- * scif_destroy_remote_lookup:
- * @remote_dev: SCIF remote device
- * @window: remote window
- *
- * Destroy lookup entries used for the remote
- * end to copy over the physical addresses.
- */
-static void scif_destroy_remote_lookup(struct scif_dev *remote_dev,
-                                      struct scif_window *window)
-{
-       int i, j;
-
-       if (window->nr_lookup) {
-               struct scif_rma_lookup *lup = &window->dma_addr_lookup;
-               struct scif_rma_lookup *npup = &window->num_pages_lookup;
-
-               for (i = 0, j = 0; i < window->nr_pages;
-                       i += SCIF_NR_ADDR_IN_PAGE, j++) {
-                       if (lup->lookup && lup->lookup[j])
-                               scif_unmap_single(lup->lookup[j],
-                                                 remote_dev,
-                                                 PAGE_SIZE);
-                       if (npup->lookup && npup->lookup[j])
-                               scif_unmap_single(npup->lookup[j],
-                                                 remote_dev,
-                                                 PAGE_SIZE);
-               }
-               if (lup->lookup)
-                       scif_free_coherent(lup->lookup, lup->offset,
-                                          remote_dev, window->nr_lookup *
-                                          sizeof(*lup->lookup));
-               if (npup->lookup)
-                       scif_free_coherent(npup->lookup, npup->offset,
-                                          remote_dev, window->nr_lookup *
-                                          sizeof(*npup->lookup));
-               if (window->mapped_offset)
-                       scif_unmap_single(window->mapped_offset,
-                                         remote_dev, sizeof(*window));
-               window->nr_lookup = 0;
-       }
-}
-
-/**
- * scif_create_remote_window:
- * @scifdev:  SCIF device
- * @nr_pages: number of pages in window
- *
- * Allocate and prepare a remote registration window.
- */
-static struct scif_window *
-scif_create_remote_window(struct scif_dev *scifdev, int nr_pages)
-{
-       struct scif_window *window;
-
-       might_sleep();
-       window = scif_zalloc(sizeof(*window));
-       if (!window)
-               goto error_ret;
-
-       window->magic = SCIFEP_MAGIC;
-       window->nr_pages = nr_pages;
-
-       window->dma_addr = scif_zalloc(nr_pages * sizeof(*window->dma_addr));
-       if (!window->dma_addr)
-               goto error_window;
-
-       window->num_pages = scif_zalloc(nr_pages *
-                                       sizeof(*window->num_pages));
-       if (!window->num_pages)
-               goto error_window;
-
-       if (scif_create_remote_lookup(scifdev, window))
-               goto error_window;
-
-       window->type = SCIF_WINDOW_PEER;
-       window->unreg_state = OP_IDLE;
-       INIT_LIST_HEAD(&window->list);
-       return window;
-error_window:
-       scif_destroy_remote_window(window);
-error_ret:
-       return NULL;
-}
-
-/**
- * scif_destroy_remote_window:
- * @window: remote registration window
- *
- * Deallocate resources for remote window.
- */
-void
-scif_destroy_remote_window(struct scif_window *window)
-{
-       scif_free(window->dma_addr, window->nr_pages *
-                 sizeof(*window->dma_addr));
-       scif_free(window->num_pages, window->nr_pages *
-                 sizeof(*window->num_pages));
-       window->magic = 0;
-       scif_free(window, sizeof(*window));
-}
-
-/**
- * scif_iommu_map: create DMA mappings if the IOMMU is enabled
- * @remote_dev: SCIF remote device
- * @window: remote registration window
- *
- * Map the physical pages using dma_map_sg(..) and then detect the number
- * of contiguous DMA mappings allocated
- */
-static int scif_iommu_map(struct scif_dev *remote_dev,
-                         struct scif_window *window)
-{
-       struct scatterlist *sg;
-       int i, err;
-       scif_pinned_pages_t pin = window->pinned_pages;
-
-       window->st = kzalloc(sizeof(*window->st), GFP_KERNEL);
-       if (!window->st)
-               return -ENOMEM;
-
-       err = sg_alloc_table(window->st, window->nr_pages, GFP_KERNEL);
-       if (err)
-               return err;
-
-       for_each_sg(window->st->sgl, sg, window->st->nents, i)
-               sg_set_page(sg, pin->pages[i], PAGE_SIZE, 0x0);
-
-       err = dma_map_sg(&remote_dev->sdev->dev, window->st->sgl,
-                        window->st->nents, DMA_BIDIRECTIONAL);
-       if (!err)
-               return -ENOMEM;
-       /* Detect contiguous ranges of DMA mappings */
-       sg = window->st->sgl;
-       for (i = 0; sg; i++) {
-               dma_addr_t last_da;
-
-               window->dma_addr[i] = sg_dma_address(sg);
-               window->num_pages[i] = sg_dma_len(sg) >> PAGE_SHIFT;
-               last_da = sg_dma_address(sg) + sg_dma_len(sg);
-               while ((sg = sg_next(sg)) && sg_dma_address(sg) == last_da) {
-                       window->num_pages[i] +=
-                               (sg_dma_len(sg) >> PAGE_SHIFT);
-                       last_da = window->dma_addr[i] +
-                               sg_dma_len(sg);
-               }
-               window->nr_contig_chunks++;
-       }
-       return 0;
-}
-
-/**
- * scif_map_window:
- * @remote_dev: SCIF remote device
- * @window: self registration window
- *
- * Map pages of a window into the aperture/PCI.
- * Also determine addresses required for DMA.
- */
-int
-scif_map_window(struct scif_dev *remote_dev, struct scif_window *window)
-{
-       int i, j, k, err = 0, nr_contig_pages;
-       scif_pinned_pages_t pin;
-       phys_addr_t phys_prev, phys_curr;
-
-       might_sleep();
-
-       pin = window->pinned_pages;
-
-       if (intel_iommu_enabled && !scifdev_self(remote_dev))
-               return scif_iommu_map(remote_dev, window);
-
-       for (i = 0, j = 0; i < window->nr_pages; i += nr_contig_pages, j++) {
-               phys_prev = page_to_phys(pin->pages[i]);
-               nr_contig_pages = 1;
-
-               /* Detect physically contiguous chunks */
-               for (k = i + 1; k < window->nr_pages; k++) {
-                       phys_curr = page_to_phys(pin->pages[k]);
-                       if (phys_curr != (phys_prev + PAGE_SIZE))
-                               break;
-                       phys_prev = phys_curr;
-                       nr_contig_pages++;
-               }
-               window->num_pages[j] = nr_contig_pages;
-               window->nr_contig_chunks++;
-               if (scif_is_mgmt_node()) {
-                       /*
-                        * Management node has to deal with SMPT on X100 and
-                        * hence the DMA mapping is required
-                        */
-                       err = scif_map_single(&window->dma_addr[j],
-                                             phys_to_virt(page_to_phys(
-                                                          pin->pages[i])),
-                                             remote_dev,
-                                             nr_contig_pages << PAGE_SHIFT);
-                       if (err)
-                               return err;
-               } else {
-                       window->dma_addr[j] = page_to_phys(pin->pages[i]);
-               }
-       }
-       return err;
-}
-
-/**
- * scif_send_scif_unregister:
- * @ep: end point
- * @window: self registration window
- *
- * Send a SCIF_UNREGISTER message.
- */
-static int scif_send_scif_unregister(struct scif_endpt *ep,
-                                    struct scif_window *window)
-{
-       struct scifmsg msg;
-
-       msg.uop = SCIF_UNREGISTER;
-       msg.src = ep->port;
-       msg.payload[0] = window->alloc_handle.vaddr;
-       msg.payload[1] = (u64)window;
-       return scif_nodeqp_send(ep->remote_dev, &msg);
-}
-
-/**
- * scif_unregister_window:
- * @window: self registration window
- *
- * Send an unregistration request and wait for a response.
- */
-int scif_unregister_window(struct scif_window *window)
-{
-       int err = 0;
-       struct scif_endpt *ep = (struct scif_endpt *)window->ep;
-       bool send_msg = false;
-
-       might_sleep();
-       switch (window->unreg_state) {
-       case OP_IDLE:
-       {
-               window->unreg_state = OP_IN_PROGRESS;
-               send_msg = true;
-       }
-               fallthrough;
-       case OP_IN_PROGRESS:
-       {
-               scif_get_window(window, 1);
-               mutex_unlock(&ep->rma_info.rma_lock);
-               if (send_msg) {
-                       err = scif_send_scif_unregister(ep, window);
-                       if (err) {
-                               window->unreg_state = OP_COMPLETED;
-                               goto done;
-                       }
-               } else {
-                       /* Return ENXIO since unregistration is in progress */
-                       mutex_lock(&ep->rma_info.rma_lock);
-                       return -ENXIO;
-               }
-retry:
-               /* Wait for a SCIF_UNREGISTER_(N)ACK message */
-               err = wait_event_timeout(window->unregwq,
-                                        window->unreg_state != OP_IN_PROGRESS,
-                                        SCIF_NODE_ALIVE_TIMEOUT);
-               if (!err && scifdev_alive(ep))
-                       goto retry;
-               if (!err) {
-                       err = -ENODEV;
-                       window->unreg_state = OP_COMPLETED;
-                       dev_err(scif_info.mdev.this_device,
-                               "%s %d err %d\n", __func__, __LINE__, err);
-               }
-               if (err > 0)
-                       err = 0;
-done:
-               mutex_lock(&ep->rma_info.rma_lock);
-               scif_put_window(window, 1);
-               break;
-       }
-       case OP_FAILED:
-       {
-               if (!scifdev_alive(ep)) {
-                       err = -ENODEV;
-                       window->unreg_state = OP_COMPLETED;
-               }
-               break;
-       }
-       case OP_COMPLETED:
-               break;
-       default:
-               err = -ENODEV;
-       }
-
-       if (window->unreg_state == OP_COMPLETED && window->ref_count)
-               scif_put_window(window, window->nr_pages);
-
-       if (!window->ref_count) {
-               atomic_inc(&ep->rma_info.tw_refcount);
-               list_del_init(&window->list);
-               scif_free_window_offset(ep, window, window->offset);
-               mutex_unlock(&ep->rma_info.rma_lock);
-               if ((!!(window->pinned_pages->map_flags & SCIF_MAP_KERNEL)) &&
-                   scifdev_alive(ep)) {
-                       scif_drain_dma_intr(ep->remote_dev->sdev,
-                                           ep->rma_info.dma_chan);
-               } else {
-                       if (!__scif_dec_pinned_vm_lock(window->mm,
-                                                      window->nr_pages)) {
-                               __scif_release_mm(window->mm);
-                               window->mm = NULL;
-                       }
-               }
-               scif_queue_for_cleanup(window, &scif_info.rma);
-               mutex_lock(&ep->rma_info.rma_lock);
-       }
-       return err;
-}
-
-/**
- * scif_send_alloc_request:
- * @ep: end point
- * @window: self registration window
- *
- * Send a remote window allocation request
- */
-static int scif_send_alloc_request(struct scif_endpt *ep,
-                                  struct scif_window *window)
-{
-       struct scifmsg msg;
-       struct scif_allocmsg *alloc = &window->alloc_handle;
-
-       /* Set up the Alloc Handle */
-       alloc->state = OP_IN_PROGRESS;
-       init_waitqueue_head(&alloc->allocwq);
-
-       /* Send out an allocation request */
-       msg.uop = SCIF_ALLOC_REQ;
-       msg.payload[1] = window->nr_pages;
-       msg.payload[2] = (u64)&window->alloc_handle;
-       return _scif_nodeqp_send(ep->remote_dev, &msg);
-}
-
-/**
- * scif_prep_remote_window:
- * @ep: end point
- * @window: self registration window
- *
- * Send a remote window allocation request, wait for an allocation response,
- * and prepares the remote window by copying over the page lists
- */
-static int scif_prep_remote_window(struct scif_endpt *ep,
-                                  struct scif_window *window)
-{
-       struct scifmsg msg;
-       struct scif_window *remote_window;
-       struct scif_allocmsg *alloc = &window->alloc_handle;
-       dma_addr_t *dma_phys_lookup, *tmp, *num_pages_lookup, *tmp1;
-       int i = 0, j = 0;
-       int nr_contig_chunks, loop_nr_contig_chunks;
-       int remaining_nr_contig_chunks, nr_lookup;
-       int err, map_err;
-
-       map_err = scif_map_window(ep->remote_dev, window);
-       if (map_err)
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d map_err %d\n", __func__, __LINE__, map_err);
-       remaining_nr_contig_chunks = window->nr_contig_chunks;
-       nr_contig_chunks = window->nr_contig_chunks;
-retry:
-       /* Wait for a SCIF_ALLOC_GNT/REJ message */
-       err = wait_event_timeout(alloc->allocwq,
-                                alloc->state != OP_IN_PROGRESS,
-                                SCIF_NODE_ALIVE_TIMEOUT);
-       mutex_lock(&ep->rma_info.rma_lock);
-       /* Synchronize with the thread waking up allocwq */
-       mutex_unlock(&ep->rma_info.rma_lock);
-       if (!err && scifdev_alive(ep))
-               goto retry;
-
-       if (!err)
-               err = -ENODEV;
-
-       if (err > 0)
-               err = 0;
-       else
-               return err;
-
-       /* Bail out. The remote end rejected this request */
-       if (alloc->state == OP_FAILED)
-               return -ENOMEM;
-
-       if (map_err) {
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d err %d\n", __func__, __LINE__, map_err);
-               msg.uop = SCIF_FREE_VIRT;
-               msg.src = ep->port;
-               msg.payload[0] = ep->remote_ep;
-               msg.payload[1] = window->alloc_handle.vaddr;
-               msg.payload[2] = (u64)window;
-               msg.payload[3] = SCIF_REGISTER;
-               spin_lock(&ep->lock);
-               if (ep->state == SCIFEP_CONNECTED)
-                       err = _scif_nodeqp_send(ep->remote_dev, &msg);
-               else
-                       err = -ENOTCONN;
-               spin_unlock(&ep->lock);
-               return err;
-       }
-
-       remote_window = scif_ioremap(alloc->phys_addr, sizeof(*window),
-                                    ep->remote_dev);
-
-       /* Compute the number of lookup entries. 21 == 2MB Shift */
-       nr_lookup = ALIGN(nr_contig_chunks, SCIF_NR_ADDR_IN_PAGE)
-                         >> ilog2(SCIF_NR_ADDR_IN_PAGE);
-
-       dma_phys_lookup =
-               scif_ioremap(remote_window->dma_addr_lookup.offset,
-                            nr_lookup *
-                            sizeof(*remote_window->dma_addr_lookup.lookup),
-                            ep->remote_dev);
-       num_pages_lookup =
-               scif_ioremap(remote_window->num_pages_lookup.offset,
-                            nr_lookup *
-                            sizeof(*remote_window->num_pages_lookup.lookup),
-                            ep->remote_dev);
-
-       while (remaining_nr_contig_chunks) {
-               loop_nr_contig_chunks = min_t(int, remaining_nr_contig_chunks,
-                                             (int)SCIF_NR_ADDR_IN_PAGE);
-               /* #1/2 - Copy  physical addresses over to the remote side */
-
-               /* #2/2 - Copy DMA addresses (addresses that are fed into the
-                * DMA engine) We transfer bus addresses which are then
-                * converted into a MIC physical address on the remote
-                * side if it is a MIC, if the remote node is a mgmt node we
-                * transfer the MIC physical address
-                */
-               tmp = scif_ioremap(dma_phys_lookup[j],
-                                  loop_nr_contig_chunks *
-                                  sizeof(*window->dma_addr),
-                                  ep->remote_dev);
-               tmp1 = scif_ioremap(num_pages_lookup[j],
-                                   loop_nr_contig_chunks *
-                                   sizeof(*window->num_pages),
-                                   ep->remote_dev);
-               if (scif_is_mgmt_node()) {
-                       memcpy_toio((void __force __iomem *)tmp,
-                                   &window->dma_addr[i], loop_nr_contig_chunks
-                                   * sizeof(*window->dma_addr));
-                       memcpy_toio((void __force __iomem *)tmp1,
-                                   &window->num_pages[i], loop_nr_contig_chunks
-                                   * sizeof(*window->num_pages));
-               } else {
-                       if (scifdev_is_p2p(ep->remote_dev)) {
-                               /*
-                                * add remote node's base address for this node
-                                * to convert it into a MIC address
-                                */
-                               int m;
-                               dma_addr_t dma_addr;
-
-                               for (m = 0; m < loop_nr_contig_chunks; m++) {
-                                       dma_addr = window->dma_addr[i + m] +
-                                               ep->remote_dev->base_addr;
-                                       writeq(dma_addr,
-                                              (void __force __iomem *)&tmp[m]);
-                               }
-                               memcpy_toio((void __force __iomem *)tmp1,
-                                           &window->num_pages[i],
-                                           loop_nr_contig_chunks
-                                           * sizeof(*window->num_pages));
-                       } else {
-                               /* Mgmt node or loopback - transfer DMA
-                                * addresses as is, this is the same as a
-                                * MIC physical address (we use the dma_addr
-                                * and not the phys_addr array since the
-                                * phys_addr is only setup if there is a mmap()
-                                * request from the mgmt node)
-                                */
-                               memcpy_toio((void __force __iomem *)tmp,
-                                           &window->dma_addr[i],
-                                           loop_nr_contig_chunks *
-                                           sizeof(*window->dma_addr));
-                               memcpy_toio((void __force __iomem *)tmp1,
-                                           &window->num_pages[i],
-                                           loop_nr_contig_chunks *
-                                           sizeof(*window->num_pages));
-                       }
-               }
-               remaining_nr_contig_chunks -= loop_nr_contig_chunks;
-               i += loop_nr_contig_chunks;
-               j++;
-               scif_iounmap(tmp, loop_nr_contig_chunks *
-                            sizeof(*window->dma_addr), ep->remote_dev);
-               scif_iounmap(tmp1, loop_nr_contig_chunks *
-                            sizeof(*window->num_pages), ep->remote_dev);
-       }
-
-       /* Prepare the remote window for the peer */
-       remote_window->peer_window = (u64)window;
-       remote_window->offset = window->offset;
-       remote_window->prot = window->prot;
-       remote_window->nr_contig_chunks = nr_contig_chunks;
-       remote_window->ep = ep->remote_ep;
-       scif_iounmap(num_pages_lookup,
-                    nr_lookup *
-                    sizeof(*remote_window->num_pages_lookup.lookup),
-                    ep->remote_dev);
-       scif_iounmap(dma_phys_lookup,
-                    nr_lookup *
-                    sizeof(*remote_window->dma_addr_lookup.lookup),
-                    ep->remote_dev);
-       scif_iounmap(remote_window, sizeof(*remote_window), ep->remote_dev);
-       window->peer_window = alloc->vaddr;
-       return err;
-}
-
-/**
- * scif_send_scif_register:
- * @ep: end point
- * @window: self registration window
- *
- * Send a SCIF_REGISTER message if EP is connected and wait for a
- * SCIF_REGISTER_(N)ACK message else send a SCIF_FREE_VIRT
- * message so that the peer can free its remote window allocated earlier.
- */
-static int scif_send_scif_register(struct scif_endpt *ep,
-                                  struct scif_window *window)
-{
-       int err = 0;
-       struct scifmsg msg;
-
-       msg.src = ep->port;
-       msg.payload[0] = ep->remote_ep;
-       msg.payload[1] = window->alloc_handle.vaddr;
-       msg.payload[2] = (u64)window;
-       spin_lock(&ep->lock);
-       if (ep->state == SCIFEP_CONNECTED) {
-               msg.uop = SCIF_REGISTER;
-               window->reg_state = OP_IN_PROGRESS;
-               err = _scif_nodeqp_send(ep->remote_dev, &msg);
-               spin_unlock(&ep->lock);
-               if (!err) {
-retry:
-                       /* Wait for a SCIF_REGISTER_(N)ACK message */
-                       err = wait_event_timeout(window->regwq,
-                                                window->reg_state !=
-                                                OP_IN_PROGRESS,
-                                                SCIF_NODE_ALIVE_TIMEOUT);
-                       if (!err && scifdev_alive(ep))
-                               goto retry;
-                       err = !err ? -ENODEV : 0;
-                       if (window->reg_state == OP_FAILED)
-                               err = -ENOTCONN;
-               }
-       } else {
-               msg.uop = SCIF_FREE_VIRT;
-               msg.payload[3] = SCIF_REGISTER;
-               err = _scif_nodeqp_send(ep->remote_dev, &msg);
-               spin_unlock(&ep->lock);
-               if (!err)
-                       err = -ENOTCONN;
-       }
-       return err;
-}
-
-/**
- * scif_get_window_offset:
- * @ep: end point descriptor
- * @flags: flags
- * @offset: offset hint
- * @num_pages: number of pages
- * @out_offset: computed offset returned by reference.
- *
- * Compute/Claim a new offset for this EP.
- */
-int scif_get_window_offset(struct scif_endpt *ep, int flags, s64 offset,
-                          int num_pages, s64 *out_offset)
-{
-       s64 page_index;
-       struct iova *iova_ptr;
-       int err = 0;
-
-       if (flags & SCIF_MAP_FIXED) {
-               page_index = SCIF_IOVA_PFN(offset);
-               iova_ptr = reserve_iova(&ep->rma_info.iovad, page_index,
-                                       page_index + num_pages - 1);
-               if (!iova_ptr)
-                       err = -EADDRINUSE;
-       } else {
-               iova_ptr = alloc_iova(&ep->rma_info.iovad, num_pages,
-                                     SCIF_DMA_63BIT_PFN - 1, 0);
-               if (!iova_ptr)
-                       err = -ENOMEM;
-       }
-       if (!err)
-               *out_offset = (iova_ptr->pfn_lo) << PAGE_SHIFT;
-       return err;
-}
-
-/**
- * scif_free_window_offset:
- * @ep: end point descriptor
- * @window: registration window
- * @offset: Offset to be freed
- *
- * Free offset for this EP. The callee is supposed to grab
- * the RMA mutex before calling this API.
- */
-void scif_free_window_offset(struct scif_endpt *ep,
-                            struct scif_window *window, s64 offset)
-{
-       if ((window && !window->offset_freed) || !window) {
-               free_iova(&ep->rma_info.iovad, offset >> PAGE_SHIFT);
-               if (window)
-                       window->offset_freed = true;
-       }
-}
-
-/**
- * scif_alloc_req: Respond to SCIF_ALLOC_REQ interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * Remote side is requesting a memory allocation.
- */
-void scif_alloc_req(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       int err;
-       struct scif_window *window = NULL;
-       int nr_pages = msg->payload[1];
-
-       window = scif_create_remote_window(scifdev, nr_pages);
-       if (!window) {
-               err = -ENOMEM;
-               goto error;
-       }
-
-       /* The peer's allocation request is granted */
-       msg->uop = SCIF_ALLOC_GNT;
-       msg->payload[0] = (u64)window;
-       msg->payload[1] = window->mapped_offset;
-       err = scif_nodeqp_send(scifdev, msg);
-       if (err)
-               scif_destroy_remote_window(window);
-       return;
-error:
-       /* The peer's allocation request is rejected */
-       dev_err(&scifdev->sdev->dev,
-               "%s %d error %d alloc_ptr %p nr_pages 0x%x\n",
-               __func__, __LINE__, err, window, nr_pages);
-       msg->uop = SCIF_ALLOC_REJ;
-       scif_nodeqp_send(scifdev, msg);
-}
-
-/**
- * scif_alloc_gnt_rej: Respond to SCIF_ALLOC_GNT/REJ interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * Remote side responded to a memory allocation.
- */
-void scif_alloc_gnt_rej(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_allocmsg *handle = (struct scif_allocmsg *)msg->payload[2];
-       struct scif_window *window = container_of(handle, struct scif_window,
-                                                 alloc_handle);
-       struct scif_endpt *ep = (struct scif_endpt *)window->ep;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       handle->vaddr = msg->payload[0];
-       handle->phys_addr = msg->payload[1];
-       if (msg->uop == SCIF_ALLOC_GNT)
-               handle->state = OP_COMPLETED;
-       else
-               handle->state = OP_FAILED;
-       wake_up(&handle->allocwq);
-       mutex_unlock(&ep->rma_info.rma_lock);
-}
-
-/**
- * scif_free_virt: Respond to SCIF_FREE_VIRT interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * Free up memory kmalloc'd earlier.
- */
-void scif_free_virt(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_window *window = (struct scif_window *)msg->payload[1];
-
-       scif_destroy_remote_window(window);
-}
-
-static void
-scif_fixup_aper_base(struct scif_dev *dev, struct scif_window *window)
-{
-       int j;
-       struct scif_hw_dev *sdev = dev->sdev;
-       phys_addr_t apt_base = 0;
-
-       /*
-        * Add the aperture base if the DMA address is not card relative
-        * since the DMA addresses need to be an offset into the bar
-        */
-       if (!scifdev_self(dev) && window->type == SCIF_WINDOW_PEER &&
-           sdev->aper && !sdev->card_rel_da)
-               apt_base = sdev->aper->pa;
-       else
-               return;
-
-       for (j = 0; j < window->nr_contig_chunks; j++) {
-               if (window->num_pages[j])
-                       window->dma_addr[j] += apt_base;
-               else
-                       break;
-       }
-}
-
-/**
- * scif_recv_reg: Respond to SCIF_REGISTER interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * Update remote window list with a new registered window.
- */
-void scif_recv_reg(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
-       struct scif_window *window =
-               (struct scif_window *)msg->payload[1];
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       spin_lock(&ep->lock);
-       if (ep->state == SCIFEP_CONNECTED) {
-               msg->uop = SCIF_REGISTER_ACK;
-               scif_nodeqp_send(ep->remote_dev, msg);
-               scif_fixup_aper_base(ep->remote_dev, window);
-               /* No further failures expected. Insert new window */
-               scif_insert_window(window, &ep->rma_info.remote_reg_list);
-       } else {
-               msg->uop = SCIF_REGISTER_NACK;
-               scif_nodeqp_send(ep->remote_dev, msg);
-       }
-       spin_unlock(&ep->lock);
-       mutex_unlock(&ep->rma_info.rma_lock);
-       /* free up any lookup resources now that page lists are transferred */
-       scif_destroy_remote_lookup(ep->remote_dev, window);
-       /*
-        * We could not insert the window but we need to
-        * destroy the window.
-        */
-       if (msg->uop == SCIF_REGISTER_NACK)
-               scif_destroy_remote_window(window);
-}
-
-/**
- * scif_recv_unreg: Respond to SCIF_UNREGISTER interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * Remove window from remote registration list;
- */
-void scif_recv_unreg(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_rma_req req;
-       struct scif_window *window = NULL;
-       struct scif_window *recv_window =
-               (struct scif_window *)msg->payload[0];
-       struct scif_endpt *ep;
-       int del_window = 0;
-
-       ep = (struct scif_endpt *)recv_window->ep;
-       req.out_window = &window;
-       req.offset = recv_window->offset;
-       req.prot = 0;
-       req.nr_bytes = recv_window->nr_pages << PAGE_SHIFT;
-       req.type = SCIF_WINDOW_FULL;
-       req.head = &ep->rma_info.remote_reg_list;
-       msg->payload[0] = ep->remote_ep;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       /* Does a valid window exist? */
-       if (scif_query_window(&req)) {
-               dev_err(&scifdev->sdev->dev,
-                       "%s %d -ENXIO\n", __func__, __LINE__);
-               msg->uop = SCIF_UNREGISTER_ACK;
-               goto error;
-       }
-       if (window) {
-               if (window->ref_count)
-                       scif_put_window(window, window->nr_pages);
-               else
-                       dev_err(&scifdev->sdev->dev,
-                               "%s %d ref count should be +ve\n",
-                               __func__, __LINE__);
-               window->unreg_state = OP_COMPLETED;
-               if (!window->ref_count) {
-                       msg->uop = SCIF_UNREGISTER_ACK;
-                       atomic_inc(&ep->rma_info.tw_refcount);
-                       ep->rma_info.async_list_del = 1;
-                       list_del_init(&window->list);
-                       del_window = 1;
-               } else {
-                       /* NACK! There are valid references to this window */
-                       msg->uop = SCIF_UNREGISTER_NACK;
-               }
-       } else {
-               /* The window did not make its way to the list at all. ACK */
-               msg->uop = SCIF_UNREGISTER_ACK;
-               scif_destroy_remote_window(recv_window);
-       }
-error:
-       mutex_unlock(&ep->rma_info.rma_lock);
-       if (del_window)
-               scif_drain_dma_intr(ep->remote_dev->sdev,
-                                   ep->rma_info.dma_chan);
-       scif_nodeqp_send(ep->remote_dev, msg);
-       if (del_window)
-               scif_queue_for_cleanup(window, &scif_info.rma);
-}
-
-/**
- * scif_recv_reg_ack: Respond to SCIF_REGISTER_ACK interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * Wake up the window waiting to complete registration.
- */
-void scif_recv_reg_ack(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_window *window =
-               (struct scif_window *)msg->payload[2];
-       struct scif_endpt *ep = (struct scif_endpt *)window->ep;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       window->reg_state = OP_COMPLETED;
-       wake_up(&window->regwq);
-       mutex_unlock(&ep->rma_info.rma_lock);
-}
-
-/**
- * scif_recv_reg_nack: Respond to SCIF_REGISTER_NACK interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * Wake up the window waiting to inform it that registration
- * cannot be completed.
- */
-void scif_recv_reg_nack(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_window *window =
-               (struct scif_window *)msg->payload[2];
-       struct scif_endpt *ep = (struct scif_endpt *)window->ep;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       window->reg_state = OP_FAILED;
-       wake_up(&window->regwq);
-       mutex_unlock(&ep->rma_info.rma_lock);
-}
-
-/**
- * scif_recv_unreg_ack: Respond to SCIF_UNREGISTER_ACK interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * Wake up the window waiting to complete unregistration.
- */
-void scif_recv_unreg_ack(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_window *window =
-               (struct scif_window *)msg->payload[1];
-       struct scif_endpt *ep = (struct scif_endpt *)window->ep;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       window->unreg_state = OP_COMPLETED;
-       wake_up(&window->unregwq);
-       mutex_unlock(&ep->rma_info.rma_lock);
-}
-
-/**
- * scif_recv_unreg_nack: Respond to SCIF_UNREGISTER_NACK interrupt message
- * @scifdev:    SCIF device
- * @msg:        Interrupt message
- *
- * Wake up the window waiting to inform it that unregistration
- * cannot be completed immediately.
- */
-void scif_recv_unreg_nack(struct scif_dev *scifdev, struct scifmsg *msg)
-{
-       struct scif_window *window =
-               (struct scif_window *)msg->payload[1];
-       struct scif_endpt *ep = (struct scif_endpt *)window->ep;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       window->unreg_state = OP_FAILED;
-       wake_up(&window->unregwq);
-       mutex_unlock(&ep->rma_info.rma_lock);
-}
-
-int __scif_pin_pages(void *addr, size_t len, int *out_prot,
-                    int map_flags, scif_pinned_pages_t *pages)
-{
-       struct scif_pinned_pages *pinned_pages;
-       int nr_pages, err = 0, i;
-       bool vmalloc_addr = false;
-       bool try_upgrade = false;
-       int prot = *out_prot;
-       int ulimit = 0;
-       struct mm_struct *mm = NULL;
-
-       /* Unsupported flags */
-       if (map_flags & ~(SCIF_MAP_KERNEL | SCIF_MAP_ULIMIT))
-               return -EINVAL;
-       ulimit = !!(map_flags & SCIF_MAP_ULIMIT);
-
-       /* Unsupported protection requested */
-       if (prot & ~(SCIF_PROT_READ | SCIF_PROT_WRITE))
-               return -EINVAL;
-
-       /* addr/len must be page aligned. len should be non zero */
-       if (!len ||
-           (ALIGN((u64)addr, PAGE_SIZE) != (u64)addr) ||
-           (ALIGN((u64)len, PAGE_SIZE) != (u64)len))
-               return -EINVAL;
-
-       might_sleep();
-
-       nr_pages = len >> PAGE_SHIFT;
-
-       /* Allocate a set of pinned pages */
-       pinned_pages = scif_create_pinned_pages(nr_pages, prot);
-       if (!pinned_pages)
-               return -ENOMEM;
-
-       if (map_flags & SCIF_MAP_KERNEL) {
-               if (is_vmalloc_addr(addr))
-                       vmalloc_addr = true;
-
-               for (i = 0; i < nr_pages; i++) {
-                       if (vmalloc_addr)
-                               pinned_pages->pages[i] =
-                                       vmalloc_to_page(addr + (i * PAGE_SIZE));
-                       else
-                               pinned_pages->pages[i] =
-                                       virt_to_page(addr + (i * PAGE_SIZE));
-               }
-               pinned_pages->nr_pages = nr_pages;
-               pinned_pages->map_flags = SCIF_MAP_KERNEL;
-       } else {
-               /*
-                * SCIF supports registration caching. If a registration has
-                * been requested with read only permissions, then we try
-                * to pin the pages with RW permissions so that a subsequent
-                * transfer with RW permission can hit the cache instead of
-                * invalidating it. If the upgrade fails with RW then we
-                * revert back to R permission and retry
-                */
-               if (prot == SCIF_PROT_READ)
-                       try_upgrade = true;
-               prot |= SCIF_PROT_WRITE;
-retry:
-               mm = current->mm;
-               if (ulimit) {
-                       err = __scif_check_inc_pinned_vm(mm, nr_pages);
-                       if (err) {
-                               pinned_pages->nr_pages = 0;
-                               goto error_unmap;
-                       }
-               }
-
-               pinned_pages->nr_pages = pin_user_pages_fast(
-                               (u64)addr,
-                               nr_pages,
-                               (prot & SCIF_PROT_WRITE) ? FOLL_WRITE : 0,
-                               pinned_pages->pages);
-               if (nr_pages != pinned_pages->nr_pages) {
-                       if (pinned_pages->nr_pages < 0)
-                               pinned_pages->nr_pages = 0;
-                       if (try_upgrade) {
-                               if (ulimit)
-                                       __scif_dec_pinned_vm_lock(mm, nr_pages);
-                               /* Roll back any pinned pages */
-                               unpin_user_pages(pinned_pages->pages,
-                                                pinned_pages->nr_pages);
-                               prot &= ~SCIF_PROT_WRITE;
-                               try_upgrade = false;
-                               goto retry;
-                       }
-               }
-               pinned_pages->map_flags = 0;
-       }
-
-       if (pinned_pages->nr_pages < nr_pages) {
-               err = -EFAULT;
-               goto dec_pinned;
-       }
-
-       *out_prot = prot;
-       atomic_set(&pinned_pages->ref_count, 1);
-       *pages = pinned_pages;
-       return err;
-dec_pinned:
-       if (ulimit)
-               __scif_dec_pinned_vm_lock(mm, nr_pages);
-       /* Something went wrong! Rollback */
-error_unmap:
-       scif_destroy_pinned_pages(pinned_pages);
-       *pages = NULL;
-       dev_dbg(scif_info.mdev.this_device,
-               "%s %d err %d len 0x%lx\n", __func__, __LINE__, err, len);
-       return err;
-}
-
-int scif_pin_pages(void *addr, size_t len, int prot,
-                  int map_flags, scif_pinned_pages_t *pages)
-{
-       return __scif_pin_pages(addr, len, &prot, map_flags, pages);
-}
-EXPORT_SYMBOL_GPL(scif_pin_pages);
-
-int scif_unpin_pages(scif_pinned_pages_t pinned_pages)
-{
-       int err = 0, ret;
-
-       if (!pinned_pages || SCIFEP_MAGIC != pinned_pages->magic)
-               return -EINVAL;
-
-       ret = atomic_sub_return(1, &pinned_pages->ref_count);
-       if (ret < 0) {
-               dev_err(scif_info.mdev.this_device,
-                       "%s %d scif_unpin_pages called without pinning? rc %d\n",
-                       __func__, __LINE__, ret);
-               return -EINVAL;
-       }
-       /*
-        * Destroy the window if the ref count for this set of pinned
-        * pages has dropped to zero. If it is positive then there is
-        * a valid registered window which is backed by these pages and
-        * it will be destroyed once all such windows are unregistered.
-        */
-       if (!ret)
-               err = scif_destroy_pinned_pages(pinned_pages);
-
-       return err;
-}
-EXPORT_SYMBOL_GPL(scif_unpin_pages);
-
-static inline void
-scif_insert_local_window(struct scif_window *window, struct scif_endpt *ep)
-{
-       mutex_lock(&ep->rma_info.rma_lock);
-       scif_insert_window(window, &ep->rma_info.reg_list);
-       mutex_unlock(&ep->rma_info.rma_lock);
-}
-
-off_t scif_register_pinned_pages(scif_epd_t epd,
-                                scif_pinned_pages_t pinned_pages,
-                                off_t offset, int map_flags)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       s64 computed_offset;
-       struct scif_window *window;
-       int err;
-       size_t len;
-       struct device *spdev;
-
-       /* Unsupported flags */
-       if (map_flags & ~SCIF_MAP_FIXED)
-               return -EINVAL;
-
-       len = pinned_pages->nr_pages << PAGE_SHIFT;
-
-       /*
-        * Offset is not page aligned/negative or offset+len
-        * wraps around with SCIF_MAP_FIXED.
-        */
-       if ((map_flags & SCIF_MAP_FIXED) &&
-           ((ALIGN(offset, PAGE_SIZE) != offset) ||
-           (offset < 0) ||
-           (len > LONG_MAX - offset)))
-               return -EINVAL;
-
-       might_sleep();
-
-       err = scif_verify_epd(ep);
-       if (err)
-               return err;
-       /*
-        * It is an error to pass pinned_pages to scif_register_pinned_pages()
-        * after calling scif_unpin_pages().
-        */
-       if (!atomic_add_unless(&pinned_pages->ref_count, 1, 0))
-               return -EINVAL;
-
-       /* Compute the offset for this registration */
-       err = scif_get_window_offset(ep, map_flags, offset,
-                                    len, &computed_offset);
-       if (err) {
-               atomic_sub(1, &pinned_pages->ref_count);
-               return err;
-       }
-
-       /* Allocate and prepare self registration window */
-       window = scif_create_window(ep, pinned_pages->nr_pages,
-                                   computed_offset, false);
-       if (!window) {
-               atomic_sub(1, &pinned_pages->ref_count);
-               scif_free_window_offset(ep, NULL, computed_offset);
-               return -ENOMEM;
-       }
-
-       window->pinned_pages = pinned_pages;
-       window->nr_pages = pinned_pages->nr_pages;
-       window->prot = pinned_pages->prot;
-
-       spdev = scif_get_peer_dev(ep->remote_dev);
-       if (IS_ERR(spdev)) {
-               err = PTR_ERR(spdev);
-               scif_destroy_window(ep, window);
-               return err;
-       }
-       err = scif_send_alloc_request(ep, window);
-       if (err) {
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-               goto error_unmap;
-       }
-
-       /* Prepare the remote registration window */
-       err = scif_prep_remote_window(ep, window);
-       if (err) {
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-               goto error_unmap;
-       }
-
-       /* Tell the peer about the new window */
-       err = scif_send_scif_register(ep, window);
-       if (err) {
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-               goto error_unmap;
-       }
-
-       scif_put_peer_dev(spdev);
-       /* No further failures expected. Insert new window */
-       scif_insert_local_window(window, ep);
-       return computed_offset;
-error_unmap:
-       scif_destroy_window(ep, window);
-       scif_put_peer_dev(spdev);
-       dev_err(&ep->remote_dev->sdev->dev,
-               "%s %d err %d\n", __func__, __LINE__, err);
-       return err;
-}
-EXPORT_SYMBOL_GPL(scif_register_pinned_pages);
-
-off_t scif_register(scif_epd_t epd, void *addr, size_t len, off_t offset,
-                   int prot, int map_flags)
-{
-       scif_pinned_pages_t pinned_pages;
-       off_t err;
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       s64 computed_offset;
-       struct scif_window *window;
-       struct mm_struct *mm = NULL;
-       struct device *spdev;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI register: ep %p addr %p len 0x%lx offset 0x%lx prot 0x%x map_flags 0x%x\n",
-               epd, addr, len, offset, prot, map_flags);
-       /* Unsupported flags */
-       if (map_flags & ~(SCIF_MAP_FIXED | SCIF_MAP_KERNEL))
-               return -EINVAL;
-
-       /*
-        * Offset is not page aligned/negative or offset+len
-        * wraps around with SCIF_MAP_FIXED.
-        */
-       if ((map_flags & SCIF_MAP_FIXED) &&
-           ((ALIGN(offset, PAGE_SIZE) != offset) ||
-           (offset < 0) ||
-           (len > LONG_MAX - offset)))
-               return -EINVAL;
-
-       /* Unsupported protection requested */
-       if (prot & ~(SCIF_PROT_READ | SCIF_PROT_WRITE))
-               return -EINVAL;
-
-       /* addr/len must be page aligned. len should be non zero */
-       if (!len || (ALIGN((u64)addr, PAGE_SIZE) != (u64)addr) ||
-           (ALIGN(len, PAGE_SIZE) != len))
-               return -EINVAL;
-
-       might_sleep();
-
-       err = scif_verify_epd(ep);
-       if (err)
-               return err;
-
-       /* Compute the offset for this registration */
-       err = scif_get_window_offset(ep, map_flags, offset,
-                                    len >> PAGE_SHIFT, &computed_offset);
-       if (err)
-               return err;
-
-       spdev = scif_get_peer_dev(ep->remote_dev);
-       if (IS_ERR(spdev)) {
-               err = PTR_ERR(spdev);
-               scif_free_window_offset(ep, NULL, computed_offset);
-               return err;
-       }
-       /* Allocate and prepare self registration window */
-       window = scif_create_window(ep, len >> PAGE_SHIFT,
-                                   computed_offset, false);
-       if (!window) {
-               scif_free_window_offset(ep, NULL, computed_offset);
-               scif_put_peer_dev(spdev);
-               return -ENOMEM;
-       }
-
-       window->nr_pages = len >> PAGE_SHIFT;
-
-       err = scif_send_alloc_request(ep, window);
-       if (err) {
-               scif_destroy_incomplete_window(ep, window);
-               scif_put_peer_dev(spdev);
-               return err;
-       }
-
-       if (!(map_flags & SCIF_MAP_KERNEL)) {
-               mm = __scif_acquire_mm();
-               map_flags |= SCIF_MAP_ULIMIT;
-       }
-       /* Pin down the pages */
-       err = __scif_pin_pages(addr, len, &prot,
-                              map_flags & (SCIF_MAP_KERNEL | SCIF_MAP_ULIMIT),
-                              &pinned_pages);
-       if (err) {
-               scif_destroy_incomplete_window(ep, window);
-               __scif_release_mm(mm);
-               goto error;
-       }
-
-       window->pinned_pages = pinned_pages;
-       window->prot = pinned_pages->prot;
-       window->mm = mm;
-
-       /* Prepare the remote registration window */
-       err = scif_prep_remote_window(ep, window);
-       if (err) {
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d err %ld\n", __func__, __LINE__, err);
-               goto error_unmap;
-       }
-
-       /* Tell the peer about the new window */
-       err = scif_send_scif_register(ep, window);
-       if (err) {
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d err %ld\n", __func__, __LINE__, err);
-               goto error_unmap;
-       }
-
-       scif_put_peer_dev(spdev);
-       /* No further failures expected. Insert new window */
-       scif_insert_local_window(window, ep);
-       dev_dbg(&ep->remote_dev->sdev->dev,
-               "SCIFAPI register: ep %p addr %p len 0x%lx computed_offset 0x%llx\n",
-               epd, addr, len, computed_offset);
-       return computed_offset;
-error_unmap:
-       scif_destroy_window(ep, window);
-error:
-       scif_put_peer_dev(spdev);
-       dev_err(&ep->remote_dev->sdev->dev,
-               "%s %d err %ld\n", __func__, __LINE__, err);
-       return err;
-}
-EXPORT_SYMBOL_GPL(scif_register);
-
-int
-scif_unregister(scif_epd_t epd, off_t offset, size_t len)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       struct scif_window *window = NULL;
-       struct scif_rma_req req;
-       int nr_pages, err;
-       struct device *spdev;
-
-       dev_dbg(scif_info.mdev.this_device,
-               "SCIFAPI unregister: ep %p offset 0x%lx len 0x%lx\n",
-               ep, offset, len);
-       /* len must be page aligned. len should be non zero */
-       if (!len ||
-           (ALIGN((u64)len, PAGE_SIZE) != (u64)len))
-               return -EINVAL;
-
-       /* Offset is not page aligned or offset+len wraps around */
-       if ((ALIGN(offset, PAGE_SIZE) != offset) ||
-           (offset < 0) ||
-           (len > LONG_MAX - offset))
-               return -EINVAL;
-
-       err = scif_verify_epd(ep);
-       if (err)
-               return err;
-
-       might_sleep();
-       nr_pages = len >> PAGE_SHIFT;
-
-       req.out_window = &window;
-       req.offset = offset;
-       req.prot = 0;
-       req.nr_bytes = len;
-       req.type = SCIF_WINDOW_FULL;
-       req.head = &ep->rma_info.reg_list;
-
-       spdev = scif_get_peer_dev(ep->remote_dev);
-       if (IS_ERR(spdev)) {
-               err = PTR_ERR(spdev);
-               return err;
-       }
-       mutex_lock(&ep->rma_info.rma_lock);
-       /* Does a valid window exist? */
-       err = scif_query_window(&req);
-       if (err) {
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-               goto error;
-       }
-       /* Unregister all the windows in this range */
-       err = scif_rma_list_unregister(window, offset, nr_pages);
-       if (err)
-               dev_err(&ep->remote_dev->sdev->dev,
-                       "%s %d err %d\n", __func__, __LINE__, err);
-error:
-       mutex_unlock(&ep->rma_info.rma_lock);
-       scif_put_peer_dev(spdev);
-       return err;
-}
-EXPORT_SYMBOL_GPL(scif_unregister);
diff --git a/drivers/misc/mic/scif/scif_rma.h b/drivers/misc/mic/scif/scif_rma.h
deleted file mode 100644 (file)
index 964dd0f..0000000
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in
- *   the documentation and/or other materials provided with the
- *   distribution.
- * * Neither the name of Intel Corporation nor the names of its
- *   contributors may be used to endorse or promote products derived
- *   from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Intel SCIF driver.
- *
- */
-#ifndef SCIF_RMA_H
-#define SCIF_RMA_H
-
-#include <linux/intel-iommu.h>
-#include <linux/mmu_notifier.h>
-
-#include "../bus/scif_bus.h"
-
-/* If this bit is set then the mark is a remote fence mark */
-#define SCIF_REMOTE_FENCE_BIT          31
-/* Magic value used to indicate a remote fence request */
-#define SCIF_REMOTE_FENCE BIT_ULL(SCIF_REMOTE_FENCE_BIT)
-
-#define SCIF_MAX_UNALIGNED_BUF_SIZE (1024 * 1024ULL)
-#define SCIF_KMEM_UNALIGNED_BUF_SIZE (SCIF_MAX_UNALIGNED_BUF_SIZE + \
-                                     (L1_CACHE_BYTES << 1))
-
-#define SCIF_IOVA_START_PFN            (1)
-#define SCIF_IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
-#define SCIF_DMA_64BIT_PFN SCIF_IOVA_PFN(DMA_BIT_MASK(64))
-#define SCIF_DMA_63BIT_PFN SCIF_IOVA_PFN(DMA_BIT_MASK(63))
-
-/*
- * struct scif_endpt_rma_info - Per Endpoint Remote Memory Access Information
- *
- * @reg_list: List of registration windows for self
- * @remote_reg_list: List of registration windows for peer
- * @iovad: Offset generator
- * @rma_lock: Synchronizes access to self/remote list and also protects the
- *           window from being destroyed while RMAs are in progress.
- * @tc_lock: Synchronizes access to temporary cached windows list
- *          for SCIF Registration Caching.
- * @mmn_lock: Synchronizes access to the list of MMU notifiers registered
- * @tw_refcount: Keeps track of number of outstanding temporary registered
- *              windows created by scif_vreadfrom/scif_vwriteto which have
- *              not been destroyed.
- * @tcw_refcount: Same as tw_refcount but for temporary cached windows
- * @tcw_total_pages: Same as tcw_refcount but in terms of pages pinned
- * @mmn_list: MMU notifier so that we can destroy the windows when required
- * @fence_refcount: Keeps track of number of outstanding remote fence
- *                 requests which have been received by the peer.
- * @dma_chan: DMA channel used for all DMA transfers for this endpoint.
- * @async_list_del: Detect asynchronous list entry deletion
- * @vma_list: List of vmas with remote memory mappings
- * @markwq: Wait queue used for scif_fence_mark/scif_fence_wait
-*/
-struct scif_endpt_rma_info {
-       struct list_head reg_list;
-       struct list_head remote_reg_list;
-       struct iova_domain iovad;
-       struct mutex rma_lock;
-       spinlock_t tc_lock;
-       struct mutex mmn_lock;
-       atomic_t tw_refcount;
-       atomic_t tcw_refcount;
-       atomic_t tcw_total_pages;
-       struct list_head mmn_list;
-       atomic_t fence_refcount;
-       struct dma_chan *dma_chan;
-       int async_list_del;
-       struct list_head vma_list;
-       wait_queue_head_t markwq;
-};
-
-/*
- * struct scif_fence_info - used for tracking fence requests
- *
- * @state: State of this transfer
- * @wq: Fences wait on this queue
- * @dma_mark: Used for storing the DMA mark
- */
-struct scif_fence_info {
-       enum scif_msg_state state;
-       struct completion comp;
-       int dma_mark;
-};
-
-/*
- * struct scif_remote_fence_info - used for tracking remote fence requests
- *
- * @msg: List of SCIF node QP fence messages
- * @list: Link to list of remote fence requests
- */
-struct scif_remote_fence_info {
-       struct scifmsg msg;
-       struct list_head list;
-};
-
-/*
- * Specifies whether an RMA operation can span across partial windows, a single
- * window or multiple contiguous windows. Mmaps can span across partial windows.
- * Unregistration can span across complete windows. scif_get_pages() can span a
- * single window. A window can also be of type self or peer.
- */
-enum scif_window_type {
-       SCIF_WINDOW_PARTIAL,
-       SCIF_WINDOW_SINGLE,
-       SCIF_WINDOW_FULL,
-       SCIF_WINDOW_SELF,
-       SCIF_WINDOW_PEER
-};
-
-/* The number of physical addresses that can be stored in a PAGE. */
-#define SCIF_NR_ADDR_IN_PAGE   (0x1000 >> 3)
-
-/*
- * struct scif_rma_lookup - RMA lookup data structure for page list transfers
- *
- * Store an array of lookup offsets. Each offset in this array maps
- * one 4K page containing 512 physical addresses i.e. 2MB. 512 such
- * offsets in a 4K page will correspond to 1GB of registered address space.
-
- * @lookup: Array of offsets
- * @offset: DMA offset of lookup array
- */
-struct scif_rma_lookup {
-       dma_addr_t *lookup;
-       dma_addr_t offset;
-};
-
-/*
- * struct scif_pinned_pages - A set of pinned pages obtained with
- * scif_pin_pages() which could be part of multiple registered
- * windows across different end points.
- *
- * @nr_pages: Number of pages which is defined as a s64 instead of an int
- * to avoid sign extension with buffers >= 2GB
- * @prot: read/write protections
- * @map_flags: Flags specified during the pin operation
- * @ref_count: Reference count bumped in terms of number of pages
- * @magic: A magic value
- * @pages: Array of pointers to struct pages populated with get_user_pages(..)
- */
-struct scif_pinned_pages {
-       s64 nr_pages;
-       int prot;
-       int map_flags;
-       atomic_t ref_count;
-       u64 magic;
-       struct page **pages;
-};
-
-/*
- * struct scif_status - Stores DMA status update information
- *
- * @src_dma_addr: Source buffer DMA address
- * @val: src location for value to be written to the destination
- * @ep: SCIF endpoint
- */
-struct scif_status {
-       dma_addr_t src_dma_addr;
-       u64 val;
-       struct scif_endpt *ep;
-};
-
-/*
- * struct scif_cb_arg - Stores the argument of the callback func
- *
- * @src_dma_addr: Source buffer DMA address
- * @status: DMA status
- * @ep: SCIF endpoint
- */
-struct scif_cb_arg {
-       dma_addr_t src_dma_addr;
-       struct scif_status *status;
-       struct scif_endpt *ep;
-};
-
-/*
- * struct scif_window - Registration Window for Self and Remote
- *
- * @nr_pages: Number of pages which is defined as a s64 instead of an int
- * to avoid sign extension with buffers >= 2GB
- * @nr_contig_chunks: Number of contiguous physical chunks
- * @prot: read/write protections
- * @ref_count: reference count in terms of number of pages
- * @magic: Cookie to detect corruption
- * @offset: registered offset
- * @va_for_temp: va address that this window represents
- * @dma_mark: Used to determine if all DMAs against the window are done
- * @ep: Pointer to EP. Useful for passing EP around with messages to
-       avoid expensive list traversals.
- * @list: link to list of windows for the endpoint
- * @type: self or peer window
- * @peer_window: Pointer to peer window. Useful for sending messages to peer
- *              without requiring an extra list traversal
- * @unreg_state: unregistration state
- * @offset_freed: True if the offset has been freed
- * @temp: True for temporary windows created via scif_vreadfrom/scif_vwriteto
- * @mm: memory descriptor for the task_struct which initiated the RMA
- * @st: scatter gather table for DMA mappings with IOMMU enabled
- * @pinned_pages: The set of pinned_pages backing this window
- * @alloc_handle: Handle for sending ALLOC_REQ
- * @regwq: Wait Queue for an registration (N)ACK
- * @reg_state: Registration state
- * @unregwq: Wait Queue for an unregistration (N)ACK
- * @dma_addr_lookup: Lookup for physical addresses used for DMA
- * @nr_lookup: Number of entries in lookup
- * @mapped_offset: Offset used to map the window by the peer
- * @dma_addr: Array of physical addresses used for Mgmt node & MIC initiated DMA
- * @num_pages: Array specifying number of pages for each physical address
- */
-struct scif_window {
-       s64 nr_pages;
-       int nr_contig_chunks;
-       int prot;
-       int ref_count;
-       u64 magic;
-       s64 offset;
-       unsigned long va_for_temp;
-       int dma_mark;
-       u64 ep;
-       struct list_head list;
-       enum scif_window_type type;
-       u64 peer_window;
-       enum scif_msg_state unreg_state;
-       bool offset_freed;
-       bool temp;
-       struct mm_struct *mm;
-       struct sg_table *st;
-       union {
-               struct {
-                       struct scif_pinned_pages *pinned_pages;
-                       struct scif_allocmsg alloc_handle;
-                       wait_queue_head_t regwq;
-                       enum scif_msg_state reg_state;
-                       wait_queue_head_t unregwq;
-               };
-               struct {
-                       struct scif_rma_lookup dma_addr_lookup;
-                       struct scif_rma_lookup num_pages_lookup;
-                       int nr_lookup;
-                       dma_addr_t mapped_offset;
-               };
-       };
-       dma_addr_t *dma_addr;
-       u64 *num_pages;
-} __packed;
-
-/*
- * scif_mmu_notif - SCIF mmu notifier information
- *
- * @mmu_notifier ep_mmu_notifier: MMU notifier operations
- * @tc_reg_list: List of temp registration windows for self
- * @mm: memory descriptor for the task_struct which initiated the RMA
- * @ep: SCIF endpoint
- * @list: link to list of MMU notifier information
- */
-struct scif_mmu_notif {
-#ifdef CONFIG_MMU_NOTIFIER
-       struct mmu_notifier ep_mmu_notifier;
-#endif
-       struct list_head tc_reg_list;
-       struct mm_struct *mm;
-       struct scif_endpt *ep;
-       struct list_head list;
-};
-
-enum scif_rma_dir {
-       SCIF_LOCAL_TO_REMOTE,
-       SCIF_REMOTE_TO_LOCAL
-};
-
-extern struct kmem_cache *unaligned_cache;
-/* Initialize RMA for this EP */
-void scif_rma_ep_init(struct scif_endpt *ep);
-/* Check if epd can be uninitialized */
-int scif_rma_ep_can_uninit(struct scif_endpt *ep);
-/* Obtain a new offset. Callee must grab RMA lock */
-int scif_get_window_offset(struct scif_endpt *ep, int flags,
-                          s64 offset, int nr_pages, s64 *out_offset);
-/* Free offset. Callee must grab RMA lock */
-void scif_free_window_offset(struct scif_endpt *ep,
-                            struct scif_window *window, s64 offset);
-/* Create self registration window */
-struct scif_window *scif_create_window(struct scif_endpt *ep, int nr_pages,
-                                      s64 offset, bool temp);
-/* Destroy self registration window.*/
-int scif_destroy_window(struct scif_endpt *ep, struct scif_window *window);
-void scif_unmap_window(struct scif_dev *remote_dev, struct scif_window *window);
-/* Map pages of self window to Aperture/PCI */
-int scif_map_window(struct scif_dev *remote_dev,
-                   struct scif_window *window);
-/* Unregister a self window */
-int scif_unregister_window(struct scif_window *window);
-/* Destroy remote registration window */
-void
-scif_destroy_remote_window(struct scif_window *window);
-/* remove valid remote memory mappings from process address space */
-void scif_zap_mmaps(int node);
-/* Query if any applications have remote memory mappings */
-bool scif_rma_do_apps_have_mmaps(int node);
-/* Cleanup remote registration lists for zombie endpoints */
-void scif_cleanup_rma_for_zombies(int node);
-/* Reserve a DMA channel for a particular endpoint */
-int scif_reserve_dma_chan(struct scif_endpt *ep);
-/* Setup a DMA mark for an endpoint */
-int _scif_fence_mark(scif_epd_t epd, int *mark);
-int scif_prog_signal(scif_epd_t epd, off_t offset, u64 val,
-                    enum scif_window_type type);
-void scif_alloc_req(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_alloc_gnt_rej(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_free_virt(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_recv_reg(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_recv_unreg(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_recv_reg_ack(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_recv_reg_nack(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_recv_unreg_ack(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_recv_unreg_nack(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_recv_munmap(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_recv_mark(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_recv_mark_resp(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_recv_wait(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_recv_wait_resp(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_recv_sig_local(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_recv_sig_remote(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_recv_sig_resp(struct scif_dev *scifdev, struct scifmsg *msg);
-void scif_mmu_notif_handler(struct work_struct *work);
-void scif_rma_handle_remote_fences(void);
-void scif_rma_destroy_windows(void);
-void scif_rma_destroy_tcw_invalid(void);
-int scif_drain_dma_intr(struct scif_hw_dev *sdev, struct dma_chan *chan);
-
-struct scif_window_iter {
-       s64 offset;
-       int index;
-};
-
-static inline void
-scif_init_window_iter(struct scif_window *window, struct scif_window_iter *iter)
-{
-       iter->offset = window->offset;
-       iter->index = 0;
-}
-
-dma_addr_t scif_off_to_dma_addr(struct scif_window *window, s64 off,
-                               size_t *nr_bytes,
-                               struct scif_window_iter *iter);
-static inline
-dma_addr_t __scif_off_to_dma_addr(struct scif_window *window, s64 off)
-{
-       return scif_off_to_dma_addr(window, off, NULL, NULL);
-}
-
-static inline bool scif_unaligned(off_t src_offset, off_t dst_offset)
-{
-       src_offset = src_offset & (L1_CACHE_BYTES - 1);
-       dst_offset = dst_offset & (L1_CACHE_BYTES - 1);
-       return !(src_offset == dst_offset);
-}
-
-/*
- * scif_zalloc:
- * @size: Size of the allocation request.
- *
- * Helper API which attempts to allocate zeroed pages via
- * __get_free_pages(..) first and then falls back on
- * vzalloc(..) if that fails.
- */
-static inline void *scif_zalloc(size_t size)
-{
-       void *ret = NULL;
-       size_t align = ALIGN(size, PAGE_SIZE);
-
-       if (align && get_order(align) < MAX_ORDER)
-               ret = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
-                                              get_order(align));
-       return ret ? ret : vzalloc(align);
-}
-
-/*
- * scif_free:
- * @addr: Address to be freed.
- * @size: Size of the allocation.
- * Helper API which frees memory allocated via scif_zalloc().
- */
-static inline void scif_free(void *addr, size_t size)
-{
-       size_t align = ALIGN(size, PAGE_SIZE);
-
-       if (is_vmalloc_addr(addr))
-               vfree(addr);
-       else
-               free_pages((unsigned long)addr, get_order(align));
-}
-
-static inline void scif_get_window(struct scif_window *window, int nr_pages)
-{
-       window->ref_count += nr_pages;
-}
-
-static inline void scif_put_window(struct scif_window *window, int nr_pages)
-{
-       window->ref_count -= nr_pages;
-}
-
-static inline void scif_set_window_ref(struct scif_window *window, int nr_pages)
-{
-       window->ref_count = nr_pages;
-}
-
-static inline void
-scif_queue_for_cleanup(struct scif_window *window, struct list_head *list)
-{
-       spin_lock(&scif_info.rmalock);
-       list_add_tail(&window->list, list);
-       spin_unlock(&scif_info.rmalock);
-       schedule_work(&scif_info.misc_work);
-}
-
-static inline void __scif_rma_destroy_tcw_helper(struct scif_window *window)
-{
-       list_del_init(&window->list);
-       scif_queue_for_cleanup(window, &scif_info.rma_tc);
-}
-
-static inline bool scif_is_iommu_enabled(void)
-{
-#ifdef CONFIG_INTEL_IOMMU
-       return intel_iommu_enabled;
-#else
-       return false;
-#endif
-}
-#endif /* SCIF_RMA_H */
diff --git a/drivers/misc/mic/scif/scif_rma_list.c b/drivers/misc/mic/scif/scif_rma_list.c
deleted file mode 100644 (file)
index ef923ba..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#include "scif_main.h"
-#include <linux/mmu_notifier.h>
-#include <linux/highmem.h>
-
-/*
- * scif_insert_tcw:
- *
- * Insert a temp window to the temp registration list sorted by va_for_temp.
- * RMA lock must be held.
- */
-void scif_insert_tcw(struct scif_window *window, struct list_head *head)
-{
-       struct scif_window *curr = NULL;
-       struct scif_window *prev = list_entry(head, struct scif_window, list);
-       struct list_head *item;
-
-       INIT_LIST_HEAD(&window->list);
-       /* Compare with tail and if the entry is new tail add it to the end */
-       if (!list_empty(head)) {
-               curr = list_entry(head->prev, struct scif_window, list);
-               if (curr->va_for_temp < window->va_for_temp) {
-                       list_add_tail(&window->list, head);
-                       return;
-               }
-       }
-       list_for_each(item, head) {
-               curr = list_entry(item, struct scif_window, list);
-               if (curr->va_for_temp > window->va_for_temp)
-                       break;
-               prev = curr;
-       }
-       list_add(&window->list, &prev->list);
-}
-
-/*
- * scif_insert_window:
- *
- * Insert a window to the self registration list sorted by offset.
- * RMA lock must be held.
- */
-void scif_insert_window(struct scif_window *window, struct list_head *head)
-{
-       struct scif_window *curr = NULL, *prev = NULL;
-       struct list_head *item;
-
-       INIT_LIST_HEAD(&window->list);
-       list_for_each(item, head) {
-               curr = list_entry(item, struct scif_window, list);
-               if (curr->offset > window->offset)
-                       break;
-               prev = curr;
-       }
-       if (!prev)
-               list_add(&window->list, head);
-       else
-               list_add(&window->list, &prev->list);
-       scif_set_window_ref(window, window->nr_pages);
-}
-
-/*
- * scif_query_tcw:
- *
- * Query the temp cached registration list of ep for an overlapping window
- * in case of permission mismatch, destroy the previous window. if permissions
- * match and overlap is partial, destroy the window but return the new range
- * RMA lock must be held.
- */
-int scif_query_tcw(struct scif_endpt *ep, struct scif_rma_req *req)
-{
-       struct list_head *item, *temp, *head = req->head;
-       struct scif_window *window;
-       u64 start_va_window, start_va_req = req->va_for_temp;
-       u64 end_va_window, end_va_req = start_va_req + req->nr_bytes;
-
-       if (!req->nr_bytes)
-               return -EINVAL;
-       /*
-        * Avoid traversing the entire list to find out that there
-        * is no entry that matches
-        */
-       if (!list_empty(head)) {
-               window = list_last_entry(head, struct scif_window, list);
-               end_va_window = window->va_for_temp +
-                       (window->nr_pages << PAGE_SHIFT);
-               if (start_va_req > end_va_window)
-                       return -ENXIO;
-       }
-       list_for_each_safe(item, temp, head) {
-               window = list_entry(item, struct scif_window, list);
-               start_va_window = window->va_for_temp;
-               end_va_window = window->va_for_temp +
-                       (window->nr_pages << PAGE_SHIFT);
-               if (start_va_req < start_va_window &&
-                   end_va_req < start_va_window)
-                       break;
-               if (start_va_req >= end_va_window)
-                       continue;
-               if ((window->prot & req->prot) == req->prot) {
-                       if (start_va_req >= start_va_window &&
-                           end_va_req <= end_va_window) {
-                               *req->out_window = window;
-                               return 0;
-                       }
-                       /* expand window */
-                       if (start_va_req < start_va_window) {
-                               req->nr_bytes +=
-                                       start_va_window - start_va_req;
-                               req->va_for_temp = start_va_window;
-                       }
-                       if (end_va_req >= end_va_window)
-                               req->nr_bytes += end_va_window - end_va_req;
-               }
-               /* Destroy the old window to create a new one */
-               __scif_rma_destroy_tcw_helper(window);
-               break;
-       }
-       return -ENXIO;
-}
-
-/*
- * scif_query_window:
- *
- * Query the registration list and check if a valid contiguous
- * range of windows exist.
- * RMA lock must be held.
- */
-int scif_query_window(struct scif_rma_req *req)
-{
-       struct list_head *item;
-       struct scif_window *window;
-       s64 end_offset, offset = req->offset;
-       u64 tmp_min, nr_bytes_left = req->nr_bytes;
-
-       if (!req->nr_bytes)
-               return -EINVAL;
-
-       list_for_each(item, req->head) {
-               window = list_entry(item, struct scif_window, list);
-               end_offset = window->offset +
-                       (window->nr_pages << PAGE_SHIFT);
-               if (offset < window->offset)
-                       /* Offset not found! */
-                       return -ENXIO;
-               if (offset >= end_offset)
-                       continue;
-               /* Check read/write protections. */
-               if ((window->prot & req->prot) != req->prot)
-                       return -EPERM;
-               if (nr_bytes_left == req->nr_bytes)
-                       /* Store the first window */
-                       *req->out_window = window;
-               tmp_min = min((u64)end_offset - offset, nr_bytes_left);
-               nr_bytes_left -= tmp_min;
-               offset += tmp_min;
-               /*
-                * Range requested encompasses
-                * multiple windows contiguously.
-                */
-               if (!nr_bytes_left) {
-                       /* Done for partial window */
-                       if (req->type == SCIF_WINDOW_PARTIAL ||
-                           req->type == SCIF_WINDOW_SINGLE)
-                               return 0;
-                       /* Extra logic for full windows */
-                       if (offset == end_offset)
-                               /* Spanning multiple whole windows */
-                               return 0;
-                               /* Not spanning multiple whole windows */
-                       return -ENXIO;
-               }
-               if (req->type == SCIF_WINDOW_SINGLE)
-                       break;
-       }
-       dev_err(scif_info.mdev.this_device,
-               "%s %d ENXIO\n", __func__, __LINE__);
-       return -ENXIO;
-}
-
-/*
- * scif_rma_list_unregister:
- *
- * Traverse the self registration list starting from window:
- * 1) Call scif_unregister_window(..)
- * RMA lock must be held.
- */
-int scif_rma_list_unregister(struct scif_window *window,
-                            s64 offset, int nr_pages)
-{
-       struct scif_endpt *ep = (struct scif_endpt *)window->ep;
-       struct list_head *head = &ep->rma_info.reg_list;
-       s64 end_offset;
-       int err = 0;
-       int loop_nr_pages;
-       struct scif_window *_window;
-
-       list_for_each_entry_safe_from(window, _window, head, list) {
-               end_offset = window->offset + (window->nr_pages << PAGE_SHIFT);
-               loop_nr_pages = min((int)((end_offset - offset) >> PAGE_SHIFT),
-                                   nr_pages);
-               err = scif_unregister_window(window);
-               if (err)
-                       return err;
-               nr_pages -= loop_nr_pages;
-               offset += (loop_nr_pages << PAGE_SHIFT);
-               if (!nr_pages)
-                       break;
-       }
-       return 0;
-}
-
-/*
- * scif_unmap_all_window:
- *
- * Traverse all the windows in the self registration list and:
- * 1) Delete any DMA mappings created
- */
-void scif_unmap_all_windows(scif_epd_t epd)
-{
-       struct list_head *item, *tmp;
-       struct scif_window *window;
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       struct list_head *head = &ep->rma_info.reg_list;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-       list_for_each_safe(item, tmp, head) {
-               window = list_entry(item, struct scif_window, list);
-               scif_unmap_window(ep->remote_dev, window);
-       }
-       mutex_unlock(&ep->rma_info.rma_lock);
-}
-
-/*
- * scif_unregister_all_window:
- *
- * Traverse all the windows in the self registration list and:
- * 1) Call scif_unregister_window(..)
- * RMA lock must be held.
- */
-int scif_unregister_all_windows(scif_epd_t epd)
-{
-       struct list_head *item, *tmp;
-       struct scif_window *window;
-       struct scif_endpt *ep = (struct scif_endpt *)epd;
-       struct list_head *head = &ep->rma_info.reg_list;
-       int err = 0;
-
-       mutex_lock(&ep->rma_info.rma_lock);
-retry:
-       item = NULL;
-       tmp = NULL;
-       list_for_each_safe(item, tmp, head) {
-               window = list_entry(item, struct scif_window, list);
-               ep->rma_info.async_list_del = 0;
-               err = scif_unregister_window(window);
-               if (err)
-                       dev_err(scif_info.mdev.this_device,
-                               "%s %d err %d\n",
-                               __func__, __LINE__, err);
-               /*
-                * Need to restart list traversal if there has been
-                * an asynchronous list entry deletion.
-                */
-               if (READ_ONCE(ep->rma_info.async_list_del))
-                       goto retry;
-       }
-       mutex_unlock(&ep->rma_info.rma_lock);
-       if (!list_empty(&ep->rma_info.mmn_list)) {
-               spin_lock(&scif_info.rmalock);
-               list_add_tail(&ep->mmu_list, &scif_info.mmu_notif_cleanup);
-               spin_unlock(&scif_info.rmalock);
-               schedule_work(&scif_info.mmu_notif_work);
-       }
-       return err;
-}
diff --git a/drivers/misc/mic/scif/scif_rma_list.h b/drivers/misc/mic/scif/scif_rma_list.h
deleted file mode 100644 (file)
index 0f8e0ed..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2015 Intel Corporation.
- *
- * Intel SCIF driver.
- */
-#ifndef SCIF_RMA_LIST_H
-#define SCIF_RMA_LIST_H
-
-/*
- * struct scif_rma_req - Self Registration list RMA Request query
- *
- * @out_window - Returns the window if found
- * @offset: Starting offset
- * @nr_bytes: number of bytes
- * @prot: protection requested i.e. read or write or both
- * @type: Specify single, partial or multiple windows
- * @head: Head of list on which to search
- * @va_for_temp: VA for searching temporary cached windows
- */
-struct scif_rma_req {
-       struct scif_window **out_window;
-       union {
-               s64 offset;
-               unsigned long va_for_temp;
-       };
-       size_t nr_bytes;
-       int prot;
-       enum scif_window_type type;
-       struct list_head *head;
-};
-
-/* Insert */
-void scif_insert_window(struct scif_window *window, struct list_head *head);
-void scif_insert_tcw(struct scif_window *window,
-                    struct list_head *head);
-/* Query */
-int scif_query_window(struct scif_rma_req *request);
-int scif_query_tcw(struct scif_endpt *ep, struct scif_rma_req *request);
-/* Called from close to unregister all self windows */
-int scif_unregister_all_windows(scif_epd_t epd);
-void scif_unmap_all_windows(scif_epd_t epd);
-/* Traverse list and unregister */
-int scif_rma_list_unregister(struct scif_window *window, s64 offset,
-                            int nr_pages);
-#endif /* SCIF_RMA_LIST_H */
diff --git a/drivers/misc/mic/vop/Makefile b/drivers/misc/mic/vop/Makefile
deleted file mode 100644 (file)
index 51b9b00..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile - Intel MIC Linux driver.
-# Copyright(c) 2016, Intel Corporation.
-#
-obj-$(CONFIG_VOP) := vop.o
-
-vop-objs += vop_main.o
-vop-objs += vop_debugfs.o
-vop-objs += vop_vringh.o
diff --git a/drivers/misc/mic/vop/vop_debugfs.c b/drivers/misc/mic/vop/vop_debugfs.c
deleted file mode 100644 (file)
index 9d4f175..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2016 Intel Corporation.
- *
- * Intel Virtio Over PCIe (VOP) driver.
- */
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-#include "vop_main.h"
-
-static int vop_dp_show(struct seq_file *s, void *pos)
-{
-       struct mic_device_desc *d;
-       struct mic_device_ctrl *dc;
-       struct mic_vqconfig *vqconfig;
-       __u32 *features;
-       __u8 *config;
-       struct vop_info *vi = s->private;
-       struct vop_device *vpdev = vi->vpdev;
-       struct mic_bootparam *bootparam = vpdev->hw_ops->get_dp(vpdev);
-       int j, k;
-
-       seq_printf(s, "Bootparam: magic 0x%x\n",
-                  bootparam->magic);
-       seq_printf(s, "Bootparam: h2c_config_db %d\n",
-                  bootparam->h2c_config_db);
-       seq_printf(s, "Bootparam: node_id %d\n",
-                  bootparam->node_id);
-       seq_printf(s, "Bootparam: c2h_scif_db %d\n",
-                  bootparam->c2h_scif_db);
-       seq_printf(s, "Bootparam: h2c_scif_db %d\n",
-                  bootparam->h2c_scif_db);
-       seq_printf(s, "Bootparam: scif_host_dma_addr 0x%llx\n",
-                  bootparam->scif_host_dma_addr);
-       seq_printf(s, "Bootparam: scif_card_dma_addr 0x%llx\n",
-                  bootparam->scif_card_dma_addr);
-
-       for (j = sizeof(*bootparam);
-               j < MIC_DP_SIZE; j += mic_total_desc_size(d)) {
-               d = (void *)bootparam + j;
-               dc = (void *)d + mic_aligned_desc_size(d);
-
-               /* end of list */
-               if (d->type == 0)
-                       break;
-
-               if (d->type == -1)
-                       continue;
-
-               seq_printf(s, "Type %d ", d->type);
-               seq_printf(s, "Num VQ %d ", d->num_vq);
-               seq_printf(s, "Feature Len %d\n", d->feature_len);
-               seq_printf(s, "Config Len %d ", d->config_len);
-               seq_printf(s, "Shutdown Status %d\n", d->status);
-
-               for (k = 0; k < d->num_vq; k++) {
-                       vqconfig = mic_vq_config(d) + k;
-                       seq_printf(s, "vqconfig[%d]: ", k);
-                       seq_printf(s, "address 0x%llx ",
-                                  vqconfig->address);
-                       seq_printf(s, "num %d ", vqconfig->num);
-                       seq_printf(s, "used address 0x%llx\n",
-                                  vqconfig->used_address);
-               }
-
-               features = (__u32 *)mic_vq_features(d);
-               seq_printf(s, "Features: Host 0x%x ", features[0]);
-               seq_printf(s, "Guest 0x%x\n", features[1]);
-
-               config = mic_vq_configspace(d);
-               for (k = 0; k < d->config_len; k++)
-                       seq_printf(s, "config[%d]=%d\n", k, config[k]);
-
-               seq_puts(s, "Device control:\n");
-               seq_printf(s, "Config Change %d ", dc->config_change);
-               seq_printf(s, "Vdev reset %d\n", dc->vdev_reset);
-               seq_printf(s, "Guest Ack %d ", dc->guest_ack);
-               seq_printf(s, "Host ack %d\n", dc->host_ack);
-               seq_printf(s, "Used address updated %d ",
-                          dc->used_address_updated);
-               seq_printf(s, "Vdev 0x%llx\n", dc->vdev);
-               seq_printf(s, "c2h doorbell %d ", dc->c2h_vdev_db);
-               seq_printf(s, "h2c doorbell %d\n", dc->h2c_vdev_db);
-       }
-       schedule_work(&vi->hotplug_work);
-       return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(vop_dp);
-
-static int vop_vdev_info_show(struct seq_file *s, void *unused)
-{
-       struct vop_info *vi = s->private;
-       struct list_head *pos, *tmp;
-       struct vop_vdev *vdev;
-       int i, j;
-
-       mutex_lock(&vi->vop_mutex);
-       list_for_each_safe(pos, tmp, &vi->vdev_list) {
-               vdev = list_entry(pos, struct vop_vdev, list);
-               seq_printf(s, "VDEV type %d state %s in %ld out %ld in_dma %ld out_dma %ld\n",
-                          vdev->virtio_id,
-                          vop_vdevup(vdev) ? "UP" : "DOWN",
-                          vdev->in_bytes,
-                          vdev->out_bytes,
-                          vdev->in_bytes_dma,
-                          vdev->out_bytes_dma);
-               for (i = 0; i < MIC_MAX_VRINGS; i++) {
-                       struct vring_desc *desc;
-                       struct vring_avail *avail;
-                       struct vring_used *used;
-                       struct vop_vringh *vvr = &vdev->vvr[i];
-                       struct vringh *vrh = &vvr->vrh;
-                       int num = vrh->vring.num;
-
-                       if (!num)
-                               continue;
-                       desc = vrh->vring.desc;
-                       seq_printf(s, "vring i %d avail_idx %d",
-                                  i, vvr->vring.info->avail_idx & (num - 1));
-                       seq_printf(s, " vring i %d avail_idx %d\n",
-                                  i, vvr->vring.info->avail_idx);
-                       seq_printf(s, "vrh i %d weak_barriers %d",
-                                  i, vrh->weak_barriers);
-                       seq_printf(s, " last_avail_idx %d last_used_idx %d",
-                                  vrh->last_avail_idx, vrh->last_used_idx);
-                       seq_printf(s, " completed %d\n", vrh->completed);
-                       for (j = 0; j < num; j++) {
-                               seq_printf(s, "desc[%d] addr 0x%llx len %d",
-                                          j, desc->addr, desc->len);
-                               seq_printf(s, " flags 0x%x next %d\n",
-                                          desc->flags, desc->next);
-                               desc++;
-                       }
-                       avail = vrh->vring.avail;
-                       seq_printf(s, "avail flags 0x%x idx %d\n",
-                                  vringh16_to_cpu(vrh, avail->flags),
-                                  vringh16_to_cpu(vrh,
-                                                  avail->idx) & (num - 1));
-                       seq_printf(s, "avail flags 0x%x idx %d\n",
-                                  vringh16_to_cpu(vrh, avail->flags),
-                                  vringh16_to_cpu(vrh, avail->idx));
-                       for (j = 0; j < num; j++)
-                               seq_printf(s, "avail ring[%d] %d\n",
-                                          j, avail->ring[j]);
-                       used = vrh->vring.used;
-                       seq_printf(s, "used flags 0x%x idx %d\n",
-                                  vringh16_to_cpu(vrh, used->flags),
-                                  vringh16_to_cpu(vrh, used->idx) & (num - 1));
-                       seq_printf(s, "used flags 0x%x idx %d\n",
-                                  vringh16_to_cpu(vrh, used->flags),
-                                  vringh16_to_cpu(vrh, used->idx));
-                       for (j = 0; j < num; j++)
-                               seq_printf(s, "used ring[%d] id %d len %d\n",
-                                          j, vringh32_to_cpu(vrh,
-                                                             used->ring[j].id),
-                                          vringh32_to_cpu(vrh,
-                                                          used->ring[j].len));
-               }
-       }
-       mutex_unlock(&vi->vop_mutex);
-
-       return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(vop_vdev_info);
-
-void vop_init_debugfs(struct vop_info *vi)
-{
-       char name[16];
-
-       snprintf(name, sizeof(name), "%s%d", KBUILD_MODNAME, vi->vpdev->dnode);
-       vi->dbg = debugfs_create_dir(name, NULL);
-       debugfs_create_file("dp", 0444, vi->dbg, vi, &vop_dp_fops);
-       debugfs_create_file("vdev_info", 0444, vi->dbg, vi, &vop_vdev_info_fops);
-}
-
-void vop_exit_debugfs(struct vop_info *vi)
-{
-       debugfs_remove_recursive(vi->dbg);
-}
diff --git a/drivers/misc/mic/vop/vop_main.c b/drivers/misc/mic/vop/vop_main.c
deleted file mode 100644 (file)
index 714b94f..0000000
+++ /dev/null
@@ -1,784 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2016 Intel Corporation.
- *
- * Adapted from:
- *
- * virtio for kvm on s390
- *
- * Copyright IBM Corp. 2008
- *
- *    Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
- *
- * Intel Virtio Over PCIe (VOP) driver.
- */
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/dma-mapping.h>
-#include <linux/io-64-nonatomic-lo-hi.h>
-
-#include "vop_main.h"
-
-#define VOP_MAX_VRINGS 4
-
-/*
- * _vop_vdev - Allocated per virtio device instance injected by the peer.
- *
- * @vdev: Virtio device
- * @desc: Virtio device page descriptor
- * @dc: Virtio device control
- * @vpdev: VOP device which is the parent for this virtio device
- * @vr: Buffer for accessing the VRING
- * @used_virt: Virtual address of used ring
- * @used: DMA address of used ring
- * @used_size: Size of the used buffer
- * @reset_done: Track whether VOP reset is complete
- * @virtio_cookie: Cookie returned upon requesting a interrupt
- * @c2h_vdev_db: The doorbell used by the guest to interrupt the host
- * @h2c_vdev_db: The doorbell used by the host to interrupt the guest
- * @dnode: The destination node
- */
-struct _vop_vdev {
-       struct virtio_device vdev;
-       struct mic_device_desc __iomem *desc;
-       struct mic_device_ctrl __iomem *dc;
-       struct vop_device *vpdev;
-       void __iomem *vr[VOP_MAX_VRINGS];
-       void *used_virt[VOP_MAX_VRINGS];
-       dma_addr_t used[VOP_MAX_VRINGS];
-       int used_size[VOP_MAX_VRINGS];
-       struct completion reset_done;
-       struct mic_irq *virtio_cookie;
-       int c2h_vdev_db;
-       int h2c_vdev_db;
-       int dnode;
-};
-
-#define to_vopvdev(vd) container_of(vd, struct _vop_vdev, vdev)
-
-#define _vop_aligned_desc_size(d) __mic_align(_vop_desc_size(d), 8)
-
-/* Helper API to obtain the parent of the virtio device */
-static inline struct device *_vop_dev(struct _vop_vdev *vdev)
-{
-       return vdev->vdev.dev.parent;
-}
-
-static inline unsigned _vop_desc_size(struct mic_device_desc __iomem *desc)
-{
-       return sizeof(*desc)
-               + ioread8(&desc->num_vq) * sizeof(struct mic_vqconfig)
-               + ioread8(&desc->feature_len) * 2
-               + ioread8(&desc->config_len);
-}
-
-static inline struct mic_vqconfig __iomem *
-_vop_vq_config(struct mic_device_desc __iomem *desc)
-{
-       return (struct mic_vqconfig __iomem *)(desc + 1);
-}
-
-static inline u8 __iomem *
-_vop_vq_features(struct mic_device_desc __iomem *desc)
-{
-       return (u8 __iomem *)(_vop_vq_config(desc) + ioread8(&desc->num_vq));
-}
-
-static inline u8 __iomem *
-_vop_vq_configspace(struct mic_device_desc __iomem *desc)
-{
-       return _vop_vq_features(desc) + ioread8(&desc->feature_len) * 2;
-}
-
-static inline unsigned
-_vop_total_desc_size(struct mic_device_desc __iomem *desc)
-{
-       return _vop_aligned_desc_size(desc) + sizeof(struct mic_device_ctrl);
-}
-
-/* This gets the device's feature bits. */
-static u64 vop_get_features(struct virtio_device *vdev)
-{
-       unsigned int i, bits;
-       u64 features = 0;
-       struct mic_device_desc __iomem *desc = to_vopvdev(vdev)->desc;
-       u8 __iomem *in_features = _vop_vq_features(desc);
-       int feature_len = ioread8(&desc->feature_len);
-
-       bits = min_t(unsigned, feature_len, sizeof(vdev->features)) * 8;
-       for (i = 0; i < bits; i++)
-               if (ioread8(&in_features[i / 8]) & (BIT(i % 8)))
-                       features |= BIT_ULL(i);
-
-       return features;
-}
-
-static void vop_transport_features(struct virtio_device *vdev)
-{
-       /*
-        * Packed ring isn't enabled on virtio_vop for now,
-        * because virtio_vop uses vring_new_virtqueue() which
-        * creates virtio rings on preallocated memory.
-        */
-       __virtio_clear_bit(vdev, VIRTIO_F_RING_PACKED);
-       __virtio_set_bit(vdev, VIRTIO_F_ACCESS_PLATFORM);
-}
-
-static int vop_finalize_features(struct virtio_device *vdev)
-{
-       unsigned int i, bits;
-       struct mic_device_desc __iomem *desc = to_vopvdev(vdev)->desc;
-       u8 feature_len = ioread8(&desc->feature_len);
-       /* Second half of bitmap is features we accept. */
-       u8 __iomem *out_features =
-               _vop_vq_features(desc) + feature_len;
-
-       /* Give virtio_ring a chance to accept features. */
-       vring_transport_features(vdev);
-
-       /* Give virtio_vop a chance to accept features. */
-       vop_transport_features(vdev);
-
-       memset_io(out_features, 0, feature_len);
-       bits = min_t(unsigned, feature_len,
-                    sizeof(vdev->features)) * 8;
-       for (i = 0; i < bits; i++) {
-               if (__virtio_test_bit(vdev, i))
-                       iowrite8(ioread8(&out_features[i / 8]) | (1 << (i % 8)),
-                                &out_features[i / 8]);
-       }
-       return 0;
-}
-
-/*
- * Reading and writing elements in config space
- */
-static void vop_get(struct virtio_device *vdev, unsigned int offset,
-                   void *buf, unsigned len)
-{
-       struct mic_device_desc __iomem *desc = to_vopvdev(vdev)->desc;
-
-       if (offset + len > ioread8(&desc->config_len))
-               return;
-       memcpy_fromio(buf, _vop_vq_configspace(desc) + offset, len);
-}
-
-static void vop_set(struct virtio_device *vdev, unsigned int offset,
-                   const void *buf, unsigned len)
-{
-       struct mic_device_desc __iomem *desc = to_vopvdev(vdev)->desc;
-
-       if (offset + len > ioread8(&desc->config_len))
-               return;
-       memcpy_toio(_vop_vq_configspace(desc) + offset, buf, len);
-}
-
-/*
- * The operations to get and set the status word just access the status
- * field of the device descriptor. set_status also interrupts the host
- * to tell about status changes.
- */
-static u8 vop_get_status(struct virtio_device *vdev)
-{
-       return ioread8(&to_vopvdev(vdev)->desc->status);
-}
-
-static void vop_set_status(struct virtio_device *dev, u8 status)
-{
-       struct _vop_vdev *vdev = to_vopvdev(dev);
-       struct vop_device *vpdev = vdev->vpdev;
-
-       if (!status)
-               return;
-       iowrite8(status, &vdev->desc->status);
-       vpdev->hw_ops->send_intr(vpdev, vdev->c2h_vdev_db);
-}
-
-/* Inform host on a virtio device reset and wait for ack from host */
-static void vop_reset_inform_host(struct virtio_device *dev)
-{
-       struct _vop_vdev *vdev = to_vopvdev(dev);
-       struct mic_device_ctrl __iomem *dc = vdev->dc;
-       struct vop_device *vpdev = vdev->vpdev;
-       int retry;
-
-       iowrite8(0, &dc->host_ack);
-       iowrite8(1, &dc->vdev_reset);
-       vpdev->hw_ops->send_intr(vpdev, vdev->c2h_vdev_db);
-
-       /* Wait till host completes all card accesses and acks the reset */
-       for (retry = 100; retry--;) {
-               if (ioread8(&dc->host_ack))
-                       break;
-               msleep(100);
-       }
-
-       dev_dbg(_vop_dev(vdev), "%s: retry: %d\n", __func__, retry);
-
-       /* Reset status to 0 in case we timed out */
-       iowrite8(0, &vdev->desc->status);
-}
-
-static void vop_reset(struct virtio_device *dev)
-{
-       struct _vop_vdev *vdev = to_vopvdev(dev);
-
-       dev_dbg(_vop_dev(vdev), "%s: virtio id %d\n",
-               __func__, dev->id.device);
-
-       vop_reset_inform_host(dev);
-       complete_all(&vdev->reset_done);
-}
-
-/*
- * The virtio_ring code calls this API when it wants to notify the Host.
- */
-static bool vop_notify(struct virtqueue *vq)
-{
-       struct _vop_vdev *vdev = vq->priv;
-       struct vop_device *vpdev = vdev->vpdev;
-
-       vpdev->hw_ops->send_intr(vpdev, vdev->c2h_vdev_db);
-       return true;
-}
-
-static void vop_del_vq(struct virtqueue *vq, int n)
-{
-       struct _vop_vdev *vdev = to_vopvdev(vq->vdev);
-       struct vop_device *vpdev = vdev->vpdev;
-
-       dma_unmap_single(&vpdev->dev, vdev->used[n],
-                        vdev->used_size[n], DMA_BIDIRECTIONAL);
-       free_pages((unsigned long)vdev->used_virt[n],
-                  get_order(vdev->used_size[n]));
-       vring_del_virtqueue(vq);
-       vpdev->hw_ops->unmap(vpdev, vdev->vr[n]);
-       vdev->vr[n] = NULL;
-}
-
-static void vop_del_vqs(struct virtio_device *dev)
-{
-       struct _vop_vdev *vdev = to_vopvdev(dev);
-       struct virtqueue *vq, *n;
-       int idx = 0;
-
-       dev_dbg(_vop_dev(vdev), "%s\n", __func__);
-
-       list_for_each_entry_safe(vq, n, &dev->vqs, list)
-               vop_del_vq(vq, idx++);
-}
-
-static struct virtqueue *vop_new_virtqueue(unsigned int index,
-                                     unsigned int num,
-                                     struct virtio_device *vdev,
-                                     bool context,
-                                     void *pages,
-                                     bool (*notify)(struct virtqueue *vq),
-                                     void (*callback)(struct virtqueue *vq),
-                                     const char *name,
-                                     void *used)
-{
-       bool weak_barriers = false;
-       struct vring vring;
-
-       vring_init(&vring, num, pages, MIC_VIRTIO_RING_ALIGN);
-       vring.used = used;
-
-       return __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
-                                    notify, callback, name);
-}
-
-/*
- * This routine will assign vring's allocated in host/io memory. Code in
- * virtio_ring.c however continues to access this io memory as if it were local
- * memory without io accessors.
- */
-static struct virtqueue *vop_find_vq(struct virtio_device *dev,
-                                    unsigned index,
-                                    void (*callback)(struct virtqueue *vq),
-                                    const char *name, bool ctx)
-{
-       struct _vop_vdev *vdev = to_vopvdev(dev);
-       struct vop_device *vpdev = vdev->vpdev;
-       struct mic_vqconfig __iomem *vqconfig;
-       struct mic_vqconfig config;
-       struct virtqueue *vq;
-       void __iomem *va;
-       struct _mic_vring_info __iomem *info;
-       void *used;
-       int vr_size, _vr_size, err, magic;
-       u8 type = ioread8(&vdev->desc->type);
-
-       if (index >= ioread8(&vdev->desc->num_vq))
-               return ERR_PTR(-ENOENT);
-
-       if (!name)
-               return ERR_PTR(-ENOENT);
-
-       /* First assign the vring's allocated in host memory */
-       vqconfig = _vop_vq_config(vdev->desc) + index;
-       memcpy_fromio(&config, vqconfig, sizeof(config));
-       _vr_size = round_up(vring_size(le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN), 4);
-       vr_size = PAGE_ALIGN(_vr_size + sizeof(struct _mic_vring_info));
-       va = vpdev->hw_ops->remap(vpdev, le64_to_cpu(config.address), vr_size);
-       if (!va)
-               return ERR_PTR(-ENOMEM);
-       vdev->vr[index] = va;
-       memset_io(va, 0x0, _vr_size);
-
-       info = va + _vr_size;
-       magic = ioread32(&info->magic);
-
-       if (WARN(magic != MIC_MAGIC + type + index, "magic mismatch")) {
-               err = -EIO;
-               goto unmap;
-       }
-
-       vdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 +
-                                            sizeof(struct vring_used_elem) *
-                                            le16_to_cpu(config.num));
-       used = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
-                                       get_order(vdev->used_size[index]));
-       vdev->used_virt[index] = used;
-       if (!used) {
-               err = -ENOMEM;
-               dev_err(_vop_dev(vdev), "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               goto unmap;
-       }
-
-       vq = vop_new_virtqueue(index, le16_to_cpu(config.num), dev, ctx,
-                              (void __force *)va, vop_notify, callback,
-                              name, used);
-       if (!vq) {
-               err = -ENOMEM;
-               goto free_used;
-       }
-
-       vdev->used[index] = dma_map_single(&vpdev->dev, used,
-                                           vdev->used_size[index],
-                                           DMA_BIDIRECTIONAL);
-       if (dma_mapping_error(&vpdev->dev, vdev->used[index])) {
-               err = -ENOMEM;
-               dev_err(_vop_dev(vdev), "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               goto del_vq;
-       }
-       writeq(vdev->used[index], &vqconfig->used_address);
-
-       vq->priv = vdev;
-       return vq;
-del_vq:
-       vring_del_virtqueue(vq);
-free_used:
-       free_pages((unsigned long)used,
-                  get_order(vdev->used_size[index]));
-unmap:
-       vpdev->hw_ops->unmap(vpdev, vdev->vr[index]);
-       return ERR_PTR(err);
-}
-
-static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs,
-                       struct virtqueue *vqs[],
-                       vq_callback_t *callbacks[],
-                       const char * const names[], const bool *ctx,
-                       struct irq_affinity *desc)
-{
-       struct _vop_vdev *vdev = to_vopvdev(dev);
-       struct vop_device *vpdev = vdev->vpdev;
-       struct mic_device_ctrl __iomem *dc = vdev->dc;
-       int i, err, retry, queue_idx = 0;
-
-       /* We must have this many virtqueues. */
-       if (nvqs > ioread8(&vdev->desc->num_vq))
-               return -ENOENT;
-
-       for (i = 0; i < nvqs; ++i) {
-               if (!names[i]) {
-                       vqs[i] = NULL;
-                       continue;
-               }
-
-               dev_dbg(_vop_dev(vdev), "%s: %d: %s\n",
-                       __func__, i, names[i]);
-               vqs[i] = vop_find_vq(dev, queue_idx++, callbacks[i], names[i],
-                                    ctx ? ctx[i] : false);
-               if (IS_ERR(vqs[i])) {
-                       err = PTR_ERR(vqs[i]);
-                       goto error;
-               }
-       }
-
-       iowrite8(1, &dc->used_address_updated);
-       /*
-        * Send an interrupt to the host to inform it that used
-        * rings have been re-assigned.
-        */
-       vpdev->hw_ops->send_intr(vpdev, vdev->c2h_vdev_db);
-       for (retry = 100; --retry;) {
-               if (!ioread8(&dc->used_address_updated))
-                       break;
-               msleep(100);
-       }
-
-       dev_dbg(_vop_dev(vdev), "%s: retry: %d\n", __func__, retry);
-       if (!retry) {
-               err = -ENODEV;
-               goto error;
-       }
-
-       return 0;
-error:
-       vop_del_vqs(dev);
-       return err;
-}
-
-/*
- * The config ops structure as defined by virtio config
- */
-static const struct virtio_config_ops vop_vq_config_ops = {
-       .get_features = vop_get_features,
-       .finalize_features = vop_finalize_features,
-       .get = vop_get,
-       .set = vop_set,
-       .get_status = vop_get_status,
-       .set_status = vop_set_status,
-       .reset = vop_reset,
-       .find_vqs = vop_find_vqs,
-       .del_vqs = vop_del_vqs,
-};
-
-static irqreturn_t vop_virtio_intr_handler(int irq, void *data)
-{
-       struct _vop_vdev *vdev = data;
-       struct vop_device *vpdev = vdev->vpdev;
-       struct virtqueue *vq;
-
-       vpdev->hw_ops->ack_interrupt(vpdev, vdev->h2c_vdev_db);
-       list_for_each_entry(vq, &vdev->vdev.vqs, list)
-               vring_interrupt(0, vq);
-
-       return IRQ_HANDLED;
-}
-
-static void vop_virtio_release_dev(struct device *_d)
-{
-       struct virtio_device *vdev =
-                       container_of(_d, struct virtio_device, dev);
-       struct _vop_vdev *vop_vdev =
-                       container_of(vdev, struct _vop_vdev, vdev);
-
-       kfree(vop_vdev);
-}
-
-/*
- * adds a new device and register it with virtio
- * appropriate drivers are loaded by the device model
- */
-static int _vop_add_device(struct mic_device_desc __iomem *d,
-                          unsigned int offset, struct vop_device *vpdev,
-                          int dnode)
-{
-       struct _vop_vdev *vdev, *reg_dev = NULL;
-       int ret;
-       u8 type = ioread8(&d->type);
-
-       vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
-       if (!vdev)
-               return -ENOMEM;
-
-       vdev->vpdev = vpdev;
-       vdev->vdev.dev.parent = &vpdev->dev;
-       vdev->vdev.dev.release = vop_virtio_release_dev;
-       vdev->vdev.id.device = type;
-       vdev->vdev.config = &vop_vq_config_ops;
-       vdev->desc = d;
-       vdev->dc = (void __iomem *)d + _vop_aligned_desc_size(d);
-       vdev->dnode = dnode;
-       vdev->vdev.priv = (void *)(unsigned long)dnode;
-       init_completion(&vdev->reset_done);
-
-       vdev->h2c_vdev_db = vpdev->hw_ops->next_db(vpdev);
-       vdev->virtio_cookie = vpdev->hw_ops->request_irq(vpdev,
-                       vop_virtio_intr_handler, "virtio intr",
-                       vdev, vdev->h2c_vdev_db);
-       if (IS_ERR(vdev->virtio_cookie)) {
-               ret = PTR_ERR(vdev->virtio_cookie);
-               goto kfree;
-       }
-       iowrite8((u8)vdev->h2c_vdev_db, &vdev->dc->h2c_vdev_db);
-       vdev->c2h_vdev_db = ioread8(&vdev->dc->c2h_vdev_db);
-
-       ret = register_virtio_device(&vdev->vdev);
-       reg_dev = vdev;
-       if (ret) {
-               dev_err(_vop_dev(vdev),
-                       "Failed to register vop device %u type %u\n",
-                       offset, type);
-               goto free_irq;
-       }
-       writeq((unsigned long)vdev, &vdev->dc->vdev);
-       dev_dbg(_vop_dev(vdev), "%s: registered vop device %u type %u vdev %p\n",
-               __func__, offset, type, vdev);
-
-       return 0;
-
-free_irq:
-       vpdev->hw_ops->free_irq(vpdev, vdev->virtio_cookie, vdev);
-kfree:
-       if (reg_dev)
-               put_device(&vdev->vdev.dev);
-       else
-               kfree(vdev);
-       return ret;
-}
-
-/*
- * match for a vop device with a specific desc pointer
- */
-static int vop_match_desc(struct device *dev, void *data)
-{
-       struct virtio_device *_dev = dev_to_virtio(dev);
-       struct _vop_vdev *vdev = to_vopvdev(_dev);
-
-       return vdev->desc == (void __iomem *)data;
-}
-
-static struct _vop_vdev *vop_dc_to_vdev(struct mic_device_ctrl __iomem *dc)
-{
-       return (struct _vop_vdev *)(unsigned long)readq(&dc->vdev);
-}
-
-static void _vop_handle_config_change(struct mic_device_desc __iomem *d,
-                                     unsigned int offset,
-                                     struct vop_device *vpdev)
-{
-       struct mic_device_ctrl __iomem *dc
-               = (void __iomem *)d + _vop_aligned_desc_size(d);
-       struct _vop_vdev *vdev = vop_dc_to_vdev(dc);
-
-       if (ioread8(&dc->config_change) != MIC_VIRTIO_PARAM_CONFIG_CHANGED)
-               return;
-
-       dev_dbg(&vpdev->dev, "%s %d\n", __func__, __LINE__);
-       virtio_config_changed(&vdev->vdev);
-       iowrite8(1, &dc->guest_ack);
-}
-
-/*
- * removes a virtio device if a hot remove event has been
- * requested by the host.
- */
-static int _vop_remove_device(struct mic_device_desc __iomem *d,
-                             unsigned int offset, struct vop_device *vpdev)
-{
-       struct mic_device_ctrl __iomem *dc
-               = (void __iomem *)d + _vop_aligned_desc_size(d);
-       struct _vop_vdev *vdev = vop_dc_to_vdev(dc);
-       u8 status;
-       int ret = -1;
-
-       if (ioread8(&dc->config_change) == MIC_VIRTIO_PARAM_DEV_REMOVE) {
-               struct device *dev = get_device(&vdev->vdev.dev);
-
-               dev_dbg(&vpdev->dev,
-                       "%s %d config_change %d type %d vdev %p\n",
-                       __func__, __LINE__,
-                       ioread8(&dc->config_change), ioread8(&d->type), vdev);
-               status = ioread8(&d->status);
-               reinit_completion(&vdev->reset_done);
-               unregister_virtio_device(&vdev->vdev);
-               vpdev->hw_ops->free_irq(vpdev, vdev->virtio_cookie, vdev);
-               iowrite8(-1, &dc->h2c_vdev_db);
-               if (status & VIRTIO_CONFIG_S_DRIVER_OK)
-                       wait_for_completion(&vdev->reset_done);
-               put_device(dev);
-               iowrite8(1, &dc->guest_ack);
-               dev_dbg(&vpdev->dev, "%s %d guest_ack %d\n",
-                       __func__, __LINE__, ioread8(&dc->guest_ack));
-               iowrite8(-1, &d->type);
-               ret = 0;
-       }
-       return ret;
-}
-
-#define REMOVE_DEVICES true
-
-static void _vop_scan_devices(void __iomem *dp, struct vop_device *vpdev,
-                             bool remove, int dnode)
-{
-       s8 type;
-       unsigned int i;
-       struct mic_device_desc __iomem *d;
-       struct mic_device_ctrl __iomem *dc;
-       struct device *dev;
-
-       for (i = sizeof(struct mic_bootparam);
-                       i < MIC_DP_SIZE; i += _vop_total_desc_size(d)) {
-               d = dp + i;
-               dc = (void __iomem *)d + _vop_aligned_desc_size(d);
-               /*
-                * This read barrier is paired with the corresponding write
-                * barrier on the host which is inserted before adding or
-                * removing a virtio device descriptor, by updating the type.
-                */
-               rmb();
-               type = ioread8(&d->type);
-
-               /* end of list */
-               if (type == 0)
-                       break;
-
-               if (type == -1)
-                       continue;
-
-               /* device already exists */
-               dev = device_find_child(&vpdev->dev, (void __force *)d,
-                                       vop_match_desc);
-               if (dev) {
-                       if (remove)
-                               iowrite8(MIC_VIRTIO_PARAM_DEV_REMOVE,
-                                        &dc->config_change);
-                       put_device(dev);
-                       _vop_handle_config_change(d, i, vpdev);
-                       _vop_remove_device(d, i, vpdev);
-                       if (remove) {
-                               iowrite8(0, &dc->config_change);
-                               iowrite8(0, &dc->guest_ack);
-                       }
-                       continue;
-               }
-
-               /* new device */
-               dev_dbg(&vpdev->dev, "%s %d Adding new virtio device %p\n",
-                       __func__, __LINE__, d);
-               if (!remove)
-                       _vop_add_device(d, i, vpdev, dnode);
-       }
-}
-
-static void vop_scan_devices(struct vop_info *vi,
-                            struct vop_device *vpdev, bool remove)
-{
-       void __iomem *dp = vpdev->hw_ops->get_remote_dp(vpdev);
-
-       if (!dp)
-               return;
-       mutex_lock(&vi->vop_mutex);
-       _vop_scan_devices(dp, vpdev, remove, vpdev->dnode);
-       mutex_unlock(&vi->vop_mutex);
-}
-
-/*
- * vop_hotplug_device tries to find changes in the device page.
- */
-static void vop_hotplug_devices(struct work_struct *work)
-{
-       struct vop_info *vi = container_of(work, struct vop_info,
-                                            hotplug_work);
-
-       vop_scan_devices(vi, vi->vpdev, !REMOVE_DEVICES);
-}
-
-/*
- * Interrupt handler for hot plug/config changes etc.
- */
-static irqreturn_t vop_extint_handler(int irq, void *data)
-{
-       struct vop_info *vi = data;
-       struct mic_bootparam __iomem *bp;
-       struct vop_device *vpdev = vi->vpdev;
-
-       bp = vpdev->hw_ops->get_remote_dp(vpdev);
-       dev_dbg(&vpdev->dev, "%s %d hotplug work\n",
-               __func__, __LINE__);
-       vpdev->hw_ops->ack_interrupt(vpdev, ioread8(&bp->h2c_config_db));
-       schedule_work(&vi->hotplug_work);
-       return IRQ_HANDLED;
-}
-
-static int vop_driver_probe(struct vop_device *vpdev)
-{
-       struct vop_info *vi;
-       int rc;
-
-       vi = kzalloc(sizeof(*vi), GFP_KERNEL);
-       if (!vi) {
-               rc = -ENOMEM;
-               goto exit;
-       }
-       dev_set_drvdata(&vpdev->dev, vi);
-       vi->vpdev = vpdev;
-
-       mutex_init(&vi->vop_mutex);
-       INIT_WORK(&vi->hotplug_work, vop_hotplug_devices);
-       if (vpdev->dnode) {
-               rc = vop_host_init(vi);
-               if (rc < 0)
-                       goto free;
-       } else {
-               struct mic_bootparam __iomem *bootparam;
-
-               vop_scan_devices(vi, vpdev, !REMOVE_DEVICES);
-
-               vi->h2c_config_db = vpdev->hw_ops->next_db(vpdev);
-               vi->cookie = vpdev->hw_ops->request_irq(vpdev,
-                                                       vop_extint_handler,
-                                                       "virtio_config_intr",
-                                                       vi, vi->h2c_config_db);
-               if (IS_ERR(vi->cookie)) {
-                       rc = PTR_ERR(vi->cookie);
-                       goto free;
-               }
-               bootparam = vpdev->hw_ops->get_remote_dp(vpdev);
-               iowrite8(vi->h2c_config_db, &bootparam->h2c_config_db);
-       }
-       vop_init_debugfs(vi);
-       return 0;
-free:
-       kfree(vi);
-exit:
-       return rc;
-}
-
-static void vop_driver_remove(struct vop_device *vpdev)
-{
-       struct vop_info *vi = dev_get_drvdata(&vpdev->dev);
-
-       if (vpdev->dnode) {
-               vop_host_uninit(vi);
-       } else {
-               struct mic_bootparam __iomem *bootparam =
-                       vpdev->hw_ops->get_remote_dp(vpdev);
-               if (bootparam)
-                       iowrite8(-1, &bootparam->h2c_config_db);
-               vpdev->hw_ops->free_irq(vpdev, vi->cookie, vi);
-               flush_work(&vi->hotplug_work);
-               vop_scan_devices(vi, vpdev, REMOVE_DEVICES);
-       }
-       vop_exit_debugfs(vi);
-       kfree(vi);
-}
-
-static const struct vop_device_id id_table[] = {
-       { VOP_DEV_TRNSP, VOP_DEV_ANY_ID },
-       { 0 },
-};
-
-static struct vop_driver vop_driver = {
-       .driver.name =  KBUILD_MODNAME,
-       .driver.owner = THIS_MODULE,
-       .id_table = id_table,
-       .probe = vop_driver_probe,
-       .remove = vop_driver_remove,
-};
-
-module_vop_driver(vop_driver);
-
-MODULE_DEVICE_TABLE(mbus, id_table);
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Intel(R) Virtio Over PCIe (VOP) driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/vop/vop_main.h b/drivers/misc/mic/vop/vop_main.h
deleted file mode 100644 (file)
index 2451d92..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2016 Intel Corporation.
- *
- * Intel Virtio Over PCIe (VOP) driver.
- */
-#ifndef _VOP_MAIN_H_
-#define _VOP_MAIN_H_
-
-#include <linux/vringh.h>
-#include <linux/virtio_config.h>
-#include <linux/virtio.h>
-#include <linux/miscdevice.h>
-
-#include <linux/mic_common.h>
-#include "../common/mic_dev.h"
-
-#include "../bus/vop_bus.h"
-
-/*
- * Note on endianness.
- * 1. Host can be both BE or LE
- * 2. Guest/card is LE. Host uses le_to_cpu to access desc/avail
- *    rings and ioreadXX/iowriteXX to access used ring.
- * 3. Device page exposed by host to guest contains LE values. Guest
- *    accesses these using ioreadXX/iowriteXX etc. This way in general we
- *    obey the virtio spec according to which guest works with native
- *    endianness and host is aware of guest endianness and does all
- *    required endianness conversion.
- * 4. Data provided from user space to guest (in ADD_DEVICE and
- *    CONFIG_CHANGE ioctl's) is not interpreted by the driver and should be
- *    in guest endianness.
- */
-
-/*
- * vop_info - Allocated per invocation of VOP probe
- *
- * @vpdev: VOP device
- * @hotplug_work: Handle virtio device creation, deletion and configuration
- * @cookie: Cookie received upon requesting a virtio configuration interrupt
- * @h2c_config_db: The doorbell used by the peer to indicate a config change
- * @vdev_list: List of "active" virtio devices injected in the peer node
- * @vop_mutex: Synchronize access to the device page as well as serialize
- *             creation/deletion of virtio devices on the peer node
- * @dp: Peer device page information
- * @dbg: Debugfs entry
- * @dma_ch: The DMA channel used by this transport for data transfers.
- * @name: Name for this transport used in misc device creation.
- * @miscdev: The misc device registered.
- */
-struct vop_info {
-       struct vop_device *vpdev;
-       struct work_struct hotplug_work;
-       struct mic_irq *cookie;
-       int h2c_config_db;
-       struct list_head vdev_list;
-       struct mutex vop_mutex;
-       void __iomem *dp;
-       struct dentry *dbg;
-       struct dma_chan *dma_ch;
-       char name[16];
-       struct miscdevice miscdev;
-};
-
-/**
- * struct vop_vringh - Virtio ring host information.
- *
- * @vring: The VOP vring used for setting up user space mappings.
- * @vrh: The host VRINGH used for accessing the card vrings.
- * @riov: The VRINGH read kernel IOV.
- * @wiov: The VRINGH write kernel IOV.
- * @head: The VRINGH head index address passed to vringh_getdesc_kern(..).
- * @vr_mutex: Mutex for synchronizing access to the VRING.
- * @buf: Temporary kernel buffer used to copy in/out data
- * from/to the card via DMA.
- * @buf_da: dma address of buf.
- * @vdev: Back pointer to VOP virtio device for vringh_notify(..).
- */
-struct vop_vringh {
-       struct mic_vring vring;
-       struct vringh vrh;
-       struct vringh_kiov riov;
-       struct vringh_kiov wiov;
-       u16 head;
-       struct mutex vr_mutex;
-       void *buf;
-       dma_addr_t buf_da;
-       struct vop_vdev *vdev;
-};
-
-/**
- * struct vop_vdev - Host information for a card Virtio device.
- *
- * @virtio_id - Virtio device id.
- * @waitq - Waitqueue to allow ring3 apps to poll.
- * @vpdev - pointer to VOP bus device.
- * @poll_wake - Used for waking up threads blocked in poll.
- * @out_bytes - Debug stats for number of bytes copied from host to card.
- * @in_bytes - Debug stats for number of bytes copied from card to host.
- * @out_bytes_dma - Debug stats for number of bytes copied from host to card
- * using DMA.
- * @in_bytes_dma - Debug stats for number of bytes copied from card to host
- * using DMA.
- * @tx_len_unaligned - Debug stats for number of bytes copied to the card where
- * the transfer length did not have the required DMA alignment.
- * @tx_dst_unaligned - Debug stats for number of bytes copied where the
- * destination address on the card did not have the required DMA alignment.
- * @vvr - Store per VRING data structures.
- * @virtio_bh_work - Work struct used to schedule virtio bottom half handling.
- * @dd - Virtio device descriptor.
- * @dc - Virtio device control fields.
- * @list - List of Virtio devices.
- * @virtio_db - The doorbell used by the card to interrupt the host.
- * @virtio_cookie - The cookie returned while requesting interrupts.
- * @vi: Transport information.
- * @vdev_mutex: Mutex synchronizing virtio device injection,
- *              removal and data transfers.
- * @destroy: Track if a virtio device is being destroyed.
- * @deleted: The virtio device has been deleted.
- */
-struct vop_vdev {
-       int virtio_id;
-       wait_queue_head_t waitq;
-       struct vop_device *vpdev;
-       int poll_wake;
-       unsigned long out_bytes;
-       unsigned long in_bytes;
-       unsigned long out_bytes_dma;
-       unsigned long in_bytes_dma;
-       unsigned long tx_len_unaligned;
-       unsigned long tx_dst_unaligned;
-       unsigned long rx_dst_unaligned;
-       struct vop_vringh vvr[MIC_MAX_VRINGS];
-       struct work_struct virtio_bh_work;
-       struct mic_device_desc *dd;
-       struct mic_device_ctrl *dc;
-       struct list_head list;
-       int virtio_db;
-       struct mic_irq *virtio_cookie;
-       struct vop_info *vi;
-       struct mutex vdev_mutex;
-       struct completion destroy;
-       bool deleted;
-};
-
-/* Helper API to check if a virtio device is running */
-static inline bool vop_vdevup(struct vop_vdev *vdev)
-{
-       return !!vdev->dd->status;
-}
-
-void vop_init_debugfs(struct vop_info *vi);
-void vop_exit_debugfs(struct vop_info *vi);
-int vop_host_init(struct vop_info *vi);
-void vop_host_uninit(struct vop_info *vi);
-#endif
diff --git a/drivers/misc/mic/vop/vop_vringh.c b/drivers/misc/mic/vop/vop_vringh.c
deleted file mode 100644 (file)
index 7014ffe..0000000
+++ /dev/null
@@ -1,1166 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2016 Intel Corporation.
- *
- * Intel Virtio Over PCIe (VOP) driver.
- */
-#include <linux/sched.h>
-#include <linux/poll.h>
-#include <linux/dma-mapping.h>
-
-#include <linux/mic_common.h>
-#include "../common/mic_dev.h"
-
-#include <linux/mic_ioctl.h>
-#include "vop_main.h"
-
-/* Helper API to obtain the VOP PCIe device */
-static inline struct device *vop_dev(struct vop_vdev *vdev)
-{
-       return vdev->vpdev->dev.parent;
-}
-
-/* Helper API to check if a virtio device is initialized */
-static inline int vop_vdev_inited(struct vop_vdev *vdev)
-{
-       if (!vdev)
-               return -EINVAL;
-       /* Device has not been created yet */
-       if (!vdev->dd || !vdev->dd->type) {
-               dev_err(vop_dev(vdev), "%s %d err %d\n",
-                       __func__, __LINE__, -EINVAL);
-               return -EINVAL;
-       }
-       /* Device has been removed/deleted */
-       if (vdev->dd->type == -1) {
-               dev_dbg(vop_dev(vdev), "%s %d err %d\n",
-                       __func__, __LINE__, -ENODEV);
-               return -ENODEV;
-       }
-       return 0;
-}
-
-static void _vop_notify(struct vringh *vrh)
-{
-       struct vop_vringh *vvrh = container_of(vrh, struct vop_vringh, vrh);
-       struct vop_vdev *vdev = vvrh->vdev;
-       struct vop_device *vpdev = vdev->vpdev;
-       s8 db = vdev->dc->h2c_vdev_db;
-
-       if (db != -1)
-               vpdev->hw_ops->send_intr(vpdev, db);
-}
-
-static void vop_virtio_init_post(struct vop_vdev *vdev)
-{
-       struct mic_vqconfig *vqconfig = mic_vq_config(vdev->dd);
-       struct vop_device *vpdev = vdev->vpdev;
-       int i, used_size;
-
-       for (i = 0; i < vdev->dd->num_vq; i++) {
-               used_size = PAGE_ALIGN(sizeof(u16) * 3 +
-                               sizeof(struct vring_used_elem) *
-                               le16_to_cpu(vqconfig->num));
-               if (!le64_to_cpu(vqconfig[i].used_address)) {
-                       dev_warn(vop_dev(vdev), "used_address zero??\n");
-                       continue;
-               }
-               vdev->vvr[i].vrh.vring.used =
-                       (void __force *)vpdev->hw_ops->remap(
-                       vpdev,
-                       le64_to_cpu(vqconfig[i].used_address),
-                       used_size);
-       }
-
-       vdev->dc->used_address_updated = 0;
-
-       dev_info(vop_dev(vdev), "%s: device type %d LINKUP\n",
-                __func__, vdev->virtio_id);
-}
-
-static inline void vop_virtio_device_reset(struct vop_vdev *vdev)
-{
-       int i;
-
-       dev_dbg(vop_dev(vdev), "%s: status %d device type %d RESET\n",
-               __func__, vdev->dd->status, vdev->virtio_id);
-
-       for (i = 0; i < vdev->dd->num_vq; i++)
-               /*
-                * Avoid lockdep false positive. The + 1 is for the vop
-                * mutex which is held in the reset devices code path.
-                */
-               mutex_lock_nested(&vdev->vvr[i].vr_mutex, i + 1);
-
-       /* 0 status means "reset" */
-       vdev->dd->status = 0;
-       vdev->dc->vdev_reset = 0;
-       vdev->dc->host_ack = 1;
-
-       for (i = 0; i < vdev->dd->num_vq; i++) {
-               struct vringh *vrh = &vdev->vvr[i].vrh;
-
-               vdev->vvr[i].vring.info->avail_idx = 0;
-               vrh->completed = 0;
-               vrh->last_avail_idx = 0;
-               vrh->last_used_idx = 0;
-       }
-
-       for (i = 0; i < vdev->dd->num_vq; i++)
-               mutex_unlock(&vdev->vvr[i].vr_mutex);
-}
-
-static void vop_virtio_reset_devices(struct vop_info *vi)
-{
-       struct list_head *pos, *tmp;
-       struct vop_vdev *vdev;
-
-       list_for_each_safe(pos, tmp, &vi->vdev_list) {
-               vdev = list_entry(pos, struct vop_vdev, list);
-               vop_virtio_device_reset(vdev);
-               vdev->poll_wake = 1;
-               wake_up(&vdev->waitq);
-       }
-}
-
-static void vop_bh_handler(struct work_struct *work)
-{
-       struct vop_vdev *vdev = container_of(work, struct vop_vdev,
-                       virtio_bh_work);
-
-       if (vdev->dc->used_address_updated)
-               vop_virtio_init_post(vdev);
-
-       if (vdev->dc->vdev_reset)
-               vop_virtio_device_reset(vdev);
-
-       vdev->poll_wake = 1;
-       wake_up(&vdev->waitq);
-}
-
-static irqreturn_t _vop_virtio_intr_handler(int irq, void *data)
-{
-       struct vop_vdev *vdev = data;
-       struct vop_device *vpdev = vdev->vpdev;
-
-       vpdev->hw_ops->ack_interrupt(vpdev, vdev->virtio_db);
-       schedule_work(&vdev->virtio_bh_work);
-       return IRQ_HANDLED;
-}
-
-static int vop_virtio_config_change(struct vop_vdev *vdev, void *argp)
-{
-       DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
-       int ret = 0, retry, i;
-       struct vop_device *vpdev = vdev->vpdev;
-       struct vop_info *vi = dev_get_drvdata(&vpdev->dev);
-       struct mic_bootparam *bootparam = vpdev->hw_ops->get_dp(vpdev);
-       s8 db = bootparam->h2c_config_db;
-
-       mutex_lock(&vi->vop_mutex);
-       for (i = 0; i < vdev->dd->num_vq; i++)
-               mutex_lock_nested(&vdev->vvr[i].vr_mutex, i + 1);
-
-       if (db == -1 || vdev->dd->type == -1) {
-               ret = -EIO;
-               goto exit;
-       }
-
-       memcpy(mic_vq_configspace(vdev->dd), argp, vdev->dd->config_len);
-       vdev->dc->config_change = MIC_VIRTIO_PARAM_CONFIG_CHANGED;
-       vpdev->hw_ops->send_intr(vpdev, db);
-
-       for (retry = 100; retry--;) {
-               ret = wait_event_timeout(wake, vdev->dc->guest_ack,
-                                        msecs_to_jiffies(100));
-               if (ret)
-                       break;
-       }
-
-       dev_dbg(vop_dev(vdev),
-               "%s %d retry: %d\n", __func__, __LINE__, retry);
-       vdev->dc->config_change = 0;
-       vdev->dc->guest_ack = 0;
-exit:
-       for (i = 0; i < vdev->dd->num_vq; i++)
-               mutex_unlock(&vdev->vvr[i].vr_mutex);
-       mutex_unlock(&vi->vop_mutex);
-       return ret;
-}
-
-static int vop_copy_dp_entry(struct vop_vdev *vdev,
-                            struct mic_device_desc *argp, __u8 *type,
-                            struct mic_device_desc **devpage)
-{
-       struct vop_device *vpdev = vdev->vpdev;
-       struct mic_device_desc *devp;
-       struct mic_vqconfig *vqconfig;
-       int ret = 0, i;
-       bool slot_found = false;
-
-       vqconfig = mic_vq_config(argp);
-       for (i = 0; i < argp->num_vq; i++) {
-               if (le16_to_cpu(vqconfig[i].num) > MIC_MAX_VRING_ENTRIES) {
-                       ret =  -EINVAL;
-                       dev_err(vop_dev(vdev), "%s %d err %d\n",
-                               __func__, __LINE__, ret);
-                       goto exit;
-               }
-       }
-
-       /* Find the first free device page entry */
-       for (i = sizeof(struct mic_bootparam);
-               i < MIC_DP_SIZE - mic_total_desc_size(argp);
-               i += mic_total_desc_size(devp)) {
-               devp = vpdev->hw_ops->get_dp(vpdev) + i;
-               if (devp->type == 0 || devp->type == -1) {
-                       slot_found = true;
-                       break;
-               }
-       }
-       if (!slot_found) {
-               ret =  -EINVAL;
-               dev_err(vop_dev(vdev), "%s %d err %d\n",
-                       __func__, __LINE__, ret);
-               goto exit;
-       }
-       /*
-        * Save off the type before doing the memcpy. Type will be set in the
-        * end after completing all initialization for the new device.
-        */
-       *type = argp->type;
-       argp->type = 0;
-       memcpy(devp, argp, mic_desc_size(argp));
-
-       *devpage = devp;
-exit:
-       return ret;
-}
-
-static void vop_init_device_ctrl(struct vop_vdev *vdev,
-                                struct mic_device_desc *devpage)
-{
-       struct mic_device_ctrl *dc;
-
-       dc = (void *)devpage + mic_aligned_desc_size(devpage);
-
-       dc->config_change = 0;
-       dc->guest_ack = 0;
-       dc->vdev_reset = 0;
-       dc->host_ack = 0;
-       dc->used_address_updated = 0;
-       dc->c2h_vdev_db = -1;
-       dc->h2c_vdev_db = -1;
-       vdev->dc = dc;
-}
-
-static int vop_virtio_add_device(struct vop_vdev *vdev,
-                                struct mic_device_desc *argp)
-{
-       struct vop_info *vi = vdev->vi;
-       struct vop_device *vpdev = vi->vpdev;
-       struct mic_device_desc *dd = NULL;
-       struct mic_vqconfig *vqconfig;
-       int vr_size, i, j, ret;
-       u8 type = 0;
-       s8 db = -1;
-       char irqname[16];
-       struct mic_bootparam *bootparam;
-       u16 num;
-       dma_addr_t vr_addr;
-
-       bootparam = vpdev->hw_ops->get_dp(vpdev);
-       init_waitqueue_head(&vdev->waitq);
-       INIT_LIST_HEAD(&vdev->list);
-       vdev->vpdev = vpdev;
-
-       ret = vop_copy_dp_entry(vdev, argp, &type, &dd);
-       if (ret) {
-               dev_err(vop_dev(vdev), "%s %d err %d\n",
-                       __func__, __LINE__, ret);
-               return ret;
-       }
-
-       vop_init_device_ctrl(vdev, dd);
-
-       vdev->dd = dd;
-       vdev->virtio_id = type;
-       vqconfig = mic_vq_config(dd);
-       INIT_WORK(&vdev->virtio_bh_work, vop_bh_handler);
-
-       for (i = 0; i < dd->num_vq; i++) {
-               struct vop_vringh *vvr = &vdev->vvr[i];
-               struct mic_vring *vr = &vdev->vvr[i].vring;
-
-               num = le16_to_cpu(vqconfig[i].num);
-               mutex_init(&vvr->vr_mutex);
-               vr_size = PAGE_ALIGN(round_up(vring_size(num, MIC_VIRTIO_RING_ALIGN), 4) +
-                       sizeof(struct _mic_vring_info));
-               vr->va = (void *)
-                       __get_free_pages(GFP_KERNEL | __GFP_ZERO,
-                                        get_order(vr_size));
-               if (!vr->va) {
-                       ret = -ENOMEM;
-                       dev_err(vop_dev(vdev), "%s %d err %d\n",
-                               __func__, __LINE__, ret);
-                       goto err;
-               }
-               vr->len = vr_size;
-               vr->info = vr->va + round_up(vring_size(num, MIC_VIRTIO_RING_ALIGN), 4);
-               vr->info->magic = cpu_to_le32(MIC_MAGIC + vdev->virtio_id + i);
-               vr_addr = dma_map_single(&vpdev->dev, vr->va, vr_size,
-                                        DMA_BIDIRECTIONAL);
-               if (dma_mapping_error(&vpdev->dev, vr_addr)) {
-                       free_pages((unsigned long)vr->va, get_order(vr_size));
-                       ret = -ENOMEM;
-                       dev_err(vop_dev(vdev), "%s %d err %d\n",
-                               __func__, __LINE__, ret);
-                       goto err;
-               }
-               vqconfig[i].address = cpu_to_le64(vr_addr);
-
-               vring_init(&vr->vr, num, vr->va, MIC_VIRTIO_RING_ALIGN);
-               ret = vringh_init_kern(&vvr->vrh,
-                                      *(u32 *)mic_vq_features(vdev->dd),
-                                      num, false, vr->vr.desc, vr->vr.avail,
-                                      vr->vr.used);
-               if (ret) {
-                       dev_err(vop_dev(vdev), "%s %d err %d\n",
-                               __func__, __LINE__, ret);
-                       goto err;
-               }
-               vringh_kiov_init(&vvr->riov, NULL, 0);
-               vringh_kiov_init(&vvr->wiov, NULL, 0);
-               vvr->head = USHRT_MAX;
-               vvr->vdev = vdev;
-               vvr->vrh.notify = _vop_notify;
-               dev_dbg(&vpdev->dev,
-                       "%s %d index %d va %p info %p vr_size 0x%x\n",
-                       __func__, __LINE__, i, vr->va, vr->info, vr_size);
-               vvr->buf = (void *)__get_free_pages(GFP_KERNEL,
-                                       get_order(VOP_INT_DMA_BUF_SIZE));
-               vvr->buf_da = dma_map_single(&vpdev->dev,
-                                         vvr->buf, VOP_INT_DMA_BUF_SIZE,
-                                         DMA_BIDIRECTIONAL);
-       }
-
-       snprintf(irqname, sizeof(irqname), "vop%dvirtio%d", vpdev->index,
-                vdev->virtio_id);
-       vdev->virtio_db = vpdev->hw_ops->next_db(vpdev);
-       vdev->virtio_cookie = vpdev->hw_ops->request_irq(vpdev,
-                       _vop_virtio_intr_handler, irqname, vdev,
-                       vdev->virtio_db);
-       if (IS_ERR(vdev->virtio_cookie)) {
-               ret = PTR_ERR(vdev->virtio_cookie);
-               dev_dbg(&vpdev->dev, "request irq failed\n");
-               goto err;
-       }
-
-       vdev->dc->c2h_vdev_db = vdev->virtio_db;
-
-       /*
-        * Order the type update with previous stores. This write barrier
-        * is paired with the corresponding read barrier before the uncached
-        * system memory read of the type, on the card while scanning the
-        * device page.
-        */
-       smp_wmb();
-       dd->type = type;
-       argp->type = type;
-
-       if (bootparam) {
-               db = bootparam->h2c_config_db;
-               if (db != -1)
-                       vpdev->hw_ops->send_intr(vpdev, db);
-       }
-       dev_dbg(&vpdev->dev, "Added virtio id %d db %d\n", dd->type, db);
-       return 0;
-err:
-       vqconfig = mic_vq_config(dd);
-       for (j = 0; j < i; j++) {
-               struct vop_vringh *vvr = &vdev->vvr[j];
-
-               dma_unmap_single(&vpdev->dev, le64_to_cpu(vqconfig[j].address),
-                                vvr->vring.len, DMA_BIDIRECTIONAL);
-               free_pages((unsigned long)vvr->vring.va,
-                          get_order(vvr->vring.len));
-       }
-       return ret;
-}
-
-static void vop_dev_remove(struct vop_info *pvi, struct mic_device_ctrl *devp,
-                          struct vop_device *vpdev)
-{
-       struct mic_bootparam *bootparam = vpdev->hw_ops->get_dp(vpdev);
-       s8 db;
-       int ret, retry;
-       DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
-
-       devp->config_change = MIC_VIRTIO_PARAM_DEV_REMOVE;
-       db = bootparam->h2c_config_db;
-       if (db != -1)
-               vpdev->hw_ops->send_intr(vpdev, db);
-       else
-               goto done;
-       for (retry = 15; retry--;) {
-               ret = wait_event_timeout(wake, devp->guest_ack,
-                                        msecs_to_jiffies(1000));
-               if (ret)
-                       break;
-       }
-done:
-       devp->config_change = 0;
-       devp->guest_ack = 0;
-}
-
-static void vop_virtio_del_device(struct vop_vdev *vdev)
-{
-       struct vop_info *vi = vdev->vi;
-       struct vop_device *vpdev = vdev->vpdev;
-       int i;
-       struct mic_vqconfig *vqconfig;
-       struct mic_bootparam *bootparam = vpdev->hw_ops->get_dp(vpdev);
-
-       if (!bootparam)
-               goto skip_hot_remove;
-       vop_dev_remove(vi, vdev->dc, vpdev);
-skip_hot_remove:
-       vpdev->hw_ops->free_irq(vpdev, vdev->virtio_cookie, vdev);
-       flush_work(&vdev->virtio_bh_work);
-       vqconfig = mic_vq_config(vdev->dd);
-       for (i = 0; i < vdev->dd->num_vq; i++) {
-               struct vop_vringh *vvr = &vdev->vvr[i];
-
-               dma_unmap_single(&vpdev->dev,
-                                vvr->buf_da, VOP_INT_DMA_BUF_SIZE,
-                                DMA_BIDIRECTIONAL);
-               free_pages((unsigned long)vvr->buf,
-                          get_order(VOP_INT_DMA_BUF_SIZE));
-               vringh_kiov_cleanup(&vvr->riov);
-               vringh_kiov_cleanup(&vvr->wiov);
-               dma_unmap_single(&vpdev->dev, le64_to_cpu(vqconfig[i].address),
-                                vvr->vring.len, DMA_BIDIRECTIONAL);
-               free_pages((unsigned long)vvr->vring.va,
-                          get_order(vvr->vring.len));
-       }
-       /*
-        * Order the type update with previous stores. This write barrier
-        * is paired with the corresponding read barrier before the uncached
-        * system memory read of the type, on the card while scanning the
-        * device page.
-        */
-       smp_wmb();
-       vdev->dd->type = -1;
-}
-
-/*
- * vop_sync_dma - Wrapper for synchronous DMAs.
- *
- * @dev - The address of the pointer to the device instance used
- * for DMA registration.
- * @dst - destination DMA address.
- * @src - source DMA address.
- * @len - size of the transfer.
- *
- * Return DMA_SUCCESS on success
- */
-static int vop_sync_dma(struct vop_vdev *vdev, dma_addr_t dst, dma_addr_t src,
-                       size_t len)
-{
-       int err = 0;
-       struct dma_device *ddev;
-       struct dma_async_tx_descriptor *tx;
-       struct vop_info *vi = dev_get_drvdata(&vdev->vpdev->dev);
-       struct dma_chan *vop_ch = vi->dma_ch;
-
-       if (!vop_ch) {
-               err = -EBUSY;
-               goto error;
-       }
-       ddev = vop_ch->device;
-       tx = ddev->device_prep_dma_memcpy(vop_ch, dst, src, len,
-               DMA_PREP_FENCE);
-       if (!tx) {
-               err = -ENOMEM;
-               goto error;
-       } else {
-               dma_cookie_t cookie;
-
-               cookie = tx->tx_submit(tx);
-               if (dma_submit_error(cookie)) {
-                       err = -ENOMEM;
-                       goto error;
-               }
-               dma_async_issue_pending(vop_ch);
-               err = dma_sync_wait(vop_ch, cookie);
-       }
-error:
-       if (err)
-               dev_err(&vi->vpdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, err);
-       return err;
-}
-
-#define VOP_USE_DMA true
-
-/*
- * Initiates the copies across the PCIe bus from card memory to a user
- * space buffer. When transfers are done using DMA, source/destination
- * addresses and transfer length must follow the alignment requirements of
- * the MIC DMA engine.
- */
-static int vop_virtio_copy_to_user(struct vop_vdev *vdev, void __user *ubuf,
-                                  size_t len, u64 daddr, size_t dlen,
-                                  int vr_idx)
-{
-       struct vop_device *vpdev = vdev->vpdev;
-       void __iomem *dbuf = vpdev->hw_ops->remap(vpdev, daddr, len);
-       struct vop_vringh *vvr = &vdev->vvr[vr_idx];
-       struct vop_info *vi = dev_get_drvdata(&vpdev->dev);
-       size_t dma_alignment;
-       bool x200;
-       size_t dma_offset, partlen;
-       int err;
-
-       if (!VOP_USE_DMA || !vi->dma_ch) {
-               if (copy_to_user(ubuf, (void __force *)dbuf, len)) {
-                       err = -EFAULT;
-                       dev_err(vop_dev(vdev), "%s %d err %d\n",
-                               __func__, __LINE__, err);
-                       goto err;
-               }
-               vdev->in_bytes += len;
-               err = 0;
-               goto err;
-       }
-
-       dma_alignment = 1 << vi->dma_ch->device->copy_align;
-       x200 = is_dma_copy_aligned(vi->dma_ch->device, 1, 1, 1);
-
-       dma_offset = daddr - round_down(daddr, dma_alignment);
-       daddr -= dma_offset;
-       len += dma_offset;
-       /*
-        * X100 uses DMA addresses as seen by the card so adding
-        * the aperture base is not required for DMA. However x200
-        * requires DMA addresses to be an offset into the bar so
-        * add the aperture base for x200.
-        */
-       if (x200)
-               daddr += vpdev->aper->pa;
-       while (len) {
-               partlen = min_t(size_t, len, VOP_INT_DMA_BUF_SIZE);
-               err = vop_sync_dma(vdev, vvr->buf_da, daddr,
-                                  ALIGN(partlen, dma_alignment));
-               if (err) {
-                       dev_err(vop_dev(vdev), "%s %d err %d\n",
-                               __func__, __LINE__, err);
-                       goto err;
-               }
-               if (copy_to_user(ubuf, vvr->buf + dma_offset,
-                                partlen - dma_offset)) {
-                       err = -EFAULT;
-                       dev_err(vop_dev(vdev), "%s %d err %d\n",
-                               __func__, __LINE__, err);
-                       goto err;
-               }
-               daddr += partlen;
-               ubuf += partlen;
-               dbuf += partlen;
-               vdev->in_bytes_dma += partlen;
-               vdev->in_bytes += partlen;
-               len -= partlen;
-               dma_offset = 0;
-       }
-       err = 0;
-err:
-       vpdev->hw_ops->unmap(vpdev, dbuf);
-       dev_dbg(vop_dev(vdev),
-               "%s: ubuf %p dbuf %p len 0x%zx vr_idx 0x%x\n",
-               __func__, ubuf, dbuf, len, vr_idx);
-       return err;
-}
-
-/*
- * Initiates copies across the PCIe bus from a user space buffer to card
- * memory. When transfers are done using DMA, source/destination addresses
- * and transfer length must follow the alignment requirements of the MIC
- * DMA engine.
- */
-static int vop_virtio_copy_from_user(struct vop_vdev *vdev, void __user *ubuf,
-                                    size_t len, u64 daddr, size_t dlen,
-                                    int vr_idx)
-{
-       struct vop_device *vpdev = vdev->vpdev;
-       void __iomem *dbuf = vpdev->hw_ops->remap(vpdev, daddr, len);
-       struct vop_vringh *vvr = &vdev->vvr[vr_idx];
-       struct vop_info *vi = dev_get_drvdata(&vdev->vpdev->dev);
-       size_t dma_alignment;
-       bool x200;
-       size_t partlen;
-       bool dma = VOP_USE_DMA && vi->dma_ch;
-       int err = 0;
-       size_t offset = 0;
-
-       if (dma) {
-               dma_alignment = 1 << vi->dma_ch->device->copy_align;
-               x200 = is_dma_copy_aligned(vi->dma_ch->device, 1, 1, 1);
-
-               if (daddr & (dma_alignment - 1)) {
-                       vdev->tx_dst_unaligned += len;
-                       dma = false;
-               } else if (ALIGN(len, dma_alignment) > dlen) {
-                       vdev->tx_len_unaligned += len;
-                       dma = false;
-               }
-       }
-
-       if (!dma)
-               goto memcpy;
-
-       /*
-        * X100 uses DMA addresses as seen by the card so adding
-        * the aperture base is not required for DMA. However x200
-        * requires DMA addresses to be an offset into the bar so
-        * add the aperture base for x200.
-        */
-       if (x200)
-               daddr += vpdev->aper->pa;
-       while (len) {
-               partlen = min_t(size_t, len, VOP_INT_DMA_BUF_SIZE);
-
-               if (copy_from_user(vvr->buf, ubuf, partlen)) {
-                       err = -EFAULT;
-                       dev_err(vop_dev(vdev), "%s %d err %d\n",
-                               __func__, __LINE__, err);
-                       goto err;
-               }
-               err = vop_sync_dma(vdev, daddr, vvr->buf_da,
-                                  ALIGN(partlen, dma_alignment));
-               if (err) {
-                       dev_err(vop_dev(vdev), "%s %d err %d\n",
-                               __func__, __LINE__, err);
-                       goto err;
-               }
-               daddr += partlen;
-               ubuf += partlen;
-               dbuf += partlen;
-               vdev->out_bytes_dma += partlen;
-               vdev->out_bytes += partlen;
-               len -= partlen;
-       }
-memcpy:
-       /*
-        * We are copying to IO below and should ideally use something
-        * like copy_from_user_toio(..) if it existed.
-        */
-       while (len) {
-               partlen = min_t(size_t, len, VOP_INT_DMA_BUF_SIZE);
-
-               if (copy_from_user(vvr->buf, ubuf + offset, partlen)) {
-                       err = -EFAULT;
-                       dev_err(vop_dev(vdev), "%s %d err %d\n",
-                               __func__, __LINE__, err);
-                       goto err;
-               }
-               memcpy_toio(dbuf + offset, vvr->buf, partlen);
-               offset += partlen;
-               vdev->out_bytes += partlen;
-               len -= partlen;
-       }
-       err = 0;
-err:
-       vpdev->hw_ops->unmap(vpdev, dbuf);
-       dev_dbg(vop_dev(vdev),
-               "%s: ubuf %p dbuf %p len 0x%zx vr_idx 0x%x\n",
-               __func__, ubuf, dbuf, len, vr_idx);
-       return err;
-}
-
-#define MIC_VRINGH_READ true
-
-/* Determine the total number of bytes consumed in a VRINGH KIOV */
-static inline u32 vop_vringh_iov_consumed(struct vringh_kiov *iov)
-{
-       int i;
-       u32 total = iov->consumed;
-
-       for (i = 0; i < iov->i; i++)
-               total += iov->iov[i].iov_len;
-       return total;
-}
-
-/*
- * Traverse the VRINGH KIOV and issue the APIs to trigger the copies.
- * This API is heavily based on the vringh_iov_xfer(..) implementation
- * in vringh.c. The reason we cannot reuse vringh_iov_pull_kern(..)
- * and vringh_iov_push_kern(..) directly is because there is no
- * way to override the VRINGH xfer(..) routines as of v3.10.
- */
-static int vop_vringh_copy(struct vop_vdev *vdev, struct vringh_kiov *iov,
-                          void __user *ubuf, size_t len, bool read, int vr_idx,
-                          size_t *out_len)
-{
-       int ret = 0;
-       size_t partlen, tot_len = 0;
-
-       while (len && iov->i < iov->used) {
-               struct kvec *kiov = &iov->iov[iov->i];
-               unsigned long daddr = (unsigned long)kiov->iov_base;
-
-               partlen = min(kiov->iov_len, len);
-               if (read)
-                       ret = vop_virtio_copy_to_user(vdev, ubuf, partlen,
-                                                     daddr,
-                                                     kiov->iov_len,
-                                                     vr_idx);
-               else
-                       ret = vop_virtio_copy_from_user(vdev, ubuf, partlen,
-                                                       daddr,
-                                                       kiov->iov_len,
-                                                       vr_idx);
-               if (ret) {
-                       dev_err(vop_dev(vdev), "%s %d err %d\n",
-                               __func__, __LINE__, ret);
-                       break;
-               }
-               len -= partlen;
-               ubuf += partlen;
-               tot_len += partlen;
-               iov->consumed += partlen;
-               kiov->iov_len -= partlen;
-               kiov->iov_base += partlen;
-               if (!kiov->iov_len) {
-                       /* Fix up old iov element then increment. */
-                       kiov->iov_len = iov->consumed;
-                       kiov->iov_base -= iov->consumed;
-
-                       iov->consumed = 0;
-                       iov->i++;
-               }
-       }
-       *out_len = tot_len;
-       return ret;
-}
-
-/*
- * Use the standard VRINGH infrastructure in the kernel to fetch new
- * descriptors, initiate the copies and update the used ring.
- */
-static int _vop_virtio_copy(struct vop_vdev *vdev, struct mic_copy_desc *copy)
-{
-       int ret = 0;
-       u32 iovcnt = copy->iovcnt;
-       struct iovec iov;
-       struct iovec __user *u_iov = copy->iov;
-       void __user *ubuf = NULL;
-       struct vop_vringh *vvr = &vdev->vvr[copy->vr_idx];
-       struct vringh_kiov *riov = &vvr->riov;
-       struct vringh_kiov *wiov = &vvr->wiov;
-       struct vringh *vrh = &vvr->vrh;
-       u16 *head = &vvr->head;
-       struct mic_vring *vr = &vvr->vring;
-       size_t len = 0, out_len;
-
-       copy->out_len = 0;
-       /* Fetch a new IOVEC if all previous elements have been processed */
-       if (riov->i == riov->used && wiov->i == wiov->used) {
-               ret = vringh_getdesc_kern(vrh, riov, wiov,
-                                         head, GFP_KERNEL);
-               /* Check if there are available descriptors */
-               if (ret <= 0)
-                       return ret;
-       }
-       while (iovcnt) {
-               if (!len) {
-                       /* Copy over a new iovec from user space. */
-                       ret = copy_from_user(&iov, u_iov, sizeof(*u_iov));
-                       if (ret) {
-                               ret = -EINVAL;
-                               dev_err(vop_dev(vdev), "%s %d err %d\n",
-                                       __func__, __LINE__, ret);
-                               break;
-                       }
-                       len = iov.iov_len;
-                       ubuf = iov.iov_base;
-               }
-               /* Issue all the read descriptors first */
-               ret = vop_vringh_copy(vdev, riov, ubuf, len,
-                                     MIC_VRINGH_READ, copy->vr_idx, &out_len);
-               if (ret) {
-                       dev_err(vop_dev(vdev), "%s %d err %d\n",
-                               __func__, __LINE__, ret);
-                       break;
-               }
-               len -= out_len;
-               ubuf += out_len;
-               copy->out_len += out_len;
-               /* Issue the write descriptors next */
-               ret = vop_vringh_copy(vdev, wiov, ubuf, len,
-                                     !MIC_VRINGH_READ, copy->vr_idx, &out_len);
-               if (ret) {
-                       dev_err(vop_dev(vdev), "%s %d err %d\n",
-                               __func__, __LINE__, ret);
-                       break;
-               }
-               len -= out_len;
-               ubuf += out_len;
-               copy->out_len += out_len;
-               if (!len) {
-                       /* One user space iovec is now completed */
-                       iovcnt--;
-                       u_iov++;
-               }
-               /* Exit loop if all elements in KIOVs have been processed. */
-               if (riov->i == riov->used && wiov->i == wiov->used)
-                       break;
-       }
-       /*
-        * Update the used ring if a descriptor was available and some data was
-        * copied in/out and the user asked for a used ring update.
-        */
-       if (*head != USHRT_MAX && copy->out_len && copy->update_used) {
-               u32 total = 0;
-
-               /* Determine the total data consumed */
-               total += vop_vringh_iov_consumed(riov);
-               total += vop_vringh_iov_consumed(wiov);
-               vringh_complete_kern(vrh, *head, total);
-               *head = USHRT_MAX;
-               if (vringh_need_notify_kern(vrh) > 0)
-                       vringh_notify(vrh);
-               vringh_kiov_cleanup(riov);
-               vringh_kiov_cleanup(wiov);
-               /* Update avail idx for user space */
-               vr->info->avail_idx = vrh->last_avail_idx;
-       }
-       return ret;
-}
-
-static inline int vop_verify_copy_args(struct vop_vdev *vdev,
-                                      struct mic_copy_desc *copy)
-{
-       if (!vdev || copy->vr_idx >= vdev->dd->num_vq)
-               return -EINVAL;
-       return 0;
-}
-
-/* Copy a specified number of virtio descriptors in a chain */
-static int vop_virtio_copy_desc(struct vop_vdev *vdev,
-                               struct mic_copy_desc *copy)
-{
-       int err;
-       struct vop_vringh *vvr;
-
-       err = vop_verify_copy_args(vdev, copy);
-       if (err)
-               return err;
-
-       vvr = &vdev->vvr[copy->vr_idx];
-       mutex_lock(&vvr->vr_mutex);
-       if (!vop_vdevup(vdev)) {
-               err = -ENODEV;
-               dev_err(vop_dev(vdev), "%s %d err %d\n",
-                       __func__, __LINE__, err);
-               goto err;
-       }
-       err = _vop_virtio_copy(vdev, copy);
-       if (err) {
-               dev_err(vop_dev(vdev), "%s %d err %d\n",
-                       __func__, __LINE__, err);
-       }
-err:
-       mutex_unlock(&vvr->vr_mutex);
-       return err;
-}
-
-static int vop_open(struct inode *inode, struct file *f)
-{
-       struct vop_vdev *vdev;
-       struct vop_info *vi = container_of(f->private_data,
-               struct vop_info, miscdev);
-
-       vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
-       if (!vdev)
-               return -ENOMEM;
-       vdev->vi = vi;
-       mutex_init(&vdev->vdev_mutex);
-       f->private_data = vdev;
-       init_completion(&vdev->destroy);
-       complete(&vdev->destroy);
-       return 0;
-}
-
-static int vop_release(struct inode *inode, struct file *f)
-{
-       struct vop_vdev *vdev = f->private_data, *vdev_tmp;
-       struct vop_info *vi = vdev->vi;
-       struct list_head *pos, *tmp;
-       bool found = false;
-
-       mutex_lock(&vdev->vdev_mutex);
-       if (vdev->deleted)
-               goto unlock;
-       mutex_lock(&vi->vop_mutex);
-       list_for_each_safe(pos, tmp, &vi->vdev_list) {
-               vdev_tmp = list_entry(pos, struct vop_vdev, list);
-               if (vdev == vdev_tmp) {
-                       vop_virtio_del_device(vdev);
-                       list_del(pos);
-                       found = true;
-                       break;
-               }
-       }
-       mutex_unlock(&vi->vop_mutex);
-unlock:
-       mutex_unlock(&vdev->vdev_mutex);
-       if (!found)
-               wait_for_completion(&vdev->destroy);
-       f->private_data = NULL;
-       kfree(vdev);
-       return 0;
-}
-
-static long vop_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
-{
-       struct vop_vdev *vdev = f->private_data;
-       struct vop_info *vi = vdev->vi;
-       void __user *argp = (void __user *)arg;
-       int ret;
-
-       switch (cmd) {
-       case MIC_VIRTIO_ADD_DEVICE:
-       {
-               struct mic_device_desc dd, *dd_config;
-
-               if (copy_from_user(&dd, argp, sizeof(dd)))
-                       return -EFAULT;
-
-               if (mic_aligned_desc_size(&dd) > MIC_MAX_DESC_BLK_SIZE ||
-                   dd.num_vq > MIC_MAX_VRINGS)
-                       return -EINVAL;
-
-               dd_config = memdup_user(argp, mic_desc_size(&dd));
-               if (IS_ERR(dd_config))
-                       return PTR_ERR(dd_config);
-
-               /* Ensure desc has not changed between the two reads */
-               if (memcmp(&dd, dd_config, sizeof(dd))) {
-                       ret = -EINVAL;
-                       goto free_ret;
-               }
-               mutex_lock(&vdev->vdev_mutex);
-               mutex_lock(&vi->vop_mutex);
-               ret = vop_virtio_add_device(vdev, dd_config);
-               if (ret)
-                       goto unlock_ret;
-               list_add_tail(&vdev->list, &vi->vdev_list);
-unlock_ret:
-               mutex_unlock(&vi->vop_mutex);
-               mutex_unlock(&vdev->vdev_mutex);
-free_ret:
-               kfree(dd_config);
-               return ret;
-       }
-       case MIC_VIRTIO_COPY_DESC:
-       {
-               struct mic_copy_desc copy;
-
-               mutex_lock(&vdev->vdev_mutex);
-               ret = vop_vdev_inited(vdev);
-               if (ret)
-                       goto _unlock_ret;
-
-               if (copy_from_user(&copy, argp, sizeof(copy))) {
-                       ret = -EFAULT;
-                       goto _unlock_ret;
-               }
-
-               ret = vop_virtio_copy_desc(vdev, &copy);
-               if (ret < 0)
-                       goto _unlock_ret;
-               if (copy_to_user(
-                       &((struct mic_copy_desc __user *)argp)->out_len,
-                       &copy.out_len, sizeof(copy.out_len)))
-                       ret = -EFAULT;
-_unlock_ret:
-               mutex_unlock(&vdev->vdev_mutex);
-               return ret;
-       }
-       case MIC_VIRTIO_CONFIG_CHANGE:
-       {
-               void *buf;
-
-               mutex_lock(&vdev->vdev_mutex);
-               ret = vop_vdev_inited(vdev);
-               if (ret)
-                       goto __unlock_ret;
-               buf = memdup_user(argp, vdev->dd->config_len);
-               if (IS_ERR(buf)) {
-                       ret = PTR_ERR(buf);
-                       goto __unlock_ret;
-               }
-               ret = vop_virtio_config_change(vdev, buf);
-               kfree(buf);
-__unlock_ret:
-               mutex_unlock(&vdev->vdev_mutex);
-               return ret;
-       }
-       default:
-               return -ENOIOCTLCMD;
-       };
-       return 0;
-}
-
-/*
- * We return EPOLLIN | EPOLLOUT from poll when new buffers are enqueued, and
- * not when previously enqueued buffers may be available. This means that
- * in the card->host (TX) path, when userspace is unblocked by poll it
- * must drain all available descriptors or it can stall.
- */
-static __poll_t vop_poll(struct file *f, poll_table *wait)
-{
-       struct vop_vdev *vdev = f->private_data;
-       __poll_t mask = 0;
-
-       mutex_lock(&vdev->vdev_mutex);
-       if (vop_vdev_inited(vdev)) {
-               mask = EPOLLERR;
-               goto done;
-       }
-       poll_wait(f, &vdev->waitq, wait);
-       if (vop_vdev_inited(vdev)) {
-               mask = EPOLLERR;
-       } else if (vdev->poll_wake) {
-               vdev->poll_wake = 0;
-               mask = EPOLLIN | EPOLLOUT;
-       }
-done:
-       mutex_unlock(&vdev->vdev_mutex);
-       return mask;
-}
-
-static inline int
-vop_query_offset(struct vop_vdev *vdev, unsigned long offset,
-                unsigned long *size, unsigned long *pa)
-{
-       struct vop_device *vpdev = vdev->vpdev;
-       unsigned long start = MIC_DP_SIZE;
-       int i;
-
-       /*
-        * MMAP interface is as follows:
-        * offset                               region
-        * 0x0                                  virtio device_page
-        * 0x1000                               first vring
-        * 0x1000 + size of 1st vring           second vring
-        * ....
-        */
-       if (!offset) {
-               *pa = virt_to_phys(vpdev->hw_ops->get_dp(vpdev));
-               *size = MIC_DP_SIZE;
-               return 0;
-       }
-
-       for (i = 0; i < vdev->dd->num_vq; i++) {
-               struct vop_vringh *vvr = &vdev->vvr[i];
-
-               if (offset == start) {
-                       *pa = virt_to_phys(vvr->vring.va);
-                       *size = vvr->vring.len;
-                       return 0;
-               }
-               start += vvr->vring.len;
-       }
-       return -1;
-}
-
-/*
- * Maps the device page and virtio rings to user space for readonly access.
- */
-static int vop_mmap(struct file *f, struct vm_area_struct *vma)
-{
-       struct vop_vdev *vdev = f->private_data;
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-       unsigned long pa, size = vma->vm_end - vma->vm_start, size_rem = size;
-       int i, err;
-
-       err = vop_vdev_inited(vdev);
-       if (err)
-               goto ret;
-       if (vma->vm_flags & VM_WRITE) {
-               err = -EACCES;
-               goto ret;
-       }
-       while (size_rem) {
-               i = vop_query_offset(vdev, offset, &size, &pa);
-               if (i < 0) {
-                       err = -EINVAL;
-                       goto ret;
-               }
-               err = remap_pfn_range(vma, vma->vm_start + offset,
-                                     pa >> PAGE_SHIFT, size,
-                                     vma->vm_page_prot);
-               if (err)
-                       goto ret;
-               size_rem -= size;
-               offset += size;
-       }
-ret:
-       return err;
-}
-
-static const struct file_operations vop_fops = {
-       .open = vop_open,
-       .release = vop_release,
-       .unlocked_ioctl = vop_ioctl,
-       .poll = vop_poll,
-       .mmap = vop_mmap,
-       .owner = THIS_MODULE,
-};
-
-int vop_host_init(struct vop_info *vi)
-{
-       int rc;
-       struct miscdevice *mdev;
-       struct vop_device *vpdev = vi->vpdev;
-
-       INIT_LIST_HEAD(&vi->vdev_list);
-       vi->dma_ch = vpdev->dma_ch;
-       mdev = &vi->miscdev;
-       mdev->minor = MISC_DYNAMIC_MINOR;
-       snprintf(vi->name, sizeof(vi->name), "vop_virtio%d", vpdev->index);
-       mdev->name = vi->name;
-       mdev->fops = &vop_fops;
-       mdev->parent = &vpdev->dev;
-
-       rc = misc_register(mdev);
-       if (rc)
-               dev_err(&vpdev->dev, "%s failed rc %d\n", __func__, rc);
-       return rc;
-}
-
-void vop_host_uninit(struct vop_info *vi)
-{
-       struct list_head *pos, *tmp;
-       struct vop_vdev *vdev;
-
-       mutex_lock(&vi->vop_mutex);
-       vop_virtio_reset_devices(vi);
-       list_for_each_safe(pos, tmp, &vi->vdev_list) {
-               vdev = list_entry(pos, struct vop_vdev, list);
-               list_del(pos);
-               reinit_completion(&vdev->destroy);
-               mutex_unlock(&vi->vop_mutex);
-               mutex_lock(&vdev->vdev_mutex);
-               vop_virtio_del_device(vdev);
-               vdev->deleted = true;
-               mutex_unlock(&vdev->vdev_mutex);
-               complete(&vdev->destroy);
-               mutex_lock(&vi->vop_mutex);
-       }
-       mutex_unlock(&vi->vop_mutex);
-       misc_deregister(&vi->miscdev);
-}
index 414314151d0a47de58a90297177bdf751ef5d81d..acb9c81a4e4569354d8422601796750de89cb5a2 100644 (file)
@@ -572,17 +572,6 @@ static void renesas_sdhi_reset(struct tmio_mmc_host *host)
                                             TMIO_MASK_INIT_RCAR2);
 }
 
-/*
- * This is a temporary workaround! This driver used 'hw_reset' wrongly and the
- * fix for that showed a regression. So, we mimic the old behaviour until the
- * proper solution is found.
- */
-static void renesas_sdhi_hw_reset(struct mmc_host *mmc)
-{
-       struct tmio_mmc_host *host = mmc_priv(mmc);
-       renesas_sdhi_reset(host);
-}
-
 #define SH_MOBILE_SDHI_MIN_TAP_ROW 3
 
 static int renesas_sdhi_select_tuning(struct tmio_mmc_host *host)
@@ -1020,8 +1009,6 @@ int renesas_sdhi_probe(struct platform_device *pdev,
                if (of_data && of_data->scc_offset) {
                        priv->scc_ctl = host->ctl + of_data->scc_offset;
                        host->reset = renesas_sdhi_reset;
-                       host->ops.hw_reset = renesas_sdhi_hw_reset;
-                       host->mmc->caps |= MMC_CAP_HW_RESET;
                }
        }
 
@@ -1160,6 +1147,7 @@ int renesas_sdhi_remove(struct platform_device *pdev)
 
        tmio_mmc_host_remove(host);
        renesas_sdhi_clk_disable(host);
+       tmio_mmc_host_free(host);
 
        return 0;
 }
index a30796e79b1cbf6d5b13512e24229e6a0af10bcf..6de02f09c3222408a457b871c225b26071cd980d 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (c) 2007 Freescale Semiconductor, Inc.
  * Copyright (c) 2009 MontaVista Software, Inc.
  * Copyright (c) 2010 Pengutronix e.K.
+ * Copyright 2020 NXP
  *   Author: Wolfram Sang <kernel@pengutronix.de>
  */
 
@@ -88,6 +89,7 @@
 /* DLL Config 0 Register */
 #define ESDHC_DLLCFG0                  0x160
 #define ESDHC_DLL_ENABLE               0x80000000
+#define ESDHC_DLL_RESET                        0x40000000
 #define ESDHC_DLL_FREQ_SEL             0x08000000
 
 /* DLL Config 1 Register */
index 829ccef874262093b9e8604cd49a671e475f9e23..d25a4b50c2f33365ec95abd95ea83f9aaf5a8c2f 100644 (file)
 #define SDHCI_ARASAN_VENDOR_REGISTER   0x78
 
 #define SDHCI_ARASAN_ITAPDLY_REGISTER  0xF0F8
+#define SDHCI_ARASAN_ITAPDLY_SEL_MASK  0xFF
+
 #define SDHCI_ARASAN_OTAPDLY_REGISTER  0xF0FC
+#define SDHCI_ARASAN_OTAPDLY_SEL_MASK  0x3F
 
 #define SDHCI_ARASAN_CQE_BASE_ADDR     0x200
 #define VENDOR_ENHANCED_STROBE         BIT(0)
@@ -600,14 +603,8 @@ static int sdhci_zynqmp_sdcardclk_set_phase(struct clk_hw *hw, int degrees)
        u8 tap_delay, tap_max = 0;
        int ret;
 
-       /*
-        * This is applicable for SDHCI_SPEC_300 and above
-        * ZynqMP does not set phase for <=25MHz clock.
-        * If degrees is zero, no need to do anything.
-        */
-       if (host->version < SDHCI_SPEC_300 ||
-           host->timing == MMC_TIMING_LEGACY ||
-           host->timing == MMC_TIMING_UHS_SDR12 || !degrees)
+       /* This is applicable for SDHCI_SPEC_300 and above */
+       if (host->version < SDHCI_SPEC_300)
                return 0;
 
        switch (host->timing) {
@@ -638,6 +635,9 @@ static int sdhci_zynqmp_sdcardclk_set_phase(struct clk_hw *hw, int degrees)
        if (ret)
                pr_err("Error setting Output Tap Delay\n");
 
+       /* Release DLL Reset */
+       zynqmp_pm_sd_dll_reset(node_id, PM_DLL_RESET_RELEASE);
+
        return ret;
 }
 
@@ -668,16 +668,13 @@ static int sdhci_zynqmp_sampleclk_set_phase(struct clk_hw *hw, int degrees)
        u8 tap_delay, tap_max = 0;
        int ret;
 
-       /*
-        * This is applicable for SDHCI_SPEC_300 and above
-        * ZynqMP does not set phase for <=25MHz clock.
-        * If degrees is zero, no need to do anything.
-        */
-       if (host->version < SDHCI_SPEC_300 ||
-           host->timing == MMC_TIMING_LEGACY ||
-           host->timing == MMC_TIMING_UHS_SDR12 || !degrees)
+       /* This is applicable for SDHCI_SPEC_300 and above */
+       if (host->version < SDHCI_SPEC_300)
                return 0;
 
+       /* Assert DLL Reset */
+       zynqmp_pm_sd_dll_reset(node_id, PM_DLL_RESET_ASSERT);
+
        switch (host->timing) {
        case MMC_TIMING_MMC_HS:
        case MMC_TIMING_SD_HS:
@@ -733,14 +730,8 @@ static int sdhci_versal_sdcardclk_set_phase(struct clk_hw *hw, int degrees)
        struct sdhci_host *host = sdhci_arasan->host;
        u8 tap_delay, tap_max = 0;
 
-       /*
-        * This is applicable for SDHCI_SPEC_300 and above
-        * Versal does not set phase for <=25MHz clock.
-        * If degrees is zero, no need to do anything.
-        */
-       if (host->version < SDHCI_SPEC_300 ||
-           host->timing == MMC_TIMING_LEGACY ||
-           host->timing == MMC_TIMING_UHS_SDR12 || !degrees)
+       /* This is applicable for SDHCI_SPEC_300 and above */
+       if (host->version < SDHCI_SPEC_300)
                return 0;
 
        switch (host->timing) {
@@ -773,6 +764,7 @@ static int sdhci_versal_sdcardclk_set_phase(struct clk_hw *hw, int degrees)
                regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER);
                regval |= SDHCI_OTAPDLY_ENABLE;
                sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
+               regval &= ~SDHCI_ARASAN_OTAPDLY_SEL_MASK;
                regval |= tap_delay;
                sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
        }
@@ -804,14 +796,8 @@ static int sdhci_versal_sampleclk_set_phase(struct clk_hw *hw, int degrees)
        struct sdhci_host *host = sdhci_arasan->host;
        u8 tap_delay, tap_max = 0;
 
-       /*
-        * This is applicable for SDHCI_SPEC_300 and above
-        * Versal does not set phase for <=25MHz clock.
-        * If degrees is zero, no need to do anything.
-        */
-       if (host->version < SDHCI_SPEC_300 ||
-           host->timing == MMC_TIMING_LEGACY ||
-           host->timing == MMC_TIMING_UHS_SDR12 || !degrees)
+       /* This is applicable for SDHCI_SPEC_300 and above */
+       if (host->version < SDHCI_SPEC_300)
                return 0;
 
        switch (host->timing) {
@@ -846,6 +832,7 @@ static int sdhci_versal_sampleclk_set_phase(struct clk_hw *hw, int degrees)
                sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
                regval |= SDHCI_ITAPDLY_ENABLE;
                sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
+               regval &= ~SDHCI_ARASAN_ITAPDLY_SEL_MASK;
                regval |= tap_delay;
                sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
                regval &= ~SDHCI_ITAPDLY_CHGWIN;
index 0b45eff6fed497a22cf89f665806f8a73bf8d3f4..ab5ab969f711deecdbca38e27c758b2f2b416bd4 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Copyright (c) 2007, 2010, 2012 Freescale Semiconductor, Inc.
  * Copyright (c) 2009 MontaVista Software, Inc.
+ * Copyright 2020 NXP
  *
  * Authors: Xiaobo Xie <X.Xie@freescale.com>
  *         Anton Vorontsov <avorontsov@ru.mvista.com>
@@ -19,6 +20,7 @@
 #include <linux/clk.h>
 #include <linux/ktime.h>
 #include <linux/dma-mapping.h>
+#include <linux/iopoll.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include "sdhci-pltfm.h"
@@ -743,6 +745,21 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
                if (host->mmc->actual_clock == MMC_HS200_MAX_DTR)
                        temp |= ESDHC_DLL_FREQ_SEL;
                sdhci_writel(host, temp, ESDHC_DLLCFG0);
+
+               temp |= ESDHC_DLL_RESET;
+               sdhci_writel(host, temp, ESDHC_DLLCFG0);
+               udelay(1);
+               temp &= ~ESDHC_DLL_RESET;
+               sdhci_writel(host, temp, ESDHC_DLLCFG0);
+
+               /* Wait max 20 ms */
+               if (read_poll_timeout(sdhci_readl, temp,
+                                     temp & ESDHC_DLL_STS_SLV_LOCK,
+                                     10, 20000, false,
+                                     host, ESDHC_DLLSTAT0))
+                       pr_err("%s: timeout for delay chain lock.\n",
+                              mmc_hostname(host->mmc));
+
                temp = sdhci_readl(host, ESDHC_TBCTL);
                sdhci_writel(host, temp | ESDHC_HS400_WNDW_ADJUST, ESDHC_TBCTL);
 
@@ -1052,6 +1069,17 @@ static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
 
        esdhc_tuning_block_enable(host, true);
 
+       /*
+        * The eSDHC controller takes the data timeout value into account
+        * during tuning. If the SD card is too slow sending the response, the
+        * timer will expire and a "Buffer Read Ready" interrupt without data
+        * is triggered. This leads to tuning errors.
+        *
+        * Just set the timeout to the maximum value because the core will
+        * already take care of it in sdhci_send_tuning().
+        */
+       sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL);
+
        hs400_tuning = host->flags & SDHCI_HS400_TUNING;
 
        do {
@@ -1296,6 +1324,8 @@ static struct soc_device_attribute soc_fixup_sdhc_clkdivs[] = {
 
 static struct soc_device_attribute soc_unreliable_pulse_detection[] = {
        { .family = "QorIQ LX2160A", .revision = "1.0", },
+       { .family = "QorIQ LX2160A", .revision = "2.0", },
+       { .family = "QorIQ LS1028A", .revision = "1.0", },
        { },
 };
 
index 23da7f7fe093afdcd0479891553ada4882433728..9552708846ca3742918bd352b7bade37b02f6471 100644 (file)
@@ -665,6 +665,15 @@ static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode,
        }
 }
 
+static void sdhci_intel_set_uhs_signaling(struct sdhci_host *host,
+                                         unsigned int timing)
+{
+       /* Set UHS timing to SDR25 for High Speed mode */
+       if (timing == MMC_TIMING_MMC_HS || timing == MMC_TIMING_SD_HS)
+               timing = MMC_TIMING_UHS_SDR25;
+       sdhci_set_uhs_signaling(host, timing);
+}
+
 #define INTEL_HS400_ES_REG 0x78
 #define INTEL_HS400_ES_BIT BIT(0)
 
@@ -721,7 +730,7 @@ static const struct sdhci_ops sdhci_intel_byt_ops = {
        .enable_dma             = sdhci_pci_enable_dma,
        .set_bus_width          = sdhci_set_bus_width,
        .reset                  = sdhci_reset,
-       .set_uhs_signaling      = sdhci_set_uhs_signaling,
+       .set_uhs_signaling      = sdhci_intel_set_uhs_signaling,
        .hw_reset               = sdhci_pci_hw_reset,
 };
 
@@ -731,7 +740,7 @@ static const struct sdhci_ops sdhci_intel_glk_ops = {
        .enable_dma             = sdhci_pci_enable_dma,
        .set_bus_width          = sdhci_set_bus_width,
        .reset                  = sdhci_cqhci_reset,
-       .set_uhs_signaling      = sdhci_set_uhs_signaling,
+       .set_uhs_signaling      = sdhci_intel_set_uhs_signaling,
        .hw_reset               = sdhci_pci_hw_reset,
        .irq                    = sdhci_cqhci_irq,
 };
index 592a55a34b58eba8163d5277faecc880460f76f7..3561ae8a481a040194e106872ed21518cbb6f173 100644 (file)
@@ -1384,9 +1384,11 @@ static inline void sdhci_auto_cmd_select(struct sdhci_host *host,
        /*
         * In case of Version 4.10 or later, use of 'Auto CMD Auto
         * Select' is recommended rather than use of 'Auto CMD12
-        * Enable' or 'Auto CMD23 Enable'.
+        * Enable' or 'Auto CMD23 Enable'. We require Version 4 Mode
+        * here because some controllers (e.g sdhci-of-dwmshc) expect it.
         */
-       if (host->version >= SDHCI_SPEC_410 && (use_cmd12 || use_cmd23)) {
+       if (host->version >= SDHCI_SPEC_410 && host->v4_mode &&
+           (use_cmd12 || use_cmd23)) {
                *mode |= SDHCI_TRNS_AUTO_SEL;
 
                ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
index 2fce0518632d6c71b748cde46b73b192f1c01d59..cb4149fd12e07841c364130aea9d2a8cb6ac9da7 100644 (file)
@@ -175,6 +175,8 @@ static void tmio_mmc_reset(struct tmio_mmc_host *host)
        if (host->reset)
                host->reset(host);
 
+       tmio_mmc_abort_dma(host);
+
        if (host->pdata->flags & TMIO_MMC_SDIO_IRQ) {
                sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask);
                sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001);
@@ -223,8 +225,6 @@ static void tmio_mmc_reset_work(struct work_struct *work)
 
        /* Ready for new calls */
        host->mrq = NULL;
-
-       tmio_mmc_abort_dma(host);
        mmc_request_done(host->mmc, mrq);
 }
 
@@ -927,6 +927,9 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        switch (ios->power_mode) {
        case MMC_POWER_OFF:
                tmio_mmc_power_off(host);
+               /* Downgrade ensures a sane state for tuning HW (e.g. SCC) */
+               if (host->mmc->ops->hs400_downgrade)
+                       host->mmc->ops->hs400_downgrade(host->mmc);
                host->set_clock(host, 0);
                break;
        case MMC_POWER_UP:
index d3c5cc513c8f932cb039df7fe301f7c7e8377c7e..0c352b39ad4be7e7f3ef49a2e4b9d523f1c17944 100644 (file)
@@ -215,8 +215,17 @@ static int gpio_nand_setup_interface(struct nand_chip *this, int csline,
        return 0;
 }
 
+static int gpio_nand_attach_chip(struct nand_chip *chip)
+{
+       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
+       chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
+
+       return 0;
+}
+
 static const struct nand_controller_ops gpio_nand_ops = {
        .exec_op = gpio_nand_exec_op,
+       .attach_chip = gpio_nand_attach_chip,
        .setup_interface = gpio_nand_setup_interface,
 };
 
@@ -260,9 +269,6 @@ static int gpio_nand_probe(struct platform_device *pdev)
                return err;
        }
 
-       this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
-       this->ecc.algo = NAND_ECC_ALGO_HAMMING;
-
        platform_set_drvdata(pdev, priv);
 
        /* Set chip enabled but write protected */
index 79b057400fe91631f52379fc4f73647499c625fe..7892022bd6dd000d029935e3a7a08a2d76dd6733 100644 (file)
@@ -236,8 +236,17 @@ static int au1550nd_exec_op(struct nand_chip *this,
        return ret;
 }
 
+static int au1550nd_attach_chip(struct nand_chip *chip)
+{
+       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
+       chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
+
+       return 0;
+}
+
 static const struct nand_controller_ops au1550nd_ops = {
        .exec_op = au1550nd_exec_op,
+       .attach_chip = au1550nd_attach_chip,
 };
 
 static int au1550nd_probe(struct platform_device *pdev)
@@ -294,8 +303,6 @@ static int au1550nd_probe(struct platform_device *pdev)
        nand_controller_init(&ctx->controller);
        ctx->controller.ops = &au1550nd_ops;
        this->controller = &ctx->controller;
-       this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
-       this->ecc.algo = NAND_ECC_ALGO_HAMMING;
 
        if (pd->devwidth)
                this->options |= NAND_BUSWIDTH_16;
index b7f3f6347761512cbf9a6cbf610483f16311ec29..282203debd0cc2327fb4b698b3b836624165e159 100644 (file)
@@ -243,8 +243,24 @@ static int cs_calculate_ecc(struct nand_chip *this, const u_char *dat,
 
 static struct cs553x_nand_controller *controllers[4];
 
+static int cs553x_attach_chip(struct nand_chip *chip)
+{
+       if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
+               return 0;
+
+       chip->ecc.size = 256;
+       chip->ecc.bytes = 3;
+       chip->ecc.hwctl  = cs_enable_hwecc;
+       chip->ecc.calculate = cs_calculate_ecc;
+       chip->ecc.correct  = nand_correct_data;
+       chip->ecc.strength = 1;
+
+       return 0;
+}
+
 static const struct nand_controller_ops cs553x_nand_controller_ops = {
        .exec_op = cs553x_exec_op,
+       .attach_chip = cs553x_attach_chip,
 };
 
 static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
@@ -286,14 +302,6 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
                goto out_mtd;
        }
 
-       this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
-       this->ecc.size = 256;
-       this->ecc.bytes = 3;
-       this->ecc.hwctl  = cs_enable_hwecc;
-       this->ecc.calculate = cs_calculate_ecc;
-       this->ecc.correct  = nand_correct_data;
-       this->ecc.strength = 1;
-
        /* Enable the following for a flash based bad block table */
        this->bbt_options = NAND_BBT_USE_FLASH;
 
index 427f320fb79b9288dd975ad1465e53a79066de03..f8c36d19ab47f36aba5d2c1696bd795058bb084b 100644 (file)
@@ -585,6 +585,10 @@ static int davinci_nand_attach_chip(struct nand_chip *chip)
        if (IS_ERR(pdata))
                return PTR_ERR(pdata);
 
+       /* Use board-specific ECC config */
+       info->chip.ecc.engine_type = pdata->engine_type;
+       info->chip.ecc.placement = pdata->ecc_placement;
+
        switch (info->chip.ecc.engine_type) {
        case NAND_ECC_ENGINE_TYPE_NONE:
                pdata->ecc_bits = 0;
@@ -850,10 +854,6 @@ static int nand_davinci_probe(struct platform_device *pdev)
        info->mask_ale          = pdata->mask_ale ? : MASK_ALE;
        info->mask_cle          = pdata->mask_cle ? : MASK_CLE;
 
-       /* Use board-specific ECC config */
-       info->chip.ecc.engine_type = pdata->engine_type;
-       info->chip.ecc.placement = pdata->ecc_placement;
-
        spin_lock_irq(&davinci_nand_lock);
 
        /* put CSxNAND into NAND mode */
index 94432a453e5eef7d50e2ba6e8c7fc86c2b5ff943..26b265e4384a1a687f78fde108037ae7cba6f6fc 100644 (file)
@@ -1269,12 +1269,31 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd)
        return 1;
 }
 
+static int doc200x_attach_chip(struct nand_chip *chip)
+{
+       if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
+               return 0;
+
+       chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED;
+       chip->ecc.size = 512;
+       chip->ecc.bytes = 6;
+       chip->ecc.strength = 2;
+       chip->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK;
+       chip->ecc.hwctl = doc200x_enable_hwecc;
+       chip->ecc.calculate = doc200x_calculate_ecc;
+       chip->ecc.correct = doc200x_correct_data;
+
+       return 0;
+}
+
 static const struct nand_controller_ops doc200x_ops = {
        .exec_op = doc200x_exec_op,
+       .attach_chip = doc200x_attach_chip,
 };
 
 static const struct nand_controller_ops doc2001plus_ops = {
        .exec_op = doc2001plus_exec_op,
+       .attach_chip = doc200x_attach_chip,
 };
 
 static int __init doc_probe(unsigned long physadr)
@@ -1452,16 +1471,6 @@ static int __init doc_probe(unsigned long physadr)
 
        nand->controller        = &doc->base;
        nand_set_controller_data(nand, doc);
-       nand->ecc.hwctl         = doc200x_enable_hwecc;
-       nand->ecc.calculate     = doc200x_calculate_ecc;
-       nand->ecc.correct       = doc200x_correct_data;
-
-       nand->ecc.engine_type   = NAND_ECC_ENGINE_TYPE_ON_HOST;
-       nand->ecc.placement     = NAND_ECC_PLACEMENT_INTERLEAVED;
-       nand->ecc.size          = 512;
-       nand->ecc.bytes         = 6;
-       nand->ecc.strength      = 2;
-       nand->ecc.options       = NAND_ECC_GENERIC_ERASED_CHECK;
        nand->bbt_options       = NAND_BBT_USE_FLASH;
        /* Skip the automatic BBT scan so we can run it manually */
        nand->options           |= NAND_SKIP_BBTSCAN | NAND_NO_BBM_QUIRK;
index 0e7a9b64301e1198f0eeca2ee5a837ea86b6c092..e345f9d9f8e8dc2c2038fcbef3171a579575f67a 100644 (file)
@@ -707,6 +707,30 @@ static int fsl_ifc_attach_chip(struct nand_chip *chip)
 {
        struct mtd_info *mtd = nand_to_mtd(chip);
        struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
+       struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+       struct fsl_ifc_global __iomem *ifc_global = ctrl->gregs;
+       u32 csor;
+
+       csor = ifc_in32(&ifc_global->csor_cs[priv->bank].csor);
+
+       /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
+       if (csor & CSOR_NAND_ECC_DEC_EN) {
+               chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
+               mtd_set_ooblayout(mtd, &fsl_ifc_ooblayout_ops);
+
+               /* Hardware generates ECC per 512 Bytes */
+               chip->ecc.size = 512;
+               if ((csor & CSOR_NAND_ECC_MODE_MASK) == CSOR_NAND_ECC_MODE_4) {
+                       chip->ecc.bytes = 8;
+                       chip->ecc.strength = 4;
+               } else {
+                       chip->ecc.bytes = 16;
+                       chip->ecc.strength = 8;
+               }
+       } else {
+               chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
+               chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
+       }
 
        dev_dbg(priv->dev, "%s: nand->numchips = %d\n", __func__,
                nanddev_ntargets(&chip->base));
@@ -910,25 +934,6 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
                return -ENODEV;
        }
 
-       /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
-       if (csor & CSOR_NAND_ECC_DEC_EN) {
-               chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
-               mtd_set_ooblayout(mtd, &fsl_ifc_ooblayout_ops);
-
-               /* Hardware generates ECC per 512 Bytes */
-               chip->ecc.size = 512;
-               if ((csor & CSOR_NAND_ECC_MODE_MASK) == CSOR_NAND_ECC_MODE_4) {
-                       chip->ecc.bytes = 8;
-                       chip->ecc.strength = 4;
-               } else {
-                       chip->ecc.bytes = 16;
-                       chip->ecc.strength = 8;
-               }
-       } else {
-               chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
-               chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
-       }
-
        ret = fsl_ifc_sram_init(priv);
        if (ret)
                return ret;
index 4191831df182053197bd83be636c35a116ae7070..c88421a1c078df01218fefd97bea15a8333ab1a6 100644 (file)
@@ -880,6 +880,20 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand)
        struct mtd_info *mtd = nand_to_mtd(nand);
        struct fsmc_nand_data *host = nand_to_fsmc(nand);
 
+       if (nand->ecc.engine_type == NAND_ECC_ENGINE_TYPE_INVALID)
+               nand->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
+
+       if (!nand->ecc.size)
+               nand->ecc.size = 512;
+
+       if (AMBA_REV_BITS(host->pid) >= 8) {
+               nand->ecc.read_page = fsmc_read_page_hwecc;
+               nand->ecc.calculate = fsmc_read_hwecc_ecc4;
+               nand->ecc.correct = fsmc_bch8_correct_data;
+               nand->ecc.bytes = 13;
+               nand->ecc.strength = 8;
+       }
+
        if (AMBA_REV_BITS(host->pid) >= 8) {
                switch (mtd->oobsize) {
                case 16:
@@ -905,6 +919,7 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand)
                dev_info(host->dev, "Using 1-bit HW ECC scheme\n");
                nand->ecc.calculate = fsmc_read_hwecc_ecc1;
                nand->ecc.correct = nand_correct_data;
+               nand->ecc.hwctl = fsmc_enable_hwecc;
                nand->ecc.bytes = 3;
                nand->ecc.strength = 1;
                nand->ecc.options |= NAND_ECC_SOFT_HAMMING_SM_ORDER;
@@ -1055,13 +1070,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 
        mtd->dev.parent = &pdev->dev;
 
-       /*
-        * Setup default ECC mode. nand_dt_init() called from nand_scan_ident()
-        * can overwrite this value if the DT provides a different value.
-        */
-       nand->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
-       nand->ecc.hwctl = fsmc_enable_hwecc;
-       nand->ecc.size = 512;
        nand->badblockbits = 7;
 
        if (host->mode == USE_DMA_ACCESS) {
@@ -1084,14 +1092,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
                nand->options |= NAND_KEEP_TIMINGS;
        }
 
-       if (AMBA_REV_BITS(host->pid) >= 8) {
-               nand->ecc.read_page = fsmc_read_page_hwecc;
-               nand->ecc.calculate = fsmc_read_hwecc_ecc4;
-               nand->ecc.correct = fsmc_bch8_correct_data;
-               nand->ecc.bytes = 13;
-               nand->ecc.strength = 8;
-       }
-
        nand_controller_init(&host->base);
        host->base.ops = &fsmc_nand_controller_ops;
        nand->controller = &host->base;
index 4ec0a1e10867c279be94d66d08fdc1a0b0f3d641..eb03b8cea1cb7175857fcdaf775f5c63206b4f23 100644 (file)
@@ -161,8 +161,17 @@ static int gpio_nand_exec_op(struct nand_chip *chip,
        return ret;
 }
 
+static int gpio_nand_attach_chip(struct nand_chip *chip)
+{
+       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
+       chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
+
+       return 0;
+}
+
 static const struct nand_controller_ops gpio_nand_ops = {
        .exec_op = gpio_nand_exec_op,
+       .attach_chip = gpio_nand_attach_chip,
 };
 
 #ifdef CONFIG_OF
@@ -342,8 +351,6 @@ static int gpio_nand_probe(struct platform_device *pdev)
        gpiomtd->base.ops = &gpio_nand_ops;
 
        nand_set_flash_node(chip, pdev->dev.of_node);
-       chip->ecc.engine_type   = NAND_ECC_ENGINE_TYPE_SOFT;
-       chip->ecc.algo          = NAND_ECC_ALGO_HAMMING;
        chip->options           = gpiomtd->plat.options;
        chip->controller        = &gpiomtd->base;
 
index 4940bb2e3c079e0ed9f881b8d0f5a70e9b727677..9e728c7317956f60ce515ae6c55cce54fdb136d3 100644 (file)
@@ -648,6 +648,9 @@ static int lpc32xx_nand_attach_chip(struct nand_chip *chip)
        struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
        struct device *dev = &host->pdev->dev;
 
+       if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
+               return 0;
+
        host->dma_buf = devm_kzalloc(dev, mtd->writesize, GFP_KERNEL);
        if (!host->dma_buf)
                return -ENOMEM;
@@ -656,8 +659,17 @@ static int lpc32xx_nand_attach_chip(struct nand_chip *chip)
        if (!host->dummy_buf)
                return -ENOMEM;
 
-       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
        chip->ecc.size = 512;
+       chip->ecc.hwctl = lpc32xx_ecc_enable;
+       chip->ecc.read_page_raw = lpc32xx_read_page;
+       chip->ecc.read_page = lpc32xx_read_page;
+       chip->ecc.write_page_raw = lpc32xx_write_page_lowlevel;
+       chip->ecc.write_page = lpc32xx_write_page_lowlevel;
+       chip->ecc.write_oob = lpc32xx_write_oob;
+       chip->ecc.read_oob = lpc32xx_read_oob;
+       chip->ecc.strength = 4;
+       chip->ecc.bytes = 10;
+
        mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops);
        host->mlcsubpages = mtd->writesize / 512;
 
@@ -741,15 +753,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, host);
 
        /* Initialize function pointers */
-       nand_chip->ecc.hwctl = lpc32xx_ecc_enable;
-       nand_chip->ecc.read_page_raw = lpc32xx_read_page;
-       nand_chip->ecc.read_page = lpc32xx_read_page;
-       nand_chip->ecc.write_page_raw = lpc32xx_write_page_lowlevel;
-       nand_chip->ecc.write_page = lpc32xx_write_page_lowlevel;
-       nand_chip->ecc.write_oob = lpc32xx_write_oob;
-       nand_chip->ecc.read_oob = lpc32xx_read_oob;
-       nand_chip->ecc.strength = 4;
-       nand_chip->ecc.bytes = 10;
        nand_chip->legacy.waitfunc = lpc32xx_waitfunc;
 
        nand_chip->options = NAND_NO_SUBPAGE_WRITE;
index 6db9d2ed6881702e37e9cb69062322f944888a83..dc7785e30d2f6cbc6d7905c946f0e8ff035085a1 100644 (file)
@@ -775,6 +775,9 @@ static int lpc32xx_nand_attach_chip(struct nand_chip *chip)
        struct mtd_info *mtd = nand_to_mtd(chip);
        struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
 
+       if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
+               return 0;
+
        /* OOB and ECC CPU and DMA work areas */
        host->ecc_buf = (uint32_t *)(host->data_buf + LPC32XX_DMA_DATA_SIZE);
 
@@ -786,11 +789,22 @@ static int lpc32xx_nand_attach_chip(struct nand_chip *chip)
        if (mtd->writesize <= 512)
                mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops);
 
+       chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED;
        /* These sizes remain the same regardless of page size */
        chip->ecc.size = 256;
+       chip->ecc.strength = 1;
        chip->ecc.bytes = LPC32XX_SLC_DEV_ECC_BYTES;
        chip->ecc.prepad = 0;
        chip->ecc.postpad = 0;
+       chip->ecc.read_page_raw = lpc32xx_nand_read_page_raw_syndrome;
+       chip->ecc.read_page = lpc32xx_nand_read_page_syndrome;
+       chip->ecc.write_page_raw = lpc32xx_nand_write_page_raw_syndrome;
+       chip->ecc.write_page = lpc32xx_nand_write_page_syndrome;
+       chip->ecc.write_oob = lpc32xx_nand_write_oob_syndrome;
+       chip->ecc.read_oob = lpc32xx_nand_read_oob_syndrome;
+       chip->ecc.calculate = lpc32xx_nand_ecc_calculate;
+       chip->ecc.correct = nand_correct_data;
+       chip->ecc.hwctl = lpc32xx_nand_ecc_enable;
 
        /*
         * Use a custom BBT marker setup for small page FLASH that
@@ -881,21 +895,9 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, host);
 
        /* NAND callbacks for LPC32xx SLC hardware */
-       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
-       chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED;
        chip->legacy.read_byte = lpc32xx_nand_read_byte;
        chip->legacy.read_buf = lpc32xx_nand_read_buf;
        chip->legacy.write_buf = lpc32xx_nand_write_buf;
-       chip->ecc.read_page_raw = lpc32xx_nand_read_page_raw_syndrome;
-       chip->ecc.read_page = lpc32xx_nand_read_page_syndrome;
-       chip->ecc.write_page_raw = lpc32xx_nand_write_page_raw_syndrome;
-       chip->ecc.write_page = lpc32xx_nand_write_page_syndrome;
-       chip->ecc.write_oob = lpc32xx_nand_write_oob_syndrome;
-       chip->ecc.read_oob = lpc32xx_nand_read_oob_syndrome;
-       chip->ecc.calculate = lpc32xx_nand_ecc_calculate;
-       chip->ecc.correct = nand_correct_data;
-       chip->ecc.strength = 1;
-       chip->ecc.hwctl = lpc32xx_nand_ecc_enable;
 
        /*
         * Allocate a large enough buffer for a single huge page plus
index dfd0d3ed5ed0418e5cfbb9c5b70216074a00a6a3..fb4c0b11689fc4bf1a2d3d3bcc61f65737d311e8 100644 (file)
 #define NFC_TIMEOUT            (HZ / 10)       /* 1/10 s */
 
 struct mpc5121_nfc_prv {
+       struct nand_controller  controller;
        struct nand_chip        chip;
        int                     irq;
        void __iomem            *regs;
@@ -602,6 +603,18 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
                iounmap(prv->csreg);
 }
 
+static int mpc5121_nfc_attach_chip(struct nand_chip *chip)
+{
+       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
+       chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
+
+       return 0;
+}
+
+static const struct nand_controller_ops mpc5121_nfc_ops = {
+       .attach_chip = mpc5121_nfc_attach_chip,
+};
+
 static int mpc5121_nfc_probe(struct platform_device *op)
 {
        struct device_node *dn = op->dev.of_node;
@@ -634,6 +647,10 @@ static int mpc5121_nfc_probe(struct platform_device *op)
        chip = &prv->chip;
        mtd = nand_to_mtd(chip);
 
+       nand_controller_init(&prv->controller);
+       prv->controller.ops = &mpc5121_nfc_ops;
+       chip->controller = &prv->controller;
+
        mtd->dev.parent = dev;
        nand_set_controller_data(chip, prv);
        nand_set_flash_node(chip, dn);
@@ -688,8 +705,6 @@ static int mpc5121_nfc_probe(struct platform_device *op)
        chip->legacy.set_features = nand_get_set_features_notsupp;
        chip->legacy.get_features = nand_get_set_features_notsupp;
        chip->bbt_options = NAND_BBT_USE_FLASH;
-       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
-       chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
 
        /* Support external chip-select logic on ADS5121 board */
        if (of_machine_is_compatible("fsl,mpc5121ads")) {
index d4200eb2ad3284984dec89758f0d798a0c333762..684c51e5e60dd07ce9963213fa3e7733f4419baf 100644 (file)
@@ -1681,6 +1681,11 @@ static int mxcnd_attach_chip(struct nand_chip *chip)
        struct mxc_nand_host *host = nand_get_controller_data(chip);
        struct device *dev = mtd->dev.parent;
 
+       chip->ecc.bytes = host->devtype_data->eccbytes;
+       host->eccsize = host->devtype_data->eccsize;
+       chip->ecc.size = 512;
+       mtd_set_ooblayout(mtd, host->devtype_data->ooblayout);
+
        switch (chip->ecc.engine_type) {
        case NAND_ECC_ENGINE_TYPE_ON_HOST:
                chip->ecc.read_page = mxc_nand_read_page;
@@ -1836,19 +1841,7 @@ static int mxcnd_probe(struct platform_device *pdev)
        if (host->devtype_data->axi_offset)
                host->regs_axi = host->base + host->devtype_data->axi_offset;
 
-       this->ecc.bytes = host->devtype_data->eccbytes;
-       host->eccsize = host->devtype_data->eccsize;
-
        this->legacy.select_chip = host->devtype_data->select_chip;
-       this->ecc.size = 512;
-       mtd_set_ooblayout(mtd, host->devtype_data->ooblayout);
-
-       if (host->pdata.hw_ecc) {
-               this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
-       } else {
-               this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
-               this->ecc.algo = NAND_ECC_ALGO_HAMMING;
-       }
 
        /* NAND bus width determines access functions used by upper layer */
        if (host->pdata.width == 2)
index df9c0f8e4b4e0723281376f33d9ee7f97274567f..e3bb65fd3ab2f2a53e2cbec2246ac0d92b661691 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/platform_data/mtd-orion_nand.h>
 
 struct orion_nand_info {
+       struct nand_controller controller;
        struct nand_chip chip;
        struct clk *clk;
 };
@@ -82,6 +83,18 @@ static void orion_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
                buf[i++] = readb(io_base);
 }
 
+static int orion_nand_attach_chip(struct nand_chip *chip)
+{
+       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
+       chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
+
+       return 0;
+}
+
+static const struct nand_controller_ops orion_nand_ops = {
+       .attach_chip = orion_nand_attach_chip,
+};
+
 static int __init orion_nand_probe(struct platform_device *pdev)
 {
        struct orion_nand_info *info;
@@ -101,6 +114,10 @@ static int __init orion_nand_probe(struct platform_device *pdev)
        nc = &info->chip;
        mtd = nand_to_mtd(nc);
 
+       nand_controller_init(&info->controller);
+       info->controller.ops = &orion_nand_ops;
+       nc->controller = &info->controller;
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        io_base = devm_ioremap_resource(&pdev->dev, res);
 
@@ -139,8 +156,6 @@ static int __init orion_nand_probe(struct platform_device *pdev)
        nc->legacy.IO_ADDR_R = nc->legacy.IO_ADDR_W = io_base;
        nc->legacy.cmd_ctrl = orion_nand_cmd_ctrl;
        nc->legacy.read_buf = orion_nand_read_buf;
-       nc->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
-       nc->ecc.algo = NAND_ECC_ALGO_HAMMING;
 
        if (board->chip_delay)
                nc->legacy.chip_delay = board->chip_delay;
index 2b8f155cc0c5ba4091e6bcc492ae58b748185f03..4dfff34800f4e5ac127b1d3df8f5c1bbf9eef63f 100644 (file)
@@ -29,6 +29,7 @@
 
 static unsigned int lpcctl;
 static struct mtd_info *pasemi_nand_mtd;
+static struct nand_controller controller;
 static const char driver_name[] = "pasemi-nand";
 
 static void pasemi_read_buf(struct nand_chip *chip, u_char *buf, int len)
@@ -73,6 +74,18 @@ static int pasemi_device_ready(struct nand_chip *chip)
        return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR);
 }
 
+static int pasemi_attach_chip(struct nand_chip *chip)
+{
+       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
+       chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
+
+       return 0;
+}
+
+static const struct nand_controller_ops pasemi_ops = {
+       .attach_chip = pasemi_attach_chip,
+};
+
 static int pasemi_nand_probe(struct platform_device *ofdev)
 {
        struct device *dev = &ofdev->dev;
@@ -100,6 +113,10 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
                goto out;
        }
 
+       controller.ops = &pasemi_ops;
+       nand_controller_init(&controller);
+       chip->controller = &controller;
+
        pasemi_nand_mtd = nand_to_mtd(chip);
 
        /* Link the private data with the MTD structure */
@@ -132,8 +149,6 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
        chip->legacy.read_buf = pasemi_read_buf;
        chip->legacy.write_buf = pasemi_write_buf;
        chip->legacy.chip_delay = 0;
-       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
-       chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
 
        /* Enable the following for a flash based bad block table */
        chip->bbt_options = NAND_BBT_USE_FLASH;
index b98c0d5c413fa837a570de0e23d27c8a68b4f9ab..93d9f1694dc13009a95a24431001c62bcee4979a 100644 (file)
 #include <linux/mtd/platnand.h>
 
 struct plat_nand_data {
+       struct nand_controller  controller;
        struct nand_chip        chip;
        void __iomem            *io_base;
 };
 
+static int plat_nand_attach_chip(struct nand_chip *chip)
+{
+       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
+       chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
+
+       return 0;
+}
+
+static const struct nand_controller_ops plat_nand_ops = {
+       .attach_chip = plat_nand_attach_chip,
+};
+
 /*
  * Probe for the NAND device.
  */
@@ -46,6 +59,10 @@ static int plat_nand_probe(struct platform_device *pdev)
        if (!data)
                return -ENOMEM;
 
+       data->controller.ops = &plat_nand_ops;
+       nand_controller_init(&data->controller);
+       data->chip.controller = &data->controller;
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        data->io_base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(data->io_base))
@@ -66,9 +83,6 @@ static int plat_nand_probe(struct platform_device *pdev)
        data->chip.options |= pdata->chip.options;
        data->chip.bbt_options |= pdata->chip.bbt_options;
 
-       data->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
-       data->chip.ecc.algo = NAND_ECC_ALGO_HAMMING;
-
        platform_set_drvdata(pdev, data);
 
        /* Handle any platform specific setup */
index 6b7addd2c42089a73bb4542e72c4039e5d04a03f..c742354c1b0becafba04aa2bb99434c32c9c4caf 100644 (file)
@@ -817,6 +817,29 @@ out:
        return ret;
 }
 
+static int r852_attach_chip(struct nand_chip *chip)
+{
+       if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
+               return 0;
+
+       chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED;
+       chip->ecc.size = R852_DMA_LEN;
+       chip->ecc.bytes = SM_OOB_SIZE;
+       chip->ecc.strength = 2;
+       chip->ecc.hwctl = r852_ecc_hwctl;
+       chip->ecc.calculate = r852_ecc_calculate;
+       chip->ecc.correct = r852_ecc_correct;
+
+       /* TODO: hack */
+       chip->ecc.read_oob = r852_read_oob;
+
+       return 0;
+}
+
+static const struct nand_controller_ops r852_ops = {
+       .attach_chip = r852_attach_chip,
+};
+
 static int  r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 {
        int error;
@@ -858,19 +881,6 @@ static int  r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
        chip->legacy.read_buf = r852_read_buf;
        chip->legacy.write_buf = r852_write_buf;
 
-       /* ecc */
-       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
-       chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED;
-       chip->ecc.size = R852_DMA_LEN;
-       chip->ecc.bytes = SM_OOB_SIZE;
-       chip->ecc.strength = 2;
-       chip->ecc.hwctl = r852_ecc_hwctl;
-       chip->ecc.calculate = r852_ecc_calculate;
-       chip->ecc.correct = r852_ecc_correct;
-
-       /* TODO: hack */
-       chip->ecc.read_oob = r852_read_oob;
-
        /* init our device structure */
        dev = kzalloc(sizeof(struct r852_device), GFP_KERNEL);
 
@@ -882,6 +892,10 @@ static int  r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
        dev->pci_dev = pci_dev;
        pci_set_drvdata(pci_dev, dev);
 
+       nand_controller_init(&dev->controller);
+       dev->controller.ops = &r852_ops;
+       chip->controller = &dev->controller;
+
        dev->bounce_buffer = dma_alloc_coherent(&pci_dev->dev, R852_DMA_LEN,
                &dev->phys_bounce_buffer, GFP_KERNEL);
 
index e9ce299c499d66240e56b0d80a61d02af3dff125..96fe301d15da26bc52e2def132ceea37a4fc897d 100644 (file)
 #define DMA_MEMORY     1
 
 struct r852_device {
+       struct nand_controller          controller;
        void __iomem *mmio;             /* mmio */
        struct nand_chip *chip;         /* nand chip backpointer */
        struct pci_dev *pci_dev;        /* pci backpointer */
index 1327bfb3d5d3f005536217fd9a304bd76f016a22..af98bcc9d689c481d3015e473863cc44882c0e7d 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/io.h>
 
 struct sharpsl_nand {
+       struct nand_controller  controller;
        struct nand_chip        chip;
 
        void __iomem            *io;
@@ -96,6 +97,25 @@ static int sharpsl_nand_calculate_ecc(struct nand_chip *chip,
        return readb(sharpsl->io + ECCCNTR) != 0;
 }
 
+static int sharpsl_attach_chip(struct nand_chip *chip)
+{
+       if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
+               return 0;
+
+       chip->ecc.size = 256;
+       chip->ecc.bytes = 3;
+       chip->ecc.strength = 1;
+       chip->ecc.hwctl = sharpsl_nand_enable_hwecc;
+       chip->ecc.calculate = sharpsl_nand_calculate_ecc;
+       chip->ecc.correct = nand_correct_data;
+
+       return 0;
+}
+
+static const struct nand_controller_ops sharpsl_ops = {
+       .attach_chip = sharpsl_attach_chip,
+};
+
 /*
  * Main initialization routine
  */
@@ -136,6 +156,10 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
        /* Get pointer to private data */
        this = (struct nand_chip *)(&sharpsl->chip);
 
+       nand_controller_init(&sharpsl->controller);
+       sharpsl->controller.ops = &sharpsl_ops;
+       this->controller = &sharpsl->controller;
+
        /* Link the private data with the MTD structure */
        mtd = nand_to_mtd(this);
        mtd->dev.parent = &pdev->dev;
@@ -156,15 +180,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
        this->legacy.dev_ready = sharpsl_nand_dev_ready;
        /* 15 us command delay time */
        this->legacy.chip_delay = 15;
-       /* set eccmode using hardware ECC */
-       this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
-       this->ecc.size = 256;
-       this->ecc.bytes = 3;
-       this->ecc.strength = 1;
        this->badblock_pattern = data->badblock_pattern;
-       this->ecc.hwctl = sharpsl_nand_enable_hwecc;
-       this->ecc.calculate = sharpsl_nand_calculate_ecc;
-       this->ecc.correct = nand_correct_data;
 
        /* Scan to find existence of the device */
        err = nand_scan(this, 1);
index 0f63ff6f7fe7dc5175a42657a98f3c3280ae982f..107208311987ee8847b047e43e6f199f571cb0bd 100644 (file)
@@ -22,6 +22,7 @@
 #define FPGA_NAND_DATA_SHIFT           16
 
 struct socrates_nand_host {
+       struct nand_controller  controller;
        struct nand_chip        nand_chip;
        void __iomem            *io_base;
        struct device           *dev;
@@ -116,6 +117,18 @@ static int socrates_nand_device_ready(struct nand_chip *nand_chip)
        return 1;
 }
 
+static int socrates_attach_chip(struct nand_chip *chip)
+{
+       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
+       chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
+
+       return 0;
+}
+
+static const struct nand_controller_ops socrates_ops = {
+       .attach_chip = socrates_attach_chip,
+};
+
 /*
  * Probe for the NAND device.
  */
@@ -141,6 +154,10 @@ static int socrates_nand_probe(struct platform_device *ofdev)
        mtd = nand_to_mtd(nand_chip);
        host->dev = &ofdev->dev;
 
+       nand_controller_init(&host->controller);
+       host->controller.ops = &socrates_ops;
+       nand_chip->controller = &host->controller;
+
        /* link the private data structures */
        nand_set_controller_data(nand_chip, host);
        nand_set_flash_node(nand_chip, ofdev->dev.of_node);
@@ -153,10 +170,6 @@ static int socrates_nand_probe(struct platform_device *ofdev)
        nand_chip->legacy.read_buf = socrates_nand_read_buf;
        nand_chip->legacy.dev_ready = socrates_nand_device_ready;
 
-       /* enable ECC */
-       nand_chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
-       nand_chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
-
        /* TODO: I have no idea what real delay is. */
        nand_chip->legacy.chip_delay = 20;      /* 20us command delay time */
 
index b31a5818234d3430c96da4fc51b924e590d6d3aa..550bda4d1415a34745bde133bf32203d3cf604e9 100644 (file)
@@ -1708,6 +1708,13 @@ static int stm32_fmc2_nfc_attach_chip(struct nand_chip *chip)
                return -EINVAL;
        }
 
+       /* Default ECC settings in case they are not set in the device tree */
+       if (!chip->ecc.size)
+               chip->ecc.size = FMC2_ECC_STEP_SIZE;
+
+       if (!chip->ecc.strength)
+               chip->ecc.strength = FMC2_ECC_BCH8;
+
        ret = nand_ecc_choose_conf(chip, &stm32_fmc2_nfc_ecc_caps,
                                   mtd->oobsize - FMC2_BBM_LEN);
        if (ret) {
@@ -1727,8 +1734,7 @@ static int stm32_fmc2_nfc_attach_chip(struct nand_chip *chip)
 
        mtd_set_ooblayout(mtd, &stm32_fmc2_nfc_ooblayout_ops);
 
-       if (chip->options & NAND_BUSWIDTH_16)
-               stm32_fmc2_nfc_set_buswidth_16(nfc, true);
+       stm32_fmc2_nfc_setup(chip);
 
        return 0;
 }
@@ -1952,11 +1958,6 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
        chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
                         NAND_USES_DMA;
 
-       /* Default ECC settings */
-       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
-       chip->ecc.size = FMC2_ECC_STEP_SIZE;
-       chip->ecc.strength = FMC2_ECC_BCH8;
-
        /* Scan to find existence of the device */
        ret = nand_scan(chip, nand->ncs);
        if (ret)
index 235a2f7b1baddc30aaa04d96d9bef46ff800af83..aa6c7e7bbf1b59f36f50f0b1725a7b2a5136de2f 100644 (file)
 /*--------------------------------------------------------------------------*/
 
 struct tmio_nand {
+       struct nand_controller controller;
        struct nand_chip chip;
        struct completion comp;
 
@@ -355,6 +356,25 @@ static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio)
                cell->disable(dev);
 }
 
+static int tmio_attach_chip(struct nand_chip *chip)
+{
+       if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
+               return 0;
+
+       chip->ecc.size = 512;
+       chip->ecc.bytes = 6;
+       chip->ecc.strength = 2;
+       chip->ecc.hwctl = tmio_nand_enable_hwecc;
+       chip->ecc.calculate = tmio_nand_calculate_ecc;
+       chip->ecc.correct = tmio_nand_correct_data;
+
+       return 0;
+}
+
+static const struct nand_controller_ops tmio_ops = {
+       .attach_chip = tmio_attach_chip,
+};
+
 static int tmio_probe(struct platform_device *dev)
 {
        struct tmio_nand_data *data = dev_get_platdata(&dev->dev);
@@ -385,6 +405,10 @@ static int tmio_probe(struct platform_device *dev)
        mtd->name = "tmio-nand";
        mtd->dev.parent = &dev->dev;
 
+       nand_controller_init(&tmio->controller);
+       tmio->controller.ops = &tmio_ops;
+       nand_chip->controller = &tmio->controller;
+
        tmio->ccr = devm_ioremap(&dev->dev, ccr->start, resource_size(ccr));
        if (!tmio->ccr)
                return -EIO;
@@ -409,15 +433,6 @@ static int tmio_probe(struct platform_device *dev)
        nand_chip->legacy.write_buf = tmio_nand_write_buf;
        nand_chip->legacy.read_buf = tmio_nand_read_buf;
 
-       /* set eccmode using hardware ECC */
-       nand_chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
-       nand_chip->ecc.size = 512;
-       nand_chip->ecc.bytes = 6;
-       nand_chip->ecc.strength = 2;
-       nand_chip->ecc.hwctl = tmio_nand_enable_hwecc;
-       nand_chip->ecc.calculate = tmio_nand_calculate_ecc;
-       nand_chip->ecc.correct = tmio_nand_correct_data;
-
        if (data)
                nand_chip->badblock_pattern = data->badblock_pattern;
 
index ef81dce6b5c4637bdd3924322d1c6aba9579ca75..fe8ed24415885effb69372dfd1f4497d67787421 100644 (file)
@@ -253,6 +253,11 @@ static int txx9ndfmc_attach_chip(struct nand_chip *chip)
 {
        struct mtd_info *mtd = nand_to_mtd(chip);
 
+       if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
+               return 0;
+
+       chip->ecc.strength = 1;
+
        if (mtd->writesize >= 512) {
                chip->ecc.size = 512;
                chip->ecc.bytes = 6;
@@ -261,6 +266,10 @@ static int txx9ndfmc_attach_chip(struct nand_chip *chip)
                chip->ecc.bytes = 3;
        }
 
+       chip->ecc.calculate = txx9ndfmc_calculate_ecc;
+       chip->ecc.correct = txx9ndfmc_correct_data;
+       chip->ecc.hwctl = txx9ndfmc_enable_hwecc;
+
        return 0;
 }
 
@@ -326,11 +335,6 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
                chip->legacy.write_buf = txx9ndfmc_write_buf;
                chip->legacy.cmd_ctrl = txx9ndfmc_cmd_ctrl;
                chip->legacy.dev_ready = txx9ndfmc_dev_ready;
-               chip->ecc.calculate = txx9ndfmc_calculate_ecc;
-               chip->ecc.correct = txx9ndfmc_correct_data;
-               chip->ecc.hwctl = txx9ndfmc_enable_hwecc;
-               chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
-               chip->ecc.strength = 1;
                chip->legacy.chip_delay = 100;
                chip->controller = &drvdata->controller;
 
index f2dbd63a5c1f1a000b7d85857c73d5146be2cae1..efc5bf5434e00ea25592a6aa97d42f1d9599ec57 100644 (file)
@@ -62,6 +62,7 @@
 #define NAND_CON_NANDM         1
 
 struct xway_nand_data {
+       struct nand_controller  controller;
        struct nand_chip        chip;
        unsigned long           csflags;
        void __iomem            *nandaddr;
@@ -145,6 +146,18 @@ static void xway_write_buf(struct nand_chip *chip, const u_char *buf, int len)
                xway_writeb(nand_to_mtd(chip), NAND_WRITE_DATA, buf[i]);
 }
 
+static int xway_attach_chip(struct nand_chip *chip)
+{
+       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
+       chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
+
+       return 0;
+}
+
+static const struct nand_controller_ops xway_nand_ops = {
+       .attach_chip = xway_attach_chip,
+};
+
 /*
  * Probe for the NAND device.
  */
@@ -180,8 +193,9 @@ static int xway_nand_probe(struct platform_device *pdev)
        data->chip.legacy.read_byte = xway_read_byte;
        data->chip.legacy.chip_delay = 30;
 
-       data->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
-       data->chip.ecc.algo = NAND_ECC_ALGO_HAMMING;
+       nand_controller_init(&data->controller);
+       data->controller.ops = &xway_nand_ops;
+       data->chip.controller = &data->controller;
 
        platform_set_drvdata(pdev, data);
        nand_set_controller_data(&data->chip, data);
index 0369d98b2d12efe0757196ee651a6e107f1cbeba..f0ae7a01703a1d7ac6d3ee699320360253b20577 100644 (file)
@@ -2701,11 +2701,10 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
 
        memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
 
-       if (spi_nor_parse_sfdp(nor, &sfdp_params)) {
+       if (spi_nor_parse_sfdp(nor, nor->params)) {
+               memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
                nor->addr_width = 0;
                nor->flags &= ~SNOR_F_4B_OPCODES;
-       } else {
-               memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
        }
 }
 
@@ -3009,13 +3008,15 @@ static int spi_nor_set_addr_width(struct spi_nor *nor)
                /* already configured from SFDP */
        } else if (nor->info->addr_width) {
                nor->addr_width = nor->info->addr_width;
-       } else if (nor->mtd.size > 0x1000000) {
-               /* enable 4-byte addressing if the device exceeds 16MiB */
-               nor->addr_width = 4;
        } else {
                nor->addr_width = 3;
        }
 
+       if (nor->addr_width == 3 && nor->mtd.size > 0x1000000) {
+               /* enable 4-byte addressing if the device exceeds 16MiB */
+               nor->addr_width = 4;
+       }
+
        if (nor->addr_width > SPI_NOR_MAX_ADDR_WIDTH) {
                dev_dbg(nor->dev, "address width is too large: %u\n",
                        nor->addr_width);
index 84ecbc6fa0ff219f8aa8380f49e4112df5596467..47afc5938c26bcab92726af762efd95bdc066db7 100644 (file)
@@ -1460,7 +1460,39 @@ static void bond_upper_dev_unlink(struct bonding *bond, struct slave *slave)
        slave->dev->flags &= ~IFF_SLAVE;
 }
 
-static struct slave *bond_alloc_slave(struct bonding *bond)
+static void slave_kobj_release(struct kobject *kobj)
+{
+       struct slave *slave = to_slave(kobj);
+       struct bonding *bond = bond_get_bond_by_slave(slave);
+
+       cancel_delayed_work_sync(&slave->notify_work);
+       if (BOND_MODE(bond) == BOND_MODE_8023AD)
+               kfree(SLAVE_AD_INFO(slave));
+
+       kfree(slave);
+}
+
+static struct kobj_type slave_ktype = {
+       .release = slave_kobj_release,
+#ifdef CONFIG_SYSFS
+       .sysfs_ops = &slave_sysfs_ops,
+#endif
+};
+
+static int bond_kobj_init(struct slave *slave)
+{
+       int err;
+
+       err = kobject_init_and_add(&slave->kobj, &slave_ktype,
+                                  &(slave->dev->dev.kobj), "bonding_slave");
+       if (err)
+               kobject_put(&slave->kobj);
+
+       return err;
+}
+
+static struct slave *bond_alloc_slave(struct bonding *bond,
+                                     struct net_device *slave_dev)
 {
        struct slave *slave = NULL;
 
@@ -1468,11 +1500,17 @@ static struct slave *bond_alloc_slave(struct bonding *bond)
        if (!slave)
                return NULL;
 
+       slave->bond = bond;
+       slave->dev = slave_dev;
+
+       if (bond_kobj_init(slave))
+               return NULL;
+
        if (BOND_MODE(bond) == BOND_MODE_8023AD) {
                SLAVE_AD_INFO(slave) = kzalloc(sizeof(struct ad_slave_info),
                                               GFP_KERNEL);
                if (!SLAVE_AD_INFO(slave)) {
-                       kfree(slave);
+                       kobject_put(&slave->kobj);
                        return NULL;
                }
        }
@@ -1481,17 +1519,6 @@ static struct slave *bond_alloc_slave(struct bonding *bond)
        return slave;
 }
 
-static void bond_free_slave(struct slave *slave)
-{
-       struct bonding *bond = bond_get_bond_by_slave(slave);
-
-       cancel_delayed_work_sync(&slave->notify_work);
-       if (BOND_MODE(bond) == BOND_MODE_8023AD)
-               kfree(SLAVE_AD_INFO(slave));
-
-       kfree(slave);
-}
-
 static void bond_fill_ifbond(struct bonding *bond, struct ifbond *info)
 {
        info->bond_mode = BOND_MODE(bond);
@@ -1678,14 +1705,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
                        goto err_undo_flags;
        }
 
-       new_slave = bond_alloc_slave(bond);
+       new_slave = bond_alloc_slave(bond, slave_dev);
        if (!new_slave) {
                res = -ENOMEM;
                goto err_undo_flags;
        }
 
-       new_slave->bond = bond;
-       new_slave->dev = slave_dev;
        /* Set the new_slave's queue_id to be zero.  Queue ID mapping
         * is set via sysfs or module option if desired.
         */
@@ -2007,7 +2032,7 @@ err_restore_mtu:
        dev_set_mtu(slave_dev, new_slave->original_mtu);
 
 err_free:
-       bond_free_slave(new_slave);
+       kobject_put(&new_slave->kobj);
 
 err_undo_flags:
        /* Enslave of first slave has failed and we need to fix master's mac */
@@ -2187,7 +2212,7 @@ static int __bond_release_one(struct net_device *bond_dev,
        if (!netif_is_bond_master(slave_dev))
                slave_dev->priv_flags &= ~IFF_BONDING;
 
-       bond_free_slave(slave);
+       kobject_put(&slave->kobj);
 
        return 0;
 }
index 9b8346638f697199a5bf953475d660bcf07e1fc8..fd07561da0348abdaf7f7d9d06e061c4d5361db2 100644 (file)
@@ -121,7 +121,6 @@ static const struct slave_attribute *slave_attrs[] = {
 };
 
 #define to_slave_attr(_at) container_of(_at, struct slave_attribute, attr)
-#define to_slave(obj)  container_of(obj, struct slave, kobj)
 
 static ssize_t slave_show(struct kobject *kobj,
                          struct attribute *attr, char *buf)
@@ -132,28 +131,15 @@ static ssize_t slave_show(struct kobject *kobj,
        return slave_attr->show(slave, buf);
 }
 
-static const struct sysfs_ops slave_sysfs_ops = {
+const struct sysfs_ops slave_sysfs_ops = {
        .show = slave_show,
 };
 
-static struct kobj_type slave_ktype = {
-#ifdef CONFIG_SYSFS
-       .sysfs_ops = &slave_sysfs_ops,
-#endif
-};
-
 int bond_sysfs_slave_add(struct slave *slave)
 {
        const struct slave_attribute **a;
        int err;
 
-       err = kobject_init_and_add(&slave->kobj, &slave_ktype,
-                                  &(slave->dev->dev.kobj), "bonding_slave");
-       if (err) {
-               kobject_put(&slave->kobj);
-               return err;
-       }
-
        for (a = slave_attrs; *a; ++a) {
                err = sysfs_create_file(&slave->kobj, &((*a)->attr));
                if (err) {
@@ -171,6 +157,4 @@ void bond_sysfs_slave_del(struct slave *slave)
 
        for (a = slave_attrs; *a; ++a)
                sysfs_remove_file(&slave->kobj, &((*a)->attr));
-
-       kobject_put(&slave->kobj);
 }
index 1ccdbe89585b2bdd1b95da4a438a722dc24b1480..1a9e9b9a4bf6c747019ab76e992d2b90c04d64e1 100644 (file)
@@ -1295,12 +1295,22 @@ int c_can_power_up(struct net_device *dev)
                                time_after(time_out, jiffies))
                cpu_relax();
 
-       if (time_after(jiffies, time_out))
-               return -ETIMEDOUT;
+       if (time_after(jiffies, time_out)) {
+               ret = -ETIMEDOUT;
+               goto err_out;
+       }
 
        ret = c_can_start(dev);
-       if (!ret)
-               c_can_irq_control(priv, true);
+       if (ret)
+               goto err_out;
+
+       c_can_irq_control(priv, true);
+
+       return 0;
+
+err_out:
+       c_can_reset_ram(priv, false);
+       c_can_pm_runtime_put_sync(priv);
 
        return ret;
 }
index b70ded3760f28cdb65d9372b4b0cf26f3afdc567..81e39d7507d8fa68d45e6e7fd9a570f23706bbe6 100644 (file)
@@ -512,9 +512,13 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
                 */
                struct sk_buff *skb = priv->echo_skb[idx];
                struct canfd_frame *cf = (struct canfd_frame *)skb->data;
-               u8 len = cf->len;
 
-               *len_ptr = len;
+               /* get the real payload length for netdev statistics */
+               if (cf->can_id & CAN_RTR_FLAG)
+                       *len_ptr = 0;
+               else
+                       *len_ptr = cf->len;
+
                priv->echo_skb[idx] = NULL;
 
                return skb;
@@ -538,7 +542,11 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
        if (!skb)
                return 0;
 
-       netif_rx(skb);
+       skb_get(skb);
+       if (netif_rx(skb) == NET_RX_SUCCESS)
+               dev_consume_skb_any(skb);
+       else
+               dev_kfree_skb_any(skb);
 
        return len;
 }
@@ -584,7 +592,7 @@ static void can_restart(struct net_device *dev)
 
        cf->can_id |= CAN_ERR_RESTARTED;
 
-       netif_rx(skb);
+       netif_rx_ni(skb);
 
        stats->rx_packets++;
        stats->rx_bytes += cf->can_dlc;
index 4d594e9774972b07fc414961494f67c491472a14..99e5f272205d33bb4dabc9695db1e8adc85c9f47 100644 (file)
  *   MX8MP FlexCAN3  03.00.17.01    yes       yes        no      yes       yes          yes
  *   VF610 FlexCAN3  ?               no       yes        no      yes       yes?          no
  * LS1021A FlexCAN2  03.00.04.00     no       yes        no       no       yes           no
- * LX2160A FlexCAN3  03.00.23.00     no       yes        no       no       yes          yes
+ * LX2160A FlexCAN3  03.00.23.00     no       yes        no      yes       yes          yes
  *
  * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
  */
@@ -400,19 +400,19 @@ static struct flexcan_devtype_data fsl_imx8mp_devtype_data = {
 static const struct flexcan_devtype_data fsl_vf610_devtype_data = {
        .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
                FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP |
-               FLEXCAN_QUIRK_BROKEN_PERR_STATE,
+               FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_SUPPORT_ECC,
 };
 
 static const struct flexcan_devtype_data fsl_ls1021a_r2_devtype_data = {
        .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
-               FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_BROKEN_PERR_STATE |
-               FLEXCAN_QUIRK_USE_OFF_TIMESTAMP,
+               FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP,
 };
 
 static const struct flexcan_devtype_data fsl_lx2160a_r1_devtype_data = {
        .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
                FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_BROKEN_PERR_STATE |
-               FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_SUPPORT_FD,
+               FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_SUPPORT_FD |
+               FLEXCAN_QUIRK_SUPPORT_ECC,
 };
 
 static const struct can_bittiming_const flexcan_bittiming_const = {
@@ -728,8 +728,10 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
        int err;
 
        err = pm_runtime_get_sync(priv->dev);
-       if (err < 0)
+       if (err < 0) {
+               pm_runtime_put_noidle(priv->dev);
                return err;
+       }
 
        err = __flexcan_get_berr_counter(dev, bec);
 
@@ -1565,14 +1567,10 @@ static int flexcan_chip_start(struct net_device *dev)
                priv->write(reg_ctrl2, &regs->ctrl2);
        }
 
-       err = flexcan_transceiver_enable(priv);
-       if (err)
-               goto out_chip_disable;
-
        /* synchronize with the can bus */
        err = flexcan_chip_unfreeze(priv);
        if (err)
-               goto out_transceiver_disable;
+               goto out_chip_disable;
 
        priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
@@ -1590,8 +1588,6 @@ static int flexcan_chip_start(struct net_device *dev)
 
        return 0;
 
- out_transceiver_disable:
-       flexcan_transceiver_disable(priv);
  out_chip_disable:
        flexcan_chip_disable(priv);
        return err;
@@ -1621,7 +1617,6 @@ static int __flexcan_chip_stop(struct net_device *dev, bool disable_on_error)
        priv->write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
                    &regs->ctrl);
 
-       flexcan_transceiver_disable(priv);
        priv->can.state = CAN_STATE_STOPPED;
 
        return 0;
@@ -1654,17 +1649,23 @@ static int flexcan_open(struct net_device *dev)
        }
 
        err = pm_runtime_get_sync(priv->dev);
-       if (err < 0)
+       if (err < 0) {
+               pm_runtime_put_noidle(priv->dev);
                return err;
+       }
 
        err = open_candev(dev);
        if (err)
                goto out_runtime_put;
 
-       err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
+       err = flexcan_transceiver_enable(priv);
        if (err)
                goto out_close;
 
+       err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
+       if (err)
+               goto out_transceiver_disable;
+
        if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
                priv->mb_size = sizeof(struct flexcan_mb) + CANFD_MAX_DLEN;
        else
@@ -1716,6 +1717,8 @@ static int flexcan_open(struct net_device *dev)
        can_rx_offload_del(&priv->offload);
  out_free_irq:
        free_irq(dev->irq, dev);
+ out_transceiver_disable:
+       flexcan_transceiver_disable(priv);
  out_close:
        close_candev(dev);
  out_runtime_put:
@@ -1734,6 +1737,7 @@ static int flexcan_close(struct net_device *dev)
 
        can_rx_offload_del(&priv->offload);
        free_irq(dev->irq, dev);
+       flexcan_transceiver_disable(priv);
 
        close_candev(dev);
        pm_runtime_put(priv->dev);
@@ -1852,7 +1856,7 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
                return -EINVAL;
 
        /* stop mode property format is:
-        * <&gpr req_gpr>.
+        * <&gpr req_gpr req_bit>.
         */
        ret = of_property_read_u32_array(np, "fsl,stop-mode", out_val,
                                         ARRAY_SIZE(out_val));
@@ -2062,6 +2066,8 @@ static int flexcan_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
 
+       device_set_wakeup_enable(&pdev->dev, false);
+       device_set_wakeup_capable(&pdev->dev, false);
        unregister_flexcandev(dev);
        pm_runtime_disable(&pdev->dev);
        free_candev(dev);
index 6f766918211a463191ae45d80260875cf92edf5d..43151dd6cb1c39c9e7d83b04c72ed4f1def945a0 100644 (file)
@@ -287,12 +287,12 @@ struct kvaser_pciefd_tx_packet {
 static const struct can_bittiming_const kvaser_pciefd_bittiming_const = {
        .name = KVASER_PCIEFD_DRV_NAME,
        .tseg1_min = 1,
-       .tseg1_max = 255,
+       .tseg1_max = 512,
        .tseg2_min = 1,
        .tseg2_max = 32,
        .sjw_max = 16,
        .brp_min = 1,
-       .brp_max = 4096,
+       .brp_max = 8192,
        .brp_inc = 1,
 };
 
@@ -692,8 +692,10 @@ static int kvaser_pciefd_open(struct net_device *netdev)
                return err;
 
        err = kvaser_pciefd_bus_on(can);
-       if (err)
+       if (err) {
+               close_candev(netdev);
                return err;
+       }
 
        return 0;
 }
index 48be627c85c28549982ace9fb350a5df21403052..5f9f8192dd0b2475ecb13ed201b018d271264a17 100644 (file)
@@ -16,7 +16,8 @@ config CAN_M_CAN_PLATFORM
 
 config CAN_M_CAN_TCAN4X5X
        depends on CAN_M_CAN
-       depends on REGMAP_SPI
+       depends on SPI
+       select REGMAP_SPI
        tristate "TCAN4X5X M_CAN device"
        help
          Say Y here if you want support for Texas Instruments TCAN4x5x
index 02c5795b739366712b9df899167092f1a09ad25e..61a93b19203799a71c07cf73a78309f12118ef4b 100644 (file)
@@ -665,7 +665,7 @@ static int m_can_handle_state_change(struct net_device *dev,
        unsigned int ecr;
 
        switch (new_state) {
-       case CAN_STATE_ERROR_ACTIVE:
+       case CAN_STATE_ERROR_WARNING:
                /* error warning state */
                cdev->can.can_stats.error_warning++;
                cdev->can.state = CAN_STATE_ERROR_WARNING;
@@ -694,7 +694,7 @@ static int m_can_handle_state_change(struct net_device *dev,
        __m_can_get_berr_counter(dev, &bec);
 
        switch (new_state) {
-       case CAN_STATE_ERROR_ACTIVE:
+       case CAN_STATE_ERROR_WARNING:
                /* error warning state */
                cf->can_id |= CAN_ERR_CRTL;
                cf->data[1] = (bec.txerr > bec.rxerr) ?
@@ -956,6 +956,8 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
        struct net_device_stats *stats = &dev->stats;
        u32 ir;
 
+       if (pm_runtime_suspended(cdev->dev))
+               return IRQ_NONE;
        ir = m_can_read(cdev, M_CAN_IR);
        if (!ir)
                return IRQ_NONE;
@@ -1031,7 +1033,7 @@ static const struct can_bittiming_const m_can_bittiming_const_31X = {
        .name = KBUILD_MODNAME,
        .tseg1_min = 2,         /* Time segment 1 = prop_seg + phase_seg1 */
        .tseg1_max = 256,
-       .tseg2_min = 1,         /* Time segment 2 = phase_seg2 */
+       .tseg2_min = 2,         /* Time segment 2 = phase_seg2 */
        .tseg2_max = 128,
        .sjw_max = 128,
        .brp_min = 1,
@@ -1383,6 +1385,8 @@ static int m_can_dev_setup(struct m_can_classdev *m_can_dev)
                                                &m_can_data_bittiming_const_31X;
                break;
        case 32:
+       case 33:
+               /* Support both MCAN version v3.2.x and v3.3.0 */
                m_can_dev->can.bittiming_const = m_can_dev->bit_timing ?
                        m_can_dev->bit_timing : &m_can_bittiming_const_31X;
 
@@ -1414,6 +1418,9 @@ static void m_can_stop(struct net_device *dev)
        /* disable all interrupts */
        m_can_disable_all_interrupts(cdev);
 
+       /* Set init mode to disengage from the network */
+       m_can_config_endisable(cdev, true);
+
        /* set the state as STOPPED */
        cdev->can.state = CAN_STATE_STOPPED;
 }
@@ -1648,7 +1655,7 @@ static int m_can_open(struct net_device *dev)
                INIT_WORK(&cdev->tx_work, m_can_tx_work_queue);
 
                err = request_threaded_irq(dev->irq, NULL, m_can_isr,
-                                          IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
+                                          IRQF_ONESHOT,
                                           dev->name, dev);
        } else {
                err = request_irq(dev->irq, m_can_isr, IRQF_SHARED, dev->name,
@@ -1812,6 +1819,12 @@ out:
 }
 EXPORT_SYMBOL_GPL(m_can_class_allocate_dev);
 
+void m_can_class_free_dev(struct net_device *net)
+{
+       free_candev(net);
+}
+EXPORT_SYMBOL_GPL(m_can_class_free_dev);
+
 int m_can_class_register(struct m_can_classdev *m_can_dev)
 {
        int ret;
@@ -1850,7 +1863,6 @@ pm_runtime_fail:
        if (ret) {
                if (m_can_dev->pm_clock_support)
                        pm_runtime_disable(m_can_dev->dev);
-               free_candev(m_can_dev->net);
        }
 
        return ret;
@@ -1908,8 +1920,6 @@ void m_can_class_unregister(struct m_can_classdev *m_can_dev)
        unregister_candev(m_can_dev->net);
 
        m_can_clk_stop(m_can_dev);
-
-       free_candev(m_can_dev->net);
 }
 EXPORT_SYMBOL_GPL(m_can_class_unregister);
 
index 49f42b50627a1c3111d3f436a5198c3dbff057b7..b2699a7c99973516cd2ee1dbf3609884a58404a8 100644 (file)
@@ -99,6 +99,7 @@ struct m_can_classdev {
 };
 
 struct m_can_classdev *m_can_class_allocate_dev(struct device *dev);
+void m_can_class_free_dev(struct net_device *net);
 int m_can_class_register(struct m_can_classdev *cdev);
 void m_can_class_unregister(struct m_can_classdev *cdev);
 int m_can_class_get_clocks(struct m_can_classdev *cdev);
index e6d0cb9ee02f0e1002dc8f3784c2b45daf488a8c..161cb9be018c091362b64b4f3555a553ea25559a 100644 (file)
@@ -67,32 +67,36 @@ static int m_can_plat_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
+       if (!priv) {
+               ret = -ENOMEM;
+               goto probe_fail;
+       }
 
        mcan_class->device_data = priv;
 
-       m_can_class_get_clocks(mcan_class);
+       ret = m_can_class_get_clocks(mcan_class);
+       if (ret)
+               goto probe_fail;
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "m_can");
        addr = devm_ioremap_resource(&pdev->dev, res);
        irq = platform_get_irq_byname(pdev, "int0");
        if (IS_ERR(addr) || irq < 0) {
                ret = -EINVAL;
-               goto failed_ret;
+               goto probe_fail;
        }
 
        /* message ram could be shared */
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram");
        if (!res) {
                ret = -ENODEV;
-               goto failed_ret;
+               goto probe_fail;
        }
 
        mram_addr = devm_ioremap(&pdev->dev, res->start, resource_size(res));
        if (!mram_addr) {
                ret = -ENOMEM;
-               goto failed_ret;
+               goto probe_fail;
        }
 
        priv->base = addr;
@@ -111,9 +115,10 @@ static int m_can_plat_probe(struct platform_device *pdev)
 
        m_can_init_ram(mcan_class);
 
-       ret = m_can_class_register(mcan_class);
+       return m_can_class_register(mcan_class);
 
-failed_ret:
+probe_fail:
+       m_can_class_free_dev(mcan_class->net);
        return ret;
 }
 
@@ -134,6 +139,8 @@ static int m_can_plat_remove(struct platform_device *pdev)
 
        m_can_class_unregister(mcan_class);
 
+       m_can_class_free_dev(mcan_class->net);
+
        platform_set_drvdata(pdev, NULL);
 
        return 0;
index eacd428e07e9f32c9c014b877d0d0105d8b4ffc9..7347ab39c5b657db2f3fda0cd2b459ddaf7ecf31 100644 (file)
@@ -440,14 +440,18 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
                return -ENOMEM;
 
        priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
+       if (!priv) {
+               ret = -ENOMEM;
+               goto out_m_can_class_free_dev;
+       }
 
        priv->power = devm_regulator_get_optional(&spi->dev, "vsup");
-       if (PTR_ERR(priv->power) == -EPROBE_DEFER)
-               return -EPROBE_DEFER;
-       else
+       if (PTR_ERR(priv->power) == -EPROBE_DEFER) {
+               ret = -EPROBE_DEFER;
+               goto out_m_can_class_free_dev;
+       } else {
                priv->power = NULL;
+       }
 
        mcan_class->device_data = priv;
 
@@ -460,8 +464,10 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
        }
 
        /* Sanity check */
-       if (freq < 20000000 || freq > TCAN4X5X_EXT_CLK_DEF)
-               return -ERANGE;
+       if (freq < 20000000 || freq > TCAN4X5X_EXT_CLK_DEF) {
+               ret = -ERANGE;
+               goto out_m_can_class_free_dev;
+       }
 
        priv->reg_offset = TCAN4X5X_MCAN_OFFSET;
        priv->mram_start = TCAN4X5X_MRAM_START;
@@ -483,14 +489,18 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
        spi->bits_per_word = 32;
        ret = spi_setup(spi);
        if (ret)
-               goto out_clk;
+               goto out_m_can_class_free_dev;
 
        priv->regmap = devm_regmap_init(&spi->dev, &tcan4x5x_bus,
                                        &spi->dev, &tcan4x5x_regmap);
+       if (IS_ERR(priv->regmap)) {
+               ret = PTR_ERR(priv->regmap);
+               goto out_m_can_class_free_dev;
+       }
 
        ret = tcan4x5x_power_enable(priv->power, 1);
        if (ret)
-               goto out_clk;
+               goto out_m_can_class_free_dev;
 
        ret = tcan4x5x_parse_config(mcan_class);
        if (ret)
@@ -509,13 +519,10 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
 
 out_power:
        tcan4x5x_power_enable(priv->power, 0);
-out_clk:
-       if (!IS_ERR(mcan_class->cclk)) {
-               clk_disable_unprepare(mcan_class->cclk);
-               clk_disable_unprepare(mcan_class->hclk);
-       }
-
+ out_m_can_class_free_dev:
+       m_can_class_free_dev(mcan_class->net);
        dev_err(&spi->dev, "Probe failed, err=%d\n", ret);
+
        return ret;
 }
 
@@ -523,9 +530,11 @@ static int tcan4x5x_can_remove(struct spi_device *spi)
 {
        struct tcan4x5x_priv *priv = spi_get_drvdata(spi);
 
+       m_can_class_unregister(priv->mcan_dev);
+
        tcan4x5x_power_enable(priv->power, 0);
 
-       m_can_class_unregister(priv->mcan_dev);
+       m_can_class_free_dev(priv->mcan_dev->net);
 
        return 0;
 }
index 10aa3e457c33d48fe2055a422c6399b56798b9e3..40c33b8a5fda3af93013c0e524f66d1ba6288907 100644 (file)
@@ -262,8 +262,7 @@ static int pucan_handle_can_rx(struct peak_canfd_priv *priv,
                cf_len = get_can_dlc(pucan_msg_get_dlc(msg));
 
        /* if this frame is an echo, */
-       if ((rx_msg_flags & PUCAN_MSG_LOOPED_BACK) &&
-           !(rx_msg_flags & PUCAN_MSG_SELF_RECEIVE)) {
+       if (rx_msg_flags & PUCAN_MSG_LOOPED_BACK) {
                unsigned long flags;
 
                spin_lock_irqsave(&priv->echo_lock, flags);
@@ -277,7 +276,13 @@ static int pucan_handle_can_rx(struct peak_canfd_priv *priv,
                netif_wake_queue(priv->ndev);
 
                spin_unlock_irqrestore(&priv->echo_lock, flags);
-               return 0;
+
+               /* if this frame is only an echo, stop here. Otherwise,
+                * continue to push this application self-received frame into
+                * its own rx queue.
+                */
+               if (!(rx_msg_flags & PUCAN_MSG_SELF_RECEIVE))
+                       return 0;
        }
 
        /* otherwise, it should be pushed into rx fifo */
index 3b180269a92d944db7e37017e846d16cef0cf2e4..6e95193b215ba4725ced3724ac006cb2acb1986b 100644 (file)
@@ -245,7 +245,7 @@ int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
 
        if (skb_queue_len(&offload->skb_queue) >
            offload->skb_queue_len_max) {
-               kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return -ENOBUFS;
        }
 
@@ -290,7 +290,7 @@ int can_rx_offload_queue_tail(struct can_rx_offload *offload,
 {
        if (skb_queue_len(&offload->skb_queue) >
            offload->skb_queue_len_max) {
-               kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return -ENOBUFS;
        }
 
index 9f107798f904b4e6771930d469b43082419df5d6..25a4d7d0b3498fb0a76bf504c66fd107434d58a7 100644 (file)
@@ -474,7 +474,6 @@ 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++;
-               stats->tx_errors++;
                cf->can_id |= CAN_ERR_LOSTARB;
                cf->data[0] = alc & 0x1f;
        }
index c3f49543ff269546ec9343323fce3cb2b9b44269..8a39be076e143e21634b976e9494d986eec3c054 100644 (file)
@@ -75,11 +75,11 @@ static const char *__mcp251xfd_get_model_str(enum mcp251xfd_model model)
 {
        switch (model) {
        case MCP251XFD_MODEL_MCP2517FD:
-               return "MCP2517FD"; break;
+               return "MCP2517FD";
        case MCP251XFD_MODEL_MCP2518FD:
-               return "MCP2518FD"; break;
+               return "MCP2518FD";
        case MCP251XFD_MODEL_MCP251XFD:
-               return "MCP251xFD"; break;
+               return "MCP251xFD";
        }
 
        return "<unknown>";
@@ -95,21 +95,21 @@ static const char *mcp251xfd_get_mode_str(const u8 mode)
 {
        switch (mode) {
        case MCP251XFD_REG_CON_MODE_MIXED:
-               return "Mixed (CAN FD/CAN 2.0)"; break;
+               return "Mixed (CAN FD/CAN 2.0)";
        case MCP251XFD_REG_CON_MODE_SLEEP:
-               return "Sleep"; break;
+               return "Sleep";
        case MCP251XFD_REG_CON_MODE_INT_LOOPBACK:
-               return "Internal Loopback"; break;
+               return "Internal Loopback";
        case MCP251XFD_REG_CON_MODE_LISTENONLY:
-               return "Listen Only"; break;
+               return "Listen Only";
        case MCP251XFD_REG_CON_MODE_CONFIG:
-               return "Configuration"; break;
+               return "Configuration";
        case MCP251XFD_REG_CON_MODE_EXT_LOOPBACK:
-               return "External Loopback"; break;
+               return "External Loopback";
        case MCP251XFD_REG_CON_MODE_CAN2_0:
-               return "CAN 2.0"; break;
+               return "CAN 2.0";
        case MCP251XFD_REG_CON_MODE_RESTRICTED:
-               return "Restricted Operation"; break;
+               return "Restricted Operation";
        }
 
        return "<unknown>";
@@ -2738,6 +2738,10 @@ static int mcp251xfd_probe(struct spi_device *spi)
        u32 freq;
        int err;
 
+       if (!spi->irq)
+               return dev_err_probe(&spi->dev, -ENXIO,
+                                    "No IRQ specified (maybe node \"interrupts-extended\" in DT missing)!\n");
+
        rx_int = devm_gpiod_get_optional(&spi->dev, "microchip,rx-int",
                                         GPIOD_IN);
        if (PTR_ERR(rx_int) == -EPROBE_DEFER)
index ba25902dd78c7584e6ab93ee4ae59fbc35a71d26..314f868b34658a40e7906a247cf5029084e2c19f 100644 (file)
@@ -173,7 +173,7 @@ mcp251xfd_regmap_nocrc_read(void *context,
                memcpy(&buf_tx->cmd, reg, sizeof(buf_tx->cmd));
                if (MCP251XFD_SANITIZE_SPI)
                        memset(buf_tx->data, 0x0, val_len);
-       };
+       }
 
        err = spi_sync(spi, &msg);
        if (err)
@@ -330,17 +330,17 @@ mcp251xfd_regmap_crc_read(void *context,
                        goto out;
                }
 
-               netdev_dbg(priv->ndev,
-                          "CRC read error at address 0x%04x (length=%zd, data=%*ph, CRC=0x%04x) retrying.\n",
-                          reg, val_len, (int)val_len, buf_rx->data,
-                          get_unaligned_be16(buf_rx->data + val_len));
-       }
-
-       if (err) {
                netdev_info(priv->ndev,
-                           "CRC read error at address 0x%04x (length=%zd, data=%*ph, CRC=0x%04x).\n",
+                           "CRC read error at address 0x%04x (length=%zd, data=%*ph, CRC=0x%04x) retrying.\n",
                            reg, val_len, (int)val_len, buf_rx->data,
                            get_unaligned_be16(buf_rx->data + val_len));
+       }
+
+       if (err) {
+               netdev_err(priv->ndev,
+                          "CRC read error at address 0x%04x (length=%zd, data=%*ph, CRC=0x%04x).\n",
+                          reg, val_len, (int)val_len, buf_rx->data,
+                          get_unaligned_be16(buf_rx->data + val_len));
 
                return err;
        }
index e2c6cf4b2228f0eeb0752a35d54275a7f2acefed..b3f2f4fe5ee041e954ec503dcb014fc19896aba1 100644 (file)
@@ -604,7 +604,6 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
                netdev_dbg(dev, "arbitration lost interrupt\n");
                alc = readl(priv->base + SUN4I_REG_STA_ADDR);
                priv->can.can_stats.arbitration_lost++;
-               stats->tx_errors++;
                if (likely(skb)) {
                        cf->can_id |= CAN_ERR_LOSTARB;
                        cf->data[0] = (alc >> 8) & 0x1f;
index 1d63006c97bcd84a6f4cb0ca77a22d34b2cedb8e..2c22f40e12bdf1b1be927c29b6f11e5587098f98 100644 (file)
@@ -881,7 +881,8 @@ static int ti_hecc_probe(struct platform_device *pdev)
        priv->base = devm_platform_ioremap_resource_byname(pdev, "hecc");
        if (IS_ERR(priv->base)) {
                dev_err(&pdev->dev, "hecc ioremap failed\n");
-               return PTR_ERR(priv->base);
+               err = PTR_ERR(priv->base);
+               goto probe_exit_candev;
        }
 
        /* handle hecc-ram memory */
@@ -889,20 +890,22 @@ static int ti_hecc_probe(struct platform_device *pdev)
                                                               "hecc-ram");
        if (IS_ERR(priv->hecc_ram)) {
                dev_err(&pdev->dev, "hecc-ram ioremap failed\n");
-               return PTR_ERR(priv->hecc_ram);
+               err = PTR_ERR(priv->hecc_ram);
+               goto probe_exit_candev;
        }
 
        /* handle mbx memory */
        priv->mbx = devm_platform_ioremap_resource_byname(pdev, "mbx");
        if (IS_ERR(priv->mbx)) {
                dev_err(&pdev->dev, "mbx ioremap failed\n");
-               return PTR_ERR(priv->mbx);
+               err = PTR_ERR(priv->mbx);
+               goto probe_exit_candev;
        }
 
        irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!irq) {
                dev_err(&pdev->dev, "No irq resource\n");
-               goto probe_exit;
+               goto probe_exit_candev;
        }
 
        priv->ndev = ndev;
@@ -933,7 +936,7 @@ static int ti_hecc_probe(struct platform_device *pdev)
        err = clk_prepare_enable(priv->clk);
        if (err) {
                dev_err(&pdev->dev, "clk_prepare_enable() failed\n");
-               goto probe_exit_clk;
+               goto probe_exit_release_clk;
        }
 
        priv->offload.mailbox_read = ti_hecc_mailbox_read;
@@ -942,7 +945,7 @@ static int ti_hecc_probe(struct platform_device *pdev)
        err = can_rx_offload_add_timestamp(ndev, &priv->offload);
        if (err) {
                dev_err(&pdev->dev, "can_rx_offload_add_timestamp() failed\n");
-               goto probe_exit_clk;
+               goto probe_exit_disable_clk;
        }
 
        err = register_candev(ndev);
@@ -960,11 +963,13 @@ static int ti_hecc_probe(struct platform_device *pdev)
 
 probe_exit_offload:
        can_rx_offload_del(&priv->offload);
-probe_exit_clk:
+probe_exit_disable_clk:
+       clk_disable_unprepare(priv->clk);
+probe_exit_release_clk:
        clk_put(priv->clk);
 probe_exit_candev:
        free_candev(ndev);
-probe_exit:
+
        return err;
 }
 
index 3005157059ca5bf4951ac441fa3b0378b282d715..018ca3b057a3baeb59d460385b464c5faa7b7747 100644 (file)
@@ -63,21 +63,27 @@ enum gs_can_identify_mode {
 };
 
 /* data types passed between host and device */
+
+/* The firmware on the original USB2CAN by Geschwister Schneider
+ * Technologie Entwicklungs- und Vertriebs UG exchanges all data
+ * between the host and the device in host byte order. This is done
+ * with the struct gs_host_config::byte_order member, which is sent
+ * first to indicate the desired byte order.
+ *
+ * The widely used open source firmware candleLight doesn't support
+ * this feature and exchanges the data in little endian byte order.
+ */
 struct gs_host_config {
-       u32 byte_order;
+       __le32 byte_order;
 } __packed;
-/* All data exchanged between host and device is exchanged in host byte order,
- * thanks to the struct gs_host_config byte_order member, which is sent first
- * to indicate the desired byte order.
- */
 
 struct gs_device_config {
        u8 reserved1;
        u8 reserved2;
        u8 reserved3;
        u8 icount;
-       u32 sw_version;
-       u32 hw_version;
+       __le32 sw_version;
+       __le32 hw_version;
 } __packed;
 
 #define GS_CAN_MODE_NORMAL               0
@@ -87,26 +93,26 @@ struct gs_device_config {
 #define GS_CAN_MODE_ONE_SHOT             BIT(3)
 
 struct gs_device_mode {
-       u32 mode;
-       u32 flags;
+       __le32 mode;
+       __le32 flags;
 } __packed;
 
 struct gs_device_state {
-       u32 state;
-       u32 rxerr;
-       u32 txerr;
+       __le32 state;
+       __le32 rxerr;
+       __le32 txerr;
 } __packed;
 
 struct gs_device_bittiming {
-       u32 prop_seg;
-       u32 phase_seg1;
-       u32 phase_seg2;
-       u32 sjw;
-       u32 brp;
+       __le32 prop_seg;
+       __le32 phase_seg1;
+       __le32 phase_seg2;
+       __le32 sjw;
+       __le32 brp;
 } __packed;
 
 struct gs_identify_mode {
-       u32 mode;
+       __le32 mode;
 } __packed;
 
 #define GS_CAN_FEATURE_LISTEN_ONLY      BIT(0)
@@ -117,23 +123,23 @@ struct gs_identify_mode {
 #define GS_CAN_FEATURE_IDENTIFY         BIT(5)
 
 struct gs_device_bt_const {
-       u32 feature;
-       u32 fclk_can;
-       u32 tseg1_min;
-       u32 tseg1_max;
-       u32 tseg2_min;
-       u32 tseg2_max;
-       u32 sjw_max;
-       u32 brp_min;
-       u32 brp_max;
-       u32 brp_inc;
+       __le32 feature;
+       __le32 fclk_can;
+       __le32 tseg1_min;
+       __le32 tseg1_max;
+       __le32 tseg2_min;
+       __le32 tseg2_max;
+       __le32 sjw_max;
+       __le32 brp_min;
+       __le32 brp_max;
+       __le32 brp_inc;
 } __packed;
 
 #define GS_CAN_FLAG_OVERFLOW 1
 
 struct gs_host_frame {
        u32 echo_id;
-       u32 can_id;
+       __le32 can_id;
 
        u8 can_dlc;
        u8 channel;
@@ -329,13 +335,13 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
                if (!skb)
                        return;
 
-               cf->can_id = hf->can_id;
+               cf->can_id = le32_to_cpu(hf->can_id);
 
                cf->can_dlc = get_can_dlc(hf->can_dlc);
                memcpy(cf->data, hf->data, 8);
 
                /* ERROR frames tell us information about the controller */
-               if (hf->can_id & CAN_ERR_FLAG)
+               if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG)
                        gs_update_state(dev, cf);
 
                netdev->stats.rx_packets++;
@@ -418,11 +424,11 @@ static int gs_usb_set_bittiming(struct net_device *netdev)
        if (!dbt)
                return -ENOMEM;
 
-       dbt->prop_seg = bt->prop_seg;
-       dbt->phase_seg1 = bt->phase_seg1;
-       dbt->phase_seg2 = bt->phase_seg2;
-       dbt->sjw = bt->sjw;
-       dbt->brp = bt->brp;
+       dbt->prop_seg = cpu_to_le32(bt->prop_seg);
+       dbt->phase_seg1 = cpu_to_le32(bt->phase_seg1);
+       dbt->phase_seg2 = cpu_to_le32(bt->phase_seg2);
+       dbt->sjw = cpu_to_le32(bt->sjw);
+       dbt->brp = cpu_to_le32(bt->brp);
 
        /* request bit timings */
        rc = usb_control_msg(interface_to_usbdev(intf),
@@ -503,7 +509,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
 
        cf = (struct can_frame *)skb->data;
 
-       hf->can_id = cf->can_id;
+       hf->can_id = cpu_to_le32(cf->can_id);
        hf->can_dlc = cf->can_dlc;
        memcpy(hf->data, cf->data, cf->can_dlc);
 
@@ -573,6 +579,7 @@ static int gs_can_open(struct net_device *netdev)
        int rc, i;
        struct gs_device_mode *dm;
        u32 ctrlmode;
+       u32 flags = 0;
 
        rc = open_candev(netdev);
        if (rc)
@@ -640,24 +647,24 @@ static int gs_can_open(struct net_device *netdev)
 
        /* flags */
        ctrlmode = dev->can.ctrlmode;
-       dm->flags = 0;
 
        if (ctrlmode & CAN_CTRLMODE_LOOPBACK)
-               dm->flags |= GS_CAN_MODE_LOOP_BACK;
+               flags |= GS_CAN_MODE_LOOP_BACK;
        else if (ctrlmode & CAN_CTRLMODE_LISTENONLY)
-               dm->flags |= GS_CAN_MODE_LISTEN_ONLY;
+               flags |= GS_CAN_MODE_LISTEN_ONLY;
 
        /* Controller is not allowed to retry TX
         * this mode is unavailable on atmels uc3c hardware
         */
        if (ctrlmode & CAN_CTRLMODE_ONE_SHOT)
-               dm->flags |= GS_CAN_MODE_ONE_SHOT;
+               flags |= GS_CAN_MODE_ONE_SHOT;
 
        if (ctrlmode & CAN_CTRLMODE_3_SAMPLES)
-               dm->flags |= GS_CAN_MODE_TRIPLE_SAMPLE;
+               flags |= GS_CAN_MODE_TRIPLE_SAMPLE;
 
        /* finally start device */
-       dm->mode = GS_CAN_MODE_START;
+       dm->mode = cpu_to_le32(GS_CAN_MODE_START);
+       dm->flags = cpu_to_le32(flags);
        rc = usb_control_msg(interface_to_usbdev(dev->iface),
                             usb_sndctrlpipe(interface_to_usbdev(dev->iface), 0),
                             GS_USB_BREQ_MODE,
@@ -737,9 +744,9 @@ static int gs_usb_set_identify(struct net_device *netdev, bool do_identify)
                return -ENOMEM;
 
        if (do_identify)
-               imode->mode = GS_CAN_IDENTIFY_ON;
+               imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_ON);
        else
-               imode->mode = GS_CAN_IDENTIFY_OFF;
+               imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_OFF);
 
        rc = usb_control_msg(interface_to_usbdev(dev->iface),
                             usb_sndctrlpipe(interface_to_usbdev(dev->iface),
@@ -790,6 +797,7 @@ static struct gs_can *gs_make_candev(unsigned int channel,
        struct net_device *netdev;
        int rc;
        struct gs_device_bt_const *bt_const;
+       u32 feature;
 
        bt_const = kmalloc(sizeof(*bt_const), GFP_KERNEL);
        if (!bt_const)
@@ -830,14 +838,14 @@ static struct gs_can *gs_make_candev(unsigned int channel,
 
        /* dev setup */
        strcpy(dev->bt_const.name, "gs_usb");
-       dev->bt_const.tseg1_min = bt_const->tseg1_min;
-       dev->bt_const.tseg1_max = bt_const->tseg1_max;
-       dev->bt_const.tseg2_min = bt_const->tseg2_min;
-       dev->bt_const.tseg2_max = bt_const->tseg2_max;
-       dev->bt_const.sjw_max = bt_const->sjw_max;
-       dev->bt_const.brp_min = bt_const->brp_min;
-       dev->bt_const.brp_max = bt_const->brp_max;
-       dev->bt_const.brp_inc = bt_const->brp_inc;
+       dev->bt_const.tseg1_min = le32_to_cpu(bt_const->tseg1_min);
+       dev->bt_const.tseg1_max = le32_to_cpu(bt_const->tseg1_max);
+       dev->bt_const.tseg2_min = le32_to_cpu(bt_const->tseg2_min);
+       dev->bt_const.tseg2_max = le32_to_cpu(bt_const->tseg2_max);
+       dev->bt_const.sjw_max = le32_to_cpu(bt_const->sjw_max);
+       dev->bt_const.brp_min = le32_to_cpu(bt_const->brp_min);
+       dev->bt_const.brp_max = le32_to_cpu(bt_const->brp_max);
+       dev->bt_const.brp_inc = le32_to_cpu(bt_const->brp_inc);
 
        dev->udev = interface_to_usbdev(intf);
        dev->iface = intf;
@@ -854,28 +862,29 @@ static struct gs_can *gs_make_candev(unsigned int channel,
 
        /* can setup */
        dev->can.state = CAN_STATE_STOPPED;
-       dev->can.clock.freq = bt_const->fclk_can;
+       dev->can.clock.freq = le32_to_cpu(bt_const->fclk_can);
        dev->can.bittiming_const = &dev->bt_const;
        dev->can.do_set_bittiming = gs_usb_set_bittiming;
 
        dev->can.ctrlmode_supported = 0;
 
-       if (bt_const->feature & GS_CAN_FEATURE_LISTEN_ONLY)
+       feature = le32_to_cpu(bt_const->feature);
+       if (feature & GS_CAN_FEATURE_LISTEN_ONLY)
                dev->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
 
-       if (bt_const->feature & GS_CAN_FEATURE_LOOP_BACK)
+       if (feature & GS_CAN_FEATURE_LOOP_BACK)
                dev->can.ctrlmode_supported |= CAN_CTRLMODE_LOOPBACK;
 
-       if (bt_const->feature & GS_CAN_FEATURE_TRIPLE_SAMPLE)
+       if (feature & GS_CAN_FEATURE_TRIPLE_SAMPLE)
                dev->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
 
-       if (bt_const->feature & GS_CAN_FEATURE_ONE_SHOT)
+       if (feature & GS_CAN_FEATURE_ONE_SHOT)
                dev->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT;
 
        SET_NETDEV_DEV(netdev, &intf->dev);
 
-       if (dconf->sw_version > 1)
-               if (bt_const->feature & GS_CAN_FEATURE_IDENTIFY)
+       if (le32_to_cpu(dconf->sw_version) > 1)
+               if (feature & GS_CAN_FEATURE_IDENTIFY)
                        netdev->ethtool_ops = &gs_usb_ethtool_ops;
 
        kfree(bt_const);
@@ -910,7 +919,7 @@ static int gs_usb_probe(struct usb_interface *intf,
        if (!hconf)
                return -ENOMEM;
 
-       hconf->byte_order = 0x0000beef;
+       hconf->byte_order = cpu_to_le32(0x0000beef);
 
        /* send host config */
        rc = usb_control_msg(interface_to_usbdev(intf),
index 7ab87a758754543a189672ad886ce8dbda2f19e3..218fadc9115583080f673335ec737d28143d7356 100644 (file)
@@ -367,7 +367,7 @@ static const struct can_bittiming_const kvaser_usb_hydra_kcan_bittiming_c = {
        .tseg2_max = 32,
        .sjw_max = 16,
        .brp_min = 1,
-       .brp_max = 4096,
+       .brp_max = 8192,
        .brp_inc = 1,
 };
 
index 5857b37dcd964d52acb861ba261dc9bdb01345ed..e97f2e0da6b07a64bcbd5dacec58812fd87bccbd 100644 (file)
@@ -326,8 +326,6 @@ static netdev_tx_t mcba_usb_start_xmit(struct sk_buff *skb,
        if (!ctx)
                return NETDEV_TX_BUSY;
 
-       can_put_echo_skb(skb, priv->netdev, ctx->ndx);
-
        if (cf->can_id & CAN_EFF_FLAG) {
                /* SIDH    | SIDL                 | EIDH   | EIDL
                 * 28 - 21 | 20 19 18 x x x 17 16 | 15 - 8 | 7 - 0
@@ -357,6 +355,8 @@ static netdev_tx_t mcba_usb_start_xmit(struct sk_buff *skb,
        if (cf->can_id & CAN_RTR_FLAG)
                usb_msg.dlc |= MCBA_DLC_RTR_MASK;
 
+       can_put_echo_skb(skb, priv->netdev, ctx->ndx);
+
        err = mcba_usb_xmit(priv, (struct mcba_usb_msg *)&usb_msg, ctx);
        if (err)
                goto xmit_failed;
index d91df34e7fa8800f6931e7d4dade99c05a62dea4..204ccb27d6d9a694ec4d4625e3dcb8d986ca1b73 100644 (file)
@@ -130,14 +130,55 @@ void peak_usb_get_ts_time(struct peak_time_ref *time_ref, u32 ts, ktime_t *time)
        /* protect from getting time before setting now */
        if (ktime_to_ns(time_ref->tv_host)) {
                u64 delta_us;
+               s64 delta_ts = 0;
+
+               /* General case: dev_ts_1 < dev_ts_2 < ts, with:
+                *
+                * - dev_ts_1 = previous sync timestamp
+                * - dev_ts_2 = last sync timestamp
+                * - ts = event timestamp
+                * - ts_period = known sync period (theoretical)
+                *             ~ dev_ts2 - dev_ts1
+                * *but*:
+                *
+                * - time counters wrap (see adapter->ts_used_bits)
+                * - sometimes, dev_ts_1 < ts < dev_ts2
+                *
+                * "normal" case (sync time counters increase):
+                * must take into account case when ts wraps (tsw)
+                *
+                *      < ts_period > <          >
+                *     |             |            |
+                *  ---+--------+----+-------0-+--+-->
+                *     ts_dev_1 |    ts_dev_2  |
+                *              ts             tsw
+                */
+               if (time_ref->ts_dev_1 < time_ref->ts_dev_2) {
+                       /* case when event time (tsw) wraps */
+                       if (ts < time_ref->ts_dev_1)
+                               delta_ts = BIT_ULL(time_ref->adapter->ts_used_bits);
+
+               /* Otherwise, sync time counter (ts_dev_2) has wrapped:
+                * handle case when event time (tsn) hasn't.
+                *
+                *      < ts_period > <          >
+                *     |             |            |
+                *  ---+--------+--0-+---------+--+-->
+                *     ts_dev_1 |    ts_dev_2  |
+                *              tsn            ts
+                */
+               } else if (time_ref->ts_dev_1 < ts) {
+                       delta_ts = -BIT_ULL(time_ref->adapter->ts_used_bits);
+               }
 
-               delta_us = ts - time_ref->ts_dev_2;
-               if (ts < time_ref->ts_dev_2)
-                       delta_us &= (1 << time_ref->adapter->ts_used_bits) - 1;
+               /* add delay between last sync and event timestamps */
+               delta_ts += (signed int)(ts - time_ref->ts_dev_2);
 
-               delta_us += time_ref->ts_total;
+               /* add time from beginning to last sync */
+               delta_ts += time_ref->ts_total;
 
-               delta_us *= time_ref->adapter->us_per_ts_scale;
+               /* convert ticks number into microseconds */
+               delta_us = delta_ts * time_ref->adapter->us_per_ts_scale;
                delta_us >>= time_ref->adapter->us_per_ts_shift;
 
                *time = ktime_add_us(time_ref->tv_host_0, delta_us);
index ab63fd9eb982df5c30e7fd12a04de59a52379a04..d29d20525588c621a80c2afbc56d8c0be48a4faa 100644 (file)
@@ -468,12 +468,18 @@ static int pcan_usb_fd_decode_canmsg(struct pcan_usb_fd_if *usb_if,
                                     struct pucan_msg *rx_msg)
 {
        struct pucan_rx_msg *rm = (struct pucan_rx_msg *)rx_msg;
-       struct peak_usb_device *dev = usb_if->dev[pucan_msg_get_channel(rm)];
-       struct net_device *netdev = dev->netdev;
+       struct peak_usb_device *dev;
+       struct net_device *netdev;
        struct canfd_frame *cfd;
        struct sk_buff *skb;
        const u16 rx_msg_flags = le16_to_cpu(rm->flags);
 
+       if (pucan_msg_get_channel(rm) >= ARRAY_SIZE(usb_if->dev))
+               return -ENOMEM;
+
+       dev = usb_if->dev[pucan_msg_get_channel(rm)];
+       netdev = dev->netdev;
+
        if (rx_msg_flags & PUCAN_MSG_EXT_DATA_LEN) {
                /* CANFD frame case */
                skb = alloc_canfd_skb(netdev, &cfd);
@@ -519,15 +525,21 @@ static int pcan_usb_fd_decode_status(struct pcan_usb_fd_if *usb_if,
                                     struct pucan_msg *rx_msg)
 {
        struct pucan_status_msg *sm = (struct pucan_status_msg *)rx_msg;
-       struct peak_usb_device *dev = usb_if->dev[pucan_stmsg_get_channel(sm)];
-       struct pcan_usb_fd_device *pdev =
-                       container_of(dev, struct pcan_usb_fd_device, dev);
+       struct pcan_usb_fd_device *pdev;
        enum can_state new_state = CAN_STATE_ERROR_ACTIVE;
        enum can_state rx_state, tx_state;
-       struct net_device *netdev = dev->netdev;
+       struct peak_usb_device *dev;
+       struct net_device *netdev;
        struct can_frame *cf;
        struct sk_buff *skb;
 
+       if (pucan_stmsg_get_channel(sm) >= ARRAY_SIZE(usb_if->dev))
+               return -ENOMEM;
+
+       dev = usb_if->dev[pucan_stmsg_get_channel(sm)];
+       pdev = container_of(dev, struct pcan_usb_fd_device, dev);
+       netdev = dev->netdev;
+
        /* nothing should be sent while in BUS_OFF state */
        if (dev->can.state == CAN_STATE_BUS_OFF)
                return 0;
@@ -579,9 +591,14 @@ static int pcan_usb_fd_decode_error(struct pcan_usb_fd_if *usb_if,
                                    struct pucan_msg *rx_msg)
 {
        struct pucan_error_msg *er = (struct pucan_error_msg *)rx_msg;
-       struct peak_usb_device *dev = usb_if->dev[pucan_ermsg_get_channel(er)];
-       struct pcan_usb_fd_device *pdev =
-                       container_of(dev, struct pcan_usb_fd_device, dev);
+       struct pcan_usb_fd_device *pdev;
+       struct peak_usb_device *dev;
+
+       if (pucan_ermsg_get_channel(er) >= ARRAY_SIZE(usb_if->dev))
+               return -EINVAL;
+
+       dev = usb_if->dev[pucan_ermsg_get_channel(er)];
+       pdev = container_of(dev, struct pcan_usb_fd_device, dev);
 
        /* keep a trace of tx and rx error counters for later use */
        pdev->bec.txerr = er->tx_err_cnt;
@@ -595,11 +612,17 @@ static int pcan_usb_fd_decode_overrun(struct pcan_usb_fd_if *usb_if,
                                      struct pucan_msg *rx_msg)
 {
        struct pcan_ufd_ovr_msg *ov = (struct pcan_ufd_ovr_msg *)rx_msg;
-       struct peak_usb_device *dev = usb_if->dev[pufd_omsg_get_channel(ov)];
-       struct net_device *netdev = dev->netdev;
+       struct peak_usb_device *dev;
+       struct net_device *netdev;
        struct can_frame *cf;
        struct sk_buff *skb;
 
+       if (pufd_omsg_get_channel(ov) >= ARRAY_SIZE(usb_if->dev))
+               return -EINVAL;
+
+       dev = usb_if->dev[pufd_omsg_get_channel(ov)];
+       netdev = dev->netdev;
+
        /* allocate an skb to store the error frame */
        skb = alloc_can_err_skb(netdev, &cf);
        if (!skb)
@@ -716,6 +739,9 @@ static int pcan_usb_fd_encode_msg(struct peak_usb_device *dev,
        u16 tx_msg_size, tx_msg_flags;
        u8 can_dlc;
 
+       if (cfd->len > CANFD_MAX_DLEN)
+               return -EINVAL;
+
        tx_msg_size = ALIGN(sizeof(struct pucan_tx_msg) + cfd->len, 4);
        tx_msg->size = cpu_to_le16(tx_msg_size);
        tx_msg->type = cpu_to_le16(PUCAN_MSG_CAN_TX);
index 6c4d00d2dbdcc3c2ec5a36defdcb7b883dd93abb..48d746e18f30219e49ed04c24165a789d0bc71fc 100644 (file)
@@ -1395,7 +1395,7 @@ static int xcan_open(struct net_device *ndev)
        if (ret < 0) {
                netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
                           __func__, ret);
-               return ret;
+               goto err;
        }
 
        ret = request_irq(ndev->irq, xcan_interrupt, priv->irq_flags,
@@ -1479,6 +1479,7 @@ static int xcan_get_berr_counter(const struct net_device *ndev,
        if (ret < 0) {
                netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
                           __func__, ret);
+               pm_runtime_put(priv->dev);
                return ret;
        }
 
@@ -1793,7 +1794,7 @@ static int xcan_probe(struct platform_device *pdev)
        if (ret < 0) {
                netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
                           __func__, ret);
-               goto err_pmdisable;
+               goto err_disableclks;
        }
 
        if (priv->read_reg(priv, XCAN_SR_OFFSET) != XCAN_SR_CONFIG_MASK) {
@@ -1828,7 +1829,6 @@ static int xcan_probe(struct platform_device *pdev)
 
 err_disableclks:
        pm_runtime_put(priv->dev);
-err_pmdisable:
        pm_runtime_disable(&pdev->dev);
 err_free:
        free_candev(ndev);
index 74db81dafee35d371e48e724171516386bfaf6a8..09701c17f3f63ea46420d24ad3e5c807a14be767 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/etherdevice.h>
 #include <linux/firmware.h>
 #include <linux/if_bridge.h>
@@ -1837,6 +1838,16 @@ static int gswip_gphy_fw_list(struct gswip_priv *priv,
                i++;
        }
 
+       /* The standalone PHY11G requires 300ms to be fully
+        * initialized and ready for any MDIO communication after being
+        * taken out of reset. For the SoC-internal GPHY variant there
+        * is no (known) documentation for the minimum time after a
+        * reset. Use the same value as for the standalone variant as
+        * some users have reported internal PHYs not being detected
+        * without any delay.
+        */
+       msleep(300);
+
        return 0;
 
 remove_gphy:
index bd297ae7cf9e79ec4e6339730259b972804380e4..34cca0a4b31c73da65669d4bb7684fe27e70aa01 100644 (file)
@@ -2297,6 +2297,8 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
                usleep_range(10000, 20000);
                gpiod_set_value_cansleep(gpiod, 0);
                usleep_range(10000, 20000);
+
+               mv88e6xxx_g1_wait_eeprom_done(chip);
        }
 }
 
index 10cd1bfd81a0a6144ca2b5319210256a126c327f..ade04c036fd9d254206a258d0890a2120442ccc7 100644 (file)
@@ -393,8 +393,10 @@ static int mv88e6xxx_region_atu_snapshot(struct devlink *dl,
        mv88e6xxx_reg_lock(chip);
 
        err = mv88e6xxx_fid_map(chip, fid_bitmap);
-       if (err)
+       if (err) {
+               kfree(table);
                goto out;
+       }
 
        while (1) {
                fid = find_next_bit(fid_bitmap, MV88E6XXX_N_FID, fid + 1);
index f62aa83ca08d49e8793c1816acab066bd309ee7c..33d443a37efc4628246ec693290b6b68e8a904ea 100644 (file)
@@ -75,6 +75,37 @@ static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip)
        return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1);
 }
 
+void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip)
+{
+       const unsigned long timeout = jiffies + 1 * HZ;
+       u16 val;
+       int err;
+
+       /* Wait up to 1 second for the switch to finish reading the
+        * EEPROM.
+        */
+       while (time_before(jiffies, timeout)) {
+               err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &val);
+               if (err) {
+                       dev_err(chip->dev, "Error reading status");
+                       return;
+               }
+
+               /* If the switch is still resetting, it may not
+                * respond on the bus, and so MDIO read returns
+                * 0xffff. Differentiate between that, and waiting for
+                * the EEPROM to be done by bit 0 being set.
+                */
+               if (val != 0xffff &&
+                   val & BIT(MV88E6XXX_G1_STS_IRQ_EEPROM_DONE))
+                       return;
+
+               usleep_range(1000, 2000);
+       }
+
+       dev_err(chip->dev, "Timeout waiting for EEPROM done");
+}
+
 /* Offset 0x01: Switch MAC Address Register Bytes 0 & 1
  * Offset 0x02: Switch MAC Address Register Bytes 2 & 3
  * Offset 0x03: Switch MAC Address Register Bytes 4 & 5
index 1e3546f8b0727fd635bc12dbdcc7842d76a7d1cf..e05abe61fa1149b5e0ac13abdab2778f22c2f99d 100644 (file)
@@ -278,6 +278,7 @@ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr);
 int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip);
 int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip);
 int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip);
+void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip);
 
 int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip);
 int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip);
index 48390b7b18ad7b9e338b1720b98284c98116de3f..1048509a849bca8dde6234ce08911d46e1e8da1d 100644 (file)
@@ -125,11 +125,9 @@ static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
  * Offset 0x08: VTU/STU Data Register 2
  * Offset 0x09: VTU/STU Data Register 3
  */
-
-static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
-                                     struct mv88e6xxx_vtu_entry *entry)
+static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip *chip,
+                                         u16 *regs)
 {
-       u16 regs[3];
        int i;
 
        /* Read all 3 VTU/STU Data registers */
@@ -142,12 +140,45 @@ static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
                        return err;
        }
 
-       /* Extract MemberTag and PortState data */
+       return 0;
+}
+
+static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
+                                     struct mv88e6xxx_vtu_entry *entry)
+{
+       u16 regs[3];
+       int err;
+       int i;
+
+       err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
+       if (err)
+               return err;
+
+       /* Extract MemberTag data */
        for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
                unsigned int member_offset = (i % 4) * 4;
-               unsigned int state_offset = member_offset + 2;
 
                entry->member[i] = (regs[i / 4] >> member_offset) & 0x3;
+       }
+
+       return 0;
+}
+
+static int mv88e6185_g1_stu_data_read(struct mv88e6xxx_chip *chip,
+                                     struct mv88e6xxx_vtu_entry *entry)
+{
+       u16 regs[3];
+       int err;
+       int i;
+
+       err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
+       if (err)
+               return err;
+
+       /* Extract PortState data */
+       for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
+               unsigned int state_offset = (i % 4) * 4 + 2;
+
                entry->state[i] = (regs[i / 4] >> state_offset) & 0x3;
        }
 
@@ -349,6 +380,10 @@ int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
                if (err)
                        return err;
 
+               err = mv88e6185_g1_stu_data_read(chip, entry);
+               if (err)
+                       return err;
+
                /* VTU DBNum[3:0] are located in VTU Operation 3:0
                 * VTU DBNum[7:4] are located in VTU Operation 11:8
                 */
@@ -374,16 +409,20 @@ int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
                return err;
 
        if (entry->valid) {
-               /* Fetch (and mask) VLAN PortState data from the STU */
-               err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
+               err = mv88e6185_g1_vtu_data_read(chip, entry);
                if (err)
                        return err;
 
-               err = mv88e6185_g1_vtu_data_read(chip, entry);
+               err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
                if (err)
                        return err;
 
-               err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
+               /* Fetch VLAN PortState data from the STU */
+               err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
+               if (err)
+                       return err;
+
+               err = mv88e6185_g1_stu_data_read(chip, entry);
                if (err)
                        return err;
        }
index 53064e0e161873eb4bf1b82b9c4acb37daceeba5..5bdac669a3392e69e340744c4fe5dd4bcdb6aacb 100644 (file)
@@ -1219,8 +1219,8 @@ qca8k_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
        priv->port_mtu[port] = new_mtu;
 
        for (i = 0; i < QCA8K_NUM_PORTS; i++)
-               if (priv->port_mtu[port] > mtu)
-                       mtu = priv->port_mtu[port];
+               if (priv->port_mtu[i] > mtu)
+                       mtu = priv->port_mtu[i];
 
        /* Include L2 header / FCS length */
        qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, mtu + ETH_HLEN + ETH_FCS_LEN);
index ad30cacc16222ae3d7fa1da63fb49c751896adff..032ab9f20438875450618ecc9051b4e1c6dc81fb 100644 (file)
@@ -516,6 +516,7 @@ int ena_com_rx_pkt(struct ena_com_io_cq *io_cq,
 {
        struct ena_com_rx_buf_info *ena_buf = &ena_rx_ctx->ena_bufs[0];
        struct ena_eth_io_rx_cdesc_base *cdesc = NULL;
+       u16 q_depth = io_cq->q_depth;
        u16 cdesc_idx = 0;
        u16 nb_hw_desc;
        u16 i = 0;
@@ -543,6 +544,8 @@ int ena_com_rx_pkt(struct ena_com_io_cq *io_cq,
        do {
                ena_buf[i].len = cdesc->length;
                ena_buf[i].req_id = cdesc->req_id;
+               if (unlikely(ena_buf[i].req_id >= q_depth))
+                       return -EIO;
 
                if (++i >= nb_hw_desc)
                        break;
index e8131dadc22c3155fb565793b2e24e8a01617500..df1884d57d1a0ca92451911f286008e29f4d729d 100644 (file)
@@ -789,24 +789,6 @@ static void ena_free_all_io_tx_resources(struct ena_adapter *adapter)
                                              adapter->num_io_queues);
 }
 
-static int validate_rx_req_id(struct ena_ring *rx_ring, u16 req_id)
-{
-       if (likely(req_id < rx_ring->ring_size))
-               return 0;
-
-       netif_err(rx_ring->adapter, rx_err, rx_ring->netdev,
-                 "Invalid rx req_id: %hu\n", req_id);
-
-       u64_stats_update_begin(&rx_ring->syncp);
-       rx_ring->rx_stats.bad_req_id++;
-       u64_stats_update_end(&rx_ring->syncp);
-
-       /* Trigger device reset */
-       rx_ring->adapter->reset_reason = ENA_REGS_RESET_INV_RX_REQ_ID;
-       set_bit(ENA_FLAG_TRIGGER_RESET, &rx_ring->adapter->flags);
-       return -EFAULT;
-}
-
 /* ena_setup_rx_resources - allocate I/O Rx resources (Descriptors)
  * @adapter: network interface device structure
  * @qid: queue index
@@ -926,10 +908,14 @@ static void ena_free_all_io_rx_resources(struct ena_adapter *adapter)
 static int ena_alloc_rx_page(struct ena_ring *rx_ring,
                                    struct ena_rx_buffer *rx_info, gfp_t gfp)
 {
+       int headroom = rx_ring->rx_headroom;
        struct ena_com_buf *ena_buf;
        struct page *page;
        dma_addr_t dma;
 
+       /* restore page offset value in case it has been changed by device */
+       rx_info->page_offset = headroom;
+
        /* if previous allocated page is not used */
        if (unlikely(rx_info->page))
                return 0;
@@ -959,10 +945,9 @@ static int ena_alloc_rx_page(struct ena_ring *rx_ring,
                  "Allocate page %p, rx_info %p\n", page, rx_info);
 
        rx_info->page = page;
-       rx_info->page_offset = 0;
        ena_buf = &rx_info->ena_buf;
-       ena_buf->paddr = dma + rx_ring->rx_headroom;
-       ena_buf->len = ENA_PAGE_SIZE - rx_ring->rx_headroom;
+       ena_buf->paddr = dma + headroom;
+       ena_buf->len = ENA_PAGE_SIZE - headroom;
 
        return 0;
 }
@@ -1356,15 +1341,10 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
        struct ena_rx_buffer *rx_info;
        u16 len, req_id, buf = 0;
        void *va;
-       int rc;
 
        len = ena_bufs[buf].len;
        req_id = ena_bufs[buf].req_id;
 
-       rc = validate_rx_req_id(rx_ring, req_id);
-       if (unlikely(rc < 0))
-               return NULL;
-
        rx_info = &rx_ring->rx_buffer_info[req_id];
 
        if (unlikely(!rx_info->page)) {
@@ -1379,7 +1359,8 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
 
        /* save virt address of first buffer */
        va = page_address(rx_info->page) + rx_info->page_offset;
-       prefetch(va + NET_IP_ALIGN);
+
+       prefetch(va);
 
        if (len <= rx_ring->rx_copybreak) {
                skb = ena_alloc_skb(rx_ring, false);
@@ -1420,8 +1401,6 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
 
                skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_info->page,
                                rx_info->page_offset, len, ENA_PAGE_SIZE);
-               /* The offset is non zero only for the first buffer */
-               rx_info->page_offset = 0;
 
                netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
                          "RX skb updated. len %d. data_len %d\n",
@@ -1440,10 +1419,6 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
                len = ena_bufs[buf].len;
                req_id = ena_bufs[buf].req_id;
 
-               rc = validate_rx_req_id(rx_ring, req_id);
-               if (unlikely(rc < 0))
-                       return NULL;
-
                rx_info = &rx_ring->rx_buffer_info[req_id];
        } while (1);
 
@@ -1544,8 +1519,7 @@ static int ena_xdp_handle_buff(struct ena_ring *rx_ring, struct xdp_buff *xdp)
        int ret;
 
        rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id];
-       xdp->data = page_address(rx_info->page) +
-               rx_info->page_offset + rx_ring->rx_headroom;
+       xdp->data = page_address(rx_info->page) + rx_info->page_offset;
        xdp_set_data_meta_invalid(xdp);
        xdp->data_hard_start = page_address(rx_info->page);
        xdp->data_end = xdp->data + rx_ring->ena_bufs[0].len;
@@ -1612,8 +1586,9 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
                if (unlikely(ena_rx_ctx.descs == 0))
                        break;
 
+               /* First descriptor might have an offset set by the device */
                rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id];
-               rx_info->page_offset = ena_rx_ctx.pkt_offset;
+               rx_info->page_offset += ena_rx_ctx.pkt_offset;
 
                netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
                          "rx_poll: q %d got packet from ena. descs #: %d l3 proto %d l4 proto %d hash: %x\n",
@@ -1697,12 +1672,18 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
 error:
        adapter = netdev_priv(rx_ring->netdev);
 
-       u64_stats_update_begin(&rx_ring->syncp);
-       rx_ring->rx_stats.bad_desc_num++;
-       u64_stats_update_end(&rx_ring->syncp);
+       if (rc == -ENOSPC) {
+               u64_stats_update_begin(&rx_ring->syncp);
+               rx_ring->rx_stats.bad_desc_num++;
+               u64_stats_update_end(&rx_ring->syncp);
+               adapter->reset_reason = ENA_REGS_RESET_TOO_MANY_RX_DESCS;
+       } else {
+               u64_stats_update_begin(&rx_ring->syncp);
+               rx_ring->rx_stats.bad_req_id++;
+               u64_stats_update_end(&rx_ring->syncp);
+               adapter->reset_reason = ENA_REGS_RESET_INV_RX_REQ_ID;
+       }
 
-       /* Too many desc from the device. Trigger reset */
-       adapter->reset_reason = ENA_REGS_RESET_TOO_MANY_RX_DESCS;
        set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
 
        return 0;
@@ -3388,16 +3369,9 @@ static int ena_device_init(struct ena_com_dev *ena_dev, struct pci_dev *pdev,
                goto err_mmio_read_less;
        }
 
-       rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(dma_width));
+       rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(dma_width));
        if (rc) {
-               dev_err(dev, "pci_set_dma_mask failed 0x%x\n", rc);
-               goto err_mmio_read_less;
-       }
-
-       rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(dma_width));
-       if (rc) {
-               dev_err(dev, "err_pci_set_consistent_dma_mask failed 0x%x\n",
-                       rc);
+               dev_err(dev, "dma_set_mask_and_coherent failed %d\n", rc);
                goto err_mmio_read_less;
        }
 
@@ -4167,6 +4141,12 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                return rc;
        }
 
+       rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(ENA_MAX_PHYS_ADDR_SIZE_BITS));
+       if (rc) {
+               dev_err(&pdev->dev, "dma_set_mask_and_coherent failed %d\n", rc);
+               goto err_disable_device;
+       }
+
        pci_set_master(pdev);
 
        ena_dev = vzalloc(sizeof(*ena_dev));
index 4f913658eea465a84e28d38b910573803d66563e..24122ccda614cc46fab36f59b208977fbc8b62b7 100644 (file)
@@ -413,85 +413,63 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
                                              buff->rxdata.pg_off,
                                              buff->len, DMA_FROM_DEVICE);
 
-               /* for single fragment packets use build_skb() */
-               if (buff->is_eop &&
-                   buff->len <= AQ_CFG_RX_FRAME_MAX - AQ_SKB_ALIGN) {
-                       skb = build_skb(aq_buf_vaddr(&buff->rxdata),
+               skb = napi_alloc_skb(napi, AQ_CFG_RX_HDR_SIZE);
+               if (unlikely(!skb)) {
+                       u64_stats_update_begin(&self->stats.rx.syncp);
+                       self->stats.rx.skb_alloc_fails++;
+                       u64_stats_update_end(&self->stats.rx.syncp);
+                       err = -ENOMEM;
+                       goto err_exit;
+               }
+               if (is_ptp_ring)
+                       buff->len -=
+                               aq_ptp_extract_ts(self->aq_nic, skb,
+                                                 aq_buf_vaddr(&buff->rxdata),
+                                                 buff->len);
+
+               hdr_len = buff->len;
+               if (hdr_len > AQ_CFG_RX_HDR_SIZE)
+                       hdr_len = eth_get_headlen(skb->dev,
+                                                 aq_buf_vaddr(&buff->rxdata),
+                                                 AQ_CFG_RX_HDR_SIZE);
+
+               memcpy(__skb_put(skb, hdr_len), aq_buf_vaddr(&buff->rxdata),
+                      ALIGN(hdr_len, sizeof(long)));
+
+               if (buff->len - hdr_len > 0) {
+                       skb_add_rx_frag(skb, 0, buff->rxdata.page,
+                                       buff->rxdata.pg_off + hdr_len,
+                                       buff->len - hdr_len,
                                        AQ_CFG_RX_FRAME_MAX);
-                       if (unlikely(!skb)) {
-                               u64_stats_update_begin(&self->stats.rx.syncp);
-                               self->stats.rx.skb_alloc_fails++;
-                               u64_stats_update_end(&self->stats.rx.syncp);
-                               err = -ENOMEM;
-                               goto err_exit;
-                       }
-                       if (is_ptp_ring)
-                               buff->len -=
-                                       aq_ptp_extract_ts(self->aq_nic, skb,
-                                               aq_buf_vaddr(&buff->rxdata),
-                                               buff->len);
-                       skb_put(skb, buff->len);
                        page_ref_inc(buff->rxdata.page);
-               } else {
-                       skb = napi_alloc_skb(napi, AQ_CFG_RX_HDR_SIZE);
-                       if (unlikely(!skb)) {
-                               u64_stats_update_begin(&self->stats.rx.syncp);
-                               self->stats.rx.skb_alloc_fails++;
-                               u64_stats_update_end(&self->stats.rx.syncp);
-                               err = -ENOMEM;
-                               goto err_exit;
-                       }
-                       if (is_ptp_ring)
-                               buff->len -=
-                                       aq_ptp_extract_ts(self->aq_nic, skb,
-                                               aq_buf_vaddr(&buff->rxdata),
-                                               buff->len);
-
-                       hdr_len = buff->len;
-                       if (hdr_len > AQ_CFG_RX_HDR_SIZE)
-                               hdr_len = eth_get_headlen(skb->dev,
-                                                         aq_buf_vaddr(&buff->rxdata),
-                                                         AQ_CFG_RX_HDR_SIZE);
-
-                       memcpy(__skb_put(skb, hdr_len), aq_buf_vaddr(&buff->rxdata),
-                              ALIGN(hdr_len, sizeof(long)));
-
-                       if (buff->len - hdr_len > 0) {
-                               skb_add_rx_frag(skb, 0, buff->rxdata.page,
-                                               buff->rxdata.pg_off + hdr_len,
-                                               buff->len - hdr_len,
-                                               AQ_CFG_RX_FRAME_MAX);
-                               page_ref_inc(buff->rxdata.page);
-                       }
+               }
 
-                       if (!buff->is_eop) {
-                               buff_ = buff;
-                               i = 1U;
-                               do {
-                                       next_ = buff_->next,
-                                       buff_ = &self->buff_ring[next_];
+               if (!buff->is_eop) {
+                       buff_ = buff;
+                       i = 1U;
+                       do {
+                               next_ = buff_->next;
+                               buff_ = &self->buff_ring[next_];
 
-                                       dma_sync_single_range_for_cpu(
-                                                       aq_nic_get_dev(self->aq_nic),
-                                                       buff_->rxdata.daddr,
-                                                       buff_->rxdata.pg_off,
-                                                       buff_->len,
-                                                       DMA_FROM_DEVICE);
-                                       skb_add_rx_frag(skb, i++,
-                                                       buff_->rxdata.page,
-                                                       buff_->rxdata.pg_off,
-                                                       buff_->len,
-                                                       AQ_CFG_RX_FRAME_MAX);
-                                       page_ref_inc(buff_->rxdata.page);
-                                       buff_->is_cleaned = 1;
-
-                                       buff->is_ip_cso &= buff_->is_ip_cso;
-                                       buff->is_udp_cso &= buff_->is_udp_cso;
-                                       buff->is_tcp_cso &= buff_->is_tcp_cso;
-                                       buff->is_cso_err |= buff_->is_cso_err;
+                               dma_sync_single_range_for_cpu(aq_nic_get_dev(self->aq_nic),
+                                                             buff_->rxdata.daddr,
+                                                             buff_->rxdata.pg_off,
+                                                             buff_->len,
+                                                             DMA_FROM_DEVICE);
+                               skb_add_rx_frag(skb, i++,
+                                               buff_->rxdata.page,
+                                               buff_->rxdata.pg_off,
+                                               buff_->len,
+                                               AQ_CFG_RX_FRAME_MAX);
+                               page_ref_inc(buff_->rxdata.page);
+                               buff_->is_cleaned = 1;
 
-                               } while (!buff_->is_eop);
-                       }
+                               buff->is_ip_cso &= buff_->is_ip_cso;
+                               buff->is_udp_cso &= buff_->is_udp_cso;
+                               buff->is_tcp_cso &= buff_->is_tcp_cso;
+                               buff->is_cso_err |= buff_->is_cso_err;
+
+                       } while (!buff_->is_eop);
                }
 
                if (buff->is_vlan)
index 0c12cf7bda504a527ef6edc10485fdf20a3c6411..3f65f2b370c57d2f0dffed3abf2f9e3148f0c1d3 100644 (file)
@@ -2543,8 +2543,8 @@ static int atl1c_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         * various kernel subsystems to support the mechanics required by a
         * fixed-high-32-bit system.
         */
-       if ((dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)) != 0) ||
-           (dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)) != 0)) {
+       err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (err) {
                dev_err(&pdev->dev, "No usable DMA configuration,aborting\n");
                goto err_dma;
        }
index 098b0328e3cb0ef8d777729eafca1e7410f317b9..ff9f96de74b813a9001b48260be3323b4777056d 100644 (file)
@@ -2312,8 +2312,8 @@ static int atl1e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         * various kernel subsystems to support the mechanics required by a
         * fixed-high-32-bit system.
         */
-       if ((dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)) != 0) ||
-           (dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)) != 0)) {
+       err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (err) {
                dev_err(&pdev->dev, "No usable DMA configuration,aborting\n");
                goto err_dma;
        }
index 7fb42f388d591db264a43a6f4cc4fbdf90c03663..7b79528d6eed2eba9339d28b22c02bea9b59a7f2 100644 (file)
@@ -88,6 +88,7 @@ config BNX2
 config CNIC
        tristate "QLogic CNIC support"
        depends on PCI && (IPV6 || IPV6=n)
+       depends on MMU
        select BNX2
        select UIO
        help
index 74c1778d841ea1cf1b8b9a978890bd859293c36b..b455b60a5434be6c98ea67537f850989c8485f74 100644 (file)
@@ -2383,7 +2383,8 @@ static int b44_init_one(struct ssb_device *sdev,
                goto err_out_free_dev;
        }
 
-       if (dma_set_mask_and_coherent(sdev->dma_dev, DMA_BIT_MASK(30))) {
+       err = dma_set_mask_and_coherent(sdev->dma_dev, DMA_BIT_MASK(30));
+       if (err) {
                dev_err(sdev->dev,
                        "Required 30BIT DMA mask unsupported by the system\n");
                goto err_out_powerdown;
index fa147865e33f4a1927c0dd439d0ab4b9bd6f150d..0af0af2b70fe43c37595f1ad7496a71215ab3185 100644 (file)
@@ -1160,16 +1160,6 @@ static void bnxt_queue_sp_work(struct bnxt *bp)
                schedule_work(&bp->sp_task);
 }
 
-static void bnxt_cancel_sp_work(struct bnxt *bp)
-{
-       if (BNXT_PF(bp)) {
-               flush_workqueue(bnxt_pf_wq);
-       } else {
-               cancel_work_sync(&bp->sp_task);
-               cancel_delayed_work_sync(&bp->fw_reset_task);
-       }
-}
-
 static void bnxt_sched_reset(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
 {
        if (!rxr->bnapi->in_reset) {
@@ -4109,7 +4099,8 @@ static void bnxt_free_mem(struct bnxt *bp, bool irq_re_init)
        bnxt_free_ntp_fltrs(bp, irq_re_init);
        if (irq_re_init) {
                bnxt_free_ring_stats(bp);
-               if (!(bp->fw_cap & BNXT_FW_CAP_PORT_STATS_NO_RESET))
+               if (!(bp->fw_cap & BNXT_FW_CAP_PORT_STATS_NO_RESET) ||
+                   test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
                        bnxt_free_port_stats(bp);
                bnxt_free_ring_grps(bp);
                bnxt_free_vnics(bp);
@@ -4362,7 +4353,8 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
        u32 bar_offset = BNXT_GRCPF_REG_CHIMP_COMM;
        u16 dst = BNXT_HWRM_CHNL_CHIMP;
 
-       if (BNXT_NO_FW_ACCESS(bp))
+       if (BNXT_NO_FW_ACCESS(bp) &&
+           le16_to_cpu(req->req_type) != HWRM_FUNC_RESET)
                return -EBUSY;
 
        if (msg_len > BNXT_HWRM_MAX_REQ_LEN) {
@@ -7766,6 +7758,7 @@ static void bnxt_add_one_ctr(u64 hw, u64 *sw, u64 mask)
 {
        u64 sw_tmp;
 
+       hw &= mask;
        sw_tmp = (*sw & ~mask) | hw;
        if (hw < (*sw & mask))
                sw_tmp += mask + 1;
@@ -9789,7 +9782,10 @@ int bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
 {
        int rc = 0;
 
-       rc = __bnxt_open_nic(bp, irq_re_init, link_re_init);
+       if (test_bit(BNXT_STATE_ABORT_ERR, &bp->state))
+               rc = -EIO;
+       if (!rc)
+               rc = __bnxt_open_nic(bp, irq_re_init, link_re_init);
        if (rc) {
                netdev_err(bp->dev, "nic open fail (rc: %x)\n", rc);
                dev_close(bp->dev);
@@ -11594,7 +11590,8 @@ static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev)
        if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) != 0 &&
            dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)) != 0) {
                dev_err(&pdev->dev, "System does not support DMA, aborting\n");
-               goto init_err_disable;
+               rc = -EIO;
+               goto init_err_release;
        }
 
        pci_set_master(pdev);
@@ -12108,15 +12105,17 @@ static void bnxt_remove_one(struct pci_dev *pdev)
        if (BNXT_PF(bp))
                bnxt_sriov_disable(bp);
 
-       clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
-       bnxt_cancel_sp_work(bp);
-       bp->sp_event = 0;
-
-       bnxt_dl_fw_reporters_destroy(bp, true);
        if (BNXT_PF(bp))
                devlink_port_type_clear(&bp->dl_port);
        pci_disable_pcie_error_reporting(pdev);
        unregister_netdev(dev);
+       clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
+       /* Flush any pending tasks */
+       cancel_work_sync(&bp->sp_task);
+       cancel_delayed_work_sync(&bp->fw_reset_task);
+       bp->sp_event = 0;
+
+       bnxt_dl_fw_reporters_destroy(bp, true);
        bnxt_dl_unregister(bp);
        bnxt_shutdown_tc(bp);
 
@@ -12676,6 +12675,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                                create_singlethread_workqueue("bnxt_pf_wq");
                        if (!bnxt_pf_wq) {
                                dev_err(&pdev->dev, "Unable to create workqueue.\n");
+                               rc = -ENOMEM;
                                goto init_err_pci_clean;
                        }
                }
@@ -12860,6 +12860,9 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
                return PCI_ERS_RESULT_DISCONNECT;
        }
 
+       if (state == pci_channel_io_frozen)
+               set_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN, &bp->state);
+
        if (netif_running(netdev))
                bnxt_close(netdev);
 
@@ -12886,7 +12889,7 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct bnxt *bp = netdev_priv(netdev);
-       int err = 0;
+       int err = 0, off;
        pci_ers_result_t result = PCI_ERS_RESULT_DISCONNECT;
 
        netdev_info(bp->dev, "PCI Slot Reset\n");
@@ -12898,6 +12901,20 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
                        "Cannot re-enable PCI device after reset.\n");
        } else {
                pci_set_master(pdev);
+               /* Upon fatal error, our device internal logic that latches to
+                * BAR value is getting reset and will restore only upon
+                * rewritting the BARs.
+                *
+                * As pci_restore_state() does not re-write the BARs if the
+                * value is same as saved value earlier, driver needs to
+                * write the BARs to 0 to force restore, in case of fatal error.
+                */
+               if (test_and_clear_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN,
+                                      &bp->state)) {
+                       for (off = PCI_BASE_ADDRESS_0;
+                            off <= PCI_BASE_ADDRESS_5; off += 4)
+                               pci_write_config_dword(bp->pdev, off, 0);
+               }
                pci_restore_state(pdev);
                pci_save_state(pdev);
 
index 21ef1c21f602acdd444437a33b91bcf0be5ff14d..47b3c31278798b1b076f15fdd45d1e9d5a05311a 100644 (file)
@@ -1781,6 +1781,7 @@ struct bnxt {
 #define BNXT_STATE_ABORT_ERR   5
 #define BNXT_STATE_FW_FATAL_COND       6
 #define BNXT_STATE_DRV_REGISTERED      7
+#define BNXT_STATE_PCI_CHANNEL_IO_FROZEN       8
 
 #define BNXT_NO_FW_ACCESS(bp)                                  \
        (test_bit(BNXT_STATE_FW_FATAL_COND, &(bp)->state) ||    \
index 53687bc7fcf5dce4ef9301389106231d1c11f062..1471c9a362388d0004b83e55fdaf750cd3c0f23f 100644 (file)
@@ -2079,6 +2079,9 @@ int bnxt_hwrm_nvm_get_dev_info(struct bnxt *bp,
        struct hwrm_nvm_get_dev_info_input req = {0};
        int rc;
 
+       if (BNXT_VF(bp))
+               return -EOPNOTSUPP;
+
        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_DEV_INFO, -1, -1);
        mutex_lock(&bp->hwrm_cmd_lock);
        rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
@@ -2997,7 +3000,7 @@ static int bnxt_get_module_eeprom(struct net_device *dev,
        /* Read A2 portion of the EEPROM */
        if (length) {
                start -= ETH_MODULE_SFF_8436_LEN;
-               rc = bnxt_read_sfp_module_eeprom_info(bp, I2C_DEV_ADDR_A2, 1,
+               rc = bnxt_read_sfp_module_eeprom_info(bp, I2C_DEV_ADDR_A2, 0,
                                                      start, length, data);
        }
        return rc;
index 883e47c5b1a7852062ab196ebc3fb80743f128d1..286f0341bdf83a32781730151b27a4a9e831cafb 100644 (file)
@@ -1929,7 +1929,8 @@ static inline int macb_clear_csum(struct sk_buff *skb)
 
 static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
 {
-       bool cloned = skb_cloned(*skb) || skb_header_cloned(*skb);
+       bool cloned = skb_cloned(*skb) || skb_header_cloned(*skb) ||
+                     skb_is_nonlinear(*skb);
        int padlen = ETH_ZLEN - (*skb)->len;
        int headroom = skb_headroom(*skb);
        int tailroom = skb_tailroom(*skb);
index 87cc0ef68b314261bc839166a0c9db59480a0b22..8ba0e08e5e640cf50813350b4997bd0488063040 100644 (file)
@@ -68,7 +68,7 @@ config CHELSIO_T3
 
 config CHELSIO_T4
        tristate "Chelsio Communications T4/T5/T6 Ethernet support"
-       depends on PCI && (IPV6 || IPV6=n)
+       depends on PCI && (IPV6 || IPV6=n) && (TLS || TLS=n)
        select FW_LOADER
        select MDIO
        select ZLIB_DEFLATE
index e18e9ce27f943daec74225bcfa23cc3c1aa96a0d..1cc3c51eff710b3859edea3c706c4dae72cffdea 100644 (file)
@@ -3175,6 +3175,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
                          GFP_KERNEL | __GFP_COMP);
        if (!avail) {
                CH_ALERT(adapter, "free list queue 0 initialization failed\n");
+               ret = -ENOMEM;
                goto err;
        }
        if (avail < q->fl[0].size)
index 3352dad6ca999315606621159be06493173170dd..27308600da1532ebcb6ecf327327687c1d71570b 100644 (file)
@@ -2124,6 +2124,9 @@ void cxgb4_inline_tx_skb(const struct sk_buff *skb, const struct sge_txq *q,
 void cxgb4_write_sgl(const struct sk_buff *skb, struct sge_txq *q,
                     struct ulptx_sgl *sgl, u64 *end, unsigned int start,
                     const dma_addr_t *addr);
+void cxgb4_write_partial_sgl(const struct sk_buff *skb, struct sge_txq *q,
+                            struct ulptx_sgl *sgl, u64 *end,
+                            const dma_addr_t *addr, u32 start, u32 send_len);
 void cxgb4_ring_tx_db(struct adapter *adap, struct sge_txq *q, int n);
 int t4_set_vlan_acl(struct adapter *adap, unsigned int mbox, unsigned int vf,
                    u16 vlan);
index 0273f40b85f766c5a8bfca1075787c3ed9b2f6c9..17410fe86626790496c804285be3827f7e9dd872 100644 (file)
@@ -3573,6 +3573,8 @@ static int chcr_stats_show(struct seq_file *seq, void *v)
                   atomic64_read(&adap->ch_ktls_stats.ktls_tx_complete_pkts));
        seq_printf(seq, "TX trim pkts :                    %20llu\n",
                   atomic64_read(&adap->ch_ktls_stats.ktls_tx_trimmed_pkts));
+       seq_printf(seq, "TX sw fallback :                  %20llu\n",
+                  atomic64_read(&adap->ch_ktls_stats.ktls_tx_fallback));
        while (i < MAX_NPORTS) {
                ktls_port = &adap->ch_ktls_stats.ktls_port[i];
                seq_printf(seq, "Port %d\n", i);
index 6ec5f2f26f05526fbaf726e786e4154cac790012..83b46440408bae19bad84e7a952ab635e0b0de23 100644 (file)
@@ -145,13 +145,13 @@ static int configure_filter_smac(struct adapter *adap, struct filter_entry *f)
        int err;
 
        /* do a set-tcb for smac-sel and CWR bit.. */
-       err = set_tcb_tflag(adap, f, f->tid, TF_CCTRL_CWR_S, 1, 1);
-       if (err)
-               goto smac_err;
-
        err = set_tcb_field(adap, f, f->tid, TCB_SMAC_SEL_W,
                            TCB_SMAC_SEL_V(TCB_SMAC_SEL_M),
                            TCB_SMAC_SEL_V(f->smt->idx), 1);
+       if (err)
+               goto smac_err;
+
+       err = set_tcb_tflag(adap, f, f->tid, TF_CCTRL_CWR_S, 1, 1);
        if (!err)
                return 0;
 
@@ -862,6 +862,7 @@ int set_filter_wr(struct adapter *adapter, int fidx)
                      FW_FILTER_WR_DIRSTEERHASH_V(f->fs.dirsteerhash) |
                      FW_FILTER_WR_LPBK_V(f->fs.action == FILTER_SWITCH) |
                      FW_FILTER_WR_DMAC_V(f->fs.newdmac) |
+                     FW_FILTER_WR_SMAC_V(f->fs.newsmac) |
                      FW_FILTER_WR_INSVLAN_V(f->fs.newvlan == VLAN_INSERT ||
                                             f->fs.newvlan == VLAN_REWRITE) |
                      FW_FILTER_WR_RMVLAN_V(f->fs.newvlan == VLAN_REMOVE ||
@@ -879,7 +880,8 @@ int set_filter_wr(struct adapter *adapter, int fidx)
                 FW_FILTER_WR_OVLAN_VLD_V(f->fs.val.ovlan_vld) |
                 FW_FILTER_WR_IVLAN_VLDM_V(f->fs.mask.ivlan_vld) |
                 FW_FILTER_WR_OVLAN_VLDM_V(f->fs.mask.ovlan_vld));
-       fwr->smac_sel = 0;
+       if (f->fs.newsmac)
+               fwr->smac_sel = f->smt->idx;
        fwr->rx_chan_rx_rpl_iq =
                htons(FW_FILTER_WR_RX_CHAN_V(0) |
                      FW_FILTER_WR_RX_RPL_IQ_V(adapter->sge.fw_evtq.abs_id));
@@ -1323,11 +1325,8 @@ static void mk_act_open_req6(struct filter_entry *f, struct sk_buff *skb,
                            TX_QUEUE_V(f->fs.nat_mode) |
                            T5_OPT_2_VALID_F |
                            RX_CHANNEL_V(cxgb4_port_e2cchan(f->dev)) |
-                           CONG_CNTRL_V((f->fs.action == FILTER_DROP) |
-                                        (f->fs.dirsteer << 1)) |
                            PACE_V((f->fs.maskhash) |
-                                  ((f->fs.dirsteerhash) << 1)) |
-                           CCTRL_ECN_V(f->fs.action == FILTER_SWITCH));
+                                  ((f->fs.dirsteerhash) << 1)));
 }
 
 static void mk_act_open_req(struct filter_entry *f, struct sk_buff *skb,
@@ -1363,11 +1362,8 @@ static void mk_act_open_req(struct filter_entry *f, struct sk_buff *skb,
                            TX_QUEUE_V(f->fs.nat_mode) |
                            T5_OPT_2_VALID_F |
                            RX_CHANNEL_V(cxgb4_port_e2cchan(f->dev)) |
-                           CONG_CNTRL_V((f->fs.action == FILTER_DROP) |
-                                        (f->fs.dirsteer << 1)) |
                            PACE_V((f->fs.maskhash) |
-                                  ((f->fs.dirsteerhash) << 1)) |
-                           CCTRL_ECN_V(f->fs.action == FILTER_SWITCH));
+                                  ((f->fs.dirsteerhash) << 1)));
 }
 
 static int cxgb4_set_hash_filter(struct net_device *dev,
@@ -2039,6 +2035,20 @@ void hash_filter_rpl(struct adapter *adap, const struct cpl_act_open_rpl *rpl)
                        }
                        return;
                }
+               switch (f->fs.action) {
+               case FILTER_PASS:
+                       if (f->fs.dirsteer)
+                               set_tcb_tflag(adap, f, tid,
+                                             TF_DIRECT_STEER_S, 1, 1);
+                       break;
+               case FILTER_DROP:
+                       set_tcb_tflag(adap, f, tid, TF_DROP_S, 1, 1);
+                       break;
+               case FILTER_SWITCH:
+                       set_tcb_tflag(adap, f, tid, TF_LPBK_S, 1, 1);
+                       break;
+               }
+
                break;
 
        default:
@@ -2106,22 +2116,11 @@ void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl)
                        if (ctx)
                                ctx->result = 0;
                } else if (ret == FW_FILTER_WR_FLT_ADDED) {
-                       int err = 0;
-
-                       if (f->fs.newsmac)
-                               err = configure_filter_smac(adap, f);
-
-                       if (!err) {
-                               f->pending = 0;  /* async setup completed */
-                               f->valid = 1;
-                               if (ctx) {
-                                       ctx->result = 0;
-                                       ctx->tid = idx;
-                               }
-                       } else {
-                               clear_filter(adap, f);
-                               if (ctx)
-                                       ctx->result = err;
+                       f->pending = 0;  /* async setup completed */
+                       f->valid = 1;
+                       if (ctx) {
+                               ctx->result = 0;
+                               ctx->tid = idx;
                        }
                } else {
                        /* Something went wrong.  Issue a warning about the
index a952fe198eb923e7b574b67637e822cbe3d7c416..7fd264a6d08546c8783e3ba8270d853fe218824c 100644 (file)
@@ -1176,6 +1176,7 @@ static u16 cxgb_select_queue(struct net_device *dev, struct sk_buff *skb,
                txq = netdev_pick_tx(dev, skb, sb_dev);
                if (xfrm_offload(skb) || is_ptp_enabled(skb, dev) ||
                    skb->encapsulation ||
+                   cxgb4_is_ktls_skb(skb) ||
                    (proto != IPPROTO_TCP && proto != IPPROTO_UDP))
                        txq = txq % pi->nqsets;
 
index b169776ab4845af3fa5cb498c289b44d8a6e1822..1b49f2fa9b18525b5d79343c28d87e7f21d3c75f 100644 (file)
@@ -388,6 +388,7 @@ struct ch_ktls_stats_debug {
        atomic64_t ktls_tx_retransmit_pkts;
        atomic64_t ktls_tx_complete_pkts;
        atomic64_t ktls_tx_trimmed_pkts;
+       atomic64_t ktls_tx_fallback;
 };
 #endif
 
@@ -493,6 +494,11 @@ struct cxgb4_uld_info {
 #endif
 };
 
+static inline bool cxgb4_is_ktls_skb(struct sk_buff *skb)
+{
+       return skb->sk && tls_is_sk_tx_device_offloaded(skb->sk);
+}
+
 void cxgb4_uld_enable(struct adapter *adap);
 void cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p);
 int cxgb4_unregister_uld(enum cxgb4_uld type);
index a9e9c7ae565dca4e6d1e21c155401cf5038e7c35..196652a114c5fb7f581f2b67bbca5d4606a3b151 100644 (file)
@@ -890,6 +890,114 @@ void cxgb4_write_sgl(const struct sk_buff *skb, struct sge_txq *q,
 }
 EXPORT_SYMBOL(cxgb4_write_sgl);
 
+/*     cxgb4_write_partial_sgl - populate SGL for partial packet
+ *     @skb: the packet
+ *     @q: the Tx queue we are writing into
+ *     @sgl: starting location for writing the SGL
+ *     @end: points right after the end of the SGL
+ *     @addr: the list of bus addresses for the SGL elements
+ *     @start: start offset in the SKB where partial data starts
+ *     @len: length of data from @start to send out
+ *
+ *     This API will handle sending out partial data of a skb if required.
+ *     Unlike cxgb4_write_sgl, @start can be any offset into the skb data,
+ *     and @len will decide how much data after @start offset to send out.
+ */
+void cxgb4_write_partial_sgl(const struct sk_buff *skb, struct sge_txq *q,
+                            struct ulptx_sgl *sgl, u64 *end,
+                            const dma_addr_t *addr, u32 start, u32 len)
+{
+       struct ulptx_sge_pair buf[MAX_SKB_FRAGS / 2 + 1] = {0}, *to;
+       u32 frag_size, skb_linear_data_len = skb_headlen(skb);
+       struct skb_shared_info *si = skb_shinfo(skb);
+       u8 i = 0, frag_idx = 0, nfrags = 0;
+       skb_frag_t *frag;
+
+       /* Fill the first SGL either from linear data or from partial
+        * frag based on @start.
+        */
+       if (unlikely(start < skb_linear_data_len)) {
+               frag_size = min(len, skb_linear_data_len - start);
+               sgl->len0 = htonl(frag_size);
+               sgl->addr0 = cpu_to_be64(addr[0] + start);
+               len -= frag_size;
+               nfrags++;
+       } else {
+               start -= skb_linear_data_len;
+               frag = &si->frags[frag_idx];
+               frag_size = skb_frag_size(frag);
+               /* find the first frag */
+               while (start >= frag_size) {
+                       start -= frag_size;
+                       frag_idx++;
+                       frag = &si->frags[frag_idx];
+                       frag_size = skb_frag_size(frag);
+               }
+
+               frag_size = min(len, skb_frag_size(frag) - start);
+               sgl->len0 = cpu_to_be32(frag_size);
+               sgl->addr0 = cpu_to_be64(addr[frag_idx + 1] + start);
+               len -= frag_size;
+               nfrags++;
+               frag_idx++;
+       }
+
+       /* If the entire partial data fit in one SGL, then send it out
+        * now.
+        */
+       if (!len)
+               goto done;
+
+       /* Most of the complexity below deals with the possibility we hit the
+        * end of the queue in the middle of writing the SGL.  For this case
+        * only we create the SGL in a temporary buffer and then copy it.
+        */
+       to = (u8 *)end > (u8 *)q->stat ? buf : sgl->sge;
+
+       /* If the skb couldn't fit in first SGL completely, fill the
+        * rest of the frags in subsequent SGLs. Note that each SGL
+        * pair can store 2 frags.
+        */
+       while (len) {
+               frag_size = min(len, skb_frag_size(&si->frags[frag_idx]));
+               to->len[i & 1] = cpu_to_be32(frag_size);
+               to->addr[i & 1] = cpu_to_be64(addr[frag_idx + 1]);
+               if (i && (i & 1))
+                       to++;
+               nfrags++;
+               frag_idx++;
+               i++;
+               len -= frag_size;
+       }
+
+       /* If we ended in an odd boundary, then set the second SGL's
+        * length in the pair to 0.
+        */
+       if (i & 1)
+               to->len[1] = cpu_to_be32(0);
+
+       /* Copy from temporary buffer to Tx ring, in case we hit the
+        * end of the queue in the middle of writing the SGL.
+        */
+       if (unlikely((u8 *)end > (u8 *)q->stat)) {
+               u32 part0 = (u8 *)q->stat - (u8 *)sgl->sge, part1;
+
+               if (likely(part0))
+                       memcpy(sgl->sge, buf, part0);
+               part1 = (u8 *)end - (u8 *)q->stat;
+               memcpy(q->desc, (u8 *)buf + part0, part1);
+               end = (void *)q->desc + part1;
+       }
+
+       /* 0-pad to multiple of 16 */
+       if ((uintptr_t)end & 8)
+               *end = 0;
+done:
+       sgl->cmd_nsge = htonl(ULPTX_CMD_V(ULP_TX_SC_DSGL) |
+                       ULPTX_NSGE_V(nfrags));
+}
+EXPORT_SYMBOL(cxgb4_write_partial_sgl);
+
 /* This function copies 64 byte coalesced work request to
  * memory mapped BAR2 space. For coalesced WR SGE fetches
  * data from the FIFO instead of from Host.
@@ -1422,7 +1530,8 @@ static netdev_tx_t cxgb4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
 #endif /* CHELSIO_IPSEC_INLINE */
 
 #if IS_ENABLED(CONFIG_CHELSIO_TLS_DEVICE)
-       if (skb->decrypted)
+       if (cxgb4_is_ktls_skb(skb) &&
+           (skb->len - (skb_transport_offset(skb) + tcp_hdrlen(skb))))
                return adap->uld[CXGB4_ULD_KTLS].tx_handler(skb, dev);
 #endif /* CHELSIO_TLS_DEVICE */
 
index 50232e063f49e598d9df7b02b5f1fa794fd3ab5c..92473dda55d9f8238f6c5c3a6ebf168349b3f8b0 100644 (file)
 #define TCB_T_FLAGS_M          0xffffffffffffffffULL
 #define TCB_T_FLAGS_V(x)       ((__u64)(x) << TCB_T_FLAGS_S)
 
+#define TF_DROP_S              22
+#define TF_DIRECT_STEER_S      23
+#define TF_LPBK_S              59
+
 #define TF_CCTRL_ECE_S         60
 #define TF_CCTRL_CWR_S         61
 #define TF_CCTRL_RFR_S         62
index 5195f692f14d1f3f4fe3412afe61040d85757117..7f90b828d159a6a98be9690d5b27f5fde90b4bb4 100644 (file)
 static LIST_HEAD(uld_ctx_list);
 static DEFINE_MUTEX(dev_mutex);
 
+/* chcr_get_nfrags_to_send: get the remaining nfrags after start offset
+ * @skb: skb
+ * @start: start offset.
+ * @len: how much data to send after @start
+ */
+static int chcr_get_nfrags_to_send(struct sk_buff *skb, u32 start, u32 len)
+{
+       struct skb_shared_info *si = skb_shinfo(skb);
+       u32 frag_size, skb_linear_data_len = skb_headlen(skb);
+       u8 nfrags = 0, frag_idx = 0;
+       skb_frag_t *frag;
+
+       /* if its a linear skb then return 1 */
+       if (!skb_is_nonlinear(skb))
+               return 1;
+
+       if (unlikely(start < skb_linear_data_len)) {
+               frag_size = min(len, skb_linear_data_len - start);
+               start = 0;
+       } else {
+               start -= skb_linear_data_len;
+
+               frag = &si->frags[frag_idx];
+               frag_size = skb_frag_size(frag);
+               while (start >= frag_size) {
+                       start -= frag_size;
+                       frag_idx++;
+                       frag = &si->frags[frag_idx];
+                       frag_size = skb_frag_size(frag);
+               }
+               frag_size = min(len, skb_frag_size(frag) - start);
+       }
+       len -= frag_size;
+       nfrags++;
+
+       while (len) {
+               frag_size = min(len, skb_frag_size(&si->frags[frag_idx]));
+               len -= frag_size;
+               nfrags++;
+               frag_idx++;
+       }
+       return nfrags;
+}
+
 static int chcr_init_tcb_fields(struct chcr_ktls_info *tx_info);
 /*
  * chcr_ktls_save_keys: calculate and save crypto keys.
@@ -500,7 +544,9 @@ static int chcr_ktls_dev_add(struct net_device *netdev, struct sock *sk,
                /* need to wait for hw response, can't free tx_info yet. */
                if (tx_info->open_state == CH_KTLS_OPEN_PENDING)
                        tx_info->pending_close = true;
-               /* free the lock after the cleanup */
+               else
+                       spin_unlock_bh(&tx_info->lock);
+               /* if in pending close, free the lock after the cleanup */
                goto put_module;
        }
        spin_unlock_bh(&tx_info->lock);
@@ -689,7 +735,8 @@ static int chcr_ktls_cpl_set_tcb_rpl(struct adapter *adap, unsigned char *input)
 }
 
 static void *__chcr_write_cpl_set_tcb_ulp(struct chcr_ktls_info *tx_info,
-                                       u32 tid, void *pos, u16 word, u64 mask,
+                                       u32 tid, void *pos, u16 word,
+                                       struct sge_eth_txq *q, u64 mask,
                                        u64 val, u32 reply)
 {
        struct cpl_set_tcb_field_core *cpl;
@@ -698,7 +745,10 @@ static void *__chcr_write_cpl_set_tcb_ulp(struct chcr_ktls_info *tx_info,
 
        /* ULP_TXPKT */
        txpkt = pos;
-       txpkt->cmd_dest = htonl(ULPTX_CMD_V(ULP_TX_PKT) | ULP_TXPKT_DEST_V(0));
+       txpkt->cmd_dest = htonl(ULPTX_CMD_V(ULP_TX_PKT) |
+                               ULP_TXPKT_CHANNELID_V(tx_info->port_id) |
+                               ULP_TXPKT_FID_V(q->q.cntxt_id) |
+                               ULP_TXPKT_RO_F);
        txpkt->len = htonl(DIV_ROUND_UP(CHCR_SET_TCB_FIELD_LEN, 16));
 
        /* ULPTX_IDATA sub-command */
@@ -753,7 +803,7 @@ static void *chcr_write_cpl_set_tcb_ulp(struct chcr_ktls_info *tx_info,
                } else {
                        u8 buf[48] = {0};
 
-                       __chcr_write_cpl_set_tcb_ulp(tx_info, tid, buf, word,
+                       __chcr_write_cpl_set_tcb_ulp(tx_info, tid, buf, word, q,
                                                     mask, val, reply);
 
                        return chcr_copy_to_txd(buf, &q->q, pos,
@@ -761,7 +811,7 @@ static void *chcr_write_cpl_set_tcb_ulp(struct chcr_ktls_info *tx_info,
                }
        }
 
-       pos = __chcr_write_cpl_set_tcb_ulp(tx_info, tid, pos, word,
+       pos = __chcr_write_cpl_set_tcb_ulp(tx_info, tid, pos, word, q,
                                           mask, val, reply);
 
        /* check again if we are at the end of the queue */
@@ -783,11 +833,11 @@ static void *chcr_write_cpl_set_tcb_ulp(struct chcr_ktls_info *tx_info,
  */
 static int chcr_ktls_xmit_tcb_cpls(struct chcr_ktls_info *tx_info,
                                   struct sge_eth_txq *q, u64 tcp_seq,
-                                  u64 tcp_ack, u64 tcp_win)
+                                  u64 tcp_ack, u64 tcp_win, bool offset)
 {
        bool first_wr = ((tx_info->prev_ack == 0) && (tx_info->prev_win == 0));
        struct ch_ktls_port_stats_debug *port_stats;
-       u32 len, cpl = 0, ndesc, wr_len;
+       u32 len, cpl = 0, ndesc, wr_len, wr_mid = 0;
        struct fw_ulptx_wr *wr;
        int credits;
        void *pos;
@@ -803,6 +853,11 @@ static int chcr_ktls_xmit_tcb_cpls(struct chcr_ktls_info *tx_info,
                return NETDEV_TX_BUSY;
        }
 
+       if (unlikely(credits < ETHTXQ_STOP_THRES)) {
+               chcr_eth_txq_stop(q);
+               wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F;
+       }
+
        pos = &q->q.desc[q->q.pidx];
        /* make space for WR, we'll fill it later when we know all the cpls
         * being sent out and have complete length.
@@ -818,7 +873,7 @@ static int chcr_ktls_xmit_tcb_cpls(struct chcr_ktls_info *tx_info,
                cpl++;
        }
        /* reset snd una if it's a re-transmit pkt */
-       if (tcp_seq != tx_info->prev_seq) {
+       if (tcp_seq != tx_info->prev_seq || offset) {
                /* reset snd_una */
                port_stats =
                        &tx_info->adap->ch_ktls_stats.ktls_port[tx_info->port_id];
@@ -827,7 +882,8 @@ static int chcr_ktls_xmit_tcb_cpls(struct chcr_ktls_info *tx_info,
                                                 TCB_SND_UNA_RAW_V
                                                 (TCB_SND_UNA_RAW_M),
                                                 TCB_SND_UNA_RAW_V(0), 0);
-               atomic64_inc(&port_stats->ktls_tx_ooo);
+               if (tcp_seq != tx_info->prev_seq)
+                       atomic64_inc(&port_stats->ktls_tx_ooo);
                cpl++;
        }
        /* update ack */
@@ -856,7 +912,8 @@ static int chcr_ktls_xmit_tcb_cpls(struct chcr_ktls_info *tx_info,
                wr->op_to_compl = htonl(FW_WR_OP_V(FW_ULPTX_WR));
                wr->cookie = 0;
                /* fill len in wr field */
-               wr->flowid_len16 = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(len, 16)));
+               wr->flowid_len16 = htonl(wr_mid |
+                                        FW_WR_LEN16_V(DIV_ROUND_UP(len, 16)));
 
                ndesc = DIV_ROUND_UP(len, 64);
                chcr_txq_advance(&q->q, ndesc);
@@ -865,35 +922,15 @@ static int chcr_ktls_xmit_tcb_cpls(struct chcr_ktls_info *tx_info,
        return 0;
 }
 
-/*
- * chcr_ktls_skb_copy
- * @nskb - new skb where the frags to be added.
- * @skb - old skb from which frags will be copied.
- */
-static void chcr_ktls_skb_copy(struct sk_buff *skb, struct sk_buff *nskb)
-{
-       int i;
-
-       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-               skb_shinfo(nskb)->frags[i] = skb_shinfo(skb)->frags[i];
-               __skb_frag_ref(&skb_shinfo(nskb)->frags[i]);
-       }
-
-       skb_shinfo(nskb)->nr_frags = skb_shinfo(skb)->nr_frags;
-       nskb->len += skb->data_len;
-       nskb->data_len = skb->data_len;
-       nskb->truesize += skb->data_len;
-}
-
 /*
  * chcr_ktls_get_tx_flits
  * returns number of flits to be sent out, it includes key context length, WR
  * size and skb fragments.
  */
 static unsigned int
-chcr_ktls_get_tx_flits(const struct sk_buff *skb, unsigned int key_ctx_len)
+chcr_ktls_get_tx_flits(u32 nr_frags, unsigned int key_ctx_len)
 {
-       return chcr_sgl_len(skb_shinfo(skb)->nr_frags) +
+       return chcr_sgl_len(nr_frags) +
               DIV_ROUND_UP(key_ctx_len + CHCR_KTLS_WR_SIZE, 8);
 }
 
@@ -957,8 +994,10 @@ chcr_ktls_write_tcp_options(struct chcr_ktls_info *tx_info, struct sk_buff *skb,
        struct tcphdr *tcp;
        int len16, pktlen;
        struct iphdr *ip;
+       u32 wr_mid = 0;
        int credits;
        u8 buf[150];
+       u64 cntrl1;
        void *pos;
 
        iplen = skb_network_header_len(skb);
@@ -967,7 +1006,7 @@ chcr_ktls_write_tcp_options(struct chcr_ktls_info *tx_info, struct sk_buff *skb,
        /* packet length = eth hdr len + ip hdr len + tcp hdr len
         * (including options).
         */
-       pktlen = skb->len - skb->data_len;
+       pktlen = skb_transport_offset(skb) + tcp_hdrlen(skb);
 
        ctrl = sizeof(*cpl) + pktlen;
        len16 = DIV_ROUND_UP(sizeof(*wr) + ctrl, 16);
@@ -980,6 +1019,11 @@ chcr_ktls_write_tcp_options(struct chcr_ktls_info *tx_info, struct sk_buff *skb,
                return NETDEV_TX_BUSY;
        }
 
+       if (unlikely(credits < ETHTXQ_STOP_THRES)) {
+               chcr_eth_txq_stop(q);
+               wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F;
+       }
+
        pos = &q->q.desc[q->q.pidx];
        wr = pos;
 
@@ -987,7 +1031,7 @@ chcr_ktls_write_tcp_options(struct chcr_ktls_info *tx_info, struct sk_buff *skb,
        wr->op_immdlen = htonl(FW_WR_OP_V(FW_ETH_TX_PKT_WR) |
                               FW_WR_IMMDLEN_V(ctrl));
 
-       wr->equiq_to_len16 = htonl(FW_WR_LEN16_V(len16));
+       wr->equiq_to_len16 = htonl(wr_mid | FW_WR_LEN16_V(len16));
        wr->r3 = 0;
 
        cpl = (void *)(wr + 1);
@@ -997,22 +1041,28 @@ chcr_ktls_write_tcp_options(struct chcr_ktls_info *tx_info, struct sk_buff *skb,
                           TXPKT_PF_V(tx_info->adap->pf));
        cpl->pack = 0;
        cpl->len = htons(pktlen);
-       /* checksum offload */
-       cpl->ctrl1 = 0;
-
-       pos = cpl + 1;
 
        memcpy(buf, skb->data, pktlen);
        if (tx_info->ip_family == AF_INET) {
                /* we need to correct ip header len */
                ip = (struct iphdr *)(buf + maclen);
                ip->tot_len = htons(pktlen - maclen);
+               cntrl1 = TXPKT_CSUM_TYPE_V(TX_CSUM_TCPIP);
 #if IS_ENABLED(CONFIG_IPV6)
        } else {
                ip6 = (struct ipv6hdr *)(buf + maclen);
                ip6->payload_len = htons(pktlen - maclen - iplen);
+               cntrl1 = TXPKT_CSUM_TYPE_V(TX_CSUM_TCPIP6);
 #endif
        }
+
+       cntrl1 |= T6_TXPKT_ETHHDR_LEN_V(maclen - ETH_HLEN) |
+                 TXPKT_IPHDR_LEN_V(iplen);
+       /* checksum offload */
+       cpl->ctrl1 = cpu_to_be64(cntrl1);
+
+       pos = cpl + 1;
+
        /* now take care of the tcp header, if fin is not set then clear push
         * bit as well, and if fin is set, it will be sent at the last so we
         * need to update the tcp sequence number as per the last packet.
@@ -1031,71 +1081,6 @@ chcr_ktls_write_tcp_options(struct chcr_ktls_info *tx_info, struct sk_buff *skb,
        return 0;
 }
 
-/* chcr_ktls_skb_shift - Shifts request length paged data from skb to another.
- * @tgt- buffer into which tail data gets added
- * @skb- buffer from which the paged data comes from
- * @shiftlen- shift up to this many bytes
- */
-static int chcr_ktls_skb_shift(struct sk_buff *tgt, struct sk_buff *skb,
-                              int shiftlen)
-{
-       skb_frag_t *fragfrom, *fragto;
-       int from, to, todo;
-
-       WARN_ON(shiftlen > skb->data_len);
-
-       todo = shiftlen;
-       from = 0;
-       to = 0;
-       fragfrom = &skb_shinfo(skb)->frags[from];
-
-       while ((todo > 0) && (from < skb_shinfo(skb)->nr_frags)) {
-               fragfrom = &skb_shinfo(skb)->frags[from];
-               fragto = &skb_shinfo(tgt)->frags[to];
-
-               if (todo >= skb_frag_size(fragfrom)) {
-                       *fragto = *fragfrom;
-                       todo -= skb_frag_size(fragfrom);
-                       from++;
-                       to++;
-
-               } else {
-                       __skb_frag_ref(fragfrom);
-                       skb_frag_page_copy(fragto, fragfrom);
-                       skb_frag_off_copy(fragto, fragfrom);
-                       skb_frag_size_set(fragto, todo);
-
-                       skb_frag_off_add(fragfrom, todo);
-                       skb_frag_size_sub(fragfrom, todo);
-                       todo = 0;
-
-                       to++;
-                       break;
-               }
-       }
-
-       /* Ready to "commit" this state change to tgt */
-       skb_shinfo(tgt)->nr_frags = to;
-
-       /* Reposition in the original skb */
-       to = 0;
-       while (from < skb_shinfo(skb)->nr_frags)
-               skb_shinfo(skb)->frags[to++] = skb_shinfo(skb)->frags[from++];
-
-       skb_shinfo(skb)->nr_frags = to;
-
-       WARN_ON(todo > 0 && !skb_shinfo(skb)->nr_frags);
-
-       skb->len -= shiftlen;
-       skb->data_len -= shiftlen;
-       skb->truesize -= shiftlen;
-       tgt->len += shiftlen;
-       tgt->data_len += shiftlen;
-       tgt->truesize += shiftlen;
-
-       return shiftlen;
-}
-
 /*
  * chcr_ktls_xmit_wr_complete: This sends out the complete record. If an skb
  * received has partial end part of the record, send out the complete record, so
@@ -1111,6 +1096,8 @@ static int chcr_ktls_skb_shift(struct sk_buff *tgt, struct sk_buff *skb,
 static int chcr_ktls_xmit_wr_complete(struct sk_buff *skb,
                                      struct chcr_ktls_info *tx_info,
                                      struct sge_eth_txq *q, u32 tcp_seq,
+                                     bool is_last_wr, u32 data_len,
+                                     u32 skb_offset, u32 nfrags,
                                      bool tcp_push, u32 mss)
 {
        u32 len16, wr_mid = 0, flits = 0, ndesc, cipher_start;
@@ -1126,7 +1113,7 @@ static int chcr_ktls_xmit_wr_complete(struct sk_buff *skb,
        u64 *end;
 
        /* get the number of flits required */
-       flits = chcr_ktls_get_tx_flits(skb, tx_info->key_ctx_len);
+       flits = chcr_ktls_get_tx_flits(nfrags, tx_info->key_ctx_len);
        /* number of descriptors */
        ndesc = chcr_flits_to_desc(flits);
        /* check if enough credits available */
@@ -1155,6 +1142,9 @@ static int chcr_ktls_xmit_wr_complete(struct sk_buff *skb,
                return NETDEV_TX_BUSY;
        }
 
+       if (!is_last_wr)
+               skb_get(skb);
+
        pos = &q->q.desc[q->q.pidx];
        end = (u64 *)pos + flits;
        /* FW_ULPTX_WR */
@@ -1187,7 +1177,7 @@ static int chcr_ktls_xmit_wr_complete(struct sk_buff *skb,
                      CPL_TX_SEC_PDU_CPLLEN_V(CHCR_CPL_TX_SEC_PDU_LEN_64BIT) |
                      CPL_TX_SEC_PDU_PLACEHOLDER_V(1) |
                      CPL_TX_SEC_PDU_IVINSRTOFST_V(TLS_HEADER_SIZE + 1));
-       cpl->pldlen = htonl(skb->data_len);
+       cpl->pldlen = htonl(data_len);
 
        /* encryption should start after tls header size + iv size */
        cipher_start = TLS_HEADER_SIZE + tx_info->iv_size + 1;
@@ -1229,7 +1219,7 @@ static int chcr_ktls_xmit_wr_complete(struct sk_buff *skb,
        /* CPL_TX_DATA */
        tx_data = (void *)pos;
        OPCODE_TID(tx_data) = htonl(MK_OPCODE_TID(CPL_TX_DATA, tx_info->tid));
-       tx_data->len = htonl(TX_DATA_MSS_V(mss) | TX_LENGTH_V(skb->data_len));
+       tx_data->len = htonl(TX_DATA_MSS_V(mss) | TX_LENGTH_V(data_len));
 
        tx_data->rsvd = htonl(tcp_seq);
 
@@ -1249,8 +1239,8 @@ static int chcr_ktls_xmit_wr_complete(struct sk_buff *skb,
        }
 
        /* send the complete packet except the header */
-       cxgb4_write_sgl(skb, &q->q, pos, end, skb->len - skb->data_len,
-                       sgl_sdesc->addr);
+       cxgb4_write_partial_sgl(skb, &q->q, pos, end, sgl_sdesc->addr,
+                               skb_offset, data_len);
        sgl_sdesc->skb = skb;
 
        chcr_txq_advance(&q->q, ndesc);
@@ -1282,10 +1272,11 @@ static int chcr_ktls_xmit_wr_short(struct sk_buff *skb,
                                   struct sge_eth_txq *q,
                                   u32 tcp_seq, bool tcp_push, u32 mss,
                                   u32 tls_rec_offset, u8 *prior_data,
-                                  u32 prior_data_len)
+                                  u32 prior_data_len, u32 data_len,
+                                  u32 skb_offset)
 {
+       u32 len16, wr_mid = 0, cipher_start, nfrags;
        struct adapter *adap = tx_info->adap;
-       u32 len16, wr_mid = 0, cipher_start;
        unsigned int flits = 0, ndesc;
        int credits, left, last_desc;
        struct tx_sw_desc *sgl_sdesc;
@@ -1298,10 +1289,11 @@ static int chcr_ktls_xmit_wr_short(struct sk_buff *skb,
        void *pos;
        u64 *end;
 
+       nfrags = chcr_get_nfrags_to_send(skb, skb_offset, data_len);
        /* get the number of flits required, it's a partial record so 2 flits
         * (AES_BLOCK_SIZE) will be added.
         */
-       flits = chcr_ktls_get_tx_flits(skb, tx_info->key_ctx_len) + 2;
+       flits = chcr_ktls_get_tx_flits(nfrags, tx_info->key_ctx_len) + 2;
        /* get the correct 8 byte IV of this record */
        iv_record = cpu_to_be64(tx_info->iv + tx_info->record_no);
        /* If it's a middle record and not 16 byte aligned to run AES CTR, need
@@ -1373,7 +1365,7 @@ static int chcr_ktls_xmit_wr_short(struct sk_buff *skb,
                htonl(CPL_TX_SEC_PDU_OPCODE_V(CPL_TX_SEC_PDU) |
                      CPL_TX_SEC_PDU_CPLLEN_V(CHCR_CPL_TX_SEC_PDU_LEN_64BIT) |
                      CPL_TX_SEC_PDU_IVINSRTOFST_V(1));
-       cpl->pldlen = htonl(skb->data_len + AES_BLOCK_LEN + prior_data_len);
+       cpl->pldlen = htonl(data_len + AES_BLOCK_LEN + prior_data_len);
        cpl->aadstart_cipherstop_hi =
                htonl(CPL_TX_SEC_PDU_CIPHERSTART_V(cipher_start));
        cpl->cipherstop_lo_authinsert = 0;
@@ -1404,7 +1396,7 @@ static int chcr_ktls_xmit_wr_short(struct sk_buff *skb,
        tx_data = (void *)pos;
        OPCODE_TID(tx_data) = htonl(MK_OPCODE_TID(CPL_TX_DATA, tx_info->tid));
        tx_data->len = htonl(TX_DATA_MSS_V(mss) |
-                       TX_LENGTH_V(skb->data_len + prior_data_len));
+                            TX_LENGTH_V(data_len + prior_data_len));
        tx_data->rsvd = htonl(tcp_seq);
        tx_data->flags = htonl(TX_BYPASS_F);
        if (tcp_push)
@@ -1437,8 +1429,8 @@ static int chcr_ktls_xmit_wr_short(struct sk_buff *skb,
        if (prior_data_len)
                pos = chcr_copy_to_txd(prior_data, &q->q, pos, 16);
        /* send the complete packet except the header */
-       cxgb4_write_sgl(skb, &q->q, pos, end, skb->len - skb->data_len,
-                       sgl_sdesc->addr);
+       cxgb4_write_partial_sgl(skb, &q->q, pos, end, sgl_sdesc->addr,
+                               skb_offset, data_len);
        sgl_sdesc->skb = skb;
 
        chcr_txq_advance(&q->q, ndesc);
@@ -1466,6 +1458,7 @@ static int chcr_ktls_tx_plaintxt(struct chcr_ktls_info *tx_info,
                                 struct sk_buff *skb, u32 tcp_seq, u32 mss,
                                 bool tcp_push, struct sge_eth_txq *q,
                                 u32 port_id, u8 *prior_data,
+                                u32 data_len, u32 skb_offset,
                                 u32 prior_data_len)
 {
        int credits, left, len16, last_desc;
@@ -1475,14 +1468,16 @@ static int chcr_ktls_tx_plaintxt(struct chcr_ktls_info *tx_info,
        struct ulptx_idata *idata;
        struct ulp_txpkt *ulptx;
        struct fw_ulptx_wr *wr;
-       u32 wr_mid = 0;
+       u32 wr_mid = 0, nfrags;
        void *pos;
        u64 *end;
 
        flits = DIV_ROUND_UP(CHCR_PLAIN_TX_DATA_LEN, 8);
-       flits += chcr_sgl_len(skb_shinfo(skb)->nr_frags);
+       nfrags = chcr_get_nfrags_to_send(skb, skb_offset, data_len);
+       flits += chcr_sgl_len(nfrags);
        if (prior_data_len)
                flits += 2;
+
        /* WR will need len16 */
        len16 = DIV_ROUND_UP(flits, 2);
        /* check how many descriptors needed */
@@ -1535,7 +1530,7 @@ static int chcr_ktls_tx_plaintxt(struct chcr_ktls_info *tx_info,
        tx_data = (struct cpl_tx_data *)(idata + 1);
        OPCODE_TID(tx_data) = htonl(MK_OPCODE_TID(CPL_TX_DATA, tx_info->tid));
        tx_data->len = htonl(TX_DATA_MSS_V(mss) |
-                       TX_LENGTH_V(skb->data_len + prior_data_len));
+                            TX_LENGTH_V(data_len + prior_data_len));
        /* set tcp seq number */
        tx_data->rsvd = htonl(tcp_seq);
        tx_data->flags = htonl(TX_BYPASS_F);
@@ -1559,8 +1554,8 @@ static int chcr_ktls_tx_plaintxt(struct chcr_ktls_info *tx_info,
                end = pos + left;
        }
        /* send the complete packet including the header */
-       cxgb4_write_sgl(skb, &q->q, pos, end, skb->len - skb->data_len,
-                       sgl_sdesc->addr);
+       cxgb4_write_partial_sgl(skb, &q->q, pos, end, sgl_sdesc->addr,
+                               skb_offset, data_len);
        sgl_sdesc->skb = skb;
 
        chcr_txq_advance(&q->q, ndesc);
@@ -1568,12 +1563,96 @@ static int chcr_ktls_tx_plaintxt(struct chcr_ktls_info *tx_info,
        return 0;
 }
 
+static int chcr_ktls_tunnel_pkt(struct chcr_ktls_info *tx_info,
+                               struct sk_buff *skb,
+                               struct sge_eth_txq *q)
+{
+       u32 ctrl, iplen, maclen, wr_mid = 0, len16;
+       struct tx_sw_desc *sgl_sdesc;
+       struct fw_eth_tx_pkt_wr *wr;
+       struct cpl_tx_pkt_core *cpl;
+       unsigned int flits, ndesc;
+       int credits, last_desc;
+       u64 cntrl1, *end;
+       void *pos;
+
+       ctrl = sizeof(*cpl);
+       flits = DIV_ROUND_UP(sizeof(*wr) + ctrl, 8);
+
+       flits += chcr_sgl_len(skb_shinfo(skb)->nr_frags + 1);
+       len16 = DIV_ROUND_UP(flits, 2);
+       /* check how many descriptors needed */
+       ndesc = DIV_ROUND_UP(flits, 8);
+
+       credits = chcr_txq_avail(&q->q) - ndesc;
+       if (unlikely(credits < 0)) {
+               chcr_eth_txq_stop(q);
+               return -ENOMEM;
+       }
+
+       if (unlikely(credits < ETHTXQ_STOP_THRES)) {
+               chcr_eth_txq_stop(q);
+               wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F;
+       }
+
+       last_desc = q->q.pidx + ndesc - 1;
+       if (last_desc >= q->q.size)
+               last_desc -= q->q.size;
+       sgl_sdesc = &q->q.sdesc[last_desc];
+
+       if (unlikely(cxgb4_map_skb(tx_info->adap->pdev_dev, skb,
+                                  sgl_sdesc->addr) < 0)) {
+               memset(sgl_sdesc->addr, 0, sizeof(sgl_sdesc->addr));
+               q->mapping_err++;
+               return -ENOMEM;
+       }
+
+       iplen = skb_network_header_len(skb);
+       maclen = skb_mac_header_len(skb);
+
+       pos = &q->q.desc[q->q.pidx];
+       end = (u64 *)pos + flits;
+       wr = pos;
+
+       /* Firmware work request header */
+       wr->op_immdlen = htonl(FW_WR_OP_V(FW_ETH_TX_PKT_WR) |
+                              FW_WR_IMMDLEN_V(ctrl));
+
+       wr->equiq_to_len16 = htonl(wr_mid | FW_WR_LEN16_V(len16));
+       wr->r3 = 0;
+
+       cpl = (void *)(wr + 1);
+
+       /* CPL header */
+       cpl->ctrl0 = htonl(TXPKT_OPCODE_V(CPL_TX_PKT) |
+                          TXPKT_INTF_V(tx_info->tx_chan) |
+                          TXPKT_PF_V(tx_info->adap->pf));
+       cpl->pack = 0;
+       cntrl1 = TXPKT_CSUM_TYPE_V(tx_info->ip_family == AF_INET ?
+                                  TX_CSUM_TCPIP : TX_CSUM_TCPIP6);
+       cntrl1 |= T6_TXPKT_ETHHDR_LEN_V(maclen - ETH_HLEN) |
+                 TXPKT_IPHDR_LEN_V(iplen);
+       /* checksum offload */
+       cpl->ctrl1 = cpu_to_be64(cntrl1);
+       cpl->len = htons(skb->len);
+
+       pos = cpl + 1;
+
+       cxgb4_write_sgl(skb, &q->q, pos, end, 0, sgl_sdesc->addr);
+       sgl_sdesc->skb = skb;
+       chcr_txq_advance(&q->q, ndesc);
+       cxgb4_ring_tx_db(tx_info->adap, &q->q, ndesc);
+       return 0;
+}
+
 /*
  * chcr_ktls_copy_record_in_skb
  * @nskb - new skb where the frags to be added.
+ * @skb - old skb, to copy socket and destructor details.
  * @record - specific record which has complete 16k record in frags.
  */
 static void chcr_ktls_copy_record_in_skb(struct sk_buff *nskb,
+                                        struct sk_buff *skb,
                                         struct tls_record_info *record)
 {
        int i = 0;
@@ -1588,6 +1667,9 @@ static void chcr_ktls_copy_record_in_skb(struct sk_buff *nskb,
        nskb->data_len = record->len;
        nskb->len += record->len;
        nskb->truesize += record->len;
+       nskb->sk = skb->sk;
+       nskb->destructor = skb->destructor;
+       refcount_add(nskb->truesize, &nskb->sk->sk_wmem_alloc);
 }
 
 /*
@@ -1659,7 +1741,7 @@ static int chcr_end_part_handler(struct chcr_ktls_info *tx_info,
                                 struct sk_buff *skb,
                                 struct tls_record_info *record,
                                 u32 tcp_seq, int mss, bool tcp_push_no_fin,
-                                struct sge_eth_txq *q,
+                                struct sge_eth_txq *q, u32 skb_offset,
                                 u32 tls_end_offset, bool last_wr)
 {
        struct sk_buff *nskb = NULL;
@@ -1668,30 +1750,37 @@ static int chcr_end_part_handler(struct chcr_ktls_info *tx_info,
                nskb = skb;
                atomic64_inc(&tx_info->adap->ch_ktls_stats.ktls_tx_complete_pkts);
        } else {
-               dev_kfree_skb_any(skb);
-
-               nskb = alloc_skb(0, GFP_KERNEL);
-               if (!nskb)
+               nskb = alloc_skb(0, GFP_ATOMIC);
+               if (!nskb) {
+                       dev_kfree_skb_any(skb);
                        return NETDEV_TX_BUSY;
+               }
+
                /* copy complete record in skb */
-               chcr_ktls_copy_record_in_skb(nskb, record);
+               chcr_ktls_copy_record_in_skb(nskb, skb, record);
                /* packet is being sent from the beginning, update the tcp_seq
                 * accordingly.
                 */
                tcp_seq = tls_record_start_seq(record);
-               /* reset snd una, so the middle record won't send the already
-                * sent part.
-                */
-               if (chcr_ktls_update_snd_una(tx_info, q))
-                       goto out;
+               /* reset skb offset */
+               skb_offset = 0;
+
+               if (last_wr)
+                       dev_kfree_skb_any(skb);
+
+               last_wr = true;
+
                atomic64_inc(&tx_info->adap->ch_ktls_stats.ktls_tx_end_pkts);
        }
 
        if (chcr_ktls_xmit_wr_complete(nskb, tx_info, q, tcp_seq,
+                                      last_wr, record->len, skb_offset,
+                                      record->num_frags,
                                       (last_wr && tcp_push_no_fin),
                                       mss)) {
                goto out;
        }
+       tx_info->prev_seq = record->end_seq;
        return 0;
 out:
        dev_kfree_skb_any(nskb);
@@ -1723,41 +1812,47 @@ static int chcr_short_record_handler(struct chcr_ktls_info *tx_info,
                                     struct sk_buff *skb,
                                     struct tls_record_info *record,
                                     u32 tcp_seq, int mss, bool tcp_push_no_fin,
+                                    u32 data_len, u32 skb_offset,
                                     struct sge_eth_txq *q, u32 tls_end_offset)
 {
        u32 tls_rec_offset = tcp_seq - tls_record_start_seq(record);
        u8 prior_data[16] = {0};
        u32 prior_data_len = 0;
-       u32 data_len;
 
        /* check if the skb is ending in middle of tag/HASH, its a big
         * trouble, send the packet before the HASH.
         */
-       int remaining_record = tls_end_offset - skb->data_len;
+       int remaining_record = tls_end_offset - data_len;
 
        if (remaining_record > 0 &&
            remaining_record < TLS_CIPHER_AES_GCM_128_TAG_SIZE) {
-               int trimmed_len = skb->data_len -
-                       (TLS_CIPHER_AES_GCM_128_TAG_SIZE - remaining_record);
-               struct sk_buff *tmp_skb = NULL;
-               /* don't process the pkt if it is only a partial tag */
-               if (skb->data_len < TLS_CIPHER_AES_GCM_128_TAG_SIZE)
-                       goto out;
+               int trimmed_len = 0;
 
-               WARN_ON(trimmed_len > skb->data_len);
+               if (tls_end_offset > TLS_CIPHER_AES_GCM_128_TAG_SIZE)
+                       trimmed_len = data_len -
+                                     (TLS_CIPHER_AES_GCM_128_TAG_SIZE -
+                                      remaining_record);
+               if (!trimmed_len)
+                       return FALLBACK;
 
-               /* shift to those many bytes */
-               tmp_skb = alloc_skb(0, GFP_KERNEL);
-               if (unlikely(!tmp_skb))
-                       goto out;
+               WARN_ON(trimmed_len > data_len);
 
-               chcr_ktls_skb_shift(tmp_skb, skb, trimmed_len);
-               /* free the last trimmed portion */
-               dev_kfree_skb_any(skb);
-               skb = tmp_skb;
+               data_len = trimmed_len;
                atomic64_inc(&tx_info->adap->ch_ktls_stats.ktls_tx_trimmed_pkts);
        }
-       data_len = skb->data_len;
+
+       /* check if it is only the header part. */
+       if (tls_rec_offset + data_len <= (TLS_HEADER_SIZE + tx_info->iv_size)) {
+               if (chcr_ktls_tx_plaintxt(tx_info, skb, tcp_seq, mss,
+                                         tcp_push_no_fin, q,
+                                         tx_info->port_id, prior_data,
+                                         data_len, skb_offset, prior_data_len))
+                       goto out;
+
+               tx_info->prev_seq = tcp_seq + data_len;
+               return 0;
+       }
+
        /* check if the middle record's start point is 16 byte aligned. CTR
         * needs 16 byte aligned start point to start encryption.
         */
@@ -1818,9 +1913,6 @@ static int chcr_short_record_handler(struct chcr_ktls_info *tx_info,
                        }
                        /* reset tcp_seq as per the prior_data_required len */
                        tcp_seq -= prior_data_len;
-                       /* include prio_data_len for  further calculation.
-                        */
-                       data_len += prior_data_len;
                }
                /* reset snd una, so the middle record won't send the already
                 * sent part.
@@ -1829,37 +1921,54 @@ static int chcr_short_record_handler(struct chcr_ktls_info *tx_info,
                        goto out;
                atomic64_inc(&tx_info->adap->ch_ktls_stats.ktls_tx_middle_pkts);
        } else {
-               /* Else means, its a partial first part of the record. Check if
-                * its only the header, don't need to send for encryption then.
-                */
-               if (data_len <= TLS_HEADER_SIZE + tx_info->iv_size) {
-                       if (chcr_ktls_tx_plaintxt(tx_info, skb, tcp_seq, mss,
-                                                 tcp_push_no_fin, q,
-                                                 tx_info->port_id,
-                                                 prior_data,
-                                                 prior_data_len)) {
-                               goto out;
-                       }
-                       return 0;
-               }
                atomic64_inc(&tx_info->adap->ch_ktls_stats.ktls_tx_start_pkts);
        }
 
        if (chcr_ktls_xmit_wr_short(skb, tx_info, q, tcp_seq, tcp_push_no_fin,
                                    mss, tls_rec_offset, prior_data,
-                                   prior_data_len)) {
+                                   prior_data_len, data_len, skb_offset)) {
                goto out;
        }
 
+       tx_info->prev_seq = tcp_seq + data_len + prior_data_len;
        return 0;
 out:
        dev_kfree_skb_any(skb);
        return NETDEV_TX_BUSY;
 }
 
+static int chcr_ktls_sw_fallback(struct sk_buff *skb,
+                                struct chcr_ktls_info *tx_info,
+                                struct sge_eth_txq *q)
+{
+       u32 data_len, skb_offset;
+       struct sk_buff *nskb;
+       struct tcphdr *th;
+
+       nskb = tls_encrypt_skb(skb);
+
+       if (!nskb)
+               return 0;
+
+       th = tcp_hdr(nskb);
+       skb_offset =  skb_transport_offset(nskb) + tcp_hdrlen(nskb);
+       data_len = nskb->len - skb_offset;
+       skb_tx_timestamp(nskb);
+
+       if (chcr_ktls_tunnel_pkt(tx_info, nskb, q))
+               goto out;
+
+       tx_info->prev_seq = ntohl(th->seq) + data_len;
+       atomic64_inc(&tx_info->adap->ch_ktls_stats.ktls_tx_fallback);
+       return 0;
+out:
+       dev_kfree_skb_any(nskb);
+       return 0;
+}
 /* nic tls TX handler */
 static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+       u32 tls_end_offset, tcp_seq, skb_data_len, skb_offset;
        struct ch_ktls_port_stats_debug *port_stats;
        struct chcr_ktls_ofld_ctx_tx *tx_ctx;
        struct ch_ktls_stats_debug *stats;
@@ -1867,20 +1976,17 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev)
        int data_len, qidx, ret = 0, mss;
        struct tls_record_info *record;
        struct chcr_ktls_info *tx_info;
-       u32 tls_end_offset, tcp_seq;
        struct tls_context *tls_ctx;
-       struct sk_buff *local_skb;
        struct sge_eth_txq *q;
        struct adapter *adap;
        unsigned long flags;
 
        tcp_seq = ntohl(th->seq);
+       skb_offset = skb_transport_offset(skb) + tcp_hdrlen(skb);
+       skb_data_len = skb->len - skb_offset;
+       data_len = skb_data_len;
 
-       mss = skb_is_gso(skb) ? skb_shinfo(skb)->gso_size : skb->data_len;
-
-       /* check if we haven't set it for ktls offload */
-       if (!skb->sk || !tls_is_sk_tx_device_offloaded(skb->sk))
-               goto out;
+       mss = skb_is_gso(skb) ? skb_shinfo(skb)->gso_size : data_len;
 
        tls_ctx = tls_get_ctx(skb->sk);
        if (unlikely(tls_ctx->netdev != dev))
@@ -1892,14 +1998,6 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev)
        if (unlikely(!tx_info))
                goto out;
 
-       /* don't touch the original skb, make a new skb to extract each records
-        * and send them separately.
-        */
-       local_skb = alloc_skb(0, GFP_KERNEL);
-
-       if (unlikely(!local_skb))
-               return NETDEV_TX_BUSY;
-
        adap = tx_info->adap;
        stats = &adap->ch_ktls_stats;
        port_stats = &stats->ktls_port[tx_info->port_id];
@@ -1914,20 +2012,7 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev)
                if (ret)
                        return NETDEV_TX_BUSY;
        }
-       /* update tcb */
-       ret = chcr_ktls_xmit_tcb_cpls(tx_info, q, ntohl(th->seq),
-                                     ntohl(th->ack_seq),
-                                     ntohs(th->window));
-       if (ret) {
-               dev_kfree_skb_any(local_skb);
-               return NETDEV_TX_BUSY;
-       }
 
-       /* copy skb contents into local skb */
-       chcr_ktls_skb_copy(skb, local_skb);
-
-       /* go through the skb and send only one record at a time. */
-       data_len = skb->data_len;
        /* TCP segments can be in received either complete or partial.
         * chcr_end_part_handler will handle cases if complete record or end
         * part of the record is received. Incase of partial end part of record,
@@ -1952,10 +2037,64 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev)
                        goto out;
                }
 
+               tls_end_offset = record->end_seq - tcp_seq;
+
+               pr_debug("seq 0x%x, end_seq 0x%x prev_seq 0x%x, datalen 0x%x\n",
+                        tcp_seq, record->end_seq, tx_info->prev_seq, data_len);
+               /* update tcb for the skb */
+               if (skb_data_len == data_len) {
+                       u32 tx_max = tcp_seq;
+
+                       if (!tls_record_is_start_marker(record) &&
+                           tls_end_offset < TLS_CIPHER_AES_GCM_128_TAG_SIZE)
+                               tx_max = record->end_seq -
+                                       TLS_CIPHER_AES_GCM_128_TAG_SIZE;
+
+                       ret = chcr_ktls_xmit_tcb_cpls(tx_info, q, tx_max,
+                                                     ntohl(th->ack_seq),
+                                                     ntohs(th->window),
+                                                     tls_end_offset !=
+                                                     record->len);
+                       if (ret) {
+                               spin_unlock_irqrestore(&tx_ctx->base.lock,
+                                                      flags);
+                               goto out;
+                       }
+
+                       if (th->fin)
+                               skb_get(skb);
+               }
+
                if (unlikely(tls_record_is_start_marker(record))) {
-                       spin_unlock_irqrestore(&tx_ctx->base.lock, flags);
                        atomic64_inc(&port_stats->ktls_tx_skip_no_sync_data);
-                       goto out;
+                       /* If tls_end_offset < data_len, means there is some
+                        * data after start marker, which needs encryption, send
+                        * plaintext first and take skb refcount. else send out
+                        * complete pkt as plaintext.
+                        */
+                       if (tls_end_offset < data_len)
+                               skb_get(skb);
+                       else
+                               tls_end_offset = data_len;
+
+                       ret = chcr_ktls_tx_plaintxt(tx_info, skb, tcp_seq, mss,
+                                                   (!th->fin && th->psh), q,
+                                                   tx_info->port_id, NULL,
+                                                   tls_end_offset, skb_offset,
+                                                   0);
+
+                       spin_unlock_irqrestore(&tx_ctx->base.lock, flags);
+                       if (ret) {
+                               /* free the refcount taken earlier */
+                               if (tls_end_offset < data_len)
+                                       dev_kfree_skb_any(skb);
+                               goto out;
+                       }
+
+                       data_len -= tls_end_offset;
+                       tcp_seq = record->end_seq;
+                       skb_offset += tls_end_offset;
+                       continue;
                }
 
                /* increase page reference count of the record, so that there
@@ -1967,73 +2106,64 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev)
                /* lock cleared */
                spin_unlock_irqrestore(&tx_ctx->base.lock, flags);
 
-               tls_end_offset = record->end_seq - tcp_seq;
 
-               pr_debug("seq 0x%x, end_seq 0x%x prev_seq 0x%x, datalen 0x%x\n",
-                        tcp_seq, record->end_seq, tx_info->prev_seq, data_len);
                /* if a tls record is finishing in this SKB */
                if (tls_end_offset <= data_len) {
-                       struct sk_buff *nskb = NULL;
-
-                       if (tls_end_offset < data_len) {
-                               nskb = alloc_skb(0, GFP_KERNEL);
-                               if (unlikely(!nskb)) {
-                                       ret = -ENOMEM;
-                                       goto clear_ref;
-                               }
-
-                               chcr_ktls_skb_shift(nskb, local_skb,
-                                                   tls_end_offset);
-                       } else {
-                               /* its the only record in this skb, directly
-                                * point it.
-                                */
-                               nskb = local_skb;
-                       }
-                       ret = chcr_end_part_handler(tx_info, nskb, record,
+                       ret = chcr_end_part_handler(tx_info, skb, record,
                                                    tcp_seq, mss,
                                                    (!th->fin && th->psh), q,
+                                                   skb_offset,
                                                    tls_end_offset,
-                                                   (nskb == local_skb));
-
-                       if (ret && nskb != local_skb)
-                               dev_kfree_skb_any(local_skb);
+                                                   skb_offset +
+                                                   tls_end_offset == skb->len);
 
                        data_len -= tls_end_offset;
                        /* tcp_seq increment is required to handle next record.
                         */
                        tcp_seq += tls_end_offset;
+                       skb_offset += tls_end_offset;
                } else {
-                       ret = chcr_short_record_handler(tx_info, local_skb,
+                       ret = chcr_short_record_handler(tx_info, skb,
                                                        record, tcp_seq, mss,
                                                        (!th->fin && th->psh),
+                                                       data_len, skb_offset,
                                                        q, tls_end_offset);
                        data_len = 0;
                }
-clear_ref:
+
                /* clear the frag ref count which increased locally before */
                for (i = 0; i < record->num_frags; i++) {
                        /* clear the frag ref count */
                        __skb_frag_unref(&record->frags[i]);
                }
                /* if any failure, come out from the loop. */
-               if (ret)
-                       goto out;
+               if (ret) {
+                       if (th->fin)
+                               dev_kfree_skb_any(skb);
+
+                       if (ret == FALLBACK)
+                               return chcr_ktls_sw_fallback(skb, tx_info, q);
+
+                       return NETDEV_TX_OK;
+               }
+
                /* length should never be less than 0 */
                WARN_ON(data_len < 0);
 
        } while (data_len > 0);
 
-       tx_info->prev_seq = ntohl(th->seq) + skb->data_len;
        atomic64_inc(&port_stats->ktls_tx_encrypted_packets);
-       atomic64_add(skb->data_len, &port_stats->ktls_tx_encrypted_bytes);
+       atomic64_add(skb_data_len, &port_stats->ktls_tx_encrypted_bytes);
 
        /* tcp finish is set, send a separate tcp msg including all the options
         * as well.
         */
-       if (th->fin)
+       if (th->fin) {
                chcr_ktls_write_tcp_options(tx_info, skb, q, tx_info->tx_chan);
+               dev_kfree_skb_any(skb);
+       }
 
+       return NETDEV_TX_OK;
 out:
        dev_kfree_skb_any(skb);
        return NETDEV_TX_OK;
index c1651b1431a031223c88f87d51de31fc11e3c583..18b3b1f024156cdbd4a503b0f51ce26f56775e32 100644 (file)
@@ -26,6 +26,7 @@
 
 #define CHCR_KTLS_WR_SIZE      (CHCR_PLAIN_TX_DATA_LEN +\
                                 sizeof(struct cpl_tx_sec_pdu))
+#define FALLBACK               35
 
 enum ch_ktls_open_state {
        CH_KTLS_OPEN_SUCCESS = 0,
index ec4f79049a061bda7109b686d1525ea238d52f9d..50e3a70e5a290a1f0e9dbafbfc7e813ed3bd6d40 100644 (file)
@@ -212,7 +212,7 @@ static struct sk_buff *alloc_ctrl_skb(struct sk_buff *skb, int len)
 {
        if (likely(skb && !skb_shared(skb) && !skb_cloned(skb))) {
                __skb_trim(skb, 0);
-               refcount_add(2, &skb->users);
+               refcount_inc(&skb->users);
        } else {
                skb = alloc_skb(len, GFP_KERNEL | __GFP_NOFAIL);
        }
@@ -772,14 +772,13 @@ static int chtls_pass_open_rpl(struct chtls_dev *cdev, struct sk_buff *skb)
        if (rpl->status != CPL_ERR_NONE) {
                pr_info("Unexpected PASS_OPEN_RPL status %u for STID %u\n",
                        rpl->status, stid);
-               return CPL_RET_BUF_DONE;
+       } else {
+               cxgb4_free_stid(cdev->tids, stid, listen_ctx->lsk->sk_family);
+               sock_put(listen_ctx->lsk);
+               kfree(listen_ctx);
+               module_put(THIS_MODULE);
        }
-       cxgb4_free_stid(cdev->tids, stid, listen_ctx->lsk->sk_family);
-       sock_put(listen_ctx->lsk);
-       kfree(listen_ctx);
-       module_put(THIS_MODULE);
-
-       return 0;
+       return CPL_RET_BUF_DONE;
 }
 
 static int chtls_close_listsrv_rpl(struct chtls_dev *cdev, struct sk_buff *skb)
@@ -796,15 +795,13 @@ static int chtls_close_listsrv_rpl(struct chtls_dev *cdev, struct sk_buff *skb)
        if (rpl->status != CPL_ERR_NONE) {
                pr_info("Unexpected CLOSE_LISTSRV_RPL status %u for STID %u\n",
                        rpl->status, stid);
-               return CPL_RET_BUF_DONE;
+       } else {
+               cxgb4_free_stid(cdev->tids, stid, listen_ctx->lsk->sk_family);
+               sock_put(listen_ctx->lsk);
+               kfree(listen_ctx);
+               module_put(THIS_MODULE);
        }
-
-       cxgb4_free_stid(cdev->tids, stid, listen_ctx->lsk->sk_family);
-       sock_put(listen_ctx->lsk);
-       kfree(listen_ctx);
-       module_put(THIS_MODULE);
-
-       return 0;
+       return CPL_RET_BUF_DONE;
 }
 
 static void chtls_purge_wr_queue(struct sock *sk)
@@ -1209,6 +1206,7 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
        sk_setup_caps(newsk, dst);
        ctx = tls_get_ctx(lsk);
        newsk->sk_destruct = ctx->sk_destruct;
+       newsk->sk_prot_creator = lsk->sk_prot_creator;
        csk->sk = newsk;
        csk->passive_reap_next = oreq;
        csk->tx_chan = cxgb4_port_chan(ndev);
@@ -1514,7 +1512,6 @@ static void add_to_reap_list(struct sock *sk)
        struct chtls_sock *csk = sk->sk_user_data;
 
        local_bh_disable();
-       bh_lock_sock(sk);
        release_tcp_port(sk); /* release the port immediately */
 
        spin_lock(&reap_list_lock);
@@ -1523,7 +1520,6 @@ static void add_to_reap_list(struct sock *sk)
        if (!csk->passive_reap_next)
                schedule_work(&reap_task);
        spin_unlock(&reap_list_lock);
-       bh_unlock_sock(sk);
        local_bh_enable();
 }
 
index f1820aca0d336902a1228db69e4f5c40b2e056f9..a4fb463af22ac335c425532787f4b8a7bb91e11d 100644 (file)
@@ -383,11 +383,15 @@ int chtls_setkey(struct chtls_sock *csk, u32 keylen,
        if (ret)
                goto out_notcb;
 
+       if (unlikely(csk_flag(sk, CSK_ABORT_SHUTDOWN)))
+               goto out_notcb;
+
        set_wr_txq(skb, CPL_PRIORITY_DATA, csk->tlshws.txqid);
        csk->wr_credits -= DIV_ROUND_UP(len, 16);
        csk->wr_unacked += DIV_ROUND_UP(len, 16);
        enqueue_wr(csk, skb);
        cxgb4_ofld_send(csk->egress_dev, skb);
+       skb = NULL;
 
        chtls_set_scmd(csk);
        /* Clear quiesce for Rx key */
index 9fb5ca6682ea23fe2b2e4d488b8d6ede74f81bbe..188d871f6b8cdbf613a50edd09b48aa1fde39b88 100644 (file)
@@ -1585,6 +1585,7 @@ skip_copy:
                        tp->urg_data = 0;
 
                if ((avail + offset) >= skb->len) {
+                       struct sk_buff *next_skb;
                        if (ULP_SKB_CB(skb)->flags & ULPCB_FLAG_TLS_HDR) {
                                tp->copied_seq += skb->len;
                                hws->rcvpld = skb->hdr_len;
@@ -1595,8 +1596,10 @@ skip_copy:
                        chtls_free_skb(sk, skb);
                        buffers_freed++;
                        hws->copied_seq = 0;
-                       if (copied >= target &&
-                           !skb_peek(&sk->sk_receive_queue))
+                       next_skb = skb_peek(&sk->sk_receive_queue);
+                       if (copied >= target && !next_skb)
+                               break;
+                       if (ULP_SKB_CB(next_skb)->flags & ULPCB_FLAG_TLS_HDR)
                                break;
                }
        } while (len > 0);
index 00024dd411471a3295a5d3e2c3f198136d479502..80fb1f537bb331baf40b64e0bacc6fa2da78228e 100644 (file)
@@ -1907,6 +1907,8 @@ err_register_netdev:
        clk_disable_unprepare(priv->rclk);
        clk_disable_unprepare(priv->clk);
 err_ncsi_dev:
+       if (priv->ndev)
+               ncsi_unregister_dev(priv->ndev);
        ftgmac100_destroy_mdio(netdev);
 err_setup_mdio:
        iounmap(priv->base);
@@ -1926,6 +1928,8 @@ static int ftgmac100_remove(struct platform_device *pdev)
        netdev = platform_get_drvdata(pdev);
        priv = netdev_priv(netdev);
 
+       if (priv->ndev)
+               ncsi_unregister_dev(priv->ndev);
        unregister_netdev(netdev);
 
        clk_disable_unprepare(priv->rclk);
index 06cc863f4dd63258556f18af04bf8898b3a76ff5..cb7c028b1bf5a9a3f057c9408e327d5775421b5c 100644 (file)
@@ -174,12 +174,17 @@ MODULE_PARM_DESC(tx_timeout, "The Tx timeout in ms");
 #define DPAA_PARSE_RESULTS_SIZE sizeof(struct fman_prs_result)
 #define DPAA_TIME_STAMP_SIZE 8
 #define DPAA_HASH_RESULTS_SIZE 8
+#define DPAA_HWA_SIZE (DPAA_PARSE_RESULTS_SIZE + DPAA_TIME_STAMP_SIZE \
+                      + DPAA_HASH_RESULTS_SIZE)
+#define DPAA_RX_PRIV_DATA_DEFAULT_SIZE (DPAA_TX_PRIV_DATA_SIZE + \
+                                       dpaa_rx_extra_headroom)
 #ifdef CONFIG_DPAA_ERRATUM_A050385
-#define DPAA_RX_PRIV_DATA_SIZE (DPAA_A050385_ALIGN - (DPAA_PARSE_RESULTS_SIZE\
-        + DPAA_TIME_STAMP_SIZE + DPAA_HASH_RESULTS_SIZE))
+#define DPAA_RX_PRIV_DATA_A050385_SIZE (DPAA_A050385_ALIGN - DPAA_HWA_SIZE)
+#define DPAA_RX_PRIV_DATA_SIZE (fman_has_errata_a050385() ? \
+                               DPAA_RX_PRIV_DATA_A050385_SIZE : \
+                               DPAA_RX_PRIV_DATA_DEFAULT_SIZE)
 #else
-#define DPAA_RX_PRIV_DATA_SIZE (u16)(DPAA_TX_PRIV_DATA_SIZE + \
-                                       dpaa_rx_extra_headroom)
+#define DPAA_RX_PRIV_DATA_SIZE DPAA_RX_PRIV_DATA_DEFAULT_SIZE
 #endif
 
 #define DPAA_ETH_PCD_RXQ_NUM   128
@@ -2115,6 +2120,15 @@ workaround:
        skb_copy_header(new_skb, skb);
        new_skb->dev = skb->dev;
 
+       /* Copy relevant timestamp info from the old skb to the new */
+       if (priv->tx_tstamp) {
+               skb_shinfo(new_skb)->tx_flags = skb_shinfo(skb)->tx_flags;
+               skb_shinfo(new_skb)->hwtstamps = skb_shinfo(skb)->hwtstamps;
+               skb_shinfo(new_skb)->tskey = skb_shinfo(skb)->tskey;
+               if (skb->sk)
+                       skb_set_owner_w(new_skb, skb->sk);
+       }
+
        /* We move the headroom when we align it so we have to reset the
         * network and transport header offsets relative to the new data
         * pointer. The checksum offload relies on these offsets.
@@ -2122,7 +2136,6 @@ workaround:
        skb_set_network_header(new_skb, skb_network_offset(skb));
        skb_set_transport_header(new_skb, skb_transport_offset(skb));
 
-       /* TODO: does timestamping need the result in the old skb? */
        dev_kfree_skb(skb);
        *s = new_skb;
 
@@ -2840,7 +2853,8 @@ out_error:
        return err;
 }
 
-static inline u16 dpaa_get_headroom(struct dpaa_buffer_layout *bl)
+static u16 dpaa_get_headroom(struct dpaa_buffer_layout *bl,
+                            enum port_type port)
 {
        u16 headroom;
 
@@ -2854,10 +2868,12 @@ static inline u16 dpaa_get_headroom(struct dpaa_buffer_layout *bl)
         *
         * Also make sure the headroom is a multiple of data_align bytes
         */
-       headroom = (u16)(bl->priv_data_size + DPAA_PARSE_RESULTS_SIZE +
-               DPAA_TIME_STAMP_SIZE + DPAA_HASH_RESULTS_SIZE);
+       headroom = (u16)(bl[port].priv_data_size + DPAA_HWA_SIZE);
 
-       return ALIGN(headroom, DPAA_FD_DATA_ALIGNMENT);
+       if (port == RX)
+               return ALIGN(headroom, DPAA_FD_RX_DATA_ALIGNMENT);
+       else
+               return ALIGN(headroom, DPAA_FD_DATA_ALIGNMENT);
 }
 
 static int dpaa_eth_probe(struct platform_device *pdev)
@@ -3025,8 +3041,8 @@ static int dpaa_eth_probe(struct platform_device *pdev)
                        goto free_dpaa_fqs;
        }
 
-       priv->tx_headroom = dpaa_get_headroom(&priv->buf_layout[TX]);
-       priv->rx_headroom = dpaa_get_headroom(&priv->buf_layout[RX]);
+       priv->tx_headroom = dpaa_get_headroom(priv->buf_layout, TX);
+       priv->rx_headroom = dpaa_get_headroom(priv->buf_layout, RX);
 
        /* All real interfaces need their ports initialized */
        err = dpaa_eth_init_ports(mac_dev, dpaa_bp, &port_fqs,
index cfd369cf4c8c7078b52f55d19e0de7b5e96f07ee..ee7a906e30b34c5463ecf77511178dcb8511c0de 100644 (file)
@@ -4,6 +4,8 @@ config FSL_DPAA2_ETH
        depends on FSL_MC_BUS && FSL_MC_DPIO
        select PHYLINK
        select PCS_LYNX
+       select FSL_XGMAC_MDIO
+       select NET_DEVLINK
        help
          This is the DPAA2 Ethernet driver supporting Freescale SoCs
          with DPAA2 (DataPath Acceleration Architecture v2).
index 0fa18b00c49b94fa880ef5dd0e8c0a49172c7a35..d99ea0f4e4a6cb23ab679c8a78bb2d43cad7582e 100644 (file)
@@ -16,6 +16,7 @@ config FSL_ENETC
 config FSL_ENETC_VF
        tristate "ENETC VF driver"
        depends on PCI && PCI_MSI
+       select FSL_ENETC_MDIO
        select PHYLINK
        select DIMLIB
        help
index 52be6e3157523214aa4ea531242774f57cfc700e..fc2075ea57fea910f5cb39c3f96a1dd9d0ae6ba9 100644 (file)
@@ -33,7 +33,10 @@ netdev_tx_t enetc_xmit(struct sk_buff *skb, struct net_device *ndev)
                return NETDEV_TX_BUSY;
        }
 
+       enetc_lock_mdio();
        count = enetc_map_tx_buffs(tx_ring, skb, priv->active_offloads);
+       enetc_unlock_mdio();
+
        if (unlikely(!count))
                goto drop_packet_err;
 
@@ -239,7 +242,7 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb,
        skb_tx_timestamp(skb);
 
        /* let H/W know BD ring has been updated */
-       enetc_wr_reg(tx_ring->tpir, i); /* includes wmb() */
+       enetc_wr_reg_hot(tx_ring->tpir, i); /* includes wmb() */
 
        return count;
 
@@ -262,12 +265,16 @@ static irqreturn_t enetc_msix(int irq, void *data)
        struct enetc_int_vector *v = data;
        int i;
 
+       enetc_lock_mdio();
+
        /* disable interrupts */
-       enetc_wr_reg(v->rbier, 0);
-       enetc_wr_reg(v->ricr1, v->rx_ictt);
+       enetc_wr_reg_hot(v->rbier, 0);
+       enetc_wr_reg_hot(v->ricr1, v->rx_ictt);
 
        for_each_set_bit(i, &v->tx_rings_map, ENETC_MAX_NUM_TXQS)
-               enetc_wr_reg(v->tbier_base + ENETC_BDR_OFF(i), 0);
+               enetc_wr_reg_hot(v->tbier_base + ENETC_BDR_OFF(i), 0);
+
+       enetc_unlock_mdio();
 
        napi_schedule(&v->napi);
 
@@ -334,19 +341,23 @@ static int enetc_poll(struct napi_struct *napi, int budget)
 
        v->rx_napi_work = false;
 
+       enetc_lock_mdio();
+
        /* enable interrupts */
-       enetc_wr_reg(v->rbier, ENETC_RBIER_RXTIE);
+       enetc_wr_reg_hot(v->rbier, ENETC_RBIER_RXTIE);
 
        for_each_set_bit(i, &v->tx_rings_map, ENETC_MAX_NUM_TXQS)
-               enetc_wr_reg(v->tbier_base + ENETC_BDR_OFF(i),
-                            ENETC_TBIER_TXTIE);
+               enetc_wr_reg_hot(v->tbier_base + ENETC_BDR_OFF(i),
+                                ENETC_TBIER_TXTIE);
+
+       enetc_unlock_mdio();
 
        return work_done;
 }
 
 static int enetc_bd_ready_count(struct enetc_bdr *tx_ring, int ci)
 {
-       int pi = enetc_rd_reg(tx_ring->tcir) & ENETC_TBCIR_IDX_MASK;
+       int pi = enetc_rd_reg_hot(tx_ring->tcir) & ENETC_TBCIR_IDX_MASK;
 
        return pi >= ci ? pi - ci : tx_ring->bd_count - ci + pi;
 }
@@ -386,7 +397,10 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
 
        i = tx_ring->next_to_clean;
        tx_swbd = &tx_ring->tx_swbd[i];
+
+       enetc_lock_mdio();
        bds_to_clean = enetc_bd_ready_count(tx_ring, i);
+       enetc_unlock_mdio();
 
        do_tstamp = false;
 
@@ -429,16 +443,20 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
                        tx_swbd = tx_ring->tx_swbd;
                }
 
+               enetc_lock_mdio();
+
                /* BD iteration loop end */
                if (is_eof) {
                        tx_frm_cnt++;
                        /* re-arm interrupt source */
-                       enetc_wr_reg(tx_ring->idr, BIT(tx_ring->index) |
-                                    BIT(16 + tx_ring->index));
+                       enetc_wr_reg_hot(tx_ring->idr, BIT(tx_ring->index) |
+                                        BIT(16 + tx_ring->index));
                }
 
                if (unlikely(!bds_to_clean))
                        bds_to_clean = enetc_bd_ready_count(tx_ring, i);
+
+               enetc_unlock_mdio();
        }
 
        tx_ring->next_to_clean = i;
@@ -515,8 +533,6 @@ static int enetc_refill_rx_ring(struct enetc_bdr *rx_ring, const int buff_cnt)
        if (likely(j)) {
                rx_ring->next_to_alloc = i; /* keep track from page reuse */
                rx_ring->next_to_use = i;
-               /* update ENETC's consumer index */
-               enetc_wr_reg(rx_ring->rcir, i);
        }
 
        return j;
@@ -534,8 +550,8 @@ static void enetc_get_rx_tstamp(struct net_device *ndev,
        u64 tstamp;
 
        if (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_TSTMP) {
-               lo = enetc_rd(hw, ENETC_SICTR0);
-               hi = enetc_rd(hw, ENETC_SICTR1);
+               lo = enetc_rd_reg_hot(hw->reg + ENETC_SICTR0);
+               hi = enetc_rd_reg_hot(hw->reg + ENETC_SICTR1);
                rxbd = enetc_rxbd_ext(rxbd);
                tstamp_lo = le32_to_cpu(rxbd->ext.tstamp);
                if (lo <= tstamp_lo)
@@ -684,23 +700,31 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
                u32 bd_status;
                u16 size;
 
+               enetc_lock_mdio();
+
                if (cleaned_cnt >= ENETC_RXBD_BUNDLE) {
                        int count = enetc_refill_rx_ring(rx_ring, cleaned_cnt);
 
+                       /* update ENETC's consumer index */
+                       enetc_wr_reg_hot(rx_ring->rcir, rx_ring->next_to_use);
                        cleaned_cnt -= count;
                }
 
                rxbd = enetc_rxbd(rx_ring, i);
                bd_status = le32_to_cpu(rxbd->r.lstatus);
-               if (!bd_status)
+               if (!bd_status) {
+                       enetc_unlock_mdio();
                        break;
+               }
 
-               enetc_wr_reg(rx_ring->idr, BIT(rx_ring->index));
+               enetc_wr_reg_hot(rx_ring->idr, BIT(rx_ring->index));
                dma_rmb(); /* for reading other rxbd fields */
                size = le16_to_cpu(rxbd->r.buf_len);
                skb = enetc_map_rx_buff_to_skb(rx_ring, i, size);
-               if (!skb)
+               if (!skb) {
+                       enetc_unlock_mdio();
                        break;
+               }
 
                enetc_get_offloads(rx_ring, rxbd, skb);
 
@@ -712,6 +736,7 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
 
                if (unlikely(bd_status &
                             ENETC_RXBD_LSTATUS(ENETC_RXBD_ERR_MASK))) {
+                       enetc_unlock_mdio();
                        dev_kfree_skb(skb);
                        while (!(bd_status & ENETC_RXBD_LSTATUS_F)) {
                                dma_rmb();
@@ -751,6 +776,8 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
 
                enetc_process_skb(rx_ring, skb);
 
+               enetc_unlock_mdio();
+
                napi_gro_receive(napi, skb);
 
                rx_frm_cnt++;
@@ -1225,6 +1252,7 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
        rx_ring->idr = hw->reg + ENETC_SIRXIDR;
 
        enetc_refill_rx_ring(rx_ring, enetc_bd_unused(rx_ring));
+       enetc_wr(hw, ENETC_SIRXIDR, rx_ring->next_to_use);
 
        /* enable ring */
        enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
index 17cf7c94fdb52c78ac5fcc98b8e8a1ee1058f565..eb6bbf1113c710ec18658ca3744f859e2617b4e7 100644 (file)
@@ -324,14 +324,100 @@ struct enetc_hw {
        void __iomem *global;
 };
 
-/* general register accessors */
-#define enetc_rd_reg(reg)      ioread32((reg))
-#define enetc_wr_reg(reg, val) iowrite32((val), (reg))
+/* ENETC register accessors */
+
+/* MDIO issue workaround (on LS1028A) -
+ * Due to a hardware issue, an access to MDIO registers
+ * that is concurrent with other ENETC register accesses
+ * may lead to the MDIO access being dropped or corrupted.
+ * To protect the MDIO accesses a readers-writers locking
+ * scheme is used, where the MDIO register accesses are
+ * protected by write locks to insure exclusivity, while
+ * the remaining ENETC registers are accessed under read
+ * locks since they only compete with MDIO accesses.
+ */
+extern rwlock_t enetc_mdio_lock;
+
+/* use this locking primitive only on the fast datapath to
+ * group together multiple non-MDIO register accesses to
+ * minimize the overhead of the lock
+ */
+static inline void enetc_lock_mdio(void)
+{
+       read_lock(&enetc_mdio_lock);
+}
+
+static inline void enetc_unlock_mdio(void)
+{
+       read_unlock(&enetc_mdio_lock);
+}
+
+/* use these accessors only on the fast datapath under
+ * the enetc_lock_mdio() locking primitive to minimize
+ * the overhead of the lock
+ */
+static inline u32 enetc_rd_reg_hot(void __iomem *reg)
+{
+       lockdep_assert_held(&enetc_mdio_lock);
+
+       return ioread32(reg);
+}
+
+static inline void enetc_wr_reg_hot(void __iomem *reg, u32 val)
+{
+       lockdep_assert_held(&enetc_mdio_lock);
+
+       iowrite32(val, reg);
+}
+
+/* internal helpers for the MDIO w/a */
+static inline u32 _enetc_rd_reg_wa(void __iomem *reg)
+{
+       u32 val;
+
+       enetc_lock_mdio();
+       val = ioread32(reg);
+       enetc_unlock_mdio();
+
+       return val;
+}
+
+static inline void _enetc_wr_reg_wa(void __iomem *reg, u32 val)
+{
+       enetc_lock_mdio();
+       iowrite32(val, reg);
+       enetc_unlock_mdio();
+}
+
+static inline u32 _enetc_rd_mdio_reg_wa(void __iomem *reg)
+{
+       unsigned long flags;
+       u32 val;
+
+       write_lock_irqsave(&enetc_mdio_lock, flags);
+       val = ioread32(reg);
+       write_unlock_irqrestore(&enetc_mdio_lock, flags);
+
+       return val;
+}
+
+static inline void _enetc_wr_mdio_reg_wa(void __iomem *reg, u32 val)
+{
+       unsigned long flags;
+
+       write_lock_irqsave(&enetc_mdio_lock, flags);
+       iowrite32(val, reg);
+       write_unlock_irqrestore(&enetc_mdio_lock, flags);
+}
+
 #ifdef ioread64
-#define enetc_rd_reg64(reg)    ioread64((reg))
+static inline u64 _enetc_rd_reg64(void __iomem *reg)
+{
+       return ioread64(reg);
+}
 #else
 /* using this to read out stats on 32b systems */
-static inline u64 enetc_rd_reg64(void __iomem *reg)
+static inline u64 _enetc_rd_reg64(void __iomem *reg)
 {
        u32 low, high, tmp;
 
@@ -345,12 +431,29 @@ static inline u64 enetc_rd_reg64(void __iomem *reg)
 }
 #endif
 
+static inline u64 _enetc_rd_reg64_wa(void __iomem *reg)
+{
+       u64 val;
+
+       enetc_lock_mdio();
+       val = _enetc_rd_reg64(reg);
+       enetc_unlock_mdio();
+
+       return val;
+}
+
+/* general register accessors */
+#define enetc_rd_reg(reg)              _enetc_rd_reg_wa((reg))
+#define enetc_wr_reg(reg, val)         _enetc_wr_reg_wa((reg), (val))
 #define enetc_rd(hw, off)              enetc_rd_reg((hw)->reg + (off))
 #define enetc_wr(hw, off, val)         enetc_wr_reg((hw)->reg + (off), val)
-#define enetc_rd64(hw, off)            enetc_rd_reg64((hw)->reg + (off))
+#define enetc_rd64(hw, off)            _enetc_rd_reg64_wa((hw)->reg + (off))
 /* port register accessors - PF only */
 #define enetc_port_rd(hw, off)         enetc_rd_reg((hw)->port + (off))
 #define enetc_port_wr(hw, off, val)    enetc_wr_reg((hw)->port + (off), val)
+#define enetc_port_rd_mdio(hw, off)    _enetc_rd_mdio_reg_wa((hw)->port + (off))
+#define enetc_port_wr_mdio(hw, off, val)       _enetc_wr_mdio_reg_wa(\
+                                                       (hw)->port + (off), val)
 /* global register accessors - PF only */
 #define enetc_global_rd(hw, off)       enetc_rd_reg((hw)->global + (off))
 #define enetc_global_wr(hw, off, val)  enetc_wr_reg((hw)->global + (off), val)
index 48c32a171afa67d8ce87dbab99607fe64e4f3507..ee0116ed4738e657a556e53b8ab96fa5b6578a35 100644 (file)
 
 static inline u32 _enetc_mdio_rd(struct enetc_mdio_priv *mdio_priv, int off)
 {
-       return enetc_port_rd(mdio_priv->hw, mdio_priv->mdio_base + off);
+       return enetc_port_rd_mdio(mdio_priv->hw, mdio_priv->mdio_base + off);
 }
 
 static inline void _enetc_mdio_wr(struct enetc_mdio_priv *mdio_priv, int off,
                                  u32 val)
 {
-       enetc_port_wr(mdio_priv->hw, mdio_priv->mdio_base + off, val);
+       enetc_port_wr_mdio(mdio_priv->hw, mdio_priv->mdio_base + off, val);
 }
 
 #define enetc_mdio_rd(mdio_priv, off) \
@@ -174,3 +174,7 @@ struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs)
        return hw;
 }
 EXPORT_SYMBOL_GPL(enetc_hw_alloc);
+
+/* Lock for MDIO access errata on LS1028A */
+DEFINE_RWLOCK(enetc_mdio_lock);
+EXPORT_SYMBOL_GPL(enetc_mdio_lock);
index c81be32bcedf61fce4f80aad5317117a5f313a0c..dbceb99c4441adbccafba6a6756b63c6b4c4aeb9 100644 (file)
@@ -92,18 +92,8 @@ static int enetc_setup_taprio(struct net_device *ndev,
        gcl_config->atc = 0xff;
        gcl_config->acl_len = cpu_to_le16(gcl_len);
 
-       if (!admin_conf->base_time) {
-               gcl_data->btl =
-                       cpu_to_le32(enetc_rd(&priv->si->hw, ENETC_SICTR0));
-               gcl_data->bth =
-                       cpu_to_le32(enetc_rd(&priv->si->hw, ENETC_SICTR1));
-       } else {
-               gcl_data->btl =
-                       cpu_to_le32(lower_32_bits(admin_conf->base_time));
-               gcl_data->bth =
-                       cpu_to_le32(upper_32_bits(admin_conf->base_time));
-       }
-
+       gcl_data->btl = cpu_to_le32(lower_32_bits(admin_conf->base_time));
+       gcl_data->bth = cpu_to_le32(upper_32_bits(admin_conf->base_time));
        gcl_data->ct = cpu_to_le32(admin_conf->cycle_time);
        gcl_data->cte = cpu_to_le32(admin_conf->cycle_time_extension);
 
@@ -402,7 +392,7 @@ struct enetc_psfp_gate {
        u32 num_entries;
        refcount_t refcount;
        struct hlist_node node;
-       struct action_gate_entry entries[0];
+       struct action_gate_entry entries[];
 };
 
 /* Only enable the green color frame now
index 832a2175636d69b7a29ecd560b8b8804fa4c759f..c527f4ee1d3aed313124d2befbb6a536801e5594 100644 (file)
@@ -456,6 +456,12 @@ struct bufdesc_ex {
  */
 #define FEC_QUIRK_HAS_FRREG            (1 << 16)
 
+/* Some FEC hardware blocks need the MMFR cleared at setup time to avoid
+ * the generation of an MII event. This must be avoided in the older
+ * FEC blocks where it will stop MII events being generated.
+ */
+#define FEC_QUIRK_CLEAR_SETUP_MII      (1 << 17)
+
 struct bufdesc_prop {
        int qid;
        /* Address of Rx and Tx buffers */
index 8f7eca1e7716c9bbaddb28f9b541a339ef326a8c..04f24c66cf3668113014208d8a2dedc76180f131 100644 (file)
@@ -100,14 +100,14 @@ static const struct fec_devinfo fec_imx27_info = {
 static const struct fec_devinfo fec_imx28_info = {
        .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME |
                  FEC_QUIRK_SINGLE_MDIO | FEC_QUIRK_HAS_RACC |
-                 FEC_QUIRK_HAS_FRREG,
+                 FEC_QUIRK_HAS_FRREG | FEC_QUIRK_CLEAR_SETUP_MII,
 };
 
 static const struct fec_devinfo fec_imx6q_info = {
        .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
                  FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
                  FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 |
-                 FEC_QUIRK_HAS_RACC,
+                 FEC_QUIRK_HAS_RACC | FEC_QUIRK_CLEAR_SETUP_MII,
 };
 
 static const struct fec_devinfo fec_mvf600_info = {
@@ -119,7 +119,8 @@ static const struct fec_devinfo fec_imx6x_info = {
                  FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
                  FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
                  FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
-                 FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE,
+                 FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE |
+                 FEC_QUIRK_CLEAR_SETUP_MII,
 };
 
 static const struct fec_devinfo fec_imx6ul_info = {
@@ -127,7 +128,7 @@ static const struct fec_devinfo fec_imx6ul_info = {
                  FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
                  FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR007885 |
                  FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC |
-                 FEC_QUIRK_HAS_COALESCE,
+                 FEC_QUIRK_HAS_COALESCE | FEC_QUIRK_CLEAR_SETUP_MII,
 };
 
 static struct platform_device_id fec_devtype[] = {
@@ -1807,7 +1808,7 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
        int ret = 0, frame_start, frame_addr, frame_op;
        bool is_c45 = !!(regnum & MII_ADDR_C45);
 
-       ret = pm_runtime_get_sync(dev);
+       ret = pm_runtime_resume_and_get(dev);
        if (ret < 0)
                return ret;
 
@@ -1866,11 +1867,9 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
        int ret, frame_start, frame_addr;
        bool is_c45 = !!(regnum & MII_ADDR_C45);
 
-       ret = pm_runtime_get_sync(dev);
+       ret = pm_runtime_resume_and_get(dev);
        if (ret < 0)
                return ret;
-       else
-               ret = 0;
 
        if (is_c45) {
                frame_start = FEC_MMFR_ST_C45;
@@ -2134,15 +2133,17 @@ static int fec_enet_mii_init(struct platform_device *pdev)
        if (suppress_preamble)
                fep->phy_speed |= BIT(7);
 
-       /* Clear MMFR to avoid to generate MII event by writing MSCR.
-        * MII event generation condition:
-        * - writing MSCR:
-        *      - mmfr[31:0]_not_zero & mscr[7:0]_is_zero &
-        *        mscr_reg_data_in[7:0] != 0
-        * - writing MMFR:
-        *      - mscr[7:0]_not_zero
-        */
-       writel(0, fep->hwp + FEC_MII_DATA);
+       if (fep->quirks & FEC_QUIRK_CLEAR_SETUP_MII) {
+               /* Clear MMFR to avoid to generate MII event by writing MSCR.
+                * MII event generation condition:
+                * - writing MSCR:
+                *      - mmfr[31:0]_not_zero & mscr[7:0]_is_zero &
+                *        mscr_reg_data_in[7:0] != 0
+                * - writing MMFR:
+                *      - mscr[7:0]_not_zero
+                */
+               writel(0, fep->hwp + FEC_MII_DATA);
+       }
 
        writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
 
@@ -2272,7 +2273,7 @@ static void fec_enet_get_regs(struct net_device *ndev,
        u32 i, off;
        int ret;
 
-       ret = pm_runtime_get_sync(dev);
+       ret = pm_runtime_resume_and_get(dev);
        if (ret < 0)
                return;
 
@@ -2973,7 +2974,7 @@ fec_enet_open(struct net_device *ndev)
        int ret;
        bool reset_again;
 
-       ret = pm_runtime_get_sync(&fep->pdev->dev);
+       ret = pm_runtime_resume_and_get(&fep->pdev->dev);
        if (ret < 0)
                return ret;
 
@@ -3767,7 +3768,7 @@ fec_drv_remove(struct platform_device *pdev)
        struct device_node *np = pdev->dev.of_node;
        int ret;
 
-       ret = pm_runtime_get_sync(&pdev->dev);
+       ret = pm_runtime_resume_and_get(&pdev->dev);
        if (ret < 0)
                return ret;
 
index 41dd3d0f3452442d60383e15b84cdac050673d6d..d391a45cebb661c7b94084648433c77c27484a99 100644 (file)
@@ -1829,20 +1829,12 @@ static netdev_tx_t gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
                fcb_len = GMAC_FCB_LEN + GMAC_TXPAL_LEN;
 
        /* make space for additional header when fcb is needed */
-       if (fcb_len && unlikely(skb_headroom(skb) < fcb_len)) {
-               struct sk_buff *skb_new;
-
-               skb_new = skb_realloc_headroom(skb, fcb_len);
-               if (!skb_new) {
+       if (fcb_len) {
+               if (unlikely(skb_cow_head(skb, fcb_len))) {
                        dev->stats.tx_errors++;
                        dev_kfree_skb_any(skb);
                        return NETDEV_TX_OK;
                }
-
-               if (skb->sk)
-                       skb_set_owner_w(skb_new, skb->sk);
-               dev_consume_skb_any(skb);
-               skb = skb_new;
        }
 
        /* total number of fragments in the SKB */
@@ -3380,7 +3372,7 @@ static int gfar_probe(struct platform_device *ofdev)
 
        if (dev->features & NETIF_F_IP_CSUM ||
            priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
-               dev->needed_headroom = GMAC_FCB_LEN;
+               dev->needed_headroom = GMAC_FCB_LEN + GMAC_TXPAL_LEN;
 
        /* Initializing some of the rx/tx queue level parameters */
        for (i = 0; i < priv->num_tx_queues; i++) {
index 714b501be7d09f805057f21222d8086900c53dc9..ba8869c3d891c0e05e29cd4fb1bcb5b17ce775ba 100644 (file)
@@ -1358,7 +1358,7 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
            (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
                upsmr |= UCC_GETH_UPSMR_TBIM;
        }
-       if ((ugeth->phy_interface == PHY_INTERFACE_MODE_SGMII))
+       if (ugeth->phy_interface == PHY_INTERFACE_MODE_SGMII)
                upsmr |= UCC_GETH_UPSMR_SGMM;
 
        out_be32(&uf_regs->upsmr, upsmr);
index 281de8326bc510ce7c536c63a77c1bb25c562145..015796a20118bcdf2c1b095d5f95c59d2300233e 100644 (file)
@@ -198,7 +198,7 @@ static_assert(sizeof(struct stats) == 16);
 
 struct gve_stats_report {
        __be64 written_count;
-       struct stats stats[0];
+       struct stats stats[];
 };
 
 static_assert(sizeof(struct gve_stats_report) == 8);
index 48a433154ce079c8c45cd8aae53eed7e0d3e5e04..02e7d74779f46adb76deb1ae935a7ce32442695a 100644 (file)
@@ -116,9 +116,8 @@ static int gve_alloc_stats_report(struct gve_priv *priv)
                       priv->tx_cfg.num_queues;
        rx_stats_num = (GVE_RX_STATS_REPORT_NUM + NIC_RX_STATS_REPORT_NUM) *
                       priv->rx_cfg.num_queues;
-       priv->stats_report_len = sizeof(struct gve_stats_report) +
-                                (tx_stats_num + rx_stats_num) *
-                                sizeof(struct stats);
+       priv->stats_report_len = struct_size(priv->stats_report, stats,
+                                            tx_stats_num + rx_stats_num);
        priv->stats_report =
                dma_alloc_coherent(&priv->pdev->dev, priv->stats_report_len,
                                   &priv->stats_report_bus, GFP_KERNEL);
index 15f69fa863236cb838397dc7d3d2d107f8b890c2..e8495f58a1a8e81fa4dbdc86b998984fea437434 100644 (file)
@@ -1373,7 +1373,7 @@ static int hclge_tm_bp_setup(struct hclge_dev *hdev)
                        return ret;
        }
 
-       return ret;
+       return 0;
 }
 
 int hclge_pause_setup_hw(struct hclge_dev *hdev, bool init)
index 50c84c5e65d29566712772b5fc51b4bf1ab43cfa..c8e3fdd5999c4f676f65d1793357b6b47f6eaf87 100644 (file)
@@ -3262,8 +3262,8 @@ static void hclgevf_uninit_hdev(struct hclgevf_dev *hdev)
                hclgevf_uninit_msi(hdev);
        }
 
-       hclgevf_pci_uninit(hdev);
        hclgevf_cmd_uninit(hdev);
+       hclgevf_pci_uninit(hdev);
        hclgevf_uninit_mac_list(hdev);
 }
 
index 7ef3369953b6a540fa15c7ad9cb192d50f570a3e..c3ec9ceed833ed4e6d128c86bbf09aa476de91b5 100644 (file)
@@ -1031,12 +1031,6 @@ static int ibmveth_is_packet_unsupported(struct sk_buff *skb,
                ret = -EOPNOTSUPP;
        }
 
-       if (!ether_addr_equal(ether_header->h_source, netdev->dev_addr)) {
-               netdev_dbg(netdev, "source packet MAC address does not match veth device's, dropping packet.\n");
-               netdev->stats.tx_dropped++;
-               ret = -EOPNOTSUPP;
-       }
-
        return ret;
 }
 
index 8148f796a8070b2aeb7c44ebfed4ca914c7dcf00..da9450f187176a3cada15670365689b14c459bfd 100644 (file)
@@ -834,7 +834,7 @@ static void release_napi(struct ibmvnic_adapter *adapter)
 static int ibmvnic_login(struct net_device *netdev)
 {
        struct ibmvnic_adapter *adapter = netdev_priv(netdev);
-       unsigned long timeout = msecs_to_jiffies(30000);
+       unsigned long timeout = msecs_to_jiffies(20000);
        int retry_count = 0;
        int retries = 10;
        bool retry;
@@ -850,10 +850,8 @@ static int ibmvnic_login(struct net_device *netdev)
                adapter->init_done_rc = 0;
                reinit_completion(&adapter->init_done);
                rc = send_login(adapter);
-               if (rc) {
-                       netdev_warn(netdev, "Unable to login\n");
+               if (rc)
                        return rc;
-               }
 
                if (!wait_for_completion_timeout(&adapter->init_done,
                                                 timeout)) {
@@ -940,7 +938,7 @@ static void release_resources(struct ibmvnic_adapter *adapter)
 static int set_link_state(struct ibmvnic_adapter *adapter, u8 link_state)
 {
        struct net_device *netdev = adapter->netdev;
-       unsigned long timeout = msecs_to_jiffies(30000);
+       unsigned long timeout = msecs_to_jiffies(20000);
        union ibmvnic_crq crq;
        bool resend;
        int rc;
@@ -1185,18 +1183,27 @@ static int ibmvnic_open(struct net_device *netdev)
        if (adapter->state != VNIC_CLOSED) {
                rc = ibmvnic_login(netdev);
                if (rc)
-                       return rc;
+                       goto out;
 
                rc = init_resources(adapter);
                if (rc) {
                        netdev_err(netdev, "failed to initialize resources\n");
                        release_resources(adapter);
-                       return rc;
+                       goto out;
                }
        }
 
        rc = __ibmvnic_open(netdev);
 
+out:
+       /*
+        * If open fails due to a pending failover, set device state and
+        * return. Device operation will be handled by reset routine.
+        */
+       if (rc && adapter->failover_pending) {
+               adapter->state = VNIC_OPEN;
+               rc = 0;
+       }
        return rc;
 }
 
@@ -1815,9 +1822,13 @@ static int ibmvnic_set_mac(struct net_device *netdev, void *p)
        int rc;
 
        rc = 0;
-       ether_addr_copy(adapter->mac_addr, addr->sa_data);
-       if (adapter->state != VNIC_PROBED)
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EADDRNOTAVAIL;
+
+       if (adapter->state != VNIC_PROBED) {
+               ether_addr_copy(adapter->mac_addr, addr->sa_data);
                rc = __ibmvnic_set_mac(netdev, addr->sa_data);
+       }
 
        return rc;
 }
@@ -1844,7 +1855,7 @@ static int do_change_param_reset(struct ibmvnic_adapter *adapter,
        if (reset_state == VNIC_OPEN) {
                rc = __ibmvnic_close(netdev);
                if (rc)
-                       return rc;
+                       goto out;
        }
 
        release_resources(adapter);
@@ -1862,24 +1873,25 @@ static int do_change_param_reset(struct ibmvnic_adapter *adapter,
        }
 
        rc = ibmvnic_reset_init(adapter, true);
-       if (rc)
-               return IBMVNIC_INIT_FAILED;
+       if (rc) {
+               rc = IBMVNIC_INIT_FAILED;
+               goto out;
+       }
 
        /* If the adapter was in PROBE state prior to the reset,
         * exit here.
         */
        if (reset_state == VNIC_PROBED)
-               return 0;
+               goto out;
 
        rc = ibmvnic_login(netdev);
        if (rc) {
-               adapter->state = reset_state;
-               return rc;
+               goto out;
        }
 
        rc = init_resources(adapter);
        if (rc)
-               return rc;
+               goto out;
 
        ibmvnic_disable_irqs(adapter);
 
@@ -1889,8 +1901,10 @@ static int do_change_param_reset(struct ibmvnic_adapter *adapter,
                return 0;
 
        rc = __ibmvnic_open(netdev);
-       if (rc)
-               return IBMVNIC_OPEN_FAILED;
+       if (rc) {
+               rc = IBMVNIC_OPEN_FAILED;
+               goto out;
+       }
 
        /* refresh device's multicast list */
        ibmvnic_set_multi(netdev);
@@ -1899,7 +1913,10 @@ static int do_change_param_reset(struct ibmvnic_adapter *adapter,
        for (i = 0; i < adapter->req_rx_queues; i++)
                napi_schedule(&adapter->napi[i]);
 
-       return 0;
+out:
+       if (rc)
+               adapter->state = reset_state;
+       return rc;
 }
 
 /**
@@ -1918,6 +1935,13 @@ static int do_reset(struct ibmvnic_adapter *adapter,
                   rwi->reset_reason);
 
        rtnl_lock();
+       /*
+        * Now that we have the rtnl lock, clear any pending failover.
+        * This will ensure ibmvnic_open() has either completed or will
+        * block until failover is complete.
+        */
+       if (rwi->reset_reason == VNIC_RESET_FAILOVER)
+               adapter->failover_pending = false;
 
        netif_carrier_off(netdev);
        adapter->reset_reason = rwi->reset_reason;
@@ -1995,7 +2019,6 @@ static int do_reset(struct ibmvnic_adapter *adapter,
 
                rc = ibmvnic_login(netdev);
                if (rc) {
-                       adapter->state = reset_state;
                        goto out;
                }
 
@@ -2054,12 +2077,18 @@ static int do_reset(struct ibmvnic_adapter *adapter,
        for (i = 0; i < adapter->req_rx_queues; i++)
                napi_schedule(&adapter->napi[i]);
 
-       if (adapter->reset_reason != VNIC_RESET_FAILOVER)
+       if (adapter->reset_reason == VNIC_RESET_FAILOVER ||
+           adapter->reset_reason == VNIC_RESET_MOBILITY) {
                call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev);
+               call_netdevice_notifiers(NETDEV_RESEND_IGMP, netdev);
+       }
 
        rc = 0;
 
 out:
+       /* restore the adapter state if reset failed */
+       if (rc)
+               adapter->state = reset_state;
        rtnl_unlock();
 
        return rc;
@@ -2092,40 +2121,46 @@ static int do_hard_reset(struct ibmvnic_adapter *adapter,
        if (rc) {
                netdev_err(adapter->netdev,
                           "Couldn't initialize crq. rc=%d\n", rc);
-               return rc;
+               goto out;
        }
 
        rc = ibmvnic_reset_init(adapter, false);
        if (rc)
-               return rc;
+               goto out;
 
        /* If the adapter was in PROBE state prior to the reset,
         * exit here.
         */
        if (reset_state == VNIC_PROBED)
-               return 0;
+               goto out;
 
        rc = ibmvnic_login(netdev);
-       if (rc) {
-               adapter->state = VNIC_PROBED;
-               return 0;
-       }
+       if (rc)
+               goto out;
 
        rc = init_resources(adapter);
        if (rc)
-               return rc;
+               goto out;
 
        ibmvnic_disable_irqs(adapter);
        adapter->state = VNIC_CLOSED;
 
        if (reset_state == VNIC_CLOSED)
-               return 0;
+               goto out;
 
        rc = __ibmvnic_open(netdev);
-       if (rc)
-               return IBMVNIC_OPEN_FAILED;
+       if (rc) {
+               rc = IBMVNIC_OPEN_FAILED;
+               goto out;
+       }
 
-       return 0;
+       call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev);
+       call_netdevice_notifiers(NETDEV_RESEND_IGMP, netdev);
+out:
+       /* restore adapter state if reset failed */
+       if (rc)
+               adapter->state = reset_state;
+       return rc;
 }
 
 static struct ibmvnic_rwi *get_next_rwi(struct ibmvnic_adapter *adapter)
@@ -2147,17 +2182,6 @@ static struct ibmvnic_rwi *get_next_rwi(struct ibmvnic_adapter *adapter)
        return rwi;
 }
 
-static void free_all_rwi(struct ibmvnic_adapter *adapter)
-{
-       struct ibmvnic_rwi *rwi;
-
-       rwi = get_next_rwi(adapter);
-       while (rwi) {
-               kfree(rwi);
-               rwi = get_next_rwi(adapter);
-       }
-}
-
 static void __ibmvnic_reset(struct work_struct *work)
 {
        struct ibmvnic_rwi *rwi;
@@ -2189,7 +2213,6 @@ static void __ibmvnic_reset(struct work_struct *work)
 
                if (!saved_state) {
                        reset_state = adapter->state;
-                       adapter->state = VNIC_RESETTING;
                        saved_state = true;
                }
                spin_unlock_irqrestore(&adapter->state_lock, flags);
@@ -2198,6 +2221,13 @@ static void __ibmvnic_reset(struct work_struct *work)
                        /* CHANGE_PARAM requestor holds rtnl_lock */
                        rc = do_change_param_reset(adapter, rwi, reset_state);
                } else if (adapter->force_reset_recovery) {
+                       /*
+                        * Since we are doing a hard reset now, clear the
+                        * failover_pending flag so we don't ignore any
+                        * future MOBILITY or other resets.
+                        */
+                       adapter->failover_pending = false;
+
                        /* Transport event occurred during previous reset */
                        if (adapter->wait_for_reset) {
                                /* Previous was CHANGE_PARAM; caller locked */
@@ -2209,20 +2239,23 @@ static void __ibmvnic_reset(struct work_struct *work)
                                rc = do_hard_reset(adapter, rwi, reset_state);
                                rtnl_unlock();
                        }
+                       if (rc) {
+                               /* give backing device time to settle down */
+                               netdev_dbg(adapter->netdev,
+                                          "[S:%d] Hard reset failed, waiting 60 secs\n",
+                                          adapter->state);
+                               set_current_state(TASK_UNINTERRUPTIBLE);
+                               schedule_timeout(60 * HZ);
+                       }
                } else if (!(rwi->reset_reason == VNIC_RESET_FATAL &&
                                adapter->from_passive_init)) {
                        rc = do_reset(adapter, rwi, reset_state);
                }
                kfree(rwi);
-               if (rc == IBMVNIC_OPEN_FAILED) {
-                       if (list_empty(&adapter->rwi_list))
-                               adapter->state = VNIC_CLOSED;
-                       else
-                               adapter->state = reset_state;
-                       rc = 0;
-               } else if (rc && rc != IBMVNIC_INIT_FAILED &&
-                   !adapter->force_reset_recovery)
-                       break;
+               adapter->last_reset_time = jiffies;
+
+               if (rc)
+                       netdev_dbg(adapter->netdev, "Reset failed, rc=%d\n", rc);
 
                rwi = get_next_rwi(adapter);
 
@@ -2236,11 +2269,6 @@ static void __ibmvnic_reset(struct work_struct *work)
                complete(&adapter->reset_done);
        }
 
-       if (rc) {
-               netdev_dbg(adapter->netdev, "Reset failed\n");
-               free_all_rwi(adapter);
-       }
-
        clear_bit_unlock(0, &adapter->resetting);
 }
 
@@ -2262,9 +2290,15 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
        unsigned long flags;
        int ret;
 
+       /*
+        * If failover is pending don't schedule any other reset.
+        * Instead let the failover complete. If there is already a
+        * a failover reset scheduled, we will detect and drop the
+        * duplicate reset when walking the ->rwi_list below.
+        */
        if (adapter->state == VNIC_REMOVING ||
            adapter->state == VNIC_REMOVED ||
-           adapter->failover_pending) {
+           (adapter->failover_pending && reason != VNIC_RESET_FAILOVER)) {
                ret = EBUSY;
                netdev_dbg(netdev, "Adapter removing or pending failover, skipping reset\n");
                goto err;
@@ -2317,6 +2351,18 @@ static void ibmvnic_tx_timeout(struct net_device *dev, unsigned int txqueue)
 {
        struct ibmvnic_adapter *adapter = netdev_priv(dev);
 
+       if (test_bit(0, &adapter->resetting)) {
+               netdev_err(adapter->netdev,
+                          "Adapter is resetting, skip timeout reset\n");
+               return;
+       }
+       /* No queuing up reset until at least 5 seconds (default watchdog val)
+        * after last reset
+        */
+       if (time_before(jiffies, (adapter->last_reset_time + dev->watchdog_timeo))) {
+               netdev_dbg(dev, "Not yet time to tx timeout.\n");
+               return;
+       }
        ibmvnic_reset(adapter, VNIC_RESET_TIMEOUT);
 }
 
@@ -2358,6 +2404,12 @@ restart_poll:
 
                if (!pending_scrq(adapter, adapter->rx_scrq[scrq_num]))
                        break;
+               /* The queue entry at the current index is peeked at above
+                * to determine that there is a valid descriptor awaiting
+                * processing. We want to be sure that the current slot
+                * holds a valid descriptor before reading its contents.
+                */
+               dma_rmb();
                next = ibmvnic_next_scrq(adapter, adapter->rx_scrq[scrq_num]);
                rx_buff =
                    (struct ibmvnic_rx_buff *)be64_to_cpu(next->
@@ -2816,15 +2868,26 @@ static int reset_one_sub_crq_queue(struct ibmvnic_adapter *adapter,
 {
        int rc;
 
+       if (!scrq) {
+               netdev_dbg(adapter->netdev,
+                          "Invalid scrq reset. irq (%d) or msgs (%p).\n",
+                          scrq->irq, scrq->msgs);
+               return -EINVAL;
+       }
+
        if (scrq->irq) {
                free_irq(scrq->irq, scrq);
                irq_dispose_mapping(scrq->irq);
                scrq->irq = 0;
        }
-
-       memset(scrq->msgs, 0, 4 * PAGE_SIZE);
-       atomic_set(&scrq->used, 0);
-       scrq->cur = 0;
+       if (scrq->msgs) {
+               memset(scrq->msgs, 0, 4 * PAGE_SIZE);
+               atomic_set(&scrq->used, 0);
+               scrq->cur = 0;
+       } else {
+               netdev_dbg(adapter->netdev, "Invalid scrq reset\n");
+               return -EINVAL;
+       }
 
        rc = h_reg_sub_crq(adapter->vdev->unit_address, scrq->msg_token,
                           4 * PAGE_SIZE, &scrq->crq_num, &scrq->hw_irq);
@@ -2835,6 +2898,9 @@ static int reset_sub_crq_queues(struct ibmvnic_adapter *adapter)
 {
        int i, rc;
 
+       if (!adapter->tx_scrq || !adapter->rx_scrq)
+               return -EINVAL;
+
        for (i = 0; i < adapter->req_tx_queues; i++) {
                netdev_dbg(adapter->netdev, "Re-setting tx_scrq[%d]\n", i);
                rc = reset_one_sub_crq_queue(adapter, adapter->tx_scrq[i]);
@@ -3053,13 +3119,18 @@ restart_loop:
                unsigned int pool = scrq->pool_index;
                int num_entries = 0;
 
+               /* The queue entry at the current index is peeked at above
+                * to determine that there is a valid descriptor awaiting
+                * processing. We want to be sure that the current slot
+                * holds a valid descriptor before reading its contents.
+                */
+               dma_rmb();
+
                next = ibmvnic_next_scrq(adapter, scrq);
                for (i = 0; i < next->tx_comp.num_comps; i++) {
-                       if (next->tx_comp.rcs[i]) {
+                       if (next->tx_comp.rcs[i])
                                dev_err(dev, "tx error %x\n",
                                        next->tx_comp.rcs[i]);
-                               continue;
-                       }
                        index = be32_to_cpu(next->tx_comp.correlators[i]);
                        if (index & IBMVNIC_TSO_POOL_MASK) {
                                tx_pool = &adapter->tso_pool[pool];
@@ -3453,6 +3524,11 @@ static union sub_crq *ibmvnic_next_scrq(struct ibmvnic_adapter *adapter,
        }
        spin_unlock_irqrestore(&scrq->lock, flags);
 
+       /* Ensure that the entire buffer descriptor has been
+        * loaded before reading its contents
+        */
+       dma_rmb();
+
        return entry;
 }
 
@@ -3674,15 +3750,16 @@ static int send_login(struct ibmvnic_adapter *adapter)
        struct ibmvnic_login_rsp_buffer *login_rsp_buffer;
        struct ibmvnic_login_buffer *login_buffer;
        struct device *dev = &adapter->vdev->dev;
+       struct vnic_login_client_data *vlcd;
        dma_addr_t rsp_buffer_token;
        dma_addr_t buffer_token;
        size_t rsp_buffer_size;
        union ibmvnic_crq crq;
+       int client_data_len;
        size_t buffer_size;
        __be64 *tx_list_p;
        __be64 *rx_list_p;
-       int client_data_len;
-       struct vnic_login_client_data *vlcd;
+       int rc;
        int i;
 
        if (!adapter->tx_scrq || !adapter->rx_scrq) {
@@ -3786,16 +3863,25 @@ static int send_login(struct ibmvnic_adapter *adapter)
        crq.login.cmd = LOGIN;
        crq.login.ioba = cpu_to_be32(buffer_token);
        crq.login.len = cpu_to_be32(buffer_size);
-       ibmvnic_send_crq(adapter, &crq);
+
+       adapter->login_pending = true;
+       rc = ibmvnic_send_crq(adapter, &crq);
+       if (rc) {
+               adapter->login_pending = false;
+               netdev_err(adapter->netdev, "Failed to send login, rc=%d\n", rc);
+               goto buf_rsp_map_failed;
+       }
 
        return 0;
 
 buf_rsp_map_failed:
        kfree(login_rsp_buffer);
+       adapter->login_rsp_buf = NULL;
 buf_rsp_alloc_failed:
        dma_unmap_single(dev, buffer_token, buffer_size, DMA_TO_DEVICE);
 buf_map_failed:
        kfree(login_buffer);
+       adapter->login_buf = NULL;
 buf_alloc_failed:
        return -1;
 }
@@ -4338,6 +4424,15 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
        u64 *size_array;
        int i;
 
+       /* CHECK: Test/set of login_pending does not need to be atomic
+        * because only ibmvnic_tasklet tests/clears this.
+        */
+       if (!adapter->login_pending) {
+               netdev_warn(netdev, "Ignoring unexpected login response\n");
+               return 0;
+       }
+       adapter->login_pending = false;
+
        dma_unmap_single(dev, adapter->login_buf_token, adapter->login_buf_sz,
                         DMA_TO_DEVICE);
        dma_unmap_single(dev, adapter->login_rsp_buf_token,
@@ -4367,7 +4462,7 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
             adapter->req_rx_add_queues !=
             be32_to_cpu(login_rsp->num_rxadd_subcrqs))) {
                dev_err(dev, "FATAL: Inconsistent login and login rsp\n");
-               ibmvnic_remove(adapter->vdev);
+               ibmvnic_reset(adapter, VNIC_RESET_FATAL);
                return -EIO;
        }
        size_array = (u64 *)((u8 *)(adapter->login_rsp_buf) +
@@ -4709,7 +4804,11 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
                case IBMVNIC_CRQ_INIT:
                        dev_info(dev, "Partner initialized\n");
                        adapter->from_passive_init = true;
-                       adapter->failover_pending = false;
+                       /* Discard any stale login responses from prev reset.
+                        * CHECK: should we clear even on INIT_COMPLETE?
+                        */
+                       adapter->login_pending = false;
+
                        if (!completion_done(&adapter->init_done)) {
                                complete(&adapter->init_done);
                                adapter->init_done_rc = -EIO;
@@ -4926,6 +5025,9 @@ static int ibmvnic_reset_crq(struct ibmvnic_adapter *adapter)
        } while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
 
        /* Clean out the queue */
+       if (!crq->msgs)
+               return -EINVAL;
+
        memset(crq->msgs, 0, PAGE_SIZE);
        crq->cur = 0;
        crq->active = false;
@@ -5044,7 +5146,7 @@ map_failed:
 static int ibmvnic_reset_init(struct ibmvnic_adapter *adapter, bool reset)
 {
        struct device *dev = &adapter->vdev->dev;
-       unsigned long timeout = msecs_to_jiffies(30000);
+       unsigned long timeout = msecs_to_jiffies(20000);
        u64 old_num_rx_queues, old_num_tx_queues;
        int rc;
 
@@ -5139,6 +5241,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
        dev_set_drvdata(&dev->dev, netdev);
        adapter->vdev = dev;
        adapter->netdev = netdev;
+       adapter->login_pending = false;
 
        ether_addr_copy(adapter->mac_addr, mac_addr_p);
        ether_addr_copy(netdev->dev_addr, adapter->mac_addr);
@@ -5202,7 +5305,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
        adapter->state = VNIC_PROBED;
 
        adapter->wait_for_reset = false;
-
+       adapter->last_reset_time = jiffies;
        return 0;
 
 ibmvnic_register_fail:
@@ -5230,7 +5333,7 @@ static int ibmvnic_remove(struct vio_dev *dev)
        unsigned long flags;
 
        spin_lock_irqsave(&adapter->state_lock, flags);
-       if (adapter->state == VNIC_RESETTING) {
+       if (test_bit(0, &adapter->resetting)) {
                spin_unlock_irqrestore(&adapter->state_lock, flags);
                return -EBUSY;
        }
index 217dcc7ded709260543cbbbb05db496001bd1840..21e7ea858cda31095e0386df91ffc146a6211865 100644 (file)
@@ -942,8 +942,7 @@ enum vnic_state {VNIC_PROBING = 1,
                 VNIC_CLOSING,
                 VNIC_CLOSED,
                 VNIC_REMOVING,
-                VNIC_REMOVED,
-                VNIC_RESETTING};
+                VNIC_REMOVED};
 
 enum ibmvnic_reset_reason {VNIC_RESET_FAILOVER = 1,
                           VNIC_RESET_MOBILITY,
@@ -1087,6 +1086,9 @@ struct ibmvnic_adapter {
        struct delayed_work ibmvnic_delayed_reset;
        unsigned long resetting;
        bool napi_enabled, from_passive_init;
+       bool login_pending;
+       /* last device reset time */
+       unsigned long last_reset_time;
 
        bool failover_pending;
        bool force_reset_recovery;
index 537300e762f049b204a62609bf0facce676f0cfe..d231a2cdd98ff244acb0c796dea11c84767e1404 100644 (file)
@@ -140,6 +140,7 @@ enum i40e_state_t {
        __I40E_CLIENT_RESET,
        __I40E_VIRTCHNL_OP_PENDING,
        __I40E_RECOVERY_MODE,
+       __I40E_VF_RESETS_DISABLED,      /* disable resets during i40e_remove */
        /* This must be last as it determines the size of the BITMAP */
        __I40E_STATE_SIZE__,
 };
index 4f8a2154b93fee621edc8ba356d8046412ca1558..1337686bd0998003e1a92a56f03ed7d8d8a99a3e 100644 (file)
@@ -4010,8 +4010,16 @@ static irqreturn_t i40e_intr(int irq, void *data)
        }
 
        if (icr0 & I40E_PFINT_ICR0_VFLR_MASK) {
-               ena_mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK;
-               set_bit(__I40E_VFLR_EVENT_PENDING, pf->state);
+               /* disable any further VFLR event notifications */
+               if (test_bit(__I40E_VF_RESETS_DISABLED, pf->state)) {
+                       u32 reg = rd32(hw, I40E_PFINT_ICR0_ENA);
+
+                       reg &= ~I40E_PFINT_ICR0_VFLR_MASK;
+                       wr32(hw, I40E_PFINT_ICR0_ENA, reg);
+               } else {
+                       ena_mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK;
+                       set_bit(__I40E_VFLR_EVENT_PENDING, pf->state);
+               }
        }
 
        if (icr0 & I40E_PFINT_ICR0_GRST_MASK) {
@@ -15311,6 +15319,11 @@ static void i40e_remove(struct pci_dev *pdev)
        while (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
                usleep_range(1000, 2000);
 
+       if (pf->flags & I40E_FLAG_SRIOV_ENABLED) {
+               set_bit(__I40E_VF_RESETS_DISABLED, pf->state);
+               i40e_free_vfs(pf);
+               pf->flags &= ~I40E_FLAG_SRIOV_ENABLED;
+       }
        /* no more scheduling of any task */
        set_bit(__I40E_SUSPENDED, pf->state);
        set_bit(__I40E_DOWN, pf->state);
@@ -15337,11 +15350,6 @@ static void i40e_remove(struct pci_dev *pdev)
         */
        i40e_notify_client_of_netdev_close(pf->vsi[pf->lan_vsi], false);
 
-       if (pf->flags & I40E_FLAG_SRIOV_ENABLED) {
-               i40e_free_vfs(pf);
-               pf->flags &= ~I40E_FLAG_SRIOV_ENABLED;
-       }
-
        i40e_fdir_teardown(pf);
 
        /* If there is a switch structure or any orphans, remove them.
index c96e2f2d4cba56d40e30ec79c73ae4df28617717..1b5390ec3d78a4e50b0a7c31c33b36669369d136 100644 (file)
@@ -1403,7 +1403,8 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf)
  * @vf: pointer to the VF structure
  * @flr: VFLR was issued or not
  *
- * Returns true if the VF is reset, false otherwise.
+ * Returns true if the VF is in reset, resets successfully, or resets
+ * are disabled and false otherwise.
  **/
 bool i40e_reset_vf(struct i40e_vf *vf, bool flr)
 {
@@ -1413,11 +1414,14 @@ bool i40e_reset_vf(struct i40e_vf *vf, bool flr)
        u32 reg;
        int i;
 
+       if (test_bit(__I40E_VF_RESETS_DISABLED, pf->state))
+               return true;
+
        /* If the VFs have been disabled, this means something else is
         * resetting the VF, so we shouldn't continue.
         */
        if (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
-               return false;
+               return true;
 
        i40e_trigger_vf_reset(vf, flr);
 
@@ -1581,6 +1585,15 @@ void i40e_free_vfs(struct i40e_pf *pf)
 
        i40e_notify_client_of_vf_enable(pf, 0);
 
+       /* Disable IOV before freeing resources. This lets any VF drivers
+        * running in the host get themselves cleaned up before we yank
+        * the carpet out from underneath their feet.
+        */
+       if (!pci_vfs_assigned(pf->pdev))
+               pci_disable_sriov(pf->pdev);
+       else
+               dev_warn(&pf->pdev->dev, "VFs are assigned - not disabling SR-IOV\n");
+
        /* Amortize wait time by stopping all VFs at the same time */
        for (i = 0; i < pf->num_alloc_vfs; i++) {
                if (test_bit(I40E_VF_STATE_INIT, &pf->vf[i].vf_states))
@@ -1596,15 +1609,6 @@ void i40e_free_vfs(struct i40e_pf *pf)
                i40e_vsi_wait_queues_disabled(pf->vsi[pf->vf[i].lan_vsi_idx]);
        }
 
-       /* Disable IOV before freeing resources. This lets any VF drivers
-        * running in the host get themselves cleaned up before we yank
-        * the carpet out from underneath their feet.
-        */
-       if (!pci_vfs_assigned(pf->pdev))
-               pci_disable_sriov(pf->pdev);
-       else
-               dev_warn(&pf->pdev->dev, "VFs are assigned - not disabling SR-IOV\n");
-
        /* free up VF resources */
        tmp = pf->num_alloc_vfs;
        pf->num_alloc_vfs = 0;
@@ -2713,6 +2717,10 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg)
                                spin_unlock_bh(&vsi->mac_filter_hash_lock);
                                goto error_param;
                        }
+                       if (is_valid_ether_addr(al->list[i].addr) &&
+                           is_zero_ether_addr(vf->default_lan_addr.addr))
+                               ether_addr_copy(vf->default_lan_addr.addr,
+                                               al->list[i].addr);
                }
        }
        spin_unlock_bh(&vsi->mac_filter_hash_lock);
@@ -2740,6 +2748,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg)
 {
        struct virtchnl_ether_addr_list *al =
            (struct virtchnl_ether_addr_list *)msg;
+       bool was_unimac_deleted = false;
        struct i40e_pf *pf = vf->pf;
        struct i40e_vsi *vsi = NULL;
        i40e_status ret = 0;
@@ -2759,6 +2768,8 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg)
                        ret = I40E_ERR_INVALID_MAC_ADDR;
                        goto error_param;
                }
+               if (ether_addr_equal(al->list[i].addr, vf->default_lan_addr.addr))
+                       was_unimac_deleted = true;
        }
        vsi = pf->vsi[vf->lan_vsi_idx];
 
@@ -2779,10 +2790,25 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg)
                dev_err(&pf->pdev->dev, "Unable to program VF %d MAC filters, error %d\n",
                        vf->vf_id, ret);
 
+       if (vf->trusted && was_unimac_deleted) {
+               struct i40e_mac_filter *f;
+               struct hlist_node *h;
+               u8 *macaddr = NULL;
+               int bkt;
+
+               /* set last unicast mac address as default */
+               spin_lock_bh(&vsi->mac_filter_hash_lock);
+               hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
+                       if (is_valid_ether_addr(f->macaddr))
+                               macaddr = f->macaddr;
+               }
+               if (macaddr)
+                       ether_addr_copy(vf->default_lan_addr.addr, macaddr);
+               spin_unlock_bh(&vsi->mac_filter_hash_lock);
+       }
 error_param:
        /* send the response to the VF */
-       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_DEL_ETH_ADDR,
-                                      ret);
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_DEL_ETH_ADDR, ret);
 }
 
 /**
index 6acede0acdca59e8407ddab65e39d94de4659079..567fd67e900efd0b2ef6b38ef7bc789be1dc247c 100644 (file)
@@ -281,8 +281,8 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget)
        unsigned int total_rx_bytes = 0, total_rx_packets = 0;
        u16 cleaned_count = I40E_DESC_UNUSED(rx_ring);
        unsigned int xdp_res, xdp_xmit = 0;
+       bool failure = false;
        struct sk_buff *skb;
-       bool failure;
 
        while (likely(total_rx_packets < (unsigned int)budget)) {
                union i40e_rx_desc *rx_desc;
index 9112dff075cf7d0f97b428decfede535c1946978..b673ac1199bbc71832b62ac84f945bca55b084da 100644 (file)
@@ -3891,21 +3891,23 @@ static int igc_change_mtu(struct net_device *netdev, int new_mtu)
 }
 
 /**
- * igc_get_stats - Get System Network Statistics
+ * igc_get_stats64 - Get System Network Statistics
  * @netdev: network interface device structure
+ * @stats: rtnl_link_stats64 pointer
  *
  * Returns the address of the device statistics structure.
  * The statistics are updated here and also from the timer callback.
  */
-static struct net_device_stats *igc_get_stats(struct net_device *netdev)
+static void igc_get_stats64(struct net_device *netdev,
+                           struct rtnl_link_stats64 *stats)
 {
        struct igc_adapter *adapter = netdev_priv(netdev);
 
+       spin_lock(&adapter->stats64_lock);
        if (!test_bit(__IGC_RESETTING, &adapter->state))
                igc_update_stats(adapter);
-
-       /* only return the current stats */
-       return &netdev->stats;
+       memcpy(stats, &adapter->stats64, sizeof(*stats));
+       spin_unlock(&adapter->stats64_lock);
 }
 
 static netdev_features_t igc_fix_features(struct net_device *netdev,
@@ -4855,7 +4857,7 @@ static const struct net_device_ops igc_netdev_ops = {
        .ndo_set_rx_mode        = igc_set_rx_mode,
        .ndo_set_mac_address    = igc_set_mac,
        .ndo_change_mtu         = igc_change_mtu,
-       .ndo_get_stats          = igc_get_stats,
+       .ndo_get_stats64        = igc_get_stats64,
        .ndo_fix_features       = igc_fix_features,
        .ndo_set_features       = igc_set_features,
        .ndo_features_check     = igc_features_check,
index 54b0bf574c05f9d7d42f32154acc919fc7889233..4a9041ee1b3915210c7deadf9a53be3f08c12b86 100644 (file)
@@ -2287,6 +2287,7 @@ mvneta_swbm_add_rx_fragment(struct mvneta_port *pp,
        dma_sync_single_for_cpu(dev->dev.parent,
                                rx_desc->buf_phys_addr,
                                len, dma_dir);
+       rx_desc->buf_phys_addr = 0;
 
        if (data_len > 0 && sinfo->nr_frags < MAX_SKB_FRAGS) {
                skb_frag_t *frag = &sinfo->frags[sinfo->nr_frags];
@@ -2295,8 +2296,8 @@ mvneta_swbm_add_rx_fragment(struct mvneta_port *pp,
                skb_frag_size_set(frag, data_len);
                __skb_frag_set_page(frag, page);
                sinfo->nr_frags++;
-
-               rx_desc->buf_phys_addr = 0;
+       } else {
+               page_pool_put_full_page(rxq->page_pool, page, true);
        }
        *size -= len;
 }
index f6616c8933ca4bffe54f439da894d1e1552d28a5..cea886c5bcb57b3e0b9950e0fb2b465768e06f20 100644 (file)
@@ -4426,6 +4426,7 @@ static int mvpp2_open(struct net_device *dev)
        if (!valid) {
                netdev_err(port->dev,
                           "invalid configuration: no dt or link IRQ");
+               err = -ENOENT;
                goto err_free_irq;
        }
 
index b1fcc44f566af71f1ae35f669dba9d541d423b5e..b6f20e2034c685cde3cdde386c719f8a3e816c5d 100644 (file)
@@ -6,6 +6,7 @@
 config PRESTERA
        tristate "Marvell Prestera Switch ASICs support"
        depends on NET_SWITCHDEV && VLAN_8021Q
+       depends on BRIDGE || BRIDGE=n
        select NET_DEVLINK
        help
          This driver supports Marvell Prestera Switch ASICs family.
index 1b97adae542e97173fa5ce65ad9e451a689c3772..be5677623455c63dc8678c3107f94dba31e2e763 100644 (file)
@@ -676,7 +676,8 @@ static int prestera_pci_probe(struct pci_dev *pdev,
        if (err)
                return err;
 
-       if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(30))) {
+       err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(30));
+       if (err) {
                dev_err(&pdev->dev, "fail to set DMA mask\n");
                goto err_dma_mask;
        }
@@ -702,8 +703,10 @@ static int prestera_pci_probe(struct pci_dev *pdev,
        dev_info(fw->dev.dev, "Prestera FW is ready\n");
 
        fw->wq = alloc_workqueue("prestera_fw_wq", WQ_HIGHPRI, 1);
-       if (!fw->wq)
+       if (!fw->wq) {
+               err = -ENOMEM;
                goto err_wq_alloc;
+       }
 
        INIT_WORK(&fw->evt_work, prestera_fw_evt_work_fn);
 
index 13250553263b55348fd50c74c149eedb96492f45..a8641a407c06a817faed34e537420ffc25e1e924 100644 (file)
@@ -966,6 +966,7 @@ static int mtk_star_enable(struct net_device *ndev)
                                      mtk_star_adjust_link, 0, priv->phy_intf);
        if (!priv->phydev) {
                netdev_err(ndev, "failed to connect to PHY\n");
+               ret = -ENODEV;
                goto err_free_irq;
        }
 
@@ -1053,7 +1054,7 @@ static int mtk_star_netdev_start_xmit(struct sk_buff *skb,
 err_drop_packet:
        dev_kfree_skb(skb);
        ndev->stats.tx_dropped++;
-       return NETDEV_TX_BUSY;
+       return NETDEV_TX_OK;
 }
 
 /* Returns the number of bytes sent or a negative number on the first
index f6ff9620a13772c66aaf205a8b1411c81275cbd9..f6cfec81ccc3bcb7b3833cca4e871e36e9283b5c 100644 (file)
@@ -1864,8 +1864,8 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
 #define         INIT_HCA_LOG_RD_OFFSET          (INIT_HCA_QPC_OFFSET + 0x77)
 #define INIT_HCA_MCAST_OFFSET           0x0c0
 #define         INIT_HCA_MC_BASE_OFFSET         (INIT_HCA_MCAST_OFFSET + 0x00)
-#define         INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12)
-#define         INIT_HCA_LOG_MC_HASH_SZ_OFFSET  (INIT_HCA_MCAST_OFFSET + 0x16)
+#define         INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x13)
+#define         INIT_HCA_LOG_MC_HASH_SZ_OFFSET  (INIT_HCA_MCAST_OFFSET + 0x17)
 #define  INIT_HCA_UC_STEERING_OFFSET    (INIT_HCA_MCAST_OFFSET + 0x18)
 #define         INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b)
 #define  INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN      0x6
@@ -1873,7 +1873,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
 #define  INIT_HCA_DRIVER_VERSION_SZ       0x40
 #define  INIT_HCA_FS_PARAM_OFFSET         0x1d0
 #define  INIT_HCA_FS_BASE_OFFSET          (INIT_HCA_FS_PARAM_OFFSET + 0x00)
-#define  INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET  (INIT_HCA_FS_PARAM_OFFSET + 0x12)
+#define  INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET  (INIT_HCA_FS_PARAM_OFFSET + 0x13)
 #define  INIT_HCA_FS_A0_OFFSET           (INIT_HCA_FS_PARAM_OFFSET + 0x18)
 #define  INIT_HCA_FS_LOG_TABLE_SZ_OFFSET  (INIT_HCA_FS_PARAM_OFFSET + 0x1b)
 #define  INIT_HCA_FS_ETH_BITS_OFFSET      (INIT_HCA_FS_PARAM_OFFSET + 0x21)
index 650ae08c71def539ed50db6103a6c036170d1eae..8f020f26ebf5fc28cbff902ff790f96658b25c17 100644 (file)
@@ -182,8 +182,8 @@ struct mlx4_init_hca_param {
        u64 cmpt_base;
        u64 mtt_base;
        u64 global_caps;
-       u16 log_mc_entry_sz;
-       u16 log_mc_hash_sz;
+       u8 log_mc_entry_sz;
+       u8 log_mc_hash_sz;
        u16 hca_core_clock; /* Internal Clock Frequency (in MHz) */
        u8  log_num_qps;
        u8  log_num_srqs;
index 3e44e4d820c5131f664369df8ba219244f86f452..95f2b26a3ee316c5f73b42a24ebad573f3b0345d 100644 (file)
@@ -187,7 +187,7 @@ static bool mlx5e_rep_is_lag_netdev(struct net_device *netdev)
        struct mlx5e_priv *priv;
 
        /* A given netdev is not a representor or not a slave of LAG configuration */
-       if (!mlx5e_eswitch_rep(netdev) || !bond_slave_get_rtnl(netdev))
+       if (!mlx5e_eswitch_rep(netdev) || !netif_is_lag_port(netdev))
                return false;
 
        priv = netdev_priv(netdev);
index e36e505d38ad819420b94afc2653ac59bfb6394e..d29af7b9c695a6da6a5d57519bc5c3cd241f89b5 100644 (file)
@@ -107,12 +107,16 @@ void mlx5e_rep_update_flows(struct mlx5e_priv *priv,
                mlx5e_tc_encap_flows_del(priv, e, &flow_list);
 
        if (neigh_connected && !(e->flags & MLX5_ENCAP_ENTRY_VALID)) {
+               struct net_device *route_dev;
+
                ether_addr_copy(e->h_dest, ha);
                ether_addr_copy(eth->h_dest, ha);
                /* Update the encap source mac, in case that we delete
                 * the flows when encap source mac changed.
                 */
-               ether_addr_copy(eth->h_source, e->route_dev->dev_addr);
+               route_dev = __dev_get_by_index(dev_net(priv->netdev), e->route_dev_ifindex);
+               if (route_dev)
+                       ether_addr_copy(eth->h_source, route_dev->dev_addr);
 
                mlx5e_tc_encap_flows_add(priv, e, &flow_list);
        }
index 7cce85faa16fafee7bdb5d68232b32978411384e..90930e54b6f2882f95336e647ca2d8b51af6d6c0 100644 (file)
@@ -77,13 +77,13 @@ static int get_route_and_out_devs(struct mlx5e_priv *priv,
        return 0;
 }
 
-static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv,
-                                  struct net_device *mirred_dev,
-                                  struct net_device **out_dev,
-                                  struct net_device **route_dev,
-                                  struct flowi4 *fl4,
-                                  struct neighbour **out_n,
-                                  u8 *out_ttl)
+static int mlx5e_route_lookup_ipv4_get(struct mlx5e_priv *priv,
+                                      struct net_device *mirred_dev,
+                                      struct net_device **out_dev,
+                                      struct net_device **route_dev,
+                                      struct flowi4 *fl4,
+                                      struct neighbour **out_n,
+                                      u8 *out_ttl)
 {
        struct neighbour *n;
        struct rtable *rt;
@@ -117,18 +117,28 @@ static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv,
                ip_rt_put(rt);
                return ret;
        }
+       dev_hold(*route_dev);
 
        if (!(*out_ttl))
                *out_ttl = ip4_dst_hoplimit(&rt->dst);
        n = dst_neigh_lookup(&rt->dst, &fl4->daddr);
        ip_rt_put(rt);
-       if (!n)
+       if (!n) {
+               dev_put(*route_dev);
                return -ENOMEM;
+       }
 
        *out_n = n;
        return 0;
 }
 
+static void mlx5e_route_lookup_ipv4_put(struct net_device *route_dev,
+                                       struct neighbour *n)
+{
+       neigh_release(n);
+       dev_put(route_dev);
+}
+
 static const char *mlx5e_netdev_kind(struct net_device *dev)
 {
        if (dev->rtnl_link_ops)
@@ -193,8 +203,8 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv,
        fl4.saddr = tun_key->u.ipv4.src;
        ttl = tun_key->ttl;
 
-       err = mlx5e_route_lookup_ipv4(priv, mirred_dev, &out_dev, &route_dev,
-                                     &fl4, &n, &ttl);
+       err = mlx5e_route_lookup_ipv4_get(priv, mirred_dev, &out_dev, &route_dev,
+                                         &fl4, &n, &ttl);
        if (err)
                return err;
 
@@ -223,7 +233,7 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv,
        e->m_neigh.family = n->ops->family;
        memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
        e->out_dev = out_dev;
-       e->route_dev = route_dev;
+       e->route_dev_ifindex = route_dev->ifindex;
 
        /* It's important to add the neigh to the hash table before checking
         * the neigh validity state. So if we'll get a notification, in case the
@@ -278,7 +288,7 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv,
 
        e->flags |= MLX5_ENCAP_ENTRY_VALID;
        mlx5e_rep_queue_neigh_stats_work(netdev_priv(out_dev));
-       neigh_release(n);
+       mlx5e_route_lookup_ipv4_put(route_dev, n);
        return err;
 
 destroy_neigh_entry:
@@ -286,18 +296,18 @@ destroy_neigh_entry:
 free_encap:
        kfree(encap_header);
 release_neigh:
-       neigh_release(n);
+       mlx5e_route_lookup_ipv4_put(route_dev, n);
        return err;
 }
 
 #if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
-static int mlx5e_route_lookup_ipv6(struct mlx5e_priv *priv,
-                                  struct net_device *mirred_dev,
-                                  struct net_device **out_dev,
-                                  struct net_device **route_dev,
-                                  struct flowi6 *fl6,
-                                  struct neighbour **out_n,
-                                  u8 *out_ttl)
+static int mlx5e_route_lookup_ipv6_get(struct mlx5e_priv *priv,
+                                      struct net_device *mirred_dev,
+                                      struct net_device **out_dev,
+                                      struct net_device **route_dev,
+                                      struct flowi6 *fl6,
+                                      struct neighbour **out_n,
+                                      u8 *out_ttl)
 {
        struct dst_entry *dst;
        struct neighbour *n;
@@ -318,15 +328,25 @@ static int mlx5e_route_lookup_ipv6(struct mlx5e_priv *priv,
                return ret;
        }
 
+       dev_hold(*route_dev);
        n = dst_neigh_lookup(dst, &fl6->daddr);
        dst_release(dst);
-       if (!n)
+       if (!n) {
+               dev_put(*route_dev);
                return -ENOMEM;
+       }
 
        *out_n = n;
        return 0;
 }
 
+static void mlx5e_route_lookup_ipv6_put(struct net_device *route_dev,
+                                       struct neighbour *n)
+{
+       neigh_release(n);
+       dev_put(route_dev);
+}
+
 int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv,
                                    struct net_device *mirred_dev,
                                    struct mlx5e_encap_entry *e)
@@ -348,8 +368,8 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv,
        fl6.daddr = tun_key->u.ipv6.dst;
        fl6.saddr = tun_key->u.ipv6.src;
 
-       err = mlx5e_route_lookup_ipv6(priv, mirred_dev, &out_dev, &route_dev,
-                                     &fl6, &n, &ttl);
+       err = mlx5e_route_lookup_ipv6_get(priv, mirred_dev, &out_dev, &route_dev,
+                                         &fl6, &n, &ttl);
        if (err)
                return err;
 
@@ -378,7 +398,7 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv,
        e->m_neigh.family = n->ops->family;
        memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
        e->out_dev = out_dev;
-       e->route_dev = route_dev;
+       e->route_dev_ifindex = route_dev->ifindex;
 
        /* It's importent to add the neigh to the hash table before checking
         * the neigh validity state. So if we'll get a notification, in case the
@@ -433,7 +453,7 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv,
 
        e->flags |= MLX5_ENCAP_ENTRY_VALID;
        mlx5e_rep_queue_neigh_stats_work(netdev_priv(out_dev));
-       neigh_release(n);
+       mlx5e_route_lookup_ipv6_put(route_dev, n);
        return err;
 
 destroy_neigh_entry:
@@ -441,7 +461,7 @@ destroy_neigh_entry:
 free_encap:
        kfree(encap_header);
 release_neigh:
-       neigh_release(n);
+       mlx5e_route_lookup_ipv6_put(route_dev, n);
        return err;
 }
 #endif
index 4e574ac730198c6bd2250a3f55169fd9e252c7ce..be3465ba38ca1f83d4450f2afa3bfe8e63f0a4f1 100644 (file)
@@ -122,9 +122,9 @@ void mlx5e_activate_xsk(struct mlx5e_channel *c)
        set_bit(MLX5E_RQ_STATE_ENABLED, &c->xskrq.state);
        /* TX queue is created active. */
 
-       spin_lock(&c->async_icosq_lock);
+       spin_lock_bh(&c->async_icosq_lock);
        mlx5e_trigger_irq(&c->async_icosq);
-       spin_unlock(&c->async_icosq_lock);
+       spin_unlock_bh(&c->async_icosq_lock);
 }
 
 void mlx5e_deactivate_xsk(struct mlx5e_channel *c)
index fb671a4571299553c38b76b970ff49ae2eee9d0f..8e96260fce1df3496cd33d5f46bda7765902052f 100644 (file)
@@ -36,9 +36,9 @@ int mlx5e_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
                if (test_and_set_bit(MLX5E_SQ_STATE_PENDING_XSK_TX, &c->async_icosq.state))
                        return 0;
 
-               spin_lock(&c->async_icosq_lock);
+               spin_lock_bh(&c->async_icosq_lock);
                mlx5e_trigger_irq(&c->async_icosq);
-               spin_unlock(&c->async_icosq_lock);
+               spin_unlock_bh(&c->async_icosq_lock);
        }
 
        return 0;
index 97f1594cee112df72589ada795ec482c5e1fe7ce..e51f60b55daa4e9b396cd5f23bf03fb081265e43 100644 (file)
@@ -44,6 +44,7 @@ static void accel_fs_tcp_set_ipv4_flow(struct mlx5_flow_spec *spec, struct sock
                         outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
 }
 
+#if IS_ENABLED(CONFIG_IPV6)
 static void accel_fs_tcp_set_ipv6_flow(struct mlx5_flow_spec *spec, struct sock *sk)
 {
        MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_protocol);
@@ -63,6 +64,7 @@ static void accel_fs_tcp_set_ipv6_flow(struct mlx5_flow_spec *spec, struct sock
                            outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
               0xff, 16);
 }
+#endif
 
 void mlx5e_accel_fs_del_sk(struct mlx5_flow_handle *rule)
 {
index 0e45590662a83087fcec79f09e96e0acb0f8b89f..381a9c8c9da9c24dc3825c46b8d7cdef47497baf 100644 (file)
@@ -64,13 +64,13 @@ static int rx_err_add_rule(struct mlx5e_priv *priv,
        if (!spec)
                return -ENOMEM;
 
-       /* Action to copy 7 bit ipsec_syndrome to regB[0:6] */
+       /* Action to copy 7 bit ipsec_syndrome to regB[24:30] */
        MLX5_SET(copy_action_in, action, action_type, MLX5_ACTION_TYPE_COPY);
        MLX5_SET(copy_action_in, action, src_field, MLX5_ACTION_IN_FIELD_IPSEC_SYNDROME);
        MLX5_SET(copy_action_in, action, src_offset, 0);
        MLX5_SET(copy_action_in, action, length, 7);
        MLX5_SET(copy_action_in, action, dst_field, MLX5_ACTION_IN_FIELD_METADATA_REG_B);
-       MLX5_SET(copy_action_in, action, dst_offset, 0);
+       MLX5_SET(copy_action_in, action, dst_offset, 24);
 
        modify_hdr = mlx5_modify_header_alloc(mdev, MLX5_FLOW_NAMESPACE_KERNEL,
                                              1, action);
@@ -488,13 +488,13 @@ static int rx_add_rule(struct mlx5e_priv *priv,
 
        setup_fte_common(attrs, ipsec_obj_id, spec, &flow_act);
 
-       /* Set 1  bit ipsec marker */
-       /* Set 24 bit ipsec_obj_id */
+       /* Set bit[31] ipsec marker */
+       /* Set bit[23-0] ipsec_obj_id */
        MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET);
        MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_B);
-       MLX5_SET(set_action_in, action, data, (ipsec_obj_id << 1) | 0x1);
-       MLX5_SET(set_action_in, action, offset, 7);
-       MLX5_SET(set_action_in, action, length, 25);
+       MLX5_SET(set_action_in, action, data, (ipsec_obj_id | BIT(31)));
+       MLX5_SET(set_action_in, action, offset, 0);
+       MLX5_SET(set_action_in, action, length, 32);
 
        modify_hdr = mlx5_modify_header_alloc(priv->mdev, MLX5_FLOW_NAMESPACE_KERNEL,
                                              1, action);
index 11e31a3db2be4bb6a2ddf8dc72bce751817d7d60..a9b45606dbdb7f6768a603d77e7ccb8253be6b31 100644 (file)
@@ -453,7 +453,6 @@ void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev,
                                       struct mlx5_cqe64 *cqe)
 {
        u32 ipsec_meta_data = be32_to_cpu(cqe->ft_metadata);
-       u8 ipsec_syndrome = ipsec_meta_data & 0xFF;
        struct mlx5e_priv *priv;
        struct xfrm_offload *xo;
        struct xfrm_state *xs;
@@ -481,7 +480,7 @@ void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev,
        xo = xfrm_offload(skb);
        xo->flags = CRYPTO_DONE;
 
-       switch (ipsec_syndrome & MLX5_IPSEC_METADATA_SYNDROM_MASK) {
+       switch (MLX5_IPSEC_METADATA_SYNDROM(ipsec_meta_data)) {
        case MLX5E_IPSEC_OFFLOAD_RX_SYNDROME_DECRYPTED:
                xo->status = CRYPTO_SUCCESS;
                if (WARN_ON_ONCE(priv->ipsec->no_trailer))
index 056dacb612b040f8b3cb709aad4e700db1611be1..9df9b9a8e09ba5bea8da15d84d8ccfeb83ecc3c4 100644 (file)
 #include "en.h"
 #include "en/txrx.h"
 
-#define MLX5_IPSEC_METADATA_MARKER_MASK      (0x80)
-#define MLX5_IPSEC_METADATA_SYNDROM_MASK     (0x7F)
-#define MLX5_IPSEC_METADATA_HANDLE(metadata) (((metadata) >> 8) & 0xFF)
+/* Bit31: IPsec marker, Bit30-24: IPsec syndrome, Bit23-0: IPsec obj id */
+#define MLX5_IPSEC_METADATA_MARKER(metadata)  (((metadata) >> 31) & 0x1)
+#define MLX5_IPSEC_METADATA_SYNDROM(metadata) (((metadata) >> 24) & GENMASK(6, 0))
+#define MLX5_IPSEC_METADATA_HANDLE(metadata)  ((metadata) & GENMASK(23, 0))
 
 struct mlx5e_accel_tx_ipsec_state {
        struct xfrm_offload *xo;
@@ -78,7 +79,7 @@ static inline unsigned int mlx5e_ipsec_tx_ids_len(struct mlx5e_accel_tx_ipsec_st
 
 static inline bool mlx5_ipsec_is_rx_flow(struct mlx5_cqe64 *cqe)
 {
-       return !!(MLX5_IPSEC_METADATA_MARKER_MASK & be32_to_cpu(cqe->ft_metadata));
+       return MLX5_IPSEC_METADATA_MARKER(be32_to_cpu(cqe->ft_metadata));
 }
 
 static inline bool mlx5e_ipsec_is_tx_flow(struct mlx5e_accel_tx_ipsec_state *ipsec_st)
index ccaccb9fc2f7b39f8f4085ecbe9d949c0052e80d..6a1d82503ef8f5fb91f695b466300d8ac9bc1a70 100644 (file)
@@ -188,7 +188,7 @@ static int post_rx_param_wqes(struct mlx5e_channel *c,
 
        err = 0;
        sq = &c->async_icosq;
-       spin_lock(&c->async_icosq_lock);
+       spin_lock_bh(&c->async_icosq_lock);
 
        cseg = post_static_params(sq, priv_rx);
        if (IS_ERR(cseg))
@@ -199,7 +199,7 @@ static int post_rx_param_wqes(struct mlx5e_channel *c,
 
        mlx5e_notify_hw(&sq->wq, sq->pc, sq->uar_map, cseg);
 unlock:
-       spin_unlock(&c->async_icosq_lock);
+       spin_unlock_bh(&c->async_icosq_lock);
 
        return err;
 
@@ -265,10 +265,10 @@ resync_post_get_progress_params(struct mlx5e_icosq *sq,
 
        BUILD_BUG_ON(MLX5E_KTLS_GET_PROGRESS_WQEBBS != 1);
 
-       spin_lock(&sq->channel->async_icosq_lock);
+       spin_lock_bh(&sq->channel->async_icosq_lock);
 
        if (unlikely(!mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, 1))) {
-               spin_unlock(&sq->channel->async_icosq_lock);
+               spin_unlock_bh(&sq->channel->async_icosq_lock);
                err = -ENOSPC;
                goto err_dma_unmap;
        }
@@ -299,7 +299,7 @@ resync_post_get_progress_params(struct mlx5e_icosq *sq,
        icosq_fill_wi(sq, pi, &wi);
        sq->pc++;
        mlx5e_notify_hw(&sq->wq, sq->pc, sq->uar_map, cseg);
-       spin_unlock(&sq->channel->async_icosq_lock);
+       spin_unlock_bh(&sq->channel->async_icosq_lock);
 
        return 0;
 
@@ -360,7 +360,7 @@ static int resync_handle_seq_match(struct mlx5e_ktls_offload_context_rx *priv_rx
        err = 0;
 
        sq = &c->async_icosq;
-       spin_lock(&c->async_icosq_lock);
+       spin_lock_bh(&c->async_icosq_lock);
 
        cseg = post_static_params(sq, priv_rx);
        if (IS_ERR(cseg)) {
@@ -372,7 +372,7 @@ static int resync_handle_seq_match(struct mlx5e_ktls_offload_context_rx *priv_rx
        mlx5e_notify_hw(&sq->wq, sq->pc, sq->uar_map, cseg);
        priv_rx->stats->tls_resync_res_ok++;
 unlock:
-       spin_unlock(&c->async_icosq_lock);
+       spin_unlock_bh(&c->async_icosq_lock);
 
        return err;
 }
@@ -476,19 +476,22 @@ static void resync_update_sn(struct mlx5e_rq *rq, struct sk_buff *skb)
 
        depth += sizeof(struct tcphdr);
 
-       if (unlikely(!sk || sk->sk_state == TCP_TIME_WAIT))
+       if (unlikely(!sk))
                return;
 
-       if (unlikely(!resync_queue_get_psv(sk)))
-               return;
+       if (unlikely(sk->sk_state == TCP_TIME_WAIT))
+               goto unref;
 
-       skb->sk = sk;
-       skb->destructor = sock_edemux;
+       if (unlikely(!resync_queue_get_psv(sk)))
+               goto unref;
 
        seq = th->seq;
        datalen = skb->len - depth;
        tls_offload_rx_resync_async_request_start(sk, seq, datalen);
        rq->stats->tls_resync_req_start++;
+
+unref:
+       sock_gen_put(sk);
 }
 
 void mlx5e_ktls_rx_resync(struct net_device *netdev, struct sock *sk,
index b3f02aac7f268cd8f18fd87601118b452e825082..ebce97921e03caad16f5384e0396e4aabde60c8b 100644 (file)
@@ -5253,6 +5253,7 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv)
 
        mlx5e_disable_async_events(priv);
        mlx5_lag_remove(mdev);
+       mlx5_vxlan_reset_to_default(mdev->vxlan);
 }
 
 int mlx5e_update_nic_rx(struct mlx5e_priv *priv)
index 9020d1419bcf622eab85e1b083f4aa664ed8a057..8932c387d46a3ef860c9ee58e790011ae23e4d27 100644 (file)
@@ -186,7 +186,7 @@ struct mlx5e_encap_entry {
        unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
 
        struct net_device *out_dev;
-       struct net_device *route_dev;
+       int route_dev_ifindex;
        struct mlx5e_tc_tunnel *tunnel;
        int reformat_type;
        u8 flags;
index 599f5b5ebc978fab7254d8143f730b0fc933447f..6628a0197b4e086d3f34d0ea3ac4a81a38514e97 100644 (file)
@@ -1584,7 +1584,7 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
        } while ((++work_done < budget) && (cqe = mlx5_cqwq_get_cqe(cqwq)));
 
 out:
-       if (rq->xdp_prog)
+       if (rcu_access_pointer(rq->xdp_prog))
                mlx5e_xdp_rx_poll_complete(rq);
 
        mlx5_cqwq_update_db_record(cqwq);
index e3a968e9e2a033bc19207d5a04695db4ac90dbdb..ce710f22b1fffbdf3ae28c5220a3dac00aff44fd 100644 (file)
@@ -4658,6 +4658,7 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv,
        return flow;
 
 err_free:
+       dealloc_mod_hdr_actions(&parse_attr->mod_hdr_acts);
        mlx5e_flow_put(priv, flow);
 out:
        return ERR_PTR(err);
@@ -4802,6 +4803,7 @@ mlx5e_add_nic_flow(struct mlx5e_priv *priv,
        return 0;
 
 err_free:
+       dealloc_mod_hdr_actions(&parse_attr->mod_hdr_acts);
        mlx5e_flow_put(priv, flow);
 out:
        return err;
@@ -5227,8 +5229,10 @@ int mlx5e_tc_nic_init(struct mlx5e_priv *priv)
 
        tc->ct = mlx5_tc_ct_init(priv, tc->chains, &priv->fs.tc.mod_hdr,
                                 MLX5_FLOW_NAMESPACE_KERNEL);
-       if (IS_ERR(tc->ct))
+       if (IS_ERR(tc->ct)) {
+               err = PTR_ERR(tc->ct);
                goto err_ct;
+       }
 
        tc->netdevice_nb.notifier_call = mlx5e_tc_netdev_event;
        err = register_netdevice_notifier_dev_net(priv->netdev,
index 3b979008143d2f3172fb0b84662c8a8913313c95..4a2ce241522e37f003665ddf15200eafc59cb0e6 100644 (file)
@@ -283,6 +283,9 @@ static inline bool mlx5e_cqe_regb_chain(struct mlx5_cqe64 *cqe)
 
        reg_b = be32_to_cpu(cqe->ft_metadata);
 
+       if (reg_b >> (MLX5E_TC_TABLE_CHAIN_TAG_BITS + ZONE_RESTORE_BITS))
+               return false;
+
        chain = reg_b & MLX5E_TC_TABLE_CHAIN_TAG_MASK;
        if (chain)
                return true;
index 82b4419af9d408b44aa1a233ecc6f0c4ea57a542..d97203cf6a007ff1f0253f9dba1fa31a51b48313 100644 (file)
@@ -144,7 +144,9 @@ static inline void mlx5e_insert_vlan(void *start, struct sk_buff *skb, u16 ihs)
        memcpy(&vhdr->h_vlan_encapsulated_proto, skb->data + cpy1_sz, cpy2_sz);
 }
 
-/* RM 2311217: no L4 inner checksum for IPsec tunnel type packet */
+/* If packet is not IP's CHECKSUM_PARTIAL (e.g. icmd packet),
+ * need to set L3 checksum flag for IPsec
+ */
 static void
 ipsec_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb,
                            struct mlx5_wqe_eth_seg *eseg)
@@ -154,19 +156,15 @@ ipsec_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb,
                eseg->cs_flags |= MLX5_ETH_WQE_L3_INNER_CSUM;
                sq->stats->csum_partial_inner++;
        } else {
-               eseg->cs_flags |= MLX5_ETH_WQE_L4_CSUM;
                sq->stats->csum_partial++;
        }
 }
 
 static inline void
-mlx5e_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb, struct mlx5_wqe_eth_seg *eseg)
+mlx5e_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb,
+                           struct mlx5e_accel_tx_state *accel,
+                           struct mlx5_wqe_eth_seg *eseg)
 {
-       if (unlikely(eseg->flow_table_metadata & cpu_to_be32(MLX5_ETH_WQE_FT_META_IPSEC))) {
-               ipsec_txwqe_build_eseg_csum(sq, skb, eseg);
-               return;
-       }
-
        if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
                eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM;
                if (skb->encapsulation) {
@@ -177,6 +175,14 @@ mlx5e_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb, struct
                        eseg->cs_flags |= MLX5_ETH_WQE_L4_CSUM;
                        sq->stats->csum_partial++;
                }
+#ifdef CONFIG_MLX5_EN_TLS
+       } else if (unlikely(accel && accel->tls.tls_tisn)) {
+               eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM;
+               sq->stats->csum_partial++;
+#endif
+       } else if (unlikely(eseg->flow_table_metadata & cpu_to_be32(MLX5_ETH_WQE_FT_META_IPSEC))) {
+               ipsec_txwqe_build_eseg_csum(sq, skb, eseg);
+
        } else
                sq->stats->csum_none++;
 }
@@ -608,12 +614,13 @@ void mlx5e_tx_mpwqe_ensure_complete(struct mlx5e_txqsq *sq)
 }
 
 static bool mlx5e_txwqe_build_eseg(struct mlx5e_priv *priv, struct mlx5e_txqsq *sq,
-                                  struct sk_buff *skb, struct mlx5_wqe_eth_seg *eseg)
+                                  struct sk_buff *skb, struct mlx5e_accel_tx_state *accel,
+                                  struct mlx5_wqe_eth_seg *eseg)
 {
        if (unlikely(!mlx5e_accel_tx_eseg(priv, skb, eseg)))
                return false;
 
-       mlx5e_txwqe_build_eseg_csum(sq, skb, eseg);
+       mlx5e_txwqe_build_eseg_csum(sq, skb, accel, eseg);
 
        return true;
 }
@@ -640,7 +647,7 @@ netdev_tx_t mlx5e_xmit(struct sk_buff *skb, struct net_device *dev)
                if (mlx5e_tx_skb_supports_mpwqe(skb, &attr)) {
                        struct mlx5_wqe_eth_seg eseg = {};
 
-                       if (unlikely(!mlx5e_txwqe_build_eseg(priv, sq, skb, &eseg)))
+                       if (unlikely(!mlx5e_txwqe_build_eseg(priv, sq, skb, &accel, &eseg)))
                                return NETDEV_TX_OK;
 
                        mlx5e_sq_xmit_mpwqe(sq, skb, &eseg, netdev_xmit_more());
@@ -657,7 +664,7 @@ netdev_tx_t mlx5e_xmit(struct sk_buff *skb, struct net_device *dev)
        /* May update the WQE, but may not post other WQEs. */
        mlx5e_accel_tx_finish(sq, wqe, &accel,
                              (struct mlx5_wqe_inline_seg *)(wqe->data + wqe_attr.ds_cnt_inl));
-       if (unlikely(!mlx5e_txwqe_build_eseg(priv, sq, skb, &wqe->eth)))
+       if (unlikely(!mlx5e_txwqe_build_eseg(priv, sq, skb, &accel, &wqe->eth)))
                return NETDEV_TX_OK;
 
        mlx5e_sq_xmit_wqe(sq, skb, &attr, &wqe_attr, wqe, pi, netdev_xmit_more());
@@ -676,7 +683,7 @@ void mlx5e_sq_xmit_simple(struct mlx5e_txqsq *sq, struct sk_buff *skb, bool xmit
        mlx5e_sq_calc_wqe_attr(skb, &attr, &wqe_attr);
        pi = mlx5e_txqsq_get_next_pi(sq, wqe_attr.num_wqebbs);
        wqe = MLX5E_TX_FETCH_WQE(sq, pi);
-       mlx5e_txwqe_build_eseg_csum(sq, skb, &wqe->eth);
+       mlx5e_txwqe_build_eseg_csum(sq, skb, NULL, &wqe->eth);
        mlx5e_sq_xmit_wqe(sq, skb, &attr, &wqe_attr, wqe, pi, xmit_more);
 }
 
@@ -945,7 +952,7 @@ void mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb,
 
        mlx5i_txwqe_build_datagram(av, dqpn, dqkey, datagram);
 
-       mlx5e_txwqe_build_eseg_csum(sq, skb, eseg);
+       mlx5e_txwqe_build_eseg_csum(sq, skb, NULL, eseg);
 
        eseg->mss = attr.mss;
 
index 6e6a9a563992830ff442ee8588aad7fac4afa2f2..d4ee0a9c03dbfc18c888fc0a313887f2b209aa30 100644 (file)
@@ -1142,6 +1142,10 @@ int mlx5_esw_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num,
        struct mlx5_vport *vport;
 
        vport = mlx5_eswitch_get_vport(esw, vport_num);
+
+       if (!vport->qos.enabled)
+               return -EOPNOTSUPP;
+
        MLX5_SET(scheduling_context, ctx, max_average_bw, rate_mbps);
 
        return mlx5_modify_scheduling_element_cmd(esw->dev,
@@ -1408,6 +1412,7 @@ static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw)
        int i;
 
        mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
+               memset(&vport->qos, 0, sizeof(vport->qos));
                memset(&vport->info, 0, sizeof(vport->info));
                vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
        }
@@ -1902,8 +1907,6 @@ int mlx5_devlink_port_function_hw_addr_get(struct devlink *devlink,
                ether_addr_copy(hw_addr, vport->info.mac);
                *hw_addr_len = ETH_ALEN;
                err = 0;
-       } else {
-               NL_SET_ERR_MSG_MOD(extack, "Eswitch vport is disabled");
        }
        mutex_unlock(&esw->state_lock);
        return err;
@@ -2223,12 +2226,15 @@ static u32 calculate_vports_min_rate_divider(struct mlx5_eswitch *esw)
                max_guarantee = evport->info.min_rate;
        }
 
-       return max_t(u32, max_guarantee / fw_max_bw_share, 1);
+       if (max_guarantee)
+               return max_t(u32, max_guarantee / fw_max_bw_share, 1);
+       return 0;
 }
 
-static int normalize_vports_min_rate(struct mlx5_eswitch *esw, u32 divider)
+static int normalize_vports_min_rate(struct mlx5_eswitch *esw)
 {
        u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
+       u32 divider = calculate_vports_min_rate_divider(esw);
        struct mlx5_vport *evport;
        u32 vport_max_rate;
        u32 vport_min_rate;
@@ -2241,9 +2247,9 @@ static int normalize_vports_min_rate(struct mlx5_eswitch *esw, u32 divider)
                        continue;
                vport_min_rate = evport->info.min_rate;
                vport_max_rate = evport->info.max_rate;
-               bw_share = MLX5_MIN_BW_SHARE;
+               bw_share = 0;
 
-               if (vport_min_rate)
+               if (divider)
                        bw_share = MLX5_RATE_TO_BW_SHARE(vport_min_rate,
                                                         divider,
                                                         fw_max_bw_share);
@@ -2268,7 +2274,6 @@ int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
        u32 fw_max_bw_share;
        u32 previous_min_rate;
-       u32 divider;
        bool min_rate_supported;
        bool max_rate_supported;
        int err = 0;
@@ -2293,8 +2298,7 @@ int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
 
        previous_min_rate = evport->info.min_rate;
        evport->info.min_rate = min_rate;
-       divider = calculate_vports_min_rate_divider(esw);
-       err = normalize_vports_min_rate(esw, divider);
+       err = normalize_vports_min_rate(esw);
        if (err) {
                evport->info.min_rate = previous_min_rate;
                goto unlock;
index 16091838bfcf9002582303d34863d7c43882dc6c..9fdd99272e3101d00bf1406e5b5712fbb49e4afe 100644 (file)
@@ -534,6 +534,13 @@ static void del_sw_hw_rule(struct fs_node *node)
                goto out;
        }
 
+       if (rule->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_PORT &&
+           --fte->dests_size) {
+               fte->modify_mask |= BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION);
+               fte->action.action &= ~MLX5_FLOW_CONTEXT_ACTION_ALLOW;
+               goto out;
+       }
+
        if ((fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) &&
            --fte->dests_size) {
                fte->modify_mask |=
@@ -2010,10 +2017,11 @@ void mlx5_del_flow_rules(struct mlx5_flow_handle *handle)
        down_write_ref_node(&fte->node, false);
        for (i = handle->num_rules - 1; i >= 0; i--)
                tree_remove_node(&handle->rule[i]->node, true);
-       if (fte->modify_mask && fte->dests_size) {
-               modify_fte(fte);
+       if (fte->dests_size) {
+               if (fte->modify_mask)
+                       modify_fte(fte);
                up_write_ref_node(&fte->node, false);
-       } else {
+       } else if (list_empty(&fte->node.children)) {
                del_hw_fte(&fte->node);
                /* Avoid double call to del_hw_fte */
                fte->node.del_hw_func = NULL;
index d046db7bb047d5f9fc9dc59b415bef0a53efb356..3a9fa629503f0e0eb889ae0e4b79dc05eafee79e 100644 (file)
@@ -90,9 +90,4 @@ int mlx5_create_encryption_key(struct mlx5_core_dev *mdev,
                               u32 key_type, u32 *p_key_id);
 void mlx5_destroy_encryption_key(struct mlx5_core_dev *mdev, u32 key_id);
 
-static inline struct net *mlx5_core_net(struct mlx5_core_dev *dev)
-{
-       return devlink_net(priv_to_devlink(dev));
-}
-
 #endif
index 3315afe2f8dce6f2e6cc1368bce9982f92cf70de..38084400ee8fab37d700f8536021851c75ed3fae 100644 (file)
@@ -167,6 +167,17 @@ struct mlx5_vxlan *mlx5_vxlan_create(struct mlx5_core_dev *mdev)
 }
 
 void mlx5_vxlan_destroy(struct mlx5_vxlan *vxlan)
+{
+       if (!mlx5_vxlan_allowed(vxlan))
+               return;
+
+       mlx5_vxlan_del_port(vxlan, IANA_VXLAN_UDP_PORT);
+       WARN_ON(!hash_empty(vxlan->htable));
+
+       kfree(vxlan);
+}
+
+void mlx5_vxlan_reset_to_default(struct mlx5_vxlan *vxlan)
 {
        struct mlx5_vxlan_port *vxlanp;
        struct hlist_node *tmp;
@@ -175,12 +186,12 @@ void mlx5_vxlan_destroy(struct mlx5_vxlan *vxlan)
        if (!mlx5_vxlan_allowed(vxlan))
                return;
 
-       /* Lockless since we are the only hash table consumers*/
        hash_for_each_safe(vxlan->htable, bkt, tmp, vxlanp, hlist) {
-               hash_del(&vxlanp->hlist);
-               mlx5_vxlan_core_del_port_cmd(vxlan->mdev, vxlanp->udp_port);
-               kfree(vxlanp);
+               /* Don't delete default UDP port added by the HW.
+                * Remove only user configured ports
+                */
+               if (vxlanp->udp_port == IANA_VXLAN_UDP_PORT)
+                       continue;
+               mlx5_vxlan_del_port(vxlan, vxlanp->udp_port);
        }
-
-       kfree(vxlan);
 }
index ec766529f49b6902e2da40d8fe58d167753bac31..34ef662da35ed4a04a194f895bc764440aa3c741 100644 (file)
@@ -56,6 +56,7 @@ void mlx5_vxlan_destroy(struct mlx5_vxlan *vxlan);
 int mlx5_vxlan_add_port(struct mlx5_vxlan *vxlan, u16 port);
 int mlx5_vxlan_del_port(struct mlx5_vxlan *vxlan, u16 port);
 bool mlx5_vxlan_lookup_port(struct mlx5_vxlan *vxlan, u16 port);
+void mlx5_vxlan_reset_to_default(struct mlx5_vxlan *vxlan);
 #else
 static inline struct mlx5_vxlan*
 mlx5_vxlan_create(struct mlx5_core_dev *mdev) { return ERR_PTR(-EOPNOTSUPP); }
@@ -63,6 +64,7 @@ static inline void mlx5_vxlan_destroy(struct mlx5_vxlan *vxlan) { return; }
 static inline int mlx5_vxlan_add_port(struct mlx5_vxlan *vxlan, u16 port) { return -EOPNOTSUPP; }
 static inline int mlx5_vxlan_del_port(struct mlx5_vxlan *vxlan, u16 port) { return -EOPNOTSUPP; }
 static inline bool mlx5_vxlan_lookup_port(struct mlx5_vxlan *vxlan, u16 port) { return false; }
+static inline void mlx5_vxlan_reset_to_default(struct mlx5_vxlan *vxlan) { return; }
 #endif
 
 #endif /* __MLX5_VXLAN_H__ */
index 150638814517c3e4376c62c8fd50dae009261717..4d7f8a357df76eacdb59099207b29c0c99ebf229 100644 (file)
@@ -422,6 +422,24 @@ static void release_all_pages(struct mlx5_core_dev *dev, u32 func_id,
                      npages, ec_function, func_id);
 }
 
+static u32 fwp_fill_manage_pages_out(struct fw_page *fwp, u32 *out, u32 index,
+                                    u32 npages)
+{
+       u32 pages_set = 0;
+       unsigned int n;
+
+       for_each_clear_bit(n, &fwp->bitmask, MLX5_NUM_4K_IN_PAGE) {
+               MLX5_ARRAY_SET64(manage_pages_out, out, pas, index + pages_set,
+                                fwp->addr + (n * MLX5_ADAPTER_PAGE_SIZE));
+               pages_set++;
+
+               if (!--npages)
+                       break;
+       }
+
+       return pages_set;
+}
+
 static int reclaim_pages_cmd(struct mlx5_core_dev *dev,
                             u32 *in, int in_size, u32 *out, int out_size)
 {
@@ -448,8 +466,7 @@ static int reclaim_pages_cmd(struct mlx5_core_dev *dev,
                fwp = rb_entry(p, struct fw_page, rb_node);
                p = rb_next(p);
 
-               MLX5_ARRAY_SET64(manage_pages_out, out, pas, i, fwp->addr);
-               i++;
+               i += fwp_fill_manage_pages_out(fwp, out, i, npages - i);
        }
 
        MLX5_SET(manage_pages_out, out, output_num_entries, i);
index 6bd34b29300718b4ad00fae2696dd5e5a2994bbd..51bbd88ff021cce252c6dc1738279c55bbf89075 100644 (file)
@@ -92,6 +92,7 @@ int mlx5dr_cmd_query_device(struct mlx5_core_dev *mdev,
        caps->eswitch_manager   = MLX5_CAP_GEN(mdev, eswitch_manager);
        caps->gvmi              = MLX5_CAP_GEN(mdev, vhca_id);
        caps->flex_protocols    = MLX5_CAP_GEN(mdev, flex_parser_protocols);
+       caps->sw_format_ver     = MLX5_CAP_GEN(mdev, steering_format_version);
 
        if (mlx5dr_matcher_supp_flex_parser_icmp_v4(caps)) {
                caps->flex_parser_id_icmp_dw0 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw0);
index 890767a2a7cb25262657760c4fcce460c5a04854..aa2c2d6c44e6bb26a9ad500c63df30c1319a4293 100644 (file)
@@ -223,6 +223,11 @@ static int dr_domain_caps_init(struct mlx5_core_dev *mdev,
        if (ret)
                return ret;
 
+       if (dmn->info.caps.sw_format_ver != MLX5_STEERING_FORMAT_CONNECTX_5) {
+               mlx5dr_err(dmn, "SW steering is not supported on this device\n");
+               return -EOPNOTSUPP;
+       }
+
        ret = dr_domain_query_fdb_caps(mdev, dmn);
        if (ret)
                return ret;
index f50f3b107aa3172edb9c9078f3bcad12038bd14f..cf62ea4f882e68df95cd2dd69275b5eff35e5a6c 100644 (file)
@@ -625,6 +625,7 @@ struct mlx5dr_cmd_caps {
        u8 max_ft_level;
        u16 roce_min_src_udp;
        u8 num_esw_ports;
+       u8 sw_format_ver;
        bool eswitch_manager;
        bool rx_sw_owner;
        bool tx_sw_owner;
index 872e9910bb7c3c4481b57b0863ce6b7a2e8dadb0..a619d90559f7010afdb972086adf9538bbf67f27 100644 (file)
@@ -6,6 +6,7 @@
 config MLXSW_CORE
        tristate "Mellanox Technologies Switch ASICs support"
        select NET_DEVLINK
+       select MLXFW
        help
          This driver supports Mellanox Technologies Switch ASICs family.
 
@@ -82,7 +83,6 @@ config MLXSW_SPECTRUM
        select GENERIC_ALLOCATOR
        select PARMAN
        select OBJAGG
-       select MLXFW
        imply PTP_1588_CLOCK
        select NET_PTP_CLASSIFY if PTP_1588_CLOCK
        default m
index 7f77c2a71d1c63682a119ed64a197ae34446e951..1a86535c496858dd413fda33bb0c18d9cee5f222 100644 (file)
@@ -571,7 +571,8 @@ static void mlxsw_emad_trans_timeout_schedule(struct mlxsw_reg_trans *trans)
        if (trans->core->fw_flash_in_progress)
                timeout = msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_DURING_FW_FLASH_MS);
 
-       queue_delayed_work(trans->core->emad_wq, &trans->timeout_dw, timeout);
+       queue_delayed_work(trans->core->emad_wq, &trans->timeout_dw,
+                          timeout << trans->retries);
 }
 
 static int mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core,
@@ -620,6 +621,9 @@ static void mlxsw_emad_transmit_retry(struct mlxsw_core *mlxsw_core,
                err = mlxsw_emad_transmit(trans->core, trans);
                if (err == 0)
                        return;
+
+               if (!atomic_dec_and_test(&trans->active))
+                       return;
        } else {
                err = -EIO;
        }
@@ -2064,6 +2068,8 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
        if (!reload)
                devlink_resources_unregister(devlink, NULL);
        mlxsw_core->bus->fini(mlxsw_core->bus_priv);
+       if (!reload)
+               devlink_free(devlink);
 
        return;
 
index 16b47fce540bb1b3ac77cd5d2524ccf36a9052bc..b08853f71b2beae79e1458e2fc2cb77eb6d4dec5 100644 (file)
@@ -1174,11 +1174,14 @@ mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port)
        u32 eth_proto_cap, eth_proto_admin, eth_proto_oper;
        const struct mlxsw_sp_port_type_speed_ops *ops;
        char ptys_pl[MLXSW_REG_PTYS_LEN];
+       u32 eth_proto_cap_masked;
        int err;
 
        ops = mlxsw_sp->port_type_speed_ops;
 
-       /* Set advertised speeds to supported speeds. */
+       /* Set advertised speeds to speeds supported by both the driver
+        * and the device.
+        */
        ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
                               0, false);
        err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
@@ -1187,8 +1190,10 @@ mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port)
 
        ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap,
                                 &eth_proto_admin, &eth_proto_oper);
+       eth_proto_cap_masked = ops->ptys_proto_cap_masked_get(eth_proto_cap);
        ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
-                              eth_proto_cap, mlxsw_sp_port->link.autoneg);
+                              eth_proto_cap_masked,
+                              mlxsw_sp_port->link.autoneg);
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
 }
 
index 3e26eb6cb1404a0feb4decab8a8b1e09916c6b55..74b3959b36d4db43e23c7d4c20c690ac899a1e48 100644 (file)
@@ -342,6 +342,7 @@ struct mlxsw_sp_port_type_speed_ops {
                                    u32 *p_eth_proto_cap,
                                    u32 *p_eth_proto_admin,
                                    u32 *p_eth_proto_oper);
+       u32 (*ptys_proto_cap_masked_get)(u32 eth_proto_cap);
 };
 
 static inline struct net_device *
index 2096b6478958234c7e39c20be87a7b2be7c40cdb..540616469e2849abd00b9a7f742a06e6753ef7d7 100644 (file)
@@ -1303,6 +1303,20 @@ mlxsw_sp1_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
                                  p_eth_proto_oper);
 }
 
+static u32 mlxsw_sp1_ptys_proto_cap_masked_get(u32 eth_proto_cap)
+{
+       u32 ptys_proto_cap_masked = 0;
+       int i;
+
+       for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
+               if (mlxsw_sp1_port_link_mode[i].mask & eth_proto_cap)
+                       ptys_proto_cap_masked |=
+                               mlxsw_sp1_port_link_mode[i].mask;
+       }
+
+       return ptys_proto_cap_masked;
+}
+
 const struct mlxsw_sp_port_type_speed_ops mlxsw_sp1_port_type_speed_ops = {
        .from_ptys_supported_port       = mlxsw_sp1_from_ptys_supported_port,
        .from_ptys_link                 = mlxsw_sp1_from_ptys_link,
@@ -1313,6 +1327,7 @@ const struct mlxsw_sp_port_type_speed_ops mlxsw_sp1_port_type_speed_ops = {
        .to_ptys_speed                  = mlxsw_sp1_to_ptys_speed,
        .reg_ptys_eth_pack              = mlxsw_sp1_reg_ptys_eth_pack,
        .reg_ptys_eth_unpack            = mlxsw_sp1_reg_ptys_eth_unpack,
+       .ptys_proto_cap_masked_get      = mlxsw_sp1_ptys_proto_cap_masked_get,
 };
 
 static const enum ethtool_link_mode_bit_indices
@@ -1731,6 +1746,20 @@ mlxsw_sp2_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
                                      p_eth_proto_admin, p_eth_proto_oper);
 }
 
+static u32 mlxsw_sp2_ptys_proto_cap_masked_get(u32 eth_proto_cap)
+{
+       u32 ptys_proto_cap_masked = 0;
+       int i;
+
+       for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
+               if (mlxsw_sp2_port_link_mode[i].mask & eth_proto_cap)
+                       ptys_proto_cap_masked |=
+                               mlxsw_sp2_port_link_mode[i].mask;
+       }
+
+       return ptys_proto_cap_masked;
+}
+
 const struct mlxsw_sp_port_type_speed_ops mlxsw_sp2_port_type_speed_ops = {
        .from_ptys_supported_port       = mlxsw_sp2_from_ptys_supported_port,
        .from_ptys_link                 = mlxsw_sp2_from_ptys_link,
@@ -1741,4 +1770,5 @@ const struct mlxsw_sp_port_type_speed_ops mlxsw_sp2_port_type_speed_ops = {
        .to_ptys_speed                  = mlxsw_sp2_to_ptys_speed,
        .reg_ptys_eth_pack              = mlxsw_sp2_reg_ptys_eth_pack,
        .reg_ptys_eth_unpack            = mlxsw_sp2_reg_ptys_eth_unpack,
+       .ptys_proto_cap_masked_get      = mlxsw_sp2_ptys_proto_cap_masked_get,
 };
index a1938842f828e339ae960c990c53a5b719f4bd9d..b319c22c211cd3f1c64c4fbae381d6375a5e3ecc 100644 (file)
@@ -148,7 +148,8 @@ static void lan743x_intr_software_isr(void *context)
 
        int_sts = lan743x_csr_read(adapter, INT_STS);
        if (int_sts & INT_BIT_SW_GP_) {
-               lan743x_csr_write(adapter, INT_STS, INT_BIT_SW_GP_);
+               /* disable the interrupt to prevent repeated re-triggering */
+               lan743x_csr_write(adapter, INT_EN_CLR, INT_BIT_SW_GP_);
                intr->software_isr_flag = 1;
        }
 }
@@ -674,14 +675,12 @@ clean_up:
 static int lan743x_dp_write(struct lan743x_adapter *adapter,
                            u32 select, u32 addr, u32 length, u32 *buf)
 {
-       int ret = -EIO;
        u32 dp_sel;
        int i;
 
-       mutex_lock(&adapter->dp_lock);
        if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_,
                                     1, 40, 100, 100))
-               goto unlock;
+               return -EIO;
        dp_sel = lan743x_csr_read(adapter, DP_SEL);
        dp_sel &= ~DP_SEL_MASK_;
        dp_sel |= select;
@@ -693,13 +692,10 @@ static int lan743x_dp_write(struct lan743x_adapter *adapter,
                lan743x_csr_write(adapter, DP_CMD, DP_CMD_WRITE_);
                if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_,
                                             1, 40, 100, 100))
-                       goto unlock;
+                       return -EIO;
        }
-       ret = 0;
 
-unlock:
-       mutex_unlock(&adapter->dp_lock);
-       return ret;
+       return 0;
 }
 
 static u32 lan743x_mac_mii_access(u16 id, u16 index, int read)
@@ -1019,16 +1015,16 @@ static void lan743x_phy_close(struct lan743x_adapter *adapter)
 static int lan743x_phy_open(struct lan743x_adapter *adapter)
 {
        struct lan743x_phy *phy = &adapter->phy;
+       struct phy_device *phydev = NULL;
        struct device_node *phynode;
-       struct phy_device *phydev;
        struct net_device *netdev;
        int ret = -EIO;
 
        netdev = adapter->netdev;
        phynode = of_node_get(adapter->pdev->dev.of_node);
-       adapter->phy_mode = PHY_INTERFACE_MODE_GMII;
 
        if (phynode) {
+               /* try devicetree phy, or fixed link */
                of_get_phy_mode(phynode, &adapter->phy_mode);
 
                if (of_phy_is_fixed_link(phynode)) {
@@ -1044,13 +1040,15 @@ static int lan743x_phy_open(struct lan743x_adapter *adapter)
                                        lan743x_phy_link_status_change, 0,
                                        adapter->phy_mode);
                of_node_put(phynode);
-               if (!phydev)
-                       goto return_error;
-       } else {
+       }
+
+       if (!phydev) {
+               /* try internal phy */
                phydev = phy_find_first(adapter->mdiobus);
                if (!phydev)
                        goto return_error;
 
+               adapter->phy_mode = PHY_INTERFACE_MODE_GMII;
                ret = phy_connect_direct(netdev, phydev,
                                         lan743x_phy_link_status_change,
                                         adapter->phy_mode);
@@ -1310,13 +1308,13 @@ clean_up_data_descriptor:
                goto clear_active;
 
        if (!(buffer_info->flags & TX_BUFFER_INFO_FLAG_TIMESTAMP_REQUESTED)) {
-               dev_kfree_skb(buffer_info->skb);
+               dev_kfree_skb_any(buffer_info->skb);
                goto clear_skb;
        }
 
        if (cleanup) {
                lan743x_ptp_unrequest_tx_timestamp(tx->adapter);
-               dev_kfree_skb(buffer_info->skb);
+               dev_kfree_skb_any(buffer_info->skb);
        } else {
                ignore_sync = (buffer_info->flags &
                               TX_BUFFER_INFO_FLAG_IGNORE_SYNC) != 0;
@@ -1626,7 +1624,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
        if (required_number_of_descriptors >
                lan743x_tx_get_avail_desc(tx)) {
                if (required_number_of_descriptors > (tx->ring_size - 1)) {
-                       dev_kfree_skb(skb);
+                       dev_kfree_skb_irq(skb);
                } else {
                        /* save to overflow buffer */
                        tx->overflow_skb = skb;
@@ -1659,7 +1657,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
                                   start_frame_length,
                                   do_timestamp,
                                   skb->ip_summed == CHECKSUM_PARTIAL)) {
-               dev_kfree_skb(skb);
+               dev_kfree_skb_irq(skb);
                goto unlock;
        }
 
@@ -1678,7 +1676,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
                         * frame assembler clean up was performed inside
                         *      lan743x_tx_frame_add_fragment
                         */
-                       dev_kfree_skb(skb);
+                       dev_kfree_skb_irq(skb);
                        goto unlock;
                }
        }
@@ -2733,7 +2731,6 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
 
        adapter->intr.irq = adapter->pdev->irq;
        lan743x_csr_write(adapter, INT_EN_CLR, 0xFFFFFFFF);
-       mutex_init(&adapter->dp_lock);
 
        ret = lan743x_gpio_init(adapter);
        if (ret)
index c61a404113179d6afb4dfa136c2619c14b98a582..a536f4a4994dfa98e46cc3ad13e15bb6db5e71ac 100644 (file)
@@ -712,9 +712,6 @@ struct lan743x_adapter {
        struct lan743x_csr      csr;
        struct lan743x_intr     intr;
 
-       /* lock, used to prevent concurrent access to data port */
-       struct mutex            dp_lock;
-
        struct lan743x_gpio     gpio;
        struct lan743x_ptp      ptp;
 
index be6660128b556ad496457ae98ab6ce8fc626fe96..040a15a828b41bb54c71af22cd047ccc27bbbb54 100644 (file)
@@ -1078,16 +1078,20 @@ static int pasemi_mac_open(struct net_device *dev)
 
        mac->tx = pasemi_mac_setup_tx_resources(dev);
 
-       if (!mac->tx)
+       if (!mac->tx) {
+               ret = -ENOMEM;
                goto out_tx_ring;
+       }
 
        /* We might already have allocated rings in case mtu was changed
         * before interface was brought up.
         */
        if (dev->mtu > 1500 && !mac->num_cs) {
                pasemi_mac_setup_csrings(mac);
-               if (!mac->num_cs)
+               if (!mac->num_cs) {
+                       ret = -ENOMEM;
                        goto out_tx_ring;
+               }
        }
 
        /* Zero out rmon counters */
index 545c99b15df8e02fca4b5b4c7f87ee60990f2907..dc5fbc2704f3a3b4f3c37fddcb686a4ea7d804d9 100644 (file)
@@ -333,7 +333,7 @@ int ionic_set_vf_config(struct ionic *ionic, int vf, u8 attr, u8 *data)
        union ionic_dev_cmd cmd = {
                .vf_setattr.opcode = IONIC_CMD_VF_SETATTR,
                .vf_setattr.attr = attr,
-               .vf_setattr.vf_index = vf,
+               .vf_setattr.vf_index = cpu_to_le16(vf),
        };
        int err;
 
@@ -391,7 +391,7 @@ void ionic_dev_cmd_queue_identify(struct ionic_dev *idev,
 {
        union ionic_dev_cmd cmd = {
                .q_identify.opcode = IONIC_CMD_Q_IDENTIFY,
-               .q_identify.lif_type = lif_type,
+               .q_identify.lif_type = cpu_to_le16(lif_type),
                .q_identify.type = qtype,
                .q_identify.ver = qver,
        };
index c109cd5a04713e28328ed233ff5a9e15092e36fa..6c243b17312c729ea5fe0050e37bd21f5734abd0 100644 (file)
@@ -29,6 +29,7 @@ struct ionic_dev_bar {
        int res_index;
 };
 
+#ifndef __CHECKER__
 /* Registers */
 static_assert(sizeof(struct ionic_intr) == 32);
 
@@ -119,6 +120,7 @@ static_assert(sizeof(struct ionic_vf_setattr_cmd) == 64);
 static_assert(sizeof(struct ionic_vf_setattr_comp) == 16);
 static_assert(sizeof(struct ionic_vf_getattr_cmd) == 64);
 static_assert(sizeof(struct ionic_vf_getattr_comp) == 16);
+#endif /* __CHECKER__ */
 
 struct ionic_devinfo {
        u8 asic_type;
index ed9808fc743b218fa280d28d3ffb72d1c7c0ddd3..35c72d4a78b3f9ed37c4ae173346848790362484 100644 (file)
@@ -126,6 +126,11 @@ static int ionic_get_link_ksettings(struct net_device *netdev,
 
        ethtool_link_ksettings_zero_link_mode(ks, supported);
 
+       if (!idev->port_info) {
+               netdev_err(netdev, "port_info not initialized\n");
+               return -EOPNOTSUPP;
+       }
+
        /* The port_info data is found in a DMA space that the NIC keeps
         * up-to-date, so there's no need to request the data from the
         * NIC, we already have it in our memory space.
index f492ae406a605bb39933859f419a1f065a32621e..d7bbf336c6f65c505e176e13646f035e0fef15cd 100644 (file)
@@ -27,9 +27,9 @@ static void ionic_dev_cmd_firmware_download(struct ionic_dev *idev, u64 addr,
 {
        union ionic_dev_cmd cmd = {
                .fw_download.opcode = IONIC_CMD_FW_DOWNLOAD,
-               .fw_download.offset = offset,
-               .fw_download.addr = addr,
-               .fw_download.length = length
+               .fw_download.offset = cpu_to_le32(offset),
+               .fw_download.addr = cpu_to_le64(addr),
+               .fw_download.length = cpu_to_le32(length),
        };
 
        ionic_dev_cmd_go(idev, &cmd);
index d655a7ae3058cf401204be51ce4160581ac31981..a12df3946a07cdcb89474d1687755bb2a3019401 100644 (file)
@@ -1656,7 +1656,6 @@ static void ionic_txrx_deinit(struct ionic_lif *lif)
        if (lif->rxqcqs) {
                for (i = 0; i < lif->nxqs && lif->rxqcqs[i]; i++) {
                        ionic_lif_qcq_deinit(lif, lif->rxqcqs[i]);
-                       ionic_rx_flush(&lif->rxqcqs[i]->cq);
                        ionic_rx_empty(&lif->rxqcqs[i]->q);
                }
        }
@@ -1915,11 +1914,11 @@ static int ionic_get_vf_config(struct net_device *netdev,
                ret = -EINVAL;
        } else {
                ivf->vf           = vf;
-               ivf->vlan         = ionic->vfs[vf].vlanid;
+               ivf->vlan         = le16_to_cpu(ionic->vfs[vf].vlanid);
                ivf->qos          = 0;
                ivf->spoofchk     = ionic->vfs[vf].spoofchk;
                ivf->linkstate    = ionic->vfs[vf].linkstate;
-               ivf->max_tx_rate  = ionic->vfs[vf].maxrate;
+               ivf->max_tx_rate  = le32_to_cpu(ionic->vfs[vf].maxrate);
                ivf->trusted      = ionic->vfs[vf].trusted;
                ether_addr_copy(ivf->mac, ionic->vfs[vf].macaddr);
        }
@@ -2019,7 +2018,7 @@ static int ionic_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan,
                ret = ionic_set_vf_config(ionic, vf,
                                          IONIC_VF_ATTR_VLAN, (u8 *)&vlan);
                if (!ret)
-                       ionic->vfs[vf].vlanid = vlan;
+                       ionic->vfs[vf].vlanid = cpu_to_le16(vlan);
        }
 
        up_write(&ionic->vf_op_lock);
@@ -2048,7 +2047,7 @@ static int ionic_set_vf_rate(struct net_device *netdev, int vf,
                ret = ionic_set_vf_config(ionic, vf,
                                          IONIC_VF_ATTR_RATE, (u8 *)&tx_max);
                if (!ret)
-                       lif->ionic->vfs[vf].maxrate = tx_max;
+                       lif->ionic->vfs[vf].maxrate = cpu_to_le32(tx_max);
        }
 
        up_write(&ionic->vf_op_lock);
@@ -2981,14 +2980,14 @@ void ionic_lif_unregister(struct ionic_lif *lif)
 
 static void ionic_lif_queue_identify(struct ionic_lif *lif)
 {
+       union ionic_q_identity __iomem *q_ident;
        struct ionic *ionic = lif->ionic;
-       union ionic_q_identity *q_ident;
        struct ionic_dev *idev;
        int qtype;
        int err;
 
        idev = &lif->ionic->idev;
-       q_ident = (union ionic_q_identity *)&idev->dev_cmd_regs->data;
+       q_ident = (union ionic_q_identity __iomem *)&idev->dev_cmd_regs->data;
 
        for (qtype = 0; qtype < ARRAY_SIZE(ionic_qtype_versions); qtype++) {
                struct ionic_qtype_info *qti = &lif->qtype_info[qtype];
@@ -3011,14 +3010,14 @@ static void ionic_lif_queue_identify(struct ionic_lif *lif)
                                             ionic_qtype_versions[qtype]);
                err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
                if (!err) {
-                       qti->version   = q_ident->version;
-                       qti->supported = q_ident->supported;
-                       qti->features  = le64_to_cpu(q_ident->features);
-                       qti->desc_sz   = le16_to_cpu(q_ident->desc_sz);
-                       qti->comp_sz   = le16_to_cpu(q_ident->comp_sz);
-                       qti->sg_desc_sz   = le16_to_cpu(q_ident->sg_desc_sz);
-                       qti->max_sg_elems = le16_to_cpu(q_ident->max_sg_elems);
-                       qti->sg_desc_stride = le16_to_cpu(q_ident->sg_desc_stride);
+                       qti->version   = readb(&q_ident->version);
+                       qti->supported = readb(&q_ident->supported);
+                       qti->features  = readq(&q_ident->features);
+                       qti->desc_sz   = readw(&q_ident->desc_sz);
+                       qti->comp_sz   = readw(&q_ident->comp_sz);
+                       qti->sg_desc_sz   = readw(&q_ident->sg_desc_sz);
+                       qti->max_sg_elems = readw(&q_ident->max_sg_elems);
+                       qti->sg_desc_stride = readw(&q_ident->sg_desc_stride);
                }
                mutex_unlock(&ionic->dev_cmd_lock);
 
index ee0740881af31cd5512839a1a96cf420715d396f..d355676f6c160d685239d52565cf96075297eae2 100644 (file)
@@ -311,7 +311,7 @@ int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
 
 static void ionic_dev_cmd_clean(struct ionic *ionic)
 {
-       union ionic_dev_cmd_regs *regs = ionic->idev.dev_cmd_regs;
+       union __iomem ionic_dev_cmd_regs *regs = ionic->idev.dev_cmd_regs;
 
        iowrite32(0, &regs->doorbell);
        memset_io(&regs->cmd, 0, sizeof(regs->cmd));
@@ -333,7 +333,7 @@ int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds)
         */
        max_wait = jiffies + (max_seconds * HZ);
 try_again:
-       opcode = idev->dev_cmd_regs->cmd.cmd.opcode;
+       opcode = readb(&idev->dev_cmd_regs->cmd.cmd.opcode);
        start_time = jiffies;
        do {
                done = ionic_dev_cmd_done(idev);
index 3f543512616ee5eca55bafc36956a952bf12eef3..2a725834f792251d83b7ebb91208584cb84cc6b6 100644 (file)
@@ -49,7 +49,7 @@ extern const int ionic_num_stats_grps;
        (*((u64 *)(((u8 *)(base_ptr)) + (desc_ptr)->offset)))
 
 #define IONIC_READ_STAT_LE64(base_ptr, desc_ptr) \
-       __le64_to_cpu(*((u64 *)(((u8 *)(base_ptr)) + (desc_ptr)->offset)))
+       __le64_to_cpu(*((__le64 *)(((u8 *)(base_ptr)) + (desc_ptr)->offset)))
 
 struct ionic_stat_desc {
        char name[ETH_GSTRING_LEN];
index 169ac4f54640dfd4c60e5c72c1ef017a74a80a9e..b3d2250c77d0492fc1ca67ba92c08b67b88e9a4a 100644 (file)
@@ -200,7 +200,7 @@ static void ionic_rx_clean(struct ionic_queue *q,
        if (likely(netdev->features & NETIF_F_RXCSUM)) {
                if (comp->csum_flags & IONIC_RXQ_COMP_CSUM_F_CALC) {
                        skb->ip_summed = CHECKSUM_COMPLETE;
-                       skb->csum = (__wsum)le16_to_cpu(comp->csum);
+                       skb->csum = (__force __wsum)le16_to_cpu(comp->csum);
                        stats->csum_complete++;
                }
        } else {
@@ -253,19 +253,6 @@ static bool ionic_rx_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info)
        return true;
 }
 
-void ionic_rx_flush(struct ionic_cq *cq)
-{
-       struct ionic_dev *idev = &cq->lif->ionic->idev;
-       u32 work_done;
-
-       work_done = ionic_cq_service(cq, cq->num_descs,
-                                    ionic_rx_service, NULL, NULL);
-
-       if (work_done)
-               ionic_intr_credits(idev->intr_ctrl, cq->bound_intr->index,
-                                  work_done, IONIC_INTR_CRED_RESET_COALESCE);
-}
-
 static int ionic_rx_page_alloc(struct ionic_queue *q,
                               struct ionic_page_info *page_info)
 {
@@ -413,22 +400,20 @@ static void ionic_rx_fill_cb(void *arg)
 void ionic_rx_empty(struct ionic_queue *q)
 {
        struct ionic_desc_info *desc_info;
-       struct ionic_rxq_desc *desc;
-       unsigned int i;
-       u16 idx;
-
-       idx = q->tail_idx;
-       while (idx != q->head_idx) {
-               desc_info = &q->info[idx];
-               desc = desc_info->desc;
-               desc->addr = 0;
-               desc->len = 0;
+       struct ionic_page_info *page_info;
+       unsigned int i, j;
 
-               for (i = 0; i < desc_info->npages; i++)
-                       ionic_rx_page_free(q, &desc_info->pages[i]);
+       for (i = 0; i < q->num_descs; i++) {
+               desc_info = &q->info[i];
+               for (j = 0; j < IONIC_RX_MAX_SG_ELEMS + 1; j++) {
+                       page_info = &desc_info->pages[j];
+                       if (page_info->page)
+                               ionic_rx_page_free(q, page_info);
+               }
 
+               desc_info->npages = 0;
+               desc_info->cb = NULL;
                desc_info->cb_arg = NULL;
-               idx = (idx + 1) & (q->num_descs - 1);
        }
 }
 
@@ -812,6 +797,7 @@ static int ionic_tx_tso(struct ionic_queue *q, struct sk_buff *skb)
        skb_frag_t *frag;
        bool start, done;
        bool outer_csum;
+       dma_addr_t addr;
        bool has_vlan;
        u16 desc_len;
        u8 desc_nsge;
@@ -893,11 +879,10 @@ static int ionic_tx_tso(struct ionic_queue *q, struct sk_buff *skb)
                        if (frag_left > 0) {
                                len = min(frag_left, left);
                                frag_left -= len;
-                               elem->addr =
-                                   cpu_to_le64(ionic_tx_map_frag(q, frag,
-                                                                 offset, len));
-                               if (dma_mapping_error(dev, elem->addr))
+                               addr = ionic_tx_map_frag(q, frag, offset, len);
+                               if (dma_mapping_error(dev, addr))
                                        goto err_out_abort;
+                               elem->addr = cpu_to_le64(addr);
                                elem->len = cpu_to_le16(len);
                                elem++;
                                desc_nsge++;
index a5883be0413f6da4e6bbef642f049521182e382c..7667b72232b8a32da7a33eb8e58383707544f61b 100644 (file)
@@ -4,7 +4,6 @@
 #ifndef _IONIC_TXRX_H_
 #define _IONIC_TXRX_H_
 
-void ionic_rx_flush(struct ionic_cq *cq);
 void ionic_tx_flush(struct ionic_cq *cq);
 
 void ionic_rx_fill(struct ionic_queue *q);
index 0e4cd8890cffc8d4dc303d852f38914ef356424f..0a22f8ce9a2c34ae82f2b64bc8625834e52b40e4 100644 (file)
@@ -1647,9 +1647,9 @@ static void qed_src_init_pf(struct qed_hwfn *p_hwfn)
                     ilog2(rounded_conn_num));
 
        STORE_RT_REG_AGG(p_hwfn, SRC_REG_FIRSTFREE_RT_OFFSET,
-                        p_hwfn->p_cxt_mngr->first_free);
+                        p_hwfn->p_cxt_mngr->src_t2.first_free);
        STORE_RT_REG_AGG(p_hwfn, SRC_REG_LASTFREE_RT_OFFSET,
-                        p_hwfn->p_cxt_mngr->last_free);
+                        p_hwfn->p_cxt_mngr->src_t2.last_free);
 }
 
 /* Timers PF */
index 8b64495f87454bdb06401acabd43eec427a503e8..056e79620a0e2fc6c870f352e063c7e9158a6478 100644 (file)
@@ -326,9 +326,6 @@ struct qed_cxt_mngr {
 
        /* SRC T2 */
        struct qed_src_t2 src_t2;
-       u32 t2_num_pages;
-       u64 first_free;
-       u64 last_free;
 
        /* total number of SRQ's for this hwfn */
        u32 srq_count;
index 512cbef240979c6970a9573708827c5ecfcfebdf..a99861124630a5e59ed6263d7b219b4ef8ea5a5b 100644 (file)
@@ -2754,14 +2754,18 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn,
        iwarp_info->partial_fpdus = kcalloc((u16)p_hwfn->p_rdma_info->num_qps,
                                            sizeof(*iwarp_info->partial_fpdus),
                                            GFP_KERNEL);
-       if (!iwarp_info->partial_fpdus)
+       if (!iwarp_info->partial_fpdus) {
+               rc = -ENOMEM;
                goto err;
+       }
 
        iwarp_info->max_num_partial_fpdus = (u16)p_hwfn->p_rdma_info->num_qps;
 
        iwarp_info->mpa_intermediate_buf = kzalloc(buff_size, GFP_KERNEL);
-       if (!iwarp_info->mpa_intermediate_buf)
+       if (!iwarp_info->mpa_intermediate_buf) {
+               rc = -ENOMEM;
                goto err;
+       }
 
        /* The mpa_bufs array serves for pending RX packets received on the
         * mpa ll2 that don't have place on the tx ring and require later
@@ -2771,8 +2775,10 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn,
        iwarp_info->mpa_bufs = kcalloc(data.input.rx_num_desc,
                                       sizeof(*iwarp_info->mpa_bufs),
                                       GFP_KERNEL);
-       if (!iwarp_info->mpa_bufs)
+       if (!iwarp_info->mpa_bufs) {
+               rc = -ENOMEM;
                goto err;
+       }
 
        INIT_LIST_HEAD(&iwarp_info->mpa_buf_pending_list);
        INIT_LIST_HEAD(&iwarp_info->mpa_buf_list);
index b8af59fc1aa47f560df1ff4e99c7892d3cd5bf5c..d2c190732d3ef3f7f283fe4730973e2ce2c096e5 100644 (file)
@@ -2231,7 +2231,8 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter)
 
        /* Boot either flash image or firmware image from host file system */
        if (qlcnic_load_fw_file == 1) {
-               if (qlcnic_83xx_load_fw_image_from_host(adapter))
+               err = qlcnic_83xx_load_fw_image_from_host(adapter);
+               if (err)
                        return err;
        } else {
                QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID,
index 29a7bfa2584dc95b05fbcc7de61a5c912739b435..3d7d3ab383f85a52ad973990a8b63f02496875d7 100644 (file)
@@ -188,6 +188,11 @@ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb)
 
        dev = skb->dev;
        port = rmnet_get_port_rcu(dev);
+       if (unlikely(!port)) {
+               atomic_long_inc(&skb->dev->rx_nohandler);
+               kfree_skb(skb);
+               goto done;
+       }
 
        switch (port->rmnet_mode) {
        case RMNET_EPMODE_VND:
index 3b6ddc706e92eae265b15a45672367891b8edff9..85d9c3e30c6994ed5d7d020f9a7dfe7766e1fda4 100644 (file)
@@ -4080,9 +4080,17 @@ err_out:
        return -EIO;
 }
 
-static bool rtl_test_hw_pad_bug(struct rtl8169_private *tp, struct sk_buff *skb)
+static bool rtl_test_hw_pad_bug(struct rtl8169_private *tp)
 {
-       return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34;
+       switch (tp->mac_version) {
+       case RTL_GIGA_MAC_VER_34:
+       case RTL_GIGA_MAC_VER_60:
+       case RTL_GIGA_MAC_VER_61:
+       case RTL_GIGA_MAC_VER_63:
+               return true;
+       default:
+               return false;
+       }
 }
 
 static void rtl8169_tso_csum_v1(struct sk_buff *skb, u32 *opts)
@@ -4154,8 +4162,9 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
 
                opts[1] |= transport_offset << TCPHO_SHIFT;
        } else {
-               if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
-                       return !eth_skb_pad(skb);
+               if (unlikely(skb->len < ETH_ZLEN && rtl_test_hw_pad_bug(tp)))
+                       /* eth_skb_pad would free the skb on error */
+                       return !__skb_put_padto(skb, ETH_ZLEN, false);
        }
 
        return true;
@@ -4334,18 +4343,9 @@ static netdev_features_t rtl8169_features_check(struct sk_buff *skb,
                    rtl_chip_supports_csum_v2(tp))
                        features &= ~NETIF_F_ALL_TSO;
        } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-               if (skb->len < ETH_ZLEN) {
-                       switch (tp->mac_version) {
-                       case RTL_GIGA_MAC_VER_11:
-                       case RTL_GIGA_MAC_VER_12:
-                       case RTL_GIGA_MAC_VER_17:
-                       case RTL_GIGA_MAC_VER_34:
-                               features &= ~NETIF_F_CSUM_MASK;
-                               break;
-                       default:
-                               break;
-                       }
-               }
+               /* work around hw bug on some chip versions */
+               if (skb->len < ETH_ZLEN)
+                       features &= ~NETIF_F_CSUM_MASK;
 
                if (transport_offset > TCPHO_MAX &&
                    rtl_chip_supports_csum_v2(tp))
@@ -4573,7 +4573,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
        }
 
        rtl_irq_disable(tp);
-       napi_schedule_irqoff(&tp->napi);
+       napi_schedule(&tp->napi);
 out:
        rtl_ack_events(tp, status);
 
@@ -4746,7 +4746,7 @@ static int rtl_open(struct net_device *dev)
        rtl_request_firmware(tp);
 
        retval = request_irq(pci_irq_vector(pdev, 0), rtl8169_interrupt,
-                            IRQF_NO_THREAD | IRQF_SHARED, dev->name, tp);
+                            IRQF_SHARED, dev->name, tp);
        if (retval < 0)
                goto err_release_fw_2;
 
index 9c4df4ede0111eae7e6b46518686c786097ce7b2..bd30505fbc57a6e31ddb431694cda784246acf9e 100644 (file)
@@ -1744,12 +1744,16 @@ static int ravb_hwtstamp_get(struct net_device *ndev, struct ifreq *req)
        config.flags = 0;
        config.tx_type = priv->tstamp_tx_ctrl ? HWTSTAMP_TX_ON :
                                                HWTSTAMP_TX_OFF;
-       if (priv->tstamp_rx_ctrl & RAVB_RXTSTAMP_TYPE_V2_L2_EVENT)
+       switch (priv->tstamp_rx_ctrl & RAVB_RXTSTAMP_TYPE) {
+       case RAVB_RXTSTAMP_TYPE_V2_L2_EVENT:
                config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
-       else if (priv->tstamp_rx_ctrl & RAVB_RXTSTAMP_TYPE_ALL)
+               break;
+       case RAVB_RXTSTAMP_TYPE_ALL:
                config.rx_filter = HWTSTAMP_FILTER_ALL;
-       else
+               break;
+       default:
                config.rx_filter = HWTSTAMP_FILTER_NONE;
+       }
 
        return copy_to_user(req->ifr_data, &config, sizeof(config)) ?
                -EFAULT : 0;
index f61cb997a8f65f37b0d9bfc387ff39e58176324b..82b1c7a5a7a948eef7615fcf426c11321971b8c7 100644 (file)
@@ -113,8 +113,10 @@ static int intel_eth_plat_probe(struct platform_device *pdev)
                /* Enable TX clock */
                if (dwmac->data->tx_clk_en) {
                        dwmac->tx_clk = devm_clk_get(&pdev->dev, "tx_clk");
-                       if (IS_ERR(dwmac->tx_clk))
+                       if (IS_ERR(dwmac->tx_clk)) {
+                               ret = PTR_ERR(dwmac->tx_clk);
                                goto err_remove_config_dt;
+                       }
 
                        clk_prepare_enable(dwmac->tx_clk);
 
index b6e5e3e36b63a182701189a6120923f28f39aad6..81ee0a071b4e96156c93b516c354d26a540e2cf6 100644 (file)
@@ -625,13 +625,6 @@ static int intel_eth_pci_probe(struct pci_dev *pdev,
        if (ret)
                return ret;
 
-       if (plat->eee_usecs_rate > 0) {
-               u32 tx_lpi_usec;
-
-               tx_lpi_usec = (plat->eee_usecs_rate / 1000000) - 1;
-               writel(tx_lpi_usec, res.addr + GMAC_1US_TIC_COUNTER);
-       }
-
        ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
        if (ret < 0)
                return ret;
@@ -641,6 +634,13 @@ static int intel_eth_pci_probe(struct pci_dev *pdev,
        res.wol_irq = pci_irq_vector(pdev, 0);
        res.irq = pci_irq_vector(pdev, 0);
 
+       if (plat->eee_usecs_rate > 0) {
+               u32 tx_lpi_usec;
+
+               tx_lpi_usec = (plat->eee_usecs_rate / 1000000) - 1;
+               writel(tx_lpi_usec, res.addr + GMAC_1US_TIC_COUNTER);
+       }
+
        ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
        if (ret) {
                pci_free_irq_vectors(pdev);
index 002791b7735687af3acc544b666db4f246710e84..ced6d76a0d8532e21d59646cfc98b252f023d7d5 100644 (file)
@@ -1171,7 +1171,6 @@ const struct stmmac_ops dwmac4_ops = {
        .pcs_get_adv_lp = dwmac4_get_adv_lp,
        .debug = dwmac4_debug,
        .set_filter = dwmac4_set_filter,
-       .flex_pps_config = dwmac5_flex_pps_config,
        .set_mac_loopback = dwmac4_set_mac_loopback,
        .update_vlan_hash = dwmac4_update_vlan_hash,
        .sarc_configure = dwmac4_sarc_configure,
@@ -1213,6 +1212,7 @@ const struct stmmac_ops dwmac410_ops = {
        .pcs_get_adv_lp = dwmac4_get_adv_lp,
        .debug = dwmac4_debug,
        .set_filter = dwmac4_set_filter,
+       .flex_pps_config = dwmac5_flex_pps_config,
        .set_mac_loopback = dwmac4_set_mac_loopback,
        .update_vlan_hash = dwmac4_update_vlan_hash,
        .sarc_configure = dwmac4_sarc_configure,
index cb87d31a99dfb6d990f752fa74f0100116f989b2..57a53a600aa556672c82b12d40f4a35bc572187d 100644 (file)
@@ -23,7 +23,7 @@ int dwmac_dma_reset(void __iomem *ioaddr)
 
        return readl_poll_timeout(ioaddr + DMA_BUS_MODE, value,
                                 !(value & DMA_BUS_MODE_SFT_RESET),
-                                10000, 100000);
+                                10000, 200000);
 }
 
 /* CSR1 enables the transmit DMA to check for new descriptor */
index 220626a8d499eb22376051d82fd752e02987c480..ba45fe237512cb40a3542c5ea304e43343e8cc4a 100644 (file)
@@ -4757,6 +4757,7 @@ static void stmmac_napi_add(struct net_device *dev)
 
                ch->priv_data = priv;
                ch->index = queue;
+               spin_lock_init(&ch->lock);
 
                if (queue < priv->plat->rx_queues_to_use) {
                        netif_napi_add(dev, &ch->rx_napi, stmmac_napi_poll_rx,
@@ -5246,6 +5247,7 @@ int stmmac_resume(struct device *dev)
                        return ret;
        }
 
+       rtnl_lock();
        mutex_lock(&priv->lock);
 
        stmmac_reset_queues_param(priv);
@@ -5261,6 +5263,7 @@ int stmmac_resume(struct device *dev)
        stmmac_enable_all_queues(priv);
 
        mutex_unlock(&priv->lock);
+       rtnl_unlock();
 
        if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
                rtnl_lock();
index 75056c14b161bafacec436ee67a1b2ec86062489..5dc60ecabe5617e7a8bcae1064b7e2d0ab8599ef 100644 (file)
@@ -1001,8 +1001,7 @@ struct am65_cpts *am65_cpts_create(struct device *dev, void __iomem *regs,
        if (IS_ERR_OR_NULL(cpts->ptp_clock)) {
                dev_err(dev, "Failed to register ptp clk %ld\n",
                        PTR_ERR(cpts->ptp_clock));
-               if (!cpts->ptp_clock)
-                       ret = -ENODEV;
+               ret = cpts->ptp_clock ? PTR_ERR(cpts->ptp_clock) : -ENODEV;
                goto refclk_disable;
        }
        cpts->phc_index = ptp_clock_index(cpts->ptp_clock);
index 9fd1f77190ad0d2e19128dfe826d14e207c08619..b0f00b4edd9491b1d0cb37df8a7c6be6818b32ef 100644 (file)
@@ -838,9 +838,12 @@ static int cpsw_ndo_open(struct net_device *ndev)
                if (ret < 0)
                        goto err_cleanup;
 
-               if (cpts_register(cpsw->cpts))
-                       dev_err(priv->dev, "error registering cpts device\n");
-
+               if (cpsw->cpts) {
+                       if (cpts_register(cpsw->cpts))
+                               dev_err(priv->dev, "error registering cpts device\n");
+                       else
+                               writel(0x10, &cpsw->wr_regs->misc_en);
+               }
        }
 
        cpsw_restore(priv);
@@ -1631,6 +1634,7 @@ static int cpsw_probe(struct platform_device *pdev)
                                       CPSW_MAX_QUEUES, CPSW_MAX_QUEUES);
        if (!ndev) {
                dev_err(dev, "error allocating net_device\n");
+               ret = -ENOMEM;
                goto clean_cpts;
        }
 
@@ -1716,7 +1720,6 @@ static int cpsw_probe(struct platform_device *pdev)
 
        /* Enable misc CPTS evnt_pend IRQ */
        cpts_set_irqpoll(cpsw->cpts, false);
-       writel(0x10, &cpsw->wr_regs->misc_en);
 
 skip_cpts:
        cpsw_notice(priv, probe,
index 4d02c51356112f291ba22953b370b297960db08c..4619c3a950b01ef19f24e9283e80f5dc3d72b2d4 100644 (file)
@@ -728,7 +728,6 @@ int cpsw_get_ts_info(struct net_device *ndev, struct ethtool_ts_info *info)
                (1 << HWTSTAMP_TX_ON);
        info->rx_filters =
                (1 << HWTSTAMP_FILTER_NONE) |
-               (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
                (1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
        return 0;
 }
index f779d2e1b5c53967989abd14f1df8cbe12943232..2f5e0ad23ad7cf13a090471f553c656063ca285a 100644 (file)
@@ -873,8 +873,12 @@ static int cpsw_ndo_open(struct net_device *ndev)
                if (ret < 0)
                        goto err_cleanup;
 
-               if (cpts_register(cpsw->cpts))
-                       dev_err(priv->dev, "error registering cpts device\n");
+               if (cpsw->cpts) {
+                       if (cpts_register(cpsw->cpts))
+                               dev_err(priv->dev, "error registering cpts device\n");
+                       else
+                               writel(0x10, &cpsw->wr_regs->misc_en);
+               }
 
                napi_enable(&cpsw->napi_rx);
                napi_enable(&cpsw->napi_tx);
@@ -2006,7 +2010,6 @@ static int cpsw_probe(struct platform_device *pdev)
 
        /* Enable misc CPTS evnt_pend IRQ */
        cpts_set_irqpoll(cpsw->cpts, false);
-       writel(0x10, &cpsw->wr_regs->misc_en);
 
 skip_cpts:
        ret = cpsw_register_notifiers(cpsw);
index 51cc29f39038b30321e24103d20e0628beb18c35..31c5e36ff7069f545f0ce9a4e05a72a3db64e428 100644 (file)
@@ -639,13 +639,10 @@ static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
                break;
        case HWTSTAMP_FILTER_ALL:
        case HWTSTAMP_FILTER_NTP_ALL:
-               return -ERANGE;
        case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
        case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
        case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
-               priv->rx_ts_enabled = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
-               cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
-               break;
+               return -ERANGE;
        case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
        case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
        case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
index d07008a818df67eae1bdd4f2159658fa0333e264..8ae9ce2014a4a3ba7b962a209e28d1f65d4a83bd 100644 (file)
@@ -224,8 +224,7 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
        if (ip_tunnel_collect_metadata() || gs->collect_md) {
                __be16 flags;
 
-               flags = TUNNEL_KEY | TUNNEL_GENEVE_OPT |
-                       (gnvh->oam ? TUNNEL_OAM : 0) |
+               flags = TUNNEL_KEY | (gnvh->oam ? TUNNEL_OAM : 0) |
                        (gnvh->critical ? TUNNEL_CRIT_OPT : 0);
 
                tun_dst = udp_tun_rx_dst(skb, geneve_get_sk_family(gs), flags,
@@ -258,11 +257,21 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
                skb_dst_set(skb, &tun_dst->dst);
 
        /* Ignore packet loops (and multicast echo) */
-       if (ether_addr_equal(eth_hdr(skb)->h_source, geneve->dev->dev_addr)) {
-               geneve->dev->stats.rx_errors++;
-               goto drop;
-       }
+       if (ether_addr_equal(eth_hdr(skb)->h_source, geneve->dev->dev_addr))
+               goto rx_error;
 
+       switch (skb_protocol(skb, true)) {
+       case htons(ETH_P_IP):
+               if (pskb_may_pull(skb, sizeof(struct iphdr)))
+                       goto rx_error;
+               break;
+       case htons(ETH_P_IPV6):
+               if (pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+                       goto rx_error;
+               break;
+       default:
+               goto rx_error;
+       }
        oiph = skb_network_header(skb);
        skb_reset_network_header(skb);
 
@@ -299,6 +308,8 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
                dev_sw_netstats_rx_add(geneve->dev, len);
 
        return;
+rx_error:
+       geneve->dev->stats.rx_errors++;
 drop:
        /* Consume bad packet */
        kfree_skb(skb);
index 030a1a5afe05ad5b69abf31a15202df38506e72f..dc668ed280b9f46619e3b0abe282146dde599b65 100644 (file)
@@ -657,10 +657,6 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
 
        gtp = netdev_priv(dev);
 
-       err = gtp_encap_enable(gtp, data);
-       if (err < 0)
-               return err;
-
        if (!data[IFLA_GTP_PDP_HASHSIZE]) {
                hashsize = 1024;
        } else {
@@ -671,12 +667,16 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
 
        err = gtp_hashtable_new(gtp, hashsize);
        if (err < 0)
-               goto out_encap;
+               return err;
+
+       err = gtp_encap_enable(gtp, data);
+       if (err < 0)
+               goto out_hashtable;
 
        err = register_netdevice(dev);
        if (err < 0) {
                netdev_dbg(dev, "failed to register new netdev %d\n", err);
-               goto out_hashtable;
+               goto out_encap;
        }
 
        gn = net_generic(dev_net(dev), gtp_net_id);
@@ -687,11 +687,11 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
 
        return 0;
 
+out_encap:
+       gtp_encap_disable(gtp);
 out_hashtable:
        kfree(gtp->addr_hash);
        kfree(gtp->tid_hash);
-out_encap:
-       gtp_encap_disable(gtp);
        return err;
 }
 
index 43f5f5d93cb06220645435a553687567c980ff11..e8599bb948c08c34e49a4a2c9bd7118fe4af2d56 100644 (file)
@@ -362,22 +362,31 @@ struct gsi_trans *gsi_channel_trans_alloc(struct gsi *gsi, u32 channel_id,
        return trans;
 }
 
-/* Free a previously-allocated transaction (used only in case of error) */
+/* Free a previously-allocated transaction */
 void gsi_trans_free(struct gsi_trans *trans)
 {
+       refcount_t *refcount = &trans->refcount;
        struct gsi_trans_info *trans_info;
+       bool last;
 
-       if (!refcount_dec_and_test(&trans->refcount))
+       /* We must hold the lock to release the last reference */
+       if (refcount_dec_not_one(refcount))
                return;
 
        trans_info = &trans->gsi->channel[trans->channel_id].trans_info;
 
        spin_lock_bh(&trans_info->spinlock);
 
-       list_del(&trans->links);
+       /* Reference might have been added before we got the lock */
+       last = refcount_dec_and_test(refcount);
+       if (last)
+               list_del(&trans->links);
 
        spin_unlock_bh(&trans_info->spinlock);
 
+       if (!last)
+               return;
+
        ipa_gsi_trans_release(trans);
 
        /* Releasing the reserved TREs implicitly frees the sgl[] and
@@ -397,15 +406,24 @@ void gsi_trans_cmd_add(struct gsi_trans *trans, void *buf, u32 size,
 
        /* assert(which < trans->tre_count); */
 
-       /* Set the page information for the buffer.  We also need to fill in
-        * the DMA address and length for the buffer (something dma_map_sg()
-        * normally does).
+       /* Commands are quite different from data transfer requests.
+        * Their payloads come from a pool whose memory is allocated
+        * using dma_alloc_coherent().  We therefore do *not* map them
+        * for DMA (unlike what we do for pages and skbs).
+        *
+        * When a transaction completes, the SGL is normally unmapped.
+        * A command transaction has direction DMA_NONE, which tells
+        * gsi_trans_complete() to skip the unmapping step.
+        *
+        * The only things we use directly in a command scatter/gather
+        * entry are the DMA address and length.  We still need the SG
+        * table flags to be maintained though, so assign a NULL page
+        * pointer for that purpose.
         */
        sg = &trans->sgl[which];
-
-       sg_set_buf(sg, buf, size);
+       sg_assign_page(sg, NULL);
        sg_dma_address(sg) = addr;
-       sg_dma_len(sg) = sg->length;
+       sg_dma_len(sg) = size;
 
        info = &trans->info[which];
        info->opcode = opcode;
index d070614176755870127e37df1dee5daecd213562..e7972e88ffe0bdbc5a20593ad6f8c51d28623943 100644 (file)
@@ -96,6 +96,7 @@ static const struct file_operations nsim_dev_take_snapshot_fops = {
        .open = simple_open,
        .write = nsim_dev_take_snapshot_write,
        .llseek = generic_file_llseek,
+       .owner = THIS_MODULE,
 };
 
 static ssize_t nsim_dev_trap_fa_cookie_read(struct file *file,
@@ -188,6 +189,7 @@ static const struct file_operations nsim_dev_trap_fa_cookie_fops = {
        .read = nsim_dev_trap_fa_cookie_read,
        .write = nsim_dev_trap_fa_cookie_write,
        .llseek = generic_file_llseek,
+       .owner = THIS_MODULE,
 };
 
 static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev)
index 62958b238d5071a409e5717f31f0a4bf328a6592..21e2974660e7beac1b9b246c6c58975c2836fd73 100644 (file)
@@ -261,6 +261,7 @@ static const struct file_operations nsim_dev_health_break_fops = {
        .open = simple_open,
        .write = nsim_dev_health_break_write,
        .llseek = generic_file_llseek,
+       .owner = THIS_MODULE,
 };
 
 int nsim_dev_health_init(struct nsim_dev *nsim_dev, struct devlink *devlink)
index 6ab023acefd6192335af473384f4df413d8f406a..02dc3123eb6c16613c1ce2ae2a24708d64cc2465 100644 (file)
@@ -124,6 +124,7 @@ static const struct file_operations nsim_udp_tunnels_info_reset_fops = {
        .open = simple_open,
        .write = nsim_udp_tunnels_info_reset_write,
        .llseek = generic_file_llseek,
+       .owner = THIS_MODULE,
 };
 
 int nsim_udp_tunnels_info_create(struct nsim_dev *nsim_dev,
index 6cf9b798b710edd13631b526329004464da1a072..10be266e48e8b74f73a124111b132a086e055c05 100644 (file)
@@ -981,7 +981,6 @@ int vsc8584_macsec_init(struct phy_device *phydev)
 
        switch (phydev->phy_id & phydev->drv->phy_id_mask) {
        case PHY_ID_VSC856X:
-       case PHY_ID_VSC8575:
        case PHY_ID_VSC8582:
        case PHY_ID_VSC8584:
                INIT_LIST_HEAD(&vsc8531->macsec_flows);
index fb1db713b7fb73528155c44dcba229ab7c69f487..575580d3ffe04110eeb730ddac73c06ef57494fe 100644 (file)
@@ -551,6 +551,8 @@ static struct phy_driver realtek_drvs[] = {
        {
                PHY_ID_MATCH_EXACT(0x00008201),
                .name           = "RTL8201CP Ethernet",
+               .read_page      = rtl821x_read_page,
+               .write_page     = rtl821x_write_page,
        }, {
                PHY_ID_MATCH_EXACT(0x001cc816),
                .name           = "RTL8201F Fast Ethernet",
index 1d18c10e8f82fcc0867d8114173f77e26a48f50c..34aa196b7465c6460d6268b6bce3864f4d45fee4 100644 (file)
@@ -2389,7 +2389,8 @@ static int sfp_probe(struct platform_device *pdev)
                        continue;
 
                sfp->gpio_irq[i] = gpiod_to_irq(sfp->gpio[i]);
-               if (!sfp->gpio_irq[i]) {
+               if (sfp->gpio_irq[i] < 0) {
+                       sfp->gpio_irq[i] = 0;
                        sfp->need_poll = true;
                        continue;
                }
index ec97669be5c2aff2bc6491e70802a9948990699c..0fc39ac5ca88b9a76a029ca5b3e96de638f73b86 100644 (file)
@@ -291,8 +291,10 @@ static int smsc_phy_probe(struct phy_device *phydev)
                return ret;
 
        ret = clk_set_rate(priv->refclk, 50 * 1000 * 1000);
-       if (ret)
+       if (ret) {
+               clk_disable_unprepare(priv->refclk);
                return ret;
+       }
 
        return 0;
 }
index be69d272052f076d9839cbe929d6ca4337e30d2f..cd06cae760356fc200f1c46a6f9c0c42f52e6dca 100644 (file)
@@ -1961,12 +1961,15 @@ static ssize_t tun_chr_write_iter(struct kiocb *iocb, struct iov_iter *from)
        struct tun_file *tfile = file->private_data;
        struct tun_struct *tun = tun_get(tfile);
        ssize_t result;
+       int noblock = 0;
 
        if (!tun)
                return -EBADFD;
 
-       result = tun_get_user(tun, tfile, NULL, from,
-                             file->f_flags & O_NONBLOCK, false);
+       if ((file->f_flags & O_NONBLOCK) || (iocb->ki_flags & IOCB_NOWAIT))
+               noblock = 1;
+
+       result = tun_get_user(tun, tfile, NULL, from, noblock, false);
 
        tun_put(tun);
        return result;
@@ -2185,10 +2188,15 @@ static ssize_t tun_chr_read_iter(struct kiocb *iocb, struct iov_iter *to)
        struct tun_file *tfile = file->private_data;
        struct tun_struct *tun = tun_get(tfile);
        ssize_t len = iov_iter_count(to), ret;
+       int noblock = 0;
 
        if (!tun)
                return -EBADFD;
-       ret = tun_do_read(tun, tfile, to, file->f_flags & O_NONBLOCK, NULL);
+
+       if ((file->f_flags & O_NONBLOCK) || (iocb->ki_flags & IOCB_NOWAIT))
+               noblock = 1;
+
+       ret = tun_do_read(tun, tfile, to, noblock, NULL);
        ret = min_t(ssize_t, ret, len);
        if (ret > 0)
                iocb->ki_pos = ret;
index ca89d8258dd3f521b51f3ec3edbda697ef884cbf..c4568a491dc4debc62e4207d78f87f6c22606d6c 100644 (file)
@@ -197,7 +197,8 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
        }
 
        /* enable ethernet mode (?) */
-       if (cx82310_enable_ethernet(dev))
+       ret = cx82310_enable_ethernet(dev);
+       if (ret)
                goto err;
 
        /* get the MAC address */
index b09b45382faf5df83534ec5f857a4b7a4f97fdbd..207e59e74935aaf4b23add136b611d3138a6349b 100644 (file)
@@ -59,7 +59,7 @@
 #define IPHETH_USBINTF_SUBCLASS 253
 #define IPHETH_USBINTF_PROTO    1
 
-#define IPHETH_BUF_SIZE         1516
+#define IPHETH_BUF_SIZE         1514
 #define IPHETH_IP_ALIGN                2       /* padding at front of URB */
 #define IPHETH_TX_TIMEOUT       (5 * HZ)
 
index a322f51873d011dfd0272fcdc6e2253b38bf6c66..fc378ff56775bc4ae6c64c4c05a59e347783bed1 100644 (file)
@@ -1070,7 +1070,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x05c6, 0x9011, 4)},
        {QMI_FIXED_INTF(0x05c6, 0x9021, 1)},
        {QMI_FIXED_INTF(0x05c6, 0x9022, 2)},
-       {QMI_FIXED_INTF(0x05c6, 0x9025, 4)},    /* Alcatel-sbell ASB TL131 TDD LTE  (China Mobile) */
+       {QMI_QUIRK_SET_DTR(0x05c6, 0x9025, 4)}, /* Alcatel-sbell ASB TL131 TDD LTE (China Mobile) */
        {QMI_FIXED_INTF(0x05c6, 0x9026, 3)},
        {QMI_FIXED_INTF(0x05c6, 0x902e, 5)},
        {QMI_FIXED_INTF(0x05c6, 0x9031, 5)},
@@ -1309,6 +1309,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x1bc7, 0x1101, 3)},    /* Telit ME910 dual modem */
        {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},    /* Telit LE920 */
        {QMI_QUIRK_SET_DTR(0x1bc7, 0x1201, 2)}, /* Telit LE920, LE920A4 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x1230, 2)}, /* Telit LE910Cx */
        {QMI_QUIRK_SET_DTR(0x1bc7, 0x1260, 2)}, /* Telit LE910Cx */
        {QMI_QUIRK_SET_DTR(0x1bc7, 0x1261, 2)}, /* Telit LE910Cx */
        {QMI_QUIRK_SET_DTR(0x1bc7, 0x1900, 1)}, /* Telit LN940 series */
index 60c1aadece89a77963f832e6085e1a630140de03..f2793ffde19134a3705453bdc2c3eeed3a75237f 100644 (file)
@@ -608,8 +608,7 @@ static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev)
        return ret;
 }
 
-static int vrf_finish_direct(struct net *net, struct sock *sk,
-                            struct sk_buff *skb)
+static void vrf_finish_direct(struct sk_buff *skb)
 {
        struct net_device *vrf_dev = skb->dev;
 
@@ -628,7 +627,8 @@ static int vrf_finish_direct(struct net *net, struct sock *sk,
                skb_pull(skb, ETH_HLEN);
        }
 
-       return 1;
+       /* reset skb device */
+       nf_reset_ct(skb);
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
@@ -707,15 +707,41 @@ static struct sk_buff *vrf_ip6_out_redirect(struct net_device *vrf_dev,
        return skb;
 }
 
+static int vrf_output6_direct_finish(struct net *net, struct sock *sk,
+                                    struct sk_buff *skb)
+{
+       vrf_finish_direct(skb);
+
+       return vrf_ip6_local_out(net, sk, skb);
+}
+
 static int vrf_output6_direct(struct net *net, struct sock *sk,
                              struct sk_buff *skb)
 {
+       int err = 1;
+
        skb->protocol = htons(ETH_P_IPV6);
 
-       return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING,
-                           net, sk, skb, NULL, skb->dev,
-                           vrf_finish_direct,
-                           !(IPCB(skb)->flags & IPSKB_REROUTED));
+       if (!(IPCB(skb)->flags & IPSKB_REROUTED))
+               err = nf_hook(NFPROTO_IPV6, NF_INET_POST_ROUTING, net, sk, skb,
+                             NULL, skb->dev, vrf_output6_direct_finish);
+
+       if (likely(err == 1))
+               vrf_finish_direct(skb);
+
+       return err;
+}
+
+static int vrf_ip6_out_direct_finish(struct net *net, struct sock *sk,
+                                    struct sk_buff *skb)
+{
+       int err;
+
+       err = vrf_output6_direct(net, sk, skb);
+       if (likely(err == 1))
+               err = vrf_ip6_local_out(net, sk, skb);
+
+       return err;
 }
 
 static struct sk_buff *vrf_ip6_out_direct(struct net_device *vrf_dev,
@@ -728,18 +754,15 @@ static struct sk_buff *vrf_ip6_out_direct(struct net_device *vrf_dev,
        skb->dev = vrf_dev;
 
        err = nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk,
-                     skb, NULL, vrf_dev, vrf_output6_direct);
+                     skb, NULL, vrf_dev, vrf_ip6_out_direct_finish);
 
        if (likely(err == 1))
                err = vrf_output6_direct(net, sk, skb);
 
-       /* reset skb device */
        if (likely(err == 1))
-               nf_reset_ct(skb);
-       else
-               skb = NULL;
+               return skb;
 
-       return skb;
+       return NULL;
 }
 
 static struct sk_buff *vrf_ip6_out(struct net_device *vrf_dev,
@@ -919,15 +942,41 @@ static struct sk_buff *vrf_ip_out_redirect(struct net_device *vrf_dev,
        return skb;
 }
 
+static int vrf_output_direct_finish(struct net *net, struct sock *sk,
+                                   struct sk_buff *skb)
+{
+       vrf_finish_direct(skb);
+
+       return vrf_ip_local_out(net, sk, skb);
+}
+
 static int vrf_output_direct(struct net *net, struct sock *sk,
                             struct sk_buff *skb)
 {
+       int err = 1;
+
        skb->protocol = htons(ETH_P_IP);
 
-       return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING,
-                           net, sk, skb, NULL, skb->dev,
-                           vrf_finish_direct,
-                           !(IPCB(skb)->flags & IPSKB_REROUTED));
+       if (!(IPCB(skb)->flags & IPSKB_REROUTED))
+               err = nf_hook(NFPROTO_IPV4, NF_INET_POST_ROUTING, net, sk, skb,
+                             NULL, skb->dev, vrf_output_direct_finish);
+
+       if (likely(err == 1))
+               vrf_finish_direct(skb);
+
+       return err;
+}
+
+static int vrf_ip_out_direct_finish(struct net *net, struct sock *sk,
+                                   struct sk_buff *skb)
+{
+       int err;
+
+       err = vrf_output_direct(net, sk, skb);
+       if (likely(err == 1))
+               err = vrf_ip_local_out(net, sk, skb);
+
+       return err;
 }
 
 static struct sk_buff *vrf_ip_out_direct(struct net_device *vrf_dev,
@@ -940,18 +989,15 @@ static struct sk_buff *vrf_ip_out_direct(struct net_device *vrf_dev,
        skb->dev = vrf_dev;
 
        err = nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, sk,
-                     skb, NULL, vrf_dev, vrf_output_direct);
+                     skb, NULL, vrf_dev, vrf_ip_out_direct_finish);
 
        if (likely(err == 1))
                err = vrf_output_direct(net, sk, skb);
 
-       /* reset skb device */
        if (likely(err == 1))
-               nf_reset_ct(skb);
-       else
-               skb = NULL;
+               return skb;
 
-       return skb;
+       return NULL;
 }
 
 static struct sk_buff *vrf_ip_out(struct net_device *vrf_dev,
index 1a557aeba32b4ee80c8a70c4e1af67235c51af70..977f77e2c2ce61fe56340002212017ddd20fbcd6 100644 (file)
@@ -3798,6 +3798,9 @@ static void vxlan_config_apply(struct net_device *dev,
                dev->gso_max_segs = lowerdev->gso_max_segs;
 
                needed_headroom = lowerdev->hard_header_len;
+               needed_headroom += lowerdev->needed_headroom;
+
+               dev->needed_tailroom = lowerdev->needed_tailroom;
 
                max_mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM :
                                           VXLAN_HEADROOM);
@@ -3877,8 +3880,10 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
 
        if (dst->remote_ifindex) {
                remote_dev = __dev_get_by_index(net, dst->remote_ifindex);
-               if (!remote_dev)
+               if (!remote_dev) {
+                       err = -ENODEV;
                        goto errout;
+               }
 
                err = netdev_upper_dev_link(remote_dev, dev, extack);
                if (err)
index f8aed0696d7752a60c94b928c05e900476642cdb..2369ca250cd65e0f09e1d1f87f28e5d31dbe283b 100644 (file)
@@ -889,6 +889,7 @@ static ssize_t cosa_write(struct file *file,
                        chan->tx_status = 1;
                        spin_unlock_irqrestore(&cosa->lock, flags);
                        up(&chan->wsem);
+                       kfree(kbuf);
                        return -ERESTARTSYS;
                }
        }
index d43e0d3f3a12230ee9725f15269297c59c06e596..052413eef0593dfb1144338ac4699731ccf55bd8 100644 (file)
@@ -5,10 +5,9 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2012-2014, 2018 - 2020 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2012-2014, 2018 - 2020 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -128,7 +126,9 @@ enum iwl_sta_flags {
        STA_FLG_MAX_AGG_SIZE_256K       = (5 << STA_FLG_MAX_AGG_SIZE_SHIFT),
        STA_FLG_MAX_AGG_SIZE_512K       = (6 << STA_FLG_MAX_AGG_SIZE_SHIFT),
        STA_FLG_MAX_AGG_SIZE_1024K      = (7 << STA_FLG_MAX_AGG_SIZE_SHIFT),
-       STA_FLG_MAX_AGG_SIZE_MSK        = (7 << STA_FLG_MAX_AGG_SIZE_SHIFT),
+       STA_FLG_MAX_AGG_SIZE_2M         = (8 << STA_FLG_MAX_AGG_SIZE_SHIFT),
+       STA_FLG_MAX_AGG_SIZE_4M         = (9 << STA_FLG_MAX_AGG_SIZE_SHIFT),
+       STA_FLG_MAX_AGG_SIZE_MSK        = (0xf << STA_FLG_MAX_AGG_SIZE_SHIFT),
 
        STA_FLG_AGG_MPDU_DENS_SHIFT     = 23,
        STA_FLG_AGG_MPDU_DENS_2US       = (4 << STA_FLG_AGG_MPDU_DENS_SHIFT),
index a731f28e101a64f646958c2e12cf866937903451..53b438d709dbe66a436df23683ea4af91907c565 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -421,12 +421,14 @@ struct iwl_hs20_roc_res {
  *     able to run the GO Negotiation. Will not be fragmented and not
  *     repetitive. Valid only on the P2P Device MAC. Only the duration will
  *     be taken into account.
+ * @SESSION_PROTECT_CONF_MAX_ID: not used
  */
 enum iwl_mvm_session_prot_conf_id {
        SESSION_PROTECT_CONF_ASSOC,
        SESSION_PROTECT_CONF_GO_CLIENT_ASSOC,
        SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV,
        SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION,
+       SESSION_PROTECT_CONF_MAX_ID,
 }; /* SESSION_PROTECTION_CONF_ID_E_VER_1 */
 
 /**
@@ -459,7 +461,7 @@ struct iwl_mvm_session_prot_cmd {
  * @mac_id: the mac id for which the session protection started / ended
  * @status: 1 means success, 0 means failure
  * @start: 1 means the session protection started, 0 means it ended
- * @conf_id: the configuration id of the session that started / eneded
+ * @conf_id: see &enum iwl_mvm_session_prot_conf_id
  *
  * Note that any session protection will always get two notifications: start
  * and end even the firmware could not schedule it.
index ca4967b81d01158ffb4f7fd0dc432c0ada697254..580b07a43856d1c608eb91995c5eb4dd9faf166d 100644 (file)
@@ -491,8 +491,8 @@ struct iwl_cfg {
 #define IWL_CFG_RF_ID_HR               0x7
 #define IWL_CFG_RF_ID_HR1              0x4
 
-#define IWL_CFG_NO_160                 0x0
-#define IWL_CFG_160                    0x1
+#define IWL_CFG_NO_160                 0x1
+#define IWL_CFG_160                    0x0
 
 #define IWL_CFG_CORES_BT               0x0
 #define IWL_CFG_CORES_BT_GNSS          0x5
index cb9e8e189a1a49d84f42efce9183a34b4ad91bae..1d48c7d7fffd4e96dd43ff9acde4ee0c99982ded 100644 (file)
 #define CSR_MAC_SHADOW_REG_CTL2                (CSR_BASE + 0x0AC)
 #define CSR_MAC_SHADOW_REG_CTL2_RX_WAKE        0xFFFF
 
+/* LTR control (since IWL_DEVICE_FAMILY_22000) */
+#define CSR_LTR_LONG_VAL_AD                    (CSR_BASE + 0x0D4)
+#define CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ       0x80000000
+#define CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE     0x1c000000
+#define CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL       0x03ff0000
+#define CSR_LTR_LONG_VAL_AD_SNOOP_REQ          0x00008000
+#define CSR_LTR_LONG_VAL_AD_SNOOP_SCALE                0x00001c00
+#define CSR_LTR_LONG_VAL_AD_SNOOP_VAL          0x000003ff
+#define CSR_LTR_LONG_VAL_AD_SCALE_USEC         2
+
 /* GIO Chicken Bits (PCI Express bus link power management) */
 #define CSR_GIO_CHICKEN_BITS    (CSR_BASE+0x100)
 
index 688c1125e67b6931ef22c27b9b34901a254661c6..b627e7da7ac9d85aea9ccb3ee68fcd0fe330d755 100644 (file)
@@ -3080,7 +3080,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
 
        /* this would be a mac80211 bug ... but don't crash */
        if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
-               return -EINVAL;
+               return test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) ? 0 : -EINVAL;
 
        /*
         * If we are in a STA removal flow and in DQA mode:
@@ -3127,6 +3127,9 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
                        goto out_unlock;
                }
 
+               if (vif->type == NL80211_IFTYPE_STATION)
+                       vif->bss_conf.he_support = sta->he_cap.has_he;
+
                if (sta->tdls &&
                    (vif->p2p ||
                     iwl_mvm_tdls_sta_count(mvm, NULL) ==
index 017537944fd0353ad7d26d1f5ca4a5619ef16b4e..799d8219463cb21f1f576da47772c9cbb102783b 100644 (file)
@@ -196,6 +196,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
                mpdu_dens = sta->ht_cap.ampdu_density;
        }
 
+
        if (sta->vht_cap.vht_supported) {
                agg_size = sta->vht_cap.cap &
                        IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
@@ -205,6 +206,23 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
                agg_size = sta->ht_cap.ampdu_factor;
        }
 
+       /* D6.0 10.12.2 A-MPDU length limit rules
+        * A STA indicates the maximum length of the A-MPDU preEOF padding
+        * that it can receive in an HE PPDU in the Maximum A-MPDU Length
+        * Exponent field in its HT Capabilities, VHT Capabilities,
+        * and HE 6 GHz Band Capabilities elements (if present) and the
+        * Maximum AMPDU Length Exponent Extension field in its HE
+        * Capabilities element
+        */
+       if (sta->he_cap.has_he)
+               agg_size += u8_get_bits(sta->he_cap.he_cap_elem.mac_cap_info[3],
+                                       IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK);
+
+       /* Limit to max A-MPDU supported by FW */
+       if (agg_size > (STA_FLG_MAX_AGG_SIZE_4M >> STA_FLG_MAX_AGG_SIZE_SHIFT))
+               agg_size = (STA_FLG_MAX_AGG_SIZE_4M >>
+                           STA_FLG_MAX_AGG_SIZE_SHIFT);
+
        add_sta_cmd.station_flags |=
                cpu_to_le32(agg_size << STA_FLG_MAX_AGG_SIZE_SHIFT);
        add_sta_cmd.station_flags |=
index 7fce79c1c11414bf7b30afe6896ba3fd5eec6162..1db6d8d38822a5234e626b4a22cdb119f70940f0 100644 (file)
@@ -641,11 +641,32 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
        }
 }
 
+static void iwl_mvm_cancel_session_protection(struct iwl_mvm *mvm,
+                                             struct iwl_mvm_vif *mvmvif)
+{
+       struct iwl_mvm_session_prot_cmd cmd = {
+               .id_and_color =
+                       cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
+                                                       mvmvif->color)),
+               .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
+               .conf_id = cpu_to_le32(mvmvif->time_event_data.id),
+       };
+       int ret;
+
+       ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD,
+                                                  MAC_CONF_GROUP, 0),
+                                  0, sizeof(cmd), &cmd);
+       if (ret)
+               IWL_ERR(mvm,
+                       "Couldn't send the SESSION_PROTECTION_CMD: %d\n", ret);
+}
+
 static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
                                        struct iwl_mvm_time_event_data *te_data,
                                        u32 *uid)
 {
        u32 id;
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif);
 
        /*
         * It is possible that by the time we got to this point the time
@@ -663,14 +684,29 @@ static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
        iwl_mvm_te_clear_data(mvm, te_data);
        spin_unlock_bh(&mvm->time_event_lock);
 
-       /*
-        * It is possible that by the time we try to remove it, the time event
-        * has already ended and removed. In such a case there is no need to
-        * send a removal command.
+       /* When session protection is supported, the te_data->id field
+        * is reused to save session protection's configuration.
         */
-       if (id == TE_MAX) {
-               IWL_DEBUG_TE(mvm, "TE 0x%x has already ended\n", *uid);
+       if (fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) {
+               if (mvmvif && id < SESSION_PROTECT_CONF_MAX_ID) {
+                       /* Session protection is still ongoing. Cancel it */
+                       iwl_mvm_cancel_session_protection(mvm, mvmvif);
+                       if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) {
+                               set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status);
+                               iwl_mvm_roc_finished(mvm);
+                       }
+               }
                return false;
+       } else {
+               /* It is possible that by the time we try to remove it, the
+                * time event has already ended and removed. In such a case
+                * there is no need to send a removal command.
+                */
+               if (id == TE_MAX) {
+                       IWL_DEBUG_TE(mvm, "TE 0x%x has already ended\n", *uid);
+                       return false;
+               }
        }
 
        return true;
@@ -771,6 +807,7 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_mvm_session_prot_notif *notif = (void *)pkt->data;
        struct ieee80211_vif *vif;
+       struct iwl_mvm_vif *mvmvif;
 
        rcu_read_lock();
        vif = iwl_mvm_rcu_dereference_vif_id(mvm, le32_to_cpu(notif->mac_id),
@@ -779,9 +816,10 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
        if (!vif)
                goto out_unlock;
 
+       mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
        /* The vif is not a P2P_DEVICE, maintain its time_event_data */
        if (vif->type != NL80211_IFTYPE_P2P_DEVICE) {
-               struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
                struct iwl_mvm_time_event_data *te_data =
                        &mvmvif->time_event_data;
 
@@ -816,10 +854,14 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
 
        if (!le32_to_cpu(notif->status) || !le32_to_cpu(notif->start)) {
                /* End TE, notify mac80211 */
+               mvmvif->time_event_data.id = SESSION_PROTECT_CONF_MAX_ID;
                ieee80211_remain_on_channel_expired(mvm->hw);
                set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status);
                iwl_mvm_roc_finished(mvm);
        } else if (le32_to_cpu(notif->start)) {
+               if (WARN_ON(mvmvif->time_event_data.id !=
+                               le32_to_cpu(notif->conf_id)))
+                       goto out_unlock;
                set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
                ieee80211_ready_on_channel(mvm->hw); /* Start TE */
        }
@@ -845,20 +887,24 @@ iwl_mvm_start_p2p_roc_session_protection(struct iwl_mvm *mvm,
 
        lockdep_assert_held(&mvm->mutex);
 
+       /* The time_event_data.id field is reused to save session
+        * protection's configuration.
+        */
        switch (type) {
        case IEEE80211_ROC_TYPE_NORMAL:
-               cmd.conf_id =
-                       cpu_to_le32(SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV);
+               mvmvif->time_event_data.id =
+                       SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV;
                break;
        case IEEE80211_ROC_TYPE_MGMT_TX:
-               cmd.conf_id =
-                       cpu_to_le32(SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION);
+               mvmvif->time_event_data.id =
+                       SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION;
                break;
        default:
                WARN_ONCE(1, "Got an invalid ROC type\n");
                return -EINVAL;
        }
 
+       cmd.conf_id = cpu_to_le32(mvmvif->time_event_data.id);
        return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD,
                                                    MAC_CONF_GROUP, 0),
                                    0, sizeof(cmd), &cmd);
@@ -960,25 +1006,6 @@ void iwl_mvm_cleanup_roc_te(struct iwl_mvm *mvm)
                __iwl_mvm_remove_time_event(mvm, te_data, &uid);
 }
 
-static void iwl_mvm_cancel_session_protection(struct iwl_mvm *mvm,
-                                             struct iwl_mvm_vif *mvmvif)
-{
-       struct iwl_mvm_session_prot_cmd cmd = {
-               .id_and_color =
-                       cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
-                                                       mvmvif->color)),
-               .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
-       };
-       int ret;
-
-       ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD,
-                                                  MAC_CONF_GROUP, 0),
-                                  0, sizeof(cmd), &cmd);
-       if (ret)
-               IWL_ERR(mvm,
-                       "Couldn't send the SESSION_PROTECTION_CMD: %d\n", ret);
-}
-
 void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 {
        struct iwl_mvm_vif *mvmvif;
@@ -988,10 +1015,13 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
                        IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) {
                mvmvif = iwl_mvm_vif_from_mac80211(vif);
 
-               iwl_mvm_cancel_session_protection(mvm, mvmvif);
-
-               if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
+               if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
+                       iwl_mvm_cancel_session_protection(mvm, mvmvif);
                        set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status);
+               } else {
+                       iwl_mvm_remove_aux_roc_te(mvm, mvmvif,
+                                                 &mvmvif->time_event_data);
+               }
 
                iwl_mvm_roc_finished(mvm);
 
@@ -1126,10 +1156,15 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
                        cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
                                                        mvmvif->color)),
                .action = cpu_to_le32(FW_CTXT_ACTION_ADD),
-               .conf_id = cpu_to_le32(SESSION_PROTECT_CONF_ASSOC),
                .duration_tu = cpu_to_le32(MSEC_TO_TU(duration)),
        };
 
+       /* The time_event_data.id field is reused to save session
+        * protection's configuration.
+        */
+       mvmvif->time_event_data.id = SESSION_PROTECT_CONF_ASSOC;
+       cmd.conf_id = cpu_to_le32(mvmvif->time_event_data.id);
+
        lockdep_assert_held(&mvm->mutex);
 
        spin_lock_bh(&mvm->time_event_lock);
index a0352fa873d9e6ef8d5d057dccd7c192e3378a15..5512e3c630c31901aa9ca4be58ffc1497e24562e 100644 (file)
@@ -252,6 +252,26 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
 
        iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL,
                    CSR_AUTO_FUNC_BOOT_ENA);
+
+       if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210) {
+               /*
+                * The firmware initializes this again later (to a smaller
+                * value), but for the boot process initialize the LTR to
+                * ~250 usec.
+                */
+               u32 val = CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ |
+                         u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC,
+                                         CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE) |
+                         u32_encode_bits(250,
+                                         CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL) |
+                         CSR_LTR_LONG_VAL_AD_SNOOP_REQ |
+                         u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC,
+                                         CSR_LTR_LONG_VAL_AD_SNOOP_SCALE) |
+                         u32_encode_bits(250, CSR_LTR_LONG_VAL_AD_SNOOP_VAL);
+
+               iwl_write32(trans, CSR_LTR_LONG_VAL_AD, val);
+       }
+
        if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
                iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1);
        else
index 129021f267912b094f0de85dbd4572cd0e323d8f..7b5ece380fbfbc0aed3262789fd9eabc7dce9c54 100644 (file)
@@ -536,9 +536,15 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
 
        {IWL_PCI_DEVICE(0x2725, 0x0090, iwlax211_2ax_cfg_so_gf_a0)},
        {IWL_PCI_DEVICE(0x2725, 0x0020, iwlax210_2ax_cfg_ty_gf_a0)},
+       {IWL_PCI_DEVICE(0x2725, 0x0024, iwlax210_2ax_cfg_ty_gf_a0)},
        {IWL_PCI_DEVICE(0x2725, 0x0310, iwlax210_2ax_cfg_ty_gf_a0)},
        {IWL_PCI_DEVICE(0x2725, 0x0510, iwlax210_2ax_cfg_ty_gf_a0)},
        {IWL_PCI_DEVICE(0x2725, 0x0A10, iwlax210_2ax_cfg_ty_gf_a0)},
+       {IWL_PCI_DEVICE(0x2725, 0xE020, iwlax210_2ax_cfg_ty_gf_a0)},
+       {IWL_PCI_DEVICE(0x2725, 0xE024, iwlax210_2ax_cfg_ty_gf_a0)},
+       {IWL_PCI_DEVICE(0x2725, 0x4020, iwlax210_2ax_cfg_ty_gf_a0)},
+       {IWL_PCI_DEVICE(0x2725, 0x6020, iwlax210_2ax_cfg_ty_gf_a0)},
+       {IWL_PCI_DEVICE(0x2725, 0x6024, iwlax210_2ax_cfg_ty_gf_a0)},
        {IWL_PCI_DEVICE(0x2725, 0x00B0, iwlax411_2ax_cfg_sosnj_gf4_a0)},
        {IWL_PCI_DEVICE(0x2726, 0x0070, iwlax201_cfg_snj_hr_b0)},
        {IWL_PCI_DEVICE(0x2726, 0x0074, iwlax201_cfg_snj_hr_b0)},
index d2e69ad53b27e31cceb9369e455821cef6d3dcc6..2fffbbc8462fc82cdcfacb6c9b1099cfd6886c2e 100644 (file)
@@ -2156,18 +2156,36 @@ static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr,
                                   void *buf, int dwords)
 {
        unsigned long flags;
-       int offs, ret = 0;
+       int offs = 0;
        u32 *vals = buf;
 
-       if (iwl_trans_grab_nic_access(trans, &flags)) {
-               iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr);
-               for (offs = 0; offs < dwords; offs++)
-                       vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
-               iwl_trans_release_nic_access(trans, &flags);
-       } else {
-               ret = -EBUSY;
+       while (offs < dwords) {
+               /* limit the time we spin here under lock to 1/2s */
+               ktime_t timeout = ktime_add_us(ktime_get(), 500 * USEC_PER_MSEC);
+
+               if (iwl_trans_grab_nic_access(trans, &flags)) {
+                       iwl_write32(trans, HBUS_TARG_MEM_RADDR,
+                                   addr + 4 * offs);
+
+                       while (offs < dwords) {
+                               vals[offs] = iwl_read32(trans,
+                                                       HBUS_TARG_MEM_RDAT);
+                               offs++;
+
+                               /* calling ktime_get is expensive so
+                                * do it once in 128 reads
+                                */
+                               if (offs % 128 == 0 && ktime_after(ktime_get(),
+                                                                  timeout))
+                                       break;
+                       }
+                       iwl_trans_release_nic_access(trans, &flags);
+               } else {
+                       return -EBUSY;
+               }
        }
-       return ret;
+
+       return 0;
 }
 
 static int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr,
index 7d3f0a2e5fa05c446c5d0ba72cf88eedbc834864..f1ae9ff835b23380fa2912d6a2196661d3c9b4a8 100644 (file)
@@ -1020,8 +1020,6 @@ void mt76u_stop_tx(struct mt76_dev *dev)
 {
        int ret;
 
-       mt76_worker_disable(&dev->tx_worker);
-
        ret = wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(&dev->phy),
                                 HZ / 5);
        if (!ret) {
@@ -1040,6 +1038,8 @@ void mt76u_stop_tx(struct mt76_dev *dev)
                                usb_kill_urb(q->entry[j].urb);
                }
 
+               mt76_worker_disable(&dev->tx_worker);
+
                /* On device removal we maight queue skb's, but mt76u_tx_kick()
                 * will fail to submit urb, cleanup those skb's manually.
                 */
@@ -1048,18 +1048,19 @@ void mt76u_stop_tx(struct mt76_dev *dev)
                        if (!q)
                                continue;
 
-                       entry = q->entry[q->tail];
-                       q->entry[q->tail].done = false;
-
-                       mt76_queue_tx_complete(dev, q, &entry);
+                       while (q->queued > 0) {
+                               entry = q->entry[q->tail];
+                               q->entry[q->tail].done = false;
+                               mt76_queue_tx_complete(dev, q, &entry);
+                       }
                }
+
+               mt76_worker_enable(&dev->tx_worker);
        }
 
        cancel_work_sync(&dev->usb.stat_work);
        clear_bit(MT76_READING_STATS, &dev->phy.state);
 
-       mt76_worker_enable(&dev->tx_worker);
-
        mt76_tx_status_check(dev, NULL, true);
 }
 EXPORT_SYMBOL_GPL(mt76u_stop_tx);
index 3852c4f0ac0b094c9fb44b848fcdd4b283ba3a3a..efbba9caef3bfef87015c5d506c3ecdeb3a1cff4 100644 (file)
@@ -147,6 +147,8 @@ static int rtw_debugfs_copy_from_user(char tmp[], int size,
 {
        int tmp_len;
 
+       memset(tmp, 0, size);
+
        if (count < num)
                return -EFAULT;
 
index 042015bc8055b21b0d80b7a813c808f9fd6cd237..b2fd87834f23dabdc95b141e8e2ebc578bcdefcf 100644 (file)
@@ -1482,7 +1482,7 @@ static bool rtw_fw_dump_check_size(struct rtw_dev *rtwdev,
 int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size,
                     u32 *buffer)
 {
-       if (!rtwdev->chip->fw_fifo_addr) {
+       if (!rtwdev->chip->fw_fifo_addr[0]) {
                rtw_dbg(rtwdev, RTW_DBG_FW, "chip not support dump fw fifo\n");
                return -ENOTSUPP;
        }
index dc995286be8449f9ed784ed9c655cea763c38185..d0a3bd9ff3c3db6a5b707d7b542852cf653f5e1b 100644 (file)
@@ -26,8 +26,8 @@ struct s3fwrn5_i2c_phy {
        struct i2c_client *i2c_dev;
        struct nci_dev *ndev;
 
-       unsigned int gpio_en;
-       unsigned int gpio_fw_wake;
+       int gpio_en;
+       int gpio_fw_wake;
 
        struct mutex mutex;
 
index 95ef4943d8bd4c2b464909effab150479aa54685..9a270e49df179f14c7e9f7d6e7bcb8252ba57392 100644 (file)
@@ -2060,8 +2060,6 @@ static void nvme_update_disk_info(struct gendisk *disk,
 
        if (id->nsattr & NVME_NS_ATTR_RO)
                set_disk_ro(disk, true);
-       else
-               set_disk_ro(disk, false);
 }
 
 static inline bool nvme_first_scan(struct gendisk *disk)
@@ -2125,7 +2123,7 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id)
 
        if (blk_queue_is_zoned(ns->queue)) {
                ret = nvme_revalidate_zones(ns);
-               if (ret)
+               if (ret && !nvme_first_scan(ns->disk))
                        return ret;
        }
 
@@ -2931,7 +2929,7 @@ int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp, u8 csi,
 static int nvme_get_effects_log(struct nvme_ctrl *ctrl, u8 csi,
                                struct nvme_effects_log **log)
 {
-       struct nvme_cel *cel = xa_load(&ctrl->cels, csi);
+       struct nvme_effects_log *cel = xa_load(&ctrl->cels, csi);
        int ret;
 
        if (cel)
@@ -2942,16 +2940,15 @@ static int nvme_get_effects_log(struct nvme_ctrl *ctrl, u8 csi,
                return -ENOMEM;
 
        ret = nvme_get_log(ctrl, 0x00, NVME_LOG_CMD_EFFECTS, 0, csi,
-                       &cel->log, sizeof(cel->log), 0);
+                       cel, sizeof(*cel), 0);
        if (ret) {
                kfree(cel);
                return ret;
        }
 
-       cel->csi = csi;
-       xa_store(&ctrl->cels, cel->csi, cel, GFP_KERNEL);
+       xa_store(&ctrl->cels, csi, cel, GFP_KERNEL);
 out:
-       *log = &cel->log;
+       *log = cel;
        return 0;
 }
 
@@ -4376,6 +4373,19 @@ void nvme_uninit_ctrl(struct nvme_ctrl *ctrl)
 }
 EXPORT_SYMBOL_GPL(nvme_uninit_ctrl);
 
+static void nvme_free_cels(struct nvme_ctrl *ctrl)
+{
+       struct nvme_effects_log *cel;
+       unsigned long i;
+
+       xa_for_each (&ctrl->cels, i, cel) {
+               xa_erase(&ctrl->cels, i);
+               kfree(cel);
+       }
+
+       xa_destroy(&ctrl->cels);
+}
+
 static void nvme_free_ctrl(struct device *dev)
 {
        struct nvme_ctrl *ctrl =
@@ -4385,8 +4395,7 @@ static void nvme_free_ctrl(struct device *dev)
        if (!subsys || ctrl->instance != subsys->instance)
                ida_simple_remove(&nvme_instance_ida, ctrl->instance);
 
-       xa_destroy(&ctrl->cels);
-
+       nvme_free_cels(ctrl);
        nvme_mpath_uninit(ctrl);
        __free_page(ctrl->discard_page);
 
@@ -4582,8 +4591,7 @@ void nvme_start_queues(struct nvme_ctrl *ctrl)
 }
 EXPORT_SYMBOL_GPL(nvme_start_queues);
 
-
-void nvme_sync_queues(struct nvme_ctrl *ctrl)
+void nvme_sync_io_queues(struct nvme_ctrl *ctrl)
 {
        struct nvme_ns *ns;
 
@@ -4591,7 +4599,12 @@ void nvme_sync_queues(struct nvme_ctrl *ctrl)
        list_for_each_entry(ns, &ctrl->namespaces, list)
                blk_sync_queue(ns->queue);
        up_read(&ctrl->namespaces_rwsem);
+}
+EXPORT_SYMBOL_GPL(nvme_sync_io_queues);
 
+void nvme_sync_queues(struct nvme_ctrl *ctrl)
+{
+       nvme_sync_io_queues(ctrl);
        if (ctrl->admin_q)
                blk_sync_queue(ctrl->admin_q);
 }
index 3c002bdcace39ac4551eecc219d6edeaae4437fd..f4c246462658fa50ac08387257c93b63ef7a122f 100644 (file)
@@ -146,7 +146,8 @@ struct nvme_fc_rport {
 
 /* fc_ctrl flags values - specified as bit positions */
 #define ASSOC_ACTIVE           0
-#define FCCTRL_TERMIO          1
+#define ASSOC_FAILED           1
+#define FCCTRL_TERMIO          2
 
 struct nvme_fc_ctrl {
        spinlock_t              lock;
@@ -157,7 +158,6 @@ struct nvme_fc_ctrl {
        u32                     cnum;
 
        bool                    ioq_live;
-       atomic_t                err_work_active;
        u64                     association_id;
        struct nvmefc_ls_rcv_op *rcv_disconn;
 
@@ -167,7 +167,6 @@ struct nvme_fc_ctrl {
        struct blk_mq_tag_set   tag_set;
 
        struct delayed_work     connect_work;
-       struct work_struct      err_work;
 
        struct kref             ref;
        unsigned long           flags;
@@ -2414,24 +2413,97 @@ nvme_fc_nvme_ctrl_freed(struct nvme_ctrl *nctrl)
        nvme_fc_ctrl_put(ctrl);
 }
 
+/*
+ * This routine is used by the transport when it needs to find active
+ * io on a queue that is to be terminated. The transport uses
+ * blk_mq_tagset_busy_itr() to find the busy requests, which then invoke
+ * this routine to kill them on a 1 by 1 basis.
+ *
+ * As FC allocates FC exchange for each io, the transport must contact
+ * the LLDD to terminate the exchange, thus releasing the FC exchange.
+ * After terminating the exchange the LLDD will call the transport's
+ * normal io done path for the request, but it will have an aborted
+ * status. The done path will return the io request back to the block
+ * layer with an error status.
+ */
+static bool
+nvme_fc_terminate_exchange(struct request *req, void *data, bool reserved)
+{
+       struct nvme_ctrl *nctrl = data;
+       struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
+       struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(req);
+
+       __nvme_fc_abort_op(ctrl, op);
+       return true;
+}
+
+/*
+ * This routine runs through all outstanding commands on the association
+ * and aborts them.  This routine is typically be called by the
+ * delete_association routine. It is also called due to an error during
+ * reconnect. In that scenario, it is most likely a command that initializes
+ * the controller, including fabric Connect commands on io queues, that
+ * may have timed out or failed thus the io must be killed for the connect
+ * thread to see the error.
+ */
 static void
-nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg)
+__nvme_fc_abort_outstanding_ios(struct nvme_fc_ctrl *ctrl, bool start_queues)
 {
-       int active;
+       /*
+        * If io queues are present, stop them and terminate all outstanding
+        * ios on them. As FC allocates FC exchange for each io, the
+        * transport must contact the LLDD to terminate the exchange,
+        * thus releasing the FC exchange. We use blk_mq_tagset_busy_itr()
+        * to tell us what io's are busy and invoke a transport routine
+        * to kill them with the LLDD.  After terminating the exchange
+        * the LLDD will call the transport's normal io done path, but it
+        * will have an aborted status. The done path will return the
+        * io requests back to the block layer as part of normal completions
+        * (but with error status).
+        */
+       if (ctrl->ctrl.queue_count > 1) {
+               nvme_stop_queues(&ctrl->ctrl);
+               blk_mq_tagset_busy_iter(&ctrl->tag_set,
+                               nvme_fc_terminate_exchange, &ctrl->ctrl);
+               blk_mq_tagset_wait_completed_request(&ctrl->tag_set);
+               if (start_queues)
+                       nvme_start_queues(&ctrl->ctrl);
+       }
+
+       /*
+        * Other transports, which don't have link-level contexts bound
+        * to sqe's, would try to gracefully shutdown the controller by
+        * writing the registers for shutdown and polling (call
+        * nvme_shutdown_ctrl()). Given a bunch of i/o was potentially
+        * just aborted and we will wait on those contexts, and given
+        * there was no indication of how live the controlelr is on the
+        * link, don't send more io to create more contexts for the
+        * shutdown. Let the controller fail via keepalive failure if
+        * its still present.
+        */
 
        /*
-        * if an error (io timeout, etc) while (re)connecting,
-        * it's an error on creating the new association.
-        * Start the error recovery thread if it hasn't already
-        * been started. It is expected there could be multiple
-        * ios hitting this path before things are cleaned up.
+        * clean up the admin queue. Same thing as above.
+        */
+       blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
+       blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
+                               nvme_fc_terminate_exchange, &ctrl->ctrl);
+       blk_mq_tagset_wait_completed_request(&ctrl->admin_tag_set);
+}
+
+static void
+nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg)
+{
+       /*
+        * if an error (io timeout, etc) while (re)connecting, the remote
+        * port requested terminating of the association (disconnect_ls)
+        * or an error (timeout or abort) occurred on an io while creating
+        * the controller.  Abort any ios on the association and let the
+        * create_association error path resolve things.
         */
        if (ctrl->ctrl.state == NVME_CTRL_CONNECTING) {
-               active = atomic_xchg(&ctrl->err_work_active, 1);
-               if (!active && !queue_work(nvme_fc_wq, &ctrl->err_work)) {
-                       atomic_set(&ctrl->err_work_active, 0);
-                       WARN_ON(1);
-               }
+               __nvme_fc_abort_outstanding_ios(ctrl, true);
+               set_bit(ASSOC_FAILED, &ctrl->flags);
                return;
        }
 
@@ -2745,30 +2817,6 @@ nvme_fc_complete_rq(struct request *rq)
        nvme_fc_ctrl_put(ctrl);
 }
 
-/*
- * This routine is used by the transport when it needs to find active
- * io on a queue that is to be terminated. The transport uses
- * blk_mq_tagset_busy_itr() to find the busy requests, which then invoke
- * this routine to kill them on a 1 by 1 basis.
- *
- * As FC allocates FC exchange for each io, the transport must contact
- * the LLDD to terminate the exchange, thus releasing the FC exchange.
- * After terminating the exchange the LLDD will call the transport's
- * normal io done path for the request, but it will have an aborted
- * status. The done path will return the io request back to the block
- * layer with an error status.
- */
-static bool
-nvme_fc_terminate_exchange(struct request *req, void *data, bool reserved)
-{
-       struct nvme_ctrl *nctrl = data;
-       struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
-       struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(req);
-
-       __nvme_fc_abort_op(ctrl, op);
-       return true;
-}
-
 
 static const struct blk_mq_ops nvme_fc_mq_ops = {
        .queue_rq       = nvme_fc_queue_rq,
@@ -2988,6 +3036,8 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
                ctrl->cnum, ctrl->lport->localport.port_name,
                ctrl->rport->remoteport.port_name, ctrl->ctrl.opts->subsysnqn);
 
+       clear_bit(ASSOC_FAILED, &ctrl->flags);
+
        /*
         * Create the admin queue
         */
@@ -3016,7 +3066,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
         */
 
        ret = nvme_enable_ctrl(&ctrl->ctrl);
-       if (ret)
+       if (ret || test_bit(ASSOC_FAILED, &ctrl->flags))
                goto out_disconnect_admin_queue;
 
        ctrl->ctrl.max_segments = ctrl->lport->ops->max_sgl_segments;
@@ -3026,7 +3076,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
        blk_mq_unquiesce_queue(ctrl->ctrl.admin_q);
 
        ret = nvme_init_identify(&ctrl->ctrl);
-       if (ret)
+       if (ret || test_bit(ASSOC_FAILED, &ctrl->flags))
                goto out_disconnect_admin_queue;
 
        /* sanity checks */
@@ -3071,9 +3121,9 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
                        ret = nvme_fc_create_io_queues(ctrl);
                else
                        ret = nvme_fc_recreate_io_queues(ctrl);
-               if (ret)
-                       goto out_term_aen_ops;
        }
+       if (ret || test_bit(ASSOC_FAILED, &ctrl->flags))
+               goto out_term_aen_ops;
 
        changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
 
@@ -3107,60 +3157,6 @@ out_free_queue:
 }
 
 
-/*
- * This routine runs through all outstanding commands on the association
- * and aborts them.  This routine is typically be called by the
- * delete_association routine. It is also called due to an error during
- * reconnect. In that scenario, it is most likely a command that initializes
- * the controller, including fabric Connect commands on io queues, that
- * may have timed out or failed thus the io must be killed for the connect
- * thread to see the error.
- */
-static void
-__nvme_fc_abort_outstanding_ios(struct nvme_fc_ctrl *ctrl, bool start_queues)
-{
-       /*
-        * If io queues are present, stop them and terminate all outstanding
-        * ios on them. As FC allocates FC exchange for each io, the
-        * transport must contact the LLDD to terminate the exchange,
-        * thus releasing the FC exchange. We use blk_mq_tagset_busy_itr()
-        * to tell us what io's are busy and invoke a transport routine
-        * to kill them with the LLDD.  After terminating the exchange
-        * the LLDD will call the transport's normal io done path, but it
-        * will have an aborted status. The done path will return the
-        * io requests back to the block layer as part of normal completions
-        * (but with error status).
-        */
-       if (ctrl->ctrl.queue_count > 1) {
-               nvme_stop_queues(&ctrl->ctrl);
-               blk_mq_tagset_busy_iter(&ctrl->tag_set,
-                               nvme_fc_terminate_exchange, &ctrl->ctrl);
-               blk_mq_tagset_wait_completed_request(&ctrl->tag_set);
-               if (start_queues)
-                       nvme_start_queues(&ctrl->ctrl);
-       }
-
-       /*
-        * Other transports, which don't have link-level contexts bound
-        * to sqe's, would try to gracefully shutdown the controller by
-        * writing the registers for shutdown and polling (call
-        * nvme_shutdown_ctrl()). Given a bunch of i/o was potentially
-        * just aborted and we will wait on those contexts, and given
-        * there was no indication of how live the controlelr is on the
-        * link, don't send more io to create more contexts for the
-        * shutdown. Let the controller fail via keepalive failure if
-        * its still present.
-        */
-
-       /*
-        * clean up the admin queue. Same thing as above.
-        */
-       blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
-       blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
-                               nvme_fc_terminate_exchange, &ctrl->ctrl);
-       blk_mq_tagset_wait_completed_request(&ctrl->admin_tag_set);
-}
-
 /*
  * This routine stops operation of the controller on the host side.
  * On the host os stack side: Admin and IO queues are stopped,
@@ -3237,7 +3233,6 @@ nvme_fc_delete_ctrl(struct nvme_ctrl *nctrl)
 {
        struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
 
-       cancel_work_sync(&ctrl->err_work);
        cancel_delayed_work_sync(&ctrl->connect_work);
        /*
         * kill the association on the link side.  this will block
@@ -3292,78 +3287,34 @@ nvme_fc_reconnect_or_delete(struct nvme_fc_ctrl *ctrl, int status)
 }
 
 static void
-__nvme_fc_terminate_io(struct nvme_fc_ctrl *ctrl)
+nvme_fc_reset_ctrl_work(struct work_struct *work)
 {
-       /*
-        * if state is CONNECTING - the error occurred as part of a
-        * reconnect attempt. Abort any ios on the association and
-        * let the create_association error paths resolve things.
-        */
-       if (ctrl->ctrl.state == NVME_CTRL_CONNECTING) {
-               __nvme_fc_abort_outstanding_ios(ctrl, true);
-               return;
-       }
-
-       /*
-        * For any other state, kill the association. As this routine
-        * is a common io abort routine for resetting and such, after
-        * the association is terminated, ensure that the state is set
-        * to CONNECTING.
-        */
+       struct nvme_fc_ctrl *ctrl =
+               container_of(work, struct nvme_fc_ctrl, ctrl.reset_work);
 
-       nvme_stop_keep_alive(&ctrl->ctrl);
+       nvme_stop_ctrl(&ctrl->ctrl);
 
        /* will block will waiting for io to terminate */
        nvme_fc_delete_association(ctrl);
 
-       if (ctrl->ctrl.state != NVME_CTRL_CONNECTING &&
-           !nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING))
+       if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING))
                dev_err(ctrl->ctrl.device,
                        "NVME-FC{%d}: error_recovery: Couldn't change state "
                        "to CONNECTING\n", ctrl->cnum);
-}
-
-static void
-nvme_fc_reset_ctrl_work(struct work_struct *work)
-{
-       struct nvme_fc_ctrl *ctrl =
-               container_of(work, struct nvme_fc_ctrl, ctrl.reset_work);
-       int ret;
 
-       __nvme_fc_terminate_io(ctrl);
-
-       nvme_stop_ctrl(&ctrl->ctrl);
-
-       if (ctrl->rport->remoteport.port_state == FC_OBJSTATE_ONLINE)
-               ret = nvme_fc_create_association(ctrl);
-       else
-               ret = -ENOTCONN;
-
-       if (ret)
-               nvme_fc_reconnect_or_delete(ctrl, ret);
-       else
-               dev_info(ctrl->ctrl.device,
-                       "NVME-FC{%d}: controller reset complete\n",
-                       ctrl->cnum);
+       if (ctrl->rport->remoteport.port_state == FC_OBJSTATE_ONLINE) {
+               if (!queue_delayed_work(nvme_wq, &ctrl->connect_work, 0)) {
+                       dev_err(ctrl->ctrl.device,
+                               "NVME-FC{%d}: failed to schedule connect "
+                               "after reset\n", ctrl->cnum);
+               } else {
+                       flush_delayed_work(&ctrl->connect_work);
+               }
+       } else {
+               nvme_fc_reconnect_or_delete(ctrl, -ENOTCONN);
+       }
 }
 
-static void
-nvme_fc_connect_err_work(struct work_struct *work)
-{
-       struct nvme_fc_ctrl *ctrl =
-                       container_of(work, struct nvme_fc_ctrl, err_work);
-
-       __nvme_fc_terminate_io(ctrl);
-
-       atomic_set(&ctrl->err_work_active, 0);
-
-       /*
-        * Rescheduling the connection after recovering
-        * from the io error is left to the reconnect work
-        * item, which is what should have stalled waiting on
-        * the io that had the error that scheduled this work.
-        */
-}
 
 static const struct nvme_ctrl_ops nvme_fc_ctrl_ops = {
        .name                   = "fc",
@@ -3491,7 +3442,6 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
        ctrl->dev = lport->dev;
        ctrl->cnum = idx;
        ctrl->ioq_live = false;
-       atomic_set(&ctrl->err_work_active, 0);
        init_waitqueue_head(&ctrl->ioabort_wait);
 
        get_device(ctrl->dev);
@@ -3499,7 +3449,6 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
 
        INIT_WORK(&ctrl->ctrl.reset_work, nvme_fc_reset_ctrl_work);
        INIT_DELAYED_WORK(&ctrl->connect_work, nvme_fc_connect_ctrl_work);
-       INIT_WORK(&ctrl->err_work, nvme_fc_connect_err_work);
        spin_lock_init(&ctrl->lock);
 
        /* io queue count */
@@ -3592,7 +3541,6 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
 fail_ctrl:
        nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING);
        cancel_work_sync(&ctrl->ctrl.reset_work);
-       cancel_work_sync(&ctrl->err_work);
        cancel_delayed_work_sync(&ctrl->connect_work);
 
        ctrl->ctrl.opts = NULL;
index cc111136a9818813ba22d7bce5c1d75b6055851a..567f7ad18a91cdcddf8e7e39ce482e4776eb90b0 100644 (file)
@@ -226,12 +226,6 @@ struct nvme_fault_inject {
 #endif
 };
 
-struct nvme_cel {
-       struct list_head        entry;
-       struct nvme_effects_log log;
-       u8                      csi;
-};
-
 struct nvme_ctrl {
        bool comp_seen;
        enum nvme_ctrl_state state;
@@ -602,6 +596,7 @@ void nvme_stop_queues(struct nvme_ctrl *ctrl);
 void nvme_start_queues(struct nvme_ctrl *ctrl);
 void nvme_kill_queues(struct nvme_ctrl *ctrl);
 void nvme_sync_queues(struct nvme_ctrl *ctrl);
+void nvme_sync_io_queues(struct nvme_ctrl *ctrl);
 void nvme_unfreeze(struct nvme_ctrl *ctrl);
 void nvme_wait_freeze(struct nvme_ctrl *ctrl);
 int nvme_wait_freeze_timeout(struct nvme_ctrl *ctrl, long timeout);
index df8f3612107f1d0ffbe6671f971af3d615fa6bdc..3be352403839a0e6785a681654d21497a108d118 100644 (file)
@@ -198,6 +198,7 @@ struct nvme_queue {
        u32 q_depth;
        u16 cq_vector;
        u16 sq_tail;
+       u16 last_sq_tail;
        u16 cq_head;
        u16 qid;
        u8 cq_phase;
@@ -291,9 +292,21 @@ static void nvme_dbbuf_init(struct nvme_dev *dev,
        nvmeq->dbbuf_cq_ei = &dev->dbbuf_eis[cq_idx(qid, dev->db_stride)];
 }
 
+static void nvme_dbbuf_free(struct nvme_queue *nvmeq)
+{
+       if (!nvmeq->qid)
+               return;
+
+       nvmeq->dbbuf_sq_db = NULL;
+       nvmeq->dbbuf_cq_db = NULL;
+       nvmeq->dbbuf_sq_ei = NULL;
+       nvmeq->dbbuf_cq_ei = NULL;
+}
+
 static void nvme_dbbuf_set(struct nvme_dev *dev)
 {
        struct nvme_command c;
+       unsigned int i;
 
        if (!dev->dbbuf_dbs)
                return;
@@ -307,6 +320,9 @@ static void nvme_dbbuf_set(struct nvme_dev *dev)
                dev_warn(dev->ctrl.device, "unable to set dbbuf\n");
                /* Free memory and continue on */
                nvme_dbbuf_dma_free(dev);
+
+               for (i = 1; i <= dev->online_queues; i++)
+                       nvme_dbbuf_free(&dev->queues[i]);
        }
 }
 
@@ -455,11 +471,24 @@ static int nvme_pci_map_queues(struct blk_mq_tag_set *set)
        return 0;
 }
 
-static inline void nvme_write_sq_db(struct nvme_queue *nvmeq)
+/*
+ * Write sq tail if we are asked to, or if the next command would wrap.
+ */
+static inline void nvme_write_sq_db(struct nvme_queue *nvmeq, bool write_sq)
 {
+       if (!write_sq) {
+               u16 next_tail = nvmeq->sq_tail + 1;
+
+               if (next_tail == nvmeq->q_depth)
+                       next_tail = 0;
+               if (next_tail != nvmeq->last_sq_tail)
+                       return;
+       }
+
        if (nvme_dbbuf_update_and_check_event(nvmeq->sq_tail,
                        nvmeq->dbbuf_sq_db, nvmeq->dbbuf_sq_ei))
                writel(nvmeq->sq_tail, nvmeq->q_db);
+       nvmeq->last_sq_tail = nvmeq->sq_tail;
 }
 
 /**
@@ -476,8 +505,7 @@ static void nvme_submit_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd,
               cmd, sizeof(*cmd));
        if (++nvmeq->sq_tail == nvmeq->q_depth)
                nvmeq->sq_tail = 0;
-       if (write_sq)
-               nvme_write_sq_db(nvmeq);
+       nvme_write_sq_db(nvmeq, write_sq);
        spin_unlock(&nvmeq->sq_lock);
 }
 
@@ -486,7 +514,8 @@ static void nvme_commit_rqs(struct blk_mq_hw_ctx *hctx)
        struct nvme_queue *nvmeq = hctx->driver_data;
 
        spin_lock(&nvmeq->sq_lock);
-       nvme_write_sq_db(nvmeq);
+       if (nvmeq->sq_tail != nvmeq->last_sq_tail)
+               nvme_write_sq_db(nvmeq, true);
        spin_unlock(&nvmeq->sq_lock);
 }
 
@@ -1496,6 +1525,7 @@ static void nvme_init_queue(struct nvme_queue *nvmeq, u16 qid)
        struct nvme_dev *dev = nvmeq->dev;
 
        nvmeq->sq_tail = 0;
+       nvmeq->last_sq_tail = 0;
        nvmeq->cq_head = 0;
        nvmeq->cq_phase = 1;
        nvmeq->q_db = &dev->dbs[qid * 2 * dev->db_stride];
index aad829a2b50d0f9348bd819f75dd35bc53bc1a51..65e3d0ef36e1a33dffad84405aaa07d819385380 100644 (file)
@@ -122,7 +122,6 @@ struct nvme_rdma_ctrl {
        struct sockaddr_storage src_addr;
 
        struct nvme_ctrl        ctrl;
-       struct mutex            teardown_lock;
        bool                    use_inline_data;
        u32                     io_queues[HCTX_MAX_TYPES];
 };
@@ -1010,8 +1009,8 @@ out_free_io_queues:
 static void nvme_rdma_teardown_admin_queue(struct nvme_rdma_ctrl *ctrl,
                bool remove)
 {
-       mutex_lock(&ctrl->teardown_lock);
        blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
+       blk_sync_queue(ctrl->ctrl.admin_q);
        nvme_rdma_stop_queue(&ctrl->queues[0]);
        if (ctrl->ctrl.admin_tagset) {
                blk_mq_tagset_busy_iter(ctrl->ctrl.admin_tagset,
@@ -1021,16 +1020,15 @@ static void nvme_rdma_teardown_admin_queue(struct nvme_rdma_ctrl *ctrl,
        if (remove)
                blk_mq_unquiesce_queue(ctrl->ctrl.admin_q);
        nvme_rdma_destroy_admin_queue(ctrl, remove);
-       mutex_unlock(&ctrl->teardown_lock);
 }
 
 static void nvme_rdma_teardown_io_queues(struct nvme_rdma_ctrl *ctrl,
                bool remove)
 {
-       mutex_lock(&ctrl->teardown_lock);
        if (ctrl->ctrl.queue_count > 1) {
                nvme_start_freeze(&ctrl->ctrl);
                nvme_stop_queues(&ctrl->ctrl);
+               nvme_sync_io_queues(&ctrl->ctrl);
                nvme_rdma_stop_io_queues(ctrl);
                if (ctrl->ctrl.tagset) {
                        blk_mq_tagset_busy_iter(ctrl->ctrl.tagset,
@@ -1041,7 +1039,6 @@ static void nvme_rdma_teardown_io_queues(struct nvme_rdma_ctrl *ctrl,
                        nvme_start_queues(&ctrl->ctrl);
                nvme_rdma_destroy_io_queues(ctrl, remove);
        }
-       mutex_unlock(&ctrl->teardown_lock);
 }
 
 static void nvme_rdma_free_ctrl(struct nvme_ctrl *nctrl)
@@ -1768,6 +1765,14 @@ static void nvme_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc)
                return;
        }
 
+       /* sanity checking for received data length */
+       if (unlikely(wc->byte_len < len)) {
+               dev_err(queue->ctrl->ctrl.device,
+                       "Unexpected nvme completion length(%d)\n", wc->byte_len);
+               nvme_rdma_error_recovery(queue->ctrl);
+               return;
+       }
+
        ib_dma_sync_single_for_cpu(ibdev, qe->dma, len, DMA_FROM_DEVICE);
        /*
         * AEN requests are special as they don't time out and can
@@ -1890,10 +1895,10 @@ static int nvme_rdma_route_resolved(struct nvme_rdma_queue *queue)
                priv.hsqsize = cpu_to_le16(queue->ctrl->ctrl.sqsize);
        }
 
-       ret = rdma_connect(queue->cm_id, &param);
+       ret = rdma_connect_locked(queue->cm_id, &param);
        if (ret) {
                dev_err(ctrl->ctrl.device,
-                       "rdma_connect failed (%d).\n", ret);
+                       "rdma_connect_locked failed (%d).\n", ret);
                goto out_destroy_queue_ib;
        }
 
@@ -1968,16 +1973,12 @@ static void nvme_rdma_complete_timed_out(struct request *rq)
 {
        struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq);
        struct nvme_rdma_queue *queue = req->queue;
-       struct nvme_rdma_ctrl *ctrl = queue->ctrl;
 
-       /* fence other contexts that may complete the command */
-       mutex_lock(&ctrl->teardown_lock);
        nvme_rdma_stop_queue(queue);
-       if (!blk_mq_request_completed(rq)) {
+       if (blk_mq_request_started(rq) && !blk_mq_request_completed(rq)) {
                nvme_req(rq)->status = NVME_SC_HOST_ABORTED_CMD;
                blk_mq_complete_request(rq);
        }
-       mutex_unlock(&ctrl->teardown_lock);
 }
 
 static enum blk_eh_timer_return
@@ -2312,7 +2313,6 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
                return ERR_PTR(-ENOMEM);
        ctrl->ctrl.opts = opts;
        INIT_LIST_HEAD(&ctrl->list);
-       mutex_init(&ctrl->teardown_lock);
 
        if (!(opts->mask & NVMF_OPT_TRSVCID)) {
                opts->trsvcid =
index d6a3e148735428cac13e39e0ea7366ed38df84cf..c0c33320fe659ffad05362a3fd146ff539fa58ea 100644 (file)
@@ -124,7 +124,6 @@ struct nvme_tcp_ctrl {
        struct sockaddr_storage src_addr;
        struct nvme_ctrl        ctrl;
 
-       struct mutex            teardown_lock;
        struct work_struct      err_work;
        struct delayed_work     connect_work;
        struct nvme_tcp_request async_req;
@@ -1886,8 +1885,8 @@ out_free_queue:
 static void nvme_tcp_teardown_admin_queue(struct nvme_ctrl *ctrl,
                bool remove)
 {
-       mutex_lock(&to_tcp_ctrl(ctrl)->teardown_lock);
        blk_mq_quiesce_queue(ctrl->admin_q);
+       blk_sync_queue(ctrl->admin_q);
        nvme_tcp_stop_queue(ctrl, 0);
        if (ctrl->admin_tagset) {
                blk_mq_tagset_busy_iter(ctrl->admin_tagset,
@@ -1897,18 +1896,17 @@ static void nvme_tcp_teardown_admin_queue(struct nvme_ctrl *ctrl,
        if (remove)
                blk_mq_unquiesce_queue(ctrl->admin_q);
        nvme_tcp_destroy_admin_queue(ctrl, remove);
-       mutex_unlock(&to_tcp_ctrl(ctrl)->teardown_lock);
 }
 
 static void nvme_tcp_teardown_io_queues(struct nvme_ctrl *ctrl,
                bool remove)
 {
-       mutex_lock(&to_tcp_ctrl(ctrl)->teardown_lock);
        if (ctrl->queue_count <= 1)
-               goto out;
+               return;
        blk_mq_quiesce_queue(ctrl->admin_q);
        nvme_start_freeze(ctrl);
        nvme_stop_queues(ctrl);
+       nvme_sync_io_queues(ctrl);
        nvme_tcp_stop_io_queues(ctrl);
        if (ctrl->tagset) {
                blk_mq_tagset_busy_iter(ctrl->tagset,
@@ -1918,8 +1916,6 @@ static void nvme_tcp_teardown_io_queues(struct nvme_ctrl *ctrl,
        if (remove)
                nvme_start_queues(ctrl);
        nvme_tcp_destroy_io_queues(ctrl, remove);
-out:
-       mutex_unlock(&to_tcp_ctrl(ctrl)->teardown_lock);
 }
 
 static void nvme_tcp_reconnect_or_remove(struct nvme_ctrl *ctrl)
@@ -2171,14 +2167,11 @@ static void nvme_tcp_complete_timed_out(struct request *rq)
        struct nvme_tcp_request *req = blk_mq_rq_to_pdu(rq);
        struct nvme_ctrl *ctrl = &req->queue->ctrl->ctrl;
 
-       /* fence other contexts that may complete the command */
-       mutex_lock(&to_tcp_ctrl(ctrl)->teardown_lock);
        nvme_tcp_stop_queue(ctrl, nvme_tcp_queue_id(req->queue));
-       if (!blk_mq_request_completed(rq)) {
+       if (blk_mq_request_started(rq) && !blk_mq_request_completed(rq)) {
                nvme_req(rq)->status = NVME_SC_HOST_ABORTED_CMD;
                blk_mq_complete_request(rq);
        }
-       mutex_unlock(&to_tcp_ctrl(ctrl)->teardown_lock);
 }
 
 static enum blk_eh_timer_return
@@ -2455,7 +2448,6 @@ static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev,
                        nvme_tcp_reconnect_ctrl_work);
        INIT_WORK(&ctrl->err_work, nvme_tcp_error_recovery_work);
        INIT_WORK(&ctrl->ctrl.reset_work, nvme_reset_ctrl_work);
-       mutex_init(&ctrl->teardown_lock);
 
        if (!(opts->mask & NVMF_OPT_TRSVCID)) {
                opts->trsvcid =
index aafcbc424b7a94e839a5c1f6d308e64686919637..957b39a82431b718f60875709c37827777dcf7d6 100644 (file)
@@ -907,8 +907,6 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
        req->error_loc = NVMET_NO_ERROR_LOC;
        req->error_slba = 0;
 
-       trace_nvmet_req_init(req, req->cmd);
-
        /* no support for fused commands yet */
        if (unlikely(flags & (NVME_CMD_FUSE_FIRST | NVME_CMD_FUSE_SECOND))) {
                req->error_loc = offsetof(struct nvme_common_command, flags);
@@ -938,6 +936,8 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
        if (status)
                goto fail;
 
+       trace_nvmet_req_init(req, req->cmd);
+
        if (unlikely(!percpu_ref_tryget_live(&sq->ref))) {
                status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
                goto fail;
index 0458046d650178b7a620a20b678ceeb1ba2a0292..c14e3249a14dc884c7ed4e571f7f4c1ab6199b36 100644 (file)
@@ -46,19 +46,12 @@ static inline struct nvmet_ctrl *nvmet_req_to_ctrl(struct nvmet_req *req)
        return req->sq->ctrl;
 }
 
-static inline void __assign_disk_name(char *name, struct nvmet_req *req,
-               bool init)
+static inline void __assign_req_name(char *name, struct nvmet_req *req)
 {
-       struct nvmet_ctrl *ctrl = nvmet_req_to_ctrl(req);
-       struct nvmet_ns *ns;
-
-       if ((init && req->sq->qid) || (!init && req->cq->qid)) {
-               ns = nvmet_find_namespace(ctrl, req->cmd->rw.nsid);
-               strncpy(name, ns->device_path, DISK_NAME_LEN);
-               return;
-       }
-
-       memset(name, 0, DISK_NAME_LEN);
+       if (req->ns)
+               strncpy(name, req->ns->device_path, DISK_NAME_LEN);
+       else
+               memset(name, 0, DISK_NAME_LEN);
 }
 #endif
 
@@ -81,7 +74,7 @@ TRACE_EVENT(nvmet_req_init,
        TP_fast_assign(
                __entry->cmd = cmd;
                __entry->ctrl = nvmet_req_to_ctrl(req);
-               __assign_disk_name(__entry->disk, req, true);
+               __assign_req_name(__entry->disk, req);
                __entry->qid = req->sq->qid;
                __entry->cid = cmd->common.command_id;
                __entry->opcode = cmd->common.opcode;
@@ -121,7 +114,7 @@ TRACE_EVENT(nvmet_req_complete,
                __entry->cid = req->cqe->command_id;
                __entry->result = le64_to_cpu(req->cqe->result.u64);
                __entry->status = le16_to_cpu(req->cqe->status) >> 1;
-               __assign_disk_name(__entry->disk, req, false);
+               __assign_req_name(__entry->disk, req);
        ),
        TP_printk("nvmet%s: %sqid=%d, cmdid=%u, res=%#llx, status=%#x",
                __print_ctrl_name(__entry->ctrl),
index eb9ab4f1e80b00c124e916ded75dfa597897ce75..1c3257a2d4e37e6677deba228b2102d0f2dc5b38 100644 (file)
@@ -1034,11 +1034,13 @@ out:
  */
 bool of_dma_is_coherent(struct device_node *np)
 {
-       struct device_node *node = of_node_get(np);
+       struct device_node *node;
 
        if (IS_ENABLED(CONFIG_OF_DMA_DEFAULT_COHERENT))
                return true;
 
+       node = of_node_get(np);
+
        while (node) {
                if (of_property_read_bool(node, "dma-coherent")) {
                        of_node_put(node);
index 655dee422563f05f14b946c32c3935d2e835e9e7..aedfaaafd3e7edb73a4468cba26cf2c177ea1164 100644 (file)
@@ -93,7 +93,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
 {
        const struct iommu_ops *iommu;
        const struct bus_dma_region *map = NULL;
-       dma_addr_t dma_start = 0;
+       u64 dma_start = 0;
        u64 mask, end, size = 0;
        bool coherent;
        int ret;
@@ -109,10 +109,10 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
                        return ret == -ENODEV ? 0 : ret;
        } else {
                const struct bus_dma_region *r = map;
-               dma_addr_t dma_end = 0;
+               u64 dma_end = 0;
 
                /* Determine the overall bounds of all DMA regions */
-               for (dma_start = ~(dma_addr_t)0; r->size; r++) {
+               for (dma_start = ~0; r->size; r++) {
                        /* Take lower and upper limits */
                        if (r->dma_start < dma_start)
                                dma_start = r->dma_start;
index bcd15448597244a4d44db9b413608f8a3b98da8a..a7fbc5e37e19ef67457425fc9381862aa66895c5 100644 (file)
@@ -200,6 +200,16 @@ static int __init __rmem_cmp(const void *a, const void *b)
        if (ra->base > rb->base)
                return 1;
 
+       /*
+        * Put the dynamic allocations (address == 0, size == 0) before static
+        * allocations at address 0x0 so that overlap detection works
+        * correctly.
+        */
+       if (ra->size < rb->size)
+               return -1;
+       if (ra->size > rb->size)
+               return 1;
+
        return 0;
 }
 
@@ -217,8 +227,7 @@ static void __init __rmem_check_for_overlap(void)
 
                this = &reserved_mem[i];
                next = &reserved_mem[i + 1];
-               if (!(this->base && next->base))
-                       continue;
+
                if (this->base + this->size > next->base) {
                        phys_addr_t this_end, next_end;
 
index 2483e765318a3c01c3d4466a45322698f6f293d0..0e0a5269dc82f8314e936bcc71d457e51d24fb48 100644 (file)
@@ -1181,6 +1181,10 @@ static void _opp_table_kref_release(struct kref *kref)
        struct opp_device *opp_dev, *temp;
        int i;
 
+       /* Drop the lock as soon as we can */
+       list_del(&opp_table->node);
+       mutex_unlock(&opp_table_lock);
+
        _of_clear_opp_table(opp_table);
 
        /* Release clk */
@@ -1208,10 +1212,7 @@ static void _opp_table_kref_release(struct kref *kref)
 
        mutex_destroy(&opp_table->genpd_virt_dev_lock);
        mutex_destroy(&opp_table->lock);
-       list_del(&opp_table->node);
        kfree(opp_table);
-
-       mutex_unlock(&opp_table_lock);
 }
 
 void dev_pm_opp_put_opp_table(struct opp_table *opp_table)
@@ -1930,7 +1931,7 @@ struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev,
                return ERR_PTR(-EINVAL);
 
        opp_table = dev_pm_opp_get_opp_table(dev);
-       if (!IS_ERR(opp_table))
+       if (IS_ERR(opp_table))
                return opp_table;
 
        /* This should be called before OPPs are initialized */
index 874b587562202219babd72ce0e7c9236a7c9ee75..9faeb83e4b326217e538d570f29e7e333d5888d5 100644 (file)
@@ -944,6 +944,8 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table)
                nr -= 2;
        }
 
+       return 0;
+
 remove_static_opp:
        _opp_remove_all_static(opp_table);
 
index 674f32db85ca4ccf5935eb4b3ba59ecdbd7401a7..44c2a6572199c341d9108e2b9243035215722ae7 100644 (file)
@@ -586,8 +586,12 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
         * ATU, so we should not program the ATU here.
         */
        if (pp->bridge->child_ops == &dw_child_pcie_ops) {
-               struct resource_entry *entry =
-                       resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM);
+               struct resource_entry *tmp, *entry = NULL;
+
+               /* Get last memory resource entry */
+               resource_list_for_each_entry(tmp, &pp->bridge->windows)
+                       if (resource_type(tmp->res) == IORESOURCE_MEM)
+                               entry = tmp;
 
                dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0,
                                          PCIE_ATU_TYPE_MEM, entry->res->start,
index eee82838f4bace3309541ae14d1b516b9000bf70..ed13e81cd691d461708f2d7b798037fee15f8449 100644 (file)
@@ -958,25 +958,16 @@ static void mvebu_pcie_powerdown(struct mvebu_pcie_port *port)
 }
 
 /*
- * We can't use devm_of_pci_get_host_bridge_resources() because we
- * need to parse our special DT properties encoding the MEM and IO
- * apertures.
+ * devm_of_pci_get_host_bridge_resources() only sets up translateable resources,
+ * so we need extra resource setup parsing our special DT properties encoding
+ * the MEM and IO apertures.
  */
 static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie)
 {
        struct device *dev = &pcie->pdev->dev;
-       struct device_node *np = dev->of_node;
        struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
        int ret;
 
-       /* Get the bus range */
-       ret = of_pci_parse_bus_range(np, &pcie->busn);
-       if (ret) {
-               dev_err(dev, "failed to parse bus-range property: %d\n", ret);
-               return ret;
-       }
-       pci_add_resource(&bridge->windows, &pcie->busn);
-
        /* Get the PCIe memory aperture */
        mvebu_mbus_get_pcie_mem_aperture(&pcie->mem);
        if (resource_size(&pcie->mem) == 0) {
@@ -986,6 +977,9 @@ static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie)
 
        pcie->mem.name = "PCI MEM";
        pci_add_resource(&bridge->windows, &pcie->mem);
+       ret = devm_request_resource(dev, &iomem_resource, &pcie->mem);
+       if (ret)
+               return ret;
 
        /* Get the PCIe IO aperture */
        mvebu_mbus_get_pcie_io_aperture(&pcie->io);
@@ -999,9 +993,12 @@ static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie)
                pcie->realio.name = "PCI I/O";
 
                pci_add_resource(&bridge->windows, &pcie->realio);
+               ret = devm_request_resource(dev, &ioport_resource, &pcie->realio);
+               if (ret)
+                       return ret;
        }
 
-       return devm_request_pci_bus_resources(dev, &bridge->windows);
+       return 0;
 }
 
 /*
index 6d4d5a2f923d9ef291eb7f09d5af3b452fe487df..e578d34095e91a1dea6731314d364bf981e1c697 100644 (file)
@@ -3516,8 +3516,13 @@ void pci_acs_init(struct pci_dev *dev)
 {
        dev->acs_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
 
-       if (dev->acs_cap)
-               pci_enable_acs(dev);
+       /*
+        * Attempt to enable ACS regardless of capability because some Root
+        * Ports (e.g. those quirked with *_intel_pch_acs_*) do not have
+        * the standard ACS capability but still support ACS via those
+        * quirks.
+        */
+       pci_enable_acs(dev);
 }
 
 /**
index 456dc4a100c20ee411d266bcfa4a0a01b6bbf8bd..e63457e145c71926fa7d4dea2c0e4384c79afea8 100644 (file)
@@ -270,11 +270,6 @@ static void usb_init_common_7211b0(struct brcm_usb_init_params *params)
        reg |= params->mode << USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT;
        brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1);
 
-       /* Fix the incorrect default */
-       reg = brcm_usb_readl(ctrl + USB_CTRL_SETUP);
-       reg &= ~USB_CTRL_SETUP_tca_drv_sel_MASK;
-       brcm_usb_writel(reg, ctrl + USB_CTRL_SETUP);
-
        usb_init_common(params);
 
        /*
index 58ec695c92ec8fb9ced3f6dbee10596bb7c0b1f0..62c24764654b2e5d3eb13365e1beb421dd9aa69c 100644 (file)
@@ -4,7 +4,7 @@
 #
 config PHY_INTEL_KEEMBAY_EMMC
        tristate "Intel Keem Bay EMMC PHY driver"
-       depends on (OF && ARM64) || COMPILE_TEST
+       depends on ARCH_KEEMBAY || COMPILE_TEST
        depends on HAS_IOMEM
        select GENERIC_PHY
        select REGMAP_MMIO
index 50c5e9306e19b704b4f11eee9b78cef3dcfe5e32..c8126bde9d7ccebe51838888f7584d098d04cfb5 100644 (file)
@@ -12,7 +12,7 @@ config PHY_MTK_TPHY
          it supports multiple usb2.0, usb3.0 ports, PCIe and
          SATA, and meanwhile supports two version T-PHY which have
          different banks layout, the T-PHY with shared banks between
-         multi-ports is first version, otherwise is second veriosn,
+         multi-ports is first version, otherwise is second version,
          so you can easily distinguish them by banks layout.
 
 config PHY_MTK_UFS
index 089db0dea7037ed8e72e977bccc9b2451189e0cc..442522ba487f07c1aa7d87b179202cd9f7923c7a 100644 (file)
@@ -364,7 +364,8 @@ static int cpcap_usb_init_irq(struct platform_device *pdev,
 
        error = devm_request_threaded_irq(ddata->dev, irq, NULL,
                                          cpcap_phy_irq_thread,
-                                         IRQF_SHARED,
+                                         IRQF_SHARED |
+                                         IRQF_ONESHOT,
                                          name, ddata);
        if (error) {
                dev_err(ddata->dev, "could not get irq %s: %i\n",
index 928db510b86c6d8d97477dda388eaf01a2b5d71d..7f6fcb8ec5babcea37516047f339c17746f7de76 100644 (file)
@@ -87,7 +87,7 @@ config PHY_QCOM_USB_HSIC
 
 config PHY_QCOM_USB_HS_28NM
        tristate "Qualcomm 28nm High-Speed PHY"
-       depends on ARCH_QCOM || COMPILE_TEST
+       depends on OF && (ARCH_QCOM || COMPILE_TEST)
        depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
        select GENERIC_PHY
        help
@@ -98,7 +98,7 @@ config PHY_QCOM_USB_HS_28NM
 
 config PHY_QCOM_USB_SS
        tristate "Qualcomm USB Super-Speed PHY driver"
-       depends on ARCH_QCOM || COMPILE_TEST
+       depends on OF && (ARCH_QCOM || COMPILE_TEST)
        depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
        select GENERIC_PHY
        help
index 5d33ad4d06f2ef884e330389a6b8b96203fc6fc6..0cda16846962594a3a31407559d9893e4adace7a 100644 (file)
@@ -3926,7 +3926,7 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
        struct phy_provider *phy_provider;
        void __iomem *serdes;
        void __iomem *usb_serdes;
-       void __iomem *dp_serdes;
+       void __iomem *dp_serdes = NULL;
        const struct qmp_phy_combo_cfg *combo_cfg = NULL;
        const struct qmp_phy_cfg *cfg = NULL;
        const struct qmp_phy_cfg *usb_cfg = NULL;
index de4a46fe176308d97b684e7051bfe7677a7ae6fe..ad88d74c18842c5cc9d962f185d9c03524bff529 100644 (file)
@@ -1242,6 +1242,7 @@ power_down:
 reset:
        reset_control_assert(padctl->rst);
 remove:
+       platform_set_drvdata(pdev, NULL);
        soc->ops->remove(padctl);
        return err;
 }
index 6a94eaecf63861f8f14cbac9e40148cc3d3afdfb..d6b849552a1e7a627376f3e0a40f41fd30bea99d 100644 (file)
@@ -286,13 +286,14 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
 static bool aspeed_expr_is_gpio(const struct aspeed_sig_expr *expr)
 {
        /*
-        * The signal type is GPIO if the signal name has "GPIO" as a prefix.
+        * The signal type is GPIO if the signal name has "GPI" as a prefix.
         * strncmp (rather than strcmp) is used to implement the prefix
         * requirement.
         *
-        * expr->signal might look like "GPIOT3" in the GPIO case.
+        * expr->signal might look like "GPIOB1" in the GPIO case.
+        * expr->signal might look like "GPIT0" in the GPI case.
         */
-       return strncmp(expr->signal, "GPIO", 4) == 0;
+       return strncmp(expr->signal, "GPI", 3) == 0;
 }
 
 static bool aspeed_gpio_in_exprs(const struct aspeed_sig_expr **exprs)
index 154ce3f908cd51d497fb091652c440daf516909e..1c10ab18478347680e23046d9bdcaa35aca80e26 100644 (file)
 #define PADCFG1_TERM_UP                        BIT(13)
 #define PADCFG1_TERM_SHIFT             10
 #define PADCFG1_TERM_MASK              GENMASK(12, 10)
-#define PADCFG1_TERM_20K               4
-#define PADCFG1_TERM_2K                        3
-#define PADCFG1_TERM_5K                        2
-#define PADCFG1_TERM_1K                        1
+#define PADCFG1_TERM_20K               BIT(2)
+#define PADCFG1_TERM_5K                        BIT(1)
+#define PADCFG1_TERM_1K                        BIT(0)
+#define PADCFG1_TERM_833               (BIT(1) | BIT(0))
 
 #define PADCFG2                                0x008
 #define PADCFG2_DEBEN                  BIT(0)
@@ -549,12 +549,12 @@ static int intel_config_get_pull(struct intel_pinctrl *pctrl, unsigned int pin,
                        return -EINVAL;
 
                switch (term) {
+               case PADCFG1_TERM_833:
+                       *arg = 833;
+                       break;
                case PADCFG1_TERM_1K:
                        *arg = 1000;
                        break;
-               case PADCFG1_TERM_2K:
-                       *arg = 2000;
-                       break;
                case PADCFG1_TERM_5K:
                        *arg = 5000;
                        break;
@@ -570,6 +570,11 @@ static int intel_config_get_pull(struct intel_pinctrl *pctrl, unsigned int pin,
                        return -EINVAL;
 
                switch (term) {
+               case PADCFG1_TERM_833:
+                       if (!(community->features & PINCTRL_FEATURE_1K_PD))
+                               return -EINVAL;
+                       *arg = 833;
+                       break;
                case PADCFG1_TERM_1K:
                        if (!(community->features & PINCTRL_FEATURE_1K_PD))
                                return -EINVAL;
@@ -678,6 +683,10 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin,
 
                value |= PADCFG1_TERM_UP;
 
+               /* Set default strength value in case none is given */
+               if (arg == 1)
+                       arg = 5000;
+
                switch (arg) {
                case 20000:
                        value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT;
@@ -685,12 +694,12 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin,
                case 5000:
                        value |= PADCFG1_TERM_5K << PADCFG1_TERM_SHIFT;
                        break;
-               case 2000:
-                       value |= PADCFG1_TERM_2K << PADCFG1_TERM_SHIFT;
-                       break;
                case 1000:
                        value |= PADCFG1_TERM_1K << PADCFG1_TERM_SHIFT;
                        break;
+               case 833:
+                       value |= PADCFG1_TERM_833 << PADCFG1_TERM_SHIFT;
+                       break;
                default:
                        ret = -EINVAL;
                }
@@ -700,6 +709,10 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin,
        case PIN_CONFIG_BIAS_PULL_DOWN:
                value &= ~(PADCFG1_TERM_UP | PADCFG1_TERM_MASK);
 
+               /* Set default strength value in case none is given */
+               if (arg == 1)
+                       arg = 5000;
+
                switch (arg) {
                case 20000:
                        value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT;
@@ -714,6 +727,13 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin,
                        }
                        value |= PADCFG1_TERM_1K << PADCFG1_TERM_SHIFT;
                        break;
+               case 833:
+                       if (!(community->features & PINCTRL_FEATURE_1K_PD)) {
+                               ret = -EINVAL;
+                               break;
+                       }
+                       value |= PADCFG1_TERM_833 << PADCFG1_TERM_SHIFT;
+                       break;
                default:
                        ret = -EINVAL;
                }
index 9a760f5cd7ed53c89bf5165733a0c2910036ecd9..4aea3e05e8c65745e5275df4a3f0348865da6405 100644 (file)
@@ -156,7 +156,7 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
                        pin_reg |= BIT(DB_TMR_OUT_UNIT_OFF);
                        pin_reg &= ~BIT(DB_TMR_LARGE_OFF);
                } else if (debounce < 250000) {
-                       time = debounce / 15600;
+                       time = debounce / 15625;
                        pin_reg |= time & DB_TMR_OUT_MASK;
                        pin_reg &= ~BIT(DB_TMR_OUT_UNIT_OFF);
                        pin_reg |= BIT(DB_TMR_LARGE_OFF);
@@ -166,14 +166,14 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
                        pin_reg |= BIT(DB_TMR_OUT_UNIT_OFF);
                        pin_reg |= BIT(DB_TMR_LARGE_OFF);
                } else {
-                       pin_reg &= ~DB_CNTRl_MASK;
+                       pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF);
                        ret = -EINVAL;
                }
        } else {
                pin_reg &= ~BIT(DB_TMR_OUT_UNIT_OFF);
                pin_reg &= ~BIT(DB_TMR_LARGE_OFF);
                pin_reg &= ~DB_TMR_OUT_MASK;
-               pin_reg &= ~DB_CNTRl_MASK;
+               pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF);
        }
        writel(pin_reg, gpio_dev->base + offset * 4);
        raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
index c8e50a58a5e53d42fdee54d95eb200d2976f292a..621909b01debd79d4eb0923fa48e314d747cc237 100644 (file)
@@ -635,44 +635,44 @@ static int jz4770_uart3_data_pins[] = { 0x6c, 0x85, };
 static int jz4770_uart3_hwflow_pins[] = { 0x88, 0x89, };
 static int jz4770_ssi0_dt_a_pins[] = { 0x15, };
 static int jz4770_ssi0_dt_b_pins[] = { 0x35, };
-static int jz4770_ssi0_dt_d_pins[] = { 0x55, };
-static int jz4770_ssi0_dt_e_pins[] = { 0x71, };
+static int jz4770_ssi0_dt_d_pins[] = { 0x75, };
+static int jz4770_ssi0_dt_e_pins[] = { 0x91, };
 static int jz4770_ssi0_dr_a_pins[] = { 0x14, };
 static int jz4770_ssi0_dr_b_pins[] = { 0x34, };
-static int jz4770_ssi0_dr_d_pins[] = { 0x54, };
-static int jz4770_ssi0_dr_e_pins[] = { 0x6e, };
+static int jz4770_ssi0_dr_d_pins[] = { 0x74, };
+static int jz4770_ssi0_dr_e_pins[] = { 0x8e, };
 static int jz4770_ssi0_clk_a_pins[] = { 0x12, };
 static int jz4770_ssi0_clk_b_pins[] = { 0x3c, };
-static int jz4770_ssi0_clk_d_pins[] = { 0x58, };
-static int jz4770_ssi0_clk_e_pins[] = { 0x6f, };
+static int jz4770_ssi0_clk_d_pins[] = { 0x78, };
+static int jz4770_ssi0_clk_e_pins[] = { 0x8f, };
 static int jz4770_ssi0_gpc_b_pins[] = { 0x3e, };
-static int jz4770_ssi0_gpc_d_pins[] = { 0x56, };
-static int jz4770_ssi0_gpc_e_pins[] = { 0x73, };
+static int jz4770_ssi0_gpc_d_pins[] = { 0x76, };
+static int jz4770_ssi0_gpc_e_pins[] = { 0x93, };
 static int jz4770_ssi0_ce0_a_pins[] = { 0x13, };
 static int jz4770_ssi0_ce0_b_pins[] = { 0x3d, };
-static int jz4770_ssi0_ce0_d_pins[] = { 0x59, };
-static int jz4770_ssi0_ce0_e_pins[] = { 0x70, };
+static int jz4770_ssi0_ce0_d_pins[] = { 0x79, };
+static int jz4770_ssi0_ce0_e_pins[] = { 0x90, };
 static int jz4770_ssi0_ce1_b_pins[] = { 0x3f, };
-static int jz4770_ssi0_ce1_d_pins[] = { 0x57, };
-static int jz4770_ssi0_ce1_e_pins[] = { 0x72, };
+static int jz4770_ssi0_ce1_d_pins[] = { 0x77, };
+static int jz4770_ssi0_ce1_e_pins[] = { 0x92, };
 static int jz4770_ssi1_dt_b_pins[] = { 0x35, };
-static int jz4770_ssi1_dt_d_pins[] = { 0x55, };
-static int jz4770_ssi1_dt_e_pins[] = { 0x71, };
+static int jz4770_ssi1_dt_d_pins[] = { 0x75, };
+static int jz4770_ssi1_dt_e_pins[] = { 0x91, };
 static int jz4770_ssi1_dr_b_pins[] = { 0x34, };
-static int jz4770_ssi1_dr_d_pins[] = { 0x54, };
-static int jz4770_ssi1_dr_e_pins[] = { 0x6e, };
+static int jz4770_ssi1_dr_d_pins[] = { 0x74, };
+static int jz4770_ssi1_dr_e_pins[] = { 0x8e, };
 static int jz4770_ssi1_clk_b_pins[] = { 0x3c, };
-static int jz4770_ssi1_clk_d_pins[] = { 0x58, };
-static int jz4770_ssi1_clk_e_pins[] = { 0x6f, };
+static int jz4770_ssi1_clk_d_pins[] = { 0x78, };
+static int jz4770_ssi1_clk_e_pins[] = { 0x8f, };
 static int jz4770_ssi1_gpc_b_pins[] = { 0x3e, };
-static int jz4770_ssi1_gpc_d_pins[] = { 0x56, };
-static int jz4770_ssi1_gpc_e_pins[] = { 0x73, };
+static int jz4770_ssi1_gpc_d_pins[] = { 0x76, };
+static int jz4770_ssi1_gpc_e_pins[] = { 0x93, };
 static int jz4770_ssi1_ce0_b_pins[] = { 0x3d, };
-static int jz4770_ssi1_ce0_d_pins[] = { 0x59, };
-static int jz4770_ssi1_ce0_e_pins[] = { 0x70, };
+static int jz4770_ssi1_ce0_d_pins[] = { 0x79, };
+static int jz4770_ssi1_ce0_e_pins[] = { 0x90, };
 static int jz4770_ssi1_ce1_b_pins[] = { 0x3f, };
-static int jz4770_ssi1_ce1_d_pins[] = { 0x57, };
-static int jz4770_ssi1_ce1_e_pins[] = { 0x72, };
+static int jz4770_ssi1_ce1_d_pins[] = { 0x77, };
+static int jz4770_ssi1_ce1_e_pins[] = { 0x92, };
 static int jz4770_mmc0_1bit_a_pins[] = { 0x12, 0x13, 0x14, };
 static int jz4770_mmc0_4bit_a_pins[] = { 0x15, 0x16, 0x17, };
 static int jz4770_mmc0_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
@@ -1050,35 +1050,35 @@ static int jz4780_ssi0_dt_a_19_pins[] = { 0x13, };
 static int jz4780_ssi0_dt_a_21_pins[] = { 0x15, };
 static int jz4780_ssi0_dt_a_28_pins[] = { 0x1c, };
 static int jz4780_ssi0_dt_b_pins[] = { 0x3d, };
-static int jz4780_ssi0_dt_d_pins[] = { 0x59, };
+static int jz4780_ssi0_dt_d_pins[] = { 0x79, };
 static int jz4780_ssi0_dr_a_20_pins[] = { 0x14, };
 static int jz4780_ssi0_dr_a_27_pins[] = { 0x1b, };
 static int jz4780_ssi0_dr_b_pins[] = { 0x34, };
-static int jz4780_ssi0_dr_d_pins[] = { 0x54, };
+static int jz4780_ssi0_dr_d_pins[] = { 0x74, };
 static int jz4780_ssi0_clk_a_pins[] = { 0x12, };
 static int jz4780_ssi0_clk_b_5_pins[] = { 0x25, };
 static int jz4780_ssi0_clk_b_28_pins[] = { 0x3c, };
-static int jz4780_ssi0_clk_d_pins[] = { 0x58, };
+static int jz4780_ssi0_clk_d_pins[] = { 0x78, };
 static int jz4780_ssi0_gpc_b_pins[] = { 0x3e, };
-static int jz4780_ssi0_gpc_d_pins[] = { 0x56, };
+static int jz4780_ssi0_gpc_d_pins[] = { 0x76, };
 static int jz4780_ssi0_ce0_a_23_pins[] = { 0x17, };
 static int jz4780_ssi0_ce0_a_25_pins[] = { 0x19, };
 static int jz4780_ssi0_ce0_b_pins[] = { 0x3f, };
-static int jz4780_ssi0_ce0_d_pins[] = { 0x57, };
+static int jz4780_ssi0_ce0_d_pins[] = { 0x77, };
 static int jz4780_ssi0_ce1_b_pins[] = { 0x35, };
-static int jz4780_ssi0_ce1_d_pins[] = { 0x55, };
+static int jz4780_ssi0_ce1_d_pins[] = { 0x75, };
 static int jz4780_ssi1_dt_b_pins[] = { 0x3d, };
-static int jz4780_ssi1_dt_d_pins[] = { 0x59, };
+static int jz4780_ssi1_dt_d_pins[] = { 0x79, };
 static int jz4780_ssi1_dr_b_pins[] = { 0x34, };
-static int jz4780_ssi1_dr_d_pins[] = { 0x54, };
+static int jz4780_ssi1_dr_d_pins[] = { 0x74, };
 static int jz4780_ssi1_clk_b_pins[] = { 0x3c, };
-static int jz4780_ssi1_clk_d_pins[] = { 0x58, };
+static int jz4780_ssi1_clk_d_pins[] = { 0x78, };
 static int jz4780_ssi1_gpc_b_pins[] = { 0x3e, };
-static int jz4780_ssi1_gpc_d_pins[] = { 0x56, };
+static int jz4780_ssi1_gpc_d_pins[] = { 0x76, };
 static int jz4780_ssi1_ce0_b_pins[] = { 0x3f, };
-static int jz4780_ssi1_ce0_d_pins[] = { 0x57, };
+static int jz4780_ssi1_ce0_d_pins[] = { 0x77, };
 static int jz4780_ssi1_ce1_b_pins[] = { 0x35, };
-static int jz4780_ssi1_ce1_d_pins[] = { 0x55, };
+static int jz4780_ssi1_ce1_d_pins[] = { 0x75, };
 static int jz4780_mmc0_8bit_a_pins[] = { 0x04, 0x05, 0x06, 0x07, 0x18, };
 static int jz4780_i2c3_pins[] = { 0x6a, 0x6b, };
 static int jz4780_i2c4_e_pins[] = { 0x8c, 0x8d, };
index 1f47a661b0a79d45afe06652d9d512b0895d34be..9ae10318f6f35905e26111209b02e7bebcfd8216 100644 (file)
@@ -119,13 +119,15 @@ static int mcp23s08_spi_regmap_init(struct mcp23s08 *mcp, struct device *dev,
                return -EINVAL;
        }
 
-       copy = devm_kmemdup(dev, &config, sizeof(config), GFP_KERNEL);
+       copy = devm_kmemdup(dev, config, sizeof(*config), GFP_KERNEL);
        if (!copy)
                return -ENOMEM;
 
        copy->name = name;
 
        mcp->regmap = devm_regmap_init(dev, &mcp23sxx_spi_regmap, mcp, copy);
+       if (IS_ERR(mcp->regmap))
+               dev_err(dev, "regmap init failed for %s\n", mcp->chip.label);
        return PTR_ERR_OR_ZERO(mcp->regmap);
 }
 
index 0401c1da79dd0cea48a301121f984d785f74091d..aa1a1c850d057425a02d1806184e235505f670f9 100644 (file)
@@ -3155,7 +3155,9 @@ static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
        if (!bank->domain)
                return -ENXIO;
 
+       clk_enable(bank->clk);
        virq = irq_create_mapping(bank->domain, offset);
+       clk_disable(bank->clk);
 
        return (virq) ? : -ENXIO;
 }
@@ -3194,7 +3196,7 @@ static void rockchip_irq_demux(struct irq_desc *desc)
 
                irq = __ffs(pend);
                pend &= ~BIT(irq);
-               virq = irq_linear_revmap(bank->domain, irq);
+               virq = irq_find_mapping(bank->domain, irq);
 
                if (!virq) {
                        dev_err(bank->drvdata->dev, "unmapped irq %d\n", irq);
@@ -3373,7 +3375,7 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
        unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
        struct irq_chip_generic *gc;
        int ret;
-       int i, j;
+       int i;
 
        for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
                if (!bank->valid) {
@@ -3400,7 +3402,7 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
 
                ret = irq_alloc_domain_generic_chips(bank->domain, 32, 1,
                                         "rockchip_gpio_irq", handle_level_irq,
-                                        clr, 0, IRQ_GC_INIT_MASK_CACHE);
+                                        clr, 0, 0);
                if (ret) {
                        dev_err(&pdev->dev, "could not alloc generic chips for bank %s\n",
                                bank->name);
@@ -3409,14 +3411,6 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
                        continue;
                }
 
-               /*
-                * Linux assumes that all interrupts start out disabled/masked.
-                * Our driver only uses the concept of masked and always keeps
-                * things enabled, so for us that's all masked and all enabled.
-                */
-               writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTMASK);
-               writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTEN);
-
                gc = irq_get_domain_generic_chip(bank->domain, 0);
                gc->reg_base = bank->reg_base;
                gc->private = bank;
@@ -3433,13 +3427,17 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
                gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type;
                gc->wake_enabled = IRQ_MSK(bank->nr_pins);
 
+               /*
+                * Linux assumes that all interrupts start out disabled/masked.
+                * Our driver only uses the concept of masked and always keeps
+                * things enabled, so for us that's all masked and all enabled.
+                */
+               writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTMASK);
+               writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTEN);
+               gc->mask_cache = 0xffffffff;
+
                irq_set_chained_handler_and_data(bank->irq,
                                                 rockchip_irq_demux, bank);
-
-               /* map the gpio irqs here, when the clock is still running */
-               for (j = 0 ; j < 32 ; j++)
-                       irq_create_mapping(bank->domain, j);
-
                clk_disable(bank->clk);
        }
 
index c4bcda90aac4a79eca80427bb33b5af86a4e1e84..77a25bdf0da70a3ff28c54c8c2a82a12a67a1067 100644 (file)
@@ -815,21 +815,14 @@ static void msm_gpio_irq_clear_unmask(struct irq_data *d, bool status_clear)
 
 static void msm_gpio_irq_enable(struct irq_data *d)
 {
-       /*
-        * Clear the interrupt that may be pending before we enable
-        * the line.
-        * This is especially a problem with the GPIOs routed to the
-        * PDC. These GPIOs are direct-connect interrupts to the GIC.
-        * Disabling the interrupt line at the PDC does not prevent
-        * the interrupt from being latched at the GIC. The state at
-        * GIC needs to be cleared before enabling.
-        */
-       if (d->parent_data) {
-               irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, 0);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
+
+       if (d->parent_data)
                irq_chip_enable_parent(d);
-       }
 
-       msm_gpio_irq_clear_unmask(d, true);
+       if (!test_bit(d->hwirq, pctrl->skip_wake_irqs))
+               msm_gpio_irq_clear_unmask(d, true);
 }
 
 static void msm_gpio_irq_disable(struct irq_data *d)
@@ -1104,6 +1097,19 @@ static int msm_gpio_irq_reqres(struct irq_data *d)
                ret = -EINVAL;
                goto out;
        }
+
+       /*
+        * Clear the interrupt that may be pending before we enable
+        * the line.
+        * This is especially a problem with the GPIOs routed to the
+        * PDC. These GPIOs are direct-connect interrupts to the GIC.
+        * Disabling the interrupt line at the PDC does not prevent
+        * the interrupt from being latched at the GIC. The state at
+        * GIC needs to be cleared before enabling.
+        */
+       if (d->parent_data && test_bit(d->hwirq, pctrl->skip_wake_irqs))
+               irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, 0);
+
        return 0;
 out:
        module_put(gc->owner);
index 826df0d637eaadab963071240c1102887c9e6451..af144e724bd9c61e2ce9045b1e04e4b3d55935ed 100644 (file)
@@ -1313,6 +1313,22 @@ static const struct msm_pingroup sm8250_groups[] = {
        [183] = SDC_PINGROUP(sdc2_data, 0xb7000, 9, 0),
 };
 
+static const struct msm_gpio_wakeirq_map sm8250_pdc_map[] = {
+       { 0, 79 }, { 1, 84 }, { 2, 80 }, { 3, 82 }, { 4, 107 }, { 7, 43 },
+       { 11, 42 }, { 14, 44 }, { 15, 52 }, { 19, 67 }, { 23, 68 }, { 24, 105 },
+       { 27, 92 }, { 28, 106 }, { 31, 69 }, { 35, 70 }, { 39, 37 },
+       { 40, 108 }, { 43, 71 }, { 45, 72 }, { 47, 83 }, { 51, 74 }, { 55, 77 },
+       { 59, 78 }, { 63, 75 }, { 64, 81 }, { 65, 87 }, { 66, 88 }, { 67, 89 },
+       { 68, 54 }, { 70, 85 }, { 77, 46 }, { 80, 90 }, { 81, 91 }, { 83, 97 },
+       { 84, 98 }, { 86, 99 }, { 87, 100 }, { 88, 101 }, { 89, 102 },
+       { 92, 103 }, { 93, 104 }, { 100, 53 }, { 103, 47 }, { 104, 48 },
+       { 108, 49 }, { 109, 94 }, { 110, 95 }, { 111, 96 }, { 112, 55 },
+       { 113, 56 }, { 118, 50 }, { 121, 51 }, { 122, 57 }, { 123, 58 },
+       { 124, 45 }, { 126, 59 }, { 128, 76 }, { 129, 86 }, { 132, 93 },
+       { 133, 65 }, { 134, 66 }, { 136, 62 }, { 137, 63 }, { 138, 64 },
+       { 142, 60 }, { 143, 61 }
+};
+
 static const struct msm_pinctrl_soc_data sm8250_pinctrl = {
        .pins = sm8250_pins,
        .npins = ARRAY_SIZE(sm8250_pins),
@@ -1323,6 +1339,8 @@ static const struct msm_pinctrl_soc_data sm8250_pinctrl = {
        .ngpios = 181,
        .tiles = sm8250_tiles,
        .ntiles = ARRAY_SIZE(sm8250_tiles),
+       .wakeirq_map = sm8250_pdc_map,
+       .nwakeirq_map = ARRAY_SIZE(sm8250_pdc_map),
 };
 
 static int sm8250_pinctrl_probe(struct platform_device *pdev)
index 49f4b73be513f515af3838e4af451c2071e945a7..5592a929b5935d1190ce58319a08d4b8a9880a12 100644 (file)
@@ -111,6 +111,7 @@ static const struct key_entry acer_wmi_keymap[] __initconst = {
        {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */
        {KE_IGNORE, 0x81, {KEY_SLEEP} },
        {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad Toggle */
+       {KE_IGNORE, 0x84, {KEY_KBDILLUMTOGGLE} }, /* Automatic Keyboard background light toggle */
        {KE_KEY, KEY_TOUCHPAD_ON, {KEY_TOUCHPAD_ON} },
        {KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} },
        {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} },
index f5901b0b07cd89fbb182e82eedbd253945a58227..0419c8001fe33f7cecb41cf850e16f973e895683 100644 (file)
@@ -206,6 +206,12 @@ static const struct dmi_system_id dmi_switches_allow_list[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "HP Stream x360 Convertible PC 11"),
                },
        },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion 13 x360 PC"),
+               },
+       },
        {} /* Array terminator */
 };
 
index e3810675090ac93f205a0d2025ec4389cc94cf52..c404706379d92afcf8fdc80d144e45be20daf427 100644 (file)
@@ -3218,7 +3218,14 @@ static int hotkey_init_tablet_mode(void)
 
                in_tablet_mode = hotkey_gmms_get_tablet_mode(res,
                                                             &has_tablet_mode);
-               if (has_tablet_mode)
+               /*
+                * The Yoga 11e series has 2 accelerometers described by a
+                * BOSC0200 ACPI node. This setup relies on a Windows service
+                * which calls special ACPI methods on this node to report
+                * the laptop/tent/tablet mode to the EC. The bmc150 iio driver
+                * does not support this, so skip the hotkey on these models.
+                */
+               if (has_tablet_mode && !acpi_dev_present("BOSC0200", "1", -1))
                        tp_features.hotkey_tablet = TP_HOTKEY_TABLET_USES_GMMS;
                type = "GMMS";
        } else if (acpi_evalf(hkey_handle, &res, "MHKG", "qd")) {
@@ -4228,6 +4235,7 @@ static void hotkey_resume(void)
                pr_err("error while attempting to reset the event firmware interface\n");
 
        tpacpi_send_radiosw_update();
+       tpacpi_input_send_tabletsw();
        hotkey_tablet_mode_notify_change();
        hotkey_wakeup_reason_notify_change();
        hotkey_wakeup_hotunplug_complete_notify_change();
@@ -8776,6 +8784,8 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
        TPACPI_Q_LNV3('N', '2', 'C', TPACPI_FAN_2CTL),  /* P52 / P72 */
        TPACPI_Q_LNV3('N', '2', 'E', TPACPI_FAN_2CTL),  /* P1 / X1 Extreme (1st gen) */
        TPACPI_Q_LNV3('N', '2', 'O', TPACPI_FAN_2CTL),  /* P1 / X1 Extreme (2nd gen) */
+       TPACPI_Q_LNV3('N', '2', 'V', TPACPI_FAN_2CTL),  /* P1 / X1 Extreme (3nd gen) */
+       TPACPI_Q_LNV3('N', '3', '0', TPACPI_FAN_2CTL),  /* P15 (1st gen) / P15v (1st gen) */
 };
 
 static int __init fan_init(struct ibm_init_struct *iibm)
@@ -9703,6 +9713,7 @@ static const struct tpacpi_quirk battery_quirk_table[] __initconst = {
        TPACPI_Q_LNV3('R', '0', 'B', true), /* Thinkpad 11e gen 3 */
        TPACPI_Q_LNV3('R', '0', 'C', true), /* Thinkpad 13 */
        TPACPI_Q_LNV3('R', '0', 'J', true), /* Thinkpad 13 gen 2 */
+       TPACPI_Q_LNV3('R', '0', 'K', true), /* Thinkpad 11e gen 4 celeron BIOS */
 };
 
 static int __init tpacpi_battery_init(struct ibm_init_struct *ibm)
index e557d757c64708f6ebef5b6411c7917679ab6c86..fa7232ad8c3952cb3067bf669fedb5a31538ac8e 100644 (file)
@@ -1478,7 +1478,7 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf,
        struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file));
        char *buffer;
        char *cmd;
-       int lcd_out, crt_out, tv_out;
+       int lcd_out = -1, crt_out = -1, tv_out = -1;
        int remain = count;
        int value;
        int ret;
@@ -1510,7 +1510,6 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf,
 
        kfree(cmd);
 
-       lcd_out = crt_out = tv_out = -1;
        ret = get_video_status(dev, &video_out);
        if (!ret) {
                unsigned int new_video_out = video_out;
index dda60f89c9512390ea299500b957e479f2571953..5783139d0a1198abcaccf112a955ee14398ed243 100644 (file)
@@ -295,6 +295,21 @@ static const struct ts_dmi_data irbis_tw90_data = {
        .properties     = irbis_tw90_props,
 };
 
+static const struct property_entry irbis_tw118_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 20),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 30),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1960),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1510),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-irbis-tw118.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       { }
+};
+
+static const struct ts_dmi_data irbis_tw118_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = irbis_tw118_props,
+};
+
 static const struct property_entry itworks_tw891_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-min-x", 1),
        PROPERTY_ENTRY_U32("touchscreen-min-y", 5),
@@ -623,6 +638,23 @@ static const struct ts_dmi_data pov_mobii_wintab_p1006w_v10_data = {
        .properties     = pov_mobii_wintab_p1006w_v10_props,
 };
 
+static const struct property_entry predia_basic_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 3),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 10),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1728),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1144),
+       PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-predia-basic.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
+       { }
+};
+
+static const struct ts_dmi_data predia_basic_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = predia_basic_props,
+};
+
 static const struct property_entry schneider_sct101ctm_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1715),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
@@ -936,6 +968,14 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "TW90"),
                },
        },
+       {
+               /* Irbis TW118 */
+               .driver_data = (void *)&irbis_tw118_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "IRBIS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TW118"),
+               },
+       },
        {
                /* I.T.Works TW891 */
                .driver_data = (void *)&itworks_tw891_data,
@@ -1109,6 +1149,16 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
                        DMI_MATCH(DMI_BIOS_DATE, "10/24/2014"),
                },
        },
+       {
+               /* Predia Basic tablet) */
+               .driver_data = (void *)&predia_basic_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "CherryTrail"),
+                       /* Above matches are too generic, add bios-version match */
+                       DMI_MATCH(DMI_BIOS_VERSION, "Mx.WT107.KUBNGEA"),
+               },
+       },
        {
                /* Point of View mobii wintab p800w (v2.1) */
                .driver_data = (void *)&pov_mobii_wintab_p800w_v21_data,
index 3bf18d7189750f2970753aded98930b03f068621..a50ab002e9e41c7f3b2fcc5026777a24c9fdec21 100644 (file)
@@ -51,7 +51,7 @@ static void pnp_remove_protocol(struct pnp_protocol *protocol)
 }
 
 /**
- * pnp_protocol_register - adds a pnp protocol to the pnp layer
+ * pnp_register_protocol - adds a pnp protocol to the pnp layer
  * @protocol: pointer to the corresponding pnp_protocol structure
  *
  *  Ex protocols: ISAPNP, PNPBIOS, etc
@@ -91,7 +91,7 @@ int pnp_register_protocol(struct pnp_protocol *protocol)
 }
 
 /**
- * pnp_protocol_unregister - removes a pnp protocol from the pnp layer
+ * pnp_unregister_protocol - removes a pnp protocol from the pnp layer
  * @protocol: pointer to the corresponding pnp_protocol structure
  */
 void pnp_unregister_protocol(struct pnp_protocol *protocol)
index 0b2830efc574993ea22dd3959b6196710f009295..70d6d52bc1e2175b38397f79ee3c58a552ab1b97 100644 (file)
@@ -620,7 +620,7 @@ static u64 rapl_unit_xlate(struct rapl_domain *rd, enum unit_type type,
        case ARBITRARY_UNIT:
        default:
                return value;
-       };
+       }
 
        if (to_raw)
                return div64_u64(value, units) * scale;
index f808c5fa9838ce3b7cd8272b27c1aa38841c9f90..3f0b8e2ef3d46b88f2dddda3ef5a9b912483ec59 100644 (file)
@@ -367,9 +367,9 @@ static void create_power_zone_common_attributes(
                                        &dev_attr_max_energy_range_uj.attr;
        if (power_zone->ops->get_energy_uj) {
                if (power_zone->ops->reset_energy_uj)
-                       dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUGO;
+                       dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUSR;
                else
-                       dev_attr_energy_uj.attr.mode = S_IRUGO;
+                       dev_attr_energy_uj.attr.mode = S_IRUSR;
                power_zone->zone_dev_attrs[count++] =
                                        &dev_attr_energy_uj.attr;
        }
index e020faff7da53199875467c50ed9dda27c8dac5c..663255774c0b08adedac00d8517f1de6a1ab51ab 100644 (file)
@@ -103,43 +103,26 @@ static int timespec_to_char_array(struct timespec64 const *ts,
        return 0;
 }
 
-static int idtcm_strverscmp(const char *ver1, const char *ver2)
+static int idtcm_strverscmp(const char *version1, const char *version2)
 {
-       u8 num1;
-       u8 num2;
-       int result = 0;
-
-       /* loop through each level of the version string */
-       while (result == 0) {
-               /* extract leading version numbers */
-               if (kstrtou8(ver1, 10, &num1) < 0)
-                       return -1;
+       u8 ver1[3], ver2[3];
+       int i;
 
-               if (kstrtou8(ver2, 10, &num2) < 0)
-                       return -1;
+       if (sscanf(version1, "%hhu.%hhu.%hhu",
+                  &ver1[0], &ver1[1], &ver1[2]) != 3)
+               return -1;
+       if (sscanf(version2, "%hhu.%hhu.%hhu",
+                  &ver2[0], &ver2[1], &ver2[2]) != 3)
+               return -1;
 
-               /* if numbers differ, then set the result */
-               if (num1 < num2)
-                       result = -1;
-               else if (num1 > num2)
-                       result = 1;
-               else {
-                       /* if numbers are the same, go to next level */
-                       ver1 = strchr(ver1, '.');
-                       ver2 = strchr(ver2, '.');
-                       if (!ver1 && !ver2)
-                               break;
-                       else if (!ver1)
-                               result = -1;
-                       else if (!ver2)
-                               result = 1;
-                       else {
-                               ver1++;
-                               ver2++;
-                       }
-               }
+       for (i = 0; i < 3; i++) {
+               if (ver1[i] > ver2[i])
+                       return 1;
+               if (ver1[i] < ver2[i])
+                       return -1;
        }
-       return result;
+
+       return 0;
 }
 
 static int idtcm_xfer_read(struct idtcm *idtcm,
index 5046b6b7fd35be4ef06a9cf3e24b2c0a46ce5026..b4c651fc749cb2281d25b66c456a0e4dbed9688e 100644 (file)
@@ -84,12 +84,14 @@ struct sl28cpld_pwm {
        struct regmap *regmap;
        u32 offset;
 };
+#define sl28cpld_pwm_from_chip(_chip) \
+       container_of(_chip, struct sl28cpld_pwm, pwm_chip)
 
 static void sl28cpld_pwm_get_state(struct pwm_chip *chip,
                                   struct pwm_device *pwm,
                                   struct pwm_state *state)
 {
-       struct sl28cpld_pwm *priv = dev_get_drvdata(chip->dev);
+       struct sl28cpld_pwm *priv = sl28cpld_pwm_from_chip(chip);
        unsigned int reg;
        int prescaler;
 
@@ -118,7 +120,7 @@ static void sl28cpld_pwm_get_state(struct pwm_chip *chip,
 static int sl28cpld_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
                              const struct pwm_state *state)
 {
-       struct sl28cpld_pwm *priv = dev_get_drvdata(chip->dev);
+       struct sl28cpld_pwm *priv = sl28cpld_pwm_from_chip(chip);
        unsigned int cycle, prescaler;
        bool write_duty_cycle_first;
        int ret;
index a4ffd71696da67782f11b3fce1648f60c2cfa8fb..42bbd99a36acff6b44754066700e270cc58f09c5 100644 (file)
@@ -1315,7 +1315,6 @@ static int _regulator_do_enable(struct regulator_dev *rdev);
 /**
  * set_machine_constraints - sets regulator constraints
  * @rdev: regulator source
- * @constraints: constraints to apply
  *
  * Allows platform initialisation code to define and constrain
  * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
@@ -1323,21 +1322,11 @@ static int _regulator_do_enable(struct regulator_dev *rdev);
  * regulator operations to proceed i.e. set_voltage, set_current_limit,
  * set_mode.
  */
-static int set_machine_constraints(struct regulator_dev *rdev,
-       const struct regulation_constraints *constraints)
+static int set_machine_constraints(struct regulator_dev *rdev)
 {
        int ret = 0;
        const struct regulator_ops *ops = rdev->desc->ops;
 
-       if (constraints)
-               rdev->constraints = kmemdup(constraints, sizeof(*constraints),
-                                           GFP_KERNEL);
-       else
-               rdev->constraints = kzalloc(sizeof(*constraints),
-                                           GFP_KERNEL);
-       if (!rdev->constraints)
-               return -ENOMEM;
-
        ret = machine_constraints_voltage(rdev, rdev->constraints);
        if (ret != 0)
                return ret;
@@ -1852,6 +1841,15 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
                }
        }
 
+       if (r == rdev) {
+               dev_err(dev, "Supply for %s (%s) resolved to itself\n",
+                       rdev->desc->name, rdev->supply_name);
+               if (!have_full_constraints())
+                       return -EINVAL;
+               r = dummy_regulator_rdev;
+               get_device(&r->dev);
+       }
+
        /*
         * If the supply's parent device is not the same as the
         * regulator's parent device, then ensure the parent device
@@ -4165,6 +4163,8 @@ int regulator_get_voltage_rdev(struct regulator_dev *rdev)
                ret = rdev->desc->fixed_uV;
        } else if (rdev->supply) {
                ret = regulator_get_voltage_rdev(rdev->supply->rdev);
+       } else if (rdev->supply_name) {
+               return -EPROBE_DEFER;
        } else {
                return -EINVAL;
        }
@@ -5144,7 +5144,6 @@ struct regulator_dev *
 regulator_register(const struct regulator_desc *regulator_desc,
                   const struct regulator_config *cfg)
 {
-       const struct regulation_constraints *constraints = NULL;
        const struct regulator_init_data *init_data;
        struct regulator_config *config = NULL;
        static atomic_t regulator_no = ATOMIC_INIT(-1);
@@ -5283,14 +5282,23 @@ regulator_register(const struct regulator_desc *regulator_desc,
 
        /* set regulator constraints */
        if (init_data)
-               constraints = &init_data->constraints;
+               rdev->constraints = kmemdup(&init_data->constraints,
+                                           sizeof(*rdev->constraints),
+                                           GFP_KERNEL);
+       else
+               rdev->constraints = kzalloc(sizeof(*rdev->constraints),
+                                           GFP_KERNEL);
+       if (!rdev->constraints) {
+               ret = -ENOMEM;
+               goto wash;
+       }
 
        if (init_data && init_data->supply_regulator)
                rdev->supply_name = init_data->supply_regulator;
        else if (regulator_desc->supply_name)
                rdev->supply_name = regulator_desc->supply_name;
 
-       ret = set_machine_constraints(rdev, constraints);
+       ret = set_machine_constraints(rdev);
        if (ret == -EPROBE_DEFER) {
                /* Regulator might be in bypass mode and so needs its supply
                 * to set the constraints */
@@ -5299,7 +5307,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
                 * that is just being created */
                ret = regulator_resolve_supply(rdev);
                if (!ret)
-                       ret = set_machine_constraints(rdev, constraints);
+                       ret = set_machine_constraints(rdev);
                else
                        rdev_dbg(rdev, "unable to resolve supply early: %pe\n",
                                 ERR_PTR(ret));
@@ -5841,13 +5849,14 @@ static int regulator_late_cleanup(struct device *dev, void *data)
        if (rdev->use_count)
                goto unlock;
 
-       /* If we can't read the status assume it's on. */
+       /* If we can't read the status assume it's always on. */
        if (ops->is_enabled)
                enabled = ops->is_enabled(rdev);
        else
                enabled = 1;
 
-       if (!enabled)
+       /* But if reading the status failed, assume that it's off. */
+       if (enabled <= 0)
                goto unlock;
 
        if (have_full_constraints()) {
index 7e8ba9246167c1cc71d0f6dee4e6c0b70f0036e2..01a12cfcea7c6a33288465cebad54edd3cdd41ea 100644 (file)
@@ -836,11 +836,14 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
                 * the switched regulator till yet.
                 */
                if (pfuze_chip->flags & PFUZE_FLAG_DISABLE_SW) {
-                       if (pfuze_chip->regulator_descs[i].sw_reg) {
-                               desc->ops = &pfuze100_sw_disable_regulator_ops;
-                               desc->enable_val = 0x8;
-                               desc->disable_val = 0x0;
-                               desc->enable_time = 500;
+                       if (pfuze_chip->chip_id == PFUZE100 ||
+                               pfuze_chip->chip_id == PFUZE200) {
+                               if (pfuze_chip->regulator_descs[i].sw_reg) {
+                                       desc->ops = &pfuze100_sw_disable_regulator_ops;
+                                       desc->enable_val = 0x8;
+                                       desc->disable_val = 0x0;
+                                       desc->enable_time = 500;
+                               }
                        }
                }
 
index 3e60bff76194801a252529f9338f5df4824a36ef..9f0a4d50cead4091f448aacf564e59d968f7048d 100644 (file)
@@ -342,8 +342,17 @@ static int ti_abb_set_voltage_sel(struct regulator_dev *rdev, unsigned sel)
                return ret;
        }
 
-       /* If data is exactly the same, then just update index, no change */
        info = &abb->info[sel];
+       /*
+        * When Linux kernel is starting up, we are'nt sure of the
+        * Bias configuration that bootloader has configured.
+        * So, we get to know the actual setting the first time
+        * we are asked to transition.
+        */
+       if (abb->current_info_idx == -EINVAL)
+               goto just_set_abb;
+
+       /* If data is exactly the same, then just update index, no change */
        oinfo = &abb->info[abb->current_info_idx];
        if (!memcmp(info, oinfo, sizeof(*info))) {
                dev_dbg(dev, "%s: Same data new idx=%d, old idx=%d\n", __func__,
@@ -351,6 +360,7 @@ static int ti_abb_set_voltage_sel(struct regulator_dev *rdev, unsigned sel)
                goto out;
        }
 
+just_set_abb:
        ret = ti_abb_set_opp(rdev, abb, info);
 
 out:
index eb17fea8075c6f49d47d42e5b692b928f1adeb93..217a7b84abdfaf650744912ce249a877c57006e6 100644 (file)
@@ -2980,6 +2980,12 @@ static int _dasd_requeue_request(struct dasd_ccw_req *cqr)
 
        if (!block)
                return -EINVAL;
+       /*
+        * If the request is an ERP request there is nothing to requeue.
+        * This will be done with the remaining original request.
+        */
+       if (cqr->refers)
+               return 0;
        spin_lock_irq(&cqr->dq->lock);
        req = (struct request *) cqr->callback_data;
        blk_mq_requeue_request(req, false);
index 485cbfcbf06ed866dad7e0b158280d703f28e61c..ef738b42a0926d40aed3720ff6ea7521dd3092e6 100644 (file)
@@ -680,7 +680,10 @@ static int ap_device_probe(struct device *dev)
 {
        struct ap_device *ap_dev = to_ap_dev(dev);
        struct ap_driver *ap_drv = to_ap_drv(dev->driver);
-       int card, queue, devres, drvres, rc;
+       int card, queue, devres, drvres, rc = -ENODEV;
+
+       if (!get_device(dev))
+               return rc;
 
        if (is_queue_dev(dev)) {
                /*
@@ -697,7 +700,7 @@ static int ap_device_probe(struct device *dev)
                mutex_unlock(&ap_perms_mutex);
                drvres = ap_drv->flags & AP_DRIVER_FLAG_DEFAULT;
                if (!!devres != !!drvres)
-                       return -ENODEV;
+                       goto out;
        }
 
        /* Add queue/card to list of active queues/cards */
@@ -718,6 +721,9 @@ static int ap_device_probe(struct device *dev)
                ap_dev->drv = NULL;
        }
 
+out:
+       if (rc)
+               put_device(dev);
        return rc;
 }
 
@@ -744,6 +750,8 @@ static int ap_device_remove(struct device *dev)
                hash_del(&to_ap_queue(dev)->hnode);
        spin_unlock_bh(&ap_queues_lock);
 
+       put_device(dev);
+
        return 0;
 }
 
@@ -1371,6 +1379,8 @@ static inline void ap_scan_domains(struct ap_card *ac)
                                            __func__, ac->id, dom);
                                goto put_dev_and_continue;
                        }
+                       /* get it and thus adjust reference counter */
+                       get_device(dev);
                        if (decfg)
                                AP_DBF_INFO("%s(%d,%d) new (decfg) queue device created\n",
                                            __func__, ac->id, dom);
index 99cb60ea663d95ee3eeef7550db014cac238362d..dd84995049b9173e4db609462345ecbf3824ee8b 100644 (file)
@@ -35,9 +35,6 @@ MODULE_DESCRIPTION("s390 protected key interface");
 #define PROTKEYBLOBBUFSIZE 256 /* protected key buffer size used internal */
 #define MAXAPQNSINLIST 64      /* max 64 apqns within a apqn list */
 
-/* mask of available pckmo subfunctions, fetched once at module init */
-static cpacf_mask_t pckmo_functions;
-
 /*
  * debug feature data and functions
  */
@@ -91,6 +88,9 @@ static int pkey_clr2protkey(u32 keytype,
                            const struct pkey_clrkey *clrkey,
                            struct pkey_protkey *protkey)
 {
+       /* mask of available pckmo subfunctions */
+       static cpacf_mask_t pckmo_functions;
+
        long fc;
        int keysize;
        u8 paramblock[64];
@@ -114,11 +114,13 @@ static int pkey_clr2protkey(u32 keytype,
                return -EINVAL;
        }
 
-       /*
-        * Check if the needed pckmo subfunction is available.
-        * These subfunctions can be enabled/disabled by customers
-        * in the LPAR profile or may even change on the fly.
-        */
+       /* Did we already check for PCKMO ? */
+       if (!pckmo_functions.bytes[0]) {
+               /* no, so check now */
+               if (!cpacf_query(CPACF_PCKMO, &pckmo_functions))
+                       return -ENODEV;
+       }
+       /* check for the pckmo subfunction we need now */
        if (!cpacf_test_func(&pckmo_functions, fc)) {
                DEBUG_ERR("%s pckmo functions not available\n", __func__);
                return -ENODEV;
@@ -2058,7 +2060,7 @@ static struct miscdevice pkey_dev = {
  */
 static int __init pkey_init(void)
 {
-       cpacf_mask_t kmc_functions;
+       cpacf_mask_t func_mask;
 
        /*
         * The pckmo instruction should be available - even if we don't
@@ -2066,15 +2068,15 @@ static int __init pkey_init(void)
         * is also the minimum level for the kmc instructions which
         * are able to work with protected keys.
         */
-       if (!cpacf_query(CPACF_PCKMO, &pckmo_functions))
+       if (!cpacf_query(CPACF_PCKMO, &func_mask))
                return -ENODEV;
 
        /* check for kmc instructions available */
-       if (!cpacf_query(CPACF_KMC, &kmc_functions))
+       if (!cpacf_query(CPACF_KMC, &func_mask))
                return -ENODEV;
-       if (!cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) ||
-           !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) ||
-           !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256))
+       if (!cpacf_test_func(&func_mask, CPACF_KMC_PAES_128) ||
+           !cpacf_test_func(&func_mask, CPACF_KMC_PAES_192) ||
+           !cpacf_test_func(&func_mask, CPACF_KMC_PAES_256))
                return -ENODEV;
 
        pkey_debug_init();
index e342eb86acd1d0f77422e291d2d80426959338ee..33b23884b133fc1d12ebc7f46b33f3bb01277f47 100644 (file)
@@ -157,11 +157,6 @@ int zcrypt_card_register(struct zcrypt_card *zc)
 {
        int rc;
 
-       rc = sysfs_create_group(&zc->card->ap_dev.device.kobj,
-                               &zcrypt_card_attr_group);
-       if (rc)
-               return rc;
-
        spin_lock(&zcrypt_list_lock);
        list_add_tail(&zc->list, &zcrypt_card_list);
        spin_unlock(&zcrypt_list_lock);
@@ -170,6 +165,14 @@ int zcrypt_card_register(struct zcrypt_card *zc)
 
        ZCRYPT_DBF(DBF_INFO, "card=%02x register online=1\n", zc->card->id);
 
+       rc = sysfs_create_group(&zc->card->ap_dev.device.kobj,
+                               &zcrypt_card_attr_group);
+       if (rc) {
+               spin_lock(&zcrypt_list_lock);
+               list_del_init(&zc->list);
+               spin_unlock(&zcrypt_list_lock);
+       }
+
        return rc;
 }
 EXPORT_SYMBOL(zcrypt_card_register);
index 3c207066313cf0f36ab8771c48002e131a924adb..5062eae73d4aa6747451dd9b6a6ea6c24b8b166f 100644 (file)
@@ -180,7 +180,6 @@ int zcrypt_queue_register(struct zcrypt_queue *zq)
                                &zcrypt_queue_attr_group);
        if (rc)
                goto out;
-       get_device(&zq->queue->ap_dev.device);
 
        if (zq->ops->rng) {
                rc = zcrypt_rng_device_add();
@@ -192,7 +191,6 @@ int zcrypt_queue_register(struct zcrypt_queue *zq)
 out_unregister:
        sysfs_remove_group(&zq->queue->ap_dev.device.kobj,
                           &zcrypt_queue_attr_group);
-       put_device(&zq->queue->ap_dev.device);
 out:
        spin_lock(&zcrypt_list_lock);
        list_del_init(&zq->list);
@@ -220,12 +218,10 @@ void zcrypt_queue_unregister(struct zcrypt_queue *zq)
        list_del_init(&zq->list);
        zcrypt_device_count--;
        spin_unlock(&zcrypt_list_lock);
-       zcrypt_card_put(zc);
        if (zq->ops->rng)
                zcrypt_rng_device_remove();
        sysfs_remove_group(&zq->queue->ap_dev.device.kobj,
                           &zcrypt_queue_attr_group);
-       put_device(&zq->queue->ap_dev.device);
-       zcrypt_queue_put(zq);
+       zcrypt_card_put(zc);
 }
 EXPORT_SYMBOL(zcrypt_queue_unregister);
index fe96ca3c88a5a7a8bc38740c1ff9a4403b4c956f..26cc943d2034046e2ef8e956a53dbe46c0228b8d 100644 (file)
@@ -390,7 +390,7 @@ static int ism_move(struct smcd_dev *smcd, u64 dmb_tok, unsigned int idx,
 }
 
 static struct ism_systemeid SYSTEM_EID = {
-       .seid_string = "IBM-SYSZ-IBMSEID00000000",
+       .seid_string = "IBM-SYSZ-ISMSEID00000000",
        .serial_number = "0000",
        .type = "0000",
 };
index f73b4756ed5e625c55a4cc6a5792a3dd5e2611d5..b235393e091caf675ffd193ee52f5d900ec7546c 100644 (file)
@@ -417,10 +417,13 @@ enum qeth_qdio_out_buffer_state {
        QETH_QDIO_BUF_EMPTY,
        /* Filled by driver; owned by hardware in order to be sent. */
        QETH_QDIO_BUF_PRIMED,
-       /* Identified to be pending in TPQ. */
+       /* Discovered by the TX completion code: */
        QETH_QDIO_BUF_PENDING,
-       /* Found in completion queue. */
-       QETH_QDIO_BUF_IN_CQ,
+       /* Finished by the TX completion code: */
+       QETH_QDIO_BUF_NEED_QAOB,
+       /* Received QAOB notification on CQ: */
+       QETH_QDIO_BUF_QAOB_OK,
+       QETH_QDIO_BUF_QAOB_ERROR,
        /* Handled via transfer pending / completion queue. */
        QETH_QDIO_BUF_HANDLED_DELAYED,
 };
index 93c9b30ab17a4a992dd3fd863e955453811faadc..e27319de7b00be04610d6d4f2f427844629e0ecc 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <net/iucv/af_iucv.h>
 #include <net/dsfield.h>
+#include <net/sock.h>
 
 #include <asm/ebcdic.h>
 #include <asm/chpid.h>
@@ -499,17 +500,12 @@ static void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q, int bidx,
 
                }
        }
-       if (forced_cleanup && (atomic_read(&(q->bufs[bidx]->state)) ==
-                                       QETH_QDIO_BUF_HANDLED_DELAYED)) {
-               /* for recovery situations */
-               qeth_init_qdio_out_buf(q, bidx);
-               QETH_CARD_TEXT(q->card, 2, "clprecov");
-       }
 }
 
 static void qeth_qdio_handle_aob(struct qeth_card *card,
                                 unsigned long phys_aob_addr)
 {
+       enum qeth_qdio_out_buffer_state new_state = QETH_QDIO_BUF_QAOB_OK;
        struct qaob *aob;
        struct qeth_qdio_out_buffer *buffer;
        enum iucv_tx_notify notification;
@@ -521,22 +517,6 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
        buffer = (struct qeth_qdio_out_buffer *) aob->user1;
        QETH_CARD_TEXT_(card, 5, "%lx", aob->user1);
 
-       if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED,
-                          QETH_QDIO_BUF_IN_CQ) == QETH_QDIO_BUF_PRIMED) {
-               notification = TX_NOTIFY_OK;
-       } else {
-               WARN_ON_ONCE(atomic_read(&buffer->state) !=
-                                                       QETH_QDIO_BUF_PENDING);
-               atomic_set(&buffer->state, QETH_QDIO_BUF_IN_CQ);
-               notification = TX_NOTIFY_DELAYED_OK;
-       }
-
-       if (aob->aorc != 0)  {
-               QETH_CARD_TEXT_(card, 2, "aorc%02X", aob->aorc);
-               notification = qeth_compute_cq_notification(aob->aorc, 1);
-       }
-       qeth_notify_skbs(buffer->q, buffer, notification);
-
        /* Free dangling allocations. The attached skbs are handled by
         * qeth_cleanup_handled_pending().
         */
@@ -548,7 +528,33 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
                if (data && buffer->is_header[i])
                        kmem_cache_free(qeth_core_header_cache, data);
        }
-       atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED);
+
+       if (aob->aorc) {
+               QETH_CARD_TEXT_(card, 2, "aorc%02X", aob->aorc);
+               new_state = QETH_QDIO_BUF_QAOB_ERROR;
+       }
+
+       switch (atomic_xchg(&buffer->state, new_state)) {
+       case QETH_QDIO_BUF_PRIMED:
+               /* Faster than TX completion code. */
+               notification = qeth_compute_cq_notification(aob->aorc, 0);
+               qeth_notify_skbs(buffer->q, buffer, notification);
+               atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED);
+               break;
+       case QETH_QDIO_BUF_PENDING:
+               /* TX completion code is active and will handle the async
+                * completion for us.
+                */
+               break;
+       case QETH_QDIO_BUF_NEED_QAOB:
+               /* TX completion code is already finished. */
+               notification = qeth_compute_cq_notification(aob->aorc, 1);
+               qeth_notify_skbs(buffer->q, buffer, notification);
+               atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED);
+               break;
+       default:
+               WARN_ON_ONCE(1);
+       }
 
        qdio_release_aob(aob);
 }
@@ -1405,7 +1411,7 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *q,
        skb_queue_walk(&buf->skb_list, skb) {
                QETH_CARD_TEXT_(q->card, 5, "skbn%d", notification);
                QETH_CARD_TEXT_(q->card, 5, "%lx", (long) skb);
-               if (skb->protocol == htons(ETH_P_AF_IUCV) && skb->sk)
+               if (skb->sk && skb->sk->sk_family == PF_IUCV)
                        iucv_sk(skb->sk)->sk_txnotify(skb, notification);
        }
 }
@@ -1416,9 +1422,6 @@ static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error,
        struct qeth_qdio_out_q *queue = buf->q;
        struct sk_buff *skb;
 
-       /* release may never happen from within CQ tasklet scope */
-       WARN_ON_ONCE(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ);
-
        if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING)
                qeth_notify_skbs(queue, buf, TX_NOTIFY_GENERALERROR);
 
@@ -5869,9 +5872,32 @@ static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue,
 
                if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED,
                                                   QETH_QDIO_BUF_PENDING) ==
-                   QETH_QDIO_BUF_PRIMED)
+                   QETH_QDIO_BUF_PRIMED) {
                        qeth_notify_skbs(queue, buffer, TX_NOTIFY_PENDING);
 
+                       /* Handle race with qeth_qdio_handle_aob(): */
+                       switch (atomic_xchg(&buffer->state,
+                                           QETH_QDIO_BUF_NEED_QAOB)) {
+                       case QETH_QDIO_BUF_PENDING:
+                               /* No concurrent QAOB notification. */
+                               break;
+                       case QETH_QDIO_BUF_QAOB_OK:
+                               qeth_notify_skbs(queue, buffer,
+                                                TX_NOTIFY_DELAYED_OK);
+                               atomic_set(&buffer->state,
+                                          QETH_QDIO_BUF_HANDLED_DELAYED);
+                               break;
+                       case QETH_QDIO_BUF_QAOB_ERROR:
+                               qeth_notify_skbs(queue, buffer,
+                                                TX_NOTIFY_DELAYED_GENERALERROR);
+                               atomic_set(&buffer->state,
+                                          QETH_QDIO_BUF_HANDLED_DELAYED);
+                               break;
+                       default:
+                               WARN_ON_ONCE(1);
+                       }
+               }
+
                QETH_CARD_TEXT_(card, 5, "pel%u", bidx);
 
                /* prepare the queue slot for re-use: */
index 28f6dda957363de45ceac0a4a8f19dfa9ceb7d49..79939ba5d523563a66b3f7ee79d8dc7071a9537e 100644 (file)
@@ -985,32 +985,19 @@ static void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
  *     change notification' and thus can support the learning_sync bridgeport
  *     attribute
  *     @card: qeth_card structure pointer
- *
- *     This is a destructive test and must be called before dev2br or
- *     bridgeport address notification is enabled!
  */
 static void qeth_l2_detect_dev2br_support(struct qeth_card *card)
 {
        struct qeth_priv *priv = netdev_priv(card->dev);
        bool dev2br_supported;
-       int rc;
 
        QETH_CARD_TEXT(card, 2, "d2brsup");
        if (!IS_IQD(card))
                return;
 
        /* dev2br requires valid cssid,iid,chid */
-       if (!card->info.ids_valid) {
-               dev2br_supported = false;
-       } else if (css_general_characteristics.enarf) {
-               dev2br_supported = true;
-       } else {
-               /* Old machines don't have the feature bit:
-                * Probe by testing whether a disable succeeds
-                */
-               rc = qeth_l2_pnso(card, PNSO_OC_NET_ADDR_INFO, 0, NULL, NULL);
-               dev2br_supported = !rc;
-       }
+       dev2br_supported = card->info.ids_valid &&
+                          css_general_characteristics.enarf;
        QETH_CARD_TEXT_(card, 2, "D2Bsup%02x", dev2br_supported);
 
        if (dev2br_supported)
@@ -2233,7 +2220,6 @@ static int qeth_l2_set_online(struct qeth_card *card, bool carrier_ok)
        struct net_device *dev = card->dev;
        int rc = 0;
 
-       /* query before bridgeport_notification may be enabled */
        qeth_l2_detect_dev2br_support(card);
 
        mutex_lock(&card->sbp_lock);
index f32da0ca529e004f448c6f9803b9c57b145a6609..308bda2e9c0007a585f7b93613c59cfc00473aa7 100644 (file)
@@ -658,8 +658,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
                                        rcu_read_lock();
                                        list_for_each_entry_rcu(h,
                                                &tmp_pg->dh_list, node) {
-                                               /* h->sdev should always be valid */
-                                               BUG_ON(!h->sdev);
+                                               if (!h->sdev)
+                                                       continue;
                                                h->sdev->access_state = desc[0];
                                        }
                                        rcu_read_unlock();
@@ -705,7 +705,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
                        pg->expiry = 0;
                        rcu_read_lock();
                        list_for_each_entry_rcu(h, &pg->dh_list, node) {
-                               BUG_ON(!h->sdev);
+                               if (!h->sdev)
+                                       continue;
                                h->sdev->access_state =
                                        (pg->state & SCSI_ACCESS_STATE_MASK);
                                if (pg->pref)
@@ -1147,7 +1148,6 @@ static void alua_bus_detach(struct scsi_device *sdev)
        spin_lock(&h->pg_lock);
        pg = rcu_dereference_protected(h->pg, lockdep_is_held(&h->pg_lock));
        rcu_assign_pointer(h->pg, NULL);
-       h->sdev = NULL;
        spin_unlock(&h->pg_lock);
        if (pg) {
                spin_lock_irq(&pg->lock);
@@ -1156,6 +1156,7 @@ static void alua_bus_detach(struct scsi_device *sdev)
                kref_put(&pg->kref, release_port_group);
        }
        sdev->handler_data = NULL;
+       synchronize_rcu();
        kfree(h);
 }
 
index 128583dfccf2079d33cf99d71a4713d5225193b1..c8dd8588f800e08c852030b7580ea9e4ab3a2287 100644 (file)
@@ -445,7 +445,7 @@ static int hisi_sas_task_prep(struct sas_task *task,
                }
        }
 
-       if (scmd) {
+       if (scmd && hisi_hba->shost->nr_hw_queues) {
                unsigned int dq_index;
                u32 blk_tag;
 
index 83ce4f11a58941bd3df70ba946bc9e5ee3a01dd5..8df70c92911dd99d525c9b64f6f79def6d7dfeac 100644 (file)
@@ -8855,7 +8855,7 @@ reinit_after_soft_reset:
        /* hook into SCSI subsystem */
        rc = hpsa_scsi_add_host(h);
        if (rc)
-               goto clean7; /* perf, sg, cmd, irq, shost, pci, lu, aer/h */
+               goto clean8; /* lastlogicals, perf, sg, cmd, irq, shost, pci, lu, aer/h */
 
        /* Monitor the controller for firmware lockups */
        h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL;
@@ -8870,6 +8870,8 @@ reinit_after_soft_reset:
                                HPSA_EVENT_MONITOR_INTERVAL);
        return 0;
 
+clean8: /* lastlogicals, perf, sg, cmd, irq, shost, pci, lu, aer/h */
+       kfree(h->lastlogicals);
 clean7: /* perf, sg, cmd, irq, shost, pci, lu, aer/h */
        hpsa_free_performant_mode(h);
        h->access.set_intr_mask(h, HPSA_INTR_OFF);
index b1f3017b6547a47dee952c333db1bf18404b62ce..29fcc44be2d57f800363a8f8a5cfe98585c89a20 100644 (file)
@@ -806,6 +806,22 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
        spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 }
 
+/**
+ * ibmvscsi_set_request_limit - Set the adapter request_limit in response to
+ * an adapter failure, reset, or SRP Login. Done under host lock to prevent
+ * race with SCSI command submission.
+ * @hostdata:  adapter to adjust
+ * @limit:     new request limit
+ */
+static void ibmvscsi_set_request_limit(struct ibmvscsi_host_data *hostdata, int limit)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(hostdata->host->host_lock, flags);
+       atomic_set(&hostdata->request_limit, limit);
+       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+}
+
 /**
  * ibmvscsi_reset_host - Reset the connection to the server
  * @hostdata:  struct ibmvscsi_host_data to reset
@@ -813,7 +829,7 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
 static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata)
 {
        scsi_block_requests(hostdata->host);
-       atomic_set(&hostdata->request_limit, 0);
+       ibmvscsi_set_request_limit(hostdata, 0);
 
        purge_requests(hostdata, DID_ERROR);
        hostdata->action = IBMVSCSI_HOST_ACTION_RESET;
@@ -1146,13 +1162,13 @@ static void login_rsp(struct srp_event_struct *evt_struct)
                dev_info(hostdata->dev, "SRP_LOGIN_REJ reason %u\n",
                         evt_struct->xfer_iu->srp.login_rej.reason);
                /* Login failed.  */
-               atomic_set(&hostdata->request_limit, -1);
+               ibmvscsi_set_request_limit(hostdata, -1);
                return;
        default:
                dev_err(hostdata->dev, "Invalid login response typecode 0x%02x!\n",
                        evt_struct->xfer_iu->srp.login_rsp.opcode);
                /* Login failed.  */
-               atomic_set(&hostdata->request_limit, -1);
+               ibmvscsi_set_request_limit(hostdata, -1);
                return;
        }
 
@@ -1163,7 +1179,7 @@ static void login_rsp(struct srp_event_struct *evt_struct)
         * This value is set rather than added to request_limit because
         * request_limit could have been set to -1 by this client.
         */
-       atomic_set(&hostdata->request_limit,
+       ibmvscsi_set_request_limit(hostdata,
                   be32_to_cpu(evt_struct->xfer_iu->srp.login_rsp.req_lim_delta));
 
        /* If we had any pending I/Os, kick them */
@@ -1195,13 +1211,13 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata)
        login->req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
                                         SRP_BUF_FORMAT_INDIRECT);
 
-       spin_lock_irqsave(hostdata->host->host_lock, flags);
        /* Start out with a request limit of 0, since this is negotiated in
         * the login request we are just sending and login requests always
         * get sent by the driver regardless of request_limit.
         */
-       atomic_set(&hostdata->request_limit, 0);
+       ibmvscsi_set_request_limit(hostdata, 0);
 
+       spin_lock_irqsave(hostdata->host->host_lock, flags);
        rc = ibmvscsi_send_srp_event(evt_struct, hostdata, login_timeout * 2);
        spin_unlock_irqrestore(hostdata->host->host_lock, flags);
        dev_info(hostdata->dev, "sent SRP login\n");
@@ -1781,7 +1797,7 @@ static void ibmvscsi_handle_crq(struct viosrp_crq *crq,
                return;
        case VIOSRP_CRQ_XPORT_EVENT:    /* Hypervisor telling us the connection is closed */
                scsi_block_requests(hostdata->host);
-               atomic_set(&hostdata->request_limit, 0);
+               ibmvscsi_set_request_limit(hostdata, 0);
                if (crq->format == 0x06) {
                        /* We need to re-setup the interpartition connection */
                        dev_info(hostdata->dev, "Re-enabling adapter!\n");
@@ -2137,12 +2153,12 @@ static void ibmvscsi_do_work(struct ibmvscsi_host_data *hostdata)
        }
 
        hostdata->action = IBMVSCSI_HOST_ACTION_NONE;
+       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 
        if (rc) {
-               atomic_set(&hostdata->request_limit, -1);
+               ibmvscsi_set_request_limit(hostdata, -1);
                dev_err(hostdata->dev, "error after %s\n", action);
        }
-       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 
        scsi_unblock_requests(hostdata->host);
 }
@@ -2226,7 +2242,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        init_waitqueue_head(&hostdata->work_wait_q);
        hostdata->host = host;
        hostdata->dev = dev;
-       atomic_set(&hostdata->request_limit, -1);
+       ibmvscsi_set_request_limit(hostdata, -1);
        hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT;
 
        if (map_persist_bufs(hostdata)) {
index 1e9c3171fa9f44bed8c982f8abaecc8284a764ff..f9314f1393fbd754c94ce5a1ce0a32383378f095 100644 (file)
@@ -533,8 +533,8 @@ static void iscsi_complete_task(struct iscsi_task *task, int state)
        if (conn->task == task)
                conn->task = NULL;
 
-       if (conn->ping_task == task)
-               conn->ping_task = NULL;
+       if (READ_ONCE(conn->ping_task) == task)
+               WRITE_ONCE(conn->ping_task, NULL);
 
        /* release get from queueing */
        __iscsi_put_task(task);
@@ -738,6 +738,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
                                                   task->conn->session->age);
        }
 
+       if (unlikely(READ_ONCE(conn->ping_task) == INVALID_SCSI_TASK))
+               WRITE_ONCE(conn->ping_task, task);
+
        if (!ihost->workq) {
                if (iscsi_prep_mgmt_task(conn, task))
                        goto free_task;
@@ -941,8 +944,11 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
         struct iscsi_nopout hdr;
        struct iscsi_task *task;
 
-       if (!rhdr && conn->ping_task)
-               return -EINVAL;
+       if (!rhdr) {
+               if (READ_ONCE(conn->ping_task))
+                       return -EINVAL;
+               WRITE_ONCE(conn->ping_task, INVALID_SCSI_TASK);
+       }
 
        memset(&hdr, 0, sizeof(struct iscsi_nopout));
        hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
@@ -957,11 +963,12 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
 
        task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
        if (!task) {
+               if (!rhdr)
+                       WRITE_ONCE(conn->ping_task, NULL);
                iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
                return -EIO;
        } else if (!rhdr) {
                /* only track our nops */
-               conn->ping_task = task;
                conn->last_ping = jiffies;
        }
 
@@ -984,7 +991,7 @@ static int iscsi_nop_out_rsp(struct iscsi_task *task,
        struct iscsi_conn *conn = task->conn;
        int rc = 0;
 
-       if (conn->ping_task != task) {
+       if (READ_ONCE(conn->ping_task) != task) {
                /*
                 * If this is not in response to one of our
                 * nops then it must be from userspace.
@@ -1923,7 +1930,7 @@ static void iscsi_start_tx(struct iscsi_conn *conn)
  */
 static int iscsi_has_ping_timed_out(struct iscsi_conn *conn)
 {
-       if (conn->ping_task &&
+       if (READ_ONCE(conn->ping_task) &&
            time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) +
                           (conn->ping_timeout * HZ), jiffies))
                return 1;
@@ -2058,7 +2065,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
         * Checking the transport already or nop from a cmd timeout still
         * running
         */
-       if (conn->ping_task) {
+       if (READ_ONCE(conn->ping_task)) {
                task->have_checked_conn = true;
                rc = BLK_EH_RESET_TIMER;
                goto done;
index 93230cd1982f478780290237939b5acac2d9b690..bb940cbcbb5dd7a6b212f20477d6d13c80d567a7 100644 (file)
@@ -1740,6 +1740,13 @@ _base_irqpoll(struct irq_poll *irqpoll, int budget)
                reply_q->irq_poll_scheduled = false;
                reply_q->irq_line_enable = true;
                enable_irq(reply_q->os_irq);
+               /*
+                * Go for one more round of processing the
+                * reply descriptor post queue incase if HBA
+                * Firmware has posted some reply descriptors
+                * while reenabling the IRQ.
+                */
+               _base_process_reply_queue(reply_q);
        }
 
        return num_entries;
@@ -6452,7 +6459,7 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc)
 
        r = _base_handshake_req_reply_wait(ioc,
            sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request,
-           sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10);
+           sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 30);
 
        if (r != 0) {
                ioc_err(ioc, "%s: handshake failed (r=%d)\n", __func__, r);
index 0f2b681449e64ab2bd5a8c8a4b7f35012458ba77..edd26a2570fa8a6dd19ea4e69afaa819c5d45a18 100644 (file)
@@ -664,7 +664,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
        Mpi26NVMeEncapsulatedRequest_t *nvme_encap_request = NULL;
        struct _pcie_device *pcie_device = NULL;
        u16 smid;
-       u8 timeout;
+       unsigned long timeout;
        u8 issue_reset;
        u32 sz, sz_arg;
        void *psge;
index 1f90051253136bab14683b0e823800ffdaeca449..b7a1dc24db3806fb5c51e38f5fd17b9e0fdff926 100644 (file)
@@ -554,10 +554,12 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport,
 
        fcport = qla_rport->fcport;
 
-       if (!qpair || !fcport || (qpair && !qpair->fw_started) ||
-           (fcport && fcport->deleted))
+       if (!qpair || !fcport)
                return -ENODEV;
 
+       if (!qpair->fw_started || fcport->deleted)
+               return -EBUSY;
+
        vha = fcport->vha;
 
        if (!(fcport->nvme_flag & NVME_FLAG_REGISTERED))
index 84f4416d366fbf25baee1af1f56f4e55d2dc2040..bd8623ee156a6c1962ac2dec41c0696101f0dd6c 100644 (file)
@@ -1001,10 +1001,8 @@ qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked)
 {
        ulong flags = 0;
 
-#ifndef __CHECKER__
        if (!hardware_locked)
                spin_lock_irqsave(&vha->hw->hardware_lock, flags);
-#endif
        if (!vha->hw->mpi_fw_dump) {
                ql_log(ql_log_warn, vha, 0x02f3, "-> mpi_fwdump no buffer\n");
        } else {
@@ -1050,10 +1048,8 @@ qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked)
        }
 
 bailout:
-#ifndef __CHECKER__
        if (!hardware_locked)
                spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
-#endif
 }
 
 void
index f2437a7570ce8b05ea01590dcd5927cf07c92751..9af50e6f94c4c483ea26fc560bc758885b2397ed 100644 (file)
@@ -1714,15 +1714,16 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost)
  */
 static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
 {
-       struct async_scan_data *data;
+       struct async_scan_data *data = NULL;
        unsigned long flags;
 
        if (strncmp(scsi_scan_type, "sync", 4) == 0)
                return NULL;
 
+       mutex_lock(&shost->scan_mutex);
        if (shost->async_scan) {
                shost_printk(KERN_DEBUG, shost, "%s called twice\n", __func__);
-               return NULL;
+               goto err;
        }
 
        data = kmalloc(sizeof(*data), GFP_KERNEL);
@@ -1733,7 +1734,6 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
                goto err;
        init_completion(&data->prev_finished);
 
-       mutex_lock(&shost->scan_mutex);
        spin_lock_irqsave(shost->host_lock, flags);
        shost->async_scan = 1;
        spin_unlock_irqrestore(shost->host_lock, flags);
@@ -1748,6 +1748,7 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
        return data;
 
  err:
+       mutex_unlock(&shost->scan_mutex);
        kfree(data);
        return NULL;
 }
index 0c65fbd41035ea36f7999f46df1d0aaf70492c61..99c8ff81de7465b813429f287db1aefea7bfbd6d 100644 (file)
@@ -1246,6 +1246,11 @@ static void storvsc_on_channel_callback(void *context)
                request = (struct storvsc_cmd_request *)
                        ((unsigned long)desc->trans_id);
 
+               if (hv_pkt_datalen(desc) < sizeof(struct vstor_packet) - vmscsi_size_delta) {
+                       dev_err(&device->device, "Invalid packet len\n");
+                       continue;
+               }
+
                if (request == &stor_device->init_request ||
                    request == &stor_device->reset_request) {
                        memcpy(&request->vstor_packet, packet,
@@ -1994,8 +1999,10 @@ static int storvsc_probe(struct hv_device *device,
                        alloc_ordered_workqueue("storvsc_error_wq_%d",
                                                WQ_MEM_RECLAIM,
                                                host->host_no);
-       if (!host_dev->handle_error_wq)
+       if (!host_dev->handle_error_wq) {
+               ret = -ENOMEM;
                goto err_out2;
+       }
        INIT_WORK(&host_dev->host_scan_work, storvsc_host_scan);
        /* Register the HBA and start the scsi bus scan */
        ret = scsi_add_host(host, &device->device);
index b8f573a0271326413bc72f2153ad115ba0648a6e..0c148fcd24debc4adc3da8fc47a0d16d41ab1e85 100644 (file)
@@ -1294,8 +1294,15 @@ static int ufshcd_devfreq_target(struct device *dev,
        }
        spin_unlock_irqrestore(hba->host->host_lock, irq_flags);
 
+       pm_runtime_get_noresume(hba->dev);
+       if (!pm_runtime_active(hba->dev)) {
+               pm_runtime_put_noidle(hba->dev);
+               ret = -EAGAIN;
+               goto out;
+       }
        start = ktime_get();
        ret = ufshcd_devfreq_scale(hba, scale_up);
+       pm_runtime_put(hba->dev);
 
        trace_ufshcd_profile_clk_scaling(dev_name(hba->dev),
                (scale_up ? "up" : "down"),
@@ -1627,12 +1634,12 @@ start:
                 */
                fallthrough;
        case CLKS_OFF:
-               ufshcd_scsi_block_requests(hba);
                hba->clk_gating.state = REQ_CLKS_ON;
                trace_ufshcd_clk_gating(dev_name(hba->dev),
                                        hba->clk_gating.state);
-               queue_work(hba->clk_gating.clk_gating_workq,
-                          &hba->clk_gating.ungate_work);
+               if (queue_work(hba->clk_gating.clk_gating_workq,
+                              &hba->clk_gating.ungate_work))
+                       ufshcd_scsi_block_requests(hba);
                /*
                 * fall through to check if we should wait for this
                 * work to be done or not.
@@ -2115,10 +2122,20 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
        unsigned long flags;
 
        if (wait_for_completion_timeout(&uic_cmd->done,
-                                       msecs_to_jiffies(UIC_CMD_TIMEOUT)))
+                                       msecs_to_jiffies(UIC_CMD_TIMEOUT))) {
                ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
-       else
+       } else {
                ret = -ETIMEDOUT;
+               dev_err(hba->dev,
+                       "uic cmd 0x%x with arg3 0x%x completion timeout\n",
+                       uic_cmd->command, uic_cmd->argument3);
+
+               if (!uic_cmd->cmd_active) {
+                       dev_err(hba->dev, "%s: UIC cmd has been completed, return the result\n",
+                               __func__);
+                       ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
+               }
+       }
 
        spin_lock_irqsave(hba->host->host_lock, flags);
        hba->active_uic_cmd = NULL;
@@ -2150,6 +2167,7 @@ __ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd,
        if (completion)
                init_completion(&uic_cmd->done);
 
+       uic_cmd->cmd_active = 1;
        ufshcd_dispatch_uic_cmd(hba, uic_cmd);
 
        return 0;
@@ -3181,13 +3199,19 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
        /* Get the length of descriptor */
        ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len);
        if (!buff_len) {
-               dev_err(hba->dev, "%s: Failed to get desc length", __func__);
+               dev_err(hba->dev, "%s: Failed to get desc length\n", __func__);
+               return -EINVAL;
+       }
+
+       if (param_offset >= buff_len) {
+               dev_err(hba->dev, "%s: Invalid offset 0x%x in descriptor IDN 0x%x, length 0x%x\n",
+                       __func__, param_offset, desc_id, buff_len);
                return -EINVAL;
        }
 
        /* Check whether we need temp memory */
        if (param_offset != 0 || param_size < buff_len) {
-               desc_buf = kmalloc(buff_len, GFP_KERNEL);
+               desc_buf = kzalloc(buff_len, GFP_KERNEL);
                if (!desc_buf)
                        return -ENOMEM;
        } else {
@@ -3201,14 +3225,14 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
                                        desc_buf, &buff_len);
 
        if (ret) {
-               dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d",
+               dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d\n",
                        __func__, desc_id, desc_index, param_offset, ret);
                goto out;
        }
 
        /* Sanity check */
        if (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id) {
-               dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header",
+               dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header\n",
                        __func__, desc_buf[QUERY_DESC_DESC_TYPE_OFFSET]);
                ret = -EINVAL;
                goto out;
@@ -3218,12 +3242,12 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
        buff_len = desc_buf[QUERY_DESC_LENGTH_OFFSET];
        ufshcd_update_desc_length(hba, desc_id, desc_index, buff_len);
 
-       /* Check wherher we will not copy more data, than available */
-       if (is_kmalloc && (param_offset + param_size) > buff_len)
-               param_size = buff_len - param_offset;
-
-       if (is_kmalloc)
+       if (is_kmalloc) {
+               /* Make sure we don't copy more data than available */
+               if (param_offset + param_size > buff_len)
+                       param_size = buff_len - param_offset;
                memcpy(param_read_buf, &desc_buf[param_offset], param_size);
+       }
 out:
        if (is_kmalloc)
                kfree(desc_buf);
@@ -3807,10 +3831,18 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
                dev_err(hba->dev,
                        "pwr ctrl cmd 0x%x with mode 0x%x completion timeout\n",
                        cmd->command, cmd->argument3);
+
+               if (!cmd->cmd_active) {
+                       dev_err(hba->dev, "%s: Power Mode Change operation has been completed, go check UPMCRS\n",
+                               __func__);
+                       goto check_upmcrs;
+               }
+
                ret = -ETIMEDOUT;
                goto out;
        }
 
+check_upmcrs:
        status = ufshcd_get_upmcrs(hba);
        if (status != PWR_LOCAL) {
                dev_err(hba->dev,
@@ -4902,11 +4934,14 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
                        ufshcd_get_uic_cmd_result(hba);
                hba->active_uic_cmd->argument3 =
                        ufshcd_get_dme_attr_val(hba);
+               if (!hba->uic_async_done)
+                       hba->active_uic_cmd->cmd_active = 0;
                complete(&hba->active_uic_cmd->done);
                retval = IRQ_HANDLED;
        }
 
        if ((intr_status & UFSHCD_UIC_PWR_MASK) && hba->uic_async_done) {
+               hba->active_uic_cmd->cmd_active = 0;
                complete(hba->uic_async_done);
                retval = IRQ_HANDLED;
        }
@@ -8878,11 +8913,7 @@ int ufshcd_shutdown(struct ufs_hba *hba)
        if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba))
                goto out;
 
-       if (pm_runtime_suspended(hba->dev)) {
-               ret = ufshcd_runtime_resume(hba);
-               if (ret)
-                       goto out;
-       }
+       pm_runtime_get_sync(hba->dev);
 
        ret = ufshcd_suspend(hba, UFS_SHUTDOWN_PM);
 out:
@@ -8906,6 +8937,7 @@ void ufshcd_remove(struct ufs_hba *hba)
        blk_mq_free_tag_set(&hba->tmf_tag_set);
        blk_cleanup_queue(hba->cmd_queue);
        scsi_remove_host(hba->host);
+       destroy_workqueue(hba->eh_wq);
        /* disable interrupts */
        ufshcd_disable_intr(hba, hba->intr_mask);
        ufshcd_hba_stop(hba);
@@ -9206,6 +9238,7 @@ out_remove_scsi_host:
 exit_gating:
        ufshcd_exit_clk_scaling(hba);
        ufshcd_exit_clk_gating(hba);
+       destroy_workqueue(hba->eh_wq);
 out_disable:
        hba->is_irq_enabled = false;
        ufshcd_hba_exit(hba);
index 47eb1430274c6d6f550c07dd016d4c153c35bd15..e0f00a42371c52cda793f5cd4609db0d9bf33eb1 100644 (file)
@@ -64,6 +64,7 @@ enum dev_cmd_type {
  * @argument1: UIC command argument 1
  * @argument2: UIC command argument 2
  * @argument3: UIC command argument 3
+ * @cmd_active: Indicate if UIC command is outstanding
  * @done: UIC command completion
  */
 struct uic_command {
@@ -71,6 +72,7 @@ struct uic_command {
        u32 argument1;
        u32 argument2;
        u32 argument3;
+       int cmd_active;
        struct completion done;
 };
 
index 7b642c330977f60cb9afa1eeaf4399a581f5972d..7f397b4ad878daf381775d093457af6d12402e2d 100644 (file)
@@ -95,7 +95,6 @@ static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int cpu)
 {
        int error;
        struct fsl_mc_device_irq *irq;
-       cpumask_t mask;
 
        irq = dpio_dev->irqs[0];
        error = devm_request_irq(&dpio_dev->dev,
@@ -112,9 +111,7 @@ static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int cpu)
        }
 
        /* set the affinity hint */
-       cpumask_clear(&mask);
-       cpumask_set_cpu(cpu, &mask);
-       if (irq_set_affinity_hint(irq->msi_desc->irq, &mask))
+       if (irq_set_affinity_hint(irq->msi_desc->irq, cpumask_of(cpu)))
                dev_err(&dpio_dev->dev,
                        "irq_set_affinity failed irq %d cpu %d\n",
                        irq->msi_desc->irq, cpu);
index af2126d2b2ff9fbf797b59c14602da94e4a8cc8e..8afb3f45d2637b6749b0f121931ab77a614ffd9d 100644 (file)
@@ -91,7 +91,7 @@ static struct generic_pm_domain *ti_sci_pd_xlate(
        struct genpd_onecell_data *genpd_data = data;
        unsigned int idx = genpdspec->args[0];
 
-       if (genpdspec->args_count < 2)
+       if (genpdspec->args_count != 1 && genpdspec->args_count != 2)
                return ERR_PTR(-EINVAL);
 
        if (idx >= genpd_data->num_domains) {
index 14c9d0133bce7db551fb2178cbb02e078c20b5eb..c028446c746045f0f830a291f9ddda7ce0bad460 100644 (file)
@@ -1327,7 +1327,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
 
        data = of_id->data;
 
-       master = spi_alloc_master(dev, sizeof(struct bcm_qspi));
+       master = devm_spi_alloc_master(dev, sizeof(struct bcm_qspi));
        if (!master) {
                dev_err(dev, "error allocating spi_master\n");
                return -ENOMEM;
@@ -1367,21 +1367,17 @@ int bcm_qspi_probe(struct platform_device *pdev,
 
        if (res) {
                qspi->base[MSPI]  = devm_ioremap_resource(dev, res);
-               if (IS_ERR(qspi->base[MSPI])) {
-                       ret = PTR_ERR(qspi->base[MSPI]);
-                       goto qspi_resource_err;
-               }
+               if (IS_ERR(qspi->base[MSPI]))
+                       return PTR_ERR(qspi->base[MSPI]);
        } else {
-               goto qspi_resource_err;
+               return 0;
        }
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi");
        if (res) {
                qspi->base[BSPI]  = devm_ioremap_resource(dev, res);
-               if (IS_ERR(qspi->base[BSPI])) {
-                       ret = PTR_ERR(qspi->base[BSPI]);
-                       goto qspi_resource_err;
-               }
+               if (IS_ERR(qspi->base[BSPI]))
+                       return PTR_ERR(qspi->base[BSPI]);
                qspi->bspi_mode = true;
        } else {
                qspi->bspi_mode = false;
@@ -1392,18 +1388,14 @@ int bcm_qspi_probe(struct platform_device *pdev,
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cs_reg");
        if (res) {
                qspi->base[CHIP_SELECT]  = devm_ioremap_resource(dev, res);
-               if (IS_ERR(qspi->base[CHIP_SELECT])) {
-                       ret = PTR_ERR(qspi->base[CHIP_SELECT]);
-                       goto qspi_resource_err;
-               }
+               if (IS_ERR(qspi->base[CHIP_SELECT]))
+                       return PTR_ERR(qspi->base[CHIP_SELECT]);
        }
 
        qspi->dev_ids = kcalloc(num_irqs, sizeof(struct bcm_qspi_dev_id),
                                GFP_KERNEL);
-       if (!qspi->dev_ids) {
-               ret = -ENOMEM;
-               goto qspi_resource_err;
-       }
+       if (!qspi->dev_ids)
+               return -ENOMEM;
 
        for (val = 0; val < num_irqs; val++) {
                irq = -1;
@@ -1484,7 +1476,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
        qspi->xfer_mode.addrlen = -1;
        qspi->xfer_mode.hp = -1;
 
-       ret = devm_spi_register_master(&pdev->dev, master);
+       ret = spi_register_master(master);
        if (ret < 0) {
                dev_err(dev, "can't register master\n");
                goto qspi_reg_err;
@@ -1497,8 +1489,6 @@ qspi_reg_err:
        clk_disable_unprepare(qspi->clk);
 qspi_probe_err:
        kfree(qspi->dev_ids);
-qspi_resource_err:
-       spi_master_put(master);
        return ret;
 }
 /* probe function to be called by SoC specific platform driver probe */
@@ -1508,10 +1498,10 @@ int bcm_qspi_remove(struct platform_device *pdev)
 {
        struct bcm_qspi *qspi = platform_get_drvdata(pdev);
 
+       spi_unregister_master(qspi->master);
        bcm_qspi_hw_uninit(qspi);
        clk_disable_unprepare(qspi->clk);
        kfree(qspi->dev_ids);
-       spi_unregister_master(qspi->master);
 
        return 0;
 }
index b87116e9b41368d5bf29c6708b28a8426cec2054..197485f2c2b2235d30cb33c9cf885a50672b264b 100644 (file)
@@ -1193,7 +1193,6 @@ static int bcm2835_spi_setup(struct spi_device *spi)
        struct spi_controller *ctlr = spi->controller;
        struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
        struct gpio_chip *chip;
-       enum gpio_lookup_flags lflags;
        u32 cs;
 
        /*
@@ -1259,21 +1258,9 @@ static int bcm2835_spi_setup(struct spi_device *spi)
        if (!chip)
                return 0;
 
-       /*
-        * Retrieve the corresponding GPIO line used for CS.
-        * The inversion semantics will be handled by the GPIO core
-        * code, so we pass GPIOD_OUT_LOW for "unasserted" and
-        * the correct flag for inversion semantics. The SPI_CS_HIGH
-        * on spi->mode cannot be checked for polarity in this case
-        * as the flag use_gpio_descriptors enforces SPI_CS_HIGH.
-        */
-       if (of_property_read_bool(spi->dev.of_node, "spi-cs-high"))
-               lflags = GPIO_ACTIVE_HIGH;
-       else
-               lflags = GPIO_ACTIVE_LOW;
        spi->cs_gpiod = gpiochip_request_own_desc(chip, 8 - spi->chip_select,
                                                  DRV_NAME,
-                                                 lflags,
+                                                 GPIO_LOOKUP_FLAGS_DEFAULT,
                                                  GPIOD_OUT_LOW);
        if (IS_ERR(spi->cs_gpiod))
                return PTR_ERR(spi->cs_gpiod);
@@ -1291,7 +1278,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
        struct bcm2835_spi *bs;
        int err;
 
-       ctlr = spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs),
+       ctlr = devm_spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs),
                                                  dma_get_cache_alignment()));
        if (!ctlr)
                return -ENOMEM;
@@ -1312,23 +1299,17 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
        bs->ctlr = ctlr;
 
        bs->regs = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(bs->regs)) {
-               err = PTR_ERR(bs->regs);
-               goto out_controller_put;
-       }
+       if (IS_ERR(bs->regs))
+               return PTR_ERR(bs->regs);
 
        bs->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(bs->clk)) {
-               err = dev_err_probe(&pdev->dev, PTR_ERR(bs->clk),
-                                   "could not get clk\n");
-               goto out_controller_put;
-       }
+       if (IS_ERR(bs->clk))
+               return dev_err_probe(&pdev->dev, PTR_ERR(bs->clk),
+                                    "could not get clk\n");
 
        bs->irq = platform_get_irq(pdev, 0);
-       if (bs->irq <= 0) {
-               err = bs->irq ? bs->irq : -ENODEV;
-               goto out_controller_put;
-       }
+       if (bs->irq <= 0)
+               return bs->irq ? bs->irq : -ENODEV;
 
        clk_prepare_enable(bs->clk);
 
@@ -1362,8 +1343,6 @@ out_dma_release:
        bcm2835_dma_release(ctlr, bs);
 out_clk_disable:
        clk_disable_unprepare(bs->clk);
-out_controller_put:
-       spi_controller_put(ctlr);
        return err;
 }
 
index 03b034c15d2beb32d1ec2c450bfa7e8286b13053..1a26865c42f83c594d4fcbb1b049336afcc0db83 100644 (file)
@@ -494,7 +494,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
        unsigned long clk_hz;
        int err;
 
-       master = spi_alloc_master(&pdev->dev, sizeof(*bs));
+       master = devm_spi_alloc_master(&pdev->dev, sizeof(*bs));
        if (!master)
                return -ENOMEM;
 
@@ -524,29 +524,25 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
 
        /* the main area */
        bs->regs = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(bs->regs)) {
-               err = PTR_ERR(bs->regs);
-               goto out_master_put;
-       }
+       if (IS_ERR(bs->regs))
+               return PTR_ERR(bs->regs);
 
        bs->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(bs->clk)) {
                err = PTR_ERR(bs->clk);
                dev_err(&pdev->dev, "could not get clk: %d\n", err);
-               goto out_master_put;
+               return err;
        }
 
        bs->irq = platform_get_irq(pdev, 0);
-       if (bs->irq <= 0) {
-               err = bs->irq ? bs->irq : -ENODEV;
-               goto out_master_put;
-       }
+       if (bs->irq <= 0)
+               return bs->irq ? bs->irq : -ENODEV;
 
        /* this also enables the HW block */
        err = clk_prepare_enable(bs->clk);
        if (err) {
                dev_err(&pdev->dev, "could not prepare clock: %d\n", err);
-               goto out_master_put;
+               return err;
        }
 
        /* just checking if the clock returns a sane value */
@@ -581,8 +577,6 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
 
 out_clk_disable:
        clk_disable_unprepare(bs->clk);
-out_master_put:
-       spi_master_put(master);
        return err;
 }
 
index 40938cf3806d0a8dd4630bce4b3fd7044b861e6a..ba7d40c2922f7ceffccd64ec2a6def928c6d2fd1 100644 (file)
@@ -1260,12 +1260,14 @@ static int cqspi_probe(struct platform_device *pdev)
        /* Obtain QSPI reset control */
        rstc = devm_reset_control_get_optional_exclusive(dev, "qspi");
        if (IS_ERR(rstc)) {
+               ret = PTR_ERR(rstc);
                dev_err(dev, "Cannot get QSPI reset.\n");
                goto probe_reset_failed;
        }
 
        rstc_ocp = devm_reset_control_get_optional_exclusive(dev, "qspi-ocp");
        if (IS_ERR(rstc_ocp)) {
+               ret = PTR_ERR(rstc_ocp);
                dev_err(dev, "Cannot get QSPI OCP reset.\n");
                goto probe_reset_failed;
        }
index 2e50cc0a9291829db61311751c611eb48caf7d2d..c33866f747dbedb590825329f760c63ca893f336 100644 (file)
@@ -357,11 +357,11 @@ static void dw_spi_irq_setup(struct dw_spi *dws)
        dw_writel(dws, DW_SPI_TXFTLR, level);
        dw_writel(dws, DW_SPI_RXFTLR, level - 1);
 
+       dws->transfer_handler = dw_spi_transfer_handler;
+
        imask = SPI_INT_TXEI | SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI |
                SPI_INT_RXFI;
        spi_umask_intr(dws, imask);
-
-       dws->transfer_handler = dw_spi_transfer_handler;
 }
 
 /*
@@ -875,7 +875,8 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
                master->set_cs = dw_spi_set_cs;
        master->transfer_one = dw_spi_transfer_one;
        master->handle_err = dw_spi_handle_err;
-       master->mem_ops = &dws->mem_ops;
+       if (dws->mem_ops.exec_op)
+               master->mem_ops = &dws->mem_ops;
        master->max_speed_hz = dws->max_freq;
        master->dev.of_node = dev->of_node;
        master->dev.fwnode = dev->fwnode;
index 8a440c7078ef92eda3a53226a3f33f97cf473659..3920cd3286d8a7d24c2430b9ec5e3c52f734c822 100644 (file)
@@ -477,7 +477,7 @@ static int fsi_spi_transfer_one_message(struct spi_controller *ctlr,
 
        rc = fsi_spi_check_mux(ctx->fsi, ctx->dev);
        if (rc)
-               return rc;
+               goto error;
 
        list_for_each_entry(transfer, &mesg->transfers, transfer_list) {
                struct fsi_spi_sequence seq;
index 3967afa465f0ec29e29f361216f87640ab474ec7..1a08c1d584abe08b9b068d0217fe765371ece2cf 100644 (file)
@@ -1080,12 +1080,11 @@ MODULE_DEVICE_TABLE(of, fsl_dspi_dt_ids);
 #ifdef CONFIG_PM_SLEEP
 static int dspi_suspend(struct device *dev)
 {
-       struct spi_controller *ctlr = dev_get_drvdata(dev);
-       struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr);
+       struct fsl_dspi *dspi = dev_get_drvdata(dev);
 
        if (dspi->irq)
                disable_irq(dspi->irq);
-       spi_controller_suspend(ctlr);
+       spi_controller_suspend(dspi->ctlr);
        clk_disable_unprepare(dspi->clk);
 
        pinctrl_pm_select_sleep_state(dev);
@@ -1095,8 +1094,7 @@ static int dspi_suspend(struct device *dev)
 
 static int dspi_resume(struct device *dev)
 {
-       struct spi_controller *ctlr = dev_get_drvdata(dev);
-       struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr);
+       struct fsl_dspi *dspi = dev_get_drvdata(dev);
        int ret;
 
        pinctrl_pm_select_default_state(dev);
@@ -1104,7 +1102,7 @@ static int dspi_resume(struct device *dev)
        ret = clk_prepare_enable(dspi->clk);
        if (ret)
                return ret;
-       spi_controller_resume(ctlr);
+       spi_controller_resume(dspi->ctlr);
        if (dspi->irq)
                enable_irq(dspi->irq);
 
index 986b9793fd3c6379472f784279ad60a2a2a44874..a2886ee44e4cb38569ab917248f3b8f53f86fb87 100644 (file)
@@ -938,9 +938,6 @@ static int fsl_lpspi_remove(struct platform_device *pdev)
                                spi_controller_get_devdata(controller);
 
        pm_runtime_disable(fsl_lpspi->dev);
-
-       spi_master_put(controller);
-
        return 0;
 }
 
index 060b1f5c9b048bbc85139d64b88586dd2bd88bec..0b597905ee72c6373a7c4e0f6c59872a751e51be 100644 (file)
@@ -1676,15 +1676,19 @@ static int spi_imx_probe(struct platform_device *pdev)
                goto out_master_put;
        }
 
-       pm_runtime_enable(spi_imx->dev);
+       ret = clk_prepare_enable(spi_imx->clk_per);
+       if (ret)
+               goto out_master_put;
+
+       ret = clk_prepare_enable(spi_imx->clk_ipg);
+       if (ret)
+               goto out_put_per;
+
        pm_runtime_set_autosuspend_delay(spi_imx->dev, MXC_RPM_TIMEOUT);
        pm_runtime_use_autosuspend(spi_imx->dev);
-
-       ret = pm_runtime_get_sync(spi_imx->dev);
-       if (ret < 0) {
-               dev_err(spi_imx->dev, "failed to enable clock\n");
-               goto out_runtime_pm_put;
-       }
+       pm_runtime_get_noresume(spi_imx->dev);
+       pm_runtime_set_active(spi_imx->dev);
+       pm_runtime_enable(spi_imx->dev);
 
        spi_imx->spi_clk = clk_get_rate(spi_imx->clk_per);
        /*
@@ -1722,8 +1726,12 @@ out_bitbang_start:
                spi_imx_sdma_exit(spi_imx);
 out_runtime_pm_put:
        pm_runtime_dont_use_autosuspend(spi_imx->dev);
-       pm_runtime_put_sync(spi_imx->dev);
+       pm_runtime_set_suspended(&pdev->dev);
        pm_runtime_disable(spi_imx->dev);
+
+       clk_disable_unprepare(spi_imx->clk_ipg);
+out_put_per:
+       clk_disable_unprepare(spi_imx->clk_per);
 out_master_put:
        spi_master_put(master);
 
index 341f7cffeaac6ed0e5b92bf90afcd4c1445641db..1cb9329de945e18777f806b9e154a6f13652d19c 100644 (file)
@@ -679,7 +679,7 @@ static int npcm_fiu_probe(struct platform_device *pdev)
        struct resource *res;
        int id;
 
-       ctrl = spi_alloc_master(dev, sizeof(*fiu));
+       ctrl = devm_spi_alloc_master(dev, sizeof(*fiu));
        if (!ctrl)
                return -ENOMEM;
 
index 0d41406c036deeb5e070b1c2ffbba26658390178..ab9035662717a3b0464bdefb6bb3ca4d10376401 100644 (file)
@@ -1001,6 +1001,7 @@ static int nxp_fspi_probe(struct platform_device *pdev)
        struct resource *res;
        struct nxp_fspi *f;
        int ret;
+       u32 reg;
 
        ctlr = spi_alloc_master(&pdev->dev, sizeof(*f));
        if (!ctlr)
@@ -1032,6 +1033,12 @@ static int nxp_fspi_probe(struct platform_device *pdev)
                goto err_put_ctrl;
        }
 
+       /* Clear potential interrupts */
+       reg = fspi_readl(f, f->iobase + FSPI_INTR);
+       if (reg)
+               fspi_writel(f, reg, f->iobase + FSPI_INTR);
+
+
        /* find the resources - controller memory mapped space */
        if (is_acpi_node(f->dev->fwnode))
                res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
index 0cab239d8e7fc00983084107c7a74f5f0367af74..fc9a59788d2eab8a46761115c0a067001a3f7d28 100644 (file)
@@ -812,18 +812,16 @@ static void spi_set_cs(struct spi_device *spi, bool enable)
                enable = !enable;
 
        if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio)) {
-               /*
-                * Honour the SPI_NO_CS flag and invert the enable line, as
-                * active low is default for SPI. Execution paths that handle
-                * polarity inversion in gpiolib (such as device tree) will
-                * enforce active high using the SPI_CS_HIGH resulting in a
-                * double inversion through the code above.
-                */
                if (!(spi->mode & SPI_NO_CS)) {
                        if (spi->cs_gpiod)
+                               /* polarity handled by gpiolib */
                                gpiod_set_value_cansleep(spi->cs_gpiod,
-                                                        !enable);
+                                                        enable1);
                        else
+                               /*
+                                * invert the enable line, as active low is
+                                * default for SPI.
+                                */
                                gpio_set_value_cansleep(spi->cs_gpio, !enable);
                }
                /* Some SPI masters need both GPIO CS & slave_select */
@@ -1992,15 +1990,6 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
        }
        spi->chip_select = value;
 
-       /*
-        * For descriptors associated with the device, polarity inversion is
-        * handled in the gpiolib, so all gpio chip selects are "active high"
-        * in the logical sense, the gpiolib will invert the line if need be.
-        */
-       if ((ctlr->use_gpio_descriptors) && ctlr->cs_gpiods &&
-           ctlr->cs_gpiods[spi->chip_select])
-               spi->mode |= SPI_CS_HIGH;
-
        /* Device speed */
        if (!of_property_read_u32(nc, "spi-max-frequency", &value))
                spi->max_speed_hz = value;
@@ -2453,6 +2442,49 @@ struct spi_controller *__spi_alloc_controller(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(__spi_alloc_controller);
 
+static void devm_spi_release_controller(struct device *dev, void *ctlr)
+{
+       spi_controller_put(*(struct spi_controller **)ctlr);
+}
+
+/**
+ * __devm_spi_alloc_controller - resource-managed __spi_alloc_controller()
+ * @dev: physical device of SPI controller
+ * @size: how much zeroed driver-private data to allocate
+ * @slave: whether to allocate an SPI master (false) or SPI slave (true)
+ * Context: can sleep
+ *
+ * Allocate an SPI controller and automatically release a reference on it
+ * when @dev is unbound from its driver.  Drivers are thus relieved from
+ * having to call spi_controller_put().
+ *
+ * The arguments to this function are identical to __spi_alloc_controller().
+ *
+ * Return: the SPI controller structure on success, else NULL.
+ */
+struct spi_controller *__devm_spi_alloc_controller(struct device *dev,
+                                                  unsigned int size,
+                                                  bool slave)
+{
+       struct spi_controller **ptr, *ctlr;
+
+       ptr = devres_alloc(devm_spi_release_controller, sizeof(*ptr),
+                          GFP_KERNEL);
+       if (!ptr)
+               return NULL;
+
+       ctlr = __spi_alloc_controller(dev, size, slave);
+       if (ctlr) {
+               *ptr = ctlr;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return ctlr;
+}
+EXPORT_SYMBOL_GPL(__devm_spi_alloc_controller);
+
 #ifdef CONFIG_OF
 static int of_spi_get_gpio_numbers(struct spi_controller *ctlr)
 {
@@ -2789,6 +2821,11 @@ int devm_spi_register_controller(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(devm_spi_register_controller);
 
+static int devm_spi_match_controller(struct device *dev, void *res, void *ctlr)
+{
+       return *(struct spi_controller **)res == ctlr;
+}
+
 static int __unregister(struct device *dev, void *null)
 {
        spi_unregister_device(to_spi_device(dev));
@@ -2830,7 +2867,15 @@ void spi_unregister_controller(struct spi_controller *ctlr)
        list_del(&ctlr->list);
        mutex_unlock(&board_lock);
 
-       device_unregister(&ctlr->dev);
+       device_del(&ctlr->dev);
+
+       /* Release the last reference on the controller if its driver
+        * has not yet been converted to devm_spi_alloc_master/slave().
+        */
+       if (!devres_find(ctlr->dev.parent, devm_spi_release_controller,
+                        devm_spi_match_controller, ctlr))
+               put_device(&ctlr->dev);
+
        /* free bus id */
        mutex_lock(&board_lock);
        if (found == ctlr)
@@ -3327,12 +3372,15 @@ int spi_setup(struct spi_device *spi)
        if (!spi->max_speed_hz)
                spi->max_speed_hz = spi->controller->max_speed_hz;
 
+       mutex_lock(&spi->controller->io_mutex);
+
        if (spi->controller->setup)
                status = spi->controller->setup(spi);
 
        if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
                status = pm_runtime_get_sync(spi->controller->dev.parent);
                if (status < 0) {
+                       mutex_unlock(&spi->controller->io_mutex);
                        pm_runtime_put_noidle(spi->controller->dev.parent);
                        dev_err(&spi->controller->dev, "Failed to power device: %d\n",
                                status);
@@ -3354,6 +3402,8 @@ int spi_setup(struct spi_device *spi)
                spi_set_cs(spi, false);
        }
 
+       mutex_unlock(&spi->controller->io_mutex);
+
        if (spi->rt && !spi->controller->rt) {
                spi->controller->rt = true;
                spi_set_thread_rt(spi->controller);
index 48ec2ee953dc5dd91b94e0202ce128157126ff15..d740c478277513c73233afce007e239a624d2edc 100644 (file)
@@ -1342,6 +1342,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
                if (dev->irq && board->has_ao_fifo) {
                        dev->write_subdev = s;
                        s->subdev_flags |= SDF_CMD_WRITE;
+                       s->len_chanlist = s->n_chan;
                        s->do_cmdtest   = cb_pcidas_ao_cmdtest;
                        s->do_cmd       = cb_pcidas_ao_cmd;
                        s->cancel       = cb_pcidas_ao_cancel;
index 5b8d0bae9ff3df03cd2c9b86569da79d21811d18..b5fded15e8a69b91039e2f3c934f1e613a8ff561 100644 (file)
@@ -293,7 +293,7 @@ static int controller_probe(struct platform_device *pdev)
        regulator = devm_regulator_register(dev, &can_power_desc, &config);
        if (IS_ERR(regulator)) {
                err = PTR_ERR(regulator);
-               goto out_reset;
+               goto out_ida;
        }
        /* make controller info visible to userspace */
        cd->class_dev = kzalloc(sizeof(*cd->class_dev), GFP_KERNEL);
index 28319351e909bd5f3dd6662e27194d6522e879cc..781c84a9b1b79e39d10f4f47bab7e5e099e23851 100644 (file)
@@ -446,7 +446,7 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
        reg |= (pps->second_chroma_qp_index_offset & 0x3f) << 16;
        reg |= (pps->chroma_qp_index_offset & 0x3f) << 8;
        reg |= (pps->pic_init_qp_minus26 + 26 + slice->slice_qp_delta) & 0x3f;
-       if (pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)
+       if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT))
                reg |= VE_H264_SHS_QP_SCALING_MATRIX_DEFAULT;
        cedrus_write(dev, VE_H264_SHS_QP, reg);
 
index f961b353c22e4071bf7f4e5d749a344335de7747..8831db383fad84fbea40f915747401b0c9a47511 100644 (file)
@@ -653,16 +653,11 @@ static int mt7621_pcie_init_virtual_bridges(struct mt7621_pcie *pcie)
        return 0;
 }
 
-static int mt7621_pcie_request_resources(struct mt7621_pcie *pcie,
-                                        struct list_head *res)
+static void mt7621_pcie_add_resources(struct mt7621_pcie *pcie,
+                                     struct list_head *res)
 {
-       struct device *dev = pcie->dev;
-
        pci_add_resource_offset(res, &pcie->io, pcie->offset.io);
        pci_add_resource_offset(res, &pcie->mem, pcie->offset.mem);
-       pci_add_resource(res, &pcie->busn);
-
-       return devm_request_pci_bus_resources(dev, res);
 }
 
 static int mt7621_pcie_register_host(struct pci_host_bridge *host,
@@ -738,11 +733,7 @@ static int mt7621_pci_probe(struct platform_device *pdev)
 
        setup_cm_memory_region(pcie);
 
-       err = mt7621_pcie_request_resources(pcie, &res);
-       if (err) {
-               dev_err(dev, "Error requesting resources\n");
-               return err;
-       }
+       mt7621_pcie_add_resources(pcie, &res);
 
        err = mt7621_pcie_register_host(bridge, &res);
        if (err) {
index cfb673a52b257e68af4512fe0afd756fc5da50f5..0bf545849b119d1a410b385313661e2743cf0db2 100644 (file)
@@ -147,12 +147,6 @@ int cvm_oct_phy_setup_device(struct net_device *dev)
 
        phy_node = of_parse_phandle(priv->of_node, "phy-handle", 0);
        if (!phy_node && of_phy_is_fixed_link(priv->of_node)) {
-               int rc;
-
-               rc = of_phy_register_fixed_link(priv->of_node);
-               if (rc)
-                       return rc;
-
                phy_node = of_node_get(priv->of_node);
        }
        if (!phy_node)
index 2c16230f993cb01545088025ab74e4d93a44771b..9ebd665e5d4275a46143fdd814e905c30fd595dc 100644 (file)
@@ -69,15 +69,17 @@ static inline int cvm_oct_check_rcv_error(struct cvmx_wqe *work)
        else
                port = work->word1.cn38xx.ipprt;
 
-       if ((work->word2.snoip.err_code == 10) && (work->word1.len <= 64)) {
+       if ((work->word2.snoip.err_code == 10) && (work->word1.len <= 64))
                /*
                 * Ignore length errors on min size packets. Some
                 * equipment incorrectly pads packets to 64+4FCS
                 * instead of 60+4FCS.  Note these packets still get
                 * counted as frame errors.
                 */
-       } else if (work->word2.snoip.err_code == 5 ||
-                  work->word2.snoip.err_code == 7) {
+               return 0;
+
+       if (work->word2.snoip.err_code == 5 ||
+           work->word2.snoip.err_code == 7) {
                /*
                 * We received a packet with either an alignment error
                 * or a FCS error. This may be signalling that we are
@@ -108,7 +110,10 @@ static inline int cvm_oct_check_rcv_error(struct cvmx_wqe *work)
                                /* Port received 0xd5 preamble */
                                work->packet_ptr.s.addr += i + 1;
                                work->word1.len -= i + 5;
-                       } else if ((*ptr & 0xf) == 0xd) {
+                               return 0;
+                       }
+
+                       if ((*ptr & 0xf) == 0xd) {
                                /* Port received 0xd preamble */
                                work->packet_ptr.s.addr += i;
                                work->word1.len -= i + 4;
@@ -118,21 +123,20 @@ static inline int cvm_oct_check_rcv_error(struct cvmx_wqe *work)
                                            ((*(ptr + 1) & 0xf) << 4);
                                        ptr++;
                                }
-                       } else {
-                               printk_ratelimited("Port %d unknown preamble, packet dropped\n",
-                                                  port);
-                               cvm_oct_free_work(work);
-                               return 1;
+                               return 0;
                        }
+
+                       printk_ratelimited("Port %d unknown preamble, packet dropped\n",
+                                          port);
+                       cvm_oct_free_work(work);
+                       return 1;
                }
-       } else {
-               printk_ratelimited("Port %d receive error code %d, packet dropped\n",
-                                  port, work->word2.snoip.err_code);
-               cvm_oct_free_work(work);
-               return 1;
        }
 
-       return 0;
+       printk_ratelimited("Port %d receive error code %d, packet dropped\n",
+                          port, work->word2.snoip.err_code);
+       cvm_oct_free_work(work);
+       return 1;
 }
 
 static void copy_segments_to_skb(struct cvmx_wqe *work, struct sk_buff *skb)
index 204f0b1e27397e692974491a1b7b166a4bba9153..5dea6e96ec901806beecb1df1931f669e642b247 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/phy.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
+#include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include <linux/if_ether.h>
 #include <linux/if_vlan.h>
@@ -892,6 +893,14 @@ static int cvm_oct_probe(struct platform_device *pdev)
                                break;
                        }
 
+                       if (priv->of_node && of_phy_is_fixed_link(priv->of_node)) {
+                               if (of_phy_register_fixed_link(priv->of_node)) {
+                                       netdev_err(dev, "Failed to register fixed link for interface %d, port %d\n",
+                                                  interface, priv->port);
+                                       dev->netdev_ops = NULL;
+                               }
+                       }
+
                        if (!dev->netdev_ops) {
                                free_netdev(dev);
                        } else if (register_netdev(dev) < 0) {
index 54e8029e6b1afb15beef1641d463b1014927803d..0017376234e28d1ecf6338c2a6c4107d0961a99c 100644 (file)
@@ -2,6 +2,7 @@
 config DMA_RALINK
        tristate "RALINK DMA support"
        depends on RALINK && !SOC_RT288X
+       depends on DMADEVICES
        select DMA_ENGINE
        select DMA_VIRTUAL_CHANNELS
 
index 79b55ec827a4c037f083670301e160161cc05f36..b2208e5f190ad3f92d929956e65aa0456420ed0d 100644 (file)
@@ -20,6 +20,7 @@ static const struct sdio_device_id sdio_ids[] = {
        { SDIO_DEVICE(0x024c, 0x0525), },
        { SDIO_DEVICE(0x024c, 0x0623), },
        { SDIO_DEVICE(0x024c, 0x0626), },
+       { SDIO_DEVICE(0x024c, 0x0627), },
        { SDIO_DEVICE(0x024c, 0xb723), },
        { /* end: all zeroes */                         },
 };
index 3a4202551cfca6605a7a3d06a7b3be0f7a2aa1f7..9097bcbd67d8226bc68315235af1de25e09cf5e4 100644 (file)
@@ -179,6 +179,9 @@ struct vchiq_mmal_instance {
 
        /* ordered workqueue to process all bulk operations */
        struct workqueue_struct *bulk_wq;
+
+       /* handle for a vchiq instance */
+       struct vchiq_instance *vchiq_instance;
 };
 
 static struct mmal_msg_context *
@@ -1840,6 +1843,7 @@ int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance)
 
        mutex_unlock(&instance->vchiq_mutex);
 
+       vchiq_shutdown(instance->vchiq_instance);
        flush_workqueue(instance->bulk_wq);
        destroy_workqueue(instance->bulk_wq);
 
@@ -1856,6 +1860,7 @@ EXPORT_SYMBOL_GPL(vchiq_mmal_finalise);
 int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
 {
        int status;
+       int err = -ENODEV;
        struct vchiq_mmal_instance *instance;
        static struct vchiq_instance *vchiq_instance;
        struct vchiq_service_params_kernel params = {
@@ -1890,17 +1895,21 @@ int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
        status = vchiq_connect(vchiq_instance);
        if (status) {
                pr_err("Failed to connect VCHI instance (status=%d)\n", status);
-               return -EIO;
+               err = -EIO;
+               goto err_shutdown_vchiq;
        }
 
        instance = kzalloc(sizeof(*instance), GFP_KERNEL);
 
-       if (!instance)
-               return -ENOMEM;
+       if (!instance) {
+               err = -ENOMEM;
+               goto err_shutdown_vchiq;
+       }
 
        mutex_init(&instance->vchiq_mutex);
 
        instance->bulk_scratch = vmalloc(PAGE_SIZE);
+       instance->vchiq_instance = vchiq_instance;
 
        mutex_init(&instance->context_map_lock);
        idr_init_base(&instance->context_map, 1);
@@ -1932,7 +1941,9 @@ err_close_services:
 err_free:
        vfree(instance->bulk_scratch);
        kfree(instance);
-       return -ENODEV;
+err_shutdown_vchiq:
+       vchiq_shutdown(vchiq_instance);
+       return err;
 }
 EXPORT_SYMBOL_GPL(vchiq_mmal_init);
 
index 43b5630c0407a29daa9688fe016cd482829a1b2d..510edd12ed19249559ae1b6e8ed11a0810053ad5 100644 (file)
@@ -24,7 +24,7 @@ description:
     In addition, it is recommended to declare a mmc-pwrseq on SDIO host above
     WFx. Without it, you may encounter issues with warm boot. The mmc-pwrseq
     should be compatible with mmc-pwrseq-simple. Please consult
-    Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt for more
+    Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml for more
     information.
 
   For SPI':'
index 2ffa587aefaa7710f25a67953b6b74d690825b87..ed53d0b455927d7387add3f913c16a4761b48924 100644 (file)
@@ -21,7 +21,7 @@ static void device_wakeup(struct wfx_dev *wdev)
 
        if (!wdev->pdata.gpio_wakeup)
                return;
-       if (gpiod_get_value_cansleep(wdev->pdata.gpio_wakeup) >= 0)
+       if (gpiod_get_value_cansleep(wdev->pdata.gpio_wakeup) > 0)
                return;
 
        if (wfx_api_older_than(wdev, 1, 4)) {
index 41f6a604a697a3966a9558886548400f157f4bd3..36b36ef39d053ce88b60d5a729380224556f3273 100644 (file)
@@ -31,13 +31,13 @@ static int wfx_get_hw_rate(struct wfx_dev *wdev,
                }
                return rate->idx + 14;
        }
+       // WFx only support 2GHz, else band information should be retrieved
+       // from ieee80211_tx_info
+       band = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ];
        if (rate->idx >= band->n_bitrates) {
                WARN(1, "wrong rate->idx value: %d", rate->idx);
                return -1;
        }
-       // WFx only support 2GHz, else band information should be retrieved
-       // from ieee80211_tx_info
-       band = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ];
        return band->bitrates[rate->idx].hw_value;
 }
 
index f77e5eee6b809ab26e64305d823e3591c8721084..518fac4864cfa61ed82098c9bc50aef0097d9d05 100644 (file)
@@ -483,8 +483,7 @@ EXPORT_SYMBOL(iscsit_queue_rsp);
 void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
 {
        spin_lock_bh(&conn->cmd_lock);
-       if (!list_empty(&cmd->i_conn_node) &&
-           !(cmd->se_cmd.transport_state & CMD_T_FABRIC_STOP))
+       if (!list_empty(&cmd->i_conn_node))
                list_del_init(&cmd->i_conn_node);
        spin_unlock_bh(&conn->cmd_lock);
 
@@ -4083,12 +4082,22 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
        spin_lock_bh(&conn->cmd_lock);
        list_splice_init(&conn->conn_cmd_list, &tmp_list);
 
-       list_for_each_entry(cmd, &tmp_list, i_conn_node) {
+       list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) {
                struct se_cmd *se_cmd = &cmd->se_cmd;
 
                if (se_cmd->se_tfo != NULL) {
                        spin_lock_irq(&se_cmd->t_state_lock);
-                       se_cmd->transport_state |= CMD_T_FABRIC_STOP;
+                       if (se_cmd->transport_state & CMD_T_ABORTED) {
+                               /*
+                                * LIO's abort path owns the cleanup for this,
+                                * so put it back on the list and let
+                                * aborted_task handle it.
+                                */
+                               list_move_tail(&cmd->i_conn_node,
+                                              &conn->conn_cmd_list);
+                       } else {
+                               se_cmd->transport_state |= CMD_T_FABRIC_STOP;
+                       }
                        spin_unlock_irq(&se_cmd->t_state_lock);
                }
        }
index ea84d08747df3749f878867228b5559c7c164674..590e6d072228109fbec0c37ea73662de7b5aa9a3 100644 (file)
@@ -194,7 +194,7 @@ struct tcmu_tmr {
 
        uint8_t tmr_type;
        uint32_t tmr_cmd_cnt;
-       int16_t tmr_cmd_ids[0];
+       int16_t tmr_cmd_ids[];
 };
 
 /*
index d7f798c3394bc72c28265c50b920ae47f3f63733..337c8d82f74ebfcc0f90e1d080a4a04456fa8156 100644 (file)
@@ -64,9 +64,13 @@ struct amdtee_session {
 /**
  * struct amdtee_context_data - AMD-TEE driver context data
  * @sess_list:    Keeps track of sessions opened in current TEE context
+ * @shm_list:     Keeps track of buffers allocated and mapped in current TEE
+ *                context
  */
 struct amdtee_context_data {
        struct list_head sess_list;
+       struct list_head shm_list;
+       struct mutex shm_mutex;   /* synchronizes access to @shm_list */
 };
 
 struct amdtee_driver_data {
@@ -89,10 +93,6 @@ struct amdtee_shm_data {
        u32     buf_id;
 };
 
-struct amdtee_shm_context {
-       struct list_head shmdata_list;
-};
-
 #define LOWER_TWO_BYTE_MASK    0x0000FFFF
 
 /**
index 27b4cd77d0db6facc167aa685f30553e4c8a1da7..8a6a8f30bb427ab060b4a132c1cbd0af06f1184a 100644 (file)
@@ -20,7 +20,6 @@
 
 static struct amdtee_driver_data *drv_data;
 static DEFINE_MUTEX(session_list_mutex);
-static struct amdtee_shm_context shmctx;
 
 static void amdtee_get_version(struct tee_device *teedev,
                               struct tee_ioctl_version_data *vers)
@@ -42,7 +41,8 @@ static int amdtee_open(struct tee_context *ctx)
                return -ENOMEM;
 
        INIT_LIST_HEAD(&ctxdata->sess_list);
-       INIT_LIST_HEAD(&shmctx.shmdata_list);
+       INIT_LIST_HEAD(&ctxdata->shm_list);
+       mutex_init(&ctxdata->shm_mutex);
 
        ctx->data = ctxdata;
        return 0;
@@ -86,6 +86,7 @@ static void amdtee_release(struct tee_context *ctx)
                list_del(&sess->list_node);
                release_session(sess);
        }
+       mutex_destroy(&ctxdata->shm_mutex);
        kfree(ctxdata);
 
        ctx->data = NULL;
@@ -152,14 +153,17 @@ static struct amdtee_session *find_session(struct amdtee_context_data *ctxdata,
 
 u32 get_buffer_id(struct tee_shm *shm)
 {
-       u32 buf_id = 0;
+       struct amdtee_context_data *ctxdata = shm->ctx->data;
        struct amdtee_shm_data *shmdata;
+       u32 buf_id = 0;
 
-       list_for_each_entry(shmdata, &shmctx.shmdata_list, shm_node)
+       mutex_lock(&ctxdata->shm_mutex);
+       list_for_each_entry(shmdata, &ctxdata->shm_list, shm_node)
                if (shmdata->kaddr == shm->kaddr) {
                        buf_id = shmdata->buf_id;
                        break;
                }
+       mutex_unlock(&ctxdata->shm_mutex);
 
        return buf_id;
 }
@@ -333,8 +337,9 @@ int amdtee_close_session(struct tee_context *ctx, u32 session)
 
 int amdtee_map_shmem(struct tee_shm *shm)
 {
-       struct shmem_desc shmem;
+       struct amdtee_context_data *ctxdata;
        struct amdtee_shm_data *shmnode;
+       struct shmem_desc shmem;
        int rc, count;
        u32 buf_id;
 
@@ -362,7 +367,10 @@ int amdtee_map_shmem(struct tee_shm *shm)
 
        shmnode->kaddr = shm->kaddr;
        shmnode->buf_id = buf_id;
-       list_add(&shmnode->shm_node, &shmctx.shmdata_list);
+       ctxdata = shm->ctx->data;
+       mutex_lock(&ctxdata->shm_mutex);
+       list_add(&shmnode->shm_node, &ctxdata->shm_list);
+       mutex_unlock(&ctxdata->shm_mutex);
 
        pr_debug("buf_id :[%x] kaddr[%p]\n", shmnode->buf_id, shmnode->kaddr);
 
@@ -371,6 +379,7 @@ int amdtee_map_shmem(struct tee_shm *shm)
 
 void amdtee_unmap_shmem(struct tee_shm *shm)
 {
+       struct amdtee_context_data *ctxdata;
        struct amdtee_shm_data *shmnode;
        u32 buf_id;
 
@@ -381,12 +390,15 @@ void amdtee_unmap_shmem(struct tee_shm *shm)
        /* Unmap the shared memory from TEE */
        handle_unmap_shmem(buf_id);
 
-       list_for_each_entry(shmnode, &shmctx.shmdata_list, shm_node)
+       ctxdata = shm->ctx->data;
+       mutex_lock(&ctxdata->shm_mutex);
+       list_for_each_entry(shmnode, &ctxdata->shm_list, shm_node)
                if (buf_id == shmnode->buf_id) {
                        list_del(&shmnode->shm_node);
                        kfree(shmnode);
                        break;
                }
+       mutex_unlock(&ctxdata->shm_mutex);
 }
 
 int amdtee_invoke_func(struct tee_context *ctx,
index 20b6fd7383c54b8ec059c258cce57aa09dd5e8ed..c981757ba0d4052733484c89a566be15255c08fc 100644 (file)
@@ -534,7 +534,8 @@ void optee_free_pages_list(void *list, size_t num_entries)
 static bool is_normal_memory(pgprot_t p)
 {
 #if defined(CONFIG_ARM)
-       return (pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC;
+       return (((pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC) ||
+               ((pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEBACK));
 #elif defined(CONFIG_ARM64)
        return (pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL);
 #else
index f53bf336c0a2025cf49c2ab017b7dfb1c4fce7dc..6ade4a5c4840789829fbd28b7825aad3742d9dc5 100644 (file)
@@ -200,7 +200,8 @@ int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
        int name_len;
        int rc;
 
-       if (connection_method == TEE_IOCTL_LOGIN_PUBLIC) {
+       if (connection_method == TEE_IOCTL_LOGIN_PUBLIC ||
+           connection_method == TEE_IOCTL_LOGIN_REE_KERNEL) {
                /* Nil UUID to be passed to TEE environment */
                uuid_copy(uuid, &uuid_null);
                return 0;
index 5e596168ba73b5ba218ea98a719e122a00b8bf0c..dcac99f327b08cb28d2f293454b701b5c5b396f3 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/err.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
+#include <linux/sys_soc.h>
 #include <linux/reboot.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
@@ -864,6 +865,17 @@ static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev)
        return bgp;
 }
 
+/*
+ * List of SoCs on which the CPU PM notifier can cause erros on the DTEMP
+ * readout.
+ * Enabled notifier on these machines results in erroneous, random values which
+ * could trigger unexpected thermal shutdown.
+ */
+static const struct soc_device_attribute soc_no_cpu_notifier[] = {
+       { .machine = "OMAP4430" },
+       { /* sentinel */ },
+};
+
 /***   Device driver call backs   ***/
 
 static
@@ -1020,7 +1032,8 @@ int ti_bandgap_probe(struct platform_device *pdev)
 
 #ifdef CONFIG_PM_SLEEP
        bgp->nb.notifier_call = bandgap_omap_cpu_notifier;
-       cpu_pm_register_notifier(&bgp->nb);
+       if (!soc_device_match(soc_no_cpu_notifier))
+               cpu_pm_register_notifier(&bgp->nb);
 #endif
 
        return 0;
@@ -1056,7 +1069,8 @@ int ti_bandgap_remove(struct platform_device *pdev)
        struct ti_bandgap *bgp = platform_get_drvdata(pdev);
        int i;
 
-       cpu_pm_unregister_notifier(&bgp->nb);
+       if (!soc_device_match(soc_no_cpu_notifier))
+               cpu_pm_unregister_notifier(&bgp->nb);
 
        /* Remove sensor interfaces */
        for (i = 0; i < bgp->conf->sensor_count; i++) {
index 3680b2784ea148bcd13384661e8bb28947eb9890..ed65d2b13964ff39497382d7f6019d8806c2e192 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/debugfs.h>
 #include <linux/pm_runtime.h>
+#include <linux/uaccess.h>
 
 #include "tb.h"
 
index b51fc3f62b1fbfe8949f3bc5d6219e94bbf301c4..82c46b200c347100f1cc29cba3de13c68398d2ef 100644 (file)
@@ -1976,7 +1976,9 @@ static int complete_rpm(struct device *dev, void *data)
 
 static void remove_unplugged_switch(struct tb_switch *sw)
 {
-       pm_runtime_get_sync(sw->dev.parent);
+       struct device *parent = get_device(sw->dev.parent);
+
+       pm_runtime_get_sync(parent);
 
        /*
         * Signal this and switches below for rpm_complete because
@@ -1987,8 +1989,10 @@ static void remove_unplugged_switch(struct tb_switch *sw)
        bus_for_each_dev(&tb_bus_type, &sw->dev, NULL, complete_rpm);
        tb_switch_remove(sw);
 
-       pm_runtime_mark_last_busy(sw->dev.parent);
-       pm_runtime_put_autosuspend(sw->dev.parent);
+       pm_runtime_mark_last_busy(parent);
+       pm_runtime_put_autosuspend(parent);
+
+       put_device(parent);
 }
 
 static void icm_free_unplugged_children(struct tb_switch *sw)
@@ -2284,6 +2288,8 @@ struct tb *icm_probe(struct tb_nhi *nhi)
 
        case PCI_DEVICE_ID_INTEL_TGL_NHI0:
        case PCI_DEVICE_ID_INTEL_TGL_NHI1:
+       case PCI_DEVICE_ID_INTEL_TGL_H_NHI0:
+       case PCI_DEVICE_ID_INTEL_TGL_H_NHI1:
                icm->is_supported = icm_tgl_is_supported;
                icm->driver_ready = icm_icl_driver_ready;
                icm->set_uuid = icm_icl_set_uuid;
index 3f79baa54829dfd423ba417e5cb0c578213021da..db80dc5dfebaefdce3fd5da2f8acfc50f83f30ca 100644 (file)
@@ -406,12 +406,23 @@ static int ring_request_msix(struct tb_ring *ring, bool no_suspend)
 
        ring->vector = ret;
 
-       ring->irq = pci_irq_vector(ring->nhi->pdev, ring->vector);
-       if (ring->irq < 0)
-               return ring->irq;
+       ret = pci_irq_vector(ring->nhi->pdev, ring->vector);
+       if (ret < 0)
+               goto err_ida_remove;
+
+       ring->irq = ret;
 
        irqflags = no_suspend ? IRQF_NO_SUSPEND : 0;
-       return request_irq(ring->irq, ring_msix, irqflags, "thunderbolt", ring);
+       ret = request_irq(ring->irq, ring_msix, irqflags, "thunderbolt", ring);
+       if (ret)
+               goto err_ida_remove;
+
+       return 0;
+
+err_ida_remove:
+       ida_simple_remove(&nhi->msix_ida, ring->vector);
+
+       return ret;
 }
 
 static void ring_release_msix(struct tb_ring *ring)
@@ -1334,6 +1345,10 @@ static struct pci_device_id nhi_ids[] = {
          .driver_data = (kernel_ulong_t)&icl_nhi_ops },
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL_NHI1),
          .driver_data = (kernel_ulong_t)&icl_nhi_ops },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL_H_NHI0),
+         .driver_data = (kernel_ulong_t)&icl_nhi_ops },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL_H_NHI1),
+         .driver_data = (kernel_ulong_t)&icl_nhi_ops },
 
        /* Any USB4 compliant host */
        { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_USB4, ~0) },
index 80162e4b013fc25b59e594383e4184c86ad3b427..4e0861d7507208e9171b0264fcdb27030da3de02 100644 (file)
@@ -75,6 +75,8 @@ extern const struct tb_nhi_ops icl_nhi_ops;
 #define PCI_DEVICE_ID_INTEL_ICL_NHI0                   0x8a17
 #define PCI_DEVICE_ID_INTEL_TGL_NHI0                   0x9a1b
 #define PCI_DEVICE_ID_INTEL_TGL_NHI1                   0x9a1d
+#define PCI_DEVICE_ID_INTEL_TGL_H_NHI0                 0x9a1f
+#define PCI_DEVICE_ID_INTEL_TGL_H_NHI1                 0x9a21
 
 #define PCI_CLASS_SERIAL_USB_USB4                      0x0c0340
 
index a9995e21b9165e6a367697248c51e40cb4435bf3..8ea360b0ff7736581a44aa9b8be82462c59205e4 100644 (file)
@@ -784,6 +784,8 @@ static inline bool tb_switch_is_tiger_lake(const struct tb_switch *sw)
                switch (sw->config.device_id) {
                case PCI_DEVICE_ID_INTEL_TGL_NHI0:
                case PCI_DEVICE_ID_INTEL_TGL_NHI1:
+               case PCI_DEVICE_ID_INTEL_TGL_H_NHI0:
+               case PCI_DEVICE_ID_INTEL_TGL_H_NHI1:
                        return true;
                }
        }
index 40f13579a3fe7648b5033e4559deeccd068cf9cc..f2583b4053e4882fab22c54b550b5881a4272059 100644 (file)
@@ -421,8 +421,12 @@ int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags)
         * upstream USB4 port.
         */
        tb_switch_for_each_port(sw, port) {
+               if (!tb_port_is_null(port))
+                       continue;
                if (!route && tb_is_upstream_port(port))
                        continue;
+               if (!port->cap_usb4)
+                       continue;
 
                ret = tb_port_read(port, &val, TB_CFG_PORT,
                                   port->cap_usb4 + PORT_CS_19, 1);
index 48907853732ac2a2f56a38b4d87849c33fbacbbe..c00ad817042e1ed59d90e43787620fe57ac8a743 100644 (file)
@@ -881,6 +881,7 @@ static void enumerate_services(struct tb_xdomain *xd)
 
                id = ida_simple_get(&xd->service_ids, 0, 0, GFP_KERNEL);
                if (id < 0) {
+                       kfree(svc->key);
                        kfree(svc);
                        break;
                }
index 718e010fcb04855ef8eed6c3ce2193ecbcf62072..09baef4ccc39ae7fb4fcfd894b5b3dc838e05b2a 100644 (file)
@@ -50,25 +50,25 @@ static const char serial21285_name[] = "Footbridge UART";
 
 static bool is_enabled(struct uart_port *port, int bit)
 {
-       unsigned long private_data = (unsigned long)port->private_data;
+       unsigned long *private_data = (unsigned long *)&port->private_data;
 
-       if (test_bit(bit, &private_data))
+       if (test_bit(bit, private_data))
                return true;
        return false;
 }
 
 static void enable(struct uart_port *port, int bit)
 {
-       unsigned long private_data = (unsigned long)port->private_data;
+       unsigned long *private_data = (unsigned long *)&port->private_data;
 
-       set_bit(bit, &private_data);
+       set_bit(bit, private_data);
 }
 
 static void disable(struct uart_port *port, int bit)
 {
-       unsigned long private_data = (unsigned long)port->private_data;
+       unsigned long *private_data = (unsigned long *)&port->private_data;
 
-       clear_bit(bit, &private_data);
+       clear_bit(bit, private_data);
 }
 
 #define is_tx_enabled(port)    is_enabled(port, tx_enabled_bit)
index 41f4120abdf291b43f4a056d09c869c9e518c1f7..fa876e2c13e5dcc2d028eda6fdeae4b125852701 100644 (file)
@@ -317,7 +317,7 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
         */
        baud = tty_termios_baud_rate(termios);
 
-       serial8250_do_set_termios(port, termios, old);
+       serial8250_do_set_termios(port, termios, NULL);
 
        tty_termios_encode_baud_rate(termios, baud, baud);
 
index 1044fc3876914a0d50847bae629a5a0c3de8bc04..28f22e58639c6c18c17c1a0f9af03da40b600b41 100644 (file)
@@ -522,6 +522,7 @@ config SERIAL_IMX_EARLYCON
        depends on OF
        select SERIAL_EARLYCON
        select SERIAL_CORE_CONSOLE
+       default y if SERIAL_IMX_CONSOLE
        help
          If you have enabled the earlycon on the Freescale IMX
          CPU you can make it the earlycon by answering Y to this option.
index 0c80a79d7442d614eecddc88a4dcd72bcdf1e4cf..c2be7cf91399295b6be57734253d9a67b0c092da 100644 (file)
@@ -789,8 +789,10 @@ static int ar933x_uart_probe(struct platform_device *pdev)
                goto err_disable_clk;
 
        up->gpios = mctrl_gpio_init(port, 0);
-       if (IS_ERR(up->gpios) && PTR_ERR(up->gpios) != -ENOSYS)
-               return PTR_ERR(up->gpios);
+       if (IS_ERR(up->gpios) && PTR_ERR(up->gpios) != -ENOSYS) {
+               ret = PTR_ERR(up->gpios);
+               goto err_disable_clk;
+       }
 
        up->rts_gpiod = mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS);
 
index ff4b88c637d0e3021077add0632b34f8029efce8..bd047e1f9bea71f982b4d743b3dc1cc7c60887f4 100644 (file)
@@ -314,9 +314,10 @@ MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
 /* Forward declare this for the dma callbacks*/
 static void lpuart_dma_tx_complete(void *arg);
 
-static inline bool is_ls1028a_lpuart(struct lpuart_port *sport)
+static inline bool is_layerscape_lpuart(struct lpuart_port *sport)
 {
-       return sport->devtype == LS1028A_LPUART;
+       return (sport->devtype == LS1021A_LPUART ||
+               sport->devtype == LS1028A_LPUART);
 }
 
 static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport)
@@ -1701,11 +1702,11 @@ static int lpuart32_startup(struct uart_port *port)
                                            UARTFIFO_FIFOSIZE_MASK);
 
        /*
-        * The LS1028A has a fixed length of 16 words. Although it supports the
-        * RX/TXSIZE fields their encoding is different. Eg the reference manual
-        * states 0b101 is 16 words.
+        * The LS1021A and LS1028A have a fixed FIFO depth of 16 words.
+        * Although they support the RX/TXSIZE fields, their encoding is
+        * different. Eg the reference manual states 0b101 is 16 words.
         */
-       if (is_ls1028a_lpuart(sport)) {
+       if (is_layerscape_lpuart(sport)) {
                sport->rxfifo_size = 16;
                sport->txfifo_size = 16;
                sport->port.fifosize = sport->txfifo_size;
index 1731d972886522e805addc3bc2f63ec5fcff6cbe..cacf7266a262d200948d2c5c10b80a0dc3323d6b 100644 (file)
@@ -942,8 +942,14 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id)
        struct imx_port *sport = dev_id;
        unsigned int usr1, usr2, ucr1, ucr2, ucr3, ucr4;
        irqreturn_t ret = IRQ_NONE;
+       unsigned long flags = 0;
 
-       spin_lock(&sport->port.lock);
+       /*
+        * IRQs might not be disabled upon entering this interrupt handler,
+        * e.g. when interrupt handlers are forced to be threaded. To support
+        * this scenario as well, disable IRQs when acquiring the spinlock.
+        */
+       spin_lock_irqsave(&sport->port.lock, flags);
 
        usr1 = imx_uart_readl(sport, USR1);
        usr2 = imx_uart_readl(sport, USR2);
@@ -1013,7 +1019,7 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id)
                ret = IRQ_HANDLED;
        }
 
-       spin_unlock(&sport->port.lock);
+       spin_unlock_irqrestore(&sport->port.lock, flags);
 
        return ret;
 }
@@ -2002,16 +2008,6 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count)
        unsigned int ucr1;
        unsigned long flags = 0;
        int locked = 1;
-       int retval;
-
-       retval = clk_enable(sport->clk_per);
-       if (retval)
-               return;
-       retval = clk_enable(sport->clk_ipg);
-       if (retval) {
-               clk_disable(sport->clk_per);
-               return;
-       }
 
        if (sport->port.sysrq)
                locked = 0;
@@ -2047,9 +2043,6 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count)
 
        if (locked)
                spin_unlock_irqrestore(&sport->port.lock, flags);
-
-       clk_disable(sport->clk_ipg);
-       clk_disable(sport->clk_per);
 }
 
 /*
@@ -2150,15 +2143,14 @@ imx_uart_console_setup(struct console *co, char *options)
 
        retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
 
-       clk_disable(sport->clk_ipg);
        if (retval) {
-               clk_unprepare(sport->clk_ipg);
+               clk_disable_unprepare(sport->clk_ipg);
                goto error_console;
        }
 
-       retval = clk_prepare(sport->clk_per);
+       retval = clk_prepare_enable(sport->clk_per);
        if (retval)
-               clk_unprepare(sport->clk_ipg);
+               clk_disable_unprepare(sport->clk_ipg);
 
 error_console:
        return retval;
index b4d89e31730e3ab548303ef164f21ebbc30481b0..7a07e7272de1258d2bf48066ccd7d0e467a3244e 100644 (file)
@@ -1280,6 +1280,9 @@ static int __init serial_txx9_init(void)
 
 #ifdef ENABLE_SERIAL_TXX9_PCI
        ret = pci_register_driver(&serial_txx9_pci_driver);
+       if (ret) {
+               platform_driver_unregister(&serial_txx9_plat_driver);
+       }
 #endif
        if (ret == 0)
                goto out;
index 7a4c02548fb3fba74ae1542ce8e72ded414e618d..56ade99ef99f41fbad5cdb14f8618fe2f666cdd5 100644 (file)
@@ -1515,10 +1515,12 @@ static void release_tty(struct tty_struct *tty, int idx)
                tty->ops->shutdown(tty);
        tty_save_termios(tty);
        tty_driver_remove_tty(tty->driver, tty);
-       tty->port->itty = NULL;
+       if (tty->port)
+               tty->port->itty = NULL;
        if (tty->link)
                tty->link->port->itty = NULL;
-       tty_buffer_cancel_work(tty->port);
+       if (tty->port)
+               tty_buffer_cancel_work(tty->port);
        if (tty->link)
                tty_buffer_cancel_work(tty->link->port);
 
@@ -2895,10 +2897,14 @@ void __do_SAK(struct tty_struct *tty)
        struct task_struct *g, *p;
        struct pid *session;
        int             i;
+       unsigned long flags;
 
        if (!tty)
                return;
-       session = tty->session;
+
+       spin_lock_irqsave(&tty->ctrl_lock, flags);
+       session = get_pid(tty->session);
+       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 
        tty_ldisc_flush(tty);
 
@@ -2930,6 +2936,7 @@ void __do_SAK(struct tty_struct *tty)
                task_unlock(p);
        } while_each_thread(g, p);
        read_unlock(&tasklist_lock);
+       put_pid(session);
 #endif
 }
 
index 28a23a0fef21c3bf5f5737175d61fd6b77155b2f..aa6d0537b379efe9256936446189fe2aa6b5dbdf 100644 (file)
@@ -103,8 +103,8 @@ static void __proc_set_tty(struct tty_struct *tty)
        put_pid(tty->session);
        put_pid(tty->pgrp);
        tty->pgrp = get_pid(task_pgrp(current));
-       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
        tty->session = get_pid(task_session(current));
+       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
        if (current->signal->tty) {
                tty_debug(tty, "current tty %s not NULL!!\n",
                          current->signal->tty->name);
@@ -293,20 +293,23 @@ void disassociate_ctty(int on_exit)
        spin_lock_irq(&current->sighand->siglock);
        put_pid(current->signal->tty_old_pgrp);
        current->signal->tty_old_pgrp = NULL;
-
        tty = tty_kref_get(current->signal->tty);
+       spin_unlock_irq(&current->sighand->siglock);
+
        if (tty) {
                unsigned long flags;
+
+               tty_lock(tty);
                spin_lock_irqsave(&tty->ctrl_lock, flags);
                put_pid(tty->session);
                put_pid(tty->pgrp);
                tty->session = NULL;
                tty->pgrp = NULL;
                spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+               tty_unlock(tty);
                tty_kref_put(tty);
        }
 
-       spin_unlock_irq(&current->sighand->siglock);
        /* Now clear signal->tty under the lock */
        read_lock(&tasklist_lock);
        session_clear_tty(task_session(current));
@@ -477,14 +480,19 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
                return -ENOTTY;
        if (retval)
                return retval;
-       if (!current->signal->tty ||
-           (current->signal->tty != real_tty) ||
-           (real_tty->session != task_session(current)))
-               return -ENOTTY;
+
        if (get_user(pgrp_nr, p))
                return -EFAULT;
        if (pgrp_nr < 0)
                return -EINVAL;
+
+       spin_lock_irq(&real_tty->ctrl_lock);
+       if (!current->signal->tty ||
+           (current->signal->tty != real_tty) ||
+           (real_tty->session != task_session(current))) {
+               retval = -ENOTTY;
+               goto out_unlock_ctrl;
+       }
        rcu_read_lock();
        pgrp = find_vpid(pgrp_nr);
        retval = -ESRCH;
@@ -494,12 +502,12 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
        if (session_of_pgrp(pgrp) != task_session(current))
                goto out_unlock;
        retval = 0;
-       spin_lock_irq(&tty->ctrl_lock);
        put_pid(real_tty->pgrp);
        real_tty->pgrp = get_pid(pgrp);
-       spin_unlock_irq(&tty->ctrl_lock);
 out_unlock:
        rcu_read_unlock();
+out_unlock_ctrl:
+       spin_unlock_irq(&real_tty->ctrl_lock);
        return retval;
 }
 
@@ -511,20 +519,30 @@ out_unlock:
  *
  *     Obtain the session id of the tty. If there is no session
  *     return an error.
- *
- *     Locking: none. Reference to current->signal->tty is safe.
  */
 static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
 {
+       unsigned long flags;
+       pid_t sid;
+
        /*
         * (tty == real_tty) is a cheap way of
         * testing if the tty is NOT a master pty.
        */
        if (tty == real_tty && current->signal->tty != real_tty)
                return -ENOTTY;
+
+       spin_lock_irqsave(&real_tty->ctrl_lock, flags);
        if (!real_tty->session)
-               return -ENOTTY;
-       return put_user(pid_vnr(real_tty->session), p);
+               goto err;
+       sid = pid_vnr(real_tty->session);
+       spin_unlock_irqrestore(&real_tty->ctrl_lock, flags);
+
+       return put_user(sid, p);
+
+err:
+       spin_unlock_irqrestore(&real_tty->ctrl_lock, flags);
+       return -ENOTTY;
 }
 
 /*
index 0db53b5b3acf6b7d33338b659c81b586e841804f..78acc270e39ac6ab269eb993a76cd3ce8eb104ec 100644 (file)
@@ -743,8 +743,13 @@ static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
                return;
 
        if ((unsigned)value < ARRAY_SIZE(func_table)) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&func_buf_lock, flags);
                if (func_table[value])
                        puts_queue(vc, func_table[value]);
+               spin_unlock_irqrestore(&func_buf_lock, flags);
+
        } else
                pr_err("k_fn called with value=%d\n", value);
 }
@@ -1991,13 +1996,11 @@ out:
 #undef s
 #undef v
 
-/* FIXME: This one needs untangling and locking */
+/* FIXME: This one needs untangling */
 int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
 {
        struct kbsentry *kbs;
-       char *p;
        u_char *q;
-       u_char __user *up;
        int sz, fnw_sz;
        int delta;
        char *first_free, *fj, *fnw;
@@ -2023,23 +2026,19 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
        i = array_index_nospec(kbs->kb_func, MAX_NR_FUNC);
 
        switch (cmd) {
-       case KDGKBSENT:
-               sz = sizeof(kbs->kb_string) - 1; /* sz should have been
-                                                 a struct member */
-               up = user_kdgkb->kb_string;
-               p = func_table[i];
-               if(p)
-                       for ( ; *p && sz; p++, sz--)
-                               if (put_user(*p, up++)) {
-                                       ret = -EFAULT;
-                                       goto reterr;
-                               }
-               if (put_user('\0', up)) {
-                       ret = -EFAULT;
-                       goto reterr;
-               }
-               kfree(kbs);
-               return ((p && *p) ? -EOVERFLOW : 0);
+       case KDGKBSENT: {
+               /* size should have been a struct member */
+               ssize_t len = sizeof(user_kdgkb->kb_string);
+
+               spin_lock_irqsave(&func_buf_lock, flags);
+               len = strlcpy(kbs->kb_string, func_table[i] ? : "", len);
+               spin_unlock_irqrestore(&func_buf_lock, flags);
+
+               ret = copy_to_user(user_kdgkb->kb_string, kbs->kb_string,
+                               len + 1) ? -EFAULT : 0;
+
+               goto reterr;
+       }
        case KDSKBSENT:
                if (!perm) {
                        ret = -EPERM;
index 9506a76f3ab67fc7333be5834fea5408ddf72f7a..d04a162939a4d527306bf7b1312306f1900184ef 100644 (file)
@@ -4704,27 +4704,6 @@ static int con_font_default(struct vc_data *vc, struct console_font_op *op)
        return rc;
 }
 
-static int con_font_copy(struct vc_data *vc, struct console_font_op *op)
-{
-       int con = op->height;
-       int rc;
-
-
-       console_lock();
-       if (vc->vc_mode != KD_TEXT)
-               rc = -EINVAL;
-       else if (!vc->vc_sw->con_font_copy)
-               rc = -ENOSYS;
-       else if (con < 0 || !vc_cons_allocated(con))
-               rc = -ENOTTY;
-       else if (con == vc->vc_num)     /* nothing to do */
-               rc = 0;
-       else
-               rc = vc->vc_sw->con_font_copy(vc, con);
-       console_unlock();
-       return rc;
-}
-
 int con_font_op(struct vc_data *vc, struct console_font_op *op)
 {
        switch (op->op) {
@@ -4735,7 +4714,8 @@ int con_font_op(struct vc_data *vc, struct console_font_op *op)
        case KD_FONT_OP_SET_DEFAULT:
                return con_font_default(vc, op);
        case KD_FONT_OP_COPY:
-               return con_font_copy(vc, op);
+               /* was buggy and never really used */
+               return -EINVAL;
        }
        return -ENOSYS;
 }
index 0a33b8ababe38fbb2c8e7b16fda2e5789a0f249a..5f61b25a9aaa89208bd565e51c44ff2fde530620 100644 (file)
@@ -484,7 +484,7 @@ static int vt_k_ioctl(struct tty_struct *tty, unsigned int cmd,
        return 0;
 }
 
-static inline int do_fontx_ioctl(int cmd,
+static inline int do_fontx_ioctl(struct vc_data *vc, int cmd,
                struct consolefontdesc __user *user_cfd,
                struct console_font_op *op)
 {
@@ -502,15 +502,16 @@ static inline int do_fontx_ioctl(int cmd,
                op->height = cfdarg.charheight;
                op->charcount = cfdarg.charcount;
                op->data = cfdarg.chardata;
-               return con_font_op(vc_cons[fg_console].d, op);
-       case GIO_FONTX: {
+               return con_font_op(vc, op);
+
+       case GIO_FONTX:
                op->op = KD_FONT_OP_GET;
                op->flags = KD_FONT_FLAG_OLD;
                op->width = 8;
                op->height = cfdarg.charheight;
                op->charcount = cfdarg.charcount;
                op->data = cfdarg.chardata;
-               i = con_font_op(vc_cons[fg_console].d, op);
+               i = con_font_op(vc, op);
                if (i)
                        return i;
                cfdarg.charheight = op->height;
@@ -518,12 +519,11 @@ static inline int do_fontx_ioctl(int cmd,
                if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
                        return -EFAULT;
                return 0;
-               }
        }
        return -EINVAL;
 }
 
-static int vt_io_fontreset(struct console_font_op *op)
+static int vt_io_fontreset(struct vc_data *vc, struct console_font_op *op)
 {
        int ret;
 
@@ -537,19 +537,19 @@ static int vt_io_fontreset(struct console_font_op *op)
 
        op->op = KD_FONT_OP_SET_DEFAULT;
        op->data = NULL;
-       ret = con_font_op(vc_cons[fg_console].d, op);
+       ret = con_font_op(vc, op);
        if (ret)
                return ret;
 
        console_lock();
-       con_set_default_unimap(vc_cons[fg_console].d);
+       con_set_default_unimap(vc);
        console_unlock();
 
        return 0;
 }
 
 static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud,
-               struct vc_data *vc)
+               bool perm, struct vc_data *vc)
 {
        struct unimapdesc tmp;
 
@@ -557,9 +557,11 @@ static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud,
                return -EFAULT;
        switch (cmd) {
        case PIO_UNIMAP:
+               if (!perm)
+                       return -EPERM;
                return con_set_unimap(vc, tmp.entry_ct, tmp.entries);
        case GIO_UNIMAP:
-               if (fg_console != vc->vc_num)
+               if (!perm && fg_console != vc->vc_num)
                        return -EPERM;
                return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct),
                                tmp.entries);
@@ -582,7 +584,7 @@ static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up,
                op.height = 0;
                op.charcount = 256;
                op.data = up;
-               return con_font_op(vc_cons[fg_console].d, &op);
+               return con_font_op(vc, &op);
 
        case GIO_FONT:
                op.op = KD_FONT_OP_GET;
@@ -591,7 +593,7 @@ static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up,
                op.height = 32;
                op.charcount = 256;
                op.data = up;
-               return con_font_op(vc_cons[fg_console].d, &op);
+               return con_font_op(vc, &op);
 
        case PIO_CMAP:
                 if (!perm)
@@ -607,13 +609,13 @@ static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up,
 
                fallthrough;
        case GIO_FONTX:
-               return do_fontx_ioctl(cmd, up, &op);
+               return do_fontx_ioctl(vc, cmd, up, &op);
 
        case PIO_FONTRESET:
                if (!perm)
                        return -EPERM;
 
-               return vt_io_fontreset(&op);
+               return vt_io_fontreset(vc, &op);
 
        case PIO_SCRNMAP:
                if (!perm)
@@ -639,10 +641,7 @@ static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up,
 
        case PIO_UNIMAP:
        case GIO_UNIMAP:
-               if (!perm)
-                       return -EPERM;
-
-               return do_unimap_ioctl(cmd, up, vc);
+               return do_unimap_ioctl(cmd, up, perm, vc);
 
        default:
                return -ENOIOCTLCMD;
@@ -1067,8 +1066,9 @@ struct compat_consolefontdesc {
 };
 
 static inline int
-compat_fontx_ioctl(int cmd, struct compat_consolefontdesc __user *user_cfd,
-                        int perm, struct console_font_op *op)
+compat_fontx_ioctl(struct vc_data *vc, int cmd,
+                  struct compat_consolefontdesc __user *user_cfd,
+                  int perm, struct console_font_op *op)
 {
        struct compat_consolefontdesc cfdarg;
        int i;
@@ -1086,7 +1086,8 @@ compat_fontx_ioctl(int cmd, struct compat_consolefontdesc __user *user_cfd,
                op->height = cfdarg.charheight;
                op->charcount = cfdarg.charcount;
                op->data = compat_ptr(cfdarg.chardata);
-               return con_font_op(vc_cons[fg_console].d, op);
+               return con_font_op(vc, op);
+
        case GIO_FONTX:
                op->op = KD_FONT_OP_GET;
                op->flags = KD_FONT_FLAG_OLD;
@@ -1094,7 +1095,7 @@ compat_fontx_ioctl(int cmd, struct compat_consolefontdesc __user *user_cfd,
                op->height = cfdarg.charheight;
                op->charcount = cfdarg.charcount;
                op->data = compat_ptr(cfdarg.chardata);
-               i = con_font_op(vc_cons[fg_console].d, op);
+               i = con_font_op(vc, op);
                if (i)
                        return i;
                cfdarg.charheight = op->height;
@@ -1184,7 +1185,7 @@ long vt_compat_ioctl(struct tty_struct *tty,
         */
        case PIO_FONTX:
        case GIO_FONTX:
-               return compat_fontx_ioctl(cmd, up, perm, &op);
+               return compat_fontx_ioctl(vc, cmd, up, perm, &op);
 
        case KDFONTOP:
                return compat_kdfontop_ioctl(up, perm, &op, vc);
index 6dca744e39e95603ebb93f1423435eb760134a67..be06f1a961c2c2a3dc8aa0f2ca44dadc117026c1 100644 (file)
@@ -413,10 +413,10 @@ static int uio_get_minor(struct uio_device *idev)
        return retval;
 }
 
-static void uio_free_minor(struct uio_device *idev)
+static void uio_free_minor(unsigned long minor)
 {
        mutex_lock(&minor_lock);
-       idr_remove(&uio_idr, idev->minor);
+       idr_remove(&uio_idr, minor);
        mutex_unlock(&minor_lock);
 }
 
@@ -990,7 +990,7 @@ err_request_irq:
 err_uio_dev_add_attributes:
        device_del(&idev->dev);
 err_device_create:
-       uio_free_minor(idev);
+       uio_free_minor(idev->minor);
        put_device(&idev->dev);
        return ret;
 }
@@ -1042,11 +1042,13 @@ EXPORT_SYMBOL_GPL(__devm_uio_register_device);
 void uio_unregister_device(struct uio_info *info)
 {
        struct uio_device *idev;
+       unsigned long minor;
 
        if (!info || !info->uio_dev)
                return;
 
        idev = info->uio_dev;
+       minor = idev->minor;
 
        mutex_lock(&idev->info_lock);
        uio_dev_del_attributes(idev);
@@ -1062,7 +1064,7 @@ void uio_unregister_device(struct uio_info *info)
 
        device_unregister(&idev->dev);
 
-       uio_free_minor(idev);
+       uio_free_minor(minor);
 
        return;
 }
index a0f73d4711ae2168226468aa3fd8cfd20d5e88ab..039ab5d2435eb79ad28b0c0e1b04a5d3f473e047 100644 (file)
@@ -427,7 +427,6 @@ static irqreturn_t cdns3_wakeup_irq(int irq, void *data)
  */
 static int cdns3_probe(struct platform_device *pdev)
 {
-       struct usb_role_switch_desc sw_desc = { };
        struct device *dev = &pdev->dev;
        struct resource *res;
        struct cdns3 *cdns;
@@ -529,18 +528,21 @@ static int cdns3_probe(struct platform_device *pdev)
        if (ret)
                goto err2;
 
-       sw_desc.set = cdns3_role_set;
-       sw_desc.get = cdns3_role_get;
-       sw_desc.allow_userspace_control = true;
-       sw_desc.driver_data = cdns;
-       if (device_property_read_bool(dev, "usb-role-switch"))
+       if (device_property_read_bool(dev, "usb-role-switch")) {
+               struct usb_role_switch_desc sw_desc = { };
+
+               sw_desc.set = cdns3_role_set;
+               sw_desc.get = cdns3_role_get;
+               sw_desc.allow_userspace_control = true;
+               sw_desc.driver_data = cdns;
                sw_desc.fwnode = dev->fwnode;
 
-       cdns->role_sw = usb_role_switch_register(dev, &sw_desc);
-       if (IS_ERR(cdns->role_sw)) {
-               ret = PTR_ERR(cdns->role_sw);
-               dev_warn(dev, "Unable to register Role Switch\n");
-               goto err3;
+               cdns->role_sw = usb_role_switch_register(dev, &sw_desc);
+               if (IS_ERR(cdns->role_sw)) {
+                       ret = PTR_ERR(cdns->role_sw);
+                       dev_warn(dev, "Unable to register Role Switch\n");
+                       goto err3;
+               }
        }
 
        if (cdns->wakeup_irq) {
@@ -551,7 +553,7 @@ static int cdns3_probe(struct platform_device *pdev)
 
                if (ret) {
                        dev_err(cdns->dev, "couldn't register wakeup irq handler\n");
-                       goto err3;
+                       goto err4;
                }
        }
 
@@ -582,7 +584,8 @@ static int cdns3_probe(struct platform_device *pdev)
        return 0;
 err4:
        cdns3_drd_exit(cdns);
-       usb_role_switch_unregister(cdns->role_sw);
+       if (cdns->role_sw)
+               usb_role_switch_unregister(cdns->role_sw);
 err3:
        set_phy_power_off(cdns);
 err2:
index 4761c852d9c4b8bc686206669f3a72cefd229185..d3121a32cc68cfc25bec49668285ef03d3458b7d 100644 (file)
@@ -137,48 +137,36 @@ static int cdns3_req_ep0_set_configuration(struct cdns3_device *priv_dev,
                                           struct usb_ctrlrequest *ctrl_req)
 {
        enum usb_device_state device_state = priv_dev->gadget.state;
-       struct cdns3_endpoint *priv_ep;
        u32 config = le16_to_cpu(ctrl_req->wValue);
        int result = 0;
-       int i;
 
        switch (device_state) {
        case USB_STATE_ADDRESS:
-               /* Configure non-control EPs */
-               for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++) {
-                       priv_ep = priv_dev->eps[i];
-                       if (!priv_ep)
-                               continue;
-
-                       if (priv_ep->flags & EP_CLAIMED)
-                               cdns3_ep_config(priv_ep);
-               }
-
                result = cdns3_ep0_delegate_req(priv_dev, ctrl_req);
 
-               if (result)
-                       return result;
-
-               if (!config) {
-                       cdns3_hw_reset_eps_config(priv_dev);
-                       usb_gadget_set_state(&priv_dev->gadget,
-                                            USB_STATE_ADDRESS);
-               }
+               if (result || !config)
+                       goto reset_config;
 
                break;
        case USB_STATE_CONFIGURED:
                result = cdns3_ep0_delegate_req(priv_dev, ctrl_req);
+               if (!config && !result)
+                       goto reset_config;
 
-               if (!config && !result) {
-                       cdns3_hw_reset_eps_config(priv_dev);
-                       usb_gadget_set_state(&priv_dev->gadget,
-                                            USB_STATE_ADDRESS);
-               }
                break;
        default:
-               result = -EINVAL;
+               return -EINVAL;
        }
 
+       return 0;
+
+reset_config:
+       if (result != USB_GADGET_DELAYED_STATUS)
+               cdns3_hw_reset_eps_config(priv_dev);
+
+       usb_gadget_set_state(&priv_dev->gadget,
+                            USB_STATE_ADDRESS);
+
        return result;
 }
 
@@ -705,6 +693,7 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep,
        unsigned long flags;
        int ret = 0;
        u8 zlp = 0;
+       int i;
 
        spin_lock_irqsave(&priv_dev->lock, flags);
        trace_cdns3_ep0_queue(priv_dev, request);
@@ -720,6 +709,17 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep,
                u32 val;
 
                cdns3_select_ep(priv_dev, 0x00);
+
+               /*
+                * Configure all non-control EPs which are not enabled by class driver
+                */
+               for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++) {
+                       priv_ep = priv_dev->eps[i];
+                       if (priv_ep && priv_ep->flags & EP_CLAIMED &&
+                           !(priv_ep->flags & EP_ENABLED))
+                               cdns3_ep_config(priv_ep, 0);
+               }
+
                cdns3_set_hw_configuration(priv_dev);
                cdns3_ep0_complete_setup(priv_dev, 0, 1);
                /* wait until configuration set */
@@ -811,6 +811,7 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev)
        struct cdns3_usb_regs __iomem *regs;
        struct cdns3_endpoint *priv_ep;
        u32 max_packet_size = 64;
+       u32 ep_cfg;
 
        regs = priv_dev->regs;
 
@@ -842,8 +843,10 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev)
                                       BIT(0) | BIT(16));
        }
 
-       writel(EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size),
-              &regs->ep_cfg);
+       ep_cfg = EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size);
+
+       if (!(priv_ep->flags & EP_CONFIGURED))
+               writel(ep_cfg, &regs->ep_cfg);
 
        writel(EP_STS_EN_SETUPEN | EP_STS_EN_DESCMISEN | EP_STS_EN_TRBERREN,
               &regs->ep_sts_en);
@@ -851,8 +854,10 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev)
        /* init ep in */
        cdns3_select_ep(priv_dev, USB_DIR_IN);
 
-       writel(EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size),
-              &regs->ep_cfg);
+       if (!(priv_ep->flags & EP_CONFIGURED))
+               writel(ep_cfg, &regs->ep_cfg);
+
+       priv_ep->flags |= EP_CONFIGURED;
 
        writel(EP_STS_EN_SETUPEN | EP_STS_EN_TRBERREN, &regs->ep_sts_en);
 
index 6e7b70a2e352b9d5ed2dd58d1f23438c787ef853..0aa85cc07ff19e48f3a914c4639e16ac145f7be7 100644 (file)
@@ -296,6 +296,8 @@ static void cdns3_ep_stall_flush(struct cdns3_endpoint *priv_ep)
  */
 void cdns3_hw_reset_eps_config(struct cdns3_device *priv_dev)
 {
+       int i;
+
        writel(USB_CONF_CFGRST, &priv_dev->regs->usb_conf);
 
        cdns3_allow_enable_l1(priv_dev, 0);
@@ -304,6 +306,10 @@ void cdns3_hw_reset_eps_config(struct cdns3_device *priv_dev)
        priv_dev->out_mem_is_allocated = 0;
        priv_dev->wait_for_setup = 0;
        priv_dev->using_streams = 0;
+
+       for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++)
+               if (priv_dev->eps[i])
+                       priv_dev->eps[i]->flags &= ~EP_CONFIGURED;
 }
 
 /**
@@ -506,7 +512,6 @@ static void cdns3_wa2_descmiss_copy_data(struct cdns3_endpoint *priv_ep,
 
        while (!list_empty(&priv_ep->wa2_descmiss_req_list)) {
                int chunk_end;
-               int length;
 
                descmiss_priv_req =
                        cdns3_next_priv_request(&priv_ep->wa2_descmiss_req_list);
@@ -517,7 +522,6 @@ static void cdns3_wa2_descmiss_copy_data(struct cdns3_endpoint *priv_ep,
                        break;
 
                chunk_end = descmiss_priv_req->flags & REQUEST_INTERNAL_CH;
-               length = request->actual + descmiss_req->actual;
                request->status = descmiss_req->status;
                __cdns3_descmiss_copy_data(request, descmiss_req);
                list_del_init(&descmiss_priv_req->list);
@@ -1110,7 +1114,7 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep,
        struct cdns3_device *priv_dev = priv_ep->cdns3_dev;
        struct cdns3_request *priv_req;
        struct cdns3_trb *trb;
-       struct cdns3_trb *link_trb;
+       struct cdns3_trb *link_trb = NULL;
        dma_addr_t trb_dma;
        u32 togle_pcs = 1;
        int sg_iter = 0;
@@ -1189,10 +1193,20 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep,
 
        /* set incorrect Cycle Bit for first trb*/
        control = priv_ep->pcs ? 0 : TRB_CYCLE;
+       trb->length = 0;
+       if (priv_dev->dev_ver >= DEV_VER_V2) {
+               u16 td_size;
+
+               td_size = DIV_ROUND_UP(request->length,
+                                      priv_ep->endpoint.maxpacket);
+               if (priv_dev->gadget.speed == USB_SPEED_SUPER)
+                       trb->length = TRB_TDL_SS_SIZE(td_size);
+               else
+                       control |= TRB_TDL_HS_SIZE(td_size);
+       }
 
        do {
                u32 length;
-               u16 td_size = 0;
 
                /* fill TRB */
                control |= TRB_TYPE(TRB_NORMAL);
@@ -1204,20 +1218,12 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep,
                        length = request->length;
                }
 
-               if (likely(priv_dev->dev_ver >= DEV_VER_V2))
-                       td_size = DIV_ROUND_UP(length,
-                                              priv_ep->endpoint.maxpacket);
-               else if (priv_ep->flags & EP_TDLCHK_EN)
+               if (priv_ep->flags & EP_TDLCHK_EN)
                        total_tdl += DIV_ROUND_UP(length,
                                               priv_ep->endpoint.maxpacket);
 
-               trb->length = cpu_to_le32(TRB_BURST_LEN(priv_ep->trb_burst_size) |
+               trb->length |= cpu_to_le32(TRB_BURST_LEN(priv_ep->trb_burst_size) |
                                        TRB_LEN(length));
-               if (priv_dev->gadget.speed == USB_SPEED_SUPER)
-                       trb->length |= cpu_to_le32(TRB_TDL_SS_SIZE(td_size));
-               else
-                       control |= TRB_TDL_HS_SIZE(td_size);
-
                pcs = priv_ep->pcs ? TRB_CYCLE : 0;
 
                /*
@@ -1254,6 +1260,7 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep,
                priv_req->end_trb = priv_ep->enqueue;
                cdns3_ep_inc_enq(priv_ep);
                trb = priv_ep->trb_pool + priv_ep->enqueue;
+               trb->length = 0;
        } while (sg_iter < num_trb);
 
        trb = priv_req->trb;
@@ -1746,11 +1753,8 @@ static int cdns3_check_ep_interrupt_proceed(struct cdns3_endpoint *priv_ep)
 
 static void cdns3_disconnect_gadget(struct cdns3_device *priv_dev)
 {
-       if (priv_dev->gadget_driver && priv_dev->gadget_driver->disconnect) {
-               spin_unlock(&priv_dev->lock);
+       if (priv_dev->gadget_driver && priv_dev->gadget_driver->disconnect)
                priv_dev->gadget_driver->disconnect(&priv_dev->gadget);
-               spin_lock(&priv_dev->lock);
-       }
 }
 
 /**
@@ -1761,6 +1765,7 @@ static void cdns3_disconnect_gadget(struct cdns3_device *priv_dev)
  */
 static void cdns3_check_usb_interrupt_proceed(struct cdns3_device *priv_dev,
                                              u32 usb_ists)
+__must_hold(&priv_dev->lock)
 {
        int speed = 0;
 
@@ -1785,7 +1790,9 @@ static void cdns3_check_usb_interrupt_proceed(struct cdns3_device *priv_dev,
 
        /* Disconnection detected */
        if (usb_ists & (USB_ISTS_DIS2I | USB_ISTS_DISI)) {
+               spin_unlock(&priv_dev->lock);
                cdns3_disconnect_gadget(priv_dev);
+               spin_lock(&priv_dev->lock);
                priv_dev->gadget.speed = USB_SPEED_UNKNOWN;
                usb_gadget_set_state(&priv_dev->gadget, USB_STATE_NOTATTACHED);
                cdns3_hw_reset_eps_config(priv_dev);
@@ -1979,27 +1986,6 @@ static int cdns3_ep_onchip_buffer_reserve(struct cdns3_device *priv_dev,
        return 0;
 }
 
-static void cdns3_stream_ep_reconfig(struct cdns3_device *priv_dev,
-                                    struct cdns3_endpoint *priv_ep)
-{
-       if (!priv_ep->use_streams || priv_dev->gadget.speed < USB_SPEED_SUPER)
-               return;
-
-       if (priv_dev->dev_ver >= DEV_VER_V3) {
-               u32 mask = BIT(priv_ep->num + (priv_ep->dir ? 16 : 0));
-
-               /*
-                * Stream capable endpoints are handled by using ep_tdl
-                * register. Other endpoints use TDL from TRB feature.
-                */
-               cdns3_clear_register_bit(&priv_dev->regs->tdl_from_trb, mask);
-       }
-
-       /*  Enable Stream Bit TDL chk and SID chk */
-       cdns3_set_register_bit(&priv_dev->regs->ep_cfg, EP_CFG_STREAM_EN |
-                              EP_CFG_TDL_CHK | EP_CFG_SID_CHK);
-}
-
 static void cdns3_configure_dmult(struct cdns3_device *priv_dev,
                                  struct cdns3_endpoint *priv_ep)
 {
@@ -2037,8 +2023,9 @@ static void cdns3_configure_dmult(struct cdns3_device *priv_dev,
 /**
  * cdns3_ep_config Configure hardware endpoint
  * @priv_ep: extended endpoint object
+ * @enable: set EP_CFG_ENABLE bit in ep_cfg register.
  */
-void cdns3_ep_config(struct cdns3_endpoint *priv_ep)
+int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
 {
        bool is_iso_ep = (priv_ep->type == USB_ENDPOINT_XFER_ISOC);
        struct cdns3_device *priv_dev = priv_ep->cdns3_dev;
@@ -2099,7 +2086,7 @@ void cdns3_ep_config(struct cdns3_endpoint *priv_ep)
                break;
        default:
                /* all other speed are not supported */
-               return;
+               return -EINVAL;
        }
 
        if (max_packet_size == 1024)
@@ -2109,11 +2096,33 @@ void cdns3_ep_config(struct cdns3_endpoint *priv_ep)
        else
                priv_ep->trb_burst_size = 16;
 
-       ret = cdns3_ep_onchip_buffer_reserve(priv_dev, buffering + 1,
-                                            !!priv_ep->dir);
-       if (ret) {
-               dev_err(priv_dev->dev, "onchip mem is full, ep is invalid\n");
-               return;
+       /* onchip buffer is only allocated before configuration */
+       if (!priv_dev->hw_configured_flag) {
+               ret = cdns3_ep_onchip_buffer_reserve(priv_dev, buffering + 1,
+                                                    !!priv_ep->dir);
+               if (ret) {
+                       dev_err(priv_dev->dev, "onchip mem is full, ep is invalid\n");
+                       return ret;
+               }
+       }
+
+       if (enable)
+               ep_cfg |= EP_CFG_ENABLE;
+
+       if (priv_ep->use_streams && priv_dev->gadget.speed >= USB_SPEED_SUPER) {
+               if (priv_dev->dev_ver >= DEV_VER_V3) {
+                       u32 mask = BIT(priv_ep->num + (priv_ep->dir ? 16 : 0));
+
+                       /*
+                        * Stream capable endpoints are handled by using ep_tdl
+                        * register. Other endpoints use TDL from TRB feature.
+                        */
+                       cdns3_clear_register_bit(&priv_dev->regs->tdl_from_trb,
+                                                mask);
+               }
+
+               /*  Enable Stream Bit TDL chk and SID chk */
+               ep_cfg |=  EP_CFG_STREAM_EN | EP_CFG_TDL_CHK | EP_CFG_SID_CHK;
        }
 
        ep_cfg |= EP_CFG_MAXPKTSIZE(max_packet_size) |
@@ -2123,9 +2132,12 @@ void cdns3_ep_config(struct cdns3_endpoint *priv_ep)
 
        cdns3_select_ep(priv_dev, bEndpointAddress);
        writel(ep_cfg, &priv_dev->regs->ep_cfg);
+       priv_ep->flags |= EP_CONFIGURED;
 
        dev_dbg(priv_dev->dev, "Configure %s: with val %08x\n",
                priv_ep->name, ep_cfg);
+
+       return 0;
 }
 
 /* Find correct direction for HW endpoint according to description */
@@ -2266,7 +2278,7 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep,
        u32 bEndpointAddress;
        unsigned long flags;
        int enable = 1;
-       int ret;
+       int ret = 0;
        int val;
 
        priv_ep = ep_to_cdns3_ep(ep);
@@ -2305,6 +2317,17 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep,
        bEndpointAddress = priv_ep->num | priv_ep->dir;
        cdns3_select_ep(priv_dev, bEndpointAddress);
 
+       /*
+        * For some versions of controller at some point during ISO OUT traffic
+        * DMA reads Transfer Ring for the EP which has never got doorbell.
+        * This issue was detected only on simulation, but to avoid this issue
+        * driver add protection against it. To fix it driver enable ISO OUT
+        * endpoint before setting DRBL. This special treatment of ISO OUT
+        * endpoints are recommended by controller specification.
+        */
+       if (priv_ep->type == USB_ENDPOINT_XFER_ISOC  && !priv_ep->dir)
+               enable = 0;
+
        if (usb_ss_max_streams(comp_desc) && usb_endpoint_xfer_bulk(desc)) {
                /*
                 * Enable stream support (SS mode) related interrupts
@@ -2315,13 +2338,17 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep,
                                EP_STS_EN_SIDERREN | EP_STS_EN_MD_EXITEN |
                                EP_STS_EN_STREAMREN;
                        priv_ep->use_streams = true;
-                       cdns3_stream_ep_reconfig(priv_dev, priv_ep);
+                       ret = cdns3_ep_config(priv_ep, enable);
                        priv_dev->using_streams |= true;
                }
+       } else {
+               ret = cdns3_ep_config(priv_ep, enable);
        }
 
-       ret = cdns3_allocate_trb_pool(priv_ep);
+       if (ret)
+               goto exit;
 
+       ret = cdns3_allocate_trb_pool(priv_ep);
        if (ret)
                goto exit;
 
@@ -2351,20 +2378,6 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep,
 
        writel(reg, &priv_dev->regs->ep_sts_en);
 
-       /*
-        * For some versions of controller at some point during ISO OUT traffic
-        * DMA reads Transfer Ring for the EP which has never got doorbell.
-        * This issue was detected only on simulation, but to avoid this issue
-        * driver add protection against it. To fix it driver enable ISO OUT
-        * endpoint before setting DRBL. This special treatment of ISO OUT
-        * endpoints are recommended by controller specification.
-        */
-       if (priv_ep->type == USB_ENDPOINT_XFER_ISOC  && !priv_ep->dir)
-               enable = 0;
-
-       if (enable)
-               cdns3_set_register_bit(&priv_dev->regs->ep_cfg, EP_CFG_ENABLE);
-
        ep->desc = desc;
        priv_ep->flags &= ~(EP_PENDING_REQUEST | EP_STALLED | EP_STALL_PENDING |
                            EP_QUIRK_ISO_OUT_EN | EP_QUIRK_EXTRA_BUF_EN);
@@ -3265,10 +3278,13 @@ err0:
 }
 
 static int cdns3_gadget_suspend(struct cdns3 *cdns, bool do_wakeup)
+__must_hold(&cdns->lock)
 {
        struct cdns3_device *priv_dev = cdns->gadget_dev;
 
+       spin_unlock(&cdns->lock);
        cdns3_disconnect_gadget(priv_dev);
+       spin_lock(&cdns->lock);
 
        priv_dev->gadget.speed = USB_SPEED_UNKNOWN;
        usb_gadget_set_state(&priv_dev->gadget, USB_STATE_NOTATTACHED);
index 1ccecd23753034edda19df66ab31910c4e14f752..21fa461c518ec269258012ff5ba6e35e79a18906 100644 (file)
@@ -1072,7 +1072,7 @@ struct cdns3_trb {
 #define TRB_TDL_SS_SIZE_GET(p) (((p) & GENMASK(23, 17)) >> 17)
 
 /* transfer_len bitmasks - bits 31:24 */
-#define TRB_BURST_LEN(p)       (((p) << 24) & GENMASK(31, 24))
+#define TRB_BURST_LEN(p)       ((unsigned int)((p) << 24) & GENMASK(31, 24))
 #define TRB_BURST_LEN_GET(p)   (((p) & GENMASK(31, 24)) >> 24)
 
 /* Data buffer pointer bitmasks*/
@@ -1159,6 +1159,7 @@ struct cdns3_endpoint {
 #define EP_QUIRK_EXTRA_BUF_DET BIT(12)
 #define EP_QUIRK_EXTRA_BUF_EN  BIT(13)
 #define EP_TDLCHK_EN           BIT(15)
+#define EP_CONFIGURED          BIT(16)
        u32                     flags;
 
        struct cdns3_request    *descmis_req;
@@ -1360,7 +1361,7 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep,
 int cdns3_init_ep0(struct cdns3_device *priv_dev,
                   struct cdns3_endpoint *priv_ep);
 void cdns3_ep0_config(struct cdns3_device *priv_dev);
-void cdns3_ep_config(struct cdns3_endpoint *priv_ep);
+int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable);
 void cdns3_check_ep0_interrupt_proceed(struct cdns3_device *priv_dev, int dir);
 int __cdns3_gadget_wakeup(struct cdns3_device *priv_dev);
 
index 30ef946a8e1a58964c28174ce0c34a0f9454ecaa..f52f1bc0559f9d306b1c3b72b4cc86327e7e583c 100644 (file)
@@ -508,6 +508,7 @@ static void acm_read_bulk_callback(struct urb *urb)
                        "%s - cooling babbling device\n", __func__);
                usb_mark_last_busy(acm->dev);
                set_bit(rb->index, &acm->urbs_in_error_delay);
+               set_bit(ACM_ERROR_DELAY, &acm->flags);
                cooldown = true;
                break;
        default:
@@ -533,7 +534,7 @@ static void acm_read_bulk_callback(struct urb *urb)
 
        if (stopped || stalled || cooldown) {
                if (stalled)
-                       schedule_work(&acm->work);
+                       schedule_delayed_work(&acm->dwork, 0);
                else if (cooldown)
                        schedule_delayed_work(&acm->dwork, HZ / 2);
                return;
@@ -563,13 +564,13 @@ static void acm_write_bulk(struct urb *urb)
        acm_write_done(acm, wb);
        spin_unlock_irqrestore(&acm->write_lock, flags);
        set_bit(EVENT_TTY_WAKEUP, &acm->flags);
-       schedule_work(&acm->work);
+       schedule_delayed_work(&acm->dwork, 0);
 }
 
 static void acm_softint(struct work_struct *work)
 {
        int i;
-       struct acm *acm = container_of(work, struct acm, work);
+       struct acm *acm = container_of(work, struct acm, dwork.work);
 
        if (test_bit(EVENT_RX_STALL, &acm->flags)) {
                smp_mb(); /* against acm_suspend() */
@@ -585,7 +586,7 @@ static void acm_softint(struct work_struct *work)
        if (test_and_clear_bit(ACM_ERROR_DELAY, &acm->flags)) {
                for (i = 0; i < acm->rx_buflimit; i++)
                        if (test_and_clear_bit(i, &acm->urbs_in_error_delay))
-                                       acm_submit_read_urb(acm, i, GFP_NOIO);
+                               acm_submit_read_urb(acm, i, GFP_KERNEL);
        }
 
        if (test_and_clear_bit(EVENT_TTY_WAKEUP, &acm->flags))
@@ -1351,7 +1352,6 @@ made_compressed_probe:
        acm->ctrlsize = ctrlsize;
        acm->readsize = readsize;
        acm->rx_buflimit = num_rx_buf;
-       INIT_WORK(&acm->work, acm_softint);
        INIT_DELAYED_WORK(&acm->dwork, acm_softint);
        init_waitqueue_head(&acm->wioctl);
        spin_lock_init(&acm->write_lock);
@@ -1561,7 +1561,6 @@ static void acm_disconnect(struct usb_interface *intf)
        }
 
        acm_kill_urbs(acm);
-       cancel_work_sync(&acm->work);
        cancel_delayed_work_sync(&acm->dwork);
 
        tty_unregister_device(acm_tty_driver, acm->minor);
@@ -1604,7 +1603,6 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
                return 0;
 
        acm_kill_urbs(acm);
-       cancel_work_sync(&acm->work);
        cancel_delayed_work_sync(&acm->dwork);
        acm->urbs_in_error_delay = 0;
 
@@ -1695,6 +1693,15 @@ static const struct usb_device_id acm_ids[] = {
        { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */
        .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
        },
+       { USB_DEVICE(0x045b, 0x023c),   /* Renesas USB Download mode */
+       .driver_info = DISABLE_ECHO,    /* Don't echo banner */
+       },
+       { USB_DEVICE(0x045b, 0x0248),   /* Renesas USB Download mode */
+       .driver_info = DISABLE_ECHO,    /* Don't echo banner */
+       },
+       { USB_DEVICE(0x045b, 0x024D),   /* Renesas USB Download mode */
+       .driver_info = DISABLE_ECHO,    /* Don't echo banner */
+       },
        { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */
        .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
        },
index 9dce179d031bb0d7e455c44aea13dedab112d8d3..8aef5eb769a0de0e5a7bd1e853ea867fcdfffd42 100644 (file)
@@ -112,8 +112,7 @@ struct acm {
 #              define ACM_ERROR_DELAY  3
        unsigned long urbs_in_error_delay;              /* these need to be restarted after a delay */
        struct usb_cdc_line_coding line;                /* bits, stop, parity */
-       struct work_struct work;                        /* work queue entry for various purposes*/
-       struct delayed_work dwork;                      /* for cool downs needed in error recovery */
+       struct delayed_work dwork;                      /* work queue entry for various purposes */
        unsigned int ctrlin;                            /* input control lines (DCD, DSR, RI, break, overruns) */
        unsigned int ctrlout;                           /* output control lines (DTR, RTS) */
        struct async_icount iocount;                    /* counters for control line changes */
index e96a858a12185bac3d5aa5e5b8d1b7caa6c3e38c..533236366a03b8d35b8c6a724946dff6d9fe44b3 100644 (file)
@@ -482,11 +482,11 @@ static void snoop_urb(struct usb_device *udev,
 
        if (userurb) {          /* Async */
                if (when == SUBMIT)
-                       dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, "
+                       dev_info(&udev->dev, "userurb %px, ep%d %s-%s, "
                                        "length %u\n",
                                        userurb, ep, t, d, length);
                else
-                       dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, "
+                       dev_info(&udev->dev, "userurb %px, ep%d %s-%s, "
                                        "actual_length %u status %d\n",
                                        userurb, ep, t, d, length,
                                        timeout_or_status);
@@ -1997,7 +1997,7 @@ static int proc_reapurb(struct usb_dev_state *ps, void __user *arg)
        if (as) {
                int retval;
 
-               snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
+               snoop(&ps->dev->dev, "reap %px\n", as->userurb);
                retval = processcompl(as, (void __user * __user *)arg);
                free_async(as);
                return retval;
@@ -2014,7 +2014,7 @@ static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg)
 
        as = async_getcompleted(ps);
        if (as) {
-               snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
+               snoop(&ps->dev->dev, "reap %px\n", as->userurb);
                retval = processcompl(as, (void __user * __user *)arg);
                free_async(as);
        } else {
@@ -2142,7 +2142,7 @@ static int proc_reapurb_compat(struct usb_dev_state *ps, void __user *arg)
        if (as) {
                int retval;
 
-               snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
+               snoop(&ps->dev->dev, "reap %px\n", as->userurb);
                retval = processcompl_compat(as, (void __user * __user *)arg);
                free_async(as);
                return retval;
@@ -2159,7 +2159,7 @@ static int proc_reapurbnonblock_compat(struct usb_dev_state *ps, void __user *ar
 
        as = async_getcompleted(ps);
        if (as) {
-               snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
+               snoop(&ps->dev->dev, "reap %px\n", as->userurb);
                retval = processcompl_compat(as, (void __user * __user *)arg);
                free_async(as);
        } else {
@@ -2624,7 +2624,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
 #endif
 
        case USBDEVFS_DISCARDURB:
-               snoop(&dev->dev, "%s: DISCARDURB %pK\n", __func__, p);
+               snoop(&dev->dev, "%s: DISCARDURB %px\n", __func__, p);
                ret = proc_unlinkurb(ps, p);
                break;
 
index 98b7449c11f3d04c92566fb2512cacdf08e6a90f..4dfa44d6cc3cf0666329b5c2b2a88680eee0503f 100644 (file)
@@ -839,6 +839,22 @@ const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
        return NULL;
 }
 
+bool usb_driver_applicable(struct usb_device *udev,
+                          struct usb_device_driver *udrv)
+{
+       if (udrv->id_table && udrv->match)
+               return usb_device_match_id(udev, udrv->id_table) != NULL &&
+                      udrv->match(udev);
+
+       if (udrv->id_table)
+               return usb_device_match_id(udev, udrv->id_table) != NULL;
+
+       if (udrv->match)
+               return udrv->match(udev);
+
+       return false;
+}
+
 static int usb_device_match(struct device *dev, struct device_driver *drv)
 {
        /* devices and interfaces are handled separately */
@@ -853,17 +869,14 @@ static int usb_device_match(struct device *dev, struct device_driver *drv)
                udev = to_usb_device(dev);
                udrv = to_usb_device_driver(drv);
 
-               if (udrv->id_table)
-                       return usb_device_match_id(udev, udrv->id_table) != NULL;
-
-               if (udrv->match)
-                       return udrv->match(udev);
-
                /* If the device driver under consideration does not have a
                 * id_table or a match function, then let the driver's probe
                 * function decide.
                 */
-               return 1;
+               if (!udrv->id_table && !udrv->match)
+                       return 1;
+
+               return usb_driver_applicable(udev, udrv);
 
        } else if (is_usb_interface(dev)) {
                struct usb_interface *intf;
@@ -941,8 +954,7 @@ static int __usb_bus_reprobe_drivers(struct device *dev, void *data)
                return 0;
 
        udev = to_usb_device(dev);
-       if (usb_device_match_id(udev, new_udriver->id_table) == NULL &&
-           (!new_udriver->match || new_udriver->match(udev) == 0))
+       if (!usb_driver_applicable(udev, new_udriver))
                return 0;
 
        ret = device_reprobe(dev);
index 22c887f5c49751e026c72ce19e2a35abb9100240..26f9fb9f67ca22537fe8bda301345bd5f0390de3 100644 (file)
@@ -205,9 +205,7 @@ static int __check_for_non_generic_match(struct device_driver *drv, void *data)
        udrv = to_usb_device_driver(drv);
        if (udrv == &usb_generic_driver)
                return 0;
-       if (usb_device_match_id(udev, udrv->id_table) != NULL)
-               return 1;
-       return (udrv->match && udrv->match(udev));
+       return usb_driver_applicable(udev, udrv);
 }
 
 static bool usb_generic_driver_match(struct usb_device *udev)
index 10574fa3f927742c0b46299c1f1cf5752754e2d8..fad31ccd1fa83828c71acc5ee84af2a40d33268f 100644 (file)
@@ -348,6 +348,10 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Guillemot Webcam Hercules Dualpix Exchange*/
        { USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Guillemot Hercules DJ Console audio card (BZ 208357) */
+       { USB_DEVICE(0x06f8, 0xb000), .driver_info =
+                       USB_QUIRK_ENDPOINT_IGNORE },
+
        /* Midiman M-Audio Keystation 88es */
        { USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME },
 
@@ -378,6 +382,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x0926, 0x3333), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
 
+       /* Kingston DataTraveler 3.0 */
+       { USB_DEVICE(0x0951, 0x1666), .driver_info = USB_QUIRK_NO_LPM },
+
        /* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */
        { USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF },
 
@@ -418,6 +425,10 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x1532, 0x0116), .driver_info =
                        USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
 
+       /* Lenovo ThinkCenter A630Z TI024Gen3 usb-audio */
+       { USB_DEVICE(0x17ef, 0xa012), .driver_info =
+                       USB_QUIRK_DISCONNECT_SUSPEND },
+
        /* BUILDWIN Photo Frame */
        { USB_DEVICE(0x1908, 0x1315), .driver_info =
                        USB_QUIRK_HONOR_BNUMINTERFACES },
@@ -518,6 +529,8 @@ static const struct usb_device_id usb_amd_resume_quirk_list[] = {
  * Matched for devices with USB_QUIRK_ENDPOINT_IGNORE.
  */
 static const struct usb_device_id usb_endpoint_ignore[] = {
+       { USB_DEVICE_INTERFACE_NUMBER(0x06f8, 0xb000, 5), .driver_info = 0x01 },
+       { USB_DEVICE_INTERFACE_NUMBER(0x06f8, 0xb000, 5), .driver_info = 0x81 },
        { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0202, 1), .driver_info = 0x85 },
        { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0208, 1), .driver_info = 0x85 },
        { }
index c893f54a3420a5c053c94f8983d5904c2438e944..82538daac8b8962b975dead6752706f44046b82a 100644 (file)
@@ -74,6 +74,8 @@ extern int usb_match_device(struct usb_device *dev,
                            const struct usb_device_id *id);
 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);
 extern void usb_forced_unbind_intf(struct usb_interface *intf);
 extern void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev);
 
index e2820676beb11f4984134ecd17c8cd937cbaee18..5f18acac7406885927b4d473045aaae94d474470 100644 (file)
@@ -608,10 +608,13 @@ static int dwc2_driver_probe(struct platform_device *dev)
 #endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
        return 0;
 
+#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
+       IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
 error_debugfs:
        dwc2_debugfs_exit(hsotg);
        if (hsotg->hcd_enabled)
                dwc2_hcd_remove(hsotg);
+#endif
 error_drd:
        dwc2_drd_exit(hsotg);
 
index bdf0925da6b642b54052d288f22daf42948369d6..841daec70b6efd808b1407da9a4ba561eb98c660 100644 (file)
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
-/**
+/*
  * core.c - DesignWare USB3 DRD Controller Core file
  *
  * Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com
index 74323b10a64ac5af7f215fde1a7d752e0d291170..2f95f08ca51190e89c14719ca880e726bef7c12b 100644 (file)
@@ -1277,7 +1277,7 @@ struct dwc3_event_type {
 #define DWC3_DEPEVT_EPCMDCMPLT         0x07
 
 /**
- * struct dwc3_event_depvt - Device Endpoint Events
+ * struct dwc3_event_depevt - Device Endpoint Events
  * @one_bit: indicates this is an endpoint event (not used)
  * @endpoint_number: number of the endpoint
  * @endpoint_event: The event we have:
index 242b6210380a4f383b9b24bc5511450e71178bc8..bae6a70664c80b48debc2a1569203c4c57008ea0 100644 (file)
@@ -40,6 +40,7 @@
 #define PCI_DEVICE_ID_INTEL_TGPLP              0xa0ee
 #define PCI_DEVICE_ID_INTEL_TGPH               0x43ee
 #define PCI_DEVICE_ID_INTEL_JSP                        0x4dee
+#define PCI_DEVICE_ID_INTEL_ADLS               0x7ae1
 
 #define PCI_INTEL_BXT_DSM_GUID         "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"
 #define PCI_INTEL_BXT_FUNC_PMU_PWR     4
@@ -367,6 +368,9 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_JSP),
          (kernel_ulong_t) &dwc3_pci_intel_properties, },
 
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADLS),
+         (kernel_ulong_t) &dwc3_pci_intel_properties, },
+
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_NL_USB),
          (kernel_ulong_t) &dwc3_pci_amd_properties, },
        {  }    /* Terminating Entry */
index 7be3903cb8427cd183b765a3e369f276429411f8..8b668ef46f7f1fbead3f3ef091229669e9006026 100644 (file)
@@ -1058,10 +1058,11 @@ void dwc3_ep0_send_delayed_status(struct dwc3 *dwc)
 {
        unsigned int direction = !dwc->ep0_expect_in;
 
+       dwc->delayed_status = false;
+
        if (dwc->ep0state != EP0_STATUS_PHASE)
                return;
 
-       dwc->delayed_status = false;
        __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
 }
 
index 05b176c82cc522b7416b0379915af615b3eac4ec..c6d455f2bb928b22cbedc5f0901221fdca997429 100644 (file)
@@ -1245,7 +1245,7 @@ int usb_string_id(struct usb_composite_dev *cdev)
 EXPORT_SYMBOL_GPL(usb_string_id);
 
 /**
- * usb_string_ids() - allocate unused string IDs in batch
+ * usb_string_ids_tab() - allocate unused string IDs in batch
  * @cdev: the device whose string descriptor IDs are being allocated
  * @str: an array of usb_string objects to assign numbers to
  * Context: single threaded during gadget setup
index 046f770a76dae1cd0d40cb028ae950bd797287d2..c727cb5de87183f6e9fc12455fe6368c9ff686fc 100644 (file)
@@ -1324,7 +1324,7 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
        case FUNCTIONFS_ENDPOINT_DESC:
        {
                int desc_idx;
-               struct usb_endpoint_descriptor *desc;
+               struct usb_endpoint_descriptor desc1, *desc;
 
                switch (epfile->ffs->gadget->speed) {
                case USB_SPEED_SUPER:
@@ -1336,10 +1336,12 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
                default:
                        desc_idx = 0;
                }
+
                desc = epfile->ep->descs[desc_idx];
+               memcpy(&desc1, desc, desc->bLength);
 
                spin_unlock_irq(&epfile->ffs->eps_lock);
-               ret = copy_to_user((void __user *)value, desc, desc->bLength);
+               ret = copy_to_user((void __user *)value, &desc1, desc1.bLength);
                if (ret)
                        ret = -EFAULT;
                return ret;
index 85cb15734aa8a6dda10dca5a879c6c8af90b9b12..19d97940eeb933c5e01f9e0cce4e070cae9d39b7 100644 (file)
@@ -1315,7 +1315,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
        midi->id = kstrdup(opts->id, GFP_KERNEL);
        if (opts->id && !midi->id) {
                status = -ENOMEM;
-               goto setup_fail;
+               goto midi_free;
        }
        midi->in_ports = opts->in_ports;
        midi->out_ports = opts->out_ports;
@@ -1327,7 +1327,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
 
        status = kfifo_alloc(&midi->in_req_fifo, midi->qlen, GFP_KERNEL);
        if (status)
-               goto setup_fail;
+               goto midi_free;
 
        spin_lock_init(&midi->transmit_lock);
 
@@ -1343,9 +1343,13 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
 
        return &midi->func;
 
+midi_free:
+       if (midi)
+               kfree(midi->id);
+       kfree(midi);
 setup_fail:
        mutex_unlock(&opts->lock);
-       kfree(midi);
+
        return ERR_PTR(status);
 }
 
index 1b430b36d0a6be6042732c586446129c09a823a5..71e7d10dd76b90b458582d69334662a9446005ff 100644 (file)
@@ -2039,6 +2039,9 @@ gadgetfs_fill_super (struct super_block *sb, struct fs_context *fc)
        return 0;
 
 Enomem:
+       kfree(CHIP);
+       CHIP = NULL;
+
        return -ENOMEM;
 }
 
index e01e366d89cd585cff3252c88e87cbe5691149d7..062dfac3039968d3f09868141aed177f91d8e5d4 100644 (file)
@@ -564,9 +564,12 @@ static int raw_ioctl_event_fetch(struct raw_dev *dev, unsigned long value)
                return -ENODEV;
        }
        length = min(arg.length, event->length);
-       if (copy_to_user((void __user *)value, event, sizeof(*event) + length))
+       if (copy_to_user((void __user *)value, event, sizeof(*event) + length)) {
+               kfree(event);
                return -EFAULT;
+       }
 
+       kfree(event);
        return 0;
 }
 
index de528e3b0662e7d536c46bb92b5e5776574ac4dd..ad6ff9c4188efb208635526583f4b63cb037a78b 100644 (file)
@@ -1051,7 +1051,7 @@ static int fsl_ep_fifo_status(struct usb_ep *_ep)
        u32 bitmask;
        struct ep_queue_head *qh;
 
-       if (!_ep || _ep->desc || !(_ep->desc->bEndpointAddress&0xF))
+       if (!_ep || !_ep->desc || !(_ep->desc->bEndpointAddress&0xF))
                return -ENODEV;
 
        ep = container_of(_ep, struct fsl_ep, ep);
index 25c1d6ab5adb457d4af5904dca7e3ff6b299a28b..3e1267d38774fa031000e5737161cc251b557de7 100644 (file)
@@ -1760,6 +1760,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto err;
        }
 
+       pci_set_drvdata(pdev, dev);
        spin_lock_init(&dev->lock);
        dev->pdev = pdev;
        dev->gadget.ops = &goku_ops;
@@ -1793,7 +1794,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        }
        dev->regs = (struct goku_udc_regs __iomem *) base;
 
-       pci_set_drvdata(pdev, dev);
        INFO(dev, "%s\n", driver_desc);
        INFO(dev, "version: " DRIVER_VERSION " %s\n", dmastr());
        INFO(dev, "irq %d, pci mem %p\n", pdev->irq, base);
index e077b2ca53c517032d0a9816a56632a36aa7cd20..869d9c4de5fcd3dbfdf5723b63b188d59a50417d 100644 (file)
@@ -479,8 +479,8 @@ static int tegra_ehci_probe(struct platform_device *pdev)
        u_phy->otg->host = hcd_to_bus(hcd);
 
        irq = platform_get_irq(pdev, 0);
-       if (!irq) {
-               err = -ENODEV;
+       if (irq < 0) {
+               err = irq;
                goto cleanup_phy;
        }
 
index ae8f60f6e6a5e092bfd314e143fdf6816079e912..44a7e58a26e3ddc0edbf1a345254c1c4472a2dd5 100644 (file)
@@ -94,10 +94,13 @@ static struct platform_device *fsl_usb2_device_register(
 
        pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask;
 
-       if (!pdev->dev.dma_mask)
+       if (!pdev->dev.dma_mask) {
                pdev->dev.dma_mask = &ofdev->dev.coherent_dma_mask;
-       else
-               dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+       } else {
+               retval = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+               if (retval)
+                       goto error;
+       }
 
        retval = platform_device_add_data(pdev, pdata, sizeof(*pdata));
        if (retval)
index 9ccdf2c216b513f7af5fc34c688dfeed88e17f51..6374501ba1390d16e496ead39cb7274a60cc2bf2 100644 (file)
@@ -91,14 +91,14 @@ static int omap_ohci_transceiver_power(struct ohci_omap_priv *priv, int on)
                                | ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
                               INNOVATOR_FPGA_CAM_USB_CONTROL);
                else if (priv->power)
-                       gpiod_set_value(priv->power, 0);
+                       gpiod_set_value_cansleep(priv->power, 0);
        } else {
                if (machine_is_omap_innovator() && cpu_is_omap1510())
                        __raw_writeb(__raw_readb(INNOVATOR_FPGA_CAM_USB_CONTROL)
                                & ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
                               INNOVATOR_FPGA_CAM_USB_CONTROL);
                else if (priv->power)
-                       gpiod_set_value(priv->power, 1);
+                       gpiod_set_value_cansleep(priv->power, 1);
        }
 
        return 0;
index 5546e7e013a8895f8968573c464f84d341f81f4d..08369857686e731f809cc95bb529416a26b65e8a 100644 (file)
@@ -240,7 +240,7 @@ static int xhci_histb_probe(struct platform_device *pdev)
        /* Initialize dma_mask and coherent_dma_mask to 32-bits */
        ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
        if (ret)
-               return ret;
+               goto disable_pm;
 
        hcd = usb_create_hcd(driver, dev, dev_name(dev));
        if (!hcd) {
index fe405cd38dbc11790b5fd91e41d78f8136c306e9..138ba4528dd3a8dba3452b2f49ffe570460a365e 100644 (file)
@@ -2252,8 +2252,8 @@ static void xhci_create_rhub_port_array(struct xhci_hcd *xhci,
 
        if (!rhub->num_ports)
                return;
-       rhub->ports = kcalloc_node(rhub->num_ports, sizeof(rhub->ports), flags,
-                       dev_to_node(dev));
+       rhub->ports = kcalloc_node(rhub->num_ports, sizeof(*rhub->ports),
+                       flags, dev_to_node(dev));
        for (i = 0; i < HCS_MAX_PORTS(xhci->hcs_params1); i++) {
                if (xhci->hw_ports[i].rhub != rhub ||
                    xhci->hw_ports[i].hcd_portnum == DUPLICATE_ENTRY)
index c26c06e5c88cde4430100b42adc6a2d414efcf50..bf89172c43cace41449d5099653fb135c533c0e8 100644 (file)
@@ -23,6 +23,8 @@
 #define SSIC_PORT_CFG2_OFFSET  0x30
 #define PROG_DONE              (1 << 30)
 #define SSIC_PORT_UNUSED       (1 << 31)
+#define SPARSE_DISABLE_BIT     17
+#define SPARSE_CNTL_ENABLE     0xC12C
 
 /* Device for a quirk */
 #define PCI_VENDOR_ID_FRESCO_LOGIC     0x1b73
@@ -161,6 +163,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
            (pdev->device == 0x15e0 || pdev->device == 0x15e1))
                xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND;
 
+       if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x15e5)
+               xhci->quirks |= XHCI_DISABLE_SPARSE;
+
        if (pdev->vendor == PCI_VENDOR_ID_AMD)
                xhci->quirks |= XHCI_TRUST_TX_LENGTH;
 
@@ -498,6 +503,15 @@ static void xhci_pme_quirk(struct usb_hcd *hcd)
        readl(reg);
 }
 
+static void xhci_sparse_control_quirk(struct usb_hcd *hcd)
+{
+       u32 reg;
+
+       reg = readl(hcd->regs + SPARSE_CNTL_ENABLE);
+       reg &= ~BIT(SPARSE_DISABLE_BIT);
+       writel(reg, hcd->regs + SPARSE_CNTL_ENABLE);
+}
+
 static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
@@ -517,6 +531,9 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
        if (xhci->quirks & XHCI_SSIC_PORT_UNUSED)
                xhci_ssic_port_unused_quirk(hcd, true);
 
+       if (xhci->quirks & XHCI_DISABLE_SPARSE)
+               xhci_sparse_control_quirk(hcd);
+
        ret = xhci_suspend(xhci, do_wakeup);
        if (ret && (xhci->quirks & XHCI_SSIC_PORT_UNUSED))
                xhci_ssic_port_unused_quirk(hcd, false);
index 482fe8c5e3b4778e1514d36e9fe22385e756fd75..d4a8d0efbbc4d6f06bcb3b807dce9f85837fb19b 100644 (file)
@@ -3533,11 +3533,14 @@ static int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
                xhci_dbg(xhci, "Slot %u ep ctx %u now has streams.\n",
                         udev->slot_id, ep_index);
                vdev->eps[ep_index].ep_state |= EP_HAS_STREAMS;
-               xhci_debugfs_create_stream_files(xhci, vdev, ep_index);
        }
        xhci_free_command(xhci, config_cmd);
        spin_unlock_irqrestore(&xhci->lock, flags);
 
+       for (i = 0; i < num_eps; i++) {
+               ep_index = xhci_get_endpoint_index(&eps[i]->desc);
+               xhci_debugfs_create_stream_files(xhci, vdev, ep_index);
+       }
        /* Subtract 1 for stream 0, which drivers can't use */
        return num_streams - 1;
 
index 8be88379c0fb232bc306bd8ebcde7e23fae1fd16..ebb359ebb261c180e17cb1ee2c44ba6ee350999c 100644 (file)
@@ -1877,6 +1877,7 @@ struct xhci_hcd {
 #define XHCI_SNPS_BROKEN_SUSPEND    BIT_ULL(35)
 #define XHCI_RENESAS_FW_QUIRK  BIT_ULL(36)
 #define XHCI_SKIP_PHY_INIT     BIT_ULL(37)
+#define XHCI_DISABLE_SPARSE    BIT_ULL(38)
 
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;
index b403094a6b3a5058840074cff6d76a268e2ad6e9..9de0171b517763951b733774ca675aef94a29a7e 100644 (file)
@@ -120,8 +120,10 @@ static int apple_mfi_fc_set_property(struct power_supply *psy,
        dev_dbg(&mfi->udev->dev, "prop: %d\n", psp);
 
        ret = pm_runtime_get_sync(&mfi->udev->dev);
-       if (ret < 0)
+       if (ret < 0) {
+               pm_runtime_put_noidle(&mfi->udev->dev);
                return ret;
+       }
 
        switch (psp) {
        case POWER_SUPPLY_PROP_CHARGE_TYPE:
@@ -163,17 +165,23 @@ static const struct power_supply_desc apple_mfi_fc_desc = {
        .property_is_writeable  = apple_mfi_fc_property_is_writeable
 };
 
+static bool mfi_fc_match(struct usb_device *udev)
+{
+       int idProduct;
+
+       idProduct = le16_to_cpu(udev->descriptor.idProduct);
+       /* See comment above mfi_fc_id_table[] */
+       return (idProduct >= 0x1200 && idProduct <= 0x12ff);
+}
+
 static int mfi_fc_probe(struct usb_device *udev)
 {
        struct power_supply_config battery_cfg = {};
        struct mfi_device *mfi = NULL;
-       int err, idProduct;
+       int err;
 
-       idProduct = le16_to_cpu(udev->descriptor.idProduct);
-       /* See comment above mfi_fc_id_table[] */
-       if (idProduct < 0x1200 || idProduct > 0x12ff) {
+       if (!mfi_fc_match(udev))
                return -ENODEV;
-       }
 
        mfi = kzalloc(sizeof(struct mfi_device), GFP_KERNEL);
        if (!mfi) {
@@ -220,6 +228,7 @@ static struct usb_device_driver mfi_fc_driver = {
        .probe =        mfi_fc_probe,
        .disconnect =   mfi_fc_disconnect,
        .id_table =     mfi_fc_id_table,
+       .match =        mfi_fc_match,
        .generic_subclass = 1,
 };
 
index 1de5c9a1d20a1b885601523d8c019f8de497b2fa..38f17d66d5bc16a3b4bf06b9c543d342ad39a0af 100644 (file)
@@ -564,6 +564,7 @@ static int mtu3_gadget_stop(struct usb_gadget *g)
 
        spin_unlock_irqrestore(&mtu->lock, flags);
 
+       synchronize_irq(mtu->irq);
        return 0;
 }
 
index 30085b2be7b90bf132641e0e726e57b4d5048e8d..5892f3ce0cdc824d41d32031069b515713edeb5b 100644 (file)
@@ -429,10 +429,12 @@ static int dsps_musb_init(struct musb *musb)
        struct platform_device *parent = to_platform_device(dev->parent);
        const struct dsps_musb_wrapper *wrp = glue->wrp;
        void __iomem *reg_base;
+       struct resource *r;
        u32 rev, val;
        int ret;
 
-       reg_base = devm_platform_ioremap_resource_byname(parent, "control");
+       r = platform_get_resource_byname(parent, IORESOURCE_MEM, "control");
+       reg_base = devm_ioremap_resource(dev, r);
        if (IS_ERR(reg_base))
                return PTR_ERR(reg_base);
        musb->ctrl_base = reg_base;
index a2e2f56c88cd0783f06c3214da0c41055ec8af0b..28deaaec581f6ef91f252fe99cd6cc99db571080 100644 (file)
 #define CH341_QUIRK_SIMULATE_BREAK     BIT(1)
 
 static const struct usb_device_id id_table[] = {
-       { USB_DEVICE(0x4348, 0x5523) },
+       { USB_DEVICE(0x1a86, 0x5512) },
+       { USB_DEVICE(0x1a86, 0x5523) },
        { USB_DEVICE(0x1a86, 0x7522) },
        { USB_DEVICE(0x1a86, 0x7523) },
-       { USB_DEVICE(0x1a86, 0x5523) },
+       { USB_DEVICE(0x4348, 0x5523) },
        { },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
index 821970609695befc0a0f4a04a8b758baba3b988c..2e40908963dafc2c299cd770f3116dfbbfcacc93 100644 (file)
@@ -357,11 +357,12 @@ static void cyberjack_write_bulk_callback(struct urb *urb)
        struct device *dev = &port->dev;
        int status = urb->status;
        unsigned long flags;
+       bool resubmitted = false;
 
-       set_bit(0, &port->write_urbs_free);
        if (status) {
                dev_dbg(dev, "%s - nonzero write bulk status received: %d\n",
                        __func__, status);
+               set_bit(0, &port->write_urbs_free);
                return;
        }
 
@@ -394,6 +395,8 @@ static void cyberjack_write_bulk_callback(struct urb *urb)
                        goto exit;
                }
 
+               resubmitted = true;
+
                dev_dbg(dev, "%s - priv->wrsent=%d\n", __func__, priv->wrsent);
                dev_dbg(dev, "%s - priv->wrfilled=%d\n", __func__, priv->wrfilled);
 
@@ -410,6 +413,8 @@ static void cyberjack_write_bulk_callback(struct urb *urb)
 
 exit:
        spin_unlock_irqrestore(&priv->lock, flags);
+       if (!resubmitted)
+               set_bit(0, &port->write_urbs_free);
        usb_serial_port_softint(port);
 }
 
index 5ee48b0650c45f146d92813f76253c3f51a828e2..5f6b82ebccc5ac0449e33b7a03d020a256886cd8 100644 (file)
@@ -276,12 +276,12 @@ static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
        priv->cfg.unknown2 = cfg->unknown2;
        spin_unlock_irqrestore(&priv->lock, flags);
 
+       kfree(cfg);
+
        /* READ_ON and urb submission */
        rc = usb_serial_generic_open(tty, port);
-       if (rc) {
-               retval = rc;
-               goto err_free_cfg;
-       }
+       if (rc)
+               return rc;
 
        rc = usb_control_msg(port->serial->dev,
                             usb_sndctrlpipe(port->serial->dev, 0),
@@ -324,8 +324,6 @@ err_disable_read:
                             KLSI_TIMEOUT);
 err_generic_close:
        usb_serial_generic_close(port);
-err_free_cfg:
-       kfree(cfg);
 
        return retval;
 }
index 2a3bfd6f867ed5acbf97aeed1da5e75d3b3d4738..56d6f6d83bd788686ca7907d799f6157cd72ce3b 100644 (file)
@@ -250,6 +250,7 @@ static void option_instat_callback(struct urb *urb);
 #define QUECTEL_PRODUCT_EP06                   0x0306
 #define QUECTEL_PRODUCT_EM12                   0x0512
 #define QUECTEL_PRODUCT_RM500Q                 0x0800
+#define QUECTEL_PRODUCT_EC200T                 0x6026
 
 #define CMOTECH_VENDOR_ID                      0x16d8
 #define CMOTECH_PRODUCT_6001                   0x6001
@@ -418,6 +419,7 @@ static void option_instat_callback(struct urb *urb);
 #define CINTERION_PRODUCT_PH8                  0x0053
 #define CINTERION_PRODUCT_AHXX                 0x0055
 #define CINTERION_PRODUCT_PLXX                 0x0060
+#define CINTERION_PRODUCT_EXS82                        0x006c
 #define CINTERION_PRODUCT_PH8_2RMNET           0x0082
 #define CINTERION_PRODUCT_PH8_AUDIO            0x0083
 #define CINTERION_PRODUCT_AHXX_2RMNET          0x0084
@@ -1104,9 +1106,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0xff, 0xff),
          .driver_info = NUMEP2 },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0, 0) },
-       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96, 0xff, 0xff, 0xff),
-         .driver_info = NUMEP2 },
-       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96, 0xff, 0, 0) },
+       { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
+         .driver_info = RSVD(4) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
          .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },
@@ -1117,6 +1118,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x10),
          .driver_info = ZLP },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) },
 
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
@@ -1189,6 +1191,8 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = NCTRL(0) | RSVD(1) },
        { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1054, 0xff),    /* Telit FT980-KS */
          .driver_info = NCTRL(2) | RSVD(3) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1055, 0xff),    /* Telit FN980 (PCIe) */
+         .driver_info = NCTRL(0) | RSVD(1) },
        { 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),
@@ -1201,6 +1205,8 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = NCTRL(0) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
          .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1203, 0xff),    /* Telit LE910Cx (RNDIS) */
+         .driver_info = NCTRL(2) | RSVD(3) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4),
          .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) | RSVD(3) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
@@ -1215,6 +1221,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920A4_1213, 0xff) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920A4_1214),
          .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) | RSVD(3) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1230, 0xff),    /* Telit LE910Cx (rmnet) */
+         .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1231, 0xff),    /* Telit LE910Cx (RNDIS) */
+         .driver_info = NCTRL(2) | RSVD(3) },
        { USB_DEVICE(TELIT_VENDOR_ID, 0x1260),
          .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
        { USB_DEVICE(TELIT_VENDOR_ID, 0x1261),
@@ -1892,6 +1902,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX_AUDIO, 0xff) },
        { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_CLS8, 0xff),
          .driver_info = RSVD(0) | RSVD(4) },
+       { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EXS82, 0xff) },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
        { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) },
@@ -2036,12 +2047,13 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = RSVD(0) | RSVD(1) | RSVD(6) },
        { USB_DEVICE(0x0489, 0xe0b5),                                           /* Foxconn T77W968 ESIM */
          .driver_info = RSVD(0) | RSVD(1) | RSVD(6) },
-       { USB_DEVICE(0x1508, 0x1001),                                           /* Fibocom NL668 */
+       { USB_DEVICE(0x1508, 0x1001),                                           /* Fibocom NL668 (IOT version) */
          .driver_info = RSVD(4) | RSVD(5) | RSVD(6) },
        { USB_DEVICE(0x2cb7, 0x0104),                                           /* Fibocom NL678 series */
          .driver_info = RSVD(4) | RSVD(5) },
        { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff),                     /* Fibocom NL678 series */
          .driver_info = RSVD(6) },
+       { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) },                   /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */
        { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) },                   /* GosunCn GM500 RNDIS */
        { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) },                   /* GosunCn GM500 MBIM */
        { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) },                   /* GosunCn GM500 ECM/NCM */
index 560efd1479ba779d812a7001115b07070ff93a2b..e5a971b83e3f567d17623b88e1826b5bd429dfdb 100644 (file)
@@ -92,7 +92,7 @@ static int slave_alloc (struct scsi_device *sdev)
 static int slave_configure(struct scsi_device *sdev)
 {
        struct us_data *us = host_to_us(sdev->host);
-       struct device *dev = sdev->host->dma_dev;
+       struct device *dev = us->pusb_dev->bus->sysdev;
 
        /*
         * Many devices have trouble transferring more than 32KB at a time,
index c8a577309e8fbe027a103effdd9f01e156a8ca17..652d6d6f1f36529e52f1ba713cb7b702588606e1 100644 (file)
@@ -837,24 +837,17 @@ static int uas_slave_alloc(struct scsi_device *sdev)
         */
        blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
 
+       if (devinfo->flags & US_FL_MAX_SECTORS_64)
+               blk_queue_max_hw_sectors(sdev->request_queue, 64);
+       else if (devinfo->flags & US_FL_MAX_SECTORS_240)
+               blk_queue_max_hw_sectors(sdev->request_queue, 240);
+
        return 0;
 }
 
 static int uas_slave_configure(struct scsi_device *sdev)
 {
        struct uas_dev_info *devinfo = sdev->hostdata;
-       struct device *dev = sdev->host->dma_dev;
-
-       if (devinfo->flags & US_FL_MAX_SECTORS_64)
-               blk_queue_max_hw_sectors(sdev->request_queue, 64);
-       else if (devinfo->flags & US_FL_MAX_SECTORS_240)
-               blk_queue_max_hw_sectors(sdev->request_queue, 240);
-       else if (devinfo->udev->speed >= USB_SPEED_SUPER)
-               blk_queue_max_hw_sectors(sdev->request_queue, 2048);
-
-       blk_queue_max_hw_sectors(sdev->request_queue,
-               min_t(size_t, queue_max_hw_sectors(sdev->request_queue),
-                     dma_max_mapping_size(dev) >> SECTOR_SHIFT));
 
        if (devinfo->flags & US_FL_NO_REPORT_OPCODES)
                sdev->no_report_opcodes = 1;
@@ -1040,7 +1033,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
        shost->can_queue = devinfo->qdepth - 2;
 
        usb_set_intfdata(intf, shost);
-       result = scsi_add_host_with_dma(shost, &intf->dev, udev->bus->sysdev);
+       result = scsi_add_host(shost, &intf->dev);
        if (result)
                goto free_streams;
 
index c2ef367cf2571b0c42a7038bd864bf578a29a800..94a64729dc27d6365a42bbd3ea9cdc80ec2da9fb 100644 (file)
@@ -1049,9 +1049,8 @@ int usb_stor_probe2(struct us_data *us)
                goto BadDevice;
        usb_autopm_get_interface_no_resume(us->pusb_intf);
        snprintf(us->scsi_name, sizeof(us->scsi_name), "usb-storage %s",
-                                       dev_name(dev));
-       result = scsi_add_host_with_dma(us_to_host(us), dev,
-                                       us->pusb_dev->bus->sysdev);
+                                       dev_name(&us->pusb_intf->dev));
+       result = scsi_add_host(us_to_host(us), dev);
        if (result) {
                dev_warn(dev,
                                "Unable to add the scsi host\n");
index 6c5908a37ee8ff5dcfbbbd4c03b4a0350c097de0..e7f120874c48379669195699f65729e28a05686d 100644 (file)
@@ -88,6 +88,7 @@ config TYPEC_STUSB160X
 config TYPEC_QCOM_PMIC
        tristate "Qualcomm PMIC USB Type-C driver"
        depends on ARCH_QCOM || COMPILE_TEST
+       depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH
        help
          Driver for supporting role switch over the Qualcomm PMIC.  This will
          handle the USB Type-C role and orientation detection reported by the
index b069a5122aaa9b162a475eb410cc3ef1cc1b261c..cf720e944aaaa44eba12eb87d06d2e96c4ab9afa 100644 (file)
@@ -71,7 +71,7 @@ struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode)
 EXPORT_SYMBOL_GPL(fwnode_typec_switch_get);
 
 /**
- * typec_put_switch - Release USB Type-C orientation switch
+ * typec_switch_put - Release USB Type-C orientation switch
  * @sw: USB Type-C orientation switch
  *
  * Decrement reference count for @sw.
index ce0bd7b3ad88e4293b53e86bb839a113c3f41492..d21750bbbb44d1f54c46d58b38925b2f2cf002fd 100644 (file)
@@ -544,11 +544,10 @@ static int stusb160x_get_fw_caps(struct stusb160x *chip,
         */
        ret = fwnode_property_read_string(fwnode, "power-role", &cap_str);
        if (!ret) {
-               chip->port_type = typec_find_port_power_role(cap_str);
-               if (chip->port_type < 0) {
-                       ret = chip->port_type;
+               ret = typec_find_port_power_role(cap_str);
+               if (ret < 0)
                        return ret;
-               }
+               chip->port_type = ret;
        }
        chip->capability.type = chip->port_type;
 
@@ -563,17 +562,15 @@ static int stusb160x_get_fw_caps(struct stusb160x *chip,
         * Supported power operation mode can be configured through device tree
         * else it is read from chip registers in stusb160x_get_caps.
         */
-       ret = fwnode_property_read_string(fwnode, "power-opmode", &cap_str);
+       ret = fwnode_property_read_string(fwnode, "typec-power-opmode", &cap_str);
        if (!ret) {
-               chip->pwr_opmode = typec_find_pwr_opmode(cap_str);
+               ret = typec_find_pwr_opmode(cap_str);
                /* Power delivery not yet supported */
-               if (chip->pwr_opmode < 0 ||
-                   chip->pwr_opmode == TYPEC_PWR_MODE_PD) {
-                       ret = chip->pwr_opmode < 0 ? chip->pwr_opmode : -EINVAL;
-                       dev_err(chip->dev, "bad power operation mode: %d\n",
-                               chip->pwr_opmode);
-                       return ret;
+               if (ret < 0 || ret == TYPEC_PWR_MODE_PD) {
+                       dev_err(chip->dev, "bad power operation mode: %d\n", ret);
+                       return -EINVAL;
                }
+               chip->pwr_opmode = ret;
        }
 
        return 0;
@@ -632,6 +629,7 @@ static const struct of_device_id stusb160x_of_match[] = {
        { .compatible = "st,stusb1600", .data = &stusb1600_regmap_config},
        {},
 };
+MODULE_DEVICE_TABLE(of, stusb160x_of_match);
 
 static int stusb160x_probe(struct i2c_client *client)
 {
@@ -729,8 +727,8 @@ static int stusb160x_probe(struct i2c_client *client)
        }
 
        chip->port = typec_register_port(chip->dev, &chip->capability);
-       if (!chip->port) {
-               ret = -ENODEV;
+       if (IS_ERR(chip->port)) {
+               ret = PTR_ERR(chip->port);
                goto all_reg_disable;
        }
 
index 55535c4f66bfab241aa433480bd56bee9c3b4555..a6fae1f865051bcb28c96a74bd12ab04b37775b8 100644 (file)
@@ -2890,6 +2890,9 @@ static void tcpm_reset_port(struct tcpm_port *port)
 
 static void tcpm_detach(struct tcpm_port *port)
 {
+       if (tcpm_port_is_disconnected(port))
+               port->hard_reset_count = 0;
+
        if (!port->attached)
                return;
 
@@ -2898,9 +2901,6 @@ static void tcpm_detach(struct tcpm_port *port)
                port->tcpc->set_bist_data(port->tcpc, false);
        }
 
-       if (tcpm_port_is_disconnected(port))
-               port->hard_reset_count = 0;
-
        tcpm_reset_port(port);
 }
 
index 26ed0b520749a24e61659f3d2bc8ed25a51fe618..571a51e162346159b7acb079a889a2d2f803d4dd 100644 (file)
@@ -238,4 +238,13 @@ void ucsi_unregister_port_psy(struct ucsi_connector *con)
                return;
 
        power_supply_unregister(con->psy);
+       con->psy = NULL;
+}
+
+void ucsi_port_psy_changed(struct ucsi_connector *con)
+{
+       if (IS_ERR_OR_NULL(con->psy))
+               return;
+
+       power_supply_changed(con->psy);
 }
index 758b988ac518a79bc43618be9d3057d693c247a1..51a570d40a42e0a3e5af47ec7517b6ba642fe018 100644 (file)
@@ -643,8 +643,10 @@ static void ucsi_handle_connector_change(struct work_struct *work)
        role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR);
 
        if (con->status.change & UCSI_CONSTAT_POWER_OPMODE_CHANGE ||
-           con->status.change & UCSI_CONSTAT_POWER_LEVEL_CHANGE)
+           con->status.change & UCSI_CONSTAT_POWER_LEVEL_CHANGE) {
                ucsi_pwr_opmode_change(con);
+               ucsi_port_psy_changed(con);
+       }
 
        if (con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) {
                typec_set_pwr_role(con->port, role);
@@ -674,6 +676,8 @@ static void ucsi_handle_connector_change(struct work_struct *work)
                        ucsi_register_partner(con);
                else
                        ucsi_unregister_partner(con);
+
+               ucsi_port_psy_changed(con);
        }
 
        if (con->status.change & UCSI_CONSTAT_CAM_CHANGE) {
@@ -994,6 +998,7 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
                                  !!(con->status.flags & UCSI_CONSTAT_PWR_DIR));
                ucsi_pwr_opmode_change(con);
                ucsi_register_partner(con);
+               ucsi_port_psy_changed(con);
        }
 
        if (con->partner) {
index cba6f77bea61b08ee0369426a2533744cb3b3b45..b7a92f24605077031000f5588be7cfe46859a386 100644 (file)
@@ -340,9 +340,11 @@ int ucsi_resume(struct ucsi *ucsi);
 #if IS_ENABLED(CONFIG_POWER_SUPPLY)
 int ucsi_register_port_psy(struct ucsi_connector *con);
 void ucsi_unregister_port_psy(struct ucsi_connector *con);
+void ucsi_port_psy_changed(struct ucsi_connector *con);
 #else
 static inline int ucsi_register_port_psy(struct ucsi_connector *con) { return 0; }
 static inline void ucsi_unregister_port_psy(struct ucsi_connector *con) { }
+static inline void ucsi_port_psy_changed(struct ucsi_connector *con) { }
 #endif /* CONFIG_POWER_SUPPLY */
 
 #if IS_ENABLED(CONFIG_TYPEC_DP_ALTMODE)
index d7d32b65610218e2c4606ef3385417eed003c323..6caf539091e55e63f71b5bdfcd923fa8c61148df 100644 (file)
@@ -13,6 +13,7 @@ config VDPA_SIM
        depends on RUNTIME_TESTING_MENU && HAS_DMA
        select DMA_OPS
        select VHOST_RING
+       select GENERIC_NET_UTILS
        default n
        help
          vDPA networking device simulator which loop TX traffic back
@@ -31,6 +32,7 @@ config IFCVF
 
 config MLX5_VDPA
        bool
+       select VHOST_IOTLB
        help
          Support library for Mellanox VDPA drivers. Provides code that is
          common for all types of VDPA drivers. The following drivers are planned:
index ef1c550f8266255464ad816e99274a70026647b8..4b6195666c589512329f4a5886cf2ba9c7486bf2 100644 (file)
@@ -239,7 +239,6 @@ static int map_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr
        u64 paend;
        struct scatterlist *sg;
        struct device *dma = mvdev->mdev->device;
-       int ret;
 
        for (map = vhost_iotlb_itree_first(iotlb, mr->start, mr->end - 1);
             map; map = vhost_iotlb_itree_next(map, start, mr->end - 1)) {
@@ -277,8 +276,8 @@ static int map_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr
 done:
        mr->log_size = log_entity_size;
        mr->nsg = nsg;
-       ret = dma_map_sg_attrs(dma, mr->sg_head.sgl, mr->nsg, DMA_BIDIRECTIONAL, 0);
-       if (!ret)
+       err = dma_map_sg_attrs(dma, mr->sg_head.sgl, mr->nsg, DMA_BIDIRECTIONAL, 0);
+       if (!err)
                goto err_map;
 
        err = create_direct_mr(mvdev, mr);
index 2629911c29bbf4e341982434682a8e5975d8c4d0..6a90fdb9cbfc6f8070a43692b858f9349d577f0e 100644 (file)
@@ -38,6 +38,10 @@ static int batch_mapping = 1;
 module_param(batch_mapping, int, 0444);
 MODULE_PARM_DESC(batch_mapping, "Batched mapping 1 -Enable; 0 - Disable");
 
+static char *macaddr;
+module_param(macaddr, charp, 0);
+MODULE_PARM_DESC(macaddr, "Ethernet MAC address");
+
 struct vdpasim_virtqueue {
        struct vringh vring;
        struct vringh_kiov iov;
@@ -60,7 +64,8 @@ struct vdpasim_virtqueue {
 
 static u64 vdpasim_features = (1ULL << VIRTIO_F_ANY_LAYOUT) |
                              (1ULL << VIRTIO_F_VERSION_1)  |
-                             (1ULL << VIRTIO_F_ACCESS_PLATFORM);
+                             (1ULL << VIRTIO_F_ACCESS_PLATFORM) |
+                             (1ULL << VIRTIO_NET_F_MAC);
 
 /* State of each vdpasim device */
 struct vdpasim {
@@ -361,7 +366,9 @@ static struct vdpasim *vdpasim_create(void)
        spin_lock_init(&vdpasim->iommu_lock);
 
        dev = &vdpasim->vdpa.dev;
-       dev->coherent_dma_mask = DMA_BIT_MASK(64);
+       dev->dma_mask = &dev->coherent_dma_mask;
+       if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)))
+               goto err_iommu;
        set_dma_ops(dev, &vdpasim_dma_ops);
 
        vdpasim->iommu = vhost_iotlb_alloc(2048, 0);
@@ -372,7 +379,15 @@ static struct vdpasim *vdpasim_create(void)
        if (!vdpasim->buffer)
                goto err_iommu;
 
-       eth_random_addr(vdpasim->config.mac);
+       if (macaddr) {
+               mac_pton(macaddr, vdpasim->config.mac);
+               if (!is_valid_ether_addr(vdpasim->config.mac)) {
+                       ret = -EADDRNOTAVAIL;
+                       goto err_iommu;
+               }
+       } else {
+               eth_random_addr(vdpasim->config.mac);
+       }
 
        vringh_set_iotlb(&vdpasim->vqs[0].vring, vdpasim->iommu);
        vringh_set_iotlb(&vdpasim->vqs[1].vring, vdpasim->iommu);
@@ -574,6 +589,16 @@ static u32 vdpasim_get_generation(struct vdpa_device *vdpa)
        return vdpasim->generation;
 }
 
+static struct vdpa_iova_range vdpasim_get_iova_range(struct vdpa_device *vdpa)
+{
+       struct vdpa_iova_range range = {
+               .first = 0ULL,
+               .last = ULLONG_MAX,
+       };
+
+       return range;
+}
+
 static int vdpasim_set_map(struct vdpa_device *vdpa,
                           struct vhost_iotlb *iotlb)
 {
@@ -657,6 +682,7 @@ static const struct vdpa_config_ops vdpasim_net_config_ops = {
        .get_config             = vdpasim_get_config,
        .set_config             = vdpasim_set_config,
        .get_generation         = vdpasim_get_generation,
+       .get_iova_range         = vdpasim_get_iova_range,
        .dma_map                = vdpasim_dma_map,
        .dma_unmap              = vdpasim_dma_unmap,
        .free                   = vdpasim_free,
@@ -683,6 +709,7 @@ static const struct vdpa_config_ops vdpasim_net_batch_config_ops = {
        .get_config             = vdpasim_get_config,
        .set_config             = vdpasim_set_config,
        .get_generation         = vdpasim_get_generation,
+       .get_iova_range         = vdpasim_get_iova_range,
        .set_map                = vdpasim_set_map,
        .free                   = vdpasim_free,
 };
index 0113a980f974955a42812ba8e8ef54038617ffd1..f27e25112c4037dc7e3d9926f970fca358dcc648 100644 (file)
@@ -248,7 +248,9 @@ static long vfio_fsl_mc_ioctl(void *device_data, unsigned int cmd,
                info.size = vdev->regions[info.index].size;
                info.flags = vdev->regions[info.index].flags;
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               if (copy_to_user((void __user *)arg, &info, minsz))
+                       return -EFAULT;
+               return 0;
        }
        case VFIO_DEVICE_GET_IRQ_INFO:
        {
@@ -267,7 +269,9 @@ static long vfio_fsl_mc_ioctl(void *device_data, unsigned int cmd,
                info.flags = VFIO_IRQ_INFO_EVENTFD;
                info.count = 1;
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               if (copy_to_user((void __user *)arg, &info, minsz))
+                       return -EFAULT;
+               return 0;
        }
        case VFIO_DEVICE_SET_IRQS:
        {
@@ -468,7 +472,7 @@ static int vfio_fsl_mc_mmap(void *device_data, struct vm_area_struct *vma)
 {
        struct vfio_fsl_mc_device *vdev = device_data;
        struct fsl_mc_device *mc_dev = vdev->mc_dev;
-       int index;
+       unsigned int index;
 
        index = vma->vm_pgoff >> (VFIO_FSL_MC_OFFSET_SHIFT - PAGE_SHIFT);
 
index c80dceb46f793893c8157fb2a4bfcacaebb3b90e..0d9f3002df7f51dc9bfebd6cba2f6c411ea34be2 100644 (file)
@@ -13,7 +13,7 @@
 #include "linux/fsl/mc.h"
 #include "vfio_fsl_mc_private.h"
 
-int vfio_fsl_mc_irqs_allocate(struct vfio_fsl_mc_device *vdev)
+static int vfio_fsl_mc_irqs_allocate(struct vfio_fsl_mc_device *vdev)
 {
        struct fsl_mc_device *mc_dev = vdev->mc_dev;
        struct vfio_fsl_mc_irq *mc_irq;
index fbd2b3404184ba31e6f72d3fb83920016ef68c58..e6190173482c7e9a2094cdad0888fece695368f9 100644 (file)
@@ -385,7 +385,7 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
            pdev->vendor == PCI_VENDOR_ID_INTEL &&
            IS_ENABLED(CONFIG_VFIO_PCI_IGD)) {
                ret = vfio_pci_igd_init(vdev);
-               if (ret) {
+               if (ret && ret != -ENODEV) {
                        pci_warn(pdev, "Failed to setup Intel IGD regions\n");
                        goto disable_exit;
                }
index 9e353c484ace2676b5fa51f0c07f0b50208cd04e..a0b5fc8e46f4dc05e8d46c0f04ecc9c54cb26363 100644 (file)
@@ -356,34 +356,60 @@ ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf,
        return done;
 }
 
-static int vfio_pci_ioeventfd_handler(void *opaque, void *unused)
+static void vfio_pci_ioeventfd_do_write(struct vfio_pci_ioeventfd *ioeventfd,
+                                       bool test_mem)
 {
-       struct vfio_pci_ioeventfd *ioeventfd = opaque;
-
        switch (ioeventfd->count) {
        case 1:
-               vfio_pci_iowrite8(ioeventfd->vdev, ioeventfd->test_mem,
+               vfio_pci_iowrite8(ioeventfd->vdev, test_mem,
                                  ioeventfd->data, ioeventfd->addr);
                break;
        case 2:
-               vfio_pci_iowrite16(ioeventfd->vdev, ioeventfd->test_mem,
+               vfio_pci_iowrite16(ioeventfd->vdev, test_mem,
                                   ioeventfd->data, ioeventfd->addr);
                break;
        case 4:
-               vfio_pci_iowrite32(ioeventfd->vdev, ioeventfd->test_mem,
+               vfio_pci_iowrite32(ioeventfd->vdev, test_mem,
                                   ioeventfd->data, ioeventfd->addr);
                break;
 #ifdef iowrite64
        case 8:
-               vfio_pci_iowrite64(ioeventfd->vdev, ioeventfd->test_mem,
+               vfio_pci_iowrite64(ioeventfd->vdev, test_mem,
                                   ioeventfd->data, ioeventfd->addr);
                break;
 #endif
        }
+}
+
+static int vfio_pci_ioeventfd_handler(void *opaque, void *unused)
+{
+       struct vfio_pci_ioeventfd *ioeventfd = opaque;
+       struct vfio_pci_device *vdev = ioeventfd->vdev;
+
+       if (ioeventfd->test_mem) {
+               if (!down_read_trylock(&vdev->memory_lock))
+                       return 1; /* Lock contended, use thread */
+               if (!__vfio_pci_memory_enabled(vdev)) {
+                       up_read(&vdev->memory_lock);
+                       return 0;
+               }
+       }
+
+       vfio_pci_ioeventfd_do_write(ioeventfd, false);
+
+       if (ioeventfd->test_mem)
+               up_read(&vdev->memory_lock);
 
        return 0;
 }
 
+static void vfio_pci_ioeventfd_thread(void *opaque, void *unused)
+{
+       struct vfio_pci_ioeventfd *ioeventfd = opaque;
+
+       vfio_pci_ioeventfd_do_write(ioeventfd, ioeventfd->test_mem);
+}
+
 long vfio_pci_ioeventfd(struct vfio_pci_device *vdev, loff_t offset,
                        uint64_t data, int count, int fd)
 {
@@ -457,7 +483,8 @@ long vfio_pci_ioeventfd(struct vfio_pci_device *vdev, loff_t offset,
        ioeventfd->test_mem = vdev->pdev->resource[bar].flags & IORESOURCE_MEM;
 
        ret = vfio_virqfd_enable(ioeventfd, vfio_pci_ioeventfd_handler,
-                                NULL, NULL, &ioeventfd->virqfd, fd);
+                                vfio_pci_ioeventfd_thread, NULL,
+                                &ioeventfd->virqfd, fd);
        if (ret) {
                kfree(ioeventfd);
                goto out_unlock;
index c0771a9567fb5dd7d4af1ec1b92b665c38cfa728..fb4b385191f288dfee2b35442b68538236deb257 100644 (file)
@@ -267,7 +267,7 @@ static int vfio_platform_open(void *device_data)
 
                ret = pm_runtime_get_sync(vdev->device);
                if (ret < 0)
-                       goto err_pm;
+                       goto err_rst;
 
                ret = vfio_platform_call_reset(vdev, &extra_dbg);
                if (ret && vdev->reset_required) {
@@ -284,7 +284,6 @@ static int vfio_platform_open(void *device_data)
 
 err_rst:
        pm_runtime_put(vdev->device);
-err_pm:
        vfio_platform_irq_cleanup(vdev);
 err_irq:
        vfio_platform_regions_cleanup(vdev);
index bb2684cc245ef522e5723ecf2a8c584c4a08a1bb..67e827638995157968e19f0864f107757c4e73f8 100644 (file)
@@ -1993,6 +1993,7 @@ static void vfio_iommu_iova_insert_copy(struct vfio_iommu *iommu,
 
        list_splice_tail(iova_copy, iova);
 }
+
 static int vfio_iommu_type1_attach_group(void *iommu_data,
                                         struct iommu_group *iommu_group)
 {
@@ -2009,18 +2010,10 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
 
        mutex_lock(&iommu->lock);
 
-       list_for_each_entry(d, &iommu->domain_list, next) {
-               if (find_iommu_group(d, iommu_group)) {
-                       mutex_unlock(&iommu->lock);
-                       return -EINVAL;
-               }
-       }
-
-       if (iommu->external_domain) {
-               if (find_iommu_group(iommu->external_domain, iommu_group)) {
-                       mutex_unlock(&iommu->lock);
-                       return -EINVAL;
-               }
+       /* Check for duplicates */
+       if (vfio_iommu_find_iommu_group(iommu, iommu_group)) {
+               mutex_unlock(&iommu->lock);
+               return -EINVAL;
        }
 
        group = kzalloc(sizeof(*group), GFP_KERNEL);
index b22adf03f58425bf3969fbb6df7496ea2c277963..6ff8a509669154e04b4a8d1b85d99e2a586781a2 100644 (file)
@@ -52,7 +52,6 @@
 #define VHOST_SCSI_VERSION  "v0.1"
 #define VHOST_SCSI_NAMELEN 256
 #define VHOST_SCSI_MAX_CDB_SIZE 32
-#define VHOST_SCSI_DEFAULT_TAGS 256
 #define VHOST_SCSI_PREALLOC_SGLS 2048
 #define VHOST_SCSI_PREALLOC_UPAGES 2048
 #define VHOST_SCSI_PREALLOC_PROT_SGLS 2048
@@ -140,6 +139,7 @@ struct vhost_scsi_tpg {
        struct se_portal_group se_tpg;
        /* Pointer back to vhost_scsi, protected by tv_tpg_mutex */
        struct vhost_scsi *vhost_scsi;
+       struct list_head tmf_queue;
 };
 
 struct vhost_scsi_tport {
@@ -189,6 +189,9 @@ struct vhost_scsi_virtqueue {
         * Writers must also take dev mutex and flush under it.
         */
        int inflight_idx;
+       struct vhost_scsi_cmd *scsi_cmds;
+       struct sbitmap scsi_tags;
+       int max_cmds;
 };
 
 struct vhost_scsi {
@@ -209,6 +212,21 @@ struct vhost_scsi {
        int vs_events_nr; /* num of pending events, protected by vq->mutex */
 };
 
+struct vhost_scsi_tmf {
+       struct vhost_work vwork;
+       struct vhost_scsi_tpg *tpg;
+       struct vhost_scsi *vhost;
+       struct vhost_scsi_virtqueue *svq;
+       struct list_head queue_entry;
+
+       struct se_cmd se_cmd;
+       u8 scsi_resp;
+       struct vhost_scsi_inflight *inflight;
+       struct iovec resp_iov;
+       int in_iovs;
+       int vq_desc;
+};
+
 /*
  * Context for processing request and control queue operations.
  */
@@ -320,11 +338,13 @@ static u32 vhost_scsi_tpg_get_inst_index(struct se_portal_group *se_tpg)
        return 1;
 }
 
-static void vhost_scsi_release_cmd(struct se_cmd *se_cmd)
+static void vhost_scsi_release_cmd_res(struct se_cmd *se_cmd)
 {
        struct vhost_scsi_cmd *tv_cmd = container_of(se_cmd,
                                struct vhost_scsi_cmd, tvc_se_cmd);
-       struct se_session *se_sess = tv_cmd->tvc_nexus->tvn_se_sess;
+       struct vhost_scsi_virtqueue *svq = container_of(tv_cmd->tvc_vq,
+                               struct vhost_scsi_virtqueue, vq);
+       struct vhost_scsi_inflight *inflight = tv_cmd->inflight;
        int i;
 
        if (tv_cmd->tvc_sgl_count) {
@@ -336,8 +356,36 @@ static void vhost_scsi_release_cmd(struct se_cmd *se_cmd)
                        put_page(sg_page(&tv_cmd->tvc_prot_sgl[i]));
        }
 
-       vhost_scsi_put_inflight(tv_cmd->inflight);
-       target_free_tag(se_sess, se_cmd);
+       sbitmap_clear_bit(&svq->scsi_tags, se_cmd->map_tag);
+       vhost_scsi_put_inflight(inflight);
+}
+
+static void vhost_scsi_release_tmf_res(struct vhost_scsi_tmf *tmf)
+{
+       struct vhost_scsi_tpg *tpg = tmf->tpg;
+       struct vhost_scsi_inflight *inflight = tmf->inflight;
+
+       mutex_lock(&tpg->tv_tpg_mutex);
+       list_add_tail(&tpg->tmf_queue, &tmf->queue_entry);
+       mutex_unlock(&tpg->tv_tpg_mutex);
+       vhost_scsi_put_inflight(inflight);
+}
+
+static void vhost_scsi_release_cmd(struct se_cmd *se_cmd)
+{
+       if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) {
+               struct vhost_scsi_tmf *tmf = container_of(se_cmd,
+                                       struct vhost_scsi_tmf, se_cmd);
+
+               vhost_work_queue(&tmf->vhost->dev, &tmf->vwork);
+       } else {
+               struct vhost_scsi_cmd *cmd = container_of(se_cmd,
+                                       struct vhost_scsi_cmd, tvc_se_cmd);
+               struct vhost_scsi *vs = cmd->tvc_vhost;
+
+               llist_add(&cmd->tvc_completion_list, &vs->vs_completion_list);
+               vhost_work_queue(&vs->dev, &vs->vs_completion_work);
+       }
 }
 
 static u32 vhost_scsi_sess_get_index(struct se_session *se_sess)
@@ -362,34 +410,25 @@ static int vhost_scsi_get_cmd_state(struct se_cmd *se_cmd)
        return 0;
 }
 
-static void vhost_scsi_complete_cmd(struct vhost_scsi_cmd *cmd)
-{
-       struct vhost_scsi *vs = cmd->tvc_vhost;
-
-       llist_add(&cmd->tvc_completion_list, &vs->vs_completion_list);
-
-       vhost_work_queue(&vs->dev, &vs->vs_completion_work);
-}
-
 static int vhost_scsi_queue_data_in(struct se_cmd *se_cmd)
 {
-       struct vhost_scsi_cmd *cmd = container_of(se_cmd,
-                               struct vhost_scsi_cmd, tvc_se_cmd);
-       vhost_scsi_complete_cmd(cmd);
+       transport_generic_free_cmd(se_cmd, 0);
        return 0;
 }
 
 static int vhost_scsi_queue_status(struct se_cmd *se_cmd)
 {
-       struct vhost_scsi_cmd *cmd = container_of(se_cmd,
-                               struct vhost_scsi_cmd, tvc_se_cmd);
-       vhost_scsi_complete_cmd(cmd);
+       transport_generic_free_cmd(se_cmd, 0);
        return 0;
 }
 
 static void vhost_scsi_queue_tm_rsp(struct se_cmd *se_cmd)
 {
-       return;
+       struct vhost_scsi_tmf *tmf = container_of(se_cmd, struct vhost_scsi_tmf,
+                                                 se_cmd);
+
+       tmf->scsi_resp = se_cmd->se_tmr_req->response;
+       transport_generic_free_cmd(&tmf->se_cmd, 0);
 }
 
 static void vhost_scsi_aborted_task(struct se_cmd *se_cmd)
@@ -429,15 +468,6 @@ vhost_scsi_allocate_evt(struct vhost_scsi *vs,
        return evt;
 }
 
-static void vhost_scsi_free_cmd(struct vhost_scsi_cmd *cmd)
-{
-       struct se_cmd *se_cmd = &cmd->tvc_se_cmd;
-
-       /* TODO locking against target/backend threads? */
-       transport_generic_free_cmd(se_cmd, 0);
-
-}
-
 static int vhost_scsi_check_stop_free(struct se_cmd *se_cmd)
 {
        return target_put_sess_cmd(se_cmd);
@@ -556,7 +586,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
                } else
                        pr_err("Faulted on virtio_scsi_cmd_resp\n");
 
-               vhost_scsi_free_cmd(cmd);
+               vhost_scsi_release_cmd_res(se_cmd);
        }
 
        vq = -1;
@@ -566,31 +596,31 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
 }
 
 static struct vhost_scsi_cmd *
-vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
+vhost_scsi_get_cmd(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
                   unsigned char *cdb, u64 scsi_tag, u16 lun, u8 task_attr,
                   u32 exp_data_len, int data_direction)
 {
+       struct vhost_scsi_virtqueue *svq = container_of(vq,
+                                       struct vhost_scsi_virtqueue, vq);
        struct vhost_scsi_cmd *cmd;
        struct vhost_scsi_nexus *tv_nexus;
-       struct se_session *se_sess;
        struct scatterlist *sg, *prot_sg;
        struct page **pages;
-       int tag, cpu;
+       int tag;
 
        tv_nexus = tpg->tpg_nexus;
        if (!tv_nexus) {
                pr_err("Unable to locate active struct vhost_scsi_nexus\n");
                return ERR_PTR(-EIO);
        }
-       se_sess = tv_nexus->tvn_se_sess;
 
-       tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
+       tag = sbitmap_get(&svq->scsi_tags, 0, false);
        if (tag < 0) {
                pr_err("Unable to obtain tag for vhost_scsi_cmd\n");
                return ERR_PTR(-ENOMEM);
        }
 
-       cmd = &((struct vhost_scsi_cmd *)se_sess->sess_cmd_map)[tag];
+       cmd = &svq->scsi_cmds[tag];
        sg = cmd->tvc_sgl;
        prot_sg = cmd->tvc_prot_sgl;
        pages = cmd->tvc_upages;
@@ -599,7 +629,6 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
        cmd->tvc_prot_sgl = prot_sg;
        cmd->tvc_upages = pages;
        cmd->tvc_se_cmd.map_tag = tag;
-       cmd->tvc_se_cmd.map_cpu = cpu;
        cmd->tvc_tag = scsi_tag;
        cmd->tvc_lun = lun;
        cmd->tvc_task_attr = task_attr;
@@ -907,6 +936,11 @@ vhost_scsi_get_req(struct vhost_virtqueue *vq, struct vhost_scsi_ctx *vc,
        return ret;
 }
 
+static u16 vhost_buf_to_lun(u8 *lun_buf)
+{
+       return ((lun_buf[2] << 8) | lun_buf[3]) & 0x3FFF;
+}
+
 static void
 vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 {
@@ -1045,12 +1079,12 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
                        tag = vhost64_to_cpu(vq, v_req_pi.tag);
                        task_attr = v_req_pi.task_attr;
                        cdb = &v_req_pi.cdb[0];
-                       lun = ((v_req_pi.lun[2] << 8) | v_req_pi.lun[3]) & 0x3FFF;
+                       lun = vhost_buf_to_lun(v_req_pi.lun);
                } else {
                        tag = vhost64_to_cpu(vq, v_req.tag);
                        task_attr = v_req.task_attr;
                        cdb = &v_req.cdb[0];
-                       lun = ((v_req.lun[2] << 8) | v_req.lun[3]) & 0x3FFF;
+                       lun = vhost_buf_to_lun(v_req.lun);
                }
                /*
                 * Check that the received CDB size does not exceeded our
@@ -1065,11 +1099,11 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
                                scsi_command_size(cdb), VHOST_SCSI_MAX_CDB_SIZE);
                                goto err;
                }
-               cmd = vhost_scsi_get_tag(vq, tpg, cdb, tag, lun, task_attr,
+               cmd = vhost_scsi_get_cmd(vq, tpg, cdb, tag, lun, task_attr,
                                         exp_data_len + prot_bytes,
                                         data_direction);
                if (IS_ERR(cmd)) {
-                       vq_err(vq, "vhost_scsi_get_tag failed %ld\n",
+                       vq_err(vq, "vhost_scsi_get_cmd failed %ld\n",
                               PTR_ERR(cmd));
                        goto err;
                }
@@ -1088,7 +1122,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
                                                      &prot_iter, exp_data_len,
                                                      &data_iter))) {
                                vq_err(vq, "Failed to map iov to sgl\n");
-                               vhost_scsi_release_cmd(&cmd->tvc_se_cmd);
+                               vhost_scsi_release_cmd_res(&cmd->tvc_se_cmd);
                                goto err;
                        }
                }
@@ -1124,9 +1158,9 @@ out:
 }
 
 static void
-vhost_scsi_send_tmf_reject(struct vhost_scsi *vs,
-                          struct vhost_virtqueue *vq,
-                          struct vhost_scsi_ctx *vc)
+vhost_scsi_send_tmf_resp(struct vhost_scsi *vs, struct vhost_virtqueue *vq,
+                        int in_iovs, int vq_desc, struct iovec *resp_iov,
+                        int tmf_resp_code)
 {
        struct virtio_scsi_ctrl_tmf_resp rsp;
        struct iov_iter iov_iter;
@@ -1134,17 +1168,87 @@ vhost_scsi_send_tmf_reject(struct vhost_scsi *vs,
 
        pr_debug("%s\n", __func__);
        memset(&rsp, 0, sizeof(rsp));
-       rsp.response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
+       rsp.response = tmf_resp_code;
 
-       iov_iter_init(&iov_iter, READ, &vq->iov[vc->out], vc->in, sizeof(rsp));
+       iov_iter_init(&iov_iter, READ, resp_iov, in_iovs, sizeof(rsp));
 
        ret = copy_to_iter(&rsp, sizeof(rsp), &iov_iter);
        if (likely(ret == sizeof(rsp)))
-               vhost_add_used_and_signal(&vs->dev, vq, vc->head, 0);
+               vhost_add_used_and_signal(&vs->dev, vq, vq_desc, 0);
        else
                pr_err("Faulted on virtio_scsi_ctrl_tmf_resp\n");
 }
 
+static void vhost_scsi_tmf_resp_work(struct vhost_work *work)
+{
+       struct vhost_scsi_tmf *tmf = container_of(work, struct vhost_scsi_tmf,
+                                                 vwork);
+       int resp_code;
+
+       if (tmf->scsi_resp == TMR_FUNCTION_COMPLETE)
+               resp_code = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
+       else
+               resp_code = VIRTIO_SCSI_S_FUNCTION_REJECTED;
+
+       vhost_scsi_send_tmf_resp(tmf->vhost, &tmf->svq->vq, tmf->in_iovs,
+                                tmf->vq_desc, &tmf->resp_iov, resp_code);
+       vhost_scsi_release_tmf_res(tmf);
+}
+
+static void
+vhost_scsi_handle_tmf(struct vhost_scsi *vs, struct vhost_scsi_tpg *tpg,
+                     struct vhost_virtqueue *vq,
+                     struct virtio_scsi_ctrl_tmf_req *vtmf,
+                     struct vhost_scsi_ctx *vc)
+{
+       struct vhost_scsi_virtqueue *svq = container_of(vq,
+                                       struct vhost_scsi_virtqueue, vq);
+       struct vhost_scsi_tmf *tmf;
+
+       if (vhost32_to_cpu(vq, vtmf->subtype) !=
+           VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET)
+               goto send_reject;
+
+       if (!tpg->tpg_nexus || !tpg->tpg_nexus->tvn_se_sess) {
+               pr_err("Unable to locate active struct vhost_scsi_nexus for LUN RESET.\n");
+               goto send_reject;
+       }
+
+       mutex_lock(&tpg->tv_tpg_mutex);
+       if (list_empty(&tpg->tmf_queue)) {
+               pr_err("Missing reserve TMF. Could not handle LUN RESET.\n");
+               mutex_unlock(&tpg->tv_tpg_mutex);
+               goto send_reject;
+       }
+
+       tmf = list_first_entry(&tpg->tmf_queue, struct vhost_scsi_tmf,
+                              queue_entry);
+       list_del_init(&tmf->queue_entry);
+       mutex_unlock(&tpg->tv_tpg_mutex);
+
+       tmf->tpg = tpg;
+       tmf->vhost = vs;
+       tmf->svq = svq;
+       tmf->resp_iov = vq->iov[vc->out];
+       tmf->vq_desc = vc->head;
+       tmf->in_iovs = vc->in;
+       tmf->inflight = vhost_scsi_get_inflight(vq);
+
+       if (target_submit_tmr(&tmf->se_cmd, tpg->tpg_nexus->tvn_se_sess, NULL,
+                             vhost_buf_to_lun(vtmf->lun), NULL,
+                             TMR_LUN_RESET, GFP_KERNEL, 0,
+                             TARGET_SCF_ACK_KREF) < 0) {
+               vhost_scsi_release_tmf_res(tmf);
+               goto send_reject;
+       }
+
+       return;
+
+send_reject:
+       vhost_scsi_send_tmf_resp(vs, vq, vc->in, vc->head, &vq->iov[vc->out],
+                                VIRTIO_SCSI_S_FUNCTION_REJECTED);
+}
+
 static void
 vhost_scsi_send_an_resp(struct vhost_scsi *vs,
                        struct vhost_virtqueue *vq,
@@ -1170,6 +1274,7 @@ vhost_scsi_send_an_resp(struct vhost_scsi *vs,
 static void
 vhost_scsi_ctl_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 {
+       struct vhost_scsi_tpg *tpg;
        union {
                __virtio32 type;
                struct virtio_scsi_ctrl_an_req an;
@@ -1251,12 +1356,12 @@ vhost_scsi_ctl_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
                vc.req += typ_size;
                vc.req_size -= typ_size;
 
-               ret = vhost_scsi_get_req(vq, &vc, NULL);
+               ret = vhost_scsi_get_req(vq, &vc, &tpg);
                if (ret)
                        goto err;
 
                if (v_req.type == VIRTIO_SCSI_T_TMF)
-                       vhost_scsi_send_tmf_reject(vs, vq, &vc);
+                       vhost_scsi_handle_tmf(vs, tpg, vq, &v_req.tmf, &vc);
                else
                        vhost_scsi_send_an_resp(vs, vq, &vc);
 err:
@@ -1373,6 +1478,83 @@ static void vhost_scsi_flush(struct vhost_scsi *vs)
                wait_for_completion(&old_inflight[i]->comp);
 }
 
+static void vhost_scsi_destroy_vq_cmds(struct vhost_virtqueue *vq)
+{
+       struct vhost_scsi_virtqueue *svq = container_of(vq,
+                                       struct vhost_scsi_virtqueue, vq);
+       struct vhost_scsi_cmd *tv_cmd;
+       unsigned int i;
+
+       if (!svq->scsi_cmds)
+               return;
+
+       for (i = 0; i < svq->max_cmds; i++) {
+               tv_cmd = &svq->scsi_cmds[i];
+
+               kfree(tv_cmd->tvc_sgl);
+               kfree(tv_cmd->tvc_prot_sgl);
+               kfree(tv_cmd->tvc_upages);
+       }
+
+       sbitmap_free(&svq->scsi_tags);
+       kfree(svq->scsi_cmds);
+       svq->scsi_cmds = NULL;
+}
+
+static int vhost_scsi_setup_vq_cmds(struct vhost_virtqueue *vq, int max_cmds)
+{
+       struct vhost_scsi_virtqueue *svq = container_of(vq,
+                                       struct vhost_scsi_virtqueue, vq);
+       struct vhost_scsi_cmd *tv_cmd;
+       unsigned int i;
+
+       if (svq->scsi_cmds)
+               return 0;
+
+       if (sbitmap_init_node(&svq->scsi_tags, max_cmds, -1, GFP_KERNEL,
+                             NUMA_NO_NODE))
+               return -ENOMEM;
+       svq->max_cmds = max_cmds;
+
+       svq->scsi_cmds = kcalloc(max_cmds, sizeof(*tv_cmd), GFP_KERNEL);
+       if (!svq->scsi_cmds) {
+               sbitmap_free(&svq->scsi_tags);
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < max_cmds; i++) {
+               tv_cmd = &svq->scsi_cmds[i];
+
+               tv_cmd->tvc_sgl = kcalloc(VHOST_SCSI_PREALLOC_SGLS,
+                                         sizeof(struct scatterlist),
+                                         GFP_KERNEL);
+               if (!tv_cmd->tvc_sgl) {
+                       pr_err("Unable to allocate tv_cmd->tvc_sgl\n");
+                       goto out;
+               }
+
+               tv_cmd->tvc_upages = kcalloc(VHOST_SCSI_PREALLOC_UPAGES,
+                                            sizeof(struct page *),
+                                            GFP_KERNEL);
+               if (!tv_cmd->tvc_upages) {
+                       pr_err("Unable to allocate tv_cmd->tvc_upages\n");
+                       goto out;
+               }
+
+               tv_cmd->tvc_prot_sgl = kcalloc(VHOST_SCSI_PREALLOC_PROT_SGLS,
+                                              sizeof(struct scatterlist),
+                                              GFP_KERNEL);
+               if (!tv_cmd->tvc_prot_sgl) {
+                       pr_err("Unable to allocate tv_cmd->tvc_prot_sgl\n");
+                       goto out;
+               }
+       }
+       return 0;
+out:
+       vhost_scsi_destroy_vq_cmds(vq);
+       return -ENOMEM;
+}
+
 /*
  * Called from vhost_scsi_ioctl() context to walk the list of available
  * vhost_scsi_tpg with an active struct vhost_scsi_nexus
@@ -1427,10 +1609,9 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs,
 
                if (!strcmp(tv_tport->tport_name, t->vhost_wwpn)) {
                        if (vs->vs_tpg && vs->vs_tpg[tpg->tport_tpgt]) {
-                               kfree(vs_tpg);
                                mutex_unlock(&tpg->tv_tpg_mutex);
                                ret = -EEXIST;
-                               goto out;
+                               goto undepend;
                        }
                        /*
                         * In order to ensure individual vhost-scsi configfs
@@ -1442,9 +1623,8 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs,
                        ret = target_depend_item(&se_tpg->tpg_group.cg_item);
                        if (ret) {
                                pr_warn("target_depend_item() failed: %d\n", ret);
-                               kfree(vs_tpg);
                                mutex_unlock(&tpg->tv_tpg_mutex);
-                               goto out;
+                               goto undepend;
                        }
                        tpg->tv_tpg_vhost_count++;
                        tpg->vhost_scsi = vs;
@@ -1457,6 +1637,16 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs,
        if (match) {
                memcpy(vs->vs_vhost_wwpn, t->vhost_wwpn,
                       sizeof(vs->vs_vhost_wwpn));
+
+               for (i = VHOST_SCSI_VQ_IO; i < VHOST_SCSI_MAX_VQ; i++) {
+                       vq = &vs->vqs[i].vq;
+                       if (!vhost_vq_is_setup(vq))
+                               continue;
+
+                       if (vhost_scsi_setup_vq_cmds(vq, vq->num))
+                               goto destroy_vq_cmds;
+               }
+
                for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) {
                        vq = &vs->vqs[i].vq;
                        mutex_lock(&vq->mutex);
@@ -1476,7 +1666,22 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs,
        vhost_scsi_flush(vs);
        kfree(vs->vs_tpg);
        vs->vs_tpg = vs_tpg;
+       goto out;
 
+destroy_vq_cmds:
+       for (i--; i >= VHOST_SCSI_VQ_IO; i--) {
+               if (!vhost_vq_get_backend(&vs->vqs[i].vq))
+                       vhost_scsi_destroy_vq_cmds(&vs->vqs[i].vq);
+       }
+undepend:
+       for (i = 0; i < VHOST_SCSI_MAX_TARGET; i++) {
+               tpg = vs_tpg[i];
+               if (tpg) {
+                       tpg->tv_tpg_vhost_count--;
+                       target_undepend_item(&tpg->se_tpg.tpg_group.cg_item);
+               }
+       }
+       kfree(vs_tpg);
 out:
        mutex_unlock(&vs->dev.mutex);
        mutex_unlock(&vhost_scsi_mutex);
@@ -1549,6 +1754,12 @@ vhost_scsi_clear_endpoint(struct vhost_scsi *vs,
                        mutex_lock(&vq->mutex);
                        vhost_vq_set_backend(vq, NULL);
                        mutex_unlock(&vq->mutex);
+                       /*
+                        * Make sure cmds are not running before tearing them
+                        * down.
+                        */
+                       vhost_scsi_flush(vs);
+                       vhost_scsi_destroy_vq_cmds(vq);
                }
        }
        /*
@@ -1811,11 +2022,19 @@ static int vhost_scsi_port_link(struct se_portal_group *se_tpg,
 {
        struct vhost_scsi_tpg *tpg = container_of(se_tpg,
                                struct vhost_scsi_tpg, se_tpg);
+       struct vhost_scsi_tmf *tmf;
+
+       tmf = kzalloc(sizeof(*tmf), GFP_KERNEL);
+       if (!tmf)
+               return -ENOMEM;
+       INIT_LIST_HEAD(&tmf->queue_entry);
+       vhost_work_init(&tmf->vwork, vhost_scsi_tmf_resp_work);
 
        mutex_lock(&vhost_scsi_mutex);
 
        mutex_lock(&tpg->tv_tpg_mutex);
        tpg->tv_tpg_port_count++;
+       list_add_tail(&tmf->queue_entry, &tpg->tmf_queue);
        mutex_unlock(&tpg->tv_tpg_mutex);
 
        vhost_scsi_hotplug(tpg, lun);
@@ -1830,11 +2049,16 @@ static void vhost_scsi_port_unlink(struct se_portal_group *se_tpg,
 {
        struct vhost_scsi_tpg *tpg = container_of(se_tpg,
                                struct vhost_scsi_tpg, se_tpg);
+       struct vhost_scsi_tmf *tmf;
 
        mutex_lock(&vhost_scsi_mutex);
 
        mutex_lock(&tpg->tv_tpg_mutex);
        tpg->tv_tpg_port_count--;
+       tmf = list_first_entry(&tpg->tmf_queue, struct vhost_scsi_tmf,
+                              queue_entry);
+       list_del(&tmf->queue_entry);
+       kfree(tmf);
        mutex_unlock(&tpg->tv_tpg_mutex);
 
        vhost_scsi_hotunplug(tpg, lun);
@@ -1842,23 +2066,6 @@ static void vhost_scsi_port_unlink(struct se_portal_group *se_tpg,
        mutex_unlock(&vhost_scsi_mutex);
 }
 
-static void vhost_scsi_free_cmd_map_res(struct se_session *se_sess)
-{
-       struct vhost_scsi_cmd *tv_cmd;
-       unsigned int i;
-
-       if (!se_sess->sess_cmd_map)
-               return;
-
-       for (i = 0; i < VHOST_SCSI_DEFAULT_TAGS; i++) {
-               tv_cmd = &((struct vhost_scsi_cmd *)se_sess->sess_cmd_map)[i];
-
-               kfree(tv_cmd->tvc_sgl);
-               kfree(tv_cmd->tvc_prot_sgl);
-               kfree(tv_cmd->tvc_upages);
-       }
-}
-
 static ssize_t vhost_scsi_tpg_attrib_fabric_prot_type_store(
                struct config_item *item, const char *page, size_t count)
 {
@@ -1898,45 +2105,6 @@ static struct configfs_attribute *vhost_scsi_tpg_attrib_attrs[] = {
        NULL,
 };
 
-static int vhost_scsi_nexus_cb(struct se_portal_group *se_tpg,
-                              struct se_session *se_sess, void *p)
-{
-       struct vhost_scsi_cmd *tv_cmd;
-       unsigned int i;
-
-       for (i = 0; i < VHOST_SCSI_DEFAULT_TAGS; i++) {
-               tv_cmd = &((struct vhost_scsi_cmd *)se_sess->sess_cmd_map)[i];
-
-               tv_cmd->tvc_sgl = kcalloc(VHOST_SCSI_PREALLOC_SGLS,
-                                         sizeof(struct scatterlist),
-                                         GFP_KERNEL);
-               if (!tv_cmd->tvc_sgl) {
-                       pr_err("Unable to allocate tv_cmd->tvc_sgl\n");
-                       goto out;
-               }
-
-               tv_cmd->tvc_upages = kcalloc(VHOST_SCSI_PREALLOC_UPAGES,
-                                            sizeof(struct page *),
-                                            GFP_KERNEL);
-               if (!tv_cmd->tvc_upages) {
-                       pr_err("Unable to allocate tv_cmd->tvc_upages\n");
-                       goto out;
-               }
-
-               tv_cmd->tvc_prot_sgl = kcalloc(VHOST_SCSI_PREALLOC_PROT_SGLS,
-                                              sizeof(struct scatterlist),
-                                              GFP_KERNEL);
-               if (!tv_cmd->tvc_prot_sgl) {
-                       pr_err("Unable to allocate tv_cmd->tvc_prot_sgl\n");
-                       goto out;
-               }
-       }
-       return 0;
-out:
-       vhost_scsi_free_cmd_map_res(se_sess);
-       return -ENOMEM;
-}
-
 static int vhost_scsi_make_nexus(struct vhost_scsi_tpg *tpg,
                                const char *name)
 {
@@ -1960,12 +2128,9 @@ static int vhost_scsi_make_nexus(struct vhost_scsi_tpg *tpg,
         * struct se_node_acl for the vhost_scsi struct se_portal_group with
         * the SCSI Initiator port name of the passed configfs group 'name'.
         */
-       tv_nexus->tvn_se_sess = target_setup_session(&tpg->se_tpg,
-                                       VHOST_SCSI_DEFAULT_TAGS,
-                                       sizeof(struct vhost_scsi_cmd),
+       tv_nexus->tvn_se_sess = target_setup_session(&tpg->se_tpg, 0, 0,
                                        TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS,
-                                       (unsigned char *)name, tv_nexus,
-                                       vhost_scsi_nexus_cb);
+                                       (unsigned char *)name, tv_nexus, NULL);
        if (IS_ERR(tv_nexus->tvn_se_sess)) {
                mutex_unlock(&tpg->tv_tpg_mutex);
                kfree(tv_nexus);
@@ -2015,7 +2180,6 @@ static int vhost_scsi_drop_nexus(struct vhost_scsi_tpg *tpg)
                " %s Initiator Port: %s\n", vhost_scsi_dump_proto_id(tpg->tport),
                tv_nexus->tvn_se_sess->se_node_acl->initiatorname);
 
-       vhost_scsi_free_cmd_map_res(se_sess);
        /*
         * Release the SCSI I_T Nexus to the emulated vhost Target Port
         */
@@ -2155,6 +2319,7 @@ vhost_scsi_make_tpg(struct se_wwn *wwn, const char *name)
        }
        mutex_init(&tpg->tv_tpg_mutex);
        INIT_LIST_HEAD(&tpg->tv_tpg_list);
+       INIT_LIST_HEAD(&tpg->tmf_queue);
        tpg->tport = tport;
        tpg->tport_tpgt = tpgt;
 
index a2dbc85e0b0d67b49ccc1f236f7f38c48035cd31..29ed4173f04e6e2a7b1ed450823643c58da8c81d 100644 (file)
@@ -47,6 +47,7 @@ struct vhost_vdpa {
        int minor;
        struct eventfd_ctx *config_ctx;
        int in_batch;
+       struct vdpa_iova_range range;
 };
 
 static DEFINE_IDA(vhost_vdpa_ida);
@@ -103,6 +104,9 @@ static void vhost_vdpa_setup_vq_irq(struct vhost_vdpa *v, u16 qid)
        vq->call_ctx.producer.token = vq->call_ctx.ctx;
        vq->call_ctx.producer.irq = irq;
        ret = irq_bypass_register_producer(&vq->call_ctx.producer);
+       if (unlikely(ret))
+               dev_info(&v->dev, "vq %u, irq bypass producer (token %p) registration fails, ret =  %d\n",
+                        qid, vq->call_ctx.producer.token, ret);
 }
 
 static void vhost_vdpa_unsetup_vq_irq(struct vhost_vdpa *v, u16 qid)
@@ -337,6 +341,18 @@ static long vhost_vdpa_set_config_call(struct vhost_vdpa *v, u32 __user *argp)
        return 0;
 }
 
+static long vhost_vdpa_get_iova_range(struct vhost_vdpa *v, u32 __user *argp)
+{
+       struct vhost_vdpa_iova_range range = {
+               .first = v->range.first,
+               .last = v->range.last,
+       };
+
+       if (copy_to_user(argp, &range, sizeof(range)))
+               return -EFAULT;
+       return 0;
+}
+
 static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
                                   void __user *argp)
 {
@@ -421,12 +437,11 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep,
        void __user *argp = (void __user *)arg;
        u64 __user *featurep = argp;
        u64 features;
-       long r;
+       long r = 0;
 
        if (cmd == VHOST_SET_BACKEND_FEATURES) {
-               r = copy_from_user(&features, featurep, sizeof(features));
-               if (r)
-                       return r;
+               if (copy_from_user(&features, featurep, sizeof(features)))
+                       return -EFAULT;
                if (features & ~VHOST_VDPA_BACKEND_FEATURES)
                        return -EOPNOTSUPP;
                vhost_set_backend_features(&v->vdev, features);
@@ -469,7 +484,11 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep,
                break;
        case VHOST_GET_BACKEND_FEATURES:
                features = VHOST_VDPA_BACKEND_FEATURES;
-               r = copy_to_user(featurep, &features, sizeof(features));
+               if (copy_to_user(featurep, &features, sizeof(features)))
+                       r = -EFAULT;
+               break;
+       case VHOST_VDPA_GET_IOVA_RANGE:
+               r = vhost_vdpa_get_iova_range(v, argp);
                break;
        default:
                r = vhost_dev_ioctl(&v->vdev, cmd, argp);
@@ -560,6 +579,8 @@ static int vhost_vdpa_map(struct vhost_vdpa *v,
 
        if (r)
                vhost_iotlb_del_range(dev->iotlb, iova, iova + size - 1);
+       else
+               atomic64_add(size >> PAGE_SHIFT, &dev->mm->pinned_vm);
 
        return r;
 }
@@ -588,31 +609,33 @@ static int vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v,
        struct vhost_dev *dev = &v->vdev;
        struct vhost_iotlb *iotlb = dev->iotlb;
        struct page **page_list;
-       struct vm_area_struct **vmas;
+       unsigned long list_size = PAGE_SIZE / sizeof(struct page *);
        unsigned int gup_flags = FOLL_LONGTERM;
-       unsigned long map_pfn, last_pfn = 0;
-       unsigned long npages, lock_limit;
-       unsigned long i, nmap = 0;
+       unsigned long npages, cur_base, map_pfn, last_pfn = 0;
+       unsigned long lock_limit, sz2pin, nchunks, i;
        u64 iova = msg->iova;
        long pinned;
        int ret = 0;
 
+       if (msg->iova < v->range.first ||
+           msg->iova + msg->size - 1 > v->range.last)
+               return -EINVAL;
+
        if (vhost_iotlb_itree_first(iotlb, msg->iova,
                                    msg->iova + msg->size - 1))
                return -EEXIST;
 
+       /* Limit the use of memory for bookkeeping */
+       page_list = (struct page **) __get_free_page(GFP_KERNEL);
+       if (!page_list)
+               return -ENOMEM;
+
        if (msg->perm & VHOST_ACCESS_WO)
                gup_flags |= FOLL_WRITE;
 
        npages = PAGE_ALIGN(msg->size + (iova & ~PAGE_MASK)) >> PAGE_SHIFT;
-       if (!npages)
-               return -EINVAL;
-
-       page_list = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
-       vmas = kvmalloc_array(npages, sizeof(struct vm_area_struct *),
-                             GFP_KERNEL);
-       if (!page_list || !vmas) {
-               ret = -ENOMEM;
+       if (!npages) {
+               ret = -EINVAL;
                goto free;
        }
 
@@ -624,70 +647,91 @@ static int vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v,
                goto unlock;
        }
 
-       pinned = pin_user_pages(msg->uaddr & PAGE_MASK, npages, gup_flags,
-                               page_list, vmas);
-       if (npages != pinned) {
-               if (pinned < 0) {
-                       ret = pinned;
-               } else {
-                       unpin_user_pages(page_list, pinned);
-                       ret = -ENOMEM;
-               }
-               goto unlock;
-       }
-
+       cur_base = msg->uaddr & PAGE_MASK;
        iova &= PAGE_MASK;
-       map_pfn = page_to_pfn(page_list[0]);
-
-       /* One more iteration to avoid extra vdpa_map() call out of loop. */
-       for (i = 0; i <= npages; i++) {
-               unsigned long this_pfn;
-               u64 csize;
-
-               /* The last chunk may have no valid PFN next to it */
-               this_pfn = i < npages ? page_to_pfn(page_list[i]) : -1UL;
-
-               if (last_pfn && (this_pfn == -1UL ||
-                                this_pfn != last_pfn + 1)) {
-                       /* Pin a contiguous chunk of memory */
-                       csize = last_pfn - map_pfn + 1;
-                       ret = vhost_vdpa_map(v, iova, csize << PAGE_SHIFT,
-                                            map_pfn << PAGE_SHIFT,
-                                            msg->perm);
-                       if (ret) {
-                               /*
-                                * Unpin the rest chunks of memory on the
-                                * flight with no corresponding vdpa_map()
-                                * calls having been made yet. On the other
-                                * hand, vdpa_unmap() in the failure path
-                                * is in charge of accounting the number of
-                                * pinned pages for its own.
-                                * This asymmetrical pattern of accounting
-                                * is for efficiency to pin all pages at
-                                * once, while there is no other callsite
-                                * of vdpa_map() than here above.
-                                */
-                               unpin_user_pages(&page_list[nmap],
-                                                npages - nmap);
-                               goto out;
+       nchunks = 0;
+
+       while (npages) {
+               sz2pin = min_t(unsigned long, npages, list_size);
+               pinned = pin_user_pages(cur_base, sz2pin,
+                                       gup_flags, page_list, NULL);
+               if (sz2pin != pinned) {
+                       if (pinned < 0) {
+                               ret = pinned;
+                       } else {
+                               unpin_user_pages(page_list, pinned);
+                               ret = -ENOMEM;
+                       }
+                       goto out;
+               }
+               nchunks++;
+
+               if (!last_pfn)
+                       map_pfn = page_to_pfn(page_list[0]);
+
+               for (i = 0; i < pinned; i++) {
+                       unsigned long this_pfn = page_to_pfn(page_list[i]);
+                       u64 csize;
+
+                       if (last_pfn && (this_pfn != last_pfn + 1)) {
+                               /* Pin a contiguous chunk of memory */
+                               csize = (last_pfn - map_pfn + 1) << PAGE_SHIFT;
+                               ret = vhost_vdpa_map(v, iova, csize,
+                                                    map_pfn << PAGE_SHIFT,
+                                                    msg->perm);
+                               if (ret) {
+                                       /*
+                                        * Unpin the pages that are left unmapped
+                                        * from this point on in the current
+                                        * page_list. The remaining outstanding
+                                        * ones which may stride across several
+                                        * chunks will be covered in the common
+                                        * error path subsequently.
+                                        */
+                                       unpin_user_pages(&page_list[i],
+                                                        pinned - i);
+                                       goto out;
+                               }
+
+                               map_pfn = this_pfn;
+                               iova += csize;
+                               nchunks = 0;
                        }
-                       atomic64_add(csize, &dev->mm->pinned_vm);
-                       nmap += csize;
-                       iova += csize << PAGE_SHIFT;
-                       map_pfn = this_pfn;
+
+                       last_pfn = this_pfn;
                }
-               last_pfn = this_pfn;
+
+               cur_base += pinned << PAGE_SHIFT;
+               npages -= pinned;
        }
 
-       WARN_ON(nmap != npages);
+       /* Pin the rest chunk */
+       ret = vhost_vdpa_map(v, iova, (last_pfn - map_pfn + 1) << PAGE_SHIFT,
+                            map_pfn << PAGE_SHIFT, msg->perm);
 out:
-       if (ret)
+       if (ret) {
+               if (nchunks) {
+                       unsigned long pfn;
+
+                       /*
+                        * Unpin the outstanding pages which are yet to be
+                        * mapped but haven't due to vdpa_map() or
+                        * pin_user_pages() failure.
+                        *
+                        * Mapped pages are accounted in vdpa_map(), hence
+                        * the corresponding unpinning will be handled by
+                        * vdpa_unmap().
+                        */
+                       WARN_ON(!last_pfn);
+                       for (pfn = map_pfn; pfn <= last_pfn; pfn++)
+                               unpin_user_page(pfn_to_page(pfn));
+               }
                vhost_vdpa_unmap(v, msg->iova, msg->size);
+       }
 unlock:
        mmap_read_unlock(dev->mm);
 free:
-       kvfree(vmas);
-       kvfree(page_list);
+       free_page((unsigned long)page_list);
        return ret;
 }
 
@@ -783,6 +827,27 @@ static void vhost_vdpa_free_domain(struct vhost_vdpa *v)
        v->domain = NULL;
 }
 
+static void vhost_vdpa_set_iova_range(struct vhost_vdpa *v)
+{
+       struct vdpa_iova_range *range = &v->range;
+       struct iommu_domain_geometry geo;
+       struct vdpa_device *vdpa = v->vdpa;
+       const struct vdpa_config_ops *ops = vdpa->config;
+
+       if (ops->get_iova_range) {
+               *range = ops->get_iova_range(vdpa);
+       } else if (v->domain &&
+                  !iommu_domain_get_attr(v->domain,
+                  DOMAIN_ATTR_GEOMETRY, &geo) &&
+                  geo.force_aperture) {
+               range->first = geo.aperture_start;
+               range->last = geo.aperture_end;
+       } else {
+               range->first = 0;
+               range->last = ULLONG_MAX;
+       }
+}
+
 static int vhost_vdpa_open(struct inode *inode, struct file *filep)
 {
        struct vhost_vdpa *v;
@@ -823,6 +888,8 @@ static int vhost_vdpa_open(struct inode *inode, struct file *filep)
        if (r)
                goto err_init_iotlb;
 
+       vhost_vdpa_set_iova_range(v);
+
        filep->private_data = v;
 
        return 0;
index 5c835a2927833a0631b6008eea48d7c3e1e5b7bd..a262e12c6dc26f76810ac28a833ea5deb1e70d74 100644 (file)
@@ -304,6 +304,12 @@ static void vhost_vring_call_reset(struct vhost_vring_call *call_ctx)
        memset(&call_ctx->producer, 0x0, sizeof(struct irq_bypass_producer));
 }
 
+bool vhost_vq_is_setup(struct vhost_virtqueue *vq)
+{
+       return vq->avail && vq->desc && vq->used && vhost_vq_access_ok(vq);
+}
+EXPORT_SYMBOL_GPL(vhost_vq_is_setup);
+
 static void vhost_vq_reset(struct vhost_dev *dev,
                           struct vhost_virtqueue *vq)
 {
index e016cd3fa02f788096906e3aba3fd53da4b409a9..b063324c7669d20bda8b0b45f822ae419c047997 100644 (file)
@@ -190,6 +190,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *,
                      struct vhost_log *log, unsigned int *log_num);
 void vhost_discard_vq_desc(struct vhost_virtqueue *, int n);
 
+bool vhost_vq_is_setup(struct vhost_virtqueue *vq);
 int vhost_vq_init_access(struct vhost_virtqueue *);
 int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len);
 int vhost_add_used_n(struct vhost_virtqueue *, struct vring_used_elem *heads,
index 8bd8b403f08721372353b5d1f4d40686fec8ece6..b7403ba8e7f70b9d8c74777410b4868ce1a195ed 100644 (file)
@@ -730,7 +730,7 @@ EXPORT_SYMBOL(vringh_iov_pull_user);
 /**
  * vringh_iov_push_user - copy bytes into vring_iov.
  * @wiov: the wiov as passed to vringh_getdesc_user() (updated as we consume)
- * @dst: the place to copy.
+ * @src: the place to copy from.
  * @len: the maximum length to copy.
  *
  * Returns the bytes copied <= len or a negative errno.
@@ -976,7 +976,7 @@ EXPORT_SYMBOL(vringh_iov_pull_kern);
 /**
  * vringh_iov_push_kern - copy bytes into vring_iov.
  * @wiov: the wiov as passed to vringh_getdesc_kern() (updated as we consume)
- * @dst: the place to copy.
+ * @src: the place to copy from.
  * @len: the maximum length to copy.
  *
  * Returns the bytes copied <= len or a negative errno.
@@ -1333,7 +1333,7 @@ EXPORT_SYMBOL(vringh_iov_pull_iotlb);
  * vringh_iov_push_iotlb - copy bytes into vring_iov.
  * @vrh: the vring.
  * @wiov: the wiov as passed to vringh_getdesc_iotlb() (updated as we consume)
- * @dst: the place to copy.
+ * @src: the place to copy from.
  * @len: the maximum length to copy.
  *
  * Returns the bytes copied <= len or a negative errno.
index 02411d89cb462e2f98b0960f480f3fafb7abae91..c8b0ae676809ba041e954ad876ec71e76da8b0ba 100644 (file)
@@ -47,6 +47,7 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <linux/completion.h>
 #include <linux/fb.h>
@@ -1092,7 +1093,12 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
                goto err1;
        }
 
-       fb_virt = ioremap(par->mem->start, screen_fb_size);
+       /*
+        * Map the VRAM cacheable for performance. This is also required for
+        * VM Connect to display properly for ARM64 Linux VM, as the host also
+        * maps the VRAM cacheable.
+        */
+       fb_virt = ioremap_cache(par->mem->start, screen_fb_size);
        if (!fb_virt)
                goto err2;
 
@@ -1114,8 +1120,15 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
 getmem_done:
        remove_conflicting_framebuffers(info->apertures,
                                        KBUILD_MODNAME, false);
-       if (!gen2vm)
+
+       if (gen2vm) {
+               /* framebuffer is reallocated, clear screen_info to avoid misuse from kexec */
+               screen_info.lfb_size = 0;
+               screen_info.lfb_base = 0;
+               screen_info.orig_video_isVGA = 0;
+       } else {
                pci_dev_put(pdev);
+       }
        kfree(info->apertures);
 
        return 0;
index f06622b48d69571fa0c8bf56800230f35252003c..f1964ea4b8269011753dbae90b6906fd938abf2a 100644 (file)
@@ -1505,10 +1505,8 @@ static __poll_t ne_enclave_poll(struct file *file, poll_table *wait)
 
        poll_wait(file, &ne_enclave->eventq, wait);
 
-       if (!ne_enclave->has_event)
-               return mask;
-
-       mask = POLLHUP;
+       if (ne_enclave->has_event)
+               mask |= EPOLLHUP;
 
        return mask;
 }
index 71ce1b7a23d1cc59bbe72755a60c4627f13c0c6d..2b385c1b4a99cbaadf9f5fec4c0d822b96f95da1 100644 (file)
@@ -395,8 +395,7 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
         */
        trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force);
 
-       map = swiotlb_tbl_map_single(dev, virt_to_phys(xen_io_tlb_start),
-                                    phys, size, size, dir, attrs);
+       map = swiotlb_tbl_map_single(dev, phys, size, size, dir, attrs);
        if (map == (phys_addr_t)DMA_MAPPING_ERROR)
                return DMA_MAPPING_ERROR;
 
index b177fd3b1eb3bfef4fb0155c5361597bdfb5242c..be5768949cb15eeab32623f122cb6bbf21791697 100644 (file)
@@ -655,6 +655,8 @@ const struct file_operations v9fs_cached_file_operations = {
        .release = v9fs_dir_release,
        .lock = v9fs_file_lock,
        .mmap = v9fs_file_mmap,
+       .splice_read = generic_file_splice_read,
+       .splice_write = iter_file_splice_write,
        .fsync = v9fs_file_fsync,
 };
 
@@ -667,6 +669,8 @@ const struct file_operations v9fs_cached_file_operations_dotl = {
        .lock = v9fs_file_lock_dotl,
        .flock = v9fs_file_flock_dotl,
        .mmap = v9fs_file_mmap,
+       .splice_read = generic_file_splice_read,
+       .splice_write = iter_file_splice_write,
        .fsync = v9fs_file_fsync_dotl,
 };
 
@@ -678,6 +682,8 @@ const struct file_operations v9fs_file_operations = {
        .release = v9fs_dir_release,
        .lock = v9fs_file_lock,
        .mmap = generic_file_readonly_mmap,
+       .splice_read = generic_file_splice_read,
+       .splice_write = iter_file_splice_write,
        .fsync = v9fs_file_fsync,
 };
 
@@ -690,6 +696,8 @@ const struct file_operations v9fs_file_operations_dotl = {
        .lock = v9fs_file_lock_dotl,
        .flock = v9fs_file_flock_dotl,
        .mmap = generic_file_readonly_mmap,
+       .splice_read = generic_file_splice_read,
+       .splice_write = iter_file_splice_write,
        .fsync = v9fs_file_fsync_dotl,
 };
 
@@ -701,6 +709,8 @@ const struct file_operations v9fs_mmap_file_operations = {
        .release = v9fs_dir_release,
        .lock = v9fs_file_lock,
        .mmap = v9fs_mmap_file_mmap,
+       .splice_read = generic_file_splice_read,
+       .splice_write = iter_file_splice_write,
        .fsync = v9fs_file_fsync,
 };
 
@@ -713,5 +723,7 @@ const struct file_operations v9fs_mmap_file_operations_dotl = {
        .lock = v9fs_file_lock_dotl,
        .flock = v9fs_file_flock_dotl,
        .mmap = v9fs_mmap_file_mmap,
+       .splice_read = generic_file_splice_read,
+       .splice_write = iter_file_splice_write,
        .fsync = v9fs_file_fsync_dotl,
 };
index 52233fa6195faf68b80b71a8b9133e3e7d56d7d0..887b673f6223022f2b9699503ef80796736f52be 100644 (file)
@@ -589,7 +589,7 @@ struct afs_cell *afs_use_cell(struct afs_cell *cell, enum afs_cell_trace reason)
  */
 void afs_unuse_cell(struct afs_net *net, struct afs_cell *cell, enum afs_cell_trace reason)
 {
-       unsigned int debug_id = cell->debug_id;
+       unsigned int debug_id;
        time64_t now, expire_delay;
        int u, a;
 
@@ -604,6 +604,7 @@ void afs_unuse_cell(struct afs_net *net, struct afs_cell *cell, enum afs_cell_tr
        if (cell->vl_servers->nr_servers)
                expire_delay = afs_cell_gc_delay;
 
+       debug_id = cell->debug_id;
        u = atomic_read(&cell->ref);
        a = atomic_dec_return(&cell->active);
        trace_afs_cell(debug_id, u, a, reason);
index 1d2e61e0ab047c733e132c8ee4a7f98c13af7941..9068d5578a26f9a6c1fe51a37599af0ff9c08e66 100644 (file)
@@ -281,8 +281,7 @@ retry:
                        if (ret < 0)
                                goto error;
 
-                       set_page_private(req->pages[i], 1);
-                       SetPagePrivate(req->pages[i]);
+                       attach_page_private(req->pages[i], (void *)1);
                        unlock_page(req->pages[i]);
                        i++;
                } else {
@@ -824,6 +823,7 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
                                vp->cb_break_before = afs_calc_vnode_cb_break(vnode);
                                vp->vnode = vnode;
                                vp->put_vnode = true;
+                               vp->speculative = true; /* vnode not locked */
                        }
                }
        }
@@ -1975,8 +1975,7 @@ static int afs_dir_releasepage(struct page *page, gfp_t gfp_flags)
 
        _enter("{{%llx:%llu}[%lu]}", dvnode->fid.vid, dvnode->fid.vnode, page->index);
 
-       set_page_private(page, 0);
-       ClearPagePrivate(page);
+       detach_page_private(page);
 
        /* The directory will need reloading. */
        if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
@@ -2003,8 +2002,6 @@ static void afs_dir_invalidatepage(struct page *page, unsigned int offset,
                afs_stat_v(dvnode, n_inval);
 
        /* we clean up only if the entire page is being invalidated */
-       if (offset == 0 && length == PAGE_SIZE) {
-               set_page_private(page, 0);
-               ClearPagePrivate(page);
-       }
+       if (offset == 0 && length == PAGE_SIZE)
+               detach_page_private(page);
 }
index b108528bf010dc56a0bde88d7451408822f64777..2ffe09abae7fcca86bf66471eb80a91e580bcb2e 100644 (file)
@@ -243,10 +243,8 @@ void afs_edit_dir_add(struct afs_vnode *vnode,
                                                   index, gfp);
                        if (!page)
                                goto error;
-                       if (!PagePrivate(page)) {
-                               set_page_private(page, 1);
-                               SetPagePrivate(page);
-                       }
+                       if (!PagePrivate(page))
+                               attach_page_private(page, (void *)1);
                        dir_page = kmap(page);
                }
 
index 371d1488cc549db412a75045b7bfaf5b4d37204e..85f5adf21aa08a50f372a9db3b5215d3822c3940 100644 (file)
@@ -33,6 +33,7 @@ const struct file_operations afs_file_operations = {
        .write_iter     = afs_file_write,
        .mmap           = afs_file_mmap,
        .splice_read    = generic_file_splice_read,
+       .splice_write   = iter_file_splice_write,
        .fsync          = afs_fsync,
        .lock           = afs_lock,
        .flock          = afs_flock,
@@ -600,6 +601,63 @@ static int afs_readpages(struct file *file, struct address_space *mapping,
        return ret;
 }
 
+/*
+ * Adjust the dirty region of the page on truncation or full invalidation,
+ * getting rid of the markers altogether if the region is entirely invalidated.
+ */
+static void afs_invalidate_dirty(struct page *page, unsigned int offset,
+                                unsigned int length)
+{
+       struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
+       unsigned long priv;
+       unsigned int f, t, end = offset + length;
+
+       priv = page_private(page);
+
+       /* we clean up only if the entire page is being invalidated */
+       if (offset == 0 && length == thp_size(page))
+               goto full_invalidate;
+
+        /* If the page was dirtied by page_mkwrite(), the PTE stays writable
+         * and we don't get another notification to tell us to expand it
+         * again.
+         */
+       if (afs_is_page_dirty_mmapped(priv))
+               return;
+
+       /* We may need to shorten the dirty region */
+       f = afs_page_dirty_from(priv);
+       t = afs_page_dirty_to(priv);
+
+       if (t <= offset || f >= end)
+               return; /* Doesn't overlap */
+
+       if (f < offset && t > end)
+               return; /* Splits the dirty region - just absorb it */
+
+       if (f >= offset && t <= end)
+               goto undirty;
+
+       if (f < offset)
+               t = offset;
+       else
+               f = end;
+       if (f == t)
+               goto undirty;
+
+       priv = afs_page_dirty(f, t);
+       set_page_private(page, priv);
+       trace_afs_page_dirty(vnode, tracepoint_string("trunc"), page->index, priv);
+       return;
+
+undirty:
+       trace_afs_page_dirty(vnode, tracepoint_string("undirty"), page->index, priv);
+       clear_page_dirty_for_io(page);
+full_invalidate:
+       priv = (unsigned long)detach_page_private(page);
+       trace_afs_page_dirty(vnode, tracepoint_string("inval"), page->index, priv);
+}
+
 /*
  * invalidate part or all of a page
  * - release a page and clean up its private data if offset is 0 (indicating
@@ -608,31 +666,23 @@ static int afs_readpages(struct file *file, struct address_space *mapping,
 static void afs_invalidatepage(struct page *page, unsigned int offset,
                               unsigned int length)
 {
-       struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
-       unsigned long priv;
-
        _enter("{%lu},%u,%u", page->index, offset, length);
 
        BUG_ON(!PageLocked(page));
 
+#ifdef CONFIG_AFS_FSCACHE
        /* we clean up only if the entire page is being invalidated */
        if (offset == 0 && length == PAGE_SIZE) {
-#ifdef CONFIG_AFS_FSCACHE
                if (PageFsCache(page)) {
                        struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
                        fscache_wait_on_page_write(vnode->cache, page);
                        fscache_uncache_page(vnode->cache, page);
                }
+       }
 #endif
 
-               if (PagePrivate(page)) {
-                       priv = page_private(page);
-                       trace_afs_page_dirty(vnode, tracepoint_string("inval"),
-                                            page->index, priv);
-                       set_page_private(page, 0);
-                       ClearPagePrivate(page);
-               }
-       }
+       if (PagePrivate(page))
+               afs_invalidate_dirty(page, offset, length);
 
        _leave("");
 }
@@ -660,11 +710,9 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags)
 #endif
 
        if (PagePrivate(page)) {
-               priv = page_private(page);
+               priv = (unsigned long)detach_page_private(page);
                trace_afs_page_dirty(vnode, tracepoint_string("rel"),
                                     page->index, priv);
-               set_page_private(page, 0);
-               ClearPagePrivate(page);
        }
 
        /* indicate that the page can be released */
index 0fe8844b4bee2f942ba64925fb14f09738ba425b..b0d7b892090da8ae5cb771fd57b52b994aa98dc4 100644 (file)
@@ -294,6 +294,13 @@ void afs_vnode_commit_status(struct afs_operation *op, struct afs_vnode_param *v
                        op->flags &= ~AFS_OPERATION_DIR_CONFLICT;
                }
        } else if (vp->scb.have_status) {
+               if (vp->dv_before + vp->dv_delta != vp->scb.status.data_version &&
+                   vp->speculative)
+                       /* Ignore the result of a speculative bulk status fetch
+                        * if it splits around a modification op, thereby
+                        * appearing to regress the data version.
+                        */
+                       goto out;
                afs_apply_status(op, vp);
                if (vp->scb.have_cb)
                        afs_apply_callback(op, vp);
@@ -305,6 +312,7 @@ void afs_vnode_commit_status(struct afs_operation *op, struct afs_vnode_param *v
                }
        }
 
+out:
        write_sequnlock(&vnode->cb_lock);
 
        if (vp->scb.have_status)
index 81b0485fd22ad59ce6b216bb13abf31d1730a92d..0d150a29e39ec173aecc1b278121d58c55c76e9f 100644 (file)
@@ -755,6 +755,7 @@ struct afs_vnode_param {
        bool                    update_ctime:1; /* Need to update the ctime */
        bool                    set_size:1;     /* Must update i_size */
        bool                    op_unlinked:1;  /* True if file was unlinked by op */
+       bool                    speculative:1;  /* T if speculative status fetch (no vnode lock) */
 };
 
 /*
@@ -812,6 +813,7 @@ struct afs_operation {
                        pgoff_t         last;           /* last page in mapping to deal with */
                        unsigned        first_offset;   /* offset into mapping[first] */
                        unsigned        last_to;        /* amount of mapping[last] */
+                       bool            laundering;     /* Laundering page, PG_writeback not set */
                } store;
                struct {
                        struct iattr    *attr;
@@ -857,6 +859,62 @@ struct afs_vnode_cache_aux {
        u64                     data_version;
 } __packed;
 
+/*
+ * We use page->private to hold the amount of the page that we've written to,
+ * splitting the field into two parts.  However, we need to represent a range
+ * 0...PAGE_SIZE, so we reduce the resolution if the size of the page
+ * exceeds what we can encode.
+ */
+#ifdef CONFIG_64BIT
+#define __AFS_PAGE_PRIV_MASK   0x7fffffffUL
+#define __AFS_PAGE_PRIV_SHIFT  32
+#define __AFS_PAGE_PRIV_MMAPPED        0x80000000UL
+#else
+#define __AFS_PAGE_PRIV_MASK   0x7fffUL
+#define __AFS_PAGE_PRIV_SHIFT  16
+#define __AFS_PAGE_PRIV_MMAPPED        0x8000UL
+#endif
+
+static inline unsigned int afs_page_dirty_resolution(void)
+{
+       int shift = PAGE_SHIFT - (__AFS_PAGE_PRIV_SHIFT - 1);
+       return (shift > 0) ? shift : 0;
+}
+
+static inline size_t afs_page_dirty_from(unsigned long priv)
+{
+       unsigned long x = priv & __AFS_PAGE_PRIV_MASK;
+
+       /* The lower bound is inclusive */
+       return x << afs_page_dirty_resolution();
+}
+
+static inline size_t afs_page_dirty_to(unsigned long priv)
+{
+       unsigned long x = (priv >> __AFS_PAGE_PRIV_SHIFT) & __AFS_PAGE_PRIV_MASK;
+
+       /* The upper bound is immediately beyond the region */
+       return (x + 1) << afs_page_dirty_resolution();
+}
+
+static inline unsigned long afs_page_dirty(size_t from, size_t to)
+{
+       unsigned int res = afs_page_dirty_resolution();
+       from >>= res;
+       to = (to - 1) >> res;
+       return (to << __AFS_PAGE_PRIV_SHIFT) | from;
+}
+
+static inline unsigned long afs_page_dirty_mmapped(unsigned long priv)
+{
+       return priv | __AFS_PAGE_PRIV_MMAPPED;
+}
+
+static inline bool afs_is_page_dirty_mmapped(unsigned long priv)
+{
+       return priv & __AFS_PAGE_PRIV_MMAPPED;
+}
+
 #include <trace/events/afs.h>
 
 /*****************************************************************************/
index da12abd6db213b20c2b8ffda1f4bd25ee00bf450..c9195fc67fd8fc41dbe5614b04e3cd9a5f0e42dd 100644 (file)
@@ -76,7 +76,7 @@ static int afs_fill_page(struct afs_vnode *vnode, struct key *key,
  */
 int afs_write_begin(struct file *file, struct address_space *mapping,
                    loff_t pos, unsigned len, unsigned flags,
-                   struct page **pagep, void **fsdata)
+                   struct page **_page, void **fsdata)
 {
        struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
        struct page *page;
@@ -90,11 +90,6 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
        _enter("{%llx:%llu},{%lx},%u,%u",
               vnode->fid.vid, vnode->fid.vnode, index, from, to);
 
-       /* We want to store information about how much of a page is altered in
-        * page->private.
-        */
-       BUILD_BUG_ON(PAGE_SIZE > 32768 && sizeof(page->private) < 8);
-
        page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page)
                return -ENOMEM;
@@ -110,9 +105,6 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
                SetPageUptodate(page);
        }
 
-       /* page won't leak in error case: it eventually gets cleaned off LRU */
-       *pagep = page;
-
 try_again:
        /* See if this page is already partially written in a way that we can
         * merge the new write with.
@@ -120,8 +112,8 @@ try_again:
        t = f = 0;
        if (PagePrivate(page)) {
                priv = page_private(page);
-               f = priv & AFS_PRIV_MAX;
-               t = priv >> AFS_PRIV_SHIFT;
+               f = afs_page_dirty_from(priv);
+               t = afs_page_dirty_to(priv);
                ASSERTCMP(f, <=, t);
        }
 
@@ -138,21 +130,9 @@ try_again:
                if (!test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags) &&
                    (to < f || from > t))
                        goto flush_conflicting_write;
-               if (from < f)
-                       f = from;
-               if (to > t)
-                       t = to;
-       } else {
-               f = from;
-               t = to;
        }
 
-       priv = (unsigned long)t << AFS_PRIV_SHIFT;
-       priv |= f;
-       trace_afs_page_dirty(vnode, tracepoint_string("begin"),
-                            page->index, priv);
-       SetPagePrivate(page);
-       set_page_private(page, priv);
+       *_page = page;
        _leave(" = 0");
        return 0;
 
@@ -162,17 +142,18 @@ try_again:
 flush_conflicting_write:
        _debug("flush conflict");
        ret = write_one_page(page);
-       if (ret < 0) {
-               _leave(" = %d", ret);
-               return ret;
-       }
+       if (ret < 0)
+               goto error;
 
        ret = lock_page_killable(page);
-       if (ret < 0) {
-               _leave(" = %d", ret);
-               return ret;
-       }
+       if (ret < 0)
+               goto error;
        goto try_again;
+
+error:
+       put_page(page);
+       _leave(" = %d", ret);
+       return ret;
 }
 
 /*
@@ -184,12 +165,18 @@ int afs_write_end(struct file *file, struct address_space *mapping,
 {
        struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
        struct key *key = afs_file_key(file);
+       unsigned long priv;
+       unsigned int f, from = pos & (PAGE_SIZE - 1);
+       unsigned int t, to = from + copied;
        loff_t i_size, maybe_i_size;
-       int ret;
+       int ret = 0;
 
        _enter("{%llx:%llu},{%lx}",
               vnode->fid.vid, vnode->fid.vnode, page->index);
 
+       if (copied == 0)
+               goto out;
+
        maybe_i_size = pos + copied;
 
        i_size = i_size_read(&vnode->vfs_inode);
@@ -215,6 +202,25 @@ int afs_write_end(struct file *file, struct address_space *mapping,
                SetPageUptodate(page);
        }
 
+       if (PagePrivate(page)) {
+               priv = page_private(page);
+               f = afs_page_dirty_from(priv);
+               t = afs_page_dirty_to(priv);
+               if (from < f)
+                       f = from;
+               if (to > t)
+                       t = to;
+               priv = afs_page_dirty(f, t);
+               set_page_private(page, priv);
+               trace_afs_page_dirty(vnode, tracepoint_string("dirty+"),
+                                    page->index, priv);
+       } else {
+               priv = afs_page_dirty(from, to);
+               attach_page_private(page, (void *)priv);
+               trace_afs_page_dirty(vnode, tracepoint_string("dirty"),
+                                    page->index, priv);
+       }
+
        set_page_dirty(page);
        if (PageDirty(page))
                _debug("dirtied");
@@ -334,10 +340,9 @@ static void afs_pages_written_back(struct afs_vnode *vnode,
                ASSERTCMP(pv.nr, ==, count);
 
                for (loop = 0; loop < count; loop++) {
-                       priv = page_private(pv.pages[loop]);
+                       priv = (unsigned long)detach_page_private(pv.pages[loop]);
                        trace_afs_page_dirty(vnode, tracepoint_string("clear"),
                                             pv.pages[loop]->index, priv);
-                       set_page_private(pv.pages[loop], 0);
                        end_page_writeback(pv.pages[loop]);
                }
                first += count;
@@ -396,7 +401,8 @@ static void afs_store_data_success(struct afs_operation *op)
        op->ctime = op->file[0].scb.status.mtime_client;
        afs_vnode_commit_status(op, &op->file[0]);
        if (op->error == 0) {
-               afs_pages_written_back(vnode, op->store.first, op->store.last);
+               if (!op->store.laundering)
+                       afs_pages_written_back(vnode, op->store.first, op->store.last);
                afs_stat_v(vnode, n_stores);
                atomic_long_add((op->store.last * PAGE_SIZE + op->store.last_to) -
                                (op->store.first * PAGE_SIZE + op->store.first_offset),
@@ -415,7 +421,7 @@ static const struct afs_operation_ops afs_store_data_operation = {
  */
 static int afs_store_data(struct address_space *mapping,
                          pgoff_t first, pgoff_t last,
-                         unsigned offset, unsigned to)
+                         unsigned offset, unsigned to, bool laundering)
 {
        struct afs_vnode *vnode = AFS_FS_I(mapping->host);
        struct afs_operation *op;
@@ -448,6 +454,7 @@ static int afs_store_data(struct address_space *mapping,
        op->store.last = last;
        op->store.first_offset = offset;
        op->store.last_to = to;
+       op->store.laundering = laundering;
        op->mtime = vnode->vfs_inode.i_mtime;
        op->flags |= AFS_OPERATION_UNINTR;
        op->ops = &afs_store_data_operation;
@@ -509,8 +516,8 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
         */
        start = primary_page->index;
        priv = page_private(primary_page);
-       offset = priv & AFS_PRIV_MAX;
-       to = priv >> AFS_PRIV_SHIFT;
+       offset = afs_page_dirty_from(priv);
+       to = afs_page_dirty_to(priv);
        trace_afs_page_dirty(vnode, tracepoint_string("store"),
                             primary_page->index, priv);
 
@@ -555,8 +562,8 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
                        }
 
                        priv = page_private(page);
-                       f = priv & AFS_PRIV_MAX;
-                       t = priv >> AFS_PRIV_SHIFT;
+                       f = afs_page_dirty_from(priv);
+                       t = afs_page_dirty_to(priv);
                        if (f != 0 &&
                            !test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags)) {
                                unlock_page(page);
@@ -601,7 +608,7 @@ no_more:
        if (end > i_size)
                to = i_size & ~PAGE_MASK;
 
-       ret = afs_store_data(mapping, first, last, offset, to);
+       ret = afs_store_data(mapping, first, last, offset, to, false);
        switch (ret) {
        case 0:
                ret = count;
@@ -857,12 +864,14 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf)
         */
        wait_on_page_writeback(vmf->page);
 
-       priv = (unsigned long)PAGE_SIZE << AFS_PRIV_SHIFT; /* To */
-       priv |= 0; /* From */
+       priv = afs_page_dirty(0, PAGE_SIZE);
+       priv = afs_page_dirty_mmapped(priv);
        trace_afs_page_dirty(vnode, tracepoint_string("mkwrite"),
                             vmf->page->index, priv);
-       SetPagePrivate(vmf->page);
-       set_page_private(vmf->page, priv);
+       if (PagePrivate(vmf->page))
+               set_page_private(vmf->page, priv);
+       else
+               attach_page_private(vmf->page, (void *)priv);
        file_update_time(file);
 
        sb_end_pagefault(inode->i_sb);
@@ -915,19 +924,18 @@ int afs_launder_page(struct page *page)
                f = 0;
                t = PAGE_SIZE;
                if (PagePrivate(page)) {
-                       f = priv & AFS_PRIV_MAX;
-                       t = priv >> AFS_PRIV_SHIFT;
+                       f = afs_page_dirty_from(priv);
+                       t = afs_page_dirty_to(priv);
                }
 
                trace_afs_page_dirty(vnode, tracepoint_string("launder"),
                                     page->index, priv);
-               ret = afs_store_data(mapping, page->index, page->index, t, f);
+               ret = afs_store_data(mapping, page->index, page->index, t, f, true);
        }
 
+       priv = (unsigned long)detach_page_private(page);
        trace_afs_page_dirty(vnode, tracepoint_string("laundered"),
                             page->index, priv);
-       set_page_private(page, 0);
-       ClearPagePrivate(page);
 
 #ifdef CONFIG_AFS_FSCACHE
        if (PageFsCache(page)) {
index 84f3c4f575318d1691068eed06827f573f4be83b..95c573dcda1169d24438775fb143a94dbd1706a2 100644 (file)
@@ -85,7 +85,7 @@ static int afs_xattr_get_acl(const struct xattr_handler *handler,
                        if (acl->size <= size)
                                memcpy(buffer, acl->data, acl->size);
                        else
-                               op->error = -ERANGE;
+                               ret = -ERANGE;
                }
        }
 
@@ -148,11 +148,6 @@ static const struct xattr_handler afs_xattr_afs_acl_handler = {
        .set    = afs_xattr_set_acl,
 };
 
-static void yfs_acl_put(struct afs_operation *op)
-{
-       yfs_free_opaque_acl(op->yacl);
-}
-
 static const struct afs_operation_ops yfs_fetch_opaque_acl_operation = {
        .issue_yfs_rpc  = yfs_fs_fetch_opaque_acl,
        .success        = afs_acl_success,
@@ -246,7 +241,7 @@ error:
 static const struct afs_operation_ops yfs_store_opaque_acl2_operation = {
        .issue_yfs_rpc  = yfs_fs_store_opaque_acl2,
        .success        = afs_acl_success,
-       .put            = yfs_acl_put,
+       .put            = afs_acl_put,
 };
 
 /*
index 3b1239b7e90d8cffaa957e30a507dad2b8174afd..bd787e71a657f9b683922eeb7cd2ac5b655eb620 100644 (file)
@@ -1990,6 +1990,7 @@ void yfs_fs_store_opaque_acl2(struct afs_operation *op)
        memcpy(bp, acl->data, acl->size);
        if (acl->size != size)
                memset((void *)bp + acl->size, 0, size - acl->size);
+       bp += size / sizeof(__be32);
        yfs_check_req(call, bp);
 
        trace_afs_make_fs_call(call, &vp->fid);
index c45c20d875388c8c3562e9bef2af8b611889fcac..6a21d8919409c4aa2c0378108337724a1f73eb35 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1572,7 +1572,7 @@ static int aio_write(struct kiocb *req, const struct iocb *iocb,
                 * we return to userspace.
                 */
                if (S_ISREG(file_inode(file)->i_mode)) {
-                       __sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, true);
+                       sb_start_write(file_inode(file)->i_sb);
                        __sb_writers_release(file_inode(file)->i_sb, SB_FREEZE_WRITE);
                }
                req->ki_flags |= IOCB_WRITE;
index b6b3d052ca86dee2084da5d806d7848e80cac1c1..fa50e8936f5fc30205bfb845afd70e1f3e7f366a 100644 (file)
@@ -1690,7 +1690,7 @@ struct elf_thread_core_info {
        struct elf_thread_core_info *next;
        struct task_struct *task;
        struct elf_prstatus prstatus;
-       struct memelfnote notes[0];
+       struct memelfnote notes[];
 };
 
 struct elf_note_info {
index b3268f4ea5f34c187108a628890231d3eec43396..771a036867dc05e5dbba4dd9f06d6536c9279c0c 100644 (file)
@@ -544,7 +544,18 @@ static int resolve_indirect_ref(struct btrfs_fs_info *fs_info,
        int level = ref->level;
        struct btrfs_key search_key = ref->key_for_search;
 
-       root = btrfs_get_fs_root(fs_info, ref->root_id, false);
+       /*
+        * If we're search_commit_root we could possibly be holding locks on
+        * other tree nodes.  This happens when qgroups does backref walks when
+        * adding new delayed refs.  To deal with this we need to look in cache
+        * for the root, and if we don't find it then we need to search the
+        * tree_root's commit root, thus the btrfs_get_fs_root_commit_root usage
+        * here.
+        */
+       if (path->search_commit_root)
+               root = btrfs_get_fs_root_commit_root(fs_info, path, ref->root_id);
+       else
+               root = btrfs_get_fs_root(fs_info, ref->root_id, false);
        if (IS_ERR(root)) {
                ret = PTR_ERR(root);
                goto out_free;
index c0f1d6818df769604a3d4652d6bd684f49195d0f..3ba6f3839d3929e5ab6d7d60ce76ccd8b44a5387 100644 (file)
@@ -2024,6 +2024,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
                key.offset = 0;
                btrfs_release_path(path);
        }
+       btrfs_release_path(path);
 
        list_for_each_entry(space_info, &info->space_info, list) {
                int i;
index 7e1549a84fcc99d4d8c7e8b45691c71ebd254867..bc920afe23bf09681cacf51b4db0f10648c3f974 100644 (file)
@@ -511,7 +511,8 @@ again:
                                /*DEFAULT_RATELIMIT_BURST*/ 1);
                if (__ratelimit(&_rs))
                        WARN(1, KERN_DEBUG
-                               "BTRFS: block rsv returned %d\n", ret);
+                               "BTRFS: block rsv %d returned %d\n",
+                               block_rsv->type, ret);
        }
 try_reserve:
        ret = btrfs_reserve_metadata_bytes(root, block_rsv, blocksize,
index aac3d6f4e35b170933d43a5befa0be88f89a2966..0b29bdb251050c60c555c4e1de6c22fd6061838e 100644 (file)
@@ -878,7 +878,10 @@ struct btrfs_fs_info {
         */
        struct ulist *qgroup_ulist;
 
-       /* protect user change for quota operations */
+       /*
+        * Protect user change for quota operations. If a transaction is needed,
+        * it must be started before locking this lock.
+        */
        struct mutex qgroup_ioctl_lock;
 
        /* list of dirty qgroups to be written at next commit */
@@ -3564,6 +3567,8 @@ struct reada_control *btrfs_reada_add(struct btrfs_root *root,
 int btrfs_reada_wait(void *handle);
 void btrfs_reada_detach(void *handle);
 int btree_readahead_hook(struct extent_buffer *eb, int err);
+void btrfs_reada_remove_dev(struct btrfs_device *dev);
+void btrfs_reada_undo_remove_dev(struct btrfs_device *dev);
 
 static inline int is_fstree(u64 rootid)
 {
index 4a0243cb9d9730401f967c46ede2ec3a62a58556..10638537b9ef30a2a6ebde52fbecd68a93aa1746 100644 (file)
@@ -91,6 +91,17 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
        ret = btrfs_search_slot(NULL, dev_root, &key, path, 0, 0);
        if (ret) {
 no_valid_dev_replace_entry_found:
+               /*
+                * We don't have a replace item or it's corrupted.  If there is
+                * a replace target, fail the mount.
+                */
+               if (btrfs_find_device(fs_info->fs_devices,
+                                     BTRFS_DEV_REPLACE_DEVID, NULL, NULL, false)) {
+                       btrfs_err(fs_info,
+                       "found replace target device without a valid replace item");
+                       ret = -EUCLEAN;
+                       goto out;
+               }
                ret = 0;
                dev_replace->replace_state =
                        BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED;
@@ -143,8 +154,19 @@ no_valid_dev_replace_entry_found:
        case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
        case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
        case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
-               dev_replace->srcdev = NULL;
-               dev_replace->tgtdev = NULL;
+               /*
+                * We don't have an active replace item but if there is a
+                * replace target, fail the mount.
+                */
+               if (btrfs_find_device(fs_info->fs_devices,
+                                     BTRFS_DEV_REPLACE_DEVID, NULL, NULL, false)) {
+                       btrfs_err(fs_info,
+                       "replace devid present without an active replace item");
+                       ret = -EUCLEAN;
+               } else {
+                       dev_replace->srcdev = NULL;
+                       dev_replace->tgtdev = NULL;
+               }
                break;
        case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
        case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
@@ -688,6 +710,9 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
        }
        btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
 
+       if (!scrub_ret)
+               btrfs_reada_remove_dev(src_device);
+
        /*
         * We have to use this loop approach because at this point src_device
         * has to be available for transaction commit to complete, yet new
@@ -696,6 +721,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
        while (1) {
                trans = btrfs_start_transaction(root, 0);
                if (IS_ERR(trans)) {
+                       btrfs_reada_undo_remove_dev(src_device);
                        mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
                        return PTR_ERR(trans);
                }
@@ -746,6 +772,7 @@ error:
                up_write(&dev_replace->rwsem);
                mutex_unlock(&fs_info->chunk_mutex);
                mutex_unlock(&fs_info->fs_devices->device_list_mutex);
+               btrfs_reada_undo_remove_dev(src_device);
                btrfs_rm_dev_replace_blocked(fs_info);
                if (tgt_device)
                        btrfs_destroy_dev_replace_tgtdev(tgt_device);
index 8e3438672a82d2f53c78922fa43572e1fc130eb8..af97ddcc6b3e8710cf9a55a4064192b3b1027b81 100644 (file)
@@ -1281,32 +1281,26 @@ int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
        return 0;
 }
 
-struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root,
-                                       struct btrfs_key *key)
+static struct btrfs_root *read_tree_root_path(struct btrfs_root *tree_root,
+                                             struct btrfs_path *path,
+                                             struct btrfs_key *key)
 {
        struct btrfs_root *root;
        struct btrfs_fs_info *fs_info = tree_root->fs_info;
-       struct btrfs_path *path;
        u64 generation;
        int ret;
        int level;
 
-       path = btrfs_alloc_path();
-       if (!path)
-               return ERR_PTR(-ENOMEM);
-
        root = btrfs_alloc_root(fs_info, key->objectid, GFP_NOFS);
-       if (!root) {
-               ret = -ENOMEM;
-               goto alloc_fail;
-       }
+       if (!root)
+               return ERR_PTR(-ENOMEM);
 
        ret = btrfs_find_root(tree_root, key, path,
                              &root->root_item, &root->root_key);
        if (ret) {
                if (ret > 0)
                        ret = -ENOENT;
-               goto find_fail;
+               goto fail;
        }
 
        generation = btrfs_root_generation(&root->root_item);
@@ -1317,21 +1311,31 @@ struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root,
        if (IS_ERR(root->node)) {
                ret = PTR_ERR(root->node);
                root->node = NULL;
-               goto find_fail;
+               goto fail;
        } else if (!btrfs_buffer_uptodate(root->node, generation, 0)) {
                ret = -EIO;
-               goto find_fail;
+               goto fail;
        }
        root->commit_root = btrfs_root_node(root);
-out:
-       btrfs_free_path(path);
        return root;
-
-find_fail:
+fail:
        btrfs_put_root(root);
-alloc_fail:
-       root = ERR_PTR(ret);
-       goto out;
+       return ERR_PTR(ret);
+}
+
+struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root,
+                                       struct btrfs_key *key)
+{
+       struct btrfs_root *root;
+       struct btrfs_path *path;
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return ERR_PTR(-ENOMEM);
+       root = read_tree_root_path(tree_root, path, key);
+       btrfs_free_path(path);
+
+       return root;
 }
 
 /*
@@ -1419,6 +1423,31 @@ static struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info,
        return root;
 }
 
+static struct btrfs_root *btrfs_get_global_root(struct btrfs_fs_info *fs_info,
+                                               u64 objectid)
+{
+       if (objectid == BTRFS_ROOT_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->tree_root);
+       if (objectid == BTRFS_EXTENT_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->extent_root);
+       if (objectid == BTRFS_CHUNK_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->chunk_root);
+       if (objectid == BTRFS_DEV_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->dev_root);
+       if (objectid == BTRFS_CSUM_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->csum_root);
+       if (objectid == BTRFS_QUOTA_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->quota_root) ?
+                       fs_info->quota_root : ERR_PTR(-ENOENT);
+       if (objectid == BTRFS_UUID_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->uuid_root) ?
+                       fs_info->uuid_root : ERR_PTR(-ENOENT);
+       if (objectid == BTRFS_FREE_SPACE_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->free_space_root) ?
+                       fs_info->free_space_root : ERR_PTR(-ENOENT);
+       return NULL;
+}
+
 int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info,
                         struct btrfs_root *root)
 {
@@ -1518,25 +1547,9 @@ static struct btrfs_root *btrfs_get_root_ref(struct btrfs_fs_info *fs_info,
        struct btrfs_key key;
        int ret;
 
-       if (objectid == BTRFS_ROOT_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->tree_root);
-       if (objectid == BTRFS_EXTENT_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->extent_root);
-       if (objectid == BTRFS_CHUNK_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->chunk_root);
-       if (objectid == BTRFS_DEV_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->dev_root);
-       if (objectid == BTRFS_CSUM_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->csum_root);
-       if (objectid == BTRFS_QUOTA_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->quota_root) ?
-                       fs_info->quota_root : ERR_PTR(-ENOENT);
-       if (objectid == BTRFS_UUID_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->uuid_root) ?
-                       fs_info->uuid_root : ERR_PTR(-ENOENT);
-       if (objectid == BTRFS_FREE_SPACE_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->free_space_root) ?
-                       fs_info->free_space_root : ERR_PTR(-ENOENT);
+       root = btrfs_get_global_root(fs_info, objectid);
+       if (root)
+               return root;
 again:
        root = btrfs_lookup_fs_root(fs_info, objectid);
        if (root) {
@@ -1621,6 +1634,52 @@ struct btrfs_root *btrfs_get_new_fs_root(struct btrfs_fs_info *fs_info,
        return btrfs_get_root_ref(fs_info, objectid, anon_dev, true);
 }
 
+/*
+ * btrfs_get_fs_root_commit_root - return a root for the given objectid
+ * @fs_info:   the fs_info
+ * @objectid:  the objectid we need to lookup
+ *
+ * This is exclusively used for backref walking, and exists specifically because
+ * of how qgroups does lookups.  Qgroups will do a backref lookup at delayed ref
+ * creation time, which means we may have to read the tree_root in order to look
+ * up a fs root that is not in memory.  If the root is not in memory we will
+ * read the tree root commit root and look up the fs root from there.  This is a
+ * temporary root, it will not be inserted into the radix tree as it doesn't
+ * have the most uptodate information, it'll simply be discarded once the
+ * backref code is finished using the root.
+ */
+struct btrfs_root *btrfs_get_fs_root_commit_root(struct btrfs_fs_info *fs_info,
+                                                struct btrfs_path *path,
+                                                u64 objectid)
+{
+       struct btrfs_root *root;
+       struct btrfs_key key;
+
+       ASSERT(path->search_commit_root && path->skip_locking);
+
+       /*
+        * This can return -ENOENT if we ask for a root that doesn't exist, but
+        * since this is called via the backref walking code we won't be looking
+        * up a root that doesn't exist, unless there's corruption.  So if root
+        * != NULL just return it.
+        */
+       root = btrfs_get_global_root(fs_info, objectid);
+       if (root)
+               return root;
+
+       root = btrfs_lookup_fs_root(fs_info, objectid);
+       if (root)
+               return root;
+
+       key.objectid = objectid;
+       key.type = BTRFS_ROOT_ITEM_KEY;
+       key.offset = (u64)-1;
+       root = read_tree_root_path(fs_info->tree_root, path, &key);
+       btrfs_release_path(path);
+
+       return root;
+}
+
 /*
  * called by the kthread helper functions to finally call the bio end_io
  * functions.  This is where read checksum verification actually happens
index fee69ced58b4b921df680dd9b39c87bdceb9df57..182540bdcea0fd3002435b034d6bd84c839949bb 100644 (file)
@@ -69,6 +69,9 @@ struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
                                     u64 objectid, bool check_ref);
 struct btrfs_root *btrfs_get_new_fs_root(struct btrfs_fs_info *fs_info,
                                         u64 objectid, dev_t anon_dev);
+struct btrfs_root *btrfs_get_fs_root_commit_root(struct btrfs_fs_info *fs_info,
+                                                struct btrfs_path *path,
+                                                u64 objectid);
 
 void btrfs_free_fs_info(struct btrfs_fs_info *fs_info);
 int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info);
index 3b21fee13e77811e1d6cba72478ef8f805ef28a8..5fd60b13f4f83287df44432acfb305228c674495 100644 (file)
@@ -3185,7 +3185,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                struct btrfs_tree_block_info *bi;
                if (item_size < sizeof(*ei) + sizeof(*bi)) {
                        btrfs_crit(info,
-"invalid extent item size for key (%llu, %u, %llu) owner %llu, has %u expect >= %lu",
+"invalid extent item size for key (%llu, %u, %llu) owner %llu, has %u expect >= %zu",
                                   key.objectid, key.type, key.offset,
                                   owner_objectid, item_size,
                                   sizeof(*ei) + sizeof(*bi));
index 0ff659455b1ebc8588ef781cab448294579b14ba..4373da7bcc0d58a3d63fe33afdbd6547a17bf7a1 100644 (file)
@@ -452,46 +452,6 @@ static void btrfs_drop_pages(struct page **pages, size_t num_pages)
        }
 }
 
-static int btrfs_find_new_delalloc_bytes(struct btrfs_inode *inode,
-                                        const u64 start,
-                                        const u64 len,
-                                        struct extent_state **cached_state)
-{
-       u64 search_start = start;
-       const u64 end = start + len - 1;
-
-       while (search_start < end) {
-               const u64 search_len = end - search_start + 1;
-               struct extent_map *em;
-               u64 em_len;
-               int ret = 0;
-
-               em = btrfs_get_extent(inode, NULL, 0, search_start, search_len);
-               if (IS_ERR(em))
-                       return PTR_ERR(em);
-
-               if (em->block_start != EXTENT_MAP_HOLE)
-                       goto next;
-
-               em_len = em->len;
-               if (em->start < search_start)
-                       em_len -= search_start - em->start;
-               if (em_len > search_len)
-                       em_len = search_len;
-
-               ret = set_extent_bit(&inode->io_tree, search_start,
-                                    search_start + em_len - 1,
-                                    EXTENT_DELALLOC_NEW,
-                                    NULL, cached_state, GFP_NOFS);
-next:
-               search_start = extent_map_end(em);
-               free_extent_map(em);
-               if (ret)
-                       return ret;
-       }
-       return 0;
-}
-
 /*
  * after copy_from_user, pages need to be dirtied and we need to make
  * sure holes are created between the current EOF and the start of
@@ -528,23 +488,6 @@ int btrfs_dirty_pages(struct btrfs_inode *inode, struct page **pages,
                         EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
                         0, 0, cached);
 
-       if (!btrfs_is_free_space_inode(inode)) {
-               if (start_pos >= isize &&
-                   !(inode->flags & BTRFS_INODE_PREALLOC)) {
-                       /*
-                        * There can't be any extents following eof in this case
-                        * so just set the delalloc new bit for the range
-                        * directly.
-                        */
-                       extra_bits |= EXTENT_DELALLOC_NEW;
-               } else {
-                       err = btrfs_find_new_delalloc_bytes(inode, start_pos,
-                                                           num_bytes, cached);
-                       if (err)
-                               return err;
-               }
-       }
-
        err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block,
                                        extra_bits, cached);
        if (err)
@@ -3628,7 +3571,8 @@ static ssize_t btrfs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
                inode_lock_shared(inode);
                ret = btrfs_direct_IO(iocb, to);
                inode_unlock_shared(inode);
-               if (ret < 0)
+               if (ret < 0 || !iov_iter_count(to) ||
+                   iocb->ki_pos >= i_size_read(file_inode(iocb->ki_filp)))
                        return ret;
        }
 
index 936c3137c6467d30e8bca4fdb6398e51b11c52ae..7e8d8169779d248def4688b8f80ad8c10be4e83b 100644 (file)
@@ -2253,11 +2253,69 @@ static int add_pending_csums(struct btrfs_trans_handle *trans,
        return 0;
 }
 
+static int btrfs_find_new_delalloc_bytes(struct btrfs_inode *inode,
+                                        const u64 start,
+                                        const u64 len,
+                                        struct extent_state **cached_state)
+{
+       u64 search_start = start;
+       const u64 end = start + len - 1;
+
+       while (search_start < end) {
+               const u64 search_len = end - search_start + 1;
+               struct extent_map *em;
+               u64 em_len;
+               int ret = 0;
+
+               em = btrfs_get_extent(inode, NULL, 0, search_start, search_len);
+               if (IS_ERR(em))
+                       return PTR_ERR(em);
+
+               if (em->block_start != EXTENT_MAP_HOLE)
+                       goto next;
+
+               em_len = em->len;
+               if (em->start < search_start)
+                       em_len -= search_start - em->start;
+               if (em_len > search_len)
+                       em_len = search_len;
+
+               ret = set_extent_bit(&inode->io_tree, search_start,
+                                    search_start + em_len - 1,
+                                    EXTENT_DELALLOC_NEW,
+                                    NULL, cached_state, GFP_NOFS);
+next:
+               search_start = extent_map_end(em);
+               free_extent_map(em);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
 int btrfs_set_extent_delalloc(struct btrfs_inode *inode, u64 start, u64 end,
                              unsigned int extra_bits,
                              struct extent_state **cached_state)
 {
        WARN_ON(PAGE_ALIGNED(end));
+
+       if (start >= i_size_read(&inode->vfs_inode) &&
+           !(inode->flags & BTRFS_INODE_PREALLOC)) {
+               /*
+                * There can't be any extents following eof in this case so just
+                * set the delalloc new bit for the range directly.
+                */
+               extra_bits |= EXTENT_DELALLOC_NEW;
+       } else {
+               int ret;
+
+               ret = btrfs_find_new_delalloc_bytes(inode, start,
+                                                   end + 1 - start,
+                                                   cached_state);
+               if (ret)
+                       return ret;
+       }
+
        return set_extent_delalloc(&inode->io_tree, start, end, extra_bits,
                                   cached_state);
 }
@@ -9672,10 +9730,16 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
                 * clear_offset by our extent size.
                 */
                clear_offset += ins.offset;
-               btrfs_dec_block_group_reservations(fs_info, ins.objectid);
 
                last_alloc = ins.offset;
                trans = insert_prealloc_file_extent(trans, inode, &ins, cur_offset);
+               /*
+                * Now that we inserted the prealloc extent we can finally
+                * decrement the number of reservations in the block group.
+                * If we did it before, we could race with relocation and have
+                * relocation miss the reserved extent, making it fail later.
+                */
+               btrfs_dec_block_group_reservations(fs_info, ins.objectid);
                if (IS_ERR(trans)) {
                        ret = PTR_ERR(trans);
                        btrfs_free_reserved_extent(fs_info, ins.objectid,
index ab408a23ba32dcafccccb741c2c890c538b84708..69a384145dc6fc2d79ac1cd05a2b8f5220686a5b 100644 (file)
@@ -1274,6 +1274,7 @@ static int cluster_pages_for_defrag(struct inode *inode,
        u64 page_start;
        u64 page_end;
        u64 page_cnt;
+       u64 start = (u64)start_index << PAGE_SHIFT;
        int ret;
        int i;
        int i_done;
@@ -1290,8 +1291,7 @@ static int cluster_pages_for_defrag(struct inode *inode,
        page_cnt = min_t(u64, (u64)num_pages, (u64)file_end - start_index + 1);
 
        ret = btrfs_delalloc_reserve_space(BTRFS_I(inode), &data_reserved,
-                       start_index << PAGE_SHIFT,
-                       page_cnt << PAGE_SHIFT);
+                       start, page_cnt << PAGE_SHIFT);
        if (ret)
                return ret;
        i_done = 0;
@@ -1380,8 +1380,7 @@ again:
                btrfs_mod_outstanding_extents(BTRFS_I(inode), 1);
                spin_unlock(&BTRFS_I(inode)->lock);
                btrfs_delalloc_release_space(BTRFS_I(inode), data_reserved,
-                               start_index << PAGE_SHIFT,
-                               (page_cnt - i_done) << PAGE_SHIFT, true);
+                               start, (page_cnt - i_done) << PAGE_SHIFT, true);
        }
 
 
@@ -1408,8 +1407,7 @@ out:
                put_page(pages[i]);
        }
        btrfs_delalloc_release_space(BTRFS_I(inode), data_reserved,
-                       start_index << PAGE_SHIFT,
-                       page_cnt << PAGE_SHIFT, true);
+                       start, page_cnt << PAGE_SHIFT, true);
        btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT);
        extent_changeset_free(data_reserved);
        return ret;
index 580899bdb9915bad902322d530808532f7e8a975..87bd37b70738ec58676f0d338a13906f1f9b6db6 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/btrfs.h>
+#include <linux/sched/mm.h>
 
 #include "ctree.h"
 #include "transaction.h"
@@ -497,13 +498,13 @@ next2:
                        break;
        }
 out:
+       btrfs_free_path(path);
        fs_info->qgroup_flags |= flags;
        if (!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON))
                clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
        else if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN &&
                 ret >= 0)
                ret = qgroup_rescan_init(fs_info, rescan_progress, 0);
-       btrfs_free_path(path);
 
        if (ret < 0) {
                ulist_free(fs_info->qgroup_ulist);
@@ -936,6 +937,7 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
        struct btrfs_key found_key;
        struct btrfs_qgroup *qgroup = NULL;
        struct btrfs_trans_handle *trans = NULL;
+       struct ulist *ulist = NULL;
        int ret = 0;
        int slot;
 
@@ -943,8 +945,8 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
        if (fs_info->quota_root)
                goto out;
 
-       fs_info->qgroup_ulist = ulist_alloc(GFP_KERNEL);
-       if (!fs_info->qgroup_ulist) {
+       ulist = ulist_alloc(GFP_KERNEL);
+       if (!ulist) {
                ret = -ENOMEM;
                goto out;
        }
@@ -952,6 +954,22 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
        ret = btrfs_sysfs_add_qgroups(fs_info);
        if (ret < 0)
                goto out;
+
+       /*
+        * Unlock qgroup_ioctl_lock before starting the transaction. This is to
+        * avoid lock acquisition inversion problems (reported by lockdep) between
+        * qgroup_ioctl_lock and the vfs freeze semaphores, acquired when we
+        * start a transaction.
+        * After we started the transaction lock qgroup_ioctl_lock again and
+        * check if someone else created the quota root in the meanwhile. If so,
+        * just return success and release the transaction handle.
+        *
+        * Also we don't need to worry about someone else calling
+        * btrfs_sysfs_add_qgroups() after we unlock and getting an error because
+        * that function returns 0 (success) when the sysfs entries already exist.
+        */
+       mutex_unlock(&fs_info->qgroup_ioctl_lock);
+
        /*
         * 1 for quota root item
         * 1 for BTRFS_QGROUP_STATUS item
@@ -961,12 +979,20 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
         * would be a lot of overkill.
         */
        trans = btrfs_start_transaction(tree_root, 2);
+
+       mutex_lock(&fs_info->qgroup_ioctl_lock);
        if (IS_ERR(trans)) {
                ret = PTR_ERR(trans);
                trans = NULL;
                goto out;
        }
 
+       if (fs_info->quota_root)
+               goto out;
+
+       fs_info->qgroup_ulist = ulist;
+       ulist = NULL;
+
        /*
         * initially create the quota tree
         */
@@ -1026,6 +1052,10 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
                btrfs_item_key_to_cpu(leaf, &found_key, slot);
 
                if (found_key.type == BTRFS_ROOT_REF_KEY) {
+
+                       /* Release locks on tree_root before we access quota_root */
+                       btrfs_release_path(path);
+
                        ret = add_qgroup_item(trans, quota_root,
                                              found_key.offset);
                        if (ret) {
@@ -1044,6 +1074,20 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
                                btrfs_abort_transaction(trans, ret);
                                goto out_free_path;
                        }
+                       ret = btrfs_search_slot_for_read(tree_root, &found_key,
+                                                        path, 1, 0);
+                       if (ret < 0) {
+                               btrfs_abort_transaction(trans, ret);
+                               goto out_free_path;
+                       }
+                       if (ret > 0) {
+                               /*
+                                * Shouldn't happen, but in case it does we
+                                * don't need to do the btrfs_next_item, just
+                                * continue.
+                                */
+                               continue;
+                       }
                }
                ret = btrfs_next_item(tree_root, path);
                if (ret < 0) {
@@ -1106,11 +1150,14 @@ out:
        if (ret) {
                ulist_free(fs_info->qgroup_ulist);
                fs_info->qgroup_ulist = NULL;
-               if (trans)
-                       btrfs_end_transaction(trans);
                btrfs_sysfs_del_qgroups(fs_info);
        }
        mutex_unlock(&fs_info->qgroup_ioctl_lock);
+       if (ret && trans)
+               btrfs_end_transaction(trans);
+       else if (trans)
+               ret = btrfs_end_transaction(trans);
+       ulist_free(ulist);
        return ret;
 }
 
@@ -1123,19 +1170,29 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
        mutex_lock(&fs_info->qgroup_ioctl_lock);
        if (!fs_info->quota_root)
                goto out;
+       mutex_unlock(&fs_info->qgroup_ioctl_lock);
 
        /*
         * 1 For the root item
         *
         * We should also reserve enough items for the quota tree deletion in
         * btrfs_clean_quota_tree but this is not done.
+        *
+        * Also, we must always start a transaction without holding the mutex
+        * qgroup_ioctl_lock, see btrfs_quota_enable().
         */
        trans = btrfs_start_transaction(fs_info->tree_root, 1);
+
+       mutex_lock(&fs_info->qgroup_ioctl_lock);
        if (IS_ERR(trans)) {
                ret = PTR_ERR(trans);
+               trans = NULL;
                goto out;
        }
 
+       if (!fs_info->quota_root)
+               goto out;
+
        clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
        btrfs_qgroup_wait_for_completion(fs_info, false);
        spin_lock(&fs_info->qgroup_lock);
@@ -1149,13 +1206,13 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
        ret = btrfs_clean_quota_tree(trans, quota_root);
        if (ret) {
                btrfs_abort_transaction(trans, ret);
-               goto end_trans;
+               goto out;
        }
 
        ret = btrfs_del_root(trans, &quota_root->root_key);
        if (ret) {
                btrfs_abort_transaction(trans, ret);
-               goto end_trans;
+               goto out;
        }
 
        list_del(&quota_root->dirty_list);
@@ -1167,10 +1224,13 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
 
        btrfs_put_root(quota_root);
 
-end_trans:
-       ret = btrfs_end_transaction(trans);
 out:
        mutex_unlock(&fs_info->qgroup_ioctl_lock);
+       if (ret && trans)
+               btrfs_end_transaction(trans);
+       else if (trans)
+               ret = btrfs_end_transaction(trans);
+
        return ret;
 }
 
@@ -1306,13 +1366,17 @@ int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, u64 src,
        struct btrfs_qgroup *member;
        struct btrfs_qgroup_list *list;
        struct ulist *tmp;
+       unsigned int nofs_flag;
        int ret = 0;
 
        /* Check the level of src and dst first */
        if (btrfs_qgroup_level(src) >= btrfs_qgroup_level(dst))
                return -EINVAL;
 
+       /* We hold a transaction handle open, must do a NOFS allocation. */
+       nofs_flag = memalloc_nofs_save();
        tmp = ulist_alloc(GFP_KERNEL);
+       memalloc_nofs_restore(nofs_flag);
        if (!tmp)
                return -ENOMEM;
 
@@ -1369,10 +1433,14 @@ static int __del_qgroup_relation(struct btrfs_trans_handle *trans, u64 src,
        struct btrfs_qgroup_list *list;
        struct ulist *tmp;
        bool found = false;
+       unsigned int nofs_flag;
        int ret = 0;
        int ret2;
 
+       /* We hold a transaction handle open, must do a NOFS allocation. */
+       nofs_flag = memalloc_nofs_save();
        tmp = ulist_alloc(GFP_KERNEL);
+       memalloc_nofs_restore(nofs_flag);
        if (!tmp)
                return -ENOMEM;
 
@@ -3417,24 +3485,20 @@ static int qgroup_unreserve_range(struct btrfs_inode *inode,
 {
        struct rb_node *node;
        struct rb_node *next;
-       struct ulist_node *entry = NULL;
+       struct ulist_node *entry;
        int ret = 0;
 
        node = reserved->range_changed.root.rb_node;
+       if (!node)
+               return 0;
        while (node) {
                entry = rb_entry(node, struct ulist_node, rb_node);
                if (entry->val < start)
                        node = node->rb_right;
-               else if (entry)
-                       node = node->rb_left;
                else
-                       break;
+                       node = node->rb_left;
        }
 
-       /* Empty changeset */
-       if (!entry)
-               return 0;
-
        if (entry->val > start && rb_prev(&entry->rb_node))
                entry = rb_entry(rb_prev(&entry->rb_node), struct ulist_node,
                                 rb_node);
@@ -3498,6 +3562,7 @@ static int try_flush_qgroup(struct btrfs_root *root)
 {
        struct btrfs_trans_handle *trans;
        int ret;
+       bool can_commit = true;
 
        /*
         * We don't want to run flush again and again, so if there is a running
@@ -3509,6 +3574,20 @@ static int try_flush_qgroup(struct btrfs_root *root)
                return 0;
        }
 
+       /*
+        * If current process holds a transaction, we shouldn't flush, as we
+        * assume all space reservation happens before a transaction handle is
+        * held.
+        *
+        * But there are cases like btrfs_delayed_item_reserve_metadata() where
+        * we try to reserve space with one transction handle already held.
+        * In that case we can't commit transaction, but at least try to end it
+        * and hope the started data writes can free some space.
+        */
+       if (current->journal_info &&
+           current->journal_info != BTRFS_SEND_TRANS_STUB)
+               can_commit = false;
+
        ret = btrfs_start_delalloc_snapshot(root);
        if (ret < 0)
                goto out;
@@ -3520,7 +3599,10 @@ static int try_flush_qgroup(struct btrfs_root *root)
                goto out;
        }
 
-       ret = btrfs_commit_transaction(trans);
+       if (can_commit)
+               ret = btrfs_commit_transaction(trans);
+       else
+               ret = btrfs_end_transaction(trans);
 out:
        clear_bit(BTRFS_ROOT_QGROUP_FLUSHING, &root->state);
        wake_up(&root->qgroup_flush_wait);
index 9d4f5316a7e8be1464d9349b6ef9a9fb20fccfcc..d9a166eb344e6484a6e86b11a4c5e7ca09dc35fa 100644 (file)
@@ -421,6 +421,9 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
                if (!dev->bdev)
                        continue;
 
+               if (test_bit(BTRFS_DEV_STATE_NO_READA, &dev->dev_state))
+                       continue;
+
                if (dev_replace_is_ongoing &&
                    dev == fs_info->dev_replace.tgtdev) {
                        /*
@@ -445,6 +448,8 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
                }
                have_zone = 1;
        }
+       if (!have_zone)
+               radix_tree_delete(&fs_info->reada_tree, index);
        spin_unlock(&fs_info->reada_lock);
        up_read(&fs_info->dev_replace.rwsem);
 
@@ -1020,3 +1025,45 @@ void btrfs_reada_detach(void *handle)
 
        kref_put(&rc->refcnt, reada_control_release);
 }
+
+/*
+ * Before removing a device (device replace or device remove ioctls), call this
+ * function to wait for all existing readahead requests on the device and to
+ * make sure no one queues more readahead requests for the device.
+ *
+ * Must be called without holding neither the device list mutex nor the device
+ * replace semaphore, otherwise it will deadlock.
+ */
+void btrfs_reada_remove_dev(struct btrfs_device *dev)
+{
+       struct btrfs_fs_info *fs_info = dev->fs_info;
+
+       /* Serialize with readahead extent creation at reada_find_extent(). */
+       spin_lock(&fs_info->reada_lock);
+       set_bit(BTRFS_DEV_STATE_NO_READA, &dev->dev_state);
+       spin_unlock(&fs_info->reada_lock);
+
+       /*
+        * There might be readahead requests added to the radix trees which
+        * were not yet added to the readahead work queue. We need to start
+        * them and wait for their completion, otherwise we can end up with
+        * use-after-free problems when dropping the last reference on the
+        * readahead extents and their zones, as they need to access the
+        * device structure.
+        */
+       reada_start_machine(fs_info);
+       btrfs_flush_workqueue(fs_info->readahead_workers);
+}
+
+/*
+ * If when removing a device (device replace or device remove ioctls) an error
+ * happens after calling btrfs_reada_remove_dev(), call this to undo what that
+ * function did. This is safe to call even if btrfs_reada_remove_dev() was not
+ * called before.
+ */
+void btrfs_reada_undo_remove_dev(struct btrfs_device *dev)
+{
+       spin_lock(&dev->fs_info->reada_lock);
+       clear_bit(BTRFS_DEV_STATE_NO_READA, &dev->dev_state);
+       spin_unlock(&dev->fs_info->reada_lock);
+}
index 7f03dbe5b609d88090d6c7ae909fad660d8b88b5..78693d3dd15bc1d08eb76766aa00ebf0d42804a0 100644 (file)
@@ -860,6 +860,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);
+                       kfree(ref);
                        kfree(ra);
                        goto out_unlock;
                }
index 3602806d71bd4fa2c3688ce45ba0b4b299f6e3bb..9ba92d86da0bf0ad0ac2b4df4789f8a4f069c4df 100644 (file)
@@ -1648,6 +1648,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
        struct btrfs_root_item *root_item;
        struct btrfs_path *path;
        struct extent_buffer *leaf;
+       int reserve_level;
        int level;
        int max_level;
        int replaced = 0;
@@ -1696,7 +1697,8 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
         * Thus the needed metadata size is at most root_level * nodesize,
         * and * 2 since we have two trees to COW.
         */
-       min_reserved = fs_info->nodesize * btrfs_root_level(root_item) * 2;
+       reserve_level = max_t(int, 1, btrfs_root_level(root_item));
+       min_reserved = fs_info->nodesize * reserve_level * 2;
        memset(&next_key, 0, sizeof(next_key));
 
        while (1) {
index cf63f1e27a2791fb962647f3da99064bb14d278c..e71e7586e9eb0600cb57bb28677b14cd6612985c 100644 (file)
@@ -3866,8 +3866,9 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
        if (!is_dev_replace && !readonly &&
            !test_bit(BTRFS_DEV_STATE_WRITEABLE, &dev->dev_state)) {
                mutex_unlock(&fs_info->fs_devices->device_list_mutex);
-               btrfs_err_in_rcu(fs_info, "scrub: device %s is not writable",
-                               rcu_str_deref(dev->name));
+               btrfs_err_in_rcu(fs_info,
+                       "scrub on devid %llu: filesystem on %s is not writable",
+                                devid, rcu_str_deref(dev->name));
                ret = -EROFS;
                goto out;
        }
index e6719f7db386a781565158782969c56865135809..04022069761deb90a2651d9eed9a94469268eb92 100644 (file)
@@ -983,7 +983,8 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
        ret = clear_extent_bit(&BTRFS_I(inode)->io_tree,
                               BTRFS_MAX_EXTENT_SIZE >> 1,
                               (BTRFS_MAX_EXTENT_SIZE >> 1) + sectorsize - 1,
-                              EXTENT_DELALLOC | EXTENT_UPTODATE, 0, 0, NULL);
+                              EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
+                              EXTENT_UPTODATE, 0, 0, NULL);
        if (ret) {
                test_err("clear_extent_bit returned %d", ret);
                goto out;
@@ -1050,7 +1051,8 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
        ret = clear_extent_bit(&BTRFS_I(inode)->io_tree,
                               BTRFS_MAX_EXTENT_SIZE + sectorsize,
                               BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1,
-                              EXTENT_DELALLOC | EXTENT_UPTODATE, 0, 0, NULL);
+                              EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
+                              EXTENT_UPTODATE, 0, 0, NULL);
        if (ret) {
                test_err("clear_extent_bit returned %d", ret);
                goto out;
@@ -1082,7 +1084,8 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
 
        /* Empty */
        ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1,
-                              EXTENT_DELALLOC | EXTENT_UPTODATE, 0, 0, NULL);
+                              EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
+                              EXTENT_UPTODATE, 0, 0, NULL);
        if (ret) {
                test_err("clear_extent_bit returned %d", ret);
                goto out;
@@ -1097,7 +1100,8 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
 out:
        if (ret)
                clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1,
-                                EXTENT_DELALLOC | EXTENT_UPTODATE, 0, 0, NULL);
+                                EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
+                                EXTENT_UPTODATE, 0, 0, NULL);
        iput(inode);
        btrfs_free_dummy_root(root);
        btrfs_free_dummy_fs_info(fs_info);
index f0ffd5ee77bd5700847bb580417a3f3242f88630..ea2bb4cb58909be561f614ee01bba24994e5ff21 100644 (file)
@@ -760,18 +760,36 @@ int btrfs_check_chunk_valid(struct extent_buffer *leaf,
        u64 type;
        u64 features;
        bool mixed = false;
+       int raid_index;
+       int nparity;
+       int ncopies;
 
        length = btrfs_chunk_length(leaf, chunk);
        stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
        num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
        sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
        type = btrfs_chunk_type(leaf, chunk);
+       raid_index = btrfs_bg_flags_to_raid_index(type);
+       ncopies = btrfs_raid_array[raid_index].ncopies;
+       nparity = btrfs_raid_array[raid_index].nparity;
 
        if (!num_stripes) {
                chunk_err(leaf, chunk, logical,
                          "invalid chunk num_stripes, have %u", num_stripes);
                return -EUCLEAN;
        }
+       if (num_stripes < ncopies) {
+               chunk_err(leaf, chunk, logical,
+                         "invalid chunk num_stripes < ncopies, have %u < %d",
+                         num_stripes, ncopies);
+               return -EUCLEAN;
+       }
+       if (nparity && num_stripes == nparity) {
+               chunk_err(leaf, chunk, logical,
+                         "invalid chunk num_stripes == nparity, have %u == %d",
+                         num_stripes, nparity);
+               return -EUCLEAN;
+       }
        if (!IS_ALIGNED(logical, fs_info->sectorsize)) {
                chunk_err(leaf, chunk, logical,
                "invalid chunk logical, have %llu should aligned to %u",
@@ -1050,6 +1068,7 @@ static int check_root_item(struct extent_buffer *leaf, struct btrfs_key *key,
                            "invalid root item size, have %u expect %zu or %u",
                            btrfs_item_size_nr(leaf, slot), sizeof(ri),
                            btrfs_legacy_root_item_size());
+               return -EUCLEAN;
        }
 
        /*
@@ -1405,6 +1424,7 @@ static int check_extent_data_ref(struct extent_buffer *leaf,
        "invalid item size, have %u expect aligned to %zu for key type %u",
                            btrfs_item_size_nr(leaf, slot),
                            sizeof(*dref), key->type);
+               return -EUCLEAN;
        }
        if (!IS_ALIGNED(key->objectid, leaf->fs_info->sectorsize)) {
                generic_err(leaf, slot,
@@ -1433,6 +1453,7 @@ static int check_extent_data_ref(struct extent_buffer *leaf,
                        extent_err(leaf, slot,
        "invalid extent data backref offset, have %llu expect aligned to %u",
                                   offset, leaf->fs_info->sectorsize);
+                       return -EUCLEAN;
                }
        }
        return 0;
index 58b9c419a2b6b257b61f43a21dd289560878a55e..78637665166e05cdbbd4cb8e110bccc1f6fefdf4 100644 (file)
@@ -431,7 +431,7 @@ static struct btrfs_device *__alloc_device(struct btrfs_fs_info *fs_info)
 
        atomic_set(&dev->reada_in_flight, 0);
        atomic_set(&dev->dev_stats_ccnt, 0);
-       btrfs_device_data_ordered_init(dev);
+       btrfs_device_data_ordered_init(dev, fs_info);
        INIT_RADIX_TREE(&dev->reada_zones, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
        INIT_RADIX_TREE(&dev->reada_extents, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
        extent_io_tree_init(fs_info, &dev->alloc_state,
@@ -940,7 +940,13 @@ static noinline struct btrfs_device *device_list_add(const char *path,
                        if (device->bdev != path_bdev) {
                                bdput(path_bdev);
                                mutex_unlock(&fs_devices->device_list_mutex);
-                               btrfs_warn_in_rcu(device->fs_info,
+                               /*
+                                * device->fs_info may not be reliable here, so
+                                * pass in a NULL instead. This avoids a
+                                * possible use-after-free when the fs_info and
+                                * fs_info->sb are already torn down.
+                                */
+                               btrfs_warn_in_rcu(NULL,
        "duplicate device %s devid %llu generation %llu scanned by %s (%d)",
                                                  path, devid, found_transid,
                                                  current->comm,
@@ -1056,22 +1062,13 @@ static void __btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices,
                        continue;
                }
 
-               if (device->devid == BTRFS_DEV_REPLACE_DEVID) {
-                       /*
-                        * In the first step, keep the device which has
-                        * the correct fsid and the devid that is used
-                        * for the dev_replace procedure.
-                        * In the second step, the dev_replace state is
-                        * read from the device tree and it is known
-                        * whether the procedure is really active or
-                        * not, which means whether this device is
-                        * used or whether it should be removed.
-                        */
-                       if (step == 0 || test_bit(BTRFS_DEV_STATE_REPLACE_TGT,
-                                                 &device->dev_state)) {
-                               continue;
-                       }
-               }
+               /*
+                * We have already validated the presence of BTRFS_DEV_REPLACE_DEVID,
+                * in btrfs_init_dev_replace() so just continue.
+                */
+               if (device->devid == BTRFS_DEV_REPLACE_DEVID)
+                       continue;
+
                if (device->bdev) {
                        blkdev_put(device->bdev, device->mode);
                        device->bdev = NULL;
@@ -1080,9 +1077,6 @@ static void __btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices,
                if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) {
                        list_del_init(&device->dev_alloc_list);
                        clear_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state);
-                       if (!test_bit(BTRFS_DEV_STATE_REPLACE_TGT,
-                                     &device->dev_state))
-                               fs_devices->rw_devices--;
                }
                list_del_init(&device->dev_list);
                fs_devices->num_devices--;
@@ -2099,6 +2093,8 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path,
 
        mutex_unlock(&uuid_mutex);
        ret = btrfs_shrink_device(device, 0);
+       if (!ret)
+               btrfs_reada_remove_dev(device);
        mutex_lock(&uuid_mutex);
        if (ret)
                goto error_undo;
@@ -2179,6 +2175,7 @@ out:
        return ret;
 
 error_undo:
+       btrfs_reada_undo_remove_dev(device);
        if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) {
                mutex_lock(&fs_info->chunk_mutex);
                list_add(&device->dev_alloc_list,
index bf27ac07d3153912c4683c2c7534970639854e78..232f02bd214fc44e013574357c1e3cd926c6e77f 100644 (file)
@@ -39,10 +39,10 @@ struct btrfs_io_geometry {
 #if BITS_PER_LONG==32 && defined(CONFIG_SMP)
 #include <linux/seqlock.h>
 #define __BTRFS_NEED_DEVICE_DATA_ORDERED
-#define btrfs_device_data_ordered_init(device) \
-       seqcount_init(&device->data_seqcount)
+#define btrfs_device_data_ordered_init(device, info)                           \
+       seqcount_mutex_init(&device->data_seqcount, &info->chunk_mutex)
 #else
-#define btrfs_device_data_ordered_init(device) do { } while (0)
+#define btrfs_device_data_ordered_init(device, info) do { } while (0)
 #endif
 
 #define BTRFS_DEV_STATE_WRITEABLE      (0)
@@ -50,6 +50,7 @@ struct btrfs_io_geometry {
 #define BTRFS_DEV_STATE_MISSING                (2)
 #define BTRFS_DEV_STATE_REPLACE_TGT    (3)
 #define BTRFS_DEV_STATE_FLUSH_SENT     (4)
+#define BTRFS_DEV_STATE_NO_READA       (5)
 
 struct btrfs_device {
        struct list_head dev_list; /* device_list_mutex */
@@ -71,7 +72,8 @@ struct btrfs_device {
        blk_status_t last_flush_error;
 
 #ifdef __BTRFS_NEED_DEVICE_DATA_ORDERED
-       seqcount_t data_seqcount;
+       /* A seqcount_t with associated chunk_mutex (for lockdep) */
+       seqcount_mutex_t data_seqcount;
 #endif
 
        /* the internal btrfs device id */
@@ -162,11 +164,9 @@ btrfs_device_get_##name(const struct btrfs_device *dev)                    \
 static inline void                                                     \
 btrfs_device_set_##name(struct btrfs_device *dev, u64 size)            \
 {                                                                      \
-       preempt_disable();                                              \
        write_seqcount_begin(&dev->data_seqcount);                      \
        dev->name = size;                                               \
        write_seqcount_end(&dev->data_seqcount);                        \
-       preempt_enable();                                               \
 }
 #elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPTION)
 #define BTRFS_DEVICE_GETSET_FUNCS(name)                                        \
index 3080cda9e82457c40d50c0fe3afc1c9aac8fa2e4..8bda092e60c5a00118ec8d5159f8a30bdcd38a04 100644 (file)
@@ -121,7 +121,7 @@ static int cachefiles_read_reissue(struct cachefiles_object *object,
                _debug("reissue read");
                ret = bmapping->a_ops->readpage(NULL, backpage);
                if (ret < 0)
-                       goto unlock_discard;
+                       goto discard;
        }
 
        /* but the page may have been read before the monitor was installed, so
@@ -138,6 +138,7 @@ static int cachefiles_read_reissue(struct cachefiles_object *object,
 
 unlock_discard:
        unlock_page(backpage);
+discard:
        spin_lock_irq(&object->work_lock);
        list_del(&monitor->op_link);
        spin_unlock_irq(&object->work_lock);
index 5027bbdca4199454c4a91b6999d28adbb6202198..ded4229c314a0270ae60a288e67879944bad6acd 100644 (file)
@@ -4074,7 +4074,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
             vino.snap, inode);
 
        mutex_lock(&session->s_mutex);
-       session->s_seq++;
+       inc_session_sequence(session);
        dout(" mds%d seq %lld cap seq %u\n", session->s_mds, session->s_seq,
             (unsigned)seq);
 
index 08f1c0c31dc2dac37d1b833b43fa31c779ce7bc5..8f1d7500a7ecb236d3610474dbf0b8d74981b0d5 100644 (file)
@@ -4231,7 +4231,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
             dname.len, dname.name);
 
        mutex_lock(&session->s_mutex);
-       session->s_seq++;
+       inc_session_sequence(session);
 
        if (!inode) {
                dout("handle_lease no inode %llx\n", vino.ino);
@@ -4385,28 +4385,48 @@ static void maybe_recover_session(struct ceph_mds_client *mdsc)
 
 bool check_session_state(struct ceph_mds_session *s)
 {
-       if (s->s_state == CEPH_MDS_SESSION_CLOSING) {
-               dout("resending session close request for mds%d\n",
-                               s->s_mds);
-               request_close_session(s);
-               return false;
-       }
-       if (s->s_ttl && time_after(jiffies, s->s_ttl)) {
-               if (s->s_state == CEPH_MDS_SESSION_OPEN) {
+       switch (s->s_state) {
+       case CEPH_MDS_SESSION_OPEN:
+               if (s->s_ttl && time_after(jiffies, s->s_ttl)) {
                        s->s_state = CEPH_MDS_SESSION_HUNG;
                        pr_info("mds%d hung\n", s->s_mds);
                }
-       }
-       if (s->s_state == CEPH_MDS_SESSION_NEW ||
-           s->s_state == CEPH_MDS_SESSION_RESTARTING ||
-           s->s_state == CEPH_MDS_SESSION_CLOSED ||
-           s->s_state == CEPH_MDS_SESSION_REJECTED)
-               /* this mds is failed or recovering, just wait */
+               break;
+       case CEPH_MDS_SESSION_CLOSING:
+               /* Should never reach this when we're unmounting */
+               WARN_ON_ONCE(true);
+               fallthrough;
+       case CEPH_MDS_SESSION_NEW:
+       case CEPH_MDS_SESSION_RESTARTING:
+       case CEPH_MDS_SESSION_CLOSED:
+       case CEPH_MDS_SESSION_REJECTED:
                return false;
+       }
 
        return true;
 }
 
+/*
+ * If the sequence is incremented while we're waiting on a REQUEST_CLOSE reply,
+ * then we need to retransmit that request.
+ */
+void inc_session_sequence(struct ceph_mds_session *s)
+{
+       lockdep_assert_held(&s->s_mutex);
+
+       s->s_seq++;
+
+       if (s->s_state == CEPH_MDS_SESSION_CLOSING) {
+               int ret;
+
+               dout("resending session close request for mds%d\n", s->s_mds);
+               ret = request_close_session(s);
+               if (ret < 0)
+                       pr_err("unable to close session to mds%d: %d\n",
+                              s->s_mds, ret);
+       }
+}
+
 /*
  * delayed work -- periodically trim expired leases, renew caps with mds
  */
index cbf8af437140584c4ede3b756f99410c09837e33..f5adbebcb38e5ca53508afd03f4622fb838ae55c 100644 (file)
@@ -480,6 +480,7 @@ struct ceph_mds_client {
 extern const char *ceph_mds_op_name(int op);
 
 extern bool check_session_state(struct ceph_mds_session *s);
+void inc_session_sequence(struct ceph_mds_session *s);
 
 extern struct ceph_mds_session *
 __ceph_lookup_mds_session(struct ceph_mds_client *, int mds);
index 83cb4f26b689b3bddc3f2959495aa5aff13067e8..9b785f11e95ac75f24b206100f32ecef741b4988 100644 (file)
@@ -53,7 +53,7 @@ void ceph_handle_quota(struct ceph_mds_client *mdsc,
 
        /* increment msg sequence number */
        mutex_lock(&session->s_mutex);
-       session->s_seq++;
+       inc_session_sequence(session);
        mutex_unlock(&session->s_mutex);
 
        /* lookup inode */
index 0da39c16dab49312f45a6c0f69cc8211fb43cc45..b611f829cb611590f2baaf36ec799a2fabb0ad66 100644 (file)
@@ -873,7 +873,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
             ceph_snap_op_name(op), split, trace_len);
 
        mutex_lock(&session->s_mutex);
-       session->s_seq++;
+       inc_session_sequence(session);
        mutex_unlock(&session->s_mutex);
 
        down_write(&mdsc->snap_rwsem);
index 23b21e9436528d317f2e125a2ee7d971cb86f2ec..ef4784e72b1d540ffb9318b93d29761a770670fa 100644 (file)
@@ -1266,6 +1266,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
                cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
        } else if (mode_from_special_sid) {
                rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
+               kfree(pntsd);
        } else {
                /* get approximated mode from ACL */
                rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
index c38156f324ddb5c1499148c943b205235d07120b..44f9cce57099583cba0e2ef99bcfb963f88b91f1 100644 (file)
@@ -876,6 +876,8 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
        list_del_init(&server->tcp_ses_list);
        spin_unlock(&cifs_tcp_ses_lock);
 
+       cancel_delayed_work_sync(&server->echo);
+
        spin_lock(&GlobalMid_Lock);
        server->tcpStatus = CifsExiting;
        spin_unlock(&GlobalMid_Lock);
@@ -4544,7 +4546,8 @@ static void set_root_ses(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
        if (ses) {
                spin_lock(&cifs_tcp_ses_lock);
                ses->ses_count++;
-               ses->tcon_ipc->remap = cifs_remap(cifs_sb);
+               if (ses->tcon_ipc)
+                       ses->tcon_ipc->remap = cifs_remap(cifs_sb);
                spin_unlock(&cifs_tcp_ses_lock);
        }
        *root_ses = ses;
index 504766cb6c197f42220517a0fc7ef4f5e75c5ae0..3d914d7d0d110013864bc568f914940679743fd3 100644 (file)
@@ -264,7 +264,7 @@ smb2_revert_current_mid(struct TCP_Server_Info *server, const unsigned int val)
 }
 
 static struct mid_q_entry *
-smb2_find_mid(struct TCP_Server_Info *server, char *buf)
+__smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue)
 {
        struct mid_q_entry *mid;
        struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
@@ -281,6 +281,10 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf)
                    (mid->mid_state == MID_REQUEST_SUBMITTED) &&
                    (mid->command == shdr->Command)) {
                        kref_get(&mid->refcount);
+                       if (dequeue) {
+                               list_del_init(&mid->qhead);
+                               mid->mid_flags |= MID_DELETED;
+                       }
                        spin_unlock(&GlobalMid_Lock);
                        return mid;
                }
@@ -289,6 +293,18 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf)
        return NULL;
 }
 
+static struct mid_q_entry *
+smb2_find_mid(struct TCP_Server_Info *server, char *buf)
+{
+       return __smb2_find_mid(server, buf, false);
+}
+
+static struct mid_q_entry *
+smb2_find_dequeue_mid(struct TCP_Server_Info *server, char *buf)
+{
+       return __smb2_find_mid(server, buf, true);
+}
+
 static void
 smb2_dump_detail(void *buf, struct TCP_Server_Info *server)
 {
@@ -3098,8 +3114,8 @@ smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
        rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE;
 
        rc = SMB2_ioctl_init(tcon, server,
-                            &rqst[1], fid.persistent_fid,
-                            fid.volatile_fid, FSCTL_GET_REPARSE_POINT,
+                            &rqst[1], COMPOUND_FID,
+                            COMPOUND_FID, FSCTL_GET_REPARSE_POINT,
                             true /* is_fctl */, NULL, 0,
                             CIFSMaxBufSize -
                             MAX_SMB2_CREATE_RESPONSE_SIZE -
@@ -4356,7 +4372,8 @@ init_read_bvec(struct page **pages, unsigned int npages, unsigned int data_size,
 static int
 handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
                 char *buf, unsigned int buf_len, struct page **pages,
-                unsigned int npages, unsigned int page_data_size)
+                unsigned int npages, unsigned int page_data_size,
+                bool is_offloaded)
 {
        unsigned int data_offset;
        unsigned int data_len;
@@ -4378,7 +4395,8 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
 
        if (server->ops->is_session_expired &&
            server->ops->is_session_expired(buf)) {
-               cifs_reconnect(server);
+               if (!is_offloaded)
+                       cifs_reconnect(server);
                return -1;
        }
 
@@ -4402,7 +4420,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
                cifs_dbg(FYI, "%s: server returned error %d\n",
                         __func__, rdata->result);
                /* normal error on read response */
-               dequeue_mid(mid, false);
+               if (is_offloaded)
+                       mid->mid_state = MID_RESPONSE_RECEIVED;
+               else
+                       dequeue_mid(mid, false);
                return 0;
        }
 
@@ -4426,7 +4447,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
                cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
                         __func__, data_offset);
                rdata->result = -EIO;
-               dequeue_mid(mid, rdata->result);
+               if (is_offloaded)
+                       mid->mid_state = MID_RESPONSE_MALFORMED;
+               else
+                       dequeue_mid(mid, rdata->result);
                return 0;
        }
 
@@ -4442,21 +4466,30 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
                        cifs_dbg(FYI, "%s: data offset (%u) beyond 1st page of response\n",
                                 __func__, data_offset);
                        rdata->result = -EIO;
-                       dequeue_mid(mid, rdata->result);
+                       if (is_offloaded)
+                               mid->mid_state = MID_RESPONSE_MALFORMED;
+                       else
+                               dequeue_mid(mid, rdata->result);
                        return 0;
                }
 
                if (data_len > page_data_size - pad_len) {
                        /* data_len is corrupt -- discard frame */
                        rdata->result = -EIO;
-                       dequeue_mid(mid, rdata->result);
+                       if (is_offloaded)
+                               mid->mid_state = MID_RESPONSE_MALFORMED;
+                       else
+                               dequeue_mid(mid, rdata->result);
                        return 0;
                }
 
                rdata->result = init_read_bvec(pages, npages, page_data_size,
                                               cur_off, &bvec);
                if (rdata->result != 0) {
-                       dequeue_mid(mid, rdata->result);
+                       if (is_offloaded)
+                               mid->mid_state = MID_RESPONSE_MALFORMED;
+                       else
+                               dequeue_mid(mid, rdata->result);
                        return 0;
                }
 
@@ -4471,7 +4504,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
                /* read response payload cannot be in both buf and pages */
                WARN_ONCE(1, "buf can not contain only a part of read data");
                rdata->result = -EIO;
-               dequeue_mid(mid, rdata->result);
+               if (is_offloaded)
+                       mid->mid_state = MID_RESPONSE_MALFORMED;
+               else
+                       dequeue_mid(mid, rdata->result);
                return 0;
        }
 
@@ -4482,7 +4518,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
        if (length < 0)
                return length;
 
-       dequeue_mid(mid, false);
+       if (is_offloaded)
+               mid->mid_state = MID_RESPONSE_RECEIVED;
+       else
+               dequeue_mid(mid, false);
        return length;
 }
 
@@ -4511,15 +4550,34 @@ static void smb2_decrypt_offload(struct work_struct *work)
        }
 
        dw->server->lstrp = jiffies;
-       mid = smb2_find_mid(dw->server, dw->buf);
+       mid = smb2_find_dequeue_mid(dw->server, dw->buf);
        if (mid == NULL)
                cifs_dbg(FYI, "mid not found\n");
        else {
                mid->decrypted = true;
                rc = handle_read_data(dw->server, mid, dw->buf,
                                      dw->server->vals->read_rsp_size,
-                                     dw->ppages, dw->npages, dw->len);
-               mid->callback(mid);
+                                     dw->ppages, dw->npages, dw->len,
+                                     true);
+               if (rc >= 0) {
+#ifdef CONFIG_CIFS_STATS2
+                       mid->when_received = jiffies;
+#endif
+                       mid->callback(mid);
+               } else {
+                       spin_lock(&GlobalMid_Lock);
+                       if (dw->server->tcpStatus == CifsNeedReconnect) {
+                               mid->mid_state = MID_RETRY_NEEDED;
+                               spin_unlock(&GlobalMid_Lock);
+                               mid->callback(mid);
+                       } else {
+                               mid->mid_state = MID_REQUEST_SUBMITTED;
+                               mid->mid_flags &= ~(MID_DELETED);
+                               list_add_tail(&mid->qhead,
+                                       &dw->server->pending_mid_q);
+                               spin_unlock(&GlobalMid_Lock);
+                       }
+               }
                cifs_mid_q_entry_release(mid);
        }
 
@@ -4622,7 +4680,7 @@ non_offloaded_decrypt:
                (*mid)->decrypted = true;
                rc = handle_read_data(server, *mid, buf,
                                      server->vals->read_rsp_size,
-                                     pages, npages, len);
+                                     pages, npages, len, false);
        }
 
 free_pages:
@@ -4765,7 +4823,7 @@ smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
        char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
 
        return handle_read_data(server, mid, buf, server->pdu_size,
-                               NULL, 0, 0);
+                               NULL, 0, 0, false);
 }
 
 static int
index 445e80862865fcd868a82b7e7269a6a13c4ad7ef..acb72705062dd08b0b6b3f210429c6bfc1ed6431 100644 (file)
@@ -2272,17 +2272,15 @@ static struct crt_sd_ctxt *
 create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
 {
        struct crt_sd_ctxt *buf;
-       struct cifs_ace *pace;
-       unsigned int sdlen, acelen;
+       __u8 *ptr, *aclptr;
+       unsigned int acelen, acl_size, ace_count;
        unsigned int owner_offset = 0;
        unsigned int group_offset = 0;
+       struct smb3_acl acl;
 
-       *len = roundup(sizeof(struct crt_sd_ctxt) + (sizeof(struct cifs_ace) * 2), 8);
+       *len = roundup(sizeof(struct crt_sd_ctxt) + (sizeof(struct cifs_ace) * 4), 8);
 
        if (set_owner) {
-               /* offset fields are from beginning of security descriptor not of create context */
-               owner_offset = sizeof(struct smb3_acl) + (sizeof(struct cifs_ace) * 2);
-
                /* sizeof(struct owner_group_sids) is already multiple of 8 so no need to round */
                *len += sizeof(struct owner_group_sids);
        }
@@ -2291,26 +2289,22 @@ create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
        if (buf == NULL)
                return buf;
 
+       ptr = (__u8 *)&buf[1];
        if (set_owner) {
+               /* offset fields are from beginning of security descriptor not of create context */
+               owner_offset = ptr - (__u8 *)&buf->sd;
                buf->sd.OffsetOwner = cpu_to_le32(owner_offset);
-               group_offset = owner_offset + sizeof(struct owner_sid);
+               group_offset = owner_offset + offsetof(struct owner_group_sids, group);
                buf->sd.OffsetGroup = cpu_to_le32(group_offset);
+
+               setup_owner_group_sids(ptr);
+               ptr += sizeof(struct owner_group_sids);
        } else {
                buf->sd.OffsetOwner = 0;
                buf->sd.OffsetGroup = 0;
        }
 
-       sdlen = sizeof(struct smb3_sd) + sizeof(struct smb3_acl) +
-                2 * sizeof(struct cifs_ace);
-       if (set_owner) {
-               sdlen += sizeof(struct owner_group_sids);
-               setup_owner_group_sids(owner_offset + sizeof(struct create_context) + 8 /* name */
-                       + (char *)buf);
-       }
-
-       buf->ccontext.DataOffset = cpu_to_le16(offsetof
-                                       (struct crt_sd_ctxt, sd));
-       buf->ccontext.DataLength = cpu_to_le32(sdlen);
+       buf->ccontext.DataOffset = cpu_to_le16(offsetof(struct crt_sd_ctxt, sd));
        buf->ccontext.NameOffset = cpu_to_le16(offsetof(struct crt_sd_ctxt, Name));
        buf->ccontext.NameLength = cpu_to_le16(4);
        /* SMB2_CREATE_SD_BUFFER_TOKEN is "SecD" */
@@ -2319,6 +2313,7 @@ create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
        buf->Name[2] = 'c';
        buf->Name[3] = 'D';
        buf->sd.Revision = 1;  /* Must be one see MS-DTYP 2.4.6 */
+
        /*
         * ACL is "self relative" ie ACL is stored in contiguous block of memory
         * and "DP" ie the DACL is present
@@ -2326,28 +2321,38 @@ create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
        buf->sd.Control = cpu_to_le16(ACL_CONTROL_SR | ACL_CONTROL_DP);
 
        /* offset owner, group and Sbz1 and SACL are all zero */
-       buf->sd.OffsetDacl = cpu_to_le32(sizeof(struct smb3_sd));
-       buf->acl.AclRevision = ACL_REVISION; /* See 2.4.4.1 of MS-DTYP */
+       buf->sd.OffsetDacl = cpu_to_le32(ptr - (__u8 *)&buf->sd);
+       /* Ship the ACL for now. we will copy it into buf later. */
+       aclptr = ptr;
+       ptr += sizeof(struct cifs_acl);
 
        /* create one ACE to hold the mode embedded in reserved special SID */
-       pace = (struct cifs_ace *)(sizeof(struct crt_sd_ctxt) + (char *)buf);
-       acelen = setup_special_mode_ACE(pace, (__u64)mode);
+       acelen = setup_special_mode_ACE((struct cifs_ace *)ptr, (__u64)mode);
+       ptr += acelen;
+       acl_size = acelen + sizeof(struct smb3_acl);
+       ace_count = 1;
 
        if (set_owner) {
                /* we do not need to reallocate buffer to add the two more ACEs. plenty of space */
-               pace = (struct cifs_ace *)(acelen + (sizeof(struct crt_sd_ctxt) + (char *)buf));
-               acelen += setup_special_user_owner_ACE(pace);
-               /* it does not appear necessary to add an ACE for the NFS group SID */
-               buf->acl.AceCount = cpu_to_le16(3);
-       } else
-               buf->acl.AceCount = cpu_to_le16(2);
+               acelen = setup_special_user_owner_ACE((struct cifs_ace *)ptr);
+               ptr += acelen;
+               acl_size += acelen;
+               ace_count += 1;
+       }
 
        /* and one more ACE to allow access for authenticated users */
-       pace = (struct cifs_ace *)(acelen + (sizeof(struct crt_sd_ctxt) +
-               (char *)buf));
-       acelen += setup_authusers_ACE(pace);
-
-       buf->acl.AclSize = cpu_to_le16(sizeof(struct cifs_acl) + acelen);
+       acelen = setup_authusers_ACE((struct cifs_ace *)ptr);
+       ptr += acelen;
+       acl_size += acelen;
+       ace_count += 1;
+
+       acl.AclRevision = ACL_REVISION; /* See 2.4.4.1 of MS-DTYP */
+       acl.AclSize = cpu_to_le16(acl_size);
+       acl.AceCount = cpu_to_le16(ace_count);
+       memcpy(aclptr, &acl, sizeof(struct cifs_acl));
+
+       buf->ccontext.DataLength = cpu_to_le32(ptr - (__u8 *)&buf->sd);
+       *len = ptr - (__u8 *)buf;
 
        return buf;
 }
index f05f9b12f689d2ca4ca0ba13f9faa99fc57437c1..fa57b03ca98c4914ba2e4fe1721160ffea51e3bd 100644 (file)
@@ -963,8 +963,6 @@ struct crt_sd_ctxt {
        struct create_context ccontext;
        __u8    Name[8];
        struct smb3_sd sd;
-       struct smb3_acl acl;
-       /* Followed by at least 4 ACEs */
 } __packed;
 
 
index e27e255d40dd899a7a7c612cd560eb4e6ff481ef..36b2ece434037ae5d01fa00479d8edf2dc3f4d7c 100644 (file)
@@ -339,8 +339,8 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
                return -EAGAIN;
 
        if (signal_pending(current)) {
-               cifs_dbg(FYI, "signal is pending before sending any data\n");
-               return -EINTR;
+               cifs_dbg(FYI, "signal pending before send request\n");
+               return -ERESTARTSYS;
        }
 
        /* cork the socket */
index 0cd9056d79cc3566c6dd19412c624ed3f12c3b07..c6acfc694f658201c2f165cba2c074ad4658fae8 100644 (file)
@@ -229,7 +229,8 @@ static int format_corename(struct core_name *cn, struct coredump_params *cprm,
                 */
                if (ispipe) {
                        if (isspace(*pat_ptr)) {
-                               was_space = true;
+                               if (cn->used != 0)
+                                       was_space = true;
                                pat_ptr++;
                                continue;
                        } else if (was_space) {
index 89bffa82ed74aafba54a78539016c2635b2bec2f..c57bebfa48fea1dff615138f5612799598c406ff 100644 (file)
@@ -74,7 +74,7 @@ int fscrypt_select_encryption_impl(struct fscrypt_info *ci)
        int i;
 
        /* The file must need contents encryption, not filenames encryption */
-       if (!fscrypt_needs_contents_encryption(inode))
+       if (!S_ISREG(inode->i_mode))
                return 0;
 
        /* The crypto mode must have a blk-crypto counterpart */
index d3c3e5d9b41f74b63db8924d12990c4b11d712e9..d595abb8ef90da8e747ffd141c4ec090872cb41d 100644 (file)
@@ -269,9 +269,7 @@ unlock:
         * New inodes may not have an inode number assigned yet.
         * Hashing their inode number is delayed until later.
         */
-       if (ci->ci_inode->i_ino == 0)
-               WARN_ON(!(ci->ci_inode->i_state & I_CREATING));
-       else
+       if (ci->ci_inode->i_ino)
                fscrypt_hash_inode_number(ci, mk);
        return 0;
 }
index a768a09430c3a9c0cad71e2f47a8544acafdf9c0..686e0ad287880c15406a479a3acc209a8fa1396f 100644 (file)
@@ -1127,24 +1127,23 @@ static const struct file_operations debugfs_devm_entry_ops = {
  *     file will be created in the root of the debugfs filesystem.
  * @read_fn: function pointer called to print the seq_file content.
  */
-struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name,
-                                          struct dentry *parent,
-                                          int (*read_fn)(struct seq_file *s,
-                                                         void *data))
+void debugfs_create_devm_seqfile(struct device *dev, const char *name,
+                                struct dentry *parent,
+                                int (*read_fn)(struct seq_file *s, void *data))
 {
        struct debugfs_devm_entry *entry;
 
        if (IS_ERR(parent))
-               return ERR_PTR(-ENOENT);
+               return;
 
        entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL);
        if (!entry)
-               return ERR_PTR(-ENOMEM);
+               return;
 
        entry->read = read_fn;
        entry->dev = dev;
 
-       return debugfs_create_file(name, S_IRUGO, parent, entry,
-                                  &debugfs_devm_entry_ops);
+       debugfs_create_file(name, S_IRUGO, parent, entry,
+                           &debugfs_devm_entry_ops);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_devm_seqfile);
index 96c0c86f3fffe59bc2b7b324e9b94fcc89ca5192..0297ad95eb5cc01cafe158185e890b3ed214b40e 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/efi.h>
 #include <linux/fs.h>
 #include <linux/ctype.h>
+#include <linux/kmemleak.h>
 #include <linux/slab.h>
 #include <linux/uuid.h>
 
@@ -103,6 +104,7 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
        var->var.VariableName[i] = '\0';
 
        inode->i_private = var;
+       kmemleak_ignore(var);
 
        err = efivar_entry_add(var, &efivarfs_list);
        if (err)
index 139d0bed42f8865d705bc4e18dc16a936e2a6b8c..3e21c0e8adae73aa75e02af892ad5b30ecfa0c1e 100644 (file)
@@ -107,11 +107,9 @@ static struct page *erofs_read_inode(struct inode *inode,
                i_gid_write(inode, le32_to_cpu(die->i_gid));
                set_nlink(inode, le32_to_cpu(die->i_nlink));
 
-               /* ns timestamp */
-               inode->i_mtime.tv_sec = inode->i_ctime.tv_sec =
-                       le64_to_cpu(die->i_ctime);
-               inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec =
-                       le32_to_cpu(die->i_ctime_nsec);
+               /* extended inode has its own timestamp */
+               inode->i_ctime.tv_sec = le64_to_cpu(die->i_ctime);
+               inode->i_ctime.tv_nsec = le32_to_cpu(die->i_ctime_nsec);
 
                inode->i_size = le64_to_cpu(die->i_size);
 
@@ -149,11 +147,9 @@ static struct page *erofs_read_inode(struct inode *inode,
                i_gid_write(inode, le16_to_cpu(dic->i_gid));
                set_nlink(inode, le16_to_cpu(dic->i_nlink));
 
-               /* use build time to derive all file time */
-               inode->i_mtime.tv_sec = inode->i_ctime.tv_sec =
-                       sbi->build_time;
-               inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec =
-                       sbi->build_time_nsec;
+               /* use build time for compact inodes */
+               inode->i_ctime.tv_sec = sbi->build_time;
+               inode->i_ctime.tv_nsec = sbi->build_time_nsec;
 
                inode->i_size = le32_to_cpu(dic->i_size);
                if (erofs_inode_is_data_compressed(vi->datalayout))
@@ -167,6 +163,11 @@ static struct page *erofs_read_inode(struct inode *inode,
                goto err_out;
        }
 
+       inode->i_mtime.tv_sec = inode->i_ctime.tv_sec;
+       inode->i_atime.tv_sec = inode->i_ctime.tv_sec;
+       inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec;
+       inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec;
+
        if (!nblks)
                /* measure inode.i_blocks as generic filesystems */
                inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9;
index 50912a5420b486dd7822da1f623915beb9141aea..86fd3bf62af615dd1ba162ea7435a0a2e269d023 100644 (file)
@@ -1078,8 +1078,11 @@ out_allocpage:
                cond_resched();
                goto repeat;
        }
-       set_page_private(page, (unsigned long)pcl);
-       SetPagePrivate(page);
+
+       if (tocache) {
+               set_page_private(page, (unsigned long)pcl);
+               SetPagePrivate(page);
+       }
 out:   /* the only exit (for tracing and debugging) */
        return page;
 }
index 5b81f3b080ee605317c465332f343b35e27c5ce7..ca50c90adc4c48796de1d766c686345bf9ece94a 100644 (file)
@@ -669,68 +669,8 @@ const struct file_operations ext4_dir_operations = {
 };
 
 #ifdef CONFIG_UNICODE
-static int ext4_d_compare(const struct dentry *dentry, unsigned int len,
-                         const char *str, const struct qstr *name)
-{
-       struct qstr qstr = {.name = str, .len = len };
-       const struct dentry *parent = READ_ONCE(dentry->d_parent);
-       const struct inode *inode = d_inode_rcu(parent);
-       char strbuf[DNAME_INLINE_LEN];
-
-       if (!inode || !IS_CASEFOLDED(inode) ||
-           !EXT4_SB(inode->i_sb)->s_encoding) {
-               if (len != name->len)
-                       return -1;
-               return memcmp(str, name->name, len);
-       }
-
-       /*
-        * If the dentry name is stored in-line, then it may be concurrently
-        * modified by a rename.  If this happens, the VFS will eventually retry
-        * the lookup, so it doesn't matter what ->d_compare() returns.
-        * However, it's unsafe to call utf8_strncasecmp() with an unstable
-        * string.  Therefore, we have to copy the name into a temporary buffer.
-        */
-       if (len <= DNAME_INLINE_LEN - 1) {
-               memcpy(strbuf, str, len);
-               strbuf[len] = 0;
-               qstr.name = strbuf;
-               /* prevent compiler from optimizing out the temporary buffer */
-               barrier();
-       }
-
-       return ext4_ci_compare(inode, name, &qstr, false);
-}
-
-static int ext4_d_hash(const struct dentry *dentry, struct qstr *str)
-{
-       const struct ext4_sb_info *sbi = EXT4_SB(dentry->d_sb);
-       const struct unicode_map *um = sbi->s_encoding;
-       const struct inode *inode = d_inode_rcu(dentry);
-       unsigned char *norm;
-       int len, ret = 0;
-
-       if (!inode || !IS_CASEFOLDED(inode) || !um)
-               return 0;
-
-       norm = kmalloc(PATH_MAX, GFP_ATOMIC);
-       if (!norm)
-               return -ENOMEM;
-
-       len = utf8_casefold(um, str, norm, PATH_MAX);
-       if (len < 0) {
-               if (ext4_has_strict_mode(sbi))
-                       ret = -EINVAL;
-               goto out;
-       }
-       str->hash = full_name_hash(dentry, norm, len);
-out:
-       kfree(norm);
-       return ret;
-}
-
 const struct dentry_operations ext4_dentry_ops = {
-       .d_hash = ext4_d_hash,
-       .d_compare = ext4_d_compare,
+       .d_hash = generic_ci_d_hash,
+       .d_compare = generic_ci_d_compare,
 };
 #endif
index 254d1c26bea8a80228ace0c1dbe330b535cfe845..65ecaf96d0a4dbc17b8066a3f66fccbc82cf923e 100644 (file)
@@ -1028,9 +1028,6 @@ struct ext4_inode_info {
                                         * protected by sbi->s_fc_lock.
                                         */
 
-       /* Fast commit subtid when this inode was committed */
-       unsigned int i_fc_committed_subtid;
-
        /* Start of lblk range that needs to be committed in this fast commit */
        ext4_lblk_t i_fc_lblk_start;
 
@@ -1166,10 +1163,6 @@ struct ext4_inode_info {
 #define        EXT4_VALID_FS                   0x0001  /* Unmounted cleanly */
 #define        EXT4_ERROR_FS                   0x0002  /* Errors detected */
 #define        EXT4_ORPHAN_FS                  0x0004  /* Orphans being recovered */
-#define EXT4_FC_INELIGIBLE             0x0008  /* Fast commit ineligible */
-#define EXT4_FC_COMMITTING             0x0010  /* File system underoing a fast
-                                                * commit.
-                                                */
 #define EXT4_FC_REPLAY                 0x0020  /* Fast commit replay ongoing */
 
 /*
@@ -1238,13 +1231,13 @@ struct ext4_inode_info {
                                                      blocks */
 #define EXT4_MOUNT2_HURD_COMPAT                0x00000004 /* Support HURD-castrated
                                                      file systems */
-#define EXT4_MOUNT2_DAX_NEVER          0x00000008 /* Do not allow Direct Access */
-#define EXT4_MOUNT2_DAX_INODE          0x00000010 /* For printing options only */
-
 #define EXT4_MOUNT2_EXPLICIT_JOURNAL_CHECKSUM  0x00000008 /* User explicitly
                                                specified journal checksum */
 
 #define EXT4_MOUNT2_JOURNAL_FAST_COMMIT        0x00000010 /* Journal fast commit */
+#define EXT4_MOUNT2_DAX_NEVER          0x00000020 /* Do not allow Direct Access */
+#define EXT4_MOUNT2_DAX_INODE          0x00000040 /* For printing options only */
+
 
 #define clear_opt(sb, opt)             EXT4_SB(sb)->s_mount_opt &= \
                                                ~EXT4_MOUNT_##opt
@@ -1426,12 +1419,6 @@ struct ext4_super_block {
 
 #ifdef __KERNEL__
 
-/*
- * run-time mount flags
- */
-#define EXT4_MF_MNTDIR_SAMPLED         0x0001
-#define EXT4_MF_FS_ABORTED             0x0002  /* Fatal error detected */
-
 #ifdef CONFIG_FS_ENCRYPTION
 #define DUMMY_ENCRYPTION_ENABLED(sbi) ((sbi)->s_dummy_enc_policy.policy != NULL)
 #else
@@ -1443,14 +1430,6 @@ struct ext4_super_block {
 
 #define EXT4_ENC_UTF8_12_1     1
 
-/*
- * Flags for ext4_sb_info.s_encoding_flags.
- */
-#define EXT4_ENC_STRICT_MODE_FL        (1 << 0)
-
-#define ext4_has_strict_mode(sbi) \
-       (sbi->s_encoding_flags & EXT4_ENC_STRICT_MODE_FL)
-
 /*
  * fourth extended-fs super-block data in memory
  */
@@ -1474,7 +1453,7 @@ struct ext4_sb_info {
        struct buffer_head * __rcu *s_group_desc;
        unsigned int s_mount_opt;
        unsigned int s_mount_opt2;
-       unsigned int s_mount_flags;
+       unsigned long s_mount_flags;
        unsigned int s_def_mount_opt;
        ext4_fsblk_t s_sb_block;
        atomic64_t s_resv_clusters;
@@ -1500,10 +1479,6 @@ struct ext4_sb_info {
        struct kobject s_kobj;
        struct completion s_kobj_unregister;
        struct super_block *s_sb;
-#ifdef CONFIG_UNICODE
-       struct unicode_map *s_encoding;
-       __u16 s_encoding_flags;
-#endif
 
        /* Journaling */
        struct journal_s *s_journal;
@@ -1706,6 +1681,34 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
        _v;                                                                \
 })
 
+/*
+ * run-time mount flags
+ */
+enum {
+       EXT4_MF_MNTDIR_SAMPLED,
+       EXT4_MF_FS_ABORTED,     /* Fatal error detected */
+       EXT4_MF_FC_INELIGIBLE,  /* Fast commit ineligible */
+       EXT4_MF_FC_COMMITTING   /* File system underoing a fast
+                                * commit.
+                                */
+};
+
+static inline void ext4_set_mount_flag(struct super_block *sb, int bit)
+{
+       set_bit(bit, &EXT4_SB(sb)->s_mount_flags);
+}
+
+static inline void ext4_clear_mount_flag(struct super_block *sb, int bit)
+{
+       clear_bit(bit, &EXT4_SB(sb)->s_mount_flags);
+}
+
+static inline int ext4_test_mount_flag(struct super_block *sb, int bit)
+{
+       return test_bit(bit, &EXT4_SB(sb)->s_mount_flags);
+}
+
+
 /*
  * Simulate_fail codes
  */
@@ -1875,6 +1878,13 @@ static inline bool ext4_verity_in_progress(struct inode *inode)
 #define EXT4_FEATURE_COMPAT_RESIZE_INODE       0x0010
 #define EXT4_FEATURE_COMPAT_DIR_INDEX          0x0020
 #define EXT4_FEATURE_COMPAT_SPARSE_SUPER2      0x0200
+/*
+ * The reason why "FAST_COMMIT" is a compat feature is that, FS becomes
+ * incompatible only if fast commit blocks are present in the FS. Since we
+ * clear the journal (and thus the fast commit blocks), we don't mark FS as
+ * incompatible. We also have a JBD2 incompat feature, which gets set when
+ * there are fast commit blocks present in the journal.
+ */
 #define EXT4_FEATURE_COMPAT_FAST_COMMIT                0x0400
 #define EXT4_FEATURE_COMPAT_STABLE_INODES      0x0800
 
@@ -2685,7 +2695,8 @@ void ext4_insert_dentry(struct inode *inode,
                        struct ext4_filename *fname);
 static inline void ext4_update_dx_flag(struct inode *inode)
 {
-       if (!ext4_has_feature_dir_index(inode->i_sb)) {
+       if (!ext4_has_feature_dir_index(inode->i_sb) &&
+           ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) {
                /* ext4_iget() should have caught this... */
                WARN_ON_ONCE(ext4_has_feature_metadata_csum(inode->i_sb));
                ext4_clear_inode_flag(inode, EXT4_INODE_INDEX);
@@ -2743,12 +2754,16 @@ extern void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate);
 int ext4_fc_info_show(struct seq_file *seq, void *v);
 void ext4_fc_init(struct super_block *sb, journal_t *journal);
 void ext4_fc_init_inode(struct inode *inode);
-void ext4_fc_track_range(struct inode *inode, ext4_lblk_t start,
+void ext4_fc_track_range(handle_t *handle, struct inode *inode, ext4_lblk_t start,
                         ext4_lblk_t end);
-void ext4_fc_track_unlink(struct inode *inode, struct dentry *dentry);
-void ext4_fc_track_link(struct inode *inode, struct dentry *dentry);
-void ext4_fc_track_create(struct inode *inode, struct dentry *dentry);
-void ext4_fc_track_inode(struct inode *inode);
+void __ext4_fc_track_unlink(handle_t *handle, struct inode *inode,
+       struct dentry *dentry);
+void __ext4_fc_track_link(handle_t *handle, struct inode *inode,
+       struct dentry *dentry);
+void ext4_fc_track_unlink(handle_t *handle, struct dentry *dentry);
+void ext4_fc_track_link(handle_t *handle, struct dentry *dentry);
+void ext4_fc_track_create(handle_t *handle, struct dentry *dentry);
+void ext4_fc_track_inode(handle_t *handle, struct inode *inode);
 void ext4_fc_mark_ineligible(struct super_block *sb, int reason);
 void ext4_fc_start_ineligible(struct super_block *sb, int reason);
 void ext4_fc_stop_ineligible(struct super_block *sb);
@@ -3464,7 +3479,7 @@ extern int ext4_handle_dirty_dirblock(handle_t *handle, struct inode *inode,
 extern int ext4_ci_compare(const struct inode *parent,
                           const struct qstr *fname,
                           const struct qstr *entry, bool quick);
-extern int __ext4_unlink(struct inode *dir, const struct qstr *d_name,
+extern int __ext4_unlink(handle_t *handle, struct inode *dir, const struct qstr *d_name,
                         struct inode *inode);
 extern int __ext4_link(struct inode *dir, struct inode *inode,
                       struct dentry *dentry);
index 559100f3e23cd2d78d7d1fb11eb8283b726df4ec..17d7096b3212dc778ccbe36ec3adf0ecc15069c8 100644 (file)
@@ -1471,16 +1471,16 @@ static int ext4_ext_search_left(struct inode *inode,
 }
 
 /*
- * search the closest allocated block to the right for *logical
- * and returns it at @logical + it's physical address at @phys
- * if *logical is the largest allocated block, the function
- * returns 0 at @phys
- * return value contains 0 (success) or error code
+ * Search the closest allocated block to the right for *logical
+ * and returns it at @logical + it's physical address at @phys.
+ * If not exists, return 0 and @phys is set to 0. We will return
+ * 1 which means we found an allocated block and ret_ex is valid.
+ * Or return a (< 0) error code.
  */
 static int ext4_ext_search_right(struct inode *inode,
                                 struct ext4_ext_path *path,
                                 ext4_lblk_t *logical, ext4_fsblk_t *phys,
-                                struct ext4_extent **ret_ex)
+                                struct ext4_extent *ret_ex)
 {
        struct buffer_head *bh = NULL;
        struct ext4_extent_header *eh;
@@ -1574,10 +1574,11 @@ got_index:
 found_extent:
        *logical = le32_to_cpu(ex->ee_block);
        *phys = ext4_ext_pblock(ex);
-       *ret_ex = ex;
+       if (ret_ex)
+               *ret_ex = *ex;
        if (bh)
                put_bh(bh);
-       return 0;
+       return 1;
 }
 
 /*
@@ -2868,8 +2869,8 @@ again:
                         */
                        lblk = ex_end + 1;
                        err = ext4_ext_search_right(inode, path, &lblk, &pblk,
-                                                   &ex);
-                       if (err)
+                                                   NULL);
+                       if (err < 0)
                                goto out;
                        if (pblk) {
                                partial.pclu = EXT4_B2C(sbi, pblk);
@@ -3723,7 +3724,6 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
        err = ext4_ext_dirty(handle, inode, path + path->p_depth);
 out:
        ext4_ext_show_leaf(inode, path);
-       ext4_fc_track_range(inode, ee_block, ee_block + ee_len - 1);
        return err;
 }
 
@@ -3795,7 +3795,6 @@ convert_initialized_extent(handle_t *handle, struct inode *inode,
        if (*allocated > map->m_len)
                *allocated = map->m_len;
        map->m_len = *allocated;
-       ext4_fc_track_range(inode, ee_block, ee_block + ee_len - 1);
        return 0;
 }
 
@@ -4039,7 +4038,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
                        struct ext4_map_blocks *map, int flags)
 {
        struct ext4_ext_path *path = NULL;
-       struct ext4_extent newex, *ex, *ex2;
+       struct ext4_extent newex, *ex, ex2;
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        ext4_fsblk_t newblock = 0, pblk;
        int err = 0, depth, ret;
@@ -4175,15 +4174,14 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
        if (err)
                goto out;
        ar.lright = map->m_lblk;
-       ex2 = NULL;
        err = ext4_ext_search_right(inode, path, &ar.lright, &ar.pright, &ex2);
-       if (err)
+       if (err < 0)
                goto out;
 
        /* Check if the extent after searching to the right implies a
         * cluster we can use. */
-       if ((sbi->s_cluster_ratio > 1) && ex2 &&
-           get_implied_cluster_alloc(inode->i_sb, map, ex2, path)) {
+       if ((sbi->s_cluster_ratio > 1) && err &&
+           get_implied_cluster_alloc(inode->i_sb, map, &ex2, path)) {
                ar.len = allocated = map->m_len;
                newblock = map->m_pblk;
                goto got_allocated_blocks;
@@ -4329,7 +4327,6 @@ got_allocated_blocks:
        map->m_len = ar.len;
        allocated = map->m_len;
        ext4_ext_show_leaf(inode, path);
-       ext4_fc_track_range(inode, map->m_lblk, map->m_lblk + map->m_len - 1);
 out:
        ext4_ext_drop_refs(path);
        kfree(path);
@@ -4602,7 +4599,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
        ret = ext4_mark_inode_dirty(handle, inode);
        if (unlikely(ret))
                goto out_handle;
-       ext4_fc_track_range(inode, offset >> inode->i_sb->s_blocksize_bits,
+       ext4_fc_track_range(handle, inode, offset >> inode->i_sb->s_blocksize_bits,
                        (offset + len - 1) >> inode->i_sb->s_blocksize_bits);
        /* Zero out partial block at the edges of the range */
        ret = ext4_zero_partial_blocks(handle, inode, offset, len);
@@ -4651,8 +4648,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
                     FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE |
                     FALLOC_FL_INSERT_RANGE))
                return -EOPNOTSUPP;
-       ext4_fc_track_range(inode, offset >> blkbits,
-                       (offset + len - 1) >> blkbits);
 
        ext4_fc_start_update(inode);
 
index 447c8d93f48081c11ed85e6076df2617af4f20c0..f2033e13a273c72b857c64c3db5e9e0561d50ca5 100644 (file)
@@ -83,7 +83,7 @@
  *
  * Atomicity of commits
  * --------------------
- * In order to gaurantee atomicity during the commit operation, fast commit
+ * In order to guarantee atomicity during the commit operation, fast commit
  * uses "EXT4_FC_TAG_TAIL" tag that marks a fast commit as complete. Tail
  * tag contains CRC of the contents and TID of the transaction after which
  * this fast commit should be applied. Recovery code replays fast commit
@@ -152,7 +152,31 @@ void ext4_fc_init_inode(struct inode *inode)
        INIT_LIST_HEAD(&ei->i_fc_list);
        init_waitqueue_head(&ei->i_fc_wait);
        atomic_set(&ei->i_fc_updates, 0);
-       ei->i_fc_committed_subtid = 0;
+}
+
+/* This function must be called with sbi->s_fc_lock held. */
+static void ext4_fc_wait_committing_inode(struct inode *inode)
+__releases(&EXT4_SB(inode->i_sb)->s_fc_lock)
+{
+       wait_queue_head_t *wq;
+       struct ext4_inode_info *ei = EXT4_I(inode);
+
+#if (BITS_PER_LONG < 64)
+       DEFINE_WAIT_BIT(wait, &ei->i_state_flags,
+                       EXT4_STATE_FC_COMMITTING);
+       wq = bit_waitqueue(&ei->i_state_flags,
+                               EXT4_STATE_FC_COMMITTING);
+#else
+       DEFINE_WAIT_BIT(wait, &ei->i_flags,
+                       EXT4_STATE_FC_COMMITTING);
+       wq = bit_waitqueue(&ei->i_flags,
+                               EXT4_STATE_FC_COMMITTING);
+#endif
+       lockdep_assert_held(&EXT4_SB(inode->i_sb)->s_fc_lock);
+       prepare_to_wait(wq, &wait.wq_entry, TASK_UNINTERRUPTIBLE);
+       spin_unlock(&EXT4_SB(inode->i_sb)->s_fc_lock);
+       schedule();
+       finish_wait(wq, &wait.wq_entry);
 }
 
 /*
@@ -176,22 +200,7 @@ restart:
                goto out;
 
        if (ext4_test_inode_state(inode, EXT4_STATE_FC_COMMITTING)) {
-               wait_queue_head_t *wq;
-#if (BITS_PER_LONG < 64)
-               DEFINE_WAIT_BIT(wait, &ei->i_state_flags,
-                               EXT4_STATE_FC_COMMITTING);
-               wq = bit_waitqueue(&ei->i_state_flags,
-                                  EXT4_STATE_FC_COMMITTING);
-#else
-               DEFINE_WAIT_BIT(wait, &ei->i_flags,
-                               EXT4_STATE_FC_COMMITTING);
-               wq = bit_waitqueue(&ei->i_flags,
-                                  EXT4_STATE_FC_COMMITTING);
-#endif
-               prepare_to_wait(wq, &wait.wq_entry, TASK_UNINTERRUPTIBLE);
-               spin_unlock(&EXT4_SB(inode->i_sb)->s_fc_lock);
-               schedule();
-               finish_wait(wq, &wait.wq_entry);
+               ext4_fc_wait_committing_inode(inode);
                goto restart;
        }
 out:
@@ -234,26 +243,10 @@ restart:
        }
 
        if (ext4_test_inode_state(inode, EXT4_STATE_FC_COMMITTING)) {
-               wait_queue_head_t *wq;
-#if (BITS_PER_LONG < 64)
-               DEFINE_WAIT_BIT(wait, &ei->i_state_flags,
-                               EXT4_STATE_FC_COMMITTING);
-               wq = bit_waitqueue(&ei->i_state_flags,
-                                  EXT4_STATE_FC_COMMITTING);
-#else
-               DEFINE_WAIT_BIT(wait, &ei->i_flags,
-                               EXT4_STATE_FC_COMMITTING);
-               wq = bit_waitqueue(&ei->i_flags,
-                                  EXT4_STATE_FC_COMMITTING);
-#endif
-               prepare_to_wait(wq, &wait.wq_entry, TASK_UNINTERRUPTIBLE);
-               spin_unlock(&EXT4_SB(inode->i_sb)->s_fc_lock);
-               schedule();
-               finish_wait(wq, &wait.wq_entry);
+               ext4_fc_wait_committing_inode(inode);
                goto restart;
        }
-       if (!list_empty(&ei->i_fc_list))
-               list_del_init(&ei->i_fc_list);
+       list_del_init(&ei->i_fc_list);
        spin_unlock(&EXT4_SB(inode->i_sb)->s_fc_lock);
 }
 
@@ -269,7 +262,7 @@ void ext4_fc_mark_ineligible(struct super_block *sb, int reason)
            (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY))
                return;
 
-       sbi->s_mount_state |= EXT4_FC_INELIGIBLE;
+       ext4_set_mount_flag(sb, EXT4_MF_FC_INELIGIBLE);
        WARN_ON(reason >= EXT4_FC_REASON_MAX);
        sbi->s_fc_stats.fc_ineligible_reason_count[reason]++;
 }
@@ -292,7 +285,7 @@ void ext4_fc_start_ineligible(struct super_block *sb, int reason)
 }
 
 /*
- * Stop a fast commit ineligible update. We set EXT4_FC_INELIGIBLE flag here
+ * Stop a fast commit ineligible update. We set EXT4_MF_FC_INELIGIBLE flag here
  * to ensure that after stopping the ineligible update, at least one full
  * commit takes place.
  */
@@ -302,14 +295,14 @@ void ext4_fc_stop_ineligible(struct super_block *sb)
            (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY))
                return;
 
-       EXT4_SB(sb)->s_mount_state |= EXT4_FC_INELIGIBLE;
+       ext4_set_mount_flag(sb, EXT4_MF_FC_INELIGIBLE);
        atomic_dec(&EXT4_SB(sb)->s_fc_ineligible_updates);
 }
 
 static inline int ext4_fc_is_ineligible(struct super_block *sb)
 {
-       return (EXT4_SB(sb)->s_mount_state & EXT4_FC_INELIGIBLE) ||
-               atomic_read(&EXT4_SB(sb)->s_fc_ineligible_updates);
+       return (ext4_test_mount_flag(sb, EXT4_MF_FC_INELIGIBLE) ||
+               atomic_read(&EXT4_SB(sb)->s_fc_ineligible_updates));
 }
 
 /*
@@ -323,13 +316,14 @@ static inline int ext4_fc_is_ineligible(struct super_block *sb)
  * If enqueue is set, this function enqueues the inode in fast commit list.
  */
 static int ext4_fc_track_template(
-       struct inode *inode, int (*__fc_track_fn)(struct inode *, void *, bool),
+       handle_t *handle, struct inode *inode,
+       int (*__fc_track_fn)(struct inode *, void *, bool),
        void *args, int enqueue)
 {
-       tid_t running_txn_tid;
        bool update = false;
        struct ext4_inode_info *ei = EXT4_I(inode);
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+       tid_t tid = 0;
        int ret;
 
        if (!test_opt2(inode->i_sb, JOURNAL_FAST_COMMIT) ||
@@ -339,15 +333,13 @@ static int ext4_fc_track_template(
        if (ext4_fc_is_ineligible(inode->i_sb))
                return -EINVAL;
 
-       running_txn_tid = sbi->s_journal ?
-               sbi->s_journal->j_commit_sequence + 1 : 0;
-
+       tid = handle->h_transaction->t_tid;
        mutex_lock(&ei->i_fc_lock);
-       if (running_txn_tid == ei->i_sync_tid) {
+       if (tid == ei->i_sync_tid) {
                update = true;
        } else {
                ext4_fc_reset_inode(inode);
-               ei->i_sync_tid = running_txn_tid;
+               ei->i_sync_tid = tid;
        }
        ret = __fc_track_fn(inode, args, update);
        mutex_unlock(&ei->i_fc_lock);
@@ -358,7 +350,7 @@ static int ext4_fc_track_template(
        spin_lock(&sbi->s_fc_lock);
        if (list_empty(&EXT4_I(inode)->i_fc_list))
                list_add_tail(&EXT4_I(inode)->i_fc_list,
-                               (sbi->s_mount_state & EXT4_FC_COMMITTING) ?
+                               (ext4_test_mount_flag(inode->i_sb, EXT4_MF_FC_COMMITTING)) ?
                                &sbi->s_fc_q[FC_Q_STAGING] :
                                &sbi->s_fc_q[FC_Q_MAIN]);
        spin_unlock(&sbi->s_fc_lock);
@@ -384,7 +376,7 @@ static int __track_dentry_update(struct inode *inode, void *arg, bool update)
        mutex_unlock(&ei->i_fc_lock);
        node = kmem_cache_alloc(ext4_fc_dentry_cachep, GFP_NOFS);
        if (!node) {
-               ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_MEM);
+               ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM);
                mutex_lock(&ei->i_fc_lock);
                return -ENOMEM;
        }
@@ -397,7 +389,7 @@ static int __track_dentry_update(struct inode *inode, void *arg, bool update)
                if (!node->fcd_name.name) {
                        kmem_cache_free(ext4_fc_dentry_cachep, node);
                        ext4_fc_mark_ineligible(inode->i_sb,
-                               EXT4_FC_REASON_MEM);
+                               EXT4_FC_REASON_NOMEM);
                        mutex_lock(&ei->i_fc_lock);
                        return -ENOMEM;
                }
@@ -411,7 +403,7 @@ static int __track_dentry_update(struct inode *inode, void *arg, bool update)
        node->fcd_name.len = dentry->d_name.len;
 
        spin_lock(&sbi->s_fc_lock);
-       if (sbi->s_mount_state & EXT4_FC_COMMITTING)
+       if (ext4_test_mount_flag(inode->i_sb, EXT4_MF_FC_COMMITTING))
                list_add_tail(&node->fcd_list,
                                &sbi->s_fc_dentry_q[FC_Q_STAGING]);
        else
@@ -422,7 +414,8 @@ static int __track_dentry_update(struct inode *inode, void *arg, bool update)
        return 0;
 }
 
-void ext4_fc_track_unlink(struct inode *inode, struct dentry *dentry)
+void __ext4_fc_track_unlink(handle_t *handle,
+               struct inode *inode, struct dentry *dentry)
 {
        struct __track_dentry_update_args args;
        int ret;
@@ -430,12 +423,18 @@ void ext4_fc_track_unlink(struct inode *inode, struct dentry *dentry)
        args.dentry = dentry;
        args.op = EXT4_FC_TAG_UNLINK;
 
-       ret = ext4_fc_track_template(inode, __track_dentry_update,
+       ret = ext4_fc_track_template(handle, inode, __track_dentry_update,
                                        (void *)&args, 0);
        trace_ext4_fc_track_unlink(inode, dentry, ret);
 }
 
-void ext4_fc_track_link(struct inode *inode, struct dentry *dentry)
+void ext4_fc_track_unlink(handle_t *handle, struct dentry *dentry)
+{
+       __ext4_fc_track_unlink(handle, d_inode(dentry), dentry);
+}
+
+void __ext4_fc_track_link(handle_t *handle,
+       struct inode *inode, struct dentry *dentry)
 {
        struct __track_dentry_update_args args;
        int ret;
@@ -443,20 +442,26 @@ void ext4_fc_track_link(struct inode *inode, struct dentry *dentry)
        args.dentry = dentry;
        args.op = EXT4_FC_TAG_LINK;
 
-       ret = ext4_fc_track_template(inode, __track_dentry_update,
+       ret = ext4_fc_track_template(handle, inode, __track_dentry_update,
                                        (void *)&args, 0);
        trace_ext4_fc_track_link(inode, dentry, ret);
 }
 
-void ext4_fc_track_create(struct inode *inode, struct dentry *dentry)
+void ext4_fc_track_link(handle_t *handle, struct dentry *dentry)
+{
+       __ext4_fc_track_link(handle, d_inode(dentry), dentry);
+}
+
+void ext4_fc_track_create(handle_t *handle, struct dentry *dentry)
 {
        struct __track_dentry_update_args args;
+       struct inode *inode = d_inode(dentry);
        int ret;
 
        args.dentry = dentry;
        args.op = EXT4_FC_TAG_CREAT;
 
-       ret = ext4_fc_track_template(inode, __track_dentry_update,
+       ret = ext4_fc_track_template(handle, inode, __track_dentry_update,
                                        (void *)&args, 0);
        trace_ext4_fc_track_create(inode, dentry, ret);
 }
@@ -472,14 +477,20 @@ static int __track_inode(struct inode *inode, void *arg, bool update)
        return 0;
 }
 
-void ext4_fc_track_inode(struct inode *inode)
+void ext4_fc_track_inode(handle_t *handle, struct inode *inode)
 {
        int ret;
 
        if (S_ISDIR(inode->i_mode))
                return;
 
-       ret = ext4_fc_track_template(inode, __track_inode, NULL, 1);
+       if (ext4_should_journal_data(inode)) {
+               ext4_fc_mark_ineligible(inode->i_sb,
+                                       EXT4_FC_REASON_INODE_JOURNAL_DATA);
+               return;
+       }
+
+       ret = ext4_fc_track_template(handle, inode, __track_inode, NULL, 1);
        trace_ext4_fc_track_inode(inode, ret);
 }
 
@@ -515,7 +526,7 @@ static int __track_range(struct inode *inode, void *arg, bool update)
        return 0;
 }
 
-void ext4_fc_track_range(struct inode *inode, ext4_lblk_t start,
+void ext4_fc_track_range(handle_t *handle, struct inode *inode, ext4_lblk_t start,
                         ext4_lblk_t end)
 {
        struct __track_range_args args;
@@ -527,7 +538,7 @@ void ext4_fc_track_range(struct inode *inode, ext4_lblk_t start,
        args.start = start;
        args.end = end;
 
-       ret = ext4_fc_track_template(inode,  __track_range, &args, 1);
+       ret = ext4_fc_track_template(handle, inode,  __track_range, &args, 1);
 
        trace_ext4_fc_track_range(inode, start, end, ret);
 }
@@ -537,10 +548,11 @@ static void ext4_fc_submit_bh(struct super_block *sb)
        int write_flags = REQ_SYNC;
        struct buffer_head *bh = EXT4_SB(sb)->s_fc_bh;
 
+       /* TODO: REQ_FUA | REQ_PREFLUSH is unnecessarily expensive. */
        if (test_opt(sb, BARRIER))
                write_flags |= REQ_FUA | REQ_PREFLUSH;
        lock_buffer(bh);
-       clear_buffer_dirty(bh);
+       set_buffer_dirty(bh);
        set_buffer_uptodate(bh);
        bh->b_end_io = ext4_end_buffer_io_sync;
        submit_bh(REQ_OP_WRITE, write_flags, bh);
@@ -846,7 +858,7 @@ static int ext4_fc_submit_inode_data_all(journal_t *journal)
        int ret = 0;
 
        spin_lock(&sbi->s_fc_lock);
-       sbi->s_mount_state |= EXT4_FC_COMMITTING;
+       ext4_set_mount_flag(sb, EXT4_MF_FC_COMMITTING);
        list_for_each(pos, &sbi->s_fc_q[FC_Q_MAIN]) {
                ei = list_entry(pos, struct ext4_inode_info, i_fc_list);
                ext4_set_inode_state(&ei->vfs_inode, EXT4_STATE_FC_COMMITTING);
@@ -900,6 +912,8 @@ static int ext4_fc_wait_inode_data_all(journal_t *journal)
 
 /* Commit all the directory entry updates */
 static int ext4_fc_commit_dentry_updates(journal_t *journal, u32 *crc)
+__acquires(&sbi->s_fc_lock)
+__releases(&sbi->s_fc_lock)
 {
        struct super_block *sb = (struct super_block *)(journal->j_private);
        struct ext4_sb_info *sbi = EXT4_SB(sb);
@@ -964,7 +978,6 @@ static int ext4_fc_commit_dentry_updates(journal_t *journal, u32 *crc)
                        fc_dentry->fcd_parent, fc_dentry->fcd_ino,
                        fc_dentry->fcd_name.len,
                        fc_dentry->fcd_name.name, crc)) {
-                       spin_lock(&sbi->s_fc_lock);
                        ret = -ENOSPC;
                        goto lock_and_exit;
                }
@@ -997,6 +1010,13 @@ static int ext4_fc_perform_commit(journal_t *journal)
        if (ret)
                return ret;
 
+       /*
+        * If file system device is different from journal device, issue a cache
+        * flush before we start writing fast commit blocks.
+        */
+       if (journal->j_fs_dev != journal->j_dev)
+               blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS);
+
        blk_start_plug(&plug);
        if (sbi->s_fc_bytes == 0) {
                /*
@@ -1032,8 +1052,6 @@ static int ext4_fc_perform_commit(journal_t *journal)
                if (ret)
                        goto out;
                spin_lock(&sbi->s_fc_lock);
-               EXT4_I(inode)->i_fc_committed_subtid =
-                       atomic_read(&sbi->s_fc_subtid);
        }
        spin_unlock(&sbi->s_fc_lock);
 
@@ -1132,7 +1150,7 @@ out:
                "Fast commit ended with blks = %d, reason = %d, subtid - %d",
                nblks, reason, subtid);
        if (reason == EXT4_FC_REASON_FC_FAILED)
-               return jbd2_fc_end_commit_fallback(journal, commit_tid);
+               return jbd2_fc_end_commit_fallback(journal);
        if (reason == EXT4_FC_REASON_FC_START_FAILED ||
                reason == EXT4_FC_REASON_INELIGIBLE)
                return jbd2_complete_transaction(journal, commit_tid);
@@ -1191,8 +1209,8 @@ static void ext4_fc_cleanup(journal_t *journal, int full)
        list_splice_init(&sbi->s_fc_q[FC_Q_STAGING],
                                &sbi->s_fc_q[FC_Q_STAGING]);
 
-       sbi->s_mount_state &= ~EXT4_FC_COMMITTING;
-       sbi->s_mount_state &= ~EXT4_FC_INELIGIBLE;
+       ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING);
+       ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE);
 
        if (full)
                sbi->s_fc_bytes = 0;
@@ -1264,7 +1282,7 @@ static int ext4_fc_replay_unlink(struct super_block *sb, struct ext4_fc_tl *tl)
                return 0;
        }
 
-       ret = __ext4_unlink(old_parent, &entry, inode);
+       ret = __ext4_unlink(NULL, old_parent, &entry, inode);
        /* -ENOENT ok coz it might not exist anymore. */
        if (ret == -ENOENT)
                ret = 0;
@@ -1617,8 +1635,10 @@ static int ext4_fc_replay_add_range(struct super_block *sb,
                if (ret == 0) {
                        /* Range is not mapped */
                        path = ext4_find_extent(inode, cur, NULL, 0);
-                       if (!path)
-                               continue;
+                       if (IS_ERR(path)) {
+                               iput(inode);
+                               return 0;
+                       }
                        memset(&newex, 0, sizeof(newex));
                        newex.ee_block = cpu_to_le32(cur);
                        ext4_ext_store_pblock(
@@ -2087,13 +2107,9 @@ void ext4_fc_init(struct super_block *sb, journal_t *journal)
        if (!test_opt2(sb, JOURNAL_FAST_COMMIT))
                return;
        journal->j_fc_cleanup_callback = ext4_fc_cleanup;
-       if (jbd2_fc_init(journal, EXT4_NUM_FC_BLKS)) {
-               pr_warn("Error while enabling fast commits, turning off.");
-               ext4_clear_feature_fast_commit(sb);
-       }
 }
 
-const char *fc_ineligible_reasons[] = {
+static const char *fc_ineligible_reasons[] = {
        "Extended attributes changed",
        "Cross rename",
        "Journal flag changed",
@@ -2102,6 +2118,7 @@ const char *fc_ineligible_reasons[] = {
        "Resize",
        "Dir renamed",
        "Falloc range op",
+       "Data journalling",
        "FC Commit Failed"
 };
 
index 06907d485989b75f973d2d95c69c0bed3c3a554f..3a6e5a1fa1b80b59240fdfa893e81d9c408c3841 100644 (file)
@@ -3,9 +3,6 @@
 #ifndef __FAST_COMMIT_H__
 #define __FAST_COMMIT_H__
 
-/* Number of blocks in journal area to allocate for fast commits */
-#define EXT4_NUM_FC_BLKS               256
-
 /* Fast commit tags */
 #define EXT4_FC_TAG_ADD_RANGE          0x0001
 #define EXT4_FC_TAG_DEL_RANGE          0x0002
@@ -100,11 +97,12 @@ enum {
        EXT4_FC_REASON_XATTR = 0,
        EXT4_FC_REASON_CROSS_RENAME,
        EXT4_FC_REASON_JOURNAL_FLAG_CHANGE,
-       EXT4_FC_REASON_MEM,
+       EXT4_FC_REASON_NOMEM,
        EXT4_FC_REASON_SWAP_BOOT,
        EXT4_FC_REASON_RESIZE,
        EXT4_FC_REASON_RENAME_DIR,
        EXT4_FC_REASON_FALLOC_RANGE,
+       EXT4_FC_REASON_INODE_JOURNAL_DATA,
        EXT4_FC_COMMIT_FAILED,
        EXT4_FC_REASON_MAX
 };
index d85412d12e3af80c97437c944a6abd12399f8205..3ed8c048fb12c547775850ba62d364bc08362c20 100644 (file)
@@ -761,7 +761,6 @@ static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
        if (!daxdev_mapping_supported(vma, dax_dev))
                return -EOPNOTSUPP;
 
-       ext4_fc_start_update(inode);
        file_accessed(file);
        if (IS_DAX(file_inode(file))) {
                vma->vm_ops = &ext4_dax_vm_ops;
@@ -769,7 +768,6 @@ static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
        } else {
                vma->vm_ops = &ext4_file_vm_ops;
        }
-       ext4_fc_stop_update(inode);
        return 0;
 }
 
@@ -782,13 +780,13 @@ static int ext4_sample_last_mounted(struct super_block *sb,
        handle_t *handle;
        int err;
 
-       if (likely(sbi->s_mount_flags & EXT4_MF_MNTDIR_SAMPLED))
+       if (likely(ext4_test_mount_flag(sb, EXT4_MF_MNTDIR_SAMPLED)))
                return 0;
 
        if (sb_rdonly(sb) || !sb_start_intwrite_trylock(sb))
                return 0;
 
-       sbi->s_mount_flags |= EXT4_MF_MNTDIR_SAMPLED;
+       ext4_set_mount_flag(sb, EXT4_MF_MNTDIR_SAMPLED);
        /*
         * Sample where the filesystem has been mounted and
         * store it in the superblock for sysadmin convenience
index b232c27675342c6a4f6aa0c05fe94754c78a7a99..4c2a9fe3006723f4ee1fc84e461d1782322ec054 100644 (file)
@@ -280,7 +280,7 @@ static int ext4_getfsmap_logdev(struct super_block *sb, struct ext4_fsmap *keys,
 
        /* Fabricate an rmap entry for the external log device. */
        irec.fmr_physical = journal->j_blk_offset;
-       irec.fmr_length = journal->j_maxlen;
+       irec.fmr_length = journal->j_total_len;
        irec.fmr_owner = EXT4_FMR_OWN_LOG;
        irec.fmr_flags = 0;
 
index 81a545fd14a3af7d807fc02e6b9de86193ca1e29..a42ca95840f280491b26e8c76555f424311f3584 100644 (file)
@@ -143,7 +143,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
        if (sb_rdonly(inode->i_sb)) {
                /* Make sure that we read updated s_mount_flags value */
                smp_rmb();
-               if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
+               if (ext4_test_mount_flag(inode->i_sb, EXT4_MF_FS_ABORTED))
                        ret = -EROFS;
                goto out;
        }
index 2924261226e0fa6dcc83f849125e0a879b0f869f..a92eb79de0cc7fedd2f53cc369348846396e24f3 100644 (file)
@@ -275,7 +275,7 @@ int ext4fs_dirhash(const struct inode *dir, const char *name, int len,
                   struct dx_hash_info *hinfo)
 {
 #ifdef CONFIG_UNICODE
-       const struct unicode_map *um = EXT4_SB(dir->i_sb)->s_encoding;
+       const struct unicode_map *um = dir->i_sb->s_encoding;
        int r, dlen;
        unsigned char *buff;
        struct qstr qstr = {.name = name, .len = len };
index caa51473207d7e13a586c646faf3006e6d1b7eeb..b41512d1badc368d17f4a105909348d660469b4e 100644 (file)
@@ -1880,6 +1880,7 @@ int ext4_inline_data_truncate(struct inode *inode, int *has_inline)
 
        ext4_write_lock_xattr(inode, &no_expand);
        if (!ext4_has_inline_data(inode)) {
+               ext4_write_unlock_xattr(inode, &no_expand);
                *has_inline = 0;
                ext4_journal_stop(handle);
                return 0;
index 03c2253005f000722151a33c7324e8a83678b36b..0d8385aea8981c335e97e3ae38518b2322b1a86b 100644 (file)
@@ -327,6 +327,8 @@ stop_handle:
        ext4_xattr_inode_array_free(ea_inode_array);
        return;
 no_delete:
+       if (!list_empty(&EXT4_I(inode)->i_fc_list))
+               ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM);
        ext4_clear_inode(inode);        /* We must guarantee clearing of inode... */
 }
 
@@ -730,7 +732,7 @@ out_sem:
                        if (ret)
                                return ret;
                }
-               ext4_fc_track_range(inode, map->m_lblk,
+               ext4_fc_track_range(handle, inode, map->m_lblk,
                            map->m_lblk + map->m_len - 1);
        }
 
@@ -1918,7 +1920,7 @@ static int __ext4_journalled_writepage(struct page *page,
        }
        if (ret == 0)
                ret = err;
-       err = ext4_jbd2_inode_add_write(handle, inode, 0, len);
+       err = ext4_jbd2_inode_add_write(handle, inode, page_offset(page), len);
        if (ret == 0)
                ret = err;
        EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid;
@@ -2440,7 +2442,7 @@ static int mpage_map_and_submit_extent(handle_t *handle,
                        struct super_block *sb = inode->i_sb;
 
                        if (ext4_forced_shutdown(EXT4_SB(sb)) ||
-                           EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)
+                           ext4_test_mount_flag(sb, EXT4_MF_FS_ABORTED))
                                goto invalidate_dirty_pages;
                        /*
                         * Let the uper layers retry transient errors.
@@ -2674,7 +2676,7 @@ static int ext4_writepages(struct address_space *mapping,
         * the stack trace.
         */
        if (unlikely(ext4_forced_shutdown(EXT4_SB(mapping->host->i_sb)) ||
-                    sbi->s_mount_flags & EXT4_MF_FS_ABORTED)) {
+                    ext4_test_mount_flag(inode->i_sb, EXT4_MF_FS_ABORTED))) {
                ret = -EROFS;
                goto out_writepages;
        }
@@ -3307,10 +3309,11 @@ static bool ext4_inode_datasync_dirty(struct inode *inode)
 
        if (journal) {
                if (jbd2_transaction_committed(journal,
-                                       EXT4_I(inode)->i_datasync_tid))
-                       return true;
-               return atomic_read(&EXT4_SB(inode->i_sb)->s_fc_subtid) >=
-                       EXT4_I(inode)->i_fc_committed_subtid;
+                       EXT4_I(inode)->i_datasync_tid))
+                       return false;
+               if (test_opt2(inode->i_sb, JOURNAL_FAST_COMMIT))
+                       return !list_empty(&EXT4_I(inode)->i_fc_list);
+               return true;
        }
 
        /* Any metadata buffers to write? */
@@ -4107,7 +4110,7 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
 
                up_write(&EXT4_I(inode)->i_data_sem);
        }
-       ext4_fc_track_range(inode, first_block, stop_block);
+       ext4_fc_track_range(handle, inode, first_block, stop_block);
        if (IS_SYNC(inode))
                ext4_handle_sync(handle);
 
@@ -5440,14 +5443,14 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
                        }
 
                        if (shrink)
-                               ext4_fc_track_range(inode,
+                               ext4_fc_track_range(handle, inode,
                                        (attr->ia_size > 0 ? attr->ia_size - 1 : 0) >>
                                        inode->i_sb->s_blocksize_bits,
                                        (oldsize > 0 ? oldsize - 1 : 0) >>
                                        inode->i_sb->s_blocksize_bits);
                        else
                                ext4_fc_track_range(
-                                       inode,
+                                       handle, inode,
                                        (oldsize > 0 ? oldsize - 1 : oldsize) >>
                                        inode->i_sb->s_blocksize_bits,
                                        (attr->ia_size > 0 ? attr->ia_size - 1 : 0) >>
@@ -5697,7 +5700,7 @@ int ext4_mark_iloc_dirty(handle_t *handle,
                put_bh(iloc->bh);
                return -EIO;
        }
-       ext4_fc_track_inode(inode);
+       ext4_fc_track_inode(handle, inode);
 
        if (IS_I_VERSION(inode))
                inode_inc_iversion(inode);
@@ -6157,7 +6160,8 @@ retry_alloc:
                        if (ext4_walk_page_buffers(handle, page_buffers(page),
                                        0, len, NULL, write_end_fn))
                                goto out_error;
-                       if (ext4_jbd2_inode_add_write(handle, inode, 0, len))
+                       if (ext4_jbd2_inode_add_write(handle, inode,
+                                                     page_offset(page), len))
                                goto out_error;
                        ext4_set_inode_state(inode, EXT4_STATE_JDATA);
                } else {
index 85abbfb98cbef7aec45d0fd18e8beb76084b661f..24af9ed5c3e52583461ce834b1da817ac1f829b7 100644 (file)
@@ -4477,7 +4477,7 @@ static inline void ext4_mb_show_pa(struct super_block *sb)
 {
        ext4_group_t i, ngroups;
 
-       if (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)
+       if (ext4_test_mount_flag(sb, EXT4_MF_FS_ABORTED))
                return;
 
        ngroups = ext4_get_groups_count(sb);
@@ -4508,7 +4508,7 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
 {
        struct super_block *sb = ac->ac_sb;
 
-       if (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)
+       if (ext4_test_mount_flag(sb, EXT4_MF_FS_ABORTED))
                return;
 
        mb_debug(sb, "Can't allocate:"
@@ -5167,7 +5167,7 @@ static ext4_fsblk_t ext4_mb_new_blocks_simple(handle_t *handle,
        struct super_block *sb = ar->inode->i_sb;
        ext4_group_t group;
        ext4_grpblk_t blkoff;
-       int  i;
+       int i = sb->s_blocksize;
        ext4_fsblk_t goal, block;
        struct ext4_super_block *es = EXT4_SB(sb)->s_es;
 
index 5159830dacb8aa61656b34784cd704fb82f811b5..33509266f5a00a96e4e9593c68b54aee0e075f02 100644 (file)
@@ -1285,8 +1285,8 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block)
 int ext4_ci_compare(const struct inode *parent, const struct qstr *name,
                    const struct qstr *entry, bool quick)
 {
-       const struct ext4_sb_info *sbi = EXT4_SB(parent->i_sb);
-       const struct unicode_map *um = sbi->s_encoding;
+       const struct super_block *sb = parent->i_sb;
+       const struct unicode_map *um = sb->s_encoding;
        int ret;
 
        if (quick)
@@ -1298,7 +1298,7 @@ int ext4_ci_compare(const struct inode *parent, const struct qstr *name,
                /* Handle invalid character sequence as either an error
                 * or as an opaque byte sequence.
                 */
-               if (ext4_has_strict_mode(sbi))
+               if (sb_has_strict_encoding(sb))
                        return -EINVAL;
 
                if (name->len != entry->len)
@@ -1315,7 +1315,7 @@ void ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,
 {
        int len;
 
-       if (!IS_CASEFOLDED(dir) || !EXT4_SB(dir->i_sb)->s_encoding) {
+       if (!IS_CASEFOLDED(dir) || !dir->i_sb->s_encoding) {
                cf_name->name = NULL;
                return;
        }
@@ -1324,7 +1324,7 @@ void ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,
        if (!cf_name->name)
                return;
 
-       len = utf8_casefold(EXT4_SB(dir->i_sb)->s_encoding,
+       len = utf8_casefold(dir->i_sb->s_encoding,
                            iname, cf_name->name,
                            EXT4_NAME_LEN);
        if (len <= 0) {
@@ -1361,7 +1361,7 @@ static inline bool ext4_match(const struct inode *parent,
 #endif
 
 #ifdef CONFIG_UNICODE
-       if (EXT4_SB(parent->i_sb)->s_encoding && IS_CASEFOLDED(parent)) {
+       if (parent->i_sb->s_encoding && IS_CASEFOLDED(parent)) {
                if (fname->cf_name.name) {
                        struct qstr cf = {.name = fname->cf_name.name,
                                          .len = fname->cf_name.len};
@@ -2180,9 +2180,6 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
        struct buffer_head *bh = NULL;
        struct ext4_dir_entry_2 *de;
        struct super_block *sb;
-#ifdef CONFIG_UNICODE
-       struct ext4_sb_info *sbi;
-#endif
        struct ext4_filename fname;
        int     retval;
        int     dx_fallback=0;
@@ -2199,9 +2196,8 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
                return -EINVAL;
 
 #ifdef CONFIG_UNICODE
-       sbi = EXT4_SB(sb);
-       if (ext4_has_strict_mode(sbi) && IS_CASEFOLDED(dir) &&
-           sbi->s_encoding && utf8_validate(sbi->s_encoding, &dentry->d_name))
+       if (sb_has_strict_encoding(sb) && IS_CASEFOLDED(dir) &&
+           sb->s_encoding && utf8_validate(sb->s_encoding, &dentry->d_name))
                return -EINVAL;
 #endif
 
@@ -2610,7 +2606,7 @@ static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode,
                       bool excl)
 {
        handle_t *handle;
-       struct inode *inode, *inode_save;
+       struct inode *inode;
        int err, credits, retries = 0;
 
        err = dquot_initialize(dir);
@@ -2628,11 +2624,9 @@ retry:
                inode->i_op = &ext4_file_inode_operations;
                inode->i_fop = &ext4_file_operations;
                ext4_set_aops(inode);
-               inode_save = inode;
-               ihold(inode_save);
                err = ext4_add_nondir(handle, dentry, &inode);
-               ext4_fc_track_create(inode_save, dentry);
-               iput(inode_save);
+               if (!err)
+                       ext4_fc_track_create(handle, dentry);
        }
        if (handle)
                ext4_journal_stop(handle);
@@ -2647,7 +2641,7 @@ static int ext4_mknod(struct inode *dir, struct dentry *dentry,
                      umode_t mode, dev_t rdev)
 {
        handle_t *handle;
-       struct inode *inode, *inode_save;
+       struct inode *inode;
        int err, credits, retries = 0;
 
        err = dquot_initialize(dir);
@@ -2664,12 +2658,9 @@ retry:
        if (!IS_ERR(inode)) {
                init_special_inode(inode, inode->i_mode, rdev);
                inode->i_op = &ext4_special_inode_operations;
-               inode_save = inode;
-               ihold(inode_save);
                err = ext4_add_nondir(handle, dentry, &inode);
                if (!err)
-                       ext4_fc_track_create(inode_save, dentry);
-               iput(inode_save);
+                       ext4_fc_track_create(handle, dentry);
        }
        if (handle)
                ext4_journal_stop(handle);
@@ -2833,7 +2824,6 @@ out_clear_inode:
                iput(inode);
                goto out_retry;
        }
-       ext4_fc_track_create(inode, dentry);
        ext4_inc_count(dir);
 
        ext4_update_dx_flag(dir);
@@ -2841,6 +2831,7 @@ out_clear_inode:
        if (err)
                goto out_clear_inode;
        d_instantiate_new(dentry, inode);
+       ext4_fc_track_create(handle, dentry);
        if (IS_DIRSYNC(dir))
                ext4_handle_sync(handle);
 
@@ -3175,7 +3166,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
                goto end_rmdir;
        ext4_dec_count(dir);
        ext4_update_dx_flag(dir);
-       ext4_fc_track_unlink(inode, dentry);
+       ext4_fc_track_unlink(handle, dentry);
        retval = ext4_mark_inode_dirty(handle, dir);
 
 #ifdef CONFIG_UNICODE
@@ -3196,13 +3187,12 @@ end_rmdir:
        return retval;
 }
 
-int __ext4_unlink(struct inode *dir, const struct qstr *d_name,
+int __ext4_unlink(handle_t *handle, struct inode *dir, const struct qstr *d_name,
                  struct inode *inode)
 {
        int retval = -ENOENT;
        struct buffer_head *bh;
        struct ext4_dir_entry_2 *de;
-       handle_t *handle = NULL;
        int skip_remove_dentry = 0;
 
        bh = ext4_find_entry(dir, d_name, &de, NULL);
@@ -3221,14 +3211,7 @@ int __ext4_unlink(struct inode *dir, const struct qstr *d_name,
                if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
                        skip_remove_dentry = 1;
                else
-                       goto out_bh;
-       }
-
-       handle = ext4_journal_start(dir, EXT4_HT_DIR,
-                                   EXT4_DATA_TRANS_BLOCKS(dir->i_sb));
-       if (IS_ERR(handle)) {
-               retval = PTR_ERR(handle);
-               goto out_bh;
+                       goto out;
        }
 
        if (IS_DIRSYNC(dir))
@@ -3237,12 +3220,12 @@ int __ext4_unlink(struct inode *dir, const struct qstr *d_name,
        if (!skip_remove_dentry) {
                retval = ext4_delete_entry(handle, dir, de, bh);
                if (retval)
-                       goto out_handle;
+                       goto out;
                dir->i_ctime = dir->i_mtime = current_time(dir);
                ext4_update_dx_flag(dir);
                retval = ext4_mark_inode_dirty(handle, dir);
                if (retval)
-                       goto out_handle;
+                       goto out;
        } else {
                retval = 0;
        }
@@ -3256,15 +3239,14 @@ int __ext4_unlink(struct inode *dir, const struct qstr *d_name,
        inode->i_ctime = current_time(inode);
        retval = ext4_mark_inode_dirty(handle, inode);
 
-out_handle:
-       ext4_journal_stop(handle);
-out_bh:
+out:
        brelse(bh);
        return retval;
 }
 
 static int ext4_unlink(struct inode *dir, struct dentry *dentry)
 {
+       handle_t *handle;
        int retval;
 
        if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
@@ -3282,9 +3264,16 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
        if (retval)
                goto out_trace;
 
-       retval = __ext4_unlink(dir, &dentry->d_name, d_inode(dentry));
+       handle = ext4_journal_start(dir, EXT4_HT_DIR,
+                                   EXT4_DATA_TRANS_BLOCKS(dir->i_sb));
+       if (IS_ERR(handle)) {
+               retval = PTR_ERR(handle);
+               goto out_trace;
+       }
+
+       retval = __ext4_unlink(handle, dir, &dentry->d_name, d_inode(dentry));
        if (!retval)
-               ext4_fc_track_unlink(d_inode(dentry), dentry);
+               ext4_fc_track_unlink(handle, dentry);
 #ifdef CONFIG_UNICODE
        /* VFS negative dentries are incompatible with Encoding and
         * Case-insensitiveness. Eventually we'll want avoid
@@ -3295,6 +3284,8 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
        if (IS_CASEFOLDED(dir))
                d_invalidate(dentry);
 #endif
+       if (handle)
+               ext4_journal_stop(handle);
 
 out_trace:
        trace_ext4_unlink_exit(dentry, retval);
@@ -3451,7 +3442,6 @@ retry:
 
        err = ext4_add_entry(handle, dentry, inode);
        if (!err) {
-               ext4_fc_track_link(inode, dentry);
                err = ext4_mark_inode_dirty(handle, inode);
                /* this can happen only for tmpfile being
                 * linked the first time
@@ -3459,6 +3449,7 @@ retry:
                if (inode->i_nlink == 1)
                        ext4_orphan_del(handle, inode);
                d_instantiate(dentry, inode);
+               ext4_fc_track_link(handle, dentry);
        } else {
                drop_nlink(inode);
                iput(inode);
@@ -3919,9 +3910,9 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
                        EXT4_FC_REASON_RENAME_DIR);
        } else {
                if (new.inode)
-                       ext4_fc_track_unlink(new.inode, new.dentry);
-               ext4_fc_track_link(old.inode, new.dentry);
-               ext4_fc_track_unlink(old.inode, old.dentry);
+                       ext4_fc_track_unlink(handle, new.dentry);
+               __ext4_fc_track_link(handle, old.inode, new.dentry);
+               __ext4_fc_track_unlink(handle, old.inode, old.dentry);
        }
 
        if (new.inode) {
index 2fe141ff3c7e602162a9da361fd8f7b825564179..94472044f4c1d5a73ff6c278193bb15702c6b5af 100644 (file)
@@ -289,18 +289,7 @@ void ext4_superblock_csum_set(struct super_block *sb)
        if (!ext4_has_metadata_csum(sb))
                return;
 
-       /*
-        * Locking the superblock prevents the scenario
-        * where:
-        *  1) a first thread pauses during checksum calculation.
-        *  2) a second thread updates the superblock, recalculates
-        *     the checksum, and updates s_checksum
-        *  3) the first thread resumes and finishes its checksum calculation
-        *     and updates s_checksum with a potentially stale or torn value.
-        */
-       lock_buffer(EXT4_SB(sb)->s_sbh);
        es->s_checksum = ext4_superblock_csum(sb, es);
-       unlock_buffer(EXT4_SB(sb)->s_sbh);
 }
 
 ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
@@ -686,7 +675,7 @@ static void ext4_handle_error(struct super_block *sb)
        if (!test_opt(sb, ERRORS_CONT)) {
                journal_t *journal = EXT4_SB(sb)->s_journal;
 
-               EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
+               ext4_set_mount_flag(sb, EXT4_MF_FS_ABORTED);
                if (journal)
                        jbd2_journal_abort(journal, -EIO);
        }
@@ -904,7 +893,7 @@ void __ext4_abort(struct super_block *sb, const char *function,
        va_end(args);
 
        if (sb_rdonly(sb) == 0) {
-               EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
+               ext4_set_mount_flag(sb, EXT4_MF_FS_ABORTED);
                if (EXT4_SB(sb)->s_journal)
                        jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
 
@@ -1288,7 +1277,7 @@ static void ext4_put_super(struct super_block *sb)
        fs_put_dax(sbi->s_daxdev);
        fscrypt_free_dummy_policy(&sbi->s_dummy_enc_policy);
 #ifdef CONFIG_UNICODE
-       utf8_unload(sbi->s_encoding);
+       utf8_unload(sb->s_encoding);
 #endif
        kfree(sbi);
 }
@@ -1716,11 +1705,10 @@ enum {
        Opt_dioread_nolock, Opt_dioread_lock,
        Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,
        Opt_max_dir_size_kb, Opt_nojournal_checksum, Opt_nombcache,
-       Opt_prefetch_block_bitmaps, Opt_no_fc,
+       Opt_prefetch_block_bitmaps,
 #ifdef CONFIG_EXT4_DEBUG
-       Opt_fc_debug_max_replay,
+       Opt_fc_debug_max_replay, Opt_fc_debug_force
 #endif
-       Opt_fc_debug_force
 };
 
 static const match_table_t tokens = {
@@ -1807,9 +1795,8 @@ static const match_table_t tokens = {
        {Opt_init_itable, "init_itable=%u"},
        {Opt_init_itable, "init_itable"},
        {Opt_noinit_itable, "noinit_itable"},
-       {Opt_no_fc, "no_fc"},
-       {Opt_fc_debug_force, "fc_debug_force"},
 #ifdef CONFIG_EXT4_DEBUG
+       {Opt_fc_debug_force, "fc_debug_force"},
        {Opt_fc_debug_max_replay, "fc_debug_max_replay=%u"},
 #endif
        {Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
@@ -2027,8 +2014,8 @@ static const struct mount_opts {
        {Opt_noquota, (EXT4_MOUNT_QUOTA | EXT4_MOUNT_USRQUOTA |
                       EXT4_MOUNT_GRPQUOTA | EXT4_MOUNT_PRJQUOTA),
                                                        MOPT_CLEAR | MOPT_Q},
-       {Opt_usrjquota, 0, MOPT_Q},
-       {Opt_grpjquota, 0, MOPT_Q},
+       {Opt_usrjquota, 0, MOPT_Q | MOPT_STRING},
+       {Opt_grpjquota, 0, MOPT_Q | MOPT_STRING},
        {Opt_offusrjquota, 0, MOPT_Q},
        {Opt_offgrpjquota, 0, MOPT_Q},
        {Opt_jqfmt_vfsold, QFMT_VFS_OLD, MOPT_QFMT},
@@ -2039,11 +2026,9 @@ static const struct mount_opts {
        {Opt_nombcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET},
        {Opt_prefetch_block_bitmaps, EXT4_MOUNT_PREFETCH_BLOCK_BITMAPS,
         MOPT_SET},
-       {Opt_no_fc, EXT4_MOUNT2_JOURNAL_FAST_COMMIT,
-        MOPT_CLEAR | MOPT_2 | MOPT_EXT4_ONLY},
+#ifdef CONFIG_EXT4_DEBUG
        {Opt_fc_debug_force, EXT4_MOUNT2_JOURNAL_FAST_COMMIT,
         MOPT_SET | MOPT_2 | MOPT_EXT4_ONLY},
-#ifdef CONFIG_EXT4_DEBUG
        {Opt_fc_debug_max_replay, 0, MOPT_GTE0},
 #endif
        {Opt_err, 0, 0}
@@ -2153,7 +2138,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                ext4_msg(sb, KERN_WARNING, "Ignoring removed %s option", opt);
                return 1;
        case Opt_abort:
-               sbi->s_mount_flags |= EXT4_MF_FS_ABORTED;
+               ext4_set_mount_flag(sb, EXT4_MF_FS_ABORTED);
                return 1;
        case Opt_i_version:
                sb->s_flags |= SB_I_VERSION;
@@ -2653,10 +2638,6 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
        } else if (test_opt2(sb, DAX_INODE)) {
                SEQ_OPTS_PUTS("dax=inode");
        }
-
-       if (test_opt2(sb, JOURNAL_FAST_COMMIT))
-               SEQ_OPTS_PUTS("fast_commit");
-
        ext4_show_quota_options(seq, sb);
        return 0;
 }
@@ -3976,7 +3957,7 @@ int ext4_calculate_overhead(struct super_block *sb)
         * loaded or not
         */
        if (sbi->s_journal && !sbi->s_journal_bdev)
-               overhead += EXT4_NUM_B2C(sbi, sbi->s_journal->j_maxlen);
+               overhead += EXT4_NUM_B2C(sbi, sbi->s_journal->j_total_len);
        else if (ext4_has_feature_journal(sb) && !sbi->s_journal && j_inum) {
                /* j_inum for internal journal is non-zero */
                j_inode = ext4_get_journal_inode(sb, j_inum);
@@ -4303,7 +4284,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                goto failed_mount;
 
 #ifdef CONFIG_UNICODE
-       if (ext4_has_feature_casefold(sb) && !sbi->s_encoding) {
+       if (ext4_has_feature_casefold(sb) && !sb->s_encoding) {
                const struct ext4_sb_encodings *encoding_info;
                struct unicode_map *encoding;
                __u16 encoding_flags;
@@ -4334,15 +4315,16 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                         "%s-%s with flags 0x%hx", encoding_info->name,
                         encoding_info->version?:"\b", encoding_flags);
 
-               sbi->s_encoding = encoding;
-               sbi->s_encoding_flags = encoding_flags;
+               sb->s_encoding = encoding;
+               sb->s_encoding_flags = encoding_flags;
        }
 #endif
 
        if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
-               printk_once(KERN_WARNING "EXT4-fs: Warning: mounting with data=journal disables delayed allocation, dioread_nolock, and O_DIRECT support!\n");
+               printk_once(KERN_WARNING "EXT4-fs: Warning: mounting with data=journal disables delayed allocation, dioread_nolock, O_DIRECT and fast_commit support!\n");
                /* can't mount with both data=journal and dioread_nolock. */
                clear_opt(sb, DIOREAD_NOLOCK);
+               clear_opt2(sb, JOURNAL_FAST_COMMIT);
                if (test_opt2(sb, EXPLICIT_DELALLOC)) {
                        ext4_msg(sb, KERN_ERR, "can't mount with "
                                 "both data=journal and delalloc");
@@ -4777,8 +4759,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        INIT_LIST_HEAD(&sbi->s_fc_dentry_q[FC_Q_MAIN]);
        INIT_LIST_HEAD(&sbi->s_fc_dentry_q[FC_Q_STAGING]);
        sbi->s_fc_bytes = 0;
-       sbi->s_mount_state &= ~EXT4_FC_INELIGIBLE;
-       sbi->s_mount_state &= ~EXT4_FC_COMMITTING;
+       ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE);
+       ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING);
        spin_lock_init(&sbi->s_fc_lock);
        memset(&sbi->s_fc_stats, 0, sizeof(sbi->s_fc_stats));
        sbi->s_fc_replay_state.fc_regions = NULL;
@@ -4857,6 +4839,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                goto failed_mount_wq;
        }
 
+       if (test_opt2(sb, JOURNAL_FAST_COMMIT) &&
+               !jbd2_journal_set_features(EXT4_SB(sb)->s_journal, 0, 0,
+                                         JBD2_FEATURE_INCOMPAT_FAST_COMMIT)) {
+               ext4_msg(sb, KERN_ERR,
+                       "Failed to set fast commit journal feature");
+               goto failed_mount_wq;
+       }
+
        /* We have now updated the journal if required, so we can
         * validate the data journaling mode. */
        switch (test_opt(sb, DATA_FLAGS)) {
@@ -4975,7 +4965,7 @@ no_journal:
        }
 
 #ifdef CONFIG_UNICODE
-       if (sbi->s_encoding)
+       if (sb->s_encoding)
                sb->s_d_op = &ext4_dentry_ops;
 #endif
 
@@ -5184,7 +5174,7 @@ failed_mount:
                crypto_free_shash(sbi->s_chksum_driver);
 
 #ifdef CONFIG_UNICODE
-       utf8_unload(sbi->s_encoding);
+       utf8_unload(sb->s_encoding);
 #endif
 
 #ifdef CONFIG_QUOTA
@@ -5872,7 +5862,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                goto restore_opts;
        }
 
-       if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
+       if (ext4_test_mount_flag(sb, EXT4_MF_FS_ABORTED))
                ext4_abort(sb, EXT4_ERR_ESHUTDOWN, "Abort forced by user");
 
        sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
@@ -5886,7 +5876,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
        }
 
        if ((bool)(*flags & SB_RDONLY) != sb_rdonly(sb)) {
-               if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) {
+               if (ext4_test_mount_flag(sb, EXT4_MF_FS_ABORTED)) {
                        err = -EROFS;
                        goto restore_opts;
                }
@@ -6560,10 +6550,6 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
        brelse(bh);
 out:
        if (inode->i_size < off + len) {
-               ext4_fc_track_range(inode,
-                       (inode->i_size > 0 ? inode->i_size - 1 : 0)
-                               >> inode->i_sb->s_blocksize_bits,
-                       (off + len) >> inode->i_sb->s_blocksize_bits);
                i_size_write(inode, off + len);
                EXT4_I(inode)->i_disksize = inode->i_size;
                err2 = ext4_mark_inode_dirty(handle, inode);
index 5ff33d18996a859451c1eab552672892b32f0a2f..4e27fe6ed3ae6a97816f3b6c2915c3f58be88656 100644 (file)
@@ -315,6 +315,7 @@ EXT4_ATTR_FEATURE(casefold);
 EXT4_ATTR_FEATURE(verity);
 #endif
 EXT4_ATTR_FEATURE(metadata_csum_seed);
+EXT4_ATTR_FEATURE(fast_commit);
 
 static struct attribute *ext4_feat_attrs[] = {
        ATTR_LIST(lazy_itable_init),
@@ -331,6 +332,7 @@ static struct attribute *ext4_feat_attrs[] = {
        ATTR_LIST(verity),
 #endif
        ATTR_LIST(metadata_csum_seed),
+       ATTR_LIST(fast_commit),
        NULL,
 };
 ATTRIBUTE_GROUPS(ext4_feat);
index 9cd2ecad07dbd0576ad92870d3de6485716119f6..cc4f987687f3c1ff611d968b311e9724aeca7f4f 100644 (file)
@@ -77,7 +77,7 @@ static int gfs2_get_block_noalloc(struct inode *inode, sector_t lblock,
        if (error)
                return error;
        if (!buffer_mapped(bh_result))
-               return -EIO;
+               return -ENODATA;
        return 0;
 }
 
index 8dff9cbd0a87cf8a303dbe4b3c33887df001056c..62d9081d1e26eeb87dd5dbd708643e5c8fc068fb 100644 (file)
@@ -1301,12 +1301,8 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,
        trace_gfs2_bmap(ip, bh_map, lblock, create, 1);
 
        ret = gfs2_iomap_get(inode, pos, length, flags, &iomap, &mp);
-       if (!ret && iomap.type == IOMAP_HOLE) {
-               if (create)
-                       ret = gfs2_iomap_alloc(inode, &iomap, &mp);
-               else
-                       ret = -ENODATA;
-       }
+       if (create && !ret && iomap.type == IOMAP_HOLE)
+               ret = gfs2_iomap_alloc(inode, &iomap, &mp);
        release_metapath(&mp);
        if (ret)
                goto out;
index 5441c17562c569e40a981e66e27554fa6a7c10cb..35a6fd103761b5fcd3f06ede79091e656153b306 100644 (file)
@@ -1035,6 +1035,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
        gl->gl_node.next = NULL;
        gl->gl_flags = 0;
        gl->gl_name = name;
+       lockdep_set_subclass(&gl->gl_lockref.lock, glops->go_subclass);
        gl->gl_lockref.count = 1;
        gl->gl_state = LM_ST_UNLOCKED;
        gl->gl_target = LM_ST_UNLOCKED;
@@ -1078,7 +1079,8 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 out_free:
        kfree(gl->gl_lksb.sb_lvbptr);
        kmem_cache_free(cachep, gl);
-       atomic_dec(&sdp->sd_glock_disposal);
+       if (atomic_dec_and_test(&sdp->sd_glock_disposal))
+               wake_up(&sdp->sd_glock_wait);
 
 out:
        return ret;
index aa3f5236befb4d5b23a59c8f4384812118756cbb..3faa421568b0abae386ca6aedb65b785384a32bc 100644 (file)
@@ -164,6 +164,31 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
                       GFS2_LFC_AIL_FLUSH);
 }
 
+/**
+ * gfs2_rgrp_metasync - sync out the metadata of a resource group
+ * @gl: the glock protecting the resource group
+ *
+ */
+
+static int gfs2_rgrp_metasync(struct gfs2_glock *gl)
+{
+       struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
+       struct address_space *metamapping = &sdp->sd_aspace;
+       struct gfs2_rgrpd *rgd = gfs2_glock2rgrp(gl);
+       const unsigned bsize = sdp->sd_sb.sb_bsize;
+       loff_t start = (rgd->rd_addr * bsize) & PAGE_MASK;
+       loff_t end = PAGE_ALIGN((rgd->rd_addr + rgd->rd_length) * bsize) - 1;
+       int error;
+
+       filemap_fdatawrite_range(metamapping, start, end);
+       error = filemap_fdatawait_range(metamapping, start, end);
+       WARN_ON_ONCE(error && !gfs2_withdrawn(sdp));
+       mapping_set_error(metamapping, error);
+       if (error)
+               gfs2_io_error(sdp);
+       return error;
+}
+
 /**
  * rgrp_go_sync - sync out the metadata for this glock
  * @gl: the glock
@@ -176,11 +201,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 static int rgrp_go_sync(struct gfs2_glock *gl)
 {
        struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
-       struct address_space *mapping = &sdp->sd_aspace;
        struct gfs2_rgrpd *rgd = gfs2_glock2rgrp(gl);
-       const unsigned bsize = sdp->sd_sb.sb_bsize;
-       loff_t start = (rgd->rd_addr * bsize) & PAGE_MASK;
-       loff_t end = PAGE_ALIGN((rgd->rd_addr + rgd->rd_length) * bsize) - 1;
        int error;
 
        if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
@@ -189,10 +210,7 @@ static int rgrp_go_sync(struct gfs2_glock *gl)
 
        gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL |
                       GFS2_LFC_RGRP_GO_SYNC);
-       filemap_fdatawrite_range(mapping, start, end);
-       error = filemap_fdatawait_range(mapping, start, end);
-       WARN_ON_ONCE(error && !gfs2_withdrawn(sdp));
-       mapping_set_error(mapping, error);
+       error = gfs2_rgrp_metasync(gl);
        if (!error)
                error = gfs2_ail_empty_gl(gl);
        gfs2_free_clones(rgd);
@@ -227,7 +245,7 @@ static void rgrp_go_inval(struct gfs2_glock *gl, int flags)
 static void gfs2_rgrp_go_dump(struct seq_file *seq, struct gfs2_glock *gl,
                              const char *fs_id_buf)
 {
-       struct gfs2_rgrpd *rgd = gfs2_glock2rgrp(gl);
+       struct gfs2_rgrpd *rgd = gl->gl_object;
 
        if (rgd)
                gfs2_rgrp_dump(seq, rgd, fs_id_buf);
@@ -266,7 +284,24 @@ static void gfs2_clear_glop_pending(struct gfs2_inode *ip)
 }
 
 /**
- * inode_go_sync - Sync the dirty data and/or metadata for an inode glock
+ * gfs2_inode_metasync - sync out the metadata of an inode
+ * @gl: the glock protecting the inode
+ *
+ */
+int gfs2_inode_metasync(struct gfs2_glock *gl)
+{
+       struct address_space *metamapping = gfs2_glock2aspace(gl);
+       int error;
+
+       filemap_fdatawrite(metamapping);
+       error = filemap_fdatawait(metamapping);
+       if (error)
+               gfs2_io_error(gl->gl_name.ln_sbd);
+       return error;
+}
+
+/**
+ * inode_go_sync - Sync the dirty metadata of an inode
  * @gl: the glock protecting the inode
  *
  */
@@ -297,8 +332,7 @@ static int inode_go_sync(struct gfs2_glock *gl)
                error = filemap_fdatawait(mapping);
                mapping_set_error(mapping, error);
        }
-       ret = filemap_fdatawait(metamapping);
-       mapping_set_error(metamapping, ret);
+       ret = gfs2_inode_metasync(gl);
        if (!error)
                error = ret;
        gfs2_ail_empty_gl(gl);
@@ -537,7 +571,19 @@ static int freeze_go_sync(struct gfs2_glock *gl)
        int error = 0;
        struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 
-       if (gl->gl_req == LM_ST_EXCLUSIVE && !gfs2_withdrawn(sdp)) {
+       /*
+        * We need to check gl_state == LM_ST_SHARED here and not gl_req ==
+        * LM_ST_EXCLUSIVE. That's because when any node does a freeze,
+        * all the nodes should have the freeze glock in SH mode and they all
+        * call do_xmote: One for EX and the others for UN. They ALL must
+        * freeze locally, and they ALL must queue freeze work. The freeze_work
+        * calls freeze_func, which tries to reacquire the freeze glock in SH,
+        * effectively waiting for the thaw on the node who holds it in EX.
+        * Once thawed, the work func acquires the freeze glock in
+        * SH and everybody goes back to thawed.
+        */
+       if (gl->gl_state == LM_ST_SHARED && !gfs2_withdrawn(sdp) &&
+           !test_bit(SDF_NORECOVERY, &sdp->sd_flags)) {
                atomic_set(&sdp->sd_freeze_state, SFS_STARTING_FREEZE);
                error = freeze_super(sdp->sd_vfs);
                if (error) {
@@ -736,6 +782,7 @@ const struct gfs2_glock_operations gfs2_iopen_glops = {
        .go_callback = iopen_go_callback,
        .go_demote_ok = iopen_go_demote_ok,
        .go_flags = GLOF_LRU | GLOF_NONDISK,
+       .go_subclass = 1,
 };
 
 const struct gfs2_glock_operations gfs2_flock_glops = {
index 2dd192e8561825920ac24d9b4931e9f3fcc71104..695898afcaf1fbf6c9d3be048a1cfa90ce11e225 100644 (file)
@@ -22,6 +22,7 @@ extern const struct gfs2_glock_operations gfs2_quota_glops;
 extern const struct gfs2_glock_operations gfs2_journal_glops;
 extern const struct gfs2_glock_operations *gfs2_glops_list[];
 
+extern int gfs2_inode_metasync(struct gfs2_glock *gl);
 extern void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync);
 
 #endif /* __GLOPS_DOT_H__ */
index d7707307f4b178a833515579fc62f2fc0df8b5b4..f8858d995b241093063f676165aee5441b014a7a 100644 (file)
@@ -247,6 +247,7 @@ struct gfs2_glock_operations {
                        const char *fs_id_buf);
        void (*go_callback)(struct gfs2_glock *gl, bool remote);
        void (*go_free)(struct gfs2_glock *gl);
+       const int go_subclass;
        const int go_type;
        const unsigned long go_flags;
 #define GLOF_ASPACE 1 /* address space attached */
index 6774865f5b5b5c5f8b468d85abc9cd4cb912afa4..65ae4fc28ede49a7354a18c6928141a09d5acbfc 100644 (file)
@@ -150,6 +150,8 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
                error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
                if (unlikely(error))
                        goto fail;
+               if (blktype != GFS2_BLKST_UNLINKED)
+                       gfs2_cancel_delete_work(io_gl);
 
                if (type == DT_UNKNOWN || blktype != GFS2_BLKST_FREE) {
                        /*
@@ -180,7 +182,6 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
                error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
                if (unlikely(error))
                        goto fail;
-               gfs2_cancel_delete_work(ip->i_iopen_gh.gh_gl);
                glock_set_object(ip->i_iopen_gh.gh_gl, ip);
                gfs2_glock_put(io_gl);
                io_gl = NULL;
@@ -724,13 +725,19 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
        flush_delayed_work(&ip->i_gl->gl_work);
        glock_set_object(ip->i_gl, ip);
 
-       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);
+       error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
        if (error)
                goto fail_free_inode;
+       gfs2_cancel_delete_work(io_gl);
+       glock_set_object(io_gl, ip);
+
+       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);
+       if (error)
+               goto fail_gunlock2;
 
        error = gfs2_trans_begin(sdp, blocks, 0);
        if (error)
-               goto fail_free_inode;
+               goto fail_gunlock2;
 
        if (blocks > 1) {
                ip->i_eattr = ip->i_no_addr + 1;
@@ -739,18 +746,12 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
        init_dinode(dip, ip, symname);
        gfs2_trans_end(sdp);
 
-       error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
-       if (error)
-               goto fail_free_inode;
-
        BUG_ON(test_and_set_bit(GLF_INODE_CREATING, &io_gl->gl_flags));
 
        error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
        if (error)
                goto fail_gunlock2;
 
-       gfs2_cancel_delete_work(ip->i_iopen_gh.gh_gl);
-       glock_set_object(ip->i_iopen_gh.gh_gl, ip);
        gfs2_set_iop(inode);
        insert_inode_hash(inode);
 
@@ -802,6 +803,7 @@ fail_gunlock3:
        gfs2_glock_dq_uninit(&ip->i_iopen_gh);
 fail_gunlock2:
        clear_bit(GLF_INODE_CREATING, &io_gl->gl_flags);
+       glock_clear_object(io_gl, ip);
        gfs2_glock_put(io_gl);
 fail_free_inode:
        if (ip->i_gl) {
@@ -2115,6 +2117,25 @@ loff_t gfs2_seek_hole(struct file *file, loff_t offset)
        return vfs_setpos(file, ret, inode->i_sb->s_maxbytes);
 }
 
+static int gfs2_update_time(struct inode *inode, struct timespec64 *time,
+                           int flags)
+{
+       struct gfs2_inode *ip = GFS2_I(inode);
+       struct gfs2_glock *gl = ip->i_gl;
+       struct gfs2_holder *gh;
+       int error;
+
+       gh = gfs2_glock_is_locked_by_me(gl);
+       if (gh && !gfs2_glock_is_held_excl(gl)) {
+               gfs2_glock_dq(gh);
+               gfs2_holder_reinit(LM_ST_EXCLUSIVE, 0, gh);
+               error = gfs2_glock_nq(gh);
+               if (error)
+                       return error;
+       }
+       return generic_update_time(inode, time, flags);
+}
+
 const struct inode_operations gfs2_file_iops = {
        .permission = gfs2_permission,
        .setattr = gfs2_setattr,
@@ -2123,6 +2144,7 @@ const struct inode_operations gfs2_file_iops = {
        .fiemap = gfs2_fiemap,
        .get_acl = gfs2_get_acl,
        .set_acl = gfs2_set_acl,
+       .update_time = gfs2_update_time,
 };
 
 const struct inode_operations gfs2_dir_iops = {
@@ -2142,6 +2164,7 @@ const struct inode_operations gfs2_dir_iops = {
        .fiemap = gfs2_fiemap,
        .get_acl = gfs2_get_acl,
        .set_acl = gfs2_set_acl,
+       .update_time = gfs2_update_time,
        .atomic_open = gfs2_atomic_open,
 };
 
index 9133b317867755497969ad490bd267573b7dc5de..2e9314091c81d0c472e374b2acb93dd353b94b5c 100644 (file)
@@ -132,6 +132,8 @@ __acquires(&sdp->sd_ail_lock)
                spin_unlock(&sdp->sd_ail_lock);
                ret = generic_writepages(mapping, wbc);
                spin_lock(&sdp->sd_ail_lock);
+               if (ret == -ENODATA) /* if a jdata write into a new hole */
+                       ret = 0; /* ignore it */
                if (ret || wbc->nr_to_write <= 0)
                        break;
                return -EBUSY;
index ed69298dd824a23c53cf6a83e7dad64c011ecf3c..3922b26264f5a87cec611ab2e6b01cf4827cde44 100644 (file)
@@ -22,6 +22,7 @@
 #include "incore.h"
 #include "inode.h"
 #include "glock.h"
+#include "glops.h"
 #include "log.h"
 #include "lops.h"
 #include "meta_io.h"
@@ -817,41 +818,19 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, u32 start,
        return error;
 }
 
-/**
- * gfs2_meta_sync - Sync all buffers associated with a glock
- * @gl: The glock
- *
- */
-
-void gfs2_meta_sync(struct gfs2_glock *gl)
-{
-       struct address_space *mapping = gfs2_glock2aspace(gl);
-       struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
-       int error;
-
-       if (mapping == NULL)
-               mapping = &sdp->sd_aspace;
-
-       filemap_fdatawrite(mapping);
-       error = filemap_fdatawait(mapping);
-
-       if (error)
-               gfs2_io_error(gl->gl_name.ln_sbd);
-}
-
 static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
 {
        struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
        struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
 
        if (error) {
-               gfs2_meta_sync(ip->i_gl);
+               gfs2_inode_metasync(ip->i_gl);
                return;
        }
        if (pass != 1)
                return;
 
-       gfs2_meta_sync(ip->i_gl);
+       gfs2_inode_metasync(ip->i_gl);
 
        fs_info(sdp, "jid=%u: Replayed %u of %u blocks\n",
                jd->jd_jid, jd->jd_replayed_blocks, jd->jd_found_blocks);
@@ -1060,14 +1039,14 @@ static void databuf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
        struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
 
        if (error) {
-               gfs2_meta_sync(ip->i_gl);
+               gfs2_inode_metasync(ip->i_gl);
                return;
        }
        if (pass != 1)
                return;
 
        /* data sync? */
-       gfs2_meta_sync(ip->i_gl);
+       gfs2_inode_metasync(ip->i_gl);
 
        fs_info(sdp, "jid=%u: Replayed %u of %u data blocks\n",
                jd->jd_jid, jd->jd_replayed_blocks, jd->jd_found_blocks);
index 4a3d8aecdf82765a22dd655c7e8913ff8a3a289d..fbdbb08dcec6af19057a4f4181e10f2441295c11 100644 (file)
@@ -27,8 +27,6 @@ extern void gfs2_log_submit_bio(struct bio **biop, int opf);
 extern void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh);
 extern int gfs2_find_jhead(struct gfs2_jdesc *jd,
                           struct gfs2_log_header_host *head, bool keep_cache);
-extern void gfs2_meta_sync(struct gfs2_glock *gl);
-
 static inline unsigned int buf_limit(struct gfs2_sbd *sdp)
 {
        unsigned int limit;
index 7a7e3c10a9a92947d7ef86b4dbcd3fa1f63d06ed..61fce59cb4d3839512974bc679bd1db4e7ecec87 100644 (file)
@@ -633,8 +633,10 @@ static int init_statfs(struct gfs2_sbd *sdp)
        if (IS_ERR(sdp->sd_statfs_inode)) {
                error = PTR_ERR(sdp->sd_statfs_inode);
                fs_err(sdp, "can't read in statfs inode: %d\n", error);
-               goto fail;
+               goto out;
        }
+       if (sdp->sd_args.ar_spectator)
+               goto out;
 
        pn = gfs2_lookup_simple(master, "per_node");
        if (IS_ERR(pn)) {
@@ -682,15 +684,17 @@ free_local:
        iput(pn);
 put_statfs:
        iput(sdp->sd_statfs_inode);
-fail:
+out:
        return error;
 }
 
 /* Uninitialize and free up memory used by the list of statfs inodes */
 static void uninit_statfs(struct gfs2_sbd *sdp)
 {
-       gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
-       free_local_statfs_inodes(sdp);
+       if (!sdp->sd_args.ar_spectator) {
+               gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
+               free_local_statfs_inodes(sdp);
+       }
        iput(sdp->sd_statfs_inode);
 }
 
@@ -704,7 +708,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
 
        if (undo) {
                jindex = 0;
-               goto fail_jinode_gh;
+               goto fail_statfs;
        }
 
        sdp->sd_jindex = gfs2_lookup_simple(master, "jindex");
index b5cbe21efdfb3b5608b1fb35dd8fc5329604c051..c26c68ebd29d4be67b3015838fca25068e6c0641 100644 (file)
@@ -349,7 +349,7 @@ static int update_statfs_inode(struct gfs2_jdesc *jd,
 
        mark_buffer_dirty(bh);
        brelse(bh);
-       gfs2_meta_sync(ip->i_gl);
+       gfs2_inode_metasync(ip->i_gl);
 
 out:
        return error;
index ee491bb9c1ccdcdef39bf233830cd82519f87963..5e8eef9990e326428d9c5e44ee19a5233029425f 100644 (file)
@@ -719,9 +719,9 @@ void gfs2_clear_rgrpd(struct gfs2_sbd *sdp)
                }
 
                gfs2_free_clones(rgd);
+               return_all_reservations(rgd);
                kfree(rgd->rd_bits);
                rgd->rd_bits = NULL;
-               return_all_reservations(rgd);
                kmem_cache_free(gfs2_rgrpd_cachep, rgd);
        }
 }
@@ -985,6 +985,10 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
        if (error < 0)
                return error;
 
+       if (RB_EMPTY_ROOT(&sdp->sd_rindex_tree)) {
+               fs_err(sdp, "no resource groups found in the file system.\n");
+               return -ENOENT;
+       }
        set_rgrp_preferences(sdp);
 
        sdp->sd_rindex_uptodate = 1;
@@ -1370,6 +1374,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+       if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))
+               return -EROFS;
+
        if (!blk_queue_discard(q))
                return -EOPNOTSUPP;
 
@@ -2526,13 +2533,13 @@ int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, unsigned int type)
 
        rbm.rgd = rgd;
        error = gfs2_rbm_from_block(&rbm, no_addr);
-       if (WARN_ON_ONCE(error))
-               goto fail;
-
-       if (gfs2_testbit(&rbm, false) != type)
-               error = -ESTALE;
+       if (!WARN_ON_ONCE(error)) {
+               if (gfs2_testbit(&rbm, false) != type)
+                       error = -ESTALE;
+       }
 
        gfs2_glock_dq_uninit(&rgd_gh);
+
 fail:
        return error;
 }
index b285192bd6b3136e3ab40096e05ef59b16bdfb96..b3d951ab806806574bb2407c8bba1e11c05fe66a 100644 (file)
@@ -738,6 +738,7 @@ restart:
        gfs2_jindex_free(sdp);
        /*  Take apart glock structures and buffer lists  */
        gfs2_gl_hash_clear(sdp);
+       truncate_inode_pages_final(&sdp->sd_aspace);
        gfs2_delete_debugfs_file(sdp);
        /*  Unmount the locking protocol  */
        gfs2_lm_unmount(sdp);
index dcc2aab1b2c43fefc751c1c0b74fcfddac61257a..4ba45caf593929d00b8d665687715521ce737eb1 100644 (file)
@@ -60,7 +60,7 @@ struct hfs_bnode {
        wait_queue_head_t lock_wq;
        atomic_t refcnt;
        unsigned int page_offset;
-       struct page *page[0];
+       struct page *page[];
 };
 
 #define HFS_BNODE_ERROR                0
index 3b03fff68543c55eea2d3e39181d4453affccafe..a92de5199ec33ded8210b133b6b45185d8649e8c 100644 (file)
@@ -117,7 +117,7 @@ struct hfs_bnode {
        wait_queue_head_t lock_wq;
        atomic_t refcnt;
        unsigned int page_offset;
-       struct page *page[0];
+       struct page *page[];
 };
 
 #define HFS_BNODE_LOCK         0
index 02894df7656dd1df1b4a13141c3089bf4ce03518..b53c055bea6a36dba4d3d0d7d957798d5aceec29 100644 (file)
@@ -482,6 +482,10 @@ static void io_impersonate_work(struct io_worker *worker,
                current->files = work->identity->files;
                current->nsproxy = work->identity->nsproxy;
                task_unlock(current);
+               if (!work->identity->files) {
+                       /* failed grabbing files, ensure work gets cancelled */
+                       work->flags |= IO_WQ_WORK_CANCEL;
+               }
        }
        if ((work->flags & IO_WQ_WORK_FS) && current->fs != work->identity->fs)
                current->fs = work->identity->fs;
index b42dfa0243bfd5ecf83caf903044a724a3919e76..a2a7c65a77aa92d09ec4dfd9d1b65535dfaf2b04 100644 (file)
@@ -205,6 +205,7 @@ struct fixed_file_ref_node {
        struct list_head                file_list;
        struct fixed_file_data          *file_data;
        struct llist_node               llist;
+       bool                            done;
 };
 
 struct fixed_file_data {
@@ -478,6 +479,7 @@ struct io_sr_msg {
 struct io_open {
        struct file                     *file;
        int                             dfd;
+       bool                            ignore_nonblock;
        struct filename                 *filename;
        struct open_how                 how;
        unsigned long                   nofile;
@@ -995,20 +997,33 @@ static void io_sq_thread_drop_mm(void)
        if (mm) {
                kthread_unuse_mm(mm);
                mmput(mm);
+               current->mm = NULL;
        }
 }
 
 static int __io_sq_thread_acquire_mm(struct io_ring_ctx *ctx)
 {
-       if (!current->mm) {
-               if (unlikely(!(ctx->flags & IORING_SETUP_SQPOLL) ||
-                            !ctx->sqo_task->mm ||
-                            !mmget_not_zero(ctx->sqo_task->mm)))
-                       return -EFAULT;
-               kthread_use_mm(ctx->sqo_task->mm);
+       struct mm_struct *mm;
+
+       if (current->mm)
+               return 0;
+
+       /* Should never happen */
+       if (unlikely(!(ctx->flags & IORING_SETUP_SQPOLL)))
+               return -EFAULT;
+
+       task_lock(ctx->sqo_task);
+       mm = ctx->sqo_task->mm;
+       if (unlikely(!mm || !mmget_not_zero(mm)))
+               mm = NULL;
+       task_unlock(ctx->sqo_task);
+
+       if (mm) {
+               kthread_use_mm(mm);
+               return 0;
        }
 
-       return 0;
+       return -EFAULT;
 }
 
 static int io_sq_thread_acquire_mm(struct io_ring_ctx *ctx,
@@ -1274,9 +1289,12 @@ static bool io_identity_cow(struct io_kiocb *req)
        /* add one for this request */
        refcount_inc(&id->count);
 
-       /* drop old identity, assign new one. one ref for req, one for tctx */
-       if (req->work.identity != tctx->identity &&
-           refcount_sub_and_test(2, &req->work.identity->count))
+       /* drop tctx and req identity references, if needed */
+       if (tctx->identity != &tctx->__identity &&
+           refcount_dec_and_test(&tctx->identity->count))
+               kfree(tctx->identity);
+       if (req->work.identity != &tctx->__identity &&
+           refcount_dec_and_test(&req->work.identity->count))
                kfree(req->work.identity);
 
        req->work.identity = id;
@@ -1295,22 +1313,6 @@ static bool io_grab_identity(struct io_kiocb *req)
                        return false;
                req->work.flags |= IO_WQ_WORK_FSIZE;
        }
-
-       if (!(req->work.flags & IO_WQ_WORK_FILES) &&
-           (def->work_flags & IO_WQ_WORK_FILES) &&
-           !(req->flags & REQ_F_NO_FILE_TABLE)) {
-               if (id->files != current->files ||
-                   id->nsproxy != current->nsproxy)
-                       return false;
-               atomic_inc(&id->files->count);
-               get_nsproxy(id->nsproxy);
-               req->flags |= REQ_F_INFLIGHT;
-
-               spin_lock_irq(&ctx->inflight_lock);
-               list_add(&req->inflight_entry, &ctx->inflight_list);
-               spin_unlock_irq(&ctx->inflight_lock);
-               req->work.flags |= IO_WQ_WORK_FILES;
-       }
 #ifdef CONFIG_BLK_CGROUP
        if (!(req->work.flags & IO_WQ_WORK_BLKCG) &&
            (def->work_flags & IO_WQ_WORK_BLKCG)) {
@@ -1352,6 +1354,21 @@ static bool io_grab_identity(struct io_kiocb *req)
                }
                spin_unlock(&current->fs->lock);
        }
+       if (!(req->work.flags & IO_WQ_WORK_FILES) &&
+           (def->work_flags & IO_WQ_WORK_FILES) &&
+           !(req->flags & REQ_F_NO_FILE_TABLE)) {
+               if (id->files != current->files ||
+                   id->nsproxy != current->nsproxy)
+                       return false;
+               atomic_inc(&id->files->count);
+               get_nsproxy(id->nsproxy);
+               req->flags |= REQ_F_INFLIGHT;
+
+               spin_lock_irq(&ctx->inflight_lock);
+               list_add(&req->inflight_entry, &ctx->inflight_list);
+               spin_unlock_irq(&ctx->inflight_lock);
+               req->work.flags |= IO_WQ_WORK_FILES;
+       }
 
        return true;
 }
@@ -1365,6 +1382,9 @@ static void io_prep_async_work(struct io_kiocb *req)
        io_req_init_async(req);
        id = req->work.identity;
 
+       if (req->flags & REQ_F_FORCE_ASYNC)
+               req->work.flags |= IO_WQ_WORK_CONCURRENT;
+
        if (req->flags & REQ_F_ISREG) {
                if (def->hash_reg_file || (ctx->flags & IORING_SETUP_IOPOLL))
                        io_wq_hash_work(&req->work, file_inode(req->file));
@@ -1574,14 +1594,29 @@ static void io_cqring_mark_overflow(struct io_ring_ctx *ctx)
        }
 }
 
-static inline bool io_match_files(struct io_kiocb *req,
-                                      struct files_struct *files)
+static inline bool __io_match_files(struct io_kiocb *req,
+                                   struct files_struct *files)
+{
+       return ((req->flags & REQ_F_WORK_INITIALIZED) &&
+               (req->work.flags & IO_WQ_WORK_FILES)) &&
+               req->work.identity->files == files;
+}
+
+static bool io_match_files(struct io_kiocb *req,
+                          struct files_struct *files)
 {
+       struct io_kiocb *link;
+
        if (!files)
                return true;
-       if ((req->flags & REQ_F_WORK_INITIALIZED) &&
-           (req->work.flags & IO_WQ_WORK_FILES))
-               return req->work.identity->files == files;
+       if (__io_match_files(req, files))
+               return true;
+       if (req->flags & REQ_F_LINK_HEAD) {
+               list_for_each_entry(link, &req->link_list, link_list) {
+                       if (__io_match_files(link, files))
+                               return true;
+               }
+       }
        return false;
 }
 
@@ -1665,7 +1700,8 @@ static void __io_cqring_fill_event(struct io_kiocb *req, long res, long cflags)
                WRITE_ONCE(cqe->user_data, req->user_data);
                WRITE_ONCE(cqe->res, res);
                WRITE_ONCE(cqe->flags, cflags);
-       } else if (ctx->cq_overflow_flushed || req->task->io_uring->in_idle) {
+       } else if (ctx->cq_overflow_flushed ||
+                  atomic_read(&req->task->io_uring->in_idle)) {
                /*
                 * If we're in ring overflow flush mode, or in task cancel mode,
                 * then we cannot store the request for later flushing, we need
@@ -1835,7 +1871,7 @@ static void __io_free_req(struct io_kiocb *req)
        io_dismantle_req(req);
 
        percpu_counter_dec(&tctx->inflight);
-       if (tctx->in_idle)
+       if (atomic_read(&tctx->in_idle))
                wake_up(&tctx->wait);
        put_task_struct(req->task);
 
@@ -1846,59 +1882,39 @@ static void __io_free_req(struct io_kiocb *req)
        percpu_ref_put(&ctx->refs);
 }
 
-static bool io_link_cancel_timeout(struct io_kiocb *req)
+static void io_kill_linked_timeout(struct io_kiocb *req)
 {
-       struct io_timeout_data *io = req->async_data;
        struct io_ring_ctx *ctx = req->ctx;
-       int ret;
-
-       ret = hrtimer_try_to_cancel(&io->timer);
-       if (ret != -1) {
-               io_cqring_fill_event(req, -ECANCELED);
-               io_commit_cqring(ctx);
-               req->flags &= ~REQ_F_LINK_HEAD;
-               io_put_req_deferred(req, 1);
-               return true;
-       }
-
-       return false;
-}
-
-static bool __io_kill_linked_timeout(struct io_kiocb *req)
-{
        struct io_kiocb *link;
-       bool wake_ev;
+       bool cancelled = false;
+       unsigned long flags;
 
-       if (list_empty(&req->link_list))
-               return false;
-       link = list_first_entry(&req->link_list, struct io_kiocb, link_list);
-       if (link->opcode != IORING_OP_LINK_TIMEOUT)
-               return false;
+       spin_lock_irqsave(&ctx->completion_lock, flags);
+       link = list_first_entry_or_null(&req->link_list, struct io_kiocb,
+                                       link_list);
        /*
         * Can happen if a linked timeout fired and link had been like
         * req -> link t-out -> link t-out [-> ...]
         */
-       if (!(link->flags & REQ_F_LTIMEOUT_ACTIVE))
-               return false;
+       if (link && (link->flags & REQ_F_LTIMEOUT_ACTIVE)) {
+               struct io_timeout_data *io = link->async_data;
+               int ret;
 
-       list_del_init(&link->link_list);
-       wake_ev = io_link_cancel_timeout(link);
+               list_del_init(&link->link_list);
+               ret = hrtimer_try_to_cancel(&io->timer);
+               if (ret != -1) {
+                       io_cqring_fill_event(link, -ECANCELED);
+                       io_commit_cqring(ctx);
+                       cancelled = true;
+               }
+       }
        req->flags &= ~REQ_F_LINK_TIMEOUT;
-       return wake_ev;
-}
-
-static void io_kill_linked_timeout(struct io_kiocb *req)
-{
-       struct io_ring_ctx *ctx = req->ctx;
-       unsigned long flags;
-       bool wake_ev;
-
-       spin_lock_irqsave(&ctx->completion_lock, flags);
-       wake_ev = __io_kill_linked_timeout(req);
        spin_unlock_irqrestore(&ctx->completion_lock, flags);
 
-       if (wake_ev)
+       if (cancelled) {
                io_cqring_ev_posted(ctx);
+               io_put_req(link);
+       }
 }
 
 static struct io_kiocb *io_req_link_next(struct io_kiocb *req)
@@ -2562,7 +2578,6 @@ static bool io_resubmit_prep(struct io_kiocb *req, int error)
        }
 end_req:
        req_set_fail_links(req);
-       io_req_complete(req, ret);
        return false;
 }
 #endif
@@ -3177,7 +3192,7 @@ static void io_req_map_rw(struct io_kiocb *req, const struct iovec *iovec,
        rw->free_iovec = iovec;
        rw->bytes_done = 0;
        /* can only be fixed buffers, no need to do anything */
-       if (iter->type == ITER_BVEC)
+       if (iov_iter_is_bvec(iter))
                return;
        if (!iovec) {
                unsigned iov_off = 0;
@@ -3532,8 +3547,7 @@ static int io_write(struct io_kiocb *req, bool force_nonblock,
         * we return to userspace.
         */
        if (req->flags & REQ_F_ISREG) {
-               __sb_start_write(file_inode(req->file)->i_sb,
-                                       SB_FREEZE_WRITE, true);
+               sb_start_write(file_inode(req->file)->i_sb);
                __sb_writers_release(file_inode(req->file)->i_sb,
                                        SB_FREEZE_WRITE);
        }
@@ -3781,6 +3795,7 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
                return ret;
        }
        req->open.nofile = rlimit(RLIMIT_NOFILE);
+       req->open.ignore_nonblock = false;
        req->flags |= REQ_F_NEED_CLEANUP;
        return 0;
 }
@@ -3824,7 +3839,7 @@ static int io_openat2(struct io_kiocb *req, bool force_nonblock)
        struct file *file;
        int ret;
 
-       if (force_nonblock)
+       if (force_nonblock && !req->open.ignore_nonblock)
                return -EAGAIN;
 
        ret = build_open_flags(&req->open.how, &op);
@@ -3839,6 +3854,21 @@ static int io_openat2(struct io_kiocb *req, bool force_nonblock)
        if (IS_ERR(file)) {
                put_unused_fd(ret);
                ret = PTR_ERR(file);
+               /*
+                * A work-around to ensure that /proc/self works that way
+                * that it should - if we get -EOPNOTSUPP back, then assume
+                * that proc_self_get_link() failed us because we're in async
+                * context. We should be safe to retry this from the task
+                * itself with force_nonblock == false set, as it should not
+                * block on lookup. Would be nice to know this upfront and
+                * avoid the async dance, but doesn't seem feasible.
+                */
+               if (ret == -EOPNOTSUPP && io_wq_current_is_worker()) {
+                       req->open.ignore_nonblock = true;
+                       refcount_inc(&req->refs);
+                       io_req_task_queue(req);
+                       return 0;
+               }
        } else {
                fsnotify_open(file);
                fd_install(ret, file);
@@ -4469,7 +4499,8 @@ static int __io_compat_recvmsg_copy_hdr(struct io_kiocb *req,
                        return -EFAULT;
                if (clen < 0)
                        return -EINVAL;
-               sr->len = iomsg->iov[0].iov_len;
+               sr->len = clen;
+               iomsg->iov[0].iov_len = clen;
                iomsg->iov = NULL;
        } else {
                ret = __import_iovec(READ, (struct iovec __user *)uiov, len,
@@ -4977,8 +5008,10 @@ static int io_poll_double_wake(struct wait_queue_entry *wait, unsigned mode,
                /* make sure double remove sees this as being gone */
                wait->private = NULL;
                spin_unlock(&poll->head->lock);
-               if (!done)
-                       __io_async_wake(req, poll, mask, io_poll_task_func);
+               if (!done) {
+                       /* use wait func handler, so it matches the rq type */
+                       poll->wait.func(&poll->wait, mode, sync, key);
+               }
        }
        refcount_dec(&req->refs);
        return 1;
@@ -6180,7 +6213,6 @@ static struct io_kiocb *io_prep_linked_timeout(struct io_kiocb *req)
 static void __io_queue_sqe(struct io_kiocb *req, struct io_comp_state *cs)
 {
        struct io_kiocb *linked_timeout;
-       struct io_kiocb *nxt;
        const struct cred *old_creds = NULL;
        int ret;
 
@@ -6206,7 +6238,6 @@ again:
         */
        if (ret == -EAGAIN && !(req->flags & REQ_F_NOWAIT)) {
                if (!io_arm_poll_handler(req)) {
-punt:
                        /*
                         * Queued up for async execution, worker will release
                         * submit reference when the iocb is actually submitted.
@@ -6216,33 +6247,25 @@ punt:
 
                if (linked_timeout)
                        io_queue_linked_timeout(linked_timeout);
-               goto exit;
-       }
+       } else if (likely(!ret)) {
+               /* drop submission reference */
+               req = io_put_req_find_next(req);
+               if (linked_timeout)
+                       io_queue_linked_timeout(linked_timeout);
 
-       if (unlikely(ret)) {
+               if (req) {
+                       if (!(req->flags & REQ_F_FORCE_ASYNC))
+                               goto again;
+                       io_queue_async_work(req);
+               }
+       } else {
                /* un-prep timeout, so it'll be killed as any other linked */
                req->flags &= ~REQ_F_LINK_TIMEOUT;
                req_set_fail_links(req);
                io_put_req(req);
                io_req_complete(req, ret);
-               goto exit;
        }
 
-       /* drop submission reference */
-       nxt = io_put_req_find_next(req);
-       if (linked_timeout)
-               io_queue_linked_timeout(linked_timeout);
-
-       if (nxt) {
-               req = nxt;
-
-               if (req->flags & REQ_F_FORCE_ASYNC) {
-                       linked_timeout = NULL;
-                       goto punt;
-               }
-               goto again;
-       }
-exit:
        if (old_creds)
                revert_creds(old_creds);
 }
@@ -6266,13 +6289,6 @@ fail_req:
                        if (unlikely(ret))
                                goto fail_req;
                }
-
-               /*
-                * Never try inline submit of IOSQE_ASYNC is set, go straight
-                * to async execution.
-                */
-               io_req_init_async(req);
-               req->work.flags |= IO_WQ_WORK_CONCURRENT;
                io_queue_async_work(req);
        } else {
                if (sqe) {
@@ -6958,9 +6974,7 @@ static int io_sqe_files_unregister(struct io_ring_ctx *ctx)
                return -ENXIO;
 
        spin_lock(&data->lock);
-       if (!list_empty(&data->ref_list))
-               ref_node = list_first_entry(&data->ref_list,
-                               struct fixed_file_ref_node, node);
+       ref_node = data->node;
        spin_unlock(&data->lock);
        if (ref_node)
                percpu_ref_kill(&ref_node->refs);
@@ -7309,10 +7323,6 @@ static void __io_file_put_work(struct fixed_file_ref_node *ref_node)
                kfree(pfile);
        }
 
-       spin_lock(&file_data->lock);
-       list_del(&ref_node->node);
-       spin_unlock(&file_data->lock);
-
        percpu_ref_exit(&ref_node->refs);
        kfree(ref_node);
        percpu_ref_put(&file_data->refs);
@@ -7339,17 +7349,32 @@ static void io_file_put_work(struct work_struct *work)
 static void io_file_data_ref_zero(struct percpu_ref *ref)
 {
        struct fixed_file_ref_node *ref_node;
+       struct fixed_file_data *data;
        struct io_ring_ctx *ctx;
-       bool first_add;
+       bool first_add = false;
        int delay = HZ;
 
        ref_node = container_of(ref, struct fixed_file_ref_node, refs);
-       ctx = ref_node->file_data->ctx;
+       data = ref_node->file_data;
+       ctx = data->ctx;
+
+       spin_lock(&data->lock);
+       ref_node->done = true;
 
-       if (percpu_ref_is_dying(&ctx->file_data->refs))
+       while (!list_empty(&data->ref_list)) {
+               ref_node = list_first_entry(&data->ref_list,
+                                       struct fixed_file_ref_node, node);
+               /* recycle ref nodes in order */
+               if (!ref_node->done)
+                       break;
+               list_del(&ref_node->node);
+               first_add |= llist_add(&ref_node->llist, &ctx->file_put_llist);
+       }
+       spin_unlock(&data->lock);
+
+       if (percpu_ref_is_dying(&data->refs))
                delay = 0;
 
-       first_add = llist_add(&ref_node->llist, &ctx->file_put_llist);
        if (!delay)
                mod_delayed_work(system_wq, &ctx->file_put_work, 0);
        else if (first_add)
@@ -7373,6 +7398,7 @@ static struct fixed_file_ref_node *alloc_fixed_file_ref_node(
        INIT_LIST_HEAD(&ref_node->node);
        INIT_LIST_HEAD(&ref_node->file_list);
        ref_node->file_data = ctx->file_data;
+       ref_node->done = false;
        return ref_node;
 }
 
@@ -7468,7 +7494,7 @@ static int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg,
 
        file_data->node = ref_node;
        spin_lock(&file_data->lock);
-       list_add(&ref_node->node, &file_data->ref_list);
+       list_add_tail(&ref_node->node, &file_data->ref_list);
        spin_unlock(&file_data->lock);
        percpu_ref_get(&file_data->refs);
        return ret;
@@ -7627,7 +7653,7 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx,
        if (needs_switch) {
                percpu_ref_kill(&data->node->refs);
                spin_lock(&data->lock);
-               list_add(&ref_node->node, &data->ref_list);
+               list_add_tail(&ref_node->node, &data->ref_list);
                data->node = ref_node;
                spin_unlock(&data->lock);
                percpu_ref_get(&ctx->file_data->refs);
@@ -7727,7 +7753,8 @@ static int io_uring_alloc_task_context(struct task_struct *task)
        xa_init(&tctx->xa);
        init_waitqueue_head(&tctx->wait);
        tctx->last = NULL;
-       tctx->in_idle = 0;
+       atomic_set(&tctx->in_idle, 0);
+       tctx->sqpoll = false;
        io_init_identity(&tctx->__identity);
        tctx->identity = &tctx->__identity;
        task->io_uring = tctx;
@@ -8420,22 +8447,6 @@ static bool io_match_link(struct io_kiocb *preq, struct io_kiocb *req)
        return false;
 }
 
-static bool io_match_link_files(struct io_kiocb *req,
-                               struct files_struct *files)
-{
-       struct io_kiocb *link;
-
-       if (io_match_files(req, files))
-               return true;
-       if (req->flags & REQ_F_LINK_HEAD) {
-               list_for_each_entry(link, &req->link_list, link_list) {
-                       if (io_match_files(link, files))
-                               return true;
-               }
-       }
-       return false;
-}
-
 /*
  * We're looking to cancel 'req' because it's holding on to our files, but
  * 'req' could be a link to another request. See if it is, and cancel that
@@ -8485,7 +8496,21 @@ static bool io_timeout_remove_link(struct io_ring_ctx *ctx,
 
 static bool io_cancel_link_cb(struct io_wq_work *work, void *data)
 {
-       return io_match_link(container_of(work, struct io_kiocb, work), data);
+       struct io_kiocb *req = container_of(work, struct io_kiocb, work);
+       bool ret;
+
+       if (req->flags & REQ_F_LINK_TIMEOUT) {
+               unsigned long flags;
+               struct io_ring_ctx *ctx = req->ctx;
+
+               /* protect against races with linked timeouts */
+               spin_lock_irqsave(&ctx->completion_lock, flags);
+               ret = io_match_link(req, data);
+               spin_unlock_irqrestore(&ctx->completion_lock, flags);
+       } else {
+               ret = io_match_link(req, data);
+       }
+       return ret;
 }
 
 static void io_attempt_cancel(struct io_ring_ctx *ctx, struct io_kiocb *req)
@@ -8511,6 +8536,7 @@ static void io_attempt_cancel(struct io_ring_ctx *ctx, struct io_kiocb *req)
 }
 
 static void io_cancel_defer_files(struct io_ring_ctx *ctx,
+                                 struct task_struct *task,
                                  struct files_struct *files)
 {
        struct io_defer_entry *de = NULL;
@@ -8518,7 +8544,8 @@ static void io_cancel_defer_files(struct io_ring_ctx *ctx,
 
        spin_lock_irq(&ctx->completion_lock);
        list_for_each_entry_reverse(de, &ctx->defer_list, list) {
-               if (io_match_link_files(de->req, files)) {
+               if (io_task_match(de->req, task) &&
+                   io_match_files(de->req, files)) {
                        list_cut_position(&list, &ctx->defer_list, &de->list);
                        break;
                }
@@ -8544,7 +8571,6 @@ static bool io_uring_cancel_files(struct io_ring_ctx *ctx,
        if (list_empty_careful(&ctx->inflight_list))
                return false;
 
-       io_cancel_defer_files(ctx, files);
        /* cancel all at once, should be faster than doing it one by one*/
        io_wq_cancel_cb(ctx->io_wq, io_wq_files_match, files, true);
 
@@ -8630,8 +8656,16 @@ static void io_uring_cancel_task_requests(struct io_ring_ctx *ctx,
 {
        struct task_struct *task = current;
 
-       if ((ctx->flags & IORING_SETUP_SQPOLL) && ctx->sq_data)
+       if ((ctx->flags & IORING_SETUP_SQPOLL) && ctx->sq_data) {
                task = ctx->sq_data->thread;
+               atomic_inc(&task->io_uring->in_idle);
+               io_sq_thread_park(ctx->sq_data);
+       }
+
+       if (files)
+               io_cancel_defer_files(ctx, NULL, files);
+       else
+               io_cancel_defer_files(ctx, task, NULL);
 
        io_cqring_overflow_flush(ctx, true, task, files);
 
@@ -8639,12 +8673,23 @@ static void io_uring_cancel_task_requests(struct io_ring_ctx *ctx,
                io_run_task_work();
                cond_resched();
        }
+
+       if ((ctx->flags & IORING_SETUP_SQPOLL) && ctx->sq_data) {
+               atomic_dec(&task->io_uring->in_idle);
+               /*
+                * If the files that are going away are the ones in the thread
+                * identity, clear them out.
+                */
+               if (task->io_uring->identity->files == files)
+                       task->io_uring->identity->files = NULL;
+               io_sq_thread_unpark(ctx->sq_data);
+       }
 }
 
 /*
  * Note that this task has used io_uring. We use it for cancelation purposes.
  */
-static int io_uring_add_task_file(struct file *file)
+static int io_uring_add_task_file(struct io_ring_ctx *ctx, struct file *file)
 {
        struct io_uring_task *tctx = current->io_uring;
 
@@ -8666,6 +8711,14 @@ static int io_uring_add_task_file(struct file *file)
                tctx->last = file;
        }
 
+       /*
+        * This is race safe in that the task itself is doing this, hence it
+        * cannot be going through the exit/cancel paths at the same time.
+        * This cannot be modified while exit/cancel is running.
+        */
+       if (!tctx->sqpoll && (ctx->flags & IORING_SETUP_SQPOLL))
+               tctx->sqpoll = true;
+
        return 0;
 }
 
@@ -8707,7 +8760,7 @@ void __io_uring_files_cancel(struct files_struct *files)
        unsigned long index;
 
        /* make sure overflow events are dropped */
-       tctx->in_idle = true;
+       atomic_inc(&tctx->in_idle);
 
        xa_for_each(&tctx->xa, index, file) {
                struct io_ring_ctx *ctx = file->private_data;
@@ -8716,6 +8769,35 @@ void __io_uring_files_cancel(struct files_struct *files)
                if (files)
                        io_uring_del_task_file(file);
        }
+
+       atomic_dec(&tctx->in_idle);
+}
+
+static s64 tctx_inflight(struct io_uring_task *tctx)
+{
+       unsigned long index;
+       struct file *file;
+       s64 inflight;
+
+       inflight = percpu_counter_sum(&tctx->inflight);
+       if (!tctx->sqpoll)
+               return inflight;
+
+       /*
+        * If we have SQPOLL rings, then we need to iterate and find them, and
+        * add the pending count for those.
+        */
+       xa_for_each(&tctx->xa, index, file) {
+               struct io_ring_ctx *ctx = file->private_data;
+
+               if (ctx->flags & IORING_SETUP_SQPOLL) {
+                       struct io_uring_task *__tctx = ctx->sqo_task->io_uring;
+
+                       inflight += percpu_counter_sum(&__tctx->inflight);
+               }
+       }
+
+       return inflight;
 }
 
 /*
@@ -8729,11 +8811,11 @@ void __io_uring_task_cancel(void)
        s64 inflight;
 
        /* make sure overflow events are dropped */
-       tctx->in_idle = true;
+       atomic_inc(&tctx->in_idle);
 
        do {
                /* read completions before cancelations */
-               inflight = percpu_counter_sum(&tctx->inflight);
+               inflight = tctx_inflight(tctx);
                if (!inflight)
                        break;
                __io_uring_files_cancel(NULL);
@@ -8744,13 +8826,13 @@ void __io_uring_task_cancel(void)
                 * If we've seen completions, retry. This avoids a race where
                 * a completion comes in before we did prepare_to_wait().
                 */
-               if (inflight != percpu_counter_sum(&tctx->inflight))
+               if (inflight != tctx_inflight(tctx))
                        continue;
                schedule();
        } while (1);
 
        finish_wait(&tctx->wait, &wait);
-       tctx->in_idle = false;
+       atomic_dec(&tctx->in_idle);
 }
 
 static int io_uring_flush(struct file *file, void *data)
@@ -8895,7 +8977,7 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
                        io_sqpoll_wait_sq(ctx);
                submitted = to_submit;
        } else if (to_submit) {
-               ret = io_uring_add_task_file(f.file);
+               ret = io_uring_add_task_file(ctx, f.file);
                if (unlikely(ret))
                        goto out;
                mutex_lock(&ctx->uring_lock);
@@ -8932,7 +9014,8 @@ out_fput:
 #ifdef CONFIG_PROC_FS
 static int io_uring_show_cred(int id, void *p, void *data)
 {
-       const struct cred *cred = p;
+       struct io_identity *iod = p;
+       const struct cred *cred = iod->creds;
        struct seq_file *m = data;
        struct user_namespace *uns = seq_user_ns(m);
        struct group_info *gi;
@@ -9124,7 +9207,7 @@ err_fd:
 #if defined(CONFIG_UNIX)
        ctx->ring_sock->file = file;
 #endif
-       if (unlikely(io_uring_add_task_file(file))) {
+       if (unlikely(io_uring_add_task_file(ctx, file))) {
                file = ERR_PTR(-ENOMEM);
                goto err_fd;
        }
@@ -9169,7 +9252,7 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p,
                 * to a power-of-two, if it isn't already. We do NOT impose
                 * any cq vs sq ring sizing.
                 */
-               if (p->cq_entries < p->sq_entries)
+               if (!p->cq_entries)
                        return -EINVAL;
                if (p->cq_entries > IORING_MAX_CQ_ENTRIES) {
                        if (!(p->flags & IORING_SETUP_CLAMP))
@@ -9177,6 +9260,8 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p,
                        p->cq_entries = IORING_MAX_CQ_ENTRIES;
                }
                p->cq_entries = roundup_pow_of_two(p->cq_entries);
+               if (p->cq_entries < p->sq_entries)
+                       return -EINVAL;
        } else {
                p->cq_entries = 2 * p->sq_entries;
        }
index 8180061b9e16488a4535ccb93b0d0db54d1dafd6..10cc7979ce38070a7d6b16f3eca9d52804626e97 100644 (file)
@@ -1374,6 +1374,7 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc,
        WARN_ON_ONCE(!wpc->ioend && !list_empty(&submit_list));
        WARN_ON_ONCE(!PageLocked(page));
        WARN_ON_ONCE(PageWriteback(page));
+       WARN_ON_ONCE(PageDirty(page));
 
        /*
         * We cannot cancel the ioend directly here on error.  We may have
@@ -1382,33 +1383,22 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc,
         * appropriately.
         */
        if (unlikely(error)) {
+               /*
+                * Let the filesystem know what portion of the current page
+                * failed to map. If the page wasn't been added to ioend, it
+                * won't be affected by I/O completion and we must unlock it
+                * now.
+                */
+               if (wpc->ops->discard_page)
+                       wpc->ops->discard_page(page, file_offset);
                if (!count) {
-                       /*
-                        * If the current page hasn't been added to ioend, it
-                        * won't be affected by I/O completions and we must
-                        * discard and unlock it right here.
-                        */
-                       if (wpc->ops->discard_page)
-                               wpc->ops->discard_page(page);
                        ClearPageUptodate(page);
                        unlock_page(page);
                        goto done;
                }
-
-               /*
-                * If the page was not fully cleaned, we need to ensure that the
-                * higher layers come back to it correctly.  That means we need
-                * to keep the page dirty, and for WB_SYNC_ALL writeback we need
-                * to ensure the PAGECACHE_TAG_TOWRITE index mark is not removed
-                * so another attempt to write this page in this writeback sweep
-                * will be made.
-                */
-               set_page_writeback_keepwrite(page);
-       } else {
-               clear_page_dirty_for_io(page);
-               set_page_writeback(page);
        }
 
+       set_page_writeback(page);
        unlock_page(page);
 
        /*
index 1558cf22ef8a8ba7197a0df2f557b3cb0d088576..ee9660e9671cbc403a5f1e25439b298a10d1915b 100644 (file)
@@ -22,7 +22,7 @@ struct SU_ER_s {
        __u8 len_des;
        __u8 len_src;
        __u8 ext_ver;
-       __u8 data[0];
+       __u8 data[];
 } __attribute__ ((packed));
 
 struct RR_RR_s {
@@ -44,7 +44,7 @@ struct RR_PN_s {
 struct SL_component {
        __u8 flags;
        __u8 len;
-       __u8 text[0];
+       __u8 text[];
 } __attribute__ ((packed));
 
 struct RR_SL_s {
@@ -54,7 +54,7 @@ struct RR_SL_s {
 
 struct RR_NM_s {
        __u8 flags;
-       char name[0];
+       char name[];
 } __attribute__ ((packed));
 
 struct RR_CL_s {
@@ -71,7 +71,7 @@ struct stamp {
 
 struct RR_TF_s {
        __u8 flags;
-       struct stamp times[0];  /* Variable number of these beasts */
+       struct stamp times[];   /* Variable number of these beasts */
 } __attribute__ ((packed));
 
 /* Linux-specific extension for transparent decompression */
index 263f02ad8ebf8bd7787316f78b570985b439db75..472932b9e6bca9d6a56fe1bb7c52e9bc35ef0f3d 100644 (file)
@@ -106,6 +106,8 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
  * for a checkpoint to free up some space in the log.
  */
 void __jbd2_log_wait_for_space(journal_t *journal)
+__acquires(&journal->j_state_lock)
+__releases(&journal->j_state_lock)
 {
        int nblocks, space_left;
        /* assert_spin_locked(&journal->j_state_lock); */
index fa688e163a80a20983fca89e0d9a982c442564c5..b121d7d434c67510a58c7d962610abc68f3423cc 100644 (file)
@@ -450,6 +450,15 @@ void jbd2_journal_commit_transaction(journal_t *journal)
                schedule();
                write_lock(&journal->j_state_lock);
                finish_wait(&journal->j_fc_wait, &wait);
+               /*
+                * TODO: by blocking fast commits here, we are increasing
+                * fsync() latency slightly. Strictly speaking, we don't need
+                * to block fast commits until the transaction enters T_FLUSH
+                * state. So an optimization is possible where we block new fast
+                * commits here and wait for existing ones to complete
+                * just before we enter T_FLUSH. That way, the existing fast
+                * commits and this full commit can proceed parallely.
+                */
        }
        write_unlock(&journal->j_state_lock);
 
@@ -801,7 +810,7 @@ start_journal_io:
                if (first_block < journal->j_tail)
                        freed += journal->j_last - journal->j_first;
                /* Update tail only if we free significant amount of space */
-               if (freed < journal->j_maxlen / 4)
+               if (freed < jbd2_journal_get_max_txn_bufs(journal))
                        update_tail = 0;
        }
        J_ASSERT(commit_transaction->t_state == T_COMMIT);
index 0c7c42bd530f5ebfca2b4fc68a7060673e4f51d0..188f79d76988174c764c7dd41a9a163efd4245fb 100644 (file)
@@ -566,12 +566,14 @@ static int __jbd2_journal_force_commit(journal_t *journal)
 }
 
 /**
- * Force and wait upon a commit if the calling process is not within
- * transaction.  This is used for forcing out undo-protected data which contains
- * bitmaps, when the fs is running out of space.
+ * jbd2_journal_force_commit_nested - Force and wait upon a commit if the
+ * calling process is not within transaction.
  *
  * @journal: journal to force
  * Returns true if progress was made.
+ *
+ * This is used for forcing out undo-protected data which contains
+ * bitmaps, when the fs is running out of space.
  */
 int jbd2_journal_force_commit_nested(journal_t *journal)
 {
@@ -582,7 +584,7 @@ int jbd2_journal_force_commit_nested(journal_t *journal)
 }
 
 /**
- * int journal_force_commit() - force any uncommitted transactions
+ * jbd2_journal_force_commit() - force any uncommitted transactions
  * @journal: journal to force
  *
  * Caller want unconditional commit. We can only force the running transaction
@@ -727,6 +729,8 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
  */
 int jbd2_fc_begin_commit(journal_t *journal, tid_t tid)
 {
+       if (unlikely(is_journal_aborted(journal)))
+               return -EIO;
        /*
         * Fast commits only allowed if at least one full commit has
         * been processed.
@@ -734,10 +738,12 @@ int jbd2_fc_begin_commit(journal_t *journal, tid_t tid)
        if (!journal->j_stats.ts_tid)
                return -EINVAL;
 
-       if (tid <= journal->j_commit_sequence)
+       write_lock(&journal->j_state_lock);
+       if (tid <= journal->j_commit_sequence) {
+               write_unlock(&journal->j_state_lock);
                return -EALREADY;
+       }
 
-       write_lock(&journal->j_state_lock);
        if (journal->j_flags & JBD2_FULL_COMMIT_ONGOING ||
            (journal->j_flags & JBD2_FAST_COMMIT_ONGOING)) {
                DEFINE_WAIT(wait);
@@ -777,13 +783,19 @@ static int __jbd2_fc_end_commit(journal_t *journal, tid_t tid, bool fallback)
 
 int jbd2_fc_end_commit(journal_t *journal)
 {
-       return __jbd2_fc_end_commit(journal, 0, 0);
+       return __jbd2_fc_end_commit(journal, 0, false);
 }
 EXPORT_SYMBOL(jbd2_fc_end_commit);
 
-int jbd2_fc_end_commit_fallback(journal_t *journal, tid_t tid)
+int jbd2_fc_end_commit_fallback(journal_t *journal)
 {
-       return __jbd2_fc_end_commit(journal, tid, 1);
+       tid_t tid;
+
+       read_lock(&journal->j_state_lock);
+       tid = journal->j_running_transaction ?
+               journal->j_running_transaction->t_tid : 0;
+       read_unlock(&journal->j_state_lock);
+       return __jbd2_fc_end_commit(journal, tid, true);
 }
 EXPORT_SYMBOL(jbd2_fc_end_commit_fallback);
 
@@ -865,7 +877,6 @@ int jbd2_fc_get_buf(journal_t *journal, struct buffer_head **bh_out)
        int fc_off;
 
        *bh_out = NULL;
-       write_lock(&journal->j_state_lock);
 
        if (journal->j_fc_off + journal->j_fc_first < journal->j_fc_last) {
                fc_off = journal->j_fc_off;
@@ -874,7 +885,6 @@ int jbd2_fc_get_buf(journal_t *journal, struct buffer_head **bh_out)
        } else {
                ret = -EINVAL;
        }
-       write_unlock(&journal->j_state_lock);
 
        if (ret)
                return ret;
@@ -887,11 +897,7 @@ int jbd2_fc_get_buf(journal_t *journal, struct buffer_head **bh_out)
        if (!bh)
                return -ENOMEM;
 
-       lock_buffer(bh);
 
-       clear_buffer_uptodate(bh);
-       set_buffer_dirty(bh);
-       unlock_buffer(bh);
        journal->j_fc_wbuf[fc_off] = bh;
 
        *bh_out = bh;
@@ -909,9 +915,7 @@ int jbd2_fc_wait_bufs(journal_t *journal, int num_blks)
        struct buffer_head *bh;
        int i, j_fc_off;
 
-       read_lock(&journal->j_state_lock);
        j_fc_off = journal->j_fc_off;
-       read_unlock(&journal->j_state_lock);
 
        /*
         * Wait in reverse order to minimize chances of us being woken up before
@@ -939,9 +943,7 @@ int jbd2_fc_release_bufs(journal_t *journal)
        struct buffer_head *bh;
        int i, j_fc_off;
 
-       read_lock(&journal->j_state_lock);
        j_fc_off = journal->j_fc_off;
-       read_unlock(&journal->j_state_lock);
 
        /*
         * Wait in reverse order to minimize chances of us being woken up before
@@ -1348,23 +1350,16 @@ static journal_t *journal_init_common(struct block_device *bdev,
        journal->j_dev = bdev;
        journal->j_fs_dev = fs_dev;
        journal->j_blk_offset = start;
-       journal->j_maxlen = len;
+       journal->j_total_len = len;
        /* We need enough buffers to write out full descriptor block. */
        n = journal->j_blocksize / jbd2_min_tag_size();
        journal->j_wbufsize = n;
+       journal->j_fc_wbuf = NULL;
        journal->j_wbuf = kmalloc_array(n, sizeof(struct buffer_head *),
                                        GFP_KERNEL);
        if (!journal->j_wbuf)
                goto err_cleanup;
 
-       if (journal->j_fc_wbufsize > 0) {
-               journal->j_fc_wbuf = kmalloc_array(journal->j_fc_wbufsize,
-                                       sizeof(struct buffer_head *),
-                                       GFP_KERNEL);
-               if (!journal->j_fc_wbuf)
-                       goto err_cleanup;
-       }
-
        bh = getblk_unmovable(journal->j_dev, start, journal->j_blocksize);
        if (!bh) {
                pr_err("%s: Cannot get buffer for journal superblock\n",
@@ -1378,23 +1373,11 @@ static journal_t *journal_init_common(struct block_device *bdev,
 
 err_cleanup:
        kfree(journal->j_wbuf);
-       kfree(journal->j_fc_wbuf);
        jbd2_journal_destroy_revoke(journal);
        kfree(journal);
        return NULL;
 }
 
-int jbd2_fc_init(journal_t *journal, int num_fc_blks)
-{
-       journal->j_fc_wbufsize = num_fc_blks;
-       journal->j_fc_wbuf = kmalloc_array(journal->j_fc_wbufsize,
-                               sizeof(struct buffer_head *), GFP_KERNEL);
-       if (!journal->j_fc_wbuf)
-               return -ENOMEM;
-       return 0;
-}
-EXPORT_SYMBOL(jbd2_fc_init);
-
 /* jbd2_journal_init_dev and jbd2_journal_init_inode:
  *
  * Create a journal structure assigned some fixed set of disk blocks to
@@ -1512,16 +1495,7 @@ static int journal_reset(journal_t *journal)
        }
 
        journal->j_first = first;
-
-       if (jbd2_has_feature_fast_commit(journal) &&
-           journal->j_fc_wbufsize > 0) {
-               journal->j_fc_last = last;
-               journal->j_last = last - journal->j_fc_wbufsize;
-               journal->j_fc_first = journal->j_last + 1;
-               journal->j_fc_off = 0;
-       } else {
-               journal->j_last = last;
-       }
+       journal->j_last = last;
 
        journal->j_head = journal->j_first;
        journal->j_tail = journal->j_first;
@@ -1531,7 +1505,14 @@ static int journal_reset(journal_t *journal)
        journal->j_commit_sequence = journal->j_transaction_sequence - 1;
        journal->j_commit_request = journal->j_commit_sequence;
 
-       journal->j_max_transaction_buffers = journal->j_maxlen / 4;
+       journal->j_max_transaction_buffers = jbd2_journal_get_max_txn_bufs(journal);
+
+       /*
+        * Now that journal recovery is done, turn fast commits off here. This
+        * way, if fast commit was enabled before the crash but if now FS has
+        * disabled it, we don't enable fast commits.
+        */
+       jbd2_clear_feature_fast_commit(journal);
 
        /*
         * As a special case, if the on-disk copy is already marked as needing
@@ -1792,15 +1773,15 @@ static int journal_get_superblock(journal_t *journal)
                goto out;
        }
 
-       if (be32_to_cpu(sb->s_maxlen) < journal->j_maxlen)
-               journal->j_maxlen = be32_to_cpu(sb->s_maxlen);
-       else if (be32_to_cpu(sb->s_maxlen) > journal->j_maxlen) {
+       if (be32_to_cpu(sb->s_maxlen) < journal->j_total_len)
+               journal->j_total_len = be32_to_cpu(sb->s_maxlen);
+       else if (be32_to_cpu(sb->s_maxlen) > journal->j_total_len) {
                printk(KERN_WARNING "JBD2: journal file too short\n");
                goto out;
        }
 
        if (be32_to_cpu(sb->s_first) == 0 ||
-           be32_to_cpu(sb->s_first) >= journal->j_maxlen) {
+           be32_to_cpu(sb->s_first) >= journal->j_total_len) {
                printk(KERN_WARNING
                        "JBD2: Invalid start block of journal: %u\n",
                        be32_to_cpu(sb->s_first));
@@ -1872,6 +1853,7 @@ static int load_superblock(journal_t *journal)
 {
        int err;
        journal_superblock_t *sb;
+       int num_fc_blocks;
 
        err = journal_get_superblock(journal);
        if (err)
@@ -1883,15 +1865,17 @@ static int load_superblock(journal_t *journal)
        journal->j_tail = be32_to_cpu(sb->s_start);
        journal->j_first = be32_to_cpu(sb->s_first);
        journal->j_errno = be32_to_cpu(sb->s_errno);
+       journal->j_last = be32_to_cpu(sb->s_maxlen);
 
-       if (jbd2_has_feature_fast_commit(journal) &&
-           journal->j_fc_wbufsize > 0) {
+       if (jbd2_has_feature_fast_commit(journal)) {
                journal->j_fc_last = be32_to_cpu(sb->s_maxlen);
-               journal->j_last = journal->j_fc_last - journal->j_fc_wbufsize;
+               num_fc_blocks = be32_to_cpu(sb->s_num_fc_blks);
+               if (!num_fc_blocks)
+                       num_fc_blocks = JBD2_MIN_FC_BLOCKS;
+               if (journal->j_last - num_fc_blocks >= JBD2_MIN_JOURNAL_BLOCKS)
+                       journal->j_last = journal->j_fc_last - num_fc_blocks;
                journal->j_fc_first = journal->j_last + 1;
                journal->j_fc_off = 0;
-       } else {
-               journal->j_last = be32_to_cpu(sb->s_maxlen);
        }
 
        return 0;
@@ -1899,7 +1883,7 @@ static int load_superblock(journal_t *journal)
 
 
 /**
- * int jbd2_journal_load() - Read journal from disk.
+ * jbd2_journal_load() - Read journal from disk.
  * @journal: Journal to act on.
  *
  * Given a journal_t structure which tells us which disk blocks contain
@@ -1954,9 +1938,6 @@ int jbd2_journal_load(journal_t *journal)
         */
        journal->j_flags &= ~JBD2_ABORT;
 
-       if (journal->j_fc_wbufsize > 0)
-               jbd2_journal_set_features(journal, 0, 0,
-                                         JBD2_FEATURE_INCOMPAT_FAST_COMMIT);
        /* OK, we've finished with the dynamic journal bits:
         * reinitialise the dynamic contents of the superblock in memory
         * and reset them on disk. */
@@ -1972,7 +1953,7 @@ recovery_error:
 }
 
 /**
- * void jbd2_journal_destroy() - Release a journal_t structure.
+ * jbd2_journal_destroy() - Release a journal_t structure.
  * @journal: Journal to act on.
  *
  * Release a journal_t structure once it is no longer in use by the
@@ -2040,8 +2021,7 @@ int jbd2_journal_destroy(journal_t *journal)
                jbd2_journal_destroy_revoke(journal);
        if (journal->j_chksum_driver)
                crypto_free_shash(journal->j_chksum_driver);
-       if (journal->j_fc_wbufsize > 0)
-               kfree(journal->j_fc_wbuf);
+       kfree(journal->j_fc_wbuf);
        kfree(journal->j_wbuf);
        kfree(journal);
 
@@ -2050,7 +2030,7 @@ int jbd2_journal_destroy(journal_t *journal)
 
 
 /**
- *int jbd2_journal_check_used_features() - Check if features specified are used.
+ * jbd2_journal_check_used_features() - Check if features specified are used.
  * @journal: Journal to check.
  * @compat: bitmask of compatible features
  * @ro: bitmask of features that force read-only mount
@@ -2085,7 +2065,7 @@ int jbd2_journal_check_used_features(journal_t *journal, unsigned long compat,
 }
 
 /**
- * int jbd2_journal_check_available_features() - Check feature set in journalling layer
+ * jbd2_journal_check_available_features() - Check feature set in journalling layer
  * @journal: Journal to check.
  * @compat: bitmask of compatible features
  * @ro: bitmask of features that force read-only mount
@@ -2116,8 +2096,39 @@ int jbd2_journal_check_available_features(journal_t *journal, unsigned long comp
        return 0;
 }
 
+static int
+jbd2_journal_initialize_fast_commit(journal_t *journal)
+{
+       journal_superblock_t *sb = journal->j_superblock;
+       unsigned long long num_fc_blks;
+
+       num_fc_blks = be32_to_cpu(sb->s_num_fc_blks);
+       if (num_fc_blks == 0)
+               num_fc_blks = JBD2_MIN_FC_BLOCKS;
+       if (journal->j_last - num_fc_blks < JBD2_MIN_JOURNAL_BLOCKS)
+               return -ENOSPC;
+
+       /* Are we called twice? */
+       WARN_ON(journal->j_fc_wbuf != NULL);
+       journal->j_fc_wbuf = kmalloc_array(num_fc_blks,
+                               sizeof(struct buffer_head *), GFP_KERNEL);
+       if (!journal->j_fc_wbuf)
+               return -ENOMEM;
+
+       journal->j_fc_wbufsize = num_fc_blks;
+       journal->j_fc_last = journal->j_last;
+       journal->j_last = journal->j_fc_last - num_fc_blks;
+       journal->j_fc_first = journal->j_last + 1;
+       journal->j_fc_off = 0;
+       journal->j_free = journal->j_last - journal->j_first;
+       journal->j_max_transaction_buffers =
+               jbd2_journal_get_max_txn_bufs(journal);
+
+       return 0;
+}
+
 /**
- * int jbd2_journal_set_features() - Mark a given journal feature in the superblock
+ * jbd2_journal_set_features() - Mark a given journal feature in the superblock
  * @journal: Journal to act on.
  * @compat: bitmask of compatible features
  * @ro: bitmask of features that force read-only mount
@@ -2159,6 +2170,13 @@ int jbd2_journal_set_features(journal_t *journal, unsigned long compat,
 
        sb = journal->j_superblock;
 
+       if (incompat & JBD2_FEATURE_INCOMPAT_FAST_COMMIT) {
+               if (jbd2_journal_initialize_fast_commit(journal)) {
+                       pr_err("JBD2: Cannot enable fast commits.\n");
+                       return 0;
+               }
+       }
+
        /* Load the checksum driver if necessary */
        if ((journal->j_chksum_driver == NULL) &&
            INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) {
@@ -2201,7 +2219,7 @@ int jbd2_journal_set_features(journal_t *journal, unsigned long compat,
 }
 
 /*
- * jbd2_journal_clear_features () - Clear a given journal feature in the
+ * jbd2_journal_clear_features() - Clear a given journal feature in the
  *                                 superblock
  * @journal: Journal to act on.
  * @compat: bitmask of compatible features
@@ -2230,7 +2248,7 @@ void jbd2_journal_clear_features(journal_t *journal, unsigned long compat,
 EXPORT_SYMBOL(jbd2_journal_clear_features);
 
 /**
- * int jbd2_journal_flush () - Flush journal
+ * jbd2_journal_flush() - Flush journal
  * @journal: Journal to act on.
  *
  * Flush all data for a given journal to disk and empty the journal.
@@ -2305,7 +2323,7 @@ out:
 }
 
 /**
- * int jbd2_journal_wipe() - Wipe journal contents
+ * jbd2_journal_wipe() - Wipe journal contents
  * @journal: Journal to act on.
  * @write: flag (see below)
  *
@@ -2346,7 +2364,7 @@ int jbd2_journal_wipe(journal_t *journal, int write)
 }
 
 /**
- * void jbd2_journal_abort () - Shutdown the journal immediately.
+ * jbd2_journal_abort () - Shutdown the journal immediately.
  * @journal: the journal to shutdown.
  * @errno:   an error number to record in the journal indicating
  *           the reason for the shutdown.
@@ -2437,7 +2455,7 @@ void jbd2_journal_abort(journal_t *journal, int errno)
 }
 
 /**
- * int jbd2_journal_errno () - returns the journal's error state.
+ * jbd2_journal_errno() - returns the journal's error state.
  * @journal: journal to examine.
  *
  * This is the errno number set with jbd2_journal_abort(), the last
@@ -2461,7 +2479,7 @@ int jbd2_journal_errno(journal_t *journal)
 }
 
 /**
- * int jbd2_journal_clear_err () - clears the journal's error state
+ * jbd2_journal_clear_err() - clears the journal's error state
  * @journal: journal to act on.
  *
  * An error must be cleared or acked to take a FS out of readonly
@@ -2481,7 +2499,7 @@ int jbd2_journal_clear_err(journal_t *journal)
 }
 
 /**
- * void jbd2_journal_ack_err() - Ack journal err.
+ * jbd2_journal_ack_err() - Ack journal err.
  * @journal: journal to act on.
  *
  * An error must be cleared or acked to take a FS out of readonly
index eb2606133cd8689055f697c7fc0f4902e09a66f6..dc0694fcfcd123d647ecac6e78cb59e04f800a7a 100644 (file)
@@ -74,8 +74,8 @@ static int do_readahead(journal_t *journal, unsigned int start)
 
        /* Do up to 128K of readahead */
        max = start + (128 * 1024 / journal->j_blocksize);
-       if (max > journal->j_maxlen)
-               max = journal->j_maxlen;
+       if (max > journal->j_total_len)
+               max = journal->j_total_len;
 
        /* Do the readahead itself.  We'll submit MAXBUF buffer_heads at
         * a time to the block device IO layer. */
@@ -134,7 +134,7 @@ static int jread(struct buffer_head **bhp, journal_t *journal,
 
        *bhp = NULL;
 
-       if (offset >= journal->j_maxlen) {
+       if (offset >= journal->j_total_len) {
                printk(KERN_ERR "JBD2: corrupted journal superblock\n");
                return -EFSCORRUPTED;
        }
index 43985738aa860d91d1ecda400783cc99eae6ed2b..9396666b731452e523798b2e96b9a94e9d802825 100644 (file)
@@ -195,8 +195,10 @@ static void wait_transaction_switching(journal_t *journal)
        DEFINE_WAIT(wait);
 
        if (WARN_ON(!journal->j_running_transaction ||
-                   journal->j_running_transaction->t_state != T_SWITCH))
+                   journal->j_running_transaction->t_state != T_SWITCH)) {
+               read_unlock(&journal->j_state_lock);
                return;
+       }
        prepare_to_wait(&journal->j_wait_transaction_locked, &wait,
                        TASK_UNINTERRUPTIBLE);
        read_unlock(&journal->j_state_lock);
@@ -517,7 +519,7 @@ EXPORT_SYMBOL(jbd2__journal_start);
 
 
 /**
- * handle_t *jbd2_journal_start() - Obtain a new handle.
+ * jbd2_journal_start() - Obtain a new handle.
  * @journal: Journal to start transaction on.
  * @nblocks: number of block buffer we might modify
  *
@@ -564,7 +566,7 @@ void jbd2_journal_free_reserved(handle_t *handle)
 EXPORT_SYMBOL(jbd2_journal_free_reserved);
 
 /**
- * int jbd2_journal_start_reserved() - start reserved handle
+ * jbd2_journal_start_reserved() - start reserved handle
  * @handle: handle to start
  * @type: for handle statistics
  * @line_no: for handle statistics
@@ -618,7 +620,7 @@ int jbd2_journal_start_reserved(handle_t *handle, unsigned int type,
 EXPORT_SYMBOL(jbd2_journal_start_reserved);
 
 /**
- * int jbd2_journal_extend() - extend buffer credits.
+ * jbd2_journal_extend() - extend buffer credits.
  * @handle:  handle to 'extend'
  * @nblocks: nr blocks to try to extend by.
  * @revoke_records: number of revoke records to try to extend by.
@@ -743,7 +745,7 @@ static void stop_this_handle(handle_t *handle)
 }
 
 /**
- * int jbd2_journal_restart() - restart a handle .
+ * jbd2__journal_restart() - restart a handle .
  * @handle:  handle to restart
  * @nblocks: nr credits requested
  * @revoke_records: number of revoke record credits requested
@@ -813,7 +815,7 @@ int jbd2_journal_restart(handle_t *handle, int nblocks)
 EXPORT_SYMBOL(jbd2_journal_restart);
 
 /**
- * void jbd2_journal_lock_updates () - establish a transaction barrier.
+ * jbd2_journal_lock_updates () - establish a transaction barrier.
  * @journal:  Journal to establish a barrier on.
  *
  * This locks out any further updates from being started, and blocks
@@ -872,7 +874,7 @@ void jbd2_journal_lock_updates(journal_t *journal)
 }
 
 /**
- * void jbd2_journal_unlock_updates (journal_t* journal) - release barrier
+ * jbd2_journal_unlock_updates () - release barrier
  * @journal:  Journal to release the barrier on.
  *
  * Release a transaction barrier obtained with jbd2_journal_lock_updates().
@@ -1180,7 +1182,8 @@ out:
 }
 
 /**
- * int jbd2_journal_get_write_access() - notify intent to modify a buffer for metadata (not data) update.
+ * jbd2_journal_get_write_access() - notify intent to modify a buffer
+ *                                  for metadata (not data) update.
  * @handle: transaction to add buffer modifications to
  * @bh:     bh to be used for metadata writes
  *
@@ -1224,7 +1227,7 @@ int jbd2_journal_get_write_access(handle_t *handle, struct buffer_head *bh)
  * unlocked buffer beforehand. */
 
 /**
- * int jbd2_journal_get_create_access () - notify intent to use newly created bh
+ * jbd2_journal_get_create_access () - notify intent to use newly created bh
  * @handle: transaction to new buffer to
  * @bh: new buffer.
  *
@@ -1304,7 +1307,7 @@ out:
 }
 
 /**
- * int jbd2_journal_get_undo_access() -  Notify intent to modify metadata with
+ * jbd2_journal_get_undo_access() -  Notify intent to modify metadata with
  *     non-rewindable consequences
  * @handle: transaction
  * @bh: buffer to undo
@@ -1381,7 +1384,7 @@ out:
 }
 
 /**
- * void jbd2_journal_set_triggers() - Add triggers for commit writeout
+ * jbd2_journal_set_triggers() - Add triggers for commit writeout
  * @bh: buffer to trigger on
  * @type: struct jbd2_buffer_trigger_type containing the trigger(s).
  *
@@ -1423,7 +1426,7 @@ void jbd2_buffer_abort_trigger(struct journal_head *jh,
 }
 
 /**
- * int jbd2_journal_dirty_metadata() -  mark a buffer as containing dirty metadata
+ * jbd2_journal_dirty_metadata() -  mark a buffer as containing dirty metadata
  * @handle: transaction to add buffer to.
  * @bh: buffer to mark
  *
@@ -1591,7 +1594,7 @@ out:
 }
 
 /**
- * void jbd2_journal_forget() - bforget() for potentially-journaled buffers.
+ * jbd2_journal_forget() - bforget() for potentially-journaled buffers.
  * @handle: transaction handle
  * @bh:     bh to 'forget'
  *
@@ -1760,7 +1763,7 @@ drop:
 }
 
 /**
- * int jbd2_journal_stop() - complete a transaction
+ * jbd2_journal_stop() - complete a transaction
  * @handle: transaction to complete.
  *
  * All done for a particular handle.
@@ -2078,7 +2081,7 @@ out:
 }
 
 /**
- * int jbd2_journal_try_to_free_buffers() - try to free page buffers.
+ * jbd2_journal_try_to_free_buffers() - try to free page buffers.
  * @journal: journal for operation
  * @page: to try and free
  *
@@ -2409,7 +2412,7 @@ zap_buffer_unlocked:
 }
 
 /**
- * void jbd2_journal_invalidatepage()
+ * jbd2_journal_invalidatepage()
  * @journal: journal to use for flush...
  * @page:    page to flush
  * @offset:  start of the range to invalidate
index fc34361c1489e9eaf5e46fbac653a5edd47becb0..7124c2e8df2f5a5f49451ef8d3bb84c7b8712e80 100644 (file)
@@ -959,7 +959,7 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
                          size_t len, loff_t *ppos)
 {
        struct simple_attr *attr;
-       u64 val;
+       unsigned long long val;
        size_t size;
        ssize_t ret;
 
@@ -977,7 +977,9 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
                goto out;
 
        attr->set_buf[size] = '\0';
-       val = simple_strtoll(attr->set_buf, NULL, 0);
+       ret = kstrtoull(attr->set_buf, 0, &val);
+       if (ret)
+               goto out;
        ret = attr->set(attr->data, val);
        if (ret == 0)
                ret = len; /* on success, claim we got the whole input */
index cb52db9a0cfb7006d2fb31d7c309d615b88a7bbe..4e011adaf967026b63399683475ebf808196f2a4 100644 (file)
@@ -955,7 +955,6 @@ out:
 
 static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence)
 {
-       struct inode *inode = file_inode(filp);
        struct nfs_open_dir_context *dir_ctx = filp->private_data;
 
        dfprintk(FILE, "NFS: llseek dir(%pD2, %lld, %d)\n",
@@ -967,15 +966,15 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence)
        case SEEK_SET:
                if (offset < 0)
                        return -EINVAL;
-               inode_lock(inode);
+               spin_lock(&filp->f_lock);
                break;
        case SEEK_CUR:
                if (offset == 0)
                        return filp->f_pos;
-               inode_lock(inode);
+               spin_lock(&filp->f_lock);
                offset += filp->f_pos;
                if (offset < 0) {
-                       inode_unlock(inode);
+                       spin_unlock(&filp->f_lock);
                        return -EINVAL;
                }
        }
@@ -987,7 +986,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence)
                        dir_ctx->dir_cookie = 0;
                dir_ctx->duped = 0;
        }
-       inode_unlock(inode);
+       spin_unlock(&filp->f_lock);
        return offset;
 }
 
@@ -998,13 +997,9 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence)
 static int nfs_fsync_dir(struct file *filp, loff_t start, loff_t end,
                         int datasync)
 {
-       struct inode *inode = file_inode(filp);
-
        dfprintk(FILE, "NFS: fsync dir(%pD2) datasync %d\n", filp, datasync);
 
-       inode_lock(inode);
-       nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
-       inode_unlock(inode);
+       nfs_inc_stats(file_inode(filp), NFSIOS_VFSFSYNC);
        return 0;
 }
 
index b51424ff8159ef301eaad02d141f964939fedb17..6c2ce799150f49d18e67c0240d9a4375e0567497 100644 (file)
@@ -1047,8 +1047,10 @@ out4:
 
 void nfs4_xattr_cache_exit(void)
 {
+       unregister_shrinker(&nfs4_xattr_large_entry_shrinker);
        unregister_shrinker(&nfs4_xattr_entry_shrinker);
        unregister_shrinker(&nfs4_xattr_cache_shrinker);
+       list_lru_destroy(&nfs4_xattr_large_entry_lru);
        list_lru_destroy(&nfs4_xattr_entry_lru);
        list_lru_destroy(&nfs4_xattr_cache_lru);
        kmem_cache_destroy(nfs4_xattr_cache_cachep);
index 0dc31ad2362e110ebc011d6aabfb5bb2e44e601d..6e060a88f98c2ed1df387d6ad7288d4cf89575d3 100644 (file)
                                 1 + nfs4_xattr_name_maxsz + 1)
 #define decode_setxattr_maxsz   (op_decode_hdr_maxsz + decode_change_info_maxsz)
 #define encode_listxattrs_maxsz  (op_encode_hdr_maxsz + 2 + 1)
-#define decode_listxattrs_maxsz  (op_decode_hdr_maxsz + 2 + 1 + 1)
+#define decode_listxattrs_maxsz  (op_decode_hdr_maxsz + 2 + 1 + 1 + 1)
 #define encode_removexattr_maxsz (op_encode_hdr_maxsz + 1 + \
                                  nfs4_xattr_name_maxsz)
 #define decode_removexattr_maxsz (op_decode_hdr_maxsz + \
@@ -531,7 +531,7 @@ static void encode_listxattrs(struct xdr_stream *xdr,
 {
        __be32 *p;
 
-       encode_op_hdr(xdr, OP_LISTXATTRS, decode_listxattrs_maxsz + 1, hdr);
+       encode_op_hdr(xdr, OP_LISTXATTRS, decode_listxattrs_maxsz, hdr);
 
        p = reserve_space(xdr, 12);
        if (unlikely(!p))
index 8d32788056022d71f030d1d90dff7c4c09ff9447..fa148308822cc8d4b02ee29772c0ba40843f1fe2 100644 (file)
 #define NFS_ROOT               "/tftpboot/%s"
 
 /* Default NFSROOT mount options. */
+#if defined(CONFIG_NFS_V2)
 #define NFS_DEF_OPTIONS                "vers=2,tcp,rsize=4096,wsize=4096"
+#elif defined(CONFIG_NFS_V3)
+#define NFS_DEF_OPTIONS                "vers=3,tcp,rsize=4096,wsize=4096"
+#else
+#define NFS_DEF_OPTIONS                "vers=4,tcp,rsize=4096,wsize=4096"
+#endif
 
 /* Parameters passed from the kernel command line */
 static char nfs_root_parms[NFS_MAXPATHLEN + 1] __initdata = "";
index 14468613d150b5fbc7e8161617a17e56f5f5834d..a633044b0dc1f7b9022a627c0debca97df9e9e4d 100644 (file)
@@ -316,10 +316,6 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp)
        fh_copy(&resp->dirfh, &argp->fh);
        fh_init(&resp->fh, NFS3_FHSIZE);
 
-       if (argp->ftype == 0 || argp->ftype >= NF3BAD) {
-               resp->status = nfserr_inval;
-               goto out;
-       }
        if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
                rdev = MKDEV(argp->major, argp->minor);
                if (MAJOR(rdev) != argp->major ||
@@ -328,7 +324,7 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp)
                        goto out;
                }
        } else if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO) {
-               resp->status = nfserr_inval;
+               resp->status = nfserr_badtype;
                goto out;
        }
 
index 9c23b6acf234de2a33642c351590ccfe60841a27..2277f83da25012a54acafc93248351ebfc225b53 100644 (file)
@@ -1114,6 +1114,7 @@ nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, __be32 *p)
 {
        struct nfsd3_pathconfres *resp = rqstp->rq_resp;
 
+       *p++ = resp->status;
        *p++ = xdr_zero;        /* no post_op_attr */
 
        if (resp->status == 0) {
index ad2fa1a8e7add59d74c9618cdd03abb180c0e62c..e83b21778816d957d33f277c6a7a048ad71b82d6 100644 (file)
@@ -1299,7 +1299,7 @@ nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct nfsd_file *src,
                        struct nfsd_file *dst)
 {
        nfs42_ssc_close(src->nf_file);
-       nfsd_file_put(src);
+       /* 'src' is freed by nfsd4_do_async_copy */
        nfsd_file_put(dst);
        mntput(ss_mnt);
 }
@@ -1486,6 +1486,7 @@ do_callback:
        cb_copy = kzalloc(sizeof(struct nfsd4_copy), GFP_KERNEL);
        if (!cb_copy)
                goto out;
+       refcount_set(&cb_copy->refcount, 1);
        memcpy(&cb_copy->cp_res, &copy->cp_res, sizeof(copy->cp_res));
        cb_copy->cp_clp = copy->cp_clp;
        cb_copy->nfserr = copy->nfserr;
index a960ec3a569ad319ea2f1a44c81fa05e9c1c5a0a..8d3ad5ef292587085132a1fa7751f30daeb89efc 100644 (file)
@@ -178,6 +178,7 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
        struct inode *inode = d_inode(dentry);
        struct dentry *parent;
        bool parent_watched = dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED;
+       bool parent_needed, parent_interested;
        __u32 p_mask;
        struct inode *p_inode = NULL;
        struct name_snapshot name;
@@ -193,7 +194,8 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
                return 0;
 
        parent = NULL;
-       if (!parent_watched && !fsnotify_event_needs_parent(inode, mnt, mask))
+       parent_needed = fsnotify_event_needs_parent(inode, mnt, mask);
+       if (!parent_watched && !parent_needed)
                goto notify;
 
        /* Does parent inode care about events on children? */
@@ -205,17 +207,17 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
 
        /*
         * Include parent/name in notification either if some notification
-        * groups require parent info (!parent_watched case) or the parent is
-        * interested in this event.
+        * groups require parent info or the parent is interested in this event.
         */
-       if (!parent_watched || (mask & p_mask & ALL_FSNOTIFY_EVENTS)) {
+       parent_interested = mask & p_mask & ALL_FSNOTIFY_EVENTS;
+       if (parent_needed || parent_interested) {
                /* When notifying parent, child should be passed as data */
                WARN_ON_ONCE(inode != fsnotify_data_inode(data, data_type));
 
                /* Notify both parent and child with child name info */
                take_dentry_name_snapshot(&name, dentry);
                file_name = &name.name;
-               if (parent_watched)
+               if (parent_interested)
                        mask |= FS_EVENT_ON_CHILD;
        }
 
index b9a9d69dde7ec4ba2b0271cd5da43e14d648bb0f..db52e843002a0914a42d576263f72318397b3a3b 100644 (file)
@@ -877,7 +877,7 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty)
                goto done;
        }
 
-       trace_ocfs2_journal_init_maxlen(j_journal->j_maxlen);
+       trace_ocfs2_journal_init_maxlen(j_journal->j_total_len);
 
        *dirty = (le32_to_cpu(di->id1.journal1.ij_flags) &
                  OCFS2_JOURNAL_DIRTY_FL);
index 1d91dd1e8711c1c26a6295bb4aa07d2e2318d21f..2febc76e9de70100f8fbc94f44bddaf5a3e3223a 100644 (file)
@@ -1713,6 +1713,7 @@ static void ocfs2_inode_init_once(void *data)
 
        oi->ip_blkno = 0ULL;
        oi->ip_clusters = 0;
+       oi->ip_next_orphan = NULL;
 
        ocfs2_resv_init_once(&oi->ip_la_data_resv);
 
index 0f707003dda53fb722f6566b2d3a9eb69c386d9a..b362523a9829ace0f2df2a93a2bd2e8e47a7bdd5 100644 (file)
@@ -1049,6 +1049,8 @@ static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count,
                oom_adj = (task->signal->oom_score_adj * -OOM_DISABLE) /
                          OOM_SCORE_ADJ_MAX;
        put_task_struct(task);
+       if (oom_adj > OOM_ADJUST_MAX)
+               oom_adj = OOM_ADJUST_MAX;
        len = snprintf(buffer, sizeof(buffer), "%d\n", oom_adj);
        return simple_read_from_buffer(buf, count, ppos, buffer, len);
 }
index d0989a443c77dfe2b99207697a391bef17032c92..419760fd77bdd82b1fa1d1565bbcc8d13ae25967 100644 (file)
@@ -19,7 +19,7 @@ static int cpuinfo_open(struct inode *inode, struct file *file)
 static const struct proc_ops cpuinfo_proc_ops = {
        .proc_flags     = PROC_ENTRY_PERMANENT,
        .proc_open      = cpuinfo_open,
-       .proc_read      = seq_read,
+       .proc_read_iter = seq_read_iter,
        .proc_lseek     = seq_lseek,
        .proc_release   = seq_release,
 };
index 2f9fa179194d72739f9f76c9270068bbe89308a0..b84663252adda0abadc9656bb56e441f4f65d570 100644 (file)
@@ -590,7 +590,7 @@ static int proc_seq_release(struct inode *inode, struct file *file)
 static const struct proc_ops proc_seq_ops = {
        /* not permanent -- can call into arbitrary seq_operations */
        .proc_open      = proc_seq_open,
-       .proc_read      = seq_read,
+       .proc_read_iter = seq_read_iter,
        .proc_lseek     = seq_lseek,
        .proc_release   = proc_seq_release,
 };
@@ -621,7 +621,7 @@ static int proc_single_open(struct inode *inode, struct file *file)
 static const struct proc_ops proc_single_ops = {
        /* not permanent -- can call into arbitrary ->single_show */
        .proc_open      = proc_single_open,
-       .proc_read      = seq_read,
+       .proc_read_iter = seq_read_iter,
        .proc_lseek     = seq_lseek,
        .proc_release   = single_release,
 };
index 58c075e2a452d63cdc230d9aeb134a2426550ef4..bde6b6f69852d2206dbd6703b8f033ff9c6591b2 100644 (file)
@@ -597,6 +597,7 @@ static const struct file_operations proc_iter_file_ops = {
        .llseek         = proc_reg_llseek,
        .read_iter      = proc_reg_read_iter,
        .write          = proc_reg_write,
+       .splice_read    = generic_file_splice_read,
        .poll           = proc_reg_poll,
        .unlocked_ioctl = proc_reg_unlocked_ioctl,
        .mmap           = proc_reg_mmap,
@@ -622,6 +623,7 @@ static const struct file_operations proc_reg_file_ops_compat = {
 static const struct file_operations proc_iter_file_ops_compat = {
        .llseek         = proc_reg_llseek,
        .read_iter      = proc_reg_read_iter,
+       .splice_read    = generic_file_splice_read,
        .write          = proc_reg_write,
        .poll           = proc_reg_poll,
        .unlocked_ioctl = proc_reg_unlocked_ioctl,
index 72cd69bcaf4ad977ab7c3b134d91cfaaeee34026..cc71ce3466dc0b6bf527808f1d52f0d384565522 100644 (file)
@@ -16,6 +16,13 @@ static const char *proc_self_get_link(struct dentry *dentry,
        pid_t tgid = task_tgid_nr_ns(current, ns);
        char *name;
 
+       /*
+        * Not currently supported. Once we can inherit all of struct pid,
+        * we can allow this.
+        */
+       if (current->flags & PF_KTHREAD)
+               return ERR_PTR(-EOPNOTSUPP);
+
        if (!tgid)
                return ERR_PTR(-ENOENT);
        /* max length of unsigned int in decimal + NULL term */
index 46b3293015fe61f78dd14781aaabc4b9491da1a2..4695b6de315129aa62daba5131b82a3346bfd25a 100644 (file)
@@ -226,7 +226,7 @@ static int stat_open(struct inode *inode, struct file *file)
 static const struct proc_ops stat_proc_ops = {
        .proc_flags     = PROC_ENTRY_PERMANENT,
        .proc_open      = stat_open,
-       .proc_read      = seq_read,
+       .proc_read_iter = seq_read_iter,
        .proc_lseek     = seq_lseek,
        .proc_release   = single_release,
 };
index 7aef49552d4c2d3a8c3789d51daae89b4d00f68e..ebfebdfe5c69a168840aad4bc5e8ccdd4d7e6dbe 100644 (file)
@@ -97,7 +97,7 @@ u64 select_estimate_accuracy(struct timespec64 *tv)
 struct poll_table_page {
        struct poll_table_page * next;
        struct poll_table_entry * entry;
-       struct poll_table_entry entries[0];
+       struct poll_table_entry entries[];
 };
 
 #define POLL_TABLE_FULL(table) \
@@ -836,7 +836,7 @@ SYSCALL_DEFINE1(old_select, struct sel_arg_struct __user *, arg)
 struct poll_list {
        struct poll_list *next;
        int len;
-       struct pollfd entries[0];
+       struct pollfd entries[];
 };
 
 #define POLLFD_PER_PAGE  ((PAGE_SIZE-sizeof(struct poll_list)) / sizeof(struct pollfd))
index 31219c1db17de3589770a683cfedd8ffd0c5095e..3b20e21604e74aaa65defc63b82f7fdbdb193953 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/mm.h>
 #include <linux/printk.h>
 #include <linux/string_helpers.h>
+#include <linux/uio.h>
 
 #include <linux/uaccess.h>
 #include <asm/page.h>
@@ -146,7 +147,28 @@ Eoverflow:
  */
 ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
 {
-       struct seq_file *m = file->private_data;
+       struct iovec iov = { .iov_base = buf, .iov_len = size};
+       struct kiocb kiocb;
+       struct iov_iter iter;
+       ssize_t ret;
+
+       init_sync_kiocb(&kiocb, file);
+       iov_iter_init(&iter, READ, &iov, 1, size);
+
+       kiocb.ki_pos = *ppos;
+       ret = seq_read_iter(&kiocb, &iter);
+       *ppos = kiocb.ki_pos;
+       return ret;
+}
+EXPORT_SYMBOL(seq_read);
+
+/*
+ * Ready-made ->f_op->read_iter()
+ */
+ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+       struct seq_file *m = iocb->ki_filp->private_data;
+       size_t size = iov_iter_count(iter);
        size_t copied = 0;
        size_t n;
        void *p;
@@ -158,14 +180,14 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
         * if request is to read from zero offset, reset iterator to first
         * record as it might have been already advanced by previous requests
         */
-       if (*ppos == 0) {
+       if (iocb->ki_pos == 0) {
                m->index = 0;
                m->count = 0;
        }
 
-       /* Don't assume *ppos is where we left it */
-       if (unlikely(*ppos != m->read_pos)) {
-               while ((err = traverse(m, *ppos)) == -EAGAIN)
+       /* Don't assume ki_pos is where we left it */
+       if (unlikely(iocb->ki_pos != m->read_pos)) {
+               while ((err = traverse(m, iocb->ki_pos)) == -EAGAIN)
                        ;
                if (err) {
                        /* With prejudice... */
@@ -174,7 +196,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
                        m->count = 0;
                        goto Done;
                } else {
-                       m->read_pos = *ppos;
+                       m->read_pos = iocb->ki_pos;
                }
        }
 
@@ -187,13 +209,11 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
        /* if not empty - flush it first */
        if (m->count) {
                n = min(m->count, size);
-               err = copy_to_user(buf, m->buf + m->from, n);
-               if (err)
+               if (copy_to_iter(m->buf + m->from, n, iter) != n)
                        goto Efault;
                m->count -= n;
                m->from += n;
                size -= n;
-               buf += n;
                copied += n;
                if (!size)
                        goto Done;
@@ -254,8 +274,7 @@ Fill:
        }
        m->op->stop(m, p);
        n = min(m->count, size);
-       err = copy_to_user(buf, m->buf, n);
-       if (err)
+       if (copy_to_iter(m->buf, n, iter) != n)
                goto Efault;
        copied += n;
        m->count -= n;
@@ -264,7 +283,7 @@ Done:
        if (!copied)
                copied = err;
        else {
-               *ppos += copied;
+               iocb->ki_pos += copied;
                m->read_pos += copied;
        }
        mutex_unlock(&m->lock);
@@ -276,7 +295,7 @@ Efault:
        err = -EFAULT;
        goto Done;
 }
-EXPORT_SYMBOL(seq_read);
+EXPORT_SYMBOL(seq_read_iter);
 
 /**
  *     seq_lseek -     ->llseek() method for sequential files.
index a51c2083cd6b181ad64f9fd8d7ef09b2bc7184bc..98bb0629ee108e87ff8876457b535442addf695e 100644 (file)
@@ -1631,55 +1631,6 @@ int super_setup_bdi(struct super_block *sb)
 }
 EXPORT_SYMBOL(super_setup_bdi);
 
-/*
- * This is an internal function, please use sb_end_{write,pagefault,intwrite}
- * instead.
- */
-void __sb_end_write(struct super_block *sb, int level)
-{
-       percpu_up_read(sb->s_writers.rw_sem + level-1);
-}
-EXPORT_SYMBOL(__sb_end_write);
-
-/*
- * This is an internal function, please use sb_start_{write,pagefault,intwrite}
- * instead.
- */
-int __sb_start_write(struct super_block *sb, int level, bool wait)
-{
-       bool force_trylock = false;
-       int ret = 1;
-
-#ifdef CONFIG_LOCKDEP
-       /*
-        * We want lockdep to tell us about possible deadlocks with freezing
-        * but it's it bit tricky to properly instrument it. Getting a freeze
-        * protection works as getting a read lock but there are subtle
-        * problems. XFS for example gets freeze protection on internal level
-        * twice in some cases, which is OK only because we already hold a
-        * freeze protection also on higher level. Due to these cases we have
-        * to use wait == F (trylock mode) which must not fail.
-        */
-       if (wait) {
-               int i;
-
-               for (i = 0; i < level - 1; i++)
-                       if (percpu_rwsem_is_held(sb->s_writers.rw_sem + i)) {
-                               force_trylock = true;
-                               break;
-                       }
-       }
-#endif
-       if (wait && !force_trylock)
-               percpu_down_read(sb->s_writers.rw_sem + level-1);
-       else
-               ret = percpu_down_read_trylock(sb->s_writers.rw_sem + level-1);
-
-       WARN_ON(force_trylock && !ret);
-       return ret;
-}
-EXPORT_SYMBOL(__sb_start_write);
-
 /**
  * sb_wait_write - wait until all writers to given file system finish
  * @sb: the super for which we wait
index 852b536551b53ef6948eee4308045b420390ff36..15640015be9d243320d5a383c48f08426eb7656f 100644 (file)
@@ -2467,6 +2467,7 @@ xfs_defer_agfl_block(
        new->xefi_startblock = XFS_AGB_TO_FSB(mp, agno, agbno);
        new->xefi_blockcount = 1;
        new->xefi_oinfo = *oinfo;
+       new->xefi_skip_discard = false;
 
        trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1);
 
index bb128db220acdf7297f0034e6421567e071945db..d6ef69ab1c67a5aa65333be1d56f2797ec784078 100644 (file)
@@ -515,7 +515,7 @@ xfs_attr_copy_value(
  *========================================================================*/
 
 /*
- * Query whether the requested number of additional bytes of extended
+ * Query whether the total requested number of attr fork bytes of extended
  * attribute space will be able to fit inline.
  *
  * Returns zero if not, else the di_forkoff fork offset to be used in the
@@ -535,6 +535,12 @@ xfs_attr_shortform_bytesfit(
        int                     maxforkoff;
        int                     offset;
 
+       /*
+        * Check if the new size could fit at all first:
+        */
+       if (bytes > XFS_LITINO(mp))
+               return 0;
+
        /* rounded down */
        offset = (XFS_LITINO(mp) - bytes) >> 3;
 
index e1bd484e55485411830ec5927f241c509b8ec0ab..6747e97a7949014b789981b5ef4a93648183c50c 100644 (file)
@@ -52,9 +52,9 @@ struct xfs_extent_free_item
 {
        xfs_fsblock_t           xefi_startblock;/* starting fs block number */
        xfs_extlen_t            xefi_blockcount;/* number of blocks in extent */
+       bool                    xefi_skip_discard;
        struct list_head        xefi_list;
        struct xfs_owner_info   xefi_oinfo;     /* extent owner */
-       bool                    xefi_skip_discard;
 };
 
 #define        XFS_BMAP_MAX_NMAP       4
index 340c83f76c806c2a4b2d549f8661935cd034e7e9..2668ebe02865f1539cb3187eede38a3086d9e382 100644 (file)
@@ -1514,7 +1514,7 @@ xfs_rmap_convert_shared(
         * record for our insertion point. This will also give us the record for
         * start block contiguity tests.
         */
-       error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
+       error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext,
                        &PREV, &i);
        if (error)
                goto done;
index 955302e7cdde94841c01123f83525d7e3e2c3dec..fed56d213a3f9c33acbc4502274e2680badd48ca 100644 (file)
@@ -113,6 +113,8 @@ xchk_bmap_get_rmap(
 
        if (info->whichfork == XFS_ATTR_FORK)
                rflags |= XFS_RMAP_ATTR_FORK;
+       if (irec->br_state == XFS_EXT_UNWRITTEN)
+               rflags |= XFS_RMAP_UNWRITTEN;
 
        /*
         * CoW staging extents are owned (on disk) by the refcountbt, so
@@ -216,13 +218,13 @@ xchk_bmap_xref_rmap(
         * which doesn't track unwritten state.
         */
        if (owner != XFS_RMAP_OWN_COW &&
-           irec->br_state == XFS_EXT_UNWRITTEN &&
-           !(rmap.rm_flags & XFS_RMAP_UNWRITTEN))
+           !!(irec->br_state == XFS_EXT_UNWRITTEN) !=
+           !!(rmap.rm_flags & XFS_RMAP_UNWRITTEN))
                xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
                                irec->br_startoff);
 
-       if (info->whichfork == XFS_ATTR_FORK &&
-           !(rmap.rm_flags & XFS_RMAP_ATTR_FORK))
+       if (!!(info->whichfork == XFS_ATTR_FORK) !=
+           !!(rmap.rm_flags & XFS_RMAP_ATTR_FORK))
                xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
                                irec->br_startoff);
        if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK)
index f52a7b8256f96c7d5eadd58ce034c90f0b61299b..debf392e051563a277e5d9edde7ef6e2be8de7b2 100644 (file)
@@ -452,32 +452,41 @@ xchk_btree_check_minrecs(
        int                     level,
        struct xfs_btree_block  *block)
 {
-       unsigned int            numrecs;
-       int                     ok_level;
-
-       numrecs = be16_to_cpu(block->bb_numrecs);
+       struct xfs_btree_cur    *cur = bs->cur;
+       unsigned int            root_level = cur->bc_nlevels - 1;
+       unsigned int            numrecs = be16_to_cpu(block->bb_numrecs);
 
        /* More records than minrecs means the block is ok. */
-       if (numrecs >= bs->cur->bc_ops->get_minrecs(bs->cur, level))
+       if (numrecs >= cur->bc_ops->get_minrecs(cur, level))
                return;
 
        /*
-        * Certain btree blocks /can/ have fewer than minrecs records.  Any
-        * level greater than or equal to the level of the highest dedicated
-        * btree block are allowed to violate this constraint.
-        *
-        * For a btree rooted in a block, the btree root can have fewer than
-        * minrecs records.  If the btree is rooted in an inode and does not
-        * store records in the root, the direct children of the root and the
-        * root itself can have fewer than minrecs records.
+        * For btrees rooted in the inode, it's possible that the root block
+        * contents spilled into a regular ondisk block because there wasn't
+        * enough space in the inode root.  The number of records in that
+        * child block might be less than the standard minrecs, but that's ok
+        * provided that there's only one direct child of the root.
         */
-       ok_level = bs->cur->bc_nlevels - 1;
-       if (bs->cur->bc_flags & XFS_BTREE_ROOT_IN_INODE)
-               ok_level--;
-       if (level >= ok_level)
+       if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) &&
+           level == cur->bc_nlevels - 2) {
+               struct xfs_btree_block  *root_block;
+               struct xfs_buf          *root_bp;
+               int                     root_maxrecs;
+
+               root_block = xfs_btree_get_block(cur, root_level, &root_bp);
+               root_maxrecs = cur->bc_ops->get_dmaxrecs(cur, root_level);
+               if (be16_to_cpu(root_block->bb_numrecs) != 1 ||
+                   numrecs <= root_maxrecs)
+                       xchk_btree_set_corrupt(bs->sc, cur, level);
                return;
+       }
 
-       xchk_btree_set_corrupt(bs->sc, bs->cur, level);
+       /*
+        * Otherwise, only the root level is allowed to have fewer than minrecs
+        * records or keyptrs.
+        */
+       if (level < root_level)
+               xchk_btree_set_corrupt(bs->sc, cur, level);
 }
 
 /*
index 7c432997edade4ee1356449e47aeb32cf38346ec..b045e95c2ea734a2f9e41e42cfbadd1d8495d4be 100644 (file)
@@ -558,14 +558,27 @@ xchk_directory_leaf1_bestfree(
        /* Check all the bestfree entries. */
        for (i = 0; i < bestcount; i++, bestp++) {
                best = be16_to_cpu(*bestp);
-               if (best == NULLDATAOFF)
-                       continue;
                error = xfs_dir3_data_read(sc->tp, sc->ip,
-                               i * args->geo->fsbcount, 0, &dbp);
+                               xfs_dir2_db_to_da(args->geo, i),
+                               XFS_DABUF_MAP_HOLE_OK,
+                               &dbp);
                if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk,
                                &error))
                        break;
-               xchk_directory_check_freesp(sc, lblk, dbp, best);
+
+               if (!dbp) {
+                       if (best != NULLDATAOFF) {
+                               xchk_fblock_set_corrupt(sc, XFS_DATA_FORK,
+                                               lblk);
+                               break;
+                       }
+                       continue;
+               }
+
+               if (best == NULLDATAOFF)
+                       xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
+               else
+                       xchk_directory_check_freesp(sc, lblk, dbp, best);
                xfs_trans_brelse(sc->tp, dbp);
                if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
                        break;
index 3aa85b64de3624be7d80e0d0518b9cbe20fac178..bb25ff1b770d12519a4419d907d1a63750787e0e 100644 (file)
@@ -121,8 +121,7 @@ xchk_inode_flags(
                goto bad;
 
        /* rt flags require rt device */
-       if ((flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT)) &&
-           !mp->m_rtdev_targp)
+       if ((flags & XFS_DIFLAG_REALTIME) && !mp->m_rtdev_targp)
                goto bad;
 
        /* new rt bitmap flag only valid for rbmino */
index beaeb6fa311973a5e9d59510526c0a098476d04e..dd672e6bbc75cfbcfe5dad7814530e9f26692aeb 100644 (file)
@@ -170,7 +170,6 @@ xchk_refcountbt_process_rmap_fragments(
         */
        INIT_LIST_HEAD(&worklist);
        rbno = NULLAGBLOCK;
-       nr = 1;
 
        /* Make sure the fragments actually /are/ in agbno order. */
        bno = 0;
@@ -184,15 +183,14 @@ xchk_refcountbt_process_rmap_fragments(
         * Find all the rmaps that start at or before the refc extent,
         * and put them on the worklist.
         */
+       nr = 0;
        list_for_each_entry_safe(frag, n, &refchk->fragments, list) {
-               if (frag->rm.rm_startblock > refchk->bno)
-                       goto done;
+               if (frag->rm.rm_startblock > refchk->bno || nr > target_nr)
+                       break;
                bno = frag->rm.rm_startblock + frag->rm.rm_blockcount;
                if (bno < rbno)
                        rbno = bno;
                list_move_tail(&frag->list, &worklist);
-               if (nr == target_nr)
-                       break;
                nr++;
        }
 
index 55d126d4e096e2e32a1dade11e271deb21078f11..4304c6416fbbc1e30b77d655bd3678c2815c5df9 100644 (file)
@@ -346,8 +346,8 @@ xfs_map_blocks(
        ssize_t                 count = i_blocksize(inode);
        xfs_fileoff_t           offset_fsb = XFS_B_TO_FSBT(mp, offset);
        xfs_fileoff_t           end_fsb = XFS_B_TO_FSB(mp, offset + count);
-       xfs_fileoff_t           cow_fsb = NULLFILEOFF;
-       int                     whichfork = XFS_DATA_FORK;
+       xfs_fileoff_t           cow_fsb;
+       int                     whichfork;
        struct xfs_bmbt_irec    imap;
        struct xfs_iext_cursor  icur;
        int                     retries = 0;
@@ -381,6 +381,8 @@ xfs_map_blocks(
         * landed in a hole and we skip the block.
         */
 retry:
+       cow_fsb = NULLFILEOFF;
+       whichfork = XFS_DATA_FORK;
        xfs_ilock(ip, XFS_ILOCK_SHARED);
        ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_BTREE ||
               (ip->i_df.if_flags & XFS_IFEXTENTS));
@@ -527,13 +529,15 @@ xfs_prepare_ioend(
  */
 static void
 xfs_discard_page(
-       struct page             *page)
+       struct page             *page,
+       loff_t                  fileoff)
 {
        struct inode            *inode = page->mapping->host;
        struct xfs_inode        *ip = XFS_I(inode);
        struct xfs_mount        *mp = ip->i_mount;
-       loff_t                  offset = page_offset(page);
-       xfs_fileoff_t           start_fsb = XFS_B_TO_FSBT(mp, offset);
+       unsigned int            pageoff = offset_in_page(fileoff);
+       xfs_fileoff_t           start_fsb = XFS_B_TO_FSBT(mp, fileoff);
+       xfs_fileoff_t           pageoff_fsb = XFS_B_TO_FSBT(mp, pageoff);
        int                     error;
 
        if (XFS_FORCED_SHUTDOWN(mp))
@@ -541,14 +545,14 @@ xfs_discard_page(
 
        xfs_alert_ratelimited(mp,
                "page discard on page "PTR_FMT", inode 0x%llx, offset %llu.",
-                       page, ip->i_ino, offset);
+                       page, ip->i_ino, fileoff);
 
        error = xfs_bmap_punch_delalloc_range(ip, start_fsb,
-                       i_blocks_per_page(inode, page));
+                       i_blocks_per_page(inode, page) - pageoff_fsb);
        if (error && !XFS_FORCED_SHUTDOWN(mp))
                xfs_alert(mp, "page discard unable to remove delalloc mapping.");
 out_invalidate:
-       iomap_invalidatepage(page, 0, PAGE_SIZE);
+       iomap_invalidatepage(page, pageoff, PAGE_SIZE - pageoff);
 }
 
 static const struct iomap_writeback_ops xfs_writeback_ops = {
index 3abb8b9d6f4c6b2b3b88f3fad14b737e46f84a8a..7b9ff824e82d48b4040f6442426d4a0e7eacb6e4 100644 (file)
@@ -706,6 +706,23 @@ relock:
        return 0;
 }
 
+/*
+ * Check that the imap we are going to return to the caller spans the entire
+ * range that the caller requested for the IO.
+ */
+static bool
+imap_spans_range(
+       struct xfs_bmbt_irec    *imap,
+       xfs_fileoff_t           offset_fsb,
+       xfs_fileoff_t           end_fsb)
+{
+       if (imap->br_startoff > offset_fsb)
+               return false;
+       if (imap->br_startoff + imap->br_blockcount < end_fsb)
+               return false;
+       return true;
+}
+
 static int
 xfs_direct_write_iomap_begin(
        struct inode            *inode,
@@ -766,6 +783,18 @@ xfs_direct_write_iomap_begin(
        if (imap_needs_alloc(inode, flags, &imap, nimaps))
                goto allocate_blocks;
 
+       /*
+        * NOWAIT IO needs to span the entire requested IO with a single map so
+        * that we avoid partial IO failures due to the rest of the IO range not
+        * covered by this map triggering an EAGAIN condition when it is
+        * subsequently mapped and aborting the IO.
+        */
+       if ((flags & IOMAP_NOWAIT) &&
+           !imap_spans_range(&imap, offset_fsb, end_fsb)) {
+               error = -EAGAIN;
+               goto out_unlock;
+       }
+
        xfs_iunlock(ip, lockmode);
        trace_xfs_iomap_found(ip, offset, length, XFS_DATA_FORK, &imap);
        return xfs_bmbt_to_iomap(ip, iomap, &imap, iomap_flags);
index 5e165456da68f42b7f23a126ee702d4f43cb1824..1414ab79eacfc27c4f8056a906133f4730153ea0 100644 (file)
@@ -911,6 +911,16 @@ xfs_setattr_size(
                error = iomap_zero_range(inode, oldsize, newsize - oldsize,
                                &did_zeroing, &xfs_buffered_write_iomap_ops);
        } else {
+               /*
+                * iomap won't detect a dirty page over an unwritten block (or a
+                * cow block over a hole) and subsequently skips zeroing the
+                * newly post-EOF portion of the page. Flush the new EOF to
+                * convert the block before the pagecache truncate.
+                */
+               error = filemap_write_and_wait_range(inode->i_mapping, newsize,
+                                                    newsize);
+               if (error)
+                       return error;
                error = iomap_truncate_page(inode, newsize, &did_zeroing,
                                &xfs_buffered_write_iomap_ops);
        }
index 233dcc8784db0b69886c84b3071902fac9673e41..2a45138831e337c134309a65d7eddbe95babc17c 100644 (file)
@@ -55,6 +55,9 @@ struct xfs_iwalk_ag {
        /* Where do we start the traversal? */
        xfs_ino_t                       startino;
 
+       /* What was the last inode number we saw when iterating the inobt? */
+       xfs_ino_t                       lastino;
+
        /* Array of inobt records we cache. */
        struct xfs_inobt_rec_incore     *recs;
 
@@ -301,6 +304,9 @@ xfs_iwalk_ag_start(
        if (XFS_IS_CORRUPT(mp, *has_more != 1))
                return -EFSCORRUPTED;
 
+       iwag->lastino = XFS_AGINO_TO_INO(mp, agno,
+                               irec->ir_startino + XFS_INODES_PER_CHUNK - 1);
+
        /*
         * If the LE lookup yielded an inobt record before the cursor position,
         * skip it and see if there's another one after it.
@@ -347,15 +353,17 @@ xfs_iwalk_run_callbacks(
        struct xfs_mount                *mp = iwag->mp;
        struct xfs_trans                *tp = iwag->tp;
        struct xfs_inobt_rec_incore     *irec;
-       xfs_agino_t                     restart;
+       xfs_agino_t                     next_agino;
        int                             error;
 
+       next_agino = XFS_INO_TO_AGINO(mp, iwag->lastino) + 1;
+
        ASSERT(iwag->nr_recs > 0);
 
        /* Delete cursor but remember the last record we cached... */
        xfs_iwalk_del_inobt(tp, curpp, agi_bpp, 0);
        irec = &iwag->recs[iwag->nr_recs - 1];
-       restart = irec->ir_startino + XFS_INODES_PER_CHUNK - 1;
+       ASSERT(next_agino == irec->ir_startino + XFS_INODES_PER_CHUNK);
 
        error = xfs_iwalk_ag_recs(iwag);
        if (error)
@@ -372,7 +380,7 @@ xfs_iwalk_run_callbacks(
        if (error)
                return error;
 
-       return xfs_inobt_lookup(*curpp, restart, XFS_LOOKUP_GE, has_more);
+       return xfs_inobt_lookup(*curpp, next_agino, XFS_LOOKUP_GE, has_more);
 }
 
 /* Walk all inodes in a single AG, from @iwag->startino to the end of the AG. */
@@ -396,6 +404,7 @@ xfs_iwalk_ag(
 
        while (!error && has_more) {
                struct xfs_inobt_rec_incore     *irec;
+               xfs_ino_t                       rec_fsino;
 
                cond_resched();
                if (xfs_pwork_want_abort(&iwag->pwork))
@@ -407,6 +416,15 @@ xfs_iwalk_ag(
                if (error || !has_more)
                        break;
 
+               /* Make sure that we always move forward. */
+               rec_fsino = XFS_AGINO_TO_INO(mp, agno, irec->ir_startino);
+               if (iwag->lastino != NULLFSINO &&
+                   XFS_IS_CORRUPT(mp, iwag->lastino >= rec_fsino)) {
+                       error = -EFSCORRUPTED;
+                       goto out;
+               }
+               iwag->lastino = rec_fsino + XFS_INODES_PER_CHUNK - 1;
+
                /* No allocated inodes in this chunk; skip it. */
                if (iwag->skip_empty && irec->ir_freecount == irec->ir_count) {
                        error = xfs_btree_increment(cur, 0, &has_more);
@@ -535,6 +553,7 @@ xfs_iwalk(
                .trim_start     = 1,
                .skip_empty     = 1,
                .pwork          = XFS_PWORK_SINGLE_THREADED,
+               .lastino        = NULLFSINO,
        };
        xfs_agnumber_t          agno = XFS_INO_TO_AGNO(mp, startino);
        int                     error;
@@ -623,6 +642,7 @@ xfs_iwalk_threaded(
                iwag->data = data;
                iwag->startino = startino;
                iwag->sz_recs = xfs_iwalk_prefetch(inode_records);
+               iwag->lastino = NULLFSINO;
                xfs_pwork_queue(&pctl, &iwag->pwork);
                startino = XFS_AGINO_TO_INO(mp, agno + 1, 0);
                if (flags & XFS_INOBT_WALK_SAME_AG)
@@ -696,6 +716,7 @@ xfs_inobt_walk(
                .startino       = startino,
                .sz_recs        = xfs_inobt_walk_prefetch(inobt_records),
                .pwork          = XFS_PWORK_SINGLE_THREADED,
+               .lastino        = NULLFSINO,
        };
        xfs_agnumber_t          agno = XFS_INO_TO_AGNO(mp, startino);
        int                     error;
index 150ee5cb8645780560f2de9f5eb057e0f05fef59..7110507a2b6bc2ee0f8ee9be771895146e11471b 100644 (file)
@@ -194,20 +194,25 @@ xfs_initialize_perag(
                }
 
                pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL);
-               if (!pag)
+               if (!pag) {
+                       error = -ENOMEM;
                        goto out_unwind_new_pags;
+               }
                pag->pag_agno = index;
                pag->pag_mount = mp;
                spin_lock_init(&pag->pag_ici_lock);
                INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
-               if (xfs_buf_hash_init(pag))
+
+               error = xfs_buf_hash_init(pag);
+               if (error)
                        goto out_free_pag;
                init_waitqueue_head(&pag->pagb_wait);
                spin_lock_init(&pag->pagb_lock);
                pag->pagb_count = 0;
                pag->pagb_tree = RB_ROOT;
 
-               if (radix_tree_preload(GFP_NOFS))
+               error = radix_tree_preload(GFP_NOFS);
+               if (error)
                        goto out_hash_destroy;
 
                spin_lock(&mp->m_perag_lock);
index b101feb2aab4528e772b4355c1d6205e9613a3f0..f3082a957d5e1a34fc264515ab59cae2f766f05a 100644 (file)
@@ -134,7 +134,7 @@ xfs_fs_map_blocks(
                goto out_unlock;
        error = invalidate_inode_pages2(inode->i_mapping);
        if (WARN_ON_ONCE(error))
-               return error;
+               goto out_unlock;
 
        end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + length);
        offset_fsb = XFS_B_TO_FSBT(mp, offset);
index 16098dc42addb81cd3f862113d719edf8a3e73b3..6fa05fb78189bb1b2479d5071f690ed00e22f8d2 100644 (file)
@@ -1502,7 +1502,8 @@ xfs_reflink_unshare(
                        &xfs_buffered_write_iomap_ops);
        if (error)
                goto out;
-       error = filemap_write_and_wait(inode->i_mapping);
+
+       error = filemap_write_and_wait_range(inode->i_mapping, offset, len);
        if (error)
                goto out;
 
index 798027bb89be8ba529120ce97a1da1a9c7511743..640f09479bdf7984799d7ecdf40d7da17d83e26c 100644 (file)
@@ -13,6 +13,7 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/compiler.h>
 #include <asm/rwonce.h>
 
 #ifndef nop
index 35e4a53b83e639fc0213d5e13a0f5c59e93307aa..6432a7fade91366ff5e6e3da4f2b425dda1fee36 100644 (file)
@@ -114,21 +114,21 @@ do {                                                                      \
 
 #define __this_cpu_generic_read_nopreempt(pcp)                         \
 ({                                                                     \
-       typeof(pcp) __ret;                                              \
+       typeof(pcp) ___ret;                                             \
        preempt_disable_notrace();                                      \
-       __ret = READ_ONCE(*raw_cpu_ptr(&(pcp)));                        \
+       ___ret = READ_ONCE(*raw_cpu_ptr(&(pcp)));                       \
        preempt_enable_notrace();                                       \
-       __ret;                                                          \
+       ___ret;                                                         \
 })
 
 #define __this_cpu_generic_read_noirq(pcp)                             \
 ({                                                                     \
-       typeof(pcp) __ret;                                              \
-       unsigned long __flags;                                          \
-       raw_local_irq_save(__flags);                                    \
-       __ret = raw_cpu_generic_read(pcp);                              \
-       raw_local_irq_restore(__flags);                                 \
-       __ret;                                                          \
+       typeof(pcp) ___ret;                                             \
+       unsigned long ___flags;                                         \
+       raw_local_irq_save(___flags);                                   \
+       ___ret = raw_cpu_generic_read(pcp);                             \
+       raw_local_irq_restore(___flags);                                \
+       ___ret;                                                         \
 })
 
 #define this_cpu_generic_read(pcp)                                     \
index 45f9872fd74759d7daf0a643d960378602c5e182..4973328f3c6e75ae04b010d10f7210d8c5279b1d 100644 (file)
@@ -12,7 +12,8 @@
 #ifdef CONFIG_UACCESS_MEMCPY
 #include <asm/unaligned.h>
 
-static inline int __get_user_fn(size_t size, const void __user *from, void *to)
+static __always_inline int
+__get_user_fn(size_t size, const void __user *from, void *to)
 {
        BUILD_BUG_ON(!__builtin_constant_p(size));
 
@@ -37,7 +38,8 @@ static inline int __get_user_fn(size_t size, const void __user *from, void *to)
 }
 #define __get_user_fn(sz, u, k)        __get_user_fn(sz, u, k)
 
-static inline int __put_user_fn(size_t size, void __user *to, void *from)
+static __always_inline int
+__put_user_fn(size_t size, void __user *to, void *from)
 {
        BUILD_BUG_ON(!__builtin_constant_p(size));
 
index cd14444bf600516a24894669b4f4473fd4021dd0..b2b3d81b1535a5abbf6803f3dfbb29058a979bc4 100644 (file)
 #ifdef CONFIG_CONSTRUCTORS
 #define KERNEL_CTORS() . = ALIGN(8);                      \
                        __ctors_start = .;                 \
+                       KEEP(*(SORT(.ctors.*)))            \
                        KEEP(*(.ctors))                    \
                        KEEP(*(SORT(.init_array.*)))       \
                        KEEP(*(.init_array))               \
index da53aebb7230b980ba23e9c87d361d9b6d6906df..a53243abd9450508bb302d59122607dede8eb049 100644 (file)
@@ -1836,7 +1836,7 @@ static inline void drm_dp_cec_unset_edid(struct drm_dp_aux *aux)
  * @link_rate: Requested Link rate from DPCD 0x219
  * @num_lanes: Number of lanes requested by sing through DPCD 0x220
  * @phy_pattern: DP Phy test pattern from DPCD 0x248
- * @hb2_reset: DP HBR2_COMPLIANCE_SCRAMBLER_RESET from DCPD 0x24A and 0x24B
+ * @hbr2_reset: DP HBR2_COMPLIANCE_SCRAMBLER_RESET from DCPD 0x24A and 0x24B
  * @custom80: DP Test_80BIT_CUSTOM_PATTERN from DPCDs 0x250 through 0x259
  * @enhanced_frame_cap: flag for enhanced frame capability.
  */
index b27a0e2169c8f56bdcd882ea18f5cd200248a327..e97daf6ffbb193a74505026492b9f29825ee365d 100644 (file)
@@ -359,13 +359,6 @@ drm_load_edid_firmware(struct drm_connector *connector)
 }
 #endif
 
-/**
- * drm_edid_are_equal - compare two edid blobs.
- * @edid1: pointer to first blob
- * @edid2: pointer to second blob
- * This helper can be used during probing to determine if
- * edid had changed.
- */
 bool drm_edid_are_equal(const struct edid *edid1, const struct edid *edid2);
 
 int
index 1c9417430d08520f8c5c9a593ee874f7d5aebdfc..f32d179e139d9cdd45621436fe866d5332bd510d 100644 (file)
@@ -338,7 +338,7 @@ void drm_dev_dbg(const struct device *dev, enum drm_debug_category category,
                 const char *format, ...);
 
 /**
- * Error output.
+ * DRM_DEV_ERROR() - Error output.
  *
  * @dev: device pointer
  * @fmt: printf() like format string.
@@ -347,10 +347,12 @@ void drm_dev_dbg(const struct device *dev, enum drm_debug_category category,
        drm_dev_printk(dev, KERN_ERR, "*ERROR* " fmt, ##__VA_ARGS__)
 
 /**
- * Rate limited error output.  Like DRM_ERROR() but won't flood the log.
+ * DRM_DEV_ERROR_RATELIMITED() - Rate limited error output.
  *
  * @dev: device pointer
  * @fmt: printf() like format string.
+ *
+ * Like DRM_ERROR() but won't flood the log.
  */
 #define DRM_DEV_ERROR_RATELIMITED(dev, fmt, ...)                       \
 ({                                                                     \
@@ -375,15 +377,27 @@ void drm_dev_dbg(const struct device *dev, enum drm_debug_category category,
 })
 
 /**
- * Debug output.
+ * DRM_DEV_DEBUG() - Debug output for generic drm code
  *
  * @dev: device pointer
  * @fmt: printf() like format string.
  */
 #define DRM_DEV_DEBUG(dev, fmt, ...)                                   \
        drm_dev_dbg(dev, DRM_UT_CORE, fmt, ##__VA_ARGS__)
+/**
+ * DRM_DEV_DEBUG_DRIVER() - Debug output for vendor specific part of the driver
+ *
+ * @dev: device pointer
+ * @fmt: printf() like format string.
+ */
 #define DRM_DEV_DEBUG_DRIVER(dev, fmt, ...)                            \
        drm_dev_dbg(dev, DRM_UT_DRIVER, fmt, ##__VA_ARGS__)
+/**
+ * DRM_DEV_DEBUG_KMS() - Debug output for modesetting code
+ *
+ * @dev: device pointer
+ * @fmt: printf() like format string.
+ */
 #define DRM_DEV_DEBUG_KMS(dev, fmt, ...)                               \
        drm_dev_dbg(dev, DRM_UT_KMS, fmt, ##__VA_ARGS__)
 
index 9197da7923361a8a4e20674e547f7f8a036b56b4..df60be7e22ca365cc3732e67364a2157430968f5 100644 (file)
@@ -252,13 +252,14 @@ static inline int kunit_run_all_tests(void)
 }
 #endif /* IS_BUILTIN(CONFIG_KUNIT) */
 
+#ifdef MODULE
 /**
- * kunit_test_suites() - used to register one or more &struct kunit_suite
- *                      with KUnit.
+ * kunit_test_suites_for_module() - used to register one or more
+ *                      &struct kunit_suite with KUnit.
  *
- * @suites_list...: a statically allocated list of &struct kunit_suite.
+ * @__suites: a statically allocated list of &struct kunit_suite.
  *
- * Registers @suites_list with the test framework. See &struct kunit_suite for
+ * Registers @__suites with the test framework. See &struct kunit_suite for
  * more information.
  *
  * If a test suite is built-in, module_init() gets translated into
@@ -267,7 +268,6 @@ static inline int kunit_run_all_tests(void)
  * module_{init|exit} functions for the builtin case when registering
  * suites via kunit_test_suites() below.
  */
-#ifdef MODULE
 #define kunit_test_suites_for_module(__suites)                         \
        static int __init kunit_test_suites_init(void)                  \
        {                                                               \
@@ -294,7 +294,7 @@ static inline int kunit_run_all_tests(void)
  * kunit_test_suites() - used to register one or more &struct kunit_suite
  *                      with KUnit.
  *
- * @suites: a statically allocated list of &struct kunit_suite.
+ * @__suites: a statically allocated list of &struct kunit_suite.
  *
  * Registers @suites with the test framework. See &struct kunit_suite for
  * more information.
@@ -308,10 +308,10 @@ static inline int kunit_run_all_tests(void)
  * module.
  *
  */
-#define kunit_test_suites(...)                                         \
+#define kunit_test_suites(__suites...)                                         \
        __kunit_test_suites(__UNIQUE_ID(array),                         \
                            __UNIQUE_ID(suites),                        \
-                           __VA_ARGS__)
+                           ##__suites)
 
 #define kunit_test_suite(suite)        kunit_test_suites(&suite)
 
@@ -1105,7 +1105,7 @@ do {                                                                             \
        KUNIT_ASSERTION(test,                                                  \
                        strcmp(__left, __right) op 0,                          \
                        kunit_binary_str_assert,                               \
-                       KUNIT_INIT_BINARY_ASSERT_STRUCT(test,                  \
+                       KUNIT_INIT_BINARY_STR_ASSERT_STRUCT(test,              \
                                                        assert_type,           \
                                                        #op,                   \
                                                        #left,                 \
index 885c9ffc835c3698a5b206f04abf4d76f82517b3..f860645f6512833c602aea5f277e896a0cf9a442 100644 (file)
@@ -87,6 +87,8 @@
                           ARM_SMCCC_SMC_32,                            \
                           0, 0x7fff)
 
+#define SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED   1
+
 /* Paravirtualised time calls (defined by ARM DEN0057A) */
 #define ARM_SMCCC_HV_PV_TIME_FEATURES                          \
        ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,                 \
index b23eeca4d67729c14e95a1a2ce082922939ebfcd..794b2a33a2c36c8f4c335a9868fbccdb11d2e99a 100644 (file)
@@ -235,6 +235,8 @@ enum hctx_type {
  * @flags:        Zero or more BLK_MQ_F_* flags.
  * @driver_data:   Pointer to data owned by the block driver that created this
  *                tag set.
+ * @active_queues_shared_sbitmap:
+ *                number of active request queues per tag set.
  * @__bitmap_tags: A shared tags sbitmap, used over all hctx's
  * @__breserved_tags:
  *                A shared reserved tags sbitmap, used over all hctx's
index 639cae2c158b5973b23f92f25974f80bca757f64..033eb5f73b6540736b3c9802ecdcad7b79ef6dbe 100644 (file)
@@ -1073,12 +1073,15 @@ static inline unsigned int blk_queue_get_max_sectors(struct request_queue *q,
  * file system requests.
  */
 static inline unsigned int blk_max_size_offset(struct request_queue *q,
-                                              sector_t offset)
-{
-       unsigned int chunk_sectors = q->limits.chunk_sectors;
-
-       if (!chunk_sectors)
-               return q->limits.max_sectors;
+                                              sector_t offset,
+                                              unsigned int chunk_sectors)
+{
+       if (!chunk_sectors) {
+               if (q->limits.chunk_sectors)
+                       chunk_sectors = q->limits.chunk_sectors;
+               else
+                       return q->limits.max_sectors;
+       }
 
        if (likely(is_power_of_2(chunk_sectors)))
                chunk_sectors -= offset & (chunk_sectors - 1);
@@ -1101,7 +1104,7 @@ static inline unsigned int blk_rq_get_max_sectors(struct request *rq,
            req_op(rq) == REQ_OP_SECURE_ERASE)
                return blk_queue_get_max_sectors(q, req_op(rq));
 
-       return min(blk_max_size_offset(q, offset),
+       return min(blk_max_size_offset(q, offset, 0),
                        blk_queue_get_max_sectors(q, req_op(rq)));
 }
 
index 9903088891fa8a81dbae5df628aaceb64b2a20eb..2696eb0fc14976a3420f89a9e63d4a585f017807 100644 (file)
@@ -12,6 +12,9 @@
 
 #define BOOTCONFIG_MAGIC       "#BOOTCONFIG\n"
 #define BOOTCONFIG_MAGIC_LEN   12
+#define BOOTCONFIG_ALIGN_SHIFT 2
+#define BOOTCONFIG_ALIGN       (1 << BOOTCONFIG_ALIGN_SHIFT)
+#define BOOTCONFIG_ALIGN_MASK  (BOOTCONFIG_ALIGN - 1)
 
 /* XBC tree node */
 struct xbc_node {
index 900b9f4e060540ce09d5cf6cd5081fee9af733e0..fc61cf4eff1c9af159ab25a37a8041de156034ef 100644 (file)
@@ -61,21 +61,17 @@ static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk)
  */
 static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)
 {
-       if (skb_shared(skb)) {
-               struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
+       struct sk_buff *nskb;
 
-               if (likely(nskb)) {
-                       can_skb_set_owner(nskb, skb->sk);
-                       consume_skb(skb);
-                       return nskb;
-               } else {
-                       kfree_skb(skb);
-                       return NULL;
-               }
+       nskb = skb_clone(skb, GFP_ATOMIC);
+       if (unlikely(!nskb)) {
+               kfree_skb(skb);
+               return NULL;
        }
 
-       /* we can assume to have an unshared skb with proper owner */
-       return skb;
+       can_skb_set_owner(nskb, skb->sk);
+       consume_skb(skb);
+       return nskb;
 }
 
 #endif /* !_CAN_SKB_H */
index 230604e7f0574f0182081263f127bf455b8ef6e7..98cff1b4b088c7ee3723a81b08f6b0d8272e5766 100644 (file)
@@ -8,8 +8,10 @@
                     + __clang_patchlevel__)
 
 #if CLANG_VERSION < 100001
+#ifndef __BPF_TRACING__
 # error Sorry, your version of Clang is too old - please use 10.0.1 or newer.
 #endif
+#endif
 
 /* Compiler specific definitions for Clang compiler */
 
 #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
 #endif
 
-/* The following are for compatibility with GCC, from compiler-gcc.h,
- * and may be redefined here because they should not be shared with other
- * compilers, like ICC.
- */
-#define barrier() __asm__ __volatile__("" : : : "memory")
-
 #if __has_feature(shadow_call_stack)
 # define __noscs       __attribute__((__no_sanitize__("shadow-call-stack")))
 #endif
index d1e3c6896b71689d1d60ab19e4e7c72f9517110a..74c6c0486eed782e267b1addd65669f1422bad65 100644 (file)
 # error Sorry, your version of GCC is too old - please use 4.9 or newer.
 #endif
 
-/* Optimization barrier */
-
-/* The "volatile" is due to gcc bugs */
-#define barrier() __asm__ __volatile__("": : :"memory")
-/*
- * This version is i.e. to prevent dead stores elimination on @ptr
- * where gcc and llvm may behave differently when otherwise using
- * normal barrier(): while gcc behavior gets along with a normal
- * barrier(), llvm needs an explicit input variable to be assumed
- * clobbered. The issue is as follows: while the inline asm might
- * access any memory it wants, the compiler could have fit all of
- * @ptr into memory registers instead, and since @ptr never escaped
- * from that, it proved that the inline asm wasn't touching any of
- * it. This version works well with both compilers, i.e. we're telling
- * the compiler that the inline asm absolutely may see the contents
- * of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495
- */
-#define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory")
-
 /*
  * This macro obfuscates arithmetic on a variable address so that gcc
  * shouldn't recognize the original var, and make assumptions about it.
 #else
 #define __diag_GCC_8(s)
 #endif
-
-#define __no_fgcse __attribute__((optimize("-fno-gcse")))
index e512f5505dadbcf7e9d3756fe7f886d63903a003..b8fe0c23cfffb32736c16ca678c37a8dcd591f15 100644 (file)
@@ -80,11 +80,25 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
 
 /* Optimization barrier */
 #ifndef barrier
-# define barrier() __memory_barrier()
+/* The "volatile" is due to gcc bugs */
+# define barrier() __asm__ __volatile__("": : :"memory")
 #endif
 
 #ifndef barrier_data
-# define barrier_data(ptr) barrier()
+/*
+ * This version is i.e. to prevent dead stores elimination on @ptr
+ * where gcc and llvm may behave differently when otherwise using
+ * normal barrier(): while gcc behavior gets along with a normal
+ * barrier(), llvm needs an explicit input variable to be assumed
+ * clobbered. The issue is as follows: while the inline asm might
+ * access any memory it wants, the compiler could have fit all of
+ * @ptr into memory registers instead, and since @ptr never escaped
+ * from that, it proved that the inline asm wasn't touching any of
+ * it. This version works well with both compilers, i.e. we're telling
+ * the compiler that the inline asm absolutely may see the contents
+ * of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495
+ */
+# define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory")
 #endif
 
 /* workaround for GCC PR82365 if needed */
index 6e390d58a9f8c5f25406fbc87a48e2fc99415629..ac3fa37a84f940450ab7f6ff3cc619647838c598 100644 (file)
@@ -247,10 +247,6 @@ struct ftrace_likely_data {
 #define asm_inline asm
 #endif
 
-#ifndef __no_fgcse
-# define __no_fgcse
-#endif
-
 /* Are two types/vars the same type (ignoring qualifiers)? */
 #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
 
index fa37b1c6644326467426335e27702c02cbbfe802..acbad3b363226efa0bd6dd45514cc1490edb2813 100644 (file)
@@ -109,6 +109,12 @@ struct cpufreq_policy {
        bool                    fast_switch_possible;
        bool                    fast_switch_enabled;
 
+       /*
+        * Set if the CPUFREQ_GOV_STRICT_TARGET flag is set for the current
+        * governor.
+        */
+       bool                    strict_target;
+
        /*
         * Preferred average time interval between consecutive invocations of
         * the driver to set the frequency for this policy.  To be set by the
@@ -298,7 +304,7 @@ __ATTR(_name, 0644, show_##_name, store_##_name)
 
 struct cpufreq_driver {
        char            name[CPUFREQ_NAME_LEN];
-       u             flags;
+       u16             flags;
        void            *driver_data;
 
        /* needed by all drivers */
@@ -422,9 +428,18 @@ struct cpufreq_driver {
  */
 #define CPUFREQ_IS_COOLING_DEV                 BIT(7)
 
+/*
+ * Set by drivers that need to update internale upper and lower boundaries along
+ * with the target frequency and so the core and governors should also invoke
+ * the diver if the target frequency does not change, but the policy min or max
+ * may have changed.
+ */
+#define CPUFREQ_NEED_UPDATE_LIMITS             BIT(8)
+
 int cpufreq_register_driver(struct cpufreq_driver *driver_data);
 int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
 
+bool cpufreq_driver_test_flags(u16 flags);
 const char *cpufreq_get_current_driver(void);
 void *cpufreq_get_driver_data(void);
 
@@ -561,12 +576,20 @@ struct cpufreq_governor {
                                         char *buf);
        int     (*store_setspeed)       (struct cpufreq_policy *policy,
                                         unsigned int freq);
-       /* For governors which change frequency dynamically by themselves */
-       bool                    dynamic_switching;
        struct list_head        governor_list;
        struct module           *owner;
+       u8                      flags;
 };
 
+/* Governor flags */
+
+/* For governors which change frequency dynamically by themselves */
+#define CPUFREQ_GOV_DYNAMIC_SWITCHING  BIT(0)
+
+/* For governors wanting the target frequency to be set exactly */
+#define CPUFREQ_GOV_STRICT_TARGET      BIT(1)
+
+
 /* Pass a target to the cpufreq driver */
 unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy,
                                        unsigned int target_freq);
index 851dd1f9a8a5f5466933e23709c50d7c39e13d5b..d6c4cc9ecc77cca2f6d6e5b719ba4eb576dd2fd1 100644 (file)
@@ -144,10 +144,9 @@ void debugfs_create_u32_array(const char *name, umode_t mode,
                              struct dentry *parent,
                              struct debugfs_u32_array *array);
 
-struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name,
-                                          struct dentry *parent,
-                                          int (*read_fn)(struct seq_file *s,
-                                                         void *data));
+void debugfs_create_devm_seqfile(struct device *dev, const char *name,
+                                struct dentry *parent,
+                                int (*read_fn)(struct seq_file *s, void *data));
 
 bool debugfs_initialized(void);
 
@@ -327,13 +326,12 @@ static inline void debugfs_create_u32_array(const char *name, umode_t mode,
 {
 }
 
-static inline struct dentry *debugfs_create_devm_seqfile(struct device *dev,
-                                                        const char *name,
-                                                        struct dentry *parent,
-                                          int (*read_fn)(struct seq_file *s,
-                                                         void *data))
+static inline void debugfs_create_devm_seqfile(struct device *dev,
+                                              const char *name,
+                                              struct dentry *parent,
+                                              int (*read_fn)(struct seq_file *s,
+                                                             void *data))
 {
-       return ERR_PTR(-ENODEV);
 }
 
 static inline ssize_t debugfs_read_file_bool(struct file *file,
index 5896441ee604c7c424a5655cb9cbe8dcae4f226e..efa2f0309f0049894ae5614c29d2f427bde44f57 100644 (file)
@@ -47,7 +47,7 @@ struct cppi5_host_desc_t {
        u32 buf_info1;
        u32 org_buf_len;
        u64 org_buf_ptr;
-       u32 epib[0];
+       u32 epib[];
 } __packed;
 
 #define CPPI5_DESC_MIN_ALIGN                   (16U)
@@ -139,7 +139,7 @@ struct cppi5_desc_epib_t {
  */
 struct cppi5_monolithic_desc_t {
        struct cppi5_desc_hdr_t hdr;
-       u32 epib[0];
+       u32 epib[];
 };
 
 #define CPPI5_INFO2_MDESC_DATA_OFFSET_SHIFT    (18U)
index 8f63245f7f7c18125c8e397d59628a4a0379429d..76d3562d30061912070f9103941317e65b5b3c32 100644 (file)
@@ -181,6 +181,7 @@ static inline char *mc_event_error_type(const unsigned int err_type)
  *                     This is a variant of the DDR4 memories.
  * @MEM_LRDDR4:                Load-Reduced DDR4 memory.
  * @MEM_LPDDR4:                Low-Power DDR4 memory.
+ * @MEM_DDR5:          Unbuffered DDR5 RAM
  * @MEM_NVDIMM:                Non-volatile RAM
  * @MEM_WIO2:          Wide I/O 2.
  */
@@ -208,6 +209,7 @@ enum mem_type {
        MEM_RDDR4,
        MEM_LRDDR4,
        MEM_LPDDR4,
+       MEM_DDR5,
        MEM_NVDIMM,
        MEM_WIO2,
 };
@@ -234,11 +236,12 @@ enum mem_type {
 #define MEM_FLAG_RDDR4          BIT(MEM_RDDR4)
 #define MEM_FLAG_LRDDR4         BIT(MEM_LRDDR4)
 #define MEM_FLAG_LPDDR4         BIT(MEM_LPDDR4)
+#define MEM_FLAG_DDR5           BIT(MEM_DDR5)
 #define MEM_FLAG_NVDIMM         BIT(MEM_NVDIMM)
 #define MEM_FLAG_WIO2          BIT(MEM_WIO2)
 
 /**
- * enum edac-type - Error Detection and Correction capabilities and mode
+ * enum edac_type - Error Detection and Correction capabilities and mode
  * @EDAC_UNKNOWN:      Unknown if ECC is available
  * @EDAC_NONE:         Doesn't support ECC
  * @EDAC_RESERVED:     Reserved ECC type
@@ -318,7 +321,7 @@ enum scrub_type {
 #define OP_OFFLINE             0x300
 
 /**
- * enum edac_mc_layer - memory controller hierarchy layer
+ * enum edac_mc_layer_type - memory controller hierarchy layer
  *
  * @EDAC_MC_LAYER_BRANCH:      memory layer is named "branch"
  * @EDAC_MC_LAYER_CHANNEL:     memory layer is named "channel"
index 72d62cbc1578f98b2e2fa75164762f61d56e8f60..1b62397bd12471be5a343d3d36ec8adaa4a0e388 100644 (file)
@@ -558,21 +558,21 @@ struct sk_filter {
 DECLARE_STATIC_KEY_FALSE(bpf_stats_enabled_key);
 
 #define __BPF_PROG_RUN(prog, ctx, dfunc)       ({                      \
-       u32 ret;                                                        \
+       u32 __ret;                                                      \
        cant_migrate();                                                 \
        if (static_branch_unlikely(&bpf_stats_enabled_key)) {           \
-               struct bpf_prog_stats *stats;                           \
-               u64 start = sched_clock();                              \
-               ret = dfunc(ctx, (prog)->insnsi, (prog)->bpf_func);     \
-               stats = this_cpu_ptr(prog->aux->stats);                 \
-               u64_stats_update_begin(&stats->syncp);                  \
-               stats->cnt++;                                           \
-               stats->nsecs += sched_clock() - start;                  \
-               u64_stats_update_end(&stats->syncp);                    \
+               struct bpf_prog_stats *__stats;                         \
+               u64 __start = sched_clock();                            \
+               __ret = dfunc(ctx, (prog)->insnsi, (prog)->bpf_func);   \
+               __stats = this_cpu_ptr(prog->aux->stats);               \
+               u64_stats_update_begin(&__stats->syncp);                \
+               __stats->cnt++;                                         \
+               __stats->nsecs += sched_clock() - __start;              \
+               u64_stats_update_end(&__stats->syncp);                  \
        } else {                                                        \
-               ret = dfunc(ctx, (prog)->insnsi, (prog)->bpf_func);     \
+               __ret = dfunc(ctx, (prog)->insnsi, (prog)->bpf_func);   \
        }                                                               \
-       ret; })
+       __ret; })
 
 #define BPF_PROG_RUN(prog, ctx)                                                \
        __BPF_PROG_RUN(prog, ctx, bpf_dispatcher_nop_func)
index 5968df82b99121fb3613508cb8c7322770164106..41a1bab98b7e14a2bbf964a17103ab3d907e5f0e 100644 (file)
 #define        ZYNQMP_PM_CAPABILITY_WAKEUP     0x4U
 #define        ZYNQMP_PM_CAPABILITY_UNUSABLE   0x8U
 
-/* Feature check status */
-#define PM_FEATURE_INVALID             -1
-#define PM_FEATURE_UNCHECKED           0
-
 /*
  * Firmware FPGA Manager flags
  * XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration
index 0bd126418bb6ad43bdf9302c50525dd3fe3baec4..8667d0cdc71e76635da29edf92bb66918ed864f2 100644 (file)
@@ -1580,8 +1580,24 @@ extern struct timespec64 current_time(struct inode *inode);
  * Snapshotting support.
  */
 
-void __sb_end_write(struct super_block *sb, int level);
-int __sb_start_write(struct super_block *sb, int level, bool wait);
+/*
+ * These are internal functions, please use sb_start_{write,pagefault,intwrite}
+ * instead.
+ */
+static inline void __sb_end_write(struct super_block *sb, int level)
+{
+       percpu_up_read(sb->s_writers.rw_sem + level-1);
+}
+
+static inline void __sb_start_write(struct super_block *sb, int level)
+{
+       percpu_down_read(sb->s_writers.rw_sem + level - 1);
+}
+
+static inline bool __sb_start_write_trylock(struct super_block *sb, int level)
+{
+       return percpu_down_read_trylock(sb->s_writers.rw_sem + level - 1);
+}
 
 #define __sb_writers_acquired(sb, lev) \
        percpu_rwsem_acquire(&(sb)->s_writers.rw_sem[(lev)-1], 1, _THIS_IP_)
@@ -1645,12 +1661,12 @@ static inline void sb_end_intwrite(struct super_block *sb)
  */
 static inline void sb_start_write(struct super_block *sb)
 {
-       __sb_start_write(sb, SB_FREEZE_WRITE, true);
+       __sb_start_write(sb, SB_FREEZE_WRITE);
 }
 
-static inline int sb_start_write_trylock(struct super_block *sb)
+static inline bool sb_start_write_trylock(struct super_block *sb)
 {
-       return __sb_start_write(sb, SB_FREEZE_WRITE, false);
+       return __sb_start_write_trylock(sb, SB_FREEZE_WRITE);
 }
 
 /**
@@ -1674,7 +1690,7 @@ static inline int sb_start_write_trylock(struct super_block *sb)
  */
 static inline void sb_start_pagefault(struct super_block *sb)
 {
-       __sb_start_write(sb, SB_FREEZE_PAGEFAULT, true);
+       __sb_start_write(sb, SB_FREEZE_PAGEFAULT);
 }
 
 /*
@@ -1692,12 +1708,12 @@ static inline void sb_start_pagefault(struct super_block *sb)
  */
 static inline void sb_start_intwrite(struct super_block *sb)
 {
-       __sb_start_write(sb, SB_FREEZE_FS, true);
+       __sb_start_write(sb, SB_FREEZE_FS);
 }
 
-static inline int sb_start_intwrite_trylock(struct super_block *sb)
+static inline bool sb_start_intwrite_trylock(struct super_block *sb)
 {
-       return __sb_start_write(sb, SB_FREEZE_FS, false);
+       return __sb_start_write_trylock(sb, SB_FREEZE_FS);
 }
 
 
@@ -2756,14 +2772,14 @@ static inline void file_start_write(struct file *file)
 {
        if (!S_ISREG(file_inode(file)->i_mode))
                return;
-       __sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, true);
+       sb_start_write(file_inode(file)->i_sb);
 }
 
 static inline bool file_start_write_trylock(struct file *file)
 {
        if (!S_ISREG(file_inode(file)->i_mode))
                return true;
-       return __sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, false);
+       return sb_start_write_trylock(file_inode(file)->i_sb);
 }
 
 static inline void file_end_write(struct file *file)
@@ -3285,7 +3301,7 @@ static inline ino_t parent_ino(struct dentry *dentry)
  */
 struct simple_transaction_argresp {
        ssize_t size;
-       char data[0];
+       char data[];
 };
 
 #define SIMPLE_TRANSACTION_LIMIT (PAGE_SIZE - sizeof(struct simple_transaction_argresp))
index 38f23d75701379cbd9c5cfc0b428c1cbaddde0a0..03da3f603d309c97a0420b725949e2da3c8bc3fb 100644 (file)
@@ -315,7 +315,7 @@ static inline int get_disk_ro(struct gendisk *disk)
 extern void disk_block_events(struct gendisk *disk);
 extern void disk_unblock_events(struct gendisk *disk);
 extern void disk_flush_events(struct gendisk *disk, unsigned int mask);
-void set_capacity_revalidate_and_notify(struct gendisk *disk, sector_t size,
+bool set_capacity_revalidate_and_notify(struct gendisk *disk, sector_t size,
                bool update_bdev);
 
 /* drivers/char/random.c */
index fbf5b3e7707eb2de652f4848dc7f2fa07b9f593e..d956987ed032db5b9ce9e9d1df440839c910bc74 100644 (file)
@@ -798,7 +798,6 @@ extern int iommu_calculate_agaw(struct intel_iommu *iommu);
 extern int iommu_calculate_max_sagaw(struct intel_iommu *iommu);
 extern int dmar_disabled;
 extern int intel_iommu_enabled;
-extern int intel_iommu_tboot_noforce;
 extern int intel_iommu_gfx_mapped;
 #else
 static inline int iommu_calculate_agaw(struct intel_iommu *iommu)
index 868364cea3b740429a7ca4e84337b7ad79846956..35b2d845704d9175466d979138d413d85423664b 100644 (file)
@@ -30,7 +30,8 @@ struct io_uring_task {
        struct percpu_counter   inflight;
        struct io_identity      __identity;
        struct io_identity      *identity;
-       bool                    in_idle;
+       atomic_t                in_idle;
+       bool                    sqpoll;
 };
 
 #if defined(CONFIG_IO_URING)
index 172b3397a1a371bc7038f201bed644c92341700f..5bd3cac4df9cb4569689a1312dd8f8b8e7455b96 100644 (file)
@@ -221,7 +221,7 @@ struct iomap_writeback_ops {
         * Optional, allows the file system to discard state on a page where
         * we failed to submit any I/O.
         */
-       void (*discard_page)(struct page *page);
+       void (*discard_page)(struct page *page, loff_t fileoff);
 };
 
 struct iomap_writepage_ctx {
index 71535e87109f3f3edf6222c4eb944648e70cd328..ea5a337e0f8b80ac8c97197039c4c391f8675096 100644 (file)
@@ -384,11 +384,19 @@ extern void irq_domain_associate_many(struct irq_domain *domain,
 extern void irq_domain_disassociate(struct irq_domain *domain,
                                    unsigned int irq);
 
-extern unsigned int irq_create_mapping(struct irq_domain *host,
-                                      irq_hw_number_t hwirq);
+extern unsigned int irq_create_mapping_affinity(struct irq_domain *host,
+                                     irq_hw_number_t hwirq,
+                                     const struct irq_affinity_desc *affinity);
 extern unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec);
 extern void irq_dispose_mapping(unsigned int virq);
 
+static inline unsigned int irq_create_mapping(struct irq_domain *host,
+                                             irq_hw_number_t hwirq)
+{
+       return irq_create_mapping_affinity(host, hwirq, NULL);
+}
+
+
 /**
  * irq_linear_revmap() - Find a linux irq from a hw irq number.
  * @domain: domain owning this hardware interrupt
index fb3d71ad6eeafbef597200be28d867f664321848..578ff196b3cef95bb64ea8a86b295a4802e355db 100644 (file)
@@ -68,6 +68,7 @@ extern void *jbd2_alloc(size_t size, gfp_t flags);
 extern void jbd2_free(void *ptr, size_t size);
 
 #define JBD2_MIN_JOURNAL_BLOCKS 1024
+#define JBD2_MIN_FC_BLOCKS     256
 
 #ifdef __KERNEL__
 
@@ -263,7 +264,10 @@ typedef struct journal_superblock_s
 /* 0x0050 */
        __u8    s_checksum_type;        /* checksum type */
        __u8    s_padding2[3];
-       __u32   s_padding[42];
+/* 0x0054 */
+       __be32  s_num_fc_blks;          /* Number of fast commit blocks */
+/* 0x0058 */
+       __u32   s_padding[41];
        __be32  s_checksum;             /* crc32c(superblock) */
 
 /* 0x0100 */
@@ -397,7 +401,7 @@ static inline void jbd_unlock_bh_journal_head(struct buffer_head *bh)
 #define JI_WAIT_DATA (1 << __JI_WAIT_DATA)
 
 /**
- * struct jbd_inode - The jbd_inode type is the structure linking inodes in
+ * struct jbd2_inode - The jbd_inode type is the structure linking inodes in
  * ordered mode present in a transaction so that we can sync them during commit.
  */
 struct jbd2_inode {
@@ -941,8 +945,9 @@ struct journal_s
        /**
         * @j_fc_off:
         *
-        * Number of fast commit blocks currently allocated.
-        * [j_state_lock].
+        * Number of fast commit blocks currently allocated. Accessed only
+        * during fast commit. Currently only process can do fast commit, so
+        * this field is not protected by any lock.
         */
        unsigned long           j_fc_off;
 
@@ -985,9 +990,9 @@ struct journal_s
        struct block_device     *j_fs_dev;
 
        /**
-        * @j_maxlen: Total maximum capacity of the journal region on disk.
+        * @j_total_len: Total maximum capacity of the journal region on disk.
         */
-       unsigned int            j_maxlen;
+       unsigned int            j_total_len;
 
        /**
         * @j_reserved_credits:
@@ -1105,8 +1110,9 @@ struct journal_s
        struct buffer_head      **j_wbuf;
 
        /**
-        * @j_fc_wbuf: Array of fast commit bhs for
-        * jbd2_journal_commit_transaction.
+        * @j_fc_wbuf: Array of fast commit bhs for fast commit. Accessed only
+        * during a fast commit. Currently only process can do fast commit, so
+        * this field is not protected by any lock.
         */
        struct buffer_head      **j_fc_wbuf;
 
@@ -1253,7 +1259,7 @@ struct journal_s
         */
        void (*j_fc_cleanup_callback)(struct journal_s *journal, int);
 
-       /*
+       /**
         * @j_fc_replay_callback:
         *
         * File-system specific function that performs replay of a fast
@@ -1611,16 +1617,20 @@ extern void __jbd2_journal_drop_transaction(journal_t *, transaction_t *);
 extern int jbd2_cleanup_journal_tail(journal_t *);
 
 /* Fast commit related APIs */
-int jbd2_fc_init(journal_t *journal, int num_fc_blks);
 int jbd2_fc_begin_commit(journal_t *journal, tid_t tid);
 int jbd2_fc_end_commit(journal_t *journal);
-int jbd2_fc_end_commit_fallback(journal_t *journal, tid_t tid);
+int jbd2_fc_end_commit_fallback(journal_t *journal);
 int jbd2_fc_get_buf(journal_t *journal, struct buffer_head **bh_out);
 int jbd2_submit_inode_data(struct jbd2_inode *jinode);
 int jbd2_wait_inode_data(journal_t *journal, struct jbd2_inode *jinode);
 int jbd2_fc_wait_bufs(journal_t *journal, int num_blks);
 int jbd2_fc_release_bufs(journal_t *journal);
 
+static inline int jbd2_journal_get_max_txn_bufs(journal_t *journal)
+{
+       return (journal->j_total_len - journal->j_fc_wbufsize) / 4;
+}
+
 /*
  * is_journal_abort
  *
index cfb62e9f37be090da5a20e4b99c5d3bc31fe7f7e..ab7f8c152b89b4e791085900f78181b3b3444ee3 100644 (file)
@@ -99,6 +99,7 @@ static inline u32 jhash(const void *key, u32 length, u32 initval)
        case 2:  a += (u32)k[1]<<8;     fallthrough;
        case 1:  a += k[0];
                 __jhash_final(a, b, c);
+                break;
        case 0: /* Nothing left to add */
                break;
        }
@@ -136,6 +137,7 @@ static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
        case 2: b += k[1];      fallthrough;
        case 1: a += k[0];
                __jhash_final(a, b, c);
+               break;
        case 0: /* Nothing left to add */
                break;
        }
index 9542b41eacfdc5d3fa2ba7c0a0d5916ac18940af..35ce84c8ca02cefe55cdaebc16a75f11ec120409 100644 (file)
@@ -14,7 +14,7 @@
  */
 struct zynqmp_ipi_message {
        size_t len;
-       u8 data[0];
+       u8 data[];
 };
 
 #endif /* _LINUX_ZYNQMP_IPI_MESSAGE_H_ */
index e391e3c56de56f44ee7fe3f351ffe246e45dcbd7..922a7f60046586d9eecced516c9efcf2a7e04ec1 100644 (file)
@@ -282,20 +282,6 @@ struct mem_cgroup {
 
        MEMCG_PADDING(_pad1_);
 
-       /*
-        * set > 0 if pages under this cgroup are moving to other cgroup.
-        */
-       atomic_t                moving_account;
-       struct task_struct      *move_lock_task;
-
-       /* Legacy local VM stats and events */
-       struct memcg_vmstats_percpu __percpu *vmstats_local;
-
-       /* Subtree VM stats and events (batched updates) */
-       struct memcg_vmstats_percpu __percpu *vmstats_percpu;
-
-       MEMCG_PADDING(_pad2_);
-
        atomic_long_t           vmstats[MEMCG_NR_STAT];
        atomic_long_t           vmevents[NR_VM_EVENT_ITEMS];
 
@@ -317,6 +303,20 @@ struct mem_cgroup {
        struct list_head objcg_list; /* list of inherited objcgs */
 #endif
 
+       MEMCG_PADDING(_pad2_);
+
+       /*
+        * set > 0 if pages under this cgroup are moving to other cgroup.
+        */
+       atomic_t                moving_account;
+       struct task_struct      *move_lock_task;
+
+       /* Legacy local VM stats and events */
+       struct memcg_vmstats_percpu __percpu *vmstats_local;
+
+       /* Subtree VM stats and events (batched updates) */
+       struct memcg_vmstats_percpu __percpu *vmstats_percpu;
+
 #ifdef CONFIG_CGROUP_WRITEBACK
        struct list_head cgwb_list;
        struct wb_domain cgwb_domain;
@@ -900,12 +900,19 @@ static inline void count_memcg_event_mm(struct mm_struct *mm,
 static inline void memcg_memory_event(struct mem_cgroup *memcg,
                                      enum memcg_memory_event event)
 {
+       bool swap_event = event == MEMCG_SWAP_HIGH || event == MEMCG_SWAP_MAX ||
+                         event == MEMCG_SWAP_FAIL;
+
        atomic_long_inc(&memcg->memory_events_local[event]);
-       cgroup_file_notify(&memcg->events_local_file);
+       if (!swap_event)
+               cgroup_file_notify(&memcg->events_local_file);
 
        do {
                atomic_long_inc(&memcg->memory_events[event]);
-               cgroup_file_notify(&memcg->events_file);
+               if (swap_event)
+                       cgroup_file_notify(&memcg->swap_events_file);
+               else
+                       cgroup_file_notify(&memcg->events_file);
 
                if (!cgroup_subsys_on_dfl(memory_cgrp_subsys))
                        break;
index d65c6fdc5cfc39506cdf379e134ae3c168b2dcb8..551093b74596bcb6c2040d1bfe5c08755869f577 100644 (file)
@@ -281,20 +281,6 @@ static inline bool movable_node_is_enabled(void)
 }
 #endif /* ! CONFIG_MEMORY_HOTPLUG */
 
-#ifdef CONFIG_NUMA
-extern int memory_add_physaddr_to_nid(u64 start);
-extern int phys_to_target_node(u64 start);
-#else
-static inline int memory_add_physaddr_to_nid(u64 start)
-{
-       return 0;
-}
-static inline int phys_to_target_node(u64 start)
-{
-       return 0;
-}
-#endif
-
 #if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_DEFERRED_STRUCT_PAGE_INIT)
 /*
  * pgdat resizing functions
diff --git a/include/linux/mic_bus.h b/include/linux/mic_bus.h
deleted file mode 100644 (file)
index e99c789..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Intel MIC Bus driver.
- *
- * This implementation is very similar to the virtio bus driver
- * implementation @ include/linux/virtio.h.
- */
-#ifndef _MIC_BUS_H_
-#define _MIC_BUS_H_
-/*
- * Everything a mbus driver needs to work with any particular mbus
- * implementation.
- */
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-
-struct mbus_device_id {
-       __u32 device;
-       __u32 vendor;
-};
-
-#define MBUS_DEV_DMA_HOST 2
-#define MBUS_DEV_DMA_MIC 3
-#define MBUS_DEV_ANY_ID 0xffffffff
-
-/**
- * mbus_device - representation of a device using mbus
- * @mmio_va: virtual address of mmio space
- * @hw_ops: the hardware ops supported by this device.
- * @id: the device type identification (used to match it with a driver).
- * @dev: underlying device.
- * be used to communicate with.
- * @index: unique position on the mbus bus
- */
-struct mbus_device {
-       void __iomem *mmio_va;
-       struct mbus_hw_ops *hw_ops;
-       struct mbus_device_id id;
-       struct device dev;
-       int index;
-};
-
-/**
- * mbus_driver - operations for a mbus I/O driver
- * @driver: underlying device driver (populate name and owner).
- * @id_table: the ids serviced by this driver.
- * @probe: the function to call when a device is found.  Returns 0 or -errno.
- * @remove: the function to call when a device is removed.
- */
-struct mbus_driver {
-       struct device_driver driver;
-       const struct mbus_device_id *id_table;
-       int (*probe)(struct mbus_device *dev);
-       void (*scan)(struct mbus_device *dev);
-       void (*remove)(struct mbus_device *dev);
-};
-
-/**
- * struct mic_irq - opaque pointer used as cookie
- */
-struct mic_irq;
-
-/**
- * mbus_hw_ops - Hardware operations for accessing a MIC device on the MIC bus.
- */
-struct mbus_hw_ops {
-       struct mic_irq* (*request_threaded_irq)(struct mbus_device *mbdev,
-                                               irq_handler_t handler,
-                                               irq_handler_t thread_fn,
-                                               const char *name, void *data,
-                                               int intr_src);
-       void (*free_irq)(struct mbus_device *mbdev,
-                        struct mic_irq *cookie, void *data);
-       void (*ack_interrupt)(struct mbus_device *mbdev, int num);
-};
-
-struct mbus_device *
-mbus_register_device(struct device *pdev, int id, const struct dma_map_ops *dma_ops,
-                    struct mbus_hw_ops *hw_ops, int index,
-                    void __iomem *mmio_va);
-void mbus_unregister_device(struct mbus_device *mbdev);
-
-int mbus_register_driver(struct mbus_driver *drv);
-void mbus_unregister_driver(struct mbus_driver *drv);
-
-static inline struct mbus_device *dev_to_mbus(struct device *_dev)
-{
-       return container_of(_dev, struct mbus_device, dev);
-}
-
-static inline struct mbus_driver *drv_to_mbus(struct device_driver *drv)
-{
-       return container_of(drv, struct mbus_driver, driver);
-}
-
-#endif /* _MIC_BUS_H */
index add85094f9a58c14579fc624fd379be15c32e59e..0f23e1ed5e71095a38df7dc153b01b15e55a8472 100644 (file)
@@ -1213,4 +1213,22 @@ static inline bool mlx5_is_roce_enabled(struct mlx5_core_dev *dev)
        return val.vbool;
 }
 
+/**
+ * mlx5_core_net - Provide net namespace of the mlx5_core_dev
+ * @dev: mlx5 core device
+ *
+ * mlx5_core_net() returns the net namespace of mlx5 core device.
+ * This can be called only in below described limited context.
+ * (a) When a devlink instance for mlx5_core is registered and
+ *     when devlink reload operation is disabled.
+ *     or
+ * (b) during devlink reload reload_down() and reload_up callbacks
+ *     where it is ensured that devlink instance's net namespace is
+ *     stable.
+ */
+static inline struct net *mlx5_core_net(struct mlx5_core_dev *dev)
+{
+       return devlink_net(priv_to_devlink(dev));
+}
+
 #endif /* MLX5_DRIVER_H */
index 651591a2965d218b71a82f3daa975a2956d9b3d0..233352447b1a4044d0bf41c4fad51899fb78fd43 100644 (file)
@@ -1223,6 +1223,11 @@ enum mlx5_fc_bulk_alloc_bitmask {
 
 #define MLX5_FC_BULK_NUM_FCS(fc_enum) (MLX5_FC_BULK_SIZE_FACTOR * (fc_enum))
 
+enum {
+       MLX5_STEERING_FORMAT_CONNECTX_5   = 0,
+       MLX5_STEERING_FORMAT_CONNECTX_6DX = 1,
+};
+
 struct mlx5_ifc_cmd_hca_cap_bits {
        u8         reserved_at_0[0x30];
        u8         vhca_id[0x10];
@@ -1521,7 +1526,9 @@ struct mlx5_ifc_cmd_hca_cap_bits {
 
        u8         general_obj_types[0x40];
 
-       u8         reserved_at_440[0x20];
+       u8         reserved_at_440[0x4];
+       u8         steering_format_version[0x4];
+       u8         create_qp_start_hint[0x18];
 
        u8         reserved_at_460[0x3];
        u8         log_max_uctx[0x5];
@@ -5823,7 +5830,7 @@ struct mlx5_ifc_alloc_modify_header_context_in_bits {
        u8         reserved_at_68[0x10];
        u8         num_of_actions[0x8];
 
-       union mlx5_ifc_set_add_copy_action_in_auto_bits actions[0];
+       union mlx5_ifc_set_add_copy_action_in_auto_bits actions[];
 };
 
 struct mlx5_ifc_dealloc_modify_header_context_out_bits {
@@ -9761,7 +9768,7 @@ struct mlx5_ifc_mcda_reg_bits {
 
        u8         reserved_at_60[0x20];
 
-       u8         data[0][0x20];
+       u8         data[][0x20];
 };
 
 enum {
index ef360fe70aafcf6d2e40bc5b89a4cd0fc82a1bc9..db6ae4d3fb4edc82ad0c7ccf80eac47726862b20 100644 (file)
@@ -2759,6 +2759,15 @@ static inline vm_fault_t vmf_insert_page(struct vm_area_struct *vma,
        return VM_FAULT_NOPAGE;
 }
 
+#ifndef io_remap_pfn_range
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+                                    unsigned long addr, unsigned long pfn,
+                                    unsigned long size, pgprot_t prot)
+{
+       return remap_pfn_range(vma, addr, pfn, size, pgprot_decrypted(prot));
+}
+#endif
+
 static inline vm_fault_t vmf_error(int err)
 {
        if (err == -ENOMEM)
index 7ccdf87f376fc3c9c9c3a4bb1ce92cd321df2354..6264617bab4d46c542f86803a860d5a0a51c6214 100644 (file)
@@ -740,7 +740,7 @@ static inline bool within_module(unsigned long addr, const struct module *mod)
 }
 
 /* Get/put a kernel symbol (calls should be symmetric) */
-#define symbol_get(x) ({ extern typeof(x) x __attribute__((weak)); &(x); })
+#define symbol_get(x) ({ extern typeof(x) x __attribute__((weak,visibility("hidden"))); &(x); })
 #define symbol_put(x) do { } while (0)
 #define symbol_put_addr(x) do { } while (0)
 
index 964b494b0e8d3ea893f4263236e80e0255f01b0d..7c3da0e1ea9d483605f2c775ccdda19ebb5b3a64 100644 (file)
@@ -2813,9 +2813,21 @@ u16 dev_pick_tx_zero(struct net_device *dev, struct sk_buff *skb,
                     struct net_device *sb_dev);
 u16 dev_pick_tx_cpu_id(struct net_device *dev, struct sk_buff *skb,
                       struct net_device *sb_dev);
+
 int dev_queue_xmit(struct sk_buff *skb);
 int dev_queue_xmit_accel(struct sk_buff *skb, struct net_device *sb_dev);
-int dev_direct_xmit(struct sk_buff *skb, u16 queue_id);
+int __dev_direct_xmit(struct sk_buff *skb, u16 queue_id);
+
+static inline int dev_direct_xmit(struct sk_buff *skb, u16 queue_id)
+{
+       int ret;
+
+       ret = __dev_direct_xmit(skb, queue_id);
+       if (!dev_xmit_complete(ret))
+               kfree_skb(skb);
+       return ret;
+}
+
 int register_netdevice(struct net_device *dev);
 void unregister_netdevice_queue(struct net_device *dev, struct list_head *head);
 void unregister_netdevice_many(struct list_head *head);
@@ -3137,6 +3149,11 @@ static inline bool dev_validate_header(const struct net_device *dev,
        return false;
 }
 
+static inline bool dev_has_header(const struct net_device *dev)
+{
+       return dev->header_ops && dev->header_ops->create;
+}
+
 typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr,
                           int len, int size);
 int register_gifconf(unsigned int family, gifconf_func_t *gifconf);
index 89016d08f6a278d9a7703cc4256c277f05fa7173..f6267e2883f261e0bd533a349759fad1b7e8d656 100644 (file)
@@ -24,6 +24,12 @@ struct nfnl_callback {
        const u_int16_t attr_count;             /* number of nlattr's */
 };
 
+enum nfnl_abort_action {
+       NFNL_ABORT_NONE         = 0,
+       NFNL_ABORT_AUTOLOAD,
+       NFNL_ABORT_VALIDATE,
+};
+
 struct nfnetlink_subsystem {
        const char *name;
        __u8 subsys_id;                 /* nfnetlink subsystem ID */
@@ -31,7 +37,8 @@ struct nfnetlink_subsystem {
        const struct nfnl_callback *cb; /* callback for individual types */
        struct module *owner;
        int (*commit)(struct net *net, struct sk_buff *skb);
-       int (*abort)(struct net *net, struct sk_buff *skb, bool autoload);
+       int (*abort)(struct net *net, struct sk_buff *skb,
+                    enum nfnl_abort_action action);
        void (*cleanup)(struct net *net);
        bool (*valid_genid)(struct net *net, u32 genid);
 };
index 082e2c41b7ff90a8e03c55f2f78c4d1129345760..5b70ca868bb1907165cc68b364534849a3a37f0c 100644 (file)
@@ -16,7 +16,7 @@ struct ip_rt_info {
        u_int32_t mark;
 };
 
-int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned addr_type);
+int ip_route_me_harder(struct net *net, struct sock *sk, struct sk_buff *skb, unsigned addr_type);
 
 struct nf_queue_entry;
 
index 9b67394471e1c63462327d5cefdd7ab2701e0acf..48314ade1506f2108e32a56a9bab93599ba67152 100644 (file)
@@ -42,7 +42,7 @@ struct nf_ipv6_ops {
 #if IS_MODULE(CONFIG_IPV6)
        int (*chk_addr)(struct net *net, const struct in6_addr *addr,
                        const struct net_device *dev, int strict);
-       int (*route_me_harder)(struct net *net, struct sk_buff *skb);
+       int (*route_me_harder)(struct net *net, struct sock *sk, struct sk_buff *skb);
        int (*dev_get_saddr)(struct net *net, const struct net_device *dev,
                       const struct in6_addr *daddr, unsigned int srcprefs,
                       struct in6_addr *saddr);
@@ -143,9 +143,9 @@ static inline int nf_br_ip6_fragment(struct net *net, struct sock *sk,
 #endif
 }
 
-int ip6_route_me_harder(struct net *net, struct sk_buff *skb);
+int ip6_route_me_harder(struct net *net, struct sock *sk, struct sk_buff *skb);
 
-static inline int nf_ip6_route_me_harder(struct net *net, struct sk_buff *skb)
+static inline int nf_ip6_route_me_harder(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
 #if IS_MODULE(CONFIG_IPV6)
        const struct nf_ipv6_ops *v6_ops = nf_get_ipv6_ops();
@@ -153,9 +153,9 @@ static inline int nf_ip6_route_me_harder(struct net *net, struct sk_buff *skb)
        if (!v6_ops)
                return -EHOSTUNREACH;
 
-       return v6_ops->route_me_harder(net, skb);
+       return v6_ops->route_me_harder(net, sk, skb);
 #elif IS_BUILTIN(CONFIG_IPV6)
-       return ip6_route_me_harder(net, skb);
+       return ip6_route_me_harder(net, sk, skb);
 #else
        return -EHOSTUNREACH;
 #endif
index 8cb33ccfb671e9b3b467dfbc5368ffc9f576fff8..cb44cfe2b7255a66722c09bfbd88d1b3714121ba 100644 (file)
 #endif
 
 #ifdef CONFIG_NUMA
+#include <linux/printk.h>
+#include <asm/sparsemem.h>
+
 /* Generic implementation available */
 int numa_map_to_online_node(int node);
-#else
+
+#ifndef memory_add_physaddr_to_nid
+static inline int memory_add_physaddr_to_nid(u64 start)
+{
+       pr_info_once("Unknown online node for memory at 0x%llx, assuming node 0\n",
+                       start);
+       return 0;
+}
+#endif
+#ifndef phys_to_target_node
+static inline int phys_to_target_node(u64 start)
+{
+       pr_info_once("Unknown target node for memory at 0x%llx, assuming node 0\n",
+                       start);
+       return 0;
+}
+#endif
+#else /* !CONFIG_NUMA */
 static inline int numa_map_to_online_node(int node)
 {
        return NUMA_NO_NODE;
 }
+static inline int memory_add_physaddr_to_nid(u64 start)
+{
+       return 0;
+}
+static inline int phys_to_target_node(u64 start)
+{
+       return 0;
+}
 #endif
 
 #endif /* _LINUX_NUMA_H */
index c77b7c31b2e49563a5c5d853bbd9c55cc725a29b..d5570deff4003f0cec29eed2cfbb77b06a8f0cec 100644 (file)
@@ -344,9 +344,9 @@ static inline struct page *find_get_page_flags(struct address_space *mapping,
 /**
  * find_lock_page - locate, pin and lock a pagecache page
  * @mapping: the address_space to search
- * @offset: the page index
+ * @index: the page index
  *
- * Looks up the page cache entry at @mapping & @offset.  If there is a
+ * Looks up the page cache entry at @mapping & @index.  If there is a
  * page cache page, it is returned locked and with an increased
  * refcount.
  *
@@ -363,9 +363,9 @@ static inline struct page *find_lock_page(struct address_space *mapping,
 /**
  * find_lock_head - Locate, pin and lock a pagecache page.
  * @mapping: The address_space to search.
- * @offset: The page index.
+ * @index: The page index.
  *
- * Looks up the page cache entry at @mapping & @offset.  If there is a
+ * Looks up the page cache entry at @mapping & @index.  If there is a
  * page cache page, its head page is returned locked and with an increased
  * refcount.
  *
@@ -906,6 +906,8 @@ static inline unsigned int __readahead_batch(struct readahead_control *rac,
        xas_set(&xas, rac->_index);
        rcu_read_lock();
        xas_for_each(&xas, page, rac->_index + rac->_nr_pages - 1) {
+               if (xas_retry(&xas, page))
+                       continue;
                VM_BUG_ON_PAGE(!PageLocked(page), page);
                VM_BUG_ON_PAGE(PageTail(page), page);
                array[i++] = page;
index 0c19d279b97f5956de14936884b919fdaa8bf4ef..96450f6fb1de888ed1135303c4a4387308656771 100644 (file)
@@ -1022,13 +1022,7 @@ struct perf_sample_data {
        struct perf_callchain_entry     *callchain;
        u64                             aux_size;
 
-       /*
-        * regs_user may point to task_pt_regs or to regs_user_copy, depending
-        * on arch details.
-        */
        struct perf_regs                regs_user;
-       struct pt_regs                  regs_user_copy;
-
        struct perf_regs                regs_intr;
        u64                             stack_user_size;
 
@@ -1400,11 +1394,14 @@ perf_event_addr_filters(struct perf_event *event)
 extern void perf_event_addr_filters_sync(struct perf_event *event);
 
 extern int perf_output_begin(struct perf_output_handle *handle,
+                            struct perf_sample_data *data,
                             struct perf_event *event, unsigned int size);
 extern int perf_output_begin_forward(struct perf_output_handle *handle,
-                                   struct perf_event *event,
-                                   unsigned int size);
+                                    struct perf_sample_data *data,
+                                    struct perf_event *event,
+                                    unsigned int size);
 extern int perf_output_begin_backward(struct perf_output_handle *handle,
+                                     struct perf_sample_data *data,
                                      struct perf_event *event,
                                      unsigned int size);
 
index 2d12e97d5e7bc16a3edf1c9a39e177f7b73e5874..f632c5725f162f723fd3536f64c0eaf64b7ae391 100644 (file)
@@ -20,8 +20,7 @@ u64 perf_reg_value(struct pt_regs *regs, int idx);
 int perf_reg_validate(u64 mask);
 u64 perf_reg_abi(struct task_struct *task);
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy);
+                       struct pt_regs *regs);
 #else
 
 #define PERF_REG_EXTENDED_MASK 0
@@ -42,8 +41,7 @@ static inline u64 perf_reg_abi(struct task_struct *task)
 }
 
 static inline void perf_get_regs_user(struct perf_regs *regs_user,
-                                     struct pt_regs *regs,
-                                     struct pt_regs *regs_user_copy)
+                                     struct pt_regs *regs)
 {
        regs_user->regs = task_pt_regs(current);
        regs_user->abi = perf_reg_abi(current);
index 38c33eabea8942bb09e09d4976f0203d61f70246..e237004d498d6b02702e2058076dfb165792ce15 100644 (file)
@@ -1427,8 +1427,17 @@ typedef unsigned int pgtbl_mod_mask;
 
 #endif /* !__ASSEMBLY__ */
 
-#ifndef io_remap_pfn_range
-#define io_remap_pfn_range remap_pfn_range
+#if !defined(MAX_POSSIBLE_PHYSMEM_BITS) && !defined(CONFIG_64BIT)
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+/*
+ * ZSMALLOC needs to know the highest PFN on 32-bit architectures
+ * with physical address space extension, but falls back to
+ * BITS_PER_LONG otherwise.
+ */
+#error Missing MAX_POSSIBLE_PHYSMEM_BITS definition
+#else
+#define MAX_POSSIBLE_PHYSMEM_BITS 32
+#endif
 #endif
 
 #ifndef has_transparent_hugepage
index eb3cb1a98b450267b248d51d90de46b8883aca10..56563e5e0dc7513706bb6a856cf671d1f099c044 100644 (file)
@@ -147,16 +147,8 @@ typedef enum {
        PHY_INTERFACE_MODE_MAX,
 } phy_interface_t;
 
-/**
+/*
  * phy_supported_speeds - return all speeds currently supported by a PHY device
- * @phy: The PHY device to return supported speeds of.
- * @speeds: buffer to store supported speeds in.
- * @size: size of speeds buffer.
- *
- * Description: Returns the number of supported speeds, and fills
- * the speeds buffer with the supported speeds. If speeds buffer is
- * too small to contain all currently supported speeds, will return as
- * many speeds as can fit.
  */
 unsigned int phy_supported_speeds(struct phy_device *phy,
                                      unsigned int *speeds,
@@ -1022,14 +1014,9 @@ static inline int __phy_modify_changed(struct phy_device *phydev, u32 regnum,
                                        regnum, mask, set);
 }
 
-/**
+/*
  * phy_read_mmd - Convenience function for reading a register
  * from an MMD on a given PHY.
- * @phydev: The phy_device struct
- * @devad: The MMD to read from
- * @regnum: The register on the MMD to read
- *
- * Same rules as for phy_read();
  */
 int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum);
 
@@ -1064,38 +1051,21 @@ int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum);
        __ret; \
 })
 
-/**
+/*
  * __phy_read_mmd - Convenience function for reading a register
  * from an MMD on a given PHY.
- * @phydev: The phy_device struct
- * @devad: The MMD to read from
- * @regnum: The register on the MMD to read
- *
- * Same rules as for __phy_read();
  */
 int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum);
 
-/**
+/*
  * phy_write_mmd - Convenience function for writing a register
  * on an MMD on a given PHY.
- * @phydev: The phy_device struct
- * @devad: The MMD to write to
- * @regnum: The register on the MMD to read
- * @val: value to write to @regnum
- *
- * Same rules as for phy_write();
  */
 int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
 
-/**
+/*
  * __phy_write_mmd - Convenience function for writing a register
  * on an MMD on a given PHY.
- * @phydev: The phy_device struct
- * @devad: The MMD to write to
- * @regnum: The register on the MMD to read
- * @val: value to write to @regnum
- *
- * Same rules as for __phy_write();
  */
 int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
 
index 1fcfe9e63cb9b7d9a44180ac40e374572db4630e..a3a9a878415f10b44b78dfda15878b39a5c3a843 100644 (file)
@@ -1419,7 +1419,7 @@ struct ec_response_flash_info_2 {
        uint16_t num_banks_total;
        /* Number of banks described in banks array. */
        uint16_t num_banks_desc;
-       struct ec_flash_bank banks[0];
+       struct ec_flash_bank banks[];
 } __ec_align4;
 
 /*
@@ -2420,12 +2420,12 @@ struct ec_response_motion_sense_fifo_info {
        /* Total amount of vector lost */
        uint16_t total_lost;
        /* Lost events since the last fifo_info, per sensors */
-       uint16_t lost[0];
+       uint16_t lost[];
 } __ec_todo_packed;
 
 struct ec_response_motion_sense_fifo_data {
        uint32_t number_data;
-       struct ec_response_motion_sensor_data data[0];
+       struct ec_response_motion_sensor_data data[];
 } __ec_todo_packed;
 
 /* List supported activity recognition */
@@ -3093,7 +3093,7 @@ struct ec_response_tmp006_get_calibration_v1 {
        uint8_t algorithm;
        uint8_t num_params;
        uint8_t reserved[2];
-       float val[0];
+       float val[];
 } __ec_align4;
 
 struct ec_params_tmp006_set_calibration_v1 {
@@ -3101,7 +3101,7 @@ struct ec_params_tmp006_set_calibration_v1 {
        uint8_t algorithm;
        uint8_t num_params;
        uint8_t reserved;
-       float val[0];
+       float val[];
 } __ec_align4;
 
 
@@ -5076,7 +5076,7 @@ struct ec_response_pd_log {
        uint8_t type;       /* event type : see PD_EVENT_xx below */
        uint8_t size_port;  /* [7:5] port number [4:0] payload size in bytes */
        uint16_t data;      /* type-defined data payload */
-       uint8_t payload[0]; /* optional additional data payload: 0..16 bytes */
+       uint8_t payload[];  /* optional additional data payload: 0..16 bytes */
 } __ec_align4;
 
 /* The timestamp is the microsecond counter shifted to get about a ms. */
@@ -5789,7 +5789,7 @@ struct ec_response_fp_encryption_status {
 
 struct ec_response_tp_frame_info {
        uint32_t n_frames;
-       uint32_t frame_sizes[0];
+       uint32_t frame_sizes[];
 } __ec_align4;
 
 /* Create a snapshot of current frame readings */
index 4a415ae851ef0891538e0ab3a3f93d08e818d3ac..02599687770c548ee4e8650c156fe65c5f8776d8 100644 (file)
@@ -69,7 +69,7 @@ struct cros_ec_command {
        uint32_t outsize;
        uint32_t insize;
        uint32_t result;
-       uint8_t data[0];
+       uint8_t data[];
 };
 
 /**
index c59999ce044e50731fffe75edc5b90b036da77df..240dce553a0bdde2a7f38f895e0064b7d1a9bbe5 100644 (file)
@@ -50,6 +50,7 @@ struct sysc_regbits {
        s8 emufree_shift;
 };
 
+#define SYSC_MODULE_QUIRK_ENA_RESETDONE        BIT(25)
 #define SYSC_MODULE_QUIRK_PRUSS                BIT(24)
 #define SYSC_MODULE_QUIRK_DSS_RESET    BIT(23)
 #define SYSC_MODULE_QUIRK_RTC_UNLOCK   BIT(22)
index 18b02dcc168e54fb1036877d55f2c1e6a42fae0d..b492ae00cc9088e61f61042a0c1b0fa576c6c18b 100644 (file)
@@ -54,11 +54,10 @@ extern u64 pm_runtime_autosuspend_expiration(struct device *dev);
 extern void pm_runtime_update_max_time_suspended(struct device *dev,
                                                 s64 delta_ns);
 extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable);
-extern void pm_runtime_clean_up_links(struct device *dev);
 extern void pm_runtime_get_suppliers(struct device *dev);
 extern void pm_runtime_put_suppliers(struct device *dev);
 extern void pm_runtime_new_link(struct device *dev);
-extern void pm_runtime_drop_link(struct device *dev);
+extern void pm_runtime_drop_link(struct device_link *link);
 
 /**
  * pm_runtime_get_if_in_use - Conditionally bump up runtime PM usage counter.
@@ -276,11 +275,10 @@ static inline u64 pm_runtime_autosuspend_expiration(
                                struct device *dev) { return 0; }
 static inline void pm_runtime_set_memalloc_noio(struct device *dev,
                                                bool enable){}
-static inline void pm_runtime_clean_up_links(struct device *dev) {}
 static inline void pm_runtime_get_suppliers(struct device *dev) {}
 static inline void pm_runtime_put_suppliers(struct device *dev) {}
 static inline void pm_runtime_new_link(struct device *dev) {}
-static inline void pm_runtime_drop_link(struct device *dev) {}
+static inline void pm_runtime_drop_link(struct device_link *link) {}
 
 #endif /* !CONFIG_PM */
 
@@ -388,6 +386,27 @@ static inline int pm_runtime_get_sync(struct device *dev)
        return __pm_runtime_resume(dev, RPM_GET_PUT);
 }
 
+/**
+ * pm_runtime_resume_and_get - Bump up usage counter of a device and resume it.
+ * @dev: Target device.
+ *
+ * Resume @dev synchronously and if that is successful, increment its runtime
+ * PM usage counter. Return 0 if the runtime PM usage counter of @dev has been
+ * incremented or a negative error code otherwise.
+ */
+static inline int pm_runtime_resume_and_get(struct device *dev)
+{
+       int ret;
+
+       ret = __pm_runtime_resume(dev, RPM_GET_PUT);
+       if (ret < 0) {
+               pm_runtime_put_noidle(dev);
+               return ret;
+       }
+
+       return 0;
+}
+
 /**
  * pm_runtime_put - Drop device usage counter and queue up "idle check" if 0.
  * @dev: Target device.
index 7fabb1af18e042e2aa126f132eed2d5a4d994e43..497990c69b0bf1352d47ecf7a79e30ff5cc71090 100644 (file)
@@ -147,24 +147,6 @@ static inline unsigned int refcount_read(const refcount_t *r)
        return atomic_read(&r->refs);
 }
 
-/**
- * refcount_add_not_zero - add a value to a refcount unless it is 0
- * @i: the value to add to the refcount
- * @r: the refcount
- *
- * Will saturate at REFCOUNT_SATURATED and WARN.
- *
- * Provides no memory ordering, it is assumed the caller has guaranteed the
- * object memory to be stable (RCU, etc.). It does provide a control dependency
- * and thereby orders future stores. See the comment on top.
- *
- * Use of this function is not recommended for the normal reference counting
- * use case in which references are taken and released one at a time.  In these
- * cases, refcount_inc(), or one of its variants, should instead be used to
- * increment a reference count.
- *
- * Return: false if the passed refcount is 0, true otherwise
- */
 static inline __must_check bool __refcount_add_not_zero(int i, refcount_t *r, int *oldp)
 {
        int old = refcount_read(r);
@@ -183,17 +165,12 @@ static inline __must_check bool __refcount_add_not_zero(int i, refcount_t *r, in
        return old;
 }
 
-static inline __must_check bool refcount_add_not_zero(int i, refcount_t *r)
-{
-       return __refcount_add_not_zero(i, r, NULL);
-}
-
 /**
- * refcount_add - add a value to a refcount
+ * refcount_add_not_zero - add a value to a refcount unless it is 0
  * @i: the value to add to the refcount
  * @r: the refcount
  *
- * Similar to atomic_add(), but will saturate at REFCOUNT_SATURATED and WARN.
+ * Will saturate at REFCOUNT_SATURATED and WARN.
  *
  * Provides no memory ordering, it is assumed the caller has guaranteed the
  * object memory to be stable (RCU, etc.). It does provide a control dependency
@@ -203,7 +180,14 @@ static inline __must_check bool refcount_add_not_zero(int i, refcount_t *r)
  * use case in which references are taken and released one at a time.  In these
  * cases, refcount_inc(), or one of its variants, should instead be used to
  * increment a reference count.
+ *
+ * Return: false if the passed refcount is 0, true otherwise
  */
+static inline __must_check bool refcount_add_not_zero(int i, refcount_t *r)
+{
+       return __refcount_add_not_zero(i, r, NULL);
+}
+
 static inline void __refcount_add(int i, refcount_t *r, int *oldp)
 {
        int old = atomic_fetch_add_relaxed(i, &r->refs);
@@ -217,11 +201,32 @@ static inline void __refcount_add(int i, refcount_t *r, int *oldp)
                refcount_warn_saturate(r, REFCOUNT_ADD_OVF);
 }
 
+/**
+ * refcount_add - add a value to a refcount
+ * @i: the value to add to the refcount
+ * @r: the refcount
+ *
+ * Similar to atomic_add(), but will saturate at REFCOUNT_SATURATED and WARN.
+ *
+ * Provides no memory ordering, it is assumed the caller has guaranteed the
+ * object memory to be stable (RCU, etc.). It does provide a control dependency
+ * and thereby orders future stores. See the comment on top.
+ *
+ * Use of this function is not recommended for the normal reference counting
+ * use case in which references are taken and released one at a time.  In these
+ * cases, refcount_inc(), or one of its variants, should instead be used to
+ * increment a reference count.
+ */
 static inline void refcount_add(int i, refcount_t *r)
 {
        __refcount_add(i, r, NULL);
 }
 
+static inline __must_check bool __refcount_inc_not_zero(refcount_t *r, int *oldp)
+{
+       return __refcount_add_not_zero(1, r, oldp);
+}
+
 /**
  * refcount_inc_not_zero - increment a refcount unless it is 0
  * @r: the refcount to increment
@@ -235,14 +240,14 @@ static inline void refcount_add(int i, refcount_t *r)
  *
  * Return: true if the increment was successful, false otherwise
  */
-static inline __must_check bool __refcount_inc_not_zero(refcount_t *r, int *oldp)
+static inline __must_check bool refcount_inc_not_zero(refcount_t *r)
 {
-       return __refcount_add_not_zero(1, r, oldp);
+       return __refcount_inc_not_zero(r, NULL);
 }
 
-static inline __must_check bool refcount_inc_not_zero(refcount_t *r)
+static inline void __refcount_inc(refcount_t *r, int *oldp)
 {
-       return __refcount_inc_not_zero(r, NULL);
+       __refcount_add(1, r, oldp);
 }
 
 /**
@@ -257,14 +262,27 @@ static inline __must_check bool refcount_inc_not_zero(refcount_t *r)
  * Will WARN if the refcount is 0, as this represents a possible use-after-free
  * condition.
  */
-static inline void __refcount_inc(refcount_t *r, int *oldp)
+static inline void refcount_inc(refcount_t *r)
 {
-       __refcount_add(1, r, oldp);
+       __refcount_inc(r, NULL);
 }
 
-static inline void refcount_inc(refcount_t *r)
+static inline __must_check bool __refcount_sub_and_test(int i, refcount_t *r, int *oldp)
 {
-       __refcount_inc(r, NULL);
+       int old = atomic_fetch_sub_release(i, &r->refs);
+
+       if (oldp)
+               *oldp = old;
+
+       if (old == i) {
+               smp_acquire__after_ctrl_dep();
+               return true;
+       }
+
+       if (unlikely(old < 0 || old - i < 0))
+               refcount_warn_saturate(r, REFCOUNT_SUB_UAF);
+
+       return false;
 }
 
 /**
@@ -287,27 +305,14 @@ static inline void refcount_inc(refcount_t *r)
  *
  * Return: true if the resulting refcount is 0, false otherwise
  */
-static inline __must_check bool __refcount_sub_and_test(int i, refcount_t *r, int *oldp)
+static inline __must_check bool refcount_sub_and_test(int i, refcount_t *r)
 {
-       int old = atomic_fetch_sub_release(i, &r->refs);
-
-       if (oldp)
-               *oldp = old;
-
-       if (old == i) {
-               smp_acquire__after_ctrl_dep();
-               return true;
-       }
-
-       if (unlikely(old < 0 || old - i < 0))
-               refcount_warn_saturate(r, REFCOUNT_SUB_UAF);
-
-       return false;
+       return __refcount_sub_and_test(i, r, NULL);
 }
 
-static inline __must_check bool refcount_sub_and_test(int i, refcount_t *r)
+static inline __must_check bool __refcount_dec_and_test(refcount_t *r, int *oldp)
 {
-       return __refcount_sub_and_test(i, r, NULL);
+       return __refcount_sub_and_test(1, r, oldp);
 }
 
 /**
@@ -323,26 +328,11 @@ static inline __must_check bool refcount_sub_and_test(int i, refcount_t *r)
  *
  * Return: true if the resulting refcount is 0, false otherwise
  */
-static inline __must_check bool __refcount_dec_and_test(refcount_t *r, int *oldp)
-{
-       return __refcount_sub_and_test(1, r, oldp);
-}
-
 static inline __must_check bool refcount_dec_and_test(refcount_t *r)
 {
        return __refcount_dec_and_test(r, NULL);
 }
 
-/**
- * refcount_dec - decrement a refcount
- * @r: the refcount
- *
- * Similar to atomic_dec(), it will WARN on underflow and fail to decrement
- * when saturated at REFCOUNT_SATURATED.
- *
- * Provides release memory ordering, such that prior loads and stores are done
- * before.
- */
 static inline void __refcount_dec(refcount_t *r, int *oldp)
 {
        int old = atomic_fetch_sub_release(1, &r->refs);
@@ -354,6 +344,16 @@ static inline void __refcount_dec(refcount_t *r, int *oldp)
                refcount_warn_saturate(r, REFCOUNT_DEC_LEAK);
 }
 
+/**
+ * refcount_dec - decrement a refcount
+ * @r: the refcount
+ *
+ * Similar to atomic_dec(), it will WARN on underflow and fail to decrement
+ * when saturated at REFCOUNT_SATURATED.
+ *
+ * Provides release memory ordering, such that prior loads and stores are done
+ * before.
+ */
 static inline void refcount_dec(refcount_t *r)
 {
        __refcount_dec(r, NULL);
index 063cd120b459339443db7b003df5cd22140316c6..76cd21fa55016e5e8ab7a09cec3d1516a18f5998 100644 (file)
@@ -552,7 +552,6 @@ struct sched_dl_entity {
         * overruns.
         */
        unsigned int                    dl_throttled      : 1;
-       unsigned int                    dl_boosted        : 1;
        unsigned int                    dl_yielded        : 1;
        unsigned int                    dl_non_contending : 1;
        unsigned int                    dl_overrun        : 1;
@@ -571,6 +570,15 @@ struct sched_dl_entity {
         * time.
         */
        struct hrtimer inactive_timer;
+
+#ifdef CONFIG_RT_MUTEXES
+       /*
+        * Priority Inheritance. When a DEADLINE scheduling entity is boosted
+        * pi_se points to the donor, otherwise points to the dl_se it belongs
+        * to (the original one/itself).
+        */
+       struct sched_dl_entity *pi_se;
+#endif
 };
 
 #ifdef CONFIG_UCLAMP_TASK
@@ -770,7 +778,6 @@ struct task_struct {
        unsigned                        sched_reset_on_fork:1;
        unsigned                        sched_contributes_to_load:1;
        unsigned                        sched_migrated:1;
-       unsigned                        sched_remote_wakeup:1;
 #ifdef CONFIG_PSI
        unsigned                        sched_psi_wake_requeue:1;
 #endif
@@ -780,6 +787,21 @@ struct task_struct {
 
        /* Unserialized, strictly 'current' */
 
+       /*
+        * This field must not be in the scheduler word above due to wakelist
+        * queueing no longer being serialized by p->on_cpu. However:
+        *
+        * p->XXX = X;                  ttwu()
+        * schedule()                     if (p->on_rq && ..) // false
+        *   smp_mb__after_spinlock();    if (smp_load_acquire(&p->on_cpu) && //true
+        *   deactivate_task()                ttwu_queue_wakelist())
+        *     p->on_rq = 0;                    p->sched_remote_wakeup = Y;
+        *
+        * guarantees all stores of 'current' are visible before
+        * ->sched_remote_wakeup gets used, so it can be in this word.
+        */
+       unsigned                        sched_remote_wakeup:1;
+
        /* Bit to tell LSMs we're in execve(): */
        unsigned                        in_execve:1;
        unsigned                        in_iowait:1;
diff --git a/include/linux/scif.h b/include/linux/scif.h
deleted file mode 100644 (file)
index 329e695..0000000
+++ /dev/null
@@ -1,1339 +0,0 @@
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Copyright(c) 2014 Intel Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in
- *   the documentation and/or other materials provided with the
- *   distribution.
- * * Neither the name of Intel Corporation nor the names of its
- *   contributors may be used to endorse or promote products derived
- *   from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Intel SCIF driver.
- *
- */
-#ifndef __SCIF_H__
-#define __SCIF_H__
-
-#include <linux/types.h>
-#include <linux/poll.h>
-#include <linux/device.h>
-#include <linux/scif_ioctl.h>
-
-#define SCIF_ACCEPT_SYNC       1
-#define SCIF_SEND_BLOCK                1
-#define SCIF_RECV_BLOCK                1
-
-enum {
-       SCIF_PROT_READ = (1 << 0),
-       SCIF_PROT_WRITE = (1 << 1)
-};
-
-enum {
-       SCIF_MAP_FIXED = 0x10,
-       SCIF_MAP_KERNEL = 0x20,
-};
-
-enum {
-       SCIF_FENCE_INIT_SELF = (1 << 0),
-       SCIF_FENCE_INIT_PEER = (1 << 1),
-       SCIF_SIGNAL_LOCAL = (1 << 4),
-       SCIF_SIGNAL_REMOTE = (1 << 5)
-};
-
-enum {
-       SCIF_RMA_USECPU = (1 << 0),
-       SCIF_RMA_USECACHE = (1 << 1),
-       SCIF_RMA_SYNC = (1 << 2),
-       SCIF_RMA_ORDERED = (1 << 3)
-};
-
-/* End of SCIF Admin Reserved Ports */
-#define SCIF_ADMIN_PORT_END    1024
-
-/* End of SCIF Reserved Ports */
-#define SCIF_PORT_RSVD         1088
-
-typedef struct scif_endpt *scif_epd_t;
-typedef struct scif_pinned_pages *scif_pinned_pages_t;
-
-/**
- * struct scif_range - SCIF registered range used in kernel mode
- * @cookie: cookie used internally by SCIF
- * @nr_pages: number of pages of PAGE_SIZE
- * @prot_flags: R/W protection
- * @phys_addr: Array of bus addresses
- * @va: Array of kernel virtual addresses backed by the pages in the phys_addr
- *     array. The va is populated only when called on the host for a remote
- *     SCIF connection on MIC. This is required to support the use case of DMA
- *     between MIC and another device which is not a SCIF node e.g., an IB or
- *     ethernet NIC.
- */
-struct scif_range {
-       void *cookie;
-       int nr_pages;
-       int prot_flags;
-       dma_addr_t *phys_addr;
-       void __iomem **va;
-};
-
-/**
- * struct scif_pollepd - SCIF endpoint to be monitored via scif_poll
- * @epd: SCIF endpoint
- * @events: requested events
- * @revents: returned events
- */
-struct scif_pollepd {
-       scif_epd_t epd;
-       __poll_t events;
-       __poll_t revents;
-};
-
-/**
- * scif_peer_dev - representation of a peer SCIF device
- *
- * Peer devices show up as PCIe devices for the mgmt node but not the cards.
- * The mgmt node discovers all the cards on the PCIe bus and informs the other
- * cards about their peers. Upon notification of a peer a node adds a peer
- * device to the peer bus to maintain symmetry in the way devices are
- * discovered across all nodes in the SCIF network.
- *
- * @dev: underlying device
- * @dnode - The destination node which this device will communicate with.
- */
-struct scif_peer_dev {
-       struct device dev;
-       u8 dnode;
-};
-
-/**
- * scif_client - representation of a SCIF client
- * @name: client name
- * @probe - client method called when a peer device is registered
- * @remove - client method called when a peer device is unregistered
- * @si - subsys_interface used internally for implementing SCIF clients
- */
-struct scif_client {
-       const char *name;
-       void (*probe)(struct scif_peer_dev *spdev);
-       void (*remove)(struct scif_peer_dev *spdev);
-       struct subsys_interface si;
-};
-
-#define SCIF_OPEN_FAILED ((scif_epd_t)-1)
-#define SCIF_REGISTER_FAILED ((off_t)-1)
-#define SCIF_MMAP_FAILED ((void *)-1)
-
-/**
- * scif_open() - Create an endpoint
- *
- * Return:
- * Upon successful completion, scif_open() returns an endpoint descriptor to
- * be used in subsequent SCIF functions calls to refer to that endpoint;
- * otherwise in user mode SCIF_OPEN_FAILED (that is ((scif_epd_t)-1)) is
- * returned and errno is set to indicate the error; in kernel mode a NULL
- * scif_epd_t is returned.
- *
- * Errors:
- * ENOMEM - Insufficient kernel memory was available
- */
-scif_epd_t scif_open(void);
-
-/**
- * scif_bind() - Bind an endpoint to a port
- * @epd:       endpoint descriptor
- * @pn:                port number
- *
- * scif_bind() binds endpoint epd to port pn, where pn is a port number on the
- * local node. If pn is zero, a port number greater than or equal to
- * SCIF_PORT_RSVD is assigned and returned. Each endpoint may be bound to
- * exactly one local port. Ports less than 1024 when requested can only be bound
- * by system (or root) processes or by processes executed by privileged users.
- *
- * Return:
- * Upon successful completion, scif_bind() returns the port number to which epd
- * is bound; otherwise in user mode -1 is returned and errno is set to
- * indicate the error; in kernel mode the negative of one of the following
- * errors is returned.
- *
- * Errors:
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- * EINVAL - the endpoint or the port is already bound
- * EISCONN - The endpoint is already connected
- * ENOSPC - No port number available for assignment
- * EACCES - The port requested is protected and the user is not the superuser
- */
-int scif_bind(scif_epd_t epd, u16 pn);
-
-/**
- * scif_listen() - Listen for connections on an endpoint
- * @epd:       endpoint descriptor
- * @backlog:   maximum pending connection requests
- *
- * scif_listen() marks the endpoint epd as a listening endpoint - that is, as
- * an endpoint that will be used to accept incoming connection requests. Once
- * so marked, the endpoint is said to be in the listening state and may not be
- * used as the endpoint of a connection.
- *
- * The endpoint, epd, must have been bound to a port.
- *
- * The backlog argument defines the maximum length to which the queue of
- * pending connections for epd may grow. If a connection request arrives when
- * the queue is full, the client may receive an error with an indication that
- * the connection was refused.
- *
- * Return:
- * Upon successful completion, scif_listen() returns 0; otherwise in user mode
- * -1 is returned and errno is set to indicate the error; in kernel mode the
- * negative of one of the following errors is returned.
- *
- * Errors:
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- * EINVAL - the endpoint is not bound to a port
- * EISCONN - The endpoint is already connected or listening
- */
-int scif_listen(scif_epd_t epd, int backlog);
-
-/**
- * scif_connect() - Initiate a connection on a port
- * @epd:       endpoint descriptor
- * @dst:       global id of port to which to connect
- *
- * The scif_connect() function requests the connection of endpoint epd to remote
- * port dst. If the connection is successful, a peer endpoint, bound to dst, is
- * created on node dst.node. On successful return, the connection is complete.
- *
- * If the endpoint epd has not already been bound to a port, scif_connect()
- * will bind it to an unused local port.
- *
- * A connection is terminated when an endpoint of the connection is closed,
- * either explicitly by scif_close(), or when a process that owns one of the
- * endpoints of the connection is terminated.
- *
- * In user space, scif_connect() supports an asynchronous connection mode
- * if the application has set the O_NONBLOCK flag on the endpoint via the
- * fcntl() system call. Setting this flag will result in the calling process
- * not to wait during scif_connect().
- *
- * Return:
- * Upon successful completion, scif_connect() returns the port ID to which the
- * endpoint, epd, is bound; otherwise in user mode -1 is returned and errno is
- * set to indicate the error; in kernel mode the negative of one of the
- * following errors is returned.
- *
- * Errors:
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- * ECONNREFUSED - The destination was not listening for connections or refused
- * the connection request
- * EINVAL - dst.port is not a valid port ID
- * EISCONN - The endpoint is already connected
- * ENOMEM - No buffer space is available
- * ENODEV - The destination node does not exist, or the node is lost or existed,
- * but is not currently in the network since it may have crashed
- * ENOSPC - No port number available for assignment
- * EOPNOTSUPP - The endpoint is listening and cannot be connected
- */
-int scif_connect(scif_epd_t epd, struct scif_port_id *dst);
-
-/**
- * scif_accept() - Accept a connection on an endpoint
- * @epd:       endpoint descriptor
- * @peer:      global id of port to which connected
- * @newepd:    new connected endpoint descriptor
- * @flags:     flags
- *
- * The scif_accept() call extracts the first connection request from the queue
- * of pending connections for the port on which epd is listening. scif_accept()
- * creates a new endpoint, bound to the same port as epd, and allocates a new
- * SCIF endpoint descriptor, returned in newepd, for the endpoint. The new
- * endpoint is connected to the endpoint through which the connection was
- * requested. epd is unaffected by this call, and remains in the listening
- * state.
- *
- * On successful return, peer holds the global port identifier (node id and
- * local port number) of the port which requested the connection.
- *
- * A connection is terminated when an endpoint of the connection is closed,
- * either explicitly by scif_close(), or when a process that owns one of the
- * endpoints of the connection is terminated.
- *
- * The number of connections that can (subsequently) be accepted on epd is only
- * limited by system resources (memory).
- *
- * The flags argument is formed by OR'ing together zero or more of the
- * following values.
- * SCIF_ACCEPT_SYNC - block until a connection request is presented. If
- *                     SCIF_ACCEPT_SYNC is not in flags, and no pending
- *                     connections are present on the queue, scif_accept()
- *                     fails with an EAGAIN error
- *
- * In user mode, the select() and poll() functions can be used to determine
- * when there is a connection request. In kernel mode, the scif_poll()
- * function may be used for this purpose. A readable event will be delivered
- * when a connection is requested.
- *
- * Return:
- * Upon successful completion, scif_accept() returns 0; otherwise in user mode
- * -1 is returned and errno is set to indicate the error; in kernel mode the
- *     negative of one of the following errors is returned.
- *
- * Errors:
- * EAGAIN - SCIF_ACCEPT_SYNC is not set and no connections are present to be
- * accepted or SCIF_ACCEPT_SYNC is not set and remote node failed to complete
- * its connection request
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- * EINTR - Interrupted function
- * EINVAL - epd is not a listening endpoint, or flags is invalid, or peer is
- * NULL, or newepd is NULL
- * ENODEV - The requesting node is lost or existed, but is not currently in the
- * network since it may have crashed
- * ENOMEM - Not enough space
- * ENOENT - Secondary part of epd registration failed
- */
-int scif_accept(scif_epd_t epd, struct scif_port_id *peer, scif_epd_t
-               *newepd, int flags);
-
-/**
- * scif_close() - Close an endpoint
- * @epd:       endpoint descriptor
- *
- * scif_close() closes an endpoint and performs necessary teardown of
- * facilities associated with that endpoint.
- *
- * If epd is a listening endpoint then it will no longer accept connection
- * requests on the port to which it is bound. Any pending connection requests
- * are rejected.
- *
- * If epd is a connected endpoint, then its peer endpoint is also closed. RMAs
- * which are in-process through epd or its peer endpoint will complete before
- * scif_close() returns. Registered windows of the local and peer endpoints are
- * released as if scif_unregister() was called against each window.
- *
- * Closing a SCIF endpoint does not affect local registered memory mapped by
- * a SCIF endpoint on a remote node. The local memory remains mapped by the peer
- * SCIF endpoint explicitly removed by calling munmap(..) by the peer.
- *
- * If the peer endpoint's receive queue is not empty at the time that epd is
- * closed, then the peer endpoint can be passed as the endpoint parameter to
- * scif_recv() until the receive queue is empty.
- *
- * epd is freed and may no longer be accessed.
- *
- * Return:
- * Upon successful completion, scif_close() returns 0; otherwise in user mode
- * -1 is returned and errno is set to indicate the error; in kernel mode the
- * negative of one of the following errors is returned.
- *
- * Errors:
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- */
-int scif_close(scif_epd_t epd);
-
-/**
- * scif_send() - Send a message
- * @epd:       endpoint descriptor
- * @msg:       message buffer address
- * @len:       message length
- * @flags:     blocking mode flags
- *
- * scif_send() sends data to the peer of endpoint epd. Up to len bytes of data
- * are copied from memory starting at address msg. On successful execution the
- * return value of scif_send() is the number of bytes that were sent, and is
- * zero if no bytes were sent because len was zero. scif_send() may be called
- * only when the endpoint is in a connected state.
- *
- * If a scif_send() call is non-blocking, then it sends only those bytes which
- * can be sent without waiting, up to a maximum of len bytes.
- *
- * If a scif_send() call is blocking, then it normally returns after sending
- * all len bytes. If a blocking call is interrupted or the connection is
- * reset, the call is considered successful if some bytes were sent or len is
- * zero, otherwise the call is considered unsuccessful.
- *
- * In user mode, the select() and poll() functions can be used to determine
- * when the send queue is not full. In kernel mode, the scif_poll() function
- * may be used for this purpose.
- *
- * It is recommended that scif_send()/scif_recv() only be used for short
- * control-type message communication between SCIF endpoints. The SCIF RMA
- * APIs are expected to provide better performance for transfer sizes of
- * 1024 bytes or longer for the current MIC hardware and software
- * implementation.
- *
- * scif_send() will block until the entire message is sent if SCIF_SEND_BLOCK
- * is passed as the flags argument.
- *
- * Return:
- * Upon successful completion, scif_send() returns the number of bytes sent;
- * otherwise in user mode -1 is returned and errno is set to indicate the
- * error; in kernel mode the negative of one of the following errors is
- * returned.
- *
- * Errors:
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- * ECONNRESET - Connection reset by peer
- * EINVAL - flags is invalid, or len is negative
- * ENODEV - The remote node is lost or existed, but is not currently in the
- * network since it may have crashed
- * ENOMEM - Not enough space
- * ENOTCONN - The endpoint is not connected
- */
-int scif_send(scif_epd_t epd, void *msg, int len, int flags);
-
-/**
- * scif_recv() - Receive a message
- * @epd:       endpoint descriptor
- * @msg:       message buffer address
- * @len:       message buffer length
- * @flags:     blocking mode flags
- *
- * scif_recv() receives data from the peer of endpoint epd. Up to len bytes of
- * data are copied to memory starting at address msg. On successful execution
- * the return value of scif_recv() is the number of bytes that were received,
- * and is zero if no bytes were received because len was zero. scif_recv() may
- * be called only when the endpoint is in a connected state.
- *
- * If a scif_recv() call is non-blocking, then it receives only those bytes
- * which can be received without waiting, up to a maximum of len bytes.
- *
- * If a scif_recv() call is blocking, then it normally returns after receiving
- * all len bytes. If the blocking call was interrupted due to a disconnection,
- * subsequent calls to scif_recv() will copy all bytes received upto the point
- * of disconnection.
- *
- * In user mode, the select() and poll() functions can be used to determine
- * when data is available to be received. In kernel mode, the scif_poll()
- * function may be used for this purpose.
- *
- * It is recommended that scif_send()/scif_recv() only be used for short
- * control-type message communication between SCIF endpoints. The SCIF RMA
- * APIs are expected to provide better performance for transfer sizes of
- * 1024 bytes or longer for the current MIC hardware and software
- * implementation.
- *
- * scif_recv() will block until the entire message is received if
- * SCIF_RECV_BLOCK is passed as the flags argument.
- *
- * Return:
- * Upon successful completion, scif_recv() returns the number of bytes
- * received; otherwise in user mode -1 is returned and errno is set to
- * indicate the error; in kernel mode the negative of one of the following
- * errors is returned.
- *
- * Errors:
- * EAGAIN - The destination node is returning from a low power state
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- * ECONNRESET - Connection reset by peer
- * EINVAL - flags is invalid, or len is negative
- * ENODEV - The remote node is lost or existed, but is not currently in the
- * network since it may have crashed
- * ENOMEM - Not enough space
- * ENOTCONN - The endpoint is not connected
- */
-int scif_recv(scif_epd_t epd, void *msg, int len, int flags);
-
-/**
- * scif_register() - Mark a memory region for remote access.
- * @epd:               endpoint descriptor
- * @addr:              starting virtual address
- * @len:               length of range
- * @offset:            offset of window
- * @prot_flags:                read/write protection flags
- * @map_flags:         mapping flags
- *
- * The scif_register() function opens a window, a range of whole pages of the
- * registered address space of the endpoint epd, starting at offset po and
- * continuing for len bytes. The value of po, further described below, is a
- * function of the parameters offset and len, and the value of map_flags. Each
- * page of the window represents the physical memory page which backs the
- * corresponding page of the range of virtual address pages starting at addr
- * and continuing for len bytes. addr and len are constrained to be multiples
- * of the page size. A successful scif_register() call returns po.
- *
- * When SCIF_MAP_FIXED is set in the map_flags argument, po will be offset
- * exactly, and offset is constrained to be a multiple of the page size. The
- * mapping established by scif_register() will not replace any existing
- * registration; an error is returned if any page within the range [offset,
- * offset + len - 1] intersects an existing window.
- *
- * When SCIF_MAP_FIXED is not set, the implementation uses offset in an
- * implementation-defined manner to arrive at po. The po value so chosen will
- * be an area of the registered address space that the implementation deems
- * suitable for a mapping of len bytes. An offset value of 0 is interpreted as
- * granting the implementation complete freedom in selecting po, subject to
- * constraints described below. A non-zero value of offset is taken to be a
- * suggestion of an offset near which the mapping should be placed. When the
- * implementation selects a value for po, it does not replace any extant
- * window. In all cases, po will be a multiple of the page size.
- *
- * The physical pages which are so represented by a window are available for
- * access in calls to mmap(), scif_readfrom(), scif_writeto(),
- * scif_vreadfrom(), and scif_vwriteto(). While a window is registered, the
- * physical pages represented by the window will not be reused by the memory
- * subsystem for any other purpose. Note that the same physical page may be
- * represented by multiple windows.
- *
- * Subsequent operations which change the memory pages to which virtual
- * addresses are mapped (such as mmap(), munmap()) have no effect on
- * existing window.
- *
- * If the process will fork(), it is recommended that the registered
- * virtual address range be marked with MADV_DONTFORK. Doing so will prevent
- * problems due to copy-on-write semantics.
- *
- * The prot_flags argument is formed by OR'ing together one or more of the
- * following values.
- * SCIF_PROT_READ - allow read operations from the window
- * SCIF_PROT_WRITE - allow write operations to the window
- *
- * Return:
- * Upon successful completion, scif_register() returns the offset at which the
- * mapping was placed (po); otherwise in user mode SCIF_REGISTER_FAILED (that
- * is (off_t *)-1) is returned and errno is set to indicate the error; in
- * kernel mode the negative of one of the following errors is returned.
- *
- * Errors:
- * EADDRINUSE - SCIF_MAP_FIXED is set in map_flags, and pages in the range
- * [offset, offset + len -1] are already registered
- * EAGAIN - The mapping could not be performed due to lack of resources
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- * ECONNRESET - Connection reset by peer
- * EINVAL - map_flags is invalid, or prot_flags is invalid, or SCIF_MAP_FIXED is
- * set in flags, and offset is not a multiple of the page size, or addr is not a
- * multiple of the page size, or len is not a multiple of the page size, or is
- * 0, or offset is negative
- * ENODEV - The remote node is lost or existed, but is not currently in the
- * network since it may have crashed
- * ENOMEM - Not enough space
- * ENOTCONN -The endpoint is not connected
- */
-off_t scif_register(scif_epd_t epd, void *addr, size_t len, off_t offset,
-                   int prot_flags, int map_flags);
-
-/**
- * scif_unregister() - Mark a memory region for remote access.
- * @epd:       endpoint descriptor
- * @offset:    start of range to unregister
- * @len:       length of range to unregister
- *
- * The scif_unregister() function closes those previously registered windows
- * which are entirely within the range [offset, offset + len - 1]. It is an
- * error to specify a range which intersects only a subrange of a window.
- *
- * On a successful return, pages within the window may no longer be specified
- * in calls to mmap(), scif_readfrom(), scif_writeto(), scif_vreadfrom(),
- * scif_vwriteto(), scif_get_pages, and scif_fence_signal(). The window,
- * however, continues to exist until all previous references against it are
- * removed. A window is referenced if there is a mapping to it created by
- * mmap(), or if scif_get_pages() was called against the window
- * (and the pages have not been returned via scif_put_pages()). A window is
- * also referenced while an RMA, in which some range of the window is a source
- * or destination, is in progress. Finally a window is referenced while some
- * offset in that window was specified to scif_fence_signal(), and the RMAs
- * marked by that call to scif_fence_signal() have not completed. While a
- * window is in this state, its registered address space pages are not
- * available for use in a new registered window.
- *
- * When all such references to the window have been removed, its references to
- * all the physical pages which it represents are removed. Similarly, the
- * registered address space pages of the window become available for
- * registration in a new window.
- *
- * Return:
- * Upon successful completion, scif_unregister() returns 0; otherwise in user
- * mode -1 is returned and errno is set to indicate the error; in kernel mode
- * the negative of one of the following errors is returned. In the event of an
- * error, no windows are unregistered.
- *
- * Errors:
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- * ECONNRESET - Connection reset by peer
- * EINVAL - the range [offset, offset + len - 1] intersects a subrange of a
- * window, or offset is negative
- * ENODEV - The remote node is lost or existed, but is not currently in the
- * network since it may have crashed
- * ENOTCONN - The endpoint is not connected
- * ENXIO - Offsets in the range [offset, offset + len - 1] are invalid for the
- * registered address space of epd
- */
-int scif_unregister(scif_epd_t epd, off_t offset, size_t len);
-
-/**
- * scif_readfrom() - Copy from a remote address space
- * @epd:       endpoint descriptor
- * @loffset:   offset in local registered address space to
- *             which to copy
- * @len:       length of range to copy
- * @roffset:   offset in remote registered address space
- *             from which to copy
- * @rma_flags: transfer mode flags
- *
- * scif_readfrom() copies len bytes from the remote registered address space of
- * the peer of endpoint epd, starting at the offset roffset to the local
- * registered address space of epd, starting at the offset loffset.
- *
- * Each of the specified ranges [loffset, loffset + len - 1] and [roffset,
- * roffset + len - 1] must be within some registered window or windows of the
- * local and remote nodes. A range may intersect multiple registered windows,
- * but only if those windows are contiguous in the registered address space.
- *
- * If rma_flags includes SCIF_RMA_USECPU, then the data is copied using
- * programmed read/writes. Otherwise the data is copied using DMA. If rma_-
- * flags includes SCIF_RMA_SYNC, then scif_readfrom() will return after the
- * transfer is complete. Otherwise, the transfer may be performed asynchron-
- * ously. The order in which any two asynchronous RMA operations complete
- * is non-deterministic. The synchronization functions, scif_fence_mark()/
- * scif_fence_wait() and scif_fence_signal(), can be used to synchronize to
- * the completion of asynchronous RMA operations on the same endpoint.
- *
- * The DMA transfer of individual bytes is not guaranteed to complete in
- * address order. If rma_flags includes SCIF_RMA_ORDERED, then the last
- * cacheline or partial cacheline of the source range will become visible on
- * the destination node after all other transferred data in the source
- * range has become visible on the destination node.
- *
- * The optimal DMA performance will likely be realized if both
- * loffset and roffset are cacheline aligned (are a multiple of 64). Lower
- * performance will likely be realized if loffset and roffset are not
- * cacheline aligned but are separated by some multiple of 64. The lowest level
- * of performance is likely if loffset and roffset are not separated by a
- * multiple of 64.
- *
- * The rma_flags argument is formed by ORing together zero or more of the
- * following values.
- * SCIF_RMA_USECPU - perform the transfer using the CPU, otherwise use the DMA
- *     engine.
- * SCIF_RMA_SYNC - perform the transfer synchronously, returning after the
- *             transfer has completed. Passing this flag results in the
- *             current implementation busy waiting and consuming CPU cycles
- *             while the DMA transfer is in progress for best performance by
- *             avoiding the interrupt latency.
- * SCIF_RMA_ORDERED - ensure that the last cacheline or partial cacheline of
- *             the source range becomes visible on the destination node
- *             after all other transferred data in the source range has
- *             become visible on the destination
- *
- * Return:
- * Upon successful completion, scif_readfrom() returns 0; otherwise in user
- * mode -1 is returned and errno is set to indicate the error; in kernel mode
- * the negative of one of the following errors is returned.
- *
- * Errors:
- * EACCES - Attempt to write to a read-only range
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- * ECONNRESET - Connection reset by peer
- * EINVAL - rma_flags is invalid
- * ENODEV - The remote node is lost or existed, but is not currently in the
- * network since it may have crashed
- * ENOTCONN - The endpoint is not connected
- * ENXIO - The range [loffset, loffset + len - 1] is invalid for the registered
- * address space of epd, or, The range [roffset, roffset + len - 1] is invalid
- * for the registered address space of the peer of epd, or loffset or roffset
- * is negative
- */
-int scif_readfrom(scif_epd_t epd, off_t loffset, size_t len, off_t
-                 roffset, int rma_flags);
-
-/**
- * scif_writeto() - Copy to a remote address space
- * @epd:       endpoint descriptor
- * @loffset:   offset in local registered address space
- *             from which to copy
- * @len:       length of range to copy
- * @roffset:   offset in remote registered address space to
- *             which to copy
- * @rma_flags: transfer mode flags
- *
- * scif_writeto() copies len bytes from the local registered address space of
- * epd, starting at the offset loffset to the remote registered address space
- * of the peer of endpoint epd, starting at the offset roffset.
- *
- * Each of the specified ranges [loffset, loffset + len - 1] and [roffset,
- * roffset + len - 1] must be within some registered window or windows of the
- * local and remote nodes. A range may intersect multiple registered windows,
- * but only if those windows are contiguous in the registered address space.
- *
- * If rma_flags includes SCIF_RMA_USECPU, then the data is copied using
- * programmed read/writes. Otherwise the data is copied using DMA. If rma_-
- * flags includes SCIF_RMA_SYNC, then scif_writeto() will return after the
- * transfer is complete. Otherwise, the transfer may be performed asynchron-
- * ously. The order in which any two asynchronous RMA operations complete
- * is non-deterministic. The synchronization functions, scif_fence_mark()/
- * scif_fence_wait() and scif_fence_signal(), can be used to synchronize to
- * the completion of asynchronous RMA operations on the same endpoint.
- *
- * The DMA transfer of individual bytes is not guaranteed to complete in
- * address order. If rma_flags includes SCIF_RMA_ORDERED, then the last
- * cacheline or partial cacheline of the source range will become visible on
- * the destination node after all other transferred data in the source
- * range has become visible on the destination node.
- *
- * The optimal DMA performance will likely be realized if both
- * loffset and roffset are cacheline aligned (are a multiple of 64). Lower
- * performance will likely be realized if loffset and roffset are not cacheline
- * aligned but are separated by some multiple of 64. The lowest level of
- * performance is likely if loffset and roffset are not separated by a multiple
- * of 64.
- *
- * The rma_flags argument is formed by ORing together zero or more of the
- * following values.
- * SCIF_RMA_USECPU - perform the transfer using the CPU, otherwise use the DMA
- *                     engine.
- * SCIF_RMA_SYNC - perform the transfer synchronously, returning after the
- *             transfer has completed. Passing this flag results in the
- *             current implementation busy waiting and consuming CPU cycles
- *             while the DMA transfer is in progress for best performance by
- *             avoiding the interrupt latency.
- * SCIF_RMA_ORDERED - ensure that the last cacheline or partial cacheline of
- *             the source range becomes visible on the destination node
- *             after all other transferred data in the source range has
- *             become visible on the destination
- *
- * Return:
- * Upon successful completion, scif_readfrom() returns 0; otherwise in user
- * mode -1 is returned and errno is set to indicate the error; in kernel mode
- * the negative of one of the following errors is returned.
- *
- * Errors:
- * EACCES - Attempt to write to a read-only range
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- * ECONNRESET - Connection reset by peer
- * EINVAL - rma_flags is invalid
- * ENODEV - The remote node is lost or existed, but is not currently in the
- * network since it may have crashed
- * ENOTCONN - The endpoint is not connected
- * ENXIO - The range [loffset, loffset + len - 1] is invalid for the registered
- * address space of epd, or, The range [roffset , roffset + len -1] is invalid
- * for the registered address space of the peer of epd, or loffset or roffset
- * is negative
- */
-int scif_writeto(scif_epd_t epd, off_t loffset, size_t len, off_t
-                roffset, int rma_flags);
-
-/**
- * scif_vreadfrom() - Copy from a remote address space
- * @epd:       endpoint descriptor
- * @addr:      address to which to copy
- * @len:       length of range to copy
- * @roffset:   offset in remote registered address space
- *             from which to copy
- * @rma_flags: transfer mode flags
- *
- * scif_vreadfrom() copies len bytes from the remote registered address
- * space of the peer of endpoint epd, starting at the offset roffset, to local
- * memory, starting at addr.
- *
- * The specified range [roffset, roffset + len - 1] must be within some
- * registered window or windows of the remote nodes. The range may
- * intersect multiple registered windows, but only if those windows are
- * contiguous in the registered address space.
- *
- * If rma_flags includes SCIF_RMA_USECPU, then the data is copied using
- * programmed read/writes. Otherwise the data is copied using DMA. If rma_-
- * flags includes SCIF_RMA_SYNC, then scif_vreadfrom() will return after the
- * transfer is complete. Otherwise, the transfer may be performed asynchron-
- * ously. The order in which any two asynchronous RMA operations complete
- * is non-deterministic. The synchronization functions, scif_fence_mark()/
- * scif_fence_wait() and scif_fence_signal(), can be used to synchronize to
- * the completion of asynchronous RMA operations on the same endpoint.
- *
- * The DMA transfer of individual bytes is not guaranteed to complete in
- * address order. If rma_flags includes SCIF_RMA_ORDERED, then the last
- * cacheline or partial cacheline of the source range will become visible on
- * the destination node after all other transferred data in the source
- * range has become visible on the destination node.
- *
- * If rma_flags includes SCIF_RMA_USECACHE, then the physical pages which back
- * the specified local memory range may be remain in a pinned state even after
- * the specified transfer completes. This may reduce overhead if some or all of
- * the same virtual address range is referenced in a subsequent call of
- * scif_vreadfrom() or scif_vwriteto().
- *
- * The optimal DMA performance will likely be realized if both
- * addr and roffset are cacheline aligned (are a multiple of 64). Lower
- * performance will likely be realized if addr and roffset are not
- * cacheline aligned but are separated by some multiple of 64. The lowest level
- * of performance is likely if addr and roffset are not separated by a
- * multiple of 64.
- *
- * The rma_flags argument is formed by ORing together zero or more of the
- * following values.
- * SCIF_RMA_USECPU - perform the transfer using the CPU, otherwise use the DMA
- *     engine.
- * SCIF_RMA_USECACHE - enable registration caching
- * SCIF_RMA_SYNC - perform the transfer synchronously, returning after the
- *             transfer has completed. Passing this flag results in the
- *             current implementation busy waiting and consuming CPU cycles
- *             while the DMA transfer is in progress for best performance by
- *             avoiding the interrupt latency.
- * SCIF_RMA_ORDERED - ensure that the last cacheline or partial cacheline of
- *     the source range becomes visible on the destination node
- *     after all other transferred data in the source range has
- *     become visible on the destination
- *
- * Return:
- * Upon successful completion, scif_vreadfrom() returns 0; otherwise in user
- * mode -1 is returned and errno is set to indicate the error; in kernel mode
- * the negative of one of the following errors is returned.
- *
- * Errors:
- * EACCES - Attempt to write to a read-only range
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- * ECONNRESET - Connection reset by peer
- * EINVAL - rma_flags is invalid
- * ENODEV - The remote node is lost or existed, but is not currently in the
- * network since it may have crashed
- * ENOTCONN - The endpoint is not connected
- * ENXIO - Offsets in the range [roffset, roffset + len - 1] are invalid for the
- * registered address space of epd
- */
-int scif_vreadfrom(scif_epd_t epd, void *addr, size_t len, off_t roffset,
-                  int rma_flags);
-
-/**
- * scif_vwriteto() - Copy to a remote address space
- * @epd:       endpoint descriptor
- * @addr:      address from which to copy
- * @len:       length of range to copy
- * @roffset:   offset in remote registered address space to
- *             which to copy
- * @rma_flags: transfer mode flags
- *
- * scif_vwriteto() copies len bytes from the local memory, starting at addr, to
- * the remote registered address space of the peer of endpoint epd, starting at
- * the offset roffset.
- *
- * The specified range [roffset, roffset + len - 1] must be within some
- * registered window or windows of the remote nodes. The range may intersect
- * multiple registered windows, but only if those windows are contiguous in the
- * registered address space.
- *
- * If rma_flags includes SCIF_RMA_USECPU, then the data is copied using
- * programmed read/writes. Otherwise the data is copied using DMA. If rma_-
- * flags includes SCIF_RMA_SYNC, then scif_vwriteto() will return after the
- * transfer is complete. Otherwise, the transfer may be performed asynchron-
- * ously. The order in which any two asynchronous RMA operations complete
- * is non-deterministic. The synchronization functions, scif_fence_mark()/
- * scif_fence_wait() and scif_fence_signal(), can be used to synchronize to
- * the completion of asynchronous RMA operations on the same endpoint.
- *
- * The DMA transfer of individual bytes is not guaranteed to complete in
- * address order. If rma_flags includes SCIF_RMA_ORDERED, then the last
- * cacheline or partial cacheline of the source range will become visible on
- * the destination node after all other transferred data in the source
- * range has become visible on the destination node.
- *
- * If rma_flags includes SCIF_RMA_USECACHE, then the physical pages which back
- * the specified local memory range may be remain in a pinned state even after
- * the specified transfer completes. This may reduce overhead if some or all of
- * the same virtual address range is referenced in a subsequent call of
- * scif_vreadfrom() or scif_vwriteto().
- *
- * The optimal DMA performance will likely be realized if both
- * addr and offset are cacheline aligned (are a multiple of 64). Lower
- * performance will likely be realized if addr and offset are not cacheline
- * aligned but are separated by some multiple of 64. The lowest level of
- * performance is likely if addr and offset are not separated by a multiple of
- * 64.
- *
- * The rma_flags argument is formed by ORing together zero or more of the
- * following values.
- * SCIF_RMA_USECPU - perform the transfer using the CPU, otherwise use the DMA
- *     engine.
- * SCIF_RMA_USECACHE - allow registration caching
- * SCIF_RMA_SYNC - perform the transfer synchronously, returning after the
- *             transfer has completed. Passing this flag results in the
- *             current implementation busy waiting and consuming CPU cycles
- *             while the DMA transfer is in progress for best performance by
- *             avoiding the interrupt latency.
- * SCIF_RMA_ORDERED - ensure that the last cacheline or partial cacheline of
- *             the source range becomes visible on the destination node
- *             after all other transferred data in the source range has
- *             become visible on the destination
- *
- * Return:
- * Upon successful completion, scif_vwriteto() returns 0; otherwise in user
- * mode -1 is returned and errno is set to indicate the error; in kernel mode
- * the negative of one of the following errors is returned.
- *
- * Errors:
- * EACCES - Attempt to write to a read-only range
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- * ECONNRESET - Connection reset by peer
- * EINVAL - rma_flags is invalid
- * ENODEV - The remote node is lost or existed, but is not currently in the
- * network since it may have crashed
- * ENOTCONN - The endpoint is not connected
- * ENXIO - Offsets in the range [roffset, roffset + len - 1] are invalid for the
- * registered address space of epd
- */
-int scif_vwriteto(scif_epd_t epd, void *addr, size_t len, off_t roffset,
-                 int rma_flags);
-
-/**
- * scif_fence_mark() - Mark previously issued RMAs
- * @epd:       endpoint descriptor
- * @flags:     control flags
- * @mark:      marked value returned as output.
- *
- * scif_fence_mark() returns after marking the current set of all uncompleted
- * RMAs initiated through the endpoint epd or the current set of all
- * uncompleted RMAs initiated through the peer of endpoint epd. The RMAs are
- * marked with a value returned at mark. The application may subsequently call
- * scif_fence_wait(), passing the value returned at mark, to await completion
- * of all RMAs so marked.
- *
- * The flags argument has exactly one of the following values.
- * SCIF_FENCE_INIT_SELF - RMA operations initiated through endpoint
- *     epd are marked
- * SCIF_FENCE_INIT_PEER - RMA operations initiated through the peer
- *     of endpoint epd are marked
- *
- * Return:
- * Upon successful completion, scif_fence_mark() returns 0; otherwise in user
- * mode -1 is returned and errno is set to indicate the error; in kernel mode
- * the negative of one of the following errors is returned.
- *
- * Errors:
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- * ECONNRESET - Connection reset by peer
- * EINVAL - flags is invalid
- * ENODEV - The remote node is lost or existed, but is not currently in the
- * network since it may have crashed
- * ENOTCONN - The endpoint is not connected
- * ENOMEM - Insufficient kernel memory was available
- */
-int scif_fence_mark(scif_epd_t epd, int flags, int *mark);
-
-/**
- * scif_fence_wait() - Wait for completion of marked RMAs
- * @epd:       endpoint descriptor
- * @mark:      mark request
- *
- * scif_fence_wait() returns after all RMAs marked with mark have completed.
- * The value passed in mark must have been obtained in a previous call to
- * scif_fence_mark().
- *
- * Return:
- * Upon successful completion, scif_fence_wait() returns 0; otherwise in user
- * mode -1 is returned and errno is set to indicate the error; in kernel mode
- * the negative of one of the following errors is returned.
- *
- * Errors:
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- * ECONNRESET - Connection reset by peer
- * ENODEV - The remote node is lost or existed, but is not currently in the
- * network since it may have crashed
- * ENOTCONN - The endpoint is not connected
- * ENOMEM - Insufficient kernel memory was available
- */
-int scif_fence_wait(scif_epd_t epd, int mark);
-
-/**
- * scif_fence_signal() - Request a memory update on completion of RMAs
- * @epd:       endpoint descriptor
- * @loff:      local offset
- * @lval:      local value to write to loffset
- * @roff:      remote offset
- * @rval:      remote value to write to roffset
- * @flags:     flags
- *
- * scif_fence_signal() returns after marking the current set of all uncompleted
- * RMAs initiated through the endpoint epd or marking the current set of all
- * uncompleted RMAs initiated through the peer of endpoint epd.
- *
- * If flags includes SCIF_SIGNAL_LOCAL, then on completion of the RMAs in the
- * marked set, lval is written to memory at the address corresponding to offset
- * loff in the local registered address space of epd. loff must be within a
- * registered window. If flags includes SCIF_SIGNAL_REMOTE, then on completion
- * of the RMAs in the marked set, rval is written to memory at the address
- * corresponding to offset roff in the remote registered address space of epd.
- * roff must be within a remote registered window of the peer of epd. Note
- * that any specified offset must be DWORD (4 byte / 32 bit) aligned.
- *
- * The flags argument is formed by OR'ing together the following.
- * Exactly one of the following values.
- * SCIF_FENCE_INIT_SELF - RMA operations initiated through endpoint
- *     epd are marked
- * SCIF_FENCE_INIT_PEER - RMA operations initiated through the peer
- *     of endpoint epd are marked
- * One or more of the following values.
- * SCIF_SIGNAL_LOCAL - On completion of the marked set of RMAs, write lval to
- *     memory at the address corresponding to offset loff in the local
- *     registered address space of epd.
- * SCIF_SIGNAL_REMOTE - On completion of the marked set of RMAs, write rval to
- *     memory at the address corresponding to offset roff in the remote
- *     registered address space of epd.
- *
- * Return:
- * Upon successful completion, scif_fence_signal() returns 0; otherwise in
- * user mode -1 is returned and errno is set to indicate the error; in kernel
- * mode the negative of one of the following errors is returned.
- *
- * Errors:
- * EBADF, ENOTTY - epd is not a valid endpoint descriptor
- * ECONNRESET - Connection reset by peer
- * EINVAL - flags is invalid, or loff or roff are not DWORD aligned
- * ENODEV - The remote node is lost or existed, but is not currently in the
- * network since it may have crashed
- * ENOTCONN - The endpoint is not connected
- * ENXIO - loff is invalid for the registered address of epd, or roff is invalid
- * for the registered address space, of the peer of epd
- */
-int scif_fence_signal(scif_epd_t epd, off_t loff, u64 lval, off_t roff,
-                     u64 rval, int flags);
-
-/**
- * scif_get_node_ids() - Return information about online nodes
- * @nodes:     array in which to return online node IDs
- * @len:       number of entries in the nodes array
- * @self:      address to place the node ID of the local node
- *
- * scif_get_node_ids() fills in the nodes array with up to len node IDs of the
- * nodes in the SCIF network. If there is not enough space in nodes, as
- * indicated by the len parameter, only len node IDs are returned in nodes. The
- * return value of scif_get_node_ids() is the total number of nodes currently in
- * the SCIF network. By checking the return value against the len parameter,
- * the user may determine if enough space for nodes was allocated.
- *
- * The node ID of the local node is returned at self.
- *
- * Return:
- * Upon successful completion, scif_get_node_ids() returns the actual number of
- * online nodes in the SCIF network including 'self'; otherwise in user mode
- * -1 is returned and errno is set to indicate the error; in kernel mode no
- * errors are returned.
- */
-int scif_get_node_ids(u16 *nodes, int len, u16 *self);
-
-/**
- * scif_pin_pages() - Pin a set of pages
- * @addr:              Virtual address of range to pin
- * @len:               Length of range to pin
- * @prot_flags:                Page protection flags
- * @map_flags:         Page classification flags
- * @pinned_pages:      Handle to pinned pages
- *
- * scif_pin_pages() pins (locks in physical memory) the physical pages which
- * back the range of virtual address pages starting at addr and continuing for
- * len bytes. addr and len are constrained to be multiples of the page size. A
- * successful scif_pin_pages() call returns a handle to pinned_pages which may
- * be used in subsequent calls to scif_register_pinned_pages().
- *
- * The pages will remain pinned as long as there is a reference against the
- * scif_pinned_pages_t value returned by scif_pin_pages() and until
- * scif_unpin_pages() is called, passing the scif_pinned_pages_t value. A
- * reference is added to a scif_pinned_pages_t value each time a window is
- * created by calling scif_register_pinned_pages() and passing the
- * scif_pinned_pages_t value. A reference is removed from a
- * scif_pinned_pages_t value each time such a window is deleted.
- *
- * Subsequent operations which change the memory pages to which virtual
- * addresses are mapped (such as mmap(), munmap()) have no effect on the
- * scif_pinned_pages_t value or windows created against it.
- *
- * If the process will fork(), it is recommended that the registered
- * virtual address range be marked with MADV_DONTFORK. Doing so will prevent
- * problems due to copy-on-write semantics.
- *
- * The prot_flags argument is formed by OR'ing together one or more of the
- * following values.
- * SCIF_PROT_READ - allow read operations against the pages
- * SCIF_PROT_WRITE - allow write operations against the pages
- * The map_flags argument can be set as SCIF_MAP_KERNEL to interpret addr as a
- * kernel space address. By default, addr is interpreted as a user space
- * address.
- *
- * Return:
- * Upon successful completion, scif_pin_pages() returns 0; otherwise the
- * negative of one of the following errors is returned.
- *
- * Errors:
- * EINVAL - prot_flags is invalid, map_flags is invalid, or offset is negative
- * ENOMEM - Not enough space
- */
-int scif_pin_pages(void *addr, size_t len, int prot_flags, int map_flags,
-                  scif_pinned_pages_t *pinned_pages);
-
-/**
- * scif_unpin_pages() - Unpin a set of pages
- * @pinned_pages:      Handle to pinned pages to be unpinned
- *
- * scif_unpin_pages() prevents scif_register_pinned_pages() from registering new
- * windows against pinned_pages. The physical pages represented by pinned_pages
- * will remain pinned until all windows previously registered against
- * pinned_pages are deleted (the window is scif_unregister()'d and all
- * references to the window are removed (see scif_unregister()).
- *
- * pinned_pages must have been obtain from a previous call to scif_pin_pages().
- * After calling scif_unpin_pages(), it is an error to pass pinned_pages to
- * scif_register_pinned_pages().
- *
- * Return:
- * Upon successful completion, scif_unpin_pages() returns 0; otherwise the
- * negative of one of the following errors is returned.
- *
- * Errors:
- * EINVAL - pinned_pages is not valid
- */
-int scif_unpin_pages(scif_pinned_pages_t pinned_pages);
-
-/**
- * scif_register_pinned_pages() - Mark a memory region for remote access.
- * @epd:               endpoint descriptor
- * @pinned_pages:      Handle to pinned pages
- * @offset:            Registered address space offset
- * @map_flags:         Flags which control where pages are mapped
- *
- * The scif_register_pinned_pages() function opens a window, a range of whole
- * pages of the registered address space of the endpoint epd, starting at
- * offset po. The value of po, further described below, is a function of the
- * parameters offset and pinned_pages, and the value of map_flags. Each page of
- * the window represents a corresponding physical memory page of the range
- * represented by pinned_pages; the length of the window is the same as the
- * length of range represented by pinned_pages. A successful
- * scif_register_pinned_pages() call returns po as the return value.
- *
- * When SCIF_MAP_FIXED is set in the map_flags argument, po will be offset
- * exactly, and offset is constrained to be a multiple of the page size. The
- * mapping established by scif_register_pinned_pages() will not replace any
- * existing registration; an error is returned if any page of the new window
- * would intersect an existing window.
- *
- * When SCIF_MAP_FIXED is not set, the implementation uses offset in an
- * implementation-defined manner to arrive at po. The po so chosen will be an
- * area of the registered address space that the implementation deems suitable
- * for a mapping of the required size. An offset value of 0 is interpreted as
- * granting the implementation complete freedom in selecting po, subject to
- * constraints described below. A non-zero value of offset is taken to be a
- * suggestion of an offset near which the mapping should be placed. When the
- * implementation selects a value for po, it does not replace any extant
- * window. In all cases, po will be a multiple of the page size.
- *
- * The physical pages which are so represented by a window are available for
- * access in calls to scif_get_pages(), scif_readfrom(), scif_writeto(),
- * scif_vreadfrom(), and scif_vwriteto(). While a window is registered, the
- * physical pages represented by the window will not be reused by the memory
- * subsystem for any other purpose. Note that the same physical page may be
- * represented by multiple windows.
- *
- * Windows created by scif_register_pinned_pages() are unregistered by
- * scif_unregister().
- *
- * The map_flags argument can be set to SCIF_MAP_FIXED which interprets a
- * fixed offset.
- *
- * Return:
- * Upon successful completion, scif_register_pinned_pages() returns the offset
- * at which the mapping was placed (po); otherwise the negative of one of the
- * following errors is returned.
- *
- * Errors:
- * EADDRINUSE - SCIF_MAP_FIXED is set in map_flags and pages in the new window
- * would intersect an existing window
- * EAGAIN - The mapping could not be performed due to lack of resources
- * ECONNRESET - Connection reset by peer
- * EINVAL - map_flags is invalid, or SCIF_MAP_FIXED is set in map_flags, and
- * offset is not a multiple of the page size, or offset is negative
- * ENODEV - The remote node is lost or existed, but is not currently in the
- * network since it may have crashed
- * ENOMEM - Not enough space
- * ENOTCONN - The endpoint is not connected
- */
-off_t scif_register_pinned_pages(scif_epd_t epd,
-                                scif_pinned_pages_t pinned_pages,
-                                off_t offset, int map_flags);
-
-/**
- * scif_get_pages() - Add references to remote registered pages
- * @epd:       endpoint descriptor
- * @offset:    remote registered offset
- * @len:       length of range of pages
- * @pages:     returned scif_range structure
- *
- * scif_get_pages() returns the addresses of the physical pages represented by
- * those pages of the registered address space of the peer of epd, starting at
- * offset and continuing for len bytes. offset and len are constrained to be
- * multiples of the page size.
- *
- * All of the pages in the specified range [offset, offset + len - 1] must be
- * within a single window of the registered address space of the peer of epd.
- *
- * The addresses are returned as a virtually contiguous array pointed to by the
- * phys_addr component of the scif_range structure whose address is returned in
- * pages. The nr_pages component of scif_range is the length of the array. The
- * prot_flags component of scif_range holds the protection flag value passed
- * when the pages were registered.
- *
- * Each physical page whose address is returned by scif_get_pages() remains
- * available and will not be released for reuse until the scif_range structure
- * is returned in a call to scif_put_pages(). The scif_range structure returned
- * by scif_get_pages() must be unmodified.
- *
- * It is an error to call scif_close() on an endpoint on which a scif_range
- * structure of that endpoint has not been returned to scif_put_pages().
- *
- * Return:
- * Upon successful completion, scif_get_pages() returns 0; otherwise the
- * negative of one of the following errors is returned.
- * Errors:
- * ECONNRESET - Connection reset by peer.
- * EINVAL - offset is not a multiple of the page size, or offset is negative, or
- * len is not a multiple of the page size
- * ENODEV - The remote node is lost or existed, but is not currently in the
- * network since it may have crashed
- * ENOTCONN - The endpoint is not connected
- * ENXIO - Offsets in the range [offset, offset + len - 1] are invalid
- * for the registered address space of the peer epd
- */
-int scif_get_pages(scif_epd_t epd, off_t offset, size_t len,
-                  struct scif_range **pages);
-
-/**
- * scif_put_pages() - Remove references from remote registered pages
- * @pages:     pages to be returned
- *
- * scif_put_pages() releases a scif_range structure previously obtained by
- * calling scif_get_pages(). The physical pages represented by pages may
- * be reused when the window which represented those pages is unregistered.
- * Therefore, those pages must not be accessed after calling scif_put_pages().
- *
- * Return:
- * Upon successful completion, scif_put_pages() returns 0; otherwise the
- * negative of one of the following errors is returned.
- * Errors:
- * EINVAL - pages does not point to a valid scif_range structure, or
- * the scif_range structure pointed to by pages was already returned
- * ENODEV - The remote node is lost or existed, but is not currently in the
- * network since it may have crashed
- * ENOTCONN - The endpoint is not connected
- */
-int scif_put_pages(struct scif_range *pages);
-
-/**
- * scif_poll() - Wait for some event on an endpoint
- * @epds:      Array of endpoint descriptors
- * @nepds:     Length of epds
- * @timeout:   Upper limit on time for which scif_poll() will block
- *
- * scif_poll() waits for one of a set of endpoints to become ready to perform
- * an I/O operation.
- *
- * The epds argument specifies the endpoint descriptors to be examined and the
- * events of interest for each endpoint descriptor. epds is a pointer to an
- * array with one member for each open endpoint descriptor of interest.
- *
- * The number of items in the epds array is specified in nepds. The epd field
- * of scif_pollepd is an endpoint descriptor of an open endpoint. The field
- * events is a bitmask specifying the events which the application is
- * interested in. The field revents is an output parameter, filled by the
- * kernel with the events that actually occurred. The bits returned in revents
- * can include any of those specified in events, or one of the values EPOLLERR,
- * EPOLLHUP, or EPOLLNVAL. (These three bits are meaningless in the events
- * field, and will be set in the revents field whenever the corresponding
- * condition is true.)
- *
- * If none of the events requested (and no error) has occurred for any of the
- * endpoint descriptors, then scif_poll() blocks until one of the events occurs.
- *
- * The timeout argument specifies an upper limit on the time for which
- * scif_poll() will block, in milliseconds. Specifying a negative value in
- * timeout means an infinite timeout.
- *
- * The following bits may be set in events and returned in revents.
- * EPOLLIN - Data may be received without blocking. For a connected
- * endpoint, this means that scif_recv() may be called without blocking. For a
- * listening endpoint, this means that scif_accept() may be called without
- * blocking.
- * EPOLLOUT - Data may be sent without blocking. For a connected endpoint, this
- * means that scif_send() may be called without blocking. EPOLLOUT may also be
- * used to block waiting for a non-blocking connect to complete. This bit value
- * has no meaning for a listening endpoint and is ignored if specified.
- *
- * The following bits are only returned in revents, and are ignored if set in
- * events.
- * EPOLLERR - An error occurred on the endpoint
- * EPOLLHUP - The connection to the peer endpoint was disconnected
- * EPOLLNVAL - The specified endpoint descriptor is invalid.
- *
- * Return:
- * Upon successful completion, scif_poll() returns a non-negative value. A
- * positive value indicates the total number of endpoint descriptors that have
- * been selected (that is, endpoint descriptors for which the revents member is
- * non-zero). A value of 0 indicates that the call timed out and no endpoint
- * descriptors have been selected. Otherwise in user mode -1 is returned and
- * errno is set to indicate the error; in kernel mode the negative of one of
- * the following errors is returned.
- *
- * Errors:
- * EINTR - A signal occurred before any requested event
- * EINVAL - The nepds argument is greater than {OPEN_MAX}
- * ENOMEM - There was no space to allocate file descriptor tables
- */
-int scif_poll(struct scif_pollepd *epds, unsigned int nepds, long timeout);
-
-/**
- * scif_client_register() - Register a SCIF client
- * @client:    client to be registered
- *
- * scif_client_register() registers a SCIF client. The probe() method
- * of the client is called when SCIF peer devices come online and the
- * remove() method is called when the peer devices disappear.
- *
- * Return:
- * Upon successful completion, scif_client_register() returns a non-negative
- * value. Otherwise the return value is the same as subsys_interface_register()
- * in the kernel.
- */
-int scif_client_register(struct scif_client *client);
-
-/**
- * scif_client_unregister() - Unregister a SCIF client
- * @client:    client to be unregistered
- *
- * scif_client_unregister() unregisters a SCIF client.
- *
- * Return:
- * None
- */
-void scif_client_unregister(struct scif_client *client);
-
-#endif /* __SCIF_H__ */
index 813614d4b71fbcfdcf84ac21b8709949d51e5a3e..b83b3ae3c877f3b4d6e7989681db89ab645e586c 100644 (file)
@@ -107,6 +107,7 @@ void seq_pad(struct seq_file *m, char c);
 char *mangle_path(char *s, const char *p, const char *esc);
 int seq_open(struct file *, const struct seq_operations *);
 ssize_t seq_read(struct file *, char __user *, size_t, loff_t *);
+ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter);
 loff_t seq_lseek(struct file *, loff_t, int);
 int seq_release(struct inode *, struct file *);
 int seq_write(struct seq_file *seq, const void *data, size_t len);
index 7bbc0e9cf084728ba6b28fbfb3ed736ee4a6e576..b256f9c65661cca7a5314af58aadac76b2a10f07 100644 (file)
@@ -238,6 +238,7 @@ static inline void siginitset(sigset_t *set, unsigned long mask)
                memset(&set->sig[1], 0, sizeof(long)*(_NSIG_WORDS-1));
                break;
        case 2: set->sig[1] = 0;
+               break;
        case 1: ;
        }
 }
@@ -250,6 +251,7 @@ static inline void siginitsetinv(sigset_t *set, unsigned long mask)
                memset(&set->sig[1], -1, sizeof(long)*(_NSIG_WORDS-1));
                break;
        case 2: set->sig[1] = -1;
+               break;
        case 1: ;
        }
 }
index 99380c0825dbe1818460556312fee5d23c9c9fc1..b390fdac158760bf7330c3e1d88caecb850fccc5 100644 (file)
@@ -734,6 +734,25 @@ static inline struct spi_controller *spi_alloc_slave(struct device *host,
        return __spi_alloc_controller(host, size, true);
 }
 
+struct spi_controller *__devm_spi_alloc_controller(struct device *dev,
+                                                  unsigned int size,
+                                                  bool slave);
+
+static inline struct spi_controller *devm_spi_alloc_master(struct device *dev,
+                                                          unsigned int size)
+{
+       return __devm_spi_alloc_controller(dev, size, false);
+}
+
+static inline struct spi_controller *devm_spi_alloc_slave(struct device *dev,
+                                                         unsigned int size)
+{
+       if (!IS_ENABLED(CONFIG_SPI_SLAVE))
+               return NULL;
+
+       return __devm_spi_alloc_controller(dev, size, true);
+}
+
 extern int spi_register_controller(struct spi_controller *ctlr);
 extern int devm_spi_register_controller(struct device *dev,
                                        struct spi_controller *ctlr);
index 513913ff748626e7a57376eaa6e7a382234239a4..fbdc657821957ec2a5d180d2dc912589270bf3af 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/dma-direction.h>
 #include <linux/init.h>
 #include <linux/types.h>
+#include <linux/limits.h>
 
 struct device;
 struct page;
@@ -45,13 +46,9 @@ enum dma_sync_target {
        SYNC_FOR_DEVICE = 1,
 };
 
-extern phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
-                                         dma_addr_t tbl_dma_addr,
-                                         phys_addr_t phys,
-                                         size_t mapping_size,
-                                         size_t alloc_size,
-                                         enum dma_data_direction dir,
-                                         unsigned long attrs);
+phys_addr_t swiotlb_tbl_map_single(struct device *hwdev, phys_addr_t phys,
+               size_t mapping_size, size_t alloc_size,
+               enum dma_data_direction dir, unsigned long attrs);
 
 extern void swiotlb_tbl_unmap_single(struct device *hwdev,
                                     phys_addr_t tlb_addr,
index c9dcb3e5781f8bac8169c783c3f42ab0e6d418fe..5117cb5b56561878d10126cd2fbef4b65b46574b 100644 (file)
@@ -124,6 +124,10 @@ static inline bool timespec64_valid_settod(const struct timespec64 *ts)
  */
 static inline s64 timespec64_to_ns(const struct timespec64 *ts)
 {
+       /* Prevent multiplication overflow */
+       if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX)
+               return KTIME_MAX;
+
        return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
 }
 
index a99e9b8e4e316b715d2f7b7cd28d8cf5fb4395b3..eb33d948788cc3ceed5a08ac1963fd05a5eff3f5 100644 (file)
@@ -306,6 +306,10 @@ struct tty_struct {
        struct termiox *termiox;        /* May be NULL for unsupported */
        char name[64];
        struct pid *pgrp;               /* Protected by ctrl lock */
+       /*
+        * Writes protected by both ctrl lock and legacy mutex, readers must use
+        * at least one of them.
+        */
        struct pid *session;
        unsigned long flags;
        int count;
index 2040696d75b6e03b6bf7802149068093dc51afe8..a2d229ab63ba58d548c822b6e3956a023e54320b 100644 (file)
@@ -437,7 +437,7 @@ static inline struct usb_composite_driver *to_cdriver(
 #define OS_STRING_IDX                  0xEE
 
 /**
- * struct usb_composite_device - represents one composite usb gadget
+ * struct usb_composite_dev - represents one composite usb gadget
  * @gadget: read-only, abstracts the gadget's usb peripheral controller
  * @req: used for control responses; buffer is pre-allocated
  * @os_desc_req: used for OS descriptors responses; buffer is pre-allocated
index eae0bfd87d911cb956b935b5e65253f5c41a99c3..30bc7a7223bb7476b75f67e8ba07e5d80df2dec1 100644 (file)
@@ -52,6 +52,16 @@ struct vdpa_device {
        int nvqs;
 };
 
+/**
+ * vDPA IOVA range - the IOVA range support by the device
+ * @first: start of the IOVA range
+ * @last: end of the IOVA range
+ */
+struct vdpa_iova_range {
+       u64 first;
+       u64 last;
+};
+
 /**
  * vDPA_config_ops - operations for configuring a vDPA device.
  * Note: vDPA device drivers are required to implement all of the
@@ -151,6 +161,10 @@ struct vdpa_device {
  * @get_generation:            Get device config generation (optional)
  *                             @vdev: vdpa device
  *                             Returns u32: device generation
+ * @get_iova_range:            Get supported iova range (optional)
+ *                             @vdev: vdpa device
+ *                             Returns the iova range supported by
+ *                             the device.
  * @set_map:                   Set device memory mapping (optional)
  *                             Needed for device that using device
  *                             specific DMA translation (on-chip IOMMU)
@@ -216,6 +230,7 @@ struct vdpa_config_ops {
        void (*set_config)(struct vdpa_device *vdev, unsigned int offset,
                           const void *buf, unsigned int len);
        u32 (*get_generation)(struct vdpa_device *vdev);
+       struct vdpa_iova_range (*get_iova_range)(struct vdpa_device *vdev);
 
        /* DMA ops */
        int (*set_map)(struct vdpa_device *vdev, struct vhost_iotlb *iotlb);
index 0fdbf653b173f1450964c3b17238d7e027dcd601..4807ca4d52e039eed97c5fccf54da9814bd3d15b 100644 (file)
@@ -20,7 +20,6 @@
  * zsmalloc mapping modes
  *
  * NOTE: These only make a difference when a mapped object spans pages.
- * They also have no effect when ZSMALLOC_PGTABLE_MAPPING is selected.
  */
 enum zs_mapmode {
        ZS_MM_RW, /* normal read-write mapping */
index 7d132cc1e58481f4550dcd7eea95cc0cf95d02ea..d9d0ff3b0ad3272c97f4fcde915cf6396fb66a85 100644 (file)
@@ -185,6 +185,11 @@ struct slave {
        struct rtnl_link_stats64 slave_stats;
 };
 
+static inline struct slave *to_slave(struct kobject *kobj)
+{
+       return container_of(kobj, struct slave, kobj);
+}
+
 struct bond_up_slave {
        unsigned int    count;
        struct rcu_head rcu;
@@ -750,6 +755,9 @@ extern struct bond_parm_tbl ad_select_tbl[];
 /* exported from bond_netlink.c */
 extern struct rtnl_link_ops bond_link_ops;
 
+/* exported from bond_sysfs_slave.c */
+extern const struct sysfs_ops slave_sysfs_ops;
+
 static inline netdev_tx_t bond_tx_drop(struct net_device *dev, struct sk_buff *skb)
 {
        atomic_long_inc(&dev->tx_dropped);
index 661edfc8722e1cf205cceb836a851de40210e1a8..d5ab8d99739f1e3c2acf90f86fd6966d2df4c96d 100644 (file)
@@ -1444,7 +1444,7 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
                                  enum cfg80211_station_type statype);
 
 /**
- * enum station_info_rate_flags - bitrate info flags
+ * enum rate_info_flags - bitrate info flags
  *
  * Used by the driver to indicate the specific rate transmission
  * type for 802.11n transmissions.
@@ -1517,7 +1517,7 @@ struct rate_info {
 };
 
 /**
- * enum station_info_rate_flags - bitrate info flags
+ * enum bss_param_flags - bitrate info flags
  *
  * Used by the driver to indicate the specific rate transmission
  * type for 802.11n transmissions.
@@ -6467,7 +6467,8 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
                          struct ieee80211_channel *channel, gfp_t gfp);
 
 /**
- * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate
+ * cfg80211_notify_new_peer_candidate - notify cfg80211 of a new mesh peer
+ *                                     candidate
  *
  * @dev: network device
  * @macaddr: the MAC address of the new candidate
@@ -7606,7 +7607,7 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate);
 void cfg80211_unregister_wdev(struct wireless_dev *wdev);
 
 /**
- * struct cfg80211_ft_event - FT Information Elements
+ * struct cfg80211_ft_event_params - FT Information Elements
  * @ies: FT IEs
  * @ies_len: length of the FT IE in bytes
  * @target_ap: target AP's MAC address
index e1eaf17802889dbb8143ae9b9523de4614708ed5..563457fec557ef6904bd247e4b08420761ba846e 100644 (file)
@@ -107,7 +107,7 @@ static inline int IP_ECN_set_ect1(struct iphdr *iph)
        if ((iph->tos & INET_ECN_MASK) != INET_ECN_ECT_0)
                return 0;
 
-       check += (__force u16)htons(0x100);
+       check += (__force u16)htons(0x1);
 
        iph->check = (__force __sum16)(check + (check>=0xFFFF));
        iph->tos ^= INET_ECN_MASK;
index 92560974ea67e6e3de6adad9dd9a75c6de9386fb..ca6a3ea9057ec431b2dd30726c2e6d06be94fe72 100644 (file)
@@ -247,8 +247,9 @@ void inet_hashinfo2_init(struct inet_hashinfo *h, const char *name,
                         unsigned long high_limit);
 int inet_hashinfo2_init_mod(struct inet_hashinfo *h);
 
-bool inet_ehash_insert(struct sock *sk, struct sock *osk);
-bool inet_ehash_nolisten(struct sock *sk, struct sock *osk);
+bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk);
+bool inet_ehash_nolisten(struct sock *sk, struct sock *osk,
+                        bool *found_dup_sk);
 int __inet_hash(struct sock *sk, struct sock *osk);
 int inet_hash(struct sock *sk);
 void inet_unhash(struct sock *sk);
index 02ccd32542d0addb47578c419dd77447e462eb68..61620677b0347aed94c1955503832427e1d608e3 100644 (file)
@@ -478,9 +478,11 @@ static inline void ip_tunnel_info_opts_set(struct ip_tunnel_info *info,
                                           const void *from, int len,
                                           __be16 flags)
 {
-       memcpy(ip_tunnel_info_opts(info), from, len);
        info->options_len = len;
-       info->key.tun_flags |= flags;
+       if (len > 0) {
+               memcpy(ip_tunnel_info_opts(info), from, len);
+               info->key.tun_flags |= flags;
+       }
 }
 
 static inline struct ip_tunnel_info *lwt_tun_info(struct lwtunnel_state *lwtstate)
@@ -526,7 +528,6 @@ static inline void ip_tunnel_info_opts_set(struct ip_tunnel_info *info,
                                           __be16 flags)
 {
        info->options_len = 0;
-       info->key.tun_flags |= flags;
 }
 
 #endif /* CONFIG_INET */
index a21e8b1381a107c8afd4a832f523bc87d045b890..851029ecff13cb617d41b4043f039ae59e832b82 100644 (file)
@@ -108,5 +108,35 @@ out_rcu_unlock:
        rcu_read_unlock();
        inet_frag_put(&fq->q);
 }
+
+/* Check if the upper layer header is truncated in the first fragment. */
+static inline bool
+ipv6frag_thdr_truncated(struct sk_buff *skb, int start, u8 *nexthdrp)
+{
+       u8 nexthdr = *nexthdrp;
+       __be16 frag_off;
+       int offset;
+
+       offset = ipv6_skip_exthdr(skb, start, &nexthdr, &frag_off);
+       if (offset < 0 || (frag_off & htons(IP6_OFFSET)))
+               return false;
+       switch (nexthdr) {
+       case NEXTHDR_TCP:
+               offset += sizeof(struct tcphdr);
+               break;
+       case NEXTHDR_UDP:
+               offset += sizeof(struct udphdr);
+               break;
+       case NEXTHDR_ICMP:
+               offset += sizeof(struct icmp6hdr);
+               break;
+       default:
+               offset += 1;
+       }
+       if (offset > skb->len)
+               return true;
+       return false;
+}
+
 #endif
 #endif
index e8e295dae744e4dc8d86182d193e0e387206a6e9..dcdba96814a2bf59dab074668ad632c6bc814566 100644 (file)
@@ -3311,7 +3311,7 @@ enum ieee80211_roc_type {
 };
 
 /**
- * enum ieee80211_reconfig_complete_type - reconfig type
+ * enum ieee80211_reconfig_type - reconfig type
  *
  * This enum is used by the reconfig_complete() callback to indicate what
  * reconfiguration type was completed.
@@ -6334,7 +6334,8 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
                              int band, struct ieee80211_sta **sta);
 
 /**
- * Sanity-check and parse the radiotap header of injected frames
+ * ieee80211_parse_tx_radiotap - Sanity-check and parse the radiotap header
+ *                              of injected frames
  * @skb: packet injected by userspace
  * @dev: the &struct device of this 802.11 device
  */
@@ -6389,7 +6390,7 @@ int ieee80211_parse_p2p_noa(const struct ieee80211_p2p_noa_attr *attr,
 void ieee80211_update_p2p_noa(struct ieee80211_noa_data *data, u32 tsf);
 
 /**
- * ieee80211_tdls_oper - request userspace to perform a TDLS operation
+ * ieee80211_tdls_oper_request - request userspace to perform a TDLS operation
  * @vif: virtual interface
  * @peer: the peer's destination address
  * @oper: the requested TDLS operation
index 81ee17594c329fedf9c01d72eb66cb28eaf123d4..22ced1381ede51914ae80bab47dcd6154de074aa 100644 (file)
@@ -204,6 +204,7 @@ struct neigh_table {
        int                     (*pconstructor)(struct pneigh_entry *);
        void                    (*pdestructor)(struct pneigh_entry *);
        void                    (*proxy_redo)(struct sk_buff *skb);
+       int                     (*is_multicast)(const void *pkey);
        bool                    (*allow_add)(const struct net_device *dev,
                                             struct netlink_ext_ack *extack);
        char                    *id;
index ea7d1d78b92d2a6a64f6017d7ffa1fe0af142997..1d34fe154fe0bd39898d1b81a571ca8e5490dbd3 100644 (file)
@@ -37,6 +37,7 @@ void nft_offload_update_dependency(struct nft_offload_ctx *ctx,
 
 struct nft_flow_key {
        struct flow_dissector_key_basic                 basic;
+       struct flow_dissector_key_control               control;
        union {
                struct flow_dissector_key_ipv4_addrs    ipv4;
                struct flow_dissector_key_ipv6_addrs    ipv6;
@@ -62,6 +63,9 @@ struct nft_flow_rule {
 
 #define NFT_OFFLOAD_F_ACTION   (1 << 0)
 
+void nft_flow_rule_set_addr_type(struct nft_flow_rule *flow,
+                                enum flow_dissector_key_id addr_type);
+
 struct nft_rule;
 struct nft_flow_rule *nft_flow_rule_create(struct net *net, const struct nft_rule *rule);
 void nft_flow_rule_destroy(struct nft_flow_rule *flow);
@@ -74,6 +78,9 @@ int nft_flow_rule_offload_commit(struct net *net);
                offsetof(struct nft_flow_key, __base.__field);          \
        (__reg)->len            = __len;                                \
        (__reg)->key            = __key;                                \
+
+#define NFT_OFFLOAD_MATCH_EXACT(__key, __base, __field, __len, __reg)  \
+       NFT_OFFLOAD_MATCH(__key, __base, __field, __len, __reg)         \
        memset(&(__reg)->mask, 0xff, (__reg)->len);
 
 int nft_chain_offload_priority(struct nft_base_chain *basechain);
index baf1e99d8193ae8230743f4955b5e96ae2ab622d..2bdd802212fe00325322ee0a8b16abd13f06c72b 100644 (file)
@@ -199,6 +199,12 @@ enum tls_context_flags {
         * to be atomic.
         */
        TLS_TX_SYNC_SCHED = 1,
+       /* tls_dev_del was called for the RX side, device state was released,
+        * but tls_ctx->netdev might still be kept, because TX-side driver
+        * resources might not be released yet. Used to prevent the second
+        * tls_dev_del call in tls_device_down if it happens simultaneously.
+        */
+       TLS_RX_DEV_CLOSED = 2,
 };
 
 struct cipher_context {
@@ -300,7 +306,8 @@ enum tls_offload_sync_type {
 #define TLS_DEVICE_RESYNC_ASYNC_LOGMAX         13
 struct tls_offload_resync_async {
        atomic64_t req;
-       u32 loglen;
+       u16 loglen;
+       u16 rcd_delta;
        u32 log[TLS_DEVICE_RESYNC_ASYNC_LOGMAX];
 };
 
@@ -471,6 +478,18 @@ static inline bool tls_bigint_increment(unsigned char *seq, int len)
        return (i == -1);
 }
 
+static inline void tls_bigint_subtract(unsigned char *seq, int  n)
+{
+       u64 rcd_sn;
+       __be64 *p;
+
+       BUILD_BUG_ON(TLS_MAX_REC_SEQ_SIZE != 8);
+
+       p = (__be64 *)seq;
+       rcd_sn = be64_to_cpu(*p);
+       *p = cpu_to_be64(rcd_sn - n);
+}
+
 static inline struct tls_context *tls_get_ctx(const struct sock *sk)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
@@ -639,6 +658,7 @@ tls_offload_rx_resync_async_request_start(struct sock *sk, __be32 seq, u16 len)
        atomic64_set(&rx_ctx->resync_async->req, ((u64)ntohl(seq) << 32) |
                     ((u64)len << 16) | RESYNC_REQ | RESYNC_REQ_ASYNC);
        rx_ctx->resync_async->loglen = 0;
+       rx_ctx->resync_async->rcd_delta = 0;
 }
 
 static inline void
index 1a9559c0cbdda363fcc5489ddec51df963720174..4f4e93bf814c3e66b392f4bca8dd6e565685f0bc 100644 (file)
@@ -31,6 +31,7 @@ struct xdp_umem {
        struct page **pgs;
        int id;
        struct list_head xsk_dma_list;
+       struct work_struct work;
 };
 
 struct xsk_map {
index 0140d086dc84ea5afae280cacb6541873df5819a..01755b838c745079c53b6daefd7a44322ef1d7c3 100644 (file)
@@ -86,7 +86,7 @@ int xp_assign_dev_shared(struct xsk_buff_pool *pool, struct xdp_umem *umem,
 void xp_destroy(struct xsk_buff_pool *pool);
 void xp_release(struct xdp_buff_xsk *xskb);
 void xp_get_pool(struct xsk_buff_pool *pool);
-void xp_put_pool(struct xsk_buff_pool *pool);
+bool xp_put_pool(struct xsk_buff_pool *pool);
 void xp_clear_dev(struct xsk_buff_pool *pool);
 void xp_add_xsk(struct xsk_buff_pool *pool, struct xdp_sock *xs);
 void xp_del_xsk(struct xsk_buff_pool *pool, struct xdp_sock *xs);
index c672ae1da26bb5f022da290af726f1cb7f62460f..32a67af18415d6f5bad03fb25b04a48e0c340b79 100644 (file)
@@ -227,19 +227,9 @@ void rdma_destroy_qp(struct rdma_cm_id *id);
 int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
                       int *qp_attr_mask);
 
-/**
- * rdma_connect - Initiate an active connection request.
- * @id: Connection identifier to connect.
- * @conn_param: Connection information used for connected QPs.
- *
- * Users must have resolved a route for the rdma_cm_id to connect with
- * by having called rdma_resolve_route before calling this routine.
- *
- * This call will either connect to a remote QP or obtain remote QP
- * information for unconnected rdma_cm_id's.  The actual operation is
- * based on the rdma_cm_id's port space.
- */
 int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);
+int rdma_connect_locked(struct rdma_cm_id *id,
+                       struct rdma_conn_param *conn_param);
 
 int rdma_connect_ece(struct rdma_cm_id *id, struct rdma_conn_param *conn_param,
                     struct rdma_ucm_ece *ece);
index c25fb86ffae9587a1239e5b4f1482e0351cc09d9..b3bbd10eb3f0797ee7acb0acd75fae37b8910b13 100644 (file)
@@ -132,6 +132,9 @@ struct iscsi_task {
        void                    *dd_data;       /* driver/transport data */
 };
 
+/* invalid scsi_task pointer */
+#define        INVALID_SCSI_TASK       (struct iscsi_task *)-1l
+
 static inline int iscsi_task_has_unsol_data(struct iscsi_task *task)
 {
        return task->unsol_r2t.data_length > task->unsol_r2t.sent;
index e128cff10dfaf3f60c48a5f9fe48441b9ca37c2d..77d9fa10812d01dcc35f0b24b6fc5a66cbe9bb94 100644 (file)
@@ -42,7 +42,7 @@ struct snd_kcontrol_new {
        snd_ctl_elem_iface_t iface;     /* interface identifier */
        unsigned int device;            /* device/client number */
        unsigned int subdevice;         /* subdevice (substream) number */
-       const unsigned char *name;      /* ASCII name of item */
+       const char *name;               /* ASCII name of item */
        unsigned int index;             /* index of item */
        unsigned int access;            /* access rights */
        unsigned int count;             /* count of same elements */
index 381a010a1bd4d2f38d953340f3f42f9e66306848..0462c577d7a3f832d38442c637cd16ab1488866e 100644 (file)
@@ -332,7 +332,8 @@ void __snd_printk(unsigned int level, const char *file, int line,
 #define snd_BUG()              WARN(1, "BUG?\n")
 
 /**
- * Suppress high rates of output when CONFIG_SND_DEBUG is enabled.
+ * snd_printd_ratelimit - Suppress high rates of output when
+ *                       CONFIG_SND_DEBUG is enabled.
  */
 #define snd_printd_ratelimit() printk_ratelimit()
 
index 2ba5df2c9e235737726cc14f13d9bffa2c3e6555..2336bf9243e185cd0e8b84b4afe3add26faf59b6 100644 (file)
@@ -1284,8 +1284,8 @@ snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs)
 }
 
 /**
- * snd_pcm_sgbuf_chunk_size - Compute the max size that fits within the contig.
- * page from the given size
+ * snd_pcm_sgbuf_get_chunk_size - Compute the max size that fits within the
+ * contig. page from the given size
  * @substream: PCM substream
  * @ofs: byte offset
  * @size: byte size to examine
diff --git a/include/sound/rt1015.h b/include/sound/rt1015.h
new file mode 100644 (file)
index 0000000..70a7538
--- /dev/null
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * linux/sound/rt1015.h -- Platform data for RT1015
+ *
+ * Copyright 2020 Realtek Microelectronics
+ */
+
+#ifndef __LINUX_SND_RT1015_H
+#define __LINUX_SND_RT1015_H
+
+struct rt1015_platform_data {
+       unsigned int power_up_delay_ms;
+};
+
+#endif
index 8eb49231c6bb7bc75d2f63127abe86d9e1656ce7..4eef374d4413e2ce79254846fafda749be3a05ce 100644 (file)
@@ -966,19 +966,6 @@ TRACE_EVENT(afs_dir_check_failed,
                      __entry->vnode, __entry->off, __entry->i_size)
            );
 
-/*
- * We use page->private to hold the amount of the page that we've written to,
- * splitting the field into two parts.  However, we need to represent a range
- * 0...PAGE_SIZE inclusive, so we can't support 64K pages on a 32-bit system.
- */
-#if PAGE_SIZE > 32768
-#define AFS_PRIV_MAX   0xffffffff
-#define AFS_PRIV_SHIFT 32
-#else
-#define AFS_PRIV_MAX   0xffff
-#define AFS_PRIV_SHIFT 16
-#endif
-
 TRACE_EVENT(afs_page_dirty,
            TP_PROTO(struct afs_vnode *vnode, const char *where,
                     pgoff_t page, unsigned long priv),
@@ -999,10 +986,11 @@ TRACE_EVENT(afs_page_dirty,
                    __entry->priv = priv;
                           ),
 
-           TP_printk("vn=%p %lx %s %lu-%lu",
+           TP_printk("vn=%p %lx %s %zx-%zx%s",
                      __entry->vnode, __entry->page, __entry->where,
-                     __entry->priv & AFS_PRIV_MAX,
-                     __entry->priv >> AFS_PRIV_SHIFT)
+                     afs_page_dirty_from(__entry->priv),
+                     afs_page_dirty_to(__entry->priv),
+                     afs_is_page_dirty_mmapped(__entry->priv) ? " M" : "")
            );
 
 TRACE_EVENT(afs_call_state,
index b14314fcf732212c6d9c89ac781f4bfb3206d6b3..70ae5497b73a6d3da4ec9543aa34c6cebf073a2e 100644 (file)
@@ -100,11 +100,12 @@ TRACE_DEFINE_ENUM(ES_REFERENCED_B);
                { EXT4_FC_REASON_XATTR,         "XATTR"},               \
                { EXT4_FC_REASON_CROSS_RENAME,  "CROSS_RENAME"},        \
                { EXT4_FC_REASON_JOURNAL_FLAG_CHANGE, "JOURNAL_FLAG_CHANGE"}, \
-               { EXT4_FC_REASON_MEM,   "NO_MEM"},                      \
+               { EXT4_FC_REASON_NOMEM, "NO_MEM"},                      \
                { EXT4_FC_REASON_SWAP_BOOT,     "SWAP_BOOT"},           \
                { EXT4_FC_REASON_RESIZE,        "RESIZE"},              \
                { EXT4_FC_REASON_RENAME_DIR,    "RENAME_DIR"},          \
-               { EXT4_FC_REASON_FALLOC_RANGE,  "FALLOC_RANGE"})
+               { EXT4_FC_REASON_FALLOC_RANGE,  "FALLOC_RANGE"},        \
+               { EXT4_FC_REASON_INODE_JOURNAL_DATA,    "INODE_JOURNAL_DATA"})
 
 TRACE_EVENT(ext4_other_inode_update_time,
        TP_PROTO(struct inode *inode, ino_t orig_ino),
@@ -2917,17 +2918,18 @@ TRACE_EVENT(ext4_fc_stats,
                    ),
 
            TP_printk("dev %d:%d fc ineligible reasons:\n"
-                     "%s:%d, %s:%d, %s:%d, %s:%d, %s:%d, %s:%d, %s:%d, %s,%d; "
+                     "%s:%d, %s:%d, %s:%d, %s:%d, %s:%d, %s:%d, %s:%d, %s:%d, %s:%d; "
                      "num_commits:%ld, ineligible: %ld, numblks: %ld",
                      MAJOR(__entry->dev), MINOR(__entry->dev),
                      FC_REASON_NAME_STAT(EXT4_FC_REASON_XATTR),
                      FC_REASON_NAME_STAT(EXT4_FC_REASON_CROSS_RENAME),
                      FC_REASON_NAME_STAT(EXT4_FC_REASON_JOURNAL_FLAG_CHANGE),
-                     FC_REASON_NAME_STAT(EXT4_FC_REASON_MEM),
+                     FC_REASON_NAME_STAT(EXT4_FC_REASON_NOMEM),
                      FC_REASON_NAME_STAT(EXT4_FC_REASON_SWAP_BOOT),
                      FC_REASON_NAME_STAT(EXT4_FC_REASON_RESIZE),
                      FC_REASON_NAME_STAT(EXT4_FC_REASON_RENAME_DIR),
                      FC_REASON_NAME_STAT(EXT4_FC_REASON_FALLOC_RANGE),
+                     FC_REASON_NAME_STAT(EXT4_FC_REASON_INODE_JOURNAL_DATA),
                      __entry->sbi->s_fc_stats.fc_num_commits,
                      __entry->sbi->s_fc_stats.fc_ineligible_commits,
                      __entry->sbi->s_fc_stats.fc_numblks)
index f45b3c01370ca9b2d17e34e7491d84a18e07a985..2a03263b5f9d4f0825c68eeabbcbef034920b416 100644 (file)
@@ -68,7 +68,8 @@ DECLARE_EVENT_CLASS(rpc_xdr_buf_class,
 
        TP_fast_assign(
                __entry->task_id = task->tk_pid;
-               __entry->client_id = task->tk_client->cl_clid;
+               __entry->client_id = task->tk_client ?
+                                    task->tk_client->cl_clid : -1;
                __entry->head_base = xdr->head[0].iov_base;
                __entry->head_len = xdr->head[0].iov_len;
                __entry->tail_base = xdr->tail[0].iov_base;
@@ -655,10 +656,10 @@ TRACE_EVENT(rpc_xdr_overflow,
                __field(size_t, tail_len)
                __field(unsigned int, page_len)
                __field(unsigned int, len)
-               __string(progname,
-                        xdr->rqst->rq_task->tk_client->cl_program->name)
-               __string(procedure,
-                        xdr->rqst->rq_task->tk_msg.rpc_proc->p_name)
+               __string(progname, xdr->rqst ?
+                        xdr->rqst->rq_task->tk_client->cl_program->name : "unknown")
+               __string(procedure, xdr->rqst ?
+                        xdr->rqst->rq_task->tk_msg.rpc_proc->p_name : "unknown")
        ),
 
        TP_fast_assign(
index e7cbccc7c14cc28c1bb77557583df75974e60dd7..57d795365987d098dc3b515274d7f7e996ff32d5 100644 (file)
@@ -190,7 +190,7 @@ TRACE_EVENT(inode_foreign_history,
        ),
 
        TP_fast_assign(
-               strncpy(__entry->name, bdi_dev_name(inode_to_bdi(inode)), 32);
+               strscpy_pad(__entry->name, bdi_dev_name(inode_to_bdi(inode)), 32);
                __entry->ino            = inode->i_ino;
                __entry->cgroup_ino     = __trace_wbc_assign_cgroup(wbc);
                __entry->history        = history;
@@ -219,7 +219,7 @@ TRACE_EVENT(inode_switch_wbs,
        ),
 
        TP_fast_assign(
-               strncpy(__entry->name,  bdi_dev_name(old_wb->bdi), 32);
+               strscpy_pad(__entry->name, bdi_dev_name(old_wb->bdi), 32);
                __entry->ino            = inode->i_ino;
                __entry->old_cgroup_ino = __trace_wb_assign_cgroup(old_wb);
                __entry->new_cgroup_ino = __trace_wb_assign_cgroup(new_wb);
@@ -252,7 +252,7 @@ TRACE_EVENT(track_foreign_dirty,
                struct address_space *mapping = page_mapping(page);
                struct inode *inode = mapping ? mapping->host : NULL;
 
-               strncpy(__entry->name,  bdi_dev_name(wb->bdi), 32);
+               strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32);
                __entry->bdi_id         = wb->bdi->id;
                __entry->ino            = inode ? inode->i_ino : 0;
                __entry->memcg_id       = wb->memcg_css->id;
@@ -285,7 +285,7 @@ TRACE_EVENT(flush_foreign,
        ),
 
        TP_fast_assign(
-               strncpy(__entry->name,  bdi_dev_name(wb->bdi), 32);
+               strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32);
                __entry->cgroup_ino     = __trace_wb_assign_cgroup(wb);
                __entry->frn_bdi_id     = frn_bdi_id;
                __entry->frn_memcg_id   = frn_memcg_id;
index 0113bc4db9f554d6f3b600d6a38deb2e54408500..5203f54a2be1c0c5a628da9608ecddfa132553d0 100644 (file)
@@ -526,6 +526,8 @@ enum devlink_attr {
        DEVLINK_ATTR_RELOAD_STATS_LIMIT,        /* u8 */
        DEVLINK_ATTR_RELOAD_STATS_VALUE,        /* u32 */
        DEVLINK_ATTR_REMOTE_RELOAD_STATS,       /* nested */
+       DEVLINK_ATTR_RELOAD_ACTION_INFO,        /* nested */
+       DEVLINK_ATTR_RELOAD_ACTION_STATS,       /* nested */
 
        /* add new attributes above here, update the policy in devlink.c */
 
index 07865c60109949fc7fb5bbb40cc1f5d77a5894b5..2072c260f5d08df8a70970a8d202f168bdeb8c80 100644 (file)
@@ -26,7 +26,7 @@
  * struct gpiochip_info - Information about a certain GPIO chip
  * @name: the Linux kernel name of this GPIO chip
  * @label: a functional name for this GPIO chip, such as a product
- * number, may be empty
+ * number, may be empty (i.e. label[0] == '\0')
  * @lines: number of GPIO lines on this chip
  */
 struct gpiochip_info {
@@ -98,7 +98,7 @@ struct gpio_v2_line_values {
  * identifying which field of the attribute union is in use.
  * @GPIO_V2_LINE_ATTR_ID_FLAGS: flags field is in use
  * @GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES: values field is in use
- * @GPIO_V2_LINE_ATTR_ID_DEBOUNCE: debounce_period_us is in use
+ * @GPIO_V2_LINE_ATTR_ID_DEBOUNCE: debounce_period_us field is in use
  */
 enum gpio_v2_line_attr_id {
        GPIO_V2_LINE_ATTR_ID_FLAGS              = 1,
@@ -110,17 +110,17 @@ enum gpio_v2_line_attr_id {
  * struct gpio_v2_line_attribute - a configurable attribute of a line
  * @id: attribute identifier with value from &enum gpio_v2_line_attr_id
  * @padding: reserved for future use and must be zero filled
- * @flags: if id is GPIO_V2_LINE_ATTR_ID_FLAGS, the flags for the GPIO
- * line, with values from enum gpio_v2_line_flag, such as
- * GPIO_V2_LINE_FLAG_ACTIVE_LOW, GPIO_V2_LINE_FLAG_OUTPUT etc, OR:ed
+ * @flags: if id is %GPIO_V2_LINE_ATTR_ID_FLAGS, the flags for the GPIO
+ * line, with values from &enum gpio_v2_line_flag, such as
+ * %GPIO_V2_LINE_FLAG_ACTIVE_LOW, %GPIO_V2_LINE_FLAG_OUTPUT etc, added
  * together.  This overrides the default flags contained in the &struct
  * gpio_v2_line_config for the associated line.
- * @values: if id is GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES, a bitmap
+ * @values: if id is %GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES, a bitmap
  * containing the values to which the lines will be set, with each bit
  * number corresponding to the index into &struct
  * gpio_v2_line_request.offsets.
- * @debounce_period_us: if id is GPIO_V2_LINE_ATTR_ID_DEBOUNCE, the desired
- * debounce period, in microseconds
+ * @debounce_period_us: if id is %GPIO_V2_LINE_ATTR_ID_DEBOUNCE, the
+ * desired debounce period, in microseconds
  */
 struct gpio_v2_line_attribute {
        __u32 id;
@@ -147,12 +147,12 @@ struct gpio_v2_line_config_attribute {
 
 /**
  * struct gpio_v2_line_config - Configuration for GPIO lines
- * @flags: flags for the GPIO lines, with values from enum
- * gpio_v2_line_flag, such as GPIO_V2_LINE_FLAG_ACTIVE_LOW,
- * GPIO_V2_LINE_FLAG_OUTPUT etc, OR:ed together.  This is the default for
+ * @flags: flags for the GPIO lines, with values from &enum
+ * gpio_v2_line_flag, such as %GPIO_V2_LINE_FLAG_ACTIVE_LOW,
+ * %GPIO_V2_LINE_FLAG_OUTPUT etc, added together.  This is the default for
  * all requested lines but may be overridden for particular lines using
- * attrs.
- * @num_attrs: the number of attributes in attrs
+ * @attrs.
+ * @num_attrs: the number of attributes in @attrs
  * @padding: reserved for future use and must be zero filled
  * @attrs: the configuration attributes associated with the requested
  * lines.  Any attribute should only be associated with a particular line
@@ -175,17 +175,17 @@ struct gpio_v2_line_config {
  * "my-bitbanged-relay"
  * @config: requested configuration for the lines.
  * @num_lines: number of lines requested in this request, i.e. the number
- * of valid fields in the GPIO_V2_LINES_MAX sized arrays, set to 1 to
+ * of valid fields in the %GPIO_V2_LINES_MAX sized arrays, set to 1 to
  * request a single line
  * @event_buffer_size: a suggested minimum number of line events that the
  * kernel should buffer.  This is only relevant if edge detection is
  * enabled in the configuration. Note that this is only a suggested value
  * and the kernel may allocate a larger buffer or cap the size of the
  * buffer. If this field is zero then the buffer size defaults to a minimum
- * of num_lines*16.
+ * of @num_lines * 16.
  * @padding: reserved for future use and must be zero filled
  * @fd: if successful this field will contain a valid anonymous file handle
- * after a GPIO_GET_LINE_IOCTL operation, zero or negative value means
+ * after a %GPIO_GET_LINE_IOCTL operation, zero or negative value means
  * error
  */
 struct gpio_v2_line_request {
@@ -203,15 +203,16 @@ struct gpio_v2_line_request {
  * struct gpio_v2_line_info - Information about a certain GPIO line
  * @name: the name of this GPIO line, such as the output pin of the line on
  * the chip, a rail or a pin header name on a board, as specified by the
- * GPIO chip, may be empty
+ * GPIO chip, may be empty (i.e. name[0] == '\0')
  * @consumer: a functional name for the consumer of this GPIO line as set
  * by whatever is using it, will be empty if there is no current user but
  * may also be empty if the consumer doesn't set this up
- * @flags: flags for the GPIO line, such as GPIO_V2_LINE_FLAG_ACTIVE_LOW,
- * GPIO_V2_LINE_FLAG_OUTPUT etc, OR:ed together
  * @offset: the local offset on this GPIO chip, fill this in when
  * requesting the line information from the kernel
- * @num_attrs: the number of attributes in attrs
+ * @num_attrs: the number of attributes in @attrs
+ * @flags: flags for the GPIO lines, with values from &enum
+ * gpio_v2_line_flag, such as %GPIO_V2_LINE_FLAG_ACTIVE_LOW,
+ * %GPIO_V2_LINE_FLAG_OUTPUT etc, added together.
  * @attrs: the configuration attributes associated with the line
  * @padding: reserved for future use
  */
@@ -244,7 +245,7 @@ enum gpio_v2_line_changed_type {
  * of a GPIO line
  * @info: updated line information
  * @timestamp_ns: estimate of time of status change occurrence, in nanoseconds
- * @event_type: the type of change with a value from enum
+ * @event_type: the type of change with a value from &enum
  * gpio_v2_line_changed_type
  * @padding: reserved for future use
  */
@@ -269,10 +270,10 @@ enum gpio_v2_line_event_id {
 /**
  * struct gpio_v2_line_event - The actual event being pushed to userspace
  * @timestamp_ns: best estimate of time of event occurrence, in nanoseconds.
- * The timestamp_ns is read from CLOCK_MONOTONIC and is intended to allow the
- * accurate measurement of the time between events.  It does not provide
+ * The @timestamp_ns is read from %CLOCK_MONOTONIC and is intended to allow
+ * the accurate measurement of the time between events. It does not provide
  * the wall-clock time.
- * @id: event identifier with value from enum gpio_v2_line_event_id
+ * @id: event identifier with value from &enum gpio_v2_line_event_id
  * @offset: the offset of the line that triggered the event
  * @seqno: the sequence number for this event in the sequence of events for
  * all the lines in this line request
@@ -291,7 +292,7 @@ struct gpio_v2_line_event {
 };
 
 /*
- *  ABI v1
+ * ABI v1
  *
  * This version of the ABI is deprecated.
  * Use the latest version of the ABI, defined above, instead.
@@ -314,13 +315,13 @@ struct gpio_v2_line_event {
  * @flags: various flags for this line
  * @name: the name of this GPIO line, such as the output pin of the line on the
  * chip, a rail or a pin header name on a board, as specified by the gpio
- * chip, may be empty
+ * chip, may be empty (i.e. name[0] == '\0')
  * @consumer: a functional name for the consumer of this GPIO line as set by
  * whatever is using it, will be empty if there is no current user but may
  * also be empty if the consumer doesn't set this up
  *
- * This struct is part of ABI v1 and is deprecated.
- * Use struct gpio_v2_line_info instead.
+ * Note: This struct is part of ABI v1 and is deprecated.
+ * Use &struct gpio_v2_line_info instead.
  */
 struct gpioline_info {
        __u32 line_offset;
@@ -344,17 +345,18 @@ enum {
  * of a GPIO line
  * @info: updated line information
  * @timestamp: estimate of time of status change occurrence, in nanoseconds
- * @event_type: one of GPIOLINE_CHANGED_REQUESTED, GPIOLINE_CHANGED_RELEASED
- * and GPIOLINE_CHANGED_CONFIG
+ * @event_type: one of %GPIOLINE_CHANGED_REQUESTED,
+ * %GPIOLINE_CHANGED_RELEASED and %GPIOLINE_CHANGED_CONFIG
+ * @padding: reserved for future use
  *
- * Note: struct gpioline_info embedded here has 32-bit alignment on its own,
+ * The &struct gpioline_info embedded here has 32-bit alignment on its own,
  * but it works fine with 64-bit alignment too. With its 72 byte size, we can
  * guarantee there are no implicit holes between it and subsequent members.
  * The 20-byte padding at the end makes sure we don't add any implicit padding
  * at the end of the structure on 64-bit architectures.
  *
- * This struct is part of ABI v1 and is deprecated.
- * Use struct gpio_v2_line_info_changed instead.
+ * Note: This struct is part of ABI v1 and is deprecated.
+ * Use &struct gpio_v2_line_info_changed instead.
  */
 struct gpioline_info_changed {
        struct gpioline_info info;
@@ -378,13 +380,13 @@ struct gpioline_info_changed {
  * @lineoffsets: an array of desired lines, specified by offset index for the
  * associated GPIO device
  * @flags: desired flags for the desired GPIO lines, such as
- * GPIOHANDLE_REQUEST_OUTPUT, GPIOHANDLE_REQUEST_ACTIVE_LOW etc, OR:ed
+ * %GPIOHANDLE_REQUEST_OUTPUT, %GPIOHANDLE_REQUEST_ACTIVE_LOW etc, added
  * together. Note that even if multiple lines are requested, the same flags
  * must be applicable to all of them, if you want lines with individual
  * flags set, request them one by one. It is possible to select
  * a batch of input or output lines, but they must all have the same
  * characteristics, i.e. all inputs or all outputs, all active low etc
- * @default_values: if the GPIOHANDLE_REQUEST_OUTPUT is set for a requested
+ * @default_values: if the %GPIOHANDLE_REQUEST_OUTPUT is set for a requested
  * line, this specifies the default output value, should be 0 (low) or
  * 1 (high), anything else than 0 or 1 will be interpreted as 1 (high)
  * @consumer_label: a desired consumer label for the selected GPIO line(s)
@@ -392,11 +394,11 @@ struct gpioline_info_changed {
  * @lines: number of lines requested in this request, i.e. the number of
  * valid fields in the above arrays, set to 1 to request a single line
  * @fd: if successful this field will contain a valid anonymous file handle
- * after a GPIO_GET_LINEHANDLE_IOCTL operation, zero or negative value
+ * after a %GPIO_GET_LINEHANDLE_IOCTL operation, zero or negative value
  * means error
  *
- * This struct is part of ABI v1 and is deprecated.
- * Use struct gpio_v2_line_request instead.
+ * Note: This struct is part of ABI v1 and is deprecated.
+ * Use &struct gpio_v2_line_request instead.
  */
 struct gpiohandle_request {
        __u32 lineoffsets[GPIOHANDLES_MAX];
@@ -410,15 +412,15 @@ struct gpiohandle_request {
 /**
  * struct gpiohandle_config - Configuration for a GPIO handle request
  * @flags: updated flags for the requested GPIO lines, such as
- * GPIOHANDLE_REQUEST_OUTPUT, GPIOHANDLE_REQUEST_ACTIVE_LOW etc, OR:ed
+ * %GPIOHANDLE_REQUEST_OUTPUT, %GPIOHANDLE_REQUEST_ACTIVE_LOW etc, added
  * together
- * @default_values: if the GPIOHANDLE_REQUEST_OUTPUT is set in flags,
+ * @default_values: if the %GPIOHANDLE_REQUEST_OUTPUT is set in flags,
  * this specifies the default output value, should be 0 (low) or
  * 1 (high), anything else than 0 or 1 will be interpreted as 1 (high)
  * @padding: reserved for future use and should be zero filled
  *
- * This struct is part of ABI v1 and is deprecated.
- * Use struct gpio_v2_line_config instead.
+ * Note: This struct is part of ABI v1 and is deprecated.
+ * Use &struct gpio_v2_line_config instead.
  */
 struct gpiohandle_config {
        __u32 flags;
@@ -432,8 +434,8 @@ struct gpiohandle_config {
  * state of a line, when setting the state of lines these should contain
  * the desired target state
  *
- * This struct is part of ABI v1 and is deprecated.
- * Use struct gpio_v2_line_values instead.
+ * Note: This struct is part of ABI v1 and is deprecated.
+ * Use &struct gpio_v2_line_values instead.
  */
 struct gpiohandle_data {
        __u8 values[GPIOHANDLES_MAX];
@@ -449,17 +451,17 @@ struct gpiohandle_data {
  * @lineoffset: the desired line to subscribe to events from, specified by
  * offset index for the associated GPIO device
  * @handleflags: desired handle flags for the desired GPIO line, such as
- * GPIOHANDLE_REQUEST_ACTIVE_LOW or GPIOHANDLE_REQUEST_OPEN_DRAIN
+ * %GPIOHANDLE_REQUEST_ACTIVE_LOW or %GPIOHANDLE_REQUEST_OPEN_DRAIN
  * @eventflags: desired flags for the desired GPIO event line, such as
- * GPIOEVENT_REQUEST_RISING_EDGE or GPIOEVENT_REQUEST_FALLING_EDGE
+ * %GPIOEVENT_REQUEST_RISING_EDGE or %GPIOEVENT_REQUEST_FALLING_EDGE
  * @consumer_label: a desired consumer label for the selected GPIO line(s)
  * such as "my-listener"
  * @fd: if successful this field will contain a valid anonymous file handle
- * after a GPIO_GET_LINEEVENT_IOCTL operation, zero or negative value
+ * after a %GPIO_GET_LINEEVENT_IOCTL operation, zero or negative value
  * means error
  *
- * This struct is part of ABI v1 and is deprecated.
- * Use struct gpio_v2_line_request instead.
+ * Note: This struct is part of ABI v1 and is deprecated.
+ * Use &struct gpio_v2_line_request instead.
  */
 struct gpioevent_request {
        __u32 lineoffset;
@@ -469,7 +471,7 @@ struct gpioevent_request {
        int fd;
 };
 
-/**
+/*
  * GPIO event types
  */
 #define GPIOEVENT_EVENT_RISING_EDGE 0x01
@@ -480,8 +482,8 @@ struct gpioevent_request {
  * @timestamp: best estimate of time of event occurrence, in nanoseconds
  * @id: event identifier
  *
- * This struct is part of ABI v1 and is deprecated.
- * Use struct gpio_v2_line_event instead.
+ * Note: This struct is part of ABI v1 and is deprecated.
+ * Use &struct gpio_v2_line_event instead.
  */
 struct gpioevent_data {
        __u64 timestamp;
index c1661febc2dc4841304bb678e235475b79fa8ec1..0564fd7ccde4180da7911f473bf2e26f04c2051e 100644 (file)
@@ -138,6 +138,7 @@ struct icmp6hdr {
 #define ICMPV6_HDR_FIELD               0
 #define ICMPV6_UNK_NEXTHDR             1
 #define ICMPV6_UNK_OPTION              2
+#define ICMPV6_HDR_INCOMP              3
 
 /*
  *     constants for (set|get)sockopt
diff --git a/include/uapi/linux/mic_common.h b/include/uapi/linux/mic_common.h
deleted file mode 100644 (file)
index 504e523..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Intel MIC driver.
- *
- */
-#ifndef __MIC_COMMON_H_
-#define __MIC_COMMON_H_
-
-#include <linux/virtio_ring.h>
-
-#define __mic_align(a, x) (((a) + (x) - 1) & ~((x) - 1))
-
-/**
- * struct mic_device_desc: Virtio device information shared between the
- * virtio driver and userspace backend
- *
- * @type: Device type: console/network/disk etc.  Type 0/-1 terminates.
- * @num_vq: Number of virtqueues.
- * @feature_len: Number of bytes of feature bits.  Multiply by 2: one for
-   host features and one for guest acknowledgements.
- * @config_len: Number of bytes of the config array after virtqueues.
- * @status: A status byte, written by the Guest.
- * @config: Start of the following variable length config.
- */
-struct mic_device_desc {
-       __s8 type;
-       __u8 num_vq;
-       __u8 feature_len;
-       __u8 config_len;
-       __u8 status;
-       __le64 config[0];
-} __attribute__ ((aligned(8)));
-
-/**
- * struct mic_device_ctrl: Per virtio device information in the device page
- * used internally by the host and card side drivers.
- *
- * @vdev: Used for storing MIC vdev information by the guest.
- * @config_change: Set to 1 by host when a config change is requested.
- * @vdev_reset: Set to 1 by guest to indicate virtio device has been reset.
- * @guest_ack: Set to 1 by guest to ack a command.
- * @host_ack: Set to 1 by host to ack a command.
- * @used_address_updated: Set to 1 by guest when the used address should be
- * updated.
- * @c2h_vdev_db: The doorbell number to be used by guest. Set by host.
- * @h2c_vdev_db: The doorbell number to be used by host. Set by guest.
- */
-struct mic_device_ctrl {
-       __le64 vdev;
-       __u8 config_change;
-       __u8 vdev_reset;
-       __u8 guest_ack;
-       __u8 host_ack;
-       __u8 used_address_updated;
-       __s8 c2h_vdev_db;
-       __s8 h2c_vdev_db;
-} __attribute__ ((aligned(8)));
-
-/**
- * struct mic_bootparam: Virtio device independent information in device page
- *
- * @magic: A magic value used by the card to ensure it can see the host
- * @h2c_config_db: Host to Card Virtio config doorbell set by card
- * @node_id: Unique id of the node
- * @h2c_scif_db - Host to card SCIF doorbell set by card
- * @c2h_scif_db - Card to host SCIF doorbell set by host
- * @scif_host_dma_addr - SCIF host queue pair DMA address
- * @scif_card_dma_addr - SCIF card queue pair DMA address
- */
-struct mic_bootparam {
-       __le32 magic;
-       __s8 h2c_config_db;
-       __u8 node_id;
-       __u8 h2c_scif_db;
-       __u8 c2h_scif_db;
-       __u64 scif_host_dma_addr;
-       __u64 scif_card_dma_addr;
-} __attribute__ ((aligned(8)));
-
-/**
- * struct mic_device_page: High level representation of the device page
- *
- * @bootparam: The bootparam structure is used for sharing information and
- * status updates between MIC host and card drivers.
- * @desc: Array of MIC virtio device descriptors.
- */
-struct mic_device_page {
-       struct mic_bootparam bootparam;
-       struct mic_device_desc desc[0];
-};
-/**
- * struct mic_vqconfig: This is how we expect the device configuration field
- * for a virtqueue to be laid out in config space.
- *
- * @address: Guest/MIC physical address of the virtio ring
- * (avail and desc rings)
- * @used_address: Guest/MIC physical address of the used ring
- * @num: The number of entries in the virtio_ring
- */
-struct mic_vqconfig {
-       __le64 address;
-       __le64 used_address;
-       __le16 num;
-} __attribute__ ((aligned(8)));
-
-/*
- * The alignment to use between consumer and producer parts of vring.
- * This is pagesize for historical reasons.
- */
-#define MIC_VIRTIO_RING_ALIGN          4096
-
-#define MIC_MAX_VRINGS                 4
-#define MIC_VRING_ENTRIES              128
-
-/*
- * Max vring entries (power of 2) to ensure desc and avail rings
- * fit in a single page
- */
-#define MIC_MAX_VRING_ENTRIES          128
-
-/**
- * Max size of the desc block in bytes: includes:
- *     - struct mic_device_desc
- *     - struct mic_vqconfig (num_vq of these)
- *     - host and guest features
- *     - virtio device config space
- */
-#define MIC_MAX_DESC_BLK_SIZE          256
-
-/**
- * struct _mic_vring_info - Host vring info exposed to userspace backend
- * for the avail index and magic for the card.
- *
- * @avail_idx: host avail idx
- * @magic: A magic debug cookie.
- */
-struct _mic_vring_info {
-       __u16 avail_idx;
-       __le32 magic;
-};
-
-/**
- * struct mic_vring - Vring information.
- *
- * @vr: The virtio ring.
- * @info: Host vring information exposed to the userspace backend for the
- * avail index and magic for the card.
- * @va: The va for the buffer allocated for vr and info.
- * @len: The length of the buffer required for allocating vr and info.
- */
-struct mic_vring {
-       struct vring vr;
-       struct _mic_vring_info *info;
-       void *va;
-       int len;
-};
-
-#define mic_aligned_desc_size(d) __mic_align(mic_desc_size(d), 8)
-
-#ifndef INTEL_MIC_CARD
-static inline unsigned mic_desc_size(const struct mic_device_desc *desc)
-{
-       return sizeof(*desc) + desc->num_vq * sizeof(struct mic_vqconfig)
-               + desc->feature_len * 2 + desc->config_len;
-}
-
-static inline struct mic_vqconfig *
-mic_vq_config(const struct mic_device_desc *desc)
-{
-       return (struct mic_vqconfig *)(desc + 1);
-}
-
-static inline __u8 *mic_vq_features(const struct mic_device_desc *desc)
-{
-       return (__u8 *)(mic_vq_config(desc) + desc->num_vq);
-}
-
-static inline __u8 *mic_vq_configspace(const struct mic_device_desc *desc)
-{
-       return mic_vq_features(desc) + desc->feature_len * 2;
-}
-static inline unsigned mic_total_desc_size(struct mic_device_desc *desc)
-{
-       return mic_aligned_desc_size(desc) + sizeof(struct mic_device_ctrl);
-}
-#endif
-
-/* Device page size */
-#define MIC_DP_SIZE 4096
-
-#define MIC_MAGIC 0xc0ffee00
-
-/**
- * enum mic_states - MIC states.
- */
-enum mic_states {
-       MIC_READY = 0,
-       MIC_BOOTING,
-       MIC_ONLINE,
-       MIC_SHUTTING_DOWN,
-       MIC_RESETTING,
-       MIC_RESET_FAILED,
-       MIC_LAST
-};
-
-/**
- * enum mic_status - MIC status reported by card after
- * a host or card initiated shutdown or a card crash.
- */
-enum mic_status {
-       MIC_NOP = 0,
-       MIC_CRASHED,
-       MIC_HALTED,
-       MIC_POWER_OFF,
-       MIC_RESTART,
-       MIC_STATUS_LAST
-};
-
-#endif
diff --git a/include/uapi/linux/mic_ioctl.h b/include/uapi/linux/mic_ioctl.h
deleted file mode 100644 (file)
index 687b9cd..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Intel MIC Host driver.
- *
- */
-#ifndef _MIC_IOCTL_H_
-#define _MIC_IOCTL_H_
-
-#include <linux/types.h>
-
-/*
- * mic_copy - MIC virtio descriptor copy.
- *
- * @iov: An array of IOVEC structures containing user space buffers.
- * @iovcnt: Number of IOVEC structures in iov.
- * @vr_idx: The vring index.
- * @update_used: A non zero value results in used index being updated.
- * @out_len: The aggregate of the total length written to or read from
- *     the virtio device.
- */
-struct mic_copy_desc {
-#ifdef __KERNEL__
-       struct iovec __user *iov;
-#else
-       struct iovec *iov;
-#endif
-       __u32 iovcnt;
-       __u8 vr_idx;
-       __u8 update_used;
-       __u32 out_len;
-};
-
-/*
- * Add a new virtio device
- * The (struct mic_device_desc *) pointer points to a device page entry
- *     for the virtio device consisting of:
- *     - struct mic_device_desc
- *     - struct mic_vqconfig (num_vq of these)
- *     - host and guest features
- *     - virtio device config space
- * The total size referenced by the pointer should equal the size returned
- * by desc_size() in mic_common.h
- */
-#define MIC_VIRTIO_ADD_DEVICE _IOWR('s', 1, struct mic_device_desc *)
-
-/*
- * Copy the number of entries in the iovec and update the used index
- * if requested by the user.
- */
-#define MIC_VIRTIO_COPY_DESC   _IOWR('s', 2, struct mic_copy_desc *)
-
-/*
- * Notify virtio device of a config change
- * The (__u8 *) pointer points to config space values for the device
- * as they should be written into the device page. The total size
- * referenced by the pointer should equal the config_len field of struct
- * mic_device_desc.
- */
-#define MIC_VIRTIO_CONFIG_CHANGE _IOWR('s', 5, __u8 *)
-
-#endif
index 8300cc29dec8aa7357d300d197e10d3edf063978..8d16744edc313df7ebc796d5fe1a01c58f425a09 100644 (file)
@@ -1058,4 +1058,6 @@ enum ovs_dec_ttl_attr {
        __OVS_DEC_TTL_ATTR_MAX
 };
 
+#define OVS_DEC_TTL_ATTR_MAX (__OVS_DEC_TTL_ATTR_MAX - 1)
+
 #endif /* _LINUX_OPENVSWITCH_H */
index 82cc58fe936818ff213e0c1719ca8972db466155..1500a0f58041ae24924cad59dcf0fa4b4d6f68b6 100644 (file)
@@ -171,9 +171,12 @@ struct statx {
  * be of use to ordinary userspace programs such as GUIs or ls rather than
  * specialised tools.
  *
- * Note that the flags marked [I] correspond to generic FS_IOC_FLAGS
+ * Note that the flags marked [I] correspond to the FS_IOC_SETFLAGS flags
  * semantically.  Where possible, the numerical value is picked to correspond
- * also.
+ * also.  Note that the DAX attribute indicates that the file is in the CPU
+ * direct access state.  It does not correspond to the per-inode flag that
+ * some filesystems support.
+ *
  */
 #define STATX_ATTR_COMPRESSED          0x00000004 /* [I] File is compressed by the fs */
 #define STATX_ATTR_IMMUTABLE           0x00000010 /* [I] File is marked immutable */
@@ -183,7 +186,7 @@ struct statx {
 #define STATX_ATTR_AUTOMOUNT           0x00001000 /* Dir: Automount trigger */
 #define STATX_ATTR_MOUNT_ROOT          0x00002000 /* Root of a mount */
 #define STATX_ATTR_VERITY              0x00100000 /* [I] Verity protected file */
-#define STATX_ATTR_DAX                 0x00002000 /* [I] File is DAX */
+#define STATX_ATTR_DAX                 0x00200000 /* File is currently in DAX state */
 
 
 #endif /* _UAPI_LINUX_STAT_H */
index 75232185324abb8bf16521b525ed007306ab582f..c998860d7bbc4351c37c702ea69ea88a814b19cf 100644 (file)
 
 /* Set event fd for config interrupt*/
 #define VHOST_VDPA_SET_CONFIG_CALL     _IOW(VHOST_VIRTIO, 0x77, int)
+
+/* Get the valid iova range */
+#define VHOST_VDPA_GET_IOVA_RANGE      _IOR(VHOST_VIRTIO, 0x78, \
+                                            struct vhost_vdpa_iova_range)
 #endif
index 9a269a88a6ffd1d6c9aff58ba854a6c7705df389..f7f6a3a28977ae15f7391e270fa327cc60e4f101 100644 (file)
@@ -138,6 +138,15 @@ struct vhost_vdpa_config {
        __u8 buf[0];
 };
 
+/* vhost vdpa IOVA range
+ * @first: First address that can be mapped by vhost-vDPA
+ * @last: Last address that can be mapped by vhost-vDPA
+ */
+struct vhost_vdpa_iova_range {
+       __u64 first;
+       __u64 last;
+};
+
 /* Feature bits */
 /* Log all write descriptors. Can be changed while device is active. */
 #define VHOST_F_LOG_ALL 26
index 7184265c0b0d4e01471e7f47e7d8ccd6e3b68509..9555f31c8425c79ac87cb239c446509e73f39369 100644 (file)
@@ -144,7 +144,7 @@ struct snd_compr_metadata {
         __u32 value[8];
 } __attribute__((packed, aligned(4)));
 
-/**
+/*
  * compress path ioctl definitions
  * SNDRV_COMPRESS_GET_CAPS: Query capability of DSP
  * SNDRV_COMPRESS_GET_CODEC_CAPS: Query capability of a codec
index 06b0b57e996cb5efad84cf74dc391766fedaf986..d1b3889f74d8fa24094a0642ced54eba0313bb9c 100644 (file)
@@ -484,9 +484,6 @@ int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level);
 
 enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc);
 enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat);
-enum ipu_color_space ipu_mbus_code_to_colorspace(u32 mbus_code);
-int ipu_stride_to_bytes(u32 pixel_stride, u32 pixelformat);
-bool ipu_pixelformat_is_planar(u32 pixelformat);
 int ipu_degrees_to_rot_mode(enum ipu_rotate_mode *mode, int degrees,
                            bool hflip, bool vflip);
 int ipu_rot_mode_to_degrees(int *degrees, enum ipu_rotate_mode mode,
index c9446911cf41e8bb3d3a03ccc19b5f2dfe27e8ac..0872a5a2e7590c0ade132f624af8d6e39de61544 100644 (file)
@@ -47,6 +47,10 @@ config CLANG_VERSION
        int
        default $(shell,$(srctree)/scripts/clang-version.sh $(CC))
 
+config LLD_VERSION
+       int
+       default $(shell,$(srctree)/scripts/lld-version.sh $(LD))
+
 config CC_CAN_LINK
        bool
        default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(m64-flag)) if 64BIT
@@ -719,7 +723,7 @@ config LOG_CPU_MAX_BUF_SHIFT
          with more CPUs. Therefore this value is used only when the sum of
          contributions is greater than the half of the default kernel ring
          buffer as defined by LOG_BUF_SHIFT. The default values are set
-         so that more than 64 CPUs are needed to trigger the allocation.
+         so that more than 16 CPUs are needed to trigger the allocation.
 
          Also this option is ignored when "log_buf_len" kernel parameter is
          used as it forces an exact (power of two) size of the ring buffer.
@@ -1348,6 +1352,12 @@ config LD_DEAD_CODE_DATA_ELIMINATION
          present. This option is not well tested yet, so use at your
          own risk.
 
+config LD_ORPHAN_WARN
+       def_bool y
+       depends on ARCH_WANT_LD_ORPHAN_WARN
+       depends on !LD_IS_LLD || LLD_VERSION >= 110000
+       depends on $(ld-option,--orphan-handling=warn)
+
 config SYSCTL
        bool
 
index 130376ec10ba06956103521492d0e7a83250a687..32b2a8affafd1b434ec319a1bfb842e7ac7a298f 100644 (file)
@@ -269,17 +269,27 @@ static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum)
        u32 size, csum;
        char *data;
        u32 *hdr;
+       int i;
 
        if (!initrd_end)
                return NULL;
 
        data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN;
-       if (memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN))
-               return NULL;
+       /*
+        * Since Grub may align the size of initrd to 4, we must
+        * check the preceding 3 bytes as well.
+        */
+       for (i = 0; i < 4; i++) {
+               if (!memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN))
+                       goto found;
+               data--;
+       }
+       return NULL;
 
+found:
        hdr = (u32 *)(data - 8);
-       size = hdr[0];
-       csum = hdr[1];
+       size = le32_to_cpu(hdr[0]);
+       csum = le32_to_cpu(hdr[1]);
 
        data = ((void *)hdr) - size;
        if ((unsigned long)data < initrd_start) {
index bdc8cd1b6767ba6d0fb0d436c3a73eb3cc076868..c1b9f71ee6aac480d935f2301d339765e301361d 100644 (file)
@@ -1,6 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-y := core.o
-CFLAGS_core.o += $(call cc-disable-warning, override-init)
+ifneq ($(CONFIG_BPF_JIT_ALWAYS_ON),y)
+# ___bpf_prog_run() needs GCSE disabled on x86; see 3193c0836f203 for details
+cflags-nogcse-$(CONFIG_X86)$(CONFIG_CC_IS_GCC) := -fno-gcse
+endif
+CFLAGS_core.o += $(call cc-disable-warning, override-init) $(cflags-nogcse-yy)
 
 obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o bpf_iter.o map_iter.o task_iter.o prog_iter.o
 obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o
index 78ea8a7bd27feb15977009604849e4d1bc564f9a..56cc5a915f6703358c52231583c86429fb8f4220 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/bpf_verifier.h>
 #include <net/bpf_sk_storage.h>
 #include <linux/bpf_local_storage.h>
+#include <linux/btf_ids.h>
 
 /* For every LSM hook that allows attachment of BPF programs, declare a nop
  * function where a BPF program can be attached.
@@ -26,7 +27,11 @@ noinline RET bpf_lsm_##NAME(__VA_ARGS__)     \
 #include <linux/lsm_hook_defs.h>
 #undef LSM_HOOK
 
-#define BPF_LSM_SYM_PREFX  "bpf_lsm_"
+#define LSM_HOOK(RET, DEFAULT, NAME, ...) BTF_ID(func, bpf_lsm_##NAME)
+BTF_SET_START(bpf_lsm_hooks)
+#include <linux/lsm_hook_defs.h>
+#undef LSM_HOOK
+BTF_SET_END(bpf_lsm_hooks)
 
 int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog,
                        const struct bpf_prog *prog)
@@ -37,8 +42,7 @@ int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog,
                return -EINVAL;
        }
 
-       if (strncmp(BPF_LSM_SYM_PREFX, prog->aux->attach_func_name,
-                   sizeof(BPF_LSM_SYM_PREFX) - 1)) {
+       if (!btf_id_set_contains(&bpf_lsm_hooks, prog->aux->attach_btf_id)) {
                bpf_log(vlog, "attach_btf_id %u points to wrong type name %s\n",
                        prog->aux->attach_btf_id, prog->aux->attach_func_name);
                return -EINVAL;
index 9268d77898b72bde759712517249d82bfc85e7c9..55454d2278b17c84f1ceee9ba27688f6205afd62 100644 (file)
@@ -1369,7 +1369,7 @@ u64 __weak bpf_probe_read_kernel(void *dst, u32 size, const void *unsafe_ptr)
  *
  * Decode and execute eBPF instructions.
  */
-static u64 __no_fgcse ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn, u64 *stack)
+static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn, u64 *stack)
 {
 #define BPF_INSN_2_LBL(x, y)    [BPF_##x | BPF_##y] = &&x##_##y
 #define BPF_INSN_3_LBL(x, y, z) [BPF_##x | BPF_##y | BPF_##z] = &&x##_##y##_##z
index 1815e97d4c9c1bbd2c9e9668db4c48f06bfa7704..1fccba6e88c4ed5092c2e591d39d440e9bfdac51 100644 (file)
@@ -821,6 +821,32 @@ static void pcpu_copy_value(struct bpf_htab *htab, void __percpu *pptr,
        }
 }
 
+static void pcpu_init_value(struct bpf_htab *htab, void __percpu *pptr,
+                           void *value, bool onallcpus)
+{
+       /* When using prealloc and not setting the initial value on all cpus,
+        * zero-fill element values for other cpus (just as what happens when
+        * not using prealloc). Otherwise, bpf program has no way to ensure
+        * known initial values for cpus other than current one
+        * (onallcpus=false always when coming from bpf prog).
+        */
+       if (htab_is_prealloc(htab) && !onallcpus) {
+               u32 size = round_up(htab->map.value_size, 8);
+               int current_cpu = raw_smp_processor_id();
+               int cpu;
+
+               for_each_possible_cpu(cpu) {
+                       if (cpu == current_cpu)
+                               bpf_long_memcpy(per_cpu_ptr(pptr, cpu), value,
+                                               size);
+                       else
+                               memset(per_cpu_ptr(pptr, cpu), 0, size);
+               }
+       } else {
+               pcpu_copy_value(htab, pptr, value, onallcpus);
+       }
+}
+
 static bool fd_htab_map_needs_adjust(const struct bpf_htab *htab)
 {
        return htab->map.map_type == BPF_MAP_TYPE_HASH_OF_MAPS &&
@@ -891,7 +917,7 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key,
                        }
                }
 
-               pcpu_copy_value(htab, pptr, value, onallcpus);
+               pcpu_init_value(htab, pptr, value, onallcpus);
 
                if (!prealloc)
                        htab_elem_set_ptr(l_new, key_size, pptr);
@@ -1183,7 +1209,7 @@ static int __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
                pcpu_copy_value(htab, htab_elem_get_ptr(l_old, key_size),
                                value, onallcpus);
        } else {
-               pcpu_copy_value(htab, htab_elem_get_ptr(l_new, key_size),
+               pcpu_init_value(htab, htab_elem_get_ptr(l_new, key_size),
                                value, onallcpus);
                hlist_nulls_add_head_rcu(&l_new->hash_node, head);
                l_new = NULL;
index ace49111d3a3669b776944b327375cc2d939e78c..26bced2624738021c7a42888e9204228f31e028c 100644 (file)
@@ -6,6 +6,7 @@ config USERMODE_DRIVER
 menuconfig BPF_PRELOAD
        bool "Preload BPF file system with kernel specific program and map iterators"
        depends on BPF
+       depends on BPF_SYSCALL
        # The dependency on !COMPILE_TEST prevents it from being enabled
        # in allmodconfig or allyesconfig configurations
        depends on !COMPILE_TEST
index 6200519582a64b671c15884f0c08932c18890c0a..1388bf73307191c6cfea96c0b7c68db020c9cca9 100644 (file)
@@ -7786,9 +7786,11 @@ static int check_return_code(struct bpf_verifier_env *env)
        struct tnum range = tnum_range(0, 1);
        enum bpf_prog_type prog_type = resolve_prog_type(env->prog);
        int err;
+       const bool is_subprog = env->cur_state->frame[0]->subprogno;
 
        /* LSM and struct_ops func-ptr's return type could be "void" */
-       if ((prog_type == BPF_PROG_TYPE_STRUCT_OPS ||
+       if (!is_subprog &&
+           (prog_type == BPF_PROG_TYPE_STRUCT_OPS ||
             prog_type == BPF_PROG_TYPE_LSM) &&
            !prog->aux->attach_func_proto->type)
                return 0;
@@ -7808,6 +7810,16 @@ static int check_return_code(struct bpf_verifier_env *env)
                return -EACCES;
        }
 
+       reg = cur_regs(env) + BPF_REG_0;
+       if (is_subprog) {
+               if (reg->type != SCALAR_VALUE) {
+                       verbose(env, "At subprogram exit the register R0 is not a scalar value (%s)\n",
+                               reg_type_str[reg->type]);
+                       return -EINVAL;
+               }
+               return 0;
+       }
+
        switch (prog_type) {
        case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
                if (env->prog->expected_attach_type == BPF_CGROUP_UDP4_RECVMSG ||
@@ -7861,7 +7873,6 @@ static int check_return_code(struct bpf_verifier_env *env)
                return 0;
        }
 
-       reg = cur_regs(env) + BPF_REG_0;
        if (reg->type != SCALAR_VALUE) {
                verbose(env, "At program exit the register R0 is not a known value (%s)\n",
                        reg_type_str[reg->type]);
@@ -9572,12 +9583,13 @@ static int check_pseudo_btf_id(struct bpf_verifier_env *env,
                               struct bpf_insn *insn,
                               struct bpf_insn_aux_data *aux)
 {
-       u32 datasec_id, type, id = insn->imm;
        const struct btf_var_secinfo *vsi;
        const struct btf_type *datasec;
        const struct btf_type *t;
        const char *sym_name;
        bool percpu = false;
+       u32 type, id = insn->imm;
+       s32 datasec_id;
        u64 addr;
        int i;
 
index 6ff2578ecf17d4691722762553c88f7d68a9bdd1..2b8d7a5db3837078388c42ecd09900748c3ad913 100644 (file)
@@ -815,6 +815,10 @@ void __init cpuhp_threads_init(void)
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
+#ifndef arch_clear_mm_cpumask_cpu
+#define arch_clear_mm_cpumask_cpu(cpu, mm) cpumask_clear_cpu(cpu, mm_cpumask(mm))
+#endif
+
 /**
  * clear_tasks_mm_cpumask - Safely clear tasks' mm_cpumask for a CPU
  * @cpu: a CPU id
@@ -850,7 +854,7 @@ void clear_tasks_mm_cpumask(int cpu)
                t = find_lock_task_mm(p);
                if (!t)
                        continue;
-               cpumask_clear_cpu(cpu, mm_cpumask(t->mm));
+               arch_clear_mm_cpumask_cpu(cpu, t->mm);
                task_unlock(t);
        }
        rcu_read_unlock();
index b4eea0abc3f00208600fe80d6f293922a56b6ffe..781b9dca197cd39da22ad9d34ec0828e6ae51ecb 100644 (file)
@@ -229,6 +229,7 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
                io_tlb_orig_addr[i] = INVALID_PHYS_ADDR;
        }
        io_tlb_index = 0;
+       no_iotlb_memory = false;
 
        if (verbose)
                swiotlb_print_info();
@@ -260,9 +261,11 @@ swiotlb_init(int verbose)
        if (vstart && !swiotlb_init_with_tbl(vstart, io_tlb_nslabs, verbose))
                return;
 
-       if (io_tlb_start)
+       if (io_tlb_start) {
                memblock_free_early(io_tlb_start,
                                    PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT));
+               io_tlb_start = 0;
+       }
        pr_warn("Cannot allocate buffer");
        no_iotlb_memory = true;
 }
@@ -360,6 +363,7 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
                io_tlb_orig_addr[i] = INVALID_PHYS_ADDR;
        }
        io_tlb_index = 0;
+       no_iotlb_memory = false;
 
        swiotlb_print_info();
 
@@ -441,14 +445,11 @@ static void swiotlb_bounce(phys_addr_t orig_addr, phys_addr_t tlb_addr,
        }
 }
 
-phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
-                                  dma_addr_t tbl_dma_addr,
-                                  phys_addr_t orig_addr,
-                                  size_t mapping_size,
-                                  size_t alloc_size,
-                                  enum dma_data_direction dir,
-                                  unsigned long attrs)
+phys_addr_t swiotlb_tbl_map_single(struct device *hwdev, phys_addr_t orig_addr,
+               size_t mapping_size, size_t alloc_size,
+               enum dma_data_direction dir, unsigned long attrs)
 {
+       dma_addr_t tbl_dma_addr = phys_to_dma_unencrypted(hwdev, io_tlb_start);
        unsigned long flags;
        phys_addr_t tlb_addr;
        unsigned int nslots, stride, index, wrap;
@@ -667,9 +668,8 @@ dma_addr_t swiotlb_map(struct device *dev, phys_addr_t paddr, size_t size,
        trace_swiotlb_bounced(dev, phys_to_dma(dev, paddr), size,
                              swiotlb_force);
 
-       swiotlb_addr = swiotlb_tbl_map_single(dev,
-                       phys_to_dma_unencrypted(dev, io_tlb_start),
-                       paddr, size, size, dir, attrs);
+       swiotlb_addr = swiotlb_tbl_map_single(dev, paddr, size, size, dir,
+                       attrs);
        if (swiotlb_addr == (phys_addr_t)DMA_MAPPING_ERROR)
                return DMA_MAPPING_ERROR;
 
index 2b8366693d5c119aa9f74e2a82cd1a1894a0c52f..e9e2df3f3f9eed2df7530d435f1569ed282fb178 100644 (file)
@@ -337,10 +337,10 @@ noinstr irqentry_state_t irqentry_enter(struct pt_regs *regs)
         * already contains a warning when RCU is not watching, so no point
         * in having another one here.
         */
+       lockdep_hardirqs_off(CALLER_ADDR0);
        instrumentation_begin();
        rcu_irq_enter_check_tick();
-       /* Use the combo lockdep/tracing function */
-       trace_hardirqs_off();
+       trace_hardirqs_off_finish();
        instrumentation_end();
 
        return ret;
index da467e1dd49a2dd3b571245b5c8eeb5adbe73ac6..dc568ca295bdc13122a5234779dd9a2010bc0b55 100644 (file)
@@ -2312,9 +2312,6 @@ group_sched_out(struct perf_event *group_event,
                event_sched_out(event, cpuctx, ctx);
 
        perf_pmu_enable(ctx->pmu);
-
-       if (group_event->attr.exclusive)
-               cpuctx->exclusive = 0;
 }
 
 #define DETACH_GROUP   0x01UL
@@ -2583,11 +2580,8 @@ group_sched_in(struct perf_event *group_event,
 
        pmu->start_txn(pmu, PERF_PMU_TXN_ADD);
 
-       if (event_sched_in(group_event, cpuctx, ctx)) {
-               pmu->cancel_txn(pmu);
-               perf_mux_hrtimer_restart(cpuctx);
-               return -EAGAIN;
-       }
+       if (event_sched_in(group_event, cpuctx, ctx))
+               goto error;
 
        /*
         * Schedule in siblings as one group (if any):
@@ -2616,10 +2610,8 @@ group_error:
        }
        event_sched_out(group_event, cpuctx, ctx);
 
+error:
        pmu->cancel_txn(pmu);
-
-       perf_mux_hrtimer_restart(cpuctx);
-
        return -EAGAIN;
 }
 
@@ -2645,7 +2637,7 @@ static int group_can_go_on(struct perf_event *event,
         * If this group is exclusive and there are already
         * events on the CPU, it can't go on.
         */
-       if (event->attr.exclusive && cpuctx->active_oncpu)
+       if (event->attr.exclusive && !list_empty(get_event_list(event)))
                return 0;
        /*
         * Otherwise, try to add it if all previous groups were able
@@ -3679,6 +3671,7 @@ static int merge_sched_in(struct perf_event *event, void *data)
 
                *can_add_hw = 0;
                ctx->rotate_necessary = 1;
+               perf_mux_hrtimer_restart(cpuctx);
        }
 
        return 0;
@@ -6374,14 +6367,13 @@ perf_output_sample_regs(struct perf_output_handle *handle,
 }
 
 static void perf_sample_regs_user(struct perf_regs *regs_user,
-                                 struct pt_regs *regs,
-                                 struct pt_regs *regs_user_copy)
+                                 struct pt_regs *regs)
 {
        if (user_mode(regs)) {
                regs_user->abi = perf_reg_abi(current);
                regs_user->regs = regs;
        } else if (!(current->flags & PF_KTHREAD)) {
-               perf_get_regs_user(regs_user, regs, regs_user_copy);
+               perf_get_regs_user(regs_user, regs);
        } else {
                regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE;
                regs_user->regs = NULL;
@@ -7083,8 +7075,7 @@ void perf_prepare_sample(struct perf_event_header *header,
        }
 
        if (sample_type & (PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER))
-               perf_sample_regs_user(&data->regs_user, regs,
-                                     &data->regs_user_copy);
+               perf_sample_regs_user(&data->regs_user, regs);
 
        if (sample_type & PERF_SAMPLE_REGS_USER) {
                /* regs dump ABI info */
@@ -7186,6 +7177,7 @@ __perf_event_output(struct perf_event *event,
                    struct perf_sample_data *data,
                    struct pt_regs *regs,
                    int (*output_begin)(struct perf_output_handle *,
+                                       struct perf_sample_data *,
                                        struct perf_event *,
                                        unsigned int))
 {
@@ -7198,7 +7190,7 @@ __perf_event_output(struct perf_event *event,
 
        perf_prepare_sample(&header, data, event, regs);
 
-       err = output_begin(&handle, event, header.size);
+       err = output_begin(&handle, data, event, header.size);
        if (err)
                goto exit;
 
@@ -7264,7 +7256,7 @@ perf_event_read_event(struct perf_event *event,
        int ret;
 
        perf_event_header__init_id(&read_event.header, &sample, event);
-       ret = perf_output_begin(&handle, event, read_event.header.size);
+       ret = perf_output_begin(&handle, &sample, event, read_event.header.size);
        if (ret)
                return;
 
@@ -7533,7 +7525,7 @@ static void perf_event_task_output(struct perf_event *event,
 
        perf_event_header__init_id(&task_event->event_id.header, &sample, event);
 
-       ret = perf_output_begin(&handle, event,
+       ret = perf_output_begin(&handle, &sample, event,
                                task_event->event_id.header.size);
        if (ret)
                goto out;
@@ -7636,7 +7628,7 @@ static void perf_event_comm_output(struct perf_event *event,
                return;
 
        perf_event_header__init_id(&comm_event->event_id.header, &sample, event);
-       ret = perf_output_begin(&handle, event,
+       ret = perf_output_begin(&handle, &sample, event,
                                comm_event->event_id.header.size);
 
        if (ret)
@@ -7736,7 +7728,7 @@ static void perf_event_namespaces_output(struct perf_event *event,
 
        perf_event_header__init_id(&namespaces_event->event_id.header,
                                   &sample, event);
-       ret = perf_output_begin(&handle, event,
+       ret = perf_output_begin(&handle, &sample, event,
                                namespaces_event->event_id.header.size);
        if (ret)
                goto out;
@@ -7863,7 +7855,7 @@ static void perf_event_cgroup_output(struct perf_event *event, void *data)
 
        perf_event_header__init_id(&cgroup_event->event_id.header,
                                   &sample, event);
-       ret = perf_output_begin(&handle, event,
+       ret = perf_output_begin(&handle, &sample, event,
                                cgroup_event->event_id.header.size);
        if (ret)
                goto out;
@@ -7989,7 +7981,7 @@ static void perf_event_mmap_output(struct perf_event *event,
        }
 
        perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
-       ret = perf_output_begin(&handle, event,
+       ret = perf_output_begin(&handle, &sample, event,
                                mmap_event->event_id.header.size);
        if (ret)
                goto out;
@@ -8299,7 +8291,7 @@ void perf_event_aux_event(struct perf_event *event, unsigned long head,
        int ret;
 
        perf_event_header__init_id(&rec.header, &sample, event);
-       ret = perf_output_begin(&handle, event, rec.header.size);
+       ret = perf_output_begin(&handle, &sample, event, rec.header.size);
 
        if (ret)
                return;
@@ -8333,7 +8325,7 @@ void perf_log_lost_samples(struct perf_event *event, u64 lost)
 
        perf_event_header__init_id(&lost_samples_event.header, &sample, event);
 
-       ret = perf_output_begin(&handle, event,
+       ret = perf_output_begin(&handle, &sample, event,
                                lost_samples_event.header.size);
        if (ret)
                return;
@@ -8388,7 +8380,7 @@ static void perf_event_switch_output(struct perf_event *event, void *data)
 
        perf_event_header__init_id(&se->event_id.header, &sample, event);
 
-       ret = perf_output_begin(&handle, event, se->event_id.header.size);
+       ret = perf_output_begin(&handle, &sample, event, se->event_id.header.size);
        if (ret)
                return;
 
@@ -8463,7 +8455,7 @@ static void perf_log_throttle(struct perf_event *event, int enable)
 
        perf_event_header__init_id(&throttle_event.header, &sample, event);
 
-       ret = perf_output_begin(&handle, event,
+       ret = perf_output_begin(&handle, &sample, event,
                                throttle_event.header.size);
        if (ret)
                return;
@@ -8506,7 +8498,7 @@ static void perf_event_ksymbol_output(struct perf_event *event, void *data)
 
        perf_event_header__init_id(&ksymbol_event->event_id.header,
                                   &sample, event);
-       ret = perf_output_begin(&handle, event,
+       ret = perf_output_begin(&handle, &sample, event,
                                ksymbol_event->event_id.header.size);
        if (ret)
                return;
@@ -8596,7 +8588,7 @@ static void perf_event_bpf_output(struct perf_event *event, void *data)
 
        perf_event_header__init_id(&bpf_event->event_id.header,
                                   &sample, event);
-       ret = perf_output_begin(&handle, event,
+       ret = perf_output_begin(&handle, data, event,
                                bpf_event->event_id.header.size);
        if (ret)
                return;
@@ -8705,7 +8697,8 @@ static void perf_event_text_poke_output(struct perf_event *event, void *data)
 
        perf_event_header__init_id(&text_poke_event->event_id.header, &sample, event);
 
-       ret = perf_output_begin(&handle, event, text_poke_event->event_id.header.size);
+       ret = perf_output_begin(&handle, &sample, event,
+                               text_poke_event->event_id.header.size);
        if (ret)
                return;
 
@@ -8786,7 +8779,7 @@ static void perf_log_itrace_start(struct perf_event *event)
        rec.tid = perf_event_tid(event, current);
 
        perf_event_header__init_id(&rec.header, &sample, event);
-       ret = perf_output_begin(&handle, event, rec.header.size);
+       ret = perf_output_begin(&handle, &sample, event, rec.header.size);
 
        if (ret)
                return;
@@ -10085,6 +10078,7 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
                        if (token == IF_SRC_FILE || token == IF_SRC_FILEADDR) {
                                int fpos = token == IF_SRC_FILE ? 2 : 1;
 
+                               kfree(filename);
                                filename = match_strdup(&args[fpos]);
                                if (!filename) {
                                        ret = -ENOMEM;
@@ -10131,16 +10125,13 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
                                 */
                                ret = -EOPNOTSUPP;
                                if (!event->ctx->task)
-                                       goto fail_free_name;
+                                       goto fail;
 
                                /* look up the path and grab its inode */
                                ret = kern_path(filename, LOOKUP_FOLLOW,
                                                &filter->path);
                                if (ret)
-                                       goto fail_free_name;
-
-                               kfree(filename);
-                               filename = NULL;
+                                       goto fail;
 
                                ret = -EINVAL;
                                if (!filter->path.dentry ||
@@ -10160,13 +10151,13 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
        if (state != IF_STATE_ACTION)
                goto fail;
 
+       kfree(filename);
        kfree(orig);
 
        return 0;
 
-fail_free_name:
-       kfree(filename);
 fail:
+       kfree(filename);
        free_filters_list(filters);
        kfree(orig);
 
index fcbf5616a441185c1669e18ba63a4fa7477ab525..228801e2078869e5d0fbe4618deca7b1dc88d9a8 100644 (file)
@@ -205,16 +205,12 @@ DEFINE_OUTPUT_COPY(__output_copy_user, arch_perf_out_copy_user)
 
 static inline int get_recursion_context(int *recursion)
 {
-       int rctx;
-
-       if (unlikely(in_nmi()))
-               rctx = 3;
-       else if (in_irq())
-               rctx = 2;
-       else if (in_softirq())
-               rctx = 1;
-       else
-               rctx = 0;
+       unsigned int pc = preempt_count();
+       unsigned char rctx = 0;
+
+       rctx += !!(pc & (NMI_MASK));
+       rctx += !!(pc & (NMI_MASK | HARDIRQ_MASK));
+       rctx += !!(pc & (NMI_MASK | HARDIRQ_MASK | SOFTIRQ_OFFSET));
 
        if (recursion[rctx])
                return -1;
index 192b8abc63309da46e60424bc16ae899a9d6cf58..ef91ae75ca56f1c991047306edf57c499200b2d5 100644 (file)
@@ -147,6 +147,7 @@ ring_buffer_has_space(unsigned long head, unsigned long tail,
 
 static __always_inline int
 __perf_output_begin(struct perf_output_handle *handle,
+                   struct perf_sample_data *data,
                    struct perf_event *event, unsigned int size,
                    bool backward)
 {
@@ -237,18 +238,16 @@ __perf_output_begin(struct perf_output_handle *handle,
        handle->size = (1UL << page_shift) - offset;
 
        if (unlikely(have_lost)) {
-               struct perf_sample_data sample_data;
-
                lost_event.header.size = sizeof(lost_event);
                lost_event.header.type = PERF_RECORD_LOST;
                lost_event.header.misc = 0;
                lost_event.id          = event->id;
                lost_event.lost        = local_xchg(&rb->lost, 0);
 
-               perf_event_header__init_id(&lost_event.header,
-                                          &sample_data, event);
+               /* XXX mostly redundant; @data is already fully initializes */
+               perf_event_header__init_id(&lost_event.header, data, event);
                perf_output_put(handle, lost_event);
-               perf_event__output_id_sample(event, handle, &sample_data);
+               perf_event__output_id_sample(event, handle, data);
        }
 
        return 0;
@@ -263,22 +262,25 @@ out:
 }
 
 int perf_output_begin_forward(struct perf_output_handle *handle,
-                            struct perf_event *event, unsigned int size)
+                             struct perf_sample_data *data,
+                             struct perf_event *event, unsigned int size)
 {
-       return __perf_output_begin(handle, event, size, false);
+       return __perf_output_begin(handle, data, event, size, false);
 }
 
 int perf_output_begin_backward(struct perf_output_handle *handle,
+                              struct perf_sample_data *data,
                               struct perf_event *event, unsigned int size)
 {
-       return __perf_output_begin(handle, event, size, true);
+       return __perf_output_begin(handle, data, event, size, true);
 }
 
 int perf_output_begin(struct perf_output_handle *handle,
+                     struct perf_sample_data *data,
                      struct perf_event *event, unsigned int size)
 {
 
-       return __perf_output_begin(handle, event, size,
+       return __perf_output_begin(handle, data, event, size,
                                   unlikely(is_write_backward(event)));
 }
 
index 87a2d515de0d5be6ff29329e79077fb21e15f5b0..1f236ed375f83c2bf6b3c88c65d94d6ac9b2c0b3 100644 (file)
@@ -454,7 +454,10 @@ static void exit_mm(void)
                mmap_read_unlock(mm);
 
                self.task = current;
-               self.next = xchg(&core_state->dumper.next, &self);
+               if (self.task->flags & PF_SIGNALED)
+                       self.next = xchg(&core_state->dumper.next, &self);
+               else
+                       self.task = NULL;
                /*
                 * Implies mb(), the result of xchg() must be visible
                 * to core_state->dumper.
index 63b349168da7255a13cbaadca263922a9826b581..b0b1ad93fa957c246033f93f69cddfa15b5c0775 100644 (file)
@@ -253,7 +253,7 @@ static ssize_t fei_write(struct file *file, const char __user *buffer,
 
        if (copy_from_user(buf, buffer, count)) {
                ret = -EFAULT;
-               goto out;
+               goto out_free;
        }
        buf[count] = '\0';
        sym = strstrip(buf);
@@ -307,8 +307,9 @@ static ssize_t fei_write(struct file *file, const char __user *buffer,
                ret = count;
        }
 out:
-       kfree(buf);
        mutex_unlock(&fei_lock);
+out_free:
+       kfree(buf);
        return ret;
 }
 
index 32083db7a2a23e93bf2ed9786c92769a0e9c7136..6d266388d3804ce75e2983cce13f91fb20d53c5b 100644 (file)
@@ -2167,14 +2167,9 @@ static __latent_entropy struct task_struct *copy_process(
        /* ok, now we should be set up.. */
        p->pid = pid_nr(pid);
        if (clone_flags & CLONE_THREAD) {
-               p->exit_signal = -1;
                p->group_leader = current->group_leader;
                p->tgid = current->tgid;
        } else {
-               if (clone_flags & CLONE_PARENT)
-                       p->exit_signal = current->group_leader->exit_signal;
-               else
-                       p->exit_signal = args->exit_signal;
                p->group_leader = p;
                p->tgid = p->pid;
        }
@@ -2218,9 +2213,14 @@ static __latent_entropy struct task_struct *copy_process(
        if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) {
                p->real_parent = current->real_parent;
                p->parent_exec_id = current->parent_exec_id;
+               if (clone_flags & CLONE_THREAD)
+                       p->exit_signal = -1;
+               else
+                       p->exit_signal = current->group_leader->exit_signal;
        } else {
                p->real_parent = current;
                p->parent_exec_id = current->self_exec_id;
+               p->exit_signal = args->exit_signal;
        }
 
        klp_copy_process(p);
index be68ac0d49adf6cf2eeff7c9c3514dc03ffcb5a9..00259c7e288eea4fba549e535be2e96b623bbfc6 100644 (file)
@@ -788,8 +788,9 @@ static void put_pi_state(struct futex_pi_state *pi_state)
         */
        if (pi_state->owner) {
                struct task_struct *owner;
+               unsigned long flags;
 
-               raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
+               raw_spin_lock_irqsave(&pi_state->pi_mutex.wait_lock, flags);
                owner = pi_state->owner;
                if (owner) {
                        raw_spin_lock(&owner->pi_lock);
@@ -797,7 +798,7 @@ static void put_pi_state(struct futex_pi_state *pi_state)
                        raw_spin_unlock(&owner->pi_lock);
                }
                rt_mutex_proxy_unlock(&pi_state->pi_mutex, owner);
-               raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
+               raw_spin_unlock_irqrestore(&pi_state->pi_mutex.wait_lock, flags);
        }
 
        if (current->pi_state_cache) {
@@ -1503,8 +1504,10 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_
         */
        newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
 
-       if (unlikely(should_fail_futex(true)))
+       if (unlikely(should_fail_futex(true))) {
                ret = -EFAULT;
+               goto out_unlock;
+       }
 
        ret = cmpxchg_futex_value_locked(&curval, uaddr, uval, newval);
        if (!ret && (curval != uval)) {
@@ -2378,10 +2381,22 @@ retry:
                }
 
                /*
-                * Since we just failed the trylock; there must be an owner.
+                * The trylock just failed, so either there is an owner or
+                * there is a higher priority waiter than this one.
                 */
                newowner = rt_mutex_owner(&pi_state->pi_mutex);
-               BUG_ON(!newowner);
+               /*
+                * If the higher priority waiter has not yet taken over the
+                * rtmutex then newowner is NULL. We can't return here with
+                * that state because it's inconsistent vs. the user space
+                * state. So drop the locks and try again. It's a valid
+                * situation and not any different from the other retry
+                * conditions.
+                */
+               if (unlikely(!newowner)) {
+                       err = -EAGAIN;
+                       goto handle_err;
+               }
        } else {
                WARN_ON_ONCE(argowner != current);
                if (oldowner == current) {
index ce76f490126cccb310750c6b32f2a7b67bd5eb60..396ebaebea3fea3578fe295c73cf041530a91d93 100644 (file)
@@ -225,8 +225,7 @@ static long hung_timeout_jiffies(unsigned long last_checked,
  * Process updating of timeout sysctl
  */
 int proc_dohung_task_timeout_secs(struct ctl_table *table, int write,
-                                 void __user *buffer,
-                                 size_t *lenp, loff_t *ppos)
+                                 void *buffer, size_t *lenp, loff_t *ppos)
 {
        int ret;
 
index 10a5aff4eecc880d50677e4ce30adbb9eb01395e..164a031cfdb66e8fd4240ace61f1bbd5d1d7e884 100644 (file)
@@ -82,6 +82,7 @@ config IRQ_FASTEOI_HIERARCHY_HANDLERS
 # Generic IRQ IPI support
 config GENERIC_IRQ_IPI
        bool
+       select IRQ_DOMAIN_HIERARCHY
 
 # Generic MSI interrupt support
 config GENERIC_MSI_IRQ
index cf8b374b892da0ce854e72c8750dfda981315dc8..e4ca69608f3b86a0d130a5f5c00370f3455d3316 100644 (file)
@@ -624,17 +624,19 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
 EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
 
 /**
- * irq_create_mapping() - Map a hardware interrupt into linux irq space
+ * irq_create_mapping_affinity() - Map a hardware interrupt into linux irq space
  * @domain: domain owning this hardware interrupt or NULL for default domain
  * @hwirq: hardware irq number in that domain space
+ * @affinity: irq affinity
  *
  * Only one mapping per hardware interrupt is permitted. Returns a linux
  * irq number.
  * If the sense/trigger is to be specified, set_irq_type() should be called
  * on the number returned from that call.
  */
-unsigned int irq_create_mapping(struct irq_domain *domain,
-                               irq_hw_number_t hwirq)
+unsigned int irq_create_mapping_affinity(struct irq_domain *domain,
+                                      irq_hw_number_t hwirq,
+                                      const struct irq_affinity_desc *affinity)
 {
        struct device_node *of_node;
        int virq;
@@ -660,7 +662,8 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
        }
 
        /* Allocate a virtual interrupt number */
-       virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node), NULL);
+       virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node),
+                                     affinity);
        if (virq <= 0) {
                pr_debug("-> virq allocation failed\n");
                return 0;
@@ -676,7 +679,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
 
        return virq;
 }
-EXPORT_SYMBOL_GPL(irq_create_mapping);
+EXPORT_SYMBOL_GPL(irq_create_mapping_affinity);
 
 /**
  * irq_create_strict_mappings() - Map a range of hw irqs to fixed linux irqs
index 8a12a25fa40d5e1c12303a6d395949d0ad4c135d..41fdbb7953c60f878049b2a5807abb4aecf95320 100644 (file)
@@ -1249,7 +1249,13 @@ __acquires(hlist_lock)
 
        *head = &kretprobe_inst_table[hash];
        hlist_lock = kretprobe_table_lock_ptr(hash);
-       raw_spin_lock_irqsave(hlist_lock, *flags);
+       /*
+        * Nested is a workaround that will soon not be needed.
+        * There's other protections that make sure the same lock
+        * is not taken on the same CPU that lockdep is unaware of.
+        * Differentiate when it is taken in NMI context.
+        */
+       raw_spin_lock_irqsave_nested(hlist_lock, *flags, !!in_nmi());
 }
 NOKPROBE_SYMBOL(kretprobe_hash_lock);
 
@@ -1258,7 +1264,13 @@ static void kretprobe_table_lock(unsigned long hash,
 __acquires(hlist_lock)
 {
        raw_spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash);
-       raw_spin_lock_irqsave(hlist_lock, *flags);
+       /*
+        * Nested is a workaround that will soon not be needed.
+        * There's other protections that make sure the same lock
+        * is not taken on the same CPU that lockdep is unaware of.
+        * Differentiate when it is taken in NMI context.
+        */
+       raw_spin_lock_irqsave_nested(hlist_lock, *flags, !!in_nmi());
 }
 NOKPROBE_SYMBOL(kretprobe_table_lock);
 
@@ -2028,7 +2040,12 @@ static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
 
        /* TODO: consider to only swap the RA after the last pre_handler fired */
        hash = hash_ptr(current, KPROBE_HASH_BITS);
-       raw_spin_lock_irqsave(&rp->lock, flags);
+       /*
+        * Nested is a workaround that will soon not be needed.
+        * There's other protections that make sure the same lock
+        * is not taken on the same CPU that lockdep is unaware of.
+        */
+       raw_spin_lock_irqsave_nested(&rp->lock, flags, 1);
        if (!hlist_empty(&rp->free_instances)) {
                ri = hlist_entry(rp->free_instances.first,
                                struct kretprobe_instance, hlist);
@@ -2039,7 +2056,7 @@ static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
                ri->task = current;
 
                if (rp->entry_handler && rp->entry_handler(ri, regs)) {
-                       raw_spin_lock_irqsave(&rp->lock, flags);
+                       raw_spin_lock_irqsave_nested(&rp->lock, flags, 1);
                        hlist_add_head(&ri->hlist, &rp->free_instances);
                        raw_spin_unlock_irqrestore(&rp->lock, flags);
                        return 0;
index e29773c82b70c26fff598f864642f7dee010efab..933a625621b8dbef0564919bf6f76aa30735372f 100644 (file)
@@ -897,7 +897,8 @@ void kthread_delayed_work_timer_fn(struct timer_list *t)
        /* Move the work from worker->delayed_work_list. */
        WARN_ON_ONCE(list_empty(&work->node));
        list_del_init(&work->node);
-       kthread_insert_work(worker, work, &worker->work_list);
+       if (!work->canceling)
+               kthread_insert_work(worker, work, &worker->work_list);
 
        raw_spin_unlock_irqrestore(&worker->lock, flags);
 }
index 3e99dfef84084695a5ff440112eb41c38159fb60..c1418b47f625a25fc32d8b18852057dc48b6cc93 100644 (file)
@@ -84,7 +84,7 @@ static inline bool lockdep_enabled(void)
        if (!debug_locks)
                return false;
 
-       if (raw_cpu_read(lockdep_recursion))
+       if (this_cpu_read(lockdep_recursion))
                return false;
 
        if (current->lockdep_recursion)
@@ -108,19 +108,21 @@ static inline void lockdep_lock(void)
 {
        DEBUG_LOCKS_WARN_ON(!irqs_disabled());
 
+       __this_cpu_inc(lockdep_recursion);
        arch_spin_lock(&__lock);
        __owner = current;
-       __this_cpu_inc(lockdep_recursion);
 }
 
 static inline void lockdep_unlock(void)
 {
+       DEBUG_LOCKS_WARN_ON(!irqs_disabled());
+
        if (debug_locks && DEBUG_LOCKS_WARN_ON(__owner != current))
                return;
 
-       __this_cpu_dec(lockdep_recursion);
        __owner = NULL;
        arch_spin_unlock(&__lock);
+       __this_cpu_dec(lockdep_recursion);
 }
 
 static inline bool lockdep_assert_locked(void)
@@ -2765,7 +2767,9 @@ print_deadlock_bug(struct task_struct *curr, struct held_lock *prev,
  * (Note that this has to be done separately, because the graph cannot
  * detect such classes of deadlocks.)
  *
- * Returns: 0 on deadlock detected, 1 on OK, 2 on recursive read
+ * Returns: 0 on deadlock detected, 1 on OK, 2 if another lock with the same
+ * lock class is held but nest_lock is also held, i.e. we rely on the
+ * nest_lock to avoid the deadlock.
  */
 static int
 check_deadlock(struct task_struct *curr, struct held_lock *next)
@@ -2788,7 +2792,7 @@ check_deadlock(struct task_struct *curr, struct held_lock *next)
                 * lock class (i.e. read_lock(lock)+read_lock(lock)):
                 */
                if ((next->read == 2) && prev->read)
-                       return 2;
+                       continue;
 
                /*
                 * We're holding the nest_lock, which serializes this lock's
@@ -3592,16 +3596,13 @@ static int validate_chain(struct task_struct *curr,
 
                if (!ret)
                        return 0;
-               /*
-                * Mark recursive read, as we jump over it when
-                * building dependencies (just like we jump over
-                * trylock entries):
-                */
-               if (ret == 2)
-                       hlock->read = 2;
                /*
                 * Add dependency only if this lock is not the head
-                * of the chain, and if it's not a secondary read-lock:
+                * of the chain, and if the new lock introduces no more
+                * lock dependency (because we already hold a lock with the
+                * same lock class) nor deadlock (because the nest_lock
+                * serializes nesting locks), see the comments for
+                * check_deadlock().
                 */
                if (!chain_head && ret != 2) {
                        if (!check_prevs_add(curr, hlock))
@@ -4057,7 +4058,7 @@ void lockdep_hardirqs_on_prepare(unsigned long ip)
        if (unlikely(in_nmi()))
                return;
 
-       if (unlikely(__this_cpu_read(lockdep_recursion)))
+       if (unlikely(this_cpu_read(lockdep_recursion)))
                return;
 
        if (unlikely(lockdep_hardirqs_enabled())) {
@@ -4126,7 +4127,7 @@ void noinstr lockdep_hardirqs_on(unsigned long ip)
                goto skip_checks;
        }
 
-       if (unlikely(__this_cpu_read(lockdep_recursion)))
+       if (unlikely(this_cpu_read(lockdep_recursion)))
                return;
 
        if (lockdep_hardirqs_enabled()) {
@@ -4396,6 +4397,9 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
        if (unlikely(hlock_class(this)->usage_mask & new_mask))
                goto unlock;
 
+       if (!hlock_class(this)->usage_mask)
+               debug_atomic_dec(nr_unused_locks);
+
        hlock_class(this)->usage_mask |= new_mask;
 
        if (new_bit < LOCK_TRACE_STATES) {
@@ -4403,19 +4407,10 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
                        return 0;
        }
 
-       switch (new_bit) {
-       case 0 ... LOCK_USED-1:
+       if (new_bit < LOCK_USED) {
                ret = mark_lock_irq(curr, this, new_bit);
                if (!ret)
                        return 0;
-               break;
-
-       case LOCK_USED:
-               debug_atomic_dec(nr_unused_locks);
-               break;
-
-       default:
-               break;
        }
 
 unlock:
index 396142ee43fdaf0011c3d4ef8d763759c83adf2d..332736a72a58e50666cc0bf14cb6ee542491ff2f 100644 (file)
@@ -605,7 +605,8 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
                panic("panic_on_warn set ...\n");
        }
 
-       dump_stack();
+       if (!regs)
+               dump_stack();
 
        print_irqtrace_events(current);
 
index 3835fb82c64bda060af746930350e3d40529a86a..164d79330849a0a3c213b2802ac41b02eb96f5a6 100644 (file)
@@ -530,7 +530,7 @@ struct module_param_attrs
 {
        unsigned int num;
        struct attribute_group grp;
-       struct param_attribute attrs[0];
+       struct param_attribute attrs[];
 };
 
 #ifdef CONFIG_SYSFS
index 4b6a54da7e65bdd662e8f485363352e6236f3ad2..45b054b7b5ec81f814f6bf12c9462318424e6e01 100644 (file)
@@ -146,7 +146,7 @@ int freeze_processes(void)
        BUG_ON(in_atomic());
 
        /*
-        * Now that the whole userspace is frozen we need to disbale
+        * Now that the whole userspace is frozen we need to disable
         * the OOM killer to disallow any further interference with
         * killable tasks. There is no guarantee oom victims will
         * ever reach a point they go away we have to wait with a timeout.
index fe64a49344bf5231fbc80fc8f8a26d714accbe07..bc1e3b5a97bddba138c5c6033ed530be0e8a2e9b 100644 (file)
@@ -528,8 +528,8 @@ static int log_store(u32 caller_id, int facility, int level,
        if (dev_info)
                memcpy(&r.info->dev_info, dev_info, sizeof(r.info->dev_info));
 
-       /* insert message */
-       if ((flags & LOG_CONT) || !(flags & LOG_NEWLINE))
+       /* A message without a trailing newline can be continued. */
+       if (!(flags & LOG_NEWLINE))
                prb_commit(&e);
        else
                prb_final_commit(&e);
index 24a960a89aa890e2b6c8ae467970b2d792f12b97..74e25a1704f2b7ee1fe0e873f68b51395bcec426 100644 (file)
@@ -345,7 +345,7 @@ DESC_ID((id) - DESCS_COUNT(desc_ring))
  */
 struct prb_data_block {
        unsigned long   id;
-       char            data[0];
+       char            data[];
 };
 
 /*
@@ -882,8 +882,6 @@ static bool desc_reserve(struct printk_ringbuffer *rb, unsigned long *id_out)
        head_id = atomic_long_read(&desc_ring->head_id); /* LMM(desc_reserve:A) */
 
        do {
-               desc = to_desc(desc_ring, head_id);
-
                id = DESC_ID(head_id + 1);
                id_prev_wrap = DESC_ID_PREV_WRAP(desc_ring, id);
 
index 43d6179508d645e5decfbf24dde54ed1815df470..79de1294f8ebd910a5b38b2ab86d28bd49d60c4c 100644 (file)
@@ -264,17 +264,11 @@ static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
        return ret;
 }
 
-static bool ptrace_has_cap(const struct cred *cred, struct user_namespace *ns,
-                          unsigned int mode)
+static bool ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
 {
-       int ret;
-
        if (mode & PTRACE_MODE_NOAUDIT)
-               ret = security_capable(cred, ns, CAP_SYS_PTRACE, CAP_OPT_NOAUDIT);
-       else
-               ret = security_capable(cred, ns, CAP_SYS_PTRACE, CAP_OPT_NONE);
-
-       return ret == 0;
+               return ns_capable_noaudit(ns, CAP_SYS_PTRACE);
+       return ns_capable(ns, CAP_SYS_PTRACE);
 }
 
 /* Returns 0 on success, -errno on denial. */
@@ -326,7 +320,7 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
            gid_eq(caller_gid, tcred->sgid) &&
            gid_eq(caller_gid, tcred->gid))
                goto ok;
-       if (ptrace_has_cap(cred, tcred->user_ns, mode))
+       if (ptrace_has_cap(tcred->user_ns, mode))
                goto ok;
        rcu_read_unlock();
        return -EPERM;
@@ -345,7 +339,7 @@ ok:
        mm = task->mm;
        if (mm &&
            ((get_dumpable(mm) != SUID_DUMP_USER) &&
-            !ptrace_has_cap(cred, mm->user_ns, mode)))
+            !ptrace_has_cap(mm->user_ns, mode)))
            return -EPERM;
 
        return security_ptrace_access_check(task, mode);
index 06895ef85d6926ec746bffff70933478a5db4049..bd04b09b84b327cde1aa8472986dfc0a5ff39719 100644 (file)
@@ -409,7 +409,7 @@ bool rcu_eqs_special_set(int cpu)
  *
  * The caller must have disabled interrupts and must not be idle.
  */
-void rcu_momentary_dyntick_idle(void)
+notrace void rcu_momentary_dyntick_idle(void)
 {
        int special;
 
@@ -4077,7 +4077,6 @@ void rcu_cpu_starting(unsigned int cpu)
        smp_mb(); /* Ensure RCU read-side usage follows above initialization. */
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 /*
  * The outgoing function has no further need of RCU, so remove it from
  * the rcu_node tree's ->qsmaskinitnext bit masks.
@@ -4117,6 +4116,7 @@ void rcu_report_dead(unsigned int cpu)
        rdp->cpu_started = false;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
 /*
  * The outgoing CPU has just passed through the dying-idle state, and we
  * are being invoked from the CPU that was IPIed to continue the offline
index 0fde39b8daab51ac3fb5e5e9434eb6eef7c97017..ca21d28a0f98f8d82a6031aa65469d0a7915fda4 100644 (file)
@@ -249,13 +249,16 @@ static bool check_slow_task(struct task_struct *t, void *arg)
 
 /*
  * Scan the current list of tasks blocked within RCU read-side critical
- * sections, printing out the tid of each.
+ * sections, printing out the tid of each of the first few of them.
  */
-static int rcu_print_task_stall(struct rcu_node *rnp)
+static int rcu_print_task_stall(struct rcu_node *rnp, unsigned long flags)
+       __releases(rnp->lock)
 {
+       int i = 0;
        int ndetected = 0;
        struct rcu_stall_chk_rdr rscr;
        struct task_struct *t;
+       struct task_struct *ts[8];
 
        if (!rcu_preempt_blocked_readers_cgp(rnp))
                return 0;
@@ -264,6 +267,14 @@ static int rcu_print_task_stall(struct rcu_node *rnp)
        t = list_entry(rnp->gp_tasks->prev,
                       struct task_struct, rcu_node_entry);
        list_for_each_entry_continue(t, &rnp->blkd_tasks, rcu_node_entry) {
+               get_task_struct(t);
+               ts[i++] = t;
+               if (i >= ARRAY_SIZE(ts))
+                       break;
+       }
+       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
+       for (i--; i; i--) {
+               t = ts[i];
                if (!try_invoke_on_locked_down_task(t, check_slow_task, &rscr))
                        pr_cont(" P%d", t->pid);
                else
@@ -273,6 +284,7 @@ static int rcu_print_task_stall(struct rcu_node *rnp)
                                ".q"[rscr.rs.b.need_qs],
                                ".e"[rscr.rs.b.exp_hint],
                                ".l"[rscr.on_blkd_list]);
+               put_task_struct(t);
                ndetected++;
        }
        pr_cont("\n");
@@ -293,8 +305,9 @@ static void rcu_print_detail_task_stall_rnp(struct rcu_node *rnp)
  * Because preemptible RCU does not exist, we never have to check for
  * tasks blocked within RCU read-side critical sections.
  */
-static int rcu_print_task_stall(struct rcu_node *rnp)
+static int rcu_print_task_stall(struct rcu_node *rnp, unsigned long flags)
 {
+       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
        return 0;
 }
 #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
@@ -472,7 +485,6 @@ static void print_other_cpu_stall(unsigned long gp_seq, unsigned long gps)
        pr_err("INFO: %s detected stalls on CPUs/tasks:\n", rcu_state.name);
        rcu_for_each_leaf_node(rnp) {
                raw_spin_lock_irqsave_rcu_node(rnp, flags);
-               ndetected += rcu_print_task_stall(rnp);
                if (rnp->qsmask != 0) {
                        for_each_leaf_node_possible_cpu(rnp, cpu)
                                if (rnp->qsmask & leaf_node_cpu_bit(rnp, cpu)) {
@@ -480,7 +492,7 @@ static void print_other_cpu_stall(unsigned long gp_seq, unsigned long gps)
                                        ndetected++;
                                }
                }
-               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
+               ndetected += rcu_print_task_stall(rnp, flags); // Releases rnp->lock.
        }
 
        for_each_possible_cpu(cpu)
index e7b78d5ae1abf8a0e207f662c95905030d09515c..af6f23d8bea164f6929453bec3d9cc1fa7f92007 100644 (file)
@@ -551,22 +551,22 @@ static int __init reboot_setup(char *str)
                        break;
 
                case 's':
-               {
-                       int rc;
-
-                       if (isdigit(*(str+1))) {
-                               rc = kstrtoint(str+1, 0, &reboot_cpu);
-                               if (rc)
-                                       return rc;
-                       } else if (str[1] == 'm' && str[2] == 'p' &&
-                                  isdigit(*(str+3))) {
-                               rc = kstrtoint(str+3, 0, &reboot_cpu);
-                               if (rc)
-                                       return rc;
-                       } else
+                       if (isdigit(*(str+1)))
+                               reboot_cpu = simple_strtoul(str+1, NULL, 0);
+                       else if (str[1] == 'm' && str[2] == 'p' &&
+                                                       isdigit(*(str+3)))
+                               reboot_cpu = simple_strtoul(str+3, NULL, 0);
+                       else
                                *mode = REBOOT_SOFT;
+                       if (reboot_cpu >= num_possible_cpus()) {
+                               pr_err("Ignoring the CPU number in reboot= option. "
+                                      "CPU %d exceeds possible cpu number %d\n",
+                                      reboot_cpu, num_possible_cpus());
+                               reboot_cpu = 0;
+                               break;
+                       }
                        break;
-               }
+
                case 'g':
                        *mode = REBOOT_GPIO;
                        break;
index d2003a7d5ab558faf1a4fcac2937e8be6ed39c6a..e7e453492cffc0082ef11ba3e826257f6324db35 100644 (file)
@@ -2501,7 +2501,12 @@ ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags,
 #ifdef CONFIG_SMP
        if (wake_flags & WF_MIGRATED)
                en_flags |= ENQUEUE_MIGRATED;
+       else
 #endif
+       if (p->in_iowait) {
+               delayacct_blkio_end(p);
+               atomic_dec(&task_rq(p)->nr_iowait);
+       }
 
        activate_task(rq, p, en_flags);
        ttwu_do_wakeup(rq, p, wake_flags, rf);
@@ -2888,11 +2893,6 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
        if (READ_ONCE(p->on_rq) && ttwu_runnable(p, wake_flags))
                goto unlock;
 
-       if (p->in_iowait) {
-               delayacct_blkio_end(p);
-               atomic_dec(&task_rq(p)->nr_iowait);
-       }
-
 #ifdef CONFIG_SMP
        /*
         * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be
@@ -2963,6 +2963,11 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
 
        cpu = select_task_rq(p, p->wake_cpu, SD_BALANCE_WAKE, wake_flags);
        if (task_cpu(p) != cpu) {
+               if (p->in_iowait) {
+                       delayacct_blkio_end(p);
+                       atomic_dec(&task_rq(p)->nr_iowait);
+               }
+
                wake_flags |= WF_MIGRATED;
                psi_ttwu_dequeue(p);
                set_task_cpu(p, cpu);
@@ -4907,20 +4912,21 @@ void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task)
                if (!dl_prio(p->normal_prio) ||
                    (pi_task && dl_prio(pi_task->prio) &&
                     dl_entity_preempt(&pi_task->dl, &p->dl))) {
-                       p->dl.dl_boosted = 1;
+                       p->dl.pi_se = pi_task->dl.pi_se;
                        queue_flag |= ENQUEUE_REPLENISH;
-               } else
-                       p->dl.dl_boosted = 0;
+               } else {
+                       p->dl.pi_se = &p->dl;
+               }
                p->sched_class = &dl_sched_class;
        } else if (rt_prio(prio)) {
                if (dl_prio(oldprio))
-                       p->dl.dl_boosted = 0;
+                       p->dl.pi_se = &p->dl;
                if (oldprio < prio)
                        queue_flag |= ENQUEUE_HEAD;
                p->sched_class = &rt_sched_class;
        } else {
                if (dl_prio(oldprio))
-                       p->dl.dl_boosted = 0;
+                       p->dl.pi_se = &p->dl;
                if (rt_prio(oldprio))
                        p->rt.timeout = 0;
                p->sched_class = &fair_sched_class;
index e254745a82cb851e0f695edfc628fbbf519b8e40..97d318b0cd0cb7d739af1ab099a1fb6104715a35 100644 (file)
@@ -102,8 +102,12 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
 static bool sugov_update_next_freq(struct sugov_policy *sg_policy, u64 time,
                                   unsigned int next_freq)
 {
-       if (sg_policy->next_freq == next_freq)
-               return false;
+       if (!sg_policy->need_freq_update) {
+               if (sg_policy->next_freq == next_freq)
+                       return false;
+       } else {
+               sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS);
+       }
 
        sg_policy->next_freq = next_freq;
        sg_policy->last_freq_update_time = time;
@@ -164,7 +168,6 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy,
        if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update)
                return sg_policy->next_freq;
 
-       sg_policy->need_freq_update = false;
        sg_policy->cached_raw_freq = freq;
        return cpufreq_driver_resolve_freq(policy, freq);
 }
@@ -440,7 +443,6 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
        struct sugov_policy *sg_policy = sg_cpu->sg_policy;
        unsigned long util, max;
        unsigned int next_f;
-       bool busy;
        unsigned int cached_freq = sg_policy->cached_raw_freq;
 
        sugov_iowait_boost(sg_cpu, time, flags);
@@ -451,9 +453,6 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
        if (!sugov_should_update_freq(sg_policy, time))
                return;
 
-       /* Limits may have changed, don't skip frequency update */
-       busy = !sg_policy->need_freq_update && sugov_cpu_is_busy(sg_cpu);
-
        util = sugov_get_util(sg_cpu);
        max = sg_cpu->max;
        util = sugov_iowait_apply(sg_cpu, time, util, max);
@@ -462,7 +461,7 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
         * Do not reduce the frequency if the CPU has not been idle
         * recently, as the reduction is likely to be premature then.
         */
-       if (busy && next_f < sg_policy->next_freq) {
+       if (sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
                next_f = sg_policy->next_freq;
 
                /* Restore cached freq as next_freq has changed */
@@ -827,9 +826,10 @@ static int sugov_start(struct cpufreq_policy *policy)
        sg_policy->next_freq                    = 0;
        sg_policy->work_in_progress             = false;
        sg_policy->limits_changed               = false;
-       sg_policy->need_freq_update             = false;
        sg_policy->cached_raw_freq              = 0;
 
+       sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS);
+
        for_each_cpu(cpu, policy->cpus) {
                struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu);
 
@@ -881,7 +881,7 @@ static void sugov_limits(struct cpufreq_policy *policy)
 struct cpufreq_governor schedutil_gov = {
        .name                   = "schedutil",
        .owner                  = THIS_MODULE,
-       .dynamic_switching      = true,
+       .flags                  = CPUFREQ_GOV_DYNAMIC_SWITCHING,
        .init                   = sugov_init,
        .exit                   = sugov_exit,
        .start                  = sugov_start,
index f232305dcefe80d6cac126c45e8967061e0dc42e..1d3c97268ec0d918c22c2c7b1dfb0942d939bd18 100644 (file)
@@ -43,6 +43,28 @@ static inline int on_dl_rq(struct sched_dl_entity *dl_se)
        return !RB_EMPTY_NODE(&dl_se->rb_node);
 }
 
+#ifdef CONFIG_RT_MUTEXES
+static inline struct sched_dl_entity *pi_of(struct sched_dl_entity *dl_se)
+{
+       return dl_se->pi_se;
+}
+
+static inline bool is_dl_boosted(struct sched_dl_entity *dl_se)
+{
+       return pi_of(dl_se) != dl_se;
+}
+#else
+static inline struct sched_dl_entity *pi_of(struct sched_dl_entity *dl_se)
+{
+       return dl_se;
+}
+
+static inline bool is_dl_boosted(struct sched_dl_entity *dl_se)
+{
+       return false;
+}
+#endif
+
 #ifdef CONFIG_SMP
 static inline struct dl_bw *dl_bw_of(int i)
 {
@@ -698,7 +720,7 @@ static inline void setup_new_dl_entity(struct sched_dl_entity *dl_se)
        struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
        struct rq *rq = rq_of_dl_rq(dl_rq);
 
-       WARN_ON(dl_se->dl_boosted);
+       WARN_ON(is_dl_boosted(dl_se));
        WARN_ON(dl_time_before(rq_clock(rq), dl_se->deadline));
 
        /*
@@ -736,21 +758,20 @@ static inline void setup_new_dl_entity(struct sched_dl_entity *dl_se)
  * could happen are, typically, a entity voluntarily trying to overcome its
  * runtime, or it just underestimated it during sched_setattr().
  */
-static void replenish_dl_entity(struct sched_dl_entity *dl_se,
-                               struct sched_dl_entity *pi_se)
+static void replenish_dl_entity(struct sched_dl_entity *dl_se)
 {
        struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
        struct rq *rq = rq_of_dl_rq(dl_rq);
 
-       BUG_ON(pi_se->dl_runtime <= 0);
+       BUG_ON(pi_of(dl_se)->dl_runtime <= 0);
 
        /*
         * This could be the case for a !-dl task that is boosted.
         * Just go with full inherited parameters.
         */
        if (dl_se->dl_deadline == 0) {
-               dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline;
-               dl_se->runtime = pi_se->dl_runtime;
+               dl_se->deadline = rq_clock(rq) + pi_of(dl_se)->dl_deadline;
+               dl_se->runtime = pi_of(dl_se)->dl_runtime;
        }
 
        if (dl_se->dl_yielded && dl_se->runtime > 0)
@@ -763,8 +784,8 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se,
         * arbitrary large.
         */
        while (dl_se->runtime <= 0) {
-               dl_se->deadline += pi_se->dl_period;
-               dl_se->runtime += pi_se->dl_runtime;
+               dl_se->deadline += pi_of(dl_se)->dl_period;
+               dl_se->runtime += pi_of(dl_se)->dl_runtime;
        }
 
        /*
@@ -778,8 +799,8 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se,
         */
        if (dl_time_before(dl_se->deadline, rq_clock(rq))) {
                printk_deferred_once("sched: DL replenish lagged too much\n");
-               dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline;
-               dl_se->runtime = pi_se->dl_runtime;
+               dl_se->deadline = rq_clock(rq) + pi_of(dl_se)->dl_deadline;
+               dl_se->runtime = pi_of(dl_se)->dl_runtime;
        }
 
        if (dl_se->dl_yielded)
@@ -812,8 +833,7 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se,
  * task with deadline equal to period this is the same of using
  * dl_period instead of dl_deadline in the equation above.
  */
-static bool dl_entity_overflow(struct sched_dl_entity *dl_se,
-                              struct sched_dl_entity *pi_se, u64 t)
+static bool dl_entity_overflow(struct sched_dl_entity *dl_se, u64 t)
 {
        u64 left, right;
 
@@ -835,9 +855,9 @@ static bool dl_entity_overflow(struct sched_dl_entity *dl_se,
         * of anything below microseconds resolution is actually fiction
         * (but still we want to give the user that illusion >;).
         */
-       left = (pi_se->dl_deadline >> DL_SCALE) * (dl_se->runtime >> DL_SCALE);
+       left = (pi_of(dl_se)->dl_deadline >> DL_SCALE) * (dl_se->runtime >> DL_SCALE);
        right = ((dl_se->deadline - t) >> DL_SCALE) *
-               (pi_se->dl_runtime >> DL_SCALE);
+               (pi_of(dl_se)->dl_runtime >> DL_SCALE);
 
        return dl_time_before(right, left);
 }
@@ -922,24 +942,23 @@ static inline bool dl_is_implicit(struct sched_dl_entity *dl_se)
  * Please refer to the comments update_dl_revised_wakeup() function to find
  * more about the Revised CBS rule.
  */
-static void update_dl_entity(struct sched_dl_entity *dl_se,
-                            struct sched_dl_entity *pi_se)
+static void update_dl_entity(struct sched_dl_entity *dl_se)
 {
        struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
        struct rq *rq = rq_of_dl_rq(dl_rq);
 
        if (dl_time_before(dl_se->deadline, rq_clock(rq)) ||
-           dl_entity_overflow(dl_se, pi_se, rq_clock(rq))) {
+           dl_entity_overflow(dl_se, rq_clock(rq))) {
 
                if (unlikely(!dl_is_implicit(dl_se) &&
                             !dl_time_before(dl_se->deadline, rq_clock(rq)) &&
-                            !dl_se->dl_boosted)){
+                            !is_dl_boosted(dl_se))) {
                        update_dl_revised_wakeup(dl_se, rq);
                        return;
                }
 
-               dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline;
-               dl_se->runtime = pi_se->dl_runtime;
+               dl_se->deadline = rq_clock(rq) + pi_of(dl_se)->dl_deadline;
+               dl_se->runtime = pi_of(dl_se)->dl_runtime;
        }
 }
 
@@ -1038,7 +1057,7 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
         * The task might have been boosted by someone else and might be in the
         * boosting/deboosting path, its not throttled.
         */
-       if (dl_se->dl_boosted)
+       if (is_dl_boosted(dl_se))
                goto unlock;
 
        /*
@@ -1066,7 +1085,7 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
         * but do not enqueue -- wait for our wakeup to do that.
         */
        if (!task_on_rq_queued(p)) {
-               replenish_dl_entity(dl_se, dl_se);
+               replenish_dl_entity(dl_se);
                goto unlock;
        }
 
@@ -1156,7 +1175,7 @@ static inline void dl_check_constrained_dl(struct sched_dl_entity *dl_se)
 
        if (dl_time_before(dl_se->deadline, rq_clock(rq)) &&
            dl_time_before(rq_clock(rq), dl_next_period(dl_se))) {
-               if (unlikely(dl_se->dl_boosted || !start_dl_timer(p)))
+               if (unlikely(is_dl_boosted(dl_se) || !start_dl_timer(p)))
                        return;
                dl_se->dl_throttled = 1;
                if (dl_se->runtime > 0)
@@ -1287,7 +1306,7 @@ throttle:
                        dl_se->dl_overrun = 1;
 
                __dequeue_task_dl(rq, curr, 0);
-               if (unlikely(dl_se->dl_boosted || !start_dl_timer(curr)))
+               if (unlikely(is_dl_boosted(dl_se) || !start_dl_timer(curr)))
                        enqueue_task_dl(rq, curr, ENQUEUE_REPLENISH);
 
                if (!is_leftmost(curr, &rq->dl))
@@ -1481,8 +1500,7 @@ static void __dequeue_dl_entity(struct sched_dl_entity *dl_se)
 }
 
 static void
-enqueue_dl_entity(struct sched_dl_entity *dl_se,
-                 struct sched_dl_entity *pi_se, int flags)
+enqueue_dl_entity(struct sched_dl_entity *dl_se, int flags)
 {
        BUG_ON(on_dl_rq(dl_se));
 
@@ -1493,9 +1511,9 @@ enqueue_dl_entity(struct sched_dl_entity *dl_se,
         */
        if (flags & ENQUEUE_WAKEUP) {
                task_contending(dl_se, flags);
-               update_dl_entity(dl_se, pi_se);
+               update_dl_entity(dl_se);
        } else if (flags & ENQUEUE_REPLENISH) {
-               replenish_dl_entity(dl_se, pi_se);
+               replenish_dl_entity(dl_se);
        } else if ((flags & ENQUEUE_RESTORE) &&
                  dl_time_before(dl_se->deadline,
                                 rq_clock(rq_of_dl_rq(dl_rq_of_se(dl_se))))) {
@@ -1512,19 +1530,7 @@ static void dequeue_dl_entity(struct sched_dl_entity *dl_se)
 
 static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags)
 {
-       struct task_struct *pi_task = rt_mutex_get_top_task(p);
-       struct sched_dl_entity *pi_se = &p->dl;
-
-       /*
-        * Use the scheduling parameters of the top pi-waiter task if:
-        * - we have a top pi-waiter which is a SCHED_DEADLINE task AND
-        * - our dl_boosted is set (i.e. the pi-waiter's (absolute) deadline is
-        *   smaller than our deadline OR we are a !SCHED_DEADLINE task getting
-        *   boosted due to a SCHED_DEADLINE pi-waiter).
-        * Otherwise we keep our runtime and deadline.
-        */
-       if (pi_task && dl_prio(pi_task->normal_prio) && p->dl.dl_boosted) {
-               pi_se = &pi_task->dl;
+       if (is_dl_boosted(&p->dl)) {
                /*
                 * Because of delays in the detection of the overrun of a
                 * thread's runtime, it might be the case that a thread
@@ -1557,7 +1563,7 @@ static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags)
                 * the throttle.
                 */
                p->dl.dl_throttled = 0;
-               BUG_ON(!p->dl.dl_boosted || flags != ENQUEUE_REPLENISH);
+               BUG_ON(!is_dl_boosted(&p->dl) || flags != ENQUEUE_REPLENISH);
                return;
        }
 
@@ -1594,7 +1600,7 @@ static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags)
                return;
        }
 
-       enqueue_dl_entity(&p->dl, pi_se, flags);
+       enqueue_dl_entity(&p->dl, flags);
 
        if (!task_current(rq, p) && p->nr_cpus_allowed > 1)
                enqueue_pushable_dl_task(rq, p);
@@ -2787,11 +2793,14 @@ void __dl_clear_params(struct task_struct *p)
        dl_se->dl_bw                    = 0;
        dl_se->dl_density               = 0;
 
-       dl_se->dl_boosted               = 0;
        dl_se->dl_throttled             = 0;
        dl_se->dl_yielded               = 0;
        dl_se->dl_non_contending        = 0;
        dl_se->dl_overrun               = 0;
+
+#ifdef CONFIG_RT_MUTEXES
+       dl_se->pi_se                    = dl_se;
+#endif
 }
 
 bool dl_param_changed(struct task_struct *p, const struct sched_attr *attr)
index 0655524700d24d8e5ab6101452acb6c9b5fdea27..2357921580f9c052ec49094f93a20ea3bf969d53 100644 (file)
@@ -251,7 +251,7 @@ static int sd_ctl_doflags(struct ctl_table *table, int write,
        unsigned long flags = *(unsigned long *)table->data;
        size_t data_size = 0;
        size_t len = 0;
-       char *tmp;
+       char *tmp, *buf;
        int idx;
 
        if (write)
@@ -269,17 +269,17 @@ static int sd_ctl_doflags(struct ctl_table *table, int write,
                return 0;
        }
 
-       tmp = kcalloc(data_size + 1, sizeof(*tmp), GFP_KERNEL);
-       if (!tmp)
+       buf = kcalloc(data_size + 1, sizeof(*buf), GFP_KERNEL);
+       if (!buf)
                return -ENOMEM;
 
        for_each_set_bit(idx, &flags, __SD_FLAG_CNT) {
                char *name = sd_flag_debug[idx].name;
 
-               len += snprintf(tmp + len, strlen(name) + 2, "%s ", name);
+               len += snprintf(buf + len, strlen(name) + 2, "%s ", name);
        }
 
-       tmp += *ppos;
+       tmp = buf + *ppos;
        len -= *ppos;
 
        if (len > *lenp)
@@ -294,7 +294,7 @@ static int sd_ctl_doflags(struct ctl_table *table, int write,
        *lenp = len;
        *ppos += len;
 
-       kfree(tmp);
+       kfree(buf);
 
        return 0;
 }
index 290f9e38378c8899447f281a067c3600a8cf6599..ae7ceba8fd4f21c4966a5edecd125222c549c1ce 100644 (file)
@@ -5477,6 +5477,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 task_new = !(flags & ENQUEUE_WAKEUP);
 
        /*
         * The code below (indirectly) updates schedutil which looks at
@@ -5549,7 +5550,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
         * into account, but that is not straightforward to implement,
         * and the following generally works well enough in practice.
         */
-       if (flags & ENQUEUE_WAKEUP)
+       if (!task_new)
                update_overutilized_status(rq);
 
 enqueue_throttle:
@@ -6172,21 +6173,21 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int t
 static int
 select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target)
 {
-       unsigned long best_cap = 0;
+       unsigned long task_util, best_cap = 0;
        int cpu, best_cpu = -1;
        struct cpumask *cpus;
 
-       sync_entity_load_avg(&p->se);
-
        cpus = this_cpu_cpumask_var_ptr(select_idle_mask);
        cpumask_and(cpus, sched_domain_span(sd), p->cpus_ptr);
 
+       task_util = uclamp_task_util(p);
+
        for_each_cpu_wrap(cpu, cpus, target) {
                unsigned long cpu_cap = capacity_of(cpu);
 
                if (!available_idle_cpu(cpu) && !sched_idle_cpu(cpu))
                        continue;
-               if (task_fits_capacity(p, cpu_cap))
+               if (fits_capacity(task_util, cpu_cap))
                        return cpu;
 
                if (cpu_cap > best_cap) {
@@ -6198,44 +6199,42 @@ select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target)
        return best_cpu;
 }
 
+static inline bool asym_fits_capacity(int task_util, int cpu)
+{
+       if (static_branch_unlikely(&sched_asym_cpucapacity))
+               return fits_capacity(task_util, capacity_of(cpu));
+
+       return true;
+}
+
 /*
  * Try and locate an idle core/thread in the LLC cache domain.
  */
 static int select_idle_sibling(struct task_struct *p, int prev, int target)
 {
        struct sched_domain *sd;
+       unsigned long task_util;
        int i, recent_used_cpu;
 
        /*
-        * For asymmetric CPU capacity systems, our domain of interest is
-        * sd_asym_cpucapacity rather than sd_llc.
+        * On asymmetric system, update task utilization because we will check
+        * that the task fits with cpu's capacity.
         */
        if (static_branch_unlikely(&sched_asym_cpucapacity)) {
-               sd = rcu_dereference(per_cpu(sd_asym_cpucapacity, target));
-               /*
-                * On an asymmetric CPU capacity system where an exclusive
-                * cpuset defines a symmetric island (i.e. one unique
-                * capacity_orig value through the cpuset), the key will be set
-                * but the CPUs within that cpuset will not have a domain with
-                * SD_ASYM_CPUCAPACITY. These should follow the usual symmetric
-                * capacity path.
-                */
-               if (!sd)
-                       goto symmetric;
-
-               i = select_idle_capacity(p, sd, target);
-               return ((unsigned)i < nr_cpumask_bits) ? i : target;
+               sync_entity_load_avg(&p->se);
+               task_util = uclamp_task_util(p);
        }
 
-symmetric:
-       if (available_idle_cpu(target) || sched_idle_cpu(target))
+       if ((available_idle_cpu(target) || sched_idle_cpu(target)) &&
+           asym_fits_capacity(task_util, target))
                return target;
 
        /*
         * If the previous CPU is cache affine and idle, don't be stupid:
         */
        if (prev != target && cpus_share_cache(prev, target) &&
-           (available_idle_cpu(prev) || sched_idle_cpu(prev)))
+           (available_idle_cpu(prev) || sched_idle_cpu(prev)) &&
+           asym_fits_capacity(task_util, prev))
                return prev;
 
        /*
@@ -6258,7 +6257,8 @@ symmetric:
            recent_used_cpu != target &&
            cpus_share_cache(recent_used_cpu, target) &&
            (available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) &&
-           cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr)) {
+           cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr) &&
+           asym_fits_capacity(task_util, recent_used_cpu)) {
                /*
                 * Replace recent_used_cpu with prev as it is a potential
                 * candidate for the next wake:
@@ -6267,6 +6267,26 @@ symmetric:
                return recent_used_cpu;
        }
 
+       /*
+        * For asymmetric CPU capacity systems, our domain of interest is
+        * sd_asym_cpucapacity rather than sd_llc.
+        */
+       if (static_branch_unlikely(&sched_asym_cpucapacity)) {
+               sd = rcu_dereference(per_cpu(sd_asym_cpucapacity, target));
+               /*
+                * On an asymmetric CPU capacity system where an exclusive
+                * cpuset defines a symmetric island (i.e. one unique
+                * capacity_orig value through the cpuset), the key will be set
+                * but the CPUs within that cpuset will not have a domain with
+                * SD_ASYM_CPUCAPACITY. These should follow the usual symmetric
+                * capacity path.
+                */
+               if (sd) {
+                       i = select_idle_capacity(p, sd, target);
+                       return ((unsigned)i < nr_cpumask_bits) ? i : target;
+               }
+       }
+
        sd = rcu_dereference(per_cpu(sd_llc, target));
        if (!sd)
                return target;
@@ -9031,7 +9051,8 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
         * emptying busiest.
         */
        if (local->group_type == group_has_spare) {
-               if (busiest->group_type > group_fully_busy) {
+               if ((busiest->group_type > group_fully_busy) &&
+                   !(env->sd->flags & SD_SHARE_PKG_RESOURCES)) {
                        /*
                         * If busiest is overloaded, try to fill spare
                         * capacity. This might end up creating spare capacity
index 24d0ee26377d08269bf095c56e648329a9c82672..c6932b8f4467a5e678c0e1dc6260890b2692369a 100644 (file)
@@ -78,7 +78,7 @@ void __weak arch_cpu_idle_dead(void) { }
 void __weak arch_cpu_idle(void)
 {
        cpu_idle_force_poll = 1;
-       local_irq_enable();
+       raw_local_irq_enable();
 }
 
 /**
@@ -94,9 +94,35 @@ void __cpuidle default_idle_call(void)
 
                trace_cpu_idle(1, smp_processor_id());
                stop_critical_timings();
+
+               /*
+                * arch_cpu_idle() is supposed to enable IRQs, however
+                * we can't do that because of RCU and tracing.
+                *
+                * Trace IRQs enable here, then switch off RCU, and have
+                * arch_cpu_idle() use raw_local_irq_enable(). Note that
+                * rcu_idle_enter() relies on lockdep IRQ state, so switch that
+                * last -- this is very similar to the entry code.
+                */
+               trace_hardirqs_on_prepare();
+               lockdep_hardirqs_on_prepare(_THIS_IP_);
                rcu_idle_enter();
+               lockdep_hardirqs_on(_THIS_IP_);
+
                arch_cpu_idle();
+
+               /*
+                * OK, so IRQs are enabled here, but RCU needs them disabled to
+                * turn itself back on.. funny thing is that disabling IRQs
+                * will cause tracing, which needs RCU. Jump through hoops to
+                * make it 'work'.
+                */
+               raw_local_irq_disable();
+               lockdep_hardirqs_off(_THIS_IP_);
                rcu_idle_exit();
+               lockdep_hardirqs_on(_THIS_IP_);
+               raw_local_irq_enable();
+
                start_critical_timings();
                trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
        }
index 8ad7a293255a02de60665b68726576c3b07cdd9e..53a7d1512dd739879586e880bc516035d7ee720d 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/filter.h>
 #include <linux/pid.h>
 #include <linux/ptrace.h>
-#include <linux/security.h>
+#include <linux/capability.h>
 #include <linux/tracehook.h>
 #include <linux/uaccess.h>
 #include <linux/anon_inodes.h>
@@ -558,8 +558,7 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog)
         * behavior of privileged children.
         */
        if (!task_no_new_privs(current) &&
-           security_capable(current_cred(), current_user_ns(),
-                                    CAP_SYS_ADMIN, CAP_OPT_NOAUDIT) != 0)
+                       !ns_capable_noaudit(current_user_ns(), CAP_SYS_ADMIN))
                return ERR_PTR(-EACCES);
 
        /* Allocate a new seccomp_filter */
index a38b3edc68511c3419a68b96d9867f000bb18d83..ef8f2a28d37c525b0994701448c026469a533259 100644 (file)
@@ -391,16 +391,17 @@ static bool task_participate_group_stop(struct task_struct *task)
 
 void task_join_group_stop(struct task_struct *task)
 {
+       unsigned long mask = current->jobctl & JOBCTL_STOP_SIGMASK;
+       struct signal_struct *sig = current->signal;
+
+       if (sig->group_stop_count) {
+               sig->group_stop_count++;
+               mask |= JOBCTL_STOP_CONSUME;
+       } else if (!(sig->flags & SIGNAL_STOP_STOPPED))
+               return;
+
        /* Have the new thread join an on-going signal group stop */
-       unsigned long jobctl = current->jobctl;
-       if (jobctl & JOBCTL_STOP_PENDING) {
-               struct signal_struct *sig = current->signal;
-               unsigned long signr = jobctl & JOBCTL_STOP_SIGMASK;
-               unsigned long gstop = JOBCTL_STOP_PENDING | JOBCTL_STOP_CONSUME;
-               if (task_set_jobctl_pending(task, signr | gstop)) {
-                       sig->group_stop_count++;
-               }
-       }
+       task_set_jobctl_pending(task, mask | JOBCTL_STOP_PENDING);
 }
 
 /*
index 865bb0228ab667d9407a889c45e47afd1e35d383..890b79cf0e7c311c94e1ce5aa882a5f7f7d4e335 100644 (file)
@@ -178,7 +178,7 @@ static void ack_state(struct multi_stop_data *msdata)
                set_state(msdata, msdata->state + 1);
 }
 
-void __weak stop_machine_yield(const struct cpumask *cpumask)
+notrace void __weak stop_machine_yield(const struct cpumask *cpumask)
 {
        cpu_relax();
 }
index 3624b9b5835de548df2eafd78f986447e798e0fb..387b4bef7dd14118892dae9f030edf53fecc0913 100644 (file)
@@ -425,11 +425,6 @@ static inline void debug_hrtimer_deactivate(struct hrtimer *timer)
        debug_object_deactivate(timer, &hrtimer_debug_descr);
 }
 
-static inline void debug_hrtimer_free(struct hrtimer *timer)
-{
-       debug_object_free(timer, &hrtimer_debug_descr);
-}
-
 static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
                           enum hrtimer_mode mode);
 
index ca4e6d57d68b9128662bf61d4ef4e5c138e43034..00629e658ca196ec1b2c06c4d15fd7e700903ac2 100644 (file)
@@ -172,10 +172,6 @@ static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
        u64 oval, nval, ointerval, ninterval;
        struct cpu_itimer *it = &tsk->signal->it[clock_id];
 
-       /*
-        * Use the to_ktime conversion because that clamps the maximum
-        * value to KTIME_MAX and avoid multiplication overflows.
-        */
        nval = timespec64_to_ns(&value->it_value);
        ninterval = timespec64_to_ns(&value->it_interval);
 
index 0642013dace49bb4e652259c84096729b2930c6b..b1b9b12899f5e43571e9cc39740f545cd6fad795 100644 (file)
@@ -68,13 +68,13 @@ static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift)
        return (cyc * mult) >> shift;
 }
 
-struct clock_read_data *sched_clock_read_begin(unsigned int *seq)
+notrace struct clock_read_data *sched_clock_read_begin(unsigned int *seq)
 {
        *seq = raw_read_seqcount_latch(&cd.seq);
        return cd.read_data + (*seq & 1);
 }
 
-int sched_clock_read_retry(unsigned int seq)
+notrace int sched_clock_read_retry(unsigned int seq)
 {
        return read_seqcount_latch_retry(&cd.seq, seq);
 }
index de37e33a868dc0efa2c947804ebd7f4d01e07eba..c3ad64fb9d8bd12151cb460e9142976b2460d1f4 100644 (file)
@@ -732,11 +732,6 @@ static inline void debug_timer_deactivate(struct timer_list *timer)
        debug_object_deactivate(timer, &timer_debug_descr);
 }
 
-static inline void debug_timer_free(struct timer_list *timer)
-{
-       debug_object_free(timer, &timer_debug_descr);
-}
-
 static inline void debug_timer_assert_init(struct timer_list *timer)
 {
        debug_object_assert_init(timer, &timer_debug_descr);
index a4020c0b4508c9977702dd71823a1c9756217872..e1bf5228fb692ac5cc47353bb371e15df278cadc 100644 (file)
@@ -202,7 +202,7 @@ config DYNAMIC_FTRACE_WITH_REGS
 
 config DYNAMIC_FTRACE_WITH_DIRECT_CALLS
        def_bool y
-       depends on DYNAMIC_FTRACE
+       depends on DYNAMIC_FTRACE_WITH_REGS
        depends on HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
 
 config FUNCTION_PROFILER
index 4517c8b66518fdc500b5874be4653b0be98f7f4e..048c655315f13a8be5678d1c2a328026ffc5b597 100644 (file)
@@ -181,6 +181,16 @@ bpf_probe_read_user_str_common(void *dst, u32 size,
 {
        int ret;
 
+       /*
+        * NB: We rely on strncpy_from_user() not copying junk past the NUL
+        * terminator into `dst`.
+        *
+        * strncpy_from_user() does long-sized strides in the fast path. If the
+        * strncpy does not mask out the bytes after the NUL in `unsafe_ptr`,
+        * then there could be junk after the NUL in `dst`. If user takes `dst`
+        * and keys a hash map with it, then semantically identical strings can
+        * occupy multiple entries in the map.
+        */
        ret = strncpy_from_user_nofault(dst, unsafe_ptr, size);
        if (unlikely(ret < 0))
                memset(dst, 0, size);
@@ -1198,7 +1208,7 @@ static int bpf_btf_printf_prepare(struct btf_ptr *ptr, u32 btf_ptr_size,
        *btf = bpf_get_btf_vmlinux();
 
        if (IS_ERR_OR_NULL(*btf))
-               return PTR_ERR(*btf);
+               return IS_ERR(*btf) ? PTR_ERR(*btf) : -EINVAL;
 
        if (ptr->type_id > 0)
                *btf_id = ptr->type_id;
index 8185f7240095f44731c30ba9f50c64d9b398f239..9c1bba8cc51b038d1c8abfa58b4d19567c3a8c27 100644 (file)
@@ -1629,6 +1629,8 @@ static bool test_rec_ops_needs_regs(struct dyn_ftrace *rec)
 static struct ftrace_ops *
 ftrace_find_tramp_ops_any(struct dyn_ftrace *rec);
 static struct ftrace_ops *
+ftrace_find_tramp_ops_any_other(struct dyn_ftrace *rec, struct ftrace_ops *op_exclude);
+static struct ftrace_ops *
 ftrace_find_tramp_ops_next(struct dyn_ftrace *rec, struct ftrace_ops *ops);
 
 static bool __ftrace_hash_rec_update(struct ftrace_ops *ops,
@@ -1778,7 +1780,7 @@ static bool __ftrace_hash_rec_update(struct ftrace_ops *ops,
                         * to it.
                         */
                        if (ftrace_rec_count(rec) == 1 &&
-                           ftrace_find_tramp_ops_any(rec))
+                           ftrace_find_tramp_ops_any_other(rec, ops))
                                rec->flags |= FTRACE_FL_TRAMP;
                        else
                                rec->flags &= ~FTRACE_FL_TRAMP;
@@ -2244,6 +2246,24 @@ ftrace_find_tramp_ops_any(struct dyn_ftrace *rec)
        return NULL;
 }
 
+static struct ftrace_ops *
+ftrace_find_tramp_ops_any_other(struct dyn_ftrace *rec, struct ftrace_ops *op_exclude)
+{
+       struct ftrace_ops *op;
+       unsigned long ip = rec->ip;
+
+       do_for_each_ftrace_op(op, ftrace_ops_list) {
+
+               if (op == op_exclude || !op->trampoline)
+                       continue;
+
+               if (hash_contains_ip(ip, op->func_hash))
+                       return op;
+       } while_for_each_ftrace_op(op);
+
+       return NULL;
+}
+
 static struct ftrace_ops *
 ftrace_find_tramp_ops_next(struct dyn_ftrace *rec,
                           struct ftrace_ops *op)
index 7f45fd9d5a4504286176045051c6ef73806abfb7..a6268e09160a5bb9085a30c65bf8ffa49306947d 100644 (file)
@@ -438,14 +438,16 @@ enum {
 };
 /*
  * Used for which event context the event is in.
- *  NMI     = 0
- *  IRQ     = 1
- *  SOFTIRQ = 2
- *  NORMAL  = 3
+ *  TRANSITION = 0
+ *  NMI     = 1
+ *  IRQ     = 2
+ *  SOFTIRQ = 3
+ *  NORMAL  = 4
  *
  * See trace_recursive_lock() comment below for more details.
  */
 enum {
+       RB_CTX_TRANSITION,
        RB_CTX_NMI,
        RB_CTX_IRQ,
        RB_CTX_SOFTIRQ,
@@ -3014,10 +3016,10 @@ rb_wakeups(struct trace_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer)
  * a bit of overhead in something as critical as function tracing,
  * we use a bitmask trick.
  *
- *  bit 0 =  NMI context
- *  bit 1 =  IRQ context
- *  bit 2 =  SoftIRQ context
- *  bit 3 =  normal context.
+ *  bit 1 =  NMI context
+ *  bit 2 =  IRQ context
+ *  bit 3 =  SoftIRQ context
+ *  bit 4 =  normal context.
  *
  * This works because this is the order of contexts that can
  * preempt other contexts. A SoftIRQ never preempts an IRQ
@@ -3040,6 +3042,30 @@ rb_wakeups(struct trace_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer)
  * The least significant bit can be cleared this way, and it
  * just so happens that it is the same bit corresponding to
  * the current context.
+ *
+ * Now the TRANSITION bit breaks the above slightly. The TRANSITION bit
+ * is set when a recursion is detected at the current context, and if
+ * the TRANSITION bit is already set, it will fail the recursion.
+ * This is needed because there's a lag between the changing of
+ * interrupt context and updating the preempt count. In this case,
+ * a false positive will be found. To handle this, one extra recursion
+ * is allowed, and this is done by the TRANSITION bit. If the TRANSITION
+ * bit is already set, then it is considered a recursion and the function
+ * ends. Otherwise, the TRANSITION bit is set, and that bit is returned.
+ *
+ * On the trace_recursive_unlock(), the TRANSITION bit will be the first
+ * to be cleared. Even if it wasn't the context that set it. That is,
+ * if an interrupt comes in while NORMAL bit is set and the ring buffer
+ * is called before preempt_count() is updated, since the check will
+ * be on the NORMAL bit, the TRANSITION bit will then be set. If an
+ * NMI then comes in, it will set the NMI bit, but when the NMI code
+ * does the trace_recursive_unlock() it will clear the TRANSTION bit
+ * and leave the NMI bit set. But this is fine, because the interrupt
+ * code that set the TRANSITION bit will then clear the NMI bit when it
+ * calls trace_recursive_unlock(). If another NMI comes in, it will
+ * set the TRANSITION bit and continue.
+ *
+ * Note: The TRANSITION bit only handles a single transition between context.
  */
 
 static __always_inline int
@@ -3055,8 +3081,16 @@ trace_recursive_lock(struct ring_buffer_per_cpu *cpu_buffer)
                bit = pc & NMI_MASK ? RB_CTX_NMI :
                        pc & HARDIRQ_MASK ? RB_CTX_IRQ : RB_CTX_SOFTIRQ;
 
-       if (unlikely(val & (1 << (bit + cpu_buffer->nest))))
-               return 1;
+       if (unlikely(val & (1 << (bit + cpu_buffer->nest)))) {
+               /*
+                * It is possible that this was called by transitioning
+                * between interrupt context, and preempt_count() has not
+                * been updated yet. In this case, use the TRANSITION bit.
+                */
+               bit = RB_CTX_TRANSITION;
+               if (val & (1 << (bit + cpu_buffer->nest)))
+                       return 1;
+       }
 
        val |= (1 << (bit + cpu_buffer->nest));
        cpu_buffer->current_context = val;
@@ -3071,8 +3105,8 @@ trace_recursive_unlock(struct ring_buffer_per_cpu *cpu_buffer)
                cpu_buffer->current_context - (1 << cpu_buffer->nest);
 }
 
-/* The recursive locking above uses 4 bits */
-#define NESTED_BITS 4
+/* The recursive locking above uses 5 bits */
+#define NESTED_BITS 5
 
 /**
  * ring_buffer_nest_start - Allow to trace while nested
@@ -3200,14 +3234,12 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
 
        /* See if we shot pass the end of this buffer page */
        if (unlikely(write > BUF_PAGE_SIZE)) {
-               if (tail != w) {
-                       /* before and after may now different, fix it up*/
-                       b_ok = rb_time_read(&cpu_buffer->before_stamp, &info->before);
-                       a_ok = rb_time_read(&cpu_buffer->write_stamp, &info->after);
-                       if (a_ok && b_ok && info->before != info->after)
-                               (void)rb_time_cmpxchg(&cpu_buffer->before_stamp,
-                                                     info->before, info->after);
-               }
+               /* before and after may now different, fix it up*/
+               b_ok = rb_time_read(&cpu_buffer->before_stamp, &info->before);
+               a_ok = rb_time_read(&cpu_buffer->write_stamp, &info->after);
+               if (a_ok && b_ok && info->before != info->after)
+                       (void)rb_time_cmpxchg(&cpu_buffer->before_stamp,
+                                             info->before, info->after);
                return rb_move_tail(cpu_buffer, tail, info);
        }
 
@@ -3253,11 +3285,11 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
                ts = rb_time_stamp(cpu_buffer->buffer);
                barrier();
  /*E*/         if (write == (local_read(&tail_page->write) & RB_WRITE_MASK) &&
-                   info->after < ts) {
+                   info->after < ts &&
+                   rb_time_cmpxchg(&cpu_buffer->write_stamp,
+                                   info->after, ts)) {
                        /* Nothing came after this event between C and E */
                        info->delta = ts - info->after;
-                       (void)rb_time_cmpxchg(&cpu_buffer->write_stamp,
-                                             info->after, info->ts);
                        info->ts = ts;
                } else {
                        /*
index 528971714fc65d30346c6fb0f4d2d05b0457f1a3..7d53c5bdea3e1be40763bbbbeb670a27e3936f08 100644 (file)
@@ -2750,7 +2750,7 @@ trace_event_buffer_lock_reserve(struct trace_buffer **current_rb,
        /*
         * If tracing is off, but we have triggers enabled
         * we still need to look at the event data. Use the temp_buffer
-        * to store the trace event for the tigger to use. It's recusive
+        * to store the trace event for the trigger to use. It's recursive
         * safe and will not be recorded anywhere.
         */
        if (!entry && trace_file->flags & EVENT_FILE_FL_TRIGGER_COND) {
@@ -2952,7 +2952,7 @@ static void __ftrace_trace_stack(struct trace_buffer *buffer,
        stackidx = __this_cpu_inc_return(ftrace_stack_reserve) - 1;
 
        /* This should never happen. If it does, yell once and skip */
-       if (WARN_ON_ONCE(stackidx > FTRACE_KSTACK_NESTING))
+       if (WARN_ON_ONCE(stackidx >= FTRACE_KSTACK_NESTING))
                goto out;
 
        /*
@@ -3132,7 +3132,7 @@ static char *get_trace_buf(void)
 
        /* Interrupts must see nesting incremented before we use the buffer */
        barrier();
-       return &buffer->buffer[buffer->nesting][0];
+       return &buffer->buffer[buffer->nesting - 1][0];
 }
 
 static void put_trace_buf(void)
@@ -3534,7 +3534,7 @@ __find_next_entry(struct trace_iterator *iter, int *ent_cpu,
 }
 
 #define STATIC_TEMP_BUF_SIZE   128
-static char static_temp_buf[STATIC_TEMP_BUF_SIZE];
+static char static_temp_buf[STATIC_TEMP_BUF_SIZE] __aligned(4);
 
 /* Find the next real entry, without updating the iterator itself */
 struct trace_entry *trace_find_next_entry(struct trace_iterator *iter,
index f3f5e77123ad75d284fd99d7a3bf6e4e43386f39..1dadef445cd1e860cc68142fe8a6e657eae81fff 100644 (file)
@@ -637,6 +637,12 @@ enum {
         * function is called to clear it.
         */
        TRACE_GRAPH_NOTRACE_BIT,
+
+       /*
+        * When transitioning between context, the preempt_count() may
+        * not be correct. Allow for a single recursion to cover this case.
+        */
+       TRACE_TRANSITION_BIT,
 };
 
 #define trace_recursion_set(bit)       do { (current)->trace_recursion |= (1<<(bit)); } while (0)
@@ -691,14 +697,27 @@ static __always_inline int trace_test_and_set_recursion(int start, int max)
                return 0;
 
        bit = trace_get_context_bit() + start;
-       if (unlikely(val & (1 << bit)))
-               return -1;
+       if (unlikely(val & (1 << bit))) {
+               /*
+                * It could be that preempt_count has not been updated during
+                * a switch between contexts. Allow for a single recursion.
+                */
+               bit = TRACE_TRANSITION_BIT;
+               if (trace_recursion_test(bit))
+                       return -1;
+               trace_recursion_set(bit);
+               barrier();
+               return bit + 1;
+       }
+
+       /* Normal check passed, clear the transition to allow it again */
+       trace_recursion_clear(TRACE_TRANSITION_BIT);
 
        val |= 1 << bit;
        current->trace_recursion = val;
        barrier();
 
-       return bit;
+       return bit + 1;
 }
 
 static __always_inline void trace_clear_recursion(int bit)
@@ -708,6 +727,7 @@ static __always_inline void trace_clear_recursion(int bit)
        if (!bit)
                return;
 
+       bit--;
        bit = 1 << bit;
        val &= ~bit;
 
index 3212e2c653b35c1eac5a20d496f319465adff124..881df991742ab18c3f38fbf86886e4ef5a6fec62 100644 (file)
@@ -584,7 +584,8 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
 {
        struct synth_field *field;
        const char *prefix = NULL, *field_type = argv[0], *field_name, *array;
-       int len, ret = 0;
+       int len, ret = -ENOMEM;
+       struct seq_buf s;
        ssize_t size;
 
        if (field_type[0] == ';')
@@ -616,10 +617,9 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
                len--;
 
        field->name = kmemdup_nul(field_name, len, GFP_KERNEL);
-       if (!field->name) {
-               ret = -ENOMEM;
+       if (!field->name)
                goto free;
-       }
+
        if (!is_good_name(field->name)) {
                synth_err(SYNTH_ERR_BAD_NAME, errpos(field_name));
                ret = -EINVAL;
@@ -630,29 +630,29 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
                field_type++;
        len = strlen(field_type) + 1;
 
-        if (array) {
-                int l = strlen(array);
+       if (array)
+               len += strlen(array);
 
-                if (l && array[l - 1] == ';')
-                        l--;
-                len += l;
-        }
        if (prefix)
                len += strlen(prefix);
 
        field->type = kzalloc(len, GFP_KERNEL);
-       if (!field->type) {
-               ret = -ENOMEM;
+       if (!field->type)
                goto free;
-       }
+
+       seq_buf_init(&s, field->type, len);
        if (prefix)
-               strcat(field->type, prefix);
-       strcat(field->type, field_type);
+               seq_buf_puts(&s, prefix);
+       seq_buf_puts(&s, field_type);
        if (array) {
-               strcat(field->type, array);
-               if (field->type[len - 1] == ';')
-                       field->type[len - 1] = '\0';
+               seq_buf_puts(&s, array);
+               if (s.buffer[s.len - 1] == ';')
+                       s.len--;
        }
+       if (WARN_ON_ONCE(!seq_buf_buffer_left(&s)))
+               goto free;
+
+       s.buffer[s.len] = '\0';
 
        size = synth_field_size(field->type);
        if (size < 0) {
@@ -663,14 +663,19 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
                if (synth_field_is_string(field->type)) {
                        char *type;
 
-                       type = kzalloc(sizeof("__data_loc ") + strlen(field->type) + 1, GFP_KERNEL);
-                       if (!type) {
-                               ret = -ENOMEM;
+                       len = sizeof("__data_loc ") + strlen(field->type) + 1;
+                       type = kzalloc(len, GFP_KERNEL);
+                       if (!type)
                                goto free;
-                       }
 
-                       strcat(type, "__data_loc ");
-                       strcat(type, field->type);
+                       seq_buf_init(&s, type, len);
+                       seq_buf_puts(&s, "__data_loc ");
+                       seq_buf_puts(&s, field->type);
+
+                       if (WARN_ON_ONCE(!seq_buf_buffer_left(&s)))
+                               goto free;
+                       s.buffer[s.len] = '\0';
+
                        kfree(field->type);
                        field->type = type;
 
index c9ad5c6fbaada366f7c8668df059a077878900ed..d071fc271eef793680836ebb42a81ee613d03d66 100644 (file)
@@ -368,7 +368,7 @@ static int start_kthread(struct trace_array *tr)
        struct task_struct *kthread;
        int next_cpu;
 
-       if (WARN_ON(hwlat_kthread))
+       if (hwlat_kthread)
                return 0;
 
        /* Just pick the first CPU on first iteration */
index b5e3496cf8033df69a33307db09a8bd0f34bca2e..4738ad48a66740fb72d77872a34b58f0a41f98f3 100644 (file)
@@ -492,8 +492,13 @@ trace_selftest_function_recursion(void)
        unregister_ftrace_function(&test_rec_probe);
 
        ret = -1;
-       if (trace_selftest_recursion_cnt != 1) {
-               pr_cont("*callback not called once (%d)* ",
+       /*
+        * Recursion allows for transitions between context,
+        * and may call the callback twice.
+        */
+       if (trace_selftest_recursion_cnt != 1 &&
+           trace_selftest_recursion_cnt != 2) {
+               pr_cont("*callback not called once (or twice) (%d)* ",
                        trace_selftest_recursion_cnt);
                goto out;
        }
index 26efd22f063396dc6c488da618c54020ecea682a..3f659f8550741011273a10c89b5053c474b66614 100644 (file)
@@ -50,7 +50,7 @@ static bool ok_to_free_tracepoints;
  */
 struct tp_probes {
        struct rcu_head rcu;
-       struct tracepoint_func probes[0];
+       struct tracepoint_func probes[];
 };
 
 static inline void *allocate_probes(int count)
index 5abb5b22ad1308844ee0dd790b3927cf5c2d5e28..71109065bd8ebf4ee946a902321b4cd8934a3d95 100644 (file)
@@ -44,8 +44,6 @@ int __read_mostly soft_watchdog_user_enabled = 1;
 int __read_mostly watchdog_thresh = 10;
 static int __read_mostly nmi_watchdog_available;
 
-static struct cpumask watchdog_allowed_mask __read_mostly;
-
 struct cpumask watchdog_cpumask __read_mostly;
 unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
 
@@ -162,6 +160,8 @@ static void lockup_detector_update_enable(void)
 int __read_mostly sysctl_softlockup_all_cpu_backtrace;
 #endif
 
+static struct cpumask watchdog_allowed_mask __read_mostly;
+
 /* Global variables, exported for sysctl */
 unsigned int __read_mostly softlockup_panic =
                        CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE;
index d7a7bc3b6098287dc7af87b2c94d5304675401f3..c789b39ed527173219adefcca72f0f7778d15aa2 100644 (file)
@@ -2446,4 +2446,6 @@ config HYPERV_TESTING
 
 endmenu # "Kernel Testing and Coverage"
 
+source "Documentation/Kconfig"
+
 endmenu # Kernel hacking
index 97d6a57cefcc5d281a7c75e8fff8ae4bdbac1a05..61ddce2cff77749e254188ed07e339a4812274dd 100644 (file)
@@ -683,7 +683,6 @@ static int __init crc32c_test(void)
 
        /* reduce OS noise */
        local_irq_save(flags);
-       local_irq_disable();
 
        nsec = ktime_get_ns();
        for (i = 0; i < 100; i++) {
@@ -694,7 +693,6 @@ static int __init crc32c_test(void)
        nsec = ktime_get_ns() - nsec;
 
        local_irq_restore(flags);
-       local_irq_enable();
 
        pr_info("crc32c: CRC_LE_BITS = %d\n", CRC_LE_BITS);
 
@@ -768,7 +766,6 @@ static int __init crc32_test(void)
 
        /* reduce OS noise */
        local_irq_save(flags);
-       local_irq_disable();
 
        nsec = ktime_get_ns();
        for (i = 0; i < 100; i++) {
@@ -783,7 +780,6 @@ static int __init crc32_test(void)
        nsec = ktime_get_ns() - nsec;
 
        local_irq_restore(flags);
-       local_irq_enable();
 
        pr_info("crc32: CRC_LE_BITS = %d, CRC_BE BITS = %d\n",
                 CRC_LE_BITS, CRC_BE_BITS);
index 0e2deac97da0dc251ff22cb91ea22947750318a5..e02f9df24d1ee1e5f02d9ff6e4e4b356c3e346e1 100644 (file)
@@ -8,7 +8,7 @@
 
 #define FONTDATAMAX 9216
 
-static struct font_data fontdata_10x18 = {
+static const struct font_data fontdata_10x18 = {
        { 0, 0, FONTDATAMAX, 0 }, {
        /* 0 0x00 '^@' */
        0x00, 0x00, /* 0000000000 */
index 87da8acd07db0c2700ca311820ff1f244ec72bde..6e3c4b7691c85e0a12f7c3209ede7e6c17a7226f 100644 (file)
@@ -3,7 +3,7 @@
 
 #define FONTDATAMAX 2560
 
-static struct font_data fontdata_6x10 = {
+static const struct font_data fontdata_6x10 = {
        { 0, 0, FONTDATAMAX, 0 }, {
        /* 0 0x00 '^@' */
        0x00, /* 00000000 */
index 5e975dfa10a53a3dd257738f8cc5c1340dd0cbe6..2d22a24e816f0d80f59a9e1e109be624ebe7cf5c 100644 (file)
@@ -9,7 +9,7 @@
 
 #define FONTDATAMAX (11*256)
 
-static struct font_data fontdata_6x11 = {
+static const struct font_data fontdata_6x11 = {
        { 0, 0, FONTDATAMAX, 0 }, {
        /* 0 0x00 '^@' */
        0x00, /* 00000000 */
index 700039a9ceaec00a5316dcd3b443ab43ca737b08..e7442a0d183dc5aee0d16c89a99d2afaed905b71 100644 (file)
@@ -3,7 +3,7 @@
 
 #define FONTDATAMAX 2048
 
-static struct font_data fontdata_6x8 = {
+static const struct font_data fontdata_6x8 = {
        { 0, 0, FONTDATAMAX, 0 }, {
        /* 0 0x00 '^@' */
        0x00, /* 000000 */
index 86d298f38505886cc36c4af28ba0107b1dc7a1de..9cc7ae2e03f7d23c5f0e2584494ddf7a6609517e 100644 (file)
@@ -8,7 +8,7 @@
 
 #define FONTDATAMAX 3584
 
-static struct font_data fontdata_7x14 = {
+static const struct font_data fontdata_7x14 = {
        { 0, 0, FONTDATAMAX, 0 }, {
        /* 0 0x00 '^@' */
        0x00, /* 0000000 */
index 37cedd36ca5ef236d544eb70e09ead940de97e5f..bab25dc59e8ddf785668851da1a313ced23233f3 100644 (file)
@@ -10,7 +10,7 @@
 
 #define FONTDATAMAX 4096
 
-static struct font_data fontdata_8x16 = {
+static const struct font_data fontdata_8x16 = {
        { 0, 0, FONTDATAMAX, 0 }, {
        /* 0 0x00 '^@' */
        0x00, /* 00000000 */
index 8ab695538395df9f7c573a8d62aaa323b7bf35e4..109d0572368f445ce8950e5bebcdb857b58f389a 100644 (file)
@@ -9,7 +9,7 @@
 
 #define FONTDATAMAX 2048
 
-static struct font_data fontdata_8x8 = {
+static const struct font_data fontdata_8x8 = {
        { 0, 0, FONTDATAMAX, 0 }, {
        /* 0 0x00 '^@' */
        0x00, /* 00000000 */
index 069b3e80c43449270f0937e60fe3c5dce1fdbdbd..fb395f0d40317f46f80445d3219f6d7fead87262 100644 (file)
@@ -5,7 +5,7 @@
 
 #define FONTDATAMAX 2048
 
-static struct font_data acorndata_8x8 = {
+static const struct font_data acorndata_8x8 = {
 { 0, 0, FONTDATAMAX, 0 }, {
 /* 00 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */
 /* 01 */  0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, /* ^A */
index 1449876c6a27027b7a3cb1af2c4bb2cbc1296917..592774a90917b450098477f334901943ff5c8389 100644 (file)
@@ -43,7 +43,7 @@ __END__;
 
 #define FONTDATAMAX 1536
 
-static struct font_data fontdata_mini_4x6 = {
+static const struct font_data fontdata_mini_4x6 = {
        { 0, 0, FONTDATAMAX, 0 }, {
        /*{*/
                /*   Char 0: ' '  */
index 32d65551e7ed29be9265cd73e4f48aee5d816934..a6f95ebce95077e2a0242533d5bca29c13a3dca1 100644 (file)
@@ -14,7 +14,7 @@
 
 #define FONTDATAMAX 2048
 
-static struct font_data fontdata_pearl8x8 = {
+static const struct font_data fontdata_pearl8x8 = {
    { 0, 0, FONTDATAMAX, 0 }, {
    /* 0 0x00 '^@' */
    0x00, /* 00000000 */
index 641a6b4dca424fb6843126d9d2cc6d1585d04d79..a5b65bd496045cc695cac6cc11d7488e99633a46 100644 (file)
@@ -3,7 +3,7 @@
 
 #define FONTDATAMAX 11264
 
-static struct font_data fontdata_sun12x22 = {
+static const struct font_data fontdata_sun12x22 = {
        { 0, 0, FONTDATAMAX, 0 }, {
        /* 0 0x00 '^@' */
        0x00, 0x00, /* 000000000000 */
index 193fe6d988e08e95d1b172d34651ee920f4674a5..e577e76a6a7c0b7a0d0a8ed0586f4f649a444b38 100644 (file)
@@ -3,7 +3,7 @@
 
 #define FONTDATAMAX 4096
 
-static struct font_data fontdata_sun8x16 = {
+static const struct font_data fontdata_sun8x16 = {
 { 0, 0, FONTDATAMAX, 0 }, {
 /* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 /* */ 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00,
index 91b9c283bd9cc5f9f95504f909d10957ad450d7e..f7c3abb6b99e20c31c84b28a1d26f1612419bd0f 100644 (file)
@@ -4,7 +4,7 @@
 
 #define FONTDATAMAX 16384
 
-static struct font_data fontdata_ter16x32 = {
+static const struct font_data fontdata_ter16x32 = {
        { 0, 0, FONTDATAMAX, 0 }, {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x7f, 0xfc,
index 0a482ef988e56e87d77d40392092e894b29084ae..a5977894640434b909f63f852a21ec7ec14a6ee2 100644 (file)
@@ -933,7 +933,7 @@ size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, void *buf,
        sg_miter_start(&miter, sgl, nents, sg_flags);
 
        if (!sg_miter_skip(&miter, skip))
-               return false;
+               return 0;
 
        while ((offset < buflen) && sg_miter_next(&miter)) {
                unsigned int len;
index e6d5fcc2cdf3ea1143e98c417a8d617519c87434..122d8d0e253cb56eec8e423b186f968f8f862cc7 100644 (file)
@@ -35,17 +35,32 @@ static inline long do_strncpy_from_user(char *dst, const char __user *src,
                goto byte_at_a_time;
 
        while (max >= sizeof(unsigned long)) {
-               unsigned long c, data;
+               unsigned long c, data, mask;
 
                /* Fall back to byte-at-a-time if we get a page fault */
                unsafe_get_user(c, (unsigned long __user *)(src+res), byte_at_a_time);
 
-               *(unsigned long *)(dst+res) = c;
+               /*
+                * Note that we mask out the bytes following the NUL. This is
+                * important to do because string oblivious code may read past
+                * the NUL. For those routines, we don't want to give them
+                * potentially random bytes after the NUL in `src`.
+                *
+                * One example of such code is BPF map keys. BPF treats map keys
+                * as an opaque set of bytes. Without the post-NUL mask, any BPF
+                * maps keyed by strings returned from strncpy_from_user() may
+                * have multiple entries for semantically identical strings.
+                */
                if (has_zero(c, &data, &constants)) {
                        data = prep_zero_mask(c, data, &constants);
                        data = create_zero_mask(data);
+                       mask = zero_bytemask(data);
+                       *(unsigned long *)(dst+res) = c & mask;
                        return res + find_zero(data);
                }
+
+               *(unsigned long *)(dst+res) = c;
+
                res += sizeof(unsigned long);
                max -= sizeof(unsigned long);
        }
index 8533d2fea2d711aafbca366c880848ef2b99be9b..ba13e924c430ffeaaf50a17fda93b3dd0ca2cf2d 100644 (file)
@@ -7,6 +7,7 @@
 
 static int collect_syscall(struct task_struct *target, struct syscall_info *info)
 {
+       unsigned long args[6] = { };
        struct pt_regs *regs;
 
        if (!try_get_task_stack(target)) {
@@ -27,8 +28,14 @@ static int collect_syscall(struct task_struct *target, struct syscall_info *info
 
        info->data.nr = syscall_get_nr(target, regs);
        if (info->data.nr != -1L)
-               syscall_get_arguments(target, regs,
-                                     (unsigned long *)&info->data.args[0]);
+               syscall_get_arguments(target, regs, args);
+
+       info->data.args[0] = args[0];
+       info->data.args[1] = args[1];
+       info->data.args[2] = args[2];
+       info->data.args[3] = args[3];
+       info->data.args[4] = args[4];
+       info->data.args[5] = args[5];
 
        put_task_stack(target);
        return 0;
index 63c26171a791cf69bc223865a9ea49e25a886f61..662f862702fc8da9f3180adc48636360c6edad71 100644 (file)
@@ -216,6 +216,12 @@ static void kmalloc_oob_16(struct kunit *test)
                u64 words[2];
        } *ptr1, *ptr2;
 
+       /* This test is specifically crafted for the generic mode. */
+       if (!IS_ENABLED(CONFIG_KASAN_GENERIC)) {
+               kunit_info(test, "CONFIG_KASAN_GENERIC required\n");
+               return;
+       }
+
        ptr1 = kmalloc(sizeof(*ptr1) - 3, GFP_KERNEL);
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr1);
 
@@ -227,6 +233,23 @@ static void kmalloc_oob_16(struct kunit *test)
        kfree(ptr2);
 }
 
+static void kmalloc_uaf_16(struct kunit *test)
+{
+       struct {
+               u64 words[2];
+       } *ptr1, *ptr2;
+
+       ptr1 = kmalloc(sizeof(*ptr1), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr1);
+
+       ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr2);
+       kfree(ptr2);
+
+       KUNIT_EXPECT_KASAN_FAIL(test, *ptr1 = *ptr2);
+       kfree(ptr1);
+}
+
 static void kmalloc_oob_memset_2(struct kunit *test)
 {
        char *ptr;
@@ -429,6 +452,12 @@ static void kasan_global_oob(struct kunit *test)
        volatile int i = 3;
        char *p = &global_array[ARRAY_SIZE(global_array) + i];
 
+       /* Only generic mode instruments globals. */
+       if (!IS_ENABLED(CONFIG_KASAN_GENERIC)) {
+               kunit_info(test, "CONFIG_KASAN_GENERIC required");
+               return;
+       }
+
        KUNIT_EXPECT_KASAN_FAIL(test, *(volatile char *)p);
 }
 
@@ -467,6 +496,12 @@ static void kasan_alloca_oob_left(struct kunit *test)
        char alloca_array[i];
        char *p = alloca_array - 1;
 
+       /* Only generic mode instruments dynamic allocas. */
+       if (!IS_ENABLED(CONFIG_KASAN_GENERIC)) {
+               kunit_info(test, "CONFIG_KASAN_GENERIC required");
+               return;
+       }
+
        if (!IS_ENABLED(CONFIG_KASAN_STACK)) {
                kunit_info(test, "CONFIG_KASAN_STACK is not enabled");
                return;
@@ -481,6 +516,12 @@ static void kasan_alloca_oob_right(struct kunit *test)
        char alloca_array[i];
        char *p = alloca_array + i;
 
+       /* Only generic mode instruments dynamic allocas. */
+       if (!IS_ENABLED(CONFIG_KASAN_GENERIC)) {
+               kunit_info(test, "CONFIG_KASAN_GENERIC required");
+               return;
+       }
+
        if (!IS_ENABLED(CONFIG_KASAN_STACK)) {
                kunit_info(test, "CONFIG_KASAN_STACK is not enabled");
                return;
@@ -551,6 +592,9 @@ static void kasan_memchr(struct kunit *test)
                return;
        }
 
+       if (OOB_TAG_OFF)
+               size = round_up(size, OOB_TAG_OFF);
+
        ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO);
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
 
@@ -573,6 +617,9 @@ static void kasan_memcmp(struct kunit *test)
                return;
        }
 
+       if (OOB_TAG_OFF)
+               size = round_up(size, OOB_TAG_OFF);
+
        ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO);
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
        memset(arr, 0, sizeof(arr));
@@ -619,13 +666,50 @@ static void kasan_strings(struct kunit *test)
        KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result = strnlen(ptr, 1));
 }
 
-static void kasan_bitops(struct kunit *test)
+static void kasan_bitops_modify(struct kunit *test, int nr, void *addr)
+{
+       KUNIT_EXPECT_KASAN_FAIL(test, set_bit(nr, addr));
+       KUNIT_EXPECT_KASAN_FAIL(test, __set_bit(nr, addr));
+       KUNIT_EXPECT_KASAN_FAIL(test, clear_bit(nr, addr));
+       KUNIT_EXPECT_KASAN_FAIL(test, __clear_bit(nr, addr));
+       KUNIT_EXPECT_KASAN_FAIL(test, clear_bit_unlock(nr, addr));
+       KUNIT_EXPECT_KASAN_FAIL(test, __clear_bit_unlock(nr, addr));
+       KUNIT_EXPECT_KASAN_FAIL(test, change_bit(nr, addr));
+       KUNIT_EXPECT_KASAN_FAIL(test, __change_bit(nr, addr));
+}
+
+static void kasan_bitops_test_and_modify(struct kunit *test, int nr, void *addr)
+{
+       KUNIT_EXPECT_KASAN_FAIL(test, test_and_set_bit(nr, addr));
+       KUNIT_EXPECT_KASAN_FAIL(test, __test_and_set_bit(nr, addr));
+       KUNIT_EXPECT_KASAN_FAIL(test, test_and_set_bit_lock(nr, addr));
+       KUNIT_EXPECT_KASAN_FAIL(test, test_and_clear_bit(nr, addr));
+       KUNIT_EXPECT_KASAN_FAIL(test, __test_and_clear_bit(nr, addr));
+       KUNIT_EXPECT_KASAN_FAIL(test, test_and_change_bit(nr, addr));
+       KUNIT_EXPECT_KASAN_FAIL(test, __test_and_change_bit(nr, addr));
+       KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result = test_bit(nr, addr));
+
+#if defined(clear_bit_unlock_is_negative_byte)
+       KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result =
+                               clear_bit_unlock_is_negative_byte(nr, addr));
+#endif
+}
+
+static void kasan_bitops_generic(struct kunit *test)
 {
+       long *bits;
+
+       /* This test is specifically crafted for the generic mode. */
+       if (!IS_ENABLED(CONFIG_KASAN_GENERIC)) {
+               kunit_info(test, "CONFIG_KASAN_GENERIC required\n");
+               return;
+       }
+
        /*
         * Allocate 1 more byte, which causes kzalloc to round up to 16-bytes;
         * this way we do not actually corrupt other memory.
         */
-       long *bits = kzalloc(sizeof(*bits) + 1, GFP_KERNEL);
+       bits = kzalloc(sizeof(*bits) + 1, GFP_KERNEL);
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bits);
 
        /*
@@ -633,55 +717,34 @@ static void kasan_bitops(struct kunit *test)
         * below accesses are still out-of-bounds, since bitops are defined to
         * operate on the whole long the bit is in.
         */
-       KUNIT_EXPECT_KASAN_FAIL(test, set_bit(BITS_PER_LONG, bits));
-
-       KUNIT_EXPECT_KASAN_FAIL(test, __set_bit(BITS_PER_LONG, bits));
-
-       KUNIT_EXPECT_KASAN_FAIL(test, clear_bit(BITS_PER_LONG, bits));
-
-       KUNIT_EXPECT_KASAN_FAIL(test, __clear_bit(BITS_PER_LONG, bits));
-
-       KUNIT_EXPECT_KASAN_FAIL(test, clear_bit_unlock(BITS_PER_LONG, bits));
-
-       KUNIT_EXPECT_KASAN_FAIL(test, __clear_bit_unlock(BITS_PER_LONG, bits));
-
-       KUNIT_EXPECT_KASAN_FAIL(test, change_bit(BITS_PER_LONG, bits));
-
-       KUNIT_EXPECT_KASAN_FAIL(test, __change_bit(BITS_PER_LONG, bits));
+       kasan_bitops_modify(test, BITS_PER_LONG, bits);
 
        /*
         * Below calls try to access bit beyond allocated memory.
         */
-       KUNIT_EXPECT_KASAN_FAIL(test,
-               test_and_set_bit(BITS_PER_LONG + BITS_PER_BYTE, bits));
-
-       KUNIT_EXPECT_KASAN_FAIL(test,
-               __test_and_set_bit(BITS_PER_LONG + BITS_PER_BYTE, bits));
-
-       KUNIT_EXPECT_KASAN_FAIL(test,
-               test_and_set_bit_lock(BITS_PER_LONG + BITS_PER_BYTE, bits));
+       kasan_bitops_test_and_modify(test, BITS_PER_LONG + BITS_PER_BYTE, bits);
 
-       KUNIT_EXPECT_KASAN_FAIL(test,
-               test_and_clear_bit(BITS_PER_LONG + BITS_PER_BYTE, bits));
+       kfree(bits);
+}
 
-       KUNIT_EXPECT_KASAN_FAIL(test,
-               __test_and_clear_bit(BITS_PER_LONG + BITS_PER_BYTE, bits));
+static void kasan_bitops_tags(struct kunit *test)
+{
+       long *bits;
 
-       KUNIT_EXPECT_KASAN_FAIL(test,
-               test_and_change_bit(BITS_PER_LONG + BITS_PER_BYTE, bits));
+       /* This test is specifically crafted for the tag-based mode. */
+       if (IS_ENABLED(CONFIG_KASAN_GENERIC)) {
+               kunit_info(test, "CONFIG_KASAN_SW_TAGS required\n");
+               return;
+       }
 
-       KUNIT_EXPECT_KASAN_FAIL(test,
-               __test_and_change_bit(BITS_PER_LONG + BITS_PER_BYTE, bits));
+       /* Allocation size will be rounded to up granule size, which is 16. */
+       bits = kzalloc(sizeof(*bits), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bits);
 
-       KUNIT_EXPECT_KASAN_FAIL(test,
-               kasan_int_result =
-                       test_bit(BITS_PER_LONG + BITS_PER_BYTE, bits));
+       /* Do the accesses past the 16 allocated bytes. */
+       kasan_bitops_modify(test, BITS_PER_LONG, &bits[1]);
+       kasan_bitops_test_and_modify(test, BITS_PER_LONG + BITS_PER_BYTE, &bits[1]);
 
-#if defined(clear_bit_unlock_is_negative_byte)
-       KUNIT_EXPECT_KASAN_FAIL(test,
-               kasan_int_result = clear_bit_unlock_is_negative_byte(
-                       BITS_PER_LONG + BITS_PER_BYTE, bits));
-#endif
        kfree(bits);
 }
 
@@ -728,6 +791,7 @@ static struct kunit_case kasan_kunit_test_cases[] = {
        KUNIT_CASE(kmalloc_oob_krealloc_more),
        KUNIT_CASE(kmalloc_oob_krealloc_less),
        KUNIT_CASE(kmalloc_oob_16),
+       KUNIT_CASE(kmalloc_uaf_16),
        KUNIT_CASE(kmalloc_oob_in_memset),
        KUNIT_CASE(kmalloc_oob_memset_2),
        KUNIT_CASE(kmalloc_oob_memset_4),
@@ -751,7 +815,8 @@ static struct kunit_case kasan_kunit_test_cases[] = {
        KUNIT_CASE(kasan_memchr),
        KUNIT_CASE(kasan_memcmp),
        KUNIT_CASE(kasan_strings),
-       KUNIT_CASE(kasan_bitops),
+       KUNIT_CASE(kasan_bitops_generic),
+       KUNIT_CASE(kasan_bitops_tags),
        KUNIT_CASE(kmalloc_double_kzfree),
        KUNIT_CASE(vmalloc_oob),
        {}
index aa9ef23474df0234557a9799354c3d1d50dfdcad..db107016d29b32952efa5def52873176292ec720 100644 (file)
@@ -4,6 +4,7 @@
 #include "dfltcc_util.h"
 #include "dfltcc.h"
 #include <asm/setup.h>
+#include <linux/export.h>
 #include <linux/zutil.h>
 
 /*
@@ -29,6 +30,7 @@ int dfltcc_can_inflate(
     return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) &&
                is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0);
 }
+EXPORT_SYMBOL(dfltcc_can_inflate);
 
 static int dfltcc_was_inflate_used(
     z_streamp strm
@@ -147,3 +149,4 @@ dfltcc_inflate_action dfltcc_inflate(
     return (cc == DFLTCC_CC_OP1_TOO_SHORT || cc == DFLTCC_CC_OP2_TOO_SHORT) ?
         DFLTCC_INFLATE_BREAK : DFLTCC_INFLATE_CONTINUE;
 }
+EXPORT_SYMBOL(dfltcc_inflate);
index d42423f884a75639a4ac326c367ab6935fb89575..390165ffbb0fc2395a7460836eea971e0c0176f3 100644 (file)
@@ -707,19 +707,6 @@ config ZSMALLOC
          returned by an alloc().  This handle must be mapped in order to
          access the allocated space.
 
-config ZSMALLOC_PGTABLE_MAPPING
-       bool "Use page table mapping to access object in zsmalloc"
-       depends on ZSMALLOC=y
-       help
-         By default, zsmalloc uses a copy-based object mapping method to
-         access allocations that span two pages. However, if a particular
-         architecture (ex, ARM) performs VM mapping faster than copying,
-         then you should select this. This causes zsmalloc to use page table
-         mapping rather than copying for object mapping.
-
-         You can check speed with zsmalloc benchmark:
-         https://github.com/spartacus06/zsmapbench
-
 config ZSMALLOC_STAT
        bool "Export zsmalloc statistics"
        depends on ZSMALLOC
index 6e0ee5641788655ac0ce89a3bf6b1b46c5715f00..13cb7a961b319b11c83fb699a1d6e8e8d4b73e45 100644 (file)
@@ -817,6 +817,10 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
         * delay for some time until fewer pages are isolated
         */
        while (unlikely(too_many_isolated(pgdat))) {
+               /* stop isolation if there are still pages not migrated */
+               if (cc->nr_migratepages)
+                       return 0;
+
                /* async migration should just abort */
                if (cc->mode == MIGRATE_ASYNC)
                        return 0;
@@ -1012,8 +1016,8 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
 
 isolate_success:
                list_add(&page->lru, &cc->migratepages);
-               cc->nr_migratepages++;
-               nr_isolated++;
+               cc->nr_migratepages += compound_nr(page);
+               nr_isolated += compound_nr(page);
 
                /*
                 * Avoid isolating too much unless this block is being
@@ -1021,7 +1025,7 @@ isolate_success:
                 * or a lock is contended. For contention, isolate quickly to
                 * potentially remove one source of contention.
                 */
-               if (cc->nr_migratepages == COMPACT_CLUSTER_MAX &&
+               if (cc->nr_migratepages >= COMPACT_CLUSTER_MAX &&
                    !cc->rescan && !cc->contended) {
                        ++low_pfn;
                        break;
@@ -1132,7 +1136,7 @@ isolate_migratepages_range(struct compact_control *cc, unsigned long start_pfn,
                if (!pfn)
                        break;
 
-               if (cc->nr_migratepages == COMPACT_CLUSTER_MAX)
+               if (cc->nr_migratepages >= COMPACT_CLUSTER_MAX)
                        break;
        }
 
index d5e7c2029d16b4d8d8801d1058221b645904d5d7..331f4261d7237b7a451d7a9315f204519c4ea119 100644 (file)
@@ -827,7 +827,7 @@ int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask)
 }
 EXPORT_SYMBOL_GPL(replace_page_cache_page);
 
-noinline int __add_to_page_cache_locked(struct page *page,
+static noinline int __add_to_page_cache_locked(struct page *page,
                                        struct address_space *mapping,
                                        pgoff_t offset, gfp_t gfp,
                                        void **shadowp)
@@ -1484,11 +1484,19 @@ void end_page_writeback(struct page *page)
                rotate_reclaimable_page(page);
        }
 
+       /*
+        * Writeback does not hold a page reference of its own, relying
+        * on truncation to wait for the clearing of PG_writeback.
+        * But here we must make sure that the page is not freed and
+        * reused before the wake_up_page().
+        */
+       get_page(page);
        if (!test_clear_page_writeback(page))
                BUG();
 
        smp_mb__after_atomic();
        wake_up_page(page, PG_writeback);
+       put_page(page);
 }
 EXPORT_SYMBOL(end_page_writeback);
 
@@ -2347,10 +2355,15 @@ page_ok:
 
 page_not_up_to_date:
                /* Get exclusive access to the page ... */
-               if (iocb->ki_flags & IOCB_WAITQ)
+               if (iocb->ki_flags & IOCB_WAITQ) {
+                       if (written) {
+                               put_page(page);
+                               goto out;
+                       }
                        error = lock_page_async(page, iocb->ki_waitq);
-               else
+               } else {
                        error = lock_page_killable(page);
+               }
                if (unlikely(error))
                        goto readpage_error;
 
@@ -2393,10 +2406,15 @@ readpage:
                }
 
                if (!PageUptodate(page)) {
-                       if (iocb->ki_flags & IOCB_WAITQ)
+                       if (iocb->ki_flags & IOCB_WAITQ) {
+                               if (written) {
+                                       put_page(page);
+                                       goto out;
+                               }
                                error = lock_page_async(page, iocb->ki_waitq);
-                       else
+                       } else {
                                error = lock_page_killable(page);
+                       }
 
                        if (unlikely(error))
                                goto readpage_error;
index 102877ed77a4b42af7e0a625cfc4b79791494f95..98eb8e6d2609c32efec9a1fe21840149140354fa 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1647,8 +1647,11 @@ check_again:
                /*
                 * drop the above get_user_pages reference.
                 */
-               for (i = 0; i < nr_pages; i++)
-                       put_page(pages[i]);
+               if (gup_flags & FOLL_PIN)
+                       unpin_user_pages(pages, nr_pages);
+               else
+                       for (i = 0; i < nr_pages; i++)
+                               put_page(pages[i]);
 
                if (migrate_pages(&cma_page_list, alloc_migration_target, NULL,
                        (unsigned long)&mtc, MIGRATE_SYNC, MR_CONTIG_RANGE)) {
@@ -1728,8 +1731,11 @@ static long __gup_longterm_locked(struct mm_struct *mm,
                        goto out;
 
                if (check_dax_vmas(vmas_tmp, rc)) {
-                       for (i = 0; i < rc; i++)
-                               put_page(pages[i]);
+                       if (gup_flags & FOLL_PIN)
+                               unpin_user_pages(pages, rc);
+                       else
+                               for (i = 0; i < rc; i++)
+                                       put_page(pages[i]);
                        rc = -EOPNOTSUPP;
                        goto out;
                }
index 9474dbc150eddd8c668efea7f60a86ef26967bb0..ec2bb93f7431438aa4d3f9d44bd5b02c3279e6b9 100644 (file)
@@ -710,7 +710,6 @@ vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf)
                        transparent_hugepage_use_zero_page()) {
                pgtable_t pgtable;
                struct page *zero_page;
-               bool set;
                vm_fault_t ret;
                pgtable = pte_alloc_one(vma->vm_mm);
                if (unlikely(!pgtable))
@@ -723,25 +722,25 @@ vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf)
                }
                vmf->ptl = pmd_lock(vma->vm_mm, vmf->pmd);
                ret = 0;
-               set = false;
                if (pmd_none(*vmf->pmd)) {
                        ret = check_stable_address_space(vma->vm_mm);
                        if (ret) {
                                spin_unlock(vmf->ptl);
+                               pte_free(vma->vm_mm, pgtable);
                        } else if (userfaultfd_missing(vma)) {
                                spin_unlock(vmf->ptl);
+                               pte_free(vma->vm_mm, pgtable);
                                ret = handle_userfault(vmf, VM_UFFD_MISSING);
                                VM_BUG_ON(ret & VM_FAULT_FALLBACK);
                        } else {
                                set_huge_zero_page(pgtable, vma->vm_mm, vma,
                                                   haddr, vmf->pmd, zero_page);
                                spin_unlock(vmf->ptl);
-                               set = true;
                        }
-               } else
+               } else {
                        spin_unlock(vmf->ptl);
-               if (!set)
                        pte_free(vma->vm_mm, pgtable);
+               }
                return ret;
        }
        gfp = alloc_hugepage_direct_gfpmask(vma);
index fe76f8fd5a732c5f1301fab8600dd081cdc4498e..37f15c3c24dce351e7cba15847985a1f1415d456 100644 (file)
@@ -648,6 +648,8 @@ retry:
                        }
 
                        del += t - f;
+                       hugetlb_cgroup_uncharge_file_region(
+                               resv, rg, t - f);
 
                        /* New entry for end of split region */
                        nrg->from = t;
@@ -660,9 +662,6 @@ retry:
                        /* Original entry is trimmed */
                        rg->to = f;
 
-                       hugetlb_cgroup_uncharge_file_region(
-                               resv, rg, nrg->to - nrg->from);
-
                        list_add(&nrg->link, &rg->link);
                        nrg = NULL;
                        break;
@@ -678,17 +677,17 @@ retry:
                }
 
                if (f <= rg->from) {    /* Trim beginning of region */
-                       del += t - rg->from;
-                       rg->from = t;
-
                        hugetlb_cgroup_uncharge_file_region(resv, rg,
                                                            t - rg->from);
-               } else {                /* Trim end of region */
-                       del += rg->to - f;
-                       rg->to = f;
 
+                       del += t - rg->from;
+                       rg->from = t;
+               } else {                /* Trim end of region */
                        hugetlb_cgroup_uncharge_file_region(resv, rg,
                                                            rg->to - f);
+
+                       del += rg->to - f;
+                       rg->to = f;
                }
        }
 
@@ -1568,104 +1567,24 @@ int PageHeadHuge(struct page *page_head)
        return page_head[1].compound_dtor == HUGETLB_PAGE_DTOR;
 }
 
-/*
- * Find address_space associated with hugetlbfs page.
- * Upon entry page is locked and page 'was' mapped although mapped state
- * could change.  If necessary, use anon_vma to find vma and associated
- * address space.  The returned mapping may be stale, but it can not be
- * invalid as page lock (which is held) is required to destroy mapping.
- */
-static struct address_space *_get_hugetlb_page_mapping(struct page *hpage)
-{
-       struct anon_vma *anon_vma;
-       pgoff_t pgoff_start, pgoff_end;
-       struct anon_vma_chain *avc;
-       struct address_space *mapping = page_mapping(hpage);
-
-       /* Simple file based mapping */
-       if (mapping)
-               return mapping;
-
-       /*
-        * Even anonymous hugetlbfs mappings are associated with an
-        * underlying hugetlbfs file (see hugetlb_file_setup in mmap
-        * code).  Find a vma associated with the anonymous vma, and
-        * use the file pointer to get address_space.
-        */
-       anon_vma = page_lock_anon_vma_read(hpage);
-       if (!anon_vma)
-               return mapping;  /* NULL */
-
-       /* Use first found vma */
-       pgoff_start = page_to_pgoff(hpage);
-       pgoff_end = pgoff_start + pages_per_huge_page(page_hstate(hpage)) - 1;
-       anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root,
-                                       pgoff_start, pgoff_end) {
-               struct vm_area_struct *vma = avc->vma;
-
-               mapping = vma->vm_file->f_mapping;
-               break;
-       }
-
-       anon_vma_unlock_read(anon_vma);
-       return mapping;
-}
-
 /*
  * Find and lock address space (mapping) in write mode.
  *
- * Upon entry, the page is locked which allows us to find the mapping
- * even in the case of an anon page.  However, locking order dictates
- * the i_mmap_rwsem be acquired BEFORE the page lock.  This is hugetlbfs
- * specific.  So, we first try to lock the sema while still holding the
- * page lock.  If this works, great!  If not, then we need to drop the
- * page lock and then acquire i_mmap_rwsem and reacquire page lock.  Of
- * course, need to revalidate state along the way.
+ * Upon entry, the page is locked which means that page_mapping() is
+ * stable.  Due to locking order, we can only trylock_write.  If we can
+ * not get the lock, simply return NULL to caller.
  */
 struct address_space *hugetlb_page_mapping_lock_write(struct page *hpage)
 {
-       struct address_space *mapping, *mapping2;
+       struct address_space *mapping = page_mapping(hpage);
 
-       mapping = _get_hugetlb_page_mapping(hpage);
-retry:
        if (!mapping)
                return mapping;
 
-       /*
-        * If no contention, take lock and return
-        */
        if (i_mmap_trylock_write(mapping))
                return mapping;
 
-       /*
-        * Must drop page lock and wait on mapping sema.
-        * Note:  Once page lock is dropped, mapping could become invalid.
-        * As a hack, increase map count until we lock page again.
-        */
-       atomic_inc(&hpage->_mapcount);
-       unlock_page(hpage);
-       i_mmap_lock_write(mapping);
-       lock_page(hpage);
-       atomic_add_negative(-1, &hpage->_mapcount);
-
-       /* verify page is still mapped */
-       if (!page_mapped(hpage)) {
-               i_mmap_unlock_write(mapping);
-               return NULL;
-       }
-
-       /*
-        * Get address space again and verify it is the same one
-        * we locked.  If not, drop lock and retry.
-        */
-       mapping2 = _get_hugetlb_page_mapping(hpage);
-       if (mapping2 != mapping) {
-               i_mmap_unlock_write(mapping);
-               mapping = mapping2;
-               goto retry;
-       }
-
-       return mapping;
+       return NULL;
 }
 
 pgoff_t __basepage_index(struct page *page)
@@ -2443,6 +2362,9 @@ struct page *alloc_huge_page(struct vm_area_struct *vma,
 
                rsv_adjust = hugepage_subpool_put_pages(spool, 1);
                hugetlb_acct_memory(h, -rsv_adjust);
+               if (deferred_reserve)
+                       hugetlb_cgroup_uncharge_page_rsvd(hstate_index(h),
+                                       pages_per_huge_page(h), page);
        }
        return page;
 
index 1f87aec9ab5c77a1215714d8afd40d6829be6703..9182848dda3e06bca5fc2d12744ad37578ac9b3d 100644 (file)
@@ -82,11 +82,8 @@ static inline bool hugetlb_cgroup_have_usage(struct hugetlb_cgroup *h_cg)
 
        for (idx = 0; idx < hugetlb_max_hstate; idx++) {
                if (page_counter_read(
-                           hugetlb_cgroup_counter_from_cgroup(h_cg, idx)) ||
-                   page_counter_read(hugetlb_cgroup_counter_from_cgroup_rsvd(
-                           h_cg, idx))) {
+                               hugetlb_cgroup_counter_from_cgroup(h_cg, idx)))
                        return true;
-               }
        }
        return false;
 }
@@ -202,9 +199,10 @@ static void hugetlb_cgroup_css_offline(struct cgroup_subsys_state *css)
        struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(css);
        struct hstate *h;
        struct page *page;
-       int idx = 0;
+       int idx;
 
        do {
+               idx = 0;
                for_each_hstate(h) {
                        spin_lock(&hugetlb_lock);
                        list_for_each_entry(page, &h->hugepage_activelist, lru)
index 5aa6e44bc2ae57ccd6fce36265a1fc5fb1ff3d7f..fe230081690b4b67c0562d9aa6b0810ac992c773 100644 (file)
@@ -534,7 +534,6 @@ static void memcg_drain_list_lru_node(struct list_lru *lru, int nid,
        struct list_lru_node *nlru = &lru->node[nid];
        int dst_idx = dst_memcg->kmemcg_id;
        struct list_lru_one *src, *dst;
-       bool set;
 
        /*
         * Since list_lru_{add,del} may be called under an IRQ-safe lock,
@@ -546,11 +545,12 @@ static void memcg_drain_list_lru_node(struct list_lru *lru, int nid,
        dst = list_lru_from_memcg_idx(nlru, dst_idx);
 
        list_splice_init(&src->list, &dst->list);
-       set = (!dst->nr_items && src->nr_items);
-       dst->nr_items += src->nr_items;
-       if (set)
+
+       if (src->nr_items) {
+               dst->nr_items += src->nr_items;
                memcg_set_shrinker_bit(dst_memcg, nid, lru_shrinker_id(lru));
-       src->nr_items = 0;
+               src->nr_items = 0;
+       }
 
        spin_unlock_irq(&nlru->lock);
 }
index 416a56b8e757bf3465ab13cea51e0751ade2c745..a8d8d48a57fe968fe837f6432c90280ac9f35f15 100644 (file)
@@ -226,7 +226,7 @@ static void force_shm_swapin_readahead(struct vm_area_struct *vma,
                struct address_space *mapping)
 {
        XA_STATE(xas, &mapping->i_pages, linear_page_index(vma, start));
-       pgoff_t end_index = end / PAGE_SIZE;
+       pgoff_t end_index = linear_page_index(vma, end + PAGE_SIZE - 1);
        struct page *page;
 
        rcu_read_lock();
@@ -1231,8 +1231,6 @@ SYSCALL_DEFINE5(process_madvise, int, pidfd, const struct iovec __user *, vec,
                ret = total_len - iov_iter_count(&iter);
 
        mmput(mm);
-       return ret;
-
 release_task:
        put_task_struct(task);
 put_pid:
index 3a24e3b619f567efc5f0c5625974c0da854edcae..29459a6ce1c7ad06f00d9cc3873a4126fd1914cb 100644 (file)
@@ -867,8 +867,13 @@ void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val)
        rcu_read_lock();
        memcg = mem_cgroup_from_obj(p);
 
-       /* Untracked pages have no memcg, no lruvec. Update only the node */
-       if (!memcg || memcg == root_mem_cgroup) {
+       /*
+        * Untracked pages have no memcg, no lruvec. Update only the
+        * node. If we reparent the slab objects to the root memcg,
+        * when we free the slab object, we need to update the per-memcg
+        * vmstats to keep it correct for the root memcg.
+        */
+       if (!memcg) {
                __mod_node_page_state(pgdat, idx, val);
        } else {
                lruvec = mem_cgroup_lruvec(memcg, pgdat);
@@ -4110,11 +4115,17 @@ static int memcg_stat_show(struct seq_file *m, void *v)
                           (u64)memsw * PAGE_SIZE);
 
        for (i = 0; i < ARRAY_SIZE(memcg1_stats); i++) {
+               unsigned long nr;
+
                if (memcg1_stats[i] == MEMCG_SWAP && !do_memsw_account())
                        continue;
+               nr = memcg_page_state(memcg, memcg1_stats[i]);
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+               if (memcg1_stats[i] == NR_ANON_THPS)
+                       nr *= HPAGE_PMD_NR;
+#endif
                seq_printf(m, "total_%s %llu\n", memcg1_stat_names[i],
-                          (u64)memcg_page_state(memcg, memcg1_stats[i]) *
-                          PAGE_SIZE);
+                                               (u64)nr * PAGE_SIZE);
        }
 
        for (i = 0; i < ARRAY_SIZE(memcg1_events); i++)
@@ -5339,17 +5350,22 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
                memcg->swappiness = mem_cgroup_swappiness(parent);
                memcg->oom_kill_disable = parent->oom_kill_disable;
        }
-       if (parent && parent->use_hierarchy) {
+       if (!parent) {
+               page_counter_init(&memcg->memory, NULL);
+               page_counter_init(&memcg->swap, NULL);
+               page_counter_init(&memcg->kmem, NULL);
+               page_counter_init(&memcg->tcpmem, NULL);
+       } else if (parent->use_hierarchy) {
                memcg->use_hierarchy = true;
                page_counter_init(&memcg->memory, &parent->memory);
                page_counter_init(&memcg->swap, &parent->swap);
                page_counter_init(&memcg->kmem, &parent->kmem);
                page_counter_init(&memcg->tcpmem, &parent->tcpmem);
        } else {
-               page_counter_init(&memcg->memory, NULL);
-               page_counter_init(&memcg->swap, NULL);
-               page_counter_init(&memcg->kmem, NULL);
-               page_counter_init(&memcg->tcpmem, NULL);
+               page_counter_init(&memcg->memory, &root_mem_cgroup->memory);
+               page_counter_init(&memcg->swap, &root_mem_cgroup->swap);
+               page_counter_init(&memcg->kmem, &root_mem_cgroup->kmem);
+               page_counter_init(&memcg->tcpmem, &root_mem_cgroup->tcpmem);
                /*
                 * Deeper hierachy with use_hierarchy == false doesn't make
                 * much sense so let cgroup subsystem know about this
index c0bb186bba62eed80a8b2c1e7dd8e67579755063..5d880d4eb9a2678a557d7ad2c1d08358e65f0088 100644 (file)
@@ -1057,27 +1057,25 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
        if (!PageHuge(hpage)) {
                unmap_success = try_to_unmap(hpage, ttu);
        } else {
-               /*
-                * For hugetlb pages, try_to_unmap could potentially call
-                * huge_pmd_unshare.  Because of this, take semaphore in
-                * write mode here and set TTU_RMAP_LOCKED to indicate we
-                * have taken the lock at this higer level.
-                *
-                * Note that the call to hugetlb_page_mapping_lock_write
-                * is necessary even if mapping is already set.  It handles
-                * ugliness of potentially having to drop page lock to obtain
-                * i_mmap_rwsem.
-                */
-               mapping = hugetlb_page_mapping_lock_write(hpage);
-
-               if (mapping) {
-                       unmap_success = try_to_unmap(hpage,
+               if (!PageAnon(hpage)) {
+                       /*
+                        * For hugetlb pages in shared mappings, try_to_unmap
+                        * could potentially call huge_pmd_unshare.  Because of
+                        * this, take semaphore in write mode here and set
+                        * TTU_RMAP_LOCKED to indicate we have taken the lock
+                        * at this higer level.
+                        */
+                       mapping = hugetlb_page_mapping_lock_write(hpage);
+                       if (mapping) {
+                               unmap_success = try_to_unmap(hpage,
                                                     ttu|TTU_RMAP_LOCKED);
-                       i_mmap_unlock_write(mapping);
+                               i_mmap_unlock_write(mapping);
+                       } else {
+                               pr_info("Memory failure: %#lx: could not lock mapping for mapped huge page\n", pfn);
+                               unmap_success = false;
+                       }
                } else {
-                       pr_info("Memory failure: %#lx: could not find mapping for mapped huge page\n",
-                               pfn);
-                       unmap_success = false;
+                       unmap_success = try_to_unmap(hpage, ttu);
                }
        }
        if (!unmap_success)
index b44d4c7ba73b49ba5567db90beecc8dc924b5948..63b2e46b65552bb711afb92aa06b19c900122117 100644 (file)
@@ -350,24 +350,6 @@ int __ref __add_pages(int nid, unsigned long pfn, unsigned long nr_pages,
        return err;
 }
 
-#ifdef CONFIG_NUMA
-int __weak memory_add_physaddr_to_nid(u64 start)
-{
-       pr_info_once("Unknown online node for memory at 0x%llx, assuming node 0\n",
-                       start);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
-
-int __weak phys_to_target_node(u64 start)
-{
-       pr_info_once("Unknown target node for memory at 0x%llx, assuming node 0\n",
-                       start);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(phys_to_target_node);
-#endif
-
 /* find the smallest valid pfn in the range [start_pfn, end_pfn) */
 static unsigned long find_smallest_section_pfn(int nid, struct zone *zone,
                                     unsigned long start_pfn,
index 3fde772ef5ef5bdb297869844ef4f616ebd90bae..3ca4898f3f249f3e18bcf7ed4f3d49cfdf0ef439 100644 (file)
@@ -525,7 +525,7 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
        unsigned long flags = qp->flags;
        int ret;
        bool has_unmovable = false;
-       pte_t *pte;
+       pte_t *pte, *mapped_pte;
        spinlock_t *ptl;
 
        ptl = pmd_trans_huge_lock(pmd, vma);
@@ -539,7 +539,7 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
        if (pmd_trans_unstable(pmd))
                return 0;
 
-       pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
+       mapped_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
        for (; addr != end; pte++, addr += PAGE_SIZE) {
                if (!pte_present(*pte))
                        continue;
@@ -571,7 +571,7 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
                } else
                        break;
        }
-       pte_unmap_unlock(pte - 1, ptl);
+       pte_unmap_unlock(mapped_pte, ptl);
        cond_resched();
 
        if (has_unmovable)
index 73a206d0f64542e0f28a52da3b52ce3c7b4635ae..16b2fb482da11245092e732c858264ada92d2364 100644 (file)
@@ -41,28 +41,24 @@ EXPORT_SYMBOL_GPL(memremap_compat_align);
 DEFINE_STATIC_KEY_FALSE(devmap_managed_key);
 EXPORT_SYMBOL(devmap_managed_key);
 
-static void devmap_managed_enable_put(void)
+static void devmap_managed_enable_put(struct dev_pagemap *pgmap)
 {
-       static_branch_dec(&devmap_managed_key);
+       if (pgmap->type == MEMORY_DEVICE_PRIVATE ||
+           pgmap->type == MEMORY_DEVICE_FS_DAX)
+               static_branch_dec(&devmap_managed_key);
 }
 
-static int devmap_managed_enable_get(struct dev_pagemap *pgmap)
+static void devmap_managed_enable_get(struct dev_pagemap *pgmap)
 {
-       if (pgmap->type == MEMORY_DEVICE_PRIVATE &&
-           (!pgmap->ops || !pgmap->ops->page_free)) {
-               WARN(1, "Missing page_free method\n");
-               return -EINVAL;
-       }
-
-       static_branch_inc(&devmap_managed_key);
-       return 0;
+       if (pgmap->type == MEMORY_DEVICE_PRIVATE ||
+           pgmap->type == MEMORY_DEVICE_FS_DAX)
+               static_branch_inc(&devmap_managed_key);
 }
 #else
-static int devmap_managed_enable_get(struct dev_pagemap *pgmap)
+static void devmap_managed_enable_get(struct dev_pagemap *pgmap)
 {
-       return -EINVAL;
 }
-static void devmap_managed_enable_put(void)
+static void devmap_managed_enable_put(struct dev_pagemap *pgmap)
 {
 }
 #endif /* CONFIG_DEV_PAGEMAP_OPS */
@@ -169,7 +165,7 @@ void memunmap_pages(struct dev_pagemap *pgmap)
                pageunmap_range(pgmap, i);
 
        WARN_ONCE(pgmap->altmap.alloc, "failed to free all reserved pages\n");
-       devmap_managed_enable_put();
+       devmap_managed_enable_put(pgmap);
 }
 EXPORT_SYMBOL_GPL(memunmap_pages);
 
@@ -307,7 +303,6 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
                .pgprot = PAGE_KERNEL,
        };
        const int nr_range = pgmap->nr_range;
-       bool need_devmap_managed = true;
        int error, i;
 
        if (WARN_ONCE(!nr_range, "nr_range must be specified\n"))
@@ -323,6 +318,10 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
                        WARN(1, "Missing migrate_to_ram method\n");
                        return ERR_PTR(-EINVAL);
                }
+               if (!pgmap->ops->page_free) {
+                       WARN(1, "Missing page_free method\n");
+                       return ERR_PTR(-EINVAL);
+               }
                if (!pgmap->owner) {
                        WARN(1, "Missing owner\n");
                        return ERR_PTR(-EINVAL);
@@ -336,11 +335,9 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
                }
                break;
        case MEMORY_DEVICE_GENERIC:
-               need_devmap_managed = false;
                break;
        case MEMORY_DEVICE_PCI_P2PDMA:
                params.pgprot = pgprot_noncached(params.pgprot);
-               need_devmap_managed = false;
                break;
        default:
                WARN(1, "Invalid pgmap type %d\n", pgmap->type);
@@ -364,11 +361,7 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
                }
        }
 
-       if (need_devmap_managed) {
-               error = devmap_managed_enable_get(pgmap);
-               if (error)
-                       return ERR_PTR(error);
-       }
+       devmap_managed_enable_get(pgmap);
 
        /*
         * Clear the pgmap nr_range as it will be incremented for each
index 5ca5842df5db2586c07087245acfd760bc24e990..5795cb82e27c35ceb0df155165f91ef467ebcfbf 100644 (file)
@@ -1328,34 +1328,38 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
                goto put_anon;
 
        if (page_mapped(hpage)) {
-               /*
-                * try_to_unmap could potentially call huge_pmd_unshare.
-                * Because of this, take semaphore in write mode here and
-                * set TTU_RMAP_LOCKED to let lower levels know we have
-                * taken the lock.
-                */
-               mapping = hugetlb_page_mapping_lock_write(hpage);
-               if (unlikely(!mapping))
-                       goto unlock_put_anon;
+               bool mapping_locked = false;
+               enum ttu_flags ttu = TTU_MIGRATION|TTU_IGNORE_MLOCK|
+                                       TTU_IGNORE_ACCESS;
+
+               if (!PageAnon(hpage)) {
+                       /*
+                        * In shared mappings, try_to_unmap could potentially
+                        * call huge_pmd_unshare.  Because of this, take
+                        * semaphore in write mode here and set TTU_RMAP_LOCKED
+                        * to let lower levels know we have taken the lock.
+                        */
+                       mapping = hugetlb_page_mapping_lock_write(hpage);
+                       if (unlikely(!mapping))
+                               goto unlock_put_anon;
+
+                       mapping_locked = true;
+                       ttu |= TTU_RMAP_LOCKED;
+               }
 
-               try_to_unmap(hpage,
-                       TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS|
-                       TTU_RMAP_LOCKED);
+               try_to_unmap(hpage, ttu);
                page_was_mapped = 1;
-               /*
-                * Leave mapping locked until after subsequent call to
-                * remove_migration_ptes()
-                */
+
+               if (mapping_locked)
+                       i_mmap_unlock_write(mapping);
        }
 
        if (!page_mapped(hpage))
                rc = move_to_new_page(new_hpage, hpage, mode);
 
-       if (page_was_mapped) {
+       if (page_was_mapped)
                remove_migration_ptes(hpage,
-                       rc == MIGRATEPAGE_SUCCESS ? new_hpage : hpage, true);
-               i_mmap_unlock_write(mapping);
-       }
+                       rc == MIGRATEPAGE_SUCCESS ? new_hpage : hpage, false);
 
 unlock_put_anon:
        unlock_page(new_hpage);
index d91ecb00d38cd9733905d7f4fcaa8e2a6cfb222e..5c8b4485860de42ad69f056c7f67ad38e3ad58e6 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1808,6 +1808,17 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
                if (error)
                        goto unmap_and_free_vma;
 
+               /* Can addr have changed??
+                *
+                * Answer: Yes, several device drivers can do it in their
+                *         f_op->mmap method. -DaveM
+                * Bug: If addr is changed, prev, rb_link, rb_parent should
+                *      be updated for vma_link()
+                */
+               WARN_ON_ONCE(addr != vma->vm_start);
+
+               addr = vma->vm_start;
+
                /* If vm_flags changed after call_mmap(), we should try merge vma again
                 * as we may succeed this time.
                 */
@@ -1822,25 +1833,12 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
                                fput(vma->vm_file);
                                vm_area_free(vma);
                                vma = merge;
-                               /* Update vm_flags and possible addr to pick up the change. We don't
-                                * warn here if addr changed as the vma is not linked by vma_link().
-                                */
-                               addr = vma->vm_start;
+                               /* Update vm_flags to pick up the change. */
                                vm_flags = vma->vm_flags;
                                goto unmap_writable;
                        }
                }
 
-               /* Can addr have changed??
-                *
-                * Answer: Yes, several device drivers can do it in their
-                *         f_op->mmap method. -DaveM
-                * Bug: If addr is changed, prev, rb_link, rb_parent should
-                *      be updated for vma_link()
-                */
-               WARN_ON_ONCE(addr != vma->vm_start);
-
-               addr = vma->vm_start;
                vm_flags = vma->vm_flags;
        } else if (vm_flags & VM_SHARED) {
                error = shmem_zero_setup(vma);
index 7709f0e223f5d9457779f27d64803eb4f387d5bd..586042472ac9010e757d39e86d3283f55202951b 100644 (file)
@@ -2754,12 +2754,6 @@ int test_clear_page_writeback(struct page *page)
        } else {
                ret = TestClearPageWriteback(page);
        }
-       /*
-        * NOTE: Page might be free now! Writeback doesn't hold a page
-        * reference on its own, it relies on truncation to wait for
-        * the clearing of PG_writeback. The below can only access
-        * page state that is static across allocation cycles.
-        */
        if (ret) {
                dec_lruvec_state(lruvec, NR_WRITEBACK);
                dec_zone_page_state(page, NR_ZONE_WRITE_PENDING);
index 23f5066bd4a554087fea3952d8423003fd7cc304..eaa227a479e4a4324d4947168245bd3d0b03fdd0 100644 (file)
@@ -5103,6 +5103,11 @@ refill:
                if (!page_ref_sub_and_test(page, nc->pagecnt_bias))
                        goto refill;
 
+               if (unlikely(nc->pfmemalloc)) {
+                       free_the_page(page, compound_order(page));
+                       goto refill;
+               }
+
 #if (PAGE_SIZE < PAGE_FRAG_CACHE_MAX_SIZE)
                /* if size can vary use size else just use PAGE_SIZE */
                size = nc->size;
index 66a93f096394ab4accb21fa77867f55e702428b2..ad7a37ee74ef5f2ed8ead98c966a08f7d4e2384a 100644 (file)
@@ -1315,8 +1315,8 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(unsigned long tmp_addr,
        region_size = ALIGN(start_offset + map_size, lcm_align);
 
        /* allocate chunk */
-       alloc_size = sizeof(struct pcpu_chunk) +
-               BITS_TO_LONGS(region_size >> PAGE_SHIFT) * sizeof(unsigned long);
+       alloc_size = struct_size(chunk, populated,
+                                BITS_TO_LONGS(region_size >> PAGE_SHIFT));
        chunk = memblock_alloc(alloc_size, SMP_CACHE_BYTES);
        if (!chunk)
                panic("%s: Failed to allocate %zu bytes\n", __func__,
@@ -2521,8 +2521,8 @@ void __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
        pcpu_unit_pages = ai->unit_size >> PAGE_SHIFT;
        pcpu_unit_size = pcpu_unit_pages << PAGE_SHIFT;
        pcpu_atom_size = ai->atom_size;
-       pcpu_chunk_struct_size = sizeof(struct pcpu_chunk) +
-               BITS_TO_LONGS(pcpu_unit_pages) * sizeof(unsigned long);
+       pcpu_chunk_struct_size = struct_size(chunk, populated,
+                                            BITS_TO_LONGS(pcpu_unit_pages));
 
        pcpu_stats_save_ai(ai);
 
index fd12da80b6f27bab90763d9cca7c43d38f226b06..702250f148e73adc34a6d036c33cdaaedd46b924 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) 2010-2011 Christopher Yeoh <cyeoh@au1.ibm.com>, IBM Corp.
  */
 
+#include <linux/compat.h>
 #include <linux/mm.h>
 #include <linux/uio.h>
 #include <linux/sched.h>
@@ -273,7 +274,8 @@ static ssize_t process_vm_rw(pid_t pid,
                return rc;
        if (!iov_iter_count(&iter))
                goto free_iov_l;
-       iov_r = iovec_from_user(rvec, riovcnt, UIO_FASTIOV, iovstack_r, false);
+       iov_r = iovec_from_user(rvec, riovcnt, UIO_FASTIOV, iovstack_r,
+                               in_compat_syscall());
        if (IS_ERR(iov_r)) {
                rc = PTR_ERR(iov_r);
                goto free_iov_l;
index 1b84945d655c9732ae68296c1e5f513400f02a61..31b29321adfe1e3bd1b804ea2f0c910d47f52693 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1413,9 +1413,6 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
                /*
                 * If sharing is possible, start and end will be adjusted
                 * accordingly.
-                *
-                * If called for a huge page, caller must hold i_mmap_rwsem
-                * in write mode as it is possible to call huge_pmd_unshare.
                 */
                adjust_range_if_pmd_sharing_possible(vma, &range.start,
                                                     &range.end);
@@ -1462,7 +1459,7 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
                subpage = page - page_to_pfn(page) + pte_pfn(*pvmw.pte);
                address = pvmw.address;
 
-               if (PageHuge(page)) {
+               if (PageHuge(page) && !PageAnon(page)) {
                        /*
                         * To call huge_pmd_unshare, i_mmap_rwsem must be
                         * held in write mode.  Caller needs to explicitly
index 6d7c6a5056baac906432f3b65daf6f7297aedc99..f9977d6613d6189a204daf040a40e126194fb727 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -274,22 +274,32 @@ static inline size_t obj_full_size(struct kmem_cache *s)
        return s->size + sizeof(struct obj_cgroup *);
 }
 
-static inline struct obj_cgroup *memcg_slab_pre_alloc_hook(struct kmem_cache *s,
-                                                          size_t objects,
-                                                          gfp_t flags)
+/*
+ * Returns false if the allocation should fail.
+ */
+static inline bool memcg_slab_pre_alloc_hook(struct kmem_cache *s,
+                                            struct obj_cgroup **objcgp,
+                                            size_t objects, gfp_t flags)
 {
        struct obj_cgroup *objcg;
 
+       if (!memcg_kmem_enabled())
+               return true;
+
+       if (!(flags & __GFP_ACCOUNT) && !(s->flags & SLAB_ACCOUNT))
+               return true;
+
        objcg = get_obj_cgroup_from_current();
        if (!objcg)
-               return NULL;
+               return true;
 
        if (obj_cgroup_charge(objcg, flags, objects * obj_full_size(s))) {
                obj_cgroup_put(objcg);
-               return NULL;
+               return false;
        }
 
-       return objcg;
+       *objcgp = objcg;
+       return true;
 }
 
 static inline void mod_objcg_state(struct obj_cgroup *objcg,
@@ -315,7 +325,7 @@ static inline void memcg_slab_post_alloc_hook(struct kmem_cache *s,
        unsigned long off;
        size_t i;
 
-       if (!objcg)
+       if (!memcg_kmem_enabled() || !objcg)
                return;
 
        flags &= ~__GFP_ACCOUNT;
@@ -400,11 +410,11 @@ static inline void memcg_free_page_obj_cgroups(struct page *page)
 {
 }
 
-static inline struct obj_cgroup *memcg_slab_pre_alloc_hook(struct kmem_cache *s,
-                                                          size_t objects,
-                                                          gfp_t flags)
+static inline bool memcg_slab_pre_alloc_hook(struct kmem_cache *s,
+                                            struct obj_cgroup **objcgp,
+                                            size_t objects, gfp_t flags)
 {
-       return NULL;
+       return true;
 }
 
 static inline void memcg_slab_post_alloc_hook(struct kmem_cache *s,
@@ -508,9 +518,8 @@ static inline struct kmem_cache *slab_pre_alloc_hook(struct kmem_cache *s,
        if (should_failslab(s, flags))
                return NULL;
 
-       if (memcg_kmem_enabled() &&
-           ((flags & __GFP_ACCOUNT) || (s->flags & SLAB_ACCOUNT)))
-               *objcgp = memcg_slab_pre_alloc_hook(s, size, flags);
+       if (!memcg_slab_pre_alloc_hook(s, objcgp, size, flags))
+               return NULL;
 
        return s;
 }
@@ -529,8 +538,7 @@ static inline void slab_post_alloc_hook(struct kmem_cache *s,
                                         s->flags, flags);
        }
 
-       if (memcg_kmem_enabled())
-               memcg_slab_post_alloc_hook(s, objcg, flags, size, p);
+       memcg_slab_post_alloc_hook(s, objcg, flags, size, p);
 }
 
 #ifndef CONFIG_SLOB
index b30be2385d1cdeb80098985fec23d7b8223bd106..34dcc09e2ec9b0fb746942002d26c65a8be21a56 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2852,7 +2852,7 @@ redo:
 
        object = c->freelist;
        page = c->page;
-       if (unlikely(!object || !node_match(page, node))) {
+       if (unlikely(!object || !page || !node_match(page, node))) {
                object = __slab_alloc(s, gfpflags, node, addr, c);
        } else {
                void *next_object = get_freepointer_safe(s, object);
index c4a613688a175c4cc0e3d9c045e56a4bbb10fe79..d58361109066d67844bfbd64a41ebc33dd1bed7b 100644 (file)
@@ -2867,6 +2867,7 @@ late_initcall(max_swapfiles_check);
 static struct swap_info_struct *alloc_swap_info(void)
 {
        struct swap_info_struct *p;
+       struct swap_info_struct *defer = NULL;
        unsigned int type;
        int i;
 
@@ -2895,7 +2896,7 @@ static struct swap_info_struct *alloc_swap_info(void)
                smp_wmb();
                WRITE_ONCE(nr_swapfiles, nr_swapfiles + 1);
        } else {
-               kvfree(p);
+               defer = p;
                p = swap_info[type];
                /*
                 * Do not memset this entry: a racing procfs swap_next()
@@ -2908,6 +2909,7 @@ static struct swap_info_struct *alloc_swap_info(void)
                plist_node_init(&p->avail_lists[i], 0);
        p->flags = SWP_USED;
        spin_unlock(&swap_lock);
+       kvfree(defer);
        spin_lock_init(&p->lock);
        spin_lock_init(&p->cont_lock);
 
index 18cec39a9f53e48447e278785c2e6443f9357afa..960edf5803ca97fa22e94d65ff76be49b8d4be3b 100644 (file)
@@ -528,7 +528,7 @@ void truncate_inode_pages_final(struct address_space *mapping)
 }
 EXPORT_SYMBOL(truncate_inode_pages_final);
 
-unsigned long __invalidate_mapping_pages(struct address_space *mapping,
+static unsigned long __invalidate_mapping_pages(struct address_space *mapping,
                pgoff_t start, pgoff_t end, unsigned long *nr_pagevec)
 {
        pgoff_t indices[PAGEVEC_SIZE];
index 1b8f0e059767715deea0ba16125584ab4aa3ff20..7b4e31eac2cff1bfdb80fe9468df0db23e29336d 100644 (file)
@@ -1516,7 +1516,8 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
        nr_reclaimed = shrink_page_list(&clean_pages, zone->zone_pgdat, &sc,
                        TTU_IGNORE_ACCESS, &stat, true);
        list_splice(&clean_pages, page_list);
-       mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_FILE, -nr_reclaimed);
+       mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_FILE,
+                           -(long)nr_reclaimed);
        /*
         * Since lazyfree pages are isolated from file LRU from the beginning,
         * they will rotate back to anonymous LRU in the end if it failed to
@@ -1526,7 +1527,7 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
        mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_ANON,
                            stat.nr_lazyfree_fail);
        mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_FILE,
-                           -stat.nr_lazyfree_fail);
+                           -(long)stat.nr_lazyfree_fail);
        return nr_reclaimed;
 }
 
index 918c7b019b3d78a2cb8a1498c0fbc1ee0c5e11ca..cdfaaadea8ff7cf5d5c356dc41a7843bb6ea22a5 100644 (file)
@@ -293,11 +293,7 @@ struct zspage {
 };
 
 struct mapping_area {
-#ifdef CONFIG_ZSMALLOC_PGTABLE_MAPPING
-       struct vm_struct *vm; /* vm area for mapping object that span pages */
-#else
        char *vm_buf; /* copy buffer for objects that span pages */
-#endif
        char *vm_addr; /* address of kmap_atomic()'ed pages */
        enum zs_mapmode vm_mm; /* mapping mode */
 };
@@ -1113,54 +1109,6 @@ static struct zspage *find_get_zspage(struct size_class *class)
        return zspage;
 }
 
-#ifdef CONFIG_ZSMALLOC_PGTABLE_MAPPING
-static inline int __zs_cpu_up(struct mapping_area *area)
-{
-       /*
-        * Make sure we don't leak memory if a cpu UP notification
-        * and zs_init() race and both call zs_cpu_up() on the same cpu
-        */
-       if (area->vm)
-               return 0;
-       area->vm = get_vm_area(PAGE_SIZE * 2, 0);
-       if (!area->vm)
-               return -ENOMEM;
-
-       /*
-        * Populate ptes in advance to avoid pte allocation with GFP_KERNEL
-        * in non-preemtible context of zs_map_object.
-        */
-       return apply_to_page_range(&init_mm, (unsigned long)area->vm->addr,
-                       PAGE_SIZE * 2, NULL, NULL);
-}
-
-static inline void __zs_cpu_down(struct mapping_area *area)
-{
-       if (area->vm)
-               free_vm_area(area->vm);
-       area->vm = NULL;
-}
-
-static inline void *__zs_map_object(struct mapping_area *area,
-                               struct page *pages[2], int off, int size)
-{
-       unsigned long addr = (unsigned long)area->vm->addr;
-
-       BUG_ON(map_kernel_range(addr, PAGE_SIZE * 2, PAGE_KERNEL, pages) < 0);
-       area->vm_addr = area->vm->addr;
-       return area->vm_addr + off;
-}
-
-static inline void __zs_unmap_object(struct mapping_area *area,
-                               struct page *pages[2], int off, int size)
-{
-       unsigned long addr = (unsigned long)area->vm_addr;
-
-       unmap_kernel_range(addr, PAGE_SIZE * 2);
-}
-
-#else /* CONFIG_ZSMALLOC_PGTABLE_MAPPING */
-
 static inline int __zs_cpu_up(struct mapping_area *area)
 {
        /*
@@ -1241,8 +1189,6 @@ out:
        pagefault_enable();
 }
 
-#endif /* CONFIG_ZSMALLOC_PGTABLE_MAPPING */
-
 static int zs_cpu_prepare(unsigned int cpu)
 {
        struct mapping_area *area;
index dbabb65d8b6773acc95fc9047453ec0118da2ce1..7226c784dbe0c70e4d6899634cb3821ff5a61960 100644 (file)
@@ -954,9 +954,8 @@ static void *lec_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
        struct lec_state *state = seq->private;
 
-       v = lec_get_idx(state, 1);
-       *pos += !!PTR_ERR(v);
-       return v;
+       ++*pos;
+       return lec_get_idx(state, 1);
 }
 
 static int lec_seq_show(struct seq_file *seq, void *v)
index 9a47ef8b95c43d6bbe60c6223bd37e54749a100b..1f1f5b0873b29323cc26d2476f0c0c39b5e6e1c0 100644 (file)
@@ -391,6 +391,7 @@ out:
 
 /**
  * batadv_frag_create() - create a fragment from skb
+ * @net_dev: outgoing device for fragment
  * @skb: skb to create fragment from
  * @frag_head: header to use in new fragment
  * @fragment_size: size of new fragment
@@ -401,22 +402,25 @@ out:
  *
  * Return: the new fragment, NULL on error.
  */
-static struct sk_buff *batadv_frag_create(struct sk_buff *skb,
+static struct sk_buff *batadv_frag_create(struct net_device *net_dev,
+                                         struct sk_buff *skb,
                                          struct batadv_frag_packet *frag_head,
                                          unsigned int fragment_size)
 {
+       unsigned int ll_reserved = LL_RESERVED_SPACE(net_dev);
+       unsigned int tailroom = net_dev->needed_tailroom;
        struct sk_buff *skb_fragment;
        unsigned int header_size = sizeof(*frag_head);
        unsigned int mtu = fragment_size + header_size;
 
-       skb_fragment = netdev_alloc_skb(NULL, mtu + ETH_HLEN);
+       skb_fragment = dev_alloc_skb(ll_reserved + mtu + tailroom);
        if (!skb_fragment)
                goto err;
 
        skb_fragment->priority = skb->priority;
 
        /* Eat the last mtu-bytes of the skb */
-       skb_reserve(skb_fragment, header_size + ETH_HLEN);
+       skb_reserve(skb_fragment, ll_reserved + header_size);
        skb_split(skb, skb_fragment, skb->len - fragment_size);
 
        /* Add the header */
@@ -439,11 +443,12 @@ int batadv_frag_send_packet(struct sk_buff *skb,
                            struct batadv_orig_node *orig_node,
                            struct batadv_neigh_node *neigh_node)
 {
+       struct net_device *net_dev = neigh_node->if_incoming->net_dev;
        struct batadv_priv *bat_priv;
        struct batadv_hard_iface *primary_if = NULL;
        struct batadv_frag_packet frag_header;
        struct sk_buff *skb_fragment;
-       unsigned int mtu = neigh_node->if_incoming->net_dev->mtu;
+       unsigned int mtu = net_dev->mtu;
        unsigned int header_size = sizeof(frag_header);
        unsigned int max_fragment_size, num_fragments;
        int ret;
@@ -503,7 +508,7 @@ int batadv_frag_send_packet(struct sk_buff *skb,
                        goto put_primary_if;
                }
 
-               skb_fragment = batadv_frag_create(skb, &frag_header,
+               skb_fragment = batadv_frag_create(net_dev, skb, &frag_header,
                                                  max_fragment_size);
                if (!skb_fragment) {
                        ret = -ENOMEM;
@@ -522,13 +527,14 @@ int batadv_frag_send_packet(struct sk_buff *skb,
                frag_header.no++;
        }
 
-       /* Make room for the fragment header. */
-       if (batadv_skb_head_push(skb, header_size) < 0 ||
-           pskb_expand_head(skb, header_size + ETH_HLEN, 0, GFP_ATOMIC) < 0) {
-               ret = -ENOMEM;
+       /* make sure that there is at least enough head for the fragmentation
+        * and ethernet headers
+        */
+       ret = skb_cow_head(skb, ETH_HLEN + header_size);
+       if (ret < 0)
                goto put_primary_if;
-       }
 
+       skb_push(skb, header_size);
        memcpy(skb->data, &frag_header, header_size);
 
        /* Send the last fragment */
index dad99641df2a82d4235ad0bdba16110d8ca75663..33904595fc56a1e512edd5f217ff602f5a9744fe 100644 (file)
@@ -554,6 +554,9 @@ static void batadv_hardif_recalc_extra_skbroom(struct net_device *soft_iface)
        needed_headroom = lower_headroom + (lower_header_len - ETH_HLEN);
        needed_headroom += batadv_max_header_len();
 
+       /* fragmentation headers don't strip the unicast/... header */
+       needed_headroom += sizeof(struct batadv_frag_packet);
+
        soft_iface->needed_headroom = needed_headroom;
        soft_iface->needed_tailroom = lower_tailroom;
 }
index a67b2b09144785b07771c4a4ba7379f13cda4a71..c0ca5fbe5b0811bf8d84151b80a6be855df7ad05 100644 (file)
@@ -180,6 +180,7 @@ static const struct file_operations batadv_log_fops = {
        .read           = batadv_log_read,
        .poll           = batadv_log_poll,
        .llseek         = no_llseek,
+       .owner          = THIS_MODULE,
 };
 
 /**
index 8579bfeb283640a4c2a9f6154218d80c87d19660..4b39534a14a18cbd8f1a55d949a21aea20b45a01 100644 (file)
 struct msft_cp_read_supported_features {
        __u8   sub_opcode;
 } __packed;
+
 struct msft_rp_read_supported_features {
        __u8   status;
        __u8   sub_opcode;
        __le64 features;
        __u8   evt_prefix_len;
-       __u8   evt_prefix[0];
+       __u8   evt_prefix[];
 } __packed;
 
 struct msft_data {
index 6f742fee874ae1854a878ffa2df142c48b0db011..7730c8f3cb53adf57bba7a8df97e36c7c1f865e7 100644 (file)
@@ -207,6 +207,7 @@ static void br_get_stats64(struct net_device *dev,
 {
        struct net_bridge *br = netdev_priv(dev);
 
+       netdev_stats_to_stats64(stats, &dev->stats);
        dev_fetch_sw_netstats(stats, br->stats);
 }
 
index 04c3f9a82650d5a55fb3440ac88002f687ce5f92..8edfb98ae1d583665f5396b5110a3875e0518561 100644 (file)
@@ -735,6 +735,11 @@ static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff
        mtu_reserved = nf_bridge_mtu_reduction(skb);
        mtu = skb->dev->mtu;
 
+       if (nf_bridge->pkt_otherhost) {
+               skb->pkt_type = PACKET_OTHERHOST;
+               nf_bridge->pkt_otherhost = false;
+       }
+
        if (nf_bridge->frag_max_size && nf_bridge->frag_max_size < mtu)
                mtu = nf_bridge->frag_max_size;
 
@@ -835,8 +840,6 @@ static unsigned int br_nf_post_routing(void *priv,
        else
                return NF_ACCEPT;
 
-       /* We assume any code from br_dev_queue_push_xmit onwards doesn't care
-        * about the value of skb->pkt_type. */
        if (skb->pkt_type == PACKET_OTHERHOST) {
                skb->pkt_type = PACKET_HOST;
                nf_bridge->pkt_otherhost = true;
index 224e5e0283a986d9444948122479977d8107d1e9..7c9958df91d353c8a86dcd61a0c99e557fbfa16a 100644 (file)
@@ -62,8 +62,9 @@ config CAN_ISOTP
          communication between CAN nodes via two defined CAN Identifiers.
          As CAN frames can only transport a small amount of data bytes
          (max. 8 bytes for 'classic' CAN and max. 64 bytes for CAN FD) this
-         segmentation is needed to transport longer PDUs as needed e.g. for
-         vehicle diagnosis (UDS, ISO 14229) or IP-over-CAN traffic.
+         segmentation is needed to transport longer Protocol Data Units (PDU)
+         as needed e.g. for vehicle diagnosis (UDS, ISO 14229) or IP-over-CAN
+         traffic.
          This protocol driver implements data transfers according to
          ISO 15765-2:2016 for 'classic' CAN and CAN FD frame types.
          If you want to perform automotive vehicle diagnostic services (UDS),
index 6373ab9c5507c03f8eb127b00f1e404c9dfc15eb..4c343b43067f64d9fe5d62840216fdd09c3b1dc6 100644 (file)
@@ -541,10 +541,13 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,
 
        /* Check for bugs in CAN protocol implementations using af_can.c:
         * 'rcv' will be NULL if no matching list item was found for removal.
+        * As this case may potentially happen when closing a socket while
+        * the notifier for removing the CAN netdev is running we just print
+        * a warning here.
         */
        if (!rcv) {
-               WARN(1, "BUG: receive list entry not found for dev %s, id %03X, mask %03X\n",
-                    DNAME(dev), can_id, mask);
+               pr_warn("can: receive list entry not found for dev %s, id %03X, mask %03X\n",
+                       DNAME(dev), can_id, mask);
                goto out;
        }
 
@@ -677,16 +680,25 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
 {
        struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
 
-       if (unlikely(dev->type != ARPHRD_CAN || skb->len != CAN_MTU ||
-                    cfd->len > CAN_MAX_DLEN)) {
-               pr_warn_once("PF_CAN: dropped non conform CAN skbuf: dev type %d, len %d, datalen %d\n",
+       if (unlikely(dev->type != ARPHRD_CAN || skb->len != CAN_MTU)) {
+               pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d\n",
+                            dev->type, skb->len);
+               goto free_skb;
+       }
+
+       /* This check is made separately since cfd->len would be uninitialized if skb->len = 0. */
+       if (unlikely(cfd->len > CAN_MAX_DLEN)) {
+               pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d, datalen %d\n",
                             dev->type, skb->len, cfd->len);
-               kfree_skb(skb);
-               return NET_RX_DROP;
+               goto free_skb;
        }
 
        can_receive(skb, dev);
        return NET_RX_SUCCESS;
+
+free_skb:
+       kfree_skb(skb);
+       return NET_RX_DROP;
 }
 
 static int canfd_rcv(struct sk_buff *skb, struct net_device *dev,
@@ -694,16 +706,25 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev,
 {
        struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
 
-       if (unlikely(dev->type != ARPHRD_CAN || skb->len != CANFD_MTU ||
-                    cfd->len > CANFD_MAX_DLEN)) {
-               pr_warn_once("PF_CAN: dropped non conform CAN FD skbuf: dev type %d, len %d, datalen %d\n",
+       if (unlikely(dev->type != ARPHRD_CAN || skb->len != CANFD_MTU)) {
+               pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d\n",
+                            dev->type, skb->len);
+               goto free_skb;
+       }
+
+       /* This check is made separately since cfd->len would be uninitialized if skb->len = 0. */
+       if (unlikely(cfd->len > CANFD_MAX_DLEN)) {
+               pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d, datalen %d\n",
                             dev->type, skb->len, cfd->len);
-               kfree_skb(skb);
-               return NET_RX_DROP;
+               goto free_skb;
        }
 
        can_receive(skb, dev);
        return NET_RX_SUCCESS;
+
+free_skb:
+       kfree_skb(skb);
+       return NET_RX_DROP;
 }
 
 /* af_can protocol functions */
index 4c2062875893fd14c4c814bb8f787be75f6d1393..d78ab13bd8be99554a5d4873e4d6b7081cf289d3 100644 (file)
@@ -252,14 +252,16 @@ static void isotp_rcv_skb(struct sk_buff *skb, struct sock *sk)
 
 static u8 padlen(u8 datalen)
 {
-       const u8 plen[] = {8, 8, 8, 8, 8, 8, 8, 8, 8,           /* 0 - 8 */
-                          12, 12, 12, 12,                      /* 9 - 12 */
-                          16, 16, 16, 16,                      /* 13 - 16 */
-                          20, 20, 20, 20,                      /* 17 - 20 */
-                          24, 24, 24, 24,                      /* 21 - 24 */
-                          32, 32, 32, 32, 32, 32, 32, 32,      /* 25 - 32 */
-                          48, 48, 48, 48, 48, 48, 48, 48,      /* 33 - 40 */
-                          48, 48, 48, 48, 48, 48, 48, 48};     /* 41 - 48 */
+       static const u8 plen[] = {
+               8, 8, 8, 8, 8, 8, 8, 8, 8,      /* 0 - 8 */
+               12, 12, 12, 12,                 /* 9 - 12 */
+               16, 16, 16, 16,                 /* 13 - 16 */
+               20, 20, 20, 20,                 /* 17 - 20 */
+               24, 24, 24, 24,                 /* 21 - 24 */
+               32, 32, 32, 32, 32, 32, 32, 32, /* 25 - 32 */
+               48, 48, 48, 48, 48, 48, 48, 48, /* 33 - 40 */
+               48, 48, 48, 48, 48, 48, 48, 48  /* 41 - 48 */
+       };
 
        if (datalen > 48)
                return 64;
@@ -569,10 +571,6 @@ static int isotp_rcv_cf(struct sock *sk, struct canfd_frame *cf, int ae,
                return 0;
        }
 
-       /* no creation of flow control frames */
-       if (so->opt.flags & CAN_ISOTP_LISTEN_MODE)
-               return 0;
-
        /* perform blocksize handling, if enabled */
        if (!so->rxfc.bs || ++so->rx.bs < so->rxfc.bs) {
                /* start rx timeout watchdog */
@@ -581,6 +579,10 @@ static int isotp_rcv_cf(struct sock *sk, struct canfd_frame *cf, int ae,
                return 0;
        }
 
+       /* no creation of flow control frames */
+       if (so->opt.flags & CAN_ISOTP_LISTEN_MODE)
+               return 0;
+
        /* we reached the specified blocksize so->rxfc.bs */
        isotp_send_fc(sk, ae, ISOTP_FC_CTS);
        return 0;
index 1be4c898b2fa884b96c3363a1dca09279f541e89..f23966526a88589d95fdc97143c0c4f8f4b99860 100644 (file)
@@ -475,6 +475,12 @@ static int j1939_sk_bind(struct socket *sock, struct sockaddr *uaddr, int len)
                        goto out_release_sock;
                }
 
+               if (!(ndev->flags & IFF_UP)) {
+                       dev_put(ndev);
+                       ret = -ENETDOWN;
+                       goto out_release_sock;
+               }
+
                priv = j1939_netdev_start(ndev);
                dev_put(ndev);
                if (IS_ERR(priv)) {
index 550928b8b8a2c988270411ffdad80ab1f5b9dc03..5ea8695f507eb650cb51e0a81ccd27bb67683e18 100644 (file)
@@ -462,6 +462,9 @@ void can_init_proc(struct net *net)
  */
 void can_remove_proc(struct net *net)
 {
+       if (!net->can.proc_dir)
+               return;
+
        if (net->can.pde_stats)
                remove_proc_entry(CAN_PROC_STATS, net->can.proc_dir);
 
@@ -486,6 +489,5 @@ void can_remove_proc(struct net *net)
        if (net->can.pde_rcvlist_sff)
                remove_proc_entry(CAN_PROC_RCVLIST_SFF, net->can.proc_dir);
 
-       if (net->can.proc_dir)
-               remove_proc_entry("can", net->proc_net);
+       remove_proc_entry("can", net->proc_net);
 }
index 82dc6b48e45fdff2dd117e6ff23bccad480aa612..8588ade790cb77f565d1dc2e950a0a79ebb8d749 100644 (file)
@@ -4180,7 +4180,7 @@ int dev_queue_xmit_accel(struct sk_buff *skb, struct net_device *sb_dev)
 }
 EXPORT_SYMBOL(dev_queue_xmit_accel);
 
-int dev_direct_xmit(struct sk_buff *skb, u16 queue_id)
+int __dev_direct_xmit(struct sk_buff *skb, u16 queue_id)
 {
        struct net_device *dev = skb->dev;
        struct sk_buff *orig_skb = skb;
@@ -4210,17 +4210,13 @@ int dev_direct_xmit(struct sk_buff *skb, u16 queue_id)
        dev_xmit_recursion_dec();
 
        local_bh_enable();
-
-       if (!dev_xmit_complete(ret))
-               kfree_skb(skb);
-
        return ret;
 drop:
        atomic_long_inc(&dev->tx_dropped);
        kfree_skb_list(skb);
        return NET_XMIT_DROP;
 }
-EXPORT_SYMBOL(dev_direct_xmit);
+EXPORT_SYMBOL(__dev_direct_xmit);
 
 /*************************************************************************
  *                     Receiver routines
index a578634052a3c77366bee7922e8fd16eee564ec7..8c5ddffd707defd66da8c7b6cda530c61a37196d 100644 (file)
@@ -517,7 +517,7 @@ devlink_reload_limit_is_supported(struct devlink *devlink, enum devlink_reload_l
        return test_bit(limit, &devlink->ops->reload_limits);
 }
 
-static int devlink_reload_stat_put(struct sk_buff *msg, enum devlink_reload_action action,
+static int devlink_reload_stat_put(struct sk_buff *msg,
                                   enum devlink_reload_limit limit, u32 value)
 {
        struct nlattr *reload_stats_entry;
@@ -526,8 +526,7 @@ static int devlink_reload_stat_put(struct sk_buff *msg, enum devlink_reload_acti
        if (!reload_stats_entry)
                return -EMSGSIZE;
 
-       if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_ACTION, action) ||
-           nla_put_u8(msg, DEVLINK_ATTR_RELOAD_STATS_LIMIT, limit) ||
+       if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_STATS_LIMIT, limit) ||
            nla_put_u32(msg, DEVLINK_ATTR_RELOAD_STATS_VALUE, value))
                goto nla_put_failure;
        nla_nest_end(msg, reload_stats_entry);
@@ -540,7 +539,7 @@ nla_put_failure:
 
 static int devlink_reload_stats_put(struct sk_buff *msg, struct devlink *devlink, bool is_remote)
 {
-       struct nlattr *reload_stats_attr;
+       struct nlattr *reload_stats_attr, *act_info, *act_stats;
        int i, j, stat_idx;
        u32 value;
 
@@ -552,17 +551,29 @@ static int devlink_reload_stats_put(struct sk_buff *msg, struct devlink *devlink
        if (!reload_stats_attr)
                return -EMSGSIZE;
 
-       for (j = 0; j <= DEVLINK_RELOAD_LIMIT_MAX; j++) {
-               /* Remote stats are shown even if not locally supported. Stats
-                * of actions with unspecified limit are shown though drivers
-                * don't need to register unspecified limit.
-                */
-               if (!is_remote && j != DEVLINK_RELOAD_LIMIT_UNSPEC &&
-                   !devlink_reload_limit_is_supported(devlink, j))
+       for (i = 0; i <= DEVLINK_RELOAD_ACTION_MAX; i++) {
+               if ((!is_remote &&
+                    !devlink_reload_action_is_supported(devlink, i)) ||
+                   i == DEVLINK_RELOAD_ACTION_UNSPEC)
                        continue;
-               for (i = 0; i <= DEVLINK_RELOAD_ACTION_MAX; i++) {
-                       if ((!is_remote && !devlink_reload_action_is_supported(devlink, i)) ||
-                           i == DEVLINK_RELOAD_ACTION_UNSPEC ||
+               act_info = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_ACTION_INFO);
+               if (!act_info)
+                       goto nla_put_failure;
+
+               if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_ACTION, i))
+                       goto action_info_nest_cancel;
+               act_stats = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_ACTION_STATS);
+               if (!act_stats)
+                       goto action_info_nest_cancel;
+
+               for (j = 0; j <= DEVLINK_RELOAD_LIMIT_MAX; j++) {
+                       /* Remote stats are shown even if not locally supported.
+                        * Stats of actions with unspecified limit are shown
+                        * though drivers don't need to register unspecified
+                        * limit.
+                        */
+                       if ((!is_remote && j != DEVLINK_RELOAD_LIMIT_UNSPEC &&
+                            !devlink_reload_limit_is_supported(devlink, j)) ||
                            devlink_reload_combination_is_invalid(i, j))
                                continue;
 
@@ -571,13 +582,19 @@ static int devlink_reload_stats_put(struct sk_buff *msg, struct devlink *devlink
                                value = devlink->stats.reload_stats[stat_idx];
                        else
                                value = devlink->stats.remote_reload_stats[stat_idx];
-                       if (devlink_reload_stat_put(msg, i, j, value))
-                               goto nla_put_failure;
+                       if (devlink_reload_stat_put(msg, j, value))
+                               goto action_stats_nest_cancel;
                }
+               nla_nest_end(msg, act_stats);
+               nla_nest_end(msg, act_info);
        }
        nla_nest_end(msg, reload_stats_attr);
        return 0;
 
+action_stats_nest_cancel:
+       nla_nest_cancel(msg, act_stats);
+action_info_nest_cancel:
+       nla_nest_cancel(msg, act_info);
 nla_put_failure:
        nla_nest_cancel(msg, reload_stats_attr);
        return -EMSGSIZE;
@@ -755,6 +772,8 @@ static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
        if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
                goto nla_put_failure;
 
+       /* Hold rtnl lock while accessing port's netdev attributes. */
+       rtnl_lock();
        spin_lock_bh(&devlink_port->type_lock);
        if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
                goto nla_put_failure_type_locked;
@@ -763,9 +782,10 @@ static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
                        devlink_port->desired_type))
                goto nla_put_failure_type_locked;
        if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) {
+               struct net *net = devlink_net(devlink_port->devlink);
                struct net_device *netdev = devlink_port->type_dev;
 
-               if (netdev &&
+               if (netdev && net_eq(net, dev_net(netdev)) &&
                    (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX,
                                 netdev->ifindex) ||
                     nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME,
@@ -781,6 +801,7 @@ static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
                        goto nla_put_failure_type_locked;
        }
        spin_unlock_bh(&devlink_port->type_lock);
+       rtnl_unlock();
        if (devlink_nl_port_attrs_put(msg, devlink_port))
                goto nla_put_failure;
        if (devlink_nl_port_function_attrs_put(msg, devlink_port, extack))
@@ -791,6 +812,7 @@ static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
 
 nla_put_failure_type_locked:
        spin_unlock_bh(&devlink_port->type_lock);
+       rtnl_unlock();
 nla_put_failure:
        genlmsg_cancel(msg, hdr);
        return -EMSGSIZE;
@@ -1448,7 +1470,7 @@ static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
                err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index,
                                                pool_index, &cur, &max);
                if (err && err != -EOPNOTSUPP)
-                       return err;
+                       goto sb_occ_get_failure;
                if (!err) {
                        if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
                                goto nla_put_failure;
@@ -1461,8 +1483,10 @@ static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
        return 0;
 
 nla_put_failure:
+       err = -EMSGSIZE;
+sb_occ_get_failure:
        genlmsg_cancel(msg, hdr);
-       return -EMSGSIZE;
+       return err;
 }
 
 static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb,
@@ -4213,10 +4237,12 @@ static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink,
        if (err)
                goto nla_put_failure;
 
-       if (region->port)
-               if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
-                               region->port->index))
+       if (region->port) {
+               err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
+                                 region->port->index);
+               if (err)
                        goto nla_put_failure;
+       }
 
        err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->ops->name);
        if (err)
@@ -4265,10 +4291,12 @@ devlink_nl_region_notify_build(struct devlink_region *region,
        if (err)
                goto out_cancel_msg;
 
-       if (region->port)
-               if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
-                               region->port->index))
+       if (region->port) {
+               err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
+                                 region->port->index);
+               if (err)
                        goto out_cancel_msg;
+       }
 
        err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
                             region->ops->name);
@@ -4915,8 +4943,10 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
                index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
 
                port = devlink_port_get_by_index(devlink, index);
-               if (!port)
-                       return -ENODEV;
+               if (!port) {
+                       err = -ENODEV;
+                       goto out_unlock;
+               }
        }
 
        region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]);
@@ -4962,10 +4992,12 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
        if (err)
                goto nla_put_failure;
 
-       if (region->port)
-               if (nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX,
-                               region->port->index))
+       if (region->port) {
+               err = nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX,
+                                 region->port->index);
+               if (err)
                        goto nla_put_failure;
+       }
 
        err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
        if (err)
@@ -8246,8 +8278,6 @@ static int __devlink_port_attrs_set(struct devlink_port *devlink_port,
 {
        struct devlink_port_attrs *attrs = &devlink_port->attrs;
 
-       if (WARN_ON(devlink_port->registered))
-               return -EEXIST;
        devlink_port->attrs_set = true;
        attrs->flavour = flavour;
        if (attrs->switch_id.id_len) {
@@ -8271,6 +8301,8 @@ void devlink_port_attrs_set(struct devlink_port *devlink_port,
 {
        int ret;
 
+       if (WARN_ON(devlink_port->registered))
+               return;
        devlink_port->attrs = *attrs;
        ret = __devlink_port_attrs_set(devlink_port, attrs->flavour);
        if (ret)
@@ -8293,6 +8325,8 @@ void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u32 contro
        struct devlink_port_attrs *attrs = &devlink_port->attrs;
        int ret;
 
+       if (WARN_ON(devlink_port->registered))
+               return;
        ret = __devlink_port_attrs_set(devlink_port,
                                       DEVLINK_PORT_FLAVOUR_PCI_PF);
        if (ret)
@@ -8318,6 +8352,8 @@ void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u32 contro
        struct devlink_port_attrs *attrs = &devlink_port->attrs;
        int ret;
 
+       if (WARN_ON(devlink_port->registered))
+               return;
        ret = __devlink_port_attrs_set(devlink_port,
                                       DEVLINK_PORT_FLAVOUR_PCI_VF);
        if (ret)
index e095fb871d9120787bfdf62149f4d82e0e3b0a51..6eb2e5ec2c5068e1d798557e55d084b785187a9b 100644 (file)
@@ -99,9 +99,14 @@ void gro_cells_destroy(struct gro_cells *gcells)
                struct gro_cell *cell = per_cpu_ptr(gcells->cells, i);
 
                napi_disable(&cell->napi);
-               netif_napi_del(&cell->napi);
+               __netif_napi_del(&cell->napi);
                __skb_queue_purge(&cell->napi_skbs);
        }
+       /* This barrier is needed because netpoll could access dev->napi_list
+        * under rcu protection.
+        */
+       synchronize_net();
+
        free_percpu(gcells->cells);
        gcells->cells = NULL;
 }
index 8e39e28b0a8dd8965c865cfc6d96522904b19a53..9500d28a43b0e1a390382912b6fb59db935e727b 100644 (file)
@@ -235,6 +235,8 @@ static int neigh_forced_gc(struct neigh_table *tbl)
 
                        write_lock(&n->lock);
                        if ((n->nud_state == NUD_FAILED) ||
+                           (tbl->is_multicast &&
+                            tbl->is_multicast(n->primary_key)) ||
                            time_after(tref, n->updated))
                                remove = true;
                        write_unlock(&n->lock);
index c310c7c1cef7f21538d248926aab6303cecf68b0..960948290001eed4d07a8d20327e9158659adc45 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/export.h>
 #include <linux/if_vlan.h>
+#include <net/dsa.h>
 #include <net/tcp.h>
 #include <net/udp.h>
 #include <net/addrconf.h>
@@ -657,15 +658,15 @@ EXPORT_SYMBOL_GPL(__netpoll_setup);
 
 int netpoll_setup(struct netpoll *np)
 {
-       struct net_device *ndev = NULL;
+       struct net_device *ndev = NULL, *dev = NULL;
+       struct net *net = current->nsproxy->net_ns;
        struct in_device *in_dev;
        int err;
 
        rtnl_lock();
-       if (np->dev_name[0]) {
-               struct net *net = current->nsproxy->net_ns;
+       if (np->dev_name[0])
                ndev = __dev_get_by_name(net, np->dev_name);
-       }
+
        if (!ndev) {
                np_err(np, "%s doesn't exist, aborting\n", np->dev_name);
                err = -ENODEV;
@@ -673,6 +674,19 @@ int netpoll_setup(struct netpoll *np)
        }
        dev_hold(ndev);
 
+       /* bring up DSA management network devices up first */
+       for_each_netdev(net, dev) {
+               if (!netdev_uses_dsa(dev))
+                       continue;
+
+               err = dev_change_flags(dev, dev->flags | IFF_UP, NULL);
+               if (err < 0) {
+                       np_err(np, "%s failed to open %s\n",
+                              np->dev_name, dev->name);
+                       goto put;
+               }
+       }
+
        if (netdev_master_upper_dev_get(ndev)) {
                np_err(np, "%s is a slave device, aborting\n", np->dev_name);
                err = -EBUSY;
index 1ba8f01637441f868e19077c56d420573be7b6e9..e578544b2cc7110ec2f6bcf4c29d93e4b4b1ad14 100644 (file)
@@ -4549,7 +4549,7 @@ struct sk_buff *sock_dequeue_err_skb(struct sock *sk)
        if (skb && (skb_next = skb_peek(q))) {
                icmp_next = is_icmp_err_skb(skb_next);
                if (icmp_next)
-                       sk->sk_err = SKB_EXT_ERR(skb_next)->ee.ee_origin;
+                       sk->sk_err = SKB_EXT_ERR(skb_next)->ee.ee_errno;
        }
        spin_unlock_irqrestore(&q->lock, flags);
 
@@ -5786,6 +5786,9 @@ int skb_mpls_dec_ttl(struct sk_buff *skb)
        if (unlikely(!eth_p_mpls(skb->protocol)))
                return -EINVAL;
 
+       if (!pskb_may_pull(skb, skb_network_offset(skb) + MPLS_HLEN))
+               return -ENOMEM;
+
        lse = be32_to_cpu(mpls_hdr(skb)->label_stack_entry);
        ttl = (lse & MPLS_LS_TTL_MASK) >> MPLS_LS_TTL_SHIFT;
        if (!--ttl)
index 654182ecf87b709ad5e5440ff7157fcb94d2ebae..25cdbb20f3a037e3c9f324a41449034001f3b48d 100644 (file)
@@ -170,10 +170,12 @@ static int sk_msg_free_elem(struct sock *sk, struct sk_msg *msg, u32 i,
        struct scatterlist *sge = sk_msg_elem(msg, i);
        u32 len = sge->length;
 
-       if (charge)
-               sk_mem_uncharge(sk, len);
-       if (!msg->skb)
+       /* When the skb owns the memory we free it from consume_skb path. */
+       if (!msg->skb) {
+               if (charge)
+                       sk_mem_uncharge(sk, len);
                put_page(sg_page(sge));
+       }
        memset(sge, 0, sizeof(*sge));
        return len;
 }
@@ -397,28 +399,45 @@ out:
 }
 EXPORT_SYMBOL_GPL(sk_msg_memcopy_from_iter);
 
-static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb)
+static struct sk_msg *sk_psock_create_ingress_msg(struct sock *sk,
+                                                 struct sk_buff *skb)
 {
-       struct sock *sk = psock->sk;
-       int copied = 0, num_sge;
        struct sk_msg *msg;
 
+       if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf)
+               return NULL;
+
+       if (!sk_rmem_schedule(sk, skb, skb->truesize))
+               return NULL;
+
        msg = kzalloc(sizeof(*msg), __GFP_NOWARN | GFP_ATOMIC);
        if (unlikely(!msg))
-               return -EAGAIN;
-       if (!sk_rmem_schedule(sk, skb, skb->len)) {
-               kfree(msg);
-               return -EAGAIN;
-       }
+               return NULL;
 
        sk_msg_init(msg);
+       return msg;
+}
+
+static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,
+                                       struct sk_psock *psock,
+                                       struct sock *sk,
+                                       struct sk_msg *msg)
+{
+       int num_sge, copied;
+
+       /* skb linearize may fail with ENOMEM, but lets simply try again
+        * later if this happens. Under memory pressure we don't want to
+        * drop the skb. We need to linearize the skb so that the mapping
+        * in skb_to_sgvec can not error.
+        */
+       if (skb_linearize(skb))
+               return -EAGAIN;
        num_sge = skb_to_sgvec(skb, msg->sg.data, 0, skb->len);
        if (unlikely(num_sge < 0)) {
                kfree(msg);
                return num_sge;
        }
 
-       sk_mem_charge(sk, skb->len);
        copied = skb->len;
        msg->sg.start = 0;
        msg->sg.size = copied;
@@ -430,6 +449,48 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb)
        return copied;
 }
 
+static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb);
+
+static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb)
+{
+       struct sock *sk = psock->sk;
+       struct sk_msg *msg;
+
+       /* If we are receiving on the same sock skb->sk is already assigned,
+        * skip memory accounting and owner transition seeing it already set
+        * correctly.
+        */
+       if (unlikely(skb->sk == sk))
+               return sk_psock_skb_ingress_self(psock, skb);
+       msg = sk_psock_create_ingress_msg(sk, skb);
+       if (!msg)
+               return -EAGAIN;
+
+       /* This will transition ownership of the data from the socket where
+        * the BPF program was run initiating the redirect to the socket
+        * we will eventually receive this data on. The data will be released
+        * from skb_consume found in __tcp_bpf_recvmsg() after its been copied
+        * into user buffers.
+        */
+       skb_set_owner_r(skb, sk);
+       return sk_psock_skb_ingress_enqueue(skb, psock, sk, msg);
+}
+
+/* Puts an skb on the ingress queue of the socket already assigned to the
+ * skb. In this case we do not need to check memory limits or skb_set_owner_r
+ * because the skb is already accounted for here.
+ */
+static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb)
+{
+       struct sk_msg *msg = kzalloc(sizeof(*msg), __GFP_NOWARN | GFP_ATOMIC);
+       struct sock *sk = psock->sk;
+
+       if (unlikely(!msg))
+               return -EAGAIN;
+       sk_msg_init(msg);
+       return sk_psock_skb_ingress_enqueue(skb, psock, sk, msg);
+}
+
 static int sk_psock_handle_skb(struct sk_psock *psock, struct sk_buff *skb,
                               u32 off, u32 len, bool ingress)
 {
@@ -789,7 +850,7 @@ static void sk_psock_verdict_apply(struct sk_psock *psock,
                 * retrying later from workqueue.
                 */
                if (skb_queue_empty(&psock->ingress_skb)) {
-                       err = sk_psock_skb_ingress(psock, skb);
+                       err = sk_psock_skb_ingress_self(psock, skb);
                }
                if (err < 0) {
                        skb_queue_tail(&psock->ingress_skb, skb);
index bb3d70664dde0521091147bc40baf546b2b80c94..b0b6e6a4784e5f503bd6e34dbd650d15129ec7cf 100644 (file)
@@ -427,7 +427,7 @@ struct sock *dccp_v4_request_recv_sock(const struct sock *sk,
 
        if (__inet_inherit_port(sk, newsk) < 0)
                goto put_and_exit;
-       *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash));
+       *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash), NULL);
        if (*own_req)
                ireq->ireq_opt = NULL;
        else
index ef4ab28cfde0e3c1ce9c18550599c7b00bb6de8d..78ee1b5acf1f1c18289817f1771588c892c41166 100644 (file)
@@ -533,7 +533,7 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
                dccp_done(newsk);
                goto out;
        }
-       *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash));
+       *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash), NULL);
        /* Clone pktoptions received with SYN, if we own the req */
        if (*own_req && ireq->pktopts) {
                newnp->pktoptions = skb_clone(ireq->pktopts, GFP_ATOMIC);
index 8ee4cdbd6b82f130ff97b7ca8f3ba043b12c3d83..1c9f4df273bd55287aa08e5da82c32f1bc96a1ed 100644 (file)
@@ -280,7 +280,7 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)
                                          active_diff_mask, compact);
        }
        if (mod)
-               ethtool_notify(dev, ETHTOOL_MSG_FEATURES_NTF, NULL);
+               netdev_features_change(dev);
 
 out_rtnl:
        rtnl_unlock();
index 687971d83b4e760d16f328d65a0ba2e36b6c0dbc..922dd73e57406e95f000be2a76fcc8de27bd06d0 100644 (file)
@@ -125,6 +125,7 @@ static int arp_constructor(struct neighbour *neigh);
 static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb);
 static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb);
 static void parp_redo(struct sk_buff *skb);
+static int arp_is_multicast(const void *pkey);
 
 static const struct neigh_ops arp_generic_ops = {
        .family =               AF_INET,
@@ -156,6 +157,7 @@ struct neigh_table arp_tbl = {
        .key_eq         = arp_key_eq,
        .constructor    = arp_constructor,
        .proxy_redo     = parp_redo,
+       .is_multicast   = arp_is_multicast,
        .id             = "arp_cache",
        .parms          = {
                .tbl                    = &arp_tbl,
@@ -928,6 +930,10 @@ static void parp_redo(struct sk_buff *skb)
        arp_process(dev_net(skb->dev), NULL, skb);
 }
 
+static int arp_is_multicast(const void *pkey)
+{
+       return ipv4_is_multicast(*((__be32 *)pkey));
+}
 
 /*
  *     Receive an arp request from the device layer.
index 86a23e4a6a50ffce36e5ac1849361f4dd91e6eac..b87140a1fa284f37ce5bc7f0f3d1fbd0414e7a88 100644 (file)
@@ -696,7 +696,7 @@ int fib_gw_from_via(struct fib_config *cfg, struct nlattr *nla,
                cfg->fc_gw4 = *((__be32 *)via->rtvia_addr);
                break;
        case AF_INET6:
-#ifdef CONFIG_IPV6
+#if IS_ENABLED(CONFIG_IPV6)
                if (alen != sizeof(struct in6_addr)) {
                        NL_SET_ERR_MSG(extack, "Invalid IPv6 address in RTA_VIA");
                        return -EINVAL;
index 4148f5f78f313cde1e0596b9eb3696df16e3f990..f60869acbef0291b08e5cd27ea47a51b4fdefa05 100644 (file)
@@ -787,7 +787,7 @@ static void reqsk_queue_hash_req(struct request_sock *req,
        timer_setup(&req->rsk_timer, reqsk_timer_handler, TIMER_PINNED);
        mod_timer(&req->rsk_timer, jiffies + timeout);
 
-       inet_ehash_insert(req_to_sk(req), NULL);
+       inet_ehash_insert(req_to_sk(req), NULL, NULL);
        /* before letting lookups find us, make sure all req fields
         * are committed to memory and refcnt initialized.
         */
index 366a4507b5a3188bddbdc86a286b4d4a6c59d0ef..93474b1bea4e002e4fc2aefc3d311b0445961cf7 100644 (file)
@@ -479,8 +479,10 @@ static int inet_req_diag_fill(struct sock *sk, struct sk_buff *skb,
        r->idiag_inode  = 0;
 
        if (net_admin && nla_put_u32(skb, INET_DIAG_MARK,
-                                    inet_rsk(reqsk)->ir_mark))
+                                    inet_rsk(reqsk)->ir_mark)) {
+               nlmsg_cancel(skb, nlh);
                return -EMSGSIZE;
+       }
 
        nlmsg_end(skb, nlh);
        return 0;
index 8cbe74313f38268a3cf2fecb36eb2d1d2dd60ac0..45fb450b45227ce05cc5a2fd8b8a32089ad5c476 100644 (file)
@@ -20,6 +20,9 @@
 #include <net/addrconf.h>
 #include <net/inet_connection_sock.h>
 #include <net/inet_hashtables.h>
+#if IS_ENABLED(CONFIG_IPV6)
+#include <net/inet6_hashtables.h>
+#endif
 #include <net/secure_seq.h>
 #include <net/ip.h>
 #include <net/tcp.h>
@@ -508,10 +511,52 @@ static u32 inet_sk_port_offset(const struct sock *sk)
                                          inet->inet_dport);
 }
 
-/* insert a socket into ehash, and eventually remove another one
- * (The another one can be a SYN_RECV or TIMEWAIT
+/* Searches for an exsiting socket in the ehash bucket list.
+ * Returns true if found, false otherwise.
  */
-bool inet_ehash_insert(struct sock *sk, struct sock *osk)
+static bool inet_ehash_lookup_by_sk(struct sock *sk,
+                                   struct hlist_nulls_head *list)
+{
+       const __portpair ports = INET_COMBINED_PORTS(sk->sk_dport, sk->sk_num);
+       const int sdif = sk->sk_bound_dev_if;
+       const int dif = sk->sk_bound_dev_if;
+       const struct hlist_nulls_node *node;
+       struct net *net = sock_net(sk);
+       struct sock *esk;
+
+       INET_ADDR_COOKIE(acookie, sk->sk_daddr, sk->sk_rcv_saddr);
+
+       sk_nulls_for_each_rcu(esk, node, list) {
+               if (esk->sk_hash != sk->sk_hash)
+                       continue;
+               if (sk->sk_family == AF_INET) {
+                       if (unlikely(INET_MATCH(esk, net, acookie,
+                                               sk->sk_daddr,
+                                               sk->sk_rcv_saddr,
+                                               ports, dif, sdif))) {
+                               return true;
+                       }
+               }
+#if IS_ENABLED(CONFIG_IPV6)
+               else if (sk->sk_family == AF_INET6) {
+                       if (unlikely(INET6_MATCH(esk, net,
+                                                &sk->sk_v6_daddr,
+                                                &sk->sk_v6_rcv_saddr,
+                                                ports, dif, sdif))) {
+                               return true;
+                       }
+               }
+#endif
+       }
+       return false;
+}
+
+/* Insert a socket into ehash, and eventually remove another one
+ * (The another one can be a SYN_RECV or TIMEWAIT)
+ * If an existing socket already exists, socket sk is not inserted,
+ * and sets found_dup_sk parameter to true.
+ */
+bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk)
 {
        struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
        struct hlist_nulls_head *list;
@@ -530,16 +575,23 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk)
        if (osk) {
                WARN_ON_ONCE(sk->sk_hash != osk->sk_hash);
                ret = sk_nulls_del_node_init_rcu(osk);
+       } else if (found_dup_sk) {
+               *found_dup_sk = inet_ehash_lookup_by_sk(sk, list);
+               if (*found_dup_sk)
+                       ret = false;
        }
+
        if (ret)
                __sk_nulls_add_node_rcu(sk, list);
+
        spin_unlock(lock);
+
        return ret;
 }
 
-bool inet_ehash_nolisten(struct sock *sk, struct sock *osk)
+bool inet_ehash_nolisten(struct sock *sk, struct sock *osk, bool *found_dup_sk)
 {
-       bool ok = inet_ehash_insert(sk, osk);
+       bool ok = inet_ehash_insert(sk, osk, found_dup_sk);
 
        if (ok) {
                sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
@@ -583,7 +635,7 @@ int __inet_hash(struct sock *sk, struct sock *osk)
        int err = 0;
 
        if (sk->sk_state != TCP_LISTEN) {
-               inet_ehash_nolisten(sk, osk);
+               inet_ehash_nolisten(sk, osk, NULL);
                return 0;
        }
        WARN_ON(!sk_unhashed(sk));
@@ -679,7 +731,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
                tb = inet_csk(sk)->icsk_bind_hash;
                spin_lock_bh(&head->lock);
                if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
-                       inet_ehash_nolisten(sk, NULL);
+                       inet_ehash_nolisten(sk, NULL, NULL);
                        spin_unlock_bh(&head->lock);
                        return 0;
                }
@@ -758,7 +810,7 @@ ok:
        inet_bind_hash(sk, tb, port);
        if (sk_unhashed(sk)) {
                inet_sk(sk)->inet_sport = htons(port);
-               inet_ehash_nolisten(sk, (struct sock *)tw);
+               inet_ehash_nolisten(sk, (struct sock *)tw, NULL);
        }
        if (tw)
                inet_twsk_bind_unhash(tw, hinfo);
index 8b04d1dcfec4eb5d0fb697497e0e5599ce8704f1..ee65c9225178d66948a7b70b3d243499eadbc168 100644 (file)
@@ -608,9 +608,6 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
                        ttl = ip4_dst_hoplimit(&rt->dst);
        }
 
-       if (!df && skb->protocol == htons(ETH_P_IP))
-               df = inner_iph->frag_off & htons(IP_DF);
-
        headroom += LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len;
        if (headroom > dev->needed_headroom)
                dev->needed_headroom = headroom;
index 25f1caf5abf93c85ea6d8483e36e1d69b1d5065e..e25be2d01a7ac0694ac04b2e98312ab9ea053090 100644 (file)
@@ -263,7 +263,7 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
        const struct icmphdr *icmph = icmp_hdr(skb);
        const struct iphdr *iph = ip_hdr(skb);
 
-       if (mtu <= 576 || iph->frag_off != htons(IP_DF))
+       if (mtu < 576 || iph->frag_off != htons(IP_DF))
                return 0;
 
        if (ipv4_is_lbcast(iph->daddr)  || ipv4_is_multicast(iph->daddr) ||
@@ -359,7 +359,7 @@ static int iptunnel_pmtud_check_icmpv6(struct sk_buff *skb, int mtu)
        __be16 frag_off;
        int offset;
 
-       if (mtu <= IPV6_MIN_MTU)
+       if (mtu < IPV6_MIN_MTU)
                return 0;
 
        if (stype == IPV6_ADDR_ANY || stype == IPV6_ADDR_MULTICAST ||
index a058213b77a787a1aa1c0779ae9017932eaff785..7c841037c53349855f9711a70bd0ac333b8bd716 100644 (file)
 #include <net/netfilter/nf_queue.h>
 
 /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
-int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_type)
+int ip_route_me_harder(struct net *net, struct sock *sk, struct sk_buff *skb, unsigned int addr_type)
 {
        const struct iphdr *iph = ip_hdr(skb);
        struct rtable *rt;
        struct flowi4 fl4 = {};
        __be32 saddr = iph->saddr;
-       const struct sock *sk = skb_to_full_sk(skb);
-       __u8 flags = sk ? inet_sk_flowi_flags(sk) : 0;
+       __u8 flags;
        struct net_device *dev = skb_dst(skb)->dev;
        unsigned int hh_len;
 
+       sk = sk_to_full_sk(sk);
+       flags = sk ? inet_sk_flowi_flags(sk) : 0;
+
        if (addr_type == RTN_UNSPEC)
                addr_type = inet_addr_type_dev_table(net, dev, saddr);
        if (addr_type == RTN_LOCAL || addr_type == RTN_UNICAST)
index f703a717ab1d23bdf94ee0b47d4182ddd7810a4c..83307958927307845951ef5cb2682f05e7b2024b 100644 (file)
@@ -62,7 +62,7 @@ ipt_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state)
                    iph->daddr != daddr ||
                    skb->mark != mark ||
                    iph->tos != tos) {
-                       err = ip_route_me_harder(state->net, skb, RTN_UNSPEC);
+                       err = ip_route_me_harder(state->net, state->sk, skb, RTN_UNSPEC);
                        if (err < 0)
                                ret = NF_DROP_ERR(err);
                }
index 9dcfa4e461b65aaada32b4d5e11946ae3ae919c8..93b07739807b270854e663b16ac103b159009d72 100644 (file)
@@ -145,7 +145,7 @@ void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
                                   ip4_dst_hoplimit(skb_dst(nskb)));
        nf_reject_ip_tcphdr_put(nskb, oldskb, oth);
 
-       if (ip_route_me_harder(net, nskb, RTN_UNSPEC))
+       if (ip_route_me_harder(net, nskb->sk, nskb, RTN_UNSPEC))
                goto free_nskb;
 
        niph = ip_hdr(nskb);
index dc2a399cd9f4fa5ad729430d40c7838128e79b21..9f43abeac3a8e5bc11d6e2b716e632439cee504c 100644 (file)
@@ -3222,7 +3222,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 
        fl4.daddr = dst;
        fl4.saddr = src;
-       fl4.flowi4_tos = rtm->rtm_tos;
+       fl4.flowi4_tos = rtm->rtm_tos & IPTOS_RT_MASK;
        fl4.flowi4_oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0;
        fl4.flowi4_mark = mark;
        fl4.flowi4_uid = uid;
@@ -3246,8 +3246,9 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
                fl4.flowi4_iif = iif; /* for rt_fill_info */
                skb->dev        = dev;
                skb->mark       = mark;
-               err = ip_route_input_rcu(skb, dst, src, rtm->rtm_tos,
-                                        dev, &res);
+               err = ip_route_input_rcu(skb, dst, src,
+                                        rtm->rtm_tos & IPTOS_RT_MASK, dev,
+                                        &res);
 
                rt = skb_rtable(skb);
                if (err == 0 && rt->dst.error)
index 6ac473b47f30d4d5e5e9455424b1a91d84e649ee..00dc3f943c80b5a1815180e00aeebf532100140e 100644 (file)
@@ -331,7 +331,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
        __u32 cookie = ntohl(th->ack_seq) - 1;
        struct sock *ret = sk;
        struct request_sock *req;
-       int mss;
+       int full_space, mss;
        struct rtable *rt;
        __u8 rcv_wscale;
        struct flowi4 fl4;
@@ -427,8 +427,13 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
 
        /* Try to redo what tcp_v4_send_synack did. */
        req->rsk_window_clamp = tp->window_clamp ? :dst_metric(&rt->dst, RTAX_WINDOW);
+       /* limit the window selection if the user enforce a smaller rx buffer */
+       full_space = tcp_full_space(sk);
+       if (sk->sk_userlocks & SOCK_RCVBUF_LOCK &&
+           (req->rsk_window_clamp > full_space || req->rsk_window_clamp == 0))
+               req->rsk_window_clamp = full_space;
 
-       tcp_select_initial_window(sk, tcp_full_space(sk), req->mss,
+       tcp_select_initial_window(sk, full_space, req->mss,
                                  &req->rsk_rcv_wnd, &req->rsk_window_clamp,
                                  ireq->wscale_ok, &rcv_wscale,
                                  dst_metric(&rt->dst, RTAX_INITRWND));
index bae4284bf542437fab45b32d5cb5a464d88a63ee..b2bc3d7fe9e806718f6e20ad9fa775ffb83806fb 100644 (file)
@@ -485,6 +485,8 @@ static inline bool tcp_stream_is_readable(const struct tcp_sock *tp,
                        return true;
                if (tcp_rmem_pressure(sk))
                        return true;
+               if (tcp_receive_window(tp) <= inet_csk(sk)->icsk_ack.rcv_mss)
+                       return true;
        }
        if (sk->sk_prot->stream_memory_read)
                return sk->sk_prot->stream_memory_read(sk);
index 6c4d79baff2696b859d214bb63108b9f2f61f457..6ea3dc2e421946c2d384a16e022efc1a7ab1874a 100644 (file)
@@ -945,7 +945,7 @@ static void bbr_update_min_rtt(struct sock *sk, const struct rate_sample *rs)
        filter_expired = after(tcp_jiffies32,
                               bbr->min_rtt_stamp + bbr_min_rtt_win_sec * HZ);
        if (rs->rtt_us >= 0 &&
-           (rs->rtt_us <= bbr->min_rtt_us ||
+           (rs->rtt_us < bbr->min_rtt_us ||
             (filter_expired && !rs->is_ack_delayed))) {
                bbr->min_rtt_us = rs->rtt_us;
                bbr->min_rtt_stamp = tcp_jiffies32;
index 37f4cb2bba5cbd0b47b3a34cbd26d6b750c0c796..bc7d2a586e18307cb54cff1e8104234b378c1654 100644 (file)
@@ -15,8 +15,8 @@ int __tcp_bpf_recvmsg(struct sock *sk, struct sk_psock *psock,
 {
        struct iov_iter *iter = &msg->msg_iter;
        int peek = flags & MSG_PEEK;
-       int i, ret, copied = 0;
        struct sk_msg *msg_rx;
+       int i, copied = 0;
 
        msg_rx = list_first_entry_or_null(&psock->ingress_msg,
                                          struct sk_msg, list);
@@ -37,17 +37,16 @@ int __tcp_bpf_recvmsg(struct sock *sk, struct sk_psock *psock,
                        page = sg_page(sge);
                        if (copied + copy > len)
                                copy = len - copied;
-                       ret = copy_page_to_iter(page, sge->offset, copy, iter);
-                       if (ret != copy) {
-                               msg_rx->sg.start = i;
-                               return -EFAULT;
-                       }
+                       copy = copy_page_to_iter(page, sge->offset, copy, iter);
+                       if (!copy)
+                               return copied ? copied : -EFAULT;
 
                        copied += copy;
                        if (likely(!peek)) {
                                sge->offset += copy;
                                sge->length -= copy;
-                               sk_mem_uncharge(sk, copy);
+                               if (!msg_rx->skb)
+                                       sk_mem_uncharge(sk, copy);
                                msg_rx->sg.size -= copy;
 
                                if (!sge->length) {
@@ -56,6 +55,11 @@ int __tcp_bpf_recvmsg(struct sock *sk, struct sk_psock *psock,
                                                put_page(page);
                                }
                        } else {
+                               /* Lets not optimize peek case if copy_page_to_iter
+                                * didn't copy the entire length lets just break.
+                                */
+                               if (copy != sge->length)
+                                       return copied;
                                sk_msg_iter_var_next(i);
                        }
 
index db47ac24d057e0678af80f0e5b8cf6619c7d3182..563d016e7478302847d11a43f4c5832eb3989054 100644 (file)
@@ -198,6 +198,11 @@ static void tcp_reinit_congestion_control(struct sock *sk,
        icsk->icsk_ca_setsockopt = 1;
        memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
 
+       if (ca->flags & TCP_CONG_NEEDS_ECN)
+               INET_ECN_xmit(sk);
+       else
+               INET_ECN_dontxmit(sk);
+
        if (!((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)))
                tcp_init_congestion_control(sk);
 }
index fc445833b5e508d20aa52ff68fb4b698b21c4cd7..389d1b34024854a9bdcbe861d4820d1bfb495e24 100644 (file)
@@ -4908,7 +4908,8 @@ void tcp_data_ready(struct sock *sk)
        int avail = tp->rcv_nxt - tp->copied_seq;
 
        if (avail < sk->sk_rcvlowat && !tcp_rmem_pressure(sk) &&
-           !sock_flag(sk, SOCK_DONE))
+           !sock_flag(sk, SOCK_DONE) &&
+           tcp_receive_window(tp) > inet_csk(sk)->icsk_ack.rcv_mss)
                return;
 
        sk->sk_data_ready(sk);
index 7352c097ae48f7df6caba1ae5b98dccfecd79d1a..8391aa29e7a41ecb06c3feed13e038b827a7ab11 100644 (file)
@@ -980,17 +980,22 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
 
        skb = tcp_make_synack(sk, dst, req, foc, synack_type, syn_skb);
 
-       tos = sock_net(sk)->ipv4.sysctl_tcp_reflect_tos ?
-                       tcp_rsk(req)->syn_tos : inet_sk(sk)->tos;
-
        if (skb) {
                __tcp_v4_send_check(skb, ireq->ir_loc_addr, ireq->ir_rmt_addr);
 
+               tos = sock_net(sk)->ipv4.sysctl_tcp_reflect_tos ?
+                               tcp_rsk(req)->syn_tos & ~INET_ECN_MASK :
+                               inet_sk(sk)->tos;
+
+               if (!INET_ECN_is_capable(tos) &&
+                   tcp_bpf_ca_needs_ecn((struct sock *)req))
+                       tos |= INET_ECN_ECT_0;
+
                rcu_read_lock();
                err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr,
                                            ireq->ir_rmt_addr,
                                            rcu_dereference(ireq->ireq_opt),
-                                           tos & ~INET_ECN_MASK);
+                                           tos);
                rcu_read_unlock();
                err = net_xmit_eval(err);
        }
@@ -1498,6 +1503,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
                                  bool *own_req)
 {
        struct inet_request_sock *ireq;
+       bool found_dup_sk = false;
        struct inet_sock *newinet;
        struct tcp_sock *newtp;
        struct sock *newsk;
@@ -1575,12 +1581,22 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
 
        if (__inet_inherit_port(sk, newsk) < 0)
                goto put_and_exit;
-       *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash));
+       *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash),
+                                      &found_dup_sk);
        if (likely(*own_req)) {
                tcp_move_syn(newtp, req);
                ireq->ireq_opt = NULL;
        } else {
-               newinet->inet_opt = NULL;
+               if (!req_unhash && found_dup_sk) {
+                       /* This code path should only be executed in the
+                        * syncookie case only
+                        */
+                       bh_unlock_sock(newsk);
+                       sock_put(newsk);
+                       newsk = NULL;
+               } else {
+                       newinet->inet_opt = NULL;
+               }
        }
        return newsk;
 
index e67a66fbf27b830f9c911ab9a469860d3496fff0..c62805cd31319f844eb3c1ef4760c9ee999a2484 100644 (file)
@@ -366,7 +366,7 @@ out:
 static struct sk_buff *udp_gro_receive_segment(struct list_head *head,
                                               struct sk_buff *skb)
 {
-       struct udphdr *uh = udp_hdr(skb);
+       struct udphdr *uh = udp_gro_udphdr(skb);
        struct sk_buff *pp = NULL;
        struct udphdr *uh2;
        struct sk_buff *p;
@@ -500,12 +500,22 @@ out:
 }
 EXPORT_SYMBOL(udp_gro_receive);
 
+static struct sock *udp4_gro_lookup_skb(struct sk_buff *skb, __be16 sport,
+                                       __be16 dport)
+{
+       const struct iphdr *iph = skb_gro_network_header(skb);
+
+       return __udp4_lib_lookup(dev_net(skb->dev), iph->saddr, sport,
+                                iph->daddr, dport, inet_iif(skb),
+                                inet_sdif(skb), &udp_table, NULL);
+}
+
 INDIRECT_CALLABLE_SCOPE
 struct sk_buff *udp4_gro_receive(struct list_head *head, struct sk_buff *skb)
 {
        struct udphdr *uh = udp_gro_udphdr(skb);
+       struct sock *sk = NULL;
        struct sk_buff *pp;
-       struct sock *sk;
 
        if (unlikely(!uh))
                goto flush;
@@ -523,7 +533,10 @@ struct sk_buff *udp4_gro_receive(struct list_head *head, struct sk_buff *skb)
 skip:
        NAPI_GRO_CB(skb)->is_ipv6 = 0;
        rcu_read_lock();
-       sk = static_branch_unlikely(&udp_encap_needed_key) ? udp4_lib_lookup_skb(skb, uh->source, uh->dest) : NULL;
+
+       if (static_branch_unlikely(&udp_encap_needed_key))
+               sk = udp4_gro_lookup_skb(skb, uh->source, uh->dest);
+
        pp = udp_gro_receive(head, skb, uh, sk);
        rcu_read_unlock();
        return pp;
index dc19aff7c2e0055711597d7dd423fd107cd21ef7..fb0648e7fb32f9b0715030b7eb0049df81f0deea 100644 (file)
@@ -64,14 +64,14 @@ static int xfrm_tunnel_err(struct sk_buff *skb, u32 info)
 static struct xfrm_tunnel xfrm_tunnel_handler __read_mostly = {
        .handler        =       xfrm_tunnel_rcv,
        .err_handler    =       xfrm_tunnel_err,
-       .priority       =       3,
+       .priority       =       4,
 };
 
 #if IS_ENABLED(CONFIG_IPV6)
 static struct xfrm_tunnel xfrm64_tunnel_handler __read_mostly = {
        .handler        =       xfrm_tunnel_rcv,
        .err_handler    =       xfrm_tunnel_err,
-       .priority       =       2,
+       .priority       =       3,
 };
 #endif
 
index 01146b66d6669f37abf884643caf891d9972db90..8b6eb384bac7cac2f46b119a1ad851465a836ad7 100644 (file)
@@ -5022,8 +5022,10 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
                return -EMSGSIZE;
 
        if (args->netnsid >= 0 &&
-           nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid))
+           nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid)) {
+               nlmsg_cancel(skb, nlh);
                return -EMSGSIZE;
+       }
 
        put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
        if (nla_put_in6_addr(skb, IFA_MULTICAST, &ifmca->mca_addr) < 0 ||
@@ -5054,8 +5056,10 @@ static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
                return -EMSGSIZE;
 
        if (args->netnsid >= 0 &&
-           nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid))
+           nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid)) {
+               nlmsg_cancel(skb, nlh);
                return -EMSGSIZE;
+       }
 
        put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
        if (nla_put_in6_addr(skb, IFA_ANYCAST, &ifaca->aca_addr) < 0 ||
index 642fc6ac13d229230a51d8513b60fc31c00b7bc4..8a22486cf27020c93f94670ebb1ec1aa93c8fb19 100644 (file)
@@ -306,7 +306,9 @@ static int ip6addrlbl_del(struct net *net,
 /* add default label */
 static int __net_init ip6addrlbl_net_init(struct net *net)
 {
-       int err = 0;
+       struct ip6addrlbl_entry *p = NULL;
+       struct hlist_node *n;
+       int err;
        int i;
 
        ADDRLABEL(KERN_DEBUG "%s\n", __func__);
@@ -315,14 +317,20 @@ static int __net_init ip6addrlbl_net_init(struct net *net)
        INIT_HLIST_HEAD(&net->ipv6.ip6addrlbl_table.head);
 
        for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) {
-               int ret = ip6addrlbl_add(net,
-                                        ip6addrlbl_init_table[i].prefix,
-                                        ip6addrlbl_init_table[i].prefixlen,
-                                        0,
-                                        ip6addrlbl_init_table[i].label, 0);
-               /* XXX: should we free all rules when we catch an error? */
-               if (ret && (!err || err != -ENOMEM))
-                       err = ret;
+               err = ip6addrlbl_add(net,
+                                    ip6addrlbl_init_table[i].prefix,
+                                    ip6addrlbl_init_table[i].prefixlen,
+                                    0,
+                                    ip6addrlbl_init_table[i].label, 0);
+               if (err)
+                       goto err_ip6addrlbl_add;
+       }
+       return 0;
+
+err_ip6addrlbl_add:
+       hlist_for_each_entry_safe(p, n, &net->ipv6.ip6addrlbl_table.head, list) {
+               hlist_del_rcu(&p->list);
+               kfree_rcu(p, rcu);
        }
        return err;
 }
index d88d97617f7ebf93da36c395b4a01e1ed9b64285..440080da805b5ead265b8ae3e018719b1048a2ae 100644 (file)
@@ -588,7 +588,8 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
        memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
        memset(ah->auth_data, 0, ahp->icv_trunc_len);
 
-       if (ipv6_clear_mutable_options(ip6h, hdr_len, XFRM_POLICY_IN))
+       err = ipv6_clear_mutable_options(ip6h, hdr_len, XFRM_POLICY_IN);
+       if (err)
                goto out_free;
 
        ip6h->priority    = 0;
index ec448b71bf9ae7758c0d85a830bea5a408287e08..8956144ea65e8a8d64574cdb51fb09df41705170 100644 (file)
@@ -158,7 +158,13 @@ static bool is_ineligible(const struct sk_buff *skb)
                tp = skb_header_pointer(skb,
                        ptr+offsetof(struct icmp6hdr, icmp6_type),
                        sizeof(_type), &_type);
-               if (!tp || !(*tp & ICMPV6_INFOMSG_MASK))
+
+               /* Based on RFC 8200, Section 4.5 Fragment Header, return
+                * false if this is a fragment packet with no icmp header info.
+                */
+               if (!tp && frag_off != 0)
+                       return false;
+               else if (!tp || !(*tp & ICMPV6_INFOMSG_MASK))
                        return true;
        }
        return false;
index 931b186d2e4869c42ce1a906c6cb04815b533d9a..cf6e1380b527c34d6609968782045ad07a7e82b6 100644 (file)
@@ -1133,8 +1133,13 @@ static void ip6gre_tnl_link_config_route(struct ip6_tnl *t, int set_mtu,
                        return;
 
                if (rt->dst.dev) {
-                       dev->needed_headroom = rt->dst.dev->hard_header_len +
-                                              t_hlen;
+                       unsigned short dst_len = rt->dst.dev->hard_header_len +
+                                                t_hlen;
+
+                       if (t->dev->header_ops)
+                               dev->hard_header_len = dst_len;
+                       else
+                               dev->needed_headroom = dst_len;
 
                        if (set_mtu) {
                                dev->mtu = rt->dst.dev->mtu - t_hlen;
@@ -1159,7 +1164,12 @@ static int ip6gre_calc_hlen(struct ip6_tnl *tunnel)
        tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
 
        t_hlen = tunnel->hlen + sizeof(struct ipv6hdr);
-       tunnel->dev->needed_headroom = LL_MAX_HEADER + t_hlen;
+
+       if (tunnel->dev->header_ops)
+               tunnel->dev->hard_header_len = LL_MAX_HEADER + t_hlen;
+       else
+               tunnel->dev->needed_headroom = LL_MAX_HEADER + t_hlen;
+
        return t_hlen;
 }
 
index a0217e5bf3bc1132969e0ed7421cf5eceff54d69..648db3fe508f03f269b9a16bc2340f536ad6bb7c 100644 (file)
@@ -1271,6 +1271,8 @@ route_lookup:
        if (max_headroom > dev->needed_headroom)
                dev->needed_headroom = max_headroom;
 
+       skb_set_inner_ipproto(skb, proto);
+
        err = ip6_tnl_encap(skb, t, &proto, fl6);
        if (err)
                return err;
@@ -1280,8 +1282,6 @@ route_lookup:
                ipv6_push_frag_opts(skb, &opt.ops, &proto);
        }
 
-       skb_set_inner_ipproto(skb, proto);
-
        skb_push(skb, sizeof(struct ipv6hdr));
        skb_reset_network_header(skb);
        ipv6h = ipv6_hdr(skb);
index 27f29b957ee7c3bdc04eb33b3c635251278802b3..76717478f1733fb753c067efaa5dd210320e0261 100644 (file)
@@ -81,6 +81,7 @@ static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
 static int pndisc_constructor(struct pneigh_entry *n);
 static void pndisc_destructor(struct pneigh_entry *n);
 static void pndisc_redo(struct sk_buff *skb);
+static int ndisc_is_multicast(const void *pkey);
 
 static const struct neigh_ops ndisc_generic_ops = {
        .family =               AF_INET6,
@@ -115,6 +116,7 @@ struct neigh_table nd_tbl = {
        .pconstructor = pndisc_constructor,
        .pdestructor =  pndisc_destructor,
        .proxy_redo =   pndisc_redo,
+       .is_multicast = ndisc_is_multicast,
        .allow_add  =   ndisc_allow_add,
        .id =           "ndisc_cache",
        .parms = {
@@ -1706,6 +1708,11 @@ static void pndisc_redo(struct sk_buff *skb)
        kfree_skb(skb);
 }
 
+static int ndisc_is_multicast(const void *pkey)
+{
+       return ipv6_addr_is_multicast((struct in6_addr *)pkey);
+}
+
 static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb)
 {
        struct inet6_dev *idev = __in6_dev_get(skb->dev);
index 6d0e942d082d4ec0f66cb97fb20a7c466a0a0dfa..ab9a279dd6d47d34a3ad68e7cb88d588f2c6eaef 100644 (file)
 #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
 #include "../bridge/br_private.h"
 
-int ip6_route_me_harder(struct net *net, struct sk_buff *skb)
+int ip6_route_me_harder(struct net *net, struct sock *sk_partial, struct sk_buff *skb)
 {
        const struct ipv6hdr *iph = ipv6_hdr(skb);
-       struct sock *sk = sk_to_full_sk(skb->sk);
+       struct sock *sk = sk_to_full_sk(sk_partial);
        unsigned int hh_len;
        struct dst_entry *dst;
        int strict = (ipv6_addr_type(&iph->daddr) &
@@ -84,7 +84,7 @@ static int nf_ip6_reroute(struct sk_buff *skb,
                if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) ||
                    !ipv6_addr_equal(&iph->saddr, &rt_info->saddr) ||
                    skb->mark != rt_info->mark)
-                       return ip6_route_me_harder(entry->state.net, skb);
+                       return ip6_route_me_harder(entry->state.net, entry->state.sk, skb);
        }
        return 0;
 }
index 1a2748611e00388abf30a4127a24adc516cdcd2e..cee74803d7a1ce649c01c71f4d7b6860ff156aa3 100644 (file)
@@ -57,7 +57,7 @@ ip6t_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state)
             skb->mark != mark ||
             ipv6_hdr(skb)->hop_limit != hop_limit ||
             flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) {
-               err = ip6_route_me_harder(state->net, skb);
+               err = ip6_route_me_harder(state->net, state->sk, skb);
                if (err < 0)
                        ret = NF_DROP_ERR(err);
        }
index 054d287eb13d031b908efe154376d8e033d41b44..c129ad334eb392594e1c258b31e52a9d03d7724f 100644 (file)
@@ -440,6 +440,7 @@ find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff)
 int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
 {
        u16 savethdr = skb->transport_header;
+       u8 nexthdr = NEXTHDR_FRAGMENT;
        int fhoff, nhoff, ret;
        struct frag_hdr *fhdr;
        struct frag_queue *fq;
@@ -455,6 +456,14 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
        if (find_prev_fhdr(skb, &prevhdr, &nhoff, &fhoff) < 0)
                return 0;
 
+       /* Discard the first fragment if it does not include all headers
+        * RFC 8200, Section 4.5
+        */
+       if (ipv6frag_thdr_truncated(skb, fhoff, &nexthdr)) {
+               pr_debug("Drop incomplete fragment\n");
+               return 0;
+       }
+
        if (!pskb_may_pull(skb, fhoff + sizeof(*fhdr)))
                return -ENOMEM;
 
index 1f5d4d196dccee12ee979f305b1b904864ff246e..47a0dc46cbdb0a16e6fb7cee505fcbe28d5d01fc 100644 (file)
@@ -42,6 +42,8 @@
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
 
 #include <net/sock.h>
 #include <net/snmp.h>
@@ -322,6 +324,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
        struct frag_queue *fq;
        const struct ipv6hdr *hdr = ipv6_hdr(skb);
        struct net *net = dev_net(skb_dst(skb)->dev);
+       u8 nexthdr;
        int iif;
 
        if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED)
@@ -351,6 +354,20 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
                return 1;
        }
 
+       /* RFC 8200, Section 4.5 Fragment Header:
+        * If the first fragment does not include all headers through an
+        * Upper-Layer header, then that fragment should be discarded and
+        * an ICMP Parameter Problem, Code 3, message should be sent to
+        * the source of the fragment, with the Pointer field set to zero.
+        */
+       nexthdr = hdr->nexthdr;
+       if (ipv6frag_thdr_truncated(skb, skb_transport_offset(skb), &nexthdr)) {
+               __IP6_INC_STATS(net, __in6_dev_get_safely(skb->dev),
+                               IPSTATS_MIB_INHDRERRORS);
+               icmpv6_param_prob(skb, ICMPV6_HDR_INCOMP, 0);
+               return -1;
+       }
+
        iif = skb->dev ? skb->dev->ifindex : 0;
        fq = fq_find(net, fhdr->identification, hdr, iif);
        if (fq) {
index 5e2c34c0ac973643f2fdffee0e9c2d1214922425..5e7983cb61546f99f5d979cd9edef9d6026dec4d 100644 (file)
@@ -1128,7 +1128,6 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
        if (tdev && !netif_is_l3_master(tdev)) {
                int t_hlen = tunnel->hlen + sizeof(struct iphdr);
 
-               dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
                dev->mtu = tdev->mtu - t_hlen;
                if (dev->mtu < IPV6_MIN_MTU)
                        dev->mtu = IPV6_MIN_MTU;
@@ -1426,7 +1425,6 @@ static void ipip6_tunnel_setup(struct net_device *dev)
        dev->priv_destructor    = ipip6_dev_free;
 
        dev->type               = ARPHRD_SIT;
-       dev->hard_header_len    = LL_MAX_HEADER + t_hlen;
        dev->mtu                = ETH_DATA_LEN - t_hlen;
        dev->min_mtu            = IPV6_MIN_MTU;
        dev->max_mtu            = IP6_MAX_MTU - t_hlen;
index e796a64be308ccf6d1fc2d6c726d3f1763aafb8b..9b6cae1e49d9102fb0b27a7c3501e65aa3f17402 100644 (file)
@@ -136,7 +136,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
        __u32 cookie = ntohl(th->ack_seq) - 1;
        struct sock *ret = sk;
        struct request_sock *req;
-       int mss;
+       int full_space, mss;
        struct dst_entry *dst;
        __u8 rcv_wscale;
        u32 tsoff = 0;
@@ -241,7 +241,13 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
        }
 
        req->rsk_window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW);
-       tcp_select_initial_window(sk, tcp_full_space(sk), req->mss,
+       /* limit the window selection if the user enforce a smaller rx buffer */
+       full_space = tcp_full_space(sk);
+       if (sk->sk_userlocks & SOCK_RCVBUF_LOCK &&
+           (req->rsk_window_clamp > full_space || req->rsk_window_clamp == 0))
+               req->rsk_window_clamp = full_space;
+
+       tcp_select_initial_window(sk, full_space, req->mss,
                                  &req->rsk_rcv_wnd, &req->rsk_window_clamp,
                                  ireq->wscale_ok, &rcv_wscale,
                                  dst_metric(dst, RTAX_INITRWND));
index 8db59f4e5f13a99571b26f618100e0f9510b7217..992cbf3eb9e38b3c5318d2aa5b7dc49e08db7439 100644 (file)
@@ -527,15 +527,20 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
                if (np->repflow && ireq->pktopts)
                        fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts));
 
+               tclass = sock_net(sk)->ipv4.sysctl_tcp_reflect_tos ?
+                               tcp_rsk(req)->syn_tos & ~INET_ECN_MASK :
+                               np->tclass;
+
+               if (!INET_ECN_is_capable(tclass) &&
+                   tcp_bpf_ca_needs_ecn((struct sock *)req))
+                       tclass |= INET_ECN_ECT_0;
+
                rcu_read_lock();
                opt = ireq->ipv6_opt;
-               tclass = sock_net(sk)->ipv4.sysctl_tcp_reflect_tos ?
-                               tcp_rsk(req)->syn_tos : np->tclass;
                if (!opt)
                        opt = rcu_dereference(np->opt);
                err = ip6_xmit(sk, skb, fl6, sk->sk_mark, opt,
-                              tclass & ~INET_ECN_MASK,
-                              sk->sk_priority);
+                              tclass, sk->sk_priority);
                rcu_read_unlock();
                err = net_xmit_eval(err);
        }
@@ -1193,6 +1198,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
        const struct ipv6_pinfo *np = tcp_inet6_sk(sk);
        struct ipv6_txoptions *opt;
        struct inet_sock *newinet;
+       bool found_dup_sk = false;
        struct tcp_sock *newtp;
        struct sock *newsk;
 #ifdef CONFIG_TCP_MD5SIG
@@ -1368,7 +1374,8 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
                tcp_done(newsk);
                goto out;
        }
-       *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash));
+       *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash),
+                                      &found_dup_sk);
        if (*own_req) {
                tcp_move_syn(newtp, req);
 
@@ -1383,6 +1390,15 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
                                skb_set_owner_r(newnp->pktoptions, newsk);
                        }
                }
+       } else {
+               if (!req_unhash && found_dup_sk) {
+                       /* This code path should only be executed in the
+                        * syncookie case only
+                        */
+                       bh_unlock_sock(newsk);
+                       sock_put(newsk);
+                       newsk = NULL;
+               }
        }
 
        return newsk;
index 584157a0775969b2af74f4f4f820b78f64133f9b..f9e888d1b9af8bbb7fe12a5155dcaceab9475caf 100644 (file)
@@ -111,12 +111,22 @@ out:
        return segs;
 }
 
+static struct sock *udp6_gro_lookup_skb(struct sk_buff *skb, __be16 sport,
+                                       __be16 dport)
+{
+       const struct ipv6hdr *iph = skb_gro_network_header(skb);
+
+       return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport,
+                                &iph->daddr, dport, inet6_iif(skb),
+                                inet6_sdif(skb), &udp_table, NULL);
+}
+
 INDIRECT_CALLABLE_SCOPE
 struct sk_buff *udp6_gro_receive(struct list_head *head, struct sk_buff *skb)
 {
        struct udphdr *uh = udp_gro_udphdr(skb);
+       struct sock *sk = NULL;
        struct sk_buff *pp;
-       struct sock *sk;
 
        if (unlikely(!uh))
                goto flush;
@@ -135,7 +145,10 @@ struct sk_buff *udp6_gro_receive(struct list_head *head, struct sk_buff *skb)
 skip:
        NAPI_GRO_CB(skb)->is_ipv6 = 1;
        rcu_read_lock();
-       sk = static_branch_unlikely(&udpv6_encap_needed_key) ? udp6_lib_lookup_skb(skb, uh->source, uh->dest) : NULL;
+
+       if (static_branch_unlikely(&udpv6_encap_needed_key))
+               sk = udp6_gro_lookup_skb(skb, uh->source, uh->dest);
+
        pp = udp_gro_receive(head, skb, uh, sk);
        rcu_read_unlock();
        return pp;
index 25b7ebda2fabf157ecd1a12972e6d1cd28a1cc48..f696d46e6910068d1c15b487f7e68feecad5452a 100644 (file)
@@ -303,13 +303,13 @@ static const struct xfrm_type xfrm6_tunnel_type = {
 static struct xfrm6_tunnel xfrm6_tunnel_handler __read_mostly = {
        .handler        = xfrm6_tunnel_rcv,
        .err_handler    = xfrm6_tunnel_err,
-       .priority       = 2,
+       .priority       = 3,
 };
 
 static struct xfrm6_tunnel xfrm46_tunnel_handler __read_mostly = {
        .handler        = xfrm6_tunnel_rcv,
        .err_handler    = xfrm6_tunnel_err,
-       .priority       = 2,
+       .priority       = 3,
 };
 
 static int __net_init xfrm6_tunnel_net_init(struct net *net)
index d805720746672d067a35fce61868994cc03b9c0f..db7d888914fadf529292c5ee3d78042c3a716e83 100644 (file)
@@ -1434,7 +1434,8 @@ static int iucv_sock_shutdown(struct socket *sock, int how)
                break;
        }
 
-       if (how == SEND_SHUTDOWN || how == SHUTDOWN_MASK) {
+       if ((how == SEND_SHUTDOWN || how == SHUTDOWN_MASK) &&
+           sk->sk_state == IUCV_CONNECTED) {
                if (iucv->transport == AF_IUCV_TRANS_IUCV) {
                        txmsg.class = 0;
                        txmsg.tag = 0;
@@ -1644,7 +1645,7 @@ static int iucv_callback_connreq(struct iucv_path *path,
        }
 
        /* Create the new socket */
-       nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC, 0);
+       nsk = iucv_sock_alloc(NULL, sk->sk_protocol, GFP_ATOMIC, 0);
        if (!nsk) {
                err = pr_iucv->path_sever(path, user_data);
                iucv_path_free(path);
@@ -1850,7 +1851,7 @@ static int afiucv_hs_callback_syn(struct sock *sk, struct sk_buff *skb)
                goto out;
        }
 
-       nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC, 0);
+       nsk = iucv_sock_alloc(NULL, sk->sk_protocol, GFP_ATOMIC, 0);
        bh_lock_sock(sk);
        if ((sk->sk_state != IUCV_LISTEN) ||
            sk_acceptq_is_full(sk) ||
index f400240a556f571229b5d1e9f112de3753971082..6adfcb9c06dcc516cf215cdc5b0ea7ed1524099e 100644 (file)
@@ -5464,6 +5464,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
                        struct cfg80211_assoc_request *req)
 {
        bool is_6ghz = req->bss->channel->band == NL80211_BAND_6GHZ;
+       bool is_5ghz = req->bss->channel->band == NL80211_BAND_5GHZ;
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_bss *bss = (void *)req->bss->priv;
@@ -5616,7 +5617,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
        if (vht_ie && vht_ie[1] >= sizeof(struct ieee80211_vht_cap))
                memcpy(&assoc_data->ap_vht_cap, vht_ie + 2,
                       sizeof(struct ieee80211_vht_cap));
-       else if (!is_6ghz)
+       else if (is_5ghz)
                ifmgd->flags |= IEEE80211_STA_DISABLE_VHT |
                                IEEE80211_STA_DISABLE_HE;
        rcu_read_unlock();
index 86bc469a28bc5f7f6e1d2d084712801cadebacb3..b13b1da193867c776c4c20deb7241357c229aef4 100644 (file)
@@ -274,7 +274,7 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
        success = !!(info->flags & IEEE80211_TX_STAT_ACK);
 
        for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
-               if (ar[i].idx < 0)
+               if (ar[i].idx < 0 || !ar[i].count)
                        break;
 
                ndx = rix_to_ndx(mi, ar[i].idx);
@@ -287,12 +287,6 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
                        mi->r[ndx].stats.success += success;
        }
 
-       if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0))
-               mi->sample_packets++;
-
-       if (mi->sample_deferred > 0)
-               mi->sample_deferred--;
-
        if (time_after(jiffies, mi->last_stats_update +
                                mp->update_interval / (mp->new_avg ? 2 : 1)))
                minstrel_update_stats(mp, mi);
@@ -367,7 +361,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
                return;
 
        delta = (mi->total_packets * sampling_ratio / 100) -
-                       (mi->sample_packets + mi->sample_deferred / 2);
+                       mi->sample_packets;
 
        /* delta < 0: no sampling required */
        prev_sample = mi->prev_sample;
@@ -376,7 +370,6 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
                return;
 
        if (mi->total_packets >= 10000) {
-               mi->sample_deferred = 0;
                mi->sample_packets = 0;
                mi->total_packets = 0;
        } else if (delta > mi->n_rates * 2) {
@@ -401,19 +394,8 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
         * rate sampling method should be used.
         * Respect such rates that are not sampled for 20 interations.
         */
-       if (mrr_capable &&
-           msr->perfect_tx_time > mr->perfect_tx_time &&
-           msr->stats.sample_skipped < 20) {
-               /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
-                * packets that have the sampling rate deferred to the
-                * second MRR stage. Increase the sample counter only
-                * if the deferred sample rate was actually used.
-                * Use the sample_deferred counter to make sure that
-                * the sampling is not done in large bursts */
-               info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
-               rate++;
-               mi->sample_deferred++;
-       } else {
+       if (msr->perfect_tx_time < mr->perfect_tx_time ||
+           msr->stats.sample_skipped >= 20) {
                if (!msr->sample_limit)
                        return;
 
@@ -433,6 +415,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
 
        rate->idx = mi->r[ndx].rix;
        rate->count = minstrel_get_retry_count(&mi->r[ndx], info);
+       info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
 }
 
 
index dbb43bcd3c45a205165df331620d8e003fbcc8a7..86cd80b3ffdef8423ea39069c1e8ac0e6f5bd560 100644 (file)
@@ -126,7 +126,6 @@ struct minstrel_sta_info {
        u8 max_prob_rate;
        unsigned int total_packets;
        unsigned int sample_packets;
-       int sample_deferred;
 
        unsigned int sample_row;
        unsigned int sample_column;
index fb4f2b9b294f03cc3aa28dbf2f5d11e78c0936a0..ec6973ee88ef49d9169ce9141642859166c6059f 100644 (file)
@@ -258,6 +258,24 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
  */
 void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
 {
+       /*
+        * If we had used sta_info_pre_move_state() then we might not
+        * have gone through the state transitions down again, so do
+        * it here now (and warn if it's inserted).
+        *
+        * This will clear state such as fast TX/RX that may have been
+        * allocated during state transitions.
+        */
+       while (sta->sta_state > IEEE80211_STA_NONE) {
+               int ret;
+
+               WARN_ON_ONCE(test_sta_flag(sta, WLAN_STA_INSERTED));
+
+               ret = sta_info_move_state(sta, sta->sta_state - 1);
+               if (WARN_ONCE(ret, "sta_info_move_state() returned %d\n", ret))
+                       break;
+       }
+
        if (sta->rate_ctrl)
                rate_control_free_sta(sta);
 
@@ -687,7 +705,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
  out_drop_sta:
        local->num_sta--;
        synchronize_net();
-       __cleanup_single_sta(sta);
+       cleanup_single_sta(sta);
  out_err:
        mutex_unlock(&local->sta_mtx);
        kfree(sinfo);
@@ -706,19 +724,13 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)
 
        err = sta_info_insert_check(sta);
        if (err) {
+               sta_info_free(local, sta);
                mutex_unlock(&local->sta_mtx);
                rcu_read_lock();
-               goto out_free;
+               return err;
        }
 
-       err = sta_info_insert_finish(sta);
-       if (err)
-               goto out_free;
-
-       return 0;
- out_free:
-       sta_info_free(local, sta);
-       return err;
+       return sta_info_insert_finish(sta);
 }
 
 int sta_info_insert(struct sta_info *sta)
index 00ae81e9e1a12d9756a39b490e53a6b300d1f28f..7afd07636b81da4fcc12b702a8af852d7eb80b2b 100644 (file)
@@ -785,7 +785,7 @@ int sta_info_init(struct ieee80211_local *local);
 void sta_info_stop(struct ieee80211_local *local);
 
 /**
- * sta_info_flush - flush matching STA entries from the STA table
+ * __sta_info_flush - flush matching STA entries from the STA table
  *
  * Returns the number of removed STA entries.
  *
@@ -794,6 +794,13 @@ void sta_info_stop(struct ieee80211_local *local);
  */
 int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans);
 
+/**
+ * sta_info_flush - flush matching STA entries from the STA table
+ *
+ * Returns the number of removed STA entries.
+ *
+ * @sdata: sdata to remove all stations from
+ */
 static inline int sta_info_flush(struct ieee80211_sub_if_data *sdata)
 {
        return __sta_info_flush(sdata, false);
index 6feb45135020e5484b18c7b4de564dd5fd0d0a4a..3485610755ef019e437ece4d15ef296f4ae7a516 100644 (file)
@@ -49,7 +49,8 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
        int ac;
 
        if (info->flags & (IEEE80211_TX_CTL_NO_PS_BUFFER |
-                          IEEE80211_TX_CTL_AMPDU)) {
+                          IEEE80211_TX_CTL_AMPDU |
+                          IEEE80211_TX_CTL_HW_80211_ENCAP)) {
                ieee80211_free_txskb(&local->hw, skb);
                return;
        }
@@ -915,15 +916,6 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
                        ieee80211_mpsp_trigger_process(
                                ieee80211_get_qos_ctl(hdr), sta, true, acked);
 
-               if (!acked && test_sta_flag(sta, WLAN_STA_PS_STA)) {
-                       /*
-                        * The STA is in power save mode, so assume
-                        * that this TX packet failed because of that.
-                        */
-                       ieee80211_handle_filtered_frame(local, sta, skb);
-                       return;
-               }
-
                if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL) &&
                    (ieee80211_is_data(hdr->frame_control)) &&
                    (rates_idx != -1))
@@ -1150,6 +1142,12 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
                                                            -info->status.ack_signal);
                                }
                        } else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
+                               /*
+                                * The STA is in power save mode, so assume
+                                * that this TX packet failed because of that.
+                                */
+                               if (skb)
+                                       ieee80211_handle_filtered_frame(local, sta, skb);
                                return;
                        } else if (noack_success) {
                                /* nothing to do here, do not account as lost */
index 8ba10a48ded4cab1c80e7da7026b2c19a3941035..56a4d0d20a267a9cadf246945f0373ddea39a1a7 100644 (file)
@@ -1942,19 +1942,24 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
 
 /* device xmit handlers */
 
+enum ieee80211_encrypt {
+       ENCRYPT_NO,
+       ENCRYPT_MGMT,
+       ENCRYPT_DATA,
+};
+
 static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
                                struct sk_buff *skb,
-                               int head_need, bool may_encrypt)
+                               int head_need,
+                               enum ieee80211_encrypt encrypt)
 {
        struct ieee80211_local *local = sdata->local;
-       struct ieee80211_hdr *hdr;
        bool enc_tailroom;
        int tail_need = 0;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
-       enc_tailroom = may_encrypt &&
-                      (sdata->crypto_tx_tailroom_needed_cnt ||
-                       ieee80211_is_mgmt(hdr->frame_control));
+       enc_tailroom = encrypt == ENCRYPT_MGMT ||
+                      (encrypt == ENCRYPT_DATA &&
+                       sdata->crypto_tx_tailroom_needed_cnt);
 
        if (enc_tailroom) {
                tail_need = IEEE80211_ENCRYPT_TAILROOM;
@@ -1985,23 +1990,29 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
        int headroom;
-       bool may_encrypt;
+       enum ieee80211_encrypt encrypt;
 
-       may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT);
+       if (info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)
+               encrypt = ENCRYPT_NO;
+       else if (ieee80211_is_mgmt(hdr->frame_control))
+               encrypt = ENCRYPT_MGMT;
+       else
+               encrypt = ENCRYPT_DATA;
 
        headroom = local->tx_headroom;
-       if (may_encrypt)
+       if (encrypt != ENCRYPT_NO)
                headroom += sdata->encrypt_headroom;
        headroom -= skb_headroom(skb);
        headroom = max_t(int, 0, headroom);
 
-       if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
+       if (ieee80211_skb_resize(sdata, skb, headroom, encrypt)) {
                ieee80211_free_txskb(&local->hw, skb);
                return;
        }
 
+       /* reload after potential resize */
        hdr = (struct ieee80211_hdr *) skb->data;
        info->control.vif = &sdata->vif;
 
@@ -2828,7 +2839,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
                head_need += sdata->encrypt_headroom;
                head_need += local->tx_headroom;
                head_need = max_t(int, 0, head_need);
-               if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
+               if (ieee80211_skb_resize(sdata, skb, head_need, ENCRYPT_DATA)) {
                        ieee80211_free_txskb(&local->hw, skb);
                        skb = NULL;
                        return ERR_PTR(-ENOMEM);
@@ -3502,7 +3513,7 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
        if (unlikely(ieee80211_skb_resize(sdata, skb,
                                          max_t(int, extra_head + hw_headroom -
                                                     skb_headroom(skb), 0),
-                                         false))) {
+                                         ENCRYPT_NO))) {
                kfree_skb(skb);
                return true;
        }
@@ -3619,13 +3630,14 @@ begin:
        tx.skb = skb;
        tx.sdata = vif_to_sdata(info->control.vif);
 
-       if (txq->sta && !(info->flags & IEEE80211_TX_CTL_INJECTED)) {
+       if (txq->sta) {
                tx.sta = container_of(txq->sta, struct sta_info, sta);
                /*
                 * Drop unicast frames to unauthorised stations unless they are
-                * EAPOL frames from the local station.
+                * injected frames or EAPOL frames from the local station.
                 */
-               if (unlikely(ieee80211_is_data(hdr->frame_control) &&
+               if (unlikely(!(info->flags & IEEE80211_TX_CTL_INJECTED) &&
+                            ieee80211_is_data(hdr->frame_control) &&
                             !ieee80211_vif_is_mesh(&tx.sdata->vif) &&
                             tx.sdata->vif.type != NL80211_IFTYPE_OCB &&
                             !is_multicast_ether_addr(hdr->addr1) &&
index 185dacb3978196c040fc208a8bbeabc56715c7cd..88f2a7a0ccb86b11ea1850abd6082a73441ba810 100644 (file)
@@ -274,6 +274,15 @@ static bool __mptcp_move_skb(struct mptcp_sock *msk, struct sock *ssk,
        skb_ext_reset(skb);
        skb_orphan(skb);
 
+       /* try to fetch required memory from subflow */
+       if (!sk_rmem_schedule(sk, skb, skb->truesize)) {
+               if (ssk->sk_forward_alloc < skb->truesize)
+                       goto drop;
+               __sk_mem_reclaim(ssk, skb->truesize);
+               if (!sk_rmem_schedule(sk, skb, skb->truesize))
+                       goto drop;
+       }
+
        /* the skb map_seq accounts for the skb offset:
         * mptcp_subflow_get_mapped_dsn() is based on the current tp->copied_seq
         * value
@@ -301,6 +310,7 @@ static bool __mptcp_move_skb(struct mptcp_sock *msk, struct sock *ssk,
         * will retransmit as needed, if needed.
         */
        MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA);
+drop:
        mptcp_drop(sk, skb);
        return false;
 }
@@ -2457,6 +2467,7 @@ static struct proto mptcp_prot = {
        .memory_pressure        = &tcp_memory_pressure,
        .stream_memory_free     = mptcp_memory_free,
        .sysctl_wmem_offset     = offsetof(struct net, ipv4.sysctl_tcp_wmem),
+       .sysctl_rmem_offset     = offsetof(struct net, ipv4.sysctl_tcp_rmem),
        .sysctl_mem     = sysctl_tcp_mem,
        .obj_size       = sizeof(struct mptcp_sock),
        .slab_flags     = SLAB_TYPESAFE_BY_RCU,
index ac4a1fe3550bd0ddee6e4f3d808aa4e48003dac6..953906e407428a6432bc35a945dade5047ee1bfd 100644 (file)
@@ -543,9 +543,8 @@ create_msk:
                        fallback = true;
        } else if (subflow_req->mp_join) {
                mptcp_get_options(skb, &mp_opt);
-               if (!mp_opt.mp_join ||
-                   !mptcp_can_accept_new_subflow(subflow_req->msk) ||
-                   !subflow_hmac_valid(req, &mp_opt)) {
+               if (!mp_opt.mp_join || !subflow_hmac_valid(req, &mp_opt) ||
+                   !mptcp_can_accept_new_subflow(subflow_req->msk)) {
                        SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC);
                        fallback = true;
                }
index 8b47c4bb1c6bed37887f970b59eb5635586450d1..feb4b9ffd46258fed457742a25cbfbde8e0e87d4 100644 (file)
@@ -291,7 +291,7 @@ struct mptcp_sock *mptcp_token_iter_next(const struct net *net, long *s_slot,
 {
        struct mptcp_sock *ret = NULL;
        struct hlist_nulls_node *pos;
-       int slot, num;
+       int slot, num = 0;
 
        for (slot = *s_slot; slot <= token_mask; *s_num = 0, slot++) {
                struct token_bucket *bucket = &token_hash[slot];
index f1be3e3f6425e253df876ceee8a490e3eed98765..a9cb355324d1ab5a4d33870c13f2a178ec793a81 100644 (file)
@@ -1726,9 +1726,6 @@ struct ncsi_dev *ncsi_register_dev(struct net_device *dev,
        ndp->ptype.dev = dev;
        dev_add_pack(&ndp->ptype);
 
-       /* Set up generic netlink interface */
-       ncsi_init_netlink(dev);
-
        pdev = to_platform_device(dev->dev.parent);
        if (pdev) {
                np = pdev->dev.of_node;
@@ -1892,8 +1889,6 @@ void ncsi_unregister_dev(struct ncsi_dev *nd)
        list_del_rcu(&ndp->node);
        spin_unlock_irqrestore(&ncsi_dev_lock, flags);
 
-       ncsi_unregister_netlink(nd->dev);
-
        kfree(ndp);
 }
 EXPORT_SYMBOL_GPL(ncsi_unregister_dev);
index adddc7707aa4cc80545db81a77de156cdc62440c..bb5f1650f11cb3a5e1c2c714603ab3468a759992 100644 (file)
@@ -766,24 +766,8 @@ static struct genl_family ncsi_genl_family __ro_after_init = {
        .n_small_ops = ARRAY_SIZE(ncsi_ops),
 };
 
-int ncsi_init_netlink(struct net_device *dev)
+static int __init ncsi_init_netlink(void)
 {
-       int rc;
-
-       rc = genl_register_family(&ncsi_genl_family);
-       if (rc)
-               netdev_err(dev, "ncsi: failed to register netlink family\n");
-
-       return rc;
-}
-
-int ncsi_unregister_netlink(struct net_device *dev)
-{
-       int rc;
-
-       rc = genl_unregister_family(&ncsi_genl_family);
-       if (rc)
-               netdev_err(dev, "ncsi: failed to unregister netlink family\n");
-
-       return rc;
+       return genl_register_family(&ncsi_genl_family);
 }
+subsys_initcall(ncsi_init_netlink);
index 7502723fba837300308a4156b1a80a0bfa3d3654..39a1a9d7bf77eb4f8c51af2de096825bc93abf19 100644 (file)
@@ -22,7 +22,4 @@ int ncsi_send_netlink_err(struct net_device *dev,
                          struct nlmsghdr *nlhdr,
                          int err);
 
-int ncsi_init_netlink(struct net_device *dev);
-int ncsi_unregister_netlink(struct net_device *dev);
-
 #endif /* __NCSI_NETLINK_H__ */
index 6f35832f0de384b4f969b2e9a8ac0c3e54eaa0de..2b19189a930fd552cc859aed02eade8698bd9061 100644 (file)
@@ -271,8 +271,7 @@ flag_nested(const struct nlattr *nla)
 
 static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = {
        [IPSET_ATTR_IPADDR_IPV4]        = { .type = NLA_U32 },
-       [IPSET_ATTR_IPADDR_IPV6]        = { .type = NLA_BINARY,
-                                           .len = sizeof(struct in6_addr) },
+       [IPSET_ATTR_IPADDR_IPV6]        = NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
 };
 
 int
@@ -637,13 +636,14 @@ ip_set_match_extensions(struct ip_set *set, const struct ip_set_ext *ext,
        if (SET_WITH_COUNTER(set)) {
                struct ip_set_counter *counter = ext_counter(data, set);
 
+               ip_set_update_counter(counter, ext, flags);
+
                if (flags & IPSET_FLAG_MATCH_COUNTERS &&
                    !(ip_set_match_counter(ip_set_get_packets(counter),
                                mext->packets, mext->packets_op) &&
                      ip_set_match_counter(ip_set_get_bytes(counter),
                                mext->bytes, mext->bytes_op)))
                        return false;
-               ip_set_update_counter(counter, ext, flags);
        }
        if (SET_WITH_SKBINFO(set))
                ip_set_get_skbinfo(ext_skbinfo(data, set),
index cc3c275934f47f4817280897e1bc9f8b5424f178..c0b8215ab3d47a6719cbb0d57cffb7b73326ecad 100644 (file)
@@ -742,12 +742,12 @@ static int ip_vs_route_me_harder(struct netns_ipvs *ipvs, int af,
                struct dst_entry *dst = skb_dst(skb);
 
                if (dst->dev && !(dst->dev->flags & IFF_LOOPBACK) &&
-                   ip6_route_me_harder(ipvs->net, skb) != 0)
+                   ip6_route_me_harder(ipvs->net, skb->sk, skb) != 0)
                        return 1;
        } else
 #endif
                if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
-                   ip_route_me_harder(ipvs->net, skb, RTN_LOCAL) != 0)
+                   ip_route_me_harder(ipvs->net, skb->sk, skb, RTN_LOCAL) != 0)
                        return 1;
 
        return 0;
index e279ded4e3065a2618a3973e5923480ae09d1e3b..d45dbcba8b49c58d6872a13457373b6789573609 100644 (file)
@@ -4167,12 +4167,18 @@ int __net_init ip_vs_control_net_init(struct netns_ipvs *ipvs)
 
        spin_lock_init(&ipvs->tot_stats.lock);
 
-       proc_create_net("ip_vs", 0, ipvs->net->proc_net, &ip_vs_info_seq_ops,
-                       sizeof(struct ip_vs_iter));
-       proc_create_net_single("ip_vs_stats", 0, ipvs->net->proc_net,
-                       ip_vs_stats_show, NULL);
-       proc_create_net_single("ip_vs_stats_percpu", 0, ipvs->net->proc_net,
-                       ip_vs_stats_percpu_show, NULL);
+#ifdef CONFIG_PROC_FS
+       if (!proc_create_net("ip_vs", 0, ipvs->net->proc_net,
+                            &ip_vs_info_seq_ops, sizeof(struct ip_vs_iter)))
+               goto err_vs;
+       if (!proc_create_net_single("ip_vs_stats", 0, ipvs->net->proc_net,
+                                   ip_vs_stats_show, NULL))
+               goto err_stats;
+       if (!proc_create_net_single("ip_vs_stats_percpu", 0,
+                                   ipvs->net->proc_net,
+                                   ip_vs_stats_percpu_show, NULL))
+               goto err_percpu;
+#endif
 
        if (ip_vs_control_net_init_sysctl(ipvs))
                goto err;
@@ -4180,6 +4186,17 @@ int __net_init ip_vs_control_net_init(struct netns_ipvs *ipvs)
        return 0;
 
 err:
+#ifdef CONFIG_PROC_FS
+       remove_proc_entry("ip_vs_stats_percpu", ipvs->net->proc_net);
+
+err_percpu:
+       remove_proc_entry("ip_vs_stats", ipvs->net->proc_net);
+
+err_stats:
+       remove_proc_entry("ip_vs", ipvs->net->proc_net);
+
+err_vs:
+#endif
        free_percpu(ipvs->tot_stats.cpustats);
        return -ENOMEM;
 }
@@ -4188,9 +4205,11 @@ void __net_exit ip_vs_control_net_cleanup(struct netns_ipvs *ipvs)
 {
        ip_vs_trash_cleanup(ipvs);
        ip_vs_control_net_cleanup_sysctl(ipvs);
+#ifdef CONFIG_PROC_FS
        remove_proc_entry("ip_vs_stats_percpu", ipvs->net->proc_net);
        remove_proc_entry("ip_vs_stats", ipvs->net->proc_net);
        remove_proc_entry("ip_vs", ipvs->net->proc_net);
+#endif
        free_percpu(ipvs->tot_stats.cpustats);
 }
 
index 59151dc07fdc14fe6fa640cdd0448723d96bcb48..e87b6bd6b3cdb6b79b2d229df4ce3d74f8e374d8 100644 (file)
@@ -715,7 +715,7 @@ nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb,
 
                if (ct->tuplehash[dir].tuple.dst.u3.ip !=
                    ct->tuplehash[!dir].tuple.src.u3.ip) {
-                       err = ip_route_me_harder(state->net, skb, RTN_UNSPEC);
+                       err = ip_route_me_harder(state->net, state->sk, skb, RTN_UNSPEC);
                        if (err < 0)
                                ret = NF_DROP_ERR(err);
                }
@@ -953,7 +953,7 @@ nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb,
 
                if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3,
                                      &ct->tuplehash[!dir].tuple.src.u3)) {
-                       err = nf_ip6_route_me_harder(state->net, skb);
+                       err = nf_ip6_route_me_harder(state->net, state->sk, skb);
                        if (err < 0)
                                ret = NF_DROP_ERR(err);
                }
index 9cca35d22927382e0323cc7cb8cd16913e8d3e87..d7d34a62d3bf5fb5d7919d855a02a2c1c935b8a0 100644 (file)
@@ -446,7 +446,7 @@ synproxy_send_tcp(struct net *net,
 
        skb_dst_set_noref(nskb, skb_dst(skb));
        nskb->protocol = htons(ETH_P_IP);
-       if (ip_route_me_harder(net, nskb, RTN_UNSPEC))
+       if (ip_route_me_harder(net, nskb->sk, nskb, RTN_UNSPEC))
                goto free_nskb;
 
        if (nfct) {
index 65cb8e3c13d901e4c6b1b8d63f1c048d36dbb2cf..23abf1578594302fafca43ad0a5cc5adc5bc12a6 100644 (file)
@@ -619,7 +619,8 @@ static int nft_request_module(struct net *net, const char *fmt, ...)
 static void lockdep_nfnl_nft_mutex_not_held(void)
 {
 #ifdef CONFIG_PROVE_LOCKING
-       WARN_ON_ONCE(lockdep_nfnl_is_held(NFNL_SUBSYS_NFTABLES));
+       if (debug_locks)
+               WARN_ON_ONCE(lockdep_nfnl_is_held(NFNL_SUBSYS_NFTABLES));
 #endif
 }
 
@@ -7137,7 +7138,7 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx,
                        GFP_KERNEL);
        kfree(buf);
 
-       if (ctx->report &&
+       if (!ctx->report &&
            !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
                return;
 
@@ -7259,7 +7260,7 @@ static void nf_tables_gen_notify(struct net *net, struct sk_buff *skb,
        audit_log_nfcfg("?:0;?:0", 0, net->nft.base_seq,
                        AUDIT_NFT_OP_GEN_REGISTER, GFP_KERNEL);
 
-       if (nlmsg_report(nlh) &&
+       if (!nlmsg_report(nlh) &&
            !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
                return;
 
@@ -8053,12 +8054,16 @@ static void nf_tables_abort_release(struct nft_trans *trans)
        kfree(trans);
 }
 
-static int __nf_tables_abort(struct net *net, bool autoload)
+static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
 {
        struct nft_trans *trans, *next;
        struct nft_trans_elem *te;
        struct nft_hook *hook;
 
+       if (action == NFNL_ABORT_VALIDATE &&
+           nf_tables_validate(net) < 0)
+               return -EAGAIN;
+
        list_for_each_entry_safe_reverse(trans, next, &net->nft.commit_list,
                                         list) {
                switch (trans->msg_type) {
@@ -8190,7 +8195,7 @@ static int __nf_tables_abort(struct net *net, bool autoload)
                nf_tables_abort_release(trans);
        }
 
-       if (autoload)
+       if (action == NFNL_ABORT_AUTOLOAD)
                nf_tables_module_autoload(net);
        else
                nf_tables_module_autoload_cleanup(net);
@@ -8203,9 +8208,10 @@ static void nf_tables_cleanup(struct net *net)
        nft_validate_state_update(net, NFT_VALIDATE_SKIP);
 }
 
-static int nf_tables_abort(struct net *net, struct sk_buff *skb, bool autoload)
+static int nf_tables_abort(struct net *net, struct sk_buff *skb,
+                          enum nfnl_abort_action action)
 {
-       int ret = __nf_tables_abort(net, autoload);
+       int ret = __nf_tables_abort(net, action);
 
        mutex_unlock(&net->nft.commit_mutex);
 
@@ -8836,7 +8842,7 @@ static void __net_exit nf_tables_exit_net(struct net *net)
 {
        mutex_lock(&net->nft.commit_mutex);
        if (!list_empty(&net->nft.commit_list))
-               __nf_tables_abort(net, false);
+               __nf_tables_abort(net, NFNL_ABORT_NONE);
        __nft_release_tables(net);
        mutex_unlock(&net->nft.commit_mutex);
        WARN_ON_ONCE(!list_empty(&net->nft.tables));
index 9f625724a20fc27ea54ca1cdd3e747d170260410..9ae14270c543e045c16e75648dfb24b8a8a65633 100644 (file)
@@ -28,6 +28,23 @@ static struct nft_flow_rule *nft_flow_rule_alloc(int num_actions)
        return flow;
 }
 
+void nft_flow_rule_set_addr_type(struct nft_flow_rule *flow,
+                                enum flow_dissector_key_id addr_type)
+{
+       struct nft_flow_match *match = &flow->match;
+       struct nft_flow_key *mask = &match->mask;
+       struct nft_flow_key *key = &match->key;
+
+       if (match->dissector.used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL))
+               return;
+
+       key->control.addr_type = addr_type;
+       mask->control.addr_type = 0xffff;
+       match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_CONTROL);
+       match->dissector.offset[FLOW_DISSECTOR_KEY_CONTROL] =
+               offsetof(struct nft_flow_key, control);
+}
+
 struct nft_flow_rule *nft_flow_rule_create(struct net *net,
                                           const struct nft_rule *rule)
 {
index 2daa1f6ae344113b2031c4488595e9b9640dd9fe..d3df66a39b5e004b4e583d56ee4c0c40bbb2cdd9 100644 (file)
@@ -333,7 +333,7 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
                return netlink_ack(skb, nlh, -EINVAL, NULL);
 replay:
        status = 0;
-
+replay_abort:
        skb = netlink_skb_clone(oskb, GFP_KERNEL);
        if (!skb)
                return netlink_ack(oskb, nlh, -ENOMEM, NULL);
@@ -499,7 +499,7 @@ ack:
        }
 done:
        if (status & NFNL_BATCH_REPLAY) {
-               ss->abort(net, oskb, true);
+               ss->abort(net, oskb, NFNL_ABORT_AUTOLOAD);
                nfnl_err_reset(&err_list);
                kfree_skb(skb);
                module_put(ss->owner);
@@ -510,11 +510,25 @@ done:
                        status |= NFNL_BATCH_REPLAY;
                        goto done;
                } else if (err) {
-                       ss->abort(net, oskb, false);
+                       ss->abort(net, oskb, NFNL_ABORT_NONE);
                        netlink_ack(oskb, nlmsg_hdr(oskb), err, NULL);
                }
        } else {
-               ss->abort(net, oskb, false);
+               enum nfnl_abort_action abort_action;
+
+               if (status & NFNL_BATCH_FAILURE)
+                       abort_action = NFNL_ABORT_NONE;
+               else
+                       abort_action = NFNL_ABORT_VALIDATE;
+
+               err = ss->abort(net, oskb, abort_action);
+               if (err == -EAGAIN) {
+                       nfnl_err_reset(&err_list);
+                       kfree_skb(skb);
+                       module_put(ss->owner);
+                       status |= NFNL_BATCH_FAILURE;
+                       goto replay_abort;
+               }
        }
        if (ss->cleanup)
                ss->cleanup(net);
index 8826bbe71136c86bd1020e0598bb4509aa793421..edd02cda57fca8713c29f749ceae7e26e83aa9ff 100644 (file)
@@ -42,7 +42,7 @@ static unsigned int nf_route_table_hook4(void *priv,
                    iph->daddr != daddr ||
                    skb->mark != mark ||
                    iph->tos != tos) {
-                       err = ip_route_me_harder(state->net, skb, RTN_UNSPEC);
+                       err = ip_route_me_harder(state->net, state->sk, skb, RTN_UNSPEC);
                        if (err < 0)
                                ret = NF_DROP_ERR(err);
                }
@@ -92,7 +92,7 @@ static unsigned int nf_route_table_hook6(void *priv,
             skb->mark != mark ||
             ipv6_hdr(skb)->hop_limit != hop_limit ||
             flowlabel != *((u32 *)ipv6_hdr(skb)))) {
-               err = nf_ip6_route_me_harder(state->net, skb);
+               err = nf_ip6_route_me_harder(state->net, state->sk, skb);
                if (err < 0)
                        ret = NF_DROP_ERR(err);
        }
index bc079d68a5365f5aaeaf276d7533eab33916d14b..00e563a72d3d7c9dc3dc232afb1471b01dee89c5 100644 (file)
@@ -123,11 +123,11 @@ static int __nft_cmp_offload(struct nft_offload_ctx *ctx,
        u8 *mask = (u8 *)&flow->match.mask;
        u8 *key = (u8 *)&flow->match.key;
 
-       if (priv->op != NFT_CMP_EQ || reg->len != priv->len)
+       if (priv->op != NFT_CMP_EQ || priv->len > reg->len)
                return -EOPNOTSUPP;
 
-       memcpy(key + reg->offset, &priv->data, priv->len);
-       memcpy(mask + reg->offset, &reg->mask, priv->len);
+       memcpy(key + reg->offset, &priv->data, reg->len);
+       memcpy(mask + reg->offset, &reg->mask, reg->len);
 
        flow->match.dissector.used_keys |= BIT(reg->key);
        flow->match.dissector.offset[reg->key] = reg->base_offset;
@@ -137,7 +137,7 @@ static int __nft_cmp_offload(struct nft_offload_ctx *ctx,
            nft_reg_load16(priv->data.data) != ARPHRD_ETHER)
                return -EOPNOTSUPP;
 
-       nft_offload_update_dependency(ctx, &priv->data, priv->len);
+       nft_offload_update_dependency(ctx, &priv->data, reg->len);
 
        return 0;
 }
index b37bd02448d8c7b6f399e6cb3515e2e2851ec6fe..bf4b3ad5314c343409d1becd974970dd22e57d51 100644 (file)
@@ -724,22 +724,22 @@ static int nft_meta_get_offload(struct nft_offload_ctx *ctx,
 
        switch (priv->key) {
        case NFT_META_PROTOCOL:
-               NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, n_proto,
-                                 sizeof(__u16), reg);
+               NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_BASIC, basic, n_proto,
+                                       sizeof(__u16), reg);
                nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK);
                break;
        case NFT_META_L4PROTO:
-               NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
-                                 sizeof(__u8), reg);
+               NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
+                                       sizeof(__u8), reg);
                nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
                break;
        case NFT_META_IIF:
-               NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_META, meta,
-                                 ingress_ifindex, sizeof(__u32), reg);
+               NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_META, meta,
+                                       ingress_ifindex, sizeof(__u32), reg);
                break;
        case NFT_META_IIFTYPE:
-               NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_META, meta,
-                                 ingress_iftype, sizeof(__u16), reg);
+               NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_META, meta,
+                                       ingress_iftype, sizeof(__u16), reg);
                break;
        default:
                return -EOPNOTSUPP;
index dcd3c7b8a367c77d8a1f141e81489347de640aa9..47d4e0e21651442e5368e84ac156a2e2dd942406 100644 (file)
@@ -165,6 +165,34 @@ nla_put_failure:
        return -1;
 }
 
+static bool nft_payload_offload_mask(struct nft_offload_reg *reg,
+                                    u32 priv_len, u32 field_len)
+{
+       unsigned int remainder, delta, k;
+       struct nft_data mask = {};
+       __be32 remainder_mask;
+
+       if (priv_len == field_len) {
+               memset(&reg->mask, 0xff, priv_len);
+               return true;
+       } else if (priv_len > field_len) {
+               return false;
+       }
+
+       memset(&mask, 0xff, field_len);
+       remainder = priv_len % sizeof(u32);
+       if (remainder) {
+               k = priv_len / sizeof(u32);
+               delta = field_len - priv_len;
+               remainder_mask = htonl(~((1 << (delta * BITS_PER_BYTE)) - 1));
+               mask.data[k] = (__force u32)remainder_mask;
+       }
+
+       memcpy(&reg->mask, &mask, field_len);
+
+       return true;
+}
+
 static int nft_payload_offload_ll(struct nft_offload_ctx *ctx,
                                  struct nft_flow_rule *flow,
                                  const struct nft_payload *priv)
@@ -173,21 +201,21 @@ static int nft_payload_offload_ll(struct nft_offload_ctx *ctx,
 
        switch (priv->offset) {
        case offsetof(struct ethhdr, h_source):
-               if (priv->len != ETH_ALEN)
+               if (!nft_payload_offload_mask(reg, priv->len, ETH_ALEN))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
                                  src, ETH_ALEN, reg);
                break;
        case offsetof(struct ethhdr, h_dest):
-               if (priv->len != ETH_ALEN)
+               if (!nft_payload_offload_mask(reg, priv->len, ETH_ALEN))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
                                  dst, ETH_ALEN, reg);
                break;
        case offsetof(struct ethhdr, h_proto):
-               if (priv->len != sizeof(__be16))
+               if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic,
@@ -195,14 +223,14 @@ static int nft_payload_offload_ll(struct nft_offload_ctx *ctx,
                nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK);
                break;
        case offsetof(struct vlan_ethhdr, h_vlan_TCI):
-               if (priv->len != sizeof(__be16))
+               if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_VLAN, vlan,
                                  vlan_tci, sizeof(__be16), reg);
                break;
        case offsetof(struct vlan_ethhdr, h_vlan_encapsulated_proto):
-               if (priv->len != sizeof(__be16))
+               if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_VLAN, vlan,
@@ -210,7 +238,7 @@ static int nft_payload_offload_ll(struct nft_offload_ctx *ctx,
                nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK);
                break;
        case offsetof(struct vlan_ethhdr, h_vlan_TCI) + sizeof(struct vlan_hdr):
-               if (priv->len != sizeof(__be16))
+               if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_CVLAN, vlan,
@@ -218,7 +246,7 @@ static int nft_payload_offload_ll(struct nft_offload_ctx *ctx,
                break;
        case offsetof(struct vlan_ethhdr, h_vlan_encapsulated_proto) +
                                                        sizeof(struct vlan_hdr):
-               if (priv->len != sizeof(__be16))
+               if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_CVLAN, vlan,
@@ -239,21 +267,25 @@ static int nft_payload_offload_ip(struct nft_offload_ctx *ctx,
 
        switch (priv->offset) {
        case offsetof(struct iphdr, saddr):
-               if (priv->len != sizeof(struct in_addr))
+               if (!nft_payload_offload_mask(reg, priv->len,
+                                             sizeof(struct in_addr)))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src,
                                  sizeof(struct in_addr), reg);
+               nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV4_ADDRS);
                break;
        case offsetof(struct iphdr, daddr):
-               if (priv->len != sizeof(struct in_addr))
+               if (!nft_payload_offload_mask(reg, priv->len,
+                                             sizeof(struct in_addr)))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst,
                                  sizeof(struct in_addr), reg);
+               nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV4_ADDRS);
                break;
        case offsetof(struct iphdr, protocol):
-               if (priv->len != sizeof(__u8))
+               if (!nft_payload_offload_mask(reg, priv->len, sizeof(__u8)))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
@@ -275,21 +307,25 @@ static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx,
 
        switch (priv->offset) {
        case offsetof(struct ipv6hdr, saddr):
-               if (priv->len != sizeof(struct in6_addr))
+               if (!nft_payload_offload_mask(reg, priv->len,
+                                             sizeof(struct in6_addr)))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src,
                                  sizeof(struct in6_addr), reg);
+               nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV6_ADDRS);
                break;
        case offsetof(struct ipv6hdr, daddr):
-               if (priv->len != sizeof(struct in6_addr))
+               if (!nft_payload_offload_mask(reg, priv->len,
+                                             sizeof(struct in6_addr)))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst,
                                  sizeof(struct in6_addr), reg);
+               nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV6_ADDRS);
                break;
        case offsetof(struct ipv6hdr, nexthdr):
-               if (priv->len != sizeof(__u8))
+               if (!nft_payload_offload_mask(reg, priv->len, sizeof(__u8)))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
@@ -331,14 +367,14 @@ static int nft_payload_offload_tcp(struct nft_offload_ctx *ctx,
 
        switch (priv->offset) {
        case offsetof(struct tcphdr, source):
-               if (priv->len != sizeof(__be16))
+               if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
                                  sizeof(__be16), reg);
                break;
        case offsetof(struct tcphdr, dest):
-               if (priv->len != sizeof(__be16))
+               if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
@@ -359,14 +395,14 @@ static int nft_payload_offload_udp(struct nft_offload_ctx *ctx,
 
        switch (priv->offset) {
        case offsetof(struct udphdr, source):
-               if (priv->len != sizeof(__be16))
+               if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
                                  sizeof(__be16), reg);
                break;
        case offsetof(struct udphdr, dest):
-               if (priv->len != sizeof(__be16))
+               if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
                        return -EOPNOTSUPP;
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
index cedf47ab3c6f98d13f0397e27a4beeca44d28854..2182d361e273f18818e312e47dda770bf9b4b625 100644 (file)
@@ -191,8 +191,8 @@ static int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry
                      skb->mark == rt_info->mark &&
                      iph->daddr == rt_info->daddr &&
                      iph->saddr == rt_info->saddr))
-                       return ip_route_me_harder(entry->state.net, skb,
-                                                 RTN_UNSPEC);
+                       return ip_route_me_harder(entry->state.net, entry->state.sk,
+                                                 skb, RTN_UNSPEC);
        }
 #endif
        return 0;
index 2e8e3f7b21110e44732382d5d1af2f046ec7145d..ccb4916428116de6b81b09247491c3db1efef1b6 100644 (file)
@@ -1166,12 +1166,13 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
        struct netlbl_unlhsh_walk_arg cb_arg;
        u32 skip_bkt = cb->args[0];
        u32 skip_chain = cb->args[1];
-       u32 iter_bkt;
-       u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;
+       u32 skip_addr4 = cb->args[2];
+       u32 iter_bkt, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;
        struct netlbl_unlhsh_iface *iface;
        struct list_head *iter_list;
        struct netlbl_af4list *addr4;
 #if IS_ENABLED(CONFIG_IPV6)
+       u32 skip_addr6 = cb->args[3];
        struct netlbl_af6list *addr6;
 #endif
 
@@ -1182,7 +1183,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
        rcu_read_lock();
        for (iter_bkt = skip_bkt;
             iter_bkt < rcu_dereference(netlbl_unlhsh)->size;
-            iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) {
+            iter_bkt++) {
                iter_list = &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt];
                list_for_each_entry_rcu(iface, iter_list, list) {
                        if (!iface->valid ||
@@ -1190,7 +1191,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
                                continue;
                        netlbl_af4list_foreach_rcu(addr4,
                                                   &iface->addr4_list) {
-                               if (iter_addr4++ < cb->args[2])
+                               if (iter_addr4++ < skip_addr4)
                                        continue;
                                if (netlbl_unlabel_staticlist_gen(
                                              NLBL_UNLABEL_C_STATICLIST,
@@ -1203,10 +1204,12 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
                                        goto unlabel_staticlist_return;
                                }
                        }
+                       iter_addr4 = 0;
+                       skip_addr4 = 0;
 #if IS_ENABLED(CONFIG_IPV6)
                        netlbl_af6list_foreach_rcu(addr6,
                                                   &iface->addr6_list) {
-                               if (iter_addr6++ < cb->args[3])
+                               if (iter_addr6++ < skip_addr6)
                                        continue;
                                if (netlbl_unlabel_staticlist_gen(
                                              NLBL_UNLABEL_C_STATICLIST,
@@ -1219,8 +1222,12 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
                                        goto unlabel_staticlist_return;
                                }
                        }
+                       iter_addr6 = 0;
+                       skip_addr6 = 0;
 #endif /* IPv6 */
                }
+               iter_chain = 0;
+               skip_chain = 0;
        }
 
 unlabel_staticlist_return:
index b87bfc82f44f02e6b53b8afba309b220e9607d9a..c3a664871cb5a8df3775780c7be40c367fcc1f4e 100644 (file)
@@ -199,6 +199,9 @@ static int set_mpls(struct sk_buff *skb, struct sw_flow_key *flow_key,
        __be32 lse;
        int err;
 
+       if (!pskb_may_pull(skb, skb_network_offset(skb) + MPLS_HLEN))
+               return -ENOMEM;
+
        stack = mpls_hdr(skb);
        lse = OVS_MASKED(stack->label_stack_entry, *mpls_lse, *mask);
        err = skb_mpls_update_lse(skb, lse);
@@ -958,14 +961,13 @@ static int dec_ttl_exception_handler(struct datapath *dp, struct sk_buff *skb,
 {
        /* The first action is always 'OVS_DEC_TTL_ATTR_ARG'. */
        struct nlattr *dec_ttl_arg = nla_data(attr);
-       int rem = nla_len(attr);
 
        if (nla_len(dec_ttl_arg)) {
-               struct nlattr *actions = nla_next(dec_ttl_arg, &rem);
+               struct nlattr *actions = nla_data(dec_ttl_arg);
 
                if (actions)
-                       return clone_execute(dp, skb, key, 0, actions, rem,
-                                            last, false);
+                       return clone_execute(dp, skb, key, 0, nla_data(actions),
+                                            nla_len(actions), last, false);
        }
        consume_skb(skb);
        return 0;
index 832f898edb6adc46aed452f2224be683427e6e8e..9d6ef6cb9b26334fa1dc9036d336e44d07946370 100644 (file)
@@ -1703,13 +1703,13 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
        parms.port_no = OVSP_LOCAL;
        parms.upcall_portids = a[OVS_DP_ATTR_UPCALL_PID];
 
-       err = ovs_dp_change(dp, a);
-       if (err)
-               goto err_destroy_meters;
-
        /* So far only local changes have been made, now need the lock. */
        ovs_lock();
 
+       err = ovs_dp_change(dp, a);
+       if (err)
+               goto err_unlock_and_destroy_meters;
+
        vport = new_vport(&parms);
        if (IS_ERR(vport)) {
                err = PTR_ERR(vport);
@@ -1725,8 +1725,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
                                ovs_dp_reset_user_features(skb, info);
                }
 
-               ovs_unlock();
-               goto err_destroy_meters;
+               goto err_unlock_and_destroy_meters;
        }
 
        err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
@@ -1741,7 +1740,8 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
        ovs_notify(&dp_datapath_genl_family, reply, info);
        return 0;
 
-err_destroy_meters:
+err_unlock_and_destroy_meters:
+       ovs_unlock();
        ovs_meters_exit(dp);
 err_destroy_ports:
        kfree(dp->ports);
index 9d3e50c4d29f964d2c32fe3324aadd8c7941ab8a..ec0689ddc6356babe4d26f484102ec60e3acd577 100644 (file)
@@ -2503,28 +2503,42 @@ static int validate_and_copy_dec_ttl(struct net *net,
                                     __be16 eth_type, __be16 vlan_tci,
                                     u32 mpls_label_count, bool log)
 {
-       int start, err;
-       u32 nested = true;
+       const struct nlattr *attrs[OVS_DEC_TTL_ATTR_MAX + 1];
+       int start, action_start, err, rem;
+       const struct nlattr *a, *actions;
+
+       memset(attrs, 0, sizeof(attrs));
+       nla_for_each_nested(a, attr, rem) {
+               int type = nla_type(a);
 
-       if (!nla_len(attr))
-               return ovs_nla_add_action(sfa, OVS_ACTION_ATTR_DEC_TTL,
-                                         NULL, 0, log);
+               /* Ignore unknown attributes to be future proof. */
+               if (type > OVS_DEC_TTL_ATTR_MAX)
+                       continue;
+
+               if (!type || attrs[type])
+                       return -EINVAL;
+
+               attrs[type] = a;
+       }
+
+       actions = attrs[OVS_DEC_TTL_ATTR_ACTION];
+       if (rem || !actions || (nla_len(actions) && nla_len(actions) < NLA_HDRLEN))
+               return -EINVAL;
 
        start = add_nested_action_start(sfa, OVS_ACTION_ATTR_DEC_TTL, log);
        if (start < 0)
                return start;
 
-       err = ovs_nla_add_action(sfa, OVS_DEC_TTL_ATTR_ACTION, &nested,
-                                sizeof(nested), log);
-
-       if (err)
-               return err;
+       action_start = add_nested_action_start(sfa, OVS_DEC_TTL_ATTR_ACTION, log);
+       if (action_start < 0)
+               return start;
 
-       err = __ovs_nla_copy_actions(net, attr, key, sfa, eth_type,
+       err = __ovs_nla_copy_actions(net, actions, key, sfa, eth_type,
                                     vlan_tci, mpls_label_count, log);
        if (err)
                return err;
 
+       add_nested_action_end(*sfa, action_start);
        add_nested_action_end(*sfa, start);
        return 0;
 }
@@ -3487,20 +3501,42 @@ out:
 static int dec_ttl_action_to_attr(const struct nlattr *attr,
                                  struct sk_buff *skb)
 {
-       int err = 0, rem = nla_len(attr);
-       struct nlattr *start;
+       struct nlattr *start, *action_start;
+       const struct nlattr *a;
+       int err = 0, rem;
 
        start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_DEC_TTL);
-
        if (!start)
                return -EMSGSIZE;
 
-       err = ovs_nla_put_actions(nla_data(attr), rem, skb);
-       if (err)
-               nla_nest_cancel(skb, start);
-       else
-               nla_nest_end(skb, start);
+       nla_for_each_attr(a, nla_data(attr), nla_len(attr), rem) {
+               switch (nla_type(a)) {
+               case OVS_DEC_TTL_ATTR_ACTION:
+
+                       action_start = nla_nest_start_noflag(skb, OVS_DEC_TTL_ATTR_ACTION);
+                       if (!action_start) {
+                               err = -EMSGSIZE;
+                               goto out;
+                       }
+
+                       err = ovs_nla_put_actions(nla_data(a), nla_len(a), skb);
+                       if (err)
+                               goto out;
+
+                       nla_nest_end(skb, action_start);
+                       break;
 
+               default:
+                       /* Ignore all other option to be future compatible */
+                       break;
+               }
+       }
+
+       nla_nest_end(skb, start);
+       return 0;
+
+out:
+       nla_nest_cancel(skb, start);
        return err;
 }
 
index f3486a37361a63875529f1250864ee18b836964d..c89c8da99f1a2ea234b5a5cbbc40c2635d181d4a 100644 (file)
@@ -390,7 +390,7 @@ static struct mask_cache *tbl_mask_cache_alloc(u32 size)
 }
 int ovs_flow_tbl_masks_cache_resize(struct flow_table *table, u32 size)
 {
-       struct mask_cache *mc = rcu_dereference(table->mask_cache);
+       struct mask_cache *mc = rcu_dereference_ovsl(table->mask_cache);
        struct mask_cache *new;
 
        if (size == mc->cache_size)
index cefbd50c1090f094f0556fab41ff28d0d96a81c7..7a18ffff855140e07dd64565f480dc0e8b95bd54 100644 (file)
@@ -93,8 +93,8 @@
 
 /*
    Assumptions:
-   - If the device has no dev->header_ops, there is no LL header visible
-     above the device. In this case, its hard_header_len should be 0.
+   - If the device has no dev->header_ops->create, there is no LL header
+     visible above the device. In this case, its hard_header_len should be 0.
      The device may prepend its own header internally. In this case, its
      needed_headroom should be set to the space needed for it to add its
      internal header.
 On receive:
 -----------
 
-Incoming, dev->header_ops != NULL
+Incoming, dev_has_header(dev) == true
    mac_header -> ll header
    data       -> data
 
-Outgoing, dev->header_ops != NULL
+Outgoing, dev_has_header(dev) == true
    mac_header -> ll header
    data       -> ll header
 
-Incoming, dev->header_ops == NULL
+Incoming, dev_has_header(dev) == false
    mac_header -> data
      However drivers often make it point to the ll header.
      This is incorrect because the ll header should be invisible to us.
    data       -> data
 
-Outgoing, dev->header_ops == NULL
+Outgoing, dev_has_header(dev) == false
    mac_header -> data. ll header is invisible to us.
    data       -> data
 
 Resume
-  If dev->header_ops == NULL we are unable to restore the ll header,
+  If dev_has_header(dev) == false we are unable to restore the ll header,
     because it is invisible to us.
 
 
@@ -2069,7 +2069,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
 
        skb->dev = dev;
 
-       if (dev->header_ops) {
+       if (dev_has_header(dev)) {
                /* The device has an explicit notion of ll header,
                 * exported to higher levels.
                 *
@@ -2198,7 +2198,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
        if (!net_eq(dev_net(dev), sock_net(sk)))
                goto drop;
 
-       if (dev->header_ops) {
+       if (dev_has_header(dev)) {
                if (sk->sk_type != SOCK_DGRAM)
                        skb_push(skb, skb->data - skb_mac_header(skb));
                else if (skb->pkt_type == PACKET_OUTGOING) {
index 06603dd1c8aa38d260644f66fa076febcbbdc8b9..b36b60668b1da9d6714f29e8e64e8facfeae434a 100644 (file)
@@ -956,9 +956,10 @@ int rds_ib_cm_initiate_connect(struct rdma_cm_id *cm_id, bool isv6)
        rds_ib_cm_fill_conn_param(conn, &conn_param, &dp,
                                  conn->c_proposed_version,
                                  UINT_MAX, UINT_MAX, isv6);
-       ret = rdma_connect(cm_id, &conn_param);
+       ret = rdma_connect_locked(cm_id, &conn_param);
        if (ret)
-               rds_ib_conn_error(conn, "rdma_connect failed (%d)\n", ret);
+               rds_ib_conn_error(conn, "rdma_connect_locked failed (%d)\n",
+                                 ret);
 
 out:
        /* Beware - returning non-zero tells the rdma_cm to destroy
index 971c73c7d34cbcab766cd7bae1e1305a909c25f4..97101c55763d7e9ccc648aa1a523d68c28859459 100644 (file)
@@ -876,6 +876,9 @@ static int rfkill_resume(struct device *dev)
 
        rfkill->suspended = false;
 
+       if (!rfkill->registered)
+               return 0;
+
        if (!rfkill->persistent) {
                cur = !!(rfkill->state & RFKILL_BLOCK_SW);
                rfkill_set_block(rfkill, cur);
index 7b094275ea8b4aec4542bd084bca86c962b70edc..11c45c8c6c1641781dd733e93e5453c2be75340b 100644 (file)
@@ -96,10 +96,19 @@ static void rose_loopback_timer(struct timer_list *unused)
                }
 
                if (frametype == ROSE_CALL_REQUEST) {
-                       if ((dev = rose_dev_get(dest)) != NULL) {
-                               if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0)
-                                       kfree_skb(skb);
-                       } else {
+                       if (!rose_loopback_neigh->dev) {
+                               kfree_skb(skb);
+                               continue;
+                       }
+
+                       dev = rose_dev_get(dest);
+                       if (!dev) {
+                               kfree_skb(skb);
+                               continue;
+                       }
+
+                       if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0) {
+                               dev_put(dev);
                                kfree_skb(skb);
                        }
                } else {
index f40bf9771cb9eb3e030c33147dc2a96d8637f5f6..d1486ea496a2cacaa6c141f12c13b3210743ecb7 100644 (file)
@@ -105,6 +105,9 @@ static int tcf_mpls_act(struct sk_buff *skb, const struct tc_action *a,
                        goto drop;
                break;
        case TCA_MPLS_ACT_MODIFY:
+               if (!pskb_may_pull(skb,
+                                  skb_network_offset(skb) + MPLS_HLEN))
+                       goto drop;
                new_lse = tcf_mpls_get_lse(mpls_hdr(skb), p, false);
                if (skb_mpls_update_lse(skb, new_lse))
                        goto drop;
@@ -426,6 +429,7 @@ static void __exit mpls_cleanup_module(void)
 module_init(mpls_init_module);
 module_exit(mpls_cleanup_module);
 
+MODULE_SOFTDEP("post: mpls_gso");
 MODULE_AUTHOR("Netronome Systems <oss-drivers@netronome.com>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("MPLS manipulation actions");
index faeabff283a2b6cb97ad84ff90af38455eae3292..838b3fd94d77683cf3164734300cf5d7b5631c47 100644 (file)
@@ -652,12 +652,12 @@ static void tc_block_indr_cleanup(struct flow_block_cb *block_cb)
                               block_cb->indr.binder_type,
                               &block->flow_block, tcf_block_shared(block),
                               &extack);
+       rtnl_lock();
        down_write(&block->cb_lock);
        list_del(&block_cb->driver_list);
        list_move(&block_cb->list, &bo.cb_list);
-       up_write(&block->cb_lock);
-       rtnl_lock();
        tcf_block_unbind(block, &bo);
+       up_write(&block->cb_lock);
        rtnl_unlock();
 }
 
index 84f82771cdf5dce6552bd790242a8c0b8b320e06..0c345e43a09a3738e15ab5de81ae37effcff01e5 100644 (file)
@@ -330,7 +330,7 @@ static s64 tabledist(s64 mu, s32 sigma,
 
        /* default uniform distribution */
        if (dist == NULL)
-               return ((rnd % (2 * sigma)) + mu) - sigma;
+               return ((rnd % (2 * (u32)sigma)) + mu) - sigma;
 
        t = dist->table[rnd % dist->size];
        x = (sigma % NETEM_DIST_SCALE) * t;
@@ -812,6 +812,10 @@ static void get_slot(struct netem_sched_data *q, const struct nlattr *attr)
                q->slot_config.max_packets = INT_MAX;
        if (q->slot_config.max_bytes == 0)
                q->slot_config.max_bytes = INT_MAX;
+
+       /* capping dist_jitter to the range acceptable by tabledist() */
+       q->slot_config.dist_jitter = min_t(__s64, INT_MAX, abs(q->slot_config.dist_jitter));
+
        q->slot.packets_left = q->slot_config.max_packets;
        q->slot.bytes_left = q->slot_config.max_bytes;
        if (q->slot_config.min_delay | q->slot_config.max_delay |
@@ -1037,6 +1041,9 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
        if (tb[TCA_NETEM_SLOT])
                get_slot(q, tb[TCA_NETEM_SLOT]);
 
+       /* capping jitter to the range acceptable by tabledist() */
+       q->jitter = min_t(s64, abs(q->jitter), INT_MAX);
+
        return ret;
 
 get_table_failure:
index 55d4fc6f371d6855d2af25bb559a0da7ac10a70f..d508f6f3dd08a33419c010d7944f9f70cacdd700 100644 (file)
@@ -449,7 +449,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
                else {
                        if (!mod_timer(&t->proto_unreach_timer,
                                                jiffies + (HZ/20)))
-                               sctp_association_hold(asoc);
+                               sctp_transport_hold(t);
                }
        } else {
                struct net *net = sock_net(sk);
@@ -458,7 +458,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
                         "encountered!\n", __func__);
 
                if (del_timer(&t->proto_unreach_timer))
-                       sctp_association_put(asoc);
+                       sctp_transport_put(t);
 
                sctp_do_sm(net, SCTP_EVENT_T_OTHER,
                           SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
index aa821e71f05e77532cd42237233820099dc2b80d..0948f14ce221a3c983b42f5036b7fbf6d7d4fc9c 100644 (file)
@@ -419,7 +419,7 @@ void sctp_generate_proto_unreach_event(struct timer_list *t)
                /* Try again later.  */
                if (!mod_timer(&transport->proto_unreach_timer,
                                jiffies + (HZ/20)))
-                       sctp_association_hold(asoc);
+                       sctp_transport_hold(transport);
                goto out_unlock;
        }
 
@@ -435,7 +435,7 @@ void sctp_generate_proto_unreach_event(struct timer_list *t)
 
 out_unlock:
        bh_unlock_sock(sk);
-       sctp_association_put(asoc);
+       sctp_transport_put(transport);
 }
 
  /* Handle the timeout of the RE-CONFIG timer. */
@@ -1601,12 +1601,12 @@ static int sctp_cmd_interpreter(enum sctp_event_type event_type,
                        break;
 
                case SCTP_CMD_INIT_FAILED:
-                       sctp_cmd_init_failed(commands, asoc, cmd->obj.u32);
+                       sctp_cmd_init_failed(commands, asoc, cmd->obj.u16);
                        break;
 
                case SCTP_CMD_ASSOC_FAILED:
                        sctp_cmd_assoc_failed(commands, asoc, event_type,
-                                             subtype, chunk, cmd->obj.u32);
+                                             subtype, chunk, cmd->obj.u16);
                        break;
 
                case SCTP_CMD_INIT_COUNTER_INC:
index 806af58f43758546af7fc9ebdfee5250d70a1caf..60fcf31cdcfb79da4eb3953e5b1baf527390a6cc 100644 (file)
@@ -133,7 +133,7 @@ void sctp_transport_free(struct sctp_transport *transport)
 
        /* Delete the ICMP proto unreachable timer if it's active. */
        if (del_timer(&transport->proto_unreach_timer))
-               sctp_association_put(transport->asoc);
+               sctp_transport_put(transport);
 
        sctp_transport_put(transport);
 }
index 82be0bd0f6e8135a5d159e8a1620ef23c3986413..5dd4faaf7d6e58a8f6195ec127193c2707d21597 100644 (file)
@@ -979,7 +979,8 @@ static int __smc_connect(struct smc_sock *smc)
 
        /* check if smc modes and versions of CLC proposal and accept match */
        rc = smc_connect_check_aclc(ini, aclc);
-       version = aclc->hdr.version == SMC_V1 ? SMC_V1 : version;
+       version = aclc->hdr.version == SMC_V1 ? SMC_V1 : SMC_V2;
+       ini->smcd_version = version;
        if (rc)
                goto vlan_cleanup;
 
@@ -1317,10 +1318,10 @@ static void smc_listen_out_err(struct smc_sock *new_smc)
 
 /* listen worker: decline and fall back if possible */
 static void smc_listen_decline(struct smc_sock *new_smc, int reason_code,
-                              struct smc_init_info *ini, u8 version)
+                              int local_first, u8 version)
 {
        /* RDMA setup failed, switch back to TCP */
-       if (ini->first_contact_local)
+       if (local_first)
                smc_lgr_cleanup_early(&new_smc->conn);
        else
                smc_conn_free(&new_smc->conn);
@@ -1768,7 +1769,8 @@ static void smc_listen_work(struct work_struct *work)
 out_unlock:
        mutex_unlock(&smc_server_lgr_pending);
 out_decl:
-       smc_listen_decline(new_smc, rc, ini, version);
+       smc_listen_decline(new_smc, rc, ini ? ini->first_contact_local : 0,
+                          version);
 out_free:
        kfree(ini);
        kfree(buf);
index b3f46ab79e47217b02c983bec0fd6f17a210ced6..c579d1d5995a9e94c608eb4f3db521c97d471f5d 100644 (file)
@@ -124,7 +124,7 @@ struct smc_clc_v2_extension {
        struct smc_clnt_opts_area_hdr hdr;
        u8 roce[16];            /* RoCEv2 GID */
        u8 reserved[16];
-       u8 user_eids[0][SMC_MAX_EID_LEN];
+       u8 user_eids[][SMC_MAX_EID_LEN];
 };
 
 struct smc_clc_msg_proposal_prefix {   /* prefix part of clc proposal message*/
@@ -143,7 +143,7 @@ struct smc_clc_msg_smcd {   /* SMC-D GID information */
 struct smc_clc_smcd_v2_extension {
        u8 system_eid[SMC_MAX_EID_LEN];
        u8 reserved[16];
-       struct smc_clc_smcd_gid_chid gidchid[0];
+       struct smc_clc_smcd_gid_chid gidchid[];
 };
 
 struct smc_clc_msg_proposal {  /* clc proposal message sent by Linux */
index d790c43c473f2a5881d572d11a74067e3ae878f6..af96f813c075281f02784ae04413fa03382aae1b 100644 (file)
@@ -1309,7 +1309,8 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
                                    ini->ism_peer_gid[ini->ism_selected]) :
                     smcr_lgr_match(lgr, ini->ib_lcl, role, ini->ib_clcqpn)) &&
                    !lgr->sync_err &&
-                   lgr->vlan_id == ini->vlan_id &&
+                   (ini->smcd_version == SMC_V2 ||
+                    lgr->vlan_id == ini->vlan_id) &&
                    (role == SMC_CLNT || ini->is_smcd ||
                     lgr->conns_num < SMC_RMBS_PER_LGR_MAX)) {
                        /* link group found */
@@ -1615,8 +1616,11 @@ static struct smc_buf_desc *smcd_new_buf_create(struct smc_link_group *lgr,
                rc = smc_ism_register_dmb(lgr, bufsize, buf_desc);
                if (rc) {
                        kfree(buf_desc);
-                       return (rc == -ENOMEM) ? ERR_PTR(-EAGAIN) :
-                                                ERR_PTR(-EIO);
+                       if (rc == -ENOMEM)
+                               return ERR_PTR(-EAGAIN);
+                       if (rc == -ENOSPC)
+                               return ERR_PTR(-ENOSPC);
+                       return ERR_PTR(-EIO);
                }
                buf_desc->pages = virt_to_page(buf_desc->cpu_addr);
                /* CDC header stored in buf. So, pretend it was smaller */
index 1c314dbdc7faa450ead0cf45279f87a97f26f603..fc766b537ac7a9c2b36272c7f9b03e567b7bc6d0 100644 (file)
@@ -198,9 +198,9 @@ int smc_ib_determine_gid(struct smc_ib_device *smcibdev, u8 ibport,
                rcu_read_lock();
                ndev = rdma_read_gid_attr_ndev_rcu(attr);
                if (!IS_ERR(ndev) &&
-                   ((!vlan_id && !is_vlan_dev(attr->ndev)) ||
-                    (vlan_id && is_vlan_dev(attr->ndev) &&
-                     vlan_dev_vlan_id(attr->ndev) == vlan_id)) &&
+                   ((!vlan_id && !is_vlan_dev(ndev)) ||
+                    (vlan_id && is_vlan_dev(ndev) &&
+                     vlan_dev_vlan_id(ndev) == vlan_id)) &&
                    attr->gid_type == IB_GID_TYPE_ROCE) {
                        rcu_read_unlock();
                        if (gid)
index a18b36b5422d49b278e94793c6653b81fbc7c142..3aad6ef1850452adb533c8bb1691f38224ea0428 100644 (file)
@@ -63,19 +63,20 @@ static int proc_do_xprt(struct ctl_table *table, int write,
                        void *buffer, size_t *lenp, loff_t *ppos)
 {
        char tmpbuf[256];
-       size_t len;
+       ssize_t len;
 
-       if ((*ppos && !write) || !*lenp) {
+       if (write || *ppos) {
                *lenp = 0;
                return 0;
        }
        len = svc_print_xprts(tmpbuf, sizeof(tmpbuf));
-       *lenp = memory_read_from_buffer(buffer, *lenp, ppos, tmpbuf, len);
+       len = memory_read_from_buffer(buffer, *lenp, ppos, tmpbuf, len);
 
-       if (*lenp < 0) {
+       if (len < 0) {
                *lenp = 0;
                return -EINVAL;
        }
+       *lenp = len;
        return 0;
 }
 
index 2a78aa70157281f1e9771f0bcc426fa73d862cb3..32c79c59052b688e93e9697f67623831169a1299 100644 (file)
@@ -150,12 +150,11 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
        if (fragid == FIRST_FRAGMENT) {
                if (unlikely(head))
                        goto err;
-               if (skb_cloned(frag))
-                       frag = skb_copy(frag, GFP_ATOMIC);
+               *buf = NULL;
+               frag = skb_unshare(frag, GFP_ATOMIC);
                if (unlikely(!frag))
                        goto err;
                head = *headbuf = frag;
-               *buf = NULL;
                TIPC_SKB_CB(head)->tail = NULL;
                if (skb_is_nonlinear(head)) {
                        skb_walk_frags(head, tail) {
index d269ebe382e1fb9cea17e4ad5f3021bfad111f37..c95d037fde51eafcf95991e84cd4c0c1cff27bbc 100644 (file)
@@ -2182,6 +2182,8 @@ void tipc_node_apply_property(struct net *net, struct tipc_bearer *b,
                        else if (prop == TIPC_NLA_PROP_MTU)
                                tipc_link_set_mtu(e->link, b->mtu);
                }
+               /* Update MTU for node link entry */
+               e->mtu = tipc_link_mss(e->link);
                tipc_node_write_unlock(n);
                tipc_bearer_xmit(net, bearer_id, &xmitq, &e->maddr, NULL);
        }
index 5f6f86051c83011f623731b2c9207b7a35781ec8..13f3143609f9ef8e358010f5e9d0564c13a4e87f 100644 (file)
@@ -664,12 +664,18 @@ static int tipc_topsrv_start(struct net *net)
 
        ret = tipc_topsrv_work_start(srv);
        if (ret < 0)
-               return ret;
+               goto err_start;
 
        ret = tipc_topsrv_create_listener(srv);
        if (ret < 0)
-               tipc_topsrv_work_stop(srv);
+               goto err_create;
 
+       return 0;
+
+err_create:
+       tipc_topsrv_work_stop(srv);
+err_start:
+       kfree(srv);
        return ret;
 }
 
index cec86229a6a02b35670e00ee584a1d03a903ddba..a3ab2d3d4e4eac56426b23d87d83fafb18c4c0d7 100644 (file)
@@ -694,36 +694,51 @@ static void tls_device_resync_rx(struct tls_context *tls_ctx,
 
 static bool
 tls_device_rx_resync_async(struct tls_offload_resync_async *resync_async,
-                          s64 resync_req, u32 *seq)
+                          s64 resync_req, u32 *seq, u16 *rcd_delta)
 {
        u32 is_async = resync_req & RESYNC_REQ_ASYNC;
        u32 req_seq = resync_req >> 32;
        u32 req_end = req_seq + ((resync_req >> 16) & 0xffff);
+       u16 i;
+
+       *rcd_delta = 0;
 
        if (is_async) {
+               /* shouldn't get to wraparound:
+                * too long in async stage, something bad happened
+                */
+               if (WARN_ON_ONCE(resync_async->rcd_delta == USHRT_MAX))
+                       return false;
+
                /* asynchronous stage: log all headers seq such that
                 * req_seq <= seq <= end_seq, and wait for real resync request
                 */
-               if (between(*seq, req_seq, req_end) &&
+               if (before(*seq, req_seq))
+                       return false;
+               if (!after(*seq, req_end) &&
                    resync_async->loglen < TLS_DEVICE_RESYNC_ASYNC_LOGMAX)
                        resync_async->log[resync_async->loglen++] = *seq;
 
+               resync_async->rcd_delta++;
+
                return false;
        }
 
        /* synchronous stage: check against the logged entries and
         * proceed to check the next entries if no match was found
         */
-       while (resync_async->loglen) {
-               if (req_seq == resync_async->log[resync_async->loglen - 1] &&
-                   atomic64_try_cmpxchg(&resync_async->req,
-                                        &resync_req, 0)) {
-                       resync_async->loglen = 0;
+       for (i = 0; i < resync_async->loglen; i++)
+               if (req_seq == resync_async->log[i] &&
+                   atomic64_try_cmpxchg(&resync_async->req, &resync_req, 0)) {
+                       *rcd_delta = resync_async->rcd_delta - i;
                        *seq = req_seq;
+                       resync_async->loglen = 0;
+                       resync_async->rcd_delta = 0;
                        return true;
                }
-               resync_async->loglen--;
-       }
+
+       resync_async->loglen = 0;
+       resync_async->rcd_delta = 0;
 
        if (req_seq == *seq &&
            atomic64_try_cmpxchg(&resync_async->req,
@@ -741,6 +756,7 @@ void tls_device_rx_resync_new_rec(struct sock *sk, u32 rcd_len, u32 seq)
        u32 sock_data, is_req_pending;
        struct tls_prot_info *prot;
        s64 resync_req;
+       u16 rcd_delta;
        u32 req_seq;
 
        if (tls_ctx->rx_conf != TLS_HW)
@@ -786,8 +802,9 @@ void tls_device_rx_resync_new_rec(struct sock *sk, u32 rcd_len, u32 seq)
                        return;
 
                if (!tls_device_rx_resync_async(rx_ctx->resync_async,
-                                               resync_req, &seq))
+                                               resync_req, &seq, &rcd_delta))
                        return;
+               tls_bigint_subtract(rcd_sn, rcd_delta);
                break;
        }
 
@@ -1245,6 +1262,8 @@ void tls_device_offload_cleanup_rx(struct sock *sk)
        if (tls_ctx->tx_conf != TLS_HW) {
                dev_put(netdev);
                tls_ctx->netdev = NULL;
+       } else {
+               set_bit(TLS_RX_DEV_CLOSED, &tls_ctx->flags);
        }
 out:
        up_read(&device_offload_lock);
@@ -1274,7 +1293,8 @@ static int tls_device_down(struct net_device *netdev)
                if (ctx->tx_conf == TLS_HW)
                        netdev->tlsdev_ops->tls_dev_del(netdev, ctx,
                                                        TLS_OFFLOAD_CTX_DIR_TX);
-               if (ctx->rx_conf == TLS_HW)
+               if (ctx->rx_conf == TLS_HW &&
+                   !test_bit(TLS_RX_DEV_CLOSED, &ctx->flags))
                        netdev->tlsdev_ops->tls_dev_del(netdev, ctx,
                                                        TLS_OFFLOAD_CTX_DIR_RX);
                WRITE_ONCE(ctx->netdev, NULL);
index 95ab5545a9313601286efdadd44bb1affef422cd..845c628ac1b2717f6c9a4ef855c64924f0c847a0 100644 (file)
@@ -1295,6 +1295,12 @@ static struct sk_buff *tls_wait_data(struct sock *sk, struct sk_psock *psock,
                        return NULL;
                }
 
+               if (!skb_queue_empty(&sk->sk_receive_queue)) {
+                       __strp_unpause(&ctx->strp);
+                       if (ctx->recv_pkt)
+                               return ctx->recv_pkt;
+               }
+
                if (sk->sk_shutdown & RCV_SHUTDOWN)
                        return NULL;
 
@@ -1913,7 +1919,7 @@ pick_next_record:
                         * another message type
                         */
                        msg->msg_flags |= MSG_EOR;
-                       if (ctx->control != TLS_RECORD_TYPE_DATA)
+                       if (control != TLS_RECORD_TYPE_DATA)
                                goto recv_end;
                } else {
                        break;
index 9e93bc201cc07b26285e7f10d5502a2a6166db6b..d10916ab452679904e9fcf6525271d745f604e58 100644 (file)
@@ -438,7 +438,7 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
        case SOCK_STREAM:
                if (vsock_use_local_transport(remote_cid))
                        new_transport = transport_local;
-               else if (remote_cid <= VMADDR_CID_HOST)
+               else if (remote_cid <= VMADDR_CID_HOST || !transport_h2g)
                        new_transport = transport_g2h;
                else
                        new_transport = transport_h2g;
@@ -739,7 +739,7 @@ static struct sock *__vsock_create(struct net *net,
                vsk->buffer_min_size = psk->buffer_min_size;
                vsk->buffer_max_size = psk->buffer_max_size;
        } else {
-               vsk->trusted = capable(CAP_NET_ADMIN);
+               vsk->trusted = ns_capable_noaudit(&init_user_ns, CAP_NET_ADMIN);
                vsk->owner = get_current_cred();
                vsk->connect_timeout = VSOCK_DEFAULT_CONNECT_TIMEOUT;
                vsk->buffer_size = VSOCK_DEFAULT_BUFFER_SIZE;
index 0edda1edf9882f702b9073bf82481f01eca630f0..5956939eebb780ce1f1e17e1a15b2a85808f295c 100644 (file)
@@ -841,8 +841,10 @@ void virtio_transport_release(struct vsock_sock *vsk)
                virtio_transport_free_pkt(pkt);
        }
 
-       if (remove_sock)
+       if (remove_sock) {
+               sock_set_flag(sk, SOCK_DONE);
                vsock_remove_sock(vsk);
+       }
 }
 EXPORT_SYMBOL_GPL(virtio_transport_release);
 
@@ -1132,8 +1134,8 @@ void virtio_transport_recv_pkt(struct virtio_transport *t,
 
        lock_sock(sk);
 
-       /* Check if sk has been released before lock_sock */
-       if (sk->sk_shutdown == SHUTDOWN_MASK) {
+       /* Check if sk has been closed before lock_sock */
+       if (sock_flag(sk, SOCK_DONE)) {
                (void)virtio_transport_reset_no_sock(t, pkt);
                release_sock(sk);
                sock_put(sk);
index 9f23923e8d29b781d66bd264da00ac7ef2807c94..240282c083aa746a55f5998dbfd6ec356a404985 100644 (file)
@@ -1250,8 +1250,7 @@ void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev,
 }
 EXPORT_SYMBOL(cfg80211_stop_iface);
 
-void cfg80211_init_wdev(struct cfg80211_registered_device *rdev,
-                       struct wireless_dev *wdev)
+void cfg80211_init_wdev(struct wireless_dev *wdev)
 {
        mutex_init(&wdev->mtx);
        INIT_LIST_HEAD(&wdev->event_list);
@@ -1262,6 +1261,30 @@ void cfg80211_init_wdev(struct cfg80211_registered_device *rdev,
        spin_lock_init(&wdev->pmsr_lock);
        INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk);
 
+#ifdef CONFIG_CFG80211_WEXT
+       wdev->wext.default_key = -1;
+       wdev->wext.default_mgmt_key = -1;
+       wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
+#endif
+
+       if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT)
+               wdev->ps = true;
+       else
+               wdev->ps = false;
+       /* allow mac80211 to determine the timeout */
+       wdev->ps_timeout = -1;
+
+       if ((wdev->iftype == NL80211_IFTYPE_STATION ||
+            wdev->iftype == NL80211_IFTYPE_P2P_CLIENT ||
+            wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
+               wdev->netdev->priv_flags |= IFF_DONT_BRIDGE;
+
+       INIT_WORK(&wdev->disconnect_wk, cfg80211_autodisconnect_wk);
+}
+
+void cfg80211_register_wdev(struct cfg80211_registered_device *rdev,
+                           struct wireless_dev *wdev)
+{
        /*
         * We get here also when the interface changes network namespaces,
         * as it's registered into the new one, but we don't want it to
@@ -1295,6 +1318,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
        switch (state) {
        case NETDEV_POST_INIT:
                SET_NETDEV_DEVTYPE(dev, &wiphy_type);
+               wdev->netdev = dev;
+               /* can only change netns with wiphy */
+               dev->features |= NETIF_F_NETNS_LOCAL;
+
+               cfg80211_init_wdev(wdev);
                break;
        case NETDEV_REGISTER:
                /*
@@ -1302,35 +1330,12 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                 * called within code protected by it when interfaces
                 * are added with nl80211.
                 */
-               /* can only change netns with wiphy */
-               dev->features |= NETIF_F_NETNS_LOCAL;
-
                if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj,
                                      "phy80211")) {
                        pr_err("failed to add phy80211 symlink to netdev!\n");
                }
-               wdev->netdev = dev;
-#ifdef CONFIG_CFG80211_WEXT
-               wdev->wext.default_key = -1;
-               wdev->wext.default_mgmt_key = -1;
-               wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
-#endif
-
-               if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT)
-                       wdev->ps = true;
-               else
-                       wdev->ps = false;
-               /* allow mac80211 to determine the timeout */
-               wdev->ps_timeout = -1;
-
-               if ((wdev->iftype == NL80211_IFTYPE_STATION ||
-                    wdev->iftype == NL80211_IFTYPE_P2P_CLIENT ||
-                    wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
-                       dev->priv_flags |= IFF_DONT_BRIDGE;
-
-               INIT_WORK(&wdev->disconnect_wk, cfg80211_autodisconnect_wk);
 
-               cfg80211_init_wdev(rdev, wdev);
+               cfg80211_register_wdev(rdev, wdev);
                break;
        case NETDEV_GOING_DOWN:
                cfg80211_leave(rdev, wdev);
index e1ec9ac8e608bdf03962663dc3ecc8ef918a4502..e3e9686859d459d9d6750695695b05339a50d49a 100644 (file)
@@ -209,8 +209,9 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
 int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
                          struct net *net);
 
-void cfg80211_init_wdev(struct cfg80211_registered_device *rdev,
-                       struct wireless_dev *wdev);
+void cfg80211_init_wdev(struct wireless_dev *wdev);
+void cfg80211_register_wdev(struct cfg80211_registered_device *rdev,
+                           struct wireless_dev *wdev);
 
 static inline void wdev_lock(struct wireless_dev *wdev)
        __acquires(wdev)
index 554796a6c6fe5dcb3461d688f12a08a19a4a92cf..a77174b99b07e8fbd863e50c159501e5d26e0224 100644 (file)
@@ -3885,7 +3885,8 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
                 * P2P Device and NAN do not have a netdev, so don't go
                 * through the netdev notifier and must be added here
                 */
-               cfg80211_init_wdev(rdev, wdev);
+               cfg80211_init_wdev(wdev);
+               cfg80211_register_wdev(rdev, wdev);
                break;
        default:
                break;
index 3dab859641e1a0e7f5a66ab1ca560d862754b1c5..a04fdfb35f070eeed7b558f8a696db27daf4afa9 100644 (file)
@@ -3616,7 +3616,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
                power_rule = &reg_rule->power_rule;
 
                if (reg_rule->flags & NL80211_RRF_AUTO_BW)
-                       snprintf(bw, sizeof(bw), "%d KHz, %d KHz AUTO",
+                       snprintf(bw, sizeof(bw), "%d KHz, %u KHz AUTO",
                                 freq_range->max_bandwidth_khz,
                                 reg_get_max_bandwidth(rd, reg_rule));
                else
index 0bbb283f23c96ff434d9f7c427971ed44236c3af..e65a50192432c8b031d6f25b76337a84057cc173 100644 (file)
@@ -681,7 +681,8 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        int len, i, rc = 0;
 
        if (addr_len != sizeof(struct sockaddr_x25) ||
-           addr->sx25_family != AF_X25) {
+           addr->sx25_family != AF_X25 ||
+           strnlen(addr->sx25_addr.x25_addr, X25_ADDR_LEN) == X25_ADDR_LEN) {
                rc = -EINVAL;
                goto out;
        }
@@ -775,7 +776,8 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
 
        rc = -EINVAL;
        if (addr_len != sizeof(struct sockaddr_x25) ||
-           addr->sx25_family != AF_X25)
+           addr->sx25_family != AF_X25 ||
+           strnlen(addr->sx25_addr.x25_addr, X25_ADDR_LEN) == X25_ADDR_LEN)
                goto out;
 
        rc = -ENETUNREACH;
@@ -825,7 +827,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
        sock->state = SS_CONNECTED;
        rc = 0;
 out_put_neigh:
-       if (rc) {
+       if (rc && x25->neighbour) {
                read_lock_bh(&x25_list_lock);
                x25_neigh_put(x25->neighbour);
                x25->neighbour = NULL;
@@ -1050,6 +1052,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
        makex25->lci           = lci;
        makex25->dest_addr     = dest_addr;
        makex25->source_addr   = source_addr;
+       x25_neigh_hold(nb);
        makex25->neighbour     = nb;
        makex25->facilities    = facilities;
        makex25->dte_facilities= dte_facilities;
index 56d052bc65cb5bbe30eabcb532f9325c76b44872..56a28a686988d5590b45aa8e6fa967c2184472c3 100644 (file)
@@ -66,18 +66,31 @@ static void xdp_umem_release(struct xdp_umem *umem)
        kfree(umem);
 }
 
+static void xdp_umem_release_deferred(struct work_struct *work)
+{
+       struct xdp_umem *umem = container_of(work, struct xdp_umem, work);
+
+       xdp_umem_release(umem);
+}
+
 void xdp_get_umem(struct xdp_umem *umem)
 {
        refcount_inc(&umem->users);
 }
 
-void xdp_put_umem(struct xdp_umem *umem)
+void xdp_put_umem(struct xdp_umem *umem, bool defer_cleanup)
 {
        if (!umem)
                return;
 
-       if (refcount_dec_and_test(&umem->users))
-               xdp_umem_release(umem);
+       if (refcount_dec_and_test(&umem->users)) {
+               if (defer_cleanup) {
+                       INIT_WORK(&umem->work, xdp_umem_release_deferred);
+                       schedule_work(&umem->work);
+               } else {
+                       xdp_umem_release(umem);
+               }
+       }
 }
 
 static int xdp_umem_pin_pages(struct xdp_umem *umem, unsigned long address)
index 181fdda2f2a84c9f213a62615115afeaa219405c..aa9fe2780410e77aaf45bba9781a619a195e9c91 100644 (file)
@@ -9,7 +9,7 @@
 #include <net/xdp_sock_drv.h>
 
 void xdp_get_umem(struct xdp_umem *umem);
-void xdp_put_umem(struct xdp_umem *umem);
+void xdp_put_umem(struct xdp_umem *umem, bool defer_cleanup);
 struct xdp_umem *xdp_umem_create(struct xdp_umem_reg *mr);
 
 #endif /* XDP_UMEM_H_ */
index b71a32eeae65b2cb863c2ade8656ad969c813458..b7b039bd9d03dfe0c003f41ff5b9f5954c6557b9 100644 (file)
@@ -411,11 +411,7 @@ static int xsk_generic_xmit(struct sock *sk)
                skb_shinfo(skb)->destructor_arg = (void *)(long)desc.addr;
                skb->destructor = xsk_destruct_skb;
 
-               /* Hinder dev_direct_xmit from freeing the packet and
-                * therefore completing it in the destructor
-                */
-               refcount_inc(&skb->users);
-               err = dev_direct_xmit(skb, xs->queue_id);
+               err = __dev_direct_xmit(skb, xs->queue_id);
                if  (err == NETDEV_TX_BUSY) {
                        /* Tell user-space to retry the send */
                        skb->destructor = sock_wfree;
@@ -429,12 +425,10 @@ static int xsk_generic_xmit(struct sock *sk)
                /* Ignore NET_XMIT_CN as packet might have been sent */
                if (err == NET_XMIT_DROP) {
                        /* SKB completed but not sent */
-                       kfree_skb(skb);
                        err = -EBUSY;
                        goto out;
                }
 
-               consume_skb(skb);
                sent_frame = true;
        }
 
@@ -1146,7 +1140,8 @@ static void xsk_destruct(struct sock *sk)
        if (!sock_flag(sk, SOCK_DEAD))
                return;
 
-       xp_put_pool(xs->pool);
+       if (!xp_put_pool(xs->pool))
+               xdp_put_umem(xs->umem, !xs->pool);
 
        sk_refcnt_debug_dec(sk);
 }
index 64c9e55d4d4e78c063520aceea6a4e4d6140a1b8..9287eddec52c1e73a8b8fe45fdbf9edac74117b1 100644 (file)
@@ -185,8 +185,10 @@ err_unreg_xsk:
 err_unreg_pool:
        if (!force_zc)
                err = 0; /* fallback to copy mode */
-       if (err)
+       if (err) {
                xsk_clear_pool_at_qid(netdev, queue_id);
+               dev_put(netdev);
+       }
        return err;
 }
 
@@ -242,7 +244,7 @@ static void xp_release_deferred(struct work_struct *work)
                pool->cq = NULL;
        }
 
-       xdp_put_umem(pool->umem);
+       xdp_put_umem(pool->umem, false);
        xp_destroy(pool);
 }
 
@@ -251,15 +253,18 @@ void xp_get_pool(struct xsk_buff_pool *pool)
        refcount_inc(&pool->users);
 }
 
-void xp_put_pool(struct xsk_buff_pool *pool)
+bool xp_put_pool(struct xsk_buff_pool *pool)
 {
        if (!pool)
-               return;
+               return false;
 
        if (refcount_dec_and_test(&pool->users)) {
                INIT_WORK(&pool->work, xp_release_deferred);
                schedule_work(&pool->work);
+               return true;
        }
+
+       return false;
 }
 
 static struct xsk_dma_map *xp_find_dma_map(struct xsk_buff_pool *pool)
index aa4cdcf69d471e63ec712810edaa78008572a9e9..9b8e292a7c6a7525f509d9ae730652769892f1ce 100644 (file)
@@ -803,14 +803,14 @@ static struct xfrm6_tunnel xfrmi_ipv6_handler __read_mostly = {
        .handler        =       xfrmi6_rcv_tunnel,
        .cb_handler     =       xfrmi_rcv_cb,
        .err_handler    =       xfrmi6_err,
-       .priority       =       -1,
+       .priority       =       2,
 };
 
 static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = {
        .handler        =       xfrmi6_rcv_tunnel,
        .cb_handler     =       xfrmi_rcv_cb,
        .err_handler    =       xfrmi6_err,
-       .priority       =       -1,
+       .priority       =       2,
 };
 #endif
 
@@ -848,14 +848,14 @@ static struct xfrm_tunnel xfrmi_ipip_handler __read_mostly = {
        .handler        =       xfrmi4_rcv_tunnel,
        .cb_handler     =       xfrmi_rcv_cb,
        .err_handler    =       xfrmi4_err,
-       .priority       =       -1,
+       .priority       =       3,
 };
 
 static struct xfrm_tunnel xfrmi_ipip6_handler __read_mostly = {
        .handler        =       xfrmi4_rcv_tunnel,
        .cb_handler     =       xfrmi_rcv_cb,
        .err_handler    =       xfrmi4_err,
-       .priority       =       -1,
+       .priority       =       2,
 };
 #endif
 
index bbd4643d7e824f17d6d9e45e242b000239227b3b..a77da7aae6fe845a6fd1253a4e6d98be53ec6aec 100644 (file)
@@ -2004,6 +2004,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
        int err = -ENOENT;
        __be32 minspi = htonl(low);
        __be32 maxspi = htonl(high);
+       __be32 newspi = 0;
        u32 mark = x->mark.v & x->mark.m;
 
        spin_lock_bh(&x->lock);
@@ -2022,21 +2023,22 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
                        xfrm_state_put(x0);
                        goto unlock;
                }
-               x->id.spi = minspi;
+               newspi = minspi;
        } else {
                u32 spi = 0;
                for (h = 0; h < high-low+1; h++) {
                        spi = low + prandom_u32()%(high-low+1);
                        x0 = xfrm_state_lookup(net, mark, &x->id.daddr, htonl(spi), x->id.proto, x->props.family);
                        if (x0 == NULL) {
-                               x->id.spi = htonl(spi);
+                               newspi = htonl(spi);
                                break;
                        }
                        xfrm_state_put(x0);
                }
        }
-       if (x->id.spi) {
+       if (newspi) {
                spin_lock_bh(&net->xfrm.xfrm_state_lock);
+               x->id.spi = newspi;
                h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family);
                hlist_add_head_rcu(&x->byspi, net->xfrm.state_byspi + h);
                spin_unlock_bh(&net->xfrm.xfrm_state_lock);
index 4a74531dc403105d0dac2204367af32652d48fd2..b68bd2f8fdc924a5df2f32a12b4974d60c0b99ec 100644 (file)
@@ -290,7 +290,7 @@ static int test_debug_fs_uprobe(char *binary_path, long offset, bool is_return)
 
 int main(int argc, char **argv)
 {
-       struct rlimit r = {1024*1024, RLIM_INFINITY};
+       struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
        extern char __executable_start;
        char filename[256], buf[256];
        __u64 uprobe_file_offset;
index 3e36b3e4e3efdb282abb08262ce1a86a880fce19..3d6eab711d23e11158855ea9c6074ad184a916ef 100644 (file)
@@ -116,7 +116,7 @@ static void int_exit(int sig)
 
 int main(int ac, char **argv)
 {
-       struct rlimit r = {1024*1024, RLIM_INFINITY};
+       struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
        long key, next_key, value;
        struct bpf_link *links[2];
        struct bpf_program *prog;
index 70e987775c156f90e9c9a383fe1252a6c37b249f..83e0fecbb01ace489ba038522fd1b8c3d695301d 100644 (file)
@@ -107,7 +107,7 @@ static void print_hist(int fd)
 
 int main(int ac, char **argv)
 {
-       struct rlimit r = {1024*1024, RLIM_INFINITY};
+       struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
        struct bpf_link *links[2];
        struct bpf_program *prog;
        struct bpf_object *obj;
index 6fb8dbde62c5e0e5f0f760fb221dd6640c7eaa9e..f78cb18319aaf9d17346c0d8906de761ea27787a 100644 (file)
@@ -765,7 +765,7 @@ static int load_cpumap_prog(char *file_name, char *prog_name,
 
 int main(int argc, char **argv)
 {
-       struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY};
+       struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
        char *prog_name = "xdp_cpu_map5_lb_hash_ip_pairs";
        char *mprog_filename = "xdp_redirect_kern.o";
        char *redir_interface = NULL, *redir_map = NULL;
index caa4e7ffcfc7b85eeb04b6320c6b665b99d7db37..93fa1bc54f131eb5c441e0899fec3c53ea0f9a1c 100644 (file)
@@ -450,7 +450,7 @@ static void stats_poll(int interval, int action, __u32 cfg_opt)
 int main(int argc, char **argv)
 {
        __u32 cfg_options= NO_TOUCH ; /* Default: Don't touch packet memory */
-       struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY};
+       struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
        struct bpf_prog_load_attr prog_load_attr = {
                .prog_type      = BPF_PROG_TYPE_XDP,
        };
index c13a5bc5095bea5cb1dbb1fba19ef3a49ce4cf08..5b9a09957c6e0e653590affbf1b214b7328262f5 100644 (file)
@@ -21,6 +21,7 @@ static unsigned long my_ip = (unsigned long)schedule;
 asm (
 "      .pushsection    .text, \"ax\", @progbits\n"
 "      .type           my_tramp1, @function\n"
+"      .globl          my_tramp1\n"
 "   my_tramp1:"
 "      pushq %rbp\n"
 "      movq %rsp, %rbp\n"
@@ -29,6 +30,7 @@ asm (
 "      .size           my_tramp1, .-my_tramp1\n"
 "      ret\n"
 "      .type           my_tramp2, @function\n"
+"      .globl          my_tramp2\n"
 "   my_tramp2:"
 "      pushq %rbp\n"
 "      movq %rsp, %rbp\n"
index d5c5022be66429be712c530eafdea7ce86299244..3f0079c9bd6fa2bb99e303731d34911b4f8f035f 100644 (file)
@@ -16,6 +16,7 @@ extern void my_tramp(void *);
 asm (
 "      .pushsection    .text, \"ax\", @progbits\n"
 "      .type           my_tramp, @function\n"
+"      .globl          my_tramp\n"
 "   my_tramp:"
 "      pushq %rbp\n"
 "      movq %rsp, %rbp\n"
index 63ca06d42c803ff8ad846d446f91be45bd71d000..a2729d1ef17f538e66aa2e443b286c0560dee99f 100644 (file)
@@ -14,6 +14,7 @@ extern void my_tramp(void *);
 asm (
 "      .pushsection    .text, \"ax\", @progbits\n"
 "      .type           my_tramp, @function\n"
+"      .globl          my_tramp\n"
 "   my_tramp:"
 "      pushq %rbp\n"
 "      movq %rsp, %rbp\n"
diff --git a/samples/mic/mpssd/.gitignore b/samples/mic/mpssd/.gitignore
deleted file mode 100644 (file)
index aa03f1e..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-mpssd
diff --git a/samples/mic/mpssd/Makefile b/samples/mic/mpssd/Makefile
deleted file mode 100644 (file)
index a7a6e0c..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-ifndef CROSS_COMPILE
-uname_M := $(shell uname -m 2>/dev/null || echo not)
-ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
-
-ifeq ($(ARCH),x86)
-
-PROGS := mpssd
-CC = $(CROSS_COMPILE)gcc
-CFLAGS := -I../../../usr/include -I../../../tools/include
-
-ifdef DEBUG
-CFLAGS += -DDEBUG=$(DEBUG)
-endif
-
-all: $(PROGS)
-mpssd: mpssd.c sysfs.c
-       $(CC) $(CFLAGS) mpssd.c sysfs.c -o mpssd -lpthread
-
-install:
-       install mpssd /usr/sbin/mpssd
-       install micctrl /usr/sbin/micctrl
-
-clean:
-       rm -fr $(PROGS)
-
-endif
-endif
diff --git a/samples/mic/mpssd/micctrl b/samples/mic/mpssd/micctrl
deleted file mode 100755 (executable)
index 030a60b..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: GPL-2.0-only
-# Intel MIC Platform Software Stack (MPSS)
-#
-# Copyright(c) 2013 Intel Corporation.
-#
-# Intel MIC User Space Tools.
-#
-# micctrl - Controls MIC boot/start/stop.
-#
-# chkconfig: 2345 95 05
-# description: start MPSS stack processing.
-#
-### BEGIN INIT INFO
-# Provides: micctrl
-### END INIT INFO
-
-# Source function library.
-. /etc/init.d/functions
-
-sysfs="/sys/class/mic"
-
-_status()
-{
-       f=$sysfs/$1
-       echo -e $1 state: "`cat $f/state`" shutdown_status: "`cat $f/shutdown_status`"
-}
-
-status()
-{
-       if [ "`echo $1 | head -c3`" == "mic" ]; then
-               _status $1
-               return $?
-       fi
-       for f in $sysfs/*
-       do
-               _status `basename $f`
-               RETVAL=$?
-               [ $RETVAL -ne 0 ] && return $RETVAL
-       done
-       return 0
-}
-
-_reset()
-{
-       f=$sysfs/$1
-       echo reset > $f/state
-}
-
-reset()
-{
-       if [ "`echo $1 | head -c3`" == "mic" ]; then
-               _reset $1
-               return $?
-       fi
-       for f in $sysfs/*
-       do
-               _reset `basename $f`
-               RETVAL=$?
-               [ $RETVAL -ne 0 ] && return $RETVAL
-       done
-       return 0
-}
-
-_boot()
-{
-       f=$sysfs/$1
-       echo "linux" > $f/bootmode
-       echo "mic/uos.img" > $f/firmware
-       echo "mic/$1.image" > $f/ramdisk
-       echo "boot" > $f/state
-}
-
-boot()
-{
-       if [ "`echo $1 | head -c3`" == "mic" ]; then
-               _boot $1
-               return $?
-       fi
-       for f in $sysfs/*
-       do
-               _boot `basename $f`
-               RETVAL=$?
-               [ $RETVAL -ne 0 ] && return $RETVAL
-       done
-       return 0
-}
-
-_shutdown()
-{
-       f=$sysfs/$1
-       echo shutdown > $f/state
-}
-
-shutdown()
-{
-       if [ "`echo $1 | head -c3`" == "mic" ]; then
-               _shutdown $1
-               return $?
-       fi
-       for f in $sysfs/*
-       do
-               _shutdown `basename $f`
-               RETVAL=$?
-               [ $RETVAL -ne 0 ] && return $RETVAL
-       done
-       return 0
-}
-
-_wait()
-{
-       f=$sysfs/$1
-       while [ "`cat $f/state`" != "offline" -a "`cat $f/state`" != "online" ]
-       do
-               sleep 1
-               echo -e "Waiting for $1 to go offline"
-       done
-}
-
-wait()
-{
-       if [ "`echo $1 | head -c3`" == "mic" ]; then
-               _wait $1
-               return $?
-       fi
-       # Wait for the cards to go offline
-       for f in $sysfs/*
-       do
-               _wait `basename $f`
-               RETVAL=$?
-               [ $RETVAL -ne 0 ] && return $RETVAL
-       done
-       return 0
-}
-
-if [ ! -d "$sysfs" ]; then
-       echo -e $"Module unloaded "
-       exit 3
-fi
-
-case $1 in
-       -s)
-               status $2
-               ;;
-       -r)
-               reset $2
-               ;;
-       -b)
-               boot $2
-               ;;
-       -S)
-               shutdown $2
-               ;;
-       -w)
-               wait $2
-               ;;
-       *)
-               echo $"Usage: $0 {-s (status) |-r (reset) |-b (boot) |-S (shutdown) |-w (wait)}"
-               exit 2
-esac
-
-exit $?
diff --git a/samples/mic/mpssd/mpss b/samples/mic/mpssd/mpss
deleted file mode 100755 (executable)
index 248ac73..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: GPL-2.0-only
-# Intel MIC Platform Software Stack (MPSS)
-#
-# Copyright(c) 2013 Intel Corporation.
-#
-# Intel MIC User Space Tools.
-#
-# mpss Start mpssd.
-#
-# chkconfig: 2345 95 05
-# description: start MPSS stack processing.
-#
-### BEGIN INIT INFO
-# Provides: mpss
-# Required-Start:
-# Required-Stop:
-# Short-Description: MPSS stack control
-# Description: MPSS stack control
-### END INIT INFO
-
-# Source function library.
-. /etc/init.d/functions
-
-exec=/usr/sbin/mpssd
-sysfs="/sys/class/mic"
-mic_modules="mic_host mic_x100_dma scif vop"
-
-start()
-{
-       [ -x $exec ] || exit 5
-
-       if [ "`ps -e | awk '{print $4}' | grep mpssd | head -1`" = "mpssd" ]; then
-               echo -e $"MPSSD already running! "
-               success
-               echo
-               return 0
-       fi
-
-       echo -e $"Starting MPSS Stack"
-       echo -e $"Loading MIC drivers:" $mic_modules
-
-       modprobe -a $mic_modules
-       RETVAL=$?
-       if [ $RETVAL -ne 0 ]; then
-               failure
-               echo
-               return $RETVAL
-       fi
-
-       # Start the daemon
-       echo -n $"Starting MPSSD "
-       $exec
-       RETVAL=$?
-       if [ $RETVAL -ne 0 ]; then
-               failure
-               echo
-               return $RETVAL
-       fi
-       success
-       echo
-
-       sleep 5
-
-       # Boot the cards
-       micctrl -b
-
-       # Wait till ping works
-       for f in $sysfs/*
-       do
-               count=100
-               ipaddr=`cat $f/cmdline`
-               ipaddr=${ipaddr#*address,}
-               ipaddr=`echo $ipaddr | cut -d, -f1 | cut -d\; -f1`
-               while [ $count -ge 0 ]
-               do
-                       echo -e "Pinging "`basename $f`" "
-                       ping -c 1 $ipaddr &> /dev/null
-                       RETVAL=$?
-                       if [ $RETVAL -eq 0 ]; then
-                               success
-                               break
-                       fi
-                       sleep 1
-                       count=`expr $count - 1`
-               done
-               [ $RETVAL -ne 0 ] && failure || success
-               echo
-       done
-       return $RETVAL
-}
-
-stop()
-{
-       echo -e $"Shutting down MPSS Stack: "
-
-       # Bail out if module is unloaded
-       if [ ! -d "$sysfs" ]; then
-               echo -n $"Module unloaded "
-               success
-               echo
-               return 0
-       fi
-
-       # Shut down the cards.
-       micctrl -S
-
-       # Wait for the cards to go offline
-       for f in $sysfs/*
-       do
-               while [ "`cat $f/state`" != "ready" ]
-               do
-                       sleep 1
-                       echo -e "Waiting for "`basename $f`" to become ready"
-               done
-       done
-
-       # Display the status of the cards
-       micctrl -s
-
-       # Kill MPSSD now
-       echo -n $"Killing MPSSD"
-       killall -9 mpssd 2>/dev/null
-       RETVAL=$?
-       [ $RETVAL -ne 0 ] && failure || success
-       echo
-       return $RETVAL
-}
-
-restart()
-{
-       stop
-       sleep 5
-       start
-}
-
-status()
-{
-       micctrl -s
-       if [ "`ps -e | awk '{print $4}' | grep mpssd | head -n 1`" = "mpssd" ]; then
-               echo "mpssd is running"
-       else
-               echo "mpssd is stopped"
-       fi
-       return 0
-}
-
-unload()
-{
-       if [ ! -d "$sysfs" ]; then
-               echo -n $"No MIC_HOST Module: "
-               success
-               echo
-               return
-       fi
-
-       stop
-
-       sleep 5
-       echo -n $"Removing MIC drivers:" $mic_modules
-       modprobe -r $mic_modules
-       RETVAL=$?
-       [ $RETVAL -ne 0 ] && failure || success
-       echo
-       return $RETVAL
-}
-
-case $1 in
-       start)
-               start
-               ;;
-       stop)
-               stop
-               ;;
-       restart)
-               restart
-               ;;
-       status)
-               status
-               ;;
-       unload)
-               unload
-               ;;
-       *)
-               echo $"Usage: $0 {start|stop|restart|status|unload}"
-               exit 2
-esac
-
-exit $?
diff --git a/samples/mic/mpssd/mpssd.c b/samples/mic/mpssd/mpssd.c
deleted file mode 100644 (file)
index c03a05d..0000000
+++ /dev/null
@@ -1,1815 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Intel MIC User Space Tools.
- */
-
-#define _GNU_SOURCE
-
-#include <stdlib.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <assert.h>
-#include <unistd.h>
-#include <stdbool.h>
-#include <signal.h>
-#include <poll.h>
-#include <features.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <sys/socket.h>
-#include <linux/virtio_ring.h>
-#include <linux/virtio_net.h>
-#include <linux/virtio_console.h>
-#include <linux/virtio_blk.h>
-#include <linux/version.h>
-#include "mpssd.h"
-#include <linux/mic_ioctl.h>
-#include <linux/mic_common.h>
-#include <tools/endian.h>
-
-static void *init_mic(void *arg);
-
-static FILE *logfp;
-static struct mic_info mic_list;
-
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
-#define min_t(type, x, y) ({                           \
-               type __min1 = (x);                      \
-               type __min2 = (y);                      \
-               __min1 < __min2 ? __min1 : __min2; })
-
-/* align addr on a size boundary - adjust address up/down if needed */
-#define _ALIGN_DOWN(addr, size)  ((addr)&(~((size)-1)))
-#define _ALIGN_UP(addr, size)    _ALIGN_DOWN(addr + size - 1, size)
-
-/* align addr on a size boundary - adjust address up if needed */
-#define _ALIGN(addr, size)     _ALIGN_UP(addr, size)
-
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)        _ALIGN(addr, PAGE_SIZE)
-
-#define READ_ONCE(x) (*(volatile typeof(x) *)&(x))
-
-#define GSO_ENABLED            1
-#define MAX_GSO_SIZE           (64 * 1024)
-#define ETH_H_LEN              14
-#define MAX_NET_PKT_SIZE       (_ALIGN_UP(MAX_GSO_SIZE + ETH_H_LEN, 64))
-#define MIC_DEVICE_PAGE_END    0x1000
-
-#ifndef VIRTIO_NET_HDR_F_DATA_VALID
-#define VIRTIO_NET_HDR_F_DATA_VALID    2       /* Csum is valid */
-#endif
-
-static struct {
-       struct mic_device_desc dd;
-       struct mic_vqconfig vqconfig[2];
-       __u32 host_features, guest_acknowledgements;
-       struct virtio_console_config cons_config;
-} virtcons_dev_page = {
-       .dd = {
-               .type = VIRTIO_ID_CONSOLE,
-               .num_vq = ARRAY_SIZE(virtcons_dev_page.vqconfig),
-               .feature_len = sizeof(virtcons_dev_page.host_features),
-               .config_len = sizeof(virtcons_dev_page.cons_config),
-       },
-       .vqconfig[0] = {
-               .num = htole16(MIC_VRING_ENTRIES),
-       },
-       .vqconfig[1] = {
-               .num = htole16(MIC_VRING_ENTRIES),
-       },
-};
-
-static struct {
-       struct mic_device_desc dd;
-       struct mic_vqconfig vqconfig[2];
-       __u32 host_features, guest_acknowledgements;
-       struct virtio_net_config net_config;
-} virtnet_dev_page = {
-       .dd = {
-               .type = VIRTIO_ID_NET,
-               .num_vq = ARRAY_SIZE(virtnet_dev_page.vqconfig),
-               .feature_len = sizeof(virtnet_dev_page.host_features),
-               .config_len = sizeof(virtnet_dev_page.net_config),
-       },
-       .vqconfig[0] = {
-               .num = htole16(MIC_VRING_ENTRIES),
-       },
-       .vqconfig[1] = {
-               .num = htole16(MIC_VRING_ENTRIES),
-       },
-#if GSO_ENABLED
-       .host_features = htole32(
-               1 << VIRTIO_NET_F_CSUM |
-               1 << VIRTIO_NET_F_GSO |
-               1 << VIRTIO_NET_F_GUEST_TSO4 |
-               1 << VIRTIO_NET_F_GUEST_TSO6 |
-               1 << VIRTIO_NET_F_GUEST_ECN),
-#else
-               .host_features = 0,
-#endif
-};
-
-static const char *mic_config_dir = "/etc/mpss";
-static const char *virtblk_backend = "VIRTBLK_BACKEND";
-static struct {
-       struct mic_device_desc dd;
-       struct mic_vqconfig vqconfig[1];
-       __u32 host_features, guest_acknowledgements;
-       struct virtio_blk_config blk_config;
-} virtblk_dev_page = {
-       .dd = {
-               .type = VIRTIO_ID_BLOCK,
-               .num_vq = ARRAY_SIZE(virtblk_dev_page.vqconfig),
-               .feature_len = sizeof(virtblk_dev_page.host_features),
-               .config_len = sizeof(virtblk_dev_page.blk_config),
-       },
-       .vqconfig[0] = {
-               .num = htole16(MIC_VRING_ENTRIES),
-       },
-       .host_features =
-               htole32(1<<VIRTIO_BLK_F_SEG_MAX),
-       .blk_config = {
-               .seg_max = htole32(MIC_VRING_ENTRIES - 2),
-               .capacity = htole64(0),
-        }
-};
-
-static char *myname;
-
-static int
-tap_configure(struct mic_info *mic, char *dev)
-{
-       pid_t pid;
-       char *ifargv[7];
-       char ipaddr[IFNAMSIZ];
-       int ret = 0;
-
-       pid = fork();
-       if (pid == 0) {
-               ifargv[0] = "ip";
-               ifargv[1] = "link";
-               ifargv[2] = "set";
-               ifargv[3] = dev;
-               ifargv[4] = "up";
-               ifargv[5] = NULL;
-               mpsslog("Configuring %s\n", dev);
-               ret = execvp("ip", ifargv);
-               if (ret < 0) {
-                       mpsslog("%s execvp failed errno %s\n",
-                               mic->name, strerror(errno));
-                       return ret;
-               }
-       }
-       if (pid < 0) {
-               mpsslog("%s fork failed errno %s\n",
-                       mic->name, strerror(errno));
-               return ret;
-       }
-
-       ret = waitpid(pid, NULL, 0);
-       if (ret < 0) {
-               mpsslog("%s waitpid failed errno %s\n",
-                       mic->name, strerror(errno));
-               return ret;
-       }
-
-       snprintf(ipaddr, IFNAMSIZ, "172.31.%d.254/24", mic->id + 1);
-
-       pid = fork();
-       if (pid == 0) {
-               ifargv[0] = "ip";
-               ifargv[1] = "addr";
-               ifargv[2] = "add";
-               ifargv[3] = ipaddr;
-               ifargv[4] = "dev";
-               ifargv[5] = dev;
-               ifargv[6] = NULL;
-               mpsslog("Configuring %s ipaddr %s\n", dev, ipaddr);
-               ret = execvp("ip", ifargv);
-               if (ret < 0) {
-                       mpsslog("%s execvp failed errno %s\n",
-                               mic->name, strerror(errno));
-                       return ret;
-               }
-       }
-       if (pid < 0) {
-               mpsslog("%s fork failed errno %s\n",
-                       mic->name, strerror(errno));
-               return ret;
-       }
-
-       ret = waitpid(pid, NULL, 0);
-       if (ret < 0) {
-               mpsslog("%s waitpid failed errno %s\n",
-                       mic->name, strerror(errno));
-               return ret;
-       }
-       mpsslog("MIC name %s %s %d DONE!\n",
-               mic->name, __func__, __LINE__);
-       return 0;
-}
-
-static int tun_alloc(struct mic_info *mic, char *dev)
-{
-       struct ifreq ifr;
-       int fd, err;
-#if GSO_ENABLED
-       unsigned offload;
-#endif
-       fd = open("/dev/net/tun", O_RDWR);
-       if (fd < 0) {
-               mpsslog("Could not open /dev/net/tun %s\n", strerror(errno));
-               goto done;
-       }
-
-       memset(&ifr, 0, sizeof(ifr));
-
-       ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
-       if (*dev)
-               strncpy(ifr.ifr_name, dev, IFNAMSIZ);
-
-       err = ioctl(fd, TUNSETIFF, (void *)&ifr);
-       if (err < 0) {
-               mpsslog("%s %s %d TUNSETIFF failed %s\n",
-                       mic->name, __func__, __LINE__, strerror(errno));
-               close(fd);
-               return err;
-       }
-#if GSO_ENABLED
-       offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | TUN_F_TSO_ECN;
-
-       err = ioctl(fd, TUNSETOFFLOAD, offload);
-       if (err < 0) {
-               mpsslog("%s %s %d TUNSETOFFLOAD failed %s\n",
-                       mic->name, __func__, __LINE__, strerror(errno));
-               close(fd);
-               return err;
-       }
-#endif
-       strcpy(dev, ifr.ifr_name);
-       mpsslog("Created TAP %s\n", dev);
-done:
-       return fd;
-}
-
-#define NET_FD_VIRTIO_NET 0
-#define NET_FD_TUN 1
-#define MAX_NET_FD 2
-
-static void set_dp(struct mic_info *mic, int type, void *dp)
-{
-       switch (type) {
-       case VIRTIO_ID_CONSOLE:
-               mic->mic_console.console_dp = dp;
-               return;
-       case VIRTIO_ID_NET:
-               mic->mic_net.net_dp = dp;
-               return;
-       case VIRTIO_ID_BLOCK:
-               mic->mic_virtblk.block_dp = dp;
-               return;
-       }
-       mpsslog("%s %s %d not found\n", mic->name, __func__, type);
-       assert(0);
-}
-
-static void *get_dp(struct mic_info *mic, int type)
-{
-       switch (type) {
-       case VIRTIO_ID_CONSOLE:
-               return mic->mic_console.console_dp;
-       case VIRTIO_ID_NET:
-               return mic->mic_net.net_dp;
-       case VIRTIO_ID_BLOCK:
-               return mic->mic_virtblk.block_dp;
-       }
-       mpsslog("%s %s %d not found\n", mic->name, __func__, type);
-       assert(0);
-       return NULL;
-}
-
-static struct mic_device_desc *get_device_desc(struct mic_info *mic, int type)
-{
-       struct mic_device_desc *d;
-       int i;
-       void *dp = get_dp(mic, type);
-
-       for (i = sizeof(struct mic_bootparam); i < PAGE_SIZE;
-               i += mic_total_desc_size(d)) {
-               d = dp + i;
-
-               /* End of list */
-               if (d->type == 0)
-                       break;
-
-               if (d->type == -1)
-                       continue;
-
-               mpsslog("%s %s d-> type %d d %p\n",
-                       mic->name, __func__, d->type, d);
-
-               if (d->type == (__u8)type)
-                       return d;
-       }
-       mpsslog("%s %s %d not found\n", mic->name, __func__, type);
-       return NULL;
-}
-
-/* See comments in vhost.c for explanation of next_desc() */
-static unsigned next_desc(struct vring_desc *desc)
-{
-       unsigned int next;
-
-       if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT))
-               return -1U;
-       next = le16toh(desc->next);
-       return next;
-}
-
-/* Sum up all the IOVEC length */
-static ssize_t
-sum_iovec_len(struct mic_copy_desc *copy)
-{
-       ssize_t sum = 0;
-       unsigned int i;
-
-       for (i = 0; i < copy->iovcnt; i++)
-               sum += copy->iov[i].iov_len;
-       return sum;
-}
-
-static inline void verify_out_len(struct mic_info *mic,
-       struct mic_copy_desc *copy)
-{
-       if (copy->out_len != sum_iovec_len(copy)) {
-               mpsslog("%s %s %d BUG copy->out_len 0x%x len 0x%zx\n",
-                       mic->name, __func__, __LINE__,
-                       copy->out_len, sum_iovec_len(copy));
-               assert(copy->out_len == sum_iovec_len(copy));
-       }
-}
-
-/* Display an iovec */
-static void
-disp_iovec(struct mic_info *mic, struct mic_copy_desc *copy,
-          const char *s, int line)
-{
-       unsigned int i;
-
-       for (i = 0; i < copy->iovcnt; i++)
-               mpsslog("%s %s %d copy->iov[%d] addr %p len 0x%zx\n",
-                       mic->name, s, line, i,
-                       copy->iov[i].iov_base, copy->iov[i].iov_len);
-}
-
-static inline __u16 read_avail_idx(struct mic_vring *vr)
-{
-       return READ_ONCE(vr->info->avail_idx);
-}
-
-static inline void txrx_prepare(int type, bool tx, struct mic_vring *vr,
-                               struct mic_copy_desc *copy, ssize_t len)
-{
-       copy->vr_idx = tx ? 0 : 1;
-       copy->update_used = true;
-       if (type == VIRTIO_ID_NET)
-               copy->iov[1].iov_len = len - sizeof(struct virtio_net_hdr);
-       else
-               copy->iov[0].iov_len = len;
-}
-
-/* Central API which triggers the copies */
-static int
-mic_virtio_copy(struct mic_info *mic, int fd,
-               struct mic_vring *vr, struct mic_copy_desc *copy)
-{
-       int ret;
-
-       ret = ioctl(fd, MIC_VIRTIO_COPY_DESC, copy);
-       if (ret) {
-               mpsslog("%s %s %d errno %s ret %d\n",
-                       mic->name, __func__, __LINE__,
-                       strerror(errno), ret);
-       }
-       return ret;
-}
-
-static inline unsigned _vring_size(unsigned int num, unsigned long align)
-{
-       return _ALIGN_UP(((sizeof(struct vring_desc) * num + sizeof(__u16) * (3 + num)
-                               + align - 1) & ~(align - 1))
-               + sizeof(__u16) * 3 + sizeof(struct vring_used_elem) * num, 4);
-}
-
-/*
- * This initialization routine requires at least one
- * vring i.e. vr0. vr1 is optional.
- */
-static void *
-init_vr(struct mic_info *mic, int fd, int type,
-       struct mic_vring *vr0, struct mic_vring *vr1, int num_vq)
-{
-       int vr_size;
-       char *va;
-
-       vr_size = PAGE_ALIGN(_vring_size(MIC_VRING_ENTRIES,
-                                        MIC_VIRTIO_RING_ALIGN) +
-                            sizeof(struct _mic_vring_info));
-       va = mmap(NULL, MIC_DEVICE_PAGE_END + vr_size * num_vq,
-               PROT_READ, MAP_SHARED, fd, 0);
-       if (MAP_FAILED == va) {
-               mpsslog("%s %s %d mmap failed errno %s\n",
-                       mic->name, __func__, __LINE__,
-                       strerror(errno));
-               goto done;
-       }
-       set_dp(mic, type, va);
-       vr0->va = (struct mic_vring *)&va[MIC_DEVICE_PAGE_END];
-       vr0->info = vr0->va +
-               _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN);
-       vring_init(&vr0->vr,
-                  MIC_VRING_ENTRIES, vr0->va, MIC_VIRTIO_RING_ALIGN);
-       mpsslog("%s %s vr0 %p vr0->info %p vr_size 0x%x vring 0x%x ",
-               __func__, mic->name, vr0->va, vr0->info, vr_size,
-               _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
-       mpsslog("magic 0x%x expected 0x%x\n",
-               le32toh(vr0->info->magic), MIC_MAGIC + type);
-       assert(le32toh(vr0->info->magic) == MIC_MAGIC + type);
-       if (vr1) {
-               vr1->va = (struct mic_vring *)
-                       &va[MIC_DEVICE_PAGE_END + vr_size];
-               vr1->info = vr1->va + _vring_size(MIC_VRING_ENTRIES,
-                       MIC_VIRTIO_RING_ALIGN);
-               vring_init(&vr1->vr,
-                          MIC_VRING_ENTRIES, vr1->va, MIC_VIRTIO_RING_ALIGN);
-               mpsslog("%s %s vr1 %p vr1->info %p vr_size 0x%x vring 0x%x ",
-                       __func__, mic->name, vr1->va, vr1->info, vr_size,
-                       _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
-               mpsslog("magic 0x%x expected 0x%x\n",
-                       le32toh(vr1->info->magic), MIC_MAGIC + type + 1);
-               assert(le32toh(vr1->info->magic) == MIC_MAGIC + type + 1);
-       }
-done:
-       return va;
-}
-
-static int
-wait_for_card_driver(struct mic_info *mic, int fd, int type)
-{
-       struct pollfd pollfd;
-       int err;
-       struct mic_device_desc *desc = get_device_desc(mic, type);
-       __u8 prev_status;
-
-       if (!desc)
-               return -ENODEV;
-       prev_status = desc->status;
-       pollfd.fd = fd;
-       mpsslog("%s %s Waiting .... desc-> type %d status 0x%x\n",
-               mic->name, __func__, type, desc->status);
-
-       while (1) {
-               pollfd.events = POLLIN;
-               pollfd.revents = 0;
-               err = poll(&pollfd, 1, -1);
-               if (err < 0) {
-                       mpsslog("%s %s poll failed %s\n",
-                               mic->name, __func__, strerror(errno));
-                       continue;
-               }
-
-               if (pollfd.revents) {
-                       if (desc->status != prev_status) {
-                               mpsslog("%s %s Waiting... desc-> type %d "
-                                       "status 0x%x\n",
-                                       mic->name, __func__, type,
-                                       desc->status);
-                               prev_status = desc->status;
-                       }
-                       if (desc->status & VIRTIO_CONFIG_S_DRIVER_OK) {
-                               mpsslog("%s %s poll.revents %d\n",
-                                       mic->name, __func__, pollfd.revents);
-                               mpsslog("%s %s desc-> type %d status 0x%x\n",
-                                       mic->name, __func__, type,
-                                       desc->status);
-                               break;
-                       }
-               }
-       }
-       return 0;
-}
-
-/* Spin till we have some descriptors */
-static void
-spin_for_descriptors(struct mic_info *mic, struct mic_vring *vr)
-{
-       __u16 avail_idx = read_avail_idx(vr);
-
-       while (avail_idx == le16toh(READ_ONCE(vr->vr.avail->idx))) {
-#ifdef DEBUG
-               mpsslog("%s %s waiting for desc avail %d info_avail %d\n",
-                       mic->name, __func__,
-                       le16toh(vr->vr.avail->idx), vr->info->avail_idx);
-#endif
-               sched_yield();
-       }
-}
-
-static void *
-virtio_net(void *arg)
-{
-       static __u8 vnet_hdr[2][sizeof(struct virtio_net_hdr)];
-       static __u8 vnet_buf[2][MAX_NET_PKT_SIZE] __attribute__ ((aligned(64)));
-       struct iovec vnet_iov[2][2] = {
-               { { .iov_base = vnet_hdr[0], .iov_len = sizeof(vnet_hdr[0]) },
-                 { .iov_base = vnet_buf[0], .iov_len = sizeof(vnet_buf[0]) } },
-               { { .iov_base = vnet_hdr[1], .iov_len = sizeof(vnet_hdr[1]) },
-                 { .iov_base = vnet_buf[1], .iov_len = sizeof(vnet_buf[1]) } },
-       };
-       struct iovec *iov0 = vnet_iov[0], *iov1 = vnet_iov[1];
-       struct mic_info *mic = (struct mic_info *)arg;
-       char if_name[IFNAMSIZ];
-       struct pollfd net_poll[MAX_NET_FD];
-       struct mic_vring tx_vr, rx_vr;
-       struct mic_copy_desc copy;
-       struct mic_device_desc *desc;
-       int err;
-
-       snprintf(if_name, IFNAMSIZ, "mic%d", mic->id);
-       mic->mic_net.tap_fd = tun_alloc(mic, if_name);
-       if (mic->mic_net.tap_fd < 0)
-               goto done;
-
-       if (tap_configure(mic, if_name))
-               goto done;
-       mpsslog("MIC name %s id %d\n", mic->name, mic->id);
-
-       net_poll[NET_FD_VIRTIO_NET].fd = mic->mic_net.virtio_net_fd;
-       net_poll[NET_FD_VIRTIO_NET].events = POLLIN;
-       net_poll[NET_FD_TUN].fd = mic->mic_net.tap_fd;
-       net_poll[NET_FD_TUN].events = POLLIN;
-
-       if (MAP_FAILED == init_vr(mic, mic->mic_net.virtio_net_fd,
-                                 VIRTIO_ID_NET, &tx_vr, &rx_vr,
-               virtnet_dev_page.dd.num_vq)) {
-               mpsslog("%s init_vr failed %s\n",
-                       mic->name, strerror(errno));
-               goto done;
-       }
-
-       copy.iovcnt = 2;
-       desc = get_device_desc(mic, VIRTIO_ID_NET);
-
-       while (1) {
-               ssize_t len;
-
-               net_poll[NET_FD_VIRTIO_NET].revents = 0;
-               net_poll[NET_FD_TUN].revents = 0;
-
-               /* Start polling for data from tap and virtio net */
-               err = poll(net_poll, 2, -1);
-               if (err < 0) {
-                       mpsslog("%s poll failed %s\n",
-                               __func__, strerror(errno));
-                       continue;
-               }
-               if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
-                       err = wait_for_card_driver(mic,
-                                                  mic->mic_net.virtio_net_fd,
-                                                  VIRTIO_ID_NET);
-                       if (err) {
-                               mpsslog("%s %s %d Exiting...\n",
-                                       mic->name, __func__, __LINE__);
-                               break;
-                       }
-               }
-               /*
-                * Check if there is data to be read from TUN and write to
-                * virtio net fd if there is.
-                */
-               if (net_poll[NET_FD_TUN].revents & POLLIN) {
-                       copy.iov = iov0;
-                       len = readv(net_poll[NET_FD_TUN].fd,
-                               copy.iov, copy.iovcnt);
-                       if (len > 0) {
-                               struct virtio_net_hdr *hdr
-                                       = (struct virtio_net_hdr *)vnet_hdr[0];
-
-                               /* Disable checksums on the card since we are on
-                                  a reliable PCIe link */
-                               hdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID;
-#ifdef DEBUG
-                               mpsslog("%s %s %d hdr->flags 0x%x ", mic->name,
-                                       __func__, __LINE__, hdr->flags);
-                               mpsslog("copy.out_len %d hdr->gso_type 0x%x\n",
-                                       copy.out_len, hdr->gso_type);
-#endif
-#ifdef DEBUG
-                               disp_iovec(mic, &copy, __func__, __LINE__);
-                               mpsslog("%s %s %d read from tap 0x%lx\n",
-                                       mic->name, __func__, __LINE__,
-                                       len);
-#endif
-                               spin_for_descriptors(mic, &tx_vr);
-                               txrx_prepare(VIRTIO_ID_NET, 1, &tx_vr, &copy,
-                                            len);
-
-                               err = mic_virtio_copy(mic,
-                                       mic->mic_net.virtio_net_fd, &tx_vr,
-                                       &copy);
-                               if (err < 0) {
-                                       mpsslog("%s %s %d mic_virtio_copy %s\n",
-                                               mic->name, __func__, __LINE__,
-                                               strerror(errno));
-                               }
-                               if (!err)
-                                       verify_out_len(mic, &copy);
-#ifdef DEBUG
-                               disp_iovec(mic, &copy, __func__, __LINE__);
-                               mpsslog("%s %s %d wrote to net 0x%lx\n",
-                                       mic->name, __func__, __LINE__,
-                                       sum_iovec_len(&copy));
-#endif
-                               /* Reinitialize IOV for next run */
-                               iov0[1].iov_len = MAX_NET_PKT_SIZE;
-                       } else if (len < 0) {
-                               disp_iovec(mic, &copy, __func__, __LINE__);
-                               mpsslog("%s %s %d read failed %s ", mic->name,
-                                       __func__, __LINE__, strerror(errno));
-                               mpsslog("cnt %d sum %zd\n",
-                                       copy.iovcnt, sum_iovec_len(&copy));
-                       }
-               }
-
-               /*
-                * Check if there is data to be read from virtio net and
-                * write to TUN if there is.
-                */
-               if (net_poll[NET_FD_VIRTIO_NET].revents & POLLIN) {
-                       while (rx_vr.info->avail_idx !=
-                               le16toh(rx_vr.vr.avail->idx)) {
-                               copy.iov = iov1;
-                               txrx_prepare(VIRTIO_ID_NET, 0, &rx_vr, &copy,
-                                            MAX_NET_PKT_SIZE
-                                       + sizeof(struct virtio_net_hdr));
-
-                               err = mic_virtio_copy(mic,
-                                       mic->mic_net.virtio_net_fd, &rx_vr,
-                                       &copy);
-                               if (!err) {
-#ifdef DEBUG
-                                       struct virtio_net_hdr *hdr
-                                               = (struct virtio_net_hdr *)
-                                                       vnet_hdr[1];
-
-                                       mpsslog("%s %s %d hdr->flags 0x%x, ",
-                                               mic->name, __func__, __LINE__,
-                                               hdr->flags);
-                                       mpsslog("out_len %d gso_type 0x%x\n",
-                                               copy.out_len,
-                                               hdr->gso_type);
-#endif
-                                       /* Set the correct output iov_len */
-                                       iov1[1].iov_len = copy.out_len -
-                                               sizeof(struct virtio_net_hdr);
-                                       verify_out_len(mic, &copy);
-#ifdef DEBUG
-                                       disp_iovec(mic, &copy, __func__,
-                                                  __LINE__);
-                                       mpsslog("%s %s %d ",
-                                               mic->name, __func__, __LINE__);
-                                       mpsslog("read from net 0x%lx\n",
-                                               sum_iovec_len(&copy));
-#endif
-                                       len = writev(net_poll[NET_FD_TUN].fd,
-                                               copy.iov, copy.iovcnt);
-                                       if (len != sum_iovec_len(&copy)) {
-                                               mpsslog("Tun write failed %s ",
-                                                       strerror(errno));
-                                               mpsslog("len 0x%zx ", len);
-                                               mpsslog("read_len 0x%zx\n",
-                                                       sum_iovec_len(&copy));
-                                       } else {
-#ifdef DEBUG
-                                               disp_iovec(mic, &copy, __func__,
-                                                          __LINE__);
-                                               mpsslog("%s %s %d ",
-                                                       mic->name, __func__,
-                                                       __LINE__);
-                                               mpsslog("wrote to tap 0x%lx\n",
-                                                       len);
-#endif
-                                       }
-                               } else {
-                                       mpsslog("%s %s %d mic_virtio_copy %s\n",
-                                               mic->name, __func__, __LINE__,
-                                               strerror(errno));
-                                       break;
-                               }
-                       }
-               }
-               if (net_poll[NET_FD_VIRTIO_NET].revents & POLLERR)
-                       mpsslog("%s: %s: POLLERR\n", __func__, mic->name);
-       }
-done:
-       pthread_exit(NULL);
-}
-
-/* virtio_console */
-#define VIRTIO_CONSOLE_FD 0
-#define MONITOR_FD (VIRTIO_CONSOLE_FD + 1)
-#define MAX_CONSOLE_FD (MONITOR_FD + 1)  /* must be the last one + 1 */
-#define MAX_BUFFER_SIZE PAGE_SIZE
-
-static void *
-virtio_console(void *arg)
-{
-       static __u8 vcons_buf[2][PAGE_SIZE];
-       struct iovec vcons_iov[2] = {
-               { .iov_base = vcons_buf[0], .iov_len = sizeof(vcons_buf[0]) },
-               { .iov_base = vcons_buf[1], .iov_len = sizeof(vcons_buf[1]) },
-       };
-       struct iovec *iov0 = &vcons_iov[0], *iov1 = &vcons_iov[1];
-       struct mic_info *mic = (struct mic_info *)arg;
-       int err;
-       struct pollfd console_poll[MAX_CONSOLE_FD];
-       int pty_fd;
-       char *pts_name;
-       ssize_t len;
-       struct mic_vring tx_vr, rx_vr;
-       struct mic_copy_desc copy;
-       struct mic_device_desc *desc;
-
-       pty_fd = posix_openpt(O_RDWR);
-       if (pty_fd < 0) {
-               mpsslog("can't open a pseudoterminal master device: %s\n",
-                       strerror(errno));
-               goto _return;
-       }
-       pts_name = ptsname(pty_fd);
-       if (pts_name == NULL) {
-               mpsslog("can't get pts name\n");
-               goto _close_pty;
-       }
-       printf("%s console message goes to %s\n", mic->name, pts_name);
-       mpsslog("%s console message goes to %s\n", mic->name, pts_name);
-       err = grantpt(pty_fd);
-       if (err < 0) {
-               mpsslog("can't grant access: %s %s\n",
-                       pts_name, strerror(errno));
-               goto _close_pty;
-       }
-       err = unlockpt(pty_fd);
-       if (err < 0) {
-               mpsslog("can't unlock a pseudoterminal: %s %s\n",
-                       pts_name, strerror(errno));
-               goto _close_pty;
-       }
-       console_poll[MONITOR_FD].fd = pty_fd;
-       console_poll[MONITOR_FD].events = POLLIN;
-
-       console_poll[VIRTIO_CONSOLE_FD].fd = mic->mic_console.virtio_console_fd;
-       console_poll[VIRTIO_CONSOLE_FD].events = POLLIN;
-
-       if (MAP_FAILED == init_vr(mic, mic->mic_console.virtio_console_fd,
-                                 VIRTIO_ID_CONSOLE, &tx_vr, &rx_vr,
-               virtcons_dev_page.dd.num_vq)) {
-               mpsslog("%s init_vr failed %s\n",
-                       mic->name, strerror(errno));
-               goto _close_pty;
-       }
-
-       copy.iovcnt = 1;
-       desc = get_device_desc(mic, VIRTIO_ID_CONSOLE);
-
-       for (;;) {
-               console_poll[MONITOR_FD].revents = 0;
-               console_poll[VIRTIO_CONSOLE_FD].revents = 0;
-               err = poll(console_poll, MAX_CONSOLE_FD, -1);
-               if (err < 0) {
-                       mpsslog("%s %d: poll failed: %s\n", __func__, __LINE__,
-                               strerror(errno));
-                       continue;
-               }
-               if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
-                       err = wait_for_card_driver(mic,
-                                       mic->mic_console.virtio_console_fd,
-                                       VIRTIO_ID_CONSOLE);
-                       if (err) {
-                               mpsslog("%s %s %d Exiting...\n",
-                                       mic->name, __func__, __LINE__);
-                               break;
-                       }
-               }
-
-               if (console_poll[MONITOR_FD].revents & POLLIN) {
-                       copy.iov = iov0;
-                       len = readv(pty_fd, copy.iov, copy.iovcnt);
-                       if (len > 0) {
-#ifdef DEBUG
-                               disp_iovec(mic, &copy, __func__, __LINE__);
-                               mpsslog("%s %s %d read from tap 0x%lx\n",
-                                       mic->name, __func__, __LINE__,
-                                       len);
-#endif
-                               spin_for_descriptors(mic, &tx_vr);
-                               txrx_prepare(VIRTIO_ID_CONSOLE, 1, &tx_vr,
-                                            &copy, len);
-
-                               err = mic_virtio_copy(mic,
-                                       mic->mic_console.virtio_console_fd,
-                                       &tx_vr, &copy);
-                               if (err < 0) {
-                                       mpsslog("%s %s %d mic_virtio_copy %s\n",
-                                               mic->name, __func__, __LINE__,
-                                               strerror(errno));
-                               }
-                               if (!err)
-                                       verify_out_len(mic, &copy);
-#ifdef DEBUG
-                               disp_iovec(mic, &copy, __func__, __LINE__);
-                               mpsslog("%s %s %d wrote to net 0x%lx\n",
-                                       mic->name, __func__, __LINE__,
-                                       sum_iovec_len(&copy));
-#endif
-                               /* Reinitialize IOV for next run */
-                               iov0->iov_len = PAGE_SIZE;
-                       } else if (len < 0) {
-                               disp_iovec(mic, &copy, __func__, __LINE__);
-                               mpsslog("%s %s %d read failed %s ",
-                                       mic->name, __func__, __LINE__,
-                                       strerror(errno));
-                               mpsslog("cnt %d sum %zd\n",
-                                       copy.iovcnt, sum_iovec_len(&copy));
-                       }
-               }
-
-               if (console_poll[VIRTIO_CONSOLE_FD].revents & POLLIN) {
-                       while (rx_vr.info->avail_idx !=
-                               le16toh(rx_vr.vr.avail->idx)) {
-                               copy.iov = iov1;
-                               txrx_prepare(VIRTIO_ID_CONSOLE, 0, &rx_vr,
-                                            &copy, PAGE_SIZE);
-
-                               err = mic_virtio_copy(mic,
-                                       mic->mic_console.virtio_console_fd,
-                                       &rx_vr, &copy);
-                               if (!err) {
-                                       /* Set the correct output iov_len */
-                                       iov1->iov_len = copy.out_len;
-                                       verify_out_len(mic, &copy);
-#ifdef DEBUG
-                                       disp_iovec(mic, &copy, __func__,
-                                                  __LINE__);
-                                       mpsslog("%s %s %d ",
-                                               mic->name, __func__, __LINE__);
-                                       mpsslog("read from net 0x%lx\n",
-                                               sum_iovec_len(&copy));
-#endif
-                                       len = writev(pty_fd,
-                                               copy.iov, copy.iovcnt);
-                                       if (len != sum_iovec_len(&copy)) {
-                                               mpsslog("Tun write failed %s ",
-                                                       strerror(errno));
-                                               mpsslog("len 0x%zx ", len);
-                                               mpsslog("read_len 0x%zx\n",
-                                                       sum_iovec_len(&copy));
-                                       } else {
-#ifdef DEBUG
-                                               disp_iovec(mic, &copy, __func__,
-                                                          __LINE__);
-                                               mpsslog("%s %s %d ",
-                                                       mic->name, __func__,
-                                                       __LINE__);
-                                               mpsslog("wrote to tap 0x%lx\n",
-                                                       len);
-#endif
-                                       }
-                               } else {
-                                       mpsslog("%s %s %d mic_virtio_copy %s\n",
-                                               mic->name, __func__, __LINE__,
-                                               strerror(errno));
-                                       break;
-                               }
-                       }
-               }
-               if (console_poll[NET_FD_VIRTIO_NET].revents & POLLERR)
-                       mpsslog("%s: %s: POLLERR\n", __func__, mic->name);
-       }
-_close_pty:
-       close(pty_fd);
-_return:
-       pthread_exit(NULL);
-}
-
-static void
-add_virtio_device(struct mic_info *mic, struct mic_device_desc *dd)
-{
-       char path[PATH_MAX];
-       int fd, err;
-
-       snprintf(path, PATH_MAX, "/dev/vop_virtio%d", mic->id);
-       fd = open(path, O_RDWR);
-       if (fd < 0) {
-               mpsslog("Could not open %s %s\n", path, strerror(errno));
-               return;
-       }
-
-       err = ioctl(fd, MIC_VIRTIO_ADD_DEVICE, dd);
-       if (err < 0) {
-               mpsslog("Could not add %d %s\n", dd->type, strerror(errno));
-               close(fd);
-               return;
-       }
-       switch (dd->type) {
-       case VIRTIO_ID_NET:
-               mic->mic_net.virtio_net_fd = fd;
-               mpsslog("Added VIRTIO_ID_NET for %s\n", mic->name);
-               break;
-       case VIRTIO_ID_CONSOLE:
-               mic->mic_console.virtio_console_fd = fd;
-               mpsslog("Added VIRTIO_ID_CONSOLE for %s\n", mic->name);
-               break;
-       case VIRTIO_ID_BLOCK:
-               mic->mic_virtblk.virtio_block_fd = fd;
-               mpsslog("Added VIRTIO_ID_BLOCK for %s\n", mic->name);
-               break;
-       }
-}
-
-static bool
-set_backend_file(struct mic_info *mic)
-{
-       FILE *config;
-       char buff[PATH_MAX], *line, *evv, *p;
-
-       snprintf(buff, PATH_MAX, "%s/mpssd%03d.conf", mic_config_dir, mic->id);
-       config = fopen(buff, "r");
-       if (config == NULL)
-               return false;
-       do {  /* look for "virtblk_backend=XXXX" */
-               line = fgets(buff, PATH_MAX, config);
-               if (line == NULL)
-                       break;
-               if (*line == '#')
-                       continue;
-               p = strchr(line, '\n');
-               if (p)
-                       *p = '\0';
-       } while (strncmp(line, virtblk_backend, strlen(virtblk_backend)) != 0);
-       fclose(config);
-       if (line == NULL)
-               return false;
-       evv = strchr(line, '=');
-       if (evv == NULL)
-               return false;
-       mic->mic_virtblk.backend_file = malloc(strlen(evv) + 1);
-       if (mic->mic_virtblk.backend_file == NULL) {
-               mpsslog("%s %d can't allocate memory\n", mic->name, mic->id);
-               return false;
-       }
-       strcpy(mic->mic_virtblk.backend_file, evv + 1);
-       return true;
-}
-
-#define SECTOR_SIZE 512
-static bool
-set_backend_size(struct mic_info *mic)
-{
-       mic->mic_virtblk.backend_size = lseek(mic->mic_virtblk.backend, 0,
-               SEEK_END);
-       if (mic->mic_virtblk.backend_size < 0) {
-               mpsslog("%s: can't seek: %s\n",
-                       mic->name, mic->mic_virtblk.backend_file);
-               return false;
-       }
-       virtblk_dev_page.blk_config.capacity =
-               mic->mic_virtblk.backend_size / SECTOR_SIZE;
-       if ((mic->mic_virtblk.backend_size % SECTOR_SIZE) != 0)
-               virtblk_dev_page.blk_config.capacity++;
-
-       virtblk_dev_page.blk_config.capacity =
-               htole64(virtblk_dev_page.blk_config.capacity);
-
-       return true;
-}
-
-static bool
-open_backend(struct mic_info *mic)
-{
-       if (!set_backend_file(mic))
-               goto _error_exit;
-       mic->mic_virtblk.backend = open(mic->mic_virtblk.backend_file, O_RDWR);
-       if (mic->mic_virtblk.backend < 0) {
-               mpsslog("%s: can't open: %s\n", mic->name,
-                       mic->mic_virtblk.backend_file);
-               goto _error_free;
-       }
-       if (!set_backend_size(mic))
-               goto _error_close;
-       mic->mic_virtblk.backend_addr = mmap(NULL,
-               mic->mic_virtblk.backend_size,
-               PROT_READ|PROT_WRITE, MAP_SHARED,
-               mic->mic_virtblk.backend, 0L);
-       if (mic->mic_virtblk.backend_addr == MAP_FAILED) {
-               mpsslog("%s: can't map: %s %s\n",
-                       mic->name, mic->mic_virtblk.backend_file,
-                       strerror(errno));
-               goto _error_close;
-       }
-       return true;
-
- _error_close:
-       close(mic->mic_virtblk.backend);
- _error_free:
-       free(mic->mic_virtblk.backend_file);
- _error_exit:
-       return false;
-}
-
-static void
-close_backend(struct mic_info *mic)
-{
-       munmap(mic->mic_virtblk.backend_addr, mic->mic_virtblk.backend_size);
-       close(mic->mic_virtblk.backend);
-       free(mic->mic_virtblk.backend_file);
-}
-
-static bool
-start_virtblk(struct mic_info *mic, struct mic_vring *vring)
-{
-       if (((unsigned long)&virtblk_dev_page.blk_config % 8) != 0) {
-               mpsslog("%s: blk_config is not 8 byte aligned.\n",
-                       mic->name);
-               return false;
-       }
-       add_virtio_device(mic, &virtblk_dev_page.dd);
-       if (MAP_FAILED == init_vr(mic, mic->mic_virtblk.virtio_block_fd,
-                                 VIRTIO_ID_BLOCK, vring, NULL,
-                                 virtblk_dev_page.dd.num_vq)) {
-               mpsslog("%s init_vr failed %s\n",
-                       mic->name, strerror(errno));
-               return false;
-       }
-       return true;
-}
-
-static void
-stop_virtblk(struct mic_info *mic)
-{
-       int vr_size, ret;
-
-       vr_size = PAGE_ALIGN(_vring_size(MIC_VRING_ENTRIES,
-                                        MIC_VIRTIO_RING_ALIGN) +
-                            sizeof(struct _mic_vring_info));
-       ret = munmap(mic->mic_virtblk.block_dp,
-               MIC_DEVICE_PAGE_END + vr_size * virtblk_dev_page.dd.num_vq);
-       if (ret < 0)
-               mpsslog("%s munmap errno %d\n", mic->name, errno);
-       close(mic->mic_virtblk.virtio_block_fd);
-}
-
-static __u8
-header_error_check(struct vring_desc *desc)
-{
-       if (le32toh(desc->len) != sizeof(struct virtio_blk_outhdr)) {
-               mpsslog("%s() %d: length is not sizeof(virtio_blk_outhd)\n",
-                       __func__, __LINE__);
-               return -EIO;
-       }
-       if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT)) {
-               mpsslog("%s() %d: alone\n",
-                       __func__, __LINE__);
-               return -EIO;
-       }
-       if (le16toh(desc->flags) & VRING_DESC_F_WRITE) {
-               mpsslog("%s() %d: not read\n",
-                       __func__, __LINE__);
-               return -EIO;
-       }
-       return 0;
-}
-
-static int
-read_header(int fd, struct virtio_blk_outhdr *hdr, __u32 desc_idx)
-{
-       struct iovec iovec;
-       struct mic_copy_desc copy;
-
-       iovec.iov_len = sizeof(*hdr);
-       iovec.iov_base = hdr;
-       copy.iov = &iovec;
-       copy.iovcnt = 1;
-       copy.vr_idx = 0;  /* only one vring on virtio_block */
-       copy.update_used = false;  /* do not update used index */
-       return ioctl(fd, MIC_VIRTIO_COPY_DESC, &copy);
-}
-
-static int
-transfer_blocks(int fd, struct iovec *iovec, __u32 iovcnt)
-{
-       struct mic_copy_desc copy;
-
-       copy.iov = iovec;
-       copy.iovcnt = iovcnt;
-       copy.vr_idx = 0;  /* only one vring on virtio_block */
-       copy.update_used = false;  /* do not update used index */
-       return ioctl(fd, MIC_VIRTIO_COPY_DESC, &copy);
-}
-
-static __u8
-status_error_check(struct vring_desc *desc)
-{
-       if (le32toh(desc->len) != sizeof(__u8)) {
-               mpsslog("%s() %d: length is not sizeof(status)\n",
-                       __func__, __LINE__);
-               return -EIO;
-       }
-       return 0;
-}
-
-static int
-write_status(int fd, __u8 *status)
-{
-       struct iovec iovec;
-       struct mic_copy_desc copy;
-
-       iovec.iov_base = status;
-       iovec.iov_len = sizeof(*status);
-       copy.iov = &iovec;
-       copy.iovcnt = 1;
-       copy.vr_idx = 0;  /* only one vring on virtio_block */
-       copy.update_used = true; /* Update used index */
-       return ioctl(fd, MIC_VIRTIO_COPY_DESC, &copy);
-}
-
-#ifndef VIRTIO_BLK_T_GET_ID
-#define VIRTIO_BLK_T_GET_ID    8
-#endif
-
-static void *
-virtio_block(void *arg)
-{
-       struct mic_info *mic = (struct mic_info *)arg;
-       int ret;
-       struct pollfd block_poll;
-       struct mic_vring vring;
-       __u16 avail_idx;
-       __u32 desc_idx;
-       struct vring_desc *desc;
-       struct iovec *iovec, *piov;
-       __u8 status;
-       __u32 buffer_desc_idx;
-       struct virtio_blk_outhdr hdr;
-       void *fos;
-
-       for (;;) {  /* forever */
-               if (!open_backend(mic)) { /* No virtblk */
-                       for (mic->mic_virtblk.signaled = 0;
-                               !mic->mic_virtblk.signaled;)
-                               sleep(1);
-                       continue;
-               }
-
-               /* backend file is specified. */
-               if (!start_virtblk(mic, &vring))
-                       goto _close_backend;
-               iovec = malloc(sizeof(*iovec) *
-                       le32toh(virtblk_dev_page.blk_config.seg_max));
-               if (!iovec) {
-                       mpsslog("%s: can't alloc iovec: %s\n",
-                               mic->name, strerror(ENOMEM));
-                       goto _stop_virtblk;
-               }
-
-               block_poll.fd = mic->mic_virtblk.virtio_block_fd;
-               block_poll.events = POLLIN;
-               for (mic->mic_virtblk.signaled = 0;
-                    !mic->mic_virtblk.signaled;) {
-                       block_poll.revents = 0;
-                                       /* timeout in 1 sec to see signaled */
-                       ret = poll(&block_poll, 1, 1000);
-                       if (ret < 0) {
-                               mpsslog("%s %d: poll failed: %s\n",
-                                       __func__, __LINE__,
-                                       strerror(errno));
-                               continue;
-                       }
-
-                       if (!(block_poll.revents & POLLIN)) {
-#ifdef DEBUG
-                               mpsslog("%s %d: block_poll.revents=0x%x\n",
-                                       __func__, __LINE__, block_poll.revents);
-#endif
-                               continue;
-                       }
-
-                       /* POLLIN */
-                       while (vring.info->avail_idx !=
-                               le16toh(vring.vr.avail->idx)) {
-                               /* read header element */
-                               avail_idx =
-                                       vring.info->avail_idx &
-                                       (vring.vr.num - 1);
-                               desc_idx = le16toh(
-                                       vring.vr.avail->ring[avail_idx]);
-                               desc = &vring.vr.desc[desc_idx];
-#ifdef DEBUG
-                               mpsslog("%s() %d: avail_idx=%d ",
-                                       __func__, __LINE__,
-                                       vring.info->avail_idx);
-                               mpsslog("vring.vr.num=%d desc=%p\n",
-                                       vring.vr.num, desc);
-#endif
-                               status = header_error_check(desc);
-                               ret = read_header(
-                                       mic->mic_virtblk.virtio_block_fd,
-                                       &hdr, desc_idx);
-                               if (ret < 0) {
-                                       mpsslog("%s() %d %s: ret=%d %s\n",
-                                               __func__, __LINE__,
-                                               mic->name, ret,
-                                               strerror(errno));
-                                       break;
-                               }
-                               /* buffer element */
-                               piov = iovec;
-                               status = 0;
-                               fos = mic->mic_virtblk.backend_addr +
-                                       (hdr.sector * SECTOR_SIZE);
-                               buffer_desc_idx = next_desc(desc);
-                               desc_idx = buffer_desc_idx;
-                               for (desc = &vring.vr.desc[buffer_desc_idx];
-                                    desc->flags & VRING_DESC_F_NEXT;
-                                    desc_idx = next_desc(desc),
-                                            desc = &vring.vr.desc[desc_idx]) {
-                                       piov->iov_len = desc->len;
-                                       piov->iov_base = fos;
-                                       piov++;
-                                       fos += desc->len;
-                               }
-                               /* Returning NULLs for VIRTIO_BLK_T_GET_ID. */
-                               if (hdr.type & ~(VIRTIO_BLK_T_OUT |
-                                       VIRTIO_BLK_T_GET_ID)) {
-                                       /*
-                                         VIRTIO_BLK_T_IN - does not do
-                                         anything. Probably for documenting.
-                                         VIRTIO_BLK_T_SCSI_CMD - for
-                                         virtio_scsi.
-                                         VIRTIO_BLK_T_FLUSH - turned off in
-                                         config space.
-                                         VIRTIO_BLK_T_BARRIER - defined but not
-                                         used in anywhere.
-                                       */
-                                       mpsslog("%s() %d: type %x ",
-                                               __func__, __LINE__,
-                                               hdr.type);
-                                       mpsslog("is not supported\n");
-                                       status = -ENOTSUP;
-
-                               } else {
-                                       ret = transfer_blocks(
-                                       mic->mic_virtblk.virtio_block_fd,
-                                               iovec,
-                                               piov - iovec);
-                                       if (ret < 0 &&
-                                           status != 0)
-                                               status = ret;
-                               }
-                               /* write status and update used pointer */
-                               if (status != 0)
-                                       status = status_error_check(desc);
-                               ret = write_status(
-                                       mic->mic_virtblk.virtio_block_fd,
-                                       &status);
-#ifdef DEBUG
-                               mpsslog("%s() %d: write status=%d on desc=%p\n",
-                                       __func__, __LINE__,
-                                       status, desc);
-#endif
-                       }
-               }
-               free(iovec);
-_stop_virtblk:
-               stop_virtblk(mic);
-_close_backend:
-               close_backend(mic);
-       }  /* forever */
-
-       pthread_exit(NULL);
-}
-
-static void
-reset(struct mic_info *mic)
-{
-#define RESET_TIMEOUT 120
-       int i = RESET_TIMEOUT;
-       setsysfs(mic->name, "state", "reset");
-       while (i) {
-               char *state;
-               state = readsysfs(mic->name, "state");
-               if (!state)
-                       goto retry;
-               mpsslog("%s: %s %d state %s\n",
-                       mic->name, __func__, __LINE__, state);
-
-               if (!strcmp(state, "ready")) {
-                       free(state);
-                       break;
-               }
-               free(state);
-retry:
-               sleep(1);
-               i--;
-       }
-}
-
-static int
-get_mic_shutdown_status(struct mic_info *mic, char *shutdown_status)
-{
-       if (!strcmp(shutdown_status, "nop"))
-               return MIC_NOP;
-       if (!strcmp(shutdown_status, "crashed"))
-               return MIC_CRASHED;
-       if (!strcmp(shutdown_status, "halted"))
-               return MIC_HALTED;
-       if (!strcmp(shutdown_status, "poweroff"))
-               return MIC_POWER_OFF;
-       if (!strcmp(shutdown_status, "restart"))
-               return MIC_RESTART;
-       mpsslog("%s: BUG invalid status %s\n", mic->name, shutdown_status);
-       /* Invalid state */
-       assert(0);
-};
-
-static int get_mic_state(struct mic_info *mic)
-{
-       char *state = NULL;
-       enum mic_states mic_state;
-
-       while (!state) {
-               state = readsysfs(mic->name, "state");
-               sleep(1);
-       }
-       mpsslog("%s: %s %d state %s\n",
-               mic->name, __func__, __LINE__, state);
-
-       if (!strcmp(state, "ready")) {
-               mic_state = MIC_READY;
-       } else if (!strcmp(state, "booting")) {
-               mic_state = MIC_BOOTING;
-       } else if (!strcmp(state, "online")) {
-               mic_state = MIC_ONLINE;
-       } else if (!strcmp(state, "shutting_down")) {
-               mic_state = MIC_SHUTTING_DOWN;
-       } else if (!strcmp(state, "reset_failed")) {
-               mic_state = MIC_RESET_FAILED;
-       } else if (!strcmp(state, "resetting")) {
-               mic_state = MIC_RESETTING;
-       } else {
-               mpsslog("%s: BUG invalid state %s\n", mic->name, state);
-               assert(0);
-       }
-
-       free(state);
-       return mic_state;
-};
-
-static void mic_handle_shutdown(struct mic_info *mic)
-{
-#define SHUTDOWN_TIMEOUT 60
-       int i = SHUTDOWN_TIMEOUT;
-       char *shutdown_status;
-       while (i) {
-               shutdown_status = readsysfs(mic->name, "shutdown_status");
-               if (!shutdown_status) {
-                       sleep(1);
-                       continue;
-               }
-               mpsslog("%s: %s %d shutdown_status %s\n",
-                       mic->name, __func__, __LINE__, shutdown_status);
-               switch (get_mic_shutdown_status(mic, shutdown_status)) {
-               case MIC_RESTART:
-                       mic->restart = 1;
-               case MIC_HALTED:
-               case MIC_POWER_OFF:
-               case MIC_CRASHED:
-                       free(shutdown_status);
-                       goto reset;
-               default:
-                       break;
-               }
-               free(shutdown_status);
-               sleep(1);
-               i--;
-       }
-reset:
-       if (!i)
-               mpsslog("%s: %s %d timing out waiting for shutdown_status %s\n",
-                       mic->name, __func__, __LINE__, shutdown_status);
-       reset(mic);
-}
-
-static int open_state_fd(struct mic_info *mic)
-{
-       char pathname[PATH_MAX];
-       int fd;
-
-       snprintf(pathname, PATH_MAX - 1, "%s/%s/%s",
-                MICSYSFSDIR, mic->name, "state");
-
-       fd = open(pathname, O_RDONLY);
-       if (fd < 0)
-               mpsslog("%s: opening file %s failed %s\n",
-                       mic->name, pathname, strerror(errno));
-       return fd;
-}
-
-static int block_till_state_change(int fd, struct mic_info *mic)
-{
-       struct pollfd ufds[1];
-       char value[PAGE_SIZE];
-       int ret;
-
-       ufds[0].fd = fd;
-       ufds[0].events = POLLERR | POLLPRI;
-       ret = poll(ufds, 1, -1);
-       if (ret < 0) {
-               mpsslog("%s: %s %d poll failed %s\n",
-                       mic->name, __func__, __LINE__, strerror(errno));
-               return ret;
-       }
-
-       ret = lseek(fd, 0, SEEK_SET);
-       if (ret < 0) {
-               mpsslog("%s: %s %d Failed to seek to 0: %s\n",
-                       mic->name, __func__, __LINE__, strerror(errno));
-               return ret;
-       }
-
-       ret = read(fd, value, sizeof(value));
-       if (ret < 0) {
-               mpsslog("%s: %s %d Failed to read sysfs entry: %s\n",
-                       mic->name, __func__, __LINE__, strerror(errno));
-               return ret;
-       }
-
-       return 0;
-}
-
-static void *
-mic_config(void *arg)
-{
-       struct mic_info *mic = (struct mic_info *)arg;
-       int fd, ret, stat = 0;
-
-       fd = open_state_fd(mic);
-       if (fd < 0) {
-               mpsslog("%s: %s %d open state fd failed %s\n",
-                       mic->name, __func__, __LINE__, strerror(errno));
-               goto exit;
-       }
-
-       do {
-               ret = block_till_state_change(fd, mic);
-               if (ret < 0) {
-                       mpsslog("%s: %s %d block_till_state_change error %s\n",
-                               mic->name, __func__, __LINE__, strerror(errno));
-                       goto close_exit;
-               }
-
-               switch (get_mic_state(mic)) {
-               case MIC_SHUTTING_DOWN:
-                       mic_handle_shutdown(mic);
-                       break;
-               case MIC_READY:
-               case MIC_RESET_FAILED:
-                       ret = kill(mic->pid, SIGTERM);
-                       mpsslog("%s: %s %d kill pid %d ret %d\n",
-                               mic->name, __func__, __LINE__,
-                               mic->pid, ret);
-                       if (!ret) {
-                               ret = waitpid(mic->pid, &stat,
-                                             WIFSIGNALED(stat));
-                               mpsslog("%s: %s %d waitpid ret %d pid %d\n",
-                                       mic->name, __func__, __LINE__,
-                                       ret, mic->pid);
-                       }
-                       if (mic->boot_on_resume) {
-                               setsysfs(mic->name, "state", "boot");
-                               mic->boot_on_resume = 0;
-                       }
-                       goto close_exit;
-               default:
-                       break;
-               }
-       } while (1);
-
-close_exit:
-       close(fd);
-exit:
-       init_mic(mic);
-       pthread_exit(NULL);
-}
-
-static void
-set_cmdline(struct mic_info *mic)
-{
-       char buffer[PATH_MAX];
-       int len;
-
-       len = snprintf(buffer, PATH_MAX,
-               "clocksource=tsc highres=off nohz=off ");
-       len += snprintf(buffer + len, PATH_MAX - len,
-               "cpufreq_on;corec6_off;pc3_off;pc6_off ");
-       len += snprintf(buffer + len, PATH_MAX - len,
-               "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0",
-               mic->id + 1);
-
-       setsysfs(mic->name, "cmdline", buffer);
-       mpsslog("%s: Command line: \"%s\"\n", mic->name, buffer);
-       snprintf(buffer, PATH_MAX, "172.31.%d.1", mic->id + 1);
-       mpsslog("%s: IPADDR: \"%s\"\n", mic->name, buffer);
-}
-
-static void
-set_log_buf_info(struct mic_info *mic)
-{
-       int fd;
-       off_t len;
-       char system_map[] = "/lib/firmware/mic/System.map";
-       char *map, *temp, log_buf[17] = {'\0'};
-
-       fd = open(system_map, O_RDONLY);
-       if (fd < 0) {
-               mpsslog("%s: Opening System.map failed: %d\n",
-                       mic->name, errno);
-               return;
-       }
-       len = lseek(fd, 0, SEEK_END);
-       if (len < 0) {
-               mpsslog("%s: Reading System.map size failed: %d\n",
-                       mic->name, errno);
-               close(fd);
-               return;
-       }
-       map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
-       if (map == MAP_FAILED) {
-               mpsslog("%s: mmap of System.map failed: %d\n",
-                       mic->name, errno);
-               close(fd);
-               return;
-       }
-       temp = strstr(map, "__log_buf");
-       if (!temp) {
-               mpsslog("%s: __log_buf not found: %d\n", mic->name, errno);
-               munmap(map, len);
-               close(fd);
-               return;
-       }
-       strncpy(log_buf, temp - 19, 16);
-       setsysfs(mic->name, "log_buf_addr", log_buf);
-       mpsslog("%s: log_buf_addr: %s\n", mic->name, log_buf);
-       temp = strstr(map, "log_buf_len");
-       if (!temp) {
-               mpsslog("%s: log_buf_len not found: %d\n", mic->name, errno);
-               munmap(map, len);
-               close(fd);
-               return;
-       }
-       strncpy(log_buf, temp - 19, 16);
-       setsysfs(mic->name, "log_buf_len", log_buf);
-       mpsslog("%s: log_buf_len: %s\n", mic->name, log_buf);
-       munmap(map, len);
-       close(fd);
-}
-
-static void
-change_virtblk_backend(int x, siginfo_t *siginfo, void *p)
-{
-       struct mic_info *mic;
-
-       for (mic = mic_list.next; mic != NULL; mic = mic->next)
-               mic->mic_virtblk.signaled = 1/* true */;
-}
-
-static void
-set_mic_boot_params(struct mic_info *mic)
-{
-       set_log_buf_info(mic);
-       set_cmdline(mic);
-}
-
-static void *
-init_mic(void *arg)
-{
-       struct mic_info *mic = (struct mic_info *)arg;
-       struct sigaction ignore = {
-               .sa_flags = 0,
-               .sa_handler = SIG_IGN
-       };
-       struct sigaction act = {
-               .sa_flags = SA_SIGINFO,
-               .sa_sigaction = change_virtblk_backend,
-       };
-       char buffer[PATH_MAX];
-       int err, fd;
-
-       /*
-        * Currently, one virtio block device is supported for each MIC card
-        * at a time. Any user (or test) can send a SIGUSR1 to the MIC daemon.
-        * The signal informs the virtio block backend about a change in the
-        * configuration file which specifies the virtio backend file name on
-        * the host. Virtio block backend then re-reads the configuration file
-        * and switches to the new block device. This signalling mechanism may
-        * not be required once multiple virtio block devices are supported by
-        * the MIC daemon.
-        */
-       sigaction(SIGUSR1, &ignore, NULL);
-retry:
-       fd = open_state_fd(mic);
-       if (fd < 0) {
-               mpsslog("%s: %s %d open state fd failed %s\n",
-                       mic->name, __func__, __LINE__, strerror(errno));
-               sleep(2);
-               goto retry;
-       }
-
-       if (mic->restart) {
-               snprintf(buffer, PATH_MAX, "boot");
-               setsysfs(mic->name, "state", buffer);
-               mpsslog("%s restarting mic %d\n",
-                       mic->name, mic->restart);
-               mic->restart = 0;
-       }
-
-       while (1) {
-               while (block_till_state_change(fd, mic)) {
-                       mpsslog("%s: %s %d block_till_state_change error %s\n",
-                               mic->name, __func__, __LINE__, strerror(errno));
-                       sleep(2);
-                       continue;
-               }
-
-               if (get_mic_state(mic) == MIC_BOOTING)
-                       break;
-       }
-
-       mic->pid = fork();
-       switch (mic->pid) {
-       case 0:
-               add_virtio_device(mic, &virtcons_dev_page.dd);
-               add_virtio_device(mic, &virtnet_dev_page.dd);
-               err = pthread_create(&mic->mic_console.console_thread, NULL,
-                       virtio_console, mic);
-               if (err)
-                       mpsslog("%s virtcons pthread_create failed %s\n",
-                               mic->name, strerror(err));
-               err = pthread_create(&mic->mic_net.net_thread, NULL,
-                       virtio_net, mic);
-               if (err)
-                       mpsslog("%s virtnet pthread_create failed %s\n",
-                               mic->name, strerror(err));
-               err = pthread_create(&mic->mic_virtblk.block_thread, NULL,
-                       virtio_block, mic);
-               if (err)
-                       mpsslog("%s virtblk pthread_create failed %s\n",
-                               mic->name, strerror(err));
-               sigemptyset(&act.sa_mask);
-               err = sigaction(SIGUSR1, &act, NULL);
-               if (err)
-                       mpsslog("%s sigaction SIGUSR1 failed %s\n",
-                               mic->name, strerror(errno));
-               while (1)
-                       sleep(60);
-       case -1:
-               mpsslog("fork failed MIC name %s id %d errno %d\n",
-                       mic->name, mic->id, errno);
-               break;
-       default:
-               err = pthread_create(&mic->config_thread, NULL,
-                                    mic_config, mic);
-               if (err)
-                       mpsslog("%s mic_config pthread_create failed %s\n",
-                               mic->name, strerror(err));
-       }
-
-       return NULL;
-}
-
-static void
-start_daemon(void)
-{
-       struct mic_info *mic;
-       int err;
-
-       for (mic = mic_list.next; mic; mic = mic->next) {
-               set_mic_boot_params(mic);
-               err = pthread_create(&mic->init_thread, NULL, init_mic, mic);
-               if (err)
-                       mpsslog("%s init_mic pthread_create failed %s\n",
-                               mic->name, strerror(err));
-       }
-
-       while (1)
-               sleep(60);
-}
-
-static int
-init_mic_list(void)
-{
-       struct mic_info *mic = &mic_list;
-       struct dirent *file;
-       DIR *dp;
-       int cnt = 0;
-
-       dp = opendir(MICSYSFSDIR);
-       if (!dp)
-               return 0;
-
-       while ((file = readdir(dp)) != NULL) {
-               if (!strncmp(file->d_name, "mic", 3)) {
-                       mic->next = calloc(1, sizeof(struct mic_info));
-                       if (mic->next) {
-                               mic = mic->next;
-                               mic->id = atoi(&file->d_name[3]);
-                               mic->name = malloc(strlen(file->d_name) + 16);
-                               if (mic->name)
-                                       strcpy(mic->name, file->d_name);
-                               mpsslog("MIC name %s id %d\n", mic->name,
-                                       mic->id);
-                               cnt++;
-                       }
-               }
-       }
-
-       closedir(dp);
-       return cnt;
-}
-
-void
-mpsslog(char *format, ...)
-{
-       va_list args;
-       char buffer[4096];
-       char ts[52], *ts1;
-       time_t t;
-
-       if (logfp == NULL)
-               return;
-
-       va_start(args, format);
-       vsprintf(buffer, format, args);
-       va_end(args);
-
-       time(&t);
-       ts1 = ctime_r(&t, ts);
-       ts1[strlen(ts1) - 1] = '\0';
-       fprintf(logfp, "%s: %s", ts1, buffer);
-
-       fflush(logfp);
-}
-
-int
-main(int argc, char *argv[])
-{
-       int cnt;
-       pid_t pid;
-
-       myname = argv[0];
-
-       logfp = fopen(LOGFILE_NAME, "a+");
-       if (!logfp) {
-               fprintf(stderr, "cannot open logfile '%s'\n", LOGFILE_NAME);
-               exit(1);
-       }
-       pid = fork();
-       switch (pid) {
-       case 0:
-               break;
-       case -1:
-               exit(2);
-       default:
-               exit(0);
-       }
-
-       mpsslog("MIC Daemon start\n");
-
-       cnt = init_mic_list();
-       if (cnt == 0) {
-               mpsslog("MIC module not loaded\n");
-               exit(3);
-       }
-       mpsslog("MIC found %d devices\n", cnt);
-
-       start_daemon();
-
-       exit(0);
-}
diff --git a/samples/mic/mpssd/mpssd.h b/samples/mic/mpssd/mpssd.h
deleted file mode 100644 (file)
index 5f98bda..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Intel MIC User Space Tools.
- */
-#ifndef _MPSSD_H_
-#define _MPSSD_H_
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <libgen.h>
-#include <pthread.h>
-#include <stdarg.h>
-#include <time.h>
-#include <errno.h>
-#include <sys/dir.h>
-#include <sys/ioctl.h>
-#include <sys/poll.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <sys/utsname.h>
-#include <sys/wait.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <signal.h>
-#include <limits.h>
-#include <syslog.h>
-#include <getopt.h>
-#include <net/if.h>
-#include <linux/if_tun.h>
-#include <linux/virtio_ids.h>
-
-#define MICSYSFSDIR "/sys/class/mic"
-#define LOGFILE_NAME "/var/log/mpssd"
-#define PAGE_SIZE 4096
-
-struct mic_console_info {
-       pthread_t       console_thread;
-       int             virtio_console_fd;
-       void            *console_dp;
-};
-
-struct mic_net_info {
-       pthread_t       net_thread;
-       int             virtio_net_fd;
-       int             tap_fd;
-       void            *net_dp;
-};
-
-struct mic_virtblk_info {
-       pthread_t       block_thread;
-       int             virtio_block_fd;
-       void            *block_dp;
-       volatile sig_atomic_t   signaled;
-       char            *backend_file;
-       int             backend;
-       void            *backend_addr;
-       long            backend_size;
-};
-
-struct mic_info {
-       int             id;
-       char            *name;
-       pthread_t       config_thread;
-       pthread_t       init_thread;
-       pid_t           pid;
-       struct mic_console_info mic_console;
-       struct mic_net_info     mic_net;
-       struct mic_virtblk_info mic_virtblk;
-       int             restart;
-       int             boot_on_resume;
-       struct mic_info *next;
-};
-
-__attribute__((format(printf, 1, 2)))
-void mpsslog(char *format, ...);
-char *readsysfs(char *dir, char *entry);
-int setsysfs(char *dir, char *entry, char *value);
-#endif
diff --git a/samples/mic/mpssd/sysfs.c b/samples/mic/mpssd/sysfs.c
deleted file mode 100644 (file)
index 3fb08eb..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * Intel MIC User Space Tools.
- */
-
-#include "mpssd.h"
-
-#define PAGE_SIZE 4096
-
-char *
-readsysfs(char *dir, char *entry)
-{
-       char filename[PATH_MAX];
-       char value[PAGE_SIZE];
-       char *string = NULL;
-       int fd;
-       int len;
-
-       if (dir == NULL)
-               snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry);
-       else
-               snprintf(filename, PATH_MAX,
-                        "%s/%s/%s", MICSYSFSDIR, dir, entry);
-
-       fd = open(filename, O_RDONLY);
-       if (fd < 0) {
-               mpsslog("Failed to open sysfs entry '%s': %s\n",
-                       filename, strerror(errno));
-               return NULL;
-       }
-
-       len = read(fd, value, sizeof(value));
-       if (len < 0) {
-               mpsslog("Failed to read sysfs entry '%s': %s\n",
-                       filename, strerror(errno));
-               goto readsys_ret;
-       }
-       if (len == 0)
-               goto readsys_ret;
-
-       value[len - 1] = '\0';
-
-       string = malloc(strlen(value) + 1);
-       if (string)
-               strcpy(string, value);
-
-readsys_ret:
-       close(fd);
-       return string;
-}
-
-int
-setsysfs(char *dir, char *entry, char *value)
-{
-       char filename[PATH_MAX];
-       char *oldvalue;
-       int fd, ret = 0;
-
-       if (dir == NULL)
-               snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry);
-       else
-               snprintf(filename, PATH_MAX, "%s/%s/%s",
-                        MICSYSFSDIR, dir, entry);
-
-       oldvalue = readsysfs(dir, entry);
-
-       fd = open(filename, O_RDWR);
-       if (fd < 0) {
-               ret = errno;
-               mpsslog("Failed to open sysfs entry '%s': %s\n",
-                       filename, strerror(errno));
-               goto done;
-       }
-
-       if (!oldvalue || strcmp(value, oldvalue)) {
-               if (write(fd, value, strlen(value)) < 0) {
-                       ret = errno;
-                       mpsslog("Failed to write new sysfs entry '%s': %s\n",
-                               filename, strerror(errno));
-               }
-       }
-       close(fd);
-done:
-       if (oldvalue)
-               free(oldvalue);
-       return ret;
-}
index ae647379b57953d4b291b850f4712a5926d4400f..4c058f12dd73cb6d2d3832788f25daa9d2b413d6 100644 (file)
@@ -252,6 +252,9 @@ objtool_dep = $(objtool_obj)                                        \
 ifdef CONFIG_TRIM_UNUSED_KSYMS
 cmd_gen_ksymdeps = \
        $(CONFIG_SHELL) $(srctree)/scripts/gen_ksymdeps.sh $@ >> $(dot-target).cmd
+
+# List module undefined symbols
+undefined_syms = $(NM) $< | $(AWK) '$$1 == "U" { printf("%s%s", x++ ? " " : "", $$2) }';
 endif
 
 define rule_cc_o_c
@@ -271,13 +274,6 @@ define rule_as_o_S
        $(call cmd,modversions_S)
 endef
 
-# List module undefined symbols (or empty line if not enabled)
-ifdef CONFIG_TRIM_UNUSED_KSYMS
-cmd_undef_syms = $(NM) $< | sed -n 's/^  *U //p' | xargs echo
-else
-cmd_undef_syms = echo
-endif
-
 # Built-in and composite module parts
 $(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_dep) FORCE
        $(call if_changed_rule,cc_o_c)
@@ -285,7 +281,7 @@ $(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_dep) FORCE
 
 cmd_mod = { \
        echo $(if $($*-objs)$($*-y)$($*-m), $(addprefix $(obj)/, $($*-objs) $($*-y) $($*-m)), $(@:.mod=.o)); \
-       $(cmd_undef_syms); \
+       $(undefined_syms) echo; \
        } > $@
 
 $(obj)/%.mod: $(obj)/%.o FORCE
index 95e4cdb94fe9f7bfc99f49646c447df98caf23b8..6baee1200615d53ec7d783108a456825b385d5e0 100644 (file)
@@ -60,7 +60,6 @@ endif
 #
 ifneq ($(findstring 2, $(KBUILD_EXTRA_WARN)),)
 
-KBUILD_CFLAGS += -Wcast-align
 KBUILD_CFLAGS += -Wdisabled-optimization
 KBUILD_CFLAGS += -Wnested-externs
 KBUILD_CFLAGS += -Wshadow
@@ -80,6 +79,7 @@ endif
 ifneq ($(findstring 3, $(KBUILD_EXTRA_WARN)),)
 
 KBUILD_CFLAGS += -Wbad-function-cast
+KBUILD_CFLAGS += -Wcast-align
 KBUILD_CFLAGS += -Wcast-qual
 KBUILD_CFLAGS += -Wconversion
 KBUILD_CFLAGS += -Wpacked
index 6769caae142fbcb255cef674ff2dd3360288a72c..31484377b8b11a69c269285f757dd5094b1e46ed 100755 (executable)
@@ -408,6 +408,7 @@ class PrinterHelpers(Printer):
             'struct bpf_perf_event_data',
             'struct bpf_perf_event_value',
             'struct bpf_pidns_info',
+            'struct bpf_redir_neigh',
             'struct bpf_sock',
             'struct bpf_sock_addr',
             'struct bpf_sock_ops',
index c738cb79551411ad5c3bd3d183f75e8ca5e62c44..68dab828a722d1ef670f39fae398947b60701420 100755 (executable)
@@ -2,18 +2,28 @@
 # SPDX-License-Identifier: GPL-2.0
 
 use strict;
+use warnings;
+use utf8;
 use Pod::Usage;
 use Getopt::Long;
 use File::Find;
 use Fcntl ':mode';
 
-my $help;
-my $man;
-my $debug;
+my $help = 0;
+my $man = 0;
+my $debug = 0;
+my $enable_lineno = 0;
 my $prefix="Documentation/ABI";
 
+#
+# If true, assumes that the description is formatted with ReST
+#
+my $description_is_rst = 1;
+
 GetOptions(
        "debug|d+" => \$debug,
+       "enable-lineno" => \$enable_lineno,
+       "rst-source!" => \$description_is_rst,
        "dir=s" => \$prefix,
        'help|?' => \$help,
        man => \$man
@@ -32,6 +42,7 @@ pod2usage(2) if ($cmd eq "search" && !$arg);
 require Data::Dumper if ($debug);
 
 my %data;
+my %symbols;
 
 #
 # Displays an error message, printing file name and line
@@ -39,7 +50,15 @@ my %data;
 sub parse_error($$$$) {
        my ($file, $ln, $msg, $data) = @_;
 
-       print STDERR "file $file#$ln: $msg at\n\t$data";
+       $data =~ s/\s+$/\n/;
+
+       print STDERR "Warning: file $file#$ln:\n\t$msg";
+
+       if ($data ne "") {
+               print STDERR ". Line\n\t\t$data";
+       } else {
+           print STDERR "\n";
+       }
 }
 
 #
@@ -55,24 +74,28 @@ sub parse_abi {
        my $name = $file;
        $name =~ s,.*/,,;
 
-       my $nametag = "File $name";
+       my $fn = $file;
+       $fn =~ s,Documentation/ABI/,,;
+
+       my $nametag = "File $fn";
        $data{$nametag}->{what} = "File $name";
        $data{$nametag}->{type} = "File";
        $data{$nametag}->{file} = $name;
        $data{$nametag}->{filepath} = $file;
        $data{$nametag}->{is_file} = 1;
+       $data{$nametag}->{line_no} = 1;
 
        my $type = $file;
        $type =~ s,.*/(.*)/.*,$1,;
 
        my $what;
        my $new_what;
-       my $tag;
+       my $tag = "";
        my $ln;
        my $xrefs;
        my $space;
        my @labels;
-       my $label;
+       my $label = "";
 
        print STDERR "Opening $file\n" if ($debug > 1);
        open IN, $file;
@@ -95,16 +118,26 @@ sub parse_abi {
 
                        # Invalid, but it is a common mistake
                        if ($new_tag eq "where") {
-                               parse_error($file, $ln, "tag 'Where' is invalid. Should be 'What:' instead", $_);
+                               parse_error($file, $ln, "tag 'Where' is invalid. Should be 'What:' instead", "");
                                $new_tag = "what";
                        }
 
                        if ($new_tag =~ m/what/) {
                                $space = "";
+                               $content =~ s/[,.;]$//;
+
+                               push @{$symbols{$content}->{file}}, " $file:" . ($ln - 1);
+
                                if ($tag =~ m/what/) {
                                        $what .= ", " . $content;
                                } else {
-                                       parse_error($file, $ln, "What '$what' doesn't have a description", "") if ($what && !$data{$what}->{description});
+                                       if ($what) {
+                                               parse_error($file, $ln, "What '$what' doesn't have a description", "") if (!$data{$what}->{description});
+
+                                               foreach my $w(split /, /, $what) {
+                                                       $symbols{$w}->{xref} = $what;
+                                               };
+                                       }
 
                                        $what = $content;
                                        $label = $content;
@@ -113,7 +146,7 @@ sub parse_abi {
                                push @labels, [($content, $label)];
                                $tag = $new_tag;
 
-                               push @{$data{$nametag}->{xrefs}}, [($content, $label)] if ($data{$nametag}->{what});
+                               push @{$data{$nametag}->{symbols}}, $content if ($data{$nametag}->{what});
                                next;
                        }
 
@@ -121,30 +154,44 @@ sub parse_abi {
                                $tag = $new_tag;
 
                                if ($new_what) {
-                                       @{$data{$what}->{label}} = @labels if ($data{$nametag}->{what});
+                                       @{$data{$what}->{label_list}} = @labels if ($data{$nametag}->{what});
                                        @labels = ();
                                        $label = "";
                                        $new_what = 0;
 
                                        $data{$what}->{type} = $type;
-                                       $data{$what}->{file} = $name;
-                                       $data{$what}->{filepath} = $file;
+                                       if (!defined($data{$what}->{file})) {
+                                               $data{$what}->{file} = $name;
+                                               $data{$what}->{filepath} = $file;
+                                       } else {
+                                               if ($name ne $data{$what}->{file}) {
+                                                       $data{$what}->{file} .= " " . $name;
+                                                       $data{$what}->{filepath} .= " " . $file;
+                                               }
+                                       }
                                        print STDERR "\twhat: $what\n" if ($debug > 1);
+                                       $data{$what}->{line_no} = $ln;
+                               } else {
+                                       $data{$what}->{line_no} = $ln if (!defined($data{$what}->{line_no}));
                                }
 
                                if (!$what) {
                                        parse_error($file, $ln, "'What:' should come first:", $_);
                                        next;
                                }
-                               if ($tag eq "description") {
-                                       next if ($content =~ m/^\s*$/);
-                                       if ($content =~ m/^(\s*)(.*)/) {
-                                               my $new_content = $2;
-                                               $space = $new_tag . $sep . $1;
-                                               while ($space =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
-                                               $space =~ s/./ /g;
-                                               $data{$what}->{$tag} .= "$new_content\n";
+                               if ($new_tag eq "description") {
+                                       $sep =~ s,:, ,;
+                                       $content = ' ' x length($new_tag) . $sep . $content;
+                                       while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
+                                       if ($content =~ m/^(\s*)(\S.*)$/) {
+                                               # Preserve initial spaces for the first line
+                                               $space = $1;
+                                               $content = "$2\n";
+                                               $data{$what}->{$tag} .= $content;
+                                       } else {
+                                               undef($space);
                                        }
+
                                } else {
                                        $data{$what}->{$tag} = $content;
                                }
@@ -159,29 +206,24 @@ sub parse_abi {
                }
 
                if ($tag eq "description") {
-                       if (!$data{$what}->{description}) {
-                               next if (m/^\s*\n/);
-                               if (m/^(\s*)(.*)/) {
+                       my $content = $_;
+                       while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
+                       if (m/^\s*\n/) {
+                               $data{$what}->{$tag} .= "\n";
+                               next;
+                       }
+
+                       if (!defined($space)) {
+                               # Preserve initial spaces for the first line
+                               if ($content =~ m/^(\s*)(\S.*)$/) {
                                        $space = $1;
-                                       while ($space =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
-                                       $data{$what}->{$tag} .= "$2\n";
+                                       $content = "$2\n";
                                }
                        } else {
-                               my $content = $_;
-                               if (m/^\s*\n/) {
-                                       $data{$what}->{$tag} .= $content;
-                                       next;
-                               }
-
-                               while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
                                $space = "" if (!($content =~ s/^($space)//));
-
-                               # Compress spaces with tabs
-                               $content =~ s<^ {8}> <\t>;
-                               $content =~ s<^ {1,7}\t> <\t>;
-                               $content =~ s< {1,7}\t> <\t>;
-                               $data{$what}->{$tag} .= $content;
                        }
+                       $data{$what}->{$tag} .= $content;
+
                        next;
                }
                if (m/^\s*(.*)/) {
@@ -191,32 +233,26 @@ sub parse_abi {
                }
 
                # Everything else is error
-               parse_error($file, $ln, "Unexpected line:", $_);
+               parse_error($file, $ln, "Unexpected content", $_);
+       }
+       $data{$nametag}->{description} =~ s/^\n+// if ($data{$nametag}->{description});
+       if ($what) {
+               parse_error($file, $ln, "What '$what' doesn't have a description", "") if (!$data{$what}->{description});
+
+               foreach my $w(split /, /,$what) {
+                       $symbols{$w}->{xref} = $what;
+               };
        }
-       $data{$nametag}->{description} =~ s/^\n+//;
        close IN;
 }
 
-#
-# Outputs the book on ReST format
-#
+sub create_labels {
+       my %labels;
 
-my %labels;
+       foreach my $what (keys %data) {
+               next if ($data{$what}->{file} eq "File");
 
-sub output_rest {
-       foreach my $what (sort {
-                               ($data{$a}->{type} eq "File") cmp ($data{$b}->{type} eq "File") ||
-                               $a cmp $b
-                              } keys %data) {
-               my $type = $data{$what}->{type};
-               my $file = $data{$what}->{file};
-               my $filepath = $data{$what}->{filepath};
-
-               my $w = $what;
-               $w =~ s/([\(\)\_\-\*\=\^\~\\])/\\$1/g;
-
-
-               foreach my $p (@{$data{$what}->{label}}) {
+               foreach my $p (@{$data{$what}->{label_list}}) {
                        my ($content, $label) = @{$p};
                        $label = "abi_" . $label . " ";
                        $label =~ tr/A-Z/a-z/;
@@ -233,81 +269,167 @@ sub output_rest {
                        }
                        $labels{$label} = 1;
 
-                       $data{$what}->{label} .= $label;
-
-                       printf ".. _%s:\n\n", $label;
+                       $data{$what}->{label} = $label;
 
                        # only one label is enough
                        last;
                }
+       }
+}
 
+#
+# Outputs the book on ReST format
+#
 
-               $filepath =~ s,.*/(.*/.*),\1,;;
-               $filepath =~ s,[/\-],_,g;;
-               my $fileref = "abi_file_".$filepath;
+# \b doesn't work well with paths. So, we need to define something else
+my $bondary = qr { (?<![\w\/\`\{])(?=[\w\/\`\{])|(?<=[\w\/\`\{])(?![\w\/\`\{]) }x;
 
-               if ($type eq "File") {
-                       my $bar = $w;
-                       $bar =~ s/./-/g;
+sub output_rest {
+       create_labels();
 
-                       print ".. _$fileref:\n\n";
-                       print "$w\n$bar\n\n";
-               } else {
-                       my @names = split /\s*,\s*/,$w;
+       my $part = "";
+
+       foreach my $what (sort {
+                               ($data{$a}->{type} eq "File") cmp ($data{$b}->{type} eq "File") ||
+                               $a cmp $b
+                              } keys %data) {
+               my $type = $data{$what}->{type};
+
+               my @file = split / /, $data{$what}->{file};
+               my @filepath = split / /, $data{$what}->{filepath};
+
+               if ($enable_lineno) {
+                       printf "#define LINENO %s%s#%s\n\n",
+                              $prefix, $file[0],
+                              $data{$what}->{line_no};
+               }
+
+               my $w = $what;
+               $w =~ s/([\(\)\_\-\*\=\^\~\\])/\\$1/g;
+
+               if ($type ne "File") {
+                       my $cur_part = $what;
+                       if ($what =~ '/') {
+                               if ($what =~ m#^(\/?(?:[\w\-]+\/?){1,2})#) {
+                                       $cur_part = "Symbols under $1";
+                                       $cur_part =~ s,/$,,;
+                               }
+                       }
+
+                       if ($cur_part ne "" && $part ne $cur_part) {
+                           $part = $cur_part;
+                           my $bar = $part;
+                           $bar =~ s/./-/g;
+                           print "$part\n$bar\n\n";
+                       }
+
+                       printf ".. _%s:\n\n", $data{$what}->{label};
 
+                       my @names = split /, /,$w;
                        my $len = 0;
 
                        foreach my $name (@names) {
+                               $name = "**$name**";
                                $len = length($name) if (length($name) > $len);
                        }
 
-                       print "What:\n\n";
-
                        print "+-" . "-" x $len . "-+\n";
                        foreach my $name (@names) {
                                printf "| %s", $name . " " x ($len - length($name)) . " |\n";
                                print "+-" . "-" x $len . "-+\n";
                        }
+
                        print "\n";
                }
 
-               print "Defined on file :ref:`$file <$fileref>`\n\n" if ($type ne "File");
+               for (my $i = 0; $i < scalar(@filepath); $i++) {
+                       my $path = $filepath[$i];
+                       my $f = $file[$i];
+
+                       $path =~ s,.*/(.*/.*),$1,;;
+                       $path =~ s,[/\-],_,g;;
+                       my $fileref = "abi_file_".$path;
+
+                       if ($type eq "File") {
+                               print ".. _$fileref:\n\n";
+                       } else {
+                               print "Defined on file :ref:`$f <$fileref>`\n\n";
+                       }
+               }
 
-               my $desc = $data{$what}->{description};
-               $desc =~ s/^\s+//;
+               if ($type eq "File") {
+                       my $bar = $w;
+                       $bar =~ s/./-/g;
+                       print "$w\n$bar\n\n";
+               }
 
-               # Remove title markups from the description, as they won't work
-               $desc =~ s/\n[\-\*\=\^\~]+\n/\n/g;
+               my $desc = "";
+               $desc = $data{$what}->{description} if (defined($data{$what}->{description}));
+               $desc =~ s/\s+$/\n/;
 
                if (!($desc =~ /^\s*$/)) {
-                       if ($desc =~ m/\:\n/ || $desc =~ m/\n[\t ]+/  || $desc =~ m/[\x00-\x08\x0b-\x1f\x7b-\xff]/) {
-                               # put everything inside a code block
-                               $desc =~ s/\n/\n /g;
+                       if ($description_is_rst) {
+                               # Remove title markups from the description
+                               # Having titles inside ABI files will only work if extra
+                               # care would be taken in order to strictly follow the same
+                               # level order for each markup.
+                               $desc =~ s/\n[\-\*\=\^\~]+\n/\n\n/g;
+
+                               # Enrich text by creating cross-references
+
+                               $desc =~ s,Documentation/(?!devicetree)(\S+)\.rst,:doc:`/$1`,g;
+
+                               my @matches = $desc =~ m,Documentation/ABI/([\w\/\-]+),;
+                               foreach my $f (@matches) {
+                                       my $xref = $f;
+                                       my $path = $f;
+                                       $path =~ s,.*/(.*/.*),$1,;;
+                                       $path =~ s,[/\-],_,g;;
+                                       $xref .= " <abi_file_" . $path . ">";
+                                       $desc =~ s,\bDocumentation/ABI/$f\b,:ref:`$xref`,g;
+                               }
 
-                               print "::\n\n";
-                               print " $desc\n\n";
-                       } else {
-                               # Escape any special chars from description
-                               $desc =~s/([\x00-\x08\x0b-\x1f\x21-\x2a\x2d\x2f\x3c-\x40\x5c\x5e-\x60\x7b-\xff])/\\$1/g;
+                               @matches = $desc =~ m,$bondary(/sys/[^\s\.\,\;\:\*\s\`\'\(\)]+)$bondary,;
+
+                               foreach my $s (@matches) {
+                                       if (defined($data{$s}) && defined($data{$s}->{label})) {
+                                               my $xref = $s;
+
+                                               $xref =~ s/([\x00-\x1f\x21-\x2f\x3a-\x40\x7b-\xff])/\\$1/g;
+                                               $xref = ":ref:`$xref <" . $data{$s}->{label} . ">`";
+
+                                               $desc =~ s,$bondary$s$bondary,$xref,g;
+                                       }
+                               }
 
                                print "$desc\n\n";
+                       } else {
+                               $desc =~ s/^\s+//;
+
+                               # Remove title markups from the description, as they won't work
+                               $desc =~ s/\n[\-\*\=\^\~]+\n/\n\n/g;
+
+                               if ($desc =~ m/\:\n/ || $desc =~ m/\n[\t ]+/  || $desc =~ m/[\x00-\x08\x0b-\x1f\x7b-\xff]/) {
+                                       # put everything inside a code block
+                                       $desc =~ s/\n/\n /g;
+
+                                       print "::\n\n";
+                                       print " $desc\n\n";
+                               } else {
+                                       # Escape any special chars from description
+                                       $desc =~s/([\x00-\x08\x0b-\x1f\x21-\x2a\x2d\x2f\x3c-\x40\x5c\x5e-\x60\x7b-\xff])/\\$1/g;
+                                       print "$desc\n\n";
+                               }
                        }
                } else {
                        print "DESCRIPTION MISSING for $what\n\n" if (!$data{$what}->{is_file});
                }
 
-               if ($data{$what}->{xrefs}) {
+               if ($data{$what}->{symbols}) {
                        printf "Has the following ABI:\n\n";
 
-                       foreach my $p(@{$data{$what}->{xrefs}}) {
-                               my ($content, $label) = @{$p};
-                               $label = "abi_" . $label . " ";
-                               $label =~ tr/A-Z/a-z/;
-
-                               # Convert special chars to "_"
-                               $label =~s/([\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\xff])/_/g;
-                               $label =~ s,_+,_,g;
-                               $label =~ s,_$,,;
+                       foreach my $content(@{$data{$what}->{symbols}}) {
+                               my $label = $data{$symbols{$content}->{xref}}->{label};
 
                                # Escape special chars from content
                                $content =~s/([\x00-\x1f\x21-\x2f\x3a-\x40\x7b-\xff])/\\$1/g;
@@ -315,6 +437,14 @@ sub output_rest {
                                print "- :ref:`$content <$label>`\n\n";
                        }
                }
+
+               if (defined($data{$what}->{users})) {
+                       my $users = $data{$what}->{users};
+
+                       $users =~ s/\n/\n\t/g;
+                       printf "Users:\n\t%s\n\n", $users if ($users ne "");
+               }
+
        }
 }
 
@@ -335,27 +465,34 @@ sub search_symbols {
 
                print "\n$what\n$bar\n\n";
 
-               my $kernelversion = $data{$what}->{kernelversion};
-               my $contact = $data{$what}->{contact};
-               my $users = $data{$what}->{users};
-               my $date = $data{$what}->{date};
-               my $desc = $data{$what}->{description};
-               $kernelversion =~ s/^\s+//;
-               $contact =~ s/^\s+//;
-               $users =~ s/^\s+//;
-               $users =~ s/\n//g;
-               $date =~ s/^\s+//;
-               $desc =~ s/^\s+//;
+               my $kernelversion = $data{$what}->{kernelversion} if (defined($data{$what}->{kernelversion}));
+               my $contact = $data{$what}->{contact} if (defined($data{$what}->{contact}));
+               my $users = $data{$what}->{users} if (defined($data{$what}->{users}));
+               my $date = $data{$what}->{date} if (defined($data{$what}->{date}));
+               my $desc = $data{$what}->{description} if (defined($data{$what}->{description}));
+
+               $kernelversion =~ s/^\s+// if ($kernelversion);
+               $contact =~ s/^\s+// if ($contact);
+               if ($users) {
+                       $users =~ s/^\s+//;
+                       $users =~ s/\n//g;
+               }
+               $date =~ s/^\s+// if ($date);
+               $desc =~ s/^\s+// if ($desc);
 
                printf "Kernel version:\t\t%s\n", $kernelversion if ($kernelversion);
                printf "Date:\t\t\t%s\n", $date if ($date);
                printf "Contact:\t\t%s\n", $contact if ($contact);
                printf "Users:\t\t\t%s\n", $users if ($users);
-               print "Defined on file:\t$file\n\n";
+               print "Defined on file(s):\t$file\n\n";
                print "Description:\n\n$desc";
        }
 }
 
+# Ensure that the prefix will always end with a slash
+# While this is not needed for find, it makes the patch nicer
+# with --enable-lineno
+$prefix =~ s,/?$,/,;
 
 #
 # Parses all ABI files located at $prefix dir
@@ -367,12 +504,23 @@ print STDERR Data::Dumper->Dump([\%data], [qw(*data)]) if ($debug);
 #
 # Handles the command
 #
-if ($cmd eq "rest") {
-       output_rest;
-} elsif ($cmd eq "search") {
+if ($cmd eq "search") {
        search_symbols;
-}
+} else {
+       if ($cmd eq "rest") {
+               output_rest;
+       }
+
+       # Warn about duplicated ABI entries
+       foreach my $what(sort keys %symbols) {
+               my @files = @{$symbols{$what}->{file}};
 
+               next if (scalar(@files) == 1);
+
+               printf STDERR "Warning: $what is defined %d times: @files\n",
+                   scalar(@files);
+       }
+}
 
 __END__
 
@@ -382,7 +530,8 @@ abi_book.pl - parse the Linux ABI files and produce a ReST book.
 
 =head1 SYNOPSIS
 
-B<abi_book.pl> [--debug] [--man] [--help] [--dir=<dir>] <COMAND> [<ARGUMENT>]
+B<abi_book.pl> [--debug] [--enable-lineno] [--man] [--help]
+              [--(no-)rst-source] [--dir=<dir>] <COMAND> [<ARGUMENT>]
 
 Where <COMMAND> can be:
 
@@ -405,6 +554,17 @@ B<validate>              - validate the ABI contents
 Changes the location of the ABI search. By default, it uses
 the Documentation/ABI directory.
 
+=item B<--rst-source> and B<--no-rst-source>
+
+The input file may be using ReST syntax or not. Those two options allow
+selecting between a rst-compliant source ABI (--rst-source), or a
+plain text that may be violating ReST spec, so it requres some escaping
+logic (--no-rst-source).
+
+=item B<--enable-lineno>
+
+Enable output of #define LINENO lines.
+
 =item B<--debug>
 
 Put the script in verbose mode, useful for debugging. Can be called multiple
index c8f6b11d5da17125e6308fe1899f503a639b3a57..f699cf05d40985a79f1d54a9b51812f07bddfd98 100755 (executable)
@@ -1092,7 +1092,11 @@ sub output_struct_rst(%) {
        print "\n\n.. c:type:: " . $name . "\n\n";
     } else {
        my $name = $args{'struct'};
-       print "\n\n.. c:struct:: " . $name . "\n\n";
+       if ($args{'type'} eq 'union') {
+           print "\n\n.. c:union:: " . $name . "\n\n";
+       } else {
+           print "\n\n.. c:struct:: " . $name . "\n\n";
+       }
     }
     print_lineno($declaration_start_line);
     $lineprefix = "   ";
@@ -1427,20 +1431,25 @@ sub dump_enum($$) {
     }
 }
 
+my $typedef_type = qr { ((?:\s+[\w\*]+){1,8})\s* }x;
+my $typedef_ident = qr { \*?\s*(\w\S+)\s* }x;
+my $typedef_args = qr { \s*\((.*)\); }x;
+
+my $typedef1 = qr { typedef$typedef_type\($typedef_ident\)$typedef_args }x;
+my $typedef2 = qr { typedef$typedef_type$typedef_ident$typedef_args }x;
+
 sub dump_typedef($$) {
     my $x = shift;
     my $file = shift;
 
     $x =~ s@/\*.*?\*/@@gos;    # strip comments.
 
-    # Parse function prototypes
-    if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
-       $x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) {
-
-       # Function typedefs
+    # Parse function typedef prototypes
+    if ($x =~ $typedef1 || $x =~ $typedef2) {
        $return_type = $1;
        $declaration_name = $2;
        my $args = $3;
+       $return_type =~ s/^\s+//;
 
        create_parameterlist($args, ',', $file, $declaration_name);
 
diff --git a/scripts/lld-version.sh b/scripts/lld-version.sh
new file mode 100755 (executable)
index 0000000..d70edb4
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# Usage: $ ./scripts/lld-version.sh ld.lld
+#
+# Print the linker version of `ld.lld' in a 5 or 6-digit form
+# such as `100001' for ld.lld 10.0.1 etc.
+
+linker_string="$($* --version)"
+
+if ! ( echo $linker_string | grep -q LLD ); then
+       echo 0
+       exit 1
+fi
+
+VERSION=$(echo $linker_string | cut -d ' ' -f 2)
+MAJOR=$(echo $VERSION | cut -d . -f 1)
+MINOR=$(echo $VERSION | cut -d . -f 2)
+PATCHLEVEL=$(echo $VERSION | cut -d . -f 3)
+printf "%d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL
index 1b11f8993629c62fc89e04182b23559e15e49081..91a502bb97e8ab05c3c901c1ec7e6c413a7c71e6 100755 (executable)
@@ -45,6 +45,8 @@ create_package() {
        chmod -R go-w "$pdir"
        # in case we are in a restrictive umask environment like 0077
        chmod -R a+rX "$pdir"
+       # in case we build in a setuid/setgid directory
+       chmod -R ug-s "$pdir"
 
        # Create the package
        dpkg-gencontrol -p$pname -P"$pdir"
index 38043074ce5e4459d3a71805ca58e0a78062263f..6ebefec616e442c7271e346ae85ecbb998b65cb6 100644 (file)
@@ -101,7 +101,7 @@ struct ima_template_entry {
        struct tpm_digest *digests;
        struct ima_template_desc *template_desc; /* template descriptor */
        u32 template_data_len;
-       struct ima_field_data template_data[0]; /* template related data */
+       struct ima_field_data template_data[];  /* template related data */
 };
 
 struct ima_queue_entry {
index f68a7617cfb95e8e2bf65e3e9ea9f12227004568..3a63a989e55ee6291e0887c0f630e70fdbeccc3e 100644 (file)
@@ -151,8 +151,10 @@ static int sel_ib_pkey_sid_slow(u64 subnet_prefix, u16 pkey_num, u32 *sid)
         * is valid, it just won't be added to the cache.
         */
        new = kzalloc(sizeof(*new), GFP_ATOMIC);
-       if (!new)
+       if (!new) {
+               ret = -ENOMEM;
                goto out;
+       }
 
        new->psec.subnet_prefix = subnet_prefix;
        new->psec.pkey = pkey_num;
index 421ddc76f264fcec7d08bea37234b2b59c63c4e1..3b44378b9dec9edb1595dae8282b835a946e6ae7 100644 (file)
@@ -1539,7 +1539,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
 
  unlock:
        up_write(&card->controls_rwsem);
-       return 0;
+       return err;
 }
 
 static int snd_ctl_elem_add_user(struct snd_ctl_file *file,
@@ -1925,8 +1925,8 @@ EXPORT_SYMBOL(snd_ctl_unregister_ioctl);
 
 #ifdef CONFIG_COMPAT
 /**
- * snd_ctl_unregister_ioctl - de-register the device-specific compat 32bit
- * control-ioctls
+ * snd_ctl_unregister_ioctl_compat - de-register the device-specific compat
+ * 32bit control-ioctls
  * @fcn: ioctl callback function to unregister
  */
 int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn)
index 4d059ff2b2e4facaae4d7191665bbf6e7795db8c..4d0e8fe535a1e8087b677c2571d38ae17a08e11b 100644 (file)
@@ -356,7 +356,8 @@ int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream)
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
 
 /**
- * snd_dmaengine_pcm_release_chan_close - Close a dmaengine based PCM substream and release channel
+ * snd_dmaengine_pcm_close_release_chan - Close a dmaengine based PCM
+ *                                       substream and release channel
  * @substream: PCM substream
  *
  * Releases the DMA channel associated with the PCM substream.
index d531e1bc2b8138267e547331e1be8d9e7e55a3e8..bda3514c7b2d91e8974005ad88c66150af6c47c6 100644 (file)
@@ -490,7 +490,7 @@ void snd_pcm_set_ops(struct snd_pcm *pcm, int direction,
 EXPORT_SYMBOL(snd_pcm_set_ops);
 
 /**
- * snd_pcm_sync - set the PCM sync id
+ * snd_pcm_set_sync - set the PCM sync id
  * @substream: the pcm substream
  *
  * Sets the PCM sync identifier for the card.
index 9e0b2d73faf6bfb066bb0c980b0311a4083fdedd..47b155a49226f4978bbe123952260fa31c3013fc 100644 (file)
@@ -112,7 +112,7 @@ void snd_pcm_stream_lock(struct snd_pcm_substream *substream)
 EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
 
 /**
- * snd_pcm_stream_lock - Unlock the PCM stream
+ * snd_pcm_stream_unlock - Unlock the PCM stream
  * @substream: PCM substream
  *
  * This unlocks the PCM stream that has been locked via snd_pcm_stream_lock().
@@ -595,7 +595,7 @@ static void snd_pcm_sync_stop(struct snd_pcm_substream *substream)
 }
 
 /**
- * snd_pcm_hw_param_choose - choose a configuration defined by @params
+ * snd_pcm_hw_params_choose - choose a configuration defined by @params
  * @pcm: PCM instance
  * @params: the hw_params instance
  *
index 0f533f5bd960f391f522c9e68d56899e8e20280d..9f8c53b39f958446266b5bd243af680bde8896ce 100644 (file)
@@ -123,7 +123,7 @@ copy_resp_to_buf(struct snd_efw *efw, void *data, size_t length, int *rcode)
        t = (struct snd_efw_transaction *)data;
        length = min_t(size_t, be32_to_cpu(t->length) * sizeof(u32), length);
 
-       spin_lock_irq(&efw->lock);
+       spin_lock(&efw->lock);
 
        if (efw->push_ptr < efw->pull_ptr)
                capacity = (unsigned int)(efw->pull_ptr - efw->push_ptr);
@@ -190,7 +190,7 @@ handle_resp_for_user(struct fw_card *card, int generation, int source,
 
        copy_resp_to_buf(efw, data, length, rcode);
 end:
-       spin_unlock_irq(&instances_lock);
+       spin_unlock(&instances_lock);
 }
 
 static void
index 4d060d5b1db6dc7eabfd5d44c3ef965792925537..b0c0ef824d7d914f5748f01bed8616fb876f146f 100644 (file)
@@ -148,6 +148,8 @@ struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_bus *bus,
                return NULL;
        if (bus->idx != bus_idx)
                return NULL;
+       if (addr < 0 || addr > 31)
+               return NULL;
 
        list_for_each_entry(hlink, &bus->hlink_list, list) {
                for (i = 0; i < HDA_MAX_CODECS; i++) {
index a356c21edb90ff38bc402c86cb2f724846d7165d..4bb58e8b08a858ad70d136d6513ed44c1a9ff198 100644 (file)
@@ -2934,7 +2934,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
        snd_hdac_leave_pm(&codec->core);
 }
 
-static int hda_codec_runtime_suspend(struct device *dev)
+static int hda_codec_suspend(struct device *dev)
 {
        struct hda_codec *codec = dev_to_hda_codec(dev);
        unsigned int state;
@@ -2953,7 +2953,7 @@ static int hda_codec_runtime_suspend(struct device *dev)
        return 0;
 }
 
-static int hda_codec_runtime_resume(struct device *dev)
+static int hda_codec_resume(struct device *dev)
 {
        struct hda_codec *codec = dev_to_hda_codec(dev);
 
@@ -2967,57 +2967,70 @@ static int hda_codec_runtime_resume(struct device *dev)
        pm_runtime_mark_last_busy(dev);
        return 0;
 }
+
+static int hda_codec_runtime_suspend(struct device *dev)
+{
+       return hda_codec_suspend(dev);
+}
+
+static int hda_codec_runtime_resume(struct device *dev)
+{
+       return hda_codec_resume(dev);
+}
+
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_PM_SLEEP
-static int hda_codec_force_resume(struct device *dev)
+static int hda_codec_pm_prepare(struct device *dev)
+{
+       return pm_runtime_suspended(dev);
+}
+
+static void hda_codec_pm_complete(struct device *dev)
 {
        struct hda_codec *codec = dev_to_hda_codec(dev);
-       int ret;
 
-       ret = pm_runtime_force_resume(dev);
-       /* schedule jackpoll work for jack detection update */
-       if (codec->jackpoll_interval ||
-           (pm_runtime_suspended(dev) && hda_codec_need_resume(codec)))
-               schedule_delayed_work(&codec->jackpoll_work,
-                                     codec->jackpoll_interval);
-       return ret;
+       if (pm_runtime_suspended(dev) && (codec->jackpoll_interval ||
+           hda_codec_need_resume(codec) || codec->forced_resume))
+               pm_request_resume(dev);
 }
 
 static int hda_codec_pm_suspend(struct device *dev)
 {
        dev->power.power_state = PMSG_SUSPEND;
-       return pm_runtime_force_suspend(dev);
+       return hda_codec_suspend(dev);
 }
 
 static int hda_codec_pm_resume(struct device *dev)
 {
        dev->power.power_state = PMSG_RESUME;
-       return hda_codec_force_resume(dev);
+       return hda_codec_resume(dev);
 }
 
 static int hda_codec_pm_freeze(struct device *dev)
 {
        dev->power.power_state = PMSG_FREEZE;
-       return pm_runtime_force_suspend(dev);
+       return hda_codec_suspend(dev);
 }
 
 static int hda_codec_pm_thaw(struct device *dev)
 {
        dev->power.power_state = PMSG_THAW;
-       return hda_codec_force_resume(dev);
+       return hda_codec_resume(dev);
 }
 
 static int hda_codec_pm_restore(struct device *dev)
 {
        dev->power.power_state = PMSG_RESTORE;
-       return hda_codec_force_resume(dev);
+       return hda_codec_resume(dev);
 }
 #endif /* CONFIG_PM_SLEEP */
 
 /* referred in hda_bind.c */
 const struct dev_pm_ops hda_codec_driver_pm = {
 #ifdef CONFIG_PM_SLEEP
+       .prepare = hda_codec_pm_prepare,
+       .complete = hda_codec_pm_complete,
        .suspend = hda_codec_pm_suspend,
        .resume = hda_codec_pm_resume,
        .freeze = hda_codec_pm_freeze,
index be63ead8161f80e49c85023094eeff8e0e5148f7..68f9668788ea2d469041390d79f9c5d1d52e895d 100644 (file)
@@ -41,7 +41,7 @@
 /* 24 unused */
 #define AZX_DCAPS_COUNT_LPIB_DELAY  (1 << 25)  /* Take LPIB as delay */
 #define AZX_DCAPS_PM_RUNTIME   (1 << 26)       /* runtime PM support */
-#define AZX_DCAPS_SUSPEND_SPURIOUS_WAKEUP (1 << 27) /* Workaround for spurious wakeups after suspend */
+/* 27 unused */
 #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28)  /* CORBRP clears itself after reset */
 #define AZX_DCAPS_NO_MSI64      (1 << 29)      /* Stick to 32-bit MSIs */
 #define AZX_DCAPS_SEPARATE_STREAM_TAG  (1 << 30) /* capture and playback use separate stream tag */
@@ -143,6 +143,7 @@ struct azx {
        unsigned int align_buffer_size:1;
        unsigned int region_requested:1;
        unsigned int disabled:1; /* disabled by vga_switcheroo */
+       unsigned int pm_prepared:1;
 
        /* GTS present */
        unsigned int gts_present:1;
index bbb17481159e0dcf568a2975fd6593722011b45f..8060cc86dfea39d1378db9a73f874df5d8084b95 100644 (file)
@@ -1364,16 +1364,20 @@ static int try_assign_dacs(struct hda_codec *codec, int num_outs,
                struct nid_path *path;
                hda_nid_t pin = pins[i];
 
-               path = snd_hda_get_path_from_idx(codec, path_idx[i]);
-               if (path) {
-                       badness += assign_out_path_ctls(codec, path);
-                       continue;
+               if (!spec->obey_preferred_dacs) {
+                       path = snd_hda_get_path_from_idx(codec, path_idx[i]);
+                       if (path) {
+                               badness += assign_out_path_ctls(codec, path);
+                               continue;
+                       }
                }
 
                dacs[i] = get_preferred_dac(codec, pin);
                if (dacs[i]) {
                        if (is_dac_already_used(codec, dacs[i]))
                                badness += bad->shared_primary;
+               } else if (spec->obey_preferred_dacs) {
+                       badness += BAD_NO_PRIMARY_DAC;
                }
 
                if (!dacs[i])
index a43f0bb77dae78c12e14b62c62867678ae4fec48..0886bc81f40be64901b50d6db1a21145891dc810 100644 (file)
@@ -237,6 +237,7 @@ struct hda_gen_spec {
        unsigned int power_down_unused:1; /* power down unused widgets */
        unsigned int dac_min_mute:1; /* minimal = mute for DACs */
        unsigned int suppress_vmaster:1; /* don't create vmaster kctls */
+       unsigned int obey_preferred_dacs:1; /* obey preferred_dacs assignment */
 
        /* other internal flags */
        unsigned int no_analog:1; /* digital I/O only */
index 749b880909703f80a40392ab33623c3ae3d2d029..6852668f1bcb47633bb366460f2b87c0fd910cb5 100644 (file)
@@ -297,8 +297,7 @@ enum {
 /* PCH for HSW/BDW; with runtime PM */
 /* no i915 binding for this as HSW/BDW has another controller for HDMI */
 #define AZX_DCAPS_INTEL_PCH \
-       (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\
-        AZX_DCAPS_SUSPEND_SPURIOUS_WAKEUP)
+       (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME)
 
 /* HSW HDMI */
 #define AZX_DCAPS_INTEL_HASWELL \
@@ -985,7 +984,7 @@ static void __azx_runtime_suspend(struct azx *chip)
        display_power(chip, false);
 }
 
-static void __azx_runtime_resume(struct azx *chip, bool from_rt)
+static void __azx_runtime_resume(struct azx *chip)
 {
        struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
        struct hdac_bus *bus = azx_bus(chip);
@@ -1002,7 +1001,8 @@ static void __azx_runtime_resume(struct azx *chip, bool from_rt)
        azx_init_pci(chip);
        hda_intel_init_chip(chip, true);
 
-       if (from_rt) {
+       /* Avoid codec resume if runtime resume is for system suspend */
+       if (!chip->pm_prepared) {
                list_for_each_codec(codec, &chip->bus) {
                        if (codec->relaxed_resume)
                                continue;
@@ -1018,6 +1018,29 @@ static void __azx_runtime_resume(struct azx *chip, bool from_rt)
 }
 
 #ifdef CONFIG_PM_SLEEP
+static int azx_prepare(struct device *dev)
+{
+       struct snd_card *card = dev_get_drvdata(dev);
+       struct azx *chip;
+
+       chip = card->private_data;
+       chip->pm_prepared = 1;
+
+       /* HDA controller always requires different WAKEEN for runtime suspend
+        * and system suspend, so don't use direct-complete here.
+        */
+       return 0;
+}
+
+static void azx_complete(struct device *dev)
+{
+       struct snd_card *card = dev_get_drvdata(dev);
+       struct azx *chip;
+
+       chip = card->private_data;
+       chip->pm_prepared = 0;
+}
+
 static int azx_suspend(struct device *dev)
 {
        struct snd_card *card = dev_get_drvdata(dev);
@@ -1029,15 +1052,7 @@ static int azx_suspend(struct device *dev)
 
        chip = card->private_data;
        bus = azx_bus(chip);
-       snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-       /* An ugly workaround: direct call of __azx_runtime_suspend() and
-        * __azx_runtime_resume() for old Intel platforms that suffer from
-        * spurious wakeups after S3 suspend
-        */
-       if (chip->driver_caps & AZX_DCAPS_SUSPEND_SPURIOUS_WAKEUP)
-               __azx_runtime_suspend(chip);
-       else
-               pm_runtime_force_suspend(dev);
+       __azx_runtime_suspend(chip);
        if (bus->irq >= 0) {
                free_irq(bus->irq, chip);
                bus->irq = -1;
@@ -1066,11 +1081,7 @@ static int azx_resume(struct device *dev)
        if (azx_acquire_irq(chip, 1) < 0)
                return -EIO;
 
-       if (chip->driver_caps & AZX_DCAPS_SUSPEND_SPURIOUS_WAKEUP)
-               __azx_runtime_resume(chip, false);
-       else
-               pm_runtime_force_resume(dev);
-       snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+       __azx_runtime_resume(chip);
 
        trace_azx_resume(chip);
        return 0;
@@ -1118,10 +1129,7 @@ static int azx_runtime_suspend(struct device *dev)
        chip = card->private_data;
 
        /* enable controller wake up event */
-       if (snd_power_get_state(card) == SNDRV_CTL_POWER_D0) {
-               azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) |
-                          STATESTS_INT_MASK);
-       }
+       azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) | STATESTS_INT_MASK);
 
        __azx_runtime_suspend(chip);
        trace_azx_runtime_suspend(chip);
@@ -1132,18 +1140,14 @@ static int azx_runtime_resume(struct device *dev)
 {
        struct snd_card *card = dev_get_drvdata(dev);
        struct azx *chip;
-       bool from_rt = snd_power_get_state(card) == SNDRV_CTL_POWER_D0;
 
        if (!azx_is_pm_ready(card))
                return 0;
        chip = card->private_data;
-       __azx_runtime_resume(chip, from_rt);
+       __azx_runtime_resume(chip);
 
        /* disable controller Wake Up event*/
-       if (from_rt) {
-               azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) &
-                          ~STATESTS_INT_MASK);
-       }
+       azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) & ~STATESTS_INT_MASK);
 
        trace_azx_runtime_resume(chip);
        return 0;
@@ -1177,6 +1181,8 @@ static int azx_runtime_idle(struct device *dev)
 static const struct dev_pm_ops azx_pm = {
        SET_SYSTEM_SLEEP_PM_OPS(azx_suspend, azx_resume)
 #ifdef CONFIG_PM_SLEEP
+       .prepare = azx_prepare,
+       .complete = azx_complete,
        .freeze_noirq = azx_freeze_noirq,
        .thaw_noirq = azx_thaw_noirq,
 #endif
@@ -2356,6 +2362,7 @@ static int azx_probe_continue(struct azx *chip)
 
        if (azx_has_pm_runtime(chip)) {
                pm_runtime_use_autosuspend(&pci->dev);
+               pm_runtime_allow(&pci->dev);
                pm_runtime_put_autosuspend(&pci->dev);
        }
 
@@ -2499,6 +2506,9 @@ static const struct pci_device_id azx_ids[] = {
        /* DG1 */
        { PCI_DEVICE(0x8086, 0x490d),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+       /* Alderlake-S */
+       { PCI_DEVICE(0x8086, 0x7ad0),
+         .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
        /* Elkhart Lake */
        { PCI_DEVICE(0x8086, 0x4b55),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
index e0c38f2735c6e210d21620516ab238342e79b681..d8370a417e3d44ed51ead66ea3755c79e57906db 100644 (file)
@@ -9183,6 +9183,8 @@ static void ca0132_mmio_init(struct hda_codec *codec)
        case QUIRK_AE5:
                ca0132_mmio_init_ae5(codec);
                break;
+       default:
+               break;
        }
 }
 
index ccd1df05965404f6f8ab127c39806f08981862ff..b0068f8ca46ddff352959bf18fc0d5882be77e91 100644 (file)
@@ -4274,6 +4274,7 @@ HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI",    patch_i915_glk_hdmi),
 HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI",    patch_i915_icl_hdmi),
 HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI",  patch_i915_tgl_hdmi),
 HDA_CODEC_ENTRY(0x80862814, "DG1 HDMI",        patch_i915_tgl_hdmi),
+HDA_CODEC_ENTRY(0x80862815, "Alderlake HDMI",  patch_i915_tgl_hdmi),
 HDA_CODEC_ENTRY(0x80862816, "Rocketlake HDMI", patch_i915_tgl_hdmi),
 HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi),
 HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI",        patch_i915_icl_hdmi),
index f2398721ac1efc49566bddb7bd579ce7f14f08da..8616c56248707151abd446fc0fb3d15c709850dd 100644 (file)
@@ -119,6 +119,7 @@ struct alc_spec {
        unsigned int no_shutup_pins:1;
        unsigned int ultra_low_power:1;
        unsigned int has_hs_key:1;
+       unsigned int no_internal_mic_pin:1;
 
        /* for PLL fix */
        hda_nid_t pll_nid;
@@ -445,6 +446,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
                        alc_update_coef_idx(codec, 0x7, 1<<5, 0);
                break;
        case 0x10ec0892:
+       case 0x10ec0897:
                alc_update_coef_idx(codec, 0x7, 1<<5, 0);
                break;
        case 0x10ec0899:
@@ -2522,13 +2524,23 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
        SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
        SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1558, 0x9506, "Clevo P955HQ", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1558, 0x950A, "Clevo P955H[PR]", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1558, 0x95e1, "Clevo P95xER", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1558, 0x95e3, "Clevo P955[ER]T", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1558, 0x95e4, "Clevo P955ER", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1558, 0x95e5, "Clevo P955EE6", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1558, 0x95e6, "Clevo P950R[CDF]", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1558, 0x96e1, "Clevo P960[ER][CDFN]-K", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1558, 0x97e1, "Clevo P970[ER][CDFN]", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1558, 0x97e2, "Clevo P970RC-M", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+       SND_PCI_QUIRK(0x1558, 0x65d2, "Clevo PB51R[CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+       SND_PCI_QUIRK(0x1558, 0x65e1, "Clevo PB51[ED][DF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
-       SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+       SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
@@ -4216,6 +4228,12 @@ static void alc286_fixup_hp_gpio_led(struct hda_codec *codec,
        alc_fixup_hp_gpio_led(codec, action, 0x02, 0x20);
 }
 
+static void alc287_fixup_hp_gpio_led(struct hda_codec *codec,
+                               const struct hda_fixup *fix, int action)
+{
+       alc_fixup_hp_gpio_led(codec, action, 0x10, 0);
+}
+
 /* turn on/off mic-mute LED per capture hook via VREF change */
 static int vref_micmute_led_set(struct led_classdev *led_cdev,
                                enum led_brightness brightness)
@@ -4507,6 +4525,7 @@ static const struct coef_fw alc225_pre_hsmode[] = {
 
 static void alc_headset_mode_unplugged(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
        static const struct coef_fw coef0255[] = {
                WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
                WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */
@@ -4581,6 +4600,11 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
                {}
        };
 
+       if (spec->no_internal_mic_pin) {
+               alc_update_coef_idx(codec, 0x45, 0xf<<12 | 1<<10, 5<<12);
+               return;
+       }
+
        switch (codec->core.vendor_id) {
        case 0x10ec0255:
                alc_process_coef_fw(codec, coef0255);
@@ -5147,6 +5171,11 @@ static void alc_determine_headset_type(struct hda_codec *codec)
                {}
        };
 
+       if (spec->no_internal_mic_pin) {
+               alc_update_coef_idx(codec, 0x45, 0xf<<12 | 1<<10, 5<<12);
+               return;
+       }
+
        switch (codec->core.vendor_id) {
        case 0x10ec0255:
                alc_process_coef_fw(codec, coef0255);
@@ -5998,6 +6027,21 @@ static void alc274_fixup_bind_dacs(struct hda_codec *codec,
        codec->power_save_node = 0;
 }
 
+/* avoid DAC 0x06 for bass speaker 0x17; it has no volume control */
+static void alc289_fixup_asus_ga401(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       static const hda_nid_t preferred_pairs[] = {
+               0x14, 0x02, 0x17, 0x02, 0x21, 0x03, 0
+       };
+       struct alc_spec *spec = codec->spec;
+
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               spec->gen.preferred_dacs = preferred_pairs;
+               spec->gen.obey_preferred_dacs = 1;
+       }
+}
+
 /* The DAC of NID 0x3 will introduce click/pop noise on headphones, so invalidate it */
 static void alc285_fixup_invalidate_dacs(struct hda_codec *codec,
                              const struct hda_fixup *fix, int action)
@@ -6008,6 +6052,27 @@ static void alc285_fixup_invalidate_dacs(struct hda_codec *codec,
        snd_hda_override_wcaps(codec, 0x03, 0);
 }
 
+static void alc_combo_jack_hp_jd_restart(struct hda_codec *codec)
+{
+       switch (codec->core.vendor_id) {
+       case 0x10ec0274:
+       case 0x10ec0294:
+       case 0x10ec0225:
+       case 0x10ec0295:
+       case 0x10ec0299:
+               alc_update_coef_idx(codec, 0x4a, 0x8000, 1 << 15); /* Reset HP JD */
+               alc_update_coef_idx(codec, 0x4a, 0x8000, 0 << 15);
+               break;
+       case 0x10ec0235:
+       case 0x10ec0236:
+       case 0x10ec0255:
+       case 0x10ec0256:
+               alc_update_coef_idx(codec, 0x1b, 0x8000, 1 << 15); /* Reset HP JD */
+               alc_update_coef_idx(codec, 0x1b, 0x8000, 0 << 15);
+               break;
+       }
+}
+
 static void alc295_fixup_chromebook(struct hda_codec *codec,
                                    const struct hda_fixup *fix, int action)
 {
@@ -6018,16 +6083,7 @@ static void alc295_fixup_chromebook(struct hda_codec *codec,
                spec->ultra_low_power = true;
                break;
        case HDA_FIXUP_ACT_INIT:
-               switch (codec->core.vendor_id) {
-               case 0x10ec0295:
-                       alc_update_coef_idx(codec, 0x4a, 0x8000, 1 << 15); /* Reset HP JD */
-                       alc_update_coef_idx(codec, 0x4a, 0x8000, 0 << 15);
-                       break;
-               case 0x10ec0236:
-                       alc_update_coef_idx(codec, 0x1b, 0x8000, 1 << 15); /* Reset HP JD */
-                       alc_update_coef_idx(codec, 0x1b, 0x8000, 0 << 15);
-                       break;
-               }
+               alc_combo_jack_hp_jd_restart(codec);
                break;
        }
 }
@@ -6083,6 +6139,33 @@ static void  alc285_fixup_hp_gpio_amp_init(struct hda_codec *codec,
        alc_write_coef_idx(codec, 0x65, 0x0);
 }
 
+static void alc274_fixup_hp_headset_mic(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       switch (action) {
+       case HDA_FIXUP_ACT_INIT:
+               alc_combo_jack_hp_jd_restart(codec);
+               break;
+       }
+}
+
+static void alc_fixup_no_int_mic(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+
+       switch (action) {
+       case HDA_FIXUP_ACT_PRE_PROBE:
+               /* Mic RING SLEEVE swap for combo jack */
+               alc_update_coef_idx(codec, 0x45, 0xf<<12 | 1<<10, 5<<12);
+               spec->no_internal_mic_pin = true;
+               break;
+       case HDA_FIXUP_ACT_INIT:
+               alc_combo_jack_hp_jd_restart(codec);
+               break;
+       }
+}
+
 /* for hda_fixup_thinkpad_acpi() */
 #include "thinkpad_helper.c"
 
@@ -6277,6 +6360,12 @@ enum {
        ALC256_FIXUP_INTEL_NUC8_RUGGED,
        ALC255_FIXUP_XIAOMI_HEADSET_MIC,
        ALC274_FIXUP_HP_MIC,
+       ALC274_FIXUP_HP_HEADSET_MIC,
+       ALC256_FIXUP_ASUS_HPE,
+       ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK,
+       ALC287_FIXUP_HP_GPIO_LED,
+       ALC256_FIXUP_HP_HEADSET_MIC,
+       ALC236_FIXUP_DELL_AIO_HEADSET_MIC,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -7526,11 +7615,10 @@ static const struct hda_fixup alc269_fixups[] = {
                .chain_id = ALC269_FIXUP_HEADSET_MIC
        },
        [ALC289_FIXUP_ASUS_GA401] = {
-               .type = HDA_FIXUP_PINS,
-               .v.pins = (const struct hda_pintbl[]) {
-                       { 0x19, 0x03a11020 }, /* headset mic with jack detect */
-                       { }
-               },
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc289_fixup_asus_ga401,
+               .chained = true,
+               .chain_id = ALC289_FIXUP_ASUS_GA502,
        },
        [ALC289_FIXUP_ASUS_GA502] = {
                .type = HDA_FIXUP_PINS,
@@ -7654,7 +7742,7 @@ static const struct hda_fixup alc269_fixups[] = {
                        { }
                },
                .chained = true,
-               .chain_id = ALC289_FIXUP_ASUS_GA401
+               .chain_id = ALC289_FIXUP_ASUS_GA502
        },
        [ALC274_FIXUP_HP_MIC] = {
                .type = HDA_FIXUP_VERBS,
@@ -7664,6 +7752,43 @@ static const struct hda_fixup alc269_fixups[] = {
                        { }
                },
        },
+       [ALC274_FIXUP_HP_HEADSET_MIC] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc274_fixup_hp_headset_mic,
+               .chained = true,
+               .chain_id = ALC274_FIXUP_HP_MIC
+       },
+       [ALC256_FIXUP_ASUS_HPE] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* Set EAPD high */
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x0f },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x7778 },
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC
+       },
+       [ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_headset_jack,
+               .chained = true,
+               .chain_id = ALC269_FIXUP_THINKPAD_ACPI
+       },
+       [ALC287_FIXUP_HP_GPIO_LED] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc287_fixup_hp_gpio_led,
+       },
+       [ALC256_FIXUP_HP_HEADSET_MIC] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc274_fixup_hp_headset_mic,
+       },
+       [ALC236_FIXUP_DELL_AIO_HEADSET_MIC] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_no_int_mic,
+               .chained = true,
+               .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -7741,6 +7866,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x097d, "Dell Precision", ALC289_FIXUP_DUAL_SPK),
        SND_PCI_QUIRK(0x1028, 0x098d, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x09bf, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0a2e, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1028, 0x0a30, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC),
        SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -7807,6 +7934,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x820d, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
        SND_PCI_QUIRK(0x103c, 0x8256, "HP", ALC221_FIXUP_HP_FRONT_MIC),
        SND_PCI_QUIRK(0x103c, 0x827e, "HP x360", ALC295_FIXUP_HP_X360),
+       SND_PCI_QUIRK(0x103c, 0x827f, "HP x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
        SND_PCI_QUIRK(0x103c, 0x82bf, "HP G3 mini", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x82c0, "HP G3 mini premium", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
@@ -7815,10 +7943,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x8729, "HP", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_AMP_INIT),
-       SND_PCI_QUIRK(0x103c, 0x874e, "HP", ALC274_FIXUP_HP_MIC),
        SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED),
+       SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_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),
@@ -7848,6 +7977,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
+       SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
        SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
        SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
@@ -7883,11 +8013,49 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1558, 0x1323, "Clevo N130ZU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x1401, "Clevo L140[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x1403, "Clevo N140CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x1404, "Clevo N150CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x14a1, "Clevo L141MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x4018, "Clevo NV40M[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x4019, "Clevo NV40MZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x4020, "Clevo NV40MB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x40a1, "Clevo NL40GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x40c1, "Clevo NL40[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x40d1, "Clevo NL41DU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x50a3, "Clevo NJ51GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x50b3, "Clevo NK50S[BEZ]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x50b6, "Clevo NK50S5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x50b8, "Clevo NK50SZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x50d5, "Clevo NP50D5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x50f0, "Clevo NH50A[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x50f3, "Clevo NH58DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x5101, "Clevo S510WU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x5157, "Clevo W517GU1", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x51a1, "Clevo NS50MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x70a1, "Clevo NB70T[HJK]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x70b3, "Clevo NK70SB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x8228, "Clevo NR40BU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x8520, "Clevo NH50D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x8521, "Clevo NH77D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x8535, "Clevo NH50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x8536, "Clevo NH79D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8550, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8551, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8560, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1558, 0x8561, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1558, 0x8668, "Clevo NP50B[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x8680, "Clevo NJ50LU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x8686, "Clevo NH50[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x8a20, "Clevo NH55DCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x8a51, "Clevo NH70RCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x8d50, "Clevo NH55RCQ-M", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x951d, "Clevo N950T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x961d, "Clevo N960S[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x971d, "Clevo N970T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xa500, "Clevo NL53RU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS),
        SND_PCI_QUIRK(0x17aa, 0x1048, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
@@ -7925,6 +8093,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
        SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
+       SND_PCI_QUIRK(0x17aa, 0x22c1, "Thinkpad P1 Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK),
+       SND_PCI_QUIRK(0x17aa, 0x22c2, "Thinkpad X1 Extreme Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK),
        SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
@@ -8237,6 +8407,12 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x19, 0x02a11020},
                {0x1a, 0x02a11030},
                {0x21, 0x0221101f}),
+       SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC,
+               {0x21, 0x02211010}),
+       SND_HDA_PIN_QUIRK(0x10ec0236, 0x103c, "HP", ALC256_FIXUP_HP_HEADSET_MIC,
+               {0x14, 0x90170110},
+               {0x19, 0x02a11020},
+               {0x21, 0x02211030}),
        SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
                {0x14, 0x90170110},
                {0x21, 0x02211020}),
@@ -8339,6 +8515,14 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x1a, 0x90a70130},
                {0x1b, 0x90170110},
                {0x21, 0x03211020}),
+       SND_HDA_PIN_QUIRK(0x10ec0256, 0x103c, "HP", ALC256_FIXUP_HP_HEADSET_MIC,
+               {0x14, 0x90170110},
+               {0x19, 0x02a11020},
+               {0x21, 0x0221101f}),
+       SND_HDA_PIN_QUIRK(0x10ec0274, 0x103c, "HP", ALC274_FIXUP_HP_HEADSET_MIC,
+               {0x17, 0x90170110},
+               {0x19, 0x03a11030},
+               {0x21, 0x03211020}),
        SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
                {0x12, 0x90a60130},
                {0x14, 0x90170110},
@@ -8457,6 +8641,9 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
        SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
                ALC292_STANDARD_PINS,
                {0x13, 0x90a60140}),
+       SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_HPE,
+               {0x17, 0x90170110},
+               {0x21, 0x04211020}),
        SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_MIC,
                {0x14, 0x90170110},
                {0x1b, 0x90a70130},
@@ -10043,6 +10230,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
        HDA_CODEC_ENTRY(0x10ec0888, "ALC888", patch_alc882),
        HDA_CODEC_ENTRY(0x10ec0889, "ALC889", patch_alc882),
        HDA_CODEC_ENTRY(0x10ec0892, "ALC892", patch_alc662),
+       HDA_CODEC_ENTRY(0x10ec0897, "ALC897", patch_alc662),
        HDA_CODEC_ENTRY(0x10ec0899, "ALC898", patch_alc882),
        HDA_CODEC_ENTRY(0x10ec0900, "ALC1150", patch_alc882),
        HDA_CODEC_ENTRY(0x10ec0b00, "ALCS1200A", patch_alc882),
index 0bdd33b0af654b87999ef5b37038f8fcdf307802..fb8895af03634ff822130e9abe858d12195fe75e 100644 (file)
@@ -70,7 +70,6 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
        unsigned int i;
 #endif
 
-       mutex_lock(&mgr->msg_lock);
        err = 0;
 
        /* copy message descriptor from miXart to driver */
@@ -119,8 +118,6 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
        writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD));
 
  _clean_exit:
-       mutex_unlock(&mgr->msg_lock);
-
        return err;
 }
 
@@ -258,7 +255,9 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int
        resp.data = resp_data;
        resp.size = max_resp_size;
 
+       mutex_lock(&mgr->msg_lock);
        err = get_msg(mgr, &resp, msg_frame);
+       mutex_unlock(&mgr->msg_lock);
 
        if( request->message_id != resp.message_id )
                dev_err(&mgr->pci->dev, "RESPONSE ERROR!\n");
index 82c1eecd2528500eeaa69d8101277600a7001197..3bd350afb74348010d54f9e59b1a1961d7b9fcc8 100644 (file)
@@ -487,7 +487,6 @@ static int mchp_spdiftx_hw_params(struct snd_pcm_substream *substream,
        }
        mchp_spdiftx_channel_status_write(dev);
        spin_unlock_irqrestore(&ctrl->lock, flags);
-       mr |= SPDIFTX_MR_VALID1 | SPDIFTX_MR_VALID2;
 
        if (dev->gclk_enabled) {
                clk_disable_unprepare(dev->gclk);
index 097c4e8d9950535de336647a42fc37acc0016124..c61b17dc2af876e2d4055f3a3f483317185271d9 100644 (file)
@@ -254,8 +254,28 @@ static const struct snd_soc_dapm_widget cs42l51_dapm_widgets[] = {
                &cs42l51_adcr_mux_controls),
 };
 
+static int mclk_event(struct snd_soc_dapm_widget *w,
+                     struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+       struct cs42l51_private *cs42l51 = snd_soc_component_get_drvdata(comp);
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               return clk_prepare_enable(cs42l51->mclk_handle);
+       case SND_SOC_DAPM_POST_PMD:
+               /* Delay mclk shutdown to fulfill power-down sequence requirements */
+               msleep(20);
+               clk_disable_unprepare(cs42l51->mclk_handle);
+               break;
+       }
+
+       return 0;
+}
+
 static const struct snd_soc_dapm_widget cs42l51_dapm_mclk_widgets[] = {
-       SND_SOC_DAPM_CLOCK_SUPPLY("MCLK")
+       SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0, mclk_event,
+                           SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 };
 
 static const struct snd_soc_dapm_route cs42l51_routes[] = {
index 25fe2ddedd5454567c3601c3abd71e0cd8ebc88a..3db07293c70b663c96e45d6b9d3b1f8b08f3d335 100644 (file)
 #include <sound/soc-dapm.h>
 #include <sound/soc.h>
 #include <sound/tlv.h>
+#include <sound/rt1015.h>
 
 #include "rl6231.h"
 #include "rt1015.h"
 
+static const struct rt1015_platform_data i2s_default_platform_data = {
+       .power_up_delay_ms = 50,
+};
+
 static const struct reg_default rt1015_reg[] = {
        { 0x0000, 0x0000 },
        { 0x0004, 0xa000 },
@@ -539,7 +544,7 @@ static void rt1015_flush_work(struct work_struct *work)
        struct rt1015_priv *rt1015 = container_of(work, struct rt1015_priv,
                                                flush_work.work);
        struct snd_soc_component *component = rt1015->component;
-       unsigned int val, i = 0, count = 20;
+       unsigned int val, i = 0, count = 200;
 
        while (i < count) {
                usleep_range(1000, 1500);
@@ -650,6 +655,7 @@ static int rt1015_amp_drv_event(struct snd_soc_dapm_widget *w,
        case SND_SOC_DAPM_POST_PMU:
                if (rt1015->hw_config == RT1015_HW_28)
                        schedule_delayed_work(&rt1015->flush_work, msecs_to_jiffies(10));
+               msleep(rt1015->pdata.power_up_delay_ms);
                break;
        default:
                break;
@@ -1067,9 +1073,16 @@ static struct acpi_device_id rt1015_acpi_match[] = {
 MODULE_DEVICE_TABLE(acpi, rt1015_acpi_match);
 #endif
 
+static void rt1015_parse_dt(struct rt1015_priv *rt1015, struct device *dev)
+{
+       device_property_read_u32(dev, "realtek,power-up-delay-ms",
+               &rt1015->pdata.power_up_delay_ms);
+}
+
 static int rt1015_i2c_probe(struct i2c_client *i2c,
        const struct i2c_device_id *id)
 {
+       struct rt1015_platform_data *pdata = dev_get_platdata(&i2c->dev);
        struct rt1015_priv *rt1015;
        int ret;
        unsigned int val;
@@ -1081,6 +1094,13 @@ static int rt1015_i2c_probe(struct i2c_client *i2c,
 
        i2c_set_clientdata(i2c, rt1015);
 
+       rt1015->pdata = i2s_default_platform_data;
+
+       if (pdata)
+               rt1015->pdata = *pdata;
+       else
+               rt1015_parse_dt(rt1015, &i2c->dev);
+
        rt1015->regmap = devm_regmap_init_i2c(i2c, &rt1015_regmap);
        if (IS_ERR(rt1015->regmap)) {
                ret = PTR_ERR(rt1015->regmap);
index d3fdd30aca6d2d9a0a4b946a59c23e08c2b3d8ea..15cadb361ec3d0da3e0b5348b8ce5f892e55a77f 100644 (file)
@@ -12,6 +12,7 @@
 
 #ifndef __RT1015_H__
 #define __RT1015_H__
+#include <sound/rt1015.h>
 
 #define RT1015_DEVICE_ID_VAL                   0x1011
 #define RT1015_DEVICE_ID_VAL2                  0x1015
@@ -380,6 +381,7 @@ enum {
 
 struct rt1015_priv {
        struct snd_soc_component *component;
+       struct rt1015_platform_data pdata;
        struct regmap *regmap;
        int sysclk;
        int sysclk_src;
index a9acce7b6cca8a20175bdeaf5f40227ccc776b88..d9878173ff898870bc70aa8945c011de3a527b85 100644 (file)
@@ -43,6 +43,7 @@ static const struct reg_sequence patch_list[] = {
        {RT5682_DAC_ADC_DIG_VOL1, 0xa020},
        {RT5682_I2C_CTRL, 0x000f},
        {RT5682_PLL2_INTERNAL, 0x8266},
+       {RT5682_SAR_IL_CMD_3, 0x8365},
 };
 
 void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev)
index f2d9d52ee171b81a5ffc4304b8e4914e67b55add..4d2b1ec7c03bb800de8a4138292694f2d7dc2cb4 100644 (file)
@@ -618,7 +618,7 @@ static const char * const sb_tx8_mux_text[] = {
        "ZERO", "RX_MIX_TX8", "DEC8", "DEC8_192"
 };
 
-static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400);
 static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
 static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
 static const DECLARE_TLV_DB_SCALE(ear_pa_gain, 0, 150, 0);
index 35697b072367aced19099f6b90b84d48f19e6d19..40f682f5dab8bde1d1a6e7345336314032052e13 100644 (file)
@@ -551,7 +551,7 @@ struct wcd_iir_filter_ctl {
        struct soc_bytes_ext bytes_ext;
 };
 
-static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400);
 static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
 static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
 static const DECLARE_TLV_DB_SCALE(ear_pa_gain, 0, 150, 0);
index bcf18bf15a02db5ea8c49a3e3a5fa5ef5ae816f8..e61d00486c65370c9908414cc8d52988b567e284 100644 (file)
@@ -1937,6 +1937,7 @@ static int wm_adsp_load(struct wm_adsp *dsp)
                        mem = wm_adsp_find_region(dsp, type);
                        if (!mem) {
                                adsp_err(dsp, "No region of type: %x\n", type);
+                               ret = -EINVAL;
                                goto out_fw;
                        }
 
index 68e774e69c850f18c2ee5547b9f708c53a02c35c..4530b74f5921b74a52667c65b32396f8426e8520 100644 (file)
@@ -1026,6 +1026,8 @@ static struct snd_soc_dai_driver wsa881x_dais[] = {
                .id = 0,
                .playback = {
                        .stream_name = "SPKR Playback",
+                       .rates = SNDRV_PCM_RATE_48000,
+                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
                        .rate_max = 48000,
                        .rate_min = 48000,
                        .channels_min = 1,
index d5bae5d1ab6fd863e47326f36e18203816ca1cf4..a5b446d5af19fc2d0c4bd1a67334e39bf37ad805 100644 (file)
@@ -15,22 +15,6 @@ config SND_SOC_INTEL_SST_TOPLEVEL
 
 if SND_SOC_INTEL_SST_TOPLEVEL
 
-config SND_SST_IPC
-       tristate
-       # This option controls the IPC core for HiFi2 platforms
-
-config SND_SST_IPC_PCI
-       tristate
-       select SND_SST_IPC
-       # This option controls the PCI-based IPC for HiFi2 platforms
-       #  (Medfield, Merrifield).
-
-config SND_SST_IPC_ACPI
-       tristate
-       select SND_SST_IPC
-       # This option controls the ACPI-based IPC for HiFi2 platforms
-       # (Baytrail, Cherrytrail)
-
 config SND_SOC_INTEL_SST
        tristate
 
@@ -57,7 +41,6 @@ config SND_SST_ATOM_HIFI2_PLATFORM
 config SND_SST_ATOM_HIFI2_PLATFORM_PCI
        tristate "PCI HiFi2 (Merrifield) Platforms"
        depends on X86 && PCI
-       select SND_SST_IPC_PCI
        select SND_SST_ATOM_HIFI2_PLATFORM
        help
          If you have a Intel Merrifield/Edison platform, then
@@ -70,7 +53,6 @@ config SND_SST_ATOM_HIFI2_PLATFORM_ACPI
        tristate "ACPI HiFi2 (Baytrail, Cherrytrail) Platforms"
        default ACPI
        depends on X86 && ACPI && PCI
-       select SND_SST_IPC_ACPI
        select SND_SST_ATOM_HIFI2_PLATFORM
        select SND_SOC_ACPI_INTEL_MATCH
        select IOSF_MBI
index a9326d5ec44cbbfd816f58bffea58acb1e82d77d..c66f03f5d8d6d462ea4021544424d76d0af375f6 100644 (file)
@@ -6,4 +6,4 @@ snd-soc-sst-atom-hifi2-platform-objs := sst-mfld-platform-pcm.o \
 obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM) += snd-soc-sst-atom-hifi2-platform.o
 
 # DSP driver
-obj-$(CONFIG_SND_SST_IPC) += sst/
+obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM) += sst/
index f17c905df3e2c312f8db5c3353fd7a1cb5fd6bfb..5761d30a5f9d1e0cfc20ca8a23127ee0eda63a82 100644 (file)
@@ -3,6 +3,6 @@ snd-intel-sst-core-objs := sst.o sst_ipc.o sst_stream.o sst_drv_interface.o sst_
 snd-intel-sst-pci-objs += sst_pci.o
 snd-intel-sst-acpi-objs += sst_acpi.o
 
-obj-$(CONFIG_SND_SST_IPC) += snd-intel-sst-core.o
-obj-$(CONFIG_SND_SST_IPC_PCI) += snd-intel-sst-pci.o
-obj-$(CONFIG_SND_SST_IPC_ACPI) += snd-intel-sst-acpi.o
+obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM) += snd-intel-sst-core.o
+obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_PCI) += snd-intel-sst-pci.o
+obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) += snd-intel-sst-acpi.o
index 9dadf6561444db23bcd812dd813717602058ce2a..f790514a147ddcba91e1cea86a1583cce2339224 100644 (file)
@@ -520,10 +520,10 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
                                        BYT_RT5640_MCLK_EN),
        },
-       {       /* HP Pavilion x2 10-n000nd */
+       {       /* HP Pavilion x2 10-k0XX, 10-n0XX */
                .matches = {
-                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
                },
                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
                                        BYT_RT5640_JD_SRC_JD2_IN4N |
@@ -532,6 +532,17 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
                                        BYT_RT5640_SSP0_AIF1 |
                                        BYT_RT5640_MCLK_EN),
        },
+       {       /* HP Pavilion x2 10-p0XX */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"),
+               },
+               .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
+                                       BYT_RT5640_JD_SRC_JD1_IN4P |
+                                       BYT_RT5640_OVCD_TH_1500UA |
+                                       BYT_RT5640_OVCD_SF_0P75 |
+                                       BYT_RT5640_MCLK_EN),
+       },
        {       /* HP Stream 7 */
                .matches = {
                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
index 3ea4602dfb3ee0c1e2a59de237b7258915810fc4..9a4b3d0973f651b072fb637887fd15cea9b18b29 100644 (file)
@@ -401,17 +401,40 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
        struct snd_interval *chan = hw_param_interval(params,
                        SNDRV_PCM_HW_PARAM_CHANNELS);
        struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
-       struct snd_soc_dpcm *dpcm = container_of(
-                       params, struct snd_soc_dpcm, hw_params);
-       struct snd_soc_dai_link *fe_dai_link = dpcm->fe->dai_link;
-       struct snd_soc_dai_link *be_dai_link = dpcm->be->dai_link;
+       struct snd_soc_dpcm *dpcm, *rtd_dpcm = NULL;
+
+       /*
+        * The following loop will be called only for playback stream
+        * In this platform, there is only one playback device on every SSP
+        */
+       for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) {
+               rtd_dpcm = dpcm;
+               break;
+       }
+
+       /*
+        * This following loop will be called only for capture stream
+        * In this platform, there is only one capture device on every SSP
+        */
+       for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_CAPTURE, dpcm) {
+               rtd_dpcm = dpcm;
+               break;
+       }
+
+       if (!rtd_dpcm)
+               return -EINVAL;
+
+       /*
+        * The above 2 loops are mutually exclusive based on the stream direction,
+        * thus rtd_dpcm variable will never be overwritten
+        */
 
        /*
         * The ADSP will convert the FE rate to 48k, stereo, 24 bit
         */
-       if (!strcmp(fe_dai_link->name, "Kbl Audio Port") ||
-           !strcmp(fe_dai_link->name, "Kbl Audio Headset Playback") ||
-           !strcmp(fe_dai_link->name, "Kbl Audio Capture Port")) {
+       if (!strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Port") ||
+           !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Headset Playback") ||
+           !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Capture Port")) {
                rate->min = rate->max = 48000;
                chan->min = chan->max = 2;
                snd_mask_none(fmt);
@@ -421,7 +444,7 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
         * The speaker on the SSP0 supports S16_LE and not S24_LE.
         * thus changing the mask here
         */
-       if (!strcmp(be_dai_link->name, "SSP0-Codec"))
+       if (!strcmp(rtd_dpcm->be->dai_link->name, "SSP0-Codec"))
                snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
 
        return 0;
index 922cd0176e1ff184e1cfec19685c0792fdd80e90..f95546c184aae5bf78b583c793bfe398c497e6f6 100644 (file)
@@ -700,6 +700,8 @@ static int kabylake_set_bias_level(struct snd_soc_card *card,
        switch (level) {
        case SND_SOC_BIAS_PREPARE:
                if (dapm->bias_level == SND_SOC_BIAS_ON) {
+                       if (!__clk_is_enabled(priv->mclk))
+                               return 0;
                        dev_dbg(card->dev, "Disable mclk");
                        clk_disable_unprepare(priv->mclk);
                } else {
index 7d2968571951b38b185ce1b33690a62ff22e23e8..9e807b94173219c687758db9b5510bd9d423beab 100644 (file)
@@ -267,9 +267,12 @@ static int catpt_dsp_select_lpclock(struct catpt_dev *cdev, bool lp, bool waiti)
                                            reg, (reg & CATPT_ISD_DCPWM),
                                            500, 10000);
                if (ret) {
-                       dev_err(cdev->dev, "await WAITI timeout\n");
-                       mutex_unlock(&cdev->clk_mutex);
-                       return ret;
+                       dev_warn(cdev->dev, "await WAITI timeout\n");
+                       /* no signal - only high clock selection allowed */
+                       if (lp) {
+                               mutex_unlock(&cdev->clk_mutex);
+                               return 0;
+                       }
                }
        }
 
index f78018c857b8d06d3012ff028e1c1b7ad485b8b7..408e64e3b5fb95b2843e4d0d27cd352f776f3191 100644 (file)
@@ -458,10 +458,6 @@ static int catpt_dai_prepare(struct snd_pcm_substream *substream,
        if (ret)
                return CATPT_IPC_ERROR(ret);
 
-       ret = catpt_dsp_update_lpclock(cdev);
-       if (ret)
-               return ret;
-
        ret = catpt_dai_apply_usettings(dai, stream);
        if (ret)
                return ret;
@@ -500,6 +496,7 @@ static int catpt_dai_trigger(struct snd_pcm_substream *substream, int cmd,
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
        resume_stream:
+               catpt_dsp_update_lpclock(cdev);
                ret = catpt_ipc_resume_stream(cdev, stream->info.stream_hw_id);
                if (ret)
                        return CATPT_IPC_ERROR(ret);
@@ -507,11 +504,11 @@ static int catpt_dai_trigger(struct snd_pcm_substream *substream, int cmd,
 
        case SNDRV_PCM_TRIGGER_STOP:
                stream->prepared = false;
-               catpt_dsp_update_lpclock(cdev);
                fallthrough;
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                ret = catpt_ipc_pause_stream(cdev, stream->info.stream_hw_id);
+               catpt_dsp_update_lpclock(cdev);
                if (ret)
                        return CATPT_IPC_ERROR(ret);
                break;
@@ -534,6 +531,8 @@ void catpt_stream_update_position(struct catpt_dev *cdev,
 
        dsppos = bytes_to_frames(r, pos->stream_position);
 
+       if (!stream->prepared)
+               goto exit;
        /* only offload is set_write_pos driven */
        if (stream->template->type != CATPT_STRM_TYPE_RENDER)
                goto exit;
@@ -667,7 +666,17 @@ static int catpt_dai_pcm_new(struct snd_soc_pcm_runtime *rtm,
                break;
        }
 
+       /* see if this is a new configuration */
+       if (!memcmp(&cdev->devfmt[devfmt.iface], &devfmt, sizeof(devfmt)))
+               return 0;
+
+       pm_runtime_get_sync(cdev->dev);
+
        ret = catpt_ipc_set_device_format(cdev, &devfmt);
+
+       pm_runtime_mark_last_busy(cdev->dev);
+       pm_runtime_put_autosuspend(cdev->dev);
+
        if (ret)
                return CATPT_IPC_ERROR(ret);
 
index f54b710ee1c25ad998096857d4e14e332bf8c89c..291a686568c261d5a77c1cd4d49fad135994ede7 100644 (file)
@@ -487,9 +487,9 @@ static int kmb_dai_hw_params(struct snd_pcm_substream *substream,
                kmb_i2s->xfer_resolution = 0x02;
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
-               config->data_width = 24;
-               kmb_i2s->ccr = 0x08;
-               kmb_i2s->xfer_resolution = 0x04;
+               config->data_width = 32;
+               kmb_i2s->ccr = 0x14;
+               kmb_i2s->xfer_resolution = 0x05;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
                config->data_width = 32;
index c2c1eb16fcc0ca5ada6f0ef378b1a43bb2e723ca..26e7d9a7198f807911b4d54d65641380013cff96 100644 (file)
@@ -630,15 +630,34 @@ static struct snd_soc_codec_conf mt8183_da7219_rt1015_codec_conf[] = {
        },
 };
 
+static const struct snd_kcontrol_new mt8183_da7219_rt1015_snd_controls[] = {
+       SOC_DAPM_PIN_SWITCH("Left Spk"),
+       SOC_DAPM_PIN_SWITCH("Right Spk"),
+};
+
+static const
+struct snd_soc_dapm_widget mt8183_da7219_rt1015_dapm_widgets[] = {
+       SND_SOC_DAPM_SPK("Left Spk", NULL),
+       SND_SOC_DAPM_SPK("Right Spk", NULL),
+       SND_SOC_DAPM_PINCTRL("TDM_OUT_PINCTRL",
+                            "aud_tdm_out_on", "aud_tdm_out_off"),
+};
+
+static const struct snd_soc_dapm_route mt8183_da7219_rt1015_dapm_routes[] = {
+       {"Left Spk", NULL, "Left SPO"},
+       {"Right Spk", NULL, "Right SPO"},
+       {"I2S Playback", NULL, "TDM_OUT_PINCTRL"},
+};
+
 static struct snd_soc_card mt8183_da7219_rt1015_card = {
        .name = "mt8183_da7219_rt1015",
        .owner = THIS_MODULE,
-       .controls = mt8183_da7219_max98357_snd_controls,
-       .num_controls = ARRAY_SIZE(mt8183_da7219_max98357_snd_controls),
-       .dapm_widgets = mt8183_da7219_max98357_dapm_widgets,
-       .num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_max98357_dapm_widgets),
-       .dapm_routes = mt8183_da7219_max98357_dapm_routes,
-       .num_dapm_routes = ARRAY_SIZE(mt8183_da7219_max98357_dapm_routes),
+       .controls = mt8183_da7219_rt1015_snd_controls,
+       .num_controls = ARRAY_SIZE(mt8183_da7219_rt1015_snd_controls),
+       .dapm_widgets = mt8183_da7219_rt1015_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_rt1015_dapm_widgets),
+       .dapm_routes = mt8183_da7219_rt1015_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(mt8183_da7219_rt1015_dapm_routes),
        .dai_link = mt8183_da7219_dai_links,
        .num_links = ARRAY_SIZE(mt8183_da7219_dai_links),
        .aux_dev = &mt8183_da7219_max98357_headset_dev,
index ba2aca301a9b25426ad226bd3167d5d72c4483cc..426235a217ec607fab4019486d605a984b6b8dc0 100644 (file)
@@ -80,6 +80,12 @@ static int lpass_cpu_daiops_startup(struct snd_pcm_substream *substream,
                dev_err(dai->dev, "error in enabling mi2s osr clk: %d\n", ret);
                return ret;
        }
+       ret = clk_prepare(drvdata->mi2s_bit_clk[dai->driver->id]);
+       if (ret) {
+               dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret);
+               clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]);
+               return ret;
+       }
        return 0;
 }
 
@@ -88,9 +94,8 @@ static void lpass_cpu_daiops_shutdown(struct snd_pcm_substream *substream,
 {
        struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
 
-       clk_disable_unprepare(drvdata->mi2s_bit_clk[dai->driver->id]);
-
        clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]);
+       clk_unprepare(drvdata->mi2s_bit_clk[dai->driver->id]);
 }
 
 static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
@@ -258,28 +263,6 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream,
-               struct snd_soc_dai *dai)
-{
-       struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
-       struct lpaif_i2sctl *i2sctl = drvdata->i2sctl;
-       unsigned int id = dai->driver->id;
-       int ret;
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               ret = regmap_fields_write(i2sctl->spken, id,
-                                        LPAIF_I2SCTL_SPKEN_ENABLE);
-       } else {
-               ret = regmap_fields_write(i2sctl->micen, id,
-                                        LPAIF_I2SCTL_MICEN_ENABLE);
-       }
-
-       if (ret)
-               dev_err(dai->dev, "error writing to i2sctl enable: %d\n", ret);
-
-       return ret;
-}
-
 static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
                int cmd, struct snd_soc_dai *dai)
 {
@@ -287,6 +270,18 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
        struct lpaif_i2sctl *i2sctl = drvdata->i2sctl;
        unsigned int id = dai->driver->id;
        int ret = -EINVAL;
+       unsigned int val = 0;
+
+       ret = regmap_read(drvdata->lpaif_map,
+                               LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), &val);
+       if (ret) {
+               dev_err(dai->dev, "error reading from i2sctl reg: %d\n", ret);
+               return ret;
+       }
+       if (val == LPAIF_I2SCTL_RESET_STATE) {
+               dev_err(dai->dev, "error in i2sctl register state\n");
+               return -ENOTRECOVERABLE;
+       }
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
@@ -303,11 +298,14 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
                        dev_err(dai->dev, "error writing to i2sctl reg: %d\n",
                                ret);
 
-               ret = clk_prepare_enable(drvdata->mi2s_bit_clk[id]);
-               if (ret) {
-                       dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret);
-                       clk_disable_unprepare(drvdata->mi2s_osr_clk[id]);
-                       return ret;
+               if (drvdata->bit_clk_state[id] == LPAIF_BIT_CLK_DISABLE) {
+                       ret = clk_enable(drvdata->mi2s_bit_clk[id]);
+                       if (ret) {
+                               dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret);
+                               clk_disable(drvdata->mi2s_osr_clk[id]);
+                               return ret;
+                       }
+                       drvdata->bit_clk_state[id] = LPAIF_BIT_CLK_ENABLE;
                }
 
                break;
@@ -324,6 +322,10 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
                if (ret)
                        dev_err(dai->dev, "error writing to i2sctl reg: %d\n",
                                ret);
+               if (drvdata->bit_clk_state[id] == LPAIF_BIT_CLK_ENABLE) {
+                       clk_disable(drvdata->mi2s_bit_clk[dai->driver->id]);
+                       drvdata->bit_clk_state[id] = LPAIF_BIT_CLK_DISABLE;
+               }
                break;
        }
 
@@ -335,7 +337,6 @@ const struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops = {
        .startup        = lpass_cpu_daiops_startup,
        .shutdown       = lpass_cpu_daiops_shutdown,
        .hw_params      = lpass_cpu_daiops_hw_params,
-       .prepare        = lpass_cpu_daiops_prepare,
        .trigger        = lpass_cpu_daiops_trigger,
 };
 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_ops);
@@ -453,16 +454,20 @@ static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg)
        struct lpass_variant *v = drvdata->variant;
        int i;
 
+       for (i = 0; i < v->i2s_ports; ++i)
+               if (reg == LPAIF_I2SCTL_REG(v, i))
+                       return true;
        for (i = 0; i < v->irq_ports; ++i)
                if (reg == LPAIF_IRQSTAT_REG(v, i))
                        return true;
 
        for (i = 0; i < v->rdma_channels; ++i)
-               if (reg == LPAIF_RDMACURR_REG(v, i))
+               if (reg == LPAIF_RDMACURR_REG(v, i) || reg == LPAIF_RDMACTL_REG(v, i))
                        return true;
 
        for (i = 0; i < v->wrdma_channels; ++i)
-               if (reg == LPAIF_WRDMACURR_REG(v, i + v->wrdma_channel_start))
+               if (reg == LPAIF_WRDMACURR_REG(v, i + v->wrdma_channel_start) ||
+                       reg == LPAIF_WRDMACTL_REG(v, i + v->wrdma_channel_start))
                        return true;
 
        return false;
@@ -855,6 +860,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
                                PTR_ERR(drvdata->mi2s_bit_clk[dai_id]));
                        return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]);
                }
+               drvdata->bit_clk_state[dai_id] = LPAIF_BIT_CLK_DISABLE;
        }
 
        /* Allocation for i2sctl regmap fields */
index 08f3fe508b854f6cc199728ec7a230414ec6f941..405542832e99416737b62b2c47ccf980e8a6965b 100644 (file)
 #define LPAIF_I2SCTL_BITWIDTH_24       1
 #define LPAIF_I2SCTL_BITWIDTH_32       2
 
+#define LPAIF_BIT_CLK_DISABLE          0
+#define LPAIF_BIT_CLK_ENABLE           1
+
+#define LPAIF_I2SCTL_RESET_STATE       0x003C0004
+#define LPAIF_DMACTL_RESET_STATE       0x00200000
+
+
 /* LPAIF IRQ */
 #define LPAIF_IRQ_REG_ADDR(v, addr, port) \
        (v->irq_reg_base + (addr) + v->irq_reg_stride * (port))
index 36d1512ffd1f522db0f6aad619845ed1c27c2fe0..80b09dede5f9cbefb4f6a6a7d968ea2166ada871 100644 (file)
@@ -110,6 +110,7 @@ static int lpass_platform_pcmops_open(struct snd_soc_component *component,
        struct regmap *map;
        unsigned int dai_id = cpu_dai->driver->id;
 
+       component->id = dai_id;
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
@@ -122,8 +123,10 @@ static int lpass_platform_pcmops_open(struct snd_soc_component *component,
        else
                dma_ch = 0;
 
-       if (dma_ch < 0)
+       if (dma_ch < 0) {
+               kfree(data);
                return dma_ch;
+       }
 
        if (cpu_dai->driver->id == LPASS_DP_RX) {
                map = drvdata->hdmiif_map;
@@ -147,6 +150,7 @@ static int lpass_platform_pcmops_open(struct snd_soc_component *component,
        ret = snd_pcm_hw_constraint_integer(runtime,
                        SNDRV_PCM_HW_PARAM_PERIODS);
        if (ret < 0) {
+               kfree(data);
                dev_err(soc_runtime->dev, "setting constraints failed: %d\n",
                        ret);
                return -EINVAL;
@@ -448,19 +452,34 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
        unsigned int reg_irqclr = 0, val_irqclr = 0;
        unsigned int  reg_irqen = 0, val_irqen = 0, val_mask = 0;
        unsigned int dai_id = cpu_dai->driver->id;
+       unsigned int dma_ctrl_reg = 0;
 
        ch = pcm_data->dma_ch;
        if (dir ==  SNDRV_PCM_STREAM_PLAYBACK) {
                id = pcm_data->dma_ch;
-               if (dai_id == LPASS_DP_RX)
+               if (dai_id == LPASS_DP_RX) {
                        dmactl = drvdata->hdmi_rd_dmactl;
-               else
+                       map = drvdata->hdmiif_map;
+               } else {
                        dmactl = drvdata->rd_dmactl;
+                       map = drvdata->lpaif_map;
+               }
        } else {
                dmactl = drvdata->wr_dmactl;
                id = pcm_data->dma_ch - v->wrdma_channel_start;
+               map = drvdata->lpaif_map;
+       }
+       ret = regmap_read(map, LPAIF_DMACTL_REG(v, ch, dir, dai_id), &dma_ctrl_reg);
+       if (ret) {
+               dev_err(soc_runtime->dev, "error reading from rdmactl reg: %d\n", ret);
+               return ret;
        }
 
+       if (dma_ctrl_reg == LPAIF_DMACTL_RESET_STATE ||
+               dma_ctrl_reg == LPAIF_DMACTL_RESET_STATE + 1) {
+               dev_err(soc_runtime->dev, "error in rdmactl register state\n");
+               return -ENOTRECOVERABLE;
+       }
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
index c6292f9e613f24ecbbde90cc80b113e6a37b5c67..bc998d50160000b4e1ff216491081504e48052cf 100644 (file)
@@ -188,7 +188,7 @@ static struct lpass_variant sc7180_data = {
        .micmode                = REG_FIELD_ID(0x1000, 4, 8, 3, 0x1000),
        .micmono                = REG_FIELD_ID(0x1000, 3, 3, 3, 0x1000),
        .wssrc                  = REG_FIELD_ID(0x1000, 2, 2, 3, 0x1000),
-       .bitwidth               = REG_FIELD_ID(0x1000, 0, 0, 3, 0x1000),
+       .bitwidth               = REG_FIELD_ID(0x1000, 0, 1, 3, 0x1000),
 
        .rdma_dyncclk           = REG_FIELD_ID(0xC000, 21, 21, 5, 0x1000),
        .rdma_bursten           = REG_FIELD_ID(0xC000, 20, 20, 5, 0x1000),
index b4830f3537968592468a06767fd52597e7b4bd38..bccd1a05d771e9679cdcd7e00f3abc7e3e30ed0c 100644 (file)
@@ -68,6 +68,7 @@ struct lpass_data {
        unsigned int mi2s_playback_sd_mode[LPASS_MAX_MI2S_PORTS];
        unsigned int mi2s_capture_sd_mode[LPASS_MAX_MI2S_PORTS];
        int hdmi_port_enable;
+       int bit_clk_state[LPASS_MAX_MI2S_PORTS];
 
        /* low-power audio interface (LPAIF) registers */
        void __iomem *lpaif;
index ab1bf23c21a6847eaacec2978179ee19cc9c0ee0..6c2760e27ea6fdbab1651e9f1ccbdc07887c73d7 100644 (file)
@@ -17,6 +17,7 @@
 #include "qdsp6/q6afe.h"
 #include "../codecs/rt5663.h"
 
+#define DRIVER_NAME    "sdm845"
 #define DEFAULT_SAMPLE_RATE_48K                48000
 #define DEFAULT_MCLK_RATE              24576000
 #define TDM_BCLK_RATE          6144000
@@ -552,6 +553,7 @@ static int sdm845_snd_platform_probe(struct platform_device *pdev)
        if (!data)
                return -ENOMEM;
 
+       card->driver_name = DRIVER_NAME;
        card->dapm_widgets = sdm845_snd_widgets;
        card->num_dapm_widgets = ARRAY_SIZE(sdm845_snd_widgets);
        card->dev = dev;
index ea3986a46c12a8325e430d618b1f65422593235c..05a085f6dc7ce7d1234278023e24e45488bc55c2 100644 (file)
@@ -2341,7 +2341,7 @@ struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component,
 }
 
 /**
- * snd_soc_unregister_dai - Unregister DAIs from the ASoC core
+ * snd_soc_unregister_dais - Unregister DAIs from the ASoC core
  *
  * @component: The component for which the DAIs should be unregistered
  */
index 980f2c330b87ff595efe20fd54614cdad231d8bb..7f87b449f950b8a55c9cc526a925aef1d9e27b1a 100644 (file)
@@ -1276,7 +1276,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
 }
 
 /**
- * snd_soc_dapm_get_connected_widgets - query audio path and it's widgets.
+ * snd_soc_dapm_dai_get_connected_widgets - query audio path and it's widgets.
  * @dai: the soc DAI.
  * @stream: stream direction.
  * @list: list of active widgets for this stream.
index 68ed454f7ddf1b5b2af8d63f83ae1043334b7100..ba9ed66f98bc7607741fefa0a00ae3509116d71e 100644 (file)
@@ -118,6 +118,11 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset)
                case SOF_IPC_EXT_CC_INFO:
                        ret = get_cc_info(sdev, ext_hdr);
                        break;
+               case SOF_IPC_EXT_UNUSED:
+               case SOF_IPC_EXT_PROBE_INFO:
+               case SOF_IPC_EXT_USER_ABI_INFO:
+                       /* They are supported but we don't do anything here */
+                       break;
                default:
                        dev_warn(sdev->dev, "warning: unknown ext header type %d size 0x%x\n",
                                 ext_hdr->type, ext_hdr->hdr.size);
index fa764b61fe9c8b8123ceceedec3ebf4bd8a84864..4457214a3ae62e27534badad34949e912393ff59 100644 (file)
@@ -379,6 +379,10 @@ static const struct usb_audio_device_name usb_audio_names[] = {
 
        DEVICE_NAME(0x046d, 0x0990, "Logitech, Inc.", "QuickCam Pro 9000"),
 
+       /* ASUS ROG Strix */
+       PROFILE_NAME(0x0b05, 0x1917,
+                    "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
+
        /* Dell WD15 Dock */
        PROFILE_NAME(0x0bda, 0x4014, "Dell", "WD15 Dock", "Dell-WD15-Dock"),
        /* Dell WD19 Dock */
index c369c81e74c41f20fb67821283dbfd41dda4b228..a7212f16660ece8385d2a6aa63a15314a391d941 100644 (file)
@@ -561,7 +561,8 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
        },
        {       /* ASUS ROG Strix */
                .id = USB_ID(0x0b05, 0x1917),
-               .map = asus_rog_map,
+               .map = trx40_mobo_map,
+               .connector_map = trx40_mobo_connector_map,
        },
        {       /* MSI TRX40 Creator */
                .id = USB_ID(0x0db0, 0x0d64),
index 92b1a6d9c931959b16508464ff355c466a4b16ac..bd63a9ce6a707e25bf2e5357af0f75d5506da038 100644 (file)
@@ -607,7 +607,7 @@ static int snd_us16x08_eq_put(struct snd_kcontrol *kcontrol,
 static int snd_us16x08_meter_info(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_info *uinfo)
 {
-       uinfo->count = 1;
+       uinfo->count = 34;
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        uinfo->value.integer.max = 0x7FFF;
        uinfo->value.integer.min = 0;
index b401ee894e1bb6978b595c750d12254e7b775618..a860303cc52225cd1a61287c177678f34430ce5f 100644 (file)
@@ -336,6 +336,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
        switch (subs->stream->chip->usb_id) {
        case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
        case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
+       case USB_ID(0x22f0, 0x0006): /* Allen&Heath Qu-16 */
                ep = 0x81;
                ifnum = 3;
                goto add_sync_ep_from_ifnum;
@@ -345,6 +346,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
                ifnum = 2;
                goto add_sync_ep_from_ifnum;
        case USB_ID(0x2466, 0x8003): /* Fractal Audio Axe-Fx II */
+       case USB_ID(0x0499, 0x172a): /* Yamaha MODX */
                ep = 0x86;
                ifnum = 2;
                goto add_sync_ep_from_ifnum;
@@ -352,6 +354,10 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
                ep = 0x81;
                ifnum = 2;
                goto add_sync_ep_from_ifnum;
+       case USB_ID(0x1686, 0xf029): /* Zoom UAC-2 */
+               ep = 0x82;
+               ifnum = 2;
+               goto add_sync_ep_from_ifnum;
        case USB_ID(0x1397, 0x0001): /* Behringer UFX1604 */
        case USB_ID(0x1397, 0x0002): /* Behringer UFX1204 */
                ep = 0x81;
index b4fa80ef730d96c2ba20f23b41110e5d85e2642c..c50be2f75f702763e6eb02331e1f4e7bc2c44bac 100644 (file)
@@ -1672,13 +1672,13 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
            && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
                msleep(20);
 
-       /* Zoom R16/24, Logitech H650e/H570e, Jabra 550a, Kingston HyperX
-        *  needs a tiny delay here, otherwise requests like get/set
-        *  frequency return as failed despite actually succeeding.
+       /* Zoom R16/24, many Logitech(at least H650e/H570e/BCC950),
+        * Jabra 550a, Kingston HyperX needs a tiny delay here,
+        * otherwise requests like get/set frequency return
+        * as failed despite actually succeeding.
         */
        if ((chip->usb_id == USB_ID(0x1686, 0x00dd) ||
-            chip->usb_id == USB_ID(0x046d, 0x0a46) ||
-            chip->usb_id == USB_ID(0x046d, 0x0a56) ||
+            USB_ID_VENDOR(chip->usb_id) == 0x046d  || /* Logitech */
             chip->usb_id == USB_ID(0x0b0e, 0x0349) ||
             chip->usb_id == USB_ID(0x0951, 0x16ad)) &&
            (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
@@ -1800,6 +1800,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
        case 0x278b:  /* Rotel? */
        case 0x292b:  /* Gustard/Ess based devices */
        case 0x2ab6:  /* T+A devices */
+       case 0x3353:  /* Khadas devices */
        case 0x3842:  /* EVGA */
        case 0xc502:  /* HiBy devices */
                if (fp->dsd_raw)
index ba85bb23f06017b4ed401da32167c057d526b1d0..1c17c3a24411d6b0dfd33424d1b493d4750d0221 100644 (file)
@@ -159,6 +159,21 @@ struct kvm_sync_regs {
 struct kvm_arch_memory_slot {
 };
 
+/*
+ * PMU filter structure. Describe a range of events with a particular
+ * action. To be used with KVM_ARM_VCPU_PMU_V3_FILTER.
+ */
+struct kvm_pmu_event_filter {
+       __u16   base_event;
+       __u16   nevents;
+
+#define KVM_PMU_EVENT_ALLOW    0
+#define KVM_PMU_EVENT_DENY     1
+
+       __u8    action;
+       __u8    pad[3];
+};
+
 /* for KVM_GET/SET_VCPU_EVENTS */
 struct kvm_vcpu_events {
        struct {
@@ -242,6 +257,15 @@ struct kvm_vcpu_events {
 #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL          0
 #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL              1
 #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED       2
+
+/*
+ * Only two states can be presented by the host kernel:
+ * - NOT_REQUIRED: the guest doesn't need to do anything
+ * - NOT_AVAIL: the guest isn't mitigated (it can still use SSBS if available)
+ *
+ * All the other values are deprecated. The host still accepts all
+ * values (they are ABI), but will narrow them to the above two.
+ */
 #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2    KVM_REG_ARM_FW_REG(2)
 #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL          0
 #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN            1
@@ -329,6 +353,7 @@ struct kvm_vcpu_events {
 #define KVM_ARM_VCPU_PMU_V3_CTRL       0
 #define   KVM_ARM_VCPU_PMU_V3_IRQ      0
 #define   KVM_ARM_VCPU_PMU_V3_INIT     1
+#define   KVM_ARM_VCPU_PMU_V3_FILTER   2
 #define KVM_ARM_VCPU_TIMER_CTRL                1
 #define   KVM_ARM_VCPU_TIMER_IRQ_VTIMER                0
 #define   KVM_ARM_VCPU_TIMER_IRQ_PTIMER                1
index 6ca1e68d7103139f1ef6029980aea2f3198072be..ede318653c87dd82ea64add7bec8ff8d38efaac7 100644 (file)
@@ -29,7 +29,7 @@
        { 0x13, "SIGP conditional emergency signal" },          \
        { 0x15, "SIGP sense running" },                         \
        { 0x16, "SIGP set multithreading"},                     \
-       { 0x17, "SIGP store additional status ait address"}
+       { 0x17, "SIGP store additional status at address"}
 
 #define icpt_prog_codes                                                \
        { 0x0001, "Prog Operation" },                           \
index 2901d5df4366c0409e6d295d0eb1585aa1568ea9..dad350d42ecfbf3063c64138375e81591729b092 100644 (file)
@@ -96,7 +96,7 @@
 #define X86_FEATURE_SYSCALL32          ( 3*32+14) /* "" syscall in IA32 userspace */
 #define X86_FEATURE_SYSENTER32         ( 3*32+15) /* "" sysenter in IA32 userspace */
 #define X86_FEATURE_REP_GOOD           ( 3*32+16) /* REP microcode works well */
-/* free                                        ( 3*32+17) */
+#define X86_FEATURE_SME_COHERENT       ( 3*32+17) /* "" AMD hardware-enforced cache coherency */
 #define X86_FEATURE_LFENCE_RDTSC       ( 3*32+18) /* "" LFENCE synchronizes RDTSC */
 #define X86_FEATURE_ACC_POWER          ( 3*32+19) /* AMD Accumulated Power Mechanism */
 #define X86_FEATURE_NOPL               ( 3*32+20) /* The NOPL (0F 1F) instructions */
 #define X86_FEATURE_EPT_AD             ( 8*32+17) /* Intel Extended Page Table access-dirty bit */
 #define X86_FEATURE_VMCALL             ( 8*32+18) /* "" Hypervisor supports the VMCALL instruction */
 #define X86_FEATURE_VMW_VMMCALL                ( 8*32+19) /* "" VMware prefers VMMCALL hypercall instruction */
+#define X86_FEATURE_SEV_ES             ( 8*32+20) /* AMD Secure Encrypted Virtualization - Encrypted State */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (EBX), word 9 */
 #define X86_FEATURE_FSGSBASE           ( 9*32+ 0) /* RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/
 #define X86_FEATURE_FENCE_SWAPGS_USER  (11*32+ 4) /* "" LFENCE in user entry SWAPGS path */
 #define X86_FEATURE_FENCE_SWAPGS_KERNEL        (11*32+ 5) /* "" LFENCE in kernel entry SWAPGS path */
 #define X86_FEATURE_SPLIT_LOCK_DETECT  (11*32+ 6) /* #AC for split lock */
+#define X86_FEATURE_PER_THREAD_MBA     (11*32+ 7) /* "" Per-thread Memory Bandwidth Allocation */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
 #define X86_FEATURE_AVX512_BF16                (12*32+ 5) /* AVX512 BFLOAT16 instructions */
 #define X86_FEATURE_CLDEMOTE           (16*32+25) /* CLDEMOTE instruction */
 #define X86_FEATURE_MOVDIRI            (16*32+27) /* MOVDIRI instruction */
 #define X86_FEATURE_MOVDIR64B          (16*32+28) /* MOVDIR64B instruction */
+#define X86_FEATURE_ENQCMD             (16*32+29) /* ENQCMD and ENQCMDS instructions */
 
 /* AMD-defined CPU features, CPUID level 0x80000007 (EBX), word 17 */
 #define X86_FEATURE_OVERFLOW_RECOV     (17*32+ 0) /* MCA overflow recovery support */
 #define X86_FEATURE_MD_CLEAR           (18*32+10) /* VERW clears CPU buffers */
 #define X86_FEATURE_TSX_FORCE_ABORT    (18*32+13) /* "" TSX_FORCE_ABORT */
 #define X86_FEATURE_SERIALIZE          (18*32+14) /* SERIALIZE instruction */
+#define X86_FEATURE_TSXLDTRK           (18*32+16) /* TSX Suspend Load Address Tracking */
 #define X86_FEATURE_PCONFIG            (18*32+18) /* Intel PCONFIG */
 #define X86_FEATURE_ARCH_LBR           (18*32+19) /* Intel ARCH LBR */
 #define X86_FEATURE_SPEC_CTRL          (18*32+26) /* "" Speculation Control (IBRS + IBPB) */
index 4ea8584682f9982662e34db1f9df77377f4a3662..5861d34f977182983ab4d0834f109acaca323d0f 100644 (file)
 # define DISABLE_PTI           (1 << (X86_FEATURE_PTI & 31))
 #endif
 
+#ifdef CONFIG_IOMMU_SUPPORT
+# define DISABLE_ENQCMD        0
+#else
+# define DISABLE_ENQCMD (1 << (X86_FEATURE_ENQCMD & 31))
+#endif
+
 /*
  * Make sure to add features to the correct mask
  */
@@ -75,7 +81,8 @@
 #define DISABLED_MASK13        0
 #define DISABLED_MASK14        0
 #define DISABLED_MASK15        0
-#define DISABLED_MASK16        (DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57|DISABLE_UMIP)
+#define DISABLED_MASK16        (DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57|DISABLE_UMIP| \
+                        DISABLE_ENQCMD)
 #define DISABLED_MASK17        0
 #define DISABLED_MASK18        0
 #define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
index 568854b14d0a57d49ac5d2eabfafa054cf66bec2..52c6262e6bfd1e97c50311739fc65fe7fae59a37 100644 (file)
@@ -201,6 +201,21 @@ static inline int insn_offset_immediate(struct insn *insn)
        return insn_offset_displacement(insn) + insn->displacement.nbytes;
 }
 
+/**
+ * for_each_insn_prefix() -- Iterate prefixes in the instruction
+ * @insn: Pointer to struct insn.
+ * @idx:  Index storage.
+ * @prefix: Prefix byte.
+ *
+ * Iterate prefix bytes of given @insn. Each prefix byte is stored in @prefix
+ * and the index is stored in @idx (note that this @idx is just for a cursor,
+ * do not change it.)
+ * Since prefixes.nbytes can be bigger than 4 if some prefixes
+ * are repeated, it cannot be used for looping over the prefixes.
+ */
+#define for_each_insn_prefix(insn, idx, prefix)        \
+       for (idx = 0; idx < ARRAY_SIZE(insn->prefixes.bytes) && (prefix = insn->prefixes.bytes[idx]) != 0; idx++)
+
 #define POP_SS_OPCODE 0x1f
 #define MOV_SREG_OPCODE 0x8e
 
index 2859ee4f39a83fa4d73cc0f261e3effff7a455e7..972a34d935059aa49d01db8f20c3e598fffb22ac 100644 (file)
 #define MSR_IA32_LASTINTFROMIP         0x000001dd
 #define MSR_IA32_LASTINTTOIP           0x000001de
 
+#define MSR_IA32_PASID                 0x00000d93
+#define MSR_IA32_PASID_VALID           BIT_ULL(31)
+
 /* DEBUGCTLMSR bits (others vary by model): */
 #define DEBUGCTLMSR_LBR                        (1UL <<  0) /* last branch recording */
 #define DEBUGCTLMSR_BTF_SHIFT          1
 #define MSR_AMD64_IBSOP_REG_MASK       ((1UL<<MSR_AMD64_IBSOP_REG_COUNT)-1)
 #define MSR_AMD64_IBSCTL               0xc001103a
 #define MSR_AMD64_IBSBRTARGET          0xc001103b
+#define MSR_AMD64_ICIBSEXTDCTL         0xc001103c
 #define MSR_AMD64_IBSOPDATA4           0xc001103d
 #define MSR_AMD64_IBS_REG_COUNT_MAX    8 /* includes MSR_AMD64_IBSBRTARGET */
+#define MSR_AMD64_SEV_ES_GHCB          0xc0010130
 #define MSR_AMD64_SEV                  0xc0010131
 #define MSR_AMD64_SEV_ENABLED_BIT      0
+#define MSR_AMD64_SEV_ES_ENABLED_BIT   1
 #define MSR_AMD64_SEV_ENABLED          BIT_ULL(MSR_AMD64_SEV_ENABLED_BIT)
+#define MSR_AMD64_SEV_ES_ENABLED       BIT_ULL(MSR_AMD64_SEV_ES_ENABLED_BIT)
 
 #define MSR_AMD64_VIRT_SPEC_CTRL       0xc001011f
 
 #define MSR_CORE_PERF_FIXED_CTR0       0x00000309
 #define MSR_CORE_PERF_FIXED_CTR1       0x0000030a
 #define MSR_CORE_PERF_FIXED_CTR2       0x0000030b
+#define MSR_CORE_PERF_FIXED_CTR3       0x0000030c
 #define MSR_CORE_PERF_FIXED_CTR_CTRL   0x0000038d
 #define MSR_CORE_PERF_GLOBAL_STATUS    0x0000038e
 #define MSR_CORE_PERF_GLOBAL_CTRL      0x0000038f
 #define MSR_CORE_PERF_GLOBAL_OVF_CTRL  0x00000390
 
+#define MSR_PERF_METRICS               0x00000329
+
 /* PERF_GLOBAL_OVF_CTL bits */
 #define MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI_BIT       55
 #define MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI           (1ULL << MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI_BIT)
index 6847d85400a8b738ca2adf00ea95fdf8f349fafc..3ff0d48469f281fb104fe164c2b3c0b7dea9cae8 100644 (file)
@@ -54,7 +54,7 @@
 #endif
 
 #ifdef CONFIG_X86_64
-#ifdef CONFIG_PARAVIRT
+#ifdef CONFIG_PARAVIRT_XXL
 /* Paravirtualized systems may not have PSE or PGE available */
 #define NEED_PSE       0
 #define NEED_PGE       0
index 0780f97c185088ce214bf7f57d917fda7aff730b..89e5f3d1bba86b8bbb0e7a80cbed2d1373d093af 100644 (file)
@@ -192,6 +192,26 @@ struct kvm_msr_list {
        __u32 indices[0];
 };
 
+/* Maximum size of any access bitmap in bytes */
+#define KVM_MSR_FILTER_MAX_BITMAP_SIZE 0x600
+
+/* for KVM_X86_SET_MSR_FILTER */
+struct kvm_msr_filter_range {
+#define KVM_MSR_FILTER_READ  (1 << 0)
+#define KVM_MSR_FILTER_WRITE (1 << 1)
+       __u32 flags;
+       __u32 nmsrs; /* number of msrs in bitmap */
+       __u32 base;  /* MSR index the bitmap starts at */
+       __u8 *bitmap; /* a 1 bit allows the operations in flags, 0 denies */
+};
+
+#define KVM_MSR_FILTER_MAX_RANGES 16
+struct kvm_msr_filter {
+#define KVM_MSR_FILTER_DEFAULT_ALLOW (0 << 0)
+#define KVM_MSR_FILTER_DEFAULT_DENY  (1 << 0)
+       __u32 flags;
+       struct kvm_msr_filter_range ranges[KVM_MSR_FILTER_MAX_RANGES];
+};
 
 struct kvm_cpuid_entry {
        __u32 function;
index 2e8a30f06c74641cead87f4f460089f081c63ea7..f1d8307454e0c166fa244e65e81261c78687c1aa 100644 (file)
@@ -29,6 +29,7 @@
 #define SVM_EXIT_WRITE_DR6     0x036
 #define SVM_EXIT_WRITE_DR7     0x037
 #define SVM_EXIT_EXCP_BASE     0x040
+#define SVM_EXIT_LAST_EXCP     0x05f
 #define SVM_EXIT_INTR          0x060
 #define SVM_EXIT_NMI           0x061
 #define SVM_EXIT_SMI           0x062
 #define SVM_EXIT_MWAIT_COND    0x08c
 #define SVM_EXIT_XSETBV        0x08d
 #define SVM_EXIT_RDPRU         0x08e
+#define SVM_EXIT_INVPCID       0x0a2
 #define SVM_EXIT_NPF           0x400
 #define SVM_EXIT_AVIC_INCOMPLETE_IPI           0x401
 #define SVM_EXIT_AVIC_UNACCELERATED_ACCESS     0x402
 
+/* SEV-ES software-defined VMGEXIT events */
+#define SVM_VMGEXIT_MMIO_READ                  0x80000001
+#define SVM_VMGEXIT_MMIO_WRITE                 0x80000002
+#define SVM_VMGEXIT_NMI_COMPLETE               0x80000003
+#define SVM_VMGEXIT_AP_HLT_LOOP                        0x80000004
+#define SVM_VMGEXIT_AP_JUMP_TABLE              0x80000005
+#define SVM_VMGEXIT_SET_AP_JUMP_TABLE          0
+#define SVM_VMGEXIT_GET_AP_JUMP_TABLE          1
+#define SVM_VMGEXIT_UNSUPPORTED_EVENT          0x8000ffff
+
 #define SVM_EXIT_ERR           -1
 
 #define SVM_EXIT_REASONS \
        { SVM_EXIT_MONITOR,     "monitor" }, \
        { SVM_EXIT_MWAIT,       "mwait" }, \
        { SVM_EXIT_XSETBV,      "xsetbv" }, \
+       { SVM_EXIT_INVPCID,     "invpcid" }, \
        { SVM_EXIT_NPF,         "npf" }, \
        { SVM_EXIT_AVIC_INCOMPLETE_IPI,         "avic_incomplete_ipi" }, \
        { SVM_EXIT_AVIC_UNACCELERATED_ACCESS,   "avic_unaccelerated_access" }, \
index 0b5b8ae56bd917838ec9dfdf593a3c99ff7258aa..1e299ac73c8698622c7e631a4571b5b88e8b32f7 100644 (file)
@@ -16,8 +16,6 @@
  * to a jmp to memcpy_erms which does the REP; MOVSB mem copy.
  */
 
-.weak memcpy
-
 /*
  * memcpy - Copy a memory block.
  *
@@ -30,7 +28,7 @@
  * rax original destination
  */
 SYM_FUNC_START_ALIAS(__memcpy)
-SYM_FUNC_START_LOCAL(memcpy)
+SYM_FUNC_START_WEAK(memcpy)
        ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \
                      "jmp memcpy_erms", X86_FEATURE_ERMS
 
@@ -51,14 +49,14 @@ EXPORT_SYMBOL(__memcpy)
  * memcpy_erms() - enhanced fast string memcpy. This is faster and
  * simpler than memcpy. Use memcpy_erms when possible.
  */
-SYM_FUNC_START(memcpy_erms)
+SYM_FUNC_START_LOCAL(memcpy_erms)
        movq %rdi, %rax
        movq %rdx, %rcx
        rep movsb
        ret
 SYM_FUNC_END(memcpy_erms)
 
-SYM_FUNC_START(memcpy_orig)
+SYM_FUNC_START_LOCAL(memcpy_orig)
        movq %rdi, %rax
 
        cmpq $0x20, %rdx
index fd5d25a474b7c66a04955623f042c3bfb43f62cb..0bfd26e4ca9e938af774c5b1e4fea753d47d156c 100644 (file)
@@ -4,8 +4,7 @@
 #include <linux/linkage.h>
 #include <asm/cpufeatures.h>
 #include <asm/alternative-asm.h>
-
-.weak memset
+#include <asm/export.h>
 
 /*
  * ISO C memset - set a memory block to a byte value. This function uses fast
@@ -18,7 +17,7 @@
  *
  * rax   original destination
  */
-SYM_FUNC_START_ALIAS(memset)
+SYM_FUNC_START_WEAK(memset)
 SYM_FUNC_START(__memset)
        /*
         * Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended
@@ -44,6 +43,8 @@ SYM_FUNC_START(__memset)
        ret
 SYM_FUNC_END(__memset)
 SYM_FUNC_END_ALIAS(memset)
+EXPORT_SYMBOL(memset)
+EXPORT_SYMBOL(__memset)
 
 /*
  * ISO C memset - set a memory block to a byte value. This function uses
@@ -56,7 +57,7 @@ SYM_FUNC_END_ALIAS(memset)
  *
  * rax   original destination
  */
-SYM_FUNC_START(memset_erms)
+SYM_FUNC_START_LOCAL(memset_erms)
        movq %rdi,%r9
        movb %sil,%al
        movq %rdx,%rcx
@@ -65,7 +66,7 @@ SYM_FUNC_START(memset_erms)
        ret
 SYM_FUNC_END(memset_erms)
 
-SYM_FUNC_START(memset_orig)
+SYM_FUNC_START_LOCAL(memset_orig)
        movq %rdi,%r10
 
        /* expand byte value  */
index eb92027817a770eecb629022c5ad94d783f3cea6..7362bef1a36834df0a72ed06abbde64f523f505c 100644 (file)
@@ -10,6 +10,7 @@
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
+#include <endian.h>
 
 #include <linux/kernel.h>
 #include <linux/bootconfig.h>
@@ -147,6 +148,12 @@ static int load_xbc_file(const char *path, char **buf)
        return ret;
 }
 
+static int pr_errno(const char *msg, int err)
+{
+       pr_err("%s: %d\n", msg, err);
+       return err;
+}
+
 static int load_xbc_from_initrd(int fd, char **buf)
 {
        struct stat stat;
@@ -162,26 +169,26 @@ static int load_xbc_from_initrd(int fd, char **buf)
        if (stat.st_size < 8 + BOOTCONFIG_MAGIC_LEN)
                return 0;
 
-       if (lseek(fd, -BOOTCONFIG_MAGIC_LEN, SEEK_END) < 0) {
-               pr_err("Failed to lseek: %d\n", -errno);
-               return -errno;
-       }
+       if (lseek(fd, -BOOTCONFIG_MAGIC_LEN, SEEK_END) < 0)
+               return pr_errno("Failed to lseek for magic", -errno);
+
        if (read(fd, magic, BOOTCONFIG_MAGIC_LEN) < 0)
-               return -errno;
+               return pr_errno("Failed to read", -errno);
+
        /* Check the bootconfig magic bytes */
        if (memcmp(magic, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN) != 0)
                return 0;
 
-       if (lseek(fd, -(8 + BOOTCONFIG_MAGIC_LEN), SEEK_END) < 0) {
-               pr_err("Failed to lseek: %d\n", -errno);
-               return -errno;
-       }
+       if (lseek(fd, -(8 + BOOTCONFIG_MAGIC_LEN), SEEK_END) < 0)
+               return pr_errno("Failed to lseek for size", -errno);
 
        if (read(fd, &size, sizeof(u32)) < 0)
-               return -errno;
+               return pr_errno("Failed to read size", -errno);
+       size = le32toh(size);
 
        if (read(fd, &csum, sizeof(u32)) < 0)
-               return -errno;
+               return pr_errno("Failed to read checksum", -errno);
+       csum = le32toh(csum);
 
        /* Wrong size error  */
        if (stat.st_size < size + 8 + BOOTCONFIG_MAGIC_LEN) {
@@ -190,10 +197,8 @@ static int load_xbc_from_initrd(int fd, char **buf)
        }
 
        if (lseek(fd, stat.st_size - (size + 8 + BOOTCONFIG_MAGIC_LEN),
-                 SEEK_SET) < 0) {
-               pr_err("Failed to lseek: %d\n", -errno);
-               return -errno;
-       }
+                 SEEK_SET) < 0)
+               return pr_errno("Failed to lseek", -errno);
 
        ret = load_xbc_fd(fd, buf, size);
        if (ret < 0)
@@ -262,14 +267,16 @@ static int show_xbc(const char *path, bool list)
 
        ret = stat(path, &st);
        if (ret < 0) {
-               pr_err("Failed to stat %s: %d\n", path, -errno);
-               return -errno;
+               ret = -errno;
+               pr_err("Failed to stat %s: %d\n", path, ret);
+               return ret;
        }
 
        fd = open(path, O_RDONLY);
        if (fd < 0) {
-               pr_err("Failed to open initrd %s: %d\n", path, fd);
-               return -errno;
+               ret = -errno;
+               pr_err("Failed to open initrd %s: %d\n", path, ret);
+               return ret;
        }
 
        ret = load_xbc_from_initrd(fd, &buf);
@@ -307,8 +314,9 @@ static int delete_xbc(const char *path)
 
        fd = open(path, O_RDWR);
        if (fd < 0) {
-               pr_err("Failed to open initrd %s: %d\n", path, fd);
-               return -errno;
+               ret = -errno;
+               pr_err("Failed to open initrd %s: %d\n", path, ret);
+               return ret;
        }
 
        size = load_xbc_from_initrd(fd, &buf);
@@ -332,11 +340,13 @@ static int delete_xbc(const char *path)
 
 static int apply_xbc(const char *path, const char *xbc_path)
 {
+       char *buf, *data, *p;
+       size_t total_size;
+       struct stat stat;
+       const char *msg;
        u32 size, csum;
-       char *buf, *data;
+       int pos, pad;
        int ret, fd;
-       const char *msg;
-       int pos;
 
        ret = load_xbc_file(xbc_path, &buf);
        if (ret < 0) {
@@ -346,13 +356,12 @@ static int apply_xbc(const char *path, const char *xbc_path)
        size = strlen(buf) + 1;
        csum = checksum((unsigned char *)buf, size);
 
-       /* Prepare xbc_path data */
-       data = malloc(size + 8);
+       /* Backup the bootconfig data */
+       data = calloc(size + BOOTCONFIG_ALIGN +
+                     sizeof(u32) + sizeof(u32) + BOOTCONFIG_MAGIC_LEN, 1);
        if (!data)
                return -ENOMEM;
-       strcpy(data, buf);
-       *(u32 *)(data + size) = size;
-       *(u32 *)(data + size + 4) = csum;
+       memcpy(data, buf, size);
 
        /* Check the data format */
        ret = xbc_init(buf, &msg, &pos);
@@ -383,28 +392,61 @@ static int apply_xbc(const char *path, const char *xbc_path)
        /* Apply new one */
        fd = open(path, O_RDWR | O_APPEND);
        if (fd < 0) {
-               pr_err("Failed to open %s: %d\n", path, fd);
+               ret = -errno;
+               pr_err("Failed to open %s: %d\n", path, ret);
                free(data);
-               return fd;
+               return ret;
        }
        /* TODO: Ensure the @path is initramfs/initrd image */
-       ret = write(fd, data, size + 8);
-       if (ret < 0) {
-               pr_err("Failed to apply a boot config: %d\n", ret);
+       if (fstat(fd, &stat) < 0) {
+               pr_err("Failed to get the size of %s\n", path);
                goto out;
        }
-       /* Write a magic word of the bootconfig */
-       ret = write(fd, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN);
-       if (ret < 0) {
-               pr_err("Failed to apply a boot config magic: %d\n", ret);
-               goto out;
-       }
-       ret = 0;
+
+       /* To align up the total size to BOOTCONFIG_ALIGN, get padding size */
+       total_size = stat.st_size + size + sizeof(u32) * 2 + BOOTCONFIG_MAGIC_LEN;
+       pad = ((total_size + BOOTCONFIG_ALIGN - 1) & (~BOOTCONFIG_ALIGN_MASK)) - total_size;
+       size += pad;
+
+       /* Add a footer */
+       p = data + size;
+       *(u32 *)p = htole32(size);
+       p += sizeof(u32);
+
+       *(u32 *)p = htole32(csum);
+       p += sizeof(u32);
+
+       memcpy(p, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN);
+       p += BOOTCONFIG_MAGIC_LEN;
+
+       total_size = p - data;
+
+       ret = write(fd, data, total_size);
+       if (ret < total_size) {
+               if (ret < 0)
+                       ret = -errno;
+               pr_err("Failed to apply a boot config: %d\n", ret);
+               if (ret >= 0)
+                       goto out_rollback;
+       } else
+               ret = 0;
+
 out:
        close(fd);
        free(data);
 
        return ret;
+
+out_rollback:
+       /* Map the partial write to -ENOSPC */
+       if (ret >= 0)
+               ret = -ENOSPC;
+       if (ftruncate(fd, stat.st_size) < 0) {
+               ret = -errno;
+               pr_err("Failed to rollback the write error: %d\n", ret);
+               pr_err("The initrd %s may be corrupted. Recommend to rebuild.\n", path);
+       }
+       goto out;
 }
 
 static int usage(void)
index d295e406a756ede11baae579189deca328636174..baed891d0ba4969a9b13fbe335898fee8661a0c1 100755 (executable)
@@ -9,6 +9,7 @@ else
   TESTDIR=.
 fi
 BOOTCONF=${TESTDIR}/bootconfig
+ALIGN=4
 
 INITRD=`mktemp ${TESTDIR}/initrd-XXXX`
 TEMPCONF=`mktemp ${TESTDIR}/temp-XXXX.bconf`
@@ -59,7 +60,10 @@ echo "Show command test"
 xpass $BOOTCONF $INITRD
 
 echo "File size check"
-xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9 + 12)
+total_size=$(expr $bconf_size + $initrd_size + 9 + 12 + $ALIGN - 1 )
+total_size=$(expr $total_size / $ALIGN)
+total_size=$(expr $total_size \* $ALIGN)
+xpass test $new_size -eq $total_size
 
 echo "Apply command repeat test"
 xpass $BOOTCONF -a $TEMPCONF $INITRD
index 8ab142ff5eac578dcd594d4699731937c366f85a..2afb7d5b1aca296c5752de1097b5aea5c2019965 100644 (file)
@@ -693,6 +693,7 @@ build_btf_type_table(struct btf_attach_table *tab, enum bpf_obj_type type,
                obj_node = calloc(1, sizeof(*obj_node));
                if (!obj_node) {
                        p_err("failed to allocate memory: %s", strerror(errno));
+                       err = -ENOMEM;
                        goto err_free;
                }
 
index a43a6f10b564c3246560ff7bdacc449d0cc5dbf6..359960a8f1defc05d5b8ae31e3c95e35e0339187 100644 (file)
@@ -843,9 +843,14 @@ static int handle_perms(void)
                else
                        p_err("missing %s%s%s%s%s%s%s%srequired for full feature probing; run as root or use 'unprivileged'",
                              capability_msg(bpf_caps, 0),
+#ifdef CAP_BPF
                              capability_msg(bpf_caps, 1),
                              capability_msg(bpf_caps, 2),
-                             capability_msg(bpf_caps, 3));
+                             capability_msg(bpf_caps, 3)
+#else
+                               "", "", "", "", "", ""
+#endif /* CAP_BPF */
+                               );
                goto exit_free;
        }
 
index 910e7bac6e9ec6223e86e873c65272adbbf35ab5..3fae61ef63396dad501e1b65bf326ff7728c5522 100644 (file)
@@ -578,8 +578,8 @@ static int do_attach(int argc, char **argv)
 
        ifindex = net_parse_dev(&argc, &argv);
        if (ifindex < 1) {
-               close(progfd);
-               return -EINVAL;
+               err = -EINVAL;
+               goto cleanup;
        }
 
        if (argc) {
@@ -587,8 +587,8 @@ static int do_attach(int argc, char **argv)
                        overwrite = true;
                } else {
                        p_err("expected 'overwrite', got: '%s'?", *argv);
-                       close(progfd);
-                       return -EINVAL;
+                       err = -EINVAL;
+                       goto cleanup;
                }
        }
 
@@ -596,17 +596,17 @@ static int do_attach(int argc, char **argv)
        if (is_prefix("xdp", attach_type_strings[attach_type]))
                err = do_attach_detach_xdp(progfd, attach_type, ifindex,
                                           overwrite);
-
-       if (err < 0) {
+       if (err) {
                p_err("interface %s attach failed: %s",
                      attach_type_strings[attach_type], strerror(-err));
-               return err;
+               goto cleanup;
        }
 
        if (json_output)
                jsonw_null(json_wtr);
-
-       return 0;
+cleanup:
+       close(progfd);
+       return err;
 }
 
 static int do_detach(int argc, char **argv)
index d942c1e3372c75e451c8fdf7ad4b09aeb37b176c..acdb2c245f0a4643e6deb3f77801aba5cfab6ce9 100644 (file)
@@ -940,7 +940,7 @@ static int parse_attach_detach_args(int argc, char **argv, int *progfd,
        }
 
        if (*attach_type == BPF_FLOW_DISSECTOR) {
-               *mapfd = -1;
+               *mapfd = 0;
                return 0;
        }
 
index 4e3512f700c0857c1316dba2f80dca7b30552a77..ce5b65e07ab1074ad405f8e5a6ed345dbf2c0011 100644 (file)
@@ -70,7 +70,7 @@ int BPF_PROG(fentry_XXX)
 static inline void
 fexit_update_maps(u32 id, struct bpf_perf_event_value *after)
 {
-       struct bpf_perf_event_value *before, diff, *accum;
+       struct bpf_perf_event_value *before, diff;
 
        before = bpf_map_lookup_elem(&fentry_readings, &id);
        /* only account samples with a valid fentry_reading */
@@ -95,7 +95,7 @@ int BPF_PROG(fexit_XXX)
 {
        struct bpf_perf_event_value readings[MAX_NUM_MATRICS];
        u32 cpu = bpf_get_smp_processor_id();
-       u32 i, one = 1, zero = 0;
+       u32 i, zero = 0;
        int err;
        u64 *count;
 
index a04e81321c665f195d129e25f5d6086a27e47cfe..464873883396e9c7e85795174f019ed8106a3192 100644 (file)
@@ -185,7 +185,6 @@ int main(int argc, char *argv[])
        main_test_libperl();
        main_test_hello();
        main_test_libelf();
-       main_test_libelf_mmap();
        main_test_get_current_dir_name();
        main_test_gettid();
        main_test_glibc();
index b9d4322e1e6551f3e987624073a08a9b3368b7f8..95c072b70d0e832f70a4ac07470bcd0d1ed46deb 100644 (file)
 #define  __pure                __attribute__((pure))
 #endif
 #define  noinline      __attribute__((noinline))
-#ifdef __has_attribute
-#if __has_attribute(disable_tail_calls)
-#define __no_tail_call __attribute__((disable_tail_calls))
-#endif
-#endif
-#ifndef __no_tail_call
-#if GCC_VERSION > 40201
-#define __no_tail_call __attribute__((optimize("no-optimize-sibling-calls")))
-#else
-#define __no_tail_call
-#endif
-#endif
 #ifndef __packed
 #define __packed       __attribute__((packed))
 #endif
index 2b3f7353e891f5ad8ab63aae9ef78dab4a23449e..d22a974372c0e212433a512611ddbef78c2c74f5 100644 (file)
@@ -47,9 +47,6 @@
 #ifndef noinline
 #define noinline
 #endif
-#ifndef __no_tail_call
-#define __no_tail_call
-#endif
 
 /* Are two types/vars the same type (ignoring qualifiers)? */
 #ifndef __same_type
index f2b5d72a46c23b9f9abd6b439b29e1192bf59dff..2056318988f774931c4e0a3104144bf4a75ff52f 100644 (file)
@@ -857,9 +857,11 @@ __SYSCALL(__NR_openat2, sys_openat2)
 __SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd)
 #define __NR_faccessat2 439
 __SYSCALL(__NR_faccessat2, sys_faccessat2)
+#define __NR_process_madvise 440
+__SYSCALL(__NR_process_madvise, sys_process_madvise)
 
 #undef __NR_syscalls
-#define __NR_syscalls 440
+#define __NR_syscalls 441
 
 /*
  * 32 bit systems traditionally used different
index 00546062e0235d9b445c5288573e3bd1854aa04a..fa1f3d62f9a6cebb300c63bf82955af91ab2a6ed 100644 (file)
@@ -619,6 +619,12 @@ typedef struct drm_i915_irq_wait {
  */
 #define I915_PARAM_PERF_REVISION       54
 
+/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of
+ * timeline syncobj through drm_i915_gem_execbuffer_ext_timeline_fences. See
+ * I915_EXEC_USE_EXTENSIONS.
+ */
+#define I915_PARAM_HAS_EXEC_TIMELINE_FENCES 55
+
 /* Must be kept compact -- no holes and well documented */
 
 typedef struct drm_i915_getparam {
@@ -1046,6 +1052,38 @@ struct drm_i915_gem_exec_fence {
        __u32 flags;
 };
 
+/**
+ * See drm_i915_gem_execbuffer_ext_timeline_fences.
+ */
+#define DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES 0
+
+/**
+ * This structure describes an array of drm_syncobj and associated points for
+ * timeline variants of drm_syncobj. It is invalid to append this structure to
+ * the execbuf if I915_EXEC_FENCE_ARRAY is set.
+ */
+struct drm_i915_gem_execbuffer_ext_timeline_fences {
+       struct i915_user_extension base;
+
+       /**
+        * Number of element in the handles_ptr & value_ptr arrays.
+        */
+       __u64 fence_count;
+
+       /**
+        * Pointer to an array of struct drm_i915_gem_exec_fence of length
+        * fence_count.
+        */
+       __u64 handles_ptr;
+
+       /**
+        * Pointer to an array of u64 values of length fence_count. Values
+        * must be 0 for a binary drm_syncobj. A Value of 0 for a timeline
+        * drm_syncobj is invalid as it turns a drm_syncobj into a binary one.
+        */
+       __u64 values_ptr;
+};
+
 struct drm_i915_gem_execbuffer2 {
        /**
         * List of gem_exec_object2 structs
@@ -1062,8 +1100,14 @@ struct drm_i915_gem_execbuffer2 {
        __u32 num_cliprects;
        /**
         * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY
-        * is not set.  If I915_EXEC_FENCE_ARRAY is set, then this is a
-        * struct drm_i915_gem_exec_fence *fences.
+        * & I915_EXEC_USE_EXTENSIONS are not set.
+        *
+        * If I915_EXEC_FENCE_ARRAY is set, then this is a pointer to an array
+        * of struct drm_i915_gem_exec_fence and num_cliprects is the length
+        * of the array.
+        *
+        * If I915_EXEC_USE_EXTENSIONS is set, then this is a pointer to a
+        * single struct i915_user_extension and num_cliprects is 0.
         */
        __u64 cliprects_ptr;
 #define I915_EXEC_RING_MASK              (0x3f)
@@ -1181,7 +1225,16 @@ struct drm_i915_gem_execbuffer2 {
  */
 #define I915_EXEC_FENCE_SUBMIT         (1 << 20)
 
-#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SUBMIT << 1))
+/*
+ * Setting I915_EXEC_USE_EXTENSIONS implies that
+ * drm_i915_gem_execbuffer2.cliprects_ptr is treated as a pointer to an linked
+ * list of i915_user_extension. Each i915_user_extension node is the base of a
+ * larger structure. The list of supported structures are listed in the
+ * drm_i915_gem_execbuffer_ext enum.
+ */
+#define I915_EXEC_USE_EXTENSIONS       (1 << 21)
+
+#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_USE_EXTENSIONS << 1))
 
 #define I915_EXEC_CONTEXT_ID_MASK      (0xffffffff)
 #define i915_execbuffer2_set_context_id(eb2, context) \
index 7875709ccfebff2a5903f73e753a015015729c5d..e5de60336938121f0584e0b43e9fc01fcb3d356c 100644 (file)
@@ -45,7 +45,6 @@ struct fscrypt_policy_v1 {
        __u8 flags;
        __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
 };
-#define fscrypt_policy fscrypt_policy_v1
 
 /*
  * Process-subscribed "logon" key description prefix and payload format.
@@ -156,9 +155,9 @@ struct fscrypt_get_key_status_arg {
        __u32 __out_reserved[13];
 };
 
-#define FS_IOC_SET_ENCRYPTION_POLICY           _IOR('f', 19, struct fscrypt_policy)
+#define FS_IOC_SET_ENCRYPTION_POLICY           _IOR('f', 19, struct fscrypt_policy_v1)
 #define FS_IOC_GET_ENCRYPTION_PWSALT           _IOW('f', 20, __u8[16])
-#define FS_IOC_GET_ENCRYPTION_POLICY           _IOW('f', 21, struct fscrypt_policy)
+#define FS_IOC_GET_ENCRYPTION_POLICY           _IOW('f', 21, struct fscrypt_policy_v1)
 #define FS_IOC_GET_ENCRYPTION_POLICY_EX                _IOWR('f', 22, __u8[9]) /* size + version */
 #define FS_IOC_ADD_ENCRYPTION_KEY              _IOWR('f', 23, struct fscrypt_add_key_arg)
 #define FS_IOC_REMOVE_ENCRYPTION_KEY           _IOWR('f', 24, struct fscrypt_remove_key_arg)
@@ -170,6 +169,7 @@ struct fscrypt_get_key_status_arg {
 
 /* old names; don't add anything new here! */
 #ifndef __KERNEL__
+#define fscrypt_policy                 fscrypt_policy_v1
 #define FS_KEY_DESCRIPTOR_SIZE         FSCRYPT_KEY_DESCRIPTOR_SIZE
 #define FS_POLICY_FLAGS_PAD_4          FSCRYPT_POLICY_FLAGS_PAD_4
 #define FS_POLICY_FLAGS_PAD_8          FSCRYPT_POLICY_FLAGS_PAD_8
index 7d8eced6f459b065c445ba8dcbc107f785dc24fa..ca41220b40b8b25c8f1044496f8024458768868b 100644 (file)
@@ -248,6 +248,8 @@ struct kvm_hyperv_exit {
 #define KVM_EXIT_IOAPIC_EOI       26
 #define KVM_EXIT_HYPERV           27
 #define KVM_EXIT_ARM_NISV         28
+#define KVM_EXIT_X86_RDMSR        29
+#define KVM_EXIT_X86_WRMSR        30
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 /* Emulate instruction failed. */
@@ -413,6 +415,17 @@ struct kvm_run {
                        __u64 esr_iss;
                        __u64 fault_ipa;
                } arm_nisv;
+               /* KVM_EXIT_X86_RDMSR / KVM_EXIT_X86_WRMSR */
+               struct {
+                       __u8 error; /* user -> kernel */
+                       __u8 pad[7];
+#define KVM_MSR_EXIT_REASON_INVAL      (1 << 0)
+#define KVM_MSR_EXIT_REASON_UNKNOWN    (1 << 1)
+#define KVM_MSR_EXIT_REASON_FILTER     (1 << 2)
+                       __u32 reason; /* kernel -> user */
+                       __u32 index; /* kernel -> user */
+                       __u64 data; /* kernel <-> user */
+               } msr;
                /* Fix the size of the union. */
                char padding[256];
        };
@@ -1037,6 +1050,9 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_SMALLER_MAXPHYADDR 185
 #define KVM_CAP_S390_DIAG318 186
 #define KVM_CAP_STEAL_TIME 187
+#define KVM_CAP_X86_USER_SPACE_MSR 188
+#define KVM_CAP_X86_MSR_FILTER 189
+#define KVM_CAP_ENFORCE_PV_FEATURE_CPUID 190
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1538,6 +1554,9 @@ struct kvm_pv_cmd {
 /* Available with KVM_CAP_S390_PROTECTED */
 #define KVM_S390_PV_COMMAND            _IOWR(KVMIO, 0xc5, struct kvm_pv_cmd)
 
+/* Available with KVM_CAP_X86_MSR_FILTER */
+#define KVM_X86_SET_MSR_FILTER _IOW(KVMIO,  0xc6, struct kvm_msr_filter)
+
 /* Secure Encrypted Virtualization command */
 enum sev_cmd_id {
        /* Guest initialization commands */
index 923cc162609c016dd6360d834b34abfe6e1ba459..f55bc680b5b0a45eefca46732e265a8bfe2f46aa 100644 (file)
@@ -27,6 +27,7 @@
 #define MAP_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
 #define MAP_HUGE_MASK  HUGETLB_FLAG_ENCODE_MASK
 
+#define MAP_HUGE_16KB  HUGETLB_FLAG_ENCODE_16KB
 #define MAP_HUGE_64KB  HUGETLB_FLAG_ENCODE_64KB
 #define MAP_HUGE_512KB HUGETLB_FLAG_ENCODE_512KB
 #define MAP_HUGE_1MB   HUGETLB_FLAG_ENCODE_1MB
index 96a0240f23fed37be9430b72d2f2d9ffd6d42237..dd8306ea336c19b695fa9a748c14f5ad92fe3e63 100644 (file)
@@ -16,6 +16,7 @@
 #define MS_REMOUNT     32      /* Alter flags of a mounted FS */
 #define MS_MANDLOCK    64      /* Allow mandatory locks on an FS */
 #define MS_DIRSYNC     128     /* Directory modifications are synchronous */
+#define MS_NOSYMFOLLOW 256     /* Do not follow symlinks */
 #define MS_NOATIME     1024    /* Do not update access times. */
 #define MS_NODIRATIME  2048    /* Do not update directory access times */
 #define MS_BIND                4096
index 3e5dcdd48a4998ddc3b59ee77b376d909e345e84..b95d3c485d27e10f5a1b04354a1bb4ba7cc41146 100644 (file)
@@ -1196,7 +1196,7 @@ union perf_mem_data_src {
 
 #define PERF_MEM_SNOOPX_FWD    0x01 /* forward */
 /* 1 free */
-#define PERF_MEM_SNOOPX_SHIFT  38
+#define PERF_MEM_SNOOPX_SHIFT  38
 
 /* locked instruction */
 #define PERF_MEM_LOCK_NA       0x01 /* not available */
index 07b4f8131e362bdc815f37cea0c9067a9464f256..7f0827705c9a461fcf0af8bf070a283f4bd708c1 100644 (file)
@@ -233,6 +233,15 @@ struct prctl_mm_map {
 #define PR_SET_TAGGED_ADDR_CTRL                55
 #define PR_GET_TAGGED_ADDR_CTRL                56
 # define PR_TAGGED_ADDR_ENABLE         (1UL << 0)
+/* MTE tag check fault modes */
+# define PR_MTE_TCF_SHIFT              1
+# define PR_MTE_TCF_NONE               (0UL << PR_MTE_TCF_SHIFT)
+# define PR_MTE_TCF_SYNC               (1UL << PR_MTE_TCF_SHIFT)
+# define PR_MTE_TCF_ASYNC              (2UL << PR_MTE_TCF_SHIFT)
+# define PR_MTE_TCF_MASK               (3UL << PR_MTE_TCF_SHIFT)
+/* MTE tag inclusion mask */
+# define PR_MTE_TAG_SHIFT              3
+# define PR_MTE_TAG_MASK               (0xffffUL << PR_MTE_TAG_SHIFT)
 
 /* Control reclaim behavior when allocating memory */
 #define PR_SET_IO_FLUSHER              57
index 75232185324abb8bf16521b525ed007306ab582f..c998860d7bbc4351c37c702ea69ea88a814b19cf 100644 (file)
 
 /* Set event fd for config interrupt*/
 #define VHOST_VDPA_SET_CONFIG_CALL     _IOW(VHOST_VIRTIO, 0x77, int)
+
+/* Get the valid iova range */
+#define VHOST_VDPA_GET_IOVA_RANGE      _IOR(VHOST_VIRTIO, 0x78, \
+                                            struct vhost_vdpa_iova_range)
 #endif
index 5f9abed3e2261a7de13753335c97717326b15ea4..55bd78b3496fb4da53f64b06192deb8ce09114d4 100644 (file)
@@ -146,6 +146,7 @@ GLOBAL_SYM_COUNT = $(shell readelf -s --wide $(BPF_IN_SHARED) | \
                           awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}' | \
                           sort -u | wc -l)
 VERSIONED_SYM_COUNT = $(shell readelf --dyn-syms --wide $(OUTPUT)libbpf.so | \
+                             sed 's/\[.*\]//' | \
                              awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}' | \
                              grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | sort -u | wc -l)
 
@@ -214,6 +215,7 @@ check_abi: $(OUTPUT)libbpf.so
                    awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}'|  \
                    sort -u > $(OUTPUT)libbpf_global_syms.tmp;           \
                readelf --dyn-syms --wide $(OUTPUT)libbpf.so |           \
+                   sed 's/\[.*\]//' |                                   \
                    awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}'|  \
                    grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 |             \
                    sort -u > $(OUTPUT)libbpf_versioned_syms.tmp;        \
index d9b385fe808c695ebd473ea27903da1f343f658a..10a4c4cd13cf7cf1e9fba70eb3dd46d3a8e4fc4f 100644 (file)
@@ -15,6 +15,9 @@
 static inline size_t hash_bits(size_t h, int bits)
 {
        /* shuffle bits and return requested number of upper bits */
+       if (bits == 0)
+               return 0;
+
 #if (__SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__)
        /* LP64 case */
        return (h * 11400714819323198485llu) >> (__SIZEOF_LONG_LONG__ * 8 - bits);
@@ -174,17 +177,17 @@ bool hashmap__find(const struct hashmap *map, const void *key, void **value);
  * @key: key to iterate entries for
  */
 #define hashmap__for_each_key_entry(map, cur, _key)                        \
-       for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\
-                                            map->cap_bits);                \
-                    map->buckets ? map->buckets[bkt] : NULL; });           \
+       for (cur = map->buckets                                             \
+                    ? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \
+                    : NULL;                                                \
             cur;                                                           \
             cur = cur->next)                                               \
                if (map->equal_fn(cur->key, (_key), map->ctx))
 
 #define hashmap__for_each_key_entry_safe(map, cur, tmp, _key)              \
-       for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\
-                                            map->cap_bits);                \
-                    cur = map->buckets ? map->buckets[bkt] : NULL; });     \
+       for (cur = map->buckets                                             \
+                    ? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \
+                    : NULL;                                                \
             cur && ({ tmp = cur->next; true; });                           \
             cur = tmp)                                                     \
                if (map->equal_fn(cur->key, (_key), map->ctx))
index 3130341170706540937e941a484fa3447135825a..28baee7ba1ca862b354c216f4cf1f5bc2d7ddaa8 100644 (file)
@@ -560,8 +560,6 @@ bpf_object__init_prog(struct bpf_object *obj, struct bpf_program *prog,
                      const char *name, size_t sec_idx, const char *sec_name,
                      size_t sec_off, void *insn_data, size_t insn_data_sz)
 {
-       int i;
-
        if (insn_data_sz == 0 || insn_data_sz % BPF_INSN_SZ || sec_off % BPF_INSN_SZ) {
                pr_warn("sec '%s': corrupted program '%s', offset %zu, size %zu\n",
                        sec_name, name, sec_off, insn_data_sz);
@@ -600,13 +598,6 @@ bpf_object__init_prog(struct bpf_object *obj, struct bpf_program *prog,
                goto errout;
        memcpy(prog->insns, insn_data, insn_data_sz);
 
-       for (i = 0; i < prog->insns_cnt; i++) {
-               if (insn_is_subprog_call(&prog->insns[i])) {
-                       obj->has_subcalls = true;
-                       break;
-               }
-       }
-
        return 0;
 errout:
        pr_warn("sec '%s': failed to allocate memory for prog '%s'\n", sec_name, name);
@@ -3280,7 +3271,19 @@ bpf_object__find_program_by_title(const struct bpf_object *obj,
 static bool prog_is_subprog(const struct bpf_object *obj,
                            const struct bpf_program *prog)
 {
-       return prog->sec_idx == obj->efile.text_shndx && obj->has_subcalls;
+       /* For legacy reasons, libbpf supports an entry-point BPF programs
+        * without SEC() attribute, i.e., those in the .text section. But if
+        * there are 2 or more such programs in the .text section, they all
+        * must be subprograms called from entry-point BPF programs in
+        * designated SEC()'tions, otherwise there is no way to distinguish
+        * which of those programs should be loaded vs which are a subprogram.
+        * Similarly, if there is a function/program in .text and at least one
+        * other BPF program with custom SEC() attribute, then we just assume
+        * .text programs are subprograms (even if they are not called from
+        * other programs), because libbpf never explicitly supported mixing
+        * SEC()-designated BPF programs and .text entry-point BPF programs.
+        */
+       return prog->sec_idx == obj->efile.text_shndx && obj->nr_programs > 1;
 }
 
 struct bpf_program *
index e3c98c007825cf10c8fd4b08452d720166d15bb0..9bc537d0b92da7953c409e5e5bb08f8d21baf361 100644 (file)
@@ -891,13 +891,16 @@ int xsk_umem__delete(struct xsk_umem *umem)
 void xsk_socket__delete(struct xsk_socket *xsk)
 {
        size_t desc_sz = sizeof(struct xdp_desc);
-       struct xsk_ctx *ctx = xsk->ctx;
        struct xdp_mmap_offsets off;
+       struct xsk_umem *umem;
+       struct xsk_ctx *ctx;
        int err;
 
        if (!xsk)
                return;
 
+       ctx = xsk->ctx;
+       umem = ctx->umem;
        if (ctx->prog_fd != -1) {
                xsk_delete_bpf_maps(xsk);
                close(ctx->prog_fd);
@@ -917,11 +920,11 @@ void xsk_socket__delete(struct xsk_socket *xsk)
 
        xsk_put_ctx(ctx);
 
-       ctx->umem->refcount--;
+       umem->refcount--;
        /* Do not close an fd that also has an associated umem connected
         * to it.
         */
-       if (xsk->fd != ctx->umem->fd)
+       if (xsk->fd != umem->fd)
                close(xsk->fd);
        free(xsk);
 }
index 6890fc4b063a4a6021ad8530136745130349d483..ce8516e4de34fa60ee50c3fedc0190c625f8f3ac 100644 (file)
@@ -749,6 +749,7 @@ else
   PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
   PERL_EMBED_CCOPTS = $(shell perl -MExtUtils::Embed -e ccopts 2>/dev/null)
   PERL_EMBED_CCOPTS := $(filter-out -specs=%,$(PERL_EMBED_CCOPTS))
+  PERL_EMBED_CCOPTS := $(filter-out -flto=auto -ffat-lto-objects, $(PERL_EMBED_CCOPTS))
   PERL_EMBED_LDOPTS := $(filter-out -specs=%,$(PERL_EMBED_LDOPTS))
   FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
 
index 347809649ba28fa15be86511d563ff9d427ecaea..379819244b91d275b2c98f7ff38a59049c24b42a 100644 (file)
 437    common  openat2                 sys_openat2
 438    common  pidfd_getfd             sys_pidfd_getfd
 439    common  faccessat2              sys_faccessat2
+440    common  process_madvise         sys_process_madvise
 
 #
-# x32-specific system call numbers start at 512 to avoid cache impact
-# for native 64-bit operation. The __x32_compat_sys stubs are created
-# on-the-fly for compat_sys_*() compatibility system calls if X86_X32
-# is defined.
+# Due to a historical design error, certain syscalls are numbered differently
+# in x32 as compared to native x86_64.  These syscalls have numbers 512-547.
+# Do not add new syscalls to this range.  Numbers 548 and above are available
+# for non-x32 use.
 #
 512    x32     rt_sigaction            compat_sys_rt_sigaction
 513    x32     rt_sigreturn            compat_sys_x32_rt_sigreturn
 545    x32     execveat                compat_sys_execveat
 546    x32     preadv2                 compat_sys_preadv64v2
 547    x32     pwritev2                compat_sys_pwritev64v2
+# This is the end of the legacy x32 range.  Numbers 548 and above are
+# not special and are not to be used for x32-specific syscalls.
index 4e40402a4f81ca869f101a96af79632c741db59f..478078fb0f221737be142edff804966b055caf5e 100644 (file)
@@ -38,6 +38,13 @@ static int sample_ustack(struct perf_sample *sample,
        stack_size = stack_size > STACK_SIZE ? STACK_SIZE : stack_size;
 
        memcpy(buf, (void *) sp, stack_size);
+#ifdef MEMORY_SANITIZER
+       /*
+        * Copying the stack may copy msan poison, avoid false positives in the
+        * unwinder by removing the poison here.
+        */
+       __msan_unpoison(buf, stack_size);
+#endif
        stack->data = (char *) buf;
        stack->size = stack_size;
        return 0;
index 9ad015a1e20247a001e115284def3902e036bf67..6eb45a2aa8db39a96a238a276121a983788ffec3 100644 (file)
@@ -2,6 +2,9 @@
 
 /* Various wrappers to make the kernel .S file build in user-space: */
 
+// memcpy_orig and memcpy_erms are being defined as SYM_L_LOCAL but we need it
+#define SYM_FUNC_START_LOCAL(name)                      \
+        SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN)
 #define memcpy MEMCPY /* don't hide glibc's memcpy() */
 #define altinstr_replacement text
 #define globl p2align 4; .globl
index d550bd5261629a07575c55814d7d8b87938afd30..6f093c483842eaa2cafb9995400b7e3e18924b68 100644 (file)
@@ -1,4 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
+// memset_orig and memset_erms are being defined as SYM_L_LOCAL but we need it
+#define SYM_FUNC_START_LOCAL(name)                      \
+        SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN)
 #define memset MEMSET /* don't hide glibc's memset() */
 #define altinstr_replacement text
 #define globl p2align 4; .globl
index 584e2e1a3793a1ebd07b0383d42c2d8dc4c944ef..cefc71506409fa85d14a6a6dd44edfc07eaf011a 100644 (file)
@@ -1222,8 +1222,10 @@ static int __cmd_diff(void)
                if (compute == COMPUTE_STREAM) {
                        d->evlist_streams = evlist__create_streams(
                                                d->session->evlist, 5);
-                       if (!d->evlist_streams)
+                       if (!d->evlist_streams) {
+                               ret = -ENOMEM;
                                goto out_delete;
+                       }
                }
        }
 
index 452a75fe68e5fd3587e3cb3e99edde720fb19b33..0462dc8db2e38a8cfe4daba8947e07f1035ae478 100644 (file)
@@ -779,25 +779,15 @@ static int __cmd_inject(struct perf_inject *inject)
                        dsos__hit_all(session);
                /*
                 * The AUX areas have been removed and replaced with
-                * synthesized hardware events, so clear the feature flag and
-                * remove the evsel.
+                * synthesized hardware events, so clear the feature flag.
                 */
                if (inject->itrace_synth_opts.set) {
-                       struct evsel *evsel;
-
                        perf_header__clear_feat(&session->header,
                                                HEADER_AUXTRACE);
                        if (inject->itrace_synth_opts.last_branch ||
                            inject->itrace_synth_opts.add_last_branch)
                                perf_header__set_feat(&session->header,
                                                      HEADER_BRANCH_STACK);
-                       evsel = perf_evlist__id2evsel_strict(session->evlist,
-                                                            inject->aux_id);
-                       if (evsel) {
-                               pr_debug("Deleting %s\n", evsel__name(evsel));
-                               evlist__remove(session->evlist, evsel);
-                               evsel__delete(evsel);
-                       }
                }
                session->header.data_offset = output_data_offset;
                session->header.data_size = inject->bytes_written;
index f0a1dbacb46c718df23086fa57cafb680538bcd0..a2f1e53f37a7af0c558cb00fc753fc8fb3462e32 100644 (file)
@@ -406,7 +406,7 @@ static int report_lock_acquire_event(struct evsel *evsel,
        struct lock_seq_stat *seq;
        const char *name = evsel__strval(evsel, sample, "name");
        u64 tmp  = evsel__intval(evsel, sample, "lockdep_addr");
-       int flag = evsel__intval(evsel, sample, "flag");
+       int flag = evsel__intval(evsel, sample, "flags");
 
        memcpy(&addr, &tmp, sizeof(void *));
 
@@ -621,7 +621,7 @@ static int report_lock_release_event(struct evsel *evsel,
        case SEQ_STATE_READ_ACQUIRED:
                seq->read_count--;
                BUG_ON(seq->read_count < 0);
-               if (!seq->read_count) {
+               if (seq->read_count) {
                        ls->nr_release++;
                        goto end;
                }
index 44a75f234db17c6cb18e133521e0d0d9f112ec03..de80534473afa5fe9da8af543b438fcebd540bf3 100644 (file)
@@ -4639,9 +4639,9 @@ do_concat:
        err = 0;
 
        if (lists[0]) {
-               struct option o = OPT_CALLBACK('e', "event", &trace->evlist, "event",
-                                              "event selector. use 'perf list' to list available events",
-                                              parse_events_option);
+               struct option o = {
+                       .value = &trace->evlist,
+               };
                err = parse_events_option(&o, lists[0], 0);
        }
 out:
@@ -4655,9 +4655,12 @@ static int trace__parse_cgroups(const struct option *opt, const char *str, int u
 {
        struct trace *trace = opt->value;
 
-       if (!list_empty(&trace->evlist->core.entries))
-               return parse_cgroups(opt, str, unset);
-
+       if (!list_empty(&trace->evlist->core.entries)) {
+               struct option o = {
+                       .value = &trace->evlist,
+               };
+               return parse_cgroups(&o, str, unset);
+       }
        trace->cgroup = evlist__findnew_cgroup(trace->evlist, str);
 
        return 0;
index de3193552277c1ac892ed61daa6f6bf99fef3235..00f4fcffa81584bab4756537821551ba5dd725f3 100644 (file)
     },
     {
         "BriefDescription": "Average external Memory Bandwidth Use for reads and writes [GB / sec]",
-        "MetricExpr": "( 64 * ( uncore_imc@cas_count_read@ + uncore_imc@cas_count_write@ ) / 1000000000 ) / duration_time",
+        "MetricExpr": "( ( ( uncore_imc@cas_count_read@ + uncore_imc@cas_count_write@ ) * 1048576 ) / 1000000000 ) / duration_time",
         "MetricGroup": "Memory_BW;SoC",
         "MetricName": "DRAM_BW_Use"
     },
index f31794d3b9261e78b8edda6e20431e8b868f3d4d..0dd8b13b5cfb07ee2494512c18b619da038e58d7 100644 (file)
     },
     {
         "BriefDescription": "Average external Memory Bandwidth Use for reads and writes [GB / sec]",
-        "MetricExpr": "( 64 * ( uncore_imc@cas_count_read@ + uncore_imc@cas_count_write@ ) / 1000000000 ) / duration_time",
+        "MetricExpr": "( ( ( uncore_imc@cas_count_read@ + uncore_imc@cas_count_write@ ) * 1048576 ) / 1000000000 ) / duration_time",
         "MetricGroup": "Memory_BW;SoC",
         "MetricName": "DRAM_BW_Use"
     },
index 2491d167bf764f13d20a6f40e37068f0b7f30e6b..83638097c3bc19f8b9fc9e498432238548798aea 100644 (file)
@@ -95,7 +95,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
        return strcmp((const char *) symbol, funcs[idx]);
 }
 
-__no_tail_call noinline int test_dwarf_unwind__thread(struct thread *thread)
+noinline int test_dwarf_unwind__thread(struct thread *thread)
 {
        struct perf_sample sample;
        unsigned long cnt = 0;
@@ -126,7 +126,7 @@ __no_tail_call noinline int test_dwarf_unwind__thread(struct thread *thread)
 
 static int global_unwind_retval = -INT_MAX;
 
-__no_tail_call noinline int test_dwarf_unwind__compare(void *p1, void *p2)
+noinline int test_dwarf_unwind__compare(void *p1, void *p2)
 {
        /* Any possible value should be 'thread' */
        struct thread *thread = *(struct thread **)p1;
@@ -145,7 +145,7 @@ __no_tail_call noinline int test_dwarf_unwind__compare(void *p1, void *p2)
        return p1 - p2;
 }
 
-__no_tail_call noinline int test_dwarf_unwind__krava_3(struct thread *thread)
+noinline int test_dwarf_unwind__krava_3(struct thread *thread)
 {
        struct thread *array[2] = {thread, thread};
        void *fp = &bsearch;
@@ -164,12 +164,12 @@ __no_tail_call noinline int test_dwarf_unwind__krava_3(struct thread *thread)
        return global_unwind_retval;
 }
 
-__no_tail_call noinline int test_dwarf_unwind__krava_2(struct thread *thread)
+noinline int test_dwarf_unwind__krava_2(struct thread *thread)
 {
        return test_dwarf_unwind__krava_3(thread);
 }
 
-__no_tail_call noinline int test_dwarf_unwind__krava_1(struct thread *thread)
+noinline int test_dwarf_unwind__krava_1(struct thread *thread)
 {
        return test_dwarf_unwind__krava_2(thread);
 }
index 8d84fdbed6a6041193cf83f36252b0526e1a9cf7..18fde2f179cd22062367839393b01e8f3b8da22c 100755 (executable)
@@ -44,7 +44,7 @@ perf_script_branch_samples() {
        #   touch  6512          1         branches:u:      ffffb22082e0 strcmp+0xa0 (/lib/aarch64-linux-gnu/ld-2.27.so)
        #   touch  6512          1         branches:u:      ffffb2208320 strcmp+0xe0 (/lib/aarch64-linux-gnu/ld-2.27.so)
        perf script -F,-time -i ${perfdata} | \
-               egrep " +$1 +[0-9]+ .* +branches:([u|k]:)? +"
+               egrep " +$1 +[0-9]+ .* +branches:(.*:)? +"
 }
 
 perf_report_branch_samples() {
@@ -105,7 +105,7 @@ arm_cs_iterate_devices() {
                #     `> device_name = 'tmc_etf0'
                device_name=$(basename $path)
 
-               if is_device_sink $path $devce_name; then
+               if is_device_sink $path $device_name; then
 
                        record_touch_file $device_name $2 &&
                        perf_script_branch_samples touch &&
index a07626f072087d78738a81139a063597ccf0e02b..b0e1880cf992b15150ac645595aba7e86d4367e1 100644 (file)
@@ -2963,7 +2963,7 @@ static int perf_evsel__hists_browse(struct evsel *evsel, int nr_events,
        struct popup_action actions[MAX_OPTIONS];
        int nr_options = 0;
        int key = -1;
-       char buf[64];
+       char buf[128];
        int delay_secs = hbt ? hbt->refresh : 0;
 
 #define HIST_BROWSER_HELP_COMMON                                       \
index 8763772f1095e9774cfa30cafadaab6b180ac0c1..6b410c3d52dca948253eca99716536c4761a809a 100644 (file)
@@ -102,6 +102,8 @@ int build_id__sprintf(const struct build_id *build_id, char *bf)
        const u8 *raw = build_id->data;
        size_t i;
 
+       bf[0] = 0x0;
+
        for (i = 0; i < build_id->size; ++i) {
                sprintf(bid, "%02x", *raw);
                ++raw;
index aa898014ad12f5d6ca315e6b9cff7f85e848ce8b..7b2d471a6419dbfa1aecd5c0c9ce67a9766a0cb7 100644 (file)
@@ -356,9 +356,25 @@ bool die_is_signed_type(Dwarf_Die *tp_die)
 bool die_is_func_def(Dwarf_Die *dw_die)
 {
        Dwarf_Attribute attr;
+       Dwarf_Addr addr = 0;
+
+       if (dwarf_tag(dw_die) != DW_TAG_subprogram)
+               return false;
+
+       if (dwarf_attr(dw_die, DW_AT_declaration, &attr))
+               return false;
 
-       return (dwarf_tag(dw_die) == DW_TAG_subprogram &&
-               dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL);
+       /*
+        * DW_AT_declaration can be lost from function declaration
+        * by gcc's bug #97060.
+        * So we need to check this subprogram DIE has DW_AT_inline
+        * or an entry address.
+        */
+       if (!dwarf_attr(dw_die, DW_AT_inline, &attr) &&
+           die_entrypc(dw_die, &addr) < 0)
+               return false;
+
+       return true;
 }
 
 /**
@@ -373,6 +389,7 @@ bool die_is_func_def(Dwarf_Die *dw_die)
 int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr)
 {
        Dwarf_Addr base, end;
+       Dwarf_Attribute attr;
 
        if (!addr)
                return -EINVAL;
@@ -380,6 +397,13 @@ int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr)
        if (dwarf_entrypc(dw_die, addr) == 0)
                return 0;
 
+       /*
+        *  Since the dwarf_ranges() will return 0 if there is no
+        * DW_AT_ranges attribute, we should check it first.
+        */
+       if (!dwarf_attr(dw_die, DW_AT_ranges, &attr))
+               return -ENOENT;
+
        return dwarf_ranges(dw_die, 0, &base, addr, &end) < 0 ? -ENOENT : 0;
 }
 
index a405dad068f59dd6ab96a40759adc683fdcbf2c2..3c20b126d60d869aa136b24d4b01c93d6302938e 100644 (file)
@@ -15,6 +15,9 @@
 /* make sure libbpf doesn't use kernel-only integer typedefs */
 #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
 
+/* prevent accidental re-addition of reallocarray() */
+#pragma GCC poison reallocarray
+
 /* start with 4 buckets */
 #define HASHMAP_MIN_CAP_BITS 2
 
index e0af36b0e5d839e2fdd57f0f921c8ba17e4a3629..10a4c4cd13cf7cf1e9fba70eb3dd46d3a8e4fc4f 100644 (file)
@@ -15,6 +15,9 @@
 static inline size_t hash_bits(size_t h, int bits)
 {
        /* shuffle bits and return requested number of upper bits */
+       if (bits == 0)
+               return 0;
+
 #if (__SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__)
        /* LP64 case */
        return (h * 11400714819323198485llu) >> (__SIZEOF_LONG_LONG__ * 8 - bits);
@@ -25,6 +28,18 @@ static inline size_t hash_bits(size_t h, int bits)
 #endif
 }
 
+/* generic C-string hashing function */
+static inline size_t str_hash(const char *s)
+{
+       size_t h = 0;
+
+       while (*s) {
+               h = h * 31 + *s;
+               s++;
+       }
+       return h;
+}
+
 typedef size_t (*hashmap_hash_fn)(const void *key, void *ctx);
 typedef bool (*hashmap_equal_fn)(const void *key1, const void *key2, void *ctx);
 
@@ -162,17 +177,17 @@ bool hashmap__find(const struct hashmap *map, const void *key, void **value);
  * @key: key to iterate entries for
  */
 #define hashmap__for_each_key_entry(map, cur, _key)                        \
-       for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\
-                                            map->cap_bits);                \
-                    map->buckets ? map->buckets[bkt] : NULL; });           \
+       for (cur = map->buckets                                             \
+                    ? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \
+                    : NULL;                                                \
             cur;                                                           \
             cur = cur->next)                                               \
                if (map->equal_fn(cur->key, (_key), map->ctx))
 
 #define hashmap__for_each_key_entry_safe(map, cur, tmp, _key)              \
-       for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\
-                                            map->cap_bits);                \
-                    cur = map->buckets ? map->buckets[bkt] : NULL; });     \
+       for (cur = map->buckets                                             \
+                    ? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \
+                    : NULL;                                                \
             cur && ({ tmp = cur->next; true; });                           \
             cur = tmp)                                                     \
                if (map->equal_fn(cur->key, (_key), map->ctx))
index b8a5159361b4123651509d9510e851a51f6c1a42..5acf053fca7d418399bc35567d19c22e88652cb5 100644 (file)
@@ -25,6 +25,7 @@
 
 /* SYM_L_* -- linkage of symbols */
 #define SYM_L_GLOBAL(name)                     .globl name
+#define SYM_L_WEAK(name)                       .weak name
 #define SYM_L_LOCAL(name)                      /* nothing */
 
 #define ALIGN __ALIGN
        SYM_END(name, SYM_T_FUNC)
 #endif
 
+/* SYM_FUNC_START_WEAK -- use for weak functions */
+#ifndef SYM_FUNC_START_WEAK
+#define SYM_FUNC_START_WEAK(name)                      \
+       SYM_START(name, SYM_L_WEAK, SYM_A_ALIGN)
+#endif
+
 /*
  * SYM_FUNC_END -- the end of SYM_FUNC_START_LOCAL, SYM_FUNC_START,
  * SYM_FUNC_START_WEAK, ...
index 7d4194ffc5b081bb805f259737f64057f5527f68..15385ea00190fe21125b748c7d11801c14a3ce22 100644 (file)
@@ -786,11 +786,20 @@ static int machine__process_ksymbol_unregister(struct machine *machine,
                                               union perf_event *event,
                                               struct perf_sample *sample __maybe_unused)
 {
+       struct symbol *sym;
        struct map *map;
 
        map = maps__find(&machine->kmaps, event->ksymbol.addr);
-       if (map)
+       if (!map)
+               return 0;
+
+       if (map != machine->vmlinux_map)
                maps__remove(&machine->kmaps, map);
+       else {
+               sym = dso__find_symbol(map->dso, map->map_ip(map, map->start));
+               if (sym)
+                       dso__delete_symbol(map->dso, sym);
+       }
 
        return 0;
 }
index 2c4061035f7771ad91269f455bdcf63fce83bb50..76dd349aa48d8e90ae76f8bb876eec307f45b05c 100644 (file)
@@ -1885,8 +1885,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
        if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
                return DWARF_CB_OK;
 
-       if (die_is_func_def(sp_die) &&
-           die_match_name(sp_die, lr->function)) {
+       if (die_match_name(sp_die, lr->function) && die_is_func_def(sp_die)) {
                lf->fname = dwarf_decl_file(sp_die);
                dwarf_decl_line(sp_die, &lr->offset);
                pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
index 7cbd024e3e634433a22b105d746d147c69a66153..c83c2c6564e010895845a243f564750b15789eba 100644 (file)
@@ -1592,7 +1592,6 @@ static void _free_command_line(wchar_t **command_line, int num)
 static int python_start_script(const char *script, int argc, const char **argv)
 {
        struct tables *tables = &tables_global;
-       PyMODINIT_FUNC (*initfunc)(void);
 #if PY_MAJOR_VERSION < 3
        const char **command_line;
 #else
@@ -1607,20 +1606,18 @@ static int python_start_script(const char *script, int argc, const char **argv)
        FILE *fp;
 
 #if PY_MAJOR_VERSION < 3
-       initfunc = initperf_trace_context;
        command_line = malloc((argc + 1) * sizeof(const char *));
        command_line[0] = script;
        for (i = 1; i < argc + 1; i++)
                command_line[i] = argv[i - 1];
+       PyImport_AppendInittab(name, initperf_trace_context);
 #else
-       initfunc = PyInit_perf_trace_context;
        command_line = malloc((argc + 1) * sizeof(wchar_t *));
        command_line[0] = Py_DecodeLocale(script, NULL);
        for (i = 1; i < argc + 1; i++)
                command_line[i] = Py_DecodeLocale(argv[i - 1], NULL);
+       PyImport_AppendInittab(name, PyInit_perf_trace_context);
 #endif
-
-       PyImport_AppendInittab(name, initfunc);
        Py_Initialize();
 
 #if PY_MAJOR_VERSION < 3
index 7a5f03764702bfb56b470e5eb7a6958d2a0ec387..098080287c687697768e4fb27fb2ced4fe1e38a8 100644 (file)
@@ -595,6 +595,7 @@ static void perf_event__mmap2_swap(union perf_event *event,
        event->mmap2.maj   = bswap_32(event->mmap2.maj);
        event->mmap2.min   = bswap_32(event->mmap2.min);
        event->mmap2.ino   = bswap_64(event->mmap2.ino);
+       event->mmap2.ino_generation = bswap_64(event->mmap2.ino_generation);
 
        if (sample_id_all) {
                void *data = &event->mmap2.filename;
@@ -710,6 +711,18 @@ static void perf_event__namespaces_swap(union perf_event *event,
                swap_sample_id_all(event, &event->namespaces.link_info[i]);
 }
 
+static void perf_event__cgroup_swap(union perf_event *event, bool sample_id_all)
+{
+       event->cgroup.id = bswap_64(event->cgroup.id);
+
+       if (sample_id_all) {
+               void *data = &event->cgroup.path;
+
+               data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));
+               swap_sample_id_all(event, data);
+       }
+}
+
 static u8 revbyte(u8 b)
 {
        int rev = (b >> 4) | ((b & 0xf) << 4);
@@ -952,6 +965,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
        [PERF_RECORD_SWITCH]              = perf_event__switch_swap,
        [PERF_RECORD_SWITCH_CPU_WIDE]     = perf_event__switch_swap,
        [PERF_RECORD_NAMESPACES]          = perf_event__namespaces_swap,
+       [PERF_RECORD_CGROUP]              = perf_event__cgroup_swap,
        [PERF_RECORD_TEXT_POKE]           = perf_event__text_poke_swap,
        [PERF_RECORD_HEADER_ATTR]         = perf_event__hdr_attr_swap,
        [PERF_RECORD_HEADER_EVENT_TYPE]   = perf_event__event_type_swap,
index 4b57c0c076323ceac2909dd78c031e376f86ed24..a963b5b8eb72409152596d6b33f0d961aeb1aa40 100644 (file)
@@ -324,13 +324,10 @@ static int first_shadow_cpu(struct perf_stat_config *config,
        struct evlist *evlist = evsel->evlist;
        int i;
 
-       if (!config->aggr_get_id)
-               return 0;
-
        if (config->aggr_mode == AGGR_NONE)
                return id;
 
-       if (config->aggr_mode == AGGR_GLOBAL)
+       if (!config->aggr_get_id)
                return 0;
 
        for (i = 0; i < evsel__nr_cpus(evsel); i++) {
index 6138866665df0b105934c7e284e58139eceee19a..0d14abdf3d722f63031af608978891139d76e226 100644 (file)
@@ -515,6 +515,13 @@ void dso__insert_symbol(struct dso *dso, struct symbol *sym)
        }
 }
 
+void dso__delete_symbol(struct dso *dso, struct symbol *sym)
+{
+       rb_erase_cached(&sym->rb_node, &dso->symbols);
+       symbol__delete(sym);
+       dso__reset_find_symbol_cache(dso);
+}
+
 struct symbol *dso__find_symbol(struct dso *dso, u64 addr)
 {
        if (dso->last_find_result.addr != addr || dso->last_find_result.symbol == NULL) {
index f4801c488def850ba2da730925a494312f18795e..954d6a049ee2386fba1b648065e01117d6284b3c 100644 (file)
@@ -131,6 +131,8 @@ int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map);
 
 void dso__insert_symbol(struct dso *dso,
                        struct symbol *sym);
+void dso__delete_symbol(struct dso *dso,
+                       struct symbol *sym);
 
 struct symbol *dso__find_symbol(struct dso *dso, u64 addr);
 struct symbol *dso__find_symbol_by_name(struct dso *dso, const char *name);
index 8a23391558cf6bc4f1220d8e452d69c2ad53c853..d9c624377da73a0c8d544001db5af0a5319cda1f 100644 (file)
@@ -563,6 +563,9 @@ int perf_event__synthesize_cgroups(struct perf_tool *tool,
        char cgrp_root[PATH_MAX];
        size_t mount_len;  /* length of mount point in the path */
 
+       if (!tool || !tool->cgroup_events)
+               return 0;
+
        if (cgroupfs_find_mountpoint(cgrp_root, PATH_MAX, "perf_event") < 0) {
                pr_debug("cannot find cgroup mount point\n");
                return -1;
index 2b6551269e431f0aa4e7688b81a585f7b470cdc4..f3e3c94ab9bd56f88a6ed03ad888d48ba4b3eab5 100644 (file)
@@ -12,11 +12,12 @@ turbostat : turbostat.c
 override CFLAGS +=     -O2 -Wall -I../../../include
 override CFLAGS +=     -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"'
 override CFLAGS +=     -DINTEL_FAMILY_HEADER='"../../../../arch/x86/include/asm/intel-family.h"'
+override CFLAGS +=     -D_FILE_OFFSET_BITS=64
 override CFLAGS +=     -D_FORTIFY_SOURCE=2
 
 %: %.c
        @mkdir -p $(BUILD_OUTPUT)
-       $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ $(LDFLAGS) -lcap
+       $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ $(LDFLAGS) -lcap -lrt
 
 .PHONY : clean
 clean :
index a6db83a88e852c40024f42d46f5c55fa3dbfd446..f6b7e85b121ce1c8dacf19f14f0727aeea59b505 100644 (file)
@@ -335,7 +335,7 @@ that they count at TSC rate, which is true on all processors tested to date.
 
 .SH REFERENCES
 Volume 3B: System Programming Guide"
-http://www.intel.com/products/processor/manuals/
+https://www.intel.com/products/processor/manuals/
 
 .SH FILES
 .ta
index 33b370865d16da6f2d6c966183d39a6cecbeed8d..f3a1746f7f45448c2f6f9244e4b87ce6ce47b4cd 100644 (file)
@@ -79,6 +79,7 @@ unsigned long long  gfx_cur_rc6_ms;
 unsigned long long cpuidle_cur_cpu_lpi_us;
 unsigned long long cpuidle_cur_sys_lpi_us;
 unsigned int gfx_cur_mhz;
+unsigned int gfx_act_mhz;
 unsigned int tcc_activation_temp;
 unsigned int tcc_activation_temp_override;
 double rapl_power_units, rapl_time_units;
@@ -210,13 +211,14 @@ struct pkg_data {
        unsigned long long pkg_both_core_gfxe_c0;
        long long gfx_rc6_ms;
        unsigned int gfx_mhz;
+       unsigned int gfx_act_mhz;
        unsigned int package_id;
-       unsigned int energy_pkg;        /* MSR_PKG_ENERGY_STATUS */
-       unsigned int energy_dram;       /* MSR_DRAM_ENERGY_STATUS */
-       unsigned int energy_cores;      /* MSR_PP0_ENERGY_STATUS */
-       unsigned int energy_gfx;        /* MSR_PP1_ENERGY_STATUS */
-       unsigned int rapl_pkg_perf_status;      /* MSR_PKG_PERF_STATUS */
-       unsigned int rapl_dram_perf_status;     /* MSR_DRAM_PERF_STATUS */
+       unsigned long long energy_pkg;  /* MSR_PKG_ENERGY_STATUS */
+       unsigned long long energy_dram; /* MSR_DRAM_ENERGY_STATUS */
+       unsigned long long energy_cores;        /* MSR_PP0_ENERGY_STATUS */
+       unsigned long long energy_gfx;  /* MSR_PP1_ENERGY_STATUS */
+       unsigned long long rapl_pkg_perf_status;        /* MSR_PKG_PERF_STATUS */
+       unsigned long long rapl_dram_perf_status;       /* MSR_DRAM_PERF_STATUS */
        unsigned int pkg_temp_c;
        unsigned long long counter[MAX_ADDED_COUNTERS];
 } *package_even, *package_odd;
@@ -259,6 +261,113 @@ struct msr_counter {
 #define        SYSFS_PERCPU    (1 << 1)
 };
 
+/*
+ * The accumulated sum of MSR is defined as a monotonic
+ * increasing MSR, it will be accumulated periodically,
+ * despite its register's bit width.
+ */
+enum {
+       IDX_PKG_ENERGY,
+       IDX_DRAM_ENERGY,
+       IDX_PP0_ENERGY,
+       IDX_PP1_ENERGY,
+       IDX_PKG_PERF,
+       IDX_DRAM_PERF,
+       IDX_COUNT,
+};
+
+int get_msr_sum(int cpu, off_t offset, unsigned long long *msr);
+
+struct msr_sum_array {
+       /* get_msr_sum() = sum + (get_msr() - last) */
+       struct {
+               /*The accumulated MSR value is updated by the timer*/
+               unsigned long long sum;
+               /*The MSR footprint recorded in last timer*/
+               unsigned long long last;
+       } entries[IDX_COUNT];
+};
+
+/* The percpu MSR sum array.*/
+struct msr_sum_array *per_cpu_msr_sum;
+
+int idx_to_offset(int idx)
+{
+       int offset;
+
+       switch (idx) {
+       case IDX_PKG_ENERGY:
+               offset = MSR_PKG_ENERGY_STATUS;
+               break;
+       case IDX_DRAM_ENERGY:
+               offset = MSR_DRAM_ENERGY_STATUS;
+               break;
+       case IDX_PP0_ENERGY:
+               offset = MSR_PP0_ENERGY_STATUS;
+               break;
+       case IDX_PP1_ENERGY:
+               offset = MSR_PP1_ENERGY_STATUS;
+               break;
+       case IDX_PKG_PERF:
+               offset = MSR_PKG_PERF_STATUS;
+               break;
+       case IDX_DRAM_PERF:
+               offset = MSR_DRAM_PERF_STATUS;
+               break;
+       default:
+               offset = -1;
+       }
+       return offset;
+}
+
+int offset_to_idx(int offset)
+{
+       int idx;
+
+       switch (offset) {
+       case MSR_PKG_ENERGY_STATUS:
+               idx = IDX_PKG_ENERGY;
+               break;
+       case MSR_DRAM_ENERGY_STATUS:
+               idx = IDX_DRAM_ENERGY;
+               break;
+       case MSR_PP0_ENERGY_STATUS:
+               idx = IDX_PP0_ENERGY;
+               break;
+       case MSR_PP1_ENERGY_STATUS:
+               idx = IDX_PP1_ENERGY;
+               break;
+       case MSR_PKG_PERF_STATUS:
+               idx = IDX_PKG_PERF;
+               break;
+       case MSR_DRAM_PERF_STATUS:
+               idx = IDX_DRAM_PERF;
+               break;
+       default:
+               idx = -1;
+       }
+       return idx;
+}
+
+int idx_valid(int idx)
+{
+       switch (idx) {
+       case IDX_PKG_ENERGY:
+               return do_rapl & RAPL_PKG;
+       case IDX_DRAM_ENERGY:
+               return do_rapl & RAPL_DRAM;
+       case IDX_PP0_ENERGY:
+               return do_rapl & RAPL_CORES_ENERGY_STATUS;
+       case IDX_PP1_ENERGY:
+               return do_rapl & RAPL_GFX;
+       case IDX_PKG_PERF:
+               return do_rapl & RAPL_PKG_PERF_STATUS;
+       case IDX_DRAM_PERF:
+               return do_rapl & RAPL_DRAM_PERF_STATUS;
+       default:
+               return 0;
+       }
+}
 struct sys_counters {
        unsigned int added_thread_counters;
        unsigned int added_core_counters;
@@ -451,6 +560,7 @@ struct msr_counter bic[] = {
        { 0x0, "APIC" },
        { 0x0, "X2APIC" },
        { 0x0, "Die" },
+       { 0x0, "GFXAMHz" },
 };
 
 #define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
@@ -505,6 +615,7 @@ struct msr_counter bic[] = {
 #define        BIC_APIC        (1ULL << 48)
 #define        BIC_X2APIC      (1ULL << 49)
 #define        BIC_Die         (1ULL << 50)
+#define        BIC_GFXACTMHz   (1ULL << 51)
 
 #define BIC_DISABLED_BY_DEFAULT        (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC)
 
@@ -724,6 +835,9 @@ void print_header(char *delim)
        if (DO_BIC(BIC_GFXMHz))
                outp += sprintf(outp, "%sGFXMHz", (printed++ ? delim : ""));
 
+       if (DO_BIC(BIC_GFXACTMHz))
+               outp += sprintf(outp, "%sGFXAMHz", (printed++ ? delim : ""));
+
        if (DO_BIC(BIC_Totl_c0))
                outp += sprintf(outp, "%sTotl%%C0", (printed++ ? delim : ""));
        if (DO_BIC(BIC_Any_c0))
@@ -858,13 +972,13 @@ int dump_counters(struct thread_data *t, struct core_data *c,
                outp += sprintf(outp, "pc10: %016llX\n", p->pc10);
                outp += sprintf(outp, "cpu_lpi: %016llX\n", p->cpu_lpi);
                outp += sprintf(outp, "sys_lpi: %016llX\n", p->sys_lpi);
-               outp += sprintf(outp, "Joules PKG: %0X\n", p->energy_pkg);
-               outp += sprintf(outp, "Joules COR: %0X\n", p->energy_cores);
-               outp += sprintf(outp, "Joules GFX: %0X\n", p->energy_gfx);
-               outp += sprintf(outp, "Joules RAM: %0X\n", p->energy_dram);
-               outp += sprintf(outp, "Throttle PKG: %0X\n",
+               outp += sprintf(outp, "Joules PKG: %0llX\n", p->energy_pkg);
+               outp += sprintf(outp, "Joules COR: %0llX\n", p->energy_cores);
+               outp += sprintf(outp, "Joules GFX: %0llX\n", p->energy_gfx);
+               outp += sprintf(outp, "Joules RAM: %0llX\n", p->energy_dram);
+               outp += sprintf(outp, "Throttle PKG: %0llX\n",
                        p->rapl_pkg_perf_status);
-               outp += sprintf(outp, "Throttle RAM: %0X\n",
+               outp += sprintf(outp, "Throttle RAM: %0llX\n",
                        p->rapl_dram_perf_status);
                outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c);
 
@@ -1062,14 +1176,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
                }
        }
 
-       /*
-        * If measurement interval exceeds minimum RAPL Joule Counter range,
-        * indicate that results are suspect by printing "**" in fraction place.
-        */
-       if (interval_float < rapl_joule_counter_range)
-               fmt8 = "%s%.2f";
-       else
-               fmt8 = "%6.0f**";
+       fmt8 = "%s%.2f";
 
        if (DO_BIC(BIC_CorWatt) && (do_rapl & RAPL_PER_CORE_ENERGY))
                outp += sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units / interval_float);
@@ -1098,6 +1205,10 @@ int format_counters(struct thread_data *t, struct core_data *c,
        if (DO_BIC(BIC_GFXMHz))
                outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_mhz);
 
+       /* GFXACTMHz */
+       if (DO_BIC(BIC_GFXACTMHz))
+               outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_act_mhz);
+
        /* Totl%C0, Any%C0 GFX%C0 CPUGFX% */
        if (DO_BIC(BIC_Totl_c0))
                outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_wtd_core_c0/tsc);
@@ -1210,11 +1321,7 @@ void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_
 }
 
 #define DELTA_WRAP32(new, old)                 \
-       if (new > old) {                        \
-               old = new - old;                \
-       } else {                                \
-               old = 0x100000000 + new - old;  \
-       }
+       old = ((((unsigned long long)new << 32) - ((unsigned long long)old << 32)) >> 32);
 
 int
 delta_package(struct pkg_data *new, struct pkg_data *old)
@@ -1253,13 +1360,14 @@ delta_package(struct pkg_data *new, struct pkg_data *old)
                old->gfx_rc6_ms = new->gfx_rc6_ms - old->gfx_rc6_ms;
 
        old->gfx_mhz = new->gfx_mhz;
+       old->gfx_act_mhz = new->gfx_act_mhz;
 
-       DELTA_WRAP32(new->energy_pkg, old->energy_pkg);
-       DELTA_WRAP32(new->energy_cores, old->energy_cores);
-       DELTA_WRAP32(new->energy_gfx, old->energy_gfx);
-       DELTA_WRAP32(new->energy_dram, old->energy_dram);
-       DELTA_WRAP32(new->rapl_pkg_perf_status, old->rapl_pkg_perf_status);
-       DELTA_WRAP32(new->rapl_dram_perf_status, old->rapl_dram_perf_status);
+       old->energy_pkg = new->energy_pkg - old->energy_pkg;
+       old->energy_cores = new->energy_cores - old->energy_cores;
+       old->energy_gfx = new->energy_gfx - old->energy_gfx;
+       old->energy_dram = new->energy_dram - old->energy_dram;
+       old->rapl_pkg_perf_status = new->rapl_pkg_perf_status - old->rapl_pkg_perf_status;
+       old->rapl_dram_perf_status = new->rapl_dram_perf_status - old->rapl_dram_perf_status;
 
        for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
                if (mp->format == FORMAT_RAW)
@@ -1469,6 +1577,7 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
 
        p->gfx_rc6_ms = 0;
        p->gfx_mhz = 0;
+       p->gfx_act_mhz = 0;
        for (i = 0, mp = sys.tp; mp; i++, mp = mp->next)
                t->counter[i] = 0;
 
@@ -1564,6 +1673,7 @@ int sum_counters(struct thread_data *t, struct core_data *c,
 
        average.packages.gfx_rc6_ms = p->gfx_rc6_ms;
        average.packages.gfx_mhz = p->gfx_mhz;
+       average.packages.gfx_act_mhz = p->gfx_act_mhz;
 
        average.packages.pkg_temp_c = MAX(average.packages.pkg_temp_c, p->pkg_temp_c);
 
@@ -1784,7 +1894,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
        int i;
 
        if (cpu_migrate(cpu)) {
-               fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+               fprintf(outf, "get_counters: Could not migrate to CPU %d\n", cpu);
                return -1;
        }
 
@@ -1966,39 +2076,39 @@ retry:
                p->sys_lpi = cpuidle_cur_sys_lpi_us;
 
        if (do_rapl & RAPL_PKG) {
-               if (get_msr(cpu, MSR_PKG_ENERGY_STATUS, &msr))
+               if (get_msr_sum(cpu, MSR_PKG_ENERGY_STATUS, &msr))
                        return -13;
-               p->energy_pkg = msr & 0xFFFFFFFF;
+               p->energy_pkg = msr;
        }
        if (do_rapl & RAPL_CORES_ENERGY_STATUS) {
-               if (get_msr(cpu, MSR_PP0_ENERGY_STATUS, &msr))
+               if (get_msr_sum(cpu, MSR_PP0_ENERGY_STATUS, &msr))
                        return -14;
-               p->energy_cores = msr & 0xFFFFFFFF;
+               p->energy_cores = msr;
        }
        if (do_rapl & RAPL_DRAM) {
-               if (get_msr(cpu, MSR_DRAM_ENERGY_STATUS, &msr))
+               if (get_msr_sum(cpu, MSR_DRAM_ENERGY_STATUS, &msr))
                        return -15;
-               p->energy_dram = msr & 0xFFFFFFFF;
+               p->energy_dram = msr;
        }
        if (do_rapl & RAPL_GFX) {
-               if (get_msr(cpu, MSR_PP1_ENERGY_STATUS, &msr))
+               if (get_msr_sum(cpu, MSR_PP1_ENERGY_STATUS, &msr))
                        return -16;
-               p->energy_gfx = msr & 0xFFFFFFFF;
+               p->energy_gfx = msr;
        }
        if (do_rapl & RAPL_PKG_PERF_STATUS) {
-               if (get_msr(cpu, MSR_PKG_PERF_STATUS, &msr))
+               if (get_msr_sum(cpu, MSR_PKG_PERF_STATUS, &msr))
                        return -16;
-               p->rapl_pkg_perf_status = msr & 0xFFFFFFFF;
+               p->rapl_pkg_perf_status = msr;
        }
        if (do_rapl & RAPL_DRAM_PERF_STATUS) {
-               if (get_msr(cpu, MSR_DRAM_PERF_STATUS, &msr))
+               if (get_msr_sum(cpu, MSR_DRAM_PERF_STATUS, &msr))
                        return -16;
-               p->rapl_dram_perf_status = msr & 0xFFFFFFFF;
+               p->rapl_dram_perf_status = msr;
        }
        if (do_rapl & RAPL_AMD_F17H) {
-               if (get_msr(cpu, MSR_PKG_ENERGY_STAT, &msr))
+               if (get_msr_sum(cpu, MSR_PKG_ENERGY_STAT, &msr))
                        return -13;
-               p->energy_pkg = msr & 0xFFFFFFFF;
+               p->energy_pkg = msr;
        }
        if (DO_BIC(BIC_PkgTmp)) {
                if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr))
@@ -2012,6 +2122,9 @@ retry:
        if (DO_BIC(BIC_GFXMHz))
                p->gfx_mhz = gfx_cur_mhz;
 
+       if (DO_BIC(BIC_GFXACTMHz))
+               p->gfx_act_mhz = gfx_act_mhz;
+
        for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
                if (get_mp(cpu, mp, &p->counter[i]))
                        return -10;
@@ -2173,6 +2286,7 @@ int has_turbo_ratio_group_limits(int family, int model)
        case INTEL_FAM6_ATOM_GOLDMONT:
        case INTEL_FAM6_SKYLAKE_X:
        case INTEL_FAM6_ATOM_GOLDMONT_D:
+       case INTEL_FAM6_ATOM_TREMONT_D:
                return 1;
        }
        return 0;
@@ -2650,7 +2764,12 @@ int get_thread_siblings(struct cpu_topology *thiscpu)
 
        sprintf(path,
                "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", cpu);
-       filep = fopen_or_die(path, "r");
+       filep = fopen(path, "r");
+
+       if (!filep) {
+               warnx("%s: open failed", path);
+               return -1;
+       }
        do {
                offset -= BITMASK_SIZE;
                if (fscanf(filep, "%lx%c", &map, &character) != 2)
@@ -2763,18 +2882,25 @@ void re_initialize(void)
 {
        free_all_buffers();
        setup_all_buffers();
-       printf("turbostat: re-initialized with num_cpus %d\n", topo.num_cpus);
+       fprintf(outf, "turbostat: re-initialized with num_cpus %d\n", topo.num_cpus);
 }
 
 void set_max_cpu_num(void)
 {
        FILE *filep;
+       int base_cpu;
        unsigned long dummy;
+       char pathname[64];
+
+       base_cpu = sched_getcpu();
+       if (base_cpu < 0)
+               err(1, "cannot find calling cpu ID");
+       sprintf(pathname,
+               "/sys/devices/system/cpu/cpu%d/topology/thread_siblings",
+               base_cpu);
 
+       filep = fopen_or_die(pathname, "r");
        topo.max_cpu_num = 0;
-       filep = fopen_or_die(
-                       "/sys/devices/system/cpu/cpu0/topology/thread_siblings",
-                       "r");
        while (fscanf(filep, "%lx,", &dummy) == 1)
                topo.max_cpu_num += BITMASK_SIZE;
        fclose(filep);
@@ -2915,6 +3041,33 @@ int snapshot_gfx_mhz(void)
        return 0;
 }
 
+/*
+ * snapshot_gfx_cur_mhz()
+ *
+ * record snapshot of
+ * /sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz
+ *
+ * return 1 if config change requires a restart, else return 0
+ */
+int snapshot_gfx_act_mhz(void)
+{
+       static FILE *fp;
+       int retval;
+
+       if (fp == NULL)
+               fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", "r");
+       else {
+               rewind(fp);
+               fflush(fp);
+       }
+
+       retval = fscanf(fp, "%d", &gfx_act_mhz);
+       if (retval != 1)
+               err(1, "GFX ACT MHz");
+
+       return 0;
+}
+
 /*
  * snapshot_cpu_lpi()
  *
@@ -2980,6 +3133,9 @@ int snapshot_proc_sysfs_files(void)
        if (DO_BIC(BIC_GFXMHz))
                snapshot_gfx_mhz();
 
+       if (DO_BIC(BIC_GFXACTMHz))
+               snapshot_gfx_act_mhz();
+
        if (DO_BIC(BIC_CPU_LPI))
                snapshot_cpu_lpi_us();
 
@@ -3057,6 +3213,111 @@ void do_sleep(void)
        }
 }
 
+int get_msr_sum(int cpu, off_t offset, unsigned long long *msr)
+{
+       int ret, idx;
+       unsigned long long msr_cur, msr_last;
+
+       if (!per_cpu_msr_sum)
+               return 1;
+
+       idx = offset_to_idx(offset);
+       if (idx < 0)
+               return idx;
+       /* get_msr_sum() = sum + (get_msr() - last) */
+       ret = get_msr(cpu, offset, &msr_cur);
+       if (ret)
+               return ret;
+       msr_last = per_cpu_msr_sum[cpu].entries[idx].last;
+       DELTA_WRAP32(msr_cur, msr_last);
+       *msr = msr_last + per_cpu_msr_sum[cpu].entries[idx].sum;
+
+       return 0;
+}
+
+timer_t timerid;
+
+/* Timer callback, update the sum of MSRs periodically. */
+static int update_msr_sum(struct thread_data *t, struct core_data *c, struct pkg_data *p)
+{
+       int i, ret;
+       int cpu = t->cpu_id;
+
+       for (i = IDX_PKG_ENERGY; i < IDX_COUNT; i++) {
+               unsigned long long msr_cur, msr_last;
+               int offset;
+
+               if (!idx_valid(i))
+                       continue;
+               offset = idx_to_offset(i);
+               if (offset < 0)
+                       continue;
+               ret = get_msr(cpu, offset, &msr_cur);
+               if (ret) {
+                       fprintf(outf, "Can not update msr(0x%x)\n", offset);
+                       continue;
+               }
+
+               msr_last = per_cpu_msr_sum[cpu].entries[i].last;
+               per_cpu_msr_sum[cpu].entries[i].last = msr_cur & 0xffffffff;
+
+               DELTA_WRAP32(msr_cur, msr_last);
+               per_cpu_msr_sum[cpu].entries[i].sum += msr_last;
+       }
+       return 0;
+}
+
+static void
+msr_record_handler(union sigval v)
+{
+       for_all_cpus(update_msr_sum, EVEN_COUNTERS);
+}
+
+void msr_sum_record(void)
+{
+       struct itimerspec its;
+       struct sigevent sev;
+
+       per_cpu_msr_sum = calloc(topo.max_cpu_num + 1, sizeof(struct msr_sum_array));
+       if (!per_cpu_msr_sum) {
+               fprintf(outf, "Can not allocate memory for long time MSR.\n");
+               return;
+       }
+       /*
+        * Signal handler might be restricted, so use thread notifier instead.
+        */
+       memset(&sev, 0, sizeof(struct sigevent));
+       sev.sigev_notify = SIGEV_THREAD;
+       sev.sigev_notify_function = msr_record_handler;
+
+       sev.sigev_value.sival_ptr = &timerid;
+       if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) {
+               fprintf(outf, "Can not create timer.\n");
+               goto release_msr;
+       }
+
+       its.it_value.tv_sec = 0;
+       its.it_value.tv_nsec = 1;
+       /*
+        * A wraparound time has been calculated early.
+        * Some sources state that the peak power for a
+        * microprocessor is usually 1.5 times the TDP rating,
+        * use 2 * TDP for safety.
+        */
+       its.it_interval.tv_sec = rapl_joule_counter_range / 2;
+       its.it_interval.tv_nsec = 0;
+
+       if (timer_settime(timerid, 0, &its, NULL) == -1) {
+               fprintf(outf, "Can not set timer.\n");
+               goto release_timer;
+       }
+       return;
+
+ release_timer:
+       timer_delete(timerid);
+ release_msr:
+       free(per_cpu_msr_sum);
+}
 
 void turbostat_loop()
 {
@@ -3075,7 +3336,7 @@ restart:
        if (retval < -1) {
                exit(retval);
        } else if (retval == -1) {
-               if (restarted > 1) {
+               if (restarted > 10) {
                        exit(retval);
                }
                re_initialize();
@@ -3279,6 +3540,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
        case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
        case INTEL_FAM6_ATOM_GOLDMONT_D:        /* DNV */
        case INTEL_FAM6_ATOM_TREMONT:   /* EHL */
+       case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */
                pkg_cstate_limits = glm_pkg_cstate_limits;
                break;
        default:
@@ -3361,6 +3623,17 @@ int is_ehl(unsigned int family, unsigned int model)
        }
        return 0;
 }
+int is_jvl(unsigned int family, unsigned int model)
+{
+       if (!genuine_intel)
+               return 0;
+
+       switch (model) {
+       case INTEL_FAM6_ATOM_TREMONT_D:
+               return 1;
+       }
+       return 0;
+}
 
 int has_turbo_ratio_limit(unsigned int family, unsigned int model)
 {
@@ -3474,6 +3747,20 @@ int has_config_tdp(unsigned int family, unsigned int model)
        }
 }
 
+static void
+remove_underbar(char *s)
+{
+       char *to = s;
+
+       while (*s) {
+               if (*s != '_')
+                       *to++ = *s;
+               s++;
+       }
+
+       *to = 0;
+}
+
 static void
 dump_cstate_pstate_config_info(unsigned int family, unsigned int model)
 {
@@ -3530,9 +3817,6 @@ dump_sysfs_cstate_config(void)
        int state;
        char *sp;
 
-       if (!DO_BIC(BIC_sysfs))
-               return;
-
        if (access("/sys/devices/system/cpu/cpuidle", R_OK)) {
                fprintf(outf, "cpuidle not loaded\n");
                return;
@@ -3559,6 +3843,8 @@ dump_sysfs_cstate_config(void)
                *sp = '\0';
                fclose(input);
 
+               remove_underbar(name_buf);
+
                sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/desc",
                        base_cpu, state);
                input = fopen(path, "r");
@@ -3645,7 +3931,7 @@ int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p)
                return 0;
 
        if (cpu_migrate(cpu)) {
-               fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+               fprintf(outf, "print_epb: Could not migrate to CPU %d\n", cpu);
                return -1;
        }
 
@@ -3689,7 +3975,7 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
                return 0;
 
        if (cpu_migrate(cpu)) {
-               fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+               fprintf(outf, "print_hwp: Could not migrate to CPU %d\n", cpu);
                return -1;
        }
 
@@ -3777,7 +4063,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
                return 0;
 
        if (cpu_migrate(cpu)) {
-               fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+               fprintf(outf, "print_perf_limit: Could not migrate to CPU %d\n", cpu);
                return -1;
        }
 
@@ -3881,13 +4167,8 @@ double get_tdp_intel(unsigned int model)
 
 double get_tdp_amd(unsigned int family)
 {
-       switch (family) {
-       case 0x17:
-       case 0x18:
-       default:
-               /* This is the max stock TDP of HEDT/Server Fam17h chips */
-               return 250.0;
-       }
+       /* This is the max stock TDP of HEDT/Server Fam17h+ chips */
+       return 280.0;
 }
 
 /*
@@ -3959,6 +4240,14 @@ void rapl_probe_intel(unsigned int family, unsigned int model)
                        BIC_PRESENT(BIC_GFXWatt);
                }
                break;
+       case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */
+               do_rapl = RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
+               BIC_PRESENT(BIC_PKG__);
+               if (rapl_joules)
+                       BIC_PRESENT(BIC_Pkg_J);
+               else
+                       BIC_PRESENT(BIC_PkgWatt);
+               break;
        case INTEL_FAM6_SKYLAKE_L:      /* SKL */
        case INTEL_FAM6_CANNONLAKE_L:   /* CNL */
                do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_GFX | RAPL_PKG_POWER_INFO;
@@ -4069,27 +4358,20 @@ void rapl_probe_amd(unsigned int family, unsigned int model)
 
        if (max_extended_level >= 0x80000007) {
                __cpuid(0x80000007, eax, ebx, ecx, edx);
-               /* RAPL (Fam 17h) */
+               /* RAPL (Fam 17h+) */
                has_rapl = edx & (1 << 14);
        }
 
-       if (!has_rapl)
+       if (!has_rapl || family < 0x17)
                return;
 
-       switch (family) {
-       case 0x17: /* Zen, Zen+ */
-       case 0x18: /* Hygon Dhyana */
-               do_rapl = RAPL_AMD_F17H | RAPL_PER_CORE_ENERGY;
-               if (rapl_joules) {
-                       BIC_PRESENT(BIC_Pkg_J);
-                       BIC_PRESENT(BIC_Cor_J);
-               } else {
-                       BIC_PRESENT(BIC_PkgWatt);
-                       BIC_PRESENT(BIC_CorWatt);
-               }
-               break;
-       default:
-               return;
+       do_rapl = RAPL_AMD_F17H | RAPL_PER_CORE_ENERGY;
+       if (rapl_joules) {
+               BIC_PRESENT(BIC_Pkg_J);
+               BIC_PRESENT(BIC_Cor_J);
+       } else {
+               BIC_PRESENT(BIC_PkgWatt);
+               BIC_PRESENT(BIC_CorWatt);
        }
 
        if (get_msr(base_cpu, MSR_RAPL_PWR_UNIT, &msr))
@@ -4162,7 +4444,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
                return 0;
 
        if (cpu_migrate(cpu)) {
-               fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+               fprintf(outf, "print_thermal: Could not migrate to CPU %d\n", cpu);
                return -1;
        }
 
@@ -4234,7 +4516,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
 
        cpu = t->cpu_id;
        if (cpu_migrate(cpu)) {
-               fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+               fprintf(outf, "print_rapl: Could not migrate to CPU %d\n", cpu);
                return -1;
        }
 
@@ -4361,6 +4643,7 @@ int has_snb_msrs(unsigned int family, unsigned int model)
        case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
        case INTEL_FAM6_ATOM_GOLDMONT_D:        /* DNV */
        case INTEL_FAM6_ATOM_TREMONT:           /* EHL */
+       case INTEL_FAM6_ATOM_TREMONT_D:         /* JVL */
                return 1;
        }
        return 0;
@@ -4507,12 +4790,33 @@ double discover_bclk(unsigned int family, unsigned int model)
  * below this value, including the Digital Thermal Sensor (DTS),
  * Package Thermal Management Sensor (PTM), and thermal event thresholds.
  */
-int set_temperature_target(struct thread_data *t, struct core_data *c, struct pkg_data *p)
+int read_tcc_activation_temp()
 {
        unsigned long long msr;
-       unsigned int target_c_local;
-       int cpu;
+       unsigned int tcc, target_c, offset_c;
 
+       /* Temperature Target MSR is Nehalem and newer only */
+       if (!do_nhm_platform_info)
+               return 0;
+
+       if (get_msr(base_cpu, MSR_IA32_TEMPERATURE_TARGET, &msr))
+               return 0;
+
+       target_c = (msr >> 16) & 0xFF;
+
+       offset_c = (msr >> 24) & 0xF;
+
+       tcc = target_c - offset_c;
+
+       if (!quiet)
+               fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C) (%d default - %d offset)\n",
+                       base_cpu, msr, tcc, target_c, offset_c);
+
+       return tcc;
+}
+
+int set_temperature_target(struct thread_data *t, struct core_data *c, struct pkg_data *p)
+{
        /* tcc_activation_temp is used only for dts or ptm */
        if (!(do_dts || do_ptm))
                return 0;
@@ -4521,43 +4825,18 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk
        if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
                return 0;
 
-       cpu = t->cpu_id;
-       if (cpu_migrate(cpu)) {
-               fprintf(outf, "Could not migrate to CPU %d\n", cpu);
-               return -1;
-       }
-
        if (tcc_activation_temp_override != 0) {
                tcc_activation_temp = tcc_activation_temp_override;
-               fprintf(outf, "cpu%d: Using cmdline TCC Target (%d C)\n",
-                       cpu, tcc_activation_temp);
+               fprintf(outf, "Using cmdline TCC Target (%d C)\n", tcc_activation_temp);
                return 0;
        }
 
-       /* Temperature Target MSR is Nehalem and newer only */
-       if (!do_nhm_platform_info)
-               goto guess;
-
-       if (get_msr(base_cpu, MSR_IA32_TEMPERATURE_TARGET, &msr))
-               goto guess;
-
-       target_c_local = (msr >> 16) & 0xFF;
-
-       if (!quiet)
-               fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n",
-                       cpu, msr, target_c_local);
-
-       if (!target_c_local)
-               goto guess;
-
-       tcc_activation_temp = target_c_local;
-
-       return 0;
+       tcc_activation_temp = read_tcc_activation_temp();
+       if (tcc_activation_temp)
+               return 0;
 
-guess:
        tcc_activation_temp = TJMAX_DEFAULT;
-       fprintf(outf, "cpu%d: Guessing tjMax %d C, Please use -T to specify\n",
-               cpu, tcc_activation_temp);
+       fprintf(outf, "Guessing tjMax %d C, Please use -T to specify\n", tcc_activation_temp);
 
        return 0;
 }
@@ -4685,19 +4964,46 @@ unsigned int intel_model_duplicates(unsigned int model)
        case INTEL_FAM6_ICELAKE_NNPI:
        case INTEL_FAM6_TIGERLAKE_L:
        case INTEL_FAM6_TIGERLAKE:
+       case INTEL_FAM6_ROCKETLAKE:
+       case INTEL_FAM6_LAKEFIELD:
+       case INTEL_FAM6_ALDERLAKE:
                return INTEL_FAM6_CANNONLAKE_L;
 
-       case INTEL_FAM6_ATOM_TREMONT_D:
-               return INTEL_FAM6_ATOM_GOLDMONT_D;
-
        case INTEL_FAM6_ATOM_TREMONT_L:
                return INTEL_FAM6_ATOM_TREMONT;
 
        case INTEL_FAM6_ICELAKE_X:
+       case INTEL_FAM6_SAPPHIRERAPIDS_X:
                return INTEL_FAM6_SKYLAKE_X;
        }
        return model;
 }
+
+void print_dev_latency(void)
+{
+       char *path = "/dev/cpu_dma_latency";
+       int fd;
+       int value;
+       int retval;
+
+       fd = open(path, O_RDONLY);
+       if (fd < 0) {
+               warn("fopen %s\n", path);
+               return;
+       }
+
+       retval = read(fd, (void *)&value, sizeof(int));
+       if (retval != sizeof(int)) {
+               warn("read %s\n", path);
+               close(fd);
+               return;
+       }
+       fprintf(outf, "/dev/cpu_dma_latency: %d usec (%s)\n",
+               value, value == 2000000000 ? "default" : "constrained");
+
+       close(fd);
+}
+
 void process_cpuid()
 {
        unsigned int eax, ebx, ecx, edx;
@@ -4916,6 +5222,14 @@ void process_cpuid()
                BIC_PRESENT(BIC_Mod_c6);
                use_c1_residency_msr = 1;
        }
+       if (is_jvl(family, model)) {
+               BIC_NOT_PRESENT(BIC_CPU_c3);
+               BIC_NOT_PRESENT(BIC_CPU_c7);
+               BIC_NOT_PRESENT(BIC_Pkgpc2);
+               BIC_NOT_PRESENT(BIC_Pkgpc3);
+               BIC_NOT_PRESENT(BIC_Pkgpc6);
+               BIC_NOT_PRESENT(BIC_Pkgpc7);
+       }
        if (is_dnv(family, model)) {
                BIC_PRESENT(BIC_CPU_c1);
                BIC_NOT_PRESENT(BIC_CPU_c3);
@@ -4935,9 +5249,12 @@ void process_cpuid()
                BIC_NOT_PRESENT(BIC_Pkgpc7);
        }
        if (has_c8910_msrs(family, model)) {
-               BIC_PRESENT(BIC_Pkgpc8);
-               BIC_PRESENT(BIC_Pkgpc9);
-               BIC_PRESENT(BIC_Pkgpc10);
+               if (pkg_cstate_limit >= PCL__8)
+                       BIC_PRESENT(BIC_Pkgpc8);
+               if (pkg_cstate_limit >= PCL__9)
+                       BIC_PRESENT(BIC_Pkgpc9);
+               if (pkg_cstate_limit >= PCL_10)
+                       BIC_PRESENT(BIC_Pkgpc10);
        }
        do_irtl_hsw = has_c8910_msrs(family, model);
        if (has_skl_msrs(family, model)) {
@@ -4966,6 +5283,8 @@ void process_cpuid()
        if (!quiet)
                dump_cstate_pstate_config_info(family, model);
 
+       if (!quiet)
+               print_dev_latency();
        if (!quiet)
                dump_sysfs_cstate_config();
        if (!quiet)
@@ -4980,6 +5299,9 @@ void process_cpuid()
        if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK))
                BIC_PRESENT(BIC_GFXMHz);
 
+       if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK))
+               BIC_PRESENT(BIC_GFXACTMHz);
+
        if (!access("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", R_OK))
                BIC_PRESENT(BIC_CPU_LPI);
        else
@@ -5390,7 +5712,7 @@ int get_and_dump_counters(void)
 }
 
 void print_version() {
-       fprintf(outf, "turbostat version 20.03.20"
+       fprintf(outf, "turbostat version 20.09.30"
                " - Len Brown <lenb@kernel.org>\n");
 }
 
@@ -5597,6 +5919,8 @@ void probe_sysfs(void)
                *sp = '%';
                *(sp + 1) = '\0';
 
+               remove_underbar(name_buf);
+
                fclose(input);
 
                sprintf(path, "cpuidle/state%d/time", state);
@@ -5624,6 +5948,8 @@ void probe_sysfs(void)
                *sp = '\0';
                fclose(input);
 
+               remove_underbar(name_buf);
+
                sprintf(path, "cpuidle/state%d/usage", state);
 
                if (is_deferred_skip(name_buf))
@@ -5868,6 +6194,7 @@ int main(int argc, char **argv)
                return 0;
        }
 
+       msr_sum_record();
        /*
         * if any params left, it must be a command to fork
         */
index 3fe1eed900d414169fb99d00787e1be710c7270b..ff6c6661f075f95980f0ca36ec607b8fb210223c 100644 (file)
@@ -622,6 +622,57 @@ void cmdline(int argc, char **argv)
        }
 }
 
+/*
+ * Open a file, and exit on failure
+ */
+FILE *fopen_or_die(const char *path, const char *mode)
+{
+       FILE *filep = fopen(path, "r");
+
+       if (!filep)
+               err(1, "%s: open failed", path);
+       return filep;
+}
+
+void err_on_hypervisor(void)
+{
+       FILE *cpuinfo;
+       char *flags, *hypervisor;
+       char *buffer;
+
+       /* On VMs /proc/cpuinfo contains a "flags" entry for hypervisor */
+       cpuinfo = fopen_or_die("/proc/cpuinfo", "ro");
+
+       buffer = malloc(4096);
+       if (!buffer) {
+               fclose(cpuinfo);
+               err(-ENOMEM, "buffer malloc fail");
+       }
+
+       if (!fread(buffer, 1024, 1, cpuinfo)) {
+               fclose(cpuinfo);
+               free(buffer);
+               err(1, "Reading /proc/cpuinfo failed");
+       }
+
+       flags = strstr(buffer, "flags");
+       rewind(cpuinfo);
+       fseek(cpuinfo, flags - buffer, SEEK_SET);
+       if (!fgets(buffer, 4096, cpuinfo)) {
+               fclose(cpuinfo);
+               free(buffer);
+               err(1, "Reading /proc/cpuinfo failed");
+       }
+       fclose(cpuinfo);
+
+       hypervisor = strstr(buffer, "hypervisor");
+
+       free(buffer);
+
+       if (hypervisor)
+               err(-1,
+                   "not supported on this virtual machine");
+}
 
 int get_msr(int cpu, int offset, unsigned long long *msr)
 {
@@ -635,8 +686,10 @@ int get_msr(int cpu, int offset, unsigned long long *msr)
                err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
 
        retval = pread(fd, msr, sizeof(*msr), offset);
-       if (retval != sizeof(*msr))
+       if (retval != sizeof(*msr)) {
+               err_on_hypervisor();
                err(-1, "%s offset 0x%llx read failed", pathname, (unsigned long long)offset);
+       }
 
        if (debug > 1)
                fprintf(stderr, "get_msr(cpu%d, 0x%X, 0x%llX)\n", cpu, offset, *msr);
@@ -1086,18 +1139,6 @@ int update_cpu_msrs(int cpu)
        return 0;
 }
 
-/*
- * Open a file, and exit on failure
- */
-FILE *fopen_or_die(const char *path, const char *mode)
-{
-       FILE *filep = fopen(path, "r");
-
-       if (!filep)
-               err(1, "%s: open failed", path);
-       return filep;
-}
-
 unsigned int get_pkg_num(int cpu)
 {
        FILE *fp;
diff --git a/tools/testing/kunit/.gitattributes b/tools/testing/kunit/.gitattributes
deleted file mode 100644 (file)
index 5b7da1f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-test_data/* binary
index ebf5f5763deeccc0e059947b95d6ce8d3d20a2b6..d4f7846d0745b00394fd47197004460e412633f9 100755 (executable)
@@ -11,7 +11,6 @@ import argparse
 import sys
 import os
 import time
-import shutil
 
 from collections import namedtuple
 from enum import Enum, auto
@@ -44,11 +43,6 @@ class KunitStatus(Enum):
        BUILD_FAILURE = auto()
        TEST_FAILURE = auto()
 
-def create_default_kunitconfig():
-       if not os.path.exists(kunit_kernel.kunitconfig_path):
-               shutil.copyfile('arch/um/configs/kunit_defconfig',
-                               kunit_kernel.kunitconfig_path)
-
 def get_kernel_root_path():
        parts = sys.argv[0] if not __file__ else __file__
        parts = os.path.realpath(parts).split('tools/testing/kunit')
@@ -61,7 +55,6 @@ def config_tests(linux: kunit_kernel.LinuxSourceTree,
        kunit_parser.print_with_timestamp('Configuring KUnit Kernel ...')
 
        config_start = time.time()
-       create_default_kunitconfig()
        success = linux.build_reconfig(request.build_dir, request.make_options)
        config_end = time.time()
        if not success:
@@ -262,12 +255,12 @@ def main(argv, linux=None):
                if not os.path.exists(cli_args.build_dir):
                        os.mkdir(cli_args.build_dir)
 
-               if not os.path.exists(kunit_kernel.kunitconfig_path):
-                       create_default_kunitconfig()
-
                if not linux:
                        linux = kunit_kernel.LinuxSourceTree()
 
+               linux.create_kunitconfig(cli_args.build_dir)
+               linux.read_kunitconfig(cli_args.build_dir)
+
                request = KunitRequest(cli_args.raw_output,
                                       cli_args.timeout,
                                       cli_args.jobs,
@@ -283,12 +276,12 @@ def main(argv, linux=None):
                                not os.path.exists(cli_args.build_dir)):
                        os.mkdir(cli_args.build_dir)
 
-               if not os.path.exists(kunit_kernel.kunitconfig_path):
-                       create_default_kunitconfig()
-
                if not linux:
                        linux = kunit_kernel.LinuxSourceTree()
 
+               linux.create_kunitconfig(cli_args.build_dir)
+               linux.read_kunitconfig(cli_args.build_dir)
+
                request = KunitConfigRequest(cli_args.build_dir,
                                             cli_args.make_options)
                result = config_tests(linux, request)
@@ -301,6 +294,9 @@ def main(argv, linux=None):
                if not linux:
                        linux = kunit_kernel.LinuxSourceTree()
 
+               linux.create_kunitconfig(cli_args.build_dir)
+               linux.read_kunitconfig(cli_args.build_dir)
+
                request = KunitBuildRequest(cli_args.jobs,
                                            cli_args.build_dir,
                                            cli_args.alltests,
@@ -315,6 +311,9 @@ def main(argv, linux=None):
                if not linux:
                        linux = kunit_kernel.LinuxSourceTree()
 
+               linux.create_kunitconfig(cli_args.build_dir)
+               linux.read_kunitconfig(cli_args.build_dir)
+
                exec_request = KunitExecRequest(cli_args.timeout,
                                                cli_args.build_dir,
                                                cli_args.alltests)
@@ -337,7 +336,7 @@ def main(argv, linux=None):
                                kunit_output = f.read().splitlines()
                request = KunitParseRequest(cli_args.raw_output,
                                            kunit_output,
-                                           cli_args.build_dir,
+                                           None,
                                            cli_args.json)
                result = parse_tests(request)
                if result.status != KunitStatus.SUCCESS:
index b557b1e93f98b5c1bdbfb9121a2326bd9da8ebbd..2e3cc0fac726369266414404a6fce81c151b7234 100644 (file)
@@ -6,10 +6,10 @@
 # Author: Felix Guo <felixguoxiuping@gmail.com>
 # Author: Brendan Higgins <brendanhiggins@google.com>
 
-
 import logging
 import subprocess
 import os
+import shutil
 import signal
 
 from contextlib import ExitStack
@@ -18,8 +18,10 @@ import kunit_config
 import kunit_parser
 
 KCONFIG_PATH = '.config'
-kunitconfig_path = '.kunitconfig'
+KUNITCONFIG_PATH = '.kunitconfig'
+DEFAULT_KUNITCONFIG_PATH = 'arch/um/configs/kunit_defconfig'
 BROKEN_ALLCONFIG_PATH = 'tools/testing/kunit/configs/broken_on_uml.config'
+OUTFILE_PATH = 'test.log'
 
 class ConfigError(Exception):
        """Represents an error trying to configure the Linux kernel."""
@@ -82,36 +84,51 @@ class LinuxSourceTreeOperations(object):
                if build_dir:
                        command += ['O=' + build_dir]
                try:
-                       subprocess.check_output(command, stderr=subprocess.STDOUT)
+                       proc = subprocess.Popen(command,
+                                               stderr=subprocess.PIPE,
+                                               stdout=subprocess.DEVNULL)
                except OSError as e:
-                       raise BuildError('Could not call execute make: ' + str(e))
-               except subprocess.CalledProcessError as e:
-                       raise BuildError(e.output.decode())
-
-       def linux_bin(self, params, timeout, build_dir, outfile):
+                       raise BuildError('Could not call make command: ' + str(e))
+               _, stderr = proc.communicate()
+               if proc.returncode != 0:
+                       raise BuildError(stderr.decode())
+               if stderr:  # likely only due to build warnings
+                       print(stderr.decode())
+
+       def linux_bin(self, params, timeout, build_dir):
                """Runs the Linux UML binary. Must be named 'linux'."""
                linux_bin = './linux'
                if build_dir:
                        linux_bin = os.path.join(build_dir, 'linux')
+               outfile = get_outfile_path(build_dir)
                with open(outfile, 'w') as output:
                        process = subprocess.Popen([linux_bin] + params,
                                                   stdout=output,
                                                   stderr=subprocess.STDOUT)
                        process.wait(timeout)
 
-
 def get_kconfig_path(build_dir):
        kconfig_path = KCONFIG_PATH
        if build_dir:
                kconfig_path = os.path.join(build_dir, KCONFIG_PATH)
        return kconfig_path
 
+def get_kunitconfig_path(build_dir):
+       kunitconfig_path = KUNITCONFIG_PATH
+       if build_dir:
+               kunitconfig_path = os.path.join(build_dir, KUNITCONFIG_PATH)
+       return kunitconfig_path
+
+def get_outfile_path(build_dir):
+       outfile_path = OUTFILE_PATH
+       if build_dir:
+               outfile_path = os.path.join(build_dir, OUTFILE_PATH)
+       return outfile_path
+
 class LinuxSourceTree(object):
        """Represents a Linux kernel source tree with KUnit tests."""
 
        def __init__(self):
-               self._kconfig = kunit_config.Kconfig()
-               self._kconfig.read_from_file(kunitconfig_path)
                self._ops = LinuxSourceTreeOperations()
                signal.signal(signal.SIGINT, self.signal_handler)
 
@@ -123,6 +140,16 @@ class LinuxSourceTree(object):
                        return False
                return True
 
+       def create_kunitconfig(self, build_dir, defconfig=DEFAULT_KUNITCONFIG_PATH):
+               kunitconfig_path = get_kunitconfig_path(build_dir)
+               if not os.path.exists(kunitconfig_path):
+                       shutil.copyfile(defconfig, kunitconfig_path)
+
+       def read_kunitconfig(self, build_dir):
+               kunitconfig_path = get_kunitconfig_path(build_dir)
+               self._kconfig = kunit_config.Kconfig()
+               self._kconfig.read_from_file(kunitconfig_path)
+
        def validate_config(self, build_dir):
                kconfig_path = get_kconfig_path(build_dir)
                validated_kconfig = kunit_config.Kconfig()
@@ -178,8 +205,8 @@ class LinuxSourceTree(object):
 
        def run_kernel(self, args=[], build_dir='', timeout=None):
                args.extend(['mem=1G'])
-               outfile = 'test.log'
-               self._ops.linux_bin(args, timeout, build_dir, outfile)
+               self._ops.linux_bin(args, timeout, build_dir)
+               outfile = get_outfile_path(build_dir)
                subprocess.call(['stty', 'sane'])
                with open(outfile, 'r') as file:
                        for line in file:
index 8019e3dd4c32f13e5e0f157fad059bef804d9499..bbfe1b4e4c1c7d0912062b130b6f64c3cfe602d5 100644 (file)
@@ -12,7 +12,7 @@ from collections import namedtuple
 from datetime import datetime
 from enum import Enum, auto
 from functools import reduce
-from typing import List
+from typing import List, Optional, Tuple
 
 TestResult = namedtuple('TestResult', ['status','suites','log'])
 
@@ -54,6 +54,7 @@ kunit_end_re = re.compile('(List of all partitions:|'
 def isolate_kunit_output(kernel_output):
        started = False
        for line in kernel_output:
+               line = line.rstrip()  # line always has a trailing \n
                if kunit_start_re.search(line):
                        prefix_len = len(line.split('TAP version')[0])
                        started = True
@@ -65,8 +66,7 @@ def isolate_kunit_output(kernel_output):
 
 def raw_output(kernel_output):
        for line in kernel_output:
-               print(line)
-               yield line
+               print(line.rstrip())
 
 DIVIDER = '=' * 60
 
@@ -152,7 +152,7 @@ def parse_diagnostic(lines: List[str], test_case: TestCase) -> bool:
        else:
                return False
 
-def parse_test_case(lines: List[str]) -> TestCase:
+def parse_test_case(lines: List[str]) -> Optional[TestCase]:
        test_case = TestCase()
        save_non_diagnositic(lines, test_case)
        while parse_diagnostic(lines, test_case):
@@ -164,7 +164,7 @@ def parse_test_case(lines: List[str]) -> TestCase:
 
 SUBTEST_HEADER = re.compile(r'^[\s]+# Subtest: (.*)$')
 
-def parse_subtest_header(lines: List[str]) -> str:
+def parse_subtest_header(lines: List[str]) -> Optional[str]:
        consume_non_diagnositic(lines)
        if not lines:
                return None
@@ -177,7 +177,7 @@ def parse_subtest_header(lines: List[str]) -> str:
 
 SUBTEST_PLAN = re.compile(r'[\s]+[0-9]+\.\.([0-9]+)')
 
-def parse_subtest_plan(lines: List[str]) -> int:
+def parse_subtest_plan(lines: List[str]) -> Optional[int]:
        consume_non_diagnositic(lines)
        match = SUBTEST_PLAN.match(lines[0])
        if match:
@@ -231,7 +231,7 @@ def bubble_up_test_case_errors(test_suite: TestSuite) -> TestStatus:
        max_test_case_status = bubble_up_errors(lambda x: x.status, test_suite.cases)
        return max_status(max_test_case_status, test_suite.status)
 
-def parse_test_suite(lines: List[str], expected_suite_index: int) -> TestSuite:
+def parse_test_suite(lines: List[str], expected_suite_index: int) -> Optional[TestSuite]:
        if not lines:
                return None
        consume_non_diagnositic(lines)
@@ -242,7 +242,7 @@ def parse_test_suite(lines: List[str], expected_suite_index: int) -> TestSuite:
                return None
        test_suite.name = name
        expected_test_case_num = parse_subtest_plan(lines)
-       if not expected_test_case_num:
+       if expected_test_case_num is None:
                return None
        while expected_test_case_num > 0:
                test_case = parse_test_case(lines)
@@ -272,7 +272,7 @@ def parse_tap_header(lines: List[str]) -> bool:
 
 TEST_PLAN = re.compile(r'[0-9]+\.\.([0-9]+)')
 
-def parse_test_plan(lines: List[str]) -> int:
+def parse_test_plan(lines: List[str]) -> Optional[int]:
        consume_non_diagnositic(lines)
        match = TEST_PLAN.match(lines[0])
        if match:
@@ -311,7 +311,7 @@ def parse_test_result(lines: List[str]) -> TestResult:
        else:
                return TestResult(TestStatus.NO_TESTS, [], lines)
 
-def print_and_count_results(test_result: TestResult) -> None:
+def print_and_count_results(test_result: TestResult) -> Tuple[int, int, int]:
        total_tests = 0
        failed_tests = 0
        crashed_tests = 0
index 99c3c5671ea48a8a09d300f11db8218afad9dee7..497ab51bc1702b551e19c1def5849006b960cac7 100755 (executable)
@@ -102,7 +102,7 @@ class KUnitParserTest(unittest.TestCase):
                        'test_data/test_output_isolated_correctly.log')
                file = open(log_path)
                result = kunit_parser.isolate_kunit_output(file.readlines())
-               self.assertContains('TAP version 14\n', result)
+               self.assertContains('TAP version 14', result)
                self.assertContains('   # Subtest: example', result)
                self.assertContains('   1..2', result)
                self.assertContains('   ok 1 - example_simple_test', result)
@@ -115,7 +115,7 @@ class KUnitParserTest(unittest.TestCase):
                        'test_data/test_pound_sign.log')
                with open(log_path) as file:
                        result = kunit_parser.isolate_kunit_output(file.readlines())
-               self.assertContains('TAP version 14\n', result)
+               self.assertContains('TAP version 14', result)
                self.assertContains('   # Subtest: kunit-resource-test', result)
                self.assertContains('   1..5', result)
                self.assertContains('   ok 1 - kunit_resource_test_init_resources', result)
@@ -179,7 +179,7 @@ class KUnitParserTest(unittest.TestCase):
                print_mock = mock.patch('builtins.print').start()
                result = kunit_parser.parse_run_tests(
                        kunit_parser.isolate_kunit_output(file.readlines()))
-               print_mock.assert_any_call(StrContains("no kunit output detected"))
+               print_mock.assert_any_call(StrContains('no tests run!'))
                print_mock.stop()
                file.close()
 
@@ -198,39 +198,57 @@ class KUnitParserTest(unittest.TestCase):
                        'test_data/test_config_printk_time.log')
                with open(prefix_log) as file:
                        result = kunit_parser.parse_run_tests(file.readlines())
-               self.assertEqual('kunit-resource-test', result.suites[0].name)
+                       self.assertEqual(
+                               kunit_parser.TestStatus.SUCCESS,
+                               result.status)
+                       self.assertEqual('kunit-resource-test', result.suites[0].name)
 
        def test_ignores_multiple_prefixes(self):
                prefix_log = get_absolute_path(
                        'test_data/test_multiple_prefixes.log')
                with open(prefix_log) as file:
                        result = kunit_parser.parse_run_tests(file.readlines())
-               self.assertEqual('kunit-resource-test', result.suites[0].name)
+                       self.assertEqual(
+                               kunit_parser.TestStatus.SUCCESS,
+                               result.status)
+                       self.assertEqual('kunit-resource-test', result.suites[0].name)
 
        def test_prefix_mixed_kernel_output(self):
                mixed_prefix_log = get_absolute_path(
                        'test_data/test_interrupted_tap_output.log')
                with open(mixed_prefix_log) as file:
                        result = kunit_parser.parse_run_tests(file.readlines())
-               self.assertEqual('kunit-resource-test', result.suites[0].name)
+                       self.assertEqual(
+                               kunit_parser.TestStatus.SUCCESS,
+                               result.status)
+                       self.assertEqual('kunit-resource-test', result.suites[0].name)
 
        def test_prefix_poundsign(self):
                pound_log = get_absolute_path('test_data/test_pound_sign.log')
                with open(pound_log) as file:
                        result = kunit_parser.parse_run_tests(file.readlines())
-               self.assertEqual('kunit-resource-test', result.suites[0].name)
+                       self.assertEqual(
+                               kunit_parser.TestStatus.SUCCESS,
+                               result.status)
+                       self.assertEqual('kunit-resource-test', result.suites[0].name)
 
        def test_kernel_panic_end(self):
                panic_log = get_absolute_path('test_data/test_kernel_panic_interrupt.log')
                with open(panic_log) as file:
                        result = kunit_parser.parse_run_tests(file.readlines())
-               self.assertEqual('kunit-resource-test', result.suites[0].name)
+                       self.assertEqual(
+                               kunit_parser.TestStatus.TEST_CRASHED,
+                               result.status)
+                       self.assertEqual('kunit-resource-test', result.suites[0].name)
 
        def test_pound_no_prefix(self):
                pound_log = get_absolute_path('test_data/test_pound_no_prefix.log')
                with open(pound_log) as file:
                        result = kunit_parser.parse_run_tests(file.readlines())
-               self.assertEqual('kunit-resource-test', result.suites[0].name)
+                       self.assertEqual(
+                               kunit_parser.TestStatus.SUCCESS,
+                               result.status)
+                       self.assertEqual('kunit-resource-test', result.suites[0].name)
 
 class KUnitJsonTest(unittest.TestCase):
 
index c02ca773946d641291e27d44d73174cc16a17d9d..6bdb57f76eacef0396e68942cb3fa983b6992bab 100644 (file)
@@ -1,6 +1,7 @@
 [    0.060000] printk: console [mc-1] enabled
 [    0.060000] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
 [    0.060000] TAP version 14
+[    0.060000] 1..3
 [    0.060000]         # Subtest: kunit-resource-test
 [    0.060000]         1..5
 [    0.060000]         ok 1 - kunit_resource_test_init_resources
@@ -28,4 +29,4 @@
 [    0.060000] Stack:
 [    0.060000]  602086f8 601bc260 705c0000 705c0000
 [    0.060000]  602086f8 6005fcec 705c0000 6002c6ab
-[    0.060000]  6005fcec 601bc260 705c0000 3000000010
\ No newline at end of file
+[    0.060000]  6005fcec 601bc260 705c0000 3000000010
index 5c73fb3a1c6fd13a9b163a48d02eb33b0315a375..1fb677728abeb0fe6aa5edb3a0387c05906b9815 100644 (file)
@@ -1,6 +1,7 @@
 [    0.060000] printk: console [mc-1] enabled
 [    0.060000] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
 [    0.060000] TAP version 14
+[    0.060000] 1..3
 [    0.060000]         # Subtest: kunit-resource-test
 [    0.060000]         1..5
 [    0.060000]         ok 1 - kunit_resource_test_init_resources
@@ -34,4 +35,4 @@
 [    0.060000] Stack:
 [    0.060000]  602086f8 601bc260 705c0000 705c0000
 [    0.060000]  602086f8 6005fcec 705c0000 6002c6ab
-[    0.060000]  6005fcec 601bc260 705c0000 3000000010
\ No newline at end of file
+[    0.060000]  6005fcec 601bc260 705c0000 3000000010
index c045eee75f27fefaabf3ba073d9e282721c19a67..a014ffe9725e3c4e81697f742cee2652a41b2108 100644 (file)
@@ -1,6 +1,7 @@
 [    0.060000] printk: console [mc-1] enabled
 [    0.060000] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
 [    0.060000] TAP version 14
+[    0.060000] 1..3
 [    0.060000]         # Subtest: kunit-resource-test
 [    0.060000]         1..5
 [    0.060000]         ok 1 - kunit_resource_test_init_resources
@@ -22,4 +23,4 @@
 [    0.060000] Stack:
 [    0.060000]  602086f8 601bc260 705c0000 705c0000
 [    0.060000]  602086f8 6005fcec 705c0000 6002c6ab
-[    0.060000]  6005fcec 601bc260 705c0000 3000000010
\ No newline at end of file
+[    0.060000]  6005fcec 601bc260 705c0000 3000000010
index bc48407dcc36c44665c7d2ac620e42e7caf98481..0ad78481a0b450bf463ca7aaab0ae739d4e43018 100644 (file)
@@ -1,6 +1,7 @@
 [    0.060000][    T1] printk: console [mc-1] enabled
 [    0.060000][    T1] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
 [    0.060000][    T1] TAP version 14
+[    0.060000][    T1] 1..3
 [    0.060000][    T1]         # Subtest: kunit-resource-test
 [    0.060000][    T1]         1..5
 [    0.060000][    T1]         ok 1 - kunit_resource_test_init_resources
@@ -28,4 +29,4 @@
 [    0.060000][    T1] Stack:
 [    0.060000][    T1]  602086f8 601bc260 705c0000 705c0000
 [    0.060000][    T1]  602086f8 6005fcec 705c0000 6002c6ab
-[    0.060000][    T1]  6005fcec 601bc260 705c0000 3000000010
\ No newline at end of file
+[    0.060000][    T1]  6005fcec 601bc260 705c0000 3000000010
index 2ceb360be7d52cbee4b0a5a426456605ded7466e..dc4cf09a96d077bbc0b5fbcb312251742e390379 100644 (file)
@@ -1,6 +1,7 @@
  printk: console [mc-1] enabled
  random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
  TAP version 14
+ 1..3
        # Subtest: kunit-resource-test
        1..5
        ok 1 - kunit_resource_test_init_resources
@@ -30,4 +31,4 @@
  Stack:
   602086f8 601bc260 705c0000 705c0000
   602086f8 6005fcec 705c0000 6002c6ab
-  6005fcec 601bc260 705c0000 3000000010
\ No newline at end of file
+  6005fcec 601bc260 705c0000 3000000010
index 28ffa5ba03bfa81ea02ea9d38e7de7acf3dd9e5d..3f358e3a7ba0d118c1dc15e5f637fb8ffb5aa388 100644 (file)
@@ -1,6 +1,7 @@
 [    0.060000] printk: console [mc-1] enabled
 [    0.060000] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
 [    0.060000] TAP version 14
+[    0.060000] 1..3
 [    0.060000]         # Subtest: kunit-resource-test
 [    0.060000]         1..5
 [    0.060000]         ok 1 - kunit_resource_test_init_resources
index 6ae907f375d20a30b56590ce0d1e149707463a72..f9a12005fcea85214b4d940cd23c661b576adc7a 100644 (file)
@@ -33,6 +33,7 @@ typedef unsigned long dma_addr_t;
 #define __ALIGN_KERNEL(x, a)           __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
 #define __ALIGN_KERNEL_MASK(x, mask)   (((x) + (mask)) & ~(mask))
 #define ALIGN(x, a)                    __ALIGN_KERNEL((x), (a))
+#define ALIGN_DOWN(x, a)               __ALIGN_KERNEL((x) - ((a) - 1), (a))
 
 #define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE)
 
index b2c7e9f7b8d3dcc1df66a381bc27678e1576f2e8..f561aed7c6570352178e44a214b228c58d800697 100644 (file)
@@ -52,9 +52,9 @@ int main(void)
 {
        const unsigned int sgmax = SCATTERLIST_MAX_SEGMENT;
        struct test *test, tests[] = {
-               { -EINVAL, 1, pfn(0), PAGE_SIZE, PAGE_SIZE + 1, 1 },
                { -EINVAL, 1, pfn(0), PAGE_SIZE, 0, 1 },
-               { -EINVAL, 1, pfn(0), PAGE_SIZE, sgmax + 1, 1 },
+               { 0, 1, pfn(0), PAGE_SIZE, PAGE_SIZE + 1, 1 },
+               { 0, 1, pfn(0), PAGE_SIZE, sgmax + 1, 1 },
                { 0, 1, pfn(0), PAGE_SIZE, sgmax, 1 },
                { 0, 1, pfn(0), 1, sgmax, 1 },
                { 0, 2, pfn(0, 1), 2 * PAGE_SIZE, sgmax, 1 },
index 242635d79035a78e71f1f67a44ae3fe507bdce66..c9fa141ebdcc8fd39a5e307556b6f8c4c09e2289 100644 (file)
@@ -417,6 +417,9 @@ int main(int argc, char *argv[])
        /* Register SIGSEGV handler */
        mte_register_signal(SIGSEGV, mte_default_handler);
 
+       /* Set test plan */
+       ksft_set_plan(20);
+
        /* Buffer by byte tests */
        evaluate_test(check_buffer_by_byte(USE_MMAP, MTE_SYNC_ERR),
        "Check buffer correctness by byte with sync err mode and mmap memory\n");
index 97bebdecd29efb52ac3143c75a87340bdcaf158d..43bd94f853ba70a59e974ebcecbb0ab11d6b6ef8 100644 (file)
@@ -163,6 +163,9 @@ int main(int argc, char *argv[])
        mte_register_signal(SIGSEGV, mte_default_handler);
        mte_register_signal(SIGBUS, mte_default_handler);
 
+       /* Set test plan */
+       ksft_set_plan(12);
+
        evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),
                "Check child anonymous memory with private mapping, precise mode and mmap memory\n");
        evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED),
index bc41ae630c86c5c5b521772fdff9d6702f9c28e0..3b23c4d61d38885bd8ee98a2c6f7c1a6748cdb4e 100644 (file)
@@ -140,6 +140,10 @@ int main(int argc, char *argv[])
        /* Register signal handlers */
        mte_register_signal(SIGBUS, mte_default_handler);
        mte_register_signal(SIGSEGV, mte_default_handler);
+
+       /* Set test plan */
+       ksft_set_plan(4);
+
        /* Enable KSM */
        mte_ksm_setup();
 
index 33b13b86199b5eb7762a7e1583ca3c81af60338e..a04b12c21ac90fcd06080d0c0a67780ece9502a3 100644 (file)
@@ -205,7 +205,11 @@ int main(int argc, char *argv[])
        mte_register_signal(SIGBUS, mte_default_handler);
        mte_register_signal(SIGSEGV, mte_default_handler);
 
+       /* Set test plan */
+       ksft_set_plan(22);
+
        mte_enable_pstate_tco();
+
        evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_OFF),
        "Check anonymous memory with private mapping, sync error mode, mmap memory and tag check off\n");
        evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_OFF),
index 94d245a0ed560fc8ec95dc9bfad4dc32f55e7aac..deaef1f610768104abe2b076f0e5166cd5ac211f 100644 (file)
@@ -170,6 +170,9 @@ int main(int argc, char *argv[])
        /* Register SIGSEGV handler */
        mte_register_signal(SIGSEGV, mte_default_handler);
 
+       /* Set test plan */
+       ksft_set_plan(4);
+
        evaluate_test(check_single_included_tags(USE_MMAP, MTE_SYNC_ERR),
                      "Check an included tag value with sync mode\n");
        evaluate_test(check_multiple_included_tags(USE_MMAP, MTE_SYNC_ERR),
index 594e98e76880a57592b4204c33a487f06b8df66a..4bfa80f2a8c3e1743bea5e8867e28e432888e040 100644 (file)
@@ -92,9 +92,13 @@ int main(int argc, char *argv[])
        err = mte_default_setup();
        if (err)
                return err;
+
        /* Register signal handlers */
        mte_register_signal(SIGSEGV, mte_default_handler);
 
+       /* Set test plan */
+       ksft_set_plan(4);
+
        evaluate_test(check_usermem_access_fault(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),
                "Check memory access from kernel in sync mode, private mapping and mmap memory\n");
        evaluate_test(check_usermem_access_fault(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED),
diff --git a/tools/testing/selftests/bpf/prog_tests/map_init.c b/tools/testing/selftests/bpf/prog_tests/map_init.c
new file mode 100644 (file)
index 0000000..14a3110
--- /dev/null
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2020 Tessares SA <http://www.tessares.net> */
+
+#include <test_progs.h>
+#include "test_map_init.skel.h"
+
+#define TEST_VALUE 0x1234
+#define FILL_VALUE 0xdeadbeef
+
+static int nr_cpus;
+static int duration;
+
+typedef unsigned long long map_key_t;
+typedef unsigned long long map_value_t;
+typedef struct {
+       map_value_t v; /* padding */
+} __bpf_percpu_val_align pcpu_map_value_t;
+
+
+static int map_populate(int map_fd, int num)
+{
+       pcpu_map_value_t value[nr_cpus];
+       int i, err;
+       map_key_t key;
+
+       for (i = 0; i < nr_cpus; i++)
+               bpf_percpu(value, i) = FILL_VALUE;
+
+       for (key = 1; key <= num; key++) {
+               err = bpf_map_update_elem(map_fd, &key, value, BPF_NOEXIST);
+               if (!ASSERT_OK(err, "bpf_map_update_elem"))
+                       return -1;
+       }
+
+       return 0;
+}
+
+static struct test_map_init *setup(enum bpf_map_type map_type, int map_sz,
+                           int *map_fd, int populate)
+{
+       struct test_map_init *skel;
+       int err;
+
+       skel = test_map_init__open();
+       if (!ASSERT_OK_PTR(skel, "skel_open"))
+               return NULL;
+
+       err = bpf_map__set_type(skel->maps.hashmap1, map_type);
+       if (!ASSERT_OK(err, "bpf_map__set_type"))
+               goto error;
+
+       err = bpf_map__set_max_entries(skel->maps.hashmap1, map_sz);
+       if (!ASSERT_OK(err, "bpf_map__set_max_entries"))
+               goto error;
+
+       err = test_map_init__load(skel);
+       if (!ASSERT_OK(err, "skel_load"))
+               goto error;
+
+       *map_fd = bpf_map__fd(skel->maps.hashmap1);
+       if (CHECK(*map_fd < 0, "bpf_map__fd", "failed\n"))
+               goto error;
+
+       err = map_populate(*map_fd, populate);
+       if (!ASSERT_OK(err, "map_populate"))
+               goto error_map;
+
+       return skel;
+
+error_map:
+       close(*map_fd);
+error:
+       test_map_init__destroy(skel);
+       return NULL;
+}
+
+/* executes bpf program that updates map with key, value */
+static int prog_run_insert_elem(struct test_map_init *skel, map_key_t key,
+                               map_value_t value)
+{
+       struct test_map_init__bss *bss;
+
+       bss = skel->bss;
+
+       bss->inKey = key;
+       bss->inValue = value;
+       bss->inPid = getpid();
+
+       if (!ASSERT_OK(test_map_init__attach(skel), "skel_attach"))
+               return -1;
+
+       /* Let tracepoint trigger */
+       syscall(__NR_getpgid);
+
+       test_map_init__detach(skel);
+
+       return 0;
+}
+
+static int check_values_one_cpu(pcpu_map_value_t *value, map_value_t expected)
+{
+       int i, nzCnt = 0;
+       map_value_t val;
+
+       for (i = 0; i < nr_cpus; i++) {
+               val = bpf_percpu(value, i);
+               if (val) {
+                       if (CHECK(val != expected, "map value",
+                                 "unexpected for cpu %d: 0x%llx\n", i, val))
+                               return -1;
+                       nzCnt++;
+               }
+       }
+
+       if (CHECK(nzCnt != 1, "map value", "set for %d CPUs instead of 1!\n",
+                 nzCnt))
+               return -1;
+
+       return 0;
+}
+
+/* Add key=1 elem with values set for all CPUs
+ * Delete elem key=1
+ * Run bpf prog that inserts new key=1 elem with value=0x1234
+ *   (bpf prog can only set value for current CPU)
+ * Lookup Key=1 and check value is as expected for all CPUs:
+ *   value set by bpf prog for one CPU, 0 for all others
+ */
+static void test_pcpu_map_init(void)
+{
+       pcpu_map_value_t value[nr_cpus];
+       struct test_map_init *skel;
+       int map_fd, err;
+       map_key_t key;
+
+       /* max 1 elem in map so insertion is forced to reuse freed entry */
+       skel = setup(BPF_MAP_TYPE_PERCPU_HASH, 1, &map_fd, 1);
+       if (!ASSERT_OK_PTR(skel, "prog_setup"))
+               return;
+
+       /* delete element so the entry can be re-used*/
+       key = 1;
+       err = bpf_map_delete_elem(map_fd, &key);
+       if (!ASSERT_OK(err, "bpf_map_delete_elem"))
+               goto cleanup;
+
+       /* run bpf prog that inserts new elem, re-using the slot just freed */
+       err = prog_run_insert_elem(skel, key, TEST_VALUE);
+       if (!ASSERT_OK(err, "prog_run_insert_elem"))
+               goto cleanup;
+
+       /* check that key=1 was re-created by bpf prog */
+       err = bpf_map_lookup_elem(map_fd, &key, value);
+       if (!ASSERT_OK(err, "bpf_map_lookup_elem"))
+               goto cleanup;
+
+       /* and has expected values */
+       check_values_one_cpu(value, TEST_VALUE);
+
+cleanup:
+       test_map_init__destroy(skel);
+}
+
+/* Add key=1 and key=2 elems with values set for all CPUs
+ * Run bpf prog that inserts new key=3 elem
+ *   (only for current cpu; other cpus should have initial value = 0)
+ * Lookup Key=1 and check value is as expected for all CPUs
+ */
+static void test_pcpu_lru_map_init(void)
+{
+       pcpu_map_value_t value[nr_cpus];
+       struct test_map_init *skel;
+       int map_fd, err;
+       map_key_t key;
+
+       /* Set up LRU map with 2 elements, values filled for all CPUs.
+        * With these 2 elements, the LRU map is full
+        */
+       skel = setup(BPF_MAP_TYPE_LRU_PERCPU_HASH, 2, &map_fd, 2);
+       if (!ASSERT_OK_PTR(skel, "prog_setup"))
+               return;
+
+       /* run bpf prog that inserts new key=3 element, re-using LRU slot */
+       key = 3;
+       err = prog_run_insert_elem(skel, key, TEST_VALUE);
+       if (!ASSERT_OK(err, "prog_run_insert_elem"))
+               goto cleanup;
+
+       /* check that key=3 replaced one of earlier elements */
+       err = bpf_map_lookup_elem(map_fd, &key, value);
+       if (!ASSERT_OK(err, "bpf_map_lookup_elem"))
+               goto cleanup;
+
+       /* and has expected values */
+       check_values_one_cpu(value, TEST_VALUE);
+
+cleanup:
+       test_map_init__destroy(skel);
+}
+
+void test_map_init(void)
+{
+       nr_cpus = bpf_num_possible_cpus();
+       if (nr_cpus <= 1) {
+               printf("%s:SKIP: >1 cpu needed for this test\n", __func__);
+               test__skip();
+               return;
+       }
+
+       if (test__start_subtest("pcpu_map_init"))
+               test_pcpu_map_init();
+       if (test__start_subtest("pcpu_lru_map_init"))
+               test_pcpu_lru_map_init();
+}
diff --git a/tools/testing/selftests/bpf/prog_tests/probe_read_user_str.c b/tools/testing/selftests/bpf/prog_tests/probe_read_user_str.c
new file mode 100644 (file)
index 0000000..e419298
--- /dev/null
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <test_progs.h>
+#include "test_probe_read_user_str.skel.h"
+
+static const char str1[] = "mestring";
+static const char str2[] = "mestringalittlebigger";
+static const char str3[] = "mestringblubblubblubblubblub";
+
+static int test_one_str(struct test_probe_read_user_str *skel, const char *str,
+                       size_t len)
+{
+       int err, duration = 0;
+       char buf[256];
+
+       /* Ensure bytes after string are ones */
+       memset(buf, 1, sizeof(buf));
+       memcpy(buf, str, len);
+
+       /* Give prog our userspace pointer */
+       skel->bss->user_ptr = buf;
+
+       /* Trigger tracepoint */
+       usleep(1);
+
+       /* Did helper fail? */
+       if (CHECK(skel->bss->ret < 0, "prog_ret", "prog returned: %ld\n",
+                 skel->bss->ret))
+               return 1;
+
+       /* Check that string was copied correctly */
+       err = memcmp(skel->bss->buf, str, len);
+       if (CHECK(err, "memcmp", "prog copied wrong string"))
+               return 1;
+
+       /* Now check that no extra trailing bytes were copied */
+       memset(buf, 0, sizeof(buf));
+       err = memcmp(skel->bss->buf + len, buf, sizeof(buf) - len);
+       if (CHECK(err, "memcmp", "trailing bytes were not stripped"))
+               return 1;
+
+       return 0;
+}
+
+void test_probe_read_user_str(void)
+{
+       struct test_probe_read_user_str *skel;
+       int err, duration = 0;
+
+       skel = test_probe_read_user_str__open_and_load();
+       if (CHECK(!skel, "test_probe_read_user_str__open_and_load",
+                 "skeleton open and load failed\n"))
+               return;
+
+       /* Give pid to bpf prog so it doesn't read from anyone else */
+       skel->bss->pid = getpid();
+
+       err = test_probe_read_user_str__attach(skel);
+       if (CHECK(err, "test_probe_read_user_str__attach",
+                 "skeleton attach failed: %d\n", err))
+               goto out;
+
+       if (test_one_str(skel, str1, sizeof(str1)))
+               goto out;
+       if (test_one_str(skel, str2, sizeof(str2)))
+               goto out;
+       if (test_one_str(skel, str3, sizeof(str3)))
+               goto out;
+
+out:
+       test_probe_read_user_str__destroy(skel);
+}
index 29188d6f5c8def2623172fd140fa3b3b27d405f5..51fac975b3163fd9491fd66210229cea15432f1d 100644 (file)
@@ -138,7 +138,8 @@ static int run_getsockopt_test(struct bpf_object *obj, int cg_parent,
         */
 
        buf = 0x40;
-       if (setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1) < 0) {
+       err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
+       if (err < 0) {
                log_err("Failed to call setsockopt(IP_TOS)");
                goto detach;
        }
index a00abf58c0373571ddc8192dc0f9551c120cba2c..3f3d2ac4dd57e821d3df9f18773085953047b574 100644 (file)
@@ -3,12 +3,14 @@
 #include <test_progs.h>
 #include <time.h>
 #include "test_subprogs.skel.h"
+#include "test_subprogs_unused.skel.h"
 
 static int duration;
 
 void test_subprogs(void)
 {
        struct test_subprogs *skel;
+       struct test_subprogs_unused *skel2;
        int err;
 
        skel = test_subprogs__open_and_load();
@@ -26,6 +28,10 @@ void test_subprogs(void)
        CHECK(skel->bss->res3 != 19, "res3", "got %d, exp %d\n", skel->bss->res3, 19);
        CHECK(skel->bss->res4 != 36, "res4", "got %d, exp %d\n", skel->bss->res4, 36);
 
+       skel2 = test_subprogs_unused__open_and_load();
+       ASSERT_OK_PTR(skel2, "unused_progs_skel");
+       test_subprogs_unused__destroy(skel2);
+
 cleanup:
        test_subprogs__destroy(skel);
 }
index 193002b14d7f66ac9c1b6942f79d662760278ac7..32e4348b714bcef612d9ce9687b09993a84fdb6f 100644 (file)
@@ -60,6 +60,7 @@ void test_test_global_funcs(void)
                { "test_global_func5.o" , "expected pointer to ctx, but got PTR" },
                { "test_global_func6.o" , "modified ctx ptr R2" },
                { "test_global_func7.o" , "foo() doesn't return scalar" },
+               { "test_global_func8.o" },
        };
        libbpf_print_fn_t old_print_fn = NULL;
        int err, i, duration = 0;
index 00578311a4233e33a9607da2a8c2bff32a8f4ffa..30982a7e4d0f78f20869c9e0c826244ad1b4cfbc 100644 (file)
@@ -243,7 +243,10 @@ static ino_t get_inode_from_kernfs(struct kernfs_node* node)
        }
 }
 
-int pids_cgrp_id = 1;
+extern bool CONFIG_CGROUP_PIDS __kconfig __weak;
+enum cgroup_subsys_id___local {
+       pids_cgrp_id___local = 123, /* value doesn't matter */
+};
 
 static INLINE void* populate_cgroup_info(struct cgroup_data_t* cgroup_data,
                                         struct task_struct* task,
@@ -253,7 +256,9 @@ static INLINE void* populate_cgroup_info(struct cgroup_data_t* cgroup_data,
                BPF_CORE_READ(task, nsproxy, cgroup_ns, root_cset, dfl_cgrp, kn);
        struct kernfs_node* proc_kernfs = BPF_CORE_READ(task, cgroups, dfl_cgrp, kn);
 
-       if (ENABLE_CGROUP_V1_RESOLVER) {
+       if (ENABLE_CGROUP_V1_RESOLVER && CONFIG_CGROUP_PIDS) {
+               int cgrp_id = bpf_core_enum_value(enum cgroup_subsys_id___local,
+                                                 pids_cgrp_id___local);
 #ifdef UNROLL
 #pragma unroll
 #endif
@@ -262,7 +267,7 @@ static INLINE void* populate_cgroup_info(struct cgroup_data_t* cgroup_data,
                                BPF_CORE_READ(task, cgroups, subsys[i]);
                        if (subsys != NULL) {
                                int subsys_id = BPF_CORE_READ(subsys, ss, id);
-                               if (subsys_id == pids_cgrp_id) {
+                               if (subsys_id == cgrp_id) {
                                        proc_kernfs = BPF_CORE_READ(subsys, cgroup, kn);
                                        root_kernfs = BPF_CORE_READ(subsys, ss, root, kf_root, kn);
                                        break;
diff --git a/tools/testing/selftests/bpf/progs/test_global_func8.c b/tools/testing/selftests/bpf/progs/test_global_func8.c
new file mode 100644 (file)
index 0000000..d55a654
--- /dev/null
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2020 Facebook */
+#include <stddef.h>
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+__noinline int foo(struct __sk_buff *skb)
+{
+       return bpf_get_prandom_u32();
+}
+
+SEC("cgroup_skb/ingress")
+int test_cls(struct __sk_buff *skb)
+{
+       if (!foo(skb))
+               return 0;
+
+       return 1;
+}
diff --git a/tools/testing/selftests/bpf/progs/test_map_init.c b/tools/testing/selftests/bpf/progs/test_map_init.c
new file mode 100644 (file)
index 0000000..c89d28e
--- /dev/null
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2020 Tessares SA <http://www.tessares.net> */
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+
+__u64 inKey = 0;
+__u64 inValue = 0;
+__u32 inPid = 0;
+
+struct {
+       __uint(type, BPF_MAP_TYPE_PERCPU_HASH);
+       __uint(max_entries, 2);
+       __type(key, __u64);
+       __type(value, __u64);
+} hashmap1 SEC(".maps");
+
+
+SEC("tp/syscalls/sys_enter_getpgid")
+int sysenter_getpgid(const void *ctx)
+{
+       /* Just do it for once, when called from our own test prog. This
+        * ensures the map value is only updated for a single CPU.
+        */
+       int cur_pid = bpf_get_current_pid_tgid() >> 32;
+
+       if (cur_pid == inPid)
+               bpf_map_update_elem(&hashmap1, &inKey, &inValue, BPF_NOEXIST);
+
+       return 0;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/test_probe_read_user_str.c b/tools/testing/selftests/bpf/progs/test_probe_read_user_str.c
new file mode 100644 (file)
index 0000000..3ae398b
--- /dev/null
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+#include <sys/types.h>
+
+pid_t pid = 0;
+long ret = 0;
+void *user_ptr = 0;
+char buf[256] = {};
+
+SEC("tracepoint/syscalls/sys_enter_nanosleep")
+int on_write(void *ctx)
+{
+       if (pid != (bpf_get_current_pid_tgid() >> 32))
+               return 0;
+
+       ret = bpf_probe_read_user_str(buf, sizeof(buf), user_ptr);
+
+       return 0;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/test_subprogs_unused.c b/tools/testing/selftests/bpf/progs/test_subprogs_unused.c
new file mode 100644 (file)
index 0000000..bc49e05
--- /dev/null
@@ -0,0 +1,21 @@
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_core_read.h>
+
+const char LICENSE[] SEC("license") = "GPL";
+
+__attribute__((unused)) __noinline int unused1(int x)
+{
+       return x + 1;
+}
+
+static __attribute__((unused)) __noinline int unused2(int x)
+{
+       return x + 2;
+}
+
+SEC("raw_tp/sys_enter")
+int main_prog(void *ctx)
+{
+       return 0;
+}
index 55bd387ce7ec6ae45b2999652d7d7fbe13d56c5c..52d3f0364bdaa1b1ecf744247de63c77f3c2079f 100644 (file)
@@ -145,7 +145,7 @@ TEST(clone3_cap_checkpoint_restore)
        test_clone3_supported();
 
        EXPECT_EQ(getuid(), 0)
-               XFAIL(return, "Skipping all tests as non-root\n");
+               SKIP(return, "Skipping all tests as non-root");
 
        memset(&set_tid, 0, sizeof(set_tid));
 
index c99b98b0d461fb6e49aa07b14fa798061694bb75..575b391ddc78d31bcfc424e40c5a540428d98e09 100644 (file)
@@ -44,7 +44,7 @@ TEST(close_range)
                fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
                ASSERT_GE(fd, 0) {
                        if (errno == ENOENT)
-                               XFAIL(return, "Skipping test since /dev/null does not exist");
+                               SKIP(return, "Skipping test since /dev/null does not exist");
                }
 
                open_fds[i] = fd;
@@ -52,7 +52,7 @@ TEST(close_range)
 
        EXPECT_EQ(-1, sys_close_range(open_fds[0], open_fds[100], -1)) {
                if (errno == ENOSYS)
-                       XFAIL(return, "close_range() syscall not supported");
+                       SKIP(return, "close_range() syscall not supported");
        }
 
        EXPECT_EQ(0, sys_close_range(open_fds[0], open_fds[50], 0));
@@ -108,7 +108,7 @@ TEST(close_range_unshare)
                fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
                ASSERT_GE(fd, 0) {
                        if (errno == ENOENT)
-                               XFAIL(return, "Skipping test since /dev/null does not exist");
+                               SKIP(return, "Skipping test since /dev/null does not exist");
                }
 
                open_fds[i] = fd;
@@ -197,7 +197,7 @@ TEST(close_range_unshare_capped)
                fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
                ASSERT_GE(fd, 0) {
                        if (errno == ENOENT)
-                               XFAIL(return, "Skipping test since /dev/null does not exist");
+                               SKIP(return, "Skipping test since /dev/null does not exist");
                }
 
                open_fds[i] = fd;
index 1d27f52c61e61a1b297082abb5d65848cd40a773..477cbb042f5badec5361ffa6abd1d739fd578edb 100644 (file)
@@ -74,7 +74,7 @@ static int __do_binderfs_test(struct __test_metadata *_metadata)
        ret = mount(NULL, binderfs_mntpt, "binder", 0, 0);
        EXPECT_EQ(ret, 0) {
                if (errno == ENODEV)
-                       XFAIL(goto out, "binderfs missing");
+                       SKIP(goto out, "binderfs missing");
                TH_LOG("%s - Failed to mount binderfs", strerror(errno));
                goto rmdir;
        }
@@ -475,10 +475,10 @@ TEST(binderfs_stress)
 TEST(binderfs_test_privileged)
 {
        if (geteuid() != 0)
-               XFAIL(return, "Tests are not run as root. Skipping privileged tests");
+               SKIP(return, "Tests are not run as root. Skipping privileged tests");
 
        if (__do_binderfs_test(_metadata))
-               XFAIL(return, "The Android binderfs filesystem is not available");
+               SKIP(return, "The Android binderfs filesystem is not available");
 }
 
 TEST(binderfs_test_unprivileged)
@@ -511,7 +511,7 @@ TEST(binderfs_test_unprivileged)
        ret = wait_for_pid(pid);
        if (ret) {
                if (ret == 2)
-                       XFAIL(return, "The Android binderfs filesystem is not available");
+                       SKIP(return, "The Android binderfs filesystem is not available");
                ASSERT_EQ(ret, 0) {
                        TH_LOG("wait_for_pid() failed");
                }
index d979ff14775ad87a3a3077c487c6ca08906261c6..8f82f99f7748aff7596f2d6a4de4e4ce9be98bde 100644 (file)
@@ -3282,4 +3282,99 @@ TEST(epoll60)
        close(ctx.epfd);
 }
 
+struct epoll61_ctx {
+       int epfd;
+       int evfd;
+};
+
+static void *epoll61_write_eventfd(void *ctx_)
+{
+       struct epoll61_ctx *ctx = ctx_;
+       int64_t l = 1;
+
+       usleep(10950);
+       write(ctx->evfd, &l, sizeof(l));
+       return NULL;
+}
+
+static void *epoll61_epoll_with_timeout(void *ctx_)
+{
+       struct epoll61_ctx *ctx = ctx_;
+       struct epoll_event events[1];
+       int n;
+
+       n = epoll_wait(ctx->epfd, events, 1, 11);
+       /*
+        * If epoll returned the eventfd, write on the eventfd to wake up the
+        * blocking poller.
+        */
+       if (n == 1) {
+               int64_t l = 1;
+
+               write(ctx->evfd, &l, sizeof(l));
+       }
+       return NULL;
+}
+
+static void *epoll61_blocking_epoll(void *ctx_)
+{
+       struct epoll61_ctx *ctx = ctx_;
+       struct epoll_event events[1];
+
+       epoll_wait(ctx->epfd, events, 1, -1);
+       return NULL;
+}
+
+TEST(epoll61)
+{
+       struct epoll61_ctx ctx;
+       struct epoll_event ev;
+       int i, r;
+
+       ctx.epfd = epoll_create1(0);
+       ASSERT_GE(ctx.epfd, 0);
+       ctx.evfd = eventfd(0, EFD_NONBLOCK);
+       ASSERT_GE(ctx.evfd, 0);
+
+       ev.events = EPOLLIN | EPOLLET | EPOLLERR | EPOLLHUP;
+       ev.data.ptr = NULL;
+       r = epoll_ctl(ctx.epfd, EPOLL_CTL_ADD, ctx.evfd, &ev);
+       ASSERT_EQ(r, 0);
+
+       /*
+        * We are testing a race.  Repeat the test case 1000 times to make it
+        * more likely to fail in case of a bug.
+        */
+       for (i = 0; i < 1000; i++) {
+               pthread_t threads[3];
+               int n;
+
+               /*
+                * Start 3 threads:
+                * Thread 1 sleeps for 10.9ms and writes to the evenfd.
+                * Thread 2 calls epoll with a timeout of 11ms.
+                * Thread 3 calls epoll with a timeout of -1.
+                *
+                * The eventfd write by Thread 1 should either wakeup Thread 2
+                * or Thread 3.  If it wakes up Thread 2, Thread 2 writes on the
+                * eventfd to wake up Thread 3.
+                *
+                * If no events are missed, all three threads should eventually
+                * be joinable.
+                */
+               ASSERT_EQ(pthread_create(&threads[0], NULL,
+                                        epoll61_write_eventfd, &ctx), 0);
+               ASSERT_EQ(pthread_create(&threads[1], NULL,
+                                        epoll61_epoll_with_timeout, &ctx), 0);
+               ASSERT_EQ(pthread_create(&threads[2], NULL,
+                                        epoll61_blocking_epoll, &ctx), 0);
+
+               for (n = 0; n < ARRAY_SIZE(threads); ++n)
+                       ASSERT_EQ(pthread_join(threads[n], NULL), 0);
+       }
+
+       close(ctx.epfd);
+       close(ctx.evfd);
+}
+
 TEST_HARNESS_MAIN
index 3bcd4c3624ee0303fe0ed6bff4ddd5f1fdfcc085..b4da41d126d583d9dc92a777ffc88406d6040bb5 100644 (file)
@@ -6,7 +6,7 @@
 echo 0 > events/enable
 echo > dynamic_events
 
-PLACE=kernel_clone
+PLACE=$FUNCTION_FORK
 
 echo "p:myevent1 $PLACE" >> dynamic_events
 echo "r:myevent2 $PLACE" >> dynamic_events
index 438961971b7e170a09fbfd25ed6ea0e69bc8fb00..3a0e2885fff5894bc80f96d210f13b17f56fe13e 100644 (file)
@@ -6,7 +6,7 @@
 echo 0 > events/enable
 echo > dynamic_events
 
-PLACE=kernel_clone
+PLACE=$FUNCTION_FORK
 
 setup_events() {
 echo "p:myevent1 $PLACE" >> dynamic_events
index a8603bd23e0d803da48786e3aae1f9687f65aced..d3e138e8377f53ac23c2731d996c3ed9d6fcc30e 100644 (file)
@@ -6,7 +6,7 @@
 echo 0 > events/enable
 echo > dynamic_events
 
-PLACE=kernel_clone
+PLACE=$FUNCTION_FORK
 
 setup_events() {
 echo "p:myevent1 $PLACE" >> dynamic_events
index acb17ce543d2e6fb617e0d71eb722ebb9edebc33..80541964b9270b0619c6b0689c90ee50cf77482b 100644 (file)
@@ -39,7 +39,7 @@ do_test() {
     disable_tracing
 
     echo do_execve* > set_ftrace_filter
-    echo *do_fork >> set_ftrace_filter
+    echo $FUNCTION_FORK >> set_ftrace_filter
 
     echo $PID > set_ftrace_notrace_pid
     echo function > current_tracer
index 9f0a9687c773a566818261dc2e273ce3ab90c77f..2f7211254529ba13b3225bec3c5c29e887e77812 100644 (file)
@@ -39,7 +39,7 @@ do_test() {
     disable_tracing
 
     echo do_execve* > set_ftrace_filter
-    echo *do_fork >> set_ftrace_filter
+    echo $FUNCTION_FORK >> set_ftrace_filter
 
     echo $PID > set_ftrace_pid
     echo function > current_tracer
index 98305d76bd04f7a17639b7a829c11f2d1759f805..191d116b788324188773c98a351e66d707d85cff 100644 (file)
@@ -4,9 +4,9 @@
 # requires: set_ftrace_filter
 # flags: instance
 
-echo kernel_clone:stacktrace >> set_ftrace_filter
+echo $FUNCTION_FORK:stacktrace >> set_ftrace_filter
 
-grep -q "kernel_clone:stacktrace:unlimited" set_ftrace_filter
+grep -q "$FUNCTION_FORK:stacktrace:unlimited" set_ftrace_filter
 
 (echo "forked"; sleep 1)
 
index c5dec55b7d95d266ad159477fc4692151da11766..a6fac927ee82f68703d1bb29c8d7c4cf3ef9c03f 100644 (file)
@@ -133,6 +133,13 @@ yield() {
     ping $LOCALHOST -c 1 || sleep .001 || usleep 1 || sleep 1
 }
 
+# The fork function in the kernel was renamed from "_do_fork" to
+# "kernel_fork". As older tests should still work with older kernels
+# as well as newer kernels, check which version of fork is used on this
+# kernel so that the tests can use the fork function for the running kernel.
+FUNCTION_FORK=`(if grep '\bkernel_clone\b' /proc/kallsyms > /dev/null; then
+                echo kernel_clone; else echo '_do_fork'; fi)`
+
 # Since probe event command may include backslash, explicitly use printf "%s"
 # to NOT interpret it.
 ftrace_errlog_check() { # err-prefix command-with-error-pos-by-^ command-file
index 9737cd0578a7fab07e29ff984b8ff526d19532e7..2428a3ed78c95d8e0e1559206bc9c66be1bb9bae 100644 (file)
@@ -3,7 +3,7 @@
 # description: Kprobe dynamic event - adding and removing
 # requires: kprobe_events
 
-echo p:myevent kernel_clone > kprobe_events
+echo p:myevent $FUNCTION_FORK > kprobe_events
 grep myevent kprobe_events
 test -d events/kprobes/myevent
 echo > kprobe_events
index f9a40af76888e37cd85ec849f29454377fcbf699..010a8b1d6c1d56c8cb9187d80391ec7bd5532bf7 100644 (file)
@@ -3,7 +3,7 @@
 # description: Kprobe dynamic event - busy event check
 # requires: kprobe_events
 
-echo p:myevent kernel_clone > kprobe_events
+echo p:myevent $FUNCTION_FORK > kprobe_events
 test -d events/kprobes/myevent
 echo 1 > events/kprobes/myevent/enable
 echo > kprobe_events && exit_fail # this must fail
index eb543d3cfe5f4c45c80c2b4148edb899c0b95fa2..a96a1dc7014fb5660bd8fffc5be5b373c0300d1d 100644 (file)
@@ -3,13 +3,13 @@
 # description: Kprobe dynamic event with arguments
 # requires: kprobe_events
 
-echo 'p:testprobe kernel_clone $stack $stack0 +0($stack)' > kprobe_events
+echo "p:testprobe $FUNCTION_FORK \$stack \$stack0 +0(\$stack)" > kprobe_events
 grep testprobe kprobe_events | grep -q 'arg1=\$stack arg2=\$stack0 arg3=+0(\$stack)'
 test -d events/kprobes/testprobe
 
 echo 1 > events/kprobes/testprobe/enable
 ( echo "forked")
-grep testprobe trace | grep 'kernel_clone' | \
+grep testprobe trace | grep "$FUNCTION_FORK" | \
   grep -q 'arg1=0x[[:xdigit:]]* arg2=0x[[:xdigit:]]* arg3=0x[[:xdigit:]]*$'
 
 echo 0 > events/kprobes/testprobe/enable
index 4e5b63be51c9484396f824523f3dd4525e2920a5..a053ee2e7d779e20ce645f0dda1e95f5b9315927 100644 (file)
@@ -5,7 +5,7 @@
 
 grep -A1 "fetcharg:" README | grep -q "\$comm" || exit_unsupported # this is too old
 
-echo 'p:testprobe kernel_clone comm=$comm ' > kprobe_events
+echo "p:testprobe $FUNCTION_FORK comm=\$comm " > kprobe_events
 grep testprobe kprobe_events | grep -q 'comm=$comm'
 test -d events/kprobes/testprobe
 
index a1d70588ab2166aba2f752aab0119b4eaee68217..84285a6f60b079346a5c527ea99a5d400c678c0a 100644 (file)
@@ -30,13 +30,13 @@ esac
 : "Test get argument (1)"
 echo "p:testprobe tracefs_create_dir arg1=+0(${ARG1}):string" > kprobe_events
 echo 1 > events/kprobes/testprobe/enable
-echo "p:test kernel_clone" >> kprobe_events
+echo "p:test $FUNCTION_FORK" >> kprobe_events
 grep -qe "testprobe.* arg1=\"test\"" trace
 
 echo 0 > events/kprobes/testprobe/enable
 : "Test get argument (2)"
 echo "p:testprobe tracefs_create_dir arg1=+0(${ARG1}):string arg2=+0(${ARG1}):string" > kprobe_events
 echo 1 > events/kprobes/testprobe/enable
-echo "p:test kernel_clone" >> kprobe_events
+echo "p:test $FUNCTION_FORK" >> kprobe_events
 grep -qe "testprobe.* arg1=\"test\" arg2=\"test\"" trace
 
index bd25dd0ba0d0c984a79918ba1795608dc03b71f9..717130ed4feb28e0c34ebbd357aa8fca86f5f921 100644 (file)
@@ -14,12 +14,12 @@ elif ! grep "$SYMBOL\$" /proc/kallsyms; then
 fi
 
 : "Test get basic types symbol argument"
-echo "p:testprobe_u kernel_clone arg1=@linux_proc_banner:u64 arg2=@linux_proc_banner:u32 arg3=@linux_proc_banner:u16 arg4=@linux_proc_banner:u8" > kprobe_events
-echo "p:testprobe_s kernel_clone arg1=@linux_proc_banner:s64 arg2=@linux_proc_banner:s32 arg3=@linux_proc_banner:s16 arg4=@linux_proc_banner:s8" >> kprobe_events
+echo "p:testprobe_u $FUNCTION_FORK arg1=@linux_proc_banner:u64 arg2=@linux_proc_banner:u32 arg3=@linux_proc_banner:u16 arg4=@linux_proc_banner:u8" > kprobe_events
+echo "p:testprobe_s $FUNCTION_FORK arg1=@linux_proc_banner:s64 arg2=@linux_proc_banner:s32 arg3=@linux_proc_banner:s16 arg4=@linux_proc_banner:s8" >> kprobe_events
 if grep -q "x8/16/32/64" README; then
-  echo "p:testprobe_x kernel_clone arg1=@linux_proc_banner:x64 arg2=@linux_proc_banner:x32 arg3=@linux_proc_banner:x16 arg4=@linux_proc_banner:x8" >> kprobe_events
+  echo "p:testprobe_x $FUNCTION_FORK arg1=@linux_proc_banner:x64 arg2=@linux_proc_banner:x32 arg3=@linux_proc_banner:x16 arg4=@linux_proc_banner:x8" >> kprobe_events
 fi
-echo "p:testprobe_bf kernel_clone arg1=@linux_proc_banner:b8@4/32" >> kprobe_events
+echo "p:testprobe_bf $FUNCTION_FORK arg1=@linux_proc_banner:b8@4/32" >> kprobe_events
 echo 1 > events/kprobes/enable
 (echo "forked")
 echo 0 > events/kprobes/enable
@@ -27,7 +27,7 @@ grep "testprobe_[usx]:.* arg1=.* arg2=.* arg3=.* arg4=.*" trace
 grep "testprobe_bf:.* arg1=.*" trace
 
 : "Test get string symbol argument"
-echo "p:testprobe_str kernel_clone arg1=@linux_proc_banner:string" > kprobe_events
+echo "p:testprobe_str $FUNCTION_FORK arg1=@linux_proc_banner:string" > kprobe_events
 echo 1 > events/kprobes/enable
 (echo "forked")
 echo 0 > events/kprobes/enable
index 91fcce1c241cc7f9ec546961bfc901809d627b6f..25b7708eb55946a890e0020ba65deb668795a0c0 100644 (file)
@@ -4,7 +4,7 @@
 # requires: kprobe_events "x8/16/32/64":README
 
 gen_event() { # Bitsize
-  echo "p:testprobe kernel_clone \$stack0:s$1 \$stack0:u$1 \$stack0:x$1 \$stack0:b4@4/$1"
+  echo "p:testprobe $FUNCTION_FORK \$stack0:s$1 \$stack0:u$1 \$stack0:x$1 \$stack0:b4@4/$1"
 }
 
 check_types() { # s-type u-type x-type bf-type width
index a30a9c07290d0f8efef694199f2a3f7849c7a36f..d25d01a19778127b74858db84c3a330ae40897b9 100644 (file)
@@ -9,12 +9,16 @@ grep -A10 "fetcharg:" README | grep -q '\[u\]<offset>' || exit_unsupported
 :;: "user-memory access syntax and ustring working on user memory";:
 echo 'p:myevent do_sys_open path=+0($arg2):ustring path2=+u0($arg2):string' \
        > kprobe_events
+echo 'p:myevent2 do_sys_openat2 path=+0($arg2):ustring path2=+u0($arg2):string' \
+       >> kprobe_events
 
 grep myevent kprobe_events | \
        grep -q 'path=+0($arg2):ustring path2=+u0($arg2):string'
 echo 1 > events/kprobes/myevent/enable
+echo 1 > events/kprobes/myevent2/enable
 echo > /dev/null
 echo 0 > events/kprobes/myevent/enable
+echo 0 > events/kprobes/myevent2/enable
 
 grep myevent trace | grep -q 'path="/dev/null" path2="/dev/null"'
 
index 0d179094191f5e71a4d859acdff195704cc2e4a5..5556292601a48186087d5d7e834396de7b0aff78 100644 (file)
@@ -5,29 +5,29 @@
 
 # prepare
 echo nop > current_tracer
-echo kernel_clone > set_ftrace_filter
-echo 'p:testprobe kernel_clone' > kprobe_events
+echo $FUNCTION_FORK > set_ftrace_filter
+echo "p:testprobe $FUNCTION_FORK" > kprobe_events
 
 # kprobe on / ftrace off
 echo 1 > events/kprobes/testprobe/enable
 echo > trace
 ( echo "forked")
 grep testprobe trace
-! grep 'kernel_clone <-' trace
+! grep "$FUNCTION_FORK <-" trace
 
 # kprobe on / ftrace on
 echo function > current_tracer
 echo > trace
 ( echo "forked")
 grep testprobe trace
-grep 'kernel_clone <-' trace
+grep "$FUNCTION_FORK <-" trace
 
 # kprobe off / ftrace on
 echo 0 > events/kprobes/testprobe/enable
 echo > trace
 ( echo "forked")
 ! grep testprobe trace
-grep 'kernel_clone <-' trace
+grep "$FUNCTION_FORK <-" trace
 
 # kprobe on / ftrace on
 echo 1 > events/kprobes/testprobe/enable
@@ -35,11 +35,11 @@ echo function > current_tracer
 echo > trace
 ( echo "forked")
 grep testprobe trace
-grep 'kernel_clone <-' trace
+grep "$FUNCTION_FORK <-" trace
 
 # kprobe on / ftrace off
 echo nop > current_tracer
 echo > trace
 ( echo "forked")
 grep testprobe trace
-! grep 'kernel_clone <-' trace
+! grep "$FUNCTION_FORK <-" trace
index 45d90b6c763d822491e843835f55658fb87904f4..f0d5b7777ed76bb9df973919943fdaa7b6e5555f 100644 (file)
@@ -4,7 +4,7 @@
 # requires: kprobe_events "Create/append/":README
 
 # Choose 2 symbols for target
-SYM1=kernel_clone
+SYM1=$FUNCTION_FORK
 SYM2=do_exit
 EVENT_NAME=kprobes/testevent
 
index 1b5550ef8a9b9146549f624ddf177d6916b4b881..fa928b431555ca1b21d43231233cf2c304d3aef6 100644 (file)
@@ -86,15 +86,15 @@ esac
 
 # multiprobe errors
 if grep -q "Create/append/" README && grep -q "imm-value" README; then
-echo 'p:kprobes/testevent kernel_clone' > kprobe_events
+echo "p:kprobes/testevent $FUNCTION_FORK" > kprobe_events
 check_error '^r:kprobes/testevent do_exit'     # DIFF_PROBE_TYPE
 
 # Explicitly use printf "%s" to not interpret \1
-printf "%s" 'p:kprobes/testevent kernel_clone abcd=\1' > kprobe_events
-check_error 'p:kprobes/testevent kernel_clone ^bcd=\1' # DIFF_ARG_TYPE
-check_error 'p:kprobes/testevent kernel_clone ^abcd=\1:u8'     # DIFF_ARG_TYPE
-check_error 'p:kprobes/testevent kernel_clone ^abcd=\"foo"'    # DIFF_ARG_TYPE
-check_error '^p:kprobes/testevent kernel_clone abcd=\1'        # SAME_PROBE
+printf "%s" "p:kprobes/testevent $FUNCTION_FORK abcd=\\1" > kprobe_events
+check_error "p:kprobes/testevent $FUNCTION_FORK ^bcd=\\1"      # DIFF_ARG_TYPE
+check_error "p:kprobes/testevent $FUNCTION_FORK ^abcd=\\1:u8"  # DIFF_ARG_TYPE
+check_error "p:kprobes/testevent $FUNCTION_FORK ^abcd=\\\"foo\"" # DIFF_ARG_TYPE
+check_error "^p:kprobes/testevent $FUNCTION_FORK abcd=\\1"     # SAME_PROBE
 fi
 
 # %return suffix errors
index 7ae492c204a43595f72eb6568bef699179a8ea95..197cc2afd4046b3c48fe9321aeac9d508e0079b6 100644 (file)
@@ -4,14 +4,14 @@
 # requires: kprobe_events
 
 # Add new kretprobe event
-echo 'r:testprobe2 kernel_clone $retval' > kprobe_events
+echo "r:testprobe2 $FUNCTION_FORK \$retval" > kprobe_events
 grep testprobe2 kprobe_events | grep -q 'arg1=\$retval'
 test -d events/kprobes/testprobe2
 
 echo 1 > events/kprobes/testprobe2/enable
 ( echo "forked")
 
-cat trace | grep testprobe2 | grep -q '<- kernel_clone'
+cat trace | grep testprobe2 | grep -q "<- $FUNCTION_FORK"
 
 echo 0 > events/kprobes/testprobe2/enable
 echo '-:testprobe2' >> kprobe_events
index c4093fc1a77336b228c70d64a31fe5e03263a6ea..98166fa3eb91ccbbef854d9ad8c5c5a605b594f9 100644 (file)
@@ -4,7 +4,7 @@
 # requires: kprobe_events
 
 ! grep -q 'myevent' kprobe_profile
-echo p:myevent kernel_clone > kprobe_events
+echo "p:myevent $FUNCTION_FORK" > kprobe_events
 grep -q 'myevent[[:space:]]*0[[:space:]]*0$' kprobe_profile
 echo 1 > events/kprobes/myevent/enable
 ( echo "forked" )
index f19804df244c08669ef5241c18fa27efd5a6f100..edce85420d1934e3892f5ffe1d5c6d06c0df593f 100644 (file)
        snprintf(_metadata->results->reason, \
                 sizeof(_metadata->results->reason), fmt, ##__VA_ARGS__); \
        if (TH_LOG_ENABLED) { \
-               fprintf(TH_LOG_STREAM, "#      SKIP     %s\n", \
+               fprintf(TH_LOG_STREAM, "#      SKIP      %s\n", \
                        _metadata->results->reason); \
        } \
        _metadata->passed = 1; \
  */
 
 /**
- * ASSERT_EQ(expected, seen)
+ * ASSERT_EQ()
  *
  * @expected: expected value
  * @seen: measured value
        __EXPECT(expected, #expected, seen, #seen, ==, 1)
 
 /**
- * ASSERT_NE(expected, seen)
+ * ASSERT_NE()
  *
  * @expected: expected value
  * @seen: measured value
        __EXPECT(expected, #expected, seen, #seen, !=, 1)
 
 /**
- * ASSERT_LT(expected, seen)
+ * ASSERT_LT()
  *
  * @expected: expected value
  * @seen: measured value
        __EXPECT(expected, #expected, seen, #seen, <, 1)
 
 /**
- * ASSERT_LE(expected, seen)
+ * ASSERT_LE()
  *
  * @expected: expected value
  * @seen: measured value
        __EXPECT(expected, #expected, seen, #seen, <=, 1)
 
 /**
- * ASSERT_GT(expected, seen)
+ * ASSERT_GT()
  *
  * @expected: expected value
  * @seen: measured value
        __EXPECT(expected, #expected, seen, #seen, >, 1)
 
 /**
- * ASSERT_GE(expected, seen)
+ * ASSERT_GE()
  *
  * @expected: expected value
  * @seen: measured value
        __EXPECT(expected, #expected, seen, #seen, >=, 1)
 
 /**
- * ASSERT_NULL(seen)
+ * ASSERT_NULL()
  *
  * @seen: measured value
  *
        __EXPECT(NULL, "NULL", seen, #seen, ==, 1)
 
 /**
- * ASSERT_TRUE(seen)
+ * ASSERT_TRUE()
  *
  * @seen: measured value
  *
        __EXPECT(0, "0", seen, #seen, !=, 1)
 
 /**
- * ASSERT_FALSE(seen)
+ * ASSERT_FALSE()
  *
  * @seen: measured value
  *
        __EXPECT(0, "0", seen, #seen, ==, 1)
 
 /**
- * ASSERT_STREQ(expected, seen)
+ * ASSERT_STREQ()
  *
  * @expected: expected value
  * @seen: measured value
        __EXPECT_STR(expected, seen, ==, 1)
 
 /**
- * ASSERT_STRNE(expected, seen)
+ * ASSERT_STRNE()
  *
  * @expected: expected value
  * @seen: measured value
        __EXPECT_STR(expected, seen, !=, 1)
 
 /**
- * EXPECT_EQ(expected, seen)
+ * EXPECT_EQ()
  *
  * @expected: expected value
  * @seen: measured value
        __EXPECT(expected, #expected, seen, #seen, ==, 0)
 
 /**
- * EXPECT_NE(expected, seen)
+ * EXPECT_NE()
  *
  * @expected: expected value
  * @seen: measured value
        __EXPECT(expected, #expected, seen, #seen, !=, 0)
 
 /**
- * EXPECT_LT(expected, seen)
+ * EXPECT_LT()
  *
  * @expected: expected value
  * @seen: measured value
        __EXPECT(expected, #expected, seen, #seen, <, 0)
 
 /**
- * EXPECT_LE(expected, seen)
+ * EXPECT_LE()
  *
  * @expected: expected value
  * @seen: measured value
        __EXPECT(expected, #expected, seen, #seen, <=, 0)
 
 /**
- * EXPECT_GT(expected, seen)
+ * EXPECT_GT()
  *
  * @expected: expected value
  * @seen: measured value
        __EXPECT(expected, #expected, seen, #seen, >, 0)
 
 /**
- * EXPECT_GE(expected, seen)
+ * EXPECT_GE()
  *
  * @expected: expected value
  * @seen: measured value
        __EXPECT(expected, #expected, seen, #seen, >=, 0)
 
 /**
- * EXPECT_NULL(seen)
+ * EXPECT_NULL()
  *
  * @seen: measured value
  *
        __EXPECT(NULL, "NULL", seen, #seen, ==, 0)
 
 /**
- * EXPECT_TRUE(seen)
+ * EXPECT_TRUE()
  *
  * @seen: measured value
  *
        __EXPECT(0, "0", seen, #seen, !=, 0)
 
 /**
- * EXPECT_FALSE(seen)
+ * EXPECT_FALSE()
  *
  * @seen: measured value
  *
        __EXPECT(0, "0", seen, #seen, ==, 0)
 
 /**
- * EXPECT_STREQ(expected, seen)
+ * EXPECT_STREQ()
  *
  * @expected: expected value
  * @seen: measured value
        __EXPECT_STR(expected, seen, ==, 0)
 
 /**
- * EXPECT_STRNE(expected, seen)
+ * EXPECT_STRNE()
  *
  * @expected: expected value
  * @seen: measured value
index 307ceaadbbb993664047ca469f40bb67b5816cfc..7a2c242b7152e3e56da3341f9e7efb287175b5fd 100644 (file)
@@ -1,10 +1,13 @@
 # SPDX-License-Identifier: GPL-2.0-only
+/aarch64/get-reg-list
+/aarch64/get-reg-list-sve
 /s390x/memop
 /s390x/resets
 /s390x/sync_regs_test
 /x86_64/cr4_cpuid_sync_test
 /x86_64/debug_regs
 /x86_64/evmcs_test
+/x86_64/kvm_pv_test
 /x86_64/hyperv_cpuid
 /x86_64/mmio_warning_test
 /x86_64/platform_info_test
@@ -15,6 +18,7 @@
 /x86_64/vmx_preemption_timer_test
 /x86_64/svm_vmcall_test
 /x86_64/sync_regs_test
+/x86_64/vmx_apic_access_test
 /x86_64/vmx_close_while_nested_test
 /x86_64/vmx_dirty_log_test
 /x86_64/vmx_set_nested_state_test
@@ -23,6 +27,7 @@
 /clear_dirty_log_test
 /demand_paging_test
 /dirty_log_test
+/dirty_log_perf_test
 /kvm_create_max_vcpus
 /set_memory_region_test
 /steal_time
index 7ebe71fbca534b8720056308008cf18086da5096..3d14ef77755e537c504f151decb74ad9a4d35f1c 100644 (file)
@@ -34,13 +34,14 @@ ifeq ($(ARCH),s390)
 endif
 
 LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/sparsebit.c lib/test_util.c
-LIBKVM_x86_64 = lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/svm.c lib/x86_64/ucall.c
+LIBKVM_x86_64 = lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/svm.c lib/x86_64/ucall.c lib/x86_64/handlers.S
 LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c
 LIBKVM_s390x = lib/s390x/processor.c lib/s390x/ucall.c
 
 TEST_GEN_PROGS_x86_64 = x86_64/cr4_cpuid_sync_test
 TEST_GEN_PROGS_x86_64 += x86_64/evmcs_test
 TEST_GEN_PROGS_x86_64 += x86_64/hyperv_cpuid
+TEST_GEN_PROGS_x86_64 += x86_64/kvm_pv_test
 TEST_GEN_PROGS_x86_64 += x86_64/mmio_warning_test
 TEST_GEN_PROGS_x86_64 += x86_64/platform_info_test
 TEST_GEN_PROGS_x86_64 += x86_64/set_sregs_test
@@ -49,6 +50,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/state_test
 TEST_GEN_PROGS_x86_64 += x86_64/vmx_preemption_timer_test
 TEST_GEN_PROGS_x86_64 += x86_64/svm_vmcall_test
 TEST_GEN_PROGS_x86_64 += x86_64/sync_regs_test
+TEST_GEN_PROGS_x86_64 += x86_64/vmx_apic_access_test
 TEST_GEN_PROGS_x86_64 += x86_64/vmx_close_while_nested_test
 TEST_GEN_PROGS_x86_64 += x86_64/vmx_dirty_log_test
 TEST_GEN_PROGS_x86_64 += x86_64/vmx_set_nested_state_test
@@ -57,14 +59,15 @@ TEST_GEN_PROGS_x86_64 += x86_64/xss_msr_test
 TEST_GEN_PROGS_x86_64 += x86_64/debug_regs
 TEST_GEN_PROGS_x86_64 += x86_64/tsc_msrs_test
 TEST_GEN_PROGS_x86_64 += x86_64/user_msr_test
-TEST_GEN_PROGS_x86_64 += clear_dirty_log_test
 TEST_GEN_PROGS_x86_64 += demand_paging_test
 TEST_GEN_PROGS_x86_64 += dirty_log_test
+TEST_GEN_PROGS_x86_64 += dirty_log_perf_test
 TEST_GEN_PROGS_x86_64 += kvm_create_max_vcpus
 TEST_GEN_PROGS_x86_64 += set_memory_region_test
 TEST_GEN_PROGS_x86_64 += steal_time
 
-TEST_GEN_PROGS_aarch64 += clear_dirty_log_test
+TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list
+TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list-sve
 TEST_GEN_PROGS_aarch64 += demand_paging_test
 TEST_GEN_PROGS_aarch64 += dirty_log_test
 TEST_GEN_PROGS_aarch64 += kvm_create_max_vcpus
@@ -110,14 +113,21 @@ LDFLAGS += -pthread $(no-pie-option) $(pgste-option)
 include ../lib.mk
 
 STATIC_LIBS := $(OUTPUT)/libkvm.a
-LIBKVM_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(LIBKVM))
-EXTRA_CLEAN += $(LIBKVM_OBJ) $(STATIC_LIBS) cscope.*
+LIBKVM_C := $(filter %.c,$(LIBKVM))
+LIBKVM_S := $(filter %.S,$(LIBKVM))
+LIBKVM_C_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(LIBKVM_C))
+LIBKVM_S_OBJ := $(patsubst %.S, $(OUTPUT)/%.o, $(LIBKVM_S))
+EXTRA_CLEAN += $(LIBKVM_C_OBJ) $(LIBKVM_S_OBJ) $(STATIC_LIBS) cscope.*
+
+x := $(shell mkdir -p $(sort $(dir $(LIBKVM_C_OBJ) $(LIBKVM_S_OBJ))))
+$(LIBKVM_C_OBJ): $(OUTPUT)/%.o: %.c
+       $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
 
-x := $(shell mkdir -p $(sort $(dir $(LIBKVM_OBJ))))
-$(LIBKVM_OBJ): $(OUTPUT)/%.o: %.c
+$(LIBKVM_S_OBJ): $(OUTPUT)/%.o: %.S
        $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
 
-$(OUTPUT)/libkvm.a: $(LIBKVM_OBJ)
+LIBKVM_OBJS = $(LIBKVM_C_OBJ) $(LIBKVM_S_OBJ)
+$(OUTPUT)/libkvm.a: $(LIBKVM_OBJS)
        $(AR) crs $@ $^
 
 x := $(shell mkdir -p $(sort $(dir $(TEST_GEN_PROGS))))
diff --git a/tools/testing/selftests/kvm/aarch64/get-reg-list-sve.c b/tools/testing/selftests/kvm/aarch64/get-reg-list-sve.c
new file mode 100644 (file)
index 0000000..efba766
--- /dev/null
@@ -0,0 +1,3 @@
+// SPDX-License-Identifier: GPL-2.0
+#define REG_LIST_SVE
+#include "get-reg-list.c"
diff --git a/tools/testing/selftests/kvm/aarch64/get-reg-list.c b/tools/testing/selftests/kvm/aarch64/get-reg-list.c
new file mode 100644 (file)
index 0000000..33218a3
--- /dev/null
@@ -0,0 +1,841 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Check for KVM_GET_REG_LIST regressions.
+ *
+ * Copyright (C) 2020, Red Hat, Inc.
+ *
+ * When attempting to migrate from a host with an older kernel to a host
+ * with a newer kernel we allow the newer kernel on the destination to
+ * list new registers with get-reg-list. We assume they'll be unused, at
+ * least until the guest reboots, and so they're relatively harmless.
+ * However, if the destination host with the newer kernel is missing
+ * registers which the source host with the older kernel has, then that's
+ * a regression in get-reg-list. This test checks for that regression by
+ * checking the current list against a blessed list. We should never have
+ * missing registers, but if new ones appear then they can probably be
+ * added to the blessed list. A completely new blessed list can be created
+ * by running the test with the --list command line argument.
+ *
+ * Note, the blessed list should be created from the oldest possible
+ * kernel. We can't go older than v4.15, though, because that's the first
+ * release to expose the ID system registers in KVM_GET_REG_LIST, see
+ * commit 93390c0a1b20 ("arm64: KVM: Hide unsupported AArch64 CPU features
+ * from guests"). Also, one must use the --core-reg-fixup command line
+ * option when running on an older kernel that doesn't include df205b5c6328
+ * ("KVM: arm64: Filter out invalid core register IDs in KVM_GET_REG_LIST")
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "kvm_util.h"
+#include "test_util.h"
+#include "processor.h"
+
+#ifdef REG_LIST_SVE
+#define reg_list_sve() (true)
+#else
+#define reg_list_sve() (false)
+#endif
+
+#define REG_MASK (KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_COPROC_MASK)
+
+#define for_each_reg(i)                                                                \
+       for ((i) = 0; (i) < reg_list->n; ++(i))
+
+#define for_each_missing_reg(i)                                                        \
+       for ((i) = 0; (i) < blessed_n; ++(i))                                   \
+               if (!find_reg(reg_list->reg, reg_list->n, blessed_reg[i]))
+
+#define for_each_new_reg(i)                                                    \
+       for ((i) = 0; (i) < reg_list->n; ++(i))                                 \
+               if (!find_reg(blessed_reg, blessed_n, reg_list->reg[i]))
+
+
+static struct kvm_reg_list *reg_list;
+
+static __u64 base_regs[], vregs[], sve_regs[], rejects_set[];
+static __u64 base_regs_n, vregs_n, sve_regs_n, rejects_set_n;
+static __u64 *blessed_reg, blessed_n;
+
+static bool find_reg(__u64 regs[], __u64 nr_regs, __u64 reg)
+{
+       int i;
+
+       for (i = 0; i < nr_regs; ++i)
+               if (reg == regs[i])
+                       return true;
+       return false;
+}
+
+static const char *str_with_index(const char *template, __u64 index)
+{
+       char *str, *p;
+       int n;
+
+       str = strdup(template);
+       p = strstr(str, "##");
+       n = sprintf(p, "%lld", index);
+       strcat(p + n, strstr(template, "##") + 2);
+
+       return (const char *)str;
+}
+
+#define CORE_REGS_XX_NR_WORDS  2
+#define CORE_SPSR_XX_NR_WORDS  2
+#define CORE_FPREGS_XX_NR_WORDS        4
+
+static const char *core_id_to_str(__u64 id)
+{
+       __u64 core_off = id & ~REG_MASK, idx;
+
+       /*
+        * core_off is the offset into struct kvm_regs
+        */
+       switch (core_off) {
+       case KVM_REG_ARM_CORE_REG(regs.regs[0]) ...
+            KVM_REG_ARM_CORE_REG(regs.regs[30]):
+               idx = (core_off - KVM_REG_ARM_CORE_REG(regs.regs[0])) / CORE_REGS_XX_NR_WORDS;
+               TEST_ASSERT(idx < 31, "Unexpected regs.regs index: %lld", idx);
+               return str_with_index("KVM_REG_ARM_CORE_REG(regs.regs[##])", idx);
+       case KVM_REG_ARM_CORE_REG(regs.sp):
+               return "KVM_REG_ARM_CORE_REG(regs.sp)";
+       case KVM_REG_ARM_CORE_REG(regs.pc):
+               return "KVM_REG_ARM_CORE_REG(regs.pc)";
+       case KVM_REG_ARM_CORE_REG(regs.pstate):
+               return "KVM_REG_ARM_CORE_REG(regs.pstate)";
+       case KVM_REG_ARM_CORE_REG(sp_el1):
+               return "KVM_REG_ARM_CORE_REG(sp_el1)";
+       case KVM_REG_ARM_CORE_REG(elr_el1):
+               return "KVM_REG_ARM_CORE_REG(elr_el1)";
+       case KVM_REG_ARM_CORE_REG(spsr[0]) ...
+            KVM_REG_ARM_CORE_REG(spsr[KVM_NR_SPSR - 1]):
+               idx = (core_off - KVM_REG_ARM_CORE_REG(spsr[0])) / CORE_SPSR_XX_NR_WORDS;
+               TEST_ASSERT(idx < KVM_NR_SPSR, "Unexpected spsr index: %lld", idx);
+               return str_with_index("KVM_REG_ARM_CORE_REG(spsr[##])", idx);
+       case KVM_REG_ARM_CORE_REG(fp_regs.vregs[0]) ...
+            KVM_REG_ARM_CORE_REG(fp_regs.vregs[31]):
+               idx = (core_off - KVM_REG_ARM_CORE_REG(fp_regs.vregs[0])) / CORE_FPREGS_XX_NR_WORDS;
+               TEST_ASSERT(idx < 32, "Unexpected fp_regs.vregs index: %lld", idx);
+               return str_with_index("KVM_REG_ARM_CORE_REG(fp_regs.vregs[##])", idx);
+       case KVM_REG_ARM_CORE_REG(fp_regs.fpsr):
+               return "KVM_REG_ARM_CORE_REG(fp_regs.fpsr)";
+       case KVM_REG_ARM_CORE_REG(fp_regs.fpcr):
+               return "KVM_REG_ARM_CORE_REG(fp_regs.fpcr)";
+       }
+
+       TEST_FAIL("Unknown core reg id: 0x%llx", id);
+       return NULL;
+}
+
+static const char *sve_id_to_str(__u64 id)
+{
+       __u64 sve_off, n, i;
+
+       if (id == KVM_REG_ARM64_SVE_VLS)
+               return "KVM_REG_ARM64_SVE_VLS";
+
+       sve_off = id & ~(REG_MASK | ((1ULL << 5) - 1));
+       i = id & (KVM_ARM64_SVE_MAX_SLICES - 1);
+
+       TEST_ASSERT(i == 0, "Currently we don't expect slice > 0, reg id 0x%llx", id);
+
+       switch (sve_off) {
+       case KVM_REG_ARM64_SVE_ZREG_BASE ...
+            KVM_REG_ARM64_SVE_ZREG_BASE + (1ULL << 5) * KVM_ARM64_SVE_NUM_ZREGS - 1:
+               n = (id >> 5) & (KVM_ARM64_SVE_NUM_ZREGS - 1);
+               TEST_ASSERT(id == KVM_REG_ARM64_SVE_ZREG(n, 0),
+                           "Unexpected bits set in SVE ZREG id: 0x%llx", id);
+               return str_with_index("KVM_REG_ARM64_SVE_ZREG(##, 0)", n);
+       case KVM_REG_ARM64_SVE_PREG_BASE ...
+            KVM_REG_ARM64_SVE_PREG_BASE + (1ULL << 5) * KVM_ARM64_SVE_NUM_PREGS - 1:
+               n = (id >> 5) & (KVM_ARM64_SVE_NUM_PREGS - 1);
+               TEST_ASSERT(id == KVM_REG_ARM64_SVE_PREG(n, 0),
+                           "Unexpected bits set in SVE PREG id: 0x%llx", id);
+               return str_with_index("KVM_REG_ARM64_SVE_PREG(##, 0)", n);
+       case KVM_REG_ARM64_SVE_FFR_BASE:
+               TEST_ASSERT(id == KVM_REG_ARM64_SVE_FFR(0),
+                           "Unexpected bits set in SVE FFR id: 0x%llx", id);
+               return "KVM_REG_ARM64_SVE_FFR(0)";
+       }
+
+       return NULL;
+}
+
+static void print_reg(__u64 id)
+{
+       unsigned op0, op1, crn, crm, op2;
+       const char *reg_size = NULL;
+
+       TEST_ASSERT((id & KVM_REG_ARCH_MASK) == KVM_REG_ARM64,
+                   "KVM_REG_ARM64 missing in reg id: 0x%llx", id);
+
+       switch (id & KVM_REG_SIZE_MASK) {
+       case KVM_REG_SIZE_U8:
+               reg_size = "KVM_REG_SIZE_U8";
+               break;
+       case KVM_REG_SIZE_U16:
+               reg_size = "KVM_REG_SIZE_U16";
+               break;
+       case KVM_REG_SIZE_U32:
+               reg_size = "KVM_REG_SIZE_U32";
+               break;
+       case KVM_REG_SIZE_U64:
+               reg_size = "KVM_REG_SIZE_U64";
+               break;
+       case KVM_REG_SIZE_U128:
+               reg_size = "KVM_REG_SIZE_U128";
+               break;
+       case KVM_REG_SIZE_U256:
+               reg_size = "KVM_REG_SIZE_U256";
+               break;
+       case KVM_REG_SIZE_U512:
+               reg_size = "KVM_REG_SIZE_U512";
+               break;
+       case KVM_REG_SIZE_U1024:
+               reg_size = "KVM_REG_SIZE_U1024";
+               break;
+       case KVM_REG_SIZE_U2048:
+               reg_size = "KVM_REG_SIZE_U2048";
+               break;
+       default:
+               TEST_FAIL("Unexpected reg size: 0x%llx in reg id: 0x%llx",
+                         (id & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT, id);
+       }
+
+       switch (id & KVM_REG_ARM_COPROC_MASK) {
+       case KVM_REG_ARM_CORE:
+               printf("\tKVM_REG_ARM64 | %s | KVM_REG_ARM_CORE | %s,\n", reg_size, core_id_to_str(id));
+               break;
+       case KVM_REG_ARM_DEMUX:
+               TEST_ASSERT(!(id & ~(REG_MASK | KVM_REG_ARM_DEMUX_ID_MASK | KVM_REG_ARM_DEMUX_VAL_MASK)),
+                           "Unexpected bits set in DEMUX reg id: 0x%llx", id);
+               printf("\tKVM_REG_ARM64 | %s | KVM_REG_ARM_DEMUX | KVM_REG_ARM_DEMUX_ID_CCSIDR | %lld,\n",
+                      reg_size, id & KVM_REG_ARM_DEMUX_VAL_MASK);
+               break;
+       case KVM_REG_ARM64_SYSREG:
+               op0 = (id & KVM_REG_ARM64_SYSREG_OP0_MASK) >> KVM_REG_ARM64_SYSREG_OP0_SHIFT;
+               op1 = (id & KVM_REG_ARM64_SYSREG_OP1_MASK) >> KVM_REG_ARM64_SYSREG_OP1_SHIFT;
+               crn = (id & KVM_REG_ARM64_SYSREG_CRN_MASK) >> KVM_REG_ARM64_SYSREG_CRN_SHIFT;
+               crm = (id & KVM_REG_ARM64_SYSREG_CRM_MASK) >> KVM_REG_ARM64_SYSREG_CRM_SHIFT;
+               op2 = (id & KVM_REG_ARM64_SYSREG_OP2_MASK) >> KVM_REG_ARM64_SYSREG_OP2_SHIFT;
+               TEST_ASSERT(id == ARM64_SYS_REG(op0, op1, crn, crm, op2),
+                           "Unexpected bits set in SYSREG reg id: 0x%llx", id);
+               printf("\tARM64_SYS_REG(%d, %d, %d, %d, %d),\n", op0, op1, crn, crm, op2);
+               break;
+       case KVM_REG_ARM_FW:
+               TEST_ASSERT(id == KVM_REG_ARM_FW_REG(id & 0xffff),
+                           "Unexpected bits set in FW reg id: 0x%llx", id);
+               printf("\tKVM_REG_ARM_FW_REG(%lld),\n", id & 0xffff);
+               break;
+       case KVM_REG_ARM64_SVE:
+               if (reg_list_sve())
+                       printf("\t%s,\n", sve_id_to_str(id));
+               else
+                       TEST_FAIL("KVM_REG_ARM64_SVE is an unexpected coproc type in reg id: 0x%llx", id);
+               break;
+       default:
+               TEST_FAIL("Unexpected coproc type: 0x%llx in reg id: 0x%llx",
+                         (id & KVM_REG_ARM_COPROC_MASK) >> KVM_REG_ARM_COPROC_SHIFT, id);
+       }
+}
+
+/*
+ * Older kernels listed each 32-bit word of CORE registers separately.
+ * For 64 and 128-bit registers we need to ignore the extra words. We
+ * also need to fixup the sizes, because the older kernels stated all
+ * registers were 64-bit, even when they weren't.
+ */
+static void core_reg_fixup(void)
+{
+       struct kvm_reg_list *tmp;
+       __u64 id, core_off;
+       int i;
+
+       tmp = calloc(1, sizeof(*tmp) + reg_list->n * sizeof(__u64));
+
+       for (i = 0; i < reg_list->n; ++i) {
+               id = reg_list->reg[i];
+
+               if ((id & KVM_REG_ARM_COPROC_MASK) != KVM_REG_ARM_CORE) {
+                       tmp->reg[tmp->n++] = id;
+                       continue;
+               }
+
+               core_off = id & ~REG_MASK;
+
+               switch (core_off) {
+               case 0x52: case 0xd2: case 0xd6:
+                       /*
+                        * These offsets are pointing at padding.
+                        * We need to ignore them too.
+                        */
+                       continue;
+               case KVM_REG_ARM_CORE_REG(fp_regs.vregs[0]) ...
+                    KVM_REG_ARM_CORE_REG(fp_regs.vregs[31]):
+                       if (core_off & 3)
+                               continue;
+                       id &= ~KVM_REG_SIZE_MASK;
+                       id |= KVM_REG_SIZE_U128;
+                       tmp->reg[tmp->n++] = id;
+                       continue;
+               case KVM_REG_ARM_CORE_REG(fp_regs.fpsr):
+               case KVM_REG_ARM_CORE_REG(fp_regs.fpcr):
+                       id &= ~KVM_REG_SIZE_MASK;
+                       id |= KVM_REG_SIZE_U32;
+                       tmp->reg[tmp->n++] = id;
+                       continue;
+               default:
+                       if (core_off & 1)
+                               continue;
+                       tmp->reg[tmp->n++] = id;
+                       break;
+               }
+       }
+
+       free(reg_list);
+       reg_list = tmp;
+}
+
+static void prepare_vcpu_init(struct kvm_vcpu_init *init)
+{
+       if (reg_list_sve())
+               init->features[0] |= 1 << KVM_ARM_VCPU_SVE;
+}
+
+static void finalize_vcpu(struct kvm_vm *vm, uint32_t vcpuid)
+{
+       int feature;
+
+       if (reg_list_sve()) {
+               feature = KVM_ARM_VCPU_SVE;
+               vcpu_ioctl(vm, vcpuid, KVM_ARM_VCPU_FINALIZE, &feature);
+       }
+}
+
+static void check_supported(void)
+{
+       if (reg_list_sve() && !kvm_check_cap(KVM_CAP_ARM_SVE)) {
+               fprintf(stderr, "SVE not available, skipping tests\n");
+               exit(KSFT_SKIP);
+       }
+}
+
+int main(int ac, char **av)
+{
+       struct kvm_vcpu_init init = { .target = -1, };
+       int new_regs = 0, missing_regs = 0, i;
+       int failed_get = 0, failed_set = 0, failed_reject = 0;
+       bool print_list = false, fixup_core_regs = false;
+       struct kvm_vm *vm;
+       __u64 *vec_regs;
+
+       check_supported();
+
+       for (i = 1; i < ac; ++i) {
+               if (strcmp(av[i], "--core-reg-fixup") == 0)
+                       fixup_core_regs = true;
+               else if (strcmp(av[i], "--list") == 0)
+                       print_list = true;
+               else
+                       fprintf(stderr, "Ignoring unknown option: %s\n", av[i]);
+       }
+
+       vm = vm_create(VM_MODE_DEFAULT, DEFAULT_GUEST_PHY_PAGES, O_RDWR);
+       prepare_vcpu_init(&init);
+       aarch64_vcpu_add_default(vm, 0, &init, NULL);
+       finalize_vcpu(vm, 0);
+
+       reg_list = vcpu_get_reg_list(vm, 0);
+
+       if (fixup_core_regs)
+               core_reg_fixup();
+
+       if (print_list) {
+               putchar('\n');
+               for_each_reg(i)
+                       print_reg(reg_list->reg[i]);
+               putchar('\n');
+               return 0;
+       }
+
+       /*
+        * We only test that we can get the register and then write back the
+        * same value. Some registers may allow other values to be written
+        * back, but others only allow some bits to be changed, and at least
+        * for ID registers set will fail if the value does not exactly match
+        * what was returned by get. If registers that allow other values to
+        * be written need to have the other values tested, then we should
+        * create a new set of tests for those in a new independent test
+        * executable.
+        */
+       for_each_reg(i) {
+               uint8_t addr[2048 / 8];
+               struct kvm_one_reg reg = {
+                       .id = reg_list->reg[i],
+                       .addr = (__u64)&addr,
+               };
+               int ret;
+
+               ret = _vcpu_ioctl(vm, 0, KVM_GET_ONE_REG, &reg);
+               if (ret) {
+                       puts("Failed to get ");
+                       print_reg(reg.id);
+                       putchar('\n');
+                       ++failed_get;
+               }
+
+               /* rejects_set registers are rejected after KVM_ARM_VCPU_FINALIZE */
+               if (find_reg(rejects_set, rejects_set_n, reg.id)) {
+                       ret = _vcpu_ioctl(vm, 0, KVM_SET_ONE_REG, &reg);
+                       if (ret != -1 || errno != EPERM) {
+                               printf("Failed to reject (ret=%d, errno=%d) ", ret, errno);
+                               print_reg(reg.id);
+                               putchar('\n');
+                               ++failed_reject;
+                       }
+                       continue;
+               }
+
+               ret = _vcpu_ioctl(vm, 0, KVM_SET_ONE_REG, &reg);
+               if (ret) {
+                       puts("Failed to set ");
+                       print_reg(reg.id);
+                       putchar('\n');
+                       ++failed_set;
+               }
+       }
+
+       if (reg_list_sve()) {
+               blessed_n = base_regs_n + sve_regs_n;
+               vec_regs = sve_regs;
+       } else {
+               blessed_n = base_regs_n + vregs_n;
+               vec_regs = vregs;
+       }
+
+       blessed_reg = calloc(blessed_n, sizeof(__u64));
+       for (i = 0; i < base_regs_n; ++i)
+               blessed_reg[i] = base_regs[i];
+       for (i = 0; i < blessed_n - base_regs_n; ++i)
+               blessed_reg[base_regs_n + i] = vec_regs[i];
+
+       for_each_new_reg(i)
+               ++new_regs;
+
+       for_each_missing_reg(i)
+               ++missing_regs;
+
+       if (new_regs || missing_regs) {
+               printf("Number blessed registers: %5lld\n", blessed_n);
+               printf("Number registers:         %5lld\n", reg_list->n);
+       }
+
+       if (new_regs) {
+               printf("\nThere are %d new registers.\n"
+                      "Consider adding them to the blessed reg "
+                      "list with the following lines:\n\n", new_regs);
+               for_each_new_reg(i)
+                       print_reg(reg_list->reg[i]);
+               putchar('\n');
+       }
+
+       if (missing_regs) {
+               printf("\nThere are %d missing registers.\n"
+                      "The following lines are missing registers:\n\n", missing_regs);
+               for_each_missing_reg(i)
+                       print_reg(blessed_reg[i]);
+               putchar('\n');
+       }
+
+       TEST_ASSERT(!missing_regs && !failed_get && !failed_set && !failed_reject,
+                   "There are %d missing registers; "
+                   "%d registers failed get; %d registers failed set; %d registers failed reject",
+                   missing_regs, failed_get, failed_set, failed_reject);
+
+       return 0;
+}
+
+/*
+ * The current blessed list was primed with the output of kernel version
+ * v4.15 with --core-reg-fixup and then later updated with new registers.
+ */
+static __u64 base_regs[] = {
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[0]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[1]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[2]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[3]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[4]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[5]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[6]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[7]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[8]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[9]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[10]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[11]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[12]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[13]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[14]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[15]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[16]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[17]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[18]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[19]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[20]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[21]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[22]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[23]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[24]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[25]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[26]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[27]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[28]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[29]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[30]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.sp),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.pc),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.pstate),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(sp_el1),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(elr_el1),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(spsr[0]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(spsr[1]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(spsr[2]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(spsr[3]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(spsr[4]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.fpsr),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.fpcr),
+       KVM_REG_ARM_FW_REG(0),
+       KVM_REG_ARM_FW_REG(1),
+       KVM_REG_ARM_FW_REG(2),
+       ARM64_SYS_REG(3, 3, 14, 3, 1),  /* CNTV_CTL_EL0 */
+       ARM64_SYS_REG(3, 3, 14, 3, 2),  /* CNTV_CVAL_EL0 */
+       ARM64_SYS_REG(3, 3, 14, 0, 2),
+       ARM64_SYS_REG(3, 0, 0, 0, 0),   /* MIDR_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 0, 6),   /* REVIDR_EL1 */
+       ARM64_SYS_REG(3, 1, 0, 0, 1),   /* CLIDR_EL1 */
+       ARM64_SYS_REG(3, 1, 0, 0, 7),   /* AIDR_EL1 */
+       ARM64_SYS_REG(3, 3, 0, 0, 1),   /* CTR_EL0 */
+       ARM64_SYS_REG(2, 0, 0, 0, 4),
+       ARM64_SYS_REG(2, 0, 0, 0, 5),
+       ARM64_SYS_REG(2, 0, 0, 0, 6),
+       ARM64_SYS_REG(2, 0, 0, 0, 7),
+       ARM64_SYS_REG(2, 0, 0, 1, 4),
+       ARM64_SYS_REG(2, 0, 0, 1, 5),
+       ARM64_SYS_REG(2, 0, 0, 1, 6),
+       ARM64_SYS_REG(2, 0, 0, 1, 7),
+       ARM64_SYS_REG(2, 0, 0, 2, 0),   /* MDCCINT_EL1 */
+       ARM64_SYS_REG(2, 0, 0, 2, 2),   /* MDSCR_EL1 */
+       ARM64_SYS_REG(2, 0, 0, 2, 4),
+       ARM64_SYS_REG(2, 0, 0, 2, 5),
+       ARM64_SYS_REG(2, 0, 0, 2, 6),
+       ARM64_SYS_REG(2, 0, 0, 2, 7),
+       ARM64_SYS_REG(2, 0, 0, 3, 4),
+       ARM64_SYS_REG(2, 0, 0, 3, 5),
+       ARM64_SYS_REG(2, 0, 0, 3, 6),
+       ARM64_SYS_REG(2, 0, 0, 3, 7),
+       ARM64_SYS_REG(2, 0, 0, 4, 4),
+       ARM64_SYS_REG(2, 0, 0, 4, 5),
+       ARM64_SYS_REG(2, 0, 0, 4, 6),
+       ARM64_SYS_REG(2, 0, 0, 4, 7),
+       ARM64_SYS_REG(2, 0, 0, 5, 4),
+       ARM64_SYS_REG(2, 0, 0, 5, 5),
+       ARM64_SYS_REG(2, 0, 0, 5, 6),
+       ARM64_SYS_REG(2, 0, 0, 5, 7),
+       ARM64_SYS_REG(2, 0, 0, 6, 4),
+       ARM64_SYS_REG(2, 0, 0, 6, 5),
+       ARM64_SYS_REG(2, 0, 0, 6, 6),
+       ARM64_SYS_REG(2, 0, 0, 6, 7),
+       ARM64_SYS_REG(2, 0, 0, 7, 4),
+       ARM64_SYS_REG(2, 0, 0, 7, 5),
+       ARM64_SYS_REG(2, 0, 0, 7, 6),
+       ARM64_SYS_REG(2, 0, 0, 7, 7),
+       ARM64_SYS_REG(2, 0, 0, 8, 4),
+       ARM64_SYS_REG(2, 0, 0, 8, 5),
+       ARM64_SYS_REG(2, 0, 0, 8, 6),
+       ARM64_SYS_REG(2, 0, 0, 8, 7),
+       ARM64_SYS_REG(2, 0, 0, 9, 4),
+       ARM64_SYS_REG(2, 0, 0, 9, 5),
+       ARM64_SYS_REG(2, 0, 0, 9, 6),
+       ARM64_SYS_REG(2, 0, 0, 9, 7),
+       ARM64_SYS_REG(2, 0, 0, 10, 4),
+       ARM64_SYS_REG(2, 0, 0, 10, 5),
+       ARM64_SYS_REG(2, 0, 0, 10, 6),
+       ARM64_SYS_REG(2, 0, 0, 10, 7),
+       ARM64_SYS_REG(2, 0, 0, 11, 4),
+       ARM64_SYS_REG(2, 0, 0, 11, 5),
+       ARM64_SYS_REG(2, 0, 0, 11, 6),
+       ARM64_SYS_REG(2, 0, 0, 11, 7),
+       ARM64_SYS_REG(2, 0, 0, 12, 4),
+       ARM64_SYS_REG(2, 0, 0, 12, 5),
+       ARM64_SYS_REG(2, 0, 0, 12, 6),
+       ARM64_SYS_REG(2, 0, 0, 12, 7),
+       ARM64_SYS_REG(2, 0, 0, 13, 4),
+       ARM64_SYS_REG(2, 0, 0, 13, 5),
+       ARM64_SYS_REG(2, 0, 0, 13, 6),
+       ARM64_SYS_REG(2, 0, 0, 13, 7),
+       ARM64_SYS_REG(2, 0, 0, 14, 4),
+       ARM64_SYS_REG(2, 0, 0, 14, 5),
+       ARM64_SYS_REG(2, 0, 0, 14, 6),
+       ARM64_SYS_REG(2, 0, 0, 14, 7),
+       ARM64_SYS_REG(2, 0, 0, 15, 4),
+       ARM64_SYS_REG(2, 0, 0, 15, 5),
+       ARM64_SYS_REG(2, 0, 0, 15, 6),
+       ARM64_SYS_REG(2, 0, 0, 15, 7),
+       ARM64_SYS_REG(2, 4, 0, 7, 0),   /* DBGVCR32_EL2 */
+       ARM64_SYS_REG(3, 0, 0, 0, 5),   /* MPIDR_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 1, 0),   /* ID_PFR0_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 1, 1),   /* ID_PFR1_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 1, 2),   /* ID_DFR0_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 1, 3),   /* ID_AFR0_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 1, 4),   /* ID_MMFR0_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 1, 5),   /* ID_MMFR1_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 1, 6),   /* ID_MMFR2_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 1, 7),   /* ID_MMFR3_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 2, 0),   /* ID_ISAR0_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 2, 1),   /* ID_ISAR1_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 2, 2),   /* ID_ISAR2_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 2, 3),   /* ID_ISAR3_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 2, 4),   /* ID_ISAR4_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 2, 5),   /* ID_ISAR5_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 2, 6),   /* ID_MMFR4_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 2, 7),   /* ID_ISAR6_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 3, 0),   /* MVFR0_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 3, 1),   /* MVFR1_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 3, 2),   /* MVFR2_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 3, 3),
+       ARM64_SYS_REG(3, 0, 0, 3, 4),   /* ID_PFR2_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 3, 5),   /* ID_DFR1_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 3, 6),   /* ID_MMFR5_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 3, 7),
+       ARM64_SYS_REG(3, 0, 0, 4, 0),   /* ID_AA64PFR0_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 4, 1),   /* ID_AA64PFR1_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 4, 2),
+       ARM64_SYS_REG(3, 0, 0, 4, 3),
+       ARM64_SYS_REG(3, 0, 0, 4, 4),   /* ID_AA64ZFR0_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 4, 5),
+       ARM64_SYS_REG(3, 0, 0, 4, 6),
+       ARM64_SYS_REG(3, 0, 0, 4, 7),
+       ARM64_SYS_REG(3, 0, 0, 5, 0),   /* ID_AA64DFR0_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 5, 1),   /* ID_AA64DFR1_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 5, 2),
+       ARM64_SYS_REG(3, 0, 0, 5, 3),
+       ARM64_SYS_REG(3, 0, 0, 5, 4),   /* ID_AA64AFR0_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 5, 5),   /* ID_AA64AFR1_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 5, 6),
+       ARM64_SYS_REG(3, 0, 0, 5, 7),
+       ARM64_SYS_REG(3, 0, 0, 6, 0),   /* ID_AA64ISAR0_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 6, 1),   /* ID_AA64ISAR1_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 6, 2),
+       ARM64_SYS_REG(3, 0, 0, 6, 3),
+       ARM64_SYS_REG(3, 0, 0, 6, 4),
+       ARM64_SYS_REG(3, 0, 0, 6, 5),
+       ARM64_SYS_REG(3, 0, 0, 6, 6),
+       ARM64_SYS_REG(3, 0, 0, 6, 7),
+       ARM64_SYS_REG(3, 0, 0, 7, 0),   /* ID_AA64MMFR0_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 7, 1),   /* ID_AA64MMFR1_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 7, 2),   /* ID_AA64MMFR2_EL1 */
+       ARM64_SYS_REG(3, 0, 0, 7, 3),
+       ARM64_SYS_REG(3, 0, 0, 7, 4),
+       ARM64_SYS_REG(3, 0, 0, 7, 5),
+       ARM64_SYS_REG(3, 0, 0, 7, 6),
+       ARM64_SYS_REG(3, 0, 0, 7, 7),
+       ARM64_SYS_REG(3, 0, 1, 0, 0),   /* SCTLR_EL1 */
+       ARM64_SYS_REG(3, 0, 1, 0, 1),   /* ACTLR_EL1 */
+       ARM64_SYS_REG(3, 0, 1, 0, 2),   /* CPACR_EL1 */
+       ARM64_SYS_REG(3, 0, 2, 0, 0),   /* TTBR0_EL1 */
+       ARM64_SYS_REG(3, 0, 2, 0, 1),   /* TTBR1_EL1 */
+       ARM64_SYS_REG(3, 0, 2, 0, 2),   /* TCR_EL1 */
+       ARM64_SYS_REG(3, 0, 5, 1, 0),   /* AFSR0_EL1 */
+       ARM64_SYS_REG(3, 0, 5, 1, 1),   /* AFSR1_EL1 */
+       ARM64_SYS_REG(3, 0, 5, 2, 0),   /* ESR_EL1 */
+       ARM64_SYS_REG(3, 0, 6, 0, 0),   /* FAR_EL1 */
+       ARM64_SYS_REG(3, 0, 7, 4, 0),   /* PAR_EL1 */
+       ARM64_SYS_REG(3, 0, 9, 14, 1),  /* PMINTENSET_EL1 */
+       ARM64_SYS_REG(3, 0, 9, 14, 2),  /* PMINTENCLR_EL1 */
+       ARM64_SYS_REG(3, 0, 10, 2, 0),  /* MAIR_EL1 */
+       ARM64_SYS_REG(3, 0, 10, 3, 0),  /* AMAIR_EL1 */
+       ARM64_SYS_REG(3, 0, 12, 0, 0),  /* VBAR_EL1 */
+       ARM64_SYS_REG(3, 0, 12, 1, 1),  /* DISR_EL1 */
+       ARM64_SYS_REG(3, 0, 13, 0, 1),  /* CONTEXTIDR_EL1 */
+       ARM64_SYS_REG(3, 0, 13, 0, 4),  /* TPIDR_EL1 */
+       ARM64_SYS_REG(3, 0, 14, 1, 0),  /* CNTKCTL_EL1 */
+       ARM64_SYS_REG(3, 2, 0, 0, 0),   /* CSSELR_EL1 */
+       ARM64_SYS_REG(3, 3, 9, 12, 0),  /* PMCR_EL0 */
+       ARM64_SYS_REG(3, 3, 9, 12, 1),  /* PMCNTENSET_EL0 */
+       ARM64_SYS_REG(3, 3, 9, 12, 2),  /* PMCNTENCLR_EL0 */
+       ARM64_SYS_REG(3, 3, 9, 12, 3),  /* PMOVSCLR_EL0 */
+       ARM64_SYS_REG(3, 3, 9, 12, 4),  /* PMSWINC_EL0 */
+       ARM64_SYS_REG(3, 3, 9, 12, 5),  /* PMSELR_EL0 */
+       ARM64_SYS_REG(3, 3, 9, 13, 0),  /* PMCCNTR_EL0 */
+       ARM64_SYS_REG(3, 3, 9, 14, 0),  /* PMUSERENR_EL0 */
+       ARM64_SYS_REG(3, 3, 9, 14, 3),  /* PMOVSSET_EL0 */
+       ARM64_SYS_REG(3, 3, 13, 0, 2),  /* TPIDR_EL0 */
+       ARM64_SYS_REG(3, 3, 13, 0, 3),  /* TPIDRRO_EL0 */
+       ARM64_SYS_REG(3, 3, 14, 8, 0),
+       ARM64_SYS_REG(3, 3, 14, 8, 1),
+       ARM64_SYS_REG(3, 3, 14, 8, 2),
+       ARM64_SYS_REG(3, 3, 14, 8, 3),
+       ARM64_SYS_REG(3, 3, 14, 8, 4),
+       ARM64_SYS_REG(3, 3, 14, 8, 5),
+       ARM64_SYS_REG(3, 3, 14, 8, 6),
+       ARM64_SYS_REG(3, 3, 14, 8, 7),
+       ARM64_SYS_REG(3, 3, 14, 9, 0),
+       ARM64_SYS_REG(3, 3, 14, 9, 1),
+       ARM64_SYS_REG(3, 3, 14, 9, 2),
+       ARM64_SYS_REG(3, 3, 14, 9, 3),
+       ARM64_SYS_REG(3, 3, 14, 9, 4),
+       ARM64_SYS_REG(3, 3, 14, 9, 5),
+       ARM64_SYS_REG(3, 3, 14, 9, 6),
+       ARM64_SYS_REG(3, 3, 14, 9, 7),
+       ARM64_SYS_REG(3, 3, 14, 10, 0),
+       ARM64_SYS_REG(3, 3, 14, 10, 1),
+       ARM64_SYS_REG(3, 3, 14, 10, 2),
+       ARM64_SYS_REG(3, 3, 14, 10, 3),
+       ARM64_SYS_REG(3, 3, 14, 10, 4),
+       ARM64_SYS_REG(3, 3, 14, 10, 5),
+       ARM64_SYS_REG(3, 3, 14, 10, 6),
+       ARM64_SYS_REG(3, 3, 14, 10, 7),
+       ARM64_SYS_REG(3, 3, 14, 11, 0),
+       ARM64_SYS_REG(3, 3, 14, 11, 1),
+       ARM64_SYS_REG(3, 3, 14, 11, 2),
+       ARM64_SYS_REG(3, 3, 14, 11, 3),
+       ARM64_SYS_REG(3, 3, 14, 11, 4),
+       ARM64_SYS_REG(3, 3, 14, 11, 5),
+       ARM64_SYS_REG(3, 3, 14, 11, 6),
+       ARM64_SYS_REG(3, 3, 14, 12, 0),
+       ARM64_SYS_REG(3, 3, 14, 12, 1),
+       ARM64_SYS_REG(3, 3, 14, 12, 2),
+       ARM64_SYS_REG(3, 3, 14, 12, 3),
+       ARM64_SYS_REG(3, 3, 14, 12, 4),
+       ARM64_SYS_REG(3, 3, 14, 12, 5),
+       ARM64_SYS_REG(3, 3, 14, 12, 6),
+       ARM64_SYS_REG(3, 3, 14, 12, 7),
+       ARM64_SYS_REG(3, 3, 14, 13, 0),
+       ARM64_SYS_REG(3, 3, 14, 13, 1),
+       ARM64_SYS_REG(3, 3, 14, 13, 2),
+       ARM64_SYS_REG(3, 3, 14, 13, 3),
+       ARM64_SYS_REG(3, 3, 14, 13, 4),
+       ARM64_SYS_REG(3, 3, 14, 13, 5),
+       ARM64_SYS_REG(3, 3, 14, 13, 6),
+       ARM64_SYS_REG(3, 3, 14, 13, 7),
+       ARM64_SYS_REG(3, 3, 14, 14, 0),
+       ARM64_SYS_REG(3, 3, 14, 14, 1),
+       ARM64_SYS_REG(3, 3, 14, 14, 2),
+       ARM64_SYS_REG(3, 3, 14, 14, 3),
+       ARM64_SYS_REG(3, 3, 14, 14, 4),
+       ARM64_SYS_REG(3, 3, 14, 14, 5),
+       ARM64_SYS_REG(3, 3, 14, 14, 6),
+       ARM64_SYS_REG(3, 3, 14, 14, 7),
+       ARM64_SYS_REG(3, 3, 14, 15, 0),
+       ARM64_SYS_REG(3, 3, 14, 15, 1),
+       ARM64_SYS_REG(3, 3, 14, 15, 2),
+       ARM64_SYS_REG(3, 3, 14, 15, 3),
+       ARM64_SYS_REG(3, 3, 14, 15, 4),
+       ARM64_SYS_REG(3, 3, 14, 15, 5),
+       ARM64_SYS_REG(3, 3, 14, 15, 6),
+       ARM64_SYS_REG(3, 3, 14, 15, 7), /* PMCCFILTR_EL0 */
+       ARM64_SYS_REG(3, 4, 3, 0, 0),   /* DACR32_EL2 */
+       ARM64_SYS_REG(3, 4, 5, 0, 1),   /* IFSR32_EL2 */
+       ARM64_SYS_REG(3, 4, 5, 3, 0),   /* FPEXC32_EL2 */
+       KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX | KVM_REG_ARM_DEMUX_ID_CCSIDR | 0,
+       KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX | KVM_REG_ARM_DEMUX_ID_CCSIDR | 1,
+       KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX | KVM_REG_ARM_DEMUX_ID_CCSIDR | 2,
+};
+static __u64 base_regs_n = ARRAY_SIZE(base_regs);
+
+static __u64 vregs[] = {
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[0]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[1]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[2]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[3]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[4]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[5]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[6]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[7]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[8]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[9]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[10]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[11]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[12]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[13]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[14]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[15]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[16]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[17]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[18]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[19]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[20]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[21]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[22]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[23]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[24]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[25]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[26]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[27]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[28]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[29]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[30]),
+       KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[31]),
+};
+static __u64 vregs_n = ARRAY_SIZE(vregs);
+
+static __u64 sve_regs[] = {
+       KVM_REG_ARM64_SVE_VLS,
+       KVM_REG_ARM64_SVE_ZREG(0, 0),
+       KVM_REG_ARM64_SVE_ZREG(1, 0),
+       KVM_REG_ARM64_SVE_ZREG(2, 0),
+       KVM_REG_ARM64_SVE_ZREG(3, 0),
+       KVM_REG_ARM64_SVE_ZREG(4, 0),
+       KVM_REG_ARM64_SVE_ZREG(5, 0),
+       KVM_REG_ARM64_SVE_ZREG(6, 0),
+       KVM_REG_ARM64_SVE_ZREG(7, 0),
+       KVM_REG_ARM64_SVE_ZREG(8, 0),
+       KVM_REG_ARM64_SVE_ZREG(9, 0),
+       KVM_REG_ARM64_SVE_ZREG(10, 0),
+       KVM_REG_ARM64_SVE_ZREG(11, 0),
+       KVM_REG_ARM64_SVE_ZREG(12, 0),
+       KVM_REG_ARM64_SVE_ZREG(13, 0),
+       KVM_REG_ARM64_SVE_ZREG(14, 0),
+       KVM_REG_ARM64_SVE_ZREG(15, 0),
+       KVM_REG_ARM64_SVE_ZREG(16, 0),
+       KVM_REG_ARM64_SVE_ZREG(17, 0),
+       KVM_REG_ARM64_SVE_ZREG(18, 0),
+       KVM_REG_ARM64_SVE_ZREG(19, 0),
+       KVM_REG_ARM64_SVE_ZREG(20, 0),
+       KVM_REG_ARM64_SVE_ZREG(21, 0),
+       KVM_REG_ARM64_SVE_ZREG(22, 0),
+       KVM_REG_ARM64_SVE_ZREG(23, 0),
+       KVM_REG_ARM64_SVE_ZREG(24, 0),
+       KVM_REG_ARM64_SVE_ZREG(25, 0),
+       KVM_REG_ARM64_SVE_ZREG(26, 0),
+       KVM_REG_ARM64_SVE_ZREG(27, 0),
+       KVM_REG_ARM64_SVE_ZREG(28, 0),
+       KVM_REG_ARM64_SVE_ZREG(29, 0),
+       KVM_REG_ARM64_SVE_ZREG(30, 0),
+       KVM_REG_ARM64_SVE_ZREG(31, 0),
+       KVM_REG_ARM64_SVE_PREG(0, 0),
+       KVM_REG_ARM64_SVE_PREG(1, 0),
+       KVM_REG_ARM64_SVE_PREG(2, 0),
+       KVM_REG_ARM64_SVE_PREG(3, 0),
+       KVM_REG_ARM64_SVE_PREG(4, 0),
+       KVM_REG_ARM64_SVE_PREG(5, 0),
+       KVM_REG_ARM64_SVE_PREG(6, 0),
+       KVM_REG_ARM64_SVE_PREG(7, 0),
+       KVM_REG_ARM64_SVE_PREG(8, 0),
+       KVM_REG_ARM64_SVE_PREG(9, 0),
+       KVM_REG_ARM64_SVE_PREG(10, 0),
+       KVM_REG_ARM64_SVE_PREG(11, 0),
+       KVM_REG_ARM64_SVE_PREG(12, 0),
+       KVM_REG_ARM64_SVE_PREG(13, 0),
+       KVM_REG_ARM64_SVE_PREG(14, 0),
+       KVM_REG_ARM64_SVE_PREG(15, 0),
+       KVM_REG_ARM64_SVE_FFR(0),
+       ARM64_SYS_REG(3, 0, 1, 2, 0),   /* ZCR_EL1 */
+};
+static __u64 sve_regs_n = ARRAY_SIZE(sve_regs);
+
+static __u64 rejects_set[] = {
+#ifdef REG_LIST_SVE
+       KVM_REG_ARM64_SVE_VLS,
+#endif
+};
+static __u64 rejects_set_n = ARRAY_SIZE(rejects_set);
diff --git a/tools/testing/selftests/kvm/clear_dirty_log_test.c b/tools/testing/selftests/kvm/clear_dirty_log_test.c
deleted file mode 100644 (file)
index 11672ec..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#define USE_CLEAR_DIRTY_LOG
-#define KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE (1 << 0)
-#define KVM_DIRTY_LOG_INITIALLY_SET         (1 << 1)
-#define KVM_DIRTY_LOG_MANUAL_CAPS   (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
-               KVM_DIRTY_LOG_INITIALLY_SET)
-#include "dirty_log_test.c"
index 360cd3ea4cd679a4c8bb7544a6c689ec033c9cad..3d96a7bfaff30f6ed7d39475cf0d1b4637ba1739 100644 (file)
 #include <linux/bitops.h>
 #include <linux/userfaultfd.h>
 
-#include "test_util.h"
-#include "kvm_util.h"
+#include "perf_test_util.h"
 #include "processor.h"
+#include "test_util.h"
 
 #ifdef __NR_userfaultfd
 
-/* The memory slot index demand page */
-#define TEST_MEM_SLOT_INDEX            1
-
-/* Default guest test virtual memory offset */
-#define DEFAULT_GUEST_TEST_MEM         0xc0000000
-
-#define DEFAULT_GUEST_TEST_MEM_SIZE (1 << 30) /* 1G */
-
 #ifdef PRINT_PER_PAGE_UPDATES
 #define PER_PAGE_DEBUG(...) printf(__VA_ARGS__)
 #else
 #define PER_VCPU_DEBUG(...) _no_printf(__VA_ARGS__)
 #endif
 
-#define MAX_VCPUS 512
-
-/*
- * Guest/Host shared variables. Ensure addr_gva2hva() and/or
- * sync_global_to/from_guest() are used when accessing from
- * the host. READ/WRITE_ONCE() should also be used with anything
- * that may change.
- */
-static uint64_t host_page_size;
-static uint64_t guest_page_size;
-
 static char *guest_data_prototype;
 
-/*
- * Guest physical memory offset of the testing memory slot.
- * This will be set to the topmost valid physical address minus
- * the test memory size.
- */
-static uint64_t guest_test_phys_mem;
-
-/*
- * Guest virtual memory offset of the testing memory slot.
- * Must not conflict with identity mapped test code.
- */
-static uint64_t guest_test_virt_mem = DEFAULT_GUEST_TEST_MEM;
-
-struct vcpu_args {
-       uint64_t gva;
-       uint64_t pages;
-
-       /* Only used by the host userspace part of the vCPU thread */
-       int vcpu_id;
-       struct kvm_vm *vm;
-};
-
-static struct vcpu_args vcpu_args[MAX_VCPUS];
-
-/*
- * Continuously write to the first 8 bytes of each page in the demand paging
- * memory region.
- */
-static void guest_code(uint32_t vcpu_id)
-{
-       uint64_t gva;
-       uint64_t pages;
-       int i;
-
-       /* Make sure vCPU args data structure is not corrupt. */
-       GUEST_ASSERT(vcpu_args[vcpu_id].vcpu_id == vcpu_id);
-
-       gva = vcpu_args[vcpu_id].gva;
-       pages = vcpu_args[vcpu_id].pages;
-
-       for (i = 0; i < pages; i++) {
-               uint64_t addr = gva + (i * guest_page_size);
-
-               addr &= ~(host_page_size - 1);
-               *(uint64_t *)addr = 0x0123456789ABCDEF;
-       }
-
-       GUEST_SYNC(1);
-}
-
 static void *vcpu_worker(void *data)
 {
        int ret;
-       struct vcpu_args *args = (struct vcpu_args *)data;
-       struct kvm_vm *vm = args->vm;
-       int vcpu_id = args->vcpu_id;
+       struct vcpu_args *vcpu_args = (struct vcpu_args *)data;
+       int vcpu_id = vcpu_args->vcpu_id;
+       struct kvm_vm *vm = perf_test_args.vm;
        struct kvm_run *run;
-       struct timespec start, end, ts_diff;
+       struct timespec start;
+       struct timespec ts_diff;
 
        vcpu_args_set(vm, vcpu_id, 1, vcpu_id);
        run = vcpu_state(vm, vcpu_id);
@@ -133,52 +65,18 @@ static void *vcpu_worker(void *data)
                            exit_reason_str(run->exit_reason));
        }
 
-       clock_gettime(CLOCK_MONOTONIC, &end);
-       ts_diff = timespec_sub(end, start);
+       ts_diff = timespec_diff_now(start);
        PER_VCPU_DEBUG("vCPU %d execution time: %ld.%.9lds\n", vcpu_id,
                       ts_diff.tv_sec, ts_diff.tv_nsec);
 
        return NULL;
 }
 
-#define PAGE_SHIFT_4K  12
-#define PTES_PER_4K_PT 512
-
-static struct kvm_vm *create_vm(enum vm_guest_mode mode, int vcpus,
-                               uint64_t vcpu_memory_bytes)
-{
-       struct kvm_vm *vm;
-       uint64_t pages = DEFAULT_GUEST_PHY_PAGES;
-
-       /* Account for a few pages per-vCPU for stacks */
-       pages += DEFAULT_STACK_PGS * vcpus;
-
-       /*
-        * Reserve twice the ammount of memory needed to map the test region and
-        * the page table / stacks region, at 4k, for page tables. Do the
-        * calculation with 4K page size: the smallest of all archs. (e.g., 64K
-        * page size guest will need even less memory for page tables).
-        */
-       pages += (2 * pages) / PTES_PER_4K_PT;
-       pages += ((2 * vcpus * vcpu_memory_bytes) >> PAGE_SHIFT_4K) /
-                PTES_PER_4K_PT;
-       pages = vm_adjust_num_guest_pages(mode, pages);
-
-       pr_info("Testing guest mode: %s\n", vm_guest_mode_string(mode));
-
-       vm = _vm_create(mode, pages, O_RDWR);
-       kvm_vm_elf_load(vm, program_invocation_name, 0, 0);
-#ifdef __x86_64__
-       vm_create_irqchip(vm);
-#endif
-       return vm;
-}
-
 static int handle_uffd_page_request(int uffd, uint64_t addr)
 {
        pid_t tid;
        struct timespec start;
-       struct timespec end;
+       struct timespec ts_diff;
        struct uffdio_copy copy;
        int r;
 
@@ -186,7 +84,7 @@ static int handle_uffd_page_request(int uffd, uint64_t addr)
 
        copy.src = (uint64_t)guest_data_prototype;
        copy.dst = addr;
-       copy.len = host_page_size;
+       copy.len = perf_test_args.host_page_size;
        copy.mode = 0;
 
        clock_gettime(CLOCK_MONOTONIC, &start);
@@ -198,12 +96,12 @@ static int handle_uffd_page_request(int uffd, uint64_t addr)
                return r;
        }
 
-       clock_gettime(CLOCK_MONOTONIC, &end);
+       ts_diff = timespec_diff_now(start);
 
        PER_PAGE_DEBUG("UFFDIO_COPY %d \t%ld ns\n", tid,
-                      timespec_to_ns(timespec_sub(end, start)));
+                      timespec_to_ns(ts_diff));
        PER_PAGE_DEBUG("Paged in %ld bytes at 0x%lx from thread %d\n",
-                      host_page_size, addr, tid);
+                      perf_test_args.host_page_size, addr, tid);
 
        return 0;
 }
@@ -223,7 +121,8 @@ static void *uffd_handler_thread_fn(void *arg)
        int pipefd = uffd_args->pipefd;
        useconds_t delay = uffd_args->delay;
        int64_t pages = 0;
-       struct timespec start, end, ts_diff;
+       struct timespec start;
+       struct timespec ts_diff;
 
        clock_gettime(CLOCK_MONOTONIC, &start);
        while (!quit_uffd_thread) {
@@ -292,8 +191,7 @@ static void *uffd_handler_thread_fn(void *arg)
                pages++;
        }
 
-       clock_gettime(CLOCK_MONOTONIC, &end);
-       ts_diff = timespec_sub(end, start);
+       ts_diff = timespec_diff_now(start);
        PER_VCPU_DEBUG("userfaulted %ld pages over %ld.%.9lds. (%f/sec)\n",
                       pages, ts_diff.tv_sec, ts_diff.tv_nsec,
                       pages / ((double)ts_diff.tv_sec + (double)ts_diff.tv_nsec / 100000000.0));
@@ -351,99 +249,54 @@ static int setup_demand_paging(struct kvm_vm *vm,
 }
 
 static void run_test(enum vm_guest_mode mode, bool use_uffd,
-                    useconds_t uffd_delay, int vcpus,
-                    uint64_t vcpu_memory_bytes)
+                    useconds_t uffd_delay)
 {
        pthread_t *vcpu_threads;
        pthread_t *uffd_handler_threads = NULL;
        struct uffd_handler_args *uffd_args = NULL;
-       struct timespec start, end, ts_diff;
+       struct timespec start;
+       struct timespec ts_diff;
        int *pipefds = NULL;
        struct kvm_vm *vm;
-       uint64_t guest_num_pages;
        int vcpu_id;
        int r;
 
-       vm = create_vm(mode, vcpus, vcpu_memory_bytes);
-
-       guest_page_size = vm_get_page_size(vm);
-
-       TEST_ASSERT(vcpu_memory_bytes % guest_page_size == 0,
-                   "Guest memory size is not guest page size aligned.");
-
-       guest_num_pages = (vcpus * vcpu_memory_bytes) / guest_page_size;
-       guest_num_pages = vm_adjust_num_guest_pages(mode, guest_num_pages);
-
-       /*
-        * If there should be more memory in the guest test region than there
-        * can be pages in the guest, it will definitely cause problems.
-        */
-       TEST_ASSERT(guest_num_pages < vm_get_max_gfn(vm),
-                   "Requested more guest memory than address space allows.\n"
-                   "    guest pages: %lx max gfn: %x vcpus: %d wss: %lx]\n",
-                   guest_num_pages, vm_get_max_gfn(vm), vcpus,
-                   vcpu_memory_bytes);
-
-       host_page_size = getpagesize();
-       TEST_ASSERT(vcpu_memory_bytes % host_page_size == 0,
-                   "Guest memory size is not host page size aligned.");
+       vm = create_vm(mode, nr_vcpus, guest_percpu_mem_size);
 
-       guest_test_phys_mem = (vm_get_max_gfn(vm) - guest_num_pages) *
-                             guest_page_size;
-       guest_test_phys_mem &= ~(host_page_size - 1);
+       perf_test_args.wr_fract = 1;
 
-#ifdef __s390x__
-       /* Align to 1M (segment size) */
-       guest_test_phys_mem &= ~((1 << 20) - 1);
-#endif
-
-       pr_info("guest physical test memory offset: 0x%lx\n", guest_test_phys_mem);
-
-       /* Add an extra memory slot for testing demand paging */
-       vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
-                                   guest_test_phys_mem,
-                                   TEST_MEM_SLOT_INDEX,
-                                   guest_num_pages, 0);
-
-       /* Do mapping for the demand paging memory slot */
-       virt_map(vm, guest_test_virt_mem, guest_test_phys_mem, guest_num_pages, 0);
-
-       ucall_init(vm, NULL);
-
-       guest_data_prototype = malloc(host_page_size);
+       guest_data_prototype = malloc(perf_test_args.host_page_size);
        TEST_ASSERT(guest_data_prototype,
                    "Failed to allocate buffer for guest data pattern");
-       memset(guest_data_prototype, 0xAB, host_page_size);
+       memset(guest_data_prototype, 0xAB, perf_test_args.host_page_size);
 
-       vcpu_threads = malloc(vcpus * sizeof(*vcpu_threads));
+       vcpu_threads = malloc(nr_vcpus * sizeof(*vcpu_threads));
        TEST_ASSERT(vcpu_threads, "Memory allocation failed");
 
+       add_vcpus(vm, nr_vcpus, guest_percpu_mem_size);
+
        if (use_uffd) {
                uffd_handler_threads =
-                       malloc(vcpus * sizeof(*uffd_handler_threads));
+                       malloc(nr_vcpus * sizeof(*uffd_handler_threads));
                TEST_ASSERT(uffd_handler_threads, "Memory allocation failed");
 
-               uffd_args = malloc(vcpus * sizeof(*uffd_args));
+               uffd_args = malloc(nr_vcpus * sizeof(*uffd_args));
                TEST_ASSERT(uffd_args, "Memory allocation failed");
 
-               pipefds = malloc(sizeof(int) * vcpus * 2);
+               pipefds = malloc(sizeof(int) * nr_vcpus * 2);
                TEST_ASSERT(pipefds, "Unable to allocate memory for pipefd");
-       }
-
-       for (vcpu_id = 0; vcpu_id < vcpus; vcpu_id++) {
-               vm_paddr_t vcpu_gpa;
-               void *vcpu_hva;
 
-               vm_vcpu_add_default(vm, vcpu_id, guest_code);
+               for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {
+                       vm_paddr_t vcpu_gpa;
+                       void *vcpu_hva;
 
-               vcpu_gpa = guest_test_phys_mem + (vcpu_id * vcpu_memory_bytes);
-               PER_VCPU_DEBUG("Added VCPU %d with test mem gpa [%lx, %lx)\n",
-                              vcpu_id, vcpu_gpa, vcpu_gpa + vcpu_memory_bytes);
+                       vcpu_gpa = guest_test_phys_mem + (vcpu_id * guest_percpu_mem_size);
+                       PER_VCPU_DEBUG("Added VCPU %d with test mem gpa [%lx, %lx)\n",
+                                      vcpu_id, vcpu_gpa, vcpu_gpa + guest_percpu_mem_size);
 
-               /* Cache the HVA pointer of the region */
-               vcpu_hva = addr_gpa2hva(vm, vcpu_gpa);
+                       /* Cache the HVA pointer of the region */
+                       vcpu_hva = addr_gpa2hva(vm, vcpu_gpa);
 
-               if (use_uffd) {
                        /*
                         * Set up user fault fd to handle demand paging
                         * requests.
@@ -456,53 +309,41 @@ static void run_test(enum vm_guest_mode mode, bool use_uffd,
                                                &uffd_handler_threads[vcpu_id],
                                                pipefds[vcpu_id * 2],
                                                uffd_delay, &uffd_args[vcpu_id],
-                                               vcpu_hva, vcpu_memory_bytes);
+                                               vcpu_hva, guest_percpu_mem_size);
                        if (r < 0)
                                exit(-r);
                }
-
-#ifdef __x86_64__
-               vcpu_set_cpuid(vm, vcpu_id, kvm_get_supported_cpuid());
-#endif
-
-               vcpu_args[vcpu_id].vm = vm;
-               vcpu_args[vcpu_id].vcpu_id = vcpu_id;
-               vcpu_args[vcpu_id].gva = guest_test_virt_mem +
-                                        (vcpu_id * vcpu_memory_bytes);
-               vcpu_args[vcpu_id].pages = vcpu_memory_bytes / guest_page_size;
        }
 
        /* Export the shared variables to the guest */
-       sync_global_to_guest(vm, host_page_size);
-       sync_global_to_guest(vm, guest_page_size);
-       sync_global_to_guest(vm, vcpu_args);
+       sync_global_to_guest(vm, perf_test_args);
 
        pr_info("Finished creating vCPUs and starting uffd threads\n");
 
        clock_gettime(CLOCK_MONOTONIC, &start);
 
-       for (vcpu_id = 0; vcpu_id < vcpus; vcpu_id++) {
+       for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {
                pthread_create(&vcpu_threads[vcpu_id], NULL, vcpu_worker,
-                              &vcpu_args[vcpu_id]);
+                              &perf_test_args.vcpu_args[vcpu_id]);
        }
 
        pr_info("Started all vCPUs\n");
 
        /* Wait for the vcpu threads to quit */
-       for (vcpu_id = 0; vcpu_id < vcpus; vcpu_id++) {
+       for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {
                pthread_join(vcpu_threads[vcpu_id], NULL);
                PER_VCPU_DEBUG("Joined thread for vCPU %d\n", vcpu_id);
        }
 
-       pr_info("All vCPU threads joined\n");
+       ts_diff = timespec_diff_now(start);
 
-       clock_gettime(CLOCK_MONOTONIC, &end);
+       pr_info("All vCPU threads joined\n");
 
        if (use_uffd) {
                char c;
 
                /* Tell the user fault fd handler threads to quit */
-               for (vcpu_id = 0; vcpu_id < vcpus; vcpu_id++) {
+               for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {
                        r = write(pipefds[vcpu_id * 2 + 1], &c, 1);
                        TEST_ASSERT(r == 1, "Unable to write to pipefd");
 
@@ -510,11 +351,11 @@ static void run_test(enum vm_guest_mode mode, bool use_uffd,
                }
        }
 
-       ts_diff = timespec_sub(end, start);
        pr_info("Total guest execution time: %ld.%.9lds\n",
                ts_diff.tv_sec, ts_diff.tv_nsec);
        pr_info("Overall demand paging rate: %f pgs/sec\n",
-               guest_num_pages / ((double)ts_diff.tv_sec + (double)ts_diff.tv_nsec / 100000000.0));
+               perf_test_args.vcpu_args[0].pages * nr_vcpus /
+               ((double)ts_diff.tv_sec + (double)ts_diff.tv_nsec / 100000000.0));
 
        ucall_uninit(vm);
        kvm_vm_free(vm);
@@ -568,9 +409,8 @@ static void help(char *name)
 
 int main(int argc, char *argv[])
 {
+       int max_vcpus = kvm_check_cap(KVM_CAP_MAX_VCPUS);
        bool mode_selected = false;
-       uint64_t vcpu_memory_bytes = DEFAULT_GUEST_TEST_MEM_SIZE;
-       int vcpus = 1;
        unsigned int mode;
        int opt, i;
        bool use_uffd = false;
@@ -619,15 +459,12 @@ int main(int argc, char *argv[])
                                    "A negative UFFD delay is not supported.");
                        break;
                case 'b':
-                       vcpu_memory_bytes = parse_size(optarg);
+                       guest_percpu_mem_size = parse_size(optarg);
                        break;
                case 'v':
-                       vcpus = atoi(optarg);
-                       TEST_ASSERT(vcpus > 0,
-                                   "Must have a positive number of vCPUs");
-                       TEST_ASSERT(vcpus <= MAX_VCPUS,
-                                   "This test does not currently support\n"
-                                   "more than %d vCPUs.", MAX_VCPUS);
+                       nr_vcpus = atoi(optarg);
+                       TEST_ASSERT(nr_vcpus > 0 && nr_vcpus <= max_vcpus,
+                                   "Invalid number of vcpus, must be between 1 and %d", max_vcpus);
                        break;
                case 'h':
                default:
@@ -642,7 +479,7 @@ int main(int argc, char *argv[])
                TEST_ASSERT(guest_modes[i].supported,
                            "Guest mode ID %d (%s) not supported.",
                            i, vm_guest_mode_string(i));
-               run_test(i, use_uffd, uffd_delay, vcpus, vcpu_memory_bytes);
+               run_test(i, use_uffd, uffd_delay);
        }
 
        return 0;
diff --git a/tools/testing/selftests/kvm/dirty_log_perf_test.c b/tools/testing/selftests/kvm/dirty_log_perf_test.c
new file mode 100644 (file)
index 0000000..85c9b8f
--- /dev/null
@@ -0,0 +1,376 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KVM dirty page logging performance test
+ *
+ * Based on dirty_log_test.c
+ *
+ * Copyright (C) 2018, Red Hat, Inc.
+ * Copyright (C) 2020, Google, Inc.
+ */
+
+#define _GNU_SOURCE /* for program_invocation_name */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <pthread.h>
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+
+#include "kvm_util.h"
+#include "perf_test_util.h"
+#include "processor.h"
+#include "test_util.h"
+
+/* How many host loops to run by default (one KVM_GET_DIRTY_LOG for each loop)*/
+#define TEST_HOST_LOOP_N               2UL
+
+/* Host variables */
+static bool host_quit;
+static uint64_t iteration;
+static uint64_t vcpu_last_completed_iteration[MAX_VCPUS];
+
+static void *vcpu_worker(void *data)
+{
+       int ret;
+       struct kvm_vm *vm = perf_test_args.vm;
+       uint64_t pages_count = 0;
+       struct kvm_run *run;
+       struct timespec start;
+       struct timespec ts_diff;
+       struct timespec total = (struct timespec){0};
+       struct timespec avg;
+       struct vcpu_args *vcpu_args = (struct vcpu_args *)data;
+       int vcpu_id = vcpu_args->vcpu_id;
+
+       vcpu_args_set(vm, vcpu_id, 1, vcpu_id);
+       run = vcpu_state(vm, vcpu_id);
+
+       while (!READ_ONCE(host_quit)) {
+               uint64_t current_iteration = READ_ONCE(iteration);
+
+               clock_gettime(CLOCK_MONOTONIC, &start);
+               ret = _vcpu_run(vm, vcpu_id);
+               ts_diff = timespec_diff_now(start);
+
+               TEST_ASSERT(ret == 0, "vcpu_run failed: %d\n", ret);
+               TEST_ASSERT(get_ucall(vm, vcpu_id, NULL) == UCALL_SYNC,
+                           "Invalid guest sync status: exit_reason=%s\n",
+                           exit_reason_str(run->exit_reason));
+
+               pr_debug("Got sync event from vCPU %d\n", vcpu_id);
+               vcpu_last_completed_iteration[vcpu_id] = current_iteration;
+               pr_debug("vCPU %d updated last completed iteration to %lu\n",
+                        vcpu_id, vcpu_last_completed_iteration[vcpu_id]);
+
+               if (current_iteration) {
+                       pages_count += vcpu_args->pages;
+                       total = timespec_add(total, ts_diff);
+                       pr_debug("vCPU %d iteration %lu dirty memory time: %ld.%.9lds\n",
+                               vcpu_id, current_iteration, ts_diff.tv_sec,
+                               ts_diff.tv_nsec);
+               } else {
+                       pr_debug("vCPU %d iteration %lu populate memory time: %ld.%.9lds\n",
+                               vcpu_id, current_iteration, ts_diff.tv_sec,
+                               ts_diff.tv_nsec);
+               }
+
+               while (current_iteration == READ_ONCE(iteration) &&
+                      !READ_ONCE(host_quit)) {}
+       }
+
+       avg = timespec_div(total, vcpu_last_completed_iteration[vcpu_id]);
+       pr_debug("\nvCPU %d dirtied 0x%lx pages over %lu iterations in %ld.%.9lds. (Avg %ld.%.9lds/iteration)\n",
+               vcpu_id, pages_count, vcpu_last_completed_iteration[vcpu_id],
+               total.tv_sec, total.tv_nsec, avg.tv_sec, avg.tv_nsec);
+
+       return NULL;
+}
+
+#ifdef USE_CLEAR_DIRTY_LOG
+static u64 dirty_log_manual_caps;
+#endif
+
+static void run_test(enum vm_guest_mode mode, unsigned long iterations,
+                    uint64_t phys_offset, int wr_fract)
+{
+       pthread_t *vcpu_threads;
+       struct kvm_vm *vm;
+       unsigned long *bmap;
+       uint64_t guest_num_pages;
+       uint64_t host_num_pages;
+       int vcpu_id;
+       struct timespec start;
+       struct timespec ts_diff;
+       struct timespec get_dirty_log_total = (struct timespec){0};
+       struct timespec vcpu_dirty_total = (struct timespec){0};
+       struct timespec avg;
+#ifdef USE_CLEAR_DIRTY_LOG
+       struct kvm_enable_cap cap = {};
+       struct timespec clear_dirty_log_total = (struct timespec){0};
+#endif
+
+       vm = create_vm(mode, nr_vcpus, guest_percpu_mem_size);
+
+       perf_test_args.wr_fract = wr_fract;
+
+       guest_num_pages = (nr_vcpus * guest_percpu_mem_size) >> vm_get_page_shift(vm);
+       guest_num_pages = vm_adjust_num_guest_pages(mode, guest_num_pages);
+       host_num_pages = vm_num_host_pages(mode, guest_num_pages);
+       bmap = bitmap_alloc(host_num_pages);
+
+#ifdef USE_CLEAR_DIRTY_LOG
+       cap.cap = KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2;
+       cap.args[0] = dirty_log_manual_caps;
+       vm_enable_cap(vm, &cap);
+#endif
+
+       vcpu_threads = malloc(nr_vcpus * sizeof(*vcpu_threads));
+       TEST_ASSERT(vcpu_threads, "Memory allocation failed");
+
+       add_vcpus(vm, nr_vcpus, guest_percpu_mem_size);
+
+       sync_global_to_guest(vm, perf_test_args);
+
+       /* Start the iterations */
+       iteration = 0;
+       host_quit = false;
+
+       clock_gettime(CLOCK_MONOTONIC, &start);
+       for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {
+               pthread_create(&vcpu_threads[vcpu_id], NULL, vcpu_worker,
+                              &perf_test_args.vcpu_args[vcpu_id]);
+       }
+
+       /* Allow the vCPU to populate memory */
+       pr_debug("Starting iteration %lu - Populating\n", iteration);
+       while (READ_ONCE(vcpu_last_completed_iteration[vcpu_id]) != iteration)
+               pr_debug("Waiting for vcpu_last_completed_iteration == %lu\n",
+                       iteration);
+
+       ts_diff = timespec_diff_now(start);
+       pr_info("Populate memory time: %ld.%.9lds\n",
+               ts_diff.tv_sec, ts_diff.tv_nsec);
+
+       /* Enable dirty logging */
+       clock_gettime(CLOCK_MONOTONIC, &start);
+       vm_mem_region_set_flags(vm, TEST_MEM_SLOT_INDEX,
+                               KVM_MEM_LOG_DIRTY_PAGES);
+       ts_diff = timespec_diff_now(start);
+       pr_info("Enabling dirty logging time: %ld.%.9lds\n\n",
+               ts_diff.tv_sec, ts_diff.tv_nsec);
+
+       while (iteration < iterations) {
+               /*
+                * Incrementing the iteration number will start the vCPUs
+                * dirtying memory again.
+                */
+               clock_gettime(CLOCK_MONOTONIC, &start);
+               iteration++;
+
+               pr_debug("Starting iteration %lu\n", iteration);
+               for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {
+                       while (READ_ONCE(vcpu_last_completed_iteration[vcpu_id]) != iteration)
+                               pr_debug("Waiting for vCPU %d vcpu_last_completed_iteration == %lu\n",
+                                        vcpu_id, iteration);
+               }
+
+               ts_diff = timespec_diff_now(start);
+               vcpu_dirty_total = timespec_add(vcpu_dirty_total, ts_diff);
+               pr_info("Iteration %lu dirty memory time: %ld.%.9lds\n",
+                       iteration, ts_diff.tv_sec, ts_diff.tv_nsec);
+
+               clock_gettime(CLOCK_MONOTONIC, &start);
+               kvm_vm_get_dirty_log(vm, TEST_MEM_SLOT_INDEX, bmap);
+
+               ts_diff = timespec_diff_now(start);
+               get_dirty_log_total = timespec_add(get_dirty_log_total,
+                                                  ts_diff);
+               pr_info("Iteration %lu get dirty log time: %ld.%.9lds\n",
+                       iteration, ts_diff.tv_sec, ts_diff.tv_nsec);
+
+#ifdef USE_CLEAR_DIRTY_LOG
+               clock_gettime(CLOCK_MONOTONIC, &start);
+               kvm_vm_clear_dirty_log(vm, TEST_MEM_SLOT_INDEX, bmap, 0,
+                                      host_num_pages);
+
+               ts_diff = timespec_diff_now(start);
+               clear_dirty_log_total = timespec_add(clear_dirty_log_total,
+                                                    ts_diff);
+               pr_info("Iteration %lu clear dirty log time: %ld.%.9lds\n",
+                       iteration, ts_diff.tv_sec, ts_diff.tv_nsec);
+#endif
+       }
+
+       /* Tell the vcpu thread to quit */
+       host_quit = true;
+       for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++)
+               pthread_join(vcpu_threads[vcpu_id], NULL);
+
+       /* Disable dirty logging */
+       clock_gettime(CLOCK_MONOTONIC, &start);
+       vm_mem_region_set_flags(vm, TEST_MEM_SLOT_INDEX, 0);
+       ts_diff = timespec_diff_now(start);
+       pr_info("Disabling dirty logging time: %ld.%.9lds\n",
+               ts_diff.tv_sec, ts_diff.tv_nsec);
+
+       avg = timespec_div(get_dirty_log_total, iterations);
+       pr_info("Get dirty log over %lu iterations took %ld.%.9lds. (Avg %ld.%.9lds/iteration)\n",
+               iterations, get_dirty_log_total.tv_sec,
+               get_dirty_log_total.tv_nsec, avg.tv_sec, avg.tv_nsec);
+
+#ifdef USE_CLEAR_DIRTY_LOG
+       avg = timespec_div(clear_dirty_log_total, iterations);
+       pr_info("Clear dirty log over %lu iterations took %ld.%.9lds. (Avg %ld.%.9lds/iteration)\n",
+               iterations, clear_dirty_log_total.tv_sec,
+               clear_dirty_log_total.tv_nsec, avg.tv_sec, avg.tv_nsec);
+#endif
+
+       free(bmap);
+       free(vcpu_threads);
+       ucall_uninit(vm);
+       kvm_vm_free(vm);
+}
+
+struct guest_mode {
+       bool supported;
+       bool enabled;
+};
+static struct guest_mode guest_modes[NUM_VM_MODES];
+
+#define guest_mode_init(mode, supported, enabled) ({ \
+       guest_modes[mode] = (struct guest_mode){ supported, enabled }; \
+})
+
+static void help(char *name)
+{
+       int i;
+
+       puts("");
+       printf("usage: %s [-h] [-i iterations] [-p offset] "
+              "[-m mode] [-b vcpu bytes] [-v vcpus]\n", name);
+       puts("");
+       printf(" -i: specify iteration counts (default: %"PRIu64")\n",
+              TEST_HOST_LOOP_N);
+       printf(" -p: specify guest physical test memory offset\n"
+              "     Warning: a low offset can conflict with the loaded test code.\n");
+       printf(" -m: specify the guest mode ID to test "
+              "(default: test all supported modes)\n"
+              "     This option may be used multiple times.\n"
+              "     Guest mode IDs:\n");
+       for (i = 0; i < NUM_VM_MODES; ++i) {
+               printf("         %d:    %s%s\n", i, vm_guest_mode_string(i),
+                      guest_modes[i].supported ? " (supported)" : "");
+       }
+       printf(" -b: specify the size of the memory region which should be\n"
+              "     dirtied by each vCPU. e.g. 10M or 3G.\n"
+              "     (default: 1G)\n");
+       printf(" -f: specify the fraction of pages which should be written to\n"
+              "     as opposed to simply read, in the form\n"
+              "     1/<fraction of pages to write>.\n"
+              "     (default: 1 i.e. all pages are written to.)\n");
+       printf(" -v: specify the number of vCPUs to run.\n");
+       puts("");
+       exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned long iterations = TEST_HOST_LOOP_N;
+       bool mode_selected = false;
+       uint64_t phys_offset = 0;
+       unsigned int mode;
+       int opt, i;
+       int wr_fract = 1;
+
+#ifdef USE_CLEAR_DIRTY_LOG
+       dirty_log_manual_caps =
+               kvm_check_cap(KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2);
+       if (!dirty_log_manual_caps) {
+               print_skip("KVM_CLEAR_DIRTY_LOG not available");
+               exit(KSFT_SKIP);
+       }
+       dirty_log_manual_caps &= (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE |
+                                 KVM_DIRTY_LOG_INITIALLY_SET);
+#endif
+
+#ifdef __x86_64__
+       guest_mode_init(VM_MODE_PXXV48_4K, true, true);
+#endif
+#ifdef __aarch64__
+       guest_mode_init(VM_MODE_P40V48_4K, true, true);
+       guest_mode_init(VM_MODE_P40V48_64K, true, true);
+
+       {
+               unsigned int limit = kvm_check_cap(KVM_CAP_ARM_VM_IPA_SIZE);
+
+               if (limit >= 52)
+                       guest_mode_init(VM_MODE_P52V48_64K, true, true);
+               if (limit >= 48) {
+                       guest_mode_init(VM_MODE_P48V48_4K, true, true);
+                       guest_mode_init(VM_MODE_P48V48_64K, true, true);
+               }
+       }
+#endif
+#ifdef __s390x__
+       guest_mode_init(VM_MODE_P40V48_4K, true, true);
+#endif
+
+       while ((opt = getopt(argc, argv, "hi:p:m:b:f:v:")) != -1) {
+               switch (opt) {
+               case 'i':
+                       iterations = strtol(optarg, NULL, 10);
+                       break;
+               case 'p':
+                       phys_offset = strtoull(optarg, NULL, 0);
+                       break;
+               case 'm':
+                       if (!mode_selected) {
+                               for (i = 0; i < NUM_VM_MODES; ++i)
+                                       guest_modes[i].enabled = false;
+                               mode_selected = true;
+                       }
+                       mode = strtoul(optarg, NULL, 10);
+                       TEST_ASSERT(mode < NUM_VM_MODES,
+                                   "Guest mode ID %d too big", mode);
+                       guest_modes[mode].enabled = true;
+                       break;
+               case 'b':
+                       guest_percpu_mem_size = parse_size(optarg);
+                       break;
+               case 'f':
+                       wr_fract = atoi(optarg);
+                       TEST_ASSERT(wr_fract >= 1,
+                                   "Write fraction cannot be less than one");
+                       break;
+               case 'v':
+                       nr_vcpus = atoi(optarg);
+                       TEST_ASSERT(nr_vcpus > 0,
+                                   "Must have a positive number of vCPUs");
+                       TEST_ASSERT(nr_vcpus <= MAX_VCPUS,
+                                   "This test does not currently support\n"
+                                   "more than %d vCPUs.", MAX_VCPUS);
+                       break;
+               case 'h':
+               default:
+                       help(argv[0]);
+                       break;
+               }
+       }
+
+       TEST_ASSERT(iterations >= 2, "The test should have at least two iterations");
+
+       pr_info("Test iterations: %"PRIu64"\n", iterations);
+
+       for (i = 0; i < NUM_VM_MODES; ++i) {
+               if (!guest_modes[i].enabled)
+                       continue;
+               TEST_ASSERT(guest_modes[i].supported,
+                           "Guest mode ID %d (%s) not supported.",
+                           i, vm_guest_mode_string(i));
+               run_test(i, iterations, phys_offset, wr_fract);
+       }
+
+       return 0;
+}
index 752ec158ac59c5a9bfd766c4dc7fe0936d224eb0..54da9cc20db48280b7e5281bd3a7522752ac658b 100644 (file)
@@ -128,6 +128,78 @@ static uint64_t host_dirty_count;
 static uint64_t host_clear_count;
 static uint64_t host_track_next_count;
 
+enum log_mode_t {
+       /* Only use KVM_GET_DIRTY_LOG for logging */
+       LOG_MODE_DIRTY_LOG = 0,
+
+       /* Use both KVM_[GET|CLEAR]_DIRTY_LOG for logging */
+       LOG_MODE_CLEAR_LOG = 1,
+
+       LOG_MODE_NUM,
+
+       /* Run all supported modes */
+       LOG_MODE_ALL = LOG_MODE_NUM,
+};
+
+/* Mode of logging to test.  Default is to run all supported modes */
+static enum log_mode_t host_log_mode_option = LOG_MODE_ALL;
+/* Logging mode for current run */
+static enum log_mode_t host_log_mode;
+
+static bool clear_log_supported(void)
+{
+       return kvm_check_cap(KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2);
+}
+
+static void clear_log_create_vm_done(struct kvm_vm *vm)
+{
+       struct kvm_enable_cap cap = {};
+       u64 manual_caps;
+
+       manual_caps = kvm_check_cap(KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2);
+       TEST_ASSERT(manual_caps, "MANUAL_CAPS is zero!");
+       manual_caps &= (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE |
+                       KVM_DIRTY_LOG_INITIALLY_SET);
+       cap.cap = KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2;
+       cap.args[0] = manual_caps;
+       vm_enable_cap(vm, &cap);
+}
+
+static void dirty_log_collect_dirty_pages(struct kvm_vm *vm, int slot,
+                                         void *bitmap, uint32_t num_pages)
+{
+       kvm_vm_get_dirty_log(vm, slot, bitmap);
+}
+
+static void clear_log_collect_dirty_pages(struct kvm_vm *vm, int slot,
+                                         void *bitmap, uint32_t num_pages)
+{
+       kvm_vm_get_dirty_log(vm, slot, bitmap);
+       kvm_vm_clear_dirty_log(vm, slot, bitmap, 0, num_pages);
+}
+
+struct log_mode {
+       const char *name;
+       /* Return true if this mode is supported, otherwise false */
+       bool (*supported)(void);
+       /* Hook when the vm creation is done (before vcpu creation) */
+       void (*create_vm_done)(struct kvm_vm *vm);
+       /* Hook to collect the dirty pages into the bitmap provided */
+       void (*collect_dirty_pages) (struct kvm_vm *vm, int slot,
+                                    void *bitmap, uint32_t num_pages);
+} log_modes[LOG_MODE_NUM] = {
+       {
+               .name = "dirty-log",
+               .collect_dirty_pages = dirty_log_collect_dirty_pages,
+       },
+       {
+               .name = "clear-log",
+               .supported = clear_log_supported,
+               .create_vm_done = clear_log_create_vm_done,
+               .collect_dirty_pages = clear_log_collect_dirty_pages,
+       },
+};
+
 /*
  * We use this bitmap to track some pages that should have its dirty
  * bit set in the _next_ iteration.  For example, if we detected the
@@ -137,6 +209,44 @@ static uint64_t host_track_next_count;
  */
 static unsigned long *host_bmap_track;
 
+static void log_modes_dump(void)
+{
+       int i;
+
+       printf("all");
+       for (i = 0; i < LOG_MODE_NUM; i++)
+               printf(", %s", log_modes[i].name);
+       printf("\n");
+}
+
+static bool log_mode_supported(void)
+{
+       struct log_mode *mode = &log_modes[host_log_mode];
+
+       if (mode->supported)
+               return mode->supported();
+
+       return true;
+}
+
+static void log_mode_create_vm_done(struct kvm_vm *vm)
+{
+       struct log_mode *mode = &log_modes[host_log_mode];
+
+       if (mode->create_vm_done)
+               mode->create_vm_done(vm);
+}
+
+static void log_mode_collect_dirty_pages(struct kvm_vm *vm, int slot,
+                                        void *bitmap, uint32_t num_pages)
+{
+       struct log_mode *mode = &log_modes[host_log_mode];
+
+       TEST_ASSERT(mode->collect_dirty_pages != NULL,
+                   "collect_dirty_pages() is required for any log mode!");
+       mode->collect_dirty_pages(vm, slot, bitmap, num_pages);
+}
+
 static void generate_random_array(uint64_t *guest_array, uint64_t size)
 {
        uint64_t i;
@@ -195,7 +305,7 @@ static void vm_dirty_log_verify(enum vm_guest_mode mode, unsigned long *bmap)
                                    page);
                }
 
-               if (test_bit_le(page, bmap)) {
+               if (test_and_clear_bit_le(page, bmap)) {
                        host_dirty_count++;
                        /*
                         * If the bit is set, the value written onto
@@ -252,11 +362,12 @@ static struct kvm_vm *create_vm(enum vm_guest_mode mode, uint32_t vcpuid,
 
        pr_info("Testing guest mode: %s\n", vm_guest_mode_string(mode));
 
-       vm = _vm_create(mode, DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, O_RDWR);
+       vm = vm_create(mode, DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, O_RDWR);
        kvm_vm_elf_load(vm, program_invocation_name, 0, 0);
 #ifdef __x86_64__
        vm_create_irqchip(vm);
 #endif
+       log_mode_create_vm_done(vm);
        vm_vcpu_add_default(vm, vcpuid, guest_code);
        return vm;
 }
@@ -264,10 +375,6 @@ static struct kvm_vm *create_vm(enum vm_guest_mode mode, uint32_t vcpuid,
 #define DIRTY_MEM_BITS 30 /* 1G */
 #define PAGE_SHIFT_4K  12
 
-#ifdef USE_CLEAR_DIRTY_LOG
-static u64 dirty_log_manual_caps;
-#endif
-
 static void run_test(enum vm_guest_mode mode, unsigned long iterations,
                     unsigned long interval, uint64_t phys_offset)
 {
@@ -275,6 +382,12 @@ static void run_test(enum vm_guest_mode mode, unsigned long iterations,
        struct kvm_vm *vm;
        unsigned long *bmap;
 
+       if (!log_mode_supported()) {
+               print_skip("Log mode '%s' not supported",
+                          log_modes[host_log_mode].name);
+               return;
+       }
+
        /*
         * We reserve page table for 2 times of extra dirty mem which
         * will definitely cover the original (1G+) test range.  Here
@@ -317,14 +430,6 @@ static void run_test(enum vm_guest_mode mode, unsigned long iterations,
        bmap = bitmap_alloc(host_num_pages);
        host_bmap_track = bitmap_alloc(host_num_pages);
 
-#ifdef USE_CLEAR_DIRTY_LOG
-       struct kvm_enable_cap cap = {};
-
-       cap.cap = KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2;
-       cap.args[0] = dirty_log_manual_caps;
-       vm_enable_cap(vm, &cap);
-#endif
-
        /* Add an extra memory slot for testing dirty logging */
        vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
                                    guest_test_phys_mem,
@@ -362,11 +467,8 @@ static void run_test(enum vm_guest_mode mode, unsigned long iterations,
        while (iteration < iterations) {
                /* Give the vcpu thread some time to dirty some pages */
                usleep(interval * 1000);
-               kvm_vm_get_dirty_log(vm, TEST_MEM_SLOT_INDEX, bmap);
-#ifdef USE_CLEAR_DIRTY_LOG
-               kvm_vm_clear_dirty_log(vm, TEST_MEM_SLOT_INDEX, bmap, 0,
-                                      host_num_pages);
-#endif
+               log_mode_collect_dirty_pages(vm, TEST_MEM_SLOT_INDEX,
+                                            bmap, host_num_pages);
                vm_dirty_log_verify(mode, bmap);
                iteration++;
                sync_global_to_guest(vm, iteration);
@@ -410,6 +512,9 @@ static void help(char *name)
               TEST_HOST_LOOP_INTERVAL);
        printf(" -p: specify guest physical test memory offset\n"
               "     Warning: a low offset can conflict with the loaded test code.\n");
+       printf(" -M: specify the host logging mode "
+              "(default: run all log modes).  Supported modes: \n\t");
+       log_modes_dump();
        printf(" -m: specify the guest mode ID to test "
               "(default: test all supported modes)\n"
               "     This option may be used multiple times.\n"
@@ -429,18 +534,7 @@ int main(int argc, char *argv[])
        bool mode_selected = false;
        uint64_t phys_offset = 0;
        unsigned int mode;
-       int opt, i;
-
-#ifdef USE_CLEAR_DIRTY_LOG
-       dirty_log_manual_caps =
-               kvm_check_cap(KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2);
-       if (!dirty_log_manual_caps) {
-               print_skip("KVM_CLEAR_DIRTY_LOG not available");
-               exit(KSFT_SKIP);
-       }
-       dirty_log_manual_caps &= (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE |
-                                 KVM_DIRTY_LOG_INITIALLY_SET);
-#endif
+       int opt, i, j;
 
 #ifdef __x86_64__
        guest_mode_init(VM_MODE_PXXV48_4K, true, true);
@@ -464,7 +558,7 @@ int main(int argc, char *argv[])
        guest_mode_init(VM_MODE_P40V48_4K, true, true);
 #endif
 
-       while ((opt = getopt(argc, argv, "hi:I:p:m:")) != -1) {
+       while ((opt = getopt(argc, argv, "hi:I:p:m:M:")) != -1) {
                switch (opt) {
                case 'i':
                        iterations = strtol(optarg, NULL, 10);
@@ -486,6 +580,26 @@ int main(int argc, char *argv[])
                                    "Guest mode ID %d too big", mode);
                        guest_modes[mode].enabled = true;
                        break;
+               case 'M':
+                       if (!strcmp(optarg, "all")) {
+                               host_log_mode_option = LOG_MODE_ALL;
+                               break;
+                       }
+                       for (i = 0; i < LOG_MODE_NUM; i++) {
+                               if (!strcmp(optarg, log_modes[i].name)) {
+                                       pr_info("Setting log mode to: '%s'\n",
+                                               optarg);
+                                       host_log_mode_option = i;
+                                       break;
+                               }
+                       }
+                       if (i == LOG_MODE_NUM) {
+                               printf("Log mode '%s' invalid. Please choose "
+                                      "from: ", optarg);
+                               log_modes_dump();
+                               exit(1);
+                       }
+                       break;
                case 'h':
                default:
                        help(argv[0]);
@@ -507,7 +621,18 @@ int main(int argc, char *argv[])
                TEST_ASSERT(guest_modes[i].supported,
                            "Guest mode ID %d (%s) not supported.",
                            i, vm_guest_mode_string(i));
-               run_test(i, iterations, interval, phys_offset);
+               if (host_log_mode_option == LOG_MODE_ALL) {
+                       /* Run each log mode */
+                       for (j = 0; j < LOG_MODE_NUM; j++) {
+                               pr_info("Testing Log Mode '%s'\n",
+                                       log_modes[j].name);
+                               host_log_mode = j;
+                               run_test(i, iterations, interval, phys_offset);
+                       }
+               } else {
+                       host_log_mode = host_log_mode_option;
+                       run_test(i, iterations, interval, phys_offset);
+               }
        }
 
        return 0;
index 919e161dd2893bdd362cdda61be48b1ab97774f9..7d29aa78695968d90da325fbe814a3cdd152b60d 100644 (file)
@@ -63,9 +63,11 @@ enum vm_mem_backing_src_type {
 
 int kvm_check_cap(long cap);
 int vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap);
+int vcpu_enable_cap(struct kvm_vm *vm, uint32_t vcpu_id,
+                   struct kvm_enable_cap *cap);
+void vm_enable_dirty_ring(struct kvm_vm *vm, uint32_t ring_size);
 
 struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm);
-struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm);
 void kvm_vm_free(struct kvm_vm *vmp);
 void kvm_vm_restart(struct kvm_vm *vmp, int perm);
 void kvm_vm_release(struct kvm_vm *vmp);
@@ -149,6 +151,7 @@ void vcpu_set_guest_debug(struct kvm_vm *vm, uint32_t vcpuid,
                          struct kvm_guest_debug *debug);
 void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid,
                       struct kvm_mp_state *mp_state);
+struct kvm_reg_list *vcpu_get_reg_list(struct kvm_vm *vm, uint32_t vcpuid);
 void vcpu_regs_get(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_regs *regs);
 void vcpu_regs_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_regs *regs);
 
@@ -294,6 +297,8 @@ int vm_create_device(struct kvm_vm *vm, struct kvm_create_device *cd);
        memcpy(&(g), _p, sizeof(g));                            \
 })
 
+void assert_on_unhandled_exception(struct kvm_vm *vm, uint32_t vcpuid);
+
 /* Common ucalls */
 enum {
        UCALL_NONE,
diff --git a/tools/testing/selftests/kvm/include/perf_test_util.h b/tools/testing/selftests/kvm/include/perf_test_util.h
new file mode 100644 (file)
index 0000000..2618052
--- /dev/null
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * tools/testing/selftests/kvm/include/perf_test_util.h
+ *
+ * Copyright (C) 2020, Google LLC.
+ */
+
+#ifndef SELFTEST_KVM_PERF_TEST_UTIL_H
+#define SELFTEST_KVM_PERF_TEST_UTIL_H
+
+#include "kvm_util.h"
+#include "processor.h"
+
+#define MAX_VCPUS 512
+
+#define PAGE_SHIFT_4K  12
+#define PTES_PER_4K_PT 512
+
+#define TEST_MEM_SLOT_INDEX            1
+
+/* Default guest test virtual memory offset */
+#define DEFAULT_GUEST_TEST_MEM         0xc0000000
+
+#define DEFAULT_PER_VCPU_MEM_SIZE      (1 << 30) /* 1G */
+
+/*
+ * Guest physical memory offset of the testing memory slot.
+ * This will be set to the topmost valid physical address minus
+ * the test memory size.
+ */
+static uint64_t guest_test_phys_mem;
+
+/*
+ * Guest virtual memory offset of the testing memory slot.
+ * Must not conflict with identity mapped test code.
+ */
+static uint64_t guest_test_virt_mem = DEFAULT_GUEST_TEST_MEM;
+static uint64_t guest_percpu_mem_size = DEFAULT_PER_VCPU_MEM_SIZE;
+
+/* Number of VCPUs for the test */
+static int nr_vcpus = 1;
+
+struct vcpu_args {
+       uint64_t gva;
+       uint64_t pages;
+
+       /* Only used by the host userspace part of the vCPU thread */
+       int vcpu_id;
+};
+
+struct perf_test_args {
+       struct kvm_vm *vm;
+       uint64_t host_page_size;
+       uint64_t guest_page_size;
+       int wr_fract;
+
+       struct vcpu_args vcpu_args[MAX_VCPUS];
+};
+
+static struct perf_test_args perf_test_args;
+
+/*
+ * Continuously write to the first 8 bytes of each page in the
+ * specified region.
+ */
+static void guest_code(uint32_t vcpu_id)
+{
+       struct vcpu_args *vcpu_args = &perf_test_args.vcpu_args[vcpu_id];
+       uint64_t gva;
+       uint64_t pages;
+       int i;
+
+       /* Make sure vCPU args data structure is not corrupt. */
+       GUEST_ASSERT(vcpu_args->vcpu_id == vcpu_id);
+
+       gva = vcpu_args->gva;
+       pages = vcpu_args->pages;
+
+       while (true) {
+               for (i = 0; i < pages; i++) {
+                       uint64_t addr = gva + (i * perf_test_args.guest_page_size);
+
+                       if (i % perf_test_args.wr_fract == 0)
+                               *(uint64_t *)addr = 0x0123456789ABCDEF;
+                       else
+                               READ_ONCE(*(uint64_t *)addr);
+               }
+
+               GUEST_SYNC(1);
+       }
+}
+
+static struct kvm_vm *create_vm(enum vm_guest_mode mode, int vcpus,
+                               uint64_t vcpu_memory_bytes)
+{
+       struct kvm_vm *vm;
+       uint64_t pages = DEFAULT_GUEST_PHY_PAGES;
+       uint64_t guest_num_pages;
+
+       /* Account for a few pages per-vCPU for stacks */
+       pages += DEFAULT_STACK_PGS * vcpus;
+
+       /*
+        * Reserve twice the ammount of memory needed to map the test region and
+        * the page table / stacks region, at 4k, for page tables. Do the
+        * calculation with 4K page size: the smallest of all archs. (e.g., 64K
+        * page size guest will need even less memory for page tables).
+        */
+       pages += (2 * pages) / PTES_PER_4K_PT;
+       pages += ((2 * vcpus * vcpu_memory_bytes) >> PAGE_SHIFT_4K) /
+                PTES_PER_4K_PT;
+       pages = vm_adjust_num_guest_pages(mode, pages);
+
+       pr_info("Testing guest mode: %s\n", vm_guest_mode_string(mode));
+
+       vm = vm_create(mode, pages, O_RDWR);
+       kvm_vm_elf_load(vm, program_invocation_name, 0, 0);
+#ifdef __x86_64__
+       vm_create_irqchip(vm);
+#endif
+
+       perf_test_args.vm = vm;
+       perf_test_args.guest_page_size = vm_get_page_size(vm);
+       perf_test_args.host_page_size = getpagesize();
+
+       TEST_ASSERT(vcpu_memory_bytes % perf_test_args.guest_page_size == 0,
+                   "Guest memory size is not guest page size aligned.");
+
+       guest_num_pages = (vcpus * vcpu_memory_bytes) /
+                         perf_test_args.guest_page_size;
+       guest_num_pages = vm_adjust_num_guest_pages(mode, guest_num_pages);
+
+       /*
+        * If there should be more memory in the guest test region than there
+        * can be pages in the guest, it will definitely cause problems.
+        */
+       TEST_ASSERT(guest_num_pages < vm_get_max_gfn(vm),
+                   "Requested more guest memory than address space allows.\n"
+                   "    guest pages: %lx max gfn: %x vcpus: %d wss: %lx]\n",
+                   guest_num_pages, vm_get_max_gfn(vm), vcpus,
+                   vcpu_memory_bytes);
+
+       TEST_ASSERT(vcpu_memory_bytes % perf_test_args.host_page_size == 0,
+                   "Guest memory size is not host page size aligned.");
+
+       guest_test_phys_mem = (vm_get_max_gfn(vm) - guest_num_pages) *
+                             perf_test_args.guest_page_size;
+       guest_test_phys_mem &= ~(perf_test_args.host_page_size - 1);
+
+#ifdef __s390x__
+       /* Align to 1M (segment size) */
+       guest_test_phys_mem &= ~((1 << 20) - 1);
+#endif
+
+       pr_info("guest physical test memory offset: 0x%lx\n", guest_test_phys_mem);
+
+       /* Add an extra memory slot for testing */
+       vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
+                                   guest_test_phys_mem,
+                                   TEST_MEM_SLOT_INDEX,
+                                   guest_num_pages, 0);
+
+       /* Do mapping for the demand paging memory slot */
+       virt_map(vm, guest_test_virt_mem, guest_test_phys_mem, guest_num_pages, 0);
+
+       ucall_init(vm, NULL);
+
+       return vm;
+}
+
+static void add_vcpus(struct kvm_vm *vm, int vcpus, uint64_t vcpu_memory_bytes)
+{
+       vm_paddr_t vcpu_gpa;
+       struct vcpu_args *vcpu_args;
+       int vcpu_id;
+
+       for (vcpu_id = 0; vcpu_id < vcpus; vcpu_id++) {
+               vcpu_args = &perf_test_args.vcpu_args[vcpu_id];
+
+               vm_vcpu_add_default(vm, vcpu_id, guest_code);
+
+#ifdef __x86_64__
+               vcpu_set_cpuid(vm, vcpu_id, kvm_get_supported_cpuid());
+#endif
+
+               vcpu_args->vcpu_id = vcpu_id;
+               vcpu_args->gva = guest_test_virt_mem +
+                                (vcpu_id * vcpu_memory_bytes);
+               vcpu_args->pages = vcpu_memory_bytes /
+                                  perf_test_args.guest_page_size;
+
+               vcpu_gpa = guest_test_phys_mem + (vcpu_id * vcpu_memory_bytes);
+               pr_debug("Added VCPU %d with test mem gpa [%lx, %lx)\n",
+                        vcpu_id, vcpu_gpa, vcpu_gpa + vcpu_memory_bytes);
+       }
+}
+
+#endif /* SELFTEST_KVM_PERF_TEST_UTIL_H */
index 5eb01bf51b86fc356cb220aa458096da1b744096..ffffa560436ba6ef7d45a3d40359373c2de32c04 100644 (file)
@@ -64,5 +64,7 @@ int64_t timespec_to_ns(struct timespec ts);
 struct timespec timespec_add_ns(struct timespec ts, int64_t ns);
 struct timespec timespec_add(struct timespec ts1, struct timespec ts2);
 struct timespec timespec_sub(struct timespec ts1, struct timespec ts2);
+struct timespec timespec_diff_now(struct timespec start);
+struct timespec timespec_div(struct timespec ts, int divisor);
 
 #endif /* SELFTEST_KVM_TEST_UTIL_H */
index 82b7fe16a8242778c4cf83a0c987e14964683477..8e61340b39111f6ed4fcf25684b535a8bc8c5214 100644 (file)
@@ -36,6 +36,8 @@
 #define X86_CR4_SMAP           (1ul << 21)
 #define X86_CR4_PKE            (1ul << 22)
 
+#define UNEXPECTED_VECTOR_PORT 0xfff0u
+
 /* General Registers in 64-Bit Mode */
 struct gpr64_regs {
        u64 rax;
@@ -59,7 +61,7 @@ struct gpr64_regs {
 struct desc64 {
        uint16_t limit0;
        uint16_t base0;
-       unsigned base1:8, s:1, type:4, dpl:2, p:1;
+       unsigned base1:8, type:4, s:1, dpl:2, p:1;
        unsigned limit1:4, avl:1, l:1, db:1, g:1, base2:8;
        uint32_t base3;
        uint32_t zero1;
@@ -239,6 +241,11 @@ static inline struct desc_ptr get_idt(void)
        return idt;
 }
 
+static inline void outl(uint16_t port, uint32_t value)
+{
+       __asm__ __volatile__("outl %%eax, %%dx" : : "d"(port), "a"(value));
+}
+
 #define SET_XMM(__var, __xmm) \
        asm volatile("movq %0, %%"#__xmm : : "r"(__var) : #__xmm)
 
@@ -338,6 +345,35 @@ uint32_t kvm_get_cpuid_max_basic(void);
 uint32_t kvm_get_cpuid_max_extended(void);
 void kvm_get_cpu_address_width(unsigned int *pa_bits, unsigned int *va_bits);
 
+struct ex_regs {
+       uint64_t rax, rcx, rdx, rbx;
+       uint64_t rbp, rsi, rdi;
+       uint64_t r8, r9, r10, r11;
+       uint64_t r12, r13, r14, r15;
+       uint64_t vector;
+       uint64_t error_code;
+       uint64_t rip;
+       uint64_t cs;
+       uint64_t rflags;
+};
+
+void vm_init_descriptor_tables(struct kvm_vm *vm);
+void vcpu_init_descriptor_tables(struct kvm_vm *vm, uint32_t vcpuid);
+void vm_handle_exception(struct kvm_vm *vm, int vector,
+                       void (*handler)(struct ex_regs *));
+
+/*
+ * set_cpuid() - overwrites a matching cpuid entry with the provided value.
+ *              matches based on ent->function && ent->index. returns true
+ *              if a match was found and successfully overwritten.
+ * @cpuid: the kvm cpuid list to modify.
+ * @ent: cpuid entry to insert
+ */
+bool set_cpuid(struct kvm_cpuid2 *cpuid, struct kvm_cpuid_entry2 *ent);
+
+uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2,
+                      uint64_t a3);
+
 /*
  * Basic CPU control in CR0
  */
index 54d624dd6c104410ea3ee33286829cc5300202a4..e78d7e26ba61187f240e8665beb8f3ab749f0770 100644 (file)
@@ -573,6 +573,10 @@ struct vmx_pages {
        void *eptp_hva;
        uint64_t eptp_gpa;
        void *eptp;
+
+       void *apic_access_hva;
+       uint64_t apic_access_gpa;
+       void *apic_access;
 };
 
 union vmx_basic {
@@ -615,5 +619,7 @@ void nested_map_memslot(struct vmx_pages *vmx, struct kvm_vm *vm,
                        uint32_t memslot, uint32_t eptp_memslot);
 void prepare_eptp(struct vmx_pages *vmx, struct kvm_vm *vm,
                  uint32_t eptp_memslot);
+void prepare_virtualize_apic_accesses(struct vmx_pages *vmx, struct kvm_vm *vm,
+                                     uint32_t eptp_memslot);
 
 #endif /* SELFTEST_KVM_VMX_H */
index 2afa6618b3963f76c6f5222c33cdf900eed8f860..d6c32c328e9a88883e4e69f7f8d4fc16f250be56 100644 (file)
@@ -350,3 +350,7 @@ void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...)
 
        va_end(ap);
 }
+
+void assert_on_unhandled_exception(struct kvm_vm *vm, uint32_t vcpuid)
+{
+}
index c8e0ec20d3bf42d9d0911130a221f9131476e363..2f37b90ee1a941ddbb8ec1f20bc6808cebd1f9c7 100644 (file)
@@ -94,6 +94,9 @@ uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc)
        struct kvm_run *run = vcpu_state(vm, vcpu_id);
        struct ucall ucall = {};
 
+       if (uc)
+               memset(uc, 0, sizeof(*uc));
+
        if (run->exit_reason == KVM_EXIT_MMIO &&
            run->mmio.phys_addr == (uint64_t)ucall_exit_mmio_addr) {
                vm_vaddr_t gva;
index 74776ee228f2d0d7d9421d7acb3adf4ab0cc95c9..126c6727a6b096c48e768150b72dbe1e7c4df110 100644 (file)
@@ -14,6 +14,7 @@
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include <linux/kernel.h>
 
 #define KVM_UTIL_PGS_PER_HUGEPG 512
@@ -85,6 +86,34 @@ int vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap)
        return ret;
 }
 
+/* VCPU Enable Capability
+ *
+ * Input Args:
+ *   vm - Virtual Machine
+ *   vcpu_id - VCPU
+ *   cap - Capability
+ *
+ * Output Args: None
+ *
+ * Return: On success, 0. On failure a TEST_ASSERT failure is produced.
+ *
+ * Enables a capability (KVM_CAP_*) on the VCPU.
+ */
+int vcpu_enable_cap(struct kvm_vm *vm, uint32_t vcpu_id,
+                   struct kvm_enable_cap *cap)
+{
+       struct vcpu *vcpu = vcpu_find(vm, vcpu_id);
+       int r;
+
+       TEST_ASSERT(vcpu, "cannot find vcpu %d", vcpu_id);
+
+       r = ioctl(vcpu->fd, KVM_ENABLE_CAP, cap);
+       TEST_ASSERT(!r, "KVM_ENABLE_CAP vCPU ioctl failed,\n"
+                       "  rc: %i, errno: %i", r, errno);
+
+       return r;
+}
+
 static void vm_open(struct kvm_vm *vm, int perm)
 {
        vm->kvm_fd = open(KVM_DEV_PATH, perm);
@@ -151,7 +180,7 @@ _Static_assert(sizeof(vm_guest_mode_params)/sizeof(struct vm_guest_mode_params)
  * descriptor to control the created VM is created with the permissions
  * given by perm (e.g. O_RDWR).
  */
-struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
+struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
 {
        struct kvm_vm *vm;
 
@@ -242,11 +271,6 @@ struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
        return vm;
 }
 
-struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
-{
-       return _vm_create(mode, phy_pages, perm);
-}
-
 /*
  * VM Restart
  *
@@ -664,13 +688,21 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
 
        /* As needed perform madvise */
        if (src_type == VM_MEM_SRC_ANONYMOUS || src_type == VM_MEM_SRC_ANONYMOUS_THP) {
-               ret = madvise(region->host_mem, npages * vm->page_size,
-                            src_type == VM_MEM_SRC_ANONYMOUS ? MADV_NOHUGEPAGE : MADV_HUGEPAGE);
-               TEST_ASSERT(ret == 0, "madvise failed,\n"
-                           "  addr: %p\n"
-                           "  length: 0x%lx\n"
-                           "  src_type: %x",
-                           region->host_mem, npages * vm->page_size, src_type);
+               struct stat statbuf;
+
+               ret = stat("/sys/kernel/mm/transparent_hugepage", &statbuf);
+               TEST_ASSERT(ret == 0 || (ret == -1 && errno == ENOENT),
+                           "stat /sys/kernel/mm/transparent_hugepage");
+
+               TEST_ASSERT(ret == 0 || src_type != VM_MEM_SRC_ANONYMOUS_THP,
+                           "VM_MEM_SRC_ANONYMOUS_THP requires THP to be configured in the host kernel");
+
+               if (ret == 0) {
+                       ret = madvise(region->host_mem, npages * vm->page_size,
+                                     src_type == VM_MEM_SRC_ANONYMOUS ? MADV_NOHUGEPAGE : MADV_HUGEPAGE);
+                       TEST_ASSERT(ret == 0, "madvise failed, addr: %p length: 0x%lx src_type: %x",
+                                   region->host_mem, npages * vm->page_size, src_type);
+               }
        }
 
        region->unused_phy_pages = sparsebit_alloc();
@@ -1195,6 +1227,9 @@ int _vcpu_run(struct kvm_vm *vm, uint32_t vcpuid)
        do {
                rc = ioctl(vcpu->fd, KVM_RUN, NULL);
        } while (rc == -1 && errno == EINTR);
+
+       assert_on_unhandled_exception(vm, vcpuid);
+
        return rc;
 }
 
@@ -1251,6 +1286,35 @@ void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid,
                "rc: %i errno: %i", ret, errno);
 }
 
+/*
+ * VM VCPU Get Reg List
+ *
+ * Input Args:
+ *   vm - Virtual Machine
+ *   vcpuid - VCPU ID
+ *
+ * Output Args:
+ *   None
+ *
+ * Return:
+ *   A pointer to an allocated struct kvm_reg_list
+ *
+ * Get the list of guest registers which are supported for
+ * KVM_GET_ONE_REG/KVM_SET_ONE_REG calls
+ */
+struct kvm_reg_list *vcpu_get_reg_list(struct kvm_vm *vm, uint32_t vcpuid)
+{
+       struct kvm_reg_list reg_list_n = { .n = 0 }, *reg_list;
+       int ret;
+
+       ret = _vcpu_ioctl(vm, vcpuid, KVM_GET_REG_LIST, &reg_list_n);
+       TEST_ASSERT(ret == -1 && errno == E2BIG, "KVM_GET_REG_LIST n=0");
+       reg_list = calloc(1, sizeof(*reg_list) + reg_list_n.n * sizeof(__u64));
+       reg_list->n = reg_list_n.n;
+       vcpu_ioctl(vm, vcpuid, KVM_GET_REG_LIST, reg_list);
+       return reg_list;
+}
+
 /*
  * VM VCPU Regs Get
  *
index 2ef446520748a7b2990cc75018fc247efb55231b..f07d383d03a11ca51404c79d876997fec6b09d8c 100644 (file)
@@ -50,6 +50,8 @@ struct kvm_vm {
        vm_paddr_t pgd;
        vm_vaddr_t gdt;
        vm_vaddr_t tss;
+       vm_vaddr_t idt;
+       vm_vaddr_t handlers;
 };
 
 struct vcpu *vcpu_find(struct kvm_vm *vm, uint32_t vcpuid);
index a88c5d665725d70529af23148d4a04b6bf62f409..7349bb2e1a243919035635af98313c89ecc57c58 100644 (file)
@@ -241,3 +241,7 @@ void vcpu_dump(FILE *stream, struct kvm_vm *vm, uint32_t vcpuid, uint8_t indent)
        fprintf(stream, "%*spstate: psw: 0x%.16llx:0x%.16llx\n",
                indent, "", vcpu->state->psw_mask, vcpu->state->psw_addr);
 }
+
+void assert_on_unhandled_exception(struct kvm_vm *vm, uint32_t vcpuid)
+{
+}
index fd589dc9bfab6415baf5524b63db02b0b6d6e5e6..9d3b0f15249ac4453431a57bf328bc714bb56d4c 100644 (file)
@@ -38,6 +38,9 @@ uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc)
        struct kvm_run *run = vcpu_state(vm, vcpu_id);
        struct ucall ucall = {};
 
+       if (uc)
+               memset(uc, 0, sizeof(*uc));
+
        if (run->exit_reason == KVM_EXIT_S390_SIEIC &&
            run->s390_sieic.icptcode == 4 &&
            (run->s390_sieic.ipa >> 8) == 0x83 &&    /* 0x83 means DIAGNOSE */
index 689e97c27ee24a244164e51d7edf79868208e472..8e04c0b1608e65aaa55fe8c5ce8db4d486b302ed 100644 (file)
@@ -4,10 +4,13 @@
  *
  * Copyright (C) 2020, Google LLC.
  */
-#include <stdlib.h>
+
+#include <assert.h>
 #include <ctype.h>
 #include <limits.h>
-#include <assert.h>
+#include <stdlib.h>
+#include <time.h>
+
 #include "test_util.h"
 
 /*
@@ -81,6 +84,21 @@ struct timespec timespec_sub(struct timespec ts1, struct timespec ts2)
        return timespec_add_ns((struct timespec){0}, ns1 - ns2);
 }
 
+struct timespec timespec_diff_now(struct timespec start)
+{
+       struct timespec end;
+
+       clock_gettime(CLOCK_MONOTONIC, &end);
+       return timespec_sub(end, start);
+}
+
+struct timespec timespec_div(struct timespec ts, int divisor)
+{
+       int64_t ns = timespec_to_ns(ts) / divisor;
+
+       return timespec_add_ns((struct timespec){0}, ns);
+}
+
 void print_skip(const char *fmt, ...)
 {
        va_list ap;
diff --git a/tools/testing/selftests/kvm/lib/x86_64/handlers.S b/tools/testing/selftests/kvm/lib/x86_64/handlers.S
new file mode 100644 (file)
index 0000000..aaf7bc7
--- /dev/null
@@ -0,0 +1,81 @@
+handle_exception:
+       push %r15
+       push %r14
+       push %r13
+       push %r12
+       push %r11
+       push %r10
+       push %r9
+       push %r8
+
+       push %rdi
+       push %rsi
+       push %rbp
+       push %rbx
+       push %rdx
+       push %rcx
+       push %rax
+       mov %rsp, %rdi
+
+       call route_exception
+
+       pop %rax
+       pop %rcx
+       pop %rdx
+       pop %rbx
+       pop %rbp
+       pop %rsi
+       pop %rdi
+       pop %r8
+       pop %r9
+       pop %r10
+       pop %r11
+       pop %r12
+       pop %r13
+       pop %r14
+       pop %r15
+
+       /* Discard vector and error code. */
+       add $16, %rsp
+       iretq
+
+/*
+ * Build the handle_exception wrappers which push the vector/error code on the
+ * stack and an array of pointers to those wrappers.
+ */
+.pushsection .rodata
+.globl idt_handlers
+idt_handlers:
+.popsection
+
+.macro HANDLERS has_error from to
+       vector = \from
+       .rept \to - \from + 1
+       .align 8
+
+       /* Fetch current address and append it to idt_handlers. */
+       current_handler = .
+.pushsection .rodata
+.quad current_handler
+.popsection
+
+       .if ! \has_error
+       pushq $0
+       .endif
+       pushq $vector
+       jmp handle_exception
+       vector = vector + 1
+       .endr
+.endm
+
+.global idt_handler_code
+idt_handler_code:
+       HANDLERS has_error=0 from=0  to=7
+       HANDLERS has_error=1 from=8  to=8
+       HANDLERS has_error=0 from=9  to=9
+       HANDLERS has_error=1 from=10 to=14
+       HANDLERS has_error=0 from=15 to=16
+       HANDLERS has_error=1 from=17 to=17
+       HANDLERS has_error=0 from=18 to=255
+
+.section        .note.GNU-stack, "", %progbits
index f6eb34eaa0d222df43ae2b79e3a39f8c62ae4958..d10c5c05bdf0b9b3f8807448425a98e6dc902298 100644 (file)
 #include "../kvm_util_internal.h"
 #include "processor.h"
 
+#ifndef NUM_INTERRUPTS
+#define NUM_INTERRUPTS 256
+#endif
+
+#define DEFAULT_CODE_SELECTOR 0x8
+#define DEFAULT_DATA_SELECTOR 0x10
+
 /* Minimum physical address used for virtual translation tables. */
 #define KVM_GUEST_PAGE_TABLE_MIN_PADDR 0x180000
 
+vm_vaddr_t exception_handlers;
+
 /* Virtual translation table structure declarations */
 struct pageMapL4Entry {
        uint64_t present:1;
@@ -392,11 +401,12 @@ static void kvm_seg_fill_gdt_64bit(struct kvm_vm *vm, struct kvm_segment *segp)
        desc->limit0 = segp->limit & 0xFFFF;
        desc->base0 = segp->base & 0xFFFF;
        desc->base1 = segp->base >> 16;
-       desc->s = segp->s;
        desc->type = segp->type;
+       desc->s = segp->s;
        desc->dpl = segp->dpl;
        desc->p = segp->present;
        desc->limit1 = segp->limit >> 16;
+       desc->avl = segp->avl;
        desc->l = segp->l;
        desc->db = segp->db;
        desc->g = segp->g;
@@ -556,9 +566,9 @@ static void vcpu_setup(struct kvm_vm *vm, int vcpuid, int pgd_memslot, int gdt_m
                sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX);
 
                kvm_seg_set_unusable(&sregs.ldt);
-               kvm_seg_set_kernel_code_64bit(vm, 0x8, &sregs.cs);
-               kvm_seg_set_kernel_data_64bit(vm, 0x10, &sregs.ds);
-               kvm_seg_set_kernel_data_64bit(vm, 0x10, &sregs.es);
+               kvm_seg_set_kernel_code_64bit(vm, DEFAULT_CODE_SELECTOR, &sregs.cs);
+               kvm_seg_set_kernel_data_64bit(vm, DEFAULT_DATA_SELECTOR, &sregs.ds);
+               kvm_seg_set_kernel_data_64bit(vm, DEFAULT_DATA_SELECTOR, &sregs.es);
                kvm_setup_tss_64bit(vm, &sregs.tr, 0x18, gdt_memslot, pgd_memslot);
                break;
 
@@ -1118,3 +1128,131 @@ void kvm_get_cpu_address_width(unsigned int *pa_bits, unsigned int *va_bits)
                *va_bits = (entry->eax >> 8) & 0xff;
        }
 }
+
+struct idt_entry {
+       uint16_t offset0;
+       uint16_t selector;
+       uint16_t ist : 3;
+       uint16_t : 5;
+       uint16_t type : 4;
+       uint16_t : 1;
+       uint16_t dpl : 2;
+       uint16_t p : 1;
+       uint16_t offset1;
+       uint32_t offset2; uint32_t reserved;
+};
+
+static void set_idt_entry(struct kvm_vm *vm, int vector, unsigned long addr,
+                         int dpl, unsigned short selector)
+{
+       struct idt_entry *base =
+               (struct idt_entry *)addr_gva2hva(vm, vm->idt);
+       struct idt_entry *e = &base[vector];
+
+       memset(e, 0, sizeof(*e));
+       e->offset0 = addr;
+       e->selector = selector;
+       e->ist = 0;
+       e->type = 14;
+       e->dpl = dpl;
+       e->p = 1;
+       e->offset1 = addr >> 16;
+       e->offset2 = addr >> 32;
+}
+
+void kvm_exit_unexpected_vector(uint32_t value)
+{
+       outl(UNEXPECTED_VECTOR_PORT, value);
+}
+
+void route_exception(struct ex_regs *regs)
+{
+       typedef void(*handler)(struct ex_regs *);
+       handler *handlers = (handler *)exception_handlers;
+
+       if (handlers && handlers[regs->vector]) {
+               handlers[regs->vector](regs);
+               return;
+       }
+
+       kvm_exit_unexpected_vector(regs->vector);
+}
+
+void vm_init_descriptor_tables(struct kvm_vm *vm)
+{
+       extern void *idt_handlers;
+       int i;
+
+       vm->idt = vm_vaddr_alloc(vm, getpagesize(), 0x2000, 0, 0);
+       vm->handlers = vm_vaddr_alloc(vm, 256 * sizeof(void *), 0x2000, 0, 0);
+       /* Handlers have the same address in both address spaces.*/
+       for (i = 0; i < NUM_INTERRUPTS; i++)
+               set_idt_entry(vm, i, (unsigned long)(&idt_handlers)[i], 0,
+                       DEFAULT_CODE_SELECTOR);
+}
+
+void vcpu_init_descriptor_tables(struct kvm_vm *vm, uint32_t vcpuid)
+{
+       struct kvm_sregs sregs;
+
+       vcpu_sregs_get(vm, vcpuid, &sregs);
+       sregs.idt.base = vm->idt;
+       sregs.idt.limit = NUM_INTERRUPTS * sizeof(struct idt_entry) - 1;
+       sregs.gdt.base = vm->gdt;
+       sregs.gdt.limit = getpagesize() - 1;
+       kvm_seg_set_kernel_data_64bit(NULL, DEFAULT_DATA_SELECTOR, &sregs.gs);
+       vcpu_sregs_set(vm, vcpuid, &sregs);
+       *(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
+}
+
+void vm_handle_exception(struct kvm_vm *vm, int vector,
+                        void (*handler)(struct ex_regs *))
+{
+       vm_vaddr_t *handlers = (vm_vaddr_t *)addr_gva2hva(vm, vm->handlers);
+
+       handlers[vector] = (vm_vaddr_t)handler;
+}
+
+void assert_on_unhandled_exception(struct kvm_vm *vm, uint32_t vcpuid)
+{
+       if (vcpu_state(vm, vcpuid)->exit_reason == KVM_EXIT_IO
+               && vcpu_state(vm, vcpuid)->io.port == UNEXPECTED_VECTOR_PORT
+               && vcpu_state(vm, vcpuid)->io.size == 4) {
+               /* Grab pointer to io data */
+               uint32_t *data = (void *)vcpu_state(vm, vcpuid)
+                       + vcpu_state(vm, vcpuid)->io.data_offset;
+
+               TEST_ASSERT(false,
+                           "Unexpected vectored event in guest (vector:0x%x)",
+                           *data);
+       }
+}
+
+bool set_cpuid(struct kvm_cpuid2 *cpuid,
+              struct kvm_cpuid_entry2 *ent)
+{
+       int i;
+
+       for (i = 0; i < cpuid->nent; i++) {
+               struct kvm_cpuid_entry2 *cur = &cpuid->entries[i];
+
+               if (cur->function != ent->function || cur->index != ent->index)
+                       continue;
+
+               memcpy(cur, ent, sizeof(struct kvm_cpuid_entry2));
+               return true;
+       }
+
+       return false;
+}
+
+uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2,
+                      uint64_t a3)
+{
+       uint64_t r;
+
+       asm volatile("vmcall"
+                    : "=a"(r)
+                    : "b"(a0), "c"(a1), "d"(a2), "S"(a3));
+       return r;
+}
index da4d89ad54193b4c6bfd3ca9fe7c56632952c8ab..a3489973e2904504a7587c12cb9a05b05a93296b 100644 (file)
@@ -40,6 +40,9 @@ uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc)
        struct kvm_run *run = vcpu_state(vm, vcpu_id);
        struct ucall ucall = {};
 
+       if (uc)
+               memset(uc, 0, sizeof(*uc));
+
        if (run->exit_reason == KVM_EXIT_IO && run->io.port == UCALL_PIO_PORT) {
                struct kvm_regs regs;
 
index f1e00d43eea2e0bc0a98c900d067958802346948..2448b30e8efae6f7e6c65d201a0bf408225ab535 100644 (file)
@@ -542,3 +542,12 @@ void prepare_eptp(struct vmx_pages *vmx, struct kvm_vm *vm,
        vmx->eptp_hva = addr_gva2hva(vm, (uintptr_t)vmx->eptp);
        vmx->eptp_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->eptp);
 }
+
+void prepare_virtualize_apic_accesses(struct vmx_pages *vmx, struct kvm_vm *vm,
+                                     uint32_t eptp_memslot)
+{
+       vmx->apic_access = (void *)vm_vaddr_alloc(vm, getpagesize(),
+                                                 0x10000, 0, 0);
+       vmx->apic_access_hva = addr_gva2hva(vm, (uintptr_t)vmx->apic_access);
+       vmx->apic_access_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->apic_access);
+}
diff --git a/tools/testing/selftests/kvm/x86_64/kvm_pv_test.c b/tools/testing/selftests/kvm/x86_64/kvm_pv_test.c
new file mode 100644 (file)
index 0000000..b10a274
--- /dev/null
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2020, Google LLC.
+ *
+ * Tests for KVM paravirtual feature disablement
+ */
+#include <asm/kvm_para.h>
+#include <linux/kvm_para.h>
+#include <stdint.h>
+
+#include "test_util.h"
+#include "kvm_util.h"
+#include "processor.h"
+
+extern unsigned char rdmsr_start;
+extern unsigned char rdmsr_end;
+
+static u64 do_rdmsr(u32 idx)
+{
+       u32 lo, hi;
+
+       asm volatile("rdmsr_start: rdmsr;"
+                    "rdmsr_end:"
+                    : "=a"(lo), "=c"(hi)
+                    : "c"(idx));
+
+       return (((u64) hi) << 32) | lo;
+}
+
+extern unsigned char wrmsr_start;
+extern unsigned char wrmsr_end;
+
+static void do_wrmsr(u32 idx, u64 val)
+{
+       u32 lo, hi;
+
+       lo = val;
+       hi = val >> 32;
+
+       asm volatile("wrmsr_start: wrmsr;"
+                    "wrmsr_end:"
+                    : : "a"(lo), "c"(idx), "d"(hi));
+}
+
+static int nr_gp;
+
+static void guest_gp_handler(struct ex_regs *regs)
+{
+       unsigned char *rip = (unsigned char *)regs->rip;
+       bool r, w;
+
+       r = rip == &rdmsr_start;
+       w = rip == &wrmsr_start;
+       GUEST_ASSERT(r || w);
+
+       nr_gp++;
+
+       if (r)
+               regs->rip = (uint64_t)&rdmsr_end;
+       else
+               regs->rip = (uint64_t)&wrmsr_end;
+}
+
+struct msr_data {
+       uint32_t idx;
+       const char *name;
+};
+
+#define TEST_MSR(msr) { .idx = msr, .name = #msr }
+#define UCALL_PR_MSR 0xdeadbeef
+#define PR_MSR(msr) ucall(UCALL_PR_MSR, 1, msr)
+
+/*
+ * KVM paravirtual msrs to test. Expect a #GP if any of these msrs are read or
+ * written, as the KVM_CPUID_FEATURES leaf is cleared.
+ */
+static struct msr_data msrs_to_test[] = {
+       TEST_MSR(MSR_KVM_SYSTEM_TIME),
+       TEST_MSR(MSR_KVM_SYSTEM_TIME_NEW),
+       TEST_MSR(MSR_KVM_WALL_CLOCK),
+       TEST_MSR(MSR_KVM_WALL_CLOCK_NEW),
+       TEST_MSR(MSR_KVM_ASYNC_PF_EN),
+       TEST_MSR(MSR_KVM_STEAL_TIME),
+       TEST_MSR(MSR_KVM_PV_EOI_EN),
+       TEST_MSR(MSR_KVM_POLL_CONTROL),
+       TEST_MSR(MSR_KVM_ASYNC_PF_INT),
+       TEST_MSR(MSR_KVM_ASYNC_PF_ACK),
+};
+
+static void test_msr(struct msr_data *msr)
+{
+       PR_MSR(msr);
+       do_rdmsr(msr->idx);
+       GUEST_ASSERT(READ_ONCE(nr_gp) == 1);
+
+       nr_gp = 0;
+       do_wrmsr(msr->idx, 0);
+       GUEST_ASSERT(READ_ONCE(nr_gp) == 1);
+       nr_gp = 0;
+}
+
+struct hcall_data {
+       uint64_t nr;
+       const char *name;
+};
+
+#define TEST_HCALL(hc) { .nr = hc, .name = #hc }
+#define UCALL_PR_HCALL 0xdeadc0de
+#define PR_HCALL(hc) ucall(UCALL_PR_HCALL, 1, hc)
+
+/*
+ * KVM hypercalls to test. Expect -KVM_ENOSYS when called, as the corresponding
+ * features have been cleared in KVM_CPUID_FEATURES.
+ */
+static struct hcall_data hcalls_to_test[] = {
+       TEST_HCALL(KVM_HC_KICK_CPU),
+       TEST_HCALL(KVM_HC_SEND_IPI),
+       TEST_HCALL(KVM_HC_SCHED_YIELD),
+};
+
+static void test_hcall(struct hcall_data *hc)
+{
+       uint64_t r;
+
+       PR_HCALL(hc);
+       r = kvm_hypercall(hc->nr, 0, 0, 0, 0);
+       GUEST_ASSERT(r == -KVM_ENOSYS);
+}
+
+static void guest_main(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(msrs_to_test); i++) {
+               test_msr(&msrs_to_test[i]);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(hcalls_to_test); i++) {
+               test_hcall(&hcalls_to_test[i]);
+       }
+
+       GUEST_DONE();
+}
+
+static void clear_kvm_cpuid_features(struct kvm_cpuid2 *cpuid)
+{
+       struct kvm_cpuid_entry2 ent = {0};
+
+       ent.function = KVM_CPUID_FEATURES;
+       TEST_ASSERT(set_cpuid(cpuid, &ent),
+                   "failed to clear KVM_CPUID_FEATURES leaf");
+}
+
+static void pr_msr(struct ucall *uc)
+{
+       struct msr_data *msr = (struct msr_data *)uc->args[0];
+
+       pr_info("testing msr: %s (%#x)\n", msr->name, msr->idx);
+}
+
+static void pr_hcall(struct ucall *uc)
+{
+       struct hcall_data *hc = (struct hcall_data *)uc->args[0];
+
+       pr_info("testing hcall: %s (%lu)\n", hc->name, hc->nr);
+}
+
+static void handle_abort(struct ucall *uc)
+{
+       TEST_FAIL("%s at %s:%ld", (const char *)uc->args[0],
+                 __FILE__, uc->args[1]);
+}
+
+#define VCPU_ID 0
+
+static void enter_guest(struct kvm_vm *vm)
+{
+       struct kvm_run *run;
+       struct ucall uc;
+       int r;
+
+       run = vcpu_state(vm, VCPU_ID);
+
+       while (true) {
+               r = _vcpu_run(vm, VCPU_ID);
+               TEST_ASSERT(!r, "vcpu_run failed: %d\n", r);
+               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
+                           "unexpected exit reason: %u (%s)",
+                           run->exit_reason, exit_reason_str(run->exit_reason));
+
+               switch (get_ucall(vm, VCPU_ID, &uc)) {
+               case UCALL_PR_MSR:
+                       pr_msr(&uc);
+                       break;
+               case UCALL_PR_HCALL:
+                       pr_hcall(&uc);
+                       break;
+               case UCALL_ABORT:
+                       handle_abort(&uc);
+                       return;
+               case UCALL_DONE:
+                       return;
+               }
+       }
+}
+
+int main(void)
+{
+       struct kvm_enable_cap cap = {0};
+       struct kvm_cpuid2 *best;
+       struct kvm_vm *vm;
+
+       if (!kvm_check_cap(KVM_CAP_ENFORCE_PV_FEATURE_CPUID)) {
+               pr_info("will skip kvm paravirt restriction tests.\n");
+               return 0;
+       }
+
+       vm = vm_create_default(VCPU_ID, 0, guest_main);
+
+       cap.cap = KVM_CAP_ENFORCE_PV_FEATURE_CPUID;
+       cap.args[0] = 1;
+       vcpu_enable_cap(vm, VCPU_ID, &cap);
+
+       best = kvm_get_supported_cpuid();
+       clear_kvm_cpuid_features(best);
+       vcpu_set_cpuid(vm, VCPU_ID, best);
+
+       vm_init_descriptor_tables(vm);
+       vcpu_init_descriptor_tables(vm, VCPU_ID);
+       vm_handle_exception(vm, GP_VECTOR, guest_gp_handler);
+
+       enter_guest(vm);
+       kvm_vm_free(vm);
+}
diff --git a/tools/testing/selftests/kvm/x86_64/vmx_apic_access_test.c b/tools/testing/selftests/kvm/x86_64/vmx_apic_access_test.c
new file mode 100644 (file)
index 0000000..1f65342
--- /dev/null
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * vmx_apic_access_test
+ *
+ * Copyright (C) 2020, Google LLC.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ *
+ * The first subtest simply checks to see that an L2 guest can be
+ * launched with a valid APIC-access address that is backed by a
+ * page of L1 physical memory.
+ *
+ * The second subtest sets the APIC-access address to a (valid) L1
+ * physical address that is not backed by memory. KVM can't handle
+ * this situation, so resuming L2 should result in a KVM exit for
+ * internal error (emulation). This is not an architectural
+ * requirement. It is just a shortcoming of KVM. The internal error
+ * is unfortunate, but it's better than what used to happen!
+ */
+
+#include "test_util.h"
+#include "kvm_util.h"
+#include "processor.h"
+#include "vmx.h"
+
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "kselftest.h"
+
+#define VCPU_ID                0
+
+/* The virtual machine object. */
+static struct kvm_vm *vm;
+
+static void l2_guest_code(void)
+{
+       /* Exit to L1 */
+       __asm__ __volatile__("vmcall");
+}
+
+static void l1_guest_code(struct vmx_pages *vmx_pages, unsigned long high_gpa)
+{
+#define L2_GUEST_STACK_SIZE 64
+       unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
+       uint32_t control;
+
+       GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages));
+       GUEST_ASSERT(load_vmcs(vmx_pages));
+
+       /* Prepare the VMCS for L2 execution. */
+       prepare_vmcs(vmx_pages, l2_guest_code,
+                    &l2_guest_stack[L2_GUEST_STACK_SIZE]);
+       control = vmreadz(CPU_BASED_VM_EXEC_CONTROL);
+       control |= CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
+       vmwrite(CPU_BASED_VM_EXEC_CONTROL, control);
+       control = vmreadz(SECONDARY_VM_EXEC_CONTROL);
+       control |= SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+       vmwrite(SECONDARY_VM_EXEC_CONTROL, control);
+       vmwrite(APIC_ACCESS_ADDR, vmx_pages->apic_access_gpa);
+
+       /* Try to launch L2 with the memory-backed APIC-access address. */
+       GUEST_SYNC(vmreadz(APIC_ACCESS_ADDR));
+       GUEST_ASSERT(!vmlaunch());
+       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
+
+       vmwrite(APIC_ACCESS_ADDR, high_gpa);
+
+       /* Try to resume L2 with the unbacked APIC-access address. */
+       GUEST_SYNC(vmreadz(APIC_ACCESS_ADDR));
+       GUEST_ASSERT(!vmresume());
+       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
+
+       GUEST_DONE();
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned long apic_access_addr = ~0ul;
+       unsigned int paddr_width;
+       unsigned int vaddr_width;
+       vm_vaddr_t vmx_pages_gva;
+       unsigned long high_gpa;
+       struct vmx_pages *vmx;
+       bool done = false;
+
+       nested_vmx_check_supported();
+
+       vm = vm_create_default(VCPU_ID, 0, (void *) l1_guest_code);
+       vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
+
+       kvm_get_cpu_address_width(&paddr_width, &vaddr_width);
+       high_gpa = (1ul << paddr_width) - getpagesize();
+       if ((unsigned long)DEFAULT_GUEST_PHY_PAGES * getpagesize() > high_gpa) {
+               print_skip("No unbacked physical page available");
+               exit(KSFT_SKIP);
+       }
+
+       vmx = vcpu_alloc_vmx(vm, &vmx_pages_gva);
+       prepare_virtualize_apic_accesses(vmx, vm, 0);
+       vcpu_args_set(vm, VCPU_ID, 2, vmx_pages_gva, high_gpa);
+
+       while (!done) {
+               volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID);
+               struct ucall uc;
+
+               vcpu_run(vm, VCPU_ID);
+               if (apic_access_addr == high_gpa) {
+                       TEST_ASSERT(run->exit_reason ==
+                                   KVM_EXIT_INTERNAL_ERROR,
+                                   "Got exit reason other than KVM_EXIT_INTERNAL_ERROR: %u (%s)\n",
+                                   run->exit_reason,
+                                   exit_reason_str(run->exit_reason));
+                       TEST_ASSERT(run->internal.suberror ==
+                                   KVM_INTERNAL_ERROR_EMULATION,
+                                   "Got internal suberror other than KVM_INTERNAL_ERROR_EMULATION: %u\n",
+                                   run->internal.suberror);
+                       break;
+               }
+               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
+                           "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
+                           run->exit_reason,
+                           exit_reason_str(run->exit_reason));
+
+               switch (get_ucall(vm, VCPU_ID, &uc)) {
+               case UCALL_ABORT:
+                       TEST_FAIL("%s at %s:%ld", (const char *)uc.args[0],
+                                 __FILE__, uc.args[1]);
+                       /* NOT REACHED */
+               case UCALL_SYNC:
+                       apic_access_addr = uc.args[1];
+                       break;
+               case UCALL_DONE:
+                       done = true;
+                       break;
+               default:
+                       TEST_ASSERT(false, "Unknown ucall %lu", uc.cmd);
+               }
+       }
+       kvm_vm_free(vm);
+       return 0;
+}
index 30848ca3655598a92e3729722f6d65d992b41cfd..a5ce26d548e4f37c67c9ea71f2eec470a7378c61 100644 (file)
@@ -136,7 +136,7 @@ endif
 ifeq ($(OVERRIDE_TARGETS),)
 LOCAL_HDRS := $(selfdir)/kselftest_harness.h $(selfdir)/kselftest.h
 $(OUTPUT)/%:%.c $(LOCAL_HDRS)
-       $(LINK.c) $^ $(LDLIBS) -o $@
+       $(LINK.c) $(filter-out $(LOCAL_HDRS),$^) $(LDLIBS) -o $@
 
 $(OUTPUT)/%.o:%.S
        $(COMPILE.S) $^ -o $@
index bb11de90c0c9ed51a396a2cc127c7ea809e454c9..f6f2965e17af1f4518c840fb57a25f25bee06ca5 100644 (file)
@@ -4,3 +4,4 @@ CONFIG_USER_NS=y
 CONFIG_PID_NS=y
 CONFIG_NET_NS=y
 CONFIG_CGROUPS=y
+CONFIG_CHECKPOINT_RESTORE=y
index 7758c98be0158483ea6d40d2c37d0a5a1d4b3c6a..0930e2411dfb9a1337988e4cb815e14bfa4464b5 100644 (file)
@@ -204,7 +204,10 @@ TEST_F(child, fetch_fd)
        fd = sys_pidfd_getfd(self->pidfd, self->remote_fd, 0);
        ASSERT_GE(fd, 0);
 
-       EXPECT_EQ(0, sys_kcmp(getpid(), self->pid, KCMP_FILE, fd, self->remote_fd));
+       ret = sys_kcmp(getpid(), self->pid, KCMP_FILE, fd, self->remote_fd);
+       if (ret < 0 && errno == ENOSYS)
+               SKIP(return, "kcmp() syscall not supported");
+       EXPECT_EQ(ret, 0);
 
        ret = fcntl(fd, F_GETFD);
        ASSERT_GE(ret, 0);
index b9fe75fc3e517b75d9a70c9ac3f1d60f492392a0..8a59438ccc78bf38e8a8f0b2407cf8af61fc9215 100644 (file)
@@ -6,7 +6,6 @@
 #include <inttypes.h>
 #include <limits.h>
 #include <linux/types.h>
-#include <linux/wait.h>
 #include <sched.h>
 #include <signal.h>
 #include <stdbool.h>
index 4b115444dfe901bb8696bb0059ab645120846219..6108112753573dc4b77e611f6bfcaddefe8c2670 100644 (file)
@@ -3,7 +3,6 @@
 #define _GNU_SOURCE
 #include <errno.h>
 #include <linux/types.h>
-#include <linux/wait.h>
 #include <poll.h>
 #include <signal.h>
 #include <stdbool.h>
index 1f085b922c6ec1ccfe3422870f3d497039c60d15..6e2f2cd400caa5a4be93bf0353282bba63d7b132 100644 (file)
@@ -16,7 +16,6 @@
 #include <unistd.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
-#include <linux/kcmp.h>
 
 #include "pidfd.h"
 #include "../clone3/clone3_selftests.h"
index c585aaa2acd8a8ac4a7b33e1391ea23f5dd31563..529eb700ac26a39833a4e2c4c25b4caeb57af272 100644 (file)
@@ -330,7 +330,7 @@ static int test_pidfd_send_signal_recycled_pid_fail(void)
                ksft_exit_fail_msg("%s test: Failed to recycle pid %d\n",
                                   test_name, PID_RECYCLE);
        case PIDFD_SKIP:
-               ksft_print_msg("%s test: Skipping test\n", test_name);
+               ksft_test_result_skip("%s test: Skipping test\n", test_name);
                ret = 0;
                break;
        case PIDFD_XFAIL:
index 052b5a775dc2609e13c149c43002ed7e48e6b8a7..b7d188fc87c745fb856e1ecdcc9faec2c364c2d7 100644 (file)
@@ -42,6 +42,11 @@ int perf_event_enable(int fd);
 int perf_event_disable(int fd);
 int perf_event_reset(int fd);
 
+struct perf_event_read {
+       __u64 nr;
+       __u64 l1d_misses;
+};
+
 #if !defined(__GLIBC_PREREQ) || !__GLIBC_PREREQ(2, 30)
 #include <unistd.h>
 #include <sys/syscall.h>
index f795e06f5ae3e6d9349a4081316b18da50d7ed14..4257a1f156bb8f4883796f7207aa409aaf52f601 100644 (file)
@@ -1,2 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
 rfi_flush
+entry_flush
index eadbbff50be6c1db35d534f6634eeb1d7855f290..f25e854fe3709a7faf1638d1b7fbacaa00e18307 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0+
 
-TEST_GEN_PROGS := rfi_flush spectre_v2
+TEST_GEN_PROGS := rfi_flush entry_flush spectre_v2
 top_srcdir = ../../../../..
 
 CFLAGS += -I../../../../../usr/include
@@ -11,3 +11,5 @@ $(TEST_GEN_PROGS): ../harness.c ../utils.c
 
 $(OUTPUT)/spectre_v2: CFLAGS += -m64
 $(OUTPUT)/spectre_v2: ../pmu/event.c branch_loops.S
+$(OUTPUT)/rfi_flush: flush_utils.c
+$(OUTPUT)/entry_flush: flush_utils.c
diff --git a/tools/testing/selftests/powerpc/security/entry_flush.c b/tools/testing/selftests/powerpc/security/entry_flush.c
new file mode 100644 (file)
index 0000000..78cf914
--- /dev/null
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright 2018 IBM Corporation.
+ */
+
+#define __SANE_USERSPACE_TYPES__
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "utils.h"
+#include "flush_utils.h"
+
+int entry_flush_test(void)
+{
+       char *p;
+       int repetitions = 10;
+       int fd, passes = 0, iter, rc = 0;
+       struct perf_event_read v;
+       __u64 l1d_misses_total = 0;
+       unsigned long iterations = 100000, zero_size = 24 * 1024;
+       unsigned long l1d_misses_expected;
+       int rfi_flush_orig;
+       int entry_flush, entry_flush_orig;
+
+       SKIP_IF(geteuid() != 0);
+
+       // The PMU event we use only works on Power7 or later
+       SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
+
+       if (read_debugfs_file("powerpc/rfi_flush", &rfi_flush_orig) < 0) {
+               perror("Unable to read powerpc/rfi_flush debugfs file");
+               SKIP_IF(1);
+       }
+
+       if (read_debugfs_file("powerpc/entry_flush", &entry_flush_orig) < 0) {
+               perror("Unable to read powerpc/entry_flush debugfs file");
+               SKIP_IF(1);
+       }
+
+       if (rfi_flush_orig != 0) {
+               if (write_debugfs_file("powerpc/rfi_flush", 0) < 0) {
+                       perror("error writing to powerpc/rfi_flush debugfs file");
+                       FAIL_IF(1);
+               }
+       }
+
+       entry_flush = entry_flush_orig;
+
+       fd = perf_event_open_counter(PERF_TYPE_RAW, /* L1d miss */ 0x400f0, -1);
+       FAIL_IF(fd < 0);
+
+       p = (char *)memalign(zero_size, CACHELINE_SIZE);
+
+       FAIL_IF(perf_event_enable(fd));
+
+       // disable L1 prefetching
+       set_dscr(1);
+
+       iter = repetitions;
+
+       /*
+        * We expect to see l1d miss for each cacheline access when entry_flush
+        * is set. Allow a small variation on this.
+        */
+       l1d_misses_expected = iterations * (zero_size / CACHELINE_SIZE - 2);
+
+again:
+       FAIL_IF(perf_event_reset(fd));
+
+       syscall_loop(p, iterations, zero_size);
+
+       FAIL_IF(read(fd, &v, sizeof(v)) != sizeof(v));
+
+       if (entry_flush && v.l1d_misses >= l1d_misses_expected)
+               passes++;
+       else if (!entry_flush && v.l1d_misses < (l1d_misses_expected / 2))
+               passes++;
+
+       l1d_misses_total += v.l1d_misses;
+
+       while (--iter)
+               goto again;
+
+       if (passes < repetitions) {
+               printf("FAIL (L1D misses with entry_flush=%d: %llu %c %lu) [%d/%d failures]\n",
+                      entry_flush, l1d_misses_total, entry_flush ? '<' : '>',
+                      entry_flush ? repetitions * l1d_misses_expected :
+                      repetitions * l1d_misses_expected / 2,
+                      repetitions - passes, repetitions);
+               rc = 1;
+       } else {
+               printf("PASS (L1D misses with entry_flush=%d: %llu %c %lu) [%d/%d pass]\n",
+                      entry_flush, l1d_misses_total, entry_flush ? '>' : '<',
+                      entry_flush ? repetitions * l1d_misses_expected :
+                      repetitions * l1d_misses_expected / 2,
+                      passes, repetitions);
+       }
+
+       if (entry_flush == entry_flush_orig) {
+               entry_flush = !entry_flush_orig;
+               if (write_debugfs_file("powerpc/entry_flush", entry_flush) < 0) {
+                       perror("error writing to powerpc/entry_flush debugfs file");
+                       return 1;
+               }
+               iter = repetitions;
+               l1d_misses_total = 0;
+               passes = 0;
+               goto again;
+       }
+
+       perf_event_disable(fd);
+       close(fd);
+
+       set_dscr(0);
+
+       if (write_debugfs_file("powerpc/rfi_flush", rfi_flush_orig) < 0) {
+               perror("unable to restore original value of powerpc/rfi_flush debugfs file");
+               return 1;
+       }
+
+       if (write_debugfs_file("powerpc/entry_flush", entry_flush_orig) < 0) {
+               perror("unable to restore original value of powerpc/entry_flush debugfs file");
+               return 1;
+       }
+
+       return rc;
+}
+
+int main(int argc, char *argv[])
+{
+       return test_harness(entry_flush_test, "entry_flush_test");
+}
diff --git a/tools/testing/selftests/powerpc/security/flush_utils.c b/tools/testing/selftests/powerpc/security/flush_utils.c
new file mode 100644 (file)
index 0000000..0c3c4c4
--- /dev/null
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright 2018 IBM Corporation.
+ */
+
+#define __SANE_USERSPACE_TYPES__
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "utils.h"
+#include "flush_utils.h"
+
+static inline __u64 load(void *addr)
+{
+       __u64 tmp;
+
+       asm volatile("ld %0,0(%1)" : "=r"(tmp) : "b"(addr));
+
+       return tmp;
+}
+
+void syscall_loop(char *p, unsigned long iterations,
+                 unsigned long zero_size)
+{
+       for (unsigned long i = 0; i < iterations; i++) {
+               for (unsigned long j = 0; j < zero_size; j += CACHELINE_SIZE)
+                       load(p + j);
+               getppid();
+       }
+}
+
+static void sigill_handler(int signr, siginfo_t *info, void *unused)
+{
+       static int warned;
+       ucontext_t *ctx = (ucontext_t *)unused;
+       unsigned long *pc = &UCONTEXT_NIA(ctx);
+
+       /* mtspr 3,RS to check for move to DSCR below */
+       if ((*((unsigned int *)*pc) & 0xfc1fffff) == 0x7c0303a6) {
+               if (!warned++)
+                       printf("WARNING: Skipping over dscr setup. Consider running 'ppc64_cpu --dscr=1' manually.\n");
+               *pc += 4;
+       } else {
+               printf("SIGILL at %p\n", pc);
+               abort();
+       }
+}
+
+void set_dscr(unsigned long val)
+{
+       static int init;
+       struct sigaction sa;
+
+       if (!init) {
+               memset(&sa, 0, sizeof(sa));
+               sa.sa_sigaction = sigill_handler;
+               sa.sa_flags = SA_SIGINFO;
+               if (sigaction(SIGILL, &sa, NULL))
+                       perror("sigill_handler");
+               init = 1;
+       }
+
+       asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR));
+}
diff --git a/tools/testing/selftests/powerpc/security/flush_utils.h b/tools/testing/selftests/powerpc/security/flush_utils.h
new file mode 100644 (file)
index 0000000..07a5eb3
--- /dev/null
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+/*
+ * Copyright 2018 IBM Corporation.
+ */
+
+#ifndef _SELFTESTS_POWERPC_SECURITY_FLUSH_UTILS_H
+#define _SELFTESTS_POWERPC_SECURITY_FLUSH_UTILS_H
+
+#define CACHELINE_SIZE 128
+
+void syscall_loop(char *p, unsigned long iterations,
+                 unsigned long zero_size);
+
+void set_dscr(unsigned long val);
+
+#endif /* _SELFTESTS_POWERPC_SECURITY_FLUSH_UTILS_H */
index 93a65bd1f231b9b13d07d5ea086ebbe43f93f405..7565fd786640fc38eb280bbd9022903815caea59 100644 (file)
 #include <stdint.h>
 #include <malloc.h>
 #include <unistd.h>
-#include <signal.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include "utils.h"
+#include "flush_utils.h"
 
-#define CACHELINE_SIZE 128
-
-struct perf_event_read {
-       __u64 nr;
-       __u64 l1d_misses;
-};
-
-static inline __u64 load(void *addr)
-{
-       __u64 tmp;
-
-       asm volatile("ld %0,0(%1)" : "=r"(tmp) : "b"(addr));
-
-       return tmp;
-}
-
-static void syscall_loop(char *p, unsigned long iterations,
-                        unsigned long zero_size)
-{
-       for (unsigned long i = 0; i < iterations; i++) {
-               for (unsigned long j = 0; j < zero_size; j += CACHELINE_SIZE)
-                       load(p + j);
-               getppid();
-       }
-}
-
-static void sigill_handler(int signr, siginfo_t *info, void *unused)
-{
-       static int warned = 0;
-       ucontext_t *ctx = (ucontext_t *)unused;
-       unsigned long *pc = &UCONTEXT_NIA(ctx);
-
-       /* mtspr 3,RS to check for move to DSCR below */
-       if ((*((unsigned int *)*pc) & 0xfc1fffff) == 0x7c0303a6) {
-               if (!warned++)
-                       printf("WARNING: Skipping over dscr setup. Consider running 'ppc64_cpu --dscr=1' manually.\n");
-               *pc += 4;
-       } else {
-               printf("SIGILL at %p\n", pc);
-               abort();
-       }
-}
-
-static void set_dscr(unsigned long val)
-{
-       static int init = 0;
-       struct sigaction sa;
-
-       if (!init) {
-               memset(&sa, 0, sizeof(sa));
-               sa.sa_sigaction = sigill_handler;
-               sa.sa_flags = SA_SIGINFO;
-               if (sigaction(SIGILL, &sa, NULL))
-                       perror("sigill_handler");
-               init = 1;
-       }
-
-       asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR));
-}
 
 int rfi_flush_test(void)
 {
@@ -85,19 +26,33 @@ int rfi_flush_test(void)
        __u64 l1d_misses_total = 0;
        unsigned long iterations = 100000, zero_size = 24 * 1024;
        unsigned long l1d_misses_expected;
-       int rfi_flush_org, rfi_flush;
+       int rfi_flush_orig, rfi_flush;
+       int have_entry_flush, entry_flush_orig;
 
        SKIP_IF(geteuid() != 0);
 
        // The PMU event we use only works on Power7 or later
        SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
 
-       if (read_debugfs_file("powerpc/rfi_flush", &rfi_flush_org)) {
+       if (read_debugfs_file("powerpc/rfi_flush", &rfi_flush_orig) < 0) {
                perror("Unable to read powerpc/rfi_flush debugfs file");
                SKIP_IF(1);
        }
 
-       rfi_flush = rfi_flush_org;
+       if (read_debugfs_file("powerpc/entry_flush", &entry_flush_orig) < 0) {
+               have_entry_flush = 0;
+       } else {
+               have_entry_flush = 1;
+
+               if (entry_flush_orig != 0) {
+                       if (write_debugfs_file("powerpc/entry_flush", 0) < 0) {
+                               perror("error writing to powerpc/entry_flush debugfs file");
+                               return 1;
+                       }
+               }
+       }
+
+       rfi_flush = rfi_flush_orig;
 
        fd = perf_event_open_counter(PERF_TYPE_RAW, /* L1d miss */ 0x400f0, -1);
        FAIL_IF(fd < 0);
@@ -106,6 +61,7 @@ int rfi_flush_test(void)
 
        FAIL_IF(perf_event_enable(fd));
 
+       // disable L1 prefetching
        set_dscr(1);
 
        iter = repetitions;
@@ -147,8 +103,8 @@ again:
                       repetitions * l1d_misses_expected / 2,
                       passes, repetitions);
 
-       if (rfi_flush == rfi_flush_org) {
-               rfi_flush = !rfi_flush_org;
+       if (rfi_flush == rfi_flush_orig) {
+               rfi_flush = !rfi_flush_orig;
                if (write_debugfs_file("powerpc/rfi_flush", rfi_flush) < 0) {
                        perror("error writing to powerpc/rfi_flush debugfs file");
                        return 1;
@@ -164,11 +120,19 @@ again:
 
        set_dscr(0);
 
-       if (write_debugfs_file("powerpc/rfi_flush", rfi_flush_org) < 0) {
+       if (write_debugfs_file("powerpc/rfi_flush", rfi_flush_orig) < 0) {
                perror("unable to restore original value of powerpc/rfi_flush debugfs file");
                return 1;
        }
 
+       if (have_entry_flush) {
+               if (write_debugfs_file("powerpc/entry_flush", entry_flush_orig) < 0) {
+                       perror("unable to restore original value of powerpc/entry_flush "
+                              "debugfs file");
+                       return 1;
+               }
+       }
+
        return rc;
 }
 
index 471e2aa280776fce48921d8ecda7e92d5f5e876e..fb4fe9188806e41ee4e401e9d46d36c5cc996af7 100644 (file)
@@ -14,7 +14,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 /* Test that /proc/loadavg correctly reports last pid in pid namespace. */
-#define _GNU_SOURCE
 #include <errno.h>
 #include <sched.h>
 #include <sys/types.h>
index 9f6d000c02455135d713709f54268ea10bf64900..8511dcfe67c755719ecf9f58da6dfe7910b904cd 100644 (file)
@@ -13,7 +13,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-#define _GNU_SOURCE
 #include <unistd.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
index 30e2b78490898351a97e507018a0298e8a40e664..e7ceabed7f51f5c4588fa13653602b7340a173e5 100644 (file)
@@ -15,7 +15,6 @@
  */
 // Test that values in /proc/uptime increment monotonically
 // while shifting across CPUs.
-#define _GNU_SOURCE
 #undef NDEBUG
 #include <assert.h>
 #include <unistd.h>
index 4a180439ee9e524d12360d766fb65d189c558515..26c72f2b61b1b23220eeb3e27dfea82c75661fa9 100644 (file)
@@ -1758,10 +1758,10 @@ TEST_F(TRACE_poke, getpid_runs_normally)
                 * and the code is stored as a positive value.  \
                 */                                             \
                if (_result < 0) {                              \
-                       SYSCALL_RET(_regs) = -result;           \
+                       SYSCALL_RET(_regs) = -_result;          \
                        (_regs).ccr |= 0x10000000;              \
                } else {                                        \
-                       SYSCALL_RET(_regs) = result;            \
+                       SYSCALL_RET(_regs) = _result;           \
                        (_regs).ccr &= ~0x10000000;             \
                }                                               \
        } while (0)
@@ -1804,8 +1804,8 @@ TEST_F(TRACE_poke, getpid_runs_normally)
 #define SYSCALL_RET(_regs)     (_regs).a[(_regs).windowbase * 4 + 2]
 #elif defined(__sh__)
 # define ARCH_REGS             struct pt_regs
-# define SYSCALL_NUM(_regs)    (_regs).gpr[3]
-# define SYSCALL_RET(_regs)    (_regs).gpr[0]
+# define SYSCALL_NUM(_regs)    (_regs).regs[3]
+# define SYSCALL_RET(_regs)    (_regs).regs[0]
 #else
 # error "Do not know how to find your architecture's registers and syscalls"
 #endif
index c33a7aac27ff78a45c1fe43823ef96df185cfecf..b71828df5a6ddbae7e1861722ac4f9f9651ec6a4 100644 (file)
@@ -59,6 +59,7 @@ CONFIG_NET_IFE_SKBPRIO=m
 CONFIG_NET_IFE_SKBTCINDEX=m
 CONFIG_NET_SCH_FIFO=y
 CONFIG_NET_SCH_ETS=m
+CONFIG_NET_SCH_RED=m
 
 #
 ## Network testing
index bb543bf69d69451a32301623ca2019d18b6b3a07..361235ad574be10be1ce613445596bc1428368c8 100644 (file)
         ],
         "cmdUnderTest": "$TC filter add dev $DEV2 protocol ip pref 1 ingress flower dst_mac e4:11:22:11:4a:51 action drop",
         "expExitCode": "0",
-        "verifyCmd": "$TC filter show terse dev $DEV2 ingress",
+        "verifyCmd": "$TC -br filter show dev $DEV2 ingress",
         "matchPattern": "filter protocol ip pref 1 flower.*handle",
         "matchCount": "1",
         "teardown": [
         ],
         "cmdUnderTest": "$TC filter add dev $DEV2 protocol ip pref 1 ingress flower dst_mac e4:11:22:11:4a:51 action drop",
         "expExitCode": "0",
-        "verifyCmd": "$TC filter show terse dev $DEV2 ingress",
+        "verifyCmd": "$TC -br filter show dev $DEV2 ingress",
         "matchPattern": "  dst_mac e4:11:22:11:4a:51",
         "matchCount": "0",
         "teardown": [
index 30873b19d04bc033aa9974bec5570f919f9dce68..691893afc15d87b181b819c745605ef92412eb12 100644 (file)
@@ -60,9 +60,13 @@ ifeq ($(CAN_BUILD_X86_64),1)
 TEST_GEN_FILES += $(BINARIES_64)
 endif
 else
+
+ifneq (,$(findstring $(ARCH),powerpc))
 TEST_GEN_FILES += protection_keys
 endif
 
+endif
+
 ifneq (,$(filter $(MACHINE),arm64 ia64 mips64 parisc64 ppc64 ppc64le riscv64 s390x sh64 sparc64 x86_64))
 TEST_GEN_FILES += va_128TBswitch
 TEST_GEN_FILES += virtual_address_range
index 9b0912a017777330cf1d0fac25640edaa4c52608..c4425597769a06ee1650afc18837f1178feb3c6b 100644 (file)
@@ -206,19 +206,19 @@ static int hugetlb_release_pages(char *rel_area)
        return ret;
 }
 
-
 static void hugetlb_allocate_area(void **alloc_area)
 {
        void *area_alias = NULL;
        char **alloc_area_alias;
+
        *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
                           (map_shared ? MAP_SHARED : MAP_PRIVATE) |
                           MAP_HUGETLB,
                           huge_fd, *alloc_area == area_src ? 0 :
                           nr_pages * page_size);
        if (*alloc_area == MAP_FAILED) {
-               fprintf(stderr, "mmap of hugetlbfs file failed\n");
-               *alloc_area = NULL;
+               perror("mmap of hugetlbfs file failed");
+               goto fail;
        }
 
        if (map_shared) {
@@ -227,14 +227,11 @@ static void hugetlb_allocate_area(void **alloc_area)
                                  huge_fd, *alloc_area == area_src ? 0 :
                                  nr_pages * page_size);
                if (area_alias == MAP_FAILED) {
-                       if (munmap(*alloc_area, nr_pages * page_size) < 0) {
-                               perror("hugetlb munmap");
-                               exit(1);
-                       }
-                       *alloc_area = NULL;
-                       return;
+                       perror("mmap of hugetlb file alias failed");
+                       goto fail_munmap;
                }
        }
+
        if (*alloc_area == area_src) {
                huge_fd_off0 = *alloc_area;
                alloc_area_alias = &area_src_alias;
@@ -243,6 +240,16 @@ static void hugetlb_allocate_area(void **alloc_area)
        }
        if (area_alias)
                *alloc_area_alias = area_alias;
+
+       return;
+
+fail_munmap:
+       if (munmap(*alloc_area, nr_pages * page_size) < 0) {
+               perror("hugetlb munmap");
+               exit(1);
+       }
+fail:
+       *alloc_area = NULL;
 }
 
 static void hugetlb_alias_mapping(__u64 *start, size_t len, unsigned long offset)
index d77f4829f1e0702fa63f4019683101df9fac9e60..74c69b75f6f5ab944c6f055692b3684ca1a554d2 100755 (executable)
@@ -316,6 +316,14 @@ pp sleep 3
 n2 ping -W 1 -c 1 192.168.241.1
 n1 wg set wg0 peer "$pub2" persistent-keepalive 0
 
+# Test that sk_bound_dev_if works
+n1 ping -I wg0 -c 1 -W 1 192.168.241.2
+# What about when the mark changes and the packet must be rerouted?
+n1 iptables -t mangle -I OUTPUT -j MARK --set-xmark 1
+n1 ping -c 1 -W 1 192.168.241.2 # First the boring case
+n1 ping -I wg0 -c 1 -W 1 192.168.241.2 # Then the sk_bound_dev_if case
+n1 iptables -t mangle -D OUTPUT -j MARK --set-xmark 1
+
 # Test that onion routing works, even when it loops
 n1 wg set wg0 peer "$pub3" allowed-ips 192.168.242.2/32 endpoint 192.168.241.2:5
 ip1 addr add 192.168.242.1/24 dev wg0
index d531de13c95b06aba2f3596627673a0482bdbd09..4eecb432a66c1c2c2c40e01149088a884bfc8679 100644 (file)
@@ -18,10 +18,12 @@ CONFIG_NF_NAT=y
 CONFIG_NETFILTER_XTABLES=y
 CONFIG_NETFILTER_XT_NAT=y
 CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MARK=y
 CONFIG_NF_CONNTRACK_IPV4=y
 CONFIG_NF_NAT_IPV4=y
 CONFIG_IP_NF_IPTABLES=y
 CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_MANGLE=y
 CONFIG_IP_NF_NAT=y
 CONFIG_IP_ADVANCED_ROUTER=y
 CONFIG_IP_MULTIPLE_TABLES=y