F: include/linux/acpi.h
F: include/linux/fwnode.h
F: include/acpi/
-F: Documentation/acpi/
+F: Documentation/firmware-guide/acpi/
F: Documentation/ABI/testing/sysfs-bus-acpi
F: Documentation/ABI/testing/configfs-acpi
F: drivers/pci/*acpi*
ACPI FOR ARM64 (ACPI/arm64)
M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-M: Hanjun Guo <hanjun.guo@linaro.org>
+M: Hanjun Guo <guohanjun@huawei.com>
M: Sudeep Holla <sudeep.holla@arm.com>
L: linux-acpi@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://ez.analog.com/community/linux-device-drivers
S: Supported
F: drivers/input/misc/adxl34x.c
+F: Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml
ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
M: Stefan Popa <stefan.popa@analog.com>
F: drivers/iio/accel/adxl372.c
F: drivers/iio/accel/adxl372_spi.c
F: drivers/iio/accel/adxl372_i2c.c
-F: Documentation/devicetree/bindings/iio/accel/adxl372.txt
+F: Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml
AF9013 MEDIA DRIVER
M: Antti Palosaari <crope@iki.fi>
F: Documentation/i2c/busses/i2c-ali1563
F: drivers/i2c/busses/i2c-ali1563.c
+ALLEGRO DVT VIDEO IP CORE DRIVER
+M: Michael Tretter <m.tretter@pengutronix.de>
+R: Pengutronix Kernel Team <kernel@pengutronix.de>
+L: linux-media@vger.kernel.org
+S: Maintained
+F: drivers/staging/media/allegro-dvt/
+
ALLWINNER SECURITY SYSTEM
M: Corentin Labbe <clabbe.montjoie@gmail.com>
L: linux-crypto@vger.kernel.org
ALTERA I2C CONTROLLER DRIVER
M: Thor Thayer <thor.thayer@linux.intel.com>
S: Maintained
+F: Documentation/devicetree/bindings/i2c/i2c-altera.txt
F: drivers/i2c/busses/i2c-altera.c
ALTERA MAILBOX DRIVER
F: drivers/iio/adc/ad7768-1.c
F: Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.txt
+ANALOG DEVICES INC AD7780 DRIVER
+M: Michael Hennerich <Michael.Hennerich@analog.com>
+M: Renato Lui Geh <renatogeh@gmail.com>
+L: linux-iio@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/adc/ad7780.c
+F: Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml
+
ANALOG DEVICES INC AD9389B DRIVER
-M: Hans Verkuil <hans.verkuil@cisco.com>
+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/i2c/ad9389b*
F: drivers/mux/adgs1408.c
F: Documentation/devicetree/bindings/mux/adi,adgs1408.txt
+ANALOG DEVICES INC ADIS DRIVER LIBRARY
+M: Alexandru Ardelean <alexandru.ardelean@analog.com>
+S: Supported
+L: linux-iio@vger.kernel.org
+F: include/linux/iio/imu/adis.h
+F: drivers/iio/imu/adis.c
+
ANALOG DEVICES INC ADP5061 DRIVER
M: Stefan Popa <stefan.popa@analog.com>
L: linux-pm@vger.kernel.org
F: drivers/media/i2c/adv748x/*
ANALOG DEVICES INC ADV7511 DRIVER
-M: Hans Verkuil <hans.verkuil@cisco.com>
+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/i2c/adv7511*
ANALOG DEVICES INC ADV7604 DRIVER
-M: Hans Verkuil <hans.verkuil@cisco.com>
+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/i2c/adv7604*
ANALOG DEVICES INC ADV7842 DRIVER
-M: Hans Verkuil <hans.verkuil@cisco.com>
+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/i2c/adv7842*
M: Khuong Dinh <khuong@os.amperecomputing.com>
S: Supported
F: drivers/perf/xgene_pmu.c
-F: Documentation/perf/xgene-pmu.txt
+F: Documentation/admin-guide/perf/xgene-pmu.rst
F: Documentation/devicetree/bindings/perf/apm-xgene-pmu.txt
APTINA CAMERA SENSOR PLL
S: Maintained
F: drivers/media/i2c/aptina-pll.*
+AQUANTIA ETHERNET DRIVER (atlantic)
+M: Igor Russkikh <igor.russkikh@aquantia.com>
+L: netdev@vger.kernel.org
+S: Supported
+W: http://www.aquantia.com
+Q: http://patchwork.ozlabs.org/project/netdev/list/
+F: drivers/net/ethernet/aquantia/atlantic/
+F: Documentation/networking/device_drivers/aquantia/atlantic.txt
+
ARC FRAMEBUFFER DRIVER
M: Jaya Kumar <jayalk@intworks.biz>
S: Maintained
F: Documentation/devicetree/bindings/arm/arm-boards
F: Documentation/devicetree/bindings/auxdisplay/arm-charlcd.txt
F: Documentation/devicetree/bindings/clock/arm-integrator.txt
+F: Documentation/devicetree/bindings/i2c/i2c-versatile.txt
F: Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
F: Documentation/devicetree/bindings/mtd/arm-versatile.txt
F: arch/arm/mach-integrator/
F: arch/arm/include/asm/floppy.h
ARM PMU PROFILING AND DEBUGGING
-M: Will Deacon <will.deacon@arm.com>
+M: Will Deacon <will@kernel.org>
M: Mark Rutland <mark.rutland@arm.com>
S: Maintained
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
M: Linus Walleij <linus.walleij@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-F: Documentation/devicetree/bindings/spi/spi_pl022.txt
+F: Documentation/devicetree/bindings/spi/spi-pl022.yaml
F: drivers/spi/spi-pl022.c
ARM PRIMECELL UART PL010 AND PL011 DRIVERS
F: Documentation/devicetree/bindings/interrupt-controller/arm,vic.txt
F: drivers/irqchip/irq-vic.c
+AMAZON ANNAPURNA LABS FIC DRIVER
+M: Talel Shenhar <talel@amazon.com>
+S: Maintained
+F: Documentation/devicetree/bindings/interrupt-controller/amazon,al-fic.txt
+F: drivers/irqchip/irq-al-fic.c
+
ARM SMMU DRIVERS
-M: Will Deacon <will.deacon@arm.com>
+M: Will Deacon <will@kernel.org>
R: Robin Murphy <robin.murphy@arm.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
M: Vladimir Zapolskiy <vz@mleia.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
+F: Documentation/devicetree/bindings/i2c/i2c-lpc2k.txt
F: arch/arm/boot/dts/lpc43*
F: drivers/i2c/busses/i2c-lpc2k.c
F: drivers/memory/pl172.c
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
T: git git://github.com/vzapolskiy/linux-lpc32xx.git
S: Maintained
+F: Documentation/devicetree/bindings/i2c/i2c-pnx.txt
F: arch/arm/boot/dts/lpc32*
F: arch/arm/mach-lpc32xx/
F: drivers/i2c/busses/i2c-pnx.c
M: Linus Walleij <linus.walleij@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
+F: Documentation/devicetree/bindings/i2c/i2c-nomadik.txt
+F: Documentation/devicetree/bindings/i2c/i2c-stu300.txt
F: arch/arm/mach-nomadik/
F: arch/arm/mach-u300/
F: arch/arm/mach-ux500/
F: drivers/usb/dwc3/dwc3-qcom.c
F: include/dt-bindings/*/qcom*
F: include/linux/*/qcom*
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/agross/linux.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git
ARM/RADISYS ENP2611 MACHINE SUPPORT
M: Lennert Buytenhek <kernel@wantstofly.org>
F: drivers/clocksource/timer-rda.c
F: drivers/irqchip/irq-rda-intc.c
F: drivers/tty/serial/rda-uart.c
-F: Documentation/devicetree/bindings/arm/rda.txt
+F: Documentation/devicetree/bindings/arm/rda.yaml
F: Documentation/devicetree/bindings/interrupt-controller/rda,8810pl-intc.txt
F: Documentation/devicetree/bindings/serial/rda,8810pl-uart.txt
F: Documentation/devicetree/bindings/timer/rda,8810pl-timer.txt
L: linux-rockchip@lists.infradead.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git
S: Maintained
+F: Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
F: arch/arm/boot/dts/rk3*
F: arch/arm/boot/dts/rv1108*
F: arch/arm/mach-rockchip/
F: drivers/*/*s5pv210*
F: drivers/memory/samsung/*
F: drivers/soc/samsung/*
-F: Documentation/arm/Samsung/
+F: Documentation/arm/samsung/
F: Documentation/devicetree/bindings/arm/samsung/
F: Documentation/devicetree/bindings/sram/samsung-sram.txt
F: Documentation/devicetree/bindings/power/pd-samsung.txt
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.stlinux.com
S: Maintained
+F: Documentation/devicetree/bindings/i2c/i2c-st.txt
F: arch/arm/mach-sti/
F: arch/arm/boot/dts/sti*
F: drivers/char/hw_random/st-rng.c
S: Maintained
ARM/TEGRA HDMI CEC SUBSYSTEM SUPPORT
-M: Hans Verkuil <hans.verkuil@cisco.com>
+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-tegra@vger.kernel.org
L: linux-media@vger.kernel.org
S: Maintained
M: Tony Prisk <linux@prisktech.co.nz>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
+F: Documentation/devicetree/bindings/i2c/i2c-wmt.txt
F: arch/arm/mach-vt8500/
F: drivers/clocksource/timer-vt8500.c
F: drivers/i2c/busses/i2c-wmt.c
F: drivers/block/xsysace.c
N: zynq
N: xilinx
+F: Documentation/devicetree/bindings/i2c/i2c-cadence.txt
+F: Documentation/devicetree/bindings/i2c/i2c-xiic.txt
F: drivers/clocksource/timer-cadence-ttc.c
F: drivers/i2c/busses/i2c-cadence.c
F: drivers/mmc/host/sdhci-of-arasan.c
ARM64 PORT (AARCH64 ARCHITECTURE)
M: Catalin Marinas <catalin.marinas@arm.com>
-M: Will Deacon <will.deacon@arm.com>
+M: Will Deacon <will@kernel.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
T: git git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
S: Maintained
F: Documentation/hwmon/asc7621.rst
F: drivers/hwmon/asc7621.c
+ASPEED PINCTRL DRIVERS
+M: Andrew Jeffery <andrew@aj.id.au>
+L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
+L: openbmc@lists.ozlabs.org (moderated for non-subscribers)
+L: linux-gpio@vger.kernel.org
+S: Maintained
+F: drivers/pinctrl/aspeed/
+F: Documentation/devicetree/bindings/pinctrl/aspeed,*
+
ASPEED VIDEO ENGINE DRIVER
M: Eddie James <eajames@linux.ibm.com>
L: linux-media@vger.kernel.org
M: "Justin Sanders" <justin@coraid.com>
W: http://www.openaoe.org/
S: Supported
-F: Documentation/aoe/
+F: Documentation/admin-guide/aoe/
F: drivers/block/aoe/
ATHEROS 71XX/9XXX GPIO DRIVER
F: drivers/net/wireless/atmel/atmel*
ATOMIC INFRASTRUCTURE
-M: Will Deacon <will.deacon@arm.com>
+M: Will Deacon <will@kernel.org>
M: Peter Zijlstra <peterz@infradead.org>
R: Boqun Feng <boqun.feng@gmail.com>
L: linux-kernel@vger.kernel.org
L: linux-block@vger.kernel.org
S: Maintained
F: block/bfq-*
-F: Documentation/block/bfq-iosched.txt
+F: Documentation/block/bfq-iosched.rst
BFS FILE SYSTEM
M: "Tigran A. Aivazian" <aivazian.tigran@gmail.com>
F: arch/riscv/net/
BPF JIT for S390
-M: Martin Schwidefsky <schwidefsky@de.ibm.com>
M: Heiko Carstens <heiko.carstens@de.ibm.com>
+M: Vasily Gorbik <gor@linux.ibm.com>
+M: Christian Borntraeger <borntraeger@de.ibm.com>
L: netdev@vger.kernel.org
L: bpf@vger.kernel.org
S: Maintained
BROADCOM BCM2835 ARM ARCHITECTURE
M: Eric Anholt <eric@anholt.net>
-M: Stefan Wahren <stefan.wahren@i2se.com>
+M: Stefan Wahren <wahrenst@gmx.net>
+L: bcm-kernel-feedback-list@broadcom.com
L: linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
T: git git://github.com/anholt/linux
BROADCOM BCM53573 ARM ARCHITECTURE
M: Rafał Miłecki <rafal@milecki.pl>
+L: bcm-kernel-feedback-list@broadcom.com
L: linux-arm-kernel@lists.infradead.org
S: Maintained
F: arch/arm/boot/dts/bcm53573*
W: https://developer.arm.com/products/system-ip/trustzone-cryptocell/cryptocell-700-family
CEC FRAMEWORK
-M: Hans Verkuil <hans.verkuil@cisco.com>
+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
W: http://linuxtv.org
F: Documentation/ABI/testing/debugfs-cec-error-inj
CEC GPIO DRIVER
-M: Hans Verkuil <hans.verkuil@cisco.com>
+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
W: http://linuxtv.org
CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
L: linux-usb@vger.kernel.org
S: Orphan
-F: Documentation/usb/WUSB-Design-overview.txt
+F: Documentation/usb/wusb-design-overview.rst
F: Documentation/usb/wusb-cbaf
F: drivers/usb/host/hwa-hc.c
F: drivers/usb/host/whci/
F: Documentation/devicetree/bindings/pinctrl/cirrus,lochnagar.txt
F: Documentation/devicetree/bindings/regulator/cirrus,lochnagar.txt
F: Documentation/devicetree/bindings/sound/cirrus,lochnagar.txt
-F: Documentation/hwmon/lochnagar
+F: Documentation/hwmon/lochnagar.rst
CISCO FCOE HBA DRIVER
M: Satish Kharat <satishkh@cisco.com>
S: Supported
F: Documentation/devicetree/bindings/mfd/madera.txt
F: Documentation/devicetree/bindings/pinctrl/cirrus,madera-pinctrl.txt
+F: Documentation/devicetree/bindings/sound/madera.txt
+F: include/dt-bindings/sound/madera*
F: include/linux/irqchip/irq-madera*
F: include/linux/mfd/madera/*
+F: include/sound/madera*
F: drivers/gpio/gpio-madera*
F: drivers/irqchip/irq-madera*
F: drivers/mfd/madera*
F: drivers/mfd/cs47l*
F: drivers/pinctrl/cirrus/*
+F: sound/soc/codecs/cs47l*
+F: sound/soc/codecs/madera*
CLANG-FORMAT FILE
M: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
S: Maintained
F: .clang-format
+CLANG/LLVM BUILD SUPPORT
+L: clang-built-linux@googlegroups.com
+W: https://clangbuiltlinux.github.io/
+B: https://github.com/ClangBuiltLinux/linux/issues
+C: irc://chat.freenode.net/clangbuiltlinux
+S: Supported
+K: \b(?i:clang|llvm)\b
+
CLEANCACHE API
M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
L: linux-kernel@vger.kernel.org
F: drivers/platform/x86/classmate-laptop.c
COBALT MEDIA DRIVER
-M: Hans Verkuil <hans.verkuil@cisco.com>
+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
W: https://linuxtv.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
S: Maintained
F: Documentation/admin-guide/cgroup-v2.rst
-F: Documentation/cgroup-v1/
+F: Documentation/admin-guide/cgroup-v1/
F: include/linux/cgroup*
F: kernel/cgroup/
W: http://oss.sgi.com/projects/cpusets/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
S: Maintained
-F: Documentation/cgroup-v1/cpusets.txt
+F: Documentation/admin-guide/cgroup-v1/cpusets.rst
F: include/linux/cpuset.h
F: kernel/cgroup/cpuset.c
F: mm/memcontrol.c
F: mm/swap_cgroup.c
+CONTROL GROUP - BLOCK IO CONTROLLER (BLKIO)
+M: Tejun Heo <tj@kernel.org>
+M: Jens Axboe <axboe@kernel.dk>
+L: cgroups@vger.kernel.org
+L: linux-block@vger.kernel.org
+T: git git://git.kernel.dk/linux-block
+F: Documentation/cgroup-v1/blkio-controller.rst
+F: block/blk-cgroup.c
+F: include/linux/blk-cgroup.h
+F: block/blk-throttle.c
+F: block/blk-iolatency.c
+F: block/bfq-cgroup.c
+
CORETEMP HARDWARE MONITORING DRIVER
M: Fenghua Yu <fenghua.yu@intel.com>
L: linux-hwmon@vger.kernel.org
F: drivers/crypto/
F: include/crypto/
F: include/linux/crypto*
+F: lib/crypto/
CRYPTOGRAPHIC RANDOM NUMBER GENERATOR
M: Neil Horman <nhorman@tuxdriver.com>
M: Stuart Hayes <stuart.w.hayes@gmail.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
-F: Documentation/dcdbas.txt
+F: Documentation/driver-api/dcdbas.rst
F: drivers/platform/x86/dcdbas.*
DELL WMI NOTIFICATIONS DRIVER
S: Supported
F: drivers/mtd/nand/raw/denali*
+DESIGNWARE EDMA CORE IP DRIVER
+M: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
+L: dmaengine@vger.kernel.org
+S: Maintained
+F: drivers/dma/dw-edma/
+F: include/linux/dma/edma.h
+
DESIGNWARE USB2 DRD IP DRIVER
M: Minas Harutyunyan <hminas@synopsys.com>
L: linux-usb@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git
T: quilt http://people.redhat.com/agk/patches/linux/editing/
S: Maintained
-F: Documentation/device-mapper/
+F: Documentation/admin-guide/device-mapper/
F: drivers/md/Makefile
F: drivers/md/Kconfig
F: drivers/md/dm*
F: Documentation/devicetree/bindings/input/da90??-onkey.txt
F: Documentation/devicetree/bindings/thermal/da90??-thermal.txt
F: Documentation/devicetree/bindings/regulator/da92*.txt
+F: Documentation/devicetree/bindings/regulator/slg51000.txt
F: Documentation/devicetree/bindings/watchdog/da90??-wdt.txt
F: Documentation/devicetree/bindings/sound/da[79]*.txt
F: drivers/gpio/gpio-da90??.c
F: drivers/power/supply/da91??-*.c
F: drivers/regulator/da903x.c
F: drivers/regulator/da9???-regulator.[ch]
+F: drivers/regulator/slg51000-regulator.[ch]
F: drivers/thermal/da90??-thermal.c
F: drivers/rtc/rtc-da90??.c
F: drivers/video/backlight/da90??_bl.c
W: http://plugable.com/category/projects/udlfb/
F: drivers/video/fbdev/udlfb.c
F: include/video/udlfb.h
-F: Documentation/fb/udlfb.txt
+F: Documentation/fb/udlfb.rst
DISTRIBUTED LOCK MANAGER (DLM)
M: Christine Caulfield <ccaulfie@redhat.com>
F: Documentation/
F: scripts/kernel-doc
X: Documentation/ABI/
-X: Documentation/acpi/
+X: Documentation/firmware-guide/acpi/
X: Documentation/devicetree/
X: Documentation/i2c/
X: Documentation/media/
S: Maintained
F: drivers/staging/fsl-dpaa2/ethsw
-DPAA2 PTP CLOCK DRIVER
-M: Yangbo Lu <yangbo.lu@nxp.com>
-L: netdev@vger.kernel.org
-S: Maintained
-F: drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp*
-F: drivers/net/ethernet/freescale/dpaa2/dprtc*
-
DPT_I2O SCSI RAID DRIVER
M: Adaptec OEM Raid Solutions <aacraid@microsemi.com>
L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/block/drbd/
F: lib/lru_cache.c
-F: Documentation/blockdev/drbd/
+F: Documentation/admin-guide/blockdev/
DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
F: drivers/gpu/drm/tinydrm/st7735r.c
F: Documentation/devicetree/bindings/display/sitronix,st7735r.txt
+DRM DRIVER FOR ST-ERICSSON MCDE
+M: Linus Walleij <linus.walleij@linaro.org>
+T: git git://anongit.freedesktop.org/drm/drm-misc
+S: Maintained
+F: drivers/gpu/drm/mcde/
+F: Documentation/devicetree/bindings/display/ste,mcde.txt
+
DRM DRIVER FOR TDFX VIDEO CARDS
S: Orphan / Obsolete
F: drivers/gpu/drm/tdfx/
DRM PANEL DRIVERS
M: Thierry Reding <thierry.reding@gmail.com>
+R: Sam Ravnborg <sam@ravnborg.org>
L: dri-devel@lists.freedesktop.org
T: git git://anongit.freedesktop.org/drm/drm-misc
S: Maintained
DRM TTM SUBSYSTEM
M: Christian Koenig <christian.koenig@amd.com>
M: Huang Rui <ray.huang@amd.com>
-M: Junwei Zhang <Jerry.Zhang@amd.com>
T: git git://people.freedesktop.org/~agd5f/linux
S: Maintained
L: dri-devel@lists.freedesktop.org
DYNAMIC INTERRUPT MODERATION
M: Tal Gilboa <talgi@mellanox.com>
S: Maintained
-F: include/linux/net_dim.h
+F: include/linux/dim.h
+F: lib/dim/
DZ DECSTATION DZ11 SERIAL DRIVER
M: "Maciej W. Rozycki" <macro@linux-mips.org>
S: Maintained
F: drivers/edac/sb_edac.c
+EDAC-SIFIVE
+M: Yash Shah <yash.shah@sifive.com>
+L: linux-edac@vger.kernel.org
+S: Supported
+F: drivers/edac/sifive_edac.c
+
EDAC-SKYLAKE
M: Tony Luck <tony.luck@intel.com>
L: linux-edac@vger.kernel.org
L: netdev@vger.kernel.org
S: Maintained
F: Documentation/ABI/testing/sysfs-bus-mdio
+F: Documentation/devicetree/bindings/net/ethernet-phy.yaml
F: Documentation/devicetree/bindings/net/mdio*
F: Documentation/networking/phy.rst
F: drivers/net/phy/
L: linux-efi@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git
S: Maintained
-F: Documentation/efi-stub.txt
+F: Documentation/admin-guide/efi-stub.rst
F: arch/*/kernel/efi.c
F: arch/x86/boot/compressed/eboot.[ch]
F: arch/*/include/asm/efi.h
F: drivers/extcon/
F: include/linux/extcon/
F: include/linux/extcon.h
-F: Documentation/extcon/
+F: Documentation/firmware-guide/acpi/extcon-intel-int3496.rst
F: Documentation/devicetree/bindings/extcon/
EXYNOS DP DRIVER
S: Maintained
F: drivers/block/rsxx/
+FLEXTIMER FTM-QUADDEC DRIVER
+M: Patrick Havelange <patrick.havelange@essensium.com>
+L: linux-iio@vger.kernel.org
+S: Maintained
+F: Documentation/ABI/testing/sysfs-bus-counter-ftm-quadddec
+F: Documentation/devicetree/bindings/counter/ftm-quaddec.txt
+F: drivers/counter/ftm-quaddec.c
+
FLOPPY DRIVER
M: Jiri Kosina <jikos@kernel.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/floppy.git
K: fmc_d.*register
FPGA MANAGER FRAMEWORK
-M: Alan Tull <atull@kernel.org>
M: Moritz Fischer <mdf@kernel.org>
L: linux-fpga@vger.kernel.org
S: Maintained
M: Wu Hao <hao.wu@intel.com>
L: linux-fpga@vger.kernel.org
S: Maintained
-F: Documentation/fpga/dfl.txt
+F: Documentation/fpga/dfl.rst
F: include/uapi/linux/fpga-dfl.h
F: drivers/fpga/dfl*
S: Maintained
F: drivers/i2c/busses/i2c-cpm.c
+FREESCALE IMX DDR PMU DRIVER
+M: Frank Li <Frank.li@nxp.com>
+L: linux-arm-kernel@lists.infradead.org
+S: Maintained
+F: drivers/perf/fsl_imx8_ddr_perf.c
+F: Documentation/devicetree/bindings/perf/fsl-imx-ddr.txt
+
FREESCALE IMX LPI2C DRIVER
M: Dong Aisheng <aisheng.dong@nxp.com>
L: linux-i2c@vger.kernel.org
M: Yangbo Lu <yangbo.lu@nxp.com>
L: netdev@vger.kernel.org
S: Maintained
+F: drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp*
+F: drivers/net/ethernet/freescale/dpaa2/dprtc*
F: drivers/net/ethernet/freescale/enetc/enetc_ptp.c
F: drivers/ptp/ptp_qoriq.c
F: drivers/ptp/ptp_qoriq_debugfs.c
M: Pavel Machek <pavel@ucw.cz>
L: linux-pm@vger.kernel.org
S: Supported
-F: Documentation/power/freezing-of-tasks.txt
+F: Documentation/power/freezing-of-tasks.rst
F: include/linux/freezer.h
F: kernel/freezer.c
F: include/linux/fscrypt*.h
F: Documentation/filesystems/fscrypt.rst
+FSI SUBSYSTEM
+M: Jeremy Kerr <jk@ozlabs.org>
+M: Joel Stanley <joel@jms.id.au>
+R: Alistar Popple <alistair@popple.id.au>
+R: Eddie James <eajames@linux.ibm.com>
+L: linux-fsi@lists.ozlabs.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/joel/fsi.git
+Q: http://patchwork.ozlabs.org/project/linux-fsi/list/
+S: Supported
+F: drivers/fsi/
+F: include/linux/fsi*.h
+F: include/trace/events/fsi*.h
+
FSI-ATTACHED I2C DRIVER
M: Eddie James <eajames@linux.ibm.com>
L: linux-i2c@vger.kernel.org
F: scripts/gcc-plugins/
F: scripts/gcc-plugin.sh
F: scripts/Makefile.gcc-plugins
-F: Documentation/gcc-plugins.txt
+F: Documentation/core-api/gcc-plugins.rst
GASKET DRIVER FRAMEWORK
M: Rob Springer <rspringer@google.com>
S: Supported
F: drivers/uio/uio_pci_generic.c
+GENERIC VDSO LIBRARY:
+M: Andy Lutomirski <luto@kernel.org>
+M: Thomas Gleixner <tglx@linutronix.de>
+M: Vincenzo Frascino <vincenzo.frascino@arm.com>
+L: linux-kernel@vger.kernel.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/vdso
+S: Maintained
+F: lib/vdso/
+F: kernel/time/vsyscall.c
+F: include/vdso/
+F: include/asm-generic/vdso/vsyscall.h
+
GENWQE (IBM Generic Workqueue Card)
M: Frank Haverkamp <haver@linux.ibm.com>
S: Supported
L: gigaset307x-common@lists.sourceforge.net
W: http://gigaset307x.sourceforge.net/
S: Odd Fixes
-F: Documentation/isdn/README.gigaset
-F: drivers/isdn/gigaset/
-F: include/uapi/linux/gigaset_dev.h
+F: drivers/staging/isdn/gigaset/
GNSS SUBSYSTEM
M: Johan Hovold <johan@kernel.org>
F: include/linux/gnss.h
GO7007 MPEG CODEC
-M: Hans Verkuil <hans.verkuil@cisco.com>
+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/usb/go7007/
S: Maintained
F: drivers/input/touchscreen/goodix.c
+GOOGLE ETHERNET DRIVERS
+M: Catherine Sullivan <csully@google.com>
+R: Sagi Shahar <sagis@google.com>
+R: Jon Olson <jonolson@google.com>
+L: netdev@vger.kernel.org
+S: Supported
+F: Documentation/networking/device_drivers/google/gve.txt
+F: drivers/net/ethernet/google
+
GPD POCKET FAN DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/gpio/
F: Documentation/driver-api/gpio/
-F: Documentation/gpio/
+F: Documentation/admin-guide/gpio/
F: Documentation/ABI/testing/gpio-cdev
F: Documentation/ABI/obsolete/sysfs-gpio
F: drivers/gpio/
L: linux-crypto@vger.kernel.org
S: Odd fixes
F: Documentation/devicetree/bindings/rng/
-F: Documentation/hw_random.txt
+F: Documentation/admin-guide/hw_random.rst
F: drivers/char/hw_random/
F: include/linux/hw_random.h
HEWLETT PACKARD ENTERPRISE ILO NMI WATCHDOG DRIVER
M: Jerry Hoemann <jerry.hoemann@hpe.com>
S: Supported
-F: Documentation/watchdog/hpwdt.txt
+F: Documentation/watchdog/hpwdt.rst
F: drivers/watchdog/hpwdt.c
HEWLETT-PACKARD SMART ARRAY RAID DRIVER (hpsa)
W: http://www.hisilicon.com
S: Supported
F: drivers/perf/hisilicon
-F: Documentation/perf/hisi-pmu.txt
+F: Documentation/admin-guide/perf/hisi-pmu.rst
HISILICON ROCE DRIVER
M: Lijun Ou <oulijun@huawei.com>
HPET: High Precision Event Timers driver
M: Clemens Ladisch <clemens@ladisch.de>
S: Maintained
-F: Documentation/timers/hpet.txt
+F: Documentation/timers/hpet.rst
F: drivers/char/hpet.c
F: include/linux/hpet.h
F: include/uapi/linux/hpet.h
F: arch/x86/include/asm/hyperv-tlfs.h
F: arch/x86/kernel/cpu/mshyperv.c
F: arch/x86/hyperv
+F: drivers/clocksource/hyperv_timer.c
F: drivers/hid/hid-hyperv.c
F: drivers/hv/
F: drivers/input/serio/hyperv-keyboard.c
F: drivers/video/fbdev/hyperv_fb.c
F: drivers/iommu/hyperv_iommu.c
F: net/vmw_vsock/hyperv_transport.c
+F: include/clocksource/hyperv_timer.h
F: include/linux/hyperv.h
F: include/uapi/linux/hyperv.h
+F: include/asm-generic/mshyperv.h
F: tools/hv/
F: Documentation/ABI/stable/sysfs-bus-vmbus
+HYPERBUS SUPPORT
+M: Vignesh Raghavendra <vigneshr@ti.com>
+S: Supported
+F: drivers/mtd/hyperbus/
+F: include/linux/mtd/hyperbus.h
+F: Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt
+F: Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt
+
HYPERVISOR VIRTUAL CONSOLE DRIVER
L: linuxppc-dev@lists.ozlabs.org
S: Odd Fixes
M: Gregory CLEMENT <gregory.clement@bootlin.com>
L: linux-i2c@vger.kernel.org
S: Maintained
+F: Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
F: drivers/i2c/busses/i2c-mv64xxx.c
I2C OVER PARALLEL PORT
M: Borislav Petkov <bp@alien8.de>
L: linux-ide@vger.kernel.org
S: Maintained
-F: Documentation/cdrom/ide-cd
+F: Documentation/cdrom/ide-cd.rst
F: drivers/ide/ide-cd*
IDEAPAD LAPTOP EXTRAS DRIVER
S: Maintained
F: drivers/ipack/
+INFINEON DPS310 Driver
+M: Eddie James <eajames@linux.ibm.com>
+L: linux-iio@vger.kernel.org
+F: drivers/iio/pressure/dps310.c
+S: Maintained
+
INFINIBAND SUBSYSTEM
M: Doug Ledford <dledford@redhat.com>
M: Jason Gunthorpe <jgg@mellanox.com>
M: Harvey Hunt <harveyhuntnexus@gmail.com>
L: linux-mtd@lists.infradead.org
S: Maintained
-F: drivers/mtd/nand/raw/jz4780_*
+F: drivers/mtd/nand/raw/ingenic/
+
+INGENIC JZ47xx SoCs
+M: Paul Cercueil <paul@crapouillou.net>
+S: Maintained
+F: arch/mips/boot/dts/ingenic/
+F: arch/mips/include/asm/mach-jz4740/
+F: arch/mips/jz4740/
+F: drivers/clk/ingenic/
+F: drivers/dma/dma-jz4780.c
+F: drivers/gpu/drm/ingenic/
+F: drivers/i2c/busses/i2c-jz4780.c
+F: drivers/iio/adc/ingenic-adc.c
+F: drivers/irqchip/irq-ingenic.c
+F: drivers/memory/jz4780-nemc.c
+F: drivers/mmc/host/jz4740_mmc.c
+F: drivers/mtd/nand/raw/ingenic/
+F: drivers/pinctrl/pinctrl-ingenic.c
+F: drivers/power/supply/ingenic-battery.c
+F: drivers/pwm/pwm-jz4740.c
+F: drivers/rtc/rtc-jz4740.c
+F: drivers/tty/serial/8250/8250_ingenic.c
+F: drivers/usb/musb/jz4740.c
+F: drivers/watchdog/jz4740_wdt.c
+F: include/dt-bindings/iio/adc/ingenic,adc.h
+F: include/linux/mfd/ingenic-tcu.h
+F: sound/soc/jz4740/
+F: sound/soc/codecs/jz47*
INOTIFY
M: Jan Kara <jack@suse.cz>
M: Maik Broemme <mbroemme@libmpq.org>
L: linux-fbdev@vger.kernel.org
S: Maintained
-F: Documentation/fb/intelfb.txt
+F: Documentation/fb/intelfb.rst
F: drivers/video/fbdev/intelfb/
INTEL GPIO DRIVERS
F: include/linux/mei_cl_bus.h
F: drivers/misc/mei/*
F: drivers/watchdog/mei_wdt.c
-F: Documentation/misc-devices/mei/*
+F: Documentation/driver-api/mei/*
F: samples/mei/*
INTEL MENLOW THERMAL DRIVER
F: drivers/gpio/gpio-*cove.c
F: drivers/gpio/gpio-msic.c
-INTEL MULTIFUNCTION PMIC DEVICE DRIVERS
+INTEL PMIC MULTIFUNCTION DEVICE DRIVERS
R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
S: Maintained
F: drivers/mfd/intel_msic.c
F: drivers/infiniband/hw/i40iw/
F: include/uapi/rdma/i40iw-abi.h
+INTEL SPEED SELECT TECHNOLOGY
+M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+L: platform-driver-x86@vger.kernel.org
+S: Maintained
+F: drivers/platform/x86/intel_speed_select_if/
+F: tools/power/x86/intel-speed-select/
+F: include/uapi/linux/isst_if.h
+
INTEL TELEMETRY DRIVER
M: Rajneesh Bhardwaj <rajneesh.bhardwaj@linux.intel.com>
M: "David E. Box" <david.e.box@linux.intel.com>
W: http://tboot.sourceforge.net
T: hg http://tboot.hg.sourceforge.net:8000/hgroot/tboot/tboot
S: Supported
-F: Documentation/intel_txt.txt
+F: Documentation/x86/intel_txt.rst
F: include/linux/tboot.h
F: arch/x86/kernel/tboot.c
M: Georgi Djakov <georgi.djakov@linaro.org>
L: linux-pm@vger.kernel.org
S: Maintained
-F: Documentation/interconnect/
+F: Documentation/driver-api/interconnect.rst
F: Documentation/devicetree/bindings/interconnect/
F: drivers/interconnect/
F: include/dt-bindings/interconnect/
ISA
M: William Breathitt Gray <vilhelm.gray@gmail.com>
S: Maintained
-F: Documentation/isa.txt
+F: Documentation/driver-api/isa.rst
F: drivers/base/isa.c
F: include/linux/isa.h
ISAPNP
M: Jaroslav Kysela <perex@perex.cz>
S: Maintained
-F: Documentation/isapnp.txt
+F: Documentation/driver-api/isapnp.rst
F: drivers/pnp/isapnp/
F: include/linux/isapnp.h
W: http://www.linux-iscsi.org
F: drivers/infiniband/ulp/isert
-ISDN SUBSYSTEM
+ISDN/mISDN SUBSYSTEM
M: Karsten Keil <isdn@linux-pingi.de>
L: isdn4linux@listserv.isdn4linux.de (subscribers-only)
L: netdev@vger.kernel.org
W: http://www.isdn4linux.de
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/kkeil/isdn-2.6.git
S: Maintained
+F: drivers/isdn/mISDN
+F: drivers/isdn/hardware
+
+ISDN/CAPI SUBSYSTEM
+M: Karsten Keil <isdn@linux-pingi.de>
+L: isdn4linux@listserv.isdn4linux.de (subscribers-only)
+L: netdev@vger.kernel.org
+W: http://www.isdn4linux.de
+S: Odd Fixes
F: Documentation/isdn/
-F: drivers/isdn/
-F: include/linux/isdn.h
+F: drivers/isdn/capi/
+F: drivers/staging/isdn/
+F: net/bluetooth/cmtp/
F: include/linux/isdn/
-F: include/uapi/linux/isdn.h
F: include/uapi/linux/isdn/
IT87 HARDWARE MONITORING DRIVER
L: kexec@lists.infradead.org
W: http://lse.sourceforge.net/kdump/
S: Maintained
-F: Documentation/kdump/
+F: Documentation/admin-guide/kdump/
KEENE FM RADIO TRANSMITTER DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
KERNEL NFSD, SUNRPC, AND LOCKD SERVERS
M: "J. Bruce Fields" <bfields@fieldses.org>
-M: Jeff Layton <jlayton@kernel.org>
+M: Chuck Lever <chuck.lever@oracle.com>
L: linux-nfs@vger.kernel.org
W: http://nfs.sourceforge.net/
T: git git://linux-nfs.org/~bfields/linux.git
LEGACY EEPROM DRIVER
M: Jean Delvare <jdelvare@suse.com>
S: Maintained
-F: Documentation/misc-devices/eeprom
+F: Documentation/misc-devices/eeprom.rst
F: drivers/misc/eeprom/eeprom.c
LEGO MINDSTORMS EV3
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: Documentation/ABI/testing/sysfs-platform-lg-laptop
-F: Documentation/laptops/lg-laptop.rst
+F: Documentation/admin-guide/laptops/lg-laptop.rst
F: drivers/platform/x86/lg-laptop.c
LG2160 MEDIA DRIVER
LINUX KERNEL MEMORY CONSISTENCY MODEL (LKMM)
M: Alan Stern <stern@rowland.harvard.edu>
M: Andrea Parri <andrea.parri@amarulasolutions.com>
-M: Will Deacon <will.deacon@arm.com>
+M: Will Deacon <will@kernel.org>
M: Peter Zijlstra <peterz@infradead.org>
M: Boqun Feng <boqun.feng@gmail.com>
M: Nicholas Piggin <npiggin@gmail.com>
LIS3LV02D ACCELEROMETER DRIVER
M: Eric Piel <eric.piel@tremplin-utc.net>
S: Maintained
-F: Documentation/misc-devices/lis3lv02d
+F: Documentation/misc-devices/lis3lv02d.rst
F: drivers/misc/lis3lv02d/
F: drivers/platform/x86/hp_accel.c
LOCKING PRIMITIVES
M: Peter Zijlstra <peterz@infradead.org>
M: Ingo Molnar <mingo@redhat.com>
-M: Will Deacon <will.deacon@arm.com>
+M: Will Deacon <will@kernel.org>
L: linux-kernel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/core
S: Maintained
L: linux-ntfs-dev@lists.sourceforge.net
W: http://www.linux-ntfs.org/content/view/19/37/
S: Maintained
-F: Documentation/ldm.txt
+F: Documentation/admin-guide/ldm.rst
F: block/partitions/ldm.*
LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
S: Maintained
F: drivers/iio/dac/cio-dac.c
+MEDIA CONTROLLER FRAMEWORK
+M: Sakari Ailus <sakari.ailus@linux.intel.com>
+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+L: linux-media@vger.kernel.org
+W: https://www.linuxtv.org
+T: git git://linuxtv.org/media_tree.git
+S: Supported
+F: drivers/media/mc/
+F: include/media/media-*.h
+F: include/uapi/linux/media.h
+
MEDIA DRIVERS FOR ASCOT2E
M: Sergey Kozlov <serjk@netup.ru>
M: Abylay Ospan <aospan@netup.ru>
S: Maintained
F: drivers/net/wireless/mediatek/mt7601u/
+MEDIATEK MT7621/28/88 I2C DRIVER
+M: Stefan Roese <sr@denx.de>
+L: linux-i2c@vger.kernel.org
+S: Maintained
+F: drivers/i2c/busses/i2c-mt7621.c
+F: Documentation/devicetree/bindings/i2c/i2c-mt7621.txt
+
MEDIATEK NAND CONTROLLER DRIVER
M: Xiaolei Li <xiaolei.li@mediatek.com>
L: linux-mtd@lists.infradead.org
S: Supported
F: drivers/net/ethernet/mellanox/mlx5/core/
F: include/linux/mlx5/
+F: Documentation/networking/device_drivers/mellanox/
MELLANOX MLX5 IB driver
M: Leon Romanovsky <leonro@mellanox.com>
S: Supported
F: drivers/leds/leds-mlxcpld.c
F: drivers/leds/leds-mlxreg.c
-F: Documentation/leds/leds-mlxcpld.txt
+F: Documentation/leds/leds-mlxcpld.rst
MELLANOX PLATFORM DRIVER
M: Vadim Pasternak <vadimp@mellanox.com>
S: Maintained
F: drivers/mcb/
F: include/linux/mcb.h
-F: Documentation/men-chameleon-bus.txt
+F: Documentation/driver-api/men-chameleon-bus.rst
MEN F21BMC (Board Management Controller)
M: Andreas Werner <andreas.werner@men.de>
MESON AO CEC DRIVER FOR AMLOGIC SOCS
M: Neil Armstrong <narmstrong@baylibre.com>
-L: linux-media@lists.freedesktop.org
+L: linux-media@vger.kernel.org
L: linux-amlogic@lists.infradead.org
W: http://linux-meson.com/
S: Supported
F: drivers/mtd/nand/raw/meson_*
F: Documentation/devicetree/bindings/mtd/amlogic,meson-nand.txt
+MESON VIDEO DECODER DRIVER FOR AMLOGIC SOCS
+M: Maxime Jourdan <mjourdan@baylibre.com>
+L: linux-media@vger.kernel.org
+L: linux-amlogic@lists.infradead.org
+S: Supported
+F: drivers/staging/media/meson/vdec/
+T: git git://linuxtv.org/media_tree.git
+
METHODE UDPU SUPPORT
M: Vladimir Vid <vladimir.vid@sartura.hr>
S: Maintained
M: Eugen Hristev <eugen.hristev@microchip.com>
L: linux-media@vger.kernel.org
S: Supported
-F: drivers/media/platform/atmel/atmel-isc.c
+F: drivers/media/platform/atmel/atmel-sama5d2-isc.c
+F: drivers/media/platform/atmel/atmel-isc.h
+F: drivers/media/platform/atmel/atmel-isc-base.c
F: drivers/media/platform/atmel/atmel-isc-regs.h
F: Documentation/devicetree/bindings/media/atmel-isc.txt
F: arch/arm/mach-mmp/
MMU GATHER AND TLB INVALIDATION
-M: Will Deacon <will.deacon@arm.com>
+M: Will Deacon <will@kernel.org>
M: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
M: Andrew Morton <akpm@linux-foundation.org>
M: Nick Piggin <npiggin@gmail.com>
MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
M: Jiri Slaby <jirislaby@gmail.com>
S: Maintained
-F: Documentation/serial/moxa-smartio.rst
+F: Documentation/driver-api/serial/moxa-smartio.rst
F: drivers/tty/mxser.*
MR800 AVERMEDIA USB FM RADIO DRIVER
F: include/net/net_failover.h
F: Documentation/networking/net_failover.rst
-NETEFFECT IWARP RNIC DRIVER (IW_NES)
-M: Faisal Latif <faisal.latif@intel.com>
-L: linux-rdma@vger.kernel.org
-W: http://www.intel.com/Products/Server/Adapters/Server-Cluster/Server-Cluster-overview.htm
-S: Supported
-F: drivers/infiniband/hw/nes/
-F: include/uapi/rdma/nes-abi.h
-
NETEM NETWORK EMULATOR
M: Stephen Hemminger <stephen@networkplumber.org>
L: netem@lists.linux-foundation.org (moderated for non-subscribers)
NETFILTER
M: Pablo Neira Ayuso <pablo@netfilter.org>
-M: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+M: Jozsef Kadlecsik <kadlec@netfilter.org>
M: Florian Westphal <fw@strlen.de>
L: netfilter-devel@vger.kernel.org
L: coreteam@netfilter.org
S: Maintained
L: linux-block@vger.kernel.org
L: nbd@other.debian.org
-F: Documentation/blockdev/nbd.txt
+F: Documentation/admin-guide/blockdev/nbd.rst
F: drivers/block/nbd.c
F: include/trace/events/nbd.h
F: include/uapi/linux/nbd.h
S: Supported
F: drivers/net/ethernet/qlogic/netxen/
+NEXTHOP
+M: David Ahern <dsahern@kernel.org>
+L: netdev@vger.kernel.org
+S: Maintained
+F: include/net/nexthop.h
+F: include/uapi/linux/nexthop.h
+F: include/net/netns/nexthop.h
+F: net/ipv4/nexthop.c
+
NFC SUBSYSTEM
L: netdev@vger.kernel.org
S: Orphan
F: include/uapi/linux/sunrpc/
NILFS2 FILESYSTEM
-M: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
+M: Ryusuke Konishi <konishi.ryusuke@gmail.com>
L: linux-nilfs@vger.kernel.org
W: https://nilfs.sourceforge.io/
W: https://nilfs.osdn.jp/
M: Rui Miguel Silva <rmfrfs@gmail.com>
L: linux-iio@vger.kernel.org
S: Maintained
-F: Documentation/devicetree/bindings/iio/gyroscope/fxas21002c.txt
+F: Documentation/devicetree/bindings/iio/gyroscope/nxp,fxas21002c.txt
F: drivers/iio/gyro/fxas21002c_core.c
F: drivers/iio/gyro/fxas21002c.h
F: drivers/iio/gyro/fxas21002c_i2c.c
F: drivers/misc/ocxl/
F: include/misc/ocxl*
F: include/uapi/misc/ocxl.h
-F: Documentation/accelerators/ocxl.rst
+F: Documentation/userspace-api/accelerators/ocxl.rst
OMAP AUDIO SUPPORT
M: Peter Ujfalusi <peter.ujfalusi@ti.com>
L: linux-fbdev@vger.kernel.org
S: Orphan
F: drivers/video/fbdev/omap2/
-F: Documentation/arm/OMAP/DSS
+F: Documentation/arm/omap/dss.rst
OMAP FRAMEBUFFER SUPPORT
L: linux-fbdev@vger.kernel.org
F: drivers/mtd/nand/onenand/
F: include/linux/mtd/onenand*.h
-ONSTREAM SCSI TAPE DRIVER
-M: Willem Riede <osst@riede.org>
-L: osst-users@lists.sourceforge.net
-L: linux-scsi@vger.kernel.org
-S: Maintained
-F: Documentation/scsi/osst.txt
-F: drivers/scsi/osst.*
-F: drivers/scsi/osst_*.h
-F: drivers/scsi/st.h
-
OP-TEE DRIVER
M: Jens Wiklander <jens.wiklander@linaro.org>
S: Maintained
M: Andrew Lunn <andrew@lunn.ch>
L: linux-i2c@vger.kernel.org
S: Maintained
+F: Documentation/devicetree/bindings/i2c/i2c-ocores.txt
F: Documentation/i2c/busses/i2c-ocores
F: drivers/i2c/busses/i2c-ocores.c
F: include/linux/platform_data/i2c-ocores.h
T: git git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm.git
F: drivers/opp/
F: include/linux/pm_opp.h
-F: Documentation/power/opp.txt
+F: Documentation/power/opp.rst
F: Documentation/devicetree/bindings/opp/
OPL4 DRIVER
F: include/linux/padata.h
F: Documentation/padata.txt
+PAGE POOL
+M: Jesper Dangaard Brouer <hawk@kernel.org>
+M: Ilias Apalodimas <ilias.apalodimas@linaro.org>
+L: netdev@vger.kernel.org
+S: Supported
+F: net/core/page_pool.c
+F: include/net/page_pool.h
+
PANASONIC LAPTOP ACPI EXTRAS DRIVER
M: Harald Welte <laforge@gnumonks.org>
L: platform-driver-x86@vger.kernel.org
M: Willy Tarreau <willy@haproxy.com>
M: Ksenija Stanojevic <ksenija.stanojevic@gmail.com>
S: Odd Fixes
-F: Documentation/auxdisplay/lcd-panel-cgram.txt
+F: Documentation/admin-guide/lcd-panel-cgram.rst
F: drivers/auxdisplay/panel.c
PARALLEL PORT SUBSYSTEM
F: include/linux/parport*.h
F: drivers/char/ppdev.c
F: include/uapi/linux/ppdev.h
-F: Documentation/parport*.txt
+F: Documentation/driver-api/parport*.rst
PARAVIRT_OPS INTERFACE
M: Juergen Gross <jgross@suse.com>
M: Tim Waugh <tim@cyberelk.net>
L: linux-parport@lists.infradead.org (subscribers-only)
S: Maintained
-F: Documentation/blockdev/paride.txt
+F: Documentation/admin-guide/blockdev/paride.rst
F: drivers/block/paride/
PARISC ARCHITECTURE
F: drivers/pci/controller/dwc/*layerscape*
PCI DRIVER FOR GENERIC OF HOSTS
-M: Will Deacon <will.deacon@arm.com>
+M: Will Deacon <will@kernel.org>
L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
M: Logan Gunthorpe <logang@deltatee.com>
L: linux-pci@vger.kernel.org
S: Maintained
-F: Documentation/switchtec.txt
+F: Documentation/driver-api/switchtec.rst
F: Documentation/ABI/testing/sysfs-class-switchtec
F: drivers/pci/switch/switchtec*
F: include/uapi/linux/switchtec_ioctl.h
M: Oliver O'Halloran <oohall@gmail.com>
L: linuxppc-dev@lists.ozlabs.org
S: Supported
-F: Documentation/PCI/pci-error-recovery.txt
+F: Documentation/PCI/pci-error-recovery.rst
F: drivers/pci/pcie/aer.c
F: drivers/pci/pcie/dpc.c
F: drivers/pci/pcie/err.c
M: Linas Vepstas <linasvepstas@gmail.com>
L: linux-pci@vger.kernel.org
S: Supported
-F: Documentation/PCI/pci-error-recovery.txt
+F: Documentation/PCI/pci-error-recovery.rst
PCI MSI DRIVER FOR ALTERA MSI IP
M: Ley Foon Tan <lftan@altera.com>
F: arch/arm/mach-picoxcell/
F: drivers/crypto/picoxcell*
+PIDFD API
+M: Christian Brauner <christian@brauner.io>
+L: linux-kernel@vger.kernel.org
+S: Maintained
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux.git
+F: samples/pidfd/
+F: tools/testing/selftests/pidfd/
+K: (?i)pidfd
+K: (?i)clone3
+K: \b(clone_args|kernel_clone_args)\b
+
PIN CONTROL SUBSYSTEM
M: Linus Walleij <linus.walleij@linaro.org>
L: linux-gpio@vger.kernel.org
F: drivers/scsi/pmcraid.*
PMC SIERRA PM8001 DRIVER
-M: Jack Wang <jinpu.wang@profitbricks.com>
-M: lindar_liu@usish.com
+M: Jack Wang <jinpu.wang@cloud.ionos.com>
L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/scsi/pm8001/
W: http://wiki.enneenne.com/index.php/LinuxPPS_support
L: linuxpps@ml.enneenne.com (subscribers-only)
S: Maintained
-F: Documentation/pps/
+F: Documentation/driver-api/pps.rst
F: Documentation/devicetree/bindings/pps/pps-gpio.txt
F: Documentation/ABI/testing/sysfs-pps
F: drivers/pps/
S: Maintained
W: http://linuxptp.sourceforge.net/
F: Documentation/ABI/testing/sysfs-ptp
-F: Documentation/ptp/*
+F: Documentation/driver-api/ptp.rst
F: drivers/net/phy/dp83640*
F: drivers/ptp/*
F: include/linux/ptp_cl*
F: include/linux/tracehook.h
F: include/uapi/linux/ptrace.h
F: include/uapi/linux/ptrace.h
-F: include/asm-generic/ptrace.h
F: kernel/ptrace.c
F: arch/*/ptrace*.c
F: arch/*/*/ptrace*.c
L: linux-pwm@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm.git
-F: Documentation/pwm.txt
+F: Documentation/driver-api/pwm.rst
F: Documentation/devicetree/bindings/pwm/
F: include/linux/pwm.h
F: drivers/pwm/
QUALCOMM GENERIC INTERFACE I2C DRIVER
M: Alok Chauhan <alokc@codeaurora.org>
-M: Karthikeyan Ramasubramanian <kramasub@codeaurora.org>
L: linux-i2c@vger.kernel.org
L: linux-arm-msm@vger.kernel.org
S: Supported
RAMDISK RAM BLOCK DEVICE DRIVER
M: Jens Axboe <axboe@kernel.dk>
S: Maintained
-F: Documentation/blockdev/ramdisk.txt
+F: Documentation/admin-guide/blockdev/ramdisk.rst
F: drivers/block/brd.c
RANCHU VIRTUAL BOARD FOR MIPS
T: git git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git
S: Maintained
F: Documentation/devicetree/bindings/rtc/
-F: Documentation/rtc.txt
+F: Documentation/admin-guide/rtc.rst
F: drivers/rtc/
F: include/linux/rtc.h
F: include/uapi/linux/rtc.h
RENESAS EMEV2 I2C DRIVER
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
S: Supported
+F: Documentation/devicetree/bindings/i2c/i2c-emev2.txt
F: drivers/i2c/busses/i2c-emev2.c
RENESAS ETHERNET DRIVERS
RENESAS R-CAR I2C DRIVERS
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
S: Supported
+F: Documentation/devicetree/bindings/i2c/i2c-rcar.txt
+F: Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt
F: drivers/i2c/busses/i2c-rcar.c
F: drivers/i2c/busses/i2c-sh_mobile.c
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
S: Maintained
-F: Documentation/rfkill.txt
+F: Documentation/driver-api/rfkill.rst
F: Documentation/ABI/stable/sysfs-class-rfkill
F: net/rfkill/
F: include/linux/rfkill.h
F: drivers/media/platform/rockchip/rga/
F: Documentation/devicetree/bindings/media/rockchip-rga.txt
-ROCKCHIP VPU CODEC DRIVER
+HANTRO VPU CODEC DRIVER
M: Ezequiel Garcia <ezequiel@collabora.com>
L: linux-media@vger.kernel.org
S: Maintained
-F: drivers/staging/media/platform/rockchip/vpu/
+F: drivers/staging/media/platform/hantro/
F: Documentation/devicetree/bindings/media/rockchip-vpu.txt
ROCKER DRIVER
P: Comtrol Corp.
W: http://www.comtrol.com
S: Maintained
-F: Documentation/serial/rocket.rst
+F: Documentation/driver-api/serial/rocket.rst
F: drivers/tty/rocket*
ROCKETPORT EXPRESS/INFINITY DRIVER
F: drivers/video/fbdev/savage/
S390
-M: Martin Schwidefsky <schwidefsky@de.ibm.com>
M: Heiko Carstens <heiko.carstens@de.ibm.com>
+M: Vasily Gorbik <gor@linux.ibm.com>
+M: Christian Borntraeger <borntraeger@de.ibm.com>
L: linux-s390@vger.kernel.org
W: http://www.ibm.com/developerworks/linux/linux390/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git
L: kvm@vger.kernel.org
S: Supported
F: drivers/s390/cio/vfio_ccw*
-F: Documentation/s390/vfio-ccw.txt
+F: Documentation/s390/vfio-ccw.rst
F: include/uapi/linux/vfio_ccw.h
S390 ZCRYPT DRIVER
F: drivers/s390/crypto/vfio_ap_drv.c
F: drivers/s390/crypto/vfio_ap_private.h
F: drivers/s390/crypto/vfio_ap_ops.c
-F: Documentation/s390/vfio-ap.txt
+F: Documentation/s390/vfio-ap.rst
S390 ZFCP DRIVER
M: Steffen Maier <maier@linux.ibm.com>
L: linux-kernel@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/phy/samsung-phy.txt
-F: Documentation/phy/samsung-usb2.txt
+F: Documentation/driver-api/phy/samsung-usb2.rst
F: drivers/phy/samsung/phy-exynos4210-usb2.c
F: drivers/phy/samsung/phy-exynos4x12-usb2.c
F: drivers/phy/samsung/phy-exynos5250-usb2.c
F: drivers/misc/phantom.c
F: include/uapi/linux/phantom.h
+SENSIRION SPS30 AIR POLLUTION SENSOR DRIVER
+M: Tomasz Duszynski <tduszyns@gmail.com>
+S: Maintained
+F: drivers/iio/chemical/sps30.c
+F: Documentation/devicetree/bindings/iio/chemical/sensirion,sps30.yaml
+
SERIAL DEVICE BUS
M: Rob Herring <robh@kernel.org>
L: linux-serial@vger.kernel.org
M: Pat Gefre <pfg@sgi.com>
L: linux-ia64@vger.kernel.org
S: Supported
-F: Documentation/ia64/serial.txt
+F: Documentation/ia64/serial.rst
F: drivers/tty/serial/ioc?_serial.c
F: include/linux/ioc?.h
K: sifive
N: sifive
+SIFIVE FU540 SYSTEM-ON-CHIP
+M: Paul Walmsley <paul.walmsley@sifive.com>
+M: Palmer Dabbelt <palmer@sifive.com>
+L: linux-riscv@lists.infradead.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/pjw/sifive.git
+S: Supported
+K: fu540
+N: fu540
+
SILEAD TOUCHSCREEN DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: linux-input@vger.kernel.org
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/fbdev/sm712*
-F: Documentation/fb/sm712fb.txt
+F: Documentation/fb/sm712fb.rst
SIMPLE FIRMWARE INTERFACE (SFI)
M: Len Brown <lenb@kernel.org>
F: include/linux/siphash.h
SIOX
-M: Gavin Schenk <g.schenk@eckelmann.de>
+M: Thorsten Scherer <t.scherer@eckelmann.de>
M: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
R: Pengutronix Kernel Team <kernel@pengutronix.de>
S: Supported
M: Thomas Winischhofer <thomas@winischhofer.net>
W: http://www.winischhofer.net/linuxsisvga.shtml
S: Maintained
-F: Documentation/fb/sisfb.txt
+F: Documentation/fb/sisfb.rst
F: drivers/video/fbdev/sis/
F: include/video/sisfb.h
S: Maintained
F: drivers/leds/leds-net48xx.c
+SOFT-IWARP DRIVER (siw)
+M: Bernard Metzler <bmt@zurich.ibm.com>
+L: linux-rdma@vger.kernel.org
+S: Supported
+F: drivers/infiniband/sw/siw/
+F: include/uapi/rdma/siw-abi.h
+
SOFT-ROCE DRIVER (rxe)
M: Moni Shoua <monis@mellanox.com>
L: linux-rdma@vger.kernel.org
F: drivers/net/ethernet/socionext/netsec.c
F: Documentation/devicetree/bindings/net/socionext-netsec.txt
+SOCIONEXT (SNI) Synquacer SPI DRIVER
+M: Masahisa Kojima <masahisa.kojima@linaro.org>
+M: Jassi Brar <jaswinder.singh@linaro.org>
+L: linux-spi@vger.kernel.org
+S: Maintained
+F: drivers/spi/spi-synquacer.c
+F: Documentation/devicetree/bindings/spi/spi-synquacer.txt
+
SOLIDRUN CLEARFOG SUPPORT
M: Russell King <linux@armlinux.org.uk>
S: Maintained
L: platform-driver-x86@vger.kernel.org
W: http://www.linux.it/~malattia/wiki/index.php/Sony_drivers
S: Maintained
-F: Documentation/laptops/sony-laptop.txt
+F: Documentation/admin-guide/laptops/sony-laptop.rst
F: drivers/char/sonypi.c
F: drivers/platform/x86/sony-laptop.c
F: include/linux/sony-laptop.h
S: Maintained
F: drivers/staging/erofs/
+STAGING - FIELDBUS SUBSYSTEM
+M: Sven Van Asbroeck <TheSven73@gmail.com>
+S: Maintained
+F: drivers/staging/fieldbus/*
+F: drivers/staging/fieldbus/Documentation/
+
+STAGING - HMS ANYBUS-S BUS
+M: Sven Van Asbroeck <TheSven73@gmail.com>
+S: Maintained
+F: drivers/staging/fieldbus/anybuss/
+
STAGING - INDUSTRIAL IO
M: Jonathan Cameron <jic23@kernel.org>
L: linux-iio@vger.kernel.org
F: drivers/net/ethernet/adaptec/starfire*
STEC S1220 SKD DRIVER
-M: Bart Van Assche <bart.vanassche@wdc.com>
+M: Damien Le Moal <Damien.LeMoal@wdc.com>
L: linux-block@vger.kernel.org
S: Maintained
F: drivers/block/skd*[ch]
M: Martin Mares <mj@ucw.cz>
L: linux-video@atrey.karlin.mff.cuni.cz
S: Maintained
-F: Documentation/svga.txt
+F: Documentation/admin-guide/svga.rst
F: arch/x86/boot/video*
SWIOTLB SUBSYSTEM
F: drivers/dma-buf/sw_sync.c
F: include/linux/sync_file.h
F: include/uapi/linux/sync_file.h
-F: Documentation/sync_file.txt
+F: Documentation/driver-api/sync_file.rst
T: git git://anongit.freedesktop.org/drm/drm-misc
SYNOPSYS ARC ARCHITECTURE
TEGRA I2C DRIVER
M: Laxman Dewangan <ldewangan@nvidia.com>
+R: Dmitry Osipenko <digetx@gmail.com>
S: Supported
F: drivers/i2c/busses/i2c-tegra.c
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
T: git git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git
S: Supported
+F: Documentation/devicetree/bindings/i2c/i2c-davinci.txt
F: arch/arm/mach-davinci/
F: drivers/i2c/busses/i2c-davinci.c
F: arch/arm/boot/dts/da850*
TI LP855x BACKLIGHT DRIVER
M: Milo Kim <milo.kim@ti.com>
S: Maintained
-F: Documentation/backlight/lp855x-driver.txt
+F: Documentation/driver-api/backlight/lp855x-driver.rst
F: drivers/video/backlight/lp855x_bl.c
F: include/linux/platform_data/lp855x.h
M: Jiri Slaby <jslaby@suse.com>
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
-F: Documentation/serial/
+F: Documentation/driver-api/serial/
F: drivers/tty/
F: drivers/tty/serial/serial_core.c
F: include/linux/serial_core.h
M: Oliver Neukum <oneukum@suse.com>
L: linux-usb@vger.kernel.org
S: Maintained
-F: Documentation/usb/acm.txt
+F: Documentation/usb/acm.rst
F: drivers/usb/class/cdc-acm.*
USB AR5523 WIRELESS DRIVER
M: Alan Stern <stern@rowland.harvard.edu>
L: linux-usb@vger.kernel.org
S: Maintained
-F: Documentation/usb/ehci.txt
+F: Documentation/usb/ehci.rst
F: drivers/usb/host/ehci*
USB GADGET/PERIPHERAL SUBSYSTEM
L: linux-usb@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git
S: Maintained
-F: Documentation/hid/hiddev.txt
+F: Documentation/hid/hiddev.rst
F: drivers/hid/usbhid/
USB INTEL XHCI ROLE MUX DRIVER
M: Alan Stern <stern@rowland.harvard.edu>
L: linux-usb@vger.kernel.org
S: Maintained
-F: Documentation/usb/ohci.txt
+F: Documentation/usb/ohci.rst
F: drivers/usb/host/ohci*
USB OTG FSM (Finite State Machine)
M: Shuah Khan <skhan@linuxfoundation.org>
L: linux-usb@vger.kernel.org
S: Maintained
-F: Documentation/usb/usbip_protocol.txt
+F: Documentation/usb/usbip_protocol.rst
F: drivers/usb/usbip/
F: tools/usb/usbip/
F: tools/testing/selftests/drivers/usb/usbip/
L: linux-usb@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial.git
S: Maintained
-F: Documentation/usb/usb-serial.txt
+F: Documentation/usb/usb-serial.rst
F: drivers/usb/serial/
F: include/linux/usb/serial.h
L: linux-fbdev@vger.kernel.org
W: https://github.com/mjanusz/v86d
S: Maintained
-F: Documentation/fb/uvesafb.txt
+F: Documentation/fb/uvesafb.rst
F: drivers/video/fbdev/uvesafb.*
VF610 NAND DRIVER
L: kvm@vger.kernel.org
T: git git://github.com/awilliam/linux-vfio.git
S: Maintained
-F: Documentation/vfio.txt
+F: Documentation/driver-api/vfio.rst
F: drivers/vfio/
F: include/linux/vfio.h
F: include/uapi/linux/vfio.h
M: Kirti Wankhede <kwankhede@nvidia.com>
L: kvm@vger.kernel.org
S: Maintained
-F: Documentation/vfio-mediated-device.txt
+F: Documentation/driver-api/vfio-mediated-device.rst
F: drivers/vfio/mdev/
F: include/linux/mdev.h
F: samples/vfio-mdev/
F: drivers/net/ethernet/via/via-velocity.*
VICODEC VIRTUAL CODEC DRIVER
-M: Hans Verkuil <hans.verkuil@cisco.com>
+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
W: https://linuxtv.org
M: Pawel Osciak <pawel@osciak.com>
M: Marek Szyprowski <m.szyprowski@samsung.com>
M: Kyungmin Park <kyungmin.park@samsung.com>
+R: Tomasz Figa <tfiga@chromium.org>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/common/videobuf2/*
F: drivers/virtio/virtio_input.c
F: include/uapi/linux/virtio_input.h
+ VIRTIO IOMMU DRIVER
+ M: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
+ L: virtualization@lists.linux-foundation.org
+ S: Maintained
+ F: drivers/iommu/virtio-iommu.c
+ F: include/uapi/linux/virtio_iommu.h
+
VIRTUAL BOX GUEST DEVICE DRIVER
M: Hans de Goede <hdegoede@redhat.com>
M: Arnd Bergmann <arnd@arndb.de>
XDP SOCKETS (AF_XDP)
M: Björn Töpel <bjorn.topel@intel.com>
M: Magnus Karlsson <magnus.karlsson@intel.com>
+R: Jonathan Lemon <jonathan.lemon@gmail.com>
L: netdev@vger.kernel.org
L: bpf@vger.kernel.org
S: Maintained
F: Documentation/ABI/testing/sysfs-hypervisor-xen
XEN NETWORK BACKEND DRIVER
-M: Wei Liu <wei.liu2@citrix.com>
+M: Wei Liu <wei.liu@kernel.org>
M: Paul Durrant <paul.durrant@citrix.com>
L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
L: netdev@vger.kernel.org
T: git git://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git
S: Supported
F: Documentation/filesystems/xfs.txt
+F: Documentation/ABI/testing/sysfs-fs-xfs
+F: Documentation/filesystems/xfs.txt
+F: Documentation/filesystems/xfs-delayed-logging-design.txt
+F: Documentation/filesystems/xfs-self-describing-metadata.txt
F: fs/xfs/
+F: include/uapi/linux/dqblk_xfs.h
+F: include/uapi/linux/fsmap.h
XILINX AXI ETHERNET DRIVER
M: Anirudha Sarangi <anirudh@xilinx.com>
L: linux-i2c@vger.kernel.org
W: http://www.cavium.com
S: Supported
+F: Documentation/devicetree/bindings/i2c/i2c-xlp9xx.txt
F: drivers/i2c/busses/i2c-xlp9xx.c
XRA1403 GPIO EXPANDER
S: Maintained
F: drivers/media/dvb-frontends/zd1301_demod*
+ZHAOXIN PROCESSOR SUPPORT
+M: Tony W Wang-oc <TonyWWang-oc@zhaoxin.com>
+L: linux-kernel@vger.kernel.org
+S: Maintained
+F: arch/x86/kernel/cpu/zhaoxin.c
+
ZPOOL COMPRESSED PAGE STORAGE API
M: Dan Streetman <ddstreet@ieee.org>
L: linux-mm@kvack.org
L: linux-kernel@vger.kernel.org
S: Maintained
F: drivers/block/zram/
-F: Documentation/blockdev/zram.txt
+F: Documentation/admin-guide/blockdev/zram.rst
ZS DECSTATION Z85C30 SERIAL DRIVER
M: "Maciej W. Rozycki" <macro@linux-mips.org>
--- /dev/null
-static int viommu_match_node(struct device *dev, void *data)
+ // SPDX-License-Identifier: GPL-2.0
+ /*
+ * Virtio driver for the paravirtualized IOMMU
+ *
+ * Copyright (C) 2018 Arm Limited
+ */
+
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+ #include <linux/amba/bus.h>
+ #include <linux/delay.h>
+ #include <linux/dma-iommu.h>
+ #include <linux/freezer.h>
+ #include <linux/interval_tree.h>
+ #include <linux/iommu.h>
+ #include <linux/module.h>
+ #include <linux/of_iommu.h>
+ #include <linux/of_platform.h>
+ #include <linux/pci.h>
+ #include <linux/platform_device.h>
+ #include <linux/virtio.h>
+ #include <linux/virtio_config.h>
+ #include <linux/virtio_ids.h>
+ #include <linux/wait.h>
+
+ #include <uapi/linux/virtio_iommu.h>
+
+ #define MSI_IOVA_BASE 0x8000000
+ #define MSI_IOVA_LENGTH 0x100000
+
+ #define VIOMMU_REQUEST_VQ 0
+ #define VIOMMU_EVENT_VQ 1
+ #define VIOMMU_NR_VQS 2
+
+ struct viommu_dev {
+ struct iommu_device iommu;
+ struct device *dev;
+ struct virtio_device *vdev;
+
+ struct ida domain_ids;
+
+ struct virtqueue *vqs[VIOMMU_NR_VQS];
+ spinlock_t request_lock;
+ struct list_head requests;
+ void *evts;
+
+ /* Device configuration */
+ struct iommu_domain_geometry geometry;
+ u64 pgsize_bitmap;
+ u8 domain_bits;
+ u32 probe_size;
+ };
+
+ struct viommu_mapping {
+ phys_addr_t paddr;
+ struct interval_tree_node iova;
+ u32 flags;
+ };
+
+ struct viommu_domain {
+ struct iommu_domain domain;
+ struct viommu_dev *viommu;
+ struct mutex mutex; /* protects viommu pointer */
+ unsigned int id;
+
+ spinlock_t mappings_lock;
+ struct rb_root_cached mappings;
+
+ unsigned long nr_endpoints;
+ };
+
+ struct viommu_endpoint {
+ struct device *dev;
+ struct viommu_dev *viommu;
+ struct viommu_domain *vdomain;
+ struct list_head resv_regions;
+ };
+
+ struct viommu_request {
+ struct list_head list;
+ void *writeback;
+ unsigned int write_offset;
+ unsigned int len;
+ char buf[];
+ };
+
+ #define VIOMMU_FAULT_RESV_MASK 0xffffff00
+
+ struct viommu_event {
+ union {
+ u32 head;
+ struct virtio_iommu_fault fault;
+ };
+ };
+
+ #define to_viommu_domain(domain) \
+ container_of(domain, struct viommu_domain, domain)
+
+ static int viommu_get_req_errno(void *buf, size_t len)
+ {
+ struct virtio_iommu_req_tail *tail = buf + len - sizeof(*tail);
+
+ switch (tail->status) {
+ case VIRTIO_IOMMU_S_OK:
+ return 0;
+ case VIRTIO_IOMMU_S_UNSUPP:
+ return -ENOSYS;
+ case VIRTIO_IOMMU_S_INVAL:
+ return -EINVAL;
+ case VIRTIO_IOMMU_S_RANGE:
+ return -ERANGE;
+ case VIRTIO_IOMMU_S_NOENT:
+ return -ENOENT;
+ case VIRTIO_IOMMU_S_FAULT:
+ return -EFAULT;
+ case VIRTIO_IOMMU_S_IOERR:
+ case VIRTIO_IOMMU_S_DEVERR:
+ default:
+ return -EIO;
+ }
+ }
+
+ static void viommu_set_req_status(void *buf, size_t len, int status)
+ {
+ struct virtio_iommu_req_tail *tail = buf + len - sizeof(*tail);
+
+ tail->status = status;
+ }
+
+ static off_t viommu_get_write_desc_offset(struct viommu_dev *viommu,
+ struct virtio_iommu_req_head *req,
+ size_t len)
+ {
+ size_t tail_size = sizeof(struct virtio_iommu_req_tail);
+
+ if (req->type == VIRTIO_IOMMU_T_PROBE)
+ return len - viommu->probe_size - tail_size;
+
+ return len - tail_size;
+ }
+
+ /*
+ * __viommu_sync_req - Complete all in-flight requests
+ *
+ * Wait for all added requests to complete. When this function returns, all
+ * requests that were in-flight at the time of the call have completed.
+ */
+ static int __viommu_sync_req(struct viommu_dev *viommu)
+ {
+ int ret = 0;
+ unsigned int len;
+ size_t write_len;
+ struct viommu_request *req;
+ struct virtqueue *vq = viommu->vqs[VIOMMU_REQUEST_VQ];
+
+ assert_spin_locked(&viommu->request_lock);
+
+ virtqueue_kick(vq);
+
+ while (!list_empty(&viommu->requests)) {
+ len = 0;
+ req = virtqueue_get_buf(vq, &len);
+ if (!req)
+ continue;
+
+ if (!len)
+ viommu_set_req_status(req->buf, req->len,
+ VIRTIO_IOMMU_S_IOERR);
+
+ write_len = req->len - req->write_offset;
+ if (req->writeback && len == write_len)
+ memcpy(req->writeback, req->buf + req->write_offset,
+ write_len);
+
+ list_del(&req->list);
+ kfree(req);
+ }
+
+ return ret;
+ }
+
+ static int viommu_sync_req(struct viommu_dev *viommu)
+ {
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&viommu->request_lock, flags);
+ ret = __viommu_sync_req(viommu);
+ if (ret)
+ dev_dbg(viommu->dev, "could not sync requests (%d)\n", ret);
+ spin_unlock_irqrestore(&viommu->request_lock, flags);
+
+ return ret;
+ }
+
+ /*
+ * __viommu_add_request - Add one request to the queue
+ * @buf: pointer to the request buffer
+ * @len: length of the request buffer
+ * @writeback: copy data back to the buffer when the request completes.
+ *
+ * Add a request to the queue. Only synchronize the queue if it's already full.
+ * Otherwise don't kick the queue nor wait for requests to complete.
+ *
+ * When @writeback is true, data written by the device, including the request
+ * status, is copied into @buf after the request completes. This is unsafe if
+ * the caller allocates @buf on stack and drops the lock between add_req() and
+ * sync_req().
+ *
+ * Return 0 if the request was successfully added to the queue.
+ */
+ static int __viommu_add_req(struct viommu_dev *viommu, void *buf, size_t len,
+ bool writeback)
+ {
+ int ret;
+ off_t write_offset;
+ struct viommu_request *req;
+ struct scatterlist top_sg, bottom_sg;
+ struct scatterlist *sg[2] = { &top_sg, &bottom_sg };
+ struct virtqueue *vq = viommu->vqs[VIOMMU_REQUEST_VQ];
+
+ assert_spin_locked(&viommu->request_lock);
+
+ write_offset = viommu_get_write_desc_offset(viommu, buf, len);
+ if (write_offset <= 0)
+ return -EINVAL;
+
+ req = kzalloc(sizeof(*req) + len, GFP_ATOMIC);
+ if (!req)
+ return -ENOMEM;
+
+ req->len = len;
+ if (writeback) {
+ req->writeback = buf + write_offset;
+ req->write_offset = write_offset;
+ }
+ memcpy(&req->buf, buf, write_offset);
+
+ sg_init_one(&top_sg, req->buf, write_offset);
+ sg_init_one(&bottom_sg, req->buf + write_offset, len - write_offset);
+
+ ret = virtqueue_add_sgs(vq, sg, 1, 1, req, GFP_ATOMIC);
+ if (ret == -ENOSPC) {
+ /* If the queue is full, sync and retry */
+ if (!__viommu_sync_req(viommu))
+ ret = virtqueue_add_sgs(vq, sg, 1, 1, req, GFP_ATOMIC);
+ }
+ if (ret)
+ goto err_free;
+
+ list_add_tail(&req->list, &viommu->requests);
+ return 0;
+
+ err_free:
+ kfree(req);
+ return ret;
+ }
+
+ static int viommu_add_req(struct viommu_dev *viommu, void *buf, size_t len)
+ {
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&viommu->request_lock, flags);
+ ret = __viommu_add_req(viommu, buf, len, false);
+ if (ret)
+ dev_dbg(viommu->dev, "could not add request: %d\n", ret);
+ spin_unlock_irqrestore(&viommu->request_lock, flags);
+
+ return ret;
+ }
+
+ /*
+ * Send a request and wait for it to complete. Return the request status (as an
+ * errno)
+ */
+ static int viommu_send_req_sync(struct viommu_dev *viommu, void *buf,
+ size_t len)
+ {
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&viommu->request_lock, flags);
+
+ ret = __viommu_add_req(viommu, buf, len, true);
+ if (ret) {
+ dev_dbg(viommu->dev, "could not add request (%d)\n", ret);
+ goto out_unlock;
+ }
+
+ ret = __viommu_sync_req(viommu);
+ if (ret) {
+ dev_dbg(viommu->dev, "could not sync requests (%d)\n", ret);
+ /* Fall-through (get the actual request status) */
+ }
+
+ ret = viommu_get_req_errno(buf, len);
+ out_unlock:
+ spin_unlock_irqrestore(&viommu->request_lock, flags);
+ return ret;
+ }
+
+ /*
+ * viommu_add_mapping - add a mapping to the internal tree
+ *
+ * On success, return the new mapping. Otherwise return NULL.
+ */
+ static int viommu_add_mapping(struct viommu_domain *vdomain, unsigned long iova,
+ phys_addr_t paddr, size_t size, u32 flags)
+ {
+ unsigned long irqflags;
+ struct viommu_mapping *mapping;
+
+ mapping = kzalloc(sizeof(*mapping), GFP_ATOMIC);
+ if (!mapping)
+ return -ENOMEM;
+
+ mapping->paddr = paddr;
+ mapping->iova.start = iova;
+ mapping->iova.last = iova + size - 1;
+ mapping->flags = flags;
+
+ spin_lock_irqsave(&vdomain->mappings_lock, irqflags);
+ interval_tree_insert(&mapping->iova, &vdomain->mappings);
+ spin_unlock_irqrestore(&vdomain->mappings_lock, irqflags);
+
+ return 0;
+ }
+
+ /*
+ * viommu_del_mappings - remove mappings from the internal tree
+ *
+ * @vdomain: the domain
+ * @iova: start of the range
+ * @size: size of the range. A size of 0 corresponds to the entire address
+ * space.
+ *
+ * On success, returns the number of unmapped bytes (>= size)
+ */
+ static size_t viommu_del_mappings(struct viommu_domain *vdomain,
+ unsigned long iova, size_t size)
+ {
+ size_t unmapped = 0;
+ unsigned long flags;
+ unsigned long last = iova + size - 1;
+ struct viommu_mapping *mapping = NULL;
+ struct interval_tree_node *node, *next;
+
+ spin_lock_irqsave(&vdomain->mappings_lock, flags);
+ next = interval_tree_iter_first(&vdomain->mappings, iova, last);
+ while (next) {
+ node = next;
+ mapping = container_of(node, struct viommu_mapping, iova);
+ next = interval_tree_iter_next(node, iova, last);
+
+ /* Trying to split a mapping? */
+ if (mapping->iova.start < iova)
+ break;
+
+ /*
+ * Virtio-iommu doesn't allow UNMAP to split a mapping created
+ * with a single MAP request, so remove the full mapping.
+ */
+ unmapped += mapping->iova.last - mapping->iova.start + 1;
+
+ interval_tree_remove(node, &vdomain->mappings);
+ kfree(mapping);
+ }
+ spin_unlock_irqrestore(&vdomain->mappings_lock, flags);
+
+ return unmapped;
+ }
+
+ /*
+ * viommu_replay_mappings - re-send MAP requests
+ *
+ * When reattaching a domain that was previously detached from all endpoints,
+ * mappings were deleted from the device. Re-create the mappings available in
+ * the internal tree.
+ */
+ static int viommu_replay_mappings(struct viommu_domain *vdomain)
+ {
+ int ret = 0;
+ unsigned long flags;
+ struct viommu_mapping *mapping;
+ struct interval_tree_node *node;
+ struct virtio_iommu_req_map map;
+
+ spin_lock_irqsave(&vdomain->mappings_lock, flags);
+ node = interval_tree_iter_first(&vdomain->mappings, 0, -1UL);
+ while (node) {
+ mapping = container_of(node, struct viommu_mapping, iova);
+ map = (struct virtio_iommu_req_map) {
+ .head.type = VIRTIO_IOMMU_T_MAP,
+ .domain = cpu_to_le32(vdomain->id),
+ .virt_start = cpu_to_le64(mapping->iova.start),
+ .virt_end = cpu_to_le64(mapping->iova.last),
+ .phys_start = cpu_to_le64(mapping->paddr),
+ .flags = cpu_to_le32(mapping->flags),
+ };
+
+ ret = viommu_send_req_sync(vdomain->viommu, &map, sizeof(map));
+ if (ret)
+ break;
+
+ node = interval_tree_iter_next(node, 0, -1UL);
+ }
+ spin_unlock_irqrestore(&vdomain->mappings_lock, flags);
+
+ return ret;
+ }
+
+ static int viommu_add_resv_mem(struct viommu_endpoint *vdev,
+ struct virtio_iommu_probe_resv_mem *mem,
+ size_t len)
+ {
+ size_t size;
+ u64 start64, end64;
+ phys_addr_t start, end;
+ struct iommu_resv_region *region = NULL;
+ unsigned long prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
+
+ start = start64 = le64_to_cpu(mem->start);
+ end = end64 = le64_to_cpu(mem->end);
+ size = end64 - start64 + 1;
+
+ /* Catch any overflow, including the unlikely end64 - start64 + 1 = 0 */
+ if (start != start64 || end != end64 || size < end64 - start64)
+ return -EOVERFLOW;
+
+ if (len < sizeof(*mem))
+ return -EINVAL;
+
+ switch (mem->subtype) {
+ default:
+ dev_warn(vdev->dev, "unknown resv mem subtype 0x%x\n",
+ mem->subtype);
+ /* Fall-through */
+ case VIRTIO_IOMMU_RESV_MEM_T_RESERVED:
+ region = iommu_alloc_resv_region(start, size, 0,
+ IOMMU_RESV_RESERVED);
+ break;
+ case VIRTIO_IOMMU_RESV_MEM_T_MSI:
+ region = iommu_alloc_resv_region(start, size, prot,
+ IOMMU_RESV_MSI);
+ break;
+ }
+ if (!region)
+ return -ENOMEM;
+
+ list_add(&vdev->resv_regions, ®ion->list);
+ return 0;
+ }
+
+ static int viommu_probe_endpoint(struct viommu_dev *viommu, struct device *dev)
+ {
+ int ret;
+ u16 type, len;
+ size_t cur = 0;
+ size_t probe_len;
+ struct virtio_iommu_req_probe *probe;
+ struct virtio_iommu_probe_property *prop;
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+ struct viommu_endpoint *vdev = fwspec->iommu_priv;
+
+ if (!fwspec->num_ids)
+ return -EINVAL;
+
+ probe_len = sizeof(*probe) + viommu->probe_size +
+ sizeof(struct virtio_iommu_req_tail);
+ probe = kzalloc(probe_len, GFP_KERNEL);
+ if (!probe)
+ return -ENOMEM;
+
+ probe->head.type = VIRTIO_IOMMU_T_PROBE;
+ /*
+ * For now, assume that properties of an endpoint that outputs multiple
+ * IDs are consistent. Only probe the first one.
+ */
+ probe->endpoint = cpu_to_le32(fwspec->ids[0]);
+
+ ret = viommu_send_req_sync(viommu, probe, probe_len);
+ if (ret)
+ goto out_free;
+
+ prop = (void *)probe->properties;
+ type = le16_to_cpu(prop->type) & VIRTIO_IOMMU_PROBE_T_MASK;
+
+ while (type != VIRTIO_IOMMU_PROBE_T_NONE &&
+ cur < viommu->probe_size) {
+ len = le16_to_cpu(prop->length) + sizeof(*prop);
+
+ switch (type) {
+ case VIRTIO_IOMMU_PROBE_T_RESV_MEM:
+ ret = viommu_add_resv_mem(vdev, (void *)prop, len);
+ break;
+ default:
+ dev_err(dev, "unknown viommu prop 0x%x\n", type);
+ }
+
+ if (ret)
+ dev_err(dev, "failed to parse viommu prop 0x%x\n", type);
+
+ cur += len;
+ if (cur >= viommu->probe_size)
+ break;
+
+ prop = (void *)probe->properties + cur;
+ type = le16_to_cpu(prop->type) & VIRTIO_IOMMU_PROBE_T_MASK;
+ }
+
+ out_free:
+ kfree(probe);
+ return ret;
+ }
+
+ static int viommu_fault_handler(struct viommu_dev *viommu,
+ struct virtio_iommu_fault *fault)
+ {
+ char *reason_str;
+
+ u8 reason = fault->reason;
+ u32 flags = le32_to_cpu(fault->flags);
+ u32 endpoint = le32_to_cpu(fault->endpoint);
+ u64 address = le64_to_cpu(fault->address);
+
+ switch (reason) {
+ case VIRTIO_IOMMU_FAULT_R_DOMAIN:
+ reason_str = "domain";
+ break;
+ case VIRTIO_IOMMU_FAULT_R_MAPPING:
+ reason_str = "page";
+ break;
+ case VIRTIO_IOMMU_FAULT_R_UNKNOWN:
+ default:
+ reason_str = "unknown";
+ break;
+ }
+
+ /* TODO: find EP by ID and report_iommu_fault */
+ if (flags & VIRTIO_IOMMU_FAULT_F_ADDRESS)
+ dev_err_ratelimited(viommu->dev, "%s fault from EP %u at %#llx [%s%s%s]\n",
+ reason_str, endpoint, address,
+ flags & VIRTIO_IOMMU_FAULT_F_READ ? "R" : "",
+ flags & VIRTIO_IOMMU_FAULT_F_WRITE ? "W" : "",
+ flags & VIRTIO_IOMMU_FAULT_F_EXEC ? "X" : "");
+ else
+ dev_err_ratelimited(viommu->dev, "%s fault from EP %u\n",
+ reason_str, endpoint);
+ return 0;
+ }
+
+ static void viommu_event_handler(struct virtqueue *vq)
+ {
+ int ret;
+ unsigned int len;
+ struct scatterlist sg[1];
+ struct viommu_event *evt;
+ struct viommu_dev *viommu = vq->vdev->priv;
+
+ while ((evt = virtqueue_get_buf(vq, &len)) != NULL) {
+ if (len > sizeof(*evt)) {
+ dev_err(viommu->dev,
+ "invalid event buffer (len %u != %zu)\n",
+ len, sizeof(*evt));
+ } else if (!(evt->head & VIOMMU_FAULT_RESV_MASK)) {
+ viommu_fault_handler(viommu, &evt->fault);
+ }
+
+ sg_init_one(sg, evt, sizeof(*evt));
+ ret = virtqueue_add_inbuf(vq, sg, 1, evt, GFP_ATOMIC);
+ if (ret)
+ dev_err(viommu->dev, "could not add event buffer\n");
+ }
+
+ virtqueue_kick(vq);
+ }
+
+ /* IOMMU API */
+
+ static struct iommu_domain *viommu_domain_alloc(unsigned type)
+ {
+ struct viommu_domain *vdomain;
+
+ if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
+ return NULL;
+
+ vdomain = kzalloc(sizeof(*vdomain), GFP_KERNEL);
+ if (!vdomain)
+ return NULL;
+
+ mutex_init(&vdomain->mutex);
+ spin_lock_init(&vdomain->mappings_lock);
+ vdomain->mappings = RB_ROOT_CACHED;
+
+ if (type == IOMMU_DOMAIN_DMA &&
+ iommu_get_dma_cookie(&vdomain->domain)) {
+ kfree(vdomain);
+ return NULL;
+ }
+
+ return &vdomain->domain;
+ }
+
+ static int viommu_domain_finalise(struct viommu_dev *viommu,
+ struct iommu_domain *domain)
+ {
+ int ret;
+ struct viommu_domain *vdomain = to_viommu_domain(domain);
+ unsigned int max_domain = viommu->domain_bits > 31 ? ~0 :
+ (1U << viommu->domain_bits) - 1;
+
+ vdomain->viommu = viommu;
+
+ domain->pgsize_bitmap = viommu->pgsize_bitmap;
+ domain->geometry = viommu->geometry;
+
+ ret = ida_alloc_max(&viommu->domain_ids, max_domain, GFP_KERNEL);
+ if (ret >= 0)
+ vdomain->id = (unsigned int)ret;
+
+ return ret > 0 ? 0 : ret;
+ }
+
+ static void viommu_domain_free(struct iommu_domain *domain)
+ {
+ struct viommu_domain *vdomain = to_viommu_domain(domain);
+
+ iommu_put_dma_cookie(domain);
+
+ /* Free all remaining mappings (size 2^64) */
+ viommu_del_mappings(vdomain, 0, 0);
+
+ if (vdomain->viommu)
+ ida_free(&vdomain->viommu->domain_ids, vdomain->id);
+
+ kfree(vdomain);
+ }
+
+ static int viommu_attach_dev(struct iommu_domain *domain, struct device *dev)
+ {
+ int i;
+ int ret = 0;
+ struct virtio_iommu_req_attach req;
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+ struct viommu_endpoint *vdev = fwspec->iommu_priv;
+ struct viommu_domain *vdomain = to_viommu_domain(domain);
+
+ mutex_lock(&vdomain->mutex);
+ if (!vdomain->viommu) {
+ /*
+ * Properly initialize the domain now that we know which viommu
+ * owns it.
+ */
+ ret = viommu_domain_finalise(vdev->viommu, domain);
+ } else if (vdomain->viommu != vdev->viommu) {
+ dev_err(dev, "cannot attach to foreign vIOMMU\n");
+ ret = -EXDEV;
+ }
+ mutex_unlock(&vdomain->mutex);
+
+ if (ret)
+ return ret;
+
+ /*
+ * In the virtio-iommu device, when attaching the endpoint to a new
+ * domain, it is detached from the old one and, if as as a result the
+ * old domain isn't attached to any endpoint, all mappings are removed
+ * from the old domain and it is freed.
+ *
+ * In the driver the old domain still exists, and its mappings will be
+ * recreated if it gets reattached to an endpoint. Otherwise it will be
+ * freed explicitly.
+ *
+ * vdev->vdomain is protected by group->mutex
+ */
+ if (vdev->vdomain)
+ vdev->vdomain->nr_endpoints--;
+
+ req = (struct virtio_iommu_req_attach) {
+ .head.type = VIRTIO_IOMMU_T_ATTACH,
+ .domain = cpu_to_le32(vdomain->id),
+ };
+
+ for (i = 0; i < fwspec->num_ids; i++) {
+ req.endpoint = cpu_to_le32(fwspec->ids[i]);
+
+ ret = viommu_send_req_sync(vdomain->viommu, &req, sizeof(req));
+ if (ret)
+ return ret;
+ }
+
+ if (!vdomain->nr_endpoints) {
+ /*
+ * This endpoint is the first to be attached to the domain.
+ * Replay existing mappings (e.g. SW MSI).
+ */
+ ret = viommu_replay_mappings(vdomain);
+ if (ret)
+ return ret;
+ }
+
+ vdomain->nr_endpoints++;
+ vdev->vdomain = vdomain;
+
+ return 0;
+ }
+
+ static int viommu_map(struct iommu_domain *domain, unsigned long iova,
+ phys_addr_t paddr, size_t size, int prot)
+ {
+ int ret;
+ int flags;
+ struct virtio_iommu_req_map map;
+ struct viommu_domain *vdomain = to_viommu_domain(domain);
+
+ flags = (prot & IOMMU_READ ? VIRTIO_IOMMU_MAP_F_READ : 0) |
+ (prot & IOMMU_WRITE ? VIRTIO_IOMMU_MAP_F_WRITE : 0) |
+ (prot & IOMMU_MMIO ? VIRTIO_IOMMU_MAP_F_MMIO : 0);
+
+ ret = viommu_add_mapping(vdomain, iova, paddr, size, flags);
+ if (ret)
+ return ret;
+
+ map = (struct virtio_iommu_req_map) {
+ .head.type = VIRTIO_IOMMU_T_MAP,
+ .domain = cpu_to_le32(vdomain->id),
+ .virt_start = cpu_to_le64(iova),
+ .phys_start = cpu_to_le64(paddr),
+ .virt_end = cpu_to_le64(iova + size - 1),
+ .flags = cpu_to_le32(flags),
+ };
+
+ if (!vdomain->nr_endpoints)
+ return 0;
+
+ ret = viommu_send_req_sync(vdomain->viommu, &map, sizeof(map));
+ if (ret)
+ viommu_del_mappings(vdomain, iova, size);
+
+ return ret;
+ }
+
+ static size_t viommu_unmap(struct iommu_domain *domain, unsigned long iova,
+ size_t size)
+ {
+ int ret = 0;
+ size_t unmapped;
+ struct virtio_iommu_req_unmap unmap;
+ struct viommu_domain *vdomain = to_viommu_domain(domain);
+
+ unmapped = viommu_del_mappings(vdomain, iova, size);
+ if (unmapped < size)
+ return 0;
+
+ /* Device already removed all mappings after detach. */
+ if (!vdomain->nr_endpoints)
+ return unmapped;
+
+ unmap = (struct virtio_iommu_req_unmap) {
+ .head.type = VIRTIO_IOMMU_T_UNMAP,
+ .domain = cpu_to_le32(vdomain->id),
+ .virt_start = cpu_to_le64(iova),
+ .virt_end = cpu_to_le64(iova + unmapped - 1),
+ };
+
+ ret = viommu_add_req(vdomain->viommu, &unmap, sizeof(unmap));
+ return ret ? 0 : unmapped;
+ }
+
+ static phys_addr_t viommu_iova_to_phys(struct iommu_domain *domain,
+ dma_addr_t iova)
+ {
+ u64 paddr = 0;
+ unsigned long flags;
+ struct viommu_mapping *mapping;
+ struct interval_tree_node *node;
+ struct viommu_domain *vdomain = to_viommu_domain(domain);
+
+ spin_lock_irqsave(&vdomain->mappings_lock, flags);
+ node = interval_tree_iter_first(&vdomain->mappings, iova, iova);
+ if (node) {
+ mapping = container_of(node, struct viommu_mapping, iova);
+ paddr = mapping->paddr + (iova - mapping->iova.start);
+ }
+ spin_unlock_irqrestore(&vdomain->mappings_lock, flags);
+
+ return paddr;
+ }
+
+ static void viommu_iotlb_sync(struct iommu_domain *domain)
+ {
+ struct viommu_domain *vdomain = to_viommu_domain(domain);
+
+ viommu_sync_req(vdomain->viommu);
+ }
+
+ static void viommu_get_resv_regions(struct device *dev, struct list_head *head)
+ {
+ struct iommu_resv_region *entry, *new_entry, *msi = NULL;
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+ struct viommu_endpoint *vdev = fwspec->iommu_priv;
+ int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
+
+ list_for_each_entry(entry, &vdev->resv_regions, list) {
+ if (entry->type == IOMMU_RESV_MSI)
+ msi = entry;
+
+ new_entry = kmemdup(entry, sizeof(*entry), GFP_KERNEL);
+ if (!new_entry)
+ return;
+ list_add_tail(&new_entry->list, head);
+ }
+
+ /*
+ * If the device didn't register any bypass MSI window, add a
+ * software-mapped region.
+ */
+ if (!msi) {
+ msi = iommu_alloc_resv_region(MSI_IOVA_BASE, MSI_IOVA_LENGTH,
+ prot, IOMMU_RESV_SW_MSI);
+ if (!msi)
+ return;
+
+ list_add_tail(&msi->list, head);
+ }
+
+ iommu_dma_get_resv_regions(dev, head);
+ }
+
+ static void viommu_put_resv_regions(struct device *dev, struct list_head *head)
+ {
+ struct iommu_resv_region *entry, *next;
+
+ list_for_each_entry_safe(entry, next, head, list)
+ kfree(entry);
+ }
+
+ static struct iommu_ops viommu_ops;
+ static struct virtio_driver virtio_iommu_drv;
+
++static int viommu_match_node(struct device *dev, const void *data)
+ {
+ return dev->parent->fwnode == data;
+ }
+
+ static struct viommu_dev *viommu_get_by_fwnode(struct fwnode_handle *fwnode)
+ {
+ struct device *dev = driver_find_device(&virtio_iommu_drv.driver, NULL,
+ fwnode, viommu_match_node);
+ put_device(dev);
+
+ return dev ? dev_to_virtio(dev)->priv : NULL;
+ }
+
+ static int viommu_add_device(struct device *dev)
+ {
+ int ret;
+ struct iommu_group *group;
+ struct viommu_endpoint *vdev;
+ struct viommu_dev *viommu = NULL;
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+
+ if (!fwspec || fwspec->ops != &viommu_ops)
+ return -ENODEV;
+
+ viommu = viommu_get_by_fwnode(fwspec->iommu_fwnode);
+ if (!viommu)
+ return -ENODEV;
+
+ vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+ if (!vdev)
+ return -ENOMEM;
+
+ vdev->dev = dev;
+ vdev->viommu = viommu;
+ INIT_LIST_HEAD(&vdev->resv_regions);
+ fwspec->iommu_priv = vdev;
+
+ if (viommu->probe_size) {
+ /* Get additional information for this endpoint */
+ ret = viommu_probe_endpoint(viommu, dev);
+ if (ret)
+ goto err_free_dev;
+ }
+
+ ret = iommu_device_link(&viommu->iommu, dev);
+ if (ret)
+ goto err_free_dev;
+
+ /*
+ * Last step creates a default domain and attaches to it. Everything
+ * must be ready.
+ */
+ group = iommu_group_get_for_dev(dev);
+ if (IS_ERR(group)) {
+ ret = PTR_ERR(group);
+ goto err_unlink_dev;
+ }
+
+ iommu_group_put(group);
+
+ return PTR_ERR_OR_ZERO(group);
+
+ err_unlink_dev:
+ iommu_device_unlink(&viommu->iommu, dev);
+ err_free_dev:
+ viommu_put_resv_regions(dev, &vdev->resv_regions);
+ kfree(vdev);
+
+ return ret;
+ }
+
+ static void viommu_remove_device(struct device *dev)
+ {
+ struct viommu_endpoint *vdev;
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+
+ if (!fwspec || fwspec->ops != &viommu_ops)
+ return;
+
+ vdev = fwspec->iommu_priv;
+
+ iommu_group_remove_device(dev);
+ iommu_device_unlink(&vdev->viommu->iommu, dev);
+ viommu_put_resv_regions(dev, &vdev->resv_regions);
+ kfree(vdev);
+ }
+
+ static struct iommu_group *viommu_device_group(struct device *dev)
+ {
+ if (dev_is_pci(dev))
+ return pci_device_group(dev);
+ else
+ return generic_device_group(dev);
+ }
+
+ static int viommu_of_xlate(struct device *dev, struct of_phandle_args *args)
+ {
+ return iommu_fwspec_add_ids(dev, args->args, 1);
+ }
+
+ static struct iommu_ops viommu_ops = {
+ .domain_alloc = viommu_domain_alloc,
+ .domain_free = viommu_domain_free,
+ .attach_dev = viommu_attach_dev,
+ .map = viommu_map,
+ .unmap = viommu_unmap,
+ .iova_to_phys = viommu_iova_to_phys,
+ .iotlb_sync = viommu_iotlb_sync,
+ .add_device = viommu_add_device,
+ .remove_device = viommu_remove_device,
+ .device_group = viommu_device_group,
+ .get_resv_regions = viommu_get_resv_regions,
+ .put_resv_regions = viommu_put_resv_regions,
+ .of_xlate = viommu_of_xlate,
+ };
+
+ static int viommu_init_vqs(struct viommu_dev *viommu)
+ {
+ struct virtio_device *vdev = dev_to_virtio(viommu->dev);
+ const char *names[] = { "request", "event" };
+ vq_callback_t *callbacks[] = {
+ NULL, /* No async requests */
+ viommu_event_handler,
+ };
+
+ return virtio_find_vqs(vdev, VIOMMU_NR_VQS, viommu->vqs, callbacks,
+ names, NULL);
+ }
+
+ static int viommu_fill_evtq(struct viommu_dev *viommu)
+ {
+ int i, ret;
+ struct scatterlist sg[1];
+ struct viommu_event *evts;
+ struct virtqueue *vq = viommu->vqs[VIOMMU_EVENT_VQ];
+ size_t nr_evts = vq->num_free;
+
+ viommu->evts = evts = devm_kmalloc_array(viommu->dev, nr_evts,
+ sizeof(*evts), GFP_KERNEL);
+ if (!evts)
+ return -ENOMEM;
+
+ for (i = 0; i < nr_evts; i++) {
+ sg_init_one(sg, &evts[i], sizeof(*evts));
+ ret = virtqueue_add_inbuf(vq, sg, 1, &evts[i], GFP_KERNEL);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+ }
+
+ static int viommu_probe(struct virtio_device *vdev)
+ {
+ struct device *parent_dev = vdev->dev.parent;
+ struct viommu_dev *viommu = NULL;
+ struct device *dev = &vdev->dev;
+ u64 input_start = 0;
+ u64 input_end = -1UL;
+ int ret;
+
+ if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) ||
+ !virtio_has_feature(vdev, VIRTIO_IOMMU_F_MAP_UNMAP))
+ return -ENODEV;
+
+ viommu = devm_kzalloc(dev, sizeof(*viommu), GFP_KERNEL);
+ if (!viommu)
+ return -ENOMEM;
+
+ spin_lock_init(&viommu->request_lock);
+ ida_init(&viommu->domain_ids);
+ viommu->dev = dev;
+ viommu->vdev = vdev;
+ INIT_LIST_HEAD(&viommu->requests);
+
+ ret = viommu_init_vqs(viommu);
+ if (ret)
+ return ret;
+
+ virtio_cread(vdev, struct virtio_iommu_config, page_size_mask,
+ &viommu->pgsize_bitmap);
+
+ if (!viommu->pgsize_bitmap) {
+ ret = -EINVAL;
+ goto err_free_vqs;
+ }
+
+ viommu->domain_bits = 32;
+
+ /* Optional features */
+ virtio_cread_feature(vdev, VIRTIO_IOMMU_F_INPUT_RANGE,
+ struct virtio_iommu_config, input_range.start,
+ &input_start);
+
+ virtio_cread_feature(vdev, VIRTIO_IOMMU_F_INPUT_RANGE,
+ struct virtio_iommu_config, input_range.end,
+ &input_end);
+
+ virtio_cread_feature(vdev, VIRTIO_IOMMU_F_DOMAIN_BITS,
+ struct virtio_iommu_config, domain_bits,
+ &viommu->domain_bits);
+
+ virtio_cread_feature(vdev, VIRTIO_IOMMU_F_PROBE,
+ struct virtio_iommu_config, probe_size,
+ &viommu->probe_size);
+
+ viommu->geometry = (struct iommu_domain_geometry) {
+ .aperture_start = input_start,
+ .aperture_end = input_end,
+ .force_aperture = true,
+ };
+
+ viommu_ops.pgsize_bitmap = viommu->pgsize_bitmap;
+
+ virtio_device_ready(vdev);
+
+ /* Populate the event queue with buffers */
+ ret = viommu_fill_evtq(viommu);
+ if (ret)
+ goto err_free_vqs;
+
+ ret = iommu_device_sysfs_add(&viommu->iommu, dev, NULL, "%s",
+ virtio_bus_name(vdev));
+ if (ret)
+ goto err_free_vqs;
+
+ iommu_device_set_ops(&viommu->iommu, &viommu_ops);
+ iommu_device_set_fwnode(&viommu->iommu, parent_dev->fwnode);
+
+ iommu_device_register(&viommu->iommu);
+
+ #ifdef CONFIG_PCI
+ if (pci_bus_type.iommu_ops != &viommu_ops) {
+ pci_request_acs();
+ ret = bus_set_iommu(&pci_bus_type, &viommu_ops);
+ if (ret)
+ goto err_unregister;
+ }
+ #endif
+ #ifdef CONFIG_ARM_AMBA
+ if (amba_bustype.iommu_ops != &viommu_ops) {
+ ret = bus_set_iommu(&amba_bustype, &viommu_ops);
+ if (ret)
+ goto err_unregister;
+ }
+ #endif
+ if (platform_bus_type.iommu_ops != &viommu_ops) {
+ ret = bus_set_iommu(&platform_bus_type, &viommu_ops);
+ if (ret)
+ goto err_unregister;
+ }
+
+ vdev->priv = viommu;
+
+ dev_info(dev, "input address: %u bits\n",
+ order_base_2(viommu->geometry.aperture_end));
+ dev_info(dev, "page mask: %#llx\n", viommu->pgsize_bitmap);
+
+ return 0;
+
+ err_unregister:
+ iommu_device_sysfs_remove(&viommu->iommu);
+ iommu_device_unregister(&viommu->iommu);
+ err_free_vqs:
+ vdev->config->del_vqs(vdev);
+
+ return ret;
+ }
+
+ static void viommu_remove(struct virtio_device *vdev)
+ {
+ struct viommu_dev *viommu = vdev->priv;
+
+ iommu_device_sysfs_remove(&viommu->iommu);
+ iommu_device_unregister(&viommu->iommu);
+
+ /* Stop all virtqueues */
+ vdev->config->reset(vdev);
+ vdev->config->del_vqs(vdev);
+
+ dev_info(&vdev->dev, "device removed\n");
+ }
+
+ static void viommu_config_changed(struct virtio_device *vdev)
+ {
+ dev_warn(&vdev->dev, "config changed\n");
+ }
+
+ static unsigned int features[] = {
+ VIRTIO_IOMMU_F_MAP_UNMAP,
+ VIRTIO_IOMMU_F_DOMAIN_BITS,
+ VIRTIO_IOMMU_F_INPUT_RANGE,
+ VIRTIO_IOMMU_F_PROBE,
+ };
+
+ static struct virtio_device_id id_table[] = {
+ { VIRTIO_ID_IOMMU, VIRTIO_DEV_ANY_ID },
+ { 0 },
+ };
+
+ static struct virtio_driver virtio_iommu_drv = {
+ .driver.name = KBUILD_MODNAME,
+ .driver.owner = THIS_MODULE,
+ .id_table = id_table,
+ .feature_table = features,
+ .feature_table_size = ARRAY_SIZE(features),
+ .probe = viommu_probe,
+ .remove = viommu_remove,
+ .config_changed = viommu_config_changed,
+ };
+
+ module_virtio_driver(virtio_iommu_drv);
+
+ MODULE_DESCRIPTION("Virtio IOMMU driver");
+ MODULE_AUTHOR("Jean-Philippe Brucker <jean-philippe.brucker@arm.com>");
+ MODULE_LICENSE("GPL v2");
u32 num_queues;
- /* If the affinity hint is set for virtqueues */
- bool affinity_hint_set;
-
struct hlist_node node;
/* Protected by event_vq lock */
num_targets = virtscsi_config_get(vdev, max_target) + 1;
shost = scsi_host_alloc(&virtscsi_host_template,
- sizeof(*vscsi) + sizeof(vscsi->req_vqs[0]) * num_queues);
+ struct_size(vscsi, req_vqs, num_queues));
if (!shost)
return -ENOMEM;
+// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2009 Red Hat, Inc.
* Author: Michael S. Tsirkin <mst@redhat.com>
*
- * This work is licensed under the terms of the GNU GPL, version 2.
- *
* virtio-net server in host kernel.
*/
#include "vhost.h"
-static int experimental_zcopytx = 1;
+static int experimental_zcopytx = 0;
module_param(experimental_zcopytx, int, 0444);
MODULE_PARM_DESC(experimental_zcopytx, "Enable Zero Copy TX;"
" 1 -Enable; 0 - Disable");
if (!sock)
goto out;
- if (!vq_iotlb_prefetch(vq))
+ if (!vq_meta_prefetch(vq))
goto out;
vhost_disable_notify(&net->dev, vq);
if (!sock)
goto out;
- if (!vq_iotlb_prefetch(vq))
+ if (!vq_meta_prefetch(vq))
goto out;
vhost_disable_notify(&net->dev, vq);
+// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2009 Red Hat, Inc.
* Copyright (C) 2006 Rusty Russell IBM Corporation
*
* Inspiration, some code, and most witty comments come from
* Documentation/virtual/lguest/lguest.c, by Rusty Russell
*
- * This work is licensed under the terms of the GNU GPL, version 2.
- *
* Generic code for virtio server in host kernel.
*/
__vhost_vq_meta_reset(d->vqs[i]);
}
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ static void vhost_map_unprefetch(struct vhost_map *map)
+ {
+ kfree(map->pages);
+ map->pages = NULL;
+ map->npages = 0;
+ map->addr = NULL;
+ }
+
+ static void vhost_uninit_vq_maps(struct vhost_virtqueue *vq)
+ {
+ struct vhost_map *map[VHOST_NUM_ADDRS];
+ int i;
+
+ spin_lock(&vq->mmu_lock);
+ for (i = 0; i < VHOST_NUM_ADDRS; i++) {
+ map[i] = rcu_dereference_protected(vq->maps[i],
+ lockdep_is_held(&vq->mmu_lock));
+ if (map[i])
+ rcu_assign_pointer(vq->maps[i], NULL);
+ }
+ spin_unlock(&vq->mmu_lock);
+
+ synchronize_rcu();
+
+ for (i = 0; i < VHOST_NUM_ADDRS; i++)
+ if (map[i])
+ vhost_map_unprefetch(map[i]);
+
+ }
+
+ static void vhost_reset_vq_maps(struct vhost_virtqueue *vq)
+ {
+ int i;
+
+ vhost_uninit_vq_maps(vq);
+ for (i = 0; i < VHOST_NUM_ADDRS; i++)
+ vq->uaddrs[i].size = 0;
+ }
+
+ static bool vhost_map_range_overlap(struct vhost_uaddr *uaddr,
+ unsigned long start,
+ unsigned long end)
+ {
+ if (unlikely(!uaddr->size))
+ return false;
+
+ return !(end < uaddr->uaddr || start > uaddr->uaddr - 1 + uaddr->size);
+ }
+
+ static void vhost_invalidate_vq_start(struct vhost_virtqueue *vq,
+ int index,
+ unsigned long start,
+ unsigned long end)
+ {
+ struct vhost_uaddr *uaddr = &vq->uaddrs[index];
+ struct vhost_map *map;
+ int i;
+
+ if (!vhost_map_range_overlap(uaddr, start, end))
+ return;
+
+ spin_lock(&vq->mmu_lock);
+ ++vq->invalidate_count;
+
+ map = rcu_dereference_protected(vq->maps[index],
+ lockdep_is_held(&vq->mmu_lock));
+ if (map) {
+ if (uaddr->write) {
+ for (i = 0; i < map->npages; i++)
+ set_page_dirty(map->pages[i]);
+ }
+ rcu_assign_pointer(vq->maps[index], NULL);
+ }
+ spin_unlock(&vq->mmu_lock);
+
+ if (map) {
+ synchronize_rcu();
+ vhost_map_unprefetch(map);
+ }
+ }
+
+ static void vhost_invalidate_vq_end(struct vhost_virtqueue *vq,
+ int index,
+ unsigned long start,
+ unsigned long end)
+ {
+ if (!vhost_map_range_overlap(&vq->uaddrs[index], start, end))
+ return;
+
+ spin_lock(&vq->mmu_lock);
+ --vq->invalidate_count;
+ spin_unlock(&vq->mmu_lock);
+ }
+
+ static int vhost_invalidate_range_start(struct mmu_notifier *mn,
+ const struct mmu_notifier_range *range)
+ {
+ struct vhost_dev *dev = container_of(mn, struct vhost_dev,
+ mmu_notifier);
+ int i, j;
+
+ if (!mmu_notifier_range_blockable(range))
+ return -EAGAIN;
+
+ for (i = 0; i < dev->nvqs; i++) {
+ struct vhost_virtqueue *vq = dev->vqs[i];
+
+ for (j = 0; j < VHOST_NUM_ADDRS; j++)
+ vhost_invalidate_vq_start(vq, j,
+ range->start,
+ range->end);
+ }
+
+ return 0;
+ }
+
+ static void vhost_invalidate_range_end(struct mmu_notifier *mn,
+ const struct mmu_notifier_range *range)
+ {
+ struct vhost_dev *dev = container_of(mn, struct vhost_dev,
+ mmu_notifier);
+ int i, j;
+
+ for (i = 0; i < dev->nvqs; i++) {
+ struct vhost_virtqueue *vq = dev->vqs[i];
+
+ for (j = 0; j < VHOST_NUM_ADDRS; j++)
+ vhost_invalidate_vq_end(vq, j,
+ range->start,
+ range->end);
+ }
+ }
+
+ static const struct mmu_notifier_ops vhost_mmu_notifier_ops = {
+ .invalidate_range_start = vhost_invalidate_range_start,
+ .invalidate_range_end = vhost_invalidate_range_end,
+ };
+
+ static void vhost_init_maps(struct vhost_dev *dev)
+ {
+ struct vhost_virtqueue *vq;
+ int i, j;
+
+ dev->mmu_notifier.ops = &vhost_mmu_notifier_ops;
+
+ for (i = 0; i < dev->nvqs; ++i) {
+ vq = dev->vqs[i];
+ for (j = 0; j < VHOST_NUM_ADDRS; j++)
+ RCU_INIT_POINTER(vq->maps[j], NULL);
+ }
+ }
+ #endif
+
static void vhost_vq_reset(struct vhost_dev *dev,
struct vhost_virtqueue *vq)
{
vq->busyloop_timeout = 0;
vq->umem = NULL;
vq->iotlb = NULL;
+ vq->invalidate_count = 0;
__vhost_vq_meta_reset(vq);
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ vhost_reset_vq_maps(vq);
+ #endif
}
static int vhost_worker(void *data)
}
EXPORT_SYMBOL_GPL(vhost_exceeds_weight);
+ static size_t vhost_get_avail_size(struct vhost_virtqueue *vq,
+ unsigned int num)
+ {
+ size_t event __maybe_unused =
+ vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX) ? 2 : 0;
+
+ return sizeof(*vq->avail) +
+ sizeof(*vq->avail->ring) * num + event;
+ }
+
+ static size_t vhost_get_used_size(struct vhost_virtqueue *vq,
+ unsigned int num)
+ {
+ size_t event __maybe_unused =
+ vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX) ? 2 : 0;
+
+ return sizeof(*vq->used) +
+ sizeof(*vq->used->ring) * num + event;
+ }
+
+ static size_t vhost_get_desc_size(struct vhost_virtqueue *vq,
+ unsigned int num)
+ {
+ return sizeof(*vq->desc) * num;
+ }
+
void vhost_dev_init(struct vhost_dev *dev,
struct vhost_virtqueue **vqs, int nvqs,
int iov_limit, int weight, int byte_weight)
INIT_LIST_HEAD(&dev->read_list);
INIT_LIST_HEAD(&dev->pending_list);
spin_lock_init(&dev->iotlb_lock);
-
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ vhost_init_maps(dev);
+ #endif
for (i = 0; i < dev->nvqs; ++i) {
vq = dev->vqs[i];
vq->heads = NULL;
vq->dev = dev;
mutex_init(&vq->mutex);
+ spin_lock_init(&vq->mmu_lock);
vhost_vq_reset(dev, vq);
if (vq->handle_kick)
vhost_poll_init(&vq->poll, vq->handle_kick,
if (err)
goto err_cgroup;
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ err = mmu_notifier_register(&dev->mmu_notifier, dev->mm);
+ if (err)
+ goto err_mmu_notifier;
+ #endif
+
return 0;
+
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ err_mmu_notifier:
+ vhost_dev_free_iovecs(dev);
+ #endif
err_cgroup:
kthread_stop(worker);
dev->worker = NULL;
spin_unlock(&dev->iotlb_lock);
}
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ static void vhost_setup_uaddr(struct vhost_virtqueue *vq,
+ int index, unsigned long uaddr,
+ size_t size, bool write)
+ {
+ struct vhost_uaddr *addr = &vq->uaddrs[index];
+
+ addr->uaddr = uaddr;
+ addr->size = size;
+ addr->write = write;
+ }
+
+ static void vhost_setup_vq_uaddr(struct vhost_virtqueue *vq)
+ {
+ vhost_setup_uaddr(vq, VHOST_ADDR_DESC,
+ (unsigned long)vq->desc,
+ vhost_get_desc_size(vq, vq->num),
+ false);
+ vhost_setup_uaddr(vq, VHOST_ADDR_AVAIL,
+ (unsigned long)vq->avail,
+ vhost_get_avail_size(vq, vq->num),
+ false);
+ vhost_setup_uaddr(vq, VHOST_ADDR_USED,
+ (unsigned long)vq->used,
+ vhost_get_used_size(vq, vq->num),
+ true);
+ }
+
+ static int vhost_map_prefetch(struct vhost_virtqueue *vq,
+ int index)
+ {
+ struct vhost_map *map;
+ struct vhost_uaddr *uaddr = &vq->uaddrs[index];
+ struct page **pages;
+ int npages = DIV_ROUND_UP(uaddr->size, PAGE_SIZE);
+ int npinned;
+ void *vaddr, *v;
+ int err;
+ int i;
+
+ spin_lock(&vq->mmu_lock);
+
+ err = -EFAULT;
+ if (vq->invalidate_count)
+ goto err;
+
+ err = -ENOMEM;
+ map = kmalloc(sizeof(*map), GFP_ATOMIC);
+ if (!map)
+ goto err;
+
+ pages = kmalloc_array(npages, sizeof(struct page *), GFP_ATOMIC);
+ if (!pages)
+ goto err_pages;
+
+ err = EFAULT;
+ npinned = __get_user_pages_fast(uaddr->uaddr, npages,
+ uaddr->write, pages);
+ if (npinned > 0)
+ release_pages(pages, npinned);
+ if (npinned != npages)
+ goto err_gup;
+
+ for (i = 0; i < npinned; i++)
+ if (PageHighMem(pages[i]))
+ goto err_gup;
+
+ vaddr = v = page_address(pages[0]);
+
+ /* For simplicity, fallback to userspace address if VA is not
+ * contigious.
+ */
+ for (i = 1; i < npinned; i++) {
+ v += PAGE_SIZE;
+ if (v != page_address(pages[i]))
+ goto err_gup;
+ }
+
+ map->addr = vaddr + (uaddr->uaddr & (PAGE_SIZE - 1));
+ map->npages = npages;
+ map->pages = pages;
+
+ rcu_assign_pointer(vq->maps[index], map);
+ /* No need for a synchronize_rcu(). This function should be
+ * called by dev->worker so we are serialized with all
+ * readers.
+ */
+ spin_unlock(&vq->mmu_lock);
+
+ return 0;
+
+ err_gup:
+ kfree(pages);
+ err_pages:
+ kfree(map);
+ err:
+ spin_unlock(&vq->mmu_lock);
+ return err;
+ }
+ #endif
+
void vhost_dev_cleanup(struct vhost_dev *dev)
{
int i;
kthread_stop(dev->worker);
dev->worker = NULL;
}
- if (dev->mm)
+ if (dev->mm) {
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ mmu_notifier_unregister(&dev->mmu_notifier, dev->mm);
+ #endif
mmput(dev->mm);
+ }
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ for (i = 0; i < dev->nvqs; i++)
+ vhost_uninit_vq_maps(dev->vqs[i]);
+ #endif
dev->mm = NULL;
}
EXPORT_SYMBOL_GPL(vhost_dev_cleanup);
ret; \
})
+ static inline int vhost_put_avail_event(struct vhost_virtqueue *vq)
+ {
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ struct vhost_map *map;
+ struct vring_used *used;
+
+ if (!vq->iotlb) {
+ rcu_read_lock();
+
+ map = rcu_dereference(vq->maps[VHOST_ADDR_USED]);
+ if (likely(map)) {
+ used = map->addr;
+ *((__virtio16 *)&used->ring[vq->num]) =
+ cpu_to_vhost16(vq, vq->avail_idx);
+ rcu_read_unlock();
+ return 0;
+ }
+
+ rcu_read_unlock();
+ }
+ #endif
+
+ return vhost_put_user(vq, cpu_to_vhost16(vq, vq->avail_idx),
+ vhost_avail_event(vq));
+ }
+
+ static inline int vhost_put_used(struct vhost_virtqueue *vq,
+ struct vring_used_elem *head, int idx,
+ int count)
+ {
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ struct vhost_map *map;
+ struct vring_used *used;
+ size_t size;
+
+ if (!vq->iotlb) {
+ rcu_read_lock();
+
+ map = rcu_dereference(vq->maps[VHOST_ADDR_USED]);
+ if (likely(map)) {
+ used = map->addr;
+ size = count * sizeof(*head);
+ memcpy(used->ring + idx, head, size);
+ rcu_read_unlock();
+ return 0;
+ }
+
+ rcu_read_unlock();
+ }
+ #endif
+
+ return vhost_copy_to_user(vq, vq->used->ring + idx, head,
+ count * sizeof(*head));
+ }
+
+ static inline int vhost_put_used_flags(struct vhost_virtqueue *vq)
+
+ {
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ struct vhost_map *map;
+ struct vring_used *used;
+
+ if (!vq->iotlb) {
+ rcu_read_lock();
+
+ map = rcu_dereference(vq->maps[VHOST_ADDR_USED]);
+ if (likely(map)) {
+ used = map->addr;
+ used->flags = cpu_to_vhost16(vq, vq->used_flags);
+ rcu_read_unlock();
+ return 0;
+ }
+
+ rcu_read_unlock();
+ }
+ #endif
+
+ return vhost_put_user(vq, cpu_to_vhost16(vq, vq->used_flags),
+ &vq->used->flags);
+ }
+
+ static inline int vhost_put_used_idx(struct vhost_virtqueue *vq)
+
+ {
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ struct vhost_map *map;
+ struct vring_used *used;
+
+ if (!vq->iotlb) {
+ rcu_read_lock();
+
+ map = rcu_dereference(vq->maps[VHOST_ADDR_USED]);
+ if (likely(map)) {
+ used = map->addr;
+ used->idx = cpu_to_vhost16(vq, vq->last_used_idx);
+ rcu_read_unlock();
+ return 0;
+ }
+
+ rcu_read_unlock();
+ }
+ #endif
+
+ return vhost_put_user(vq, cpu_to_vhost16(vq, vq->last_used_idx),
+ &vq->used->idx);
+ }
+
#define vhost_get_user(vq, x, ptr, type) \
({ \
int ret; \
mutex_unlock(&d->vqs[i]->mutex);
}
+ static inline int vhost_get_avail_idx(struct vhost_virtqueue *vq,
+ __virtio16 *idx)
+ {
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ struct vhost_map *map;
+ struct vring_avail *avail;
+
+ if (!vq->iotlb) {
+ rcu_read_lock();
+
+ map = rcu_dereference(vq->maps[VHOST_ADDR_AVAIL]);
+ if (likely(map)) {
+ avail = map->addr;
+ *idx = avail->idx;
+ rcu_read_unlock();
+ return 0;
+ }
+
+ rcu_read_unlock();
+ }
+ #endif
+
+ return vhost_get_avail(vq, *idx, &vq->avail->idx);
+ }
+
+ static inline int vhost_get_avail_head(struct vhost_virtqueue *vq,
+ __virtio16 *head, int idx)
+ {
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ struct vhost_map *map;
+ struct vring_avail *avail;
+
+ if (!vq->iotlb) {
+ rcu_read_lock();
+
+ map = rcu_dereference(vq->maps[VHOST_ADDR_AVAIL]);
+ if (likely(map)) {
+ avail = map->addr;
+ *head = avail->ring[idx & (vq->num - 1)];
+ rcu_read_unlock();
+ return 0;
+ }
+
+ rcu_read_unlock();
+ }
+ #endif
+
+ return vhost_get_avail(vq, *head,
+ &vq->avail->ring[idx & (vq->num - 1)]);
+ }
+
+ static inline int vhost_get_avail_flags(struct vhost_virtqueue *vq,
+ __virtio16 *flags)
+ {
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ struct vhost_map *map;
+ struct vring_avail *avail;
+
+ if (!vq->iotlb) {
+ rcu_read_lock();
+
+ map = rcu_dereference(vq->maps[VHOST_ADDR_AVAIL]);
+ if (likely(map)) {
+ avail = map->addr;
+ *flags = avail->flags;
+ rcu_read_unlock();
+ return 0;
+ }
+
+ rcu_read_unlock();
+ }
+ #endif
+
+ return vhost_get_avail(vq, *flags, &vq->avail->flags);
+ }
+
+ static inline int vhost_get_used_event(struct vhost_virtqueue *vq,
+ __virtio16 *event)
+ {
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ struct vhost_map *map;
+ struct vring_avail *avail;
+
+ if (!vq->iotlb) {
+ rcu_read_lock();
+ map = rcu_dereference(vq->maps[VHOST_ADDR_AVAIL]);
+ if (likely(map)) {
+ avail = map->addr;
+ *event = (__virtio16)avail->ring[vq->num];
+ rcu_read_unlock();
+ return 0;
+ }
+ rcu_read_unlock();
+ }
+ #endif
+
+ return vhost_get_avail(vq, *event, vhost_used_event(vq));
+ }
+
+ static inline int vhost_get_used_idx(struct vhost_virtqueue *vq,
+ __virtio16 *idx)
+ {
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ struct vhost_map *map;
+ struct vring_used *used;
+
+ if (!vq->iotlb) {
+ rcu_read_lock();
+
+ map = rcu_dereference(vq->maps[VHOST_ADDR_USED]);
+ if (likely(map)) {
+ used = map->addr;
+ *idx = used->idx;
+ rcu_read_unlock();
+ return 0;
+ }
+
+ rcu_read_unlock();
+ }
+ #endif
+
+ return vhost_get_used(vq, *idx, &vq->used->idx);
+ }
+
+ static inline int vhost_get_desc(struct vhost_virtqueue *vq,
+ struct vring_desc *desc, int idx)
+ {
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ struct vhost_map *map;
+ struct vring_desc *d;
+
+ if (!vq->iotlb) {
+ rcu_read_lock();
+
+ map = rcu_dereference(vq->maps[VHOST_ADDR_DESC]);
+ if (likely(map)) {
+ d = map->addr;
+ *desc = *(d + idx);
+ rcu_read_unlock();
+ return 0;
+ }
+
+ rcu_read_unlock();
+ }
+ #endif
+
+ return vhost_copy_from_user(vq, desc, vq->desc + idx, sizeof(*desc));
+ }
+
static int vhost_new_umem_range(struct vhost_umem *umem,
u64 start, u64 size, u64 end,
u64 userspace_addr, int perm)
struct vring_used __user *used)
{
- size_t s __maybe_unused = vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX) ? 2 : 0;
-
- return access_ok(desc, num * sizeof *desc) &&
- access_ok(avail,
- sizeof *avail + num * sizeof *avail->ring + s) &&
- access_ok(used,
- sizeof *used + num * sizeof *used->ring + s);
+ return access_ok(desc, vhost_get_desc_size(vq, num)) &&
+ access_ok(avail, vhost_get_avail_size(vq, num)) &&
+ access_ok(used, vhost_get_used_size(vq, num));
}
static void vhost_vq_meta_update(struct vhost_virtqueue *vq,
return true;
}
- int vq_iotlb_prefetch(struct vhost_virtqueue *vq)
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ static void vhost_vq_map_prefetch(struct vhost_virtqueue *vq)
+ {
+ struct vhost_map __rcu *map;
+ int i;
+
+ for (i = 0; i < VHOST_NUM_ADDRS; i++) {
+ rcu_read_lock();
+ map = rcu_dereference(vq->maps[i]);
+ rcu_read_unlock();
+ if (unlikely(!map))
+ vhost_map_prefetch(vq, i);
+ }
+ }
+ #endif
+
+ int vq_meta_prefetch(struct vhost_virtqueue *vq)
{
- size_t s = vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX) ? 2 : 0;
unsigned int num = vq->num;
- if (!vq->iotlb)
+ if (!vq->iotlb) {
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ vhost_vq_map_prefetch(vq);
+ #endif
return 1;
+ }
return iotlb_access_ok(vq, VHOST_ACCESS_RO, (u64)(uintptr_t)vq->desc,
- num * sizeof(*vq->desc), VHOST_ADDR_DESC) &&
+ vhost_get_desc_size(vq, num), VHOST_ADDR_DESC) &&
iotlb_access_ok(vq, VHOST_ACCESS_RO, (u64)(uintptr_t)vq->avail,
- sizeof *vq->avail +
- num * sizeof(*vq->avail->ring) + s,
+ vhost_get_avail_size(vq, num),
VHOST_ADDR_AVAIL) &&
iotlb_access_ok(vq, VHOST_ACCESS_WO, (u64)(uintptr_t)vq->used,
- sizeof *vq->used +
- num * sizeof(*vq->used->ring) + s,
- VHOST_ADDR_USED);
+ vhost_get_used_size(vq, num), VHOST_ADDR_USED);
}
- EXPORT_SYMBOL_GPL(vq_iotlb_prefetch);
+ EXPORT_SYMBOL_GPL(vq_meta_prefetch);
/* Can we log writes? */
/* Caller should have device mutex but not vq mutex */
static bool vq_log_access_ok(struct vhost_virtqueue *vq,
void __user *log_base)
{
- size_t s = vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX) ? 2 : 0;
-
return vq_memory_access_ok(log_base, vq->umem,
vhost_has_feature(vq, VHOST_F_LOG_ALL)) &&
(!vq->log_used || log_access_ok(log_base, vq->log_addr,
- sizeof *vq->used +
- vq->num * sizeof *vq->used->ring + s));
+ vhost_get_used_size(vq, vq->num)));
}
/* Can we start vq? */
return -EFAULT;
}
+ static long vhost_vring_set_num(struct vhost_dev *d,
+ struct vhost_virtqueue *vq,
+ void __user *argp)
+ {
+ struct vhost_vring_state s;
+
+ /* Resizing ring with an active backend?
+ * You don't want to do that. */
+ if (vq->private_data)
+ return -EBUSY;
+
+ if (copy_from_user(&s, argp, sizeof s))
+ return -EFAULT;
+
+ if (!s.num || s.num > 0xffff || (s.num & (s.num - 1)))
+ return -EINVAL;
+ vq->num = s.num;
+
+ return 0;
+ }
+
+ static long vhost_vring_set_addr(struct vhost_dev *d,
+ struct vhost_virtqueue *vq,
+ void __user *argp)
+ {
+ struct vhost_vring_addr a;
+
+ if (copy_from_user(&a, argp, sizeof a))
+ return -EFAULT;
+ if (a.flags & ~(0x1 << VHOST_VRING_F_LOG))
+ return -EOPNOTSUPP;
+
+ /* For 32bit, verify that the top 32bits of the user
+ data are set to zero. */
+ if ((u64)(unsigned long)a.desc_user_addr != a.desc_user_addr ||
+ (u64)(unsigned long)a.used_user_addr != a.used_user_addr ||
+ (u64)(unsigned long)a.avail_user_addr != a.avail_user_addr)
+ return -EFAULT;
+
+ /* Make sure it's safe to cast pointers to vring types. */
+ BUILD_BUG_ON(__alignof__ *vq->avail > VRING_AVAIL_ALIGN_SIZE);
+ BUILD_BUG_ON(__alignof__ *vq->used > VRING_USED_ALIGN_SIZE);
+ if ((a.avail_user_addr & (VRING_AVAIL_ALIGN_SIZE - 1)) ||
+ (a.used_user_addr & (VRING_USED_ALIGN_SIZE - 1)) ||
+ (a.log_guest_addr & (VRING_USED_ALIGN_SIZE - 1)))
+ return -EINVAL;
+
+ /* We only verify access here if backend is configured.
+ * If it is not, we don't as size might not have been setup.
+ * We will verify when backend is configured. */
+ if (vq->private_data) {
+ if (!vq_access_ok(vq, vq->num,
+ (void __user *)(unsigned long)a.desc_user_addr,
+ (void __user *)(unsigned long)a.avail_user_addr,
+ (void __user *)(unsigned long)a.used_user_addr))
+ return -EINVAL;
+
+ /* Also validate log access for used ring if enabled. */
+ if ((a.flags & (0x1 << VHOST_VRING_F_LOG)) &&
+ !log_access_ok(vq->log_base, a.log_guest_addr,
+ sizeof *vq->used +
+ vq->num * sizeof *vq->used->ring))
+ return -EINVAL;
+ }
+
+ vq->log_used = !!(a.flags & (0x1 << VHOST_VRING_F_LOG));
+ vq->desc = (void __user *)(unsigned long)a.desc_user_addr;
+ vq->avail = (void __user *)(unsigned long)a.avail_user_addr;
+ vq->log_addr = a.log_guest_addr;
+ vq->used = (void __user *)(unsigned long)a.used_user_addr;
+
+ return 0;
+ }
+
+ static long vhost_vring_set_num_addr(struct vhost_dev *d,
+ struct vhost_virtqueue *vq,
+ unsigned int ioctl,
+ void __user *argp)
+ {
+ long r;
+
+ mutex_lock(&vq->mutex);
+
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ /* Unregister MMU notifer to allow invalidation callback
+ * can access vq->uaddrs[] without holding a lock.
+ */
+ if (d->mm)
+ mmu_notifier_unregister(&d->mmu_notifier, d->mm);
+
+ vhost_uninit_vq_maps(vq);
+ #endif
+
+ switch (ioctl) {
+ case VHOST_SET_VRING_NUM:
+ r = vhost_vring_set_num(d, vq, argp);
+ break;
+ case VHOST_SET_VRING_ADDR:
+ r = vhost_vring_set_addr(d, vq, argp);
+ break;
+ default:
+ BUG();
+ }
+
+ #if VHOST_ARCH_CAN_ACCEL_UACCESS
+ vhost_setup_vq_uaddr(vq);
+
+ if (d->mm)
+ mmu_notifier_register(&d->mmu_notifier, d->mm);
+ #endif
+
+ mutex_unlock(&vq->mutex);
+
+ return r;
+ }
long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp)
{
struct file *eventfp, *filep = NULL;
struct vhost_virtqueue *vq;
struct vhost_vring_state s;
struct vhost_vring_file f;
- struct vhost_vring_addr a;
u32 idx;
long r;
idx = array_index_nospec(idx, d->nvqs);
vq = d->vqs[idx];
+ if (ioctl == VHOST_SET_VRING_NUM ||
+ ioctl == VHOST_SET_VRING_ADDR) {
+ return vhost_vring_set_num_addr(d, vq, ioctl, argp);
+ }
+
mutex_lock(&vq->mutex);
switch (ioctl) {
- case VHOST_SET_VRING_NUM:
- /* Resizing ring with an active backend?
- * You don't want to do that. */
- if (vq->private_data) {
- r = -EBUSY;
- break;
- }
- if (copy_from_user(&s, argp, sizeof s)) {
- r = -EFAULT;
- break;
- }
- if (!s.num || s.num > 0xffff || (s.num & (s.num - 1))) {
- r = -EINVAL;
- break;
- }
- vq->num = s.num;
- break;
case VHOST_SET_VRING_BASE:
/* Moving base with an active backend?
* You don't want to do that. */
if (copy_to_user(argp, &s, sizeof s))
r = -EFAULT;
break;
- case VHOST_SET_VRING_ADDR:
- if (copy_from_user(&a, argp, sizeof a)) {
- r = -EFAULT;
- break;
- }
- if (a.flags & ~(0x1 << VHOST_VRING_F_LOG)) {
- r = -EOPNOTSUPP;
- break;
- }
- /* For 32bit, verify that the top 32bits of the user
- data are set to zero. */
- if ((u64)(unsigned long)a.desc_user_addr != a.desc_user_addr ||
- (u64)(unsigned long)a.used_user_addr != a.used_user_addr ||
- (u64)(unsigned long)a.avail_user_addr != a.avail_user_addr) {
- r = -EFAULT;
- break;
- }
-
- /* Make sure it's safe to cast pointers to vring types. */
- BUILD_BUG_ON(__alignof__ *vq->avail > VRING_AVAIL_ALIGN_SIZE);
- BUILD_BUG_ON(__alignof__ *vq->used > VRING_USED_ALIGN_SIZE);
- if ((a.avail_user_addr & (VRING_AVAIL_ALIGN_SIZE - 1)) ||
- (a.used_user_addr & (VRING_USED_ALIGN_SIZE - 1)) ||
- (a.log_guest_addr & (VRING_USED_ALIGN_SIZE - 1))) {
- r = -EINVAL;
- break;
- }
-
- /* We only verify access here if backend is configured.
- * If it is not, we don't as size might not have been setup.
- * We will verify when backend is configured. */
- if (vq->private_data) {
- if (!vq_access_ok(vq, vq->num,
- (void __user *)(unsigned long)a.desc_user_addr,
- (void __user *)(unsigned long)a.avail_user_addr,
- (void __user *)(unsigned long)a.used_user_addr)) {
- r = -EINVAL;
- break;
- }
-
- /* Also validate log access for used ring if enabled. */
- if ((a.flags & (0x1 << VHOST_VRING_F_LOG)) &&
- !log_access_ok(vq->log_base, a.log_guest_addr,
- sizeof *vq->used +
- vq->num * sizeof *vq->used->ring)) {
- r = -EINVAL;
- break;
- }
- }
-
- vq->log_used = !!(a.flags & (0x1 << VHOST_VRING_F_LOG));
- vq->desc = (void __user *)(unsigned long)a.desc_user_addr;
- vq->avail = (void __user *)(unsigned long)a.avail_user_addr;
- vq->log_addr = a.log_guest_addr;
- vq->used = (void __user *)(unsigned long)a.used_user_addr;
- break;
case VHOST_SET_VRING_KICK:
if (copy_from_user(&f, argp, sizeof f)) {
r = -EFAULT;
/* TODO: This is really inefficient. We need something like get_user()
* (instruction directly accesses the data, with an exception table entry
- * returning -EFAULT). See Documentation/x86/exception-tables.txt.
+ * returning -EFAULT). See Documentation/x86/exception-tables.rst.
*/
static int set_bit_to_user(int nr, void __user *addr)
{
static int vhost_update_used_flags(struct vhost_virtqueue *vq)
{
void __user *used;
- if (vhost_put_user(vq, cpu_to_vhost16(vq, vq->used_flags),
- &vq->used->flags) < 0)
+ if (vhost_put_used_flags(vq))
return -EFAULT;
if (unlikely(vq->log_used)) {
/* Make sure the flag is seen before log. */
static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event)
{
- if (vhost_put_user(vq, cpu_to_vhost16(vq, vq->avail_idx),
- vhost_avail_event(vq)))
+ if (vhost_put_avail_event(vq))
return -EFAULT;
if (unlikely(vq->log_used)) {
void __user *used;
r = -EFAULT;
goto err;
}
- r = vhost_get_used(vq, last_used_idx, &vq->used->idx);
+ r = vhost_get_used_idx(vq, &last_used_idx);
if (r) {
vq_err(vq, "Can't access used idx at %p\n",
&vq->used->idx);
last_avail_idx = vq->last_avail_idx;
if (vq->avail_idx == vq->last_avail_idx) {
- if (unlikely(vhost_get_avail(vq, avail_idx, &vq->avail->idx))) {
+ if (unlikely(vhost_get_avail_idx(vq, &avail_idx))) {
vq_err(vq, "Failed to access avail idx at %p\n",
&vq->avail->idx);
return -EFAULT;
/* Grab the next descriptor number they're advertising, and increment
* the index we've seen. */
- if (unlikely(vhost_get_avail(vq, ring_head,
- &vq->avail->ring[last_avail_idx & (vq->num - 1)]))) {
+ if (unlikely(vhost_get_avail_head(vq, &ring_head, last_avail_idx))) {
vq_err(vq, "Failed to read head: idx %d address %p\n",
last_avail_idx,
&vq->avail->ring[last_avail_idx % vq->num]);
i, vq->num, head);
return -EINVAL;
}
- ret = vhost_copy_from_user(vq, &desc, vq->desc + i,
- sizeof desc);
+ ret = vhost_get_desc(vq, &desc, i);
if (unlikely(ret)) {
vq_err(vq, "Failed to get descriptor: idx %d addr %p\n",
i, vq->desc + i);
start = vq->last_used_idx & (vq->num - 1);
used = vq->used->ring + start;
- if (count == 1) {
- if (vhost_put_user(vq, heads[0].id, &used->id)) {
- vq_err(vq, "Failed to write used id");
- return -EFAULT;
- }
- if (vhost_put_user(vq, heads[0].len, &used->len)) {
- vq_err(vq, "Failed to write used len");
- return -EFAULT;
- }
- } else if (vhost_copy_to_user(vq, used, heads, count * sizeof *used)) {
+ if (vhost_put_used(vq, heads, start, count)) {
vq_err(vq, "Failed to write used");
return -EFAULT;
}
/* Make sure buffer is written before we update index. */
smp_wmb();
- if (vhost_put_user(vq, cpu_to_vhost16(vq, vq->last_used_idx),
- &vq->used->idx)) {
+ if (vhost_put_used_idx(vq)) {
vq_err(vq, "Failed to increment used idx");
return -EFAULT;
}
if (!vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX)) {
__virtio16 flags;
- if (vhost_get_avail(vq, flags, &vq->avail->flags)) {
+ if (vhost_get_avail_flags(vq, &flags)) {
vq_err(vq, "Failed to get flags");
return true;
}
if (unlikely(!v))
return true;
- if (vhost_get_avail(vq, event, vhost_used_event(vq))) {
+ if (vhost_get_used_event(vq, &event)) {
vq_err(vq, "Failed to get used event idx");
return true;
}
if (vq->avail_idx != vq->last_avail_idx)
return false;
- r = vhost_get_avail(vq, avail_idx, &vq->avail->idx);
+ r = vhost_get_avail_idx(vq, &avail_idx);
if (unlikely(r))
return false;
vq->avail_idx = vhost16_to_cpu(vq, avail_idx);
/* They could have slipped one in as we were doing that: make
* sure it's written, then check again. */
smp_mb();
- r = vhost_get_avail(vq, avail_idx, &vq->avail->idx);
+ r = vhost_get_avail_idx(vq, &avail_idx);
if (r) {
vq_err(vq, "Failed to check avail idx at %p: %d\n",
&vq->avail->idx, r);