or does something very odd once a month document it.
PLEASE remember that submissions must be made under the terms
--- --- of the OSDL certificate of contribution and should include a
--- --- Signed-off-by: line. The current version of this "Developer's
--- --- Certificate of Origin" (DCO) is listed in the file
+++ +++ of the Linux Foundation certificate of contribution and should
+++ +++ include a Signed-off-by: line. The current version of this
+++ +++ "Developer's Certificate of Origin" (DCO) is listed in the file
Documentation/SubmittingPatches.
6. Make sure you have the right to send any changes you make. If you
S: Maintained
F: drivers/mailbox/mailbox-altera.c
+ ALTERA PIO DRIVER
+ M: Tien Hock Loh <thloh@altera.com>
+ L: linux-gpio@vger.kernel.org
+ S: Maintained
+ F: drivers/gpio/gpio-altera.c
+
ALTERA TRIPLE SPEED ETHERNET DRIVER
M: Vince Bridgers <vbridger@opensource.altera.com>
L: netdev@vger.kernel.org
F: include/linux/amd-iommu.h
AMD KFD
- M: Oded Gabbay <oded.gabbay@amd.com>
- L: dri-devel@lists.freedesktop.org
- T: git git://people.freedesktop.org/~gabbayo/linux.git
- S: Supported
- F: drivers/gpu/drm/amd/amdkfd/
+ M: Oded Gabbay <oded.gabbay@amd.com>
+ L: dri-devel@lists.freedesktop.org
+ T: git git://people.freedesktop.org/~gabbayo/linux.git
+ S: Supported
+ F: drivers/gpu/drm/amd/amdkfd/
F: drivers/gpu/drm/amd/include/cik_structs.h
F: drivers/gpu/drm/amd/include/kgd_kfd_interface.h
- F: drivers/gpu/drm/radeon/radeon_kfd.c
- F: drivers/gpu/drm/radeon/radeon_kfd.h
- F: include/uapi/linux/kfd_ioctl.h
+ F: drivers/gpu/drm/radeon/radeon_kfd.c
+ F: drivers/gpu/drm/radeon/radeon_kfd.h
+ F: include/uapi/linux/kfd_ioctl.h
AMD MICROCODE UPDATE SUPPORT
- M: Andreas Herrmann <herrmann.der.user@googlemail.com>
- L: amd64-microcode@amd64.org
+ M: Borislav Petkov <bp@alien8.de>
S: Maintained
F: arch/x86/kernel/cpu/microcode/amd*
ANDROID DRIVERS
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- M: Arve Hjønnevåg <arve@android.com>
+ M: Arve Hjønnevåg <arve@android.com>
M: Riley Andrews <riandrews@android.com>
T: git git://git.kernel.org/pub/scm/linux/kernel/gregkh/staging.git
L: devel@driverdev.osuosl.org
F: drivers/media/rc/meson-ir.c
N: meson[x68]
+ ARM/Annapurna Labs ALPINE ARCHITECTURE
+ M: Tsahee Zidenberg <tsahee@annapurnalabs.com>
+ S: Maintained
+ F: arch/arm/mach-alpine/
+
ARM/ATMEL AT91RM9200 AND AT91SAM ARM ARCHITECTURES
- - -M: Andrew Victor <linux@maxim.org.za>
M: Nicolas Ferre <nicolas.ferre@atmel.com>
+ + +M: Alexandre Belloni <alexandre.belloni@free-electrons.com>
M: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
- - -W: http://maxim.org.za/at91_26.html
W: http://www.linux4sam.org
S: Supported
F: arch/arm/mach-at91/
M: Mathieu Poirier <mathieu.poirier@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
- F: drivers/coresight/*
+ F: drivers/hwtracing/coresight/*
F: Documentation/trace/coresight.txt
F: Documentation/devicetree/bindings/arm/coresight.txt
F: Documentation/ABI/testing/sysfs-bus-coresight-devices-*
ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE
M: Hans Ulli Kroll <ulli.kroll@googlemail.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-- - -T: git git://git.berlios.de/gemini-board
++ + +T: git git://github.com/ulli-kroll/linux.git
S: Maintained
F: arch/arm/mach-gemini/
F: drivers/clocksource/timer-atlas7.c
N: [^a-z]sirf
+ + +ARM/CONEXANT DIGICOLOR MACHINE SUPPORT
+ + +M: Baruch Siach <baruch@tkos.co.il>
+ + +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+ + +S: Maintained
+ + +N: digicolor
+ + +
ARM/EBSA110 MACHINE SUPPORT
M: Russell King <linux@arm.linux.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
F: arch/arm/boot/dts/imx*
F: arch/arm/configs/imx*_defconfig
+ ARM/FREESCALE VYBRID ARM ARCHITECTURE
+ M: Shawn Guo <shawn.guo@linaro.org>
+ M: Sascha Hauer <kernel@pengutronix.de>
+ R: Stefan Agner <stefan@agner.ch>
+ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+ S: Maintained
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
+ F: arch/arm/mach-imx/*vf610*
+ F: arch/arm/boot/dts/vf*
+
ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
M: Lennert Buytenhek <kernel@wantstofly.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
M: Philipp Zabel <philipp.zabel@gmail.com>
S: Maintained
-- - -ARM/Marvell Armada 370 and Armada XP SOC support
++ + +ARM/Marvell Kirkwood and Armada 370, 375, 38x, XP SOC support
M: Jason Cooper <jason@lakedaemon.net>
M: Andrew Lunn <andrew@lunn.ch>
M: Gregory Clement <gregory.clement@free-electrons.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-mvebu/
- F: drivers/rtc/armada38x-rtc
+ F: drivers/rtc/rtc-armada38x.c
++ + +F: arch/arm/boot/dts/armada*
++ + +F: arch/arm/boot/dts/kirkwood*
++ + +
ARM/Marvell Berlin SoC support
M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-berlin/
++ + +F: arch/arm/boot/dts/berlin*
++ + +
ARM/Marvell Dove/MV78xx0/Orion SOC support
M: Jason Cooper <jason@lakedaemon.net>
M: Andrew Lunn <andrew@lunn.ch>
M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ M: Gregory Clement <gregory.clement@free-electrons.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-dove/
F: arch/arm/mach-mv78xx0/
F: arch/arm/mach-orion5x/
F: arch/arm/plat-orion/
++ + +F: arch/arm/boot/dts/dove*
++ + +F: arch/arm/boot/dts/orion5x*
++ + +
ARM/Orion SoC/Technologic Systems TS-78xx platform support
M: Alexander Clouter <alex@digriz.org.uk>
ARM/Mediatek SoC support
M: Matthias Brugger <matthias.bgg@gmail.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+ L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/boot/dts/mt6*
F: arch/arm/boot/dts/mt8*
W: http://wiki.openmoko.org/wiki/Neo_FreeRunner
S: Supported
- ARM/QUALCOMM MSM MACHINE SUPPORT
- M: David Brown <davidb@codeaurora.org>
- M: Daniel Walker <dwalker@fifo99.com>
- M: Bryan Huntsman <bryanh@codeaurora.org>
- L: linux-arm-msm@vger.kernel.org
- F: arch/arm/mach-msm/
- F: drivers/video/fbdev/msm/
- F: drivers/mmc/host/msm_sdcc.c
- F: drivers/mmc/host/msm_sdcc.h
- F: drivers/tty/serial/msm_serial.h
- F: drivers/tty/serial/msm_serial.c
- F: drivers/*/pm8???-*
- F: drivers/mfd/ssbi.c
- T: git git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git
- S: Maintained
-
ARM/TOSA MACHINE SUPPORT
M: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
M: Dirk Opfer <dirk@opfer-online.de>
S: Maintained
F: arch/arm/mach-qcom/
F: drivers/soc/qcom/
+ F: drivers/tty/serial/msm_serial.h
+ F: drivers/tty/serial/msm_serial.c
+ F: drivers/*/pm8???-*
+ F: drivers/mfd/ssbi.c
+ F: drivers/firmware/qcom_scm.c
T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git
ARM/RADISYS ENP2611 MACHINE SUPPORT
F: drivers/*/*rockchip*
F: drivers/*/*/*rockchip*
F: sound/soc/rockchip/
+ N: rockchip
ARM/SAMSUNG EXYNOS ARM ARCHITECTURES
M: Kukjin Kim <kgene@kernel.org>
++ + +M: Krzysztof Kozlowski <k.kozlowski@samsung.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/boot/dts/r7s*
F: arch/arm/boot/dts/r8a*
F: arch/arm/boot/dts/sh*
- F: arch/arm/configs/ape6evm_defconfig
F: arch/arm/configs/armadillo800eva_defconfig
F: arch/arm/configs/bockw_defconfig
F: arch/arm/configs/kzm9g_defconfig
- F: arch/arm/configs/mackerel_defconfig
F: arch/arm/configs/marzen_defconfig
F: arch/arm/configs/shmobile_defconfig
F: arch/arm/include/debug/renesas-scif.S
M: Dinh Nguyen <dinguyen@opensource.altera.com>
S: Maintained
F: arch/arm/mach-socfpga/
+ + +F: arch/arm/boot/dts/socfpga*
+ + +F: arch/arm/configs/socfpga_defconfig
W: http://www.rocketboards.org
- - -T: git://git.rocketboards.org/linux-socfpga.git
- - -T: git://git.rocketboards.org/linux-socfpga-next.git
+ + +T: git git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git
ARM/SOCFPGA CLOCK FRAMEWORK SUPPORT
M: Dinh Nguyen <dinguyen@opensource.altera.com>
F: drivers/i2c/busses/i2c-st.c
F: drivers/media/rc/st_rc.c
F: drivers/mmc/host/sdhci-st.c
+ F: drivers/phy/phy-miphy28lp.c
+ F: drivers/phy/phy-miphy365x.c
F: drivers/phy/phy-stih407-usb.c
F: drivers/phy/phy-stih41x-usb.c
F: drivers/pinctrl/pinctrl-st.c
F: drivers/mmc/host/sdhci-of-arasan.c
F: drivers/edac/synopsys_edac.c
-- ----ARM SMMU DRIVER
++ ++++ARM SMMU DRIVERS
M: Will Deacon <will.deacon@arm.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/iommu/arm-smmu.c
++ ++++F: drivers/iommu/arm-smmu-v3.c
F: drivers/iommu/io-pgtable-arm.c
ARM64 PORT (AARCH64 ARCHITECTURE)
F: include/linux/platform_data/at24.h
ATA OVER ETHERNET (AOE) DRIVER
- M: "Ed L. Cashin" <ecashin@coraid.com>
- W: http://support.coraid.com/support/linux
+ M: "Ed L. Cashin" <ed.cashin@acm.org>
+ W: http://www.openaoe.org/
S: Supported
F: Documentation/aoe/
F: drivers/block/aoe/
F: drivers/net/ethernet/atheros/
ATM
- M: Chas Williams <chas@cmf.nrl.navy.mil>
+ M: Chas Williams <3chas3@gmail.com>
L: linux-atm-general@lists.sourceforge.net (moderated for non-subscribers)
L: netdev@vger.kernel.org
W: http://linux-atm.sourceforge.net
F: drivers/tty/serial/atmel_serial.c
ATMEL Audio ALSA driver
- M: Bo Shen <voice.shen@atmel.com>
+ M: Nicolas Ferre <nicolas.ferre@atmel.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Supported
F: sound/soc/atmel
F: drivers/spi/spi-atmel.*
ATMEL SSC DRIVER
- M: Bo Shen <voice.shen@atmel.com>
+ M: Nicolas Ferre <nicolas.ferre@atmel.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Supported
F: drivers/misc/atmel-ssc.c
F: drivers/media/radio/radio-aztech*
B43 WIRELESS DRIVER
- M: Stefano Brivio <stefano.brivio@polimi.it>
L: linux-wireless@vger.kernel.org
L: b43-dev@lists.infradead.org
W: http://wireless.kernel.org/en/users/Drivers/b43
- S: Maintained
+ S: Odd Fixes
F: drivers/net/wireless/b43/
B43LEGACY WIRELESS DRIVER
M: Larry Finger <Larry.Finger@lwfinger.net>
- M: Stefano Brivio <stefano.brivio@polimi.it>
L: linux-wireless@vger.kernel.org
L: b43-dev@lists.infradead.org
W: http://wireless.kernel.org/en/users/Drivers/b43
F: drivers/net/wireless/b43legacy/
BACKLIGHT CLASS/SUBSYSTEM
-- - -M: Jingoo Han <jg1.han@samsung.com>
++ + +M: Jingoo Han <jingoohan1@gmail.com>
M: Lee Jones <lee.jones@linaro.org>
S: Maintained
F: drivers/video/backlight/
F: fs/befs/
BECKHOFF CX5020 ETHERCAT MASTER DRIVER
- M: Dariusz Marcinkiewicz <reksio@newterm.pl>
- L: netdev@vger.kernel.org
- S: Maintained
- F: drivers/net/ethernet/ec_bhf.c
+ M: Dariusz Marcinkiewicz <reksio@newterm.pl>
+ L: netdev@vger.kernel.org
+ S: Maintained
+ F: drivers/net/ethernet/ec_bhf.c
BFS FILE SYSTEM
M: "Tigran A. Aivazian" <tigran@aivazian.fsnet.co.uk>
BONDING DRIVER
M: Jay Vosburgh <j.vosburgh@gmail.com>
M: Veaceslav Falico <vfalico@gmail.com>
- M: Andy Gospodarek <andy@greyhouse.net>
+ M: Andy Gospodarek <gospo@cumulusnetworks.com>
L: netdev@vger.kernel.org
W: http://sourceforge.net/projects/bonding/
S: Supported
F: drivers/net/ethernet/broadcom/bnx2x/
BROADCOM BCM281XX/BCM11XXX/BCM216XX ARM ARCHITECTURE
- - -M: Christian Daudt <bcm@fixthebug.org>
- M: Matt Porter <mporter@linaro.org>
M: Florian Fainelli <f.fainelli@gmail.com>
+ + +M: Ray Jui <rjui@broadcom.com>
+ + +M: Scott Branden <sbranden@broadcom.com>
L: bcm-kernel-feedback-list@broadcom.com
T: git git://github.com/broadcom/mach-bcm
S: Maintained
F: drivers/usb/gadget/udc/bcm63xx_udc.*
BROADCOM BCM7XXX ARM ARCHITECTURE
- - -M: Marc Carino <marc.ceeeee@gmail.com>
M: Brian Norris <computersforpeace@gmail.com>
M: Gregory Fong <gregory.0xf0@gmail.com>
M: Florian Fainelli <f.fainelli@gmail.com>
CAN NETWORK LAYER
M: Oliver Hartkopp <socketcan@hartkopp.net>
+ M: Marc Kleine-Budde <mkl@pengutronix.de>
L: linux-can@vger.kernel.org
- W: http://gitorious.org/linux-can
+ W: https://github.com/linux-can
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git
S: Maintained
M: Wolfgang Grandegger <wg@grandegger.com>
M: Marc Kleine-Budde <mkl@pengutronix.de>
L: linux-can@vger.kernel.org
- W: http://gitorious.org/linux-can
+ W: https://github.com/linux-can
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git
S: Maintained
S: Supported
F: include/linux/capability.h
F: include/uapi/linux/capability.h
--- - -F: security/capability.c
F: security/commoncap.c
F: kernel/capability.c
CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
M: Peter Chen <Peter.Chen@freescale.com>
- T: git git://github.com/hzpeterchen/linux-usb.git
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
L: linux-usb@vger.kernel.org
S: Maintained
F: drivers/usb/chipidea/
+ CHIPONE ICN8318 I2C TOUCHSCREEN DRIVER
+ M: Hans de Goede <hdegoede@redhat.com>
+ L: linux-input@vger.kernel.org
+ S: Maintained
+ F: Documentation/devicetree/bindings/input/touchscreen/chipone_icn8318.txt
+ F: drivers/input/touchscreen/chipone_icn8318.c
+
CHROME HARDWARE PLATFORM SUPPORT
M: Olof Johansson <olof@lixom.net>
S: Maintained
CLK API
M: Russell King <linux@arm.linux.org.uk>
+ L: linux-clk@vger.kernel.org
S: Maintained
F: include/linux/clk.h
COMMON CLK FRAMEWORK
M: Mike Turquette <mturquette@linaro.org>
M: Stephen Boyd <sboyd@codeaurora.org>
- L: linux-kernel@vger.kernel.org
+ L: linux-clk@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git
S: Maintained
F: drivers/clk/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git
S: Maintained
F: Documentation/crypto/
+ F: Documentation/DocBook/crypto-API.tmpl
F: arch/*/crypto/
F: crypto/
F: drivers/crypto/
F: drivers/net/ethernet/chelsio/cxgb3/
CXGB3 ISCSI DRIVER (CXGB3I)
- M: Karen Xie <kxie@chelsio.com>
- L: linux-scsi@vger.kernel.org
- W: http://www.chelsio.com
- S: Supported
- F: drivers/scsi/cxgbi/cxgb3i
+ M: Karen Xie <kxie@chelsio.com>
+ L: linux-scsi@vger.kernel.org
+ W: http://www.chelsio.com
+ S: Supported
+ F: drivers/scsi/cxgbi/cxgb3i
CXGB3 IWARP RNIC DRIVER (IW_CXGB3)
M: Steve Wise <swise@chelsio.com>
F: drivers/net/ethernet/chelsio/cxgb4/
CXGB4 ISCSI DRIVER (CXGB4I)
- M: Karen Xie <kxie@chelsio.com>
- L: linux-scsi@vger.kernel.org
- W: http://www.chelsio.com
- S: Supported
- F: drivers/scsi/cxgbi/cxgb4i
+ M: Karen Xie <kxie@chelsio.com>
+ L: linux-scsi@vger.kernel.org
+ W: http://www.chelsio.com
+ S: Supported
+ F: drivers/scsi/cxgbi/cxgb4i
CXGB4 IWARP RNIC DRIVER (IW_CXGB4)
M: Steve Wise <swise@chelsio.com>
DELL LAPTOP DRIVER
M: Matthew Garrett <mjg59@srcf.ucam.org>
+ M: Pali Rohár <pali.rohar@gmail.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/dell-laptop.c
+ DELL LAPTOP FREEFALL DRIVER
+ M: Pali Rohár <pali.rohar@gmail.com>
+ S: Maintained
+ F: drivers/platform/x86/dell-smo8800.c
+
DELL LAPTOP SMM DRIVER
M: Guenter Roeck <linux@roeck-us.net>
S: Maintained
DELL WMI EXTRAS DRIVER
M: Matthew Garrett <mjg59@srcf.ucam.org>
+ M: Pali Rohár <pali.rohar@gmail.com>
S: Maintained
F: drivers/platform/x86/dell-wmi.c
F: Documentation/hwmon/da90??
F: drivers/gpio/gpio-da90??.c
F: drivers/hwmon/da90??-hwmon.c
+ F: drivers/iio/adc/da91??-*.c
F: drivers/input/misc/da90??_onkey.c
F: drivers/input/touchscreen/da9052_tsi.c
F: drivers/leds/leds-da90??.c
F: drivers/mfd/da903x.c
F: drivers/mfd/da90??-*.c
+ F: drivers/mfd/da91??-*.c
F: drivers/power/da9052-battery.c
+ F: drivers/power/da91??-*.c
F: drivers/regulator/da903x.c
F: drivers/regulator/da9???-regulator.[ch]
F: drivers/rtc/rtc-da90??.c
F: include/linux/mfd/da9052/
F: include/linux/mfd/da9055/
F: include/linux/mfd/da9063/
+ F: include/linux/mfd/da9150/
F: include/sound/da[79]*.h
F: sound/soc/codecs/da[79]*.[ch]
F: Documentation/hwmon/dme1737
F: drivers/hwmon/dme1737.c
- DOCKING STATION DRIVER
- M: Shaohua Li <shaohua.li@intel.com>
- L: linux-acpi@vger.kernel.org
- S: Supported
- F: drivers/acpi/dock.c
+ DMI/SMBIOS SUPPORT
+ M: Jean Delvare <jdelvare@suse.de>
+ S: Maintained
+ F: drivers/firmware/dmi-id.c
+ F: drivers/firmware/dmi_scan.c
+ F: include/linux/dmi.h
DOCUMENTATION
M: Jonathan Corbet <corbet@lwn.net>
F: Documentation/
X: Documentation/ABI/
X: Documentation/devicetree/
- X: Documentation/[a-z][a-z]_[A-Z][A-Z]/
+ X: Documentation/acpi
+ X: Documentation/power
+ X: Documentation/spi
T: git git://git.lwn.net/linux-2.6.git docs-next
DOUBLETALK DRIVER
S: Supported
F: drivers/gpu/drm/rcar-du/
F: drivers/gpu/drm/shmobile/
- F: include/linux/platform_data/rcar-du.h
F: include/linux/platform_data/shmob_drm.h
+ DRM DRIVERS FOR ROCKCHIP
+ M: Mark Yao <mark.yao@rock-chips.com>
+ L: dri-devel@lists.freedesktop.org
+ S: Maintained
+ F: drivers/gpu/drm/rockchip/
+ F: Documentation/devicetree/bindings/video/rockchip*
+
DSBR100 USB FM RADIO DRIVER
M: Alexey Klimov <klimov.linux@gmail.com>
L: linux-media@vger.kernel.org
L: linux-embedded@vger.kernel.org
S: Maintained
-- - -EMULEX LPFC FC SCSI DRIVER
-- - -M: James Smart <james.smart@emulex.com>
++ + +EMULEX/AVAGO LPFC FC/FCOE SCSI DRIVER
++ + +M: James Smart <james.smart@avagotech.com>
++ + +M: Dick Kennedy <dick.kennedy@avagotech.com>
L: linux-scsi@vger.kernel.org
-- - -W: http://sourceforge.net/projects/lpfcxxxx
++ + +W: http://www.avagotech.com
S: Supported
F: drivers/scsi/lpfc/
F: Documentation/extcon/
EXYNOS DP DRIVER
-- - -M: Jingoo Han <jg1.han@samsung.com>
++ + +M: Jingoo Han <jingoohan1@gmail.com>
L: dri-devel@lists.freedesktop.org
S: Maintained
F: drivers/gpu/drm/exynos/exynos_dp*
F: sound/soc/fsl/imx*
F: sound/soc/fsl/mpc8610_hpcd.c
+ FREESCALE QORIQ MANAGEMENT COMPLEX DRIVER
+ M: J. German Rivera <German.Rivera@freescale.com>
+ L: linux-kernel@vger.kernel.org
+ S: Maintained
+ F: drivers/staging/fsl-mc/
+
FREEVXFS FILESYSTEM
M: Christoph Hellwig <hch@infradead.org>
W: ftp://ftp.openlinux.org/pub/people/hch/vxfs
F: drivers/phy/
F: include/linux/phy/
+ GENERIC PM DOMAINS
+ M: "Rafael J. Wysocki" <rjw@rjwysocki.net>
+ M: Kevin Hilman <khilman@kernel.org>
+ M: Ulf Hansson <ulf.hansson@linaro.org>
+ L: linux-pm@vger.kernel.org
+ S: Supported
+ F: drivers/base/power/domain*.c
+ F: include/linux/pm_domain.h
+
GENERIC UIO DRIVER FOR PCI DEVICES
M: "Michael S. Tsirkin" <mst@redhat.com>
L: kvm@vger.kernel.org
GFS2 FILE SYSTEM
M: Steven Whitehouse <swhiteho@redhat.com>
+ M: Bob Peterson <rpeterso@redhat.com>
L: cluster-devel@redhat.com
W: http://sources.redhat.com/cluster/
- T: git git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes.git
- T: git git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw.git
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git
S: Supported
F: Documentation/filesystems/gfs2*.txt
F: fs/gfs2/
F: include/uapi/linux/gfs2_ondisk.h
GIGASET ISDN DRIVERS
-- - -M: Hansjoerg Lipp <hjlipp@web.de>
-- - -M: Tilman Schmidt <tilman@imap.cc>
++ + +M: Paul Bolle <pebolle@tiscali.nl>
L: gigaset307x-common@lists.sourceforge.net
W: http://gigaset307x.sourceforge.net/
-- - -S: Maintained
++ + +S: Odd Fixes
F: Documentation/isdn/README.gigaset
F: drivers/isdn/gigaset/
F: include/uapi/linux/gigaset_dev.h
F: block/partitions/efi.*
STK1160 USB VIDEO CAPTURE DRIVER
- M: Ezequiel Garcia <elezegarcia@gmail.com>
+ M: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
S: Maintained
M: Guenter Roeck <linux@roeck-us.net>
L: lm-sensors@lm-sensors.org
W: http://www.lm-sensors.org/
-- - -T: quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
++ + +T: quilt http://jdelvare.nerim.net/devel/linux/jdelvare-hwmon/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
S: Maintained
F: Documentation/hwmon/
F: drivers/iio/
F: drivers/staging/iio/
F: include/linux/iio/
+ F: tools/iio/
IKANOS/ADI EAGLE ADSL USB DRIVER
M: Matthieu Castet <castet.matthieu@free.fr>
S: Maintained
F: drivers/ipack/
+ INGENIC JZ4780 DMA Driver
+ M: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+ S: Maintained
+ F: drivers/dma/dma-jz4780.c
+
INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
M: Mimi Zohar <zohar@linux.vnet.ibm.com>
M: Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
F: drivers/video/fbdev/imsttfb.c
INFINIBAND SUBSYSTEM
- - -M: Roland Dreier <roland@kernel.org>
+ + +M: Doug Ledford <dledford@redhat.com>
M: Sean Hefty <sean.hefty@intel.com>
M: Hal Rosenstock <hal.rosenstock@gmail.com>
L: linux-rdma@vger.kernel.org
W: http://www.openfabrics.org/
Q: http://patchwork.kernel.org/project/linux-rdma/list/
- - -T: git git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git
- T: git git://github.com/dledford/linux.git
++ + +T: git git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma.git
S: Supported
F: Documentation/infiniband/
F: drivers/infiniband/
F: include/uapi/linux/if_infiniband.h
+ + +F: include/uapi/rdma/
+ + +F: include/rdma/
INOTIFY
M: John McCutchan <john@johnmccutchan.com>
F: drivers/platform/x86/intel_menlow.c
INTEL IA32 MICROCODE UPDATE SUPPORT
- M: Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
+ M: Borislav Petkov <bp@alien8.de>
S: Maintained
F: arch/x86/kernel/cpu/microcode/core*
F: arch/x86/kernel/cpu/microcode/intel*
S: Maintained
F: drivers/char/hw_random/ixp4xx-rng.c
- INTEL ETHERNET DRIVERS (e100/e1000/e1000e/fm10k/igb/igbvf/ixgb/ixgbe/ixgbevf/i40e/i40evf)
+ INTEL ETHERNET DRIVERS
M: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
- M: Jesse Brandeburg <jesse.brandeburg@intel.com>
- M: Bruce Allan <bruce.w.allan@intel.com>
- M: Carolyn Wyborny <carolyn.wyborny@intel.com>
- M: Don Skidmore <donald.c.skidmore@intel.com>
- M: Greg Rose <gregory.v.rose@intel.com>
- M: Matthew Vick <matthew.vick@intel.com>
- M: John Ronciak <john.ronciak@intel.com>
- M: Mitch Williams <mitch.a.williams@intel.com>
- M: Linux NICS <linux.nics@intel.com>
- L: e1000-devel@lists.sourceforge.net
+ R: Jesse Brandeburg <jesse.brandeburg@intel.com>
+ R: Shannon Nelson <shannon.nelson@intel.com>
+ R: Carolyn Wyborny <carolyn.wyborny@intel.com>
+ R: Don Skidmore <donald.c.skidmore@intel.com>
+ R: Matthew Vick <matthew.vick@intel.com>
+ R: John Ronciak <john.ronciak@intel.com>
+ R: Mitch Williams <mitch.a.williams@intel.com>
+ L: intel-wired-lan@lists.osuosl.org
W: http://www.intel.com/support/feedback.htm
W: http://e1000.sourceforge.net/
- T: git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net.git
- T: git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next.git
+ Q: http://patchwork.ozlabs.org/project/intel-wired-lan/list/
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-queue.git
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue.git
S: Supported
F: Documentation/networking/e100.txt
F: Documentation/networking/e1000.txt
INTEL WIRELESS WIMAX CONNECTION 2400
M: Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
M: linux-wimax@intel.com
- L: wimax@linuxwimax.org (subscribers-only)
+ L: wimax@linuxwimax.org (subscribers-only)
S: Supported
W: http://linuxwimax.org
F: Documentation/wimax/README.i2400m
F: include/linux/ipmi*
F: include/uapi/linux/ipmi*
+ QCOM AUDIO (ASoC) DRIVERS
+ M: Patrick Lai <plai@codeaurora.org>
+ M: Banajit Goswami <bgoswami@codeaurora.org>
+ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
+ S: Supported
+ F: sound/soc/qcom/
+
IPS SCSI RAID DRIVER
M: Adaptec OEM Raid Solutions <aacraid@adaptec.com>
L: linux-scsi@vger.kernel.org
F: Documentation/*/kvm*.txt
F: Documentation/virtual/kvm/
F: arch/*/kvm/
+ F: arch/x86/kernel/kvm.c
+ F: arch/x86/kernel/kvmclock.c
F: arch/*/include/asm/kvm*
F: include/linux/kvm*
F: include/uapi/linux/kvm*
LED SUBSYSTEM
M: Bryan Wu <cooloney@gmail.com>
M: Richard Purdie <rpurdie@rpsys.net>
+ + +M: Jacek Anaszewski <j.anaszewski@samsung.com>
L: linux-leds@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git
S: Maintained
F: arch/powerpc/platforms/52xx/
LINUX FOR POWERPC EMBEDDED PPC4XX
- M: Alistair Popple <alistair@popple.id.au>
+ M: Alistair Popple <alistair@popple.id.au>
M: Matt Porter <mporter@kernel.crashing.org>
W: http://www.penguinppc.org/
L: linuxppc-dev@lists.ozlabs.org
S: Maintained
F: drivers/media/dvb-frontends/m88rs2000*
- M88TS2022 MEDIA DRIVER
- M: Antti Palosaari <crope@iki.fi>
- L: linux-media@vger.kernel.org
- W: http://linuxtv.org/
- W: http://palosaari.fi/linux/
- Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
- S: Maintained
- F: drivers/media/tuners/m88ts2022*
-
MA901 MASTERKIT USB FM RADIO DRIVER
M: Alexey Klimov <klimov.linux@gmail.com>
L: linux-media@vger.kernel.org
MELLANOX ETHERNET DRIVER (mlx4_en)
M: Amir Vadai <amirv@mellanox.com>
+ M: Ido Shamay <idos@mellanox.com>
L: netdev@vger.kernel.org
S: Supported
W: http://www.mellanox.com
F: drivers/watchdog/mena21_wdt.c
MEN CHAMELEON BUS (mcb)
- M: Johannes Thumshirn <johannes.thumshirn@men.de>
+ M: Johannes Thumshirn <johannes.thumshirn@men.de>
S: Supported
F: drivers/mcb/
F: include/linux/mcb.h
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
S: Maintained
+ F: Documentation/devicetree/bindings/media/i2c/mt9v032.txt
F: drivers/media/i2c/mt9v032.c
F: include/media/mt9v032.h
F: include/linux/mfd/
MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
- M: Chris Ball <chris@printf.net>
M: Ulf Hansson <ulf.hansson@linaro.org>
L: linux-mmc@vger.kernel.org
- T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
T: git git://git.linaro.org/people/ulf.hansson/mmc.git
S: Maintained
F: drivers/mmc/
S: Maintained
F: arch/nios2/
++ + +NOKIA N900 POWER SUPPLY DRIVERS
++ + +M: Pali Rohár <pali.rohar@gmail.com>
++ + +S: Maintained
++ + +F: include/linux/power/bq2415x_charger.h
++ + +F: include/linux/power/bq27x00_battery.h
++ + +F: include/linux/power/isp1704_charger.h
++ + +F: drivers/power/bq2415x_charger.c
++ + +F: drivers/power/bq27x00_battery.c
++ + +F: drivers/power/isp1704_charger.c
++ + +F: drivers/power/rx51_battery.c
++ + +
NTB DRIVER
M: Jon Mason <jdmason@kudzu.us>
M: Dave Jiang <dave.jiang@intel.com>
F: drivers/block/nvme*
F: include/linux/nvme.h
+ NXP-NCI NFC DRIVER
+ M: Clément Perrochaud <clement.perrochaud@effinnov.com>
+ R: Charles Gorand <charles.gorand@effinnov.com>
+ L: linux-nfc@lists.01.org (moderated for non-subscribers)
+ S: Supported
+ F: drivers/nfc/nxp-nci
+
NXP TDA998X DRM DRIVER
M: Russell King <rmk+kernel@arm.linux.org.uk>
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
S: Maintained
F: arch/arm/*omap*/
+ F: arch/arm/configs/omap1_defconfig
+ F: arch/arm/configs/omap2plus_defconfig
F: drivers/i2c/busses/i2c-omap.c
F: drivers/irqchip/irq-omap-intc.c
F: drivers/mfd/*omap*.c
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
+ F: Documentation/devicetree/bindings/media/ti,omap3isp.txt
F: drivers/media/platform/omap3isp/
F: drivers/staging/media/omap4iss/
F: arch/*/boot/dts/
F: include/dt-bindings/
+ OPEN FIRMWARE AND DEVICE TREE OVERLAYS
+ M: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+ L: devicetree@vger.kernel.org
+ S: Maintained
+ F: Documentation/devicetree/dynamic-resolution-notes.txt
+ F: Documentation/devicetree/overlay-notes.txt
+ F: drivers/of/overlay.c
+ F: drivers/of/resolver.c
+
OPENRISC ARCHITECTURE
M: Jonas Bonn <jonas@southpole.se>
W: http://openrisc.net
F: drivers/pci/host/*rcar*
PCI DRIVER FOR SAMSUNG EXYNOS
-- - -M: Jingoo Han <jg1.han@samsung.com>
++ + +M: Jingoo Han <jingoohan1@gmail.com>
L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
F: drivers/pci/host/pci-exynos.c
PCI DRIVER FOR SYNOPSIS DESIGNWARE
- M: Mohit Kumar <mohit.kumar@st.com>
-- - -M: Jingoo Han <jg1.han@samsung.com>
++ + +M: Jingoo Han <jingoohan1@gmail.com>
+++ +++M: Pratyush Anand <pratyush.anand@gmail.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: drivers/pci/host/*designware*
F: drivers/pci/host/pci-host-generic.c
PCIE DRIVER FOR ST SPEAR13XX
- M: Mohit Kumar <mohit.kumar@st.com>
+++ +++M: Pratyush Anand <pratyush.anand@gmail.com>
L: linux-pci@vger.kernel.org
--- --S: Orphan
+++ ++S: Maintained
F: drivers/pci/host/*spear*
PCMCIA SUBSYSTEM
S: Maintained
QAT DRIVER
- M: Tadeusz Struk <tadeusz.struk@intel.com>
- L: qat-linux@intel.com
- S: Supported
- F: drivers/crypto/qat/
+ M: Tadeusz Struk <tadeusz.struk@intel.com>
+ L: qat-linux@intel.com
+ S: Supported
+ F: drivers/crypto/qat/
QIB DRIVER
M: Mike Marciniszyn <infinipath@intel.com>
F: drivers/net/wireless/rt2x00/
RAMDISK RAM BLOCK DEVICE DRIVER
- M: Nick Piggin <npiggin@kernel.dk>
+ M: Jens Axboe <axboe@kernel.dk>
S: Maintained
F: Documentation/blockdev/ramdisk.txt
F: drivers/block/brd.c
+ PERSISTENT MEMORY DRIVER
+ M: Ross Zwisler <ross.zwisler@linux.intel.com>
+ L: linux-nvdimm@lists.01.org
+ S: Supported
+ F: drivers/block/pmem.c
+
RANDOM NUMBER DRIVER
M: "Theodore Ts'o" <tytso@mit.edu>
S: Maintained
REAL TIME CLOCK (RTC) SUBSYSTEM
M: Alessandro Zummo <a.zummo@towertech.it>
+ M: Alexandre Belloni <alexandre.belloni@free-electrons.com>
L: rtc-linux@googlegroups.com
Q: http://patchwork.ozlabs.org/project/rtc-linux/list/
S: Maintained
S390 NETWORK DRIVERS
M: Ursula Braun <ursula.braun@de.ibm.com>
- M: Frank Blaschka <blaschka@linux.vnet.ibm.com>
M: linux390@de.ibm.com
L: linux-s390@vger.kernel.org
W: http://www.ibm.com/developerworks/linux/linux390/
F: sound/soc/samsung/
SAMSUNG FRAMEBUFFER DRIVER
-- - -M: Jingoo Han <jg1.han@samsung.com>
++ + +M: Jingoo Han <jingoohan1@gmail.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/fbdev/s3c-fb.c
L: netdev@vger.kernel.org
F: drivers/net/ethernet/samsung/sxgbe/
+ SAMSUNG THERMAL DRIVER
+ M: Lukasz Majewski <l.majewski@samsung.com>
+ L: linux-pm@vger.kernel.org
+ L: linux-samsung-soc@vger.kernel.org
+ S: Supported
+ T: https://github.com/lmajewski/linux-samsung-thermal.git
+ F: drivers/thermal/samsung/
+
SAMSUNG USB2 PHY DRIVER
M: Kamil Debski <k.debski@samsung.com>
L: linux-kernel@vger.kernel.org
F: kernel/time/clocksource.c
F: kernel/time/time*.c
F: kernel/time/ntp.c
+ F: tools/testing/selftests/timers/
SC1200 WDT DRIVER
M: Zwane Mwaikambo <zwanem@gmail.com>
F: include/scsi/sg.h
SCSI SUBSYSTEM
- M: "James E.J. Bottomley" <JBottomley@parallels.com>
+ M: "James E.J. Bottomley" <JBottomley@odin.com>
L: linux-scsi@vger.kernel.org
- T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
- T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6.git
- T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-pending-2.6.git
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
S: Maintained
F: drivers/scsi/
F: include/scsi/
F: drivers/mmc/host/sdricoh_cs.c
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
- M: Chris Ball <chris@printf.net>
L: linux-mmc@vger.kernel.org
- T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
- S: Maintained
+ S: Orphan
F: drivers/mmc/host/sdhci.*
F: drivers/mmc/host/sdhci-pltfm.[ch]
K: \bsecure_computing
K: \bTIF_SECCOMP\b
- SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF)
- M: Anton Vorontsov <anton@enomsg.org>
- L: linuxppc-dev@lists.ozlabs.org
- L: linux-mmc@vger.kernel.org
- S: Maintained
- F: drivers/mmc/host/sdhci-pltfm.[ch]
-
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER
M: Ben Dooks <ben-linux@fluff.org>
+ M: Jaehoon Chung <jh80.chung@samsung.com>
L: linux-mmc@vger.kernel.org
S: Maintained
- F: drivers/mmc/host/sdhci-s3c.c
+ F: drivers/mmc/host/sdhci-s3c*
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) ST SPEAR DRIVER
M: Viresh Kumar <viresh.linux@gmail.com>
F: include/uapi/linux/phantom.h
SERVER ENGINES 10Gbps iSCSI - BladeEngine 2 DRIVER
-- - -M: Jayamohan Kallickal <jayamohan.kallickal@emulex.com>
++ + +M: Jayamohan Kallickal <jayamohan.kallickal@avagotech.com>
++ + +M: Minh Tran <minh.tran@avagotech.com>
++ + +M: John Soni Jose <sony.john-n@avagotech.com>
L: linux-scsi@vger.kernel.org
-- - -W: http://www.emulex.com
++ + +W: http://www.avagotech.com
S: Supported
F: drivers/scsi/be2iscsi/
-- - -SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER
-- - -M: Sathya Perla <sathya.perla@emulex.com>
-- - -M: Subbu Seetharaman <subbu.seetharaman@emulex.com>
-- - -M: Ajit Khaparde <ajit.khaparde@emulex.com>
++ + +Emulex 10Gbps NIC BE2, BE3-R, Lancer, Skyhawk-R DRIVER
++ + +M: Sathya Perla <sathya.perla@avagotech.com>
++ + +M: Ajit Khaparde <ajit.khaparde@avagotech.com>
++ + +M: Padmanabh Ratnakar <padmanabh.ratnakar@avagotech.com>
++ + +M: Sriharsha Basavapatna <sriharsha.basavapatna@avagotech.com>
L: netdev@vger.kernel.org
W: http://www.emulex.com
S: Supported
F: drivers/net/ethernet/emulex/benet/
+ EMULEX ONECONNECT ROCE DRIVER
+ M: Selvin Xavier <selvin.xavier@emulex.com>
+ M: Devesh Sharma <devesh.sharma@emulex.com>
+ M: Mitesh Ahuja <mitesh.ahuja@emulex.com>
+ L: linux-rdma@vger.kernel.org
+ W: http://www.emulex.com
+ S: Supported
+ F: drivers/infiniband/hw/ocrdma/
+
SFC NETWORK DRIVER
M: Solarflare linux maintainers <linux-net-drivers@solarflare.com>
M: Shradha Shah <sshah@solarflare.com>
S: Maintained
F: drivers/media/platform/am437x/
+ OV2659 OMNIVISION SENSOR DRIVER
+ M: Lad, Prabhakar <prabhakar.csengg@gmail.com>
+ L: linux-media@vger.kernel.org
+ W: http://linuxtv.org/
+ Q: http://patchwork.linuxtv.org/project/linux-media/list/
+ T: git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
+ S: Maintained
+ F: drivers/media/i2c/ov2659.c
+ F: include/media/ov2659.h
+
SIS 190 ETHERNET DRIVER
M: Francois Romieu <romieu@fr.zoreil.com>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/staging/sm7xxfb/
+ STAGING - SILICON MOTION SM750 FRAME BUFFER DRIVER
+ M: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+ M: Teddy Wang <teddy.wang@siliconmotion.com>
+ M: Sudip Mukherjee <sudip@vectorindia.org>
+ L: linux-fbdev@vger.kernel.org
+ S: Maintained
+ F: drivers/staging/sm750fb/
+
STAGING - SLICOSS
M: Lior Dotan <liodot@gmail.com>
M: Christopher Harrer <charrer@alacritech.com>
TIPC NETWORK LAYER
M: Jon Maloy <jon.maloy@ericsson.com>
- M: Allan Stephens <allan.stephens@windriver.com>
+ M: Ying Xue <ying.xue@windriver.com>
L: netdev@vger.kernel.org (core kernel code)
L: tipc-discussion@lists.sourceforge.net (user apps, general discussion)
W: http://tipc.sourceforge.net/
F: drivers/platform/x86/topstar-laptop.c
TOSHIBA ACPI EXTRAS DRIVER
+ M: Azael Avalos <coproscefalo@gmail.com>
L: platform-driver-x86@vger.kernel.org
- S: Orphan
+ S: Maintained
F: drivers/platform/x86/toshiba_acpi.c
+ TOSHIBA BLUETOOTH DRIVER
+ M: Azael Avalos <coproscefalo@gmail.com>
+ L: platform-driver-x86@vger.kernel.org
+ S: Maintained
+ F: drivers/platform/x86/toshiba_bluetooth.c
+
+ TOSHIBA HDD ACTIVE PROTECTION SENSOR DRIVER
+ M: Azael Avalos <coproscefalo@gmail.com>
+ L: platform-driver-x86@vger.kernel.org
+ S: Maintained
+ F: drivers/platform/x86/toshiba_haps.c
+
TOSHIBA SMM DRIVER
M: Jonathan Buzzard <jonathan@buzzard.org.uk>
L: tlinux-users@tce.toshiba-dme.co.jp
TPM DEVICE DRIVER
M: Peter Huewe <peterhuewe@gmx.de>
M: Marcel Selhorst <tpmdd@selhorst.net>
+ R: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
W: http://tpmdd.sourceforge.net
L: tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers)
Q: git git://github.com/PeterHuewe/linux-tpmdd.git
F: include/uapi/linux/cdrom.h
UNISYS S-PAR DRIVERS
- M: Benjamin Romer <benjamin.romer@unisys.com>
- M: David Kershner <david.kershner@unisys.com>
- L: sparmaintainer@unisys.com (Unisys internal)
- S: Supported
- F: drivers/staging/unisys/
+ M: Benjamin Romer <benjamin.romer@unisys.com>
+ M: David Kershner <david.kershner@unisys.com>
+ L: sparmaintainer@unisys.com (Unisys internal)
+ S: Supported
+ F: drivers/staging/unisys/
UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER
M: Vinayak Holikatti <vinholikatti@gmail.com>
F: drivers/net/usb/cdc_*.c
F: include/uapi/linux/usb/cdc.h
+ USB CHAOSKEY DRIVER
+ M: Keith Packard <keithp@keithp.com>
+ L: linux-usb@vger.kernel.org
+ S: Maintained
+ F: drivers/usb/misc/chaoskey.c
+
USB CYPRESS C67X00 DRIVER
M: Peter Korsgaard <jacmet@sunsite.dk>
L: linux-usb@vger.kernel.org
F: Documentation/usb/ohci.txt
F: drivers/usb/host/ohci*
+ USB OTG FSM (Finite State Machine)
+ M: Peter Chen <Peter.Chen@freescale.com>
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
+ L: linux-usb@vger.kernel.org
+ S: Maintained
+ F: drivers/usb/common/usb-otg-fsm.c
+
USB OVER IP DRIVER
M: Valentina Manea <valentina.manea.m@gmail.com>
M: Shuah Khan <shuah.kh@samsung.com>
F: include/uapi/linux/virtio_console.h
VIRTIO CORE, NET AND BLOCK DRIVERS
- M: Rusty Russell <rusty@rustcorp.com.au>
M: "Michael S. Tsirkin" <mst@redhat.com>
L: virtualization@lists.linux-foundation.org
S: Maintained
F: drivers/vhost/
F: include/uapi/linux/vhost.h
- VIA RHINE NETWORK DRIVER
- M: Roger Luethi <rl@hellgate.ch>
+ VIRTIO INPUT DRIVER
+ M: Gerd Hoffmann <kraxel@redhat.com>
S: Maintained
--- --M: Roger Luethi <rl@hellgate.ch>
--- --S: Maintained
+ F: drivers/virtio/virtio_input.c
+ F: include/uapi/linux/virtio_input.h
+
+ VIA RHINE NETWORK DRIVER
+++ +++S: Orphan
F: drivers/net/ethernet/via/via-rhine.c
VIA SD/MMC CARD CONTROLLER DRIVER
S: Maintained
F: drivers/misc/vmw_balloon.c
+ VMWARE VMMOUSE SUBDRIVER
+ M: "VMware Graphics" <linux-graphics-maintainer@vmware.com>
+ M: "VMware, Inc." <pv-drivers@vmware.com>
+ L: linux-input@vger.kernel.org
+ S: Maintained
+ F: drivers/input/mouse/vmmouse.c
+ F: drivers/input/mouse/vmmouse.h
+
VMWARE VMXNET3 ETHERNET DRIVER
M: Shreyas Bhatewara <sbhatewara@vmware.com>
M: "VMware, Inc." <pv-drivers@vmware.com>
WIMAX STACK
M: Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
M: linux-wimax@intel.com
- L: wimax@linuxwimax.org (subscribers-only)
+ L: wimax@linuxwimax.org (subscribers-only)
S: Supported
W: http://linuxwimax.org
F: Documentation/wimax/README.wimax
S: Maintained
F: drivers/tty/serial/uartlite.c
+ XILINX VIDEO IP CORES
+ M: Hyun Kwon <hyun.kwon@xilinx.com>
+ M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ L: linux-media@vger.kernel.org
+ T: git git://linuxtv.org/media_tree.git
+ S: Supported
+ F: Documentation/devicetree/bindings/media/xilinx/
+ F: drivers/media/platform/xilinx/
+ F: include/uapi/linux/xilinx-v4l2-controls.h
+
XILLYBUS DRIVER
M: Eli Billauer <eli.billauer@gmail.com>
L: linux-kernel@vger.kernel.org
ZRAM COMPRESSED RAM BLOCK DEVICE DRVIER
M: Minchan Kim <minchan@kernel.org>
M: Nitin Gupta <ngupta@vflare.org>
+ + +R: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
L: linux-kernel@vger.kernel.org
S: Maintained
F: drivers/block/zram/
S: Maintained
F: mm/zsmalloc.c
F: include/linux/zsmalloc.h
+ F: Documentation/vm/zsmalloc.txt
ZSWAP COMPRESSED SWAP CACHING
M: Seth Jennings <sjennings@variantweb.net>
static DEFINE_RWLOCK(amd_iommu_devtable_lock);
----- -/* A list of preallocated protection domains */
----- -static LIST_HEAD(iommu_pd_list);
----- -static DEFINE_SPINLOCK(iommu_pd_list_lock);
----- -
/* List of all available dev_data structures */
static LIST_HEAD(dev_data_list);
static DEFINE_SPINLOCK(dev_data_list_lock);
struct kmem_cache *amd_iommu_irq_cache;
static void update_domain(struct protection_domain *domain);
----- -static int __init alloc_passthrough_domain(void);
+++++ +static int alloc_passthrough_domain(void);
/****************************************************************************
*
*
****************************************************************************/
+ static struct protection_domain *to_pdomain(struct iommu_domain *dom)
+ {
+ return container_of(dom, struct protection_domain, domain);
+ }
+
static struct iommu_dev_data *alloc_dev_data(u16 devid)
{
struct iommu_dev_data *dev_data;
}
/*
----- - * In this function the list of preallocated protection domains is traversed to
----- - * find the domain for a specific device
+++++ + * This function actually applies the mapping to the page table of the
+++++ + * dma_ops domain.
*/
----- -static struct dma_ops_domain *find_protection_domain(u16 devid)
+++++ +static void alloc_unity_mapping(struct dma_ops_domain *dma_dom,
+++++ + struct unity_map_entry *e)
{
----- - struct dma_ops_domain *entry, *ret = NULL;
----- - unsigned long flags;
----- - u16 alias = amd_iommu_alias_table[devid];
----- -
----- - if (list_empty(&iommu_pd_list))
----- - return NULL;
----- -
----- - spin_lock_irqsave(&iommu_pd_list_lock, flags);
+++++ + u64 addr;
----- - list_for_each_entry(entry, &iommu_pd_list, list) {
----- - if (entry->target_dev == devid ||
----- - entry->target_dev == alias) {
----- - ret = entry;
----- - break;
----- - }
+++++ + for (addr = e->address_start; addr < e->address_end;
+++++ + addr += PAGE_SIZE) {
+++++ + if (addr < dma_dom->aperture_size)
+++++ + __set_bit(addr >> PAGE_SHIFT,
+++++ + dma_dom->aperture[0]->bitmap);
}
+++++ +}
----- - spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+++++ +/*
+++++ + * Inits the unity mappings required for a specific device
+++++ + */
+++++ +static void init_unity_mappings_for_device(struct device *dev,
+++++ + struct dma_ops_domain *dma_dom)
+++++ +{
+++++ + struct unity_map_entry *e;
+++++ + u16 devid;
----- - return ret;
+++++ + devid = get_device_id(dev);
+++++ +
+++++ + list_for_each_entry(e, &amd_iommu_unity_map, list) {
+++++ + if (!(devid >= e->devid_start && devid <= e->devid_end))
+++++ + continue;
+++++ + alloc_unity_mapping(dma_dom, e);
+++++ + }
}
/*
static void init_iommu_group(struct device *dev)
{
+++++ + struct dma_ops_domain *dma_domain;
+++++ + struct iommu_domain *domain;
struct iommu_group *group;
group = iommu_group_get_for_dev(dev);
----- - if (!IS_ERR(group))
----- - iommu_group_put(group);
+++++ + if (IS_ERR(group))
+++++ + return;
+++++ +
+++++ + domain = iommu_group_default_domain(group);
+++++ + if (!domain)
+++++ + goto out;
+++++ +
+++++ + dma_domain = to_pdomain(domain)->priv;
+++++ +
+++++ + init_unity_mappings_for_device(dev, dma_domain);
+++++ +out:
+++++ + iommu_group_put(group);
}
static int __last_alias(struct pci_dev *pdev, u16 alias, void *data)
/* Unlink from alias, it may change if another device is re-plugged */
dev_data->alias_data = NULL;
+++++ + /* Remove dma-ops */
+++++ + dev->archdata.dma_ops = NULL;
+++++ +
/*
* We keep dev_data around for unplugged devices and reuse it when the
* device is re-plugged - not doing so would introduce a ton of races.
*/
}
----- -void __init amd_iommu_uninit_devices(void)
----- -{
----- - struct iommu_dev_data *dev_data, *n;
----- - struct pci_dev *pdev = NULL;
----- -
----- - for_each_pci_dev(pdev) {
----- -
----- - if (!check_device(&pdev->dev))
----- - continue;
----- -
----- - iommu_uninit_device(&pdev->dev);
----- - }
----- -
----- - /* Free all of our dev_data structures */
----- - list_for_each_entry_safe(dev_data, n, &dev_data_list, dev_data_list)
----- - free_dev_data(dev_data);
----- -}
----- -
----- -int __init amd_iommu_init_devices(void)
----- -{
----- - struct pci_dev *pdev = NULL;
----- - int ret = 0;
----- -
----- - for_each_pci_dev(pdev) {
----- -
----- - if (!check_device(&pdev->dev))
----- - continue;
----- -
----- - ret = iommu_init_device(&pdev->dev);
----- - if (ret == -ENOTSUPP)
----- - iommu_ignore_device(&pdev->dev);
----- - else if (ret)
----- - goto out_free;
----- - }
----- -
----- - /*
----- - * Initialize IOMMU groups only after iommu_init_device() has
----- - * had a chance to populate any IVRS defined aliases.
----- - */
----- - for_each_pci_dev(pdev) {
----- - if (check_device(&pdev->dev))
----- - init_iommu_group(&pdev->dev);
----- - }
----- -
----- - return 0;
----- -
----- -out_free:
----- -
----- - amd_iommu_uninit_devices();
----- -
----- - return ret;
----- -}
#ifdef CONFIG_AMD_IOMMU_STATS
/*
return unmapped;
}
----- -/*
----- - * This function checks if a specific unity mapping entry is needed for
----- - * this specific IOMMU.
----- - */
----- -static int iommu_for_unity_map(struct amd_iommu *iommu,
----- - struct unity_map_entry *entry)
----- -{
----- - u16 bdf, i;
----- -
----- - for (i = entry->devid_start; i <= entry->devid_end; ++i) {
----- - bdf = amd_iommu_alias_table[i];
----- - if (amd_iommu_rlookup_table[bdf] == iommu)
----- - return 1;
----- - }
----- -
----- - return 0;
----- -}
----- -
----- -/*
----- - * This function actually applies the mapping to the page table of the
----- - * dma_ops domain.
----- - */
----- -static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
----- - struct unity_map_entry *e)
----- -{
----- - u64 addr;
----- - int ret;
----- -
----- - for (addr = e->address_start; addr < e->address_end;
----- - addr += PAGE_SIZE) {
----- - ret = iommu_map_page(&dma_dom->domain, addr, addr, e->prot,
----- - PAGE_SIZE);
----- - if (ret)
----- - return ret;
----- - /*
----- - * if unity mapping is in aperture range mark the page
----- - * as allocated in the aperture
----- - */
----- - if (addr < dma_dom->aperture_size)
----- - __set_bit(addr >> PAGE_SHIFT,
----- - dma_dom->aperture[0]->bitmap);
----- - }
----- -
----- - return 0;
----- -}
----- -
----- -/*
----- - * Init the unity mappings for a specific IOMMU in the system
----- - *
----- - * Basically iterates over all unity mapping entries and applies them to
----- - * the default domain DMA of that IOMMU if necessary.
----- - */
----- -static int iommu_init_unity_mappings(struct amd_iommu *iommu)
----- -{
----- - struct unity_map_entry *entry;
----- - int ret;
----- -
----- - list_for_each_entry(entry, &amd_iommu_unity_map, list) {
----- - if (!iommu_for_unity_map(iommu, entry))
----- - continue;
----- - ret = dma_ops_unity_map(iommu->default_dom, entry);
----- - if (ret)
----- - return ret;
----- - }
----- -
----- - return 0;
----- -}
----- -
----- -/*
----- - * Inits the unity mappings required for a specific device
----- - */
----- -static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom,
----- - u16 devid)
----- -{
----- - struct unity_map_entry *e;
----- - int ret;
----- -
----- - list_for_each_entry(e, &amd_iommu_unity_map, list) {
----- - if (!(devid >= e->devid_start && devid <= e->devid_end))
----- - continue;
----- - ret = dma_ops_unity_map(dma_dom, e);
----- - if (ret)
----- - return ret;
----- - }
----- -
----- - return 0;
----- -}
----- -
/****************************************************************************
*
* The next functions belong to the address allocator for the dma_ops
unsigned long next_bit = dom->next_address % APERTURE_RANGE_SIZE;
int max_index = dom->aperture_size >> APERTURE_RANGE_SHIFT;
int i = start >> APERTURE_RANGE_SHIFT;
---- -- unsigned long boundary_size;
++++ ++ unsigned long boundary_size, mask;
unsigned long address = -1;
unsigned long limit;
next_bit >>= PAGE_SHIFT;
---- -- boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
---- -- PAGE_SIZE) >> PAGE_SHIFT;
++++ ++ mask = dma_get_seg_boundary(dev);
++++ ++
++++ ++ boundary_size = mask + 1 ? ALIGN(mask + 1, PAGE_SIZE) >> PAGE_SHIFT :
++++ ++ 1UL << (BITS_PER_LONG - PAGE_SHIFT);
for (;i < max_index; ++i) {
unsigned long offset = dom->aperture[i]->offset >> PAGE_SHIFT;
pt = (u64 *)__pt; \
\
for (i = 0; i < 512; ++i) { \
++++ ++ /* PTE present? */ \
if (!IOMMU_PTE_PRESENT(pt[i])) \
continue; \
\
++++ ++ /* Large PTE? */ \
++++ ++ if (PM_PTE_LEVEL(pt[i]) == 0 || \
++++ ++ PM_PTE_LEVEL(pt[i]) == 7) \
++++ ++ continue; \
++++ ++ \
p = (unsigned long)IOMMU_PTE_PAGE(pt[i]); \
FN(p); \
} \
goto free_dma_dom;
dma_dom->need_flush = false;
----- - dma_dom->target_dev = 0xffff;
add_domain_to_list(&dma_dom->domain);
dev_data->ats.enabled = false;
}
----- -/*
----- - * Find out the protection domain structure for a given PCI device. This
----- - * will give us the pointer to the page table root for example.
----- - */
----- -static struct protection_domain *domain_for_device(struct device *dev)
----- -{
----- - struct iommu_dev_data *dev_data;
----- - struct protection_domain *dom = NULL;
----- - unsigned long flags;
----- -
----- - dev_data = get_dev_data(dev);
----- -
----- - if (dev_data->domain)
----- - return dev_data->domain;
----- -
----- - if (dev_data->alias_data != NULL) {
----- - struct iommu_dev_data *alias_data = dev_data->alias_data;
----- -
----- - read_lock_irqsave(&amd_iommu_devtable_lock, flags);
----- - if (alias_data->domain != NULL) {
----- - __attach_device(dev_data, alias_data->domain);
----- - dom = alias_data->domain;
----- - }
----- - read_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
----- - }
----- -
----- - return dom;
----- -}
----- -
----- -static int device_change_notifier(struct notifier_block *nb,
----- - unsigned long action, void *data)
+++++ +static int amd_iommu_add_device(struct device *dev)
{
----- - struct dma_ops_domain *dma_domain;
----- - struct protection_domain *domain;
struct iommu_dev_data *dev_data;
----- - struct device *dev = data;
+++++ + struct iommu_domain *domain;
struct amd_iommu *iommu;
----- - unsigned long flags;
u16 devid;
+++++ + int ret;
----- - if (!check_device(dev))
+++++ + if (!check_device(dev) || get_dev_data(dev))
return 0;
----- - devid = get_device_id(dev);
----- - iommu = amd_iommu_rlookup_table[devid];
----- - dev_data = get_dev_data(dev);
----- -
----- - switch (action) {
----- - case BUS_NOTIFY_ADD_DEVICE:
+++++ + devid = get_device_id(dev);
+++++ + iommu = amd_iommu_rlookup_table[devid];
----- - iommu_init_device(dev);
----- - init_iommu_group(dev);
+++++ + ret = iommu_init_device(dev);
+++++ + if (ret) {
+++++ + if (ret != -ENOTSUPP)
+++++ + pr_err("Failed to initialize device %s - trying to proceed anyway\n",
+++++ + dev_name(dev));
----- - /*
----- - * dev_data is still NULL and
----- - * got initialized in iommu_init_device
----- - */
----- - dev_data = get_dev_data(dev);
+++++ + iommu_ignore_device(dev);
+++++ + dev->archdata.dma_ops = &nommu_dma_ops;
+++++ + goto out;
+++++ + }
+++++ + init_iommu_group(dev);
----- - if (iommu_pass_through || dev_data->iommu_v2) {
----- - dev_data->passthrough = true;
----- - attach_device(dev, pt_domain);
----- - break;
----- - }
+++++ + dev_data = get_dev_data(dev);
----- - domain = domain_for_device(dev);
+++++ + BUG_ON(!dev_data);
----- - /* allocate a protection domain if a device is added */
----- - dma_domain = find_protection_domain(devid);
----- - if (!dma_domain) {
----- - dma_domain = dma_ops_domain_alloc();
----- - if (!dma_domain)
----- - goto out;
----- - dma_domain->target_dev = devid;
----- -
----- - spin_lock_irqsave(&iommu_pd_list_lock, flags);
----- - list_add_tail(&dma_domain->list, &iommu_pd_list);
----- - spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
----- - }
+++++ + if (dev_data->iommu_v2)
+++++ + iommu_request_dm_for_dev(dev);
+++++ + /* Domains are initialized for this device - have a look what we ended up with */
+++++ + domain = iommu_get_domain_for_dev(dev);
+++++ + if (domain->type == IOMMU_DOMAIN_IDENTITY) {
+++++ + dev_data->passthrough = true;
+++++ + dev->archdata.dma_ops = &nommu_dma_ops;
+++++ + } else {
dev->archdata.dma_ops = &amd_iommu_dma_ops;
----- -
----- - break;
----- - case BUS_NOTIFY_REMOVED_DEVICE:
----- -
----- - iommu_uninit_device(dev);
----- -
----- - default:
----- - goto out;
}
+++++ +out:
iommu_completion_wait(iommu);
----- -out:
return 0;
}
----- -static struct notifier_block device_nb = {
----- - .notifier_call = device_change_notifier,
----- -};
----- -
----- -void amd_iommu_init_notifier(void)
+++++ +static void amd_iommu_remove_device(struct device *dev)
{
----- - bus_register_notifier(&pci_bus_type, &device_nb);
+++++ + struct amd_iommu *iommu;
+++++ + u16 devid;
+++++ +
+++++ + if (!check_device(dev))
+++++ + return;
+++++ +
+++++ + devid = get_device_id(dev);
+++++ + iommu = amd_iommu_rlookup_table[devid];
+++++ +
+++++ + iommu_uninit_device(dev);
+++++ + iommu_completion_wait(iommu);
}
/*****************************************************************************
static struct protection_domain *get_domain(struct device *dev)
{
struct protection_domain *domain;
----- - struct dma_ops_domain *dma_dom;
----- - u16 devid = get_device_id(dev);
+++++ + struct iommu_domain *io_domain;
if (!check_device(dev))
return ERR_PTR(-EINVAL);
----- - domain = domain_for_device(dev);
----- - if (domain != NULL && !dma_ops_domain(domain))
----- - return ERR_PTR(-EBUSY);
----- -
----- - if (domain != NULL)
----- - return domain;
+++++ + io_domain = iommu_get_domain_for_dev(dev);
+++++ + if (!io_domain)
+++++ + return NULL;
----- - /* Device not bound yet - bind it */
----- - dma_dom = find_protection_domain(devid);
----- - if (!dma_dom)
----- - dma_dom = amd_iommu_rlookup_table[devid]->default_dom;
----- - attach_device(dev, &dma_dom->domain);
----- - DUMP_printk("Using protection domain %d for device %s\n",
----- - dma_dom->domain.id, dev_name(dev));
+++++ + domain = to_pdomain(io_domain);
+++++ + if (!dma_ops_domain(domain))
+++++ + return ERR_PTR(-EBUSY);
----- - return &dma_dom->domain;
+++++ + return domain;
}
static void update_device_table(struct protection_domain *domain)
size = PAGE_ALIGN(size);
dma_mask = dev->coherent_dma_mask;
flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
+++ +++ flag |= __GFP_ZERO;
page = alloc_pages(flag | __GFP_NOWARN, get_order(size));
if (!page) {
return check_device(dev);
}
----- -/*
----- - * The function for pre-allocating protection domains.
----- - *
----- - * If the driver core informs the DMA layer if a driver grabs a device
----- - * we don't need to preallocate the protection domains anymore.
----- - * For now we have to.
----- - */
----- -static void __init prealloc_protection_domains(void)
----- -{
----- - struct iommu_dev_data *dev_data;
----- - struct dma_ops_domain *dma_dom;
----- - struct pci_dev *dev = NULL;
----- - u16 devid;
----- -
----- - for_each_pci_dev(dev) {
----- -
----- - /* Do we handle this device? */
----- - if (!check_device(&dev->dev))
----- - continue;
----- -
----- - dev_data = get_dev_data(&dev->dev);
----- - if (!amd_iommu_force_isolation && dev_data->iommu_v2) {
----- - /* Make sure passthrough domain is allocated */
----- - alloc_passthrough_domain();
----- - dev_data->passthrough = true;
----- - attach_device(&dev->dev, pt_domain);
----- - pr_info("AMD-Vi: Using passthrough domain for device %s\n",
----- - dev_name(&dev->dev));
----- - }
----- -
----- - /* Is there already any domain for it? */
----- - if (domain_for_device(&dev->dev))
----- - continue;
----- -
----- - devid = get_device_id(&dev->dev);
----- -
----- - dma_dom = dma_ops_domain_alloc();
----- - if (!dma_dom)
----- - continue;
----- - init_unity_mappings_for_device(dma_dom, devid);
----- - dma_dom->target_dev = devid;
----- -
----- - attach_device(&dev->dev, &dma_dom->domain);
----- -
----- - list_add_tail(&dma_dom->list, &iommu_pd_list);
----- - }
----- -}
----- -
static struct dma_map_ops amd_iommu_dma_ops = {
.alloc = alloc_coherent,
.free = free_coherent,
.dma_supported = amd_iommu_dma_supported,
};
----- -static unsigned device_dma_ops_init(void)
+++++ +int __init amd_iommu_init_api(void)
{
----- - struct iommu_dev_data *dev_data;
----- - struct pci_dev *pdev = NULL;
----- - unsigned unhandled = 0;
----- -
----- - for_each_pci_dev(pdev) {
----- - if (!check_device(&pdev->dev)) {
----- -
----- - iommu_ignore_device(&pdev->dev);
----- -
----- - unhandled += 1;
----- - continue;
----- - }
----- -
----- - dev_data = get_dev_data(&pdev->dev);
----- -
----- - if (!dev_data->passthrough)
----- - pdev->dev.archdata.dma_ops = &amd_iommu_dma_ops;
----- - else
----- - pdev->dev.archdata.dma_ops = &nommu_dma_ops;
----- - }
----- -
----- - return unhandled;
----- -}
----- -
----- -/*
----- - * The function which clues the AMD IOMMU driver into dma_ops.
----- - */
----- -
----- -void __init amd_iommu_init_api(void)
----- -{
----- - bus_set_iommu(&pci_bus_type, &amd_iommu_ops);
+++++ + return bus_set_iommu(&pci_bus_type, &amd_iommu_ops);
}
int __init amd_iommu_init_dma_ops(void)
{
----- - struct amd_iommu *iommu;
----- - int ret, unhandled;
----- -
----- - /*
----- - * first allocate a default protection domain for every IOMMU we
----- - * found in the system. Devices not assigned to any other
----- - * protection domain will be assigned to the default one.
----- - */
----- - for_each_iommu(iommu) {
----- - iommu->default_dom = dma_ops_domain_alloc();
----- - if (iommu->default_dom == NULL)
----- - return -ENOMEM;
----- - iommu->default_dom->domain.flags |= PD_DEFAULT_MASK;
----- - ret = iommu_init_unity_mappings(iommu);
----- - if (ret)
----- - goto free_domains;
----- - }
----- -
----- - /*
----- - * Pre-allocate the protection domains for each device.
----- - */
----- - prealloc_protection_domains();
----- -
iommu_detected = 1;
swiotlb = 0;
----- - /* Make the driver finally visible to the drivers */
----- - unhandled = device_dma_ops_init();
----- - if (unhandled && max_pfn > MAX_DMA32_PFN) {
----- - /* There are unhandled devices - initialize swiotlb for them */
----- - swiotlb = 1;
----- - }
----- -
amd_iommu_stats_init();
if (amd_iommu_unmap_flush)
pr_info("AMD-Vi: Lazy IO/TLB flushing enabled\n");
return 0;
----- -
----- -free_domains:
----- -
----- - for_each_iommu(iommu) {
----- - dma_ops_domain_free(iommu->default_dom);
----- - }
----- -
----- - return ret;
}
/*****************************************************************************
return NULL;
}
----- -static int __init alloc_passthrough_domain(void)
+++++ +static int alloc_passthrough_domain(void)
{
if (pt_domain != NULL)
return 0;
return 0;
}
- static int amd_iommu_domain_init(struct iommu_domain *dom)
- {
- struct protection_domain *domain;
-
- domain = protection_domain_alloc();
- if (!domain)
- goto out_free;
- domain->mode = PAGE_MODE_3_LEVEL;
- domain->pt_root = (void *)get_zeroed_page(GFP_KERNEL);
- if (!domain->pt_root)
- goto out_free;
+ static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
+ {
+ struct protection_domain *pdomain;
+++++ + struct dma_ops_domain *dma_domain;
---- - /* We only support unmanaged domains for now */
---- - if (type != IOMMU_DOMAIN_UNMANAGED)
---- - return NULL;
---- -
---- - pdomain = protection_domain_alloc();
---- - if (!pdomain)
---- - goto out_free;
- domain->iommu_domain = dom;
+++++ + switch (type) {
+++++ + case IOMMU_DOMAIN_UNMANAGED:
+++++ + pdomain = protection_domain_alloc();
+++++ + if (!pdomain)
+++++ + return NULL;
---- - pdomain->mode = PAGE_MODE_3_LEVEL;
---- - pdomain->pt_root = (void *)get_zeroed_page(GFP_KERNEL);
---- - if (!pdomain->pt_root)
---- - goto out_free;
- dom->priv = domain;
+++++ + pdomain->mode = PAGE_MODE_3_LEVEL;
+++++ + pdomain->pt_root = (void *)get_zeroed_page(GFP_KERNEL);
+++++ + if (!pdomain->pt_root) {
+++++ + protection_domain_free(pdomain);
+++++ + return NULL;
+++++ + }
---- - pdomain->domain.geometry.aperture_start = 0;
---- - pdomain->domain.geometry.aperture_end = ~0ULL;
---- - pdomain->domain.geometry.force_aperture = true;
- dom->geometry.aperture_start = 0;
- dom->geometry.aperture_end = ~0ULL;
- dom->geometry.force_aperture = true;
+++++ + pdomain->domain.geometry.aperture_start = 0;
+++++ + pdomain->domain.geometry.aperture_end = ~0ULL;
+++++ + pdomain->domain.geometry.force_aperture = true;
---- - return &pdomain->domain;
- return 0;
+++++ + break;
+++++ + case IOMMU_DOMAIN_DMA:
+++++ + dma_domain = dma_ops_domain_alloc();
+++++ + if (!dma_domain) {
+++++ + pr_err("AMD-Vi: Failed to allocate\n");
+++++ + return NULL;
+++++ + }
+++++ + pdomain = &dma_domain->domain;
+++++ + break;
+++++ + case IOMMU_DOMAIN_IDENTITY:
+++++ + pdomain = protection_domain_alloc();
+++++ + if (!pdomain)
+++++ + return NULL;
----- -out_free:
---- - protection_domain_free(pdomain);
- protection_domain_free(domain);
+++++ + pdomain->mode = PAGE_MODE_NONE;
+++++ + break;
+++++ + default:
+++++ + return NULL;
+++++ + }
---- - return NULL;
- return -ENOMEM;
+++++ + return &pdomain->domain;
}
- static void amd_iommu_domain_destroy(struct iommu_domain *dom)
+ static void amd_iommu_domain_free(struct iommu_domain *dom)
{
- struct protection_domain *domain = dom->priv;
+ struct protection_domain *domain;
- if (!domain)
+ if (!dom)
return;
+ domain = to_pdomain(dom);
+
if (domain->dev_cnt > 0)
cleanup_domain(domain);
free_gcr3_table(domain);
protection_domain_free(domain);
-
- dom->priv = NULL;
}
static void amd_iommu_detach_device(struct iommu_domain *dom,
static int amd_iommu_attach_device(struct iommu_domain *dom,
struct device *dev)
{
- struct protection_domain *domain = dom->priv;
+ struct protection_domain *domain = to_pdomain(dom);
struct iommu_dev_data *dev_data;
struct amd_iommu *iommu;
int ret;
static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
phys_addr_t paddr, size_t page_size, int iommu_prot)
{
- struct protection_domain *domain = dom->priv;
+ struct protection_domain *domain = to_pdomain(dom);
int prot = 0;
int ret;
static size_t amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
size_t page_size)
{
- struct protection_domain *domain = dom->priv;
+ struct protection_domain *domain = to_pdomain(dom);
size_t unmap_size;
if (domain->mode == PAGE_MODE_NONE)
static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
dma_addr_t iova)
{
- struct protection_domain *domain = dom->priv;
+ struct protection_domain *domain = to_pdomain(dom);
unsigned long offset_mask, pte_pgsize;
u64 *pte, __pte;
return false;
}
+++++ +static void amd_iommu_get_dm_regions(struct device *dev,
+++++ + struct list_head *head)
+++++ +{
+++++ + struct unity_map_entry *entry;
+++++ + u16 devid;
+++++ +
+++++ + devid = get_device_id(dev);
+++++ +
+++++ + list_for_each_entry(entry, &amd_iommu_unity_map, list) {
+++++ + struct iommu_dm_region *region;
+++++ +
+++++ + if (devid < entry->devid_start || devid > entry->devid_end)
+++++ + continue;
+++++ +
+++++ + region = kzalloc(sizeof(*region), GFP_KERNEL);
+++++ + if (!region) {
+++++ + pr_err("Out of memory allocating dm-regions for %s\n",
+++++ + dev_name(dev));
+++++ + return;
+++++ + }
+++++ +
+++++ + region->start = entry->address_start;
+++++ + region->length = entry->address_end - entry->address_start;
+++++ + if (entry->prot & IOMMU_PROT_IR)
+++++ + region->prot |= IOMMU_READ;
+++++ + if (entry->prot & IOMMU_PROT_IW)
+++++ + region->prot |= IOMMU_WRITE;
+++++ +
+++++ + list_add_tail(®ion->list, head);
+++++ + }
+++++ +}
+++++ +
+++++ +static void amd_iommu_put_dm_regions(struct device *dev,
+++++ + struct list_head *head)
+++++ +{
+++++ + struct iommu_dm_region *entry, *next;
+++++ +
+++++ + list_for_each_entry_safe(entry, next, head, list)
+++++ + kfree(entry);
+++++ +}
+++++ +
static const struct iommu_ops amd_iommu_ops = {
.capable = amd_iommu_capable,
- .domain_init = amd_iommu_domain_init,
- .domain_destroy = amd_iommu_domain_destroy,
+ .domain_alloc = amd_iommu_domain_alloc,
+ .domain_free = amd_iommu_domain_free,
.attach_dev = amd_iommu_attach_device,
.detach_dev = amd_iommu_detach_device,
.map = amd_iommu_map,
.unmap = amd_iommu_unmap,
.map_sg = default_iommu_map_sg,
.iova_to_phys = amd_iommu_iova_to_phys,
+++++ + .add_device = amd_iommu_add_device,
+++++ + .remove_device = amd_iommu_remove_device,
+++++ + .get_dm_regions = amd_iommu_get_dm_regions,
+++++ + .put_dm_regions = amd_iommu_put_dm_regions,
.pgsize_bitmap = AMD_IOMMU_PGSIZES,
};
void amd_iommu_domain_direct_map(struct iommu_domain *dom)
{
- struct protection_domain *domain = dom->priv;
+ struct protection_domain *domain = to_pdomain(dom);
unsigned long flags;
spin_lock_irqsave(&domain->lock, flags);
int amd_iommu_domain_enable_v2(struct iommu_domain *dom, int pasids)
{
- struct protection_domain *domain = dom->priv;
+ struct protection_domain *domain = to_pdomain(dom);
unsigned long flags;
int levels, ret;
int amd_iommu_flush_page(struct iommu_domain *dom, int pasid,
u64 address)
{
- struct protection_domain *domain = dom->priv;
+ struct protection_domain *domain = to_pdomain(dom);
unsigned long flags;
int ret;
int amd_iommu_flush_tlb(struct iommu_domain *dom, int pasid)
{
- struct protection_domain *domain = dom->priv;
+ struct protection_domain *domain = to_pdomain(dom);
unsigned long flags;
int ret;
int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, int pasid,
unsigned long cr3)
{
- struct protection_domain *domain = dom->priv;
+ struct protection_domain *domain = to_pdomain(dom);
unsigned long flags;
int ret;
int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid)
{
- struct protection_domain *domain = dom->priv;
+ struct protection_domain *domain = to_pdomain(dom);
unsigned long flags;
int ret;
struct iommu_domain *amd_iommu_get_v2_domain(struct pci_dev *pdev)
{
- struct protection_domain *domain;
+ struct protection_domain *pdomain;
- domain = get_domain(&pdev->dev);
- if (IS_ERR(domain))
+ pdomain = get_domain(&pdev->dev);
+ if (IS_ERR(pdomain))
return NULL;
/* Only return IOMMUv2 domains */
- if (!(domain->flags & PD_IOMMUV2_MASK))
+ if (!(pdomain->flags & PD_IOMMUV2_MASK))
return NULL;
- return domain->iommu_domain;
+ return &pdomain->domain;
}
EXPORT_SYMBOL(amd_iommu_get_v2_domain);
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
----- -#define pr_fmt(fmt) "%s: " fmt, __func__
+++++ +#define pr_fmt(fmt) "iommu: " fmt
#include <linux/device.h>
#include <linux/kernel.h>
void (*iommu_data_release)(void *iommu_data);
char *name;
int id;
+++++ + struct iommu_domain *default_domain;
+++++ + struct iommu_domain *domain;
};
struct iommu_device {
#define to_iommu_group(_kobj) \
container_of(_kobj, struct iommu_group, kobj)
+++++ +static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
+++++ + unsigned type);
+++++ +static int __iommu_attach_device(struct iommu_domain *domain,
+++++ + struct device *dev);
+++++ +static int __iommu_attach_group(struct iommu_domain *domain,
+++++ + struct iommu_group *group);
+++++ +static void __iommu_detach_group(struct iommu_domain *domain,
+++++ + struct iommu_group *group);
+++++ +
static ssize_t iommu_group_attr_show(struct kobject *kobj,
struct attribute *__attr, char *buf)
{
{
struct iommu_group *group = to_iommu_group(kobj);
+++++ + pr_debug("Releasing group %d\n", group->id);
+++++ +
if (group->iommu_data_release)
group->iommu_data_release(group->iommu_data);
ida_remove(&iommu_group_ida, group->id);
mutex_unlock(&iommu_group_mutex);
+++++ + if (group->default_domain)
+++++ + iommu_domain_free(group->default_domain);
+++++ +
kfree(group->name);
kfree(group);
}
*/
kobject_put(&group->kobj);
+++++ + pr_debug("Allocated group %d\n", group->id);
+++++ +
return group;
}
EXPORT_SYMBOL_GPL(iommu_group_alloc);
}
EXPORT_SYMBOL_GPL(iommu_group_set_name);
+++++ +static int iommu_group_create_direct_mappings(struct iommu_group *group,
+++++ + struct device *dev)
+++++ +{
+++++ + struct iommu_domain *domain = group->default_domain;
+++++ + struct iommu_dm_region *entry;
+++++ + struct list_head mappings;
+++++ + unsigned long pg_size;
+++++ + int ret = 0;
+++++ +
+++++ + if (!domain || domain->type != IOMMU_DOMAIN_DMA)
+++++ + return 0;
+++++ +
+++++ + BUG_ON(!domain->ops->pgsize_bitmap);
+++++ +
+++++ + pg_size = 1UL << __ffs(domain->ops->pgsize_bitmap);
+++++ + INIT_LIST_HEAD(&mappings);
+++++ +
+++++ + iommu_get_dm_regions(dev, &mappings);
+++++ +
+++++ + /* We need to consider overlapping regions for different devices */
+++++ + list_for_each_entry(entry, &mappings, list) {
+++++ + dma_addr_t start, end, addr;
+++++ +
+++++ + start = ALIGN(entry->start, pg_size);
+++++ + end = ALIGN(entry->start + entry->length, pg_size);
+++++ +
+++++ + for (addr = start; addr < end; addr += pg_size) {
+++++ + phys_addr_t phys_addr;
+++++ +
+++++ + phys_addr = iommu_iova_to_phys(domain, addr);
+++++ + if (phys_addr)
+++++ + continue;
+++++ +
+++++ + ret = iommu_map(domain, addr, addr, pg_size, entry->prot);
+++++ + if (ret)
+++++ + goto out;
+++++ + }
+++++ +
+++++ + }
+++++ +
+++++ +out:
+++++ + iommu_put_dm_regions(dev, &mappings);
+++++ +
+++++ + return ret;
+++++ +}
+++++ +
/**
* iommu_group_add_device - add a device to an iommu group
* @group: the group into which to add the device (reference should be held)
dev->iommu_group = group;
+++++ + iommu_group_create_direct_mappings(group, dev);
+++++ +
mutex_lock(&group->mutex);
list_add_tail(&device->list, &group->devices);
+++++ + if (group->domain)
+++++ + __iommu_attach_device(group->domain, dev);
mutex_unlock(&group->mutex);
/* Notify any listeners about change to group. */
IOMMU_GROUP_NOTIFY_ADD_DEVICE, dev);
trace_add_device_to_group(group->id, dev);
+++++ +
+++++ + pr_info("Adding device %s to group %d\n", dev_name(dev), group->id);
+++++ +
return 0;
}
EXPORT_SYMBOL_GPL(iommu_group_add_device);
struct iommu_group *group = dev->iommu_group;
struct iommu_device *tmp_device, *device = NULL;
+++++ + pr_info("Removing device %s from group %d\n", dev_name(dev), group->id);
+++++ +
/* Pre-notify listeners that a device is being removed. */
blocking_notifier_call_chain(&group->notifier,
IOMMU_GROUP_NOTIFY_DEL_DEVICE, dev);
}
EXPORT_SYMBOL_GPL(iommu_group_remove_device);
+++++ +static int iommu_group_device_count(struct iommu_group *group)
+++++ +{
+++++ + struct iommu_device *entry;
+++++ + int ret = 0;
+++++ +
+++++ + list_for_each_entry(entry, &group->devices, list)
+++++ + ret++;
+++++ +
+++++ + return ret;
+++++ +}
+++++ +
/**
* iommu_group_for_each_dev - iterate over each device in the group
* @group: the group
* The group->mutex is held across callbacks, which will block calls to
* iommu_group_add/remove_device.
*/
----- -int iommu_group_for_each_dev(struct iommu_group *group, void *data,
----- - int (*fn)(struct device *, void *))
+++++ +static int __iommu_group_for_each_dev(struct iommu_group *group, void *data,
+++++ + int (*fn)(struct device *, void *))
{
struct iommu_device *device;
int ret = 0;
----- - mutex_lock(&group->mutex);
list_for_each_entry(device, &group->devices, list) {
ret = fn(device->dev, data);
if (ret)
break;
}
+++++ + return ret;
+++++ +}
+++++ +
+++++ +
+++++ +int iommu_group_for_each_dev(struct iommu_group *group, void *data,
+++++ + int (*fn)(struct device *, void *))
+++++ +{
+++++ + int ret;
+++++ +
+++++ + mutex_lock(&group->mutex);
+++++ + ret = __iommu_group_for_each_dev(group, data, fn);
mutex_unlock(&group->mutex);
+++++ +
return ret;
}
EXPORT_SYMBOL_GPL(iommu_group_for_each_dev);
return group;
/* No shared group found, allocate new */
----- - return iommu_group_alloc();
+++++ + group = iommu_group_alloc();
+++++ + if (IS_ERR(group))
+++++ + return NULL;
+++++ +
+++++ + /*
+++++ + * Try to allocate a default domain - needs support from the
+++++ + * IOMMU driver.
+++++ + */
+++++ + group->default_domain = __iommu_domain_alloc(pdev->dev.bus,
+++++ + IOMMU_DOMAIN_DMA);
+++++ + group->domain = group->default_domain;
+++++ +
+++++ + return group;
}
/**
return group;
}
+++++ +struct iommu_domain *iommu_group_default_domain(struct iommu_group *group)
+++++ +{
+++++ + return group->default_domain;
+++++ +}
+++++ +
static int add_iommu_group(struct device *dev, void *data)
{
struct iommu_callback_data *cb = data;
WARN_ON(dev->iommu_group);
----- - ops->add_device(dev);
+++++ + return ops->add_device(dev);
+++++ +}
+++++ +
+++++ +static int remove_iommu_group(struct device *dev, void *data)
+++++ +{
+++++ + struct iommu_callback_data *cb = data;
+++++ + const struct iommu_ops *ops = cb->ops;
+++++ +
+++++ + if (ops->remove_device && dev->iommu_group)
+++++ + ops->remove_device(dev);
return 0;
}
if (action == BUS_NOTIFY_ADD_DEVICE) {
if (ops->add_device)
return ops->add_device(dev);
----- - } else if (action == BUS_NOTIFY_DEL_DEVICE) {
+++++ + } else if (action == BUS_NOTIFY_REMOVED_DEVICE) {
if (ops->remove_device && dev->iommu_group) {
ops->remove_device(dev);
return 0;
nb->notifier_call = iommu_bus_notifier;
err = bus_register_notifier(bus, nb);
----- - if (err) {
----- - kfree(nb);
----- - return err;
----- - }
+++++ + if (err)
+++++ + goto out_free;
err = bus_for_each_dev(bus, NULL, &cb, add_iommu_group);
----- - if (err) {
----- - bus_unregister_notifier(bus, nb);
----- - kfree(nb);
----- - return err;
----- - }
+++++ + if (err)
+++++ + goto out_err;
+++++ +
return 0;
+++++ +
+++++ +out_err:
+++++ + /* Clean up */
+++++ + bus_for_each_dev(bus, NULL, &cb, remove_iommu_group);
+++++ + bus_unregister_notifier(bus, nb);
+++++ +
+++++ +out_free:
+++++ + kfree(nb);
+++++ +
+++++ + return err;
}
/**
}
EXPORT_SYMBOL_GPL(iommu_set_fault_handler);
----- -struct iommu_domain *iommu_domain_alloc(struct bus_type *bus)
+++++ +static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
+++++ + unsigned type)
{
struct iommu_domain *domain;
- int ret;
if (bus == NULL || bus->iommu_ops == NULL)
return NULL;
---- - domain = bus->iommu_ops->domain_alloc(IOMMU_DOMAIN_UNMANAGED);
- domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+++++ + domain = bus->iommu_ops->domain_alloc(type);
if (!domain)
return NULL;
- domain->ops = bus->iommu_ops;
-
- ret = domain->ops->domain_init(domain);
- if (ret)
- goto out_free;
+ domain->ops = bus->iommu_ops;
---- - domain->type = IOMMU_DOMAIN_UNMANAGED;
+++++ + domain->type = type;
return domain;
- out_free:
- kfree(domain);
-
- return NULL;
+ }
++++ +
+++++ +struct iommu_domain *iommu_domain_alloc(struct bus_type *bus)
+++++ +{
+++++ + return __iommu_domain_alloc(bus, IOMMU_DOMAIN_UNMANAGED);
++++ +}
EXPORT_SYMBOL_GPL(iommu_domain_alloc);
void iommu_domain_free(struct iommu_domain *domain)
{
- if (likely(domain->ops->domain_destroy != NULL))
- domain->ops->domain_destroy(domain);
-
- kfree(domain);
+ domain->ops->domain_free(domain);
}
EXPORT_SYMBOL_GPL(iommu_domain_free);
----- -int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
+++++ +static int __iommu_attach_device(struct iommu_domain *domain,
+++++ + struct device *dev)
{
int ret;
if (unlikely(domain->ops->attach_dev == NULL))
trace_attach_device_to_domain(dev);
return ret;
}
+++++ +
+++++ +int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
+++++ +{
+++++ + struct iommu_group *group;
+++++ + int ret;
+++++ +
+++++ + group = iommu_group_get(dev);
+++++ + /* FIXME: Remove this when groups a mandatory for iommu drivers */
+++++ + if (group == NULL)
+++++ + return __iommu_attach_device(domain, dev);
+++++ +
+++++ + /*
+++++ + * We have a group - lock it to make sure the device-count doesn't
+++++ + * change while we are attaching
+++++ + */
+++++ + mutex_lock(&group->mutex);
+++++ + ret = -EINVAL;
+++++ + if (iommu_group_device_count(group) != 1)
+++++ + goto out_unlock;
+++++ +
+++++ + ret = __iommu_attach_group(domain, group);
+++++ +
+++++ +out_unlock:
+++++ + mutex_unlock(&group->mutex);
+++++ + iommu_group_put(group);
+++++ +
+++++ + return ret;
+++++ +}
EXPORT_SYMBOL_GPL(iommu_attach_device);
----- -void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
+++++ +static void __iommu_detach_device(struct iommu_domain *domain,
+++++ + struct device *dev)
{
if (unlikely(domain->ops->detach_dev == NULL))
return;
domain->ops->detach_dev(domain, dev);
trace_detach_device_from_domain(dev);
}
+++++ +
+++++ +void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
+++++ +{
+++++ + struct iommu_group *group;
+++++ +
+++++ + group = iommu_group_get(dev);
+++++ + /* FIXME: Remove this when groups a mandatory for iommu drivers */
+++++ + if (group == NULL)
+++++ + return __iommu_detach_device(domain, dev);
+++++ +
+++++ + mutex_lock(&group->mutex);
+++++ + if (iommu_group_device_count(group) != 1) {
+++++ + WARN_ON(1);
+++++ + goto out_unlock;
+++++ + }
+++++ +
+++++ + __iommu_detach_group(domain, group);
+++++ +
+++++ +out_unlock:
+++++ + mutex_unlock(&group->mutex);
+++++ + iommu_group_put(group);
+++++ +}
EXPORT_SYMBOL_GPL(iommu_detach_device);
+++++ +struct iommu_domain *iommu_get_domain_for_dev(struct device *dev)
+++++ +{
+++++ + struct iommu_domain *domain;
+++++ + struct iommu_group *group;
+++++ +
+++++ + group = iommu_group_get(dev);
+++++ + /* FIXME: Remove this when groups a mandatory for iommu drivers */
+++++ + if (group == NULL)
+++++ + return NULL;
+++++ +
+++++ + domain = group->domain;
+++++ +
+++++ + iommu_group_put(group);
+++++ +
+++++ + return domain;
+++++ +}
+++++ +EXPORT_SYMBOL_GPL(iommu_get_domain_for_dev);
+++++ +
/*
* IOMMU groups are really the natrual working unit of the IOMMU, but
* the IOMMU API works on domains and devices. Bridge that gap by
{
struct iommu_domain *domain = data;
----- - return iommu_attach_device(domain, dev);
+++++ + return __iommu_attach_device(domain, dev);
+++++ +}
+++++ +
+++++ +static int __iommu_attach_group(struct iommu_domain *domain,
+++++ + struct iommu_group *group)
+++++ +{
+++++ + int ret;
+++++ +
+++++ + if (group->default_domain && group->domain != group->default_domain)
+++++ + return -EBUSY;
+++++ +
+++++ + ret = __iommu_group_for_each_dev(group, domain,
+++++ + iommu_group_do_attach_device);
+++++ + if (ret == 0)
+++++ + group->domain = domain;
+++++ +
+++++ + return ret;
}
int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group)
{
----- - return iommu_group_for_each_dev(group, domain,
----- - iommu_group_do_attach_device);
+++++ + int ret;
+++++ +
+++++ + mutex_lock(&group->mutex);
+++++ + ret = __iommu_attach_group(domain, group);
+++++ + mutex_unlock(&group->mutex);
+++++ +
+++++ + return ret;
}
EXPORT_SYMBOL_GPL(iommu_attach_group);
{
struct iommu_domain *domain = data;
----- - iommu_detach_device(domain, dev);
+++++ + __iommu_detach_device(domain, dev);
return 0;
}
+++++ +static void __iommu_detach_group(struct iommu_domain *domain,
+++++ + struct iommu_group *group)
+++++ +{
+++++ + int ret;
+++++ +
+++++ + if (!group->default_domain) {
+++++ + __iommu_group_for_each_dev(group, domain,
+++++ + iommu_group_do_detach_device);
+++++ + group->domain = NULL;
+++++ + return;
+++++ + }
+++++ +
+++++ + if (group->domain == group->default_domain)
+++++ + return;
+++++ +
+++++ + /* Detach by re-attaching to the default domain */
+++++ + ret = __iommu_group_for_each_dev(group, group->default_domain,
+++++ + iommu_group_do_attach_device);
+++++ + if (ret != 0)
+++++ + WARN_ON(1);
+++++ + else
+++++ + group->domain = group->default_domain;
+++++ +}
+++++ +
void iommu_detach_group(struct iommu_domain *domain, struct iommu_group *group)
{
----- - iommu_group_for_each_dev(group, domain, iommu_group_do_detach_device);
+++++ + mutex_lock(&group->mutex);
+++++ + __iommu_detach_group(domain, group);
+++++ + mutex_unlock(&group->mutex);
}
EXPORT_SYMBOL_GPL(iommu_detach_group);
domain->ops->pgsize_bitmap == 0UL))
return -ENODEV;
+ if (unlikely(!(domain->type & __IOMMU_DOMAIN_PAGING)))
+ return -EINVAL;
+
/* find out the minimum page size supported */
min_pagesz = 1 << __ffs(domain->ops->pgsize_bitmap);
domain->ops->pgsize_bitmap == 0UL))
return -ENODEV;
+ if (unlikely(!(domain->type & __IOMMU_DOMAIN_PAGING)))
+ return -EINVAL;
+
/* find out the minimum page size supported */
min_pagesz = 1 << __ffs(domain->ops->pgsize_bitmap);
return 0;
}
- -----arch_initcall(iommu_init);
+ +++++core_initcall(iommu_init);
int iommu_domain_get_attr(struct iommu_domain *domain,
enum iommu_attr attr, void *data)
return ret;
}
EXPORT_SYMBOL_GPL(iommu_domain_set_attr);
+++++ +
+++++ +void iommu_get_dm_regions(struct device *dev, struct list_head *list)
+++++ +{
+++++ + const struct iommu_ops *ops = dev->bus->iommu_ops;
+++++ +
+++++ + if (ops && ops->get_dm_regions)
+++++ + ops->get_dm_regions(dev, list);
+++++ +}
+++++ +
+++++ +void iommu_put_dm_regions(struct device *dev, struct list_head *list)
+++++ +{
+++++ + const struct iommu_ops *ops = dev->bus->iommu_ops;
+++++ +
+++++ + if (ops && ops->put_dm_regions)
+++++ + ops->put_dm_regions(dev, list);
+++++ +}
+++++ +
+++++ +/* Request that a device is direct mapped by the IOMMU */
+++++ +int iommu_request_dm_for_dev(struct device *dev)
+++++ +{
+++++ + struct iommu_domain *dm_domain;
+++++ + struct iommu_group *group;
+++++ + int ret;
+++++ +
+++++ + /* Device must already be in a group before calling this function */
+++++ + group = iommu_group_get_for_dev(dev);
+++++ + if (IS_ERR(group))
+++++ + return PTR_ERR(group);
+++++ +
+++++ + mutex_lock(&group->mutex);
+++++ +
+++++ + /* Check if the default domain is already direct mapped */
+++++ + ret = 0;
+++++ + if (group->default_domain &&
+++++ + group->default_domain->type == IOMMU_DOMAIN_IDENTITY)
+++++ + goto out;
+++++ +
+++++ + /* Don't change mappings of existing devices */
+++++ + ret = -EBUSY;
+++++ + if (iommu_group_device_count(group) != 1)
+++++ + goto out;
+++++ +
+++++ + /* Allocate a direct mapped domain */
+++++ + ret = -ENOMEM;
+++++ + dm_domain = __iommu_domain_alloc(dev->bus, IOMMU_DOMAIN_IDENTITY);
+++++ + if (!dm_domain)
+++++ + goto out;
+++++ +
+++++ + /* Attach the device to the domain */
+++++ + ret = __iommu_attach_group(dm_domain, group);
+++++ + if (ret) {
+++++ + iommu_domain_free(dm_domain);
+++++ + goto out;
+++++ + }
+++++ +
+++++ + /* Make the direct mapped domain the default for this group */
+++++ + if (group->default_domain)
+++++ + iommu_domain_free(group->default_domain);
+++++ + group->default_domain = dm_domain;
+++++ +
+++++ + pr_info("Using direct mapping for device %s\n", dev_name(dev));
+++++ +
+++++ + ret = 0;
+++++ +out:
+++++ + mutex_unlock(&group->mutex);
+++++ + iommu_group_put(group);
+++++ +
+++++ + return ret;
+++++ +}
u32 *dt; /* page directory table */
spinlock_t iommus_lock; /* lock for iommus list */
spinlock_t dt_lock; /* lock for modifying page directory table */
+
+ struct iommu_domain domain;
};
struct rk_iommu {
outer_flush_range(pa_start, pa_end);
}
+ static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom)
+ {
+ return container_of(dom, struct rk_iommu_domain, domain);
+ }
+
/**
* Inspired by _wait_for in intel_drv.h
* This is NOT safe for use in interrupt context.
static phys_addr_t rk_iommu_iova_to_phys(struct iommu_domain *domain,
dma_addr_t iova)
{
- struct rk_iommu_domain *rk_domain = domain->priv;
+ struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
unsigned long flags;
phys_addr_t pt_phys, phys = 0;
u32 dte, pte;
spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
}
++++++static void rk_iommu_zap_iova_first_last(struct rk_iommu_domain *rk_domain,
++++++ dma_addr_t iova, size_t size)
++++++{
++++++ rk_iommu_zap_iova(rk_domain, iova, SPAGE_SIZE);
++++++ if (size > SPAGE_SIZE)
++++++ rk_iommu_zap_iova(rk_domain, iova + size - SPAGE_SIZE,
++++++ SPAGE_SIZE);
++++++}
++++++
static u32 *rk_dte_get_page_table(struct rk_iommu_domain *rk_domain,
dma_addr_t iova)
{
rk_table_flush(page_table, NUM_PT_ENTRIES);
rk_table_flush(dte_addr, 1);
------ /*
------ * Zap the first iova of newly allocated page table so iommu evicts
------ * old cached value of new dte from the iotlb.
------ */
------ rk_iommu_zap_iova(rk_domain, iova, SPAGE_SIZE);
------
done:
pt_phys = rk_dte_pt_address(dte);
return (u32 *)phys_to_virt(pt_phys);
rk_table_flush(pte_addr, pte_count);
++++++ /*
++++++ * Zap the first and last iova to evict from iotlb any previously
++++++ * mapped cachelines holding stale values for its dte and pte.
++++++ * We only zap the first and last iova, since only they could have
++++++ * dte or pte shared with an existing mapping.
++++++ */
++++++ rk_iommu_zap_iova_first_last(rk_domain, iova, size);
++++++
return 0;
unwind:
/* Unmap the range of iovas that we just mapped */
static int rk_iommu_map(struct iommu_domain *domain, unsigned long _iova,
phys_addr_t paddr, size_t size, int prot)
{
- struct rk_iommu_domain *rk_domain = domain->priv;
+ struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
unsigned long flags;
dma_addr_t iova = (dma_addr_t)_iova;
u32 *page_table, *pte_addr;
static size_t rk_iommu_unmap(struct iommu_domain *domain, unsigned long _iova,
size_t size)
{
- struct rk_iommu_domain *rk_domain = domain->priv;
+ struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
unsigned long flags;
dma_addr_t iova = (dma_addr_t)_iova;
phys_addr_t pt_phys;
struct device *dev)
{
struct rk_iommu *iommu;
- struct rk_iommu_domain *rk_domain = domain->priv;
+ struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
unsigned long flags;
int ret;
phys_addr_t dte_addr;
list_add_tail(&iommu->node, &rk_domain->iommus);
spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
------ dev_info(dev, "Attached to iommu domain\n");
++++++ dev_dbg(dev, "Attached to iommu domain\n");
rk_iommu_disable_stall(iommu);
struct device *dev)
{
struct rk_iommu *iommu;
- struct rk_iommu_domain *rk_domain = domain->priv;
+ struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
unsigned long flags;
/* Allow 'virtual devices' (eg drm) to detach from domain */
iommu->domain = NULL;
------ dev_info(dev, "Detached from iommu domain\n");
++++++ dev_dbg(dev, "Detached from iommu domain\n");
}
- static int rk_iommu_domain_init(struct iommu_domain *domain)
+ static struct iommu_domain *rk_iommu_domain_alloc(unsigned type)
{
struct rk_iommu_domain *rk_domain;
+ if (type != IOMMU_DOMAIN_UNMANAGED)
+ return NULL;
+
rk_domain = kzalloc(sizeof(*rk_domain), GFP_KERNEL);
if (!rk_domain)
- return -ENOMEM;
+ return NULL;
/*
* rk32xx iommus use a 2 level pagetable.
spin_lock_init(&rk_domain->dt_lock);
INIT_LIST_HEAD(&rk_domain->iommus);
- domain->priv = rk_domain;
+ return &rk_domain->domain;
- return 0;
err_dt:
kfree(rk_domain);
- return -ENOMEM;
+ return NULL;
}
- static void rk_iommu_domain_destroy(struct iommu_domain *domain)
+ static void rk_iommu_domain_free(struct iommu_domain *domain)
{
- struct rk_iommu_domain *rk_domain = domain->priv;
+ struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
int i;
WARN_ON(!list_empty(&rk_domain->iommus));
}
free_page((unsigned long)rk_domain->dt);
- kfree(domain->priv);
- domain->priv = NULL;
+ kfree(rk_domain);
}
static bool rk_iommu_is_dev_iommu_master(struct device *dev)
}
static const struct iommu_ops rk_iommu_ops = {
- .domain_init = rk_iommu_domain_init,
- .domain_destroy = rk_iommu_domain_destroy,
+ .domain_alloc = rk_iommu_domain_alloc,
+ .domain_free = rk_iommu_domain_free,
.attach_dev = rk_iommu_attach_device,
.detach_dev = rk_iommu_detach_device,
.map = rk_iommu_map,
return 0;
}
-- - -#ifdef CONFIG_OF
static const struct of_device_id rk_iommu_dt_ids[] = {
{ .compatible = "rockchip,iommu" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, rk_iommu_dt_ids);
-- - -#endif
static struct platform_driver rk_iommu_driver = {
.probe = rk_iommu_probe,
.remove = rk_iommu_remove,
.driver = {
.name = "rk_iommu",
-- - - .of_match_table = of_match_ptr(rk_iommu_dt_ids),
++ + + .of_match_table = rk_iommu_dt_ids,
},
};
static int __init rk_iommu_init(void)
{
+ struct device_node *np;
int ret;
+ np = of_find_matching_node(NULL, rk_iommu_dt_ids);
+ if (!np)
+ return 0;
+
+ of_node_put(np);
+
ret = bus_set_iommu(&platform_bus_type, &rk_iommu_ops);
if (ret)
return ret;