diff options
author | Ingo Molnar <mingo@kernel.org> | 2016-03-07 09:27:30 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-03-07 09:27:30 +0100 |
commit | ec87e1cf7d8399d81d8965c6d852f8057a8dd687 (patch) | |
tree | 472a168fa4861090edf110c8a9712a5c15ea259f | |
parent | 869ae76147ffdf21ad24f0e599303cd58a2bb39f (diff) | |
parent | f6cede5b49e822ebc41a099fe41ab4989f64e2cb (diff) | |
download | linux-ec87e1cf7d8399d81d8965c6d852f8057a8dd687.tar.bz2 |
Merge tag 'v4.5-rc7' into x86/asm, to pick up SMAP fix
Signed-off-by: Ingo Molnar <mingo@kernel.org>
649 files changed, 8473 insertions, 5775 deletions
diff --git a/Documentation/DocBook/media/v4l/media-types.xml b/Documentation/DocBook/media/v4l/media-types.xml index 1af384250910..0ee0f3386cdf 100644 --- a/Documentation/DocBook/media/v4l/media-types.xml +++ b/Documentation/DocBook/media/v4l/media-types.xml @@ -57,10 +57,6 @@ <entry>Connector for a RGB composite signal.</entry> </row> <row> - <entry><constant>MEDIA_ENT_F_CONN_TEST</constant></entry> - <entry>Connector for a test generator.</entry> - </row> - <row> <entry><constant>MEDIA_ENT_F_CAM_SENSOR</constant></entry> <entry>Camera video sensor entity.</entry> </row> diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt index ace05992a262..20df350b9ef3 100644 --- a/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt @@ -30,7 +30,7 @@ that they are defined using standard clock bindings with following clock-output-names: - "xin24m" - crystal input - required, - "ext_i2s" - external I2S clock - optional, - - "ext_gmac" - external GMAC clock - optional + - "rmii_clkin" - external EMAC clock - optional Example: Clock controller node: diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt index 7803e77d85cb..007a5b46256a 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt @@ -24,9 +24,8 @@ Main node required properties: 1 = edge triggered 4 = level triggered - Cells 4 and beyond are reserved for future use. When the 1st cell - has a value of 0 or 1, cells 4 and beyond act as padding, and may be - ignored. It is recommended that padding cells have a value of 0. + Cells 4 and beyond are reserved for future use and must have a value + of 0 if present. - reg : Specifies base physical address(s) and size of the GIC registers, in the following order: diff --git a/Documentation/devicetree/bindings/net/renesas,ravb.txt b/Documentation/devicetree/bindings/net/renesas,ravb.txt index 81a9f9e6b45f..c8ac222eac67 100644 --- a/Documentation/devicetree/bindings/net/renesas,ravb.txt +++ b/Documentation/devicetree/bindings/net/renesas,ravb.txt @@ -82,8 +82,8 @@ Example: "ch16", "ch17", "ch18", "ch19", "ch20", "ch21", "ch22", "ch23", "ch24"; - clocks = <&mstp8_clks R8A7795_CLK_ETHERAVB>; - power-domains = <&cpg_clocks>; + clocks = <&cpg CPG_MOD 812>; + power-domains = <&cpg>; phy-mode = "rgmii-id"; phy-handle = <&phy0>; diff --git a/Documentation/devicetree/bindings/regulator/tps65217.txt b/Documentation/devicetree/bindings/regulator/tps65217.txt index d18109657da6..4f05d208c95c 100644 --- a/Documentation/devicetree/bindings/regulator/tps65217.txt +++ b/Documentation/devicetree/bindings/regulator/tps65217.txt @@ -26,11 +26,7 @@ Example: ti,pmic-shutdown-controller; regulators { - #address-cells = <1>; - #size-cells = <0>; - dcdc1_reg: dcdc1 { - reg = <0>; regulator-min-microvolt = <900000>; regulator-max-microvolt = <1800000>; regulator-boot-on; @@ -38,7 +34,6 @@ Example: }; dcdc2_reg: dcdc2 { - reg = <1>; regulator-min-microvolt = <900000>; regulator-max-microvolt = <3300000>; regulator-boot-on; @@ -46,7 +41,6 @@ Example: }; dcdc3_reg: dcc3 { - reg = <2>; regulator-min-microvolt = <900000>; regulator-max-microvolt = <1500000>; regulator-boot-on; @@ -54,7 +48,6 @@ Example: }; ldo1_reg: ldo1 { - reg = <3>; regulator-min-microvolt = <1000000>; regulator-max-microvolt = <3300000>; regulator-boot-on; @@ -62,7 +55,6 @@ Example: }; ldo2_reg: ldo2 { - reg = <4>; regulator-min-microvolt = <900000>; regulator-max-microvolt = <3300000>; regulator-boot-on; @@ -70,7 +62,6 @@ Example: }; ldo3_reg: ldo3 { - reg = <5>; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; regulator-boot-on; @@ -78,7 +69,6 @@ Example: }; ldo4_reg: ldo4 { - reg = <6>; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; regulator-boot-on; diff --git a/Documentation/devicetree/bindings/rtc/s3c-rtc.txt b/Documentation/devicetree/bindings/rtc/s3c-rtc.txt index ac2fcd6ff4b8..1068ffce9f91 100644 --- a/Documentation/devicetree/bindings/rtc/s3c-rtc.txt +++ b/Documentation/devicetree/bindings/rtc/s3c-rtc.txt @@ -14,6 +14,10 @@ Required properties: interrupt number is the rtc alarm interrupt and second interrupt number is the rtc tick interrupt. The number of cells representing a interrupt depends on the parent interrupt controller. +- clocks: Must contain a list of phandle and clock specifier for the rtc + and source clocks. +- clock-names: Must contain "rtc" and "rtc_src" entries sorted in the + same order as the clocks property. Example: @@ -21,4 +25,6 @@ Example: compatible = "samsung,s3c6410-rtc"; reg = <0x10070000 0x100>; interrupts = <44 0 45 0>; + clocks = <&clock CLK_RTC>, <&s2mps11_osc S2MPS11_CLK_AP>; + clock-names = "rtc", "rtc_src"; }; diff --git a/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt b/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt index 35ae1fb3537f..ed94c217c98d 100644 --- a/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt +++ b/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt @@ -9,7 +9,7 @@ Optional properties: - fsl,uart-has-rtscts : Indicate the uart has rts and cts - fsl,irda-mode : Indicate the uart supports irda mode - fsl,dte-mode : Indicate the uart works in DTE mode. The uart works - is DCE mode by default. + in DCE mode by default. Note: Each uart controller should have an alias correctly numbered in "aliases" node. diff --git a/Documentation/watchdog/watchdog-parameters.txt b/Documentation/watchdog/watchdog-parameters.txt index 9f9ec9f76039..4e4b6f10d841 100644 --- a/Documentation/watchdog/watchdog-parameters.txt +++ b/Documentation/watchdog/watchdog-parameters.txt @@ -400,3 +400,7 @@ wm8350_wdt: nowayout: Watchdog cannot be stopped once started (default=kernel config parameter) ------------------------------------------------- +sun4v_wdt: +timeout_ms: Watchdog timeout in milliseconds 1..180000, default=60000) +nowayout: Watchdog cannot be stopped once started +------------------------------------------------- diff --git a/MAINTAINERS b/MAINTAINERS index 28eb61bbecf4..f5e6a535bc34 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -920,17 +920,24 @@ M: Emilio López <emilio@elopez.com.ar> S: Maintained F: drivers/clk/sunxi/ -ARM/Amlogic MesonX SoC support +ARM/Amlogic Meson SoC support M: Carlo Caione <carlo@caione.org> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +L: linux-meson@googlegroups.com +W: http://linux-meson.com/ S: Maintained -F: drivers/media/rc/meson-ir.c -N: meson[x68] +F: arch/arm/mach-meson/ +F: arch/arm/boot/dts/meson* +N: meson ARM/Annapurna Labs ALPINE ARCHITECTURE M: Tsahee Zidenberg <tsahee@annapurnalabs.com> +M: Antoine Tenart <antoine.tenart@free-electrons.com> S: Maintained F: arch/arm/mach-alpine/ +F: arch/arm/boot/dts/alpine* +F: arch/arm64/boot/dts/al/ +F: drivers/*/*alpine* ARM/ATMEL AT91RM9200, AT91SAM9 AND SAMA5 SOC SUPPORT M: Nicolas Ferre <nicolas.ferre@atmel.com> @@ -3444,7 +3451,6 @@ F: drivers/usb/dwc2/ DESIGNWARE USB3 DRD IP DRIVER M: Felipe Balbi <balbi@kernel.org> L: linux-usb@vger.kernel.org -L: linux-omap@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git S: Maintained F: drivers/usb/dwc3/ @@ -4512,6 +4518,12 @@ L: linuxppc-dev@lists.ozlabs.org S: Maintained F: drivers/dma/fsldma.* +FREESCALE GPMI NAND DRIVER +M: Han Xu <han.xu@nxp.com> +L: linux-mtd@lists.infradead.org +S: Maintained +F: drivers/mtd/nand/gpmi-nand/* + FREESCALE I2C CPM DRIVER M: Jochen Friedrich <jochen@scram.de> L: linuxppc-dev@lists.ozlabs.org @@ -4528,7 +4540,7 @@ F: include/linux/platform_data/video-imxfb.h F: drivers/video/fbdev/imxfb.c FREESCALE QUAD SPI DRIVER -M: Han Xu <han.xu@freescale.com> +M: Han Xu <han.xu@nxp.com> L: linux-mtd@lists.infradead.org S: Maintained F: drivers/mtd/spi-nor/fsl-quadspi.c @@ -6128,7 +6140,7 @@ F: include/uapi/linux/sunrpc/ KERNEL SELFTEST FRAMEWORK M: Shuah Khan <shuahkh@osg.samsung.com> -L: linux-api@vger.kernel.org +L: linux-kselftest@vger.kernel.org T: git git://git.kernel.org/pub/scm/shuah/linux-kselftest S: Maintained F: tools/testing/selftests @@ -7354,7 +7366,7 @@ F: drivers/tty/isicom.c F: include/linux/isicom.h MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER -M: Felipe Balbi <balbi@kernel.org> +M: Bin Liu <b-liu@ti.com> L: linux-usb@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git S: Maintained @@ -7686,13 +7698,13 @@ S: Maintained F: arch/nios2/ NOKIA N900 POWER SUPPLY DRIVERS -M: Pali Rohár <pali.rohar@gmail.com> -S: Maintained +R: Pali Rohár <pali.rohar@gmail.com> F: include/linux/power/bq2415x_charger.h F: include/linux/power/bq27xxx_battery.h F: include/linux/power/isp1704_charger.h F: drivers/power/bq2415x_charger.c F: drivers/power/bq27xxx_battery.c +F: drivers/power/bq27xxx_battery_i2c.c F: drivers/power/isp1704_charger.c F: drivers/power/rx51_battery.c @@ -7923,11 +7935,9 @@ F: drivers/media/platform/omap3isp/ F: drivers/staging/media/omap4iss/ OMAP USB SUPPORT -M: Felipe Balbi <balbi@kernel.org> L: linux-usb@vger.kernel.org L: linux-omap@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git -S: Maintained +S: Orphan F: drivers/usb/*/*omap* F: arch/arm/*omap*/usb* @@ -9558,6 +9568,12 @@ M: Andreas Noever <andreas.noever@gmail.com> S: Maintained F: drivers/thunderbolt/ +TI BQ27XXX POWER SUPPLY DRIVER +R: Andrew F. Davis <afd@ti.com> +F: include/linux/power/bq27xxx_battery.h +F: drivers/power/bq27xxx_battery.c +F: drivers/power/bq27xxx_battery_i2c.c + TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER M: John Stultz <john.stultz@linaro.org> M: Thomas Gleixner <tglx@linutronix.de> @@ -12013,7 +12029,6 @@ F: arch/arm64/xen/ F: arch/arm64/include/asm/xen/ XEN NETWORK BACKEND DRIVER -M: Ian Campbell <ian.campbell@citrix.com> M: Wei Liu <wei.liu2@citrix.com> L: xen-devel@lists.xenproject.org (moderated for non-subscribers) L: netdev@vger.kernel.org @@ -1,7 +1,7 @@ VERSION = 4 PATCHLEVEL = 5 SUBLEVEL = 0 -EXTRAVERSION = -rc4 +EXTRAVERSION = -rc7 NAME = Blurry Fish Butt # *DOCUMENTATION* diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 0655495470ad..8a188bc1786a 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -12,8 +12,6 @@ config ARC select BUILDTIME_EXTABLE_SORT select COMMON_CLK select CLONE_BACKWARDS - # ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev - select DEVTMPFS if !INITRAMFS_SOURCE="" select GENERIC_ATOMIC64 select GENERIC_CLOCKEVENTS select GENERIC_FIND_FIRST_BIT @@ -275,14 +273,6 @@ config ARC_DCCM_BASE default "0xA0000000" depends on ARC_HAS_DCCM -config ARC_HAS_HW_MPY - bool "Use Hardware Multiplier (Normal or Faster XMAC)" - default y - help - Influences how gcc generates code for MPY operations. - If enabled, MPYxx insns are generated, provided by Standard/XMAC - Multipler. Otherwise software multipy lib is used - choice prompt "MMU Version" default ARC_MMU_V3 if ARC_CPU_770 @@ -542,14 +532,6 @@ config ARC_DBG_TLB_MISS_COUNT Counts number of I and D TLB Misses and exports them via Debugfs The counters can be cleared via Debugfs as well -if SMP - -config ARC_IPI_DBG - bool "Debug Inter Core interrupts" - default n - -endif - endif config ARC_UBOOT_SUPPORT diff --git a/arch/arc/Makefile b/arch/arc/Makefile index aeb19021099e..c8230f3395f2 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile @@ -74,10 +74,6 @@ ldflags-$(CONFIG_CPU_BIG_ENDIAN) += -EB # --build-id w/o "-marclinux". Default arc-elf32-ld is OK ldflags-$(upto_gcc44) += -marclinux -ifndef CONFIG_ARC_HAS_HW_MPY - cflags-y += -mno-mpy -endif - LIBGCC := $(shell $(CC) $(cflags-y) --print-libgcc-file-name) # Modules with short calls might break for calls into builtin-kernel diff --git a/arch/arc/configs/axs101_defconfig b/arch/arc/configs/axs101_defconfig index f1ac9818b751..5d4e2a07ad3e 100644 --- a/arch/arc/configs/axs101_defconfig +++ b/arch/arc/configs/axs101_defconfig @@ -39,6 +39,7 @@ CONFIG_IP_PNP_RARP=y # CONFIG_INET_XFRM_MODE_TUNNEL is not set # CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_IPV6 is not set +CONFIG_DEVTMPFS=y # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set # CONFIG_FIRMWARE_IN_KERNEL is not set @@ -73,7 +74,6 @@ CONFIG_I2C_CHARDEV=y CONFIG_I2C_DESIGNWARE_PLATFORM=y # CONFIG_HWMON is not set CONFIG_FB=y -# CONFIG_VGA_CONSOLE is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y CONFIG_LOGO=y @@ -91,12 +91,10 @@ CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_DW=y # CONFIG_IOMMU_SUPPORT is not set CONFIG_EXT3_FS=y -CONFIG_EXT4_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_NTFS_FS=y CONFIG_TMPFS=y -CONFIG_JFFS2_FS=y CONFIG_NFS_FS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y diff --git a/arch/arc/configs/axs103_defconfig b/arch/arc/configs/axs103_defconfig index 323486d6ee83..87ee46b237ef 100644 --- a/arch/arc/configs/axs103_defconfig +++ b/arch/arc/configs/axs103_defconfig @@ -39,14 +39,10 @@ CONFIG_IP_PNP_RARP=y # CONFIG_INET_XFRM_MODE_TUNNEL is not set # CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_IPV6 is not set +CONFIG_DEVTMPFS=y # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set # CONFIG_FIRMWARE_IN_KERNEL is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_AXS=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_NETDEVICES=y @@ -78,14 +74,12 @@ CONFIG_I2C_CHARDEV=y CONFIG_I2C_DESIGNWARE_PLATFORM=y # CONFIG_HWMON is not set CONFIG_FB=y -# CONFIG_VGA_CONSOLE is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set # CONFIG_LOGO_LINUX_CLUT224 is not set -CONFIG_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD_PLATFORM=y CONFIG_USB_OHCI_HCD=y @@ -97,12 +91,10 @@ CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_DW=y # CONFIG_IOMMU_SUPPORT is not set CONFIG_EXT3_FS=y -CONFIG_EXT4_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_NTFS_FS=y CONFIG_TMPFS=y -CONFIG_JFFS2_FS=y CONFIG_NFS_FS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y diff --git a/arch/arc/configs/axs103_smp_defconfig b/arch/arc/configs/axs103_smp_defconfig index 66191cd0447e..d80daf4f7e73 100644 --- a/arch/arc/configs/axs103_smp_defconfig +++ b/arch/arc/configs/axs103_smp_defconfig @@ -40,14 +40,10 @@ CONFIG_IP_PNP_RARP=y # CONFIG_INET_XFRM_MODE_TUNNEL is not set # CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_IPV6 is not set +CONFIG_DEVTMPFS=y # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set # CONFIG_FIRMWARE_IN_KERNEL is not set -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_AXS=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_NETDEVICES=y @@ -79,14 +75,12 @@ CONFIG_I2C_CHARDEV=y CONFIG_I2C_DESIGNWARE_PLATFORM=y # CONFIG_HWMON is not set CONFIG_FB=y -# CONFIG_VGA_CONSOLE is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set # CONFIG_LOGO_LINUX_CLUT224 is not set -CONFIG_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD_PLATFORM=y CONFIG_USB_OHCI_HCD=y @@ -98,12 +92,10 @@ CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_DW=y # CONFIG_IOMMU_SUPPORT is not set CONFIG_EXT3_FS=y -CONFIG_EXT4_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_NTFS_FS=y CONFIG_TMPFS=y -CONFIG_JFFS2_FS=y CONFIG_NFS_FS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y diff --git a/arch/arc/configs/nsim_700_defconfig b/arch/arc/configs/nsim_700_defconfig index 138f9d887957..f41095340b6a 100644 --- a/arch/arc/configs/nsim_700_defconfig +++ b/arch/arc/configs/nsim_700_defconfig @@ -4,6 +4,7 @@ CONFIG_DEFAULT_HOSTNAME="ARCLinux" # CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y +# CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_HIGH_RES_TIMERS=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y @@ -26,7 +27,6 @@ CONFIG_ARC_PLAT_SIM=y CONFIG_ARC_BUILTIN_DTB_NAME="nsim_700" CONFIG_PREEMPT=y # CONFIG_COMPACTION is not set -# CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -34,6 +34,7 @@ CONFIG_UNIX_DIAG=y CONFIG_NET_KEY=y CONFIG_INET=y # CONFIG_IPV6 is not set +CONFIG_DEVTMPFS=y # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set # CONFIG_FIRMWARE_IN_KERNEL is not set @@ -51,7 +52,6 @@ CONFIG_SERIAL_ARC=y CONFIG_SERIAL_ARC_CONSOLE=y # CONFIG_HW_RANDOM is not set # CONFIG_HWMON is not set -# CONFIG_VGA_CONSOLE is not set # CONFIG_HID is not set # CONFIG_USB_SUPPORT is not set # CONFIG_IOMMU_SUPPORT is not set @@ -63,4 +63,3 @@ CONFIG_NFS_FS=y # CONFIG_ENABLE_WARN_DEPRECATED is not set # CONFIG_ENABLE_MUST_CHECK is not set # CONFIG_DEBUG_PREEMPT is not set -CONFIG_XZ_DEC=y diff --git a/arch/arc/configs/nsim_hs_defconfig b/arch/arc/configs/nsim_hs_defconfig index f68838e8068a..cfaa33cb5921 100644 --- a/arch/arc/configs/nsim_hs_defconfig +++ b/arch/arc/configs/nsim_hs_defconfig @@ -35,6 +35,7 @@ CONFIG_UNIX_DIAG=y CONFIG_NET_KEY=y CONFIG_INET=y # CONFIG_IPV6 is not set +CONFIG_DEVTMPFS=y # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set # CONFIG_FIRMWARE_IN_KERNEL is not set @@ -49,7 +50,6 @@ CONFIG_SERIAL_ARC=y CONFIG_SERIAL_ARC_CONSOLE=y # CONFIG_HW_RANDOM is not set # CONFIG_HWMON is not set -# CONFIG_VGA_CONSOLE is not set # CONFIG_HID is not set # CONFIG_USB_SUPPORT is not set # CONFIG_IOMMU_SUPPORT is not set @@ -61,4 +61,3 @@ CONFIG_NFS_FS=y # CONFIG_ENABLE_WARN_DEPRECATED is not set # CONFIG_ENABLE_MUST_CHECK is not set # CONFIG_DEBUG_PREEMPT is not set -CONFIG_XZ_DEC=y diff --git a/arch/arc/configs/nsim_hs_smp_defconfig b/arch/arc/configs/nsim_hs_smp_defconfig index 96bd1c20fb0b..bb2a8dc778b5 100644 --- a/arch/arc/configs/nsim_hs_smp_defconfig +++ b/arch/arc/configs/nsim_hs_smp_defconfig @@ -2,6 +2,7 @@ CONFIG_CROSS_COMPILE="arc-linux-" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="ARCLinux" # CONFIG_SWAP is not set +# CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_HIGH_RES_TIMERS=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y @@ -21,13 +22,11 @@ CONFIG_MODULES=y # CONFIG_IOSCHED_DEADLINE is not set # CONFIG_IOSCHED_CFQ is not set CONFIG_ARC_PLAT_SIM=y -CONFIG_ARC_BOARD_ML509=y CONFIG_ISA_ARCV2=y CONFIG_SMP=y CONFIG_ARC_BUILTIN_DTB_NAME="nsim_hs_idu" CONFIG_PREEMPT=y # CONFIG_COMPACTION is not set -# CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -35,6 +34,7 @@ CONFIG_UNIX_DIAG=y CONFIG_NET_KEY=y CONFIG_INET=y # CONFIG_IPV6 is not set +CONFIG_DEVTMPFS=y # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set # CONFIG_FIRMWARE_IN_KERNEL is not set @@ -49,7 +49,6 @@ CONFIG_SERIAL_ARC=y CONFIG_SERIAL_ARC_CONSOLE=y # CONFIG_HW_RANDOM is not set # CONFIG_HWMON is not set -# CONFIG_VGA_CONSOLE is not set # CONFIG_HID is not set # CONFIG_USB_SUPPORT is not set # CONFIG_IOMMU_SUPPORT is not set @@ -60,4 +59,3 @@ CONFIG_TMPFS=y CONFIG_NFS_FS=y # CONFIG_ENABLE_WARN_DEPRECATED is not set # CONFIG_ENABLE_MUST_CHECK is not set -CONFIG_XZ_DEC=y diff --git a/arch/arc/configs/nsimosci_defconfig b/arch/arc/configs/nsimosci_defconfig index 31e1d95764ff..646182e93753 100644 --- a/arch/arc/configs/nsimosci_defconfig +++ b/arch/arc/configs/nsimosci_defconfig @@ -33,6 +33,7 @@ CONFIG_UNIX_DIAG=y CONFIG_NET_KEY=y CONFIG_INET=y # CONFIG_IPV6 is not set +CONFIG_DEVTMPFS=y # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set # CONFIG_FIRMWARE_IN_KERNEL is not set @@ -58,7 +59,6 @@ CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set # CONFIG_HWMON is not set CONFIG_FB=y -# CONFIG_VGA_CONSOLE is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y # CONFIG_HID is not set diff --git a/arch/arc/configs/nsimosci_hs_defconfig b/arch/arc/configs/nsimosci_hs_defconfig index fcae66683ca0..ceca2541950d 100644 --- a/arch/arc/configs/nsimosci_hs_defconfig +++ b/arch/arc/configs/nsimosci_hs_defconfig @@ -34,12 +34,12 @@ CONFIG_UNIX_DIAG=y CONFIG_NET_KEY=y CONFIG_INET=y # CONFIG_IPV6 is not set +CONFIG_DEVTMPFS=y # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set # CONFIG_FIRMWARE_IN_KERNEL is not set # CONFIG_BLK_DEV is not set CONFIG_NETDEVICES=y -CONFIG_NET_OSCI_LAN=y CONFIG_INPUT_EVDEV=y # CONFIG_MOUSE_PS2_ALPS is not set # CONFIG_MOUSE_PS2_LOGIPS2PP is not set @@ -58,7 +58,6 @@ CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set # CONFIG_HWMON is not set CONFIG_FB=y -# CONFIG_VGA_CONSOLE is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y # CONFIG_HID is not set diff --git a/arch/arc/configs/nsimosci_hs_smp_defconfig b/arch/arc/configs/nsimosci_hs_smp_defconfig index b01b659168ea..4b6da90f6f26 100644 --- a/arch/arc/configs/nsimosci_hs_smp_defconfig +++ b/arch/arc/configs/nsimosci_hs_smp_defconfig @@ -2,6 +2,7 @@ CONFIG_CROSS_COMPILE="arc-linux-" CONFIG_DEFAULT_HOSTNAME="ARCLinux" # CONFIG_SWAP is not set CONFIG_SYSVIPC=y +# CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_IKCONFIG=y @@ -18,15 +19,11 @@ CONFIG_MODULES=y # CONFIG_IOSCHED_DEADLINE is not set # CONFIG_IOSCHED_CFQ is not set CONFIG_ARC_PLAT_SIM=y -CONFIG_ARC_BOARD_ML509=y CONFIG_ISA_ARCV2=y CONFIG_SMP=y -CONFIG_ARC_HAS_LL64=y -# CONFIG_ARC_HAS_RTSC is not set CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci_hs_idu" CONFIG_PREEMPT=y # CONFIG_COMPACTION is not set -# CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_NET=y CONFIG_PACKET=y CONFIG_PACKET_DIAG=y @@ -40,6 +37,7 @@ CONFIG_INET=y # CONFIG_INET_LRO is not set # CONFIG_IPV6 is not set # CONFIG_WIRELESS is not set +CONFIG_DEVTMPFS=y # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set # CONFIG_FIRMWARE_IN_KERNEL is not set @@ -56,14 +54,11 @@ CONFIG_NETDEVICES=y # CONFIG_NET_VENDOR_STMICRO is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set -CONFIG_NET_OSCI_LAN=y # CONFIG_WLAN is not set CONFIG_INPUT_EVDEV=y CONFIG_MOUSE_PS2_TOUCHKIT=y # CONFIG_SERIO_SERPORT is not set -CONFIG_SERIO_LIBPS2=y CONFIG_SERIO_ARC_PS2=y -CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_LEGACY_PTYS is not set # CONFIG_DEVKMEM is not set CONFIG_SERIAL_8250=y @@ -75,9 +70,6 @@ CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set # CONFIG_HWMON is not set CONFIG_FB=y -CONFIG_ARCPGU_RGB888=y -CONFIG_ARCPGU_DISPTYPE=0 -# CONFIG_VGA_CONSOLE is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y # CONFIG_HID is not set diff --git a/arch/arc/configs/tb10x_defconfig b/arch/arc/configs/tb10x_defconfig index 3b4dc9cebcf1..9b342eaf95ae 100644 --- a/arch/arc/configs/tb10x_defconfig +++ b/arch/arc/configs/tb10x_defconfig @@ -3,6 +3,7 @@ CONFIG_CROSS_COMPILE="arc-linux-" CONFIG_DEFAULT_HOSTNAME="tb10x" CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y +# CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_HIGH_RES_TIMERS=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y @@ -26,12 +27,10 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_BLOCK is not set CONFIG_ARC_PLAT_TB10X=y CONFIG_ARC_CACHE_LINE_SHIFT=5 -CONFIG_ARC_STACK_NONEXEC=y CONFIG_HZ=250 CONFIG_ARC_BUILTIN_DTB_NAME="abilis_tb100_dvk" CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_COMPACTION is not set -# CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -44,8 +43,8 @@ CONFIG_IP_MULTICAST=y # CONFIG_INET_DIAG is not set # CONFIG_IPV6 is not set # CONFIG_WIRELESS is not set +CONFIG_DEVTMPFS=y # CONFIG_FIRMWARE_IN_KERNEL is not set -CONFIG_PROC_DEVICETREE=y CONFIG_NETDEVICES=y # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set @@ -55,9 +54,6 @@ CONFIG_NETDEVICES=y # CONFIG_NET_VENDOR_NATSEMI is not set # CONFIG_NET_VENDOR_SEEQ is not set CONFIG_STMMAC_ETH=y -CONFIG_STMMAC_DEBUG_FS=y -CONFIG_STMMAC_DA=y -CONFIG_STMMAC_CHAINED=y # CONFIG_NET_VENDOR_WIZNET is not set # CONFIG_WLAN is not set # CONFIG_INPUT is not set @@ -91,7 +87,6 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y CONFIG_LEDS_TRIGGER_TRANSIENT=y CONFIG_DMADEVICES=y CONFIG_DW_DMAC=y -CONFIG_NET_DMA=y CONFIG_ASYNC_TX_DMA=y # CONFIG_IOMMU_SUPPORT is not set # CONFIG_DNOTIFY is not set @@ -100,17 +95,16 @@ CONFIG_TMPFS=y CONFIG_CONFIGFS_FS=y # CONFIG_MISC_FILESYSTEMS is not set # CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_DEBUG_INFO=y # CONFIG_ENABLE_WARN_DEPRECATED is not set -CONFIG_MAGIC_SYSRQ=y CONFIG_STRIP_ASM_SYMS=y CONFIG_DEBUG_FS=y CONFIG_HEADERS_CHECK=y CONFIG_DEBUG_SECTION_MISMATCH=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DEBUG_STACKOVERFLOW=y CONFIG_DETECT_HUNG_TASK=y CONFIG_SCHEDSTATS=y CONFIG_TIMER_STATS=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_MEMORY_INIT=y -CONFIG_DEBUG_STACKOVERFLOW=y -# CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index fdc5be5b1029..f9f4c6f59fdb 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -10,7 +10,8 @@ #define _ASM_ARC_ARCREGS_H /* Build Configuration Registers */ -#define ARC_REG_DCCMBASE_BCR 0x61 /* DCCM Base Addr */ +#define ARC_REG_AUX_DCCM 0x18 /* DCCM Base Addr ARCv2 */ +#define ARC_REG_DCCM_BASE_BUILD 0x61 /* DCCM Base Addr ARCompact */ #define ARC_REG_CRC_BCR 0x62 #define ARC_REG_VECBASE_BCR 0x68 #define ARC_REG_PERIBASE_BCR 0x69 @@ -18,10 +19,10 @@ #define ARC_REG_DPFP_BCR 0x6C /* ARCompact: Dbl Precision FPU */ #define ARC_REG_FP_V2_BCR 0xc8 /* ARCv2 FPU */ #define ARC_REG_SLC_BCR 0xce -#define ARC_REG_DCCM_BCR 0x74 /* DCCM Present + SZ */ +#define ARC_REG_DCCM_BUILD 0x74 /* DCCM size (common) */ #define ARC_REG_TIMERS_BCR 0x75 #define ARC_REG_AP_BCR 0x76 -#define ARC_REG_ICCM_BCR 0x78 +#define ARC_REG_ICCM_BUILD 0x78 /* ICCM size (common) */ #define ARC_REG_XY_MEM_BCR 0x79 #define ARC_REG_MAC_BCR 0x7a #define ARC_REG_MUL_BCR 0x7b @@ -36,6 +37,7 @@ #define ARC_REG_IRQ_BCR 0xF3 #define ARC_REG_SMART_BCR 0xFF #define ARC_REG_CLUSTER_BCR 0xcf +#define ARC_REG_AUX_ICCM 0x208 /* ICCM Base Addr (ARCv2) */ /* status32 Bits Positions */ #define STATUS_AE_BIT 5 /* Exception active */ @@ -246,7 +248,7 @@ struct bcr_perip { #endif }; -struct bcr_iccm { +struct bcr_iccm_arcompact { #ifdef CONFIG_CPU_BIG_ENDIAN unsigned int base:16, pad:5, sz:3, ver:8; #else @@ -254,17 +256,15 @@ struct bcr_iccm { #endif }; -/* DCCM Base Address Register: ARC_REG_DCCMBASE_BCR */ -struct bcr_dccm_base { +struct bcr_iccm_arcv2 { #ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int addr:24, ver:8; + unsigned int pad:8, sz11:4, sz01:4, sz10:4, sz00:4, ver:8; #else - unsigned int ver:8, addr:24; + unsigned int ver:8, sz00:4, sz10:4, sz01:4, sz11:4, pad:8; #endif }; -/* DCCM RAM Configuration Register: ARC_REG_DCCM_BCR */ -struct bcr_dccm { +struct bcr_dccm_arcompact { #ifdef CONFIG_CPU_BIG_ENDIAN unsigned int res:21, sz:3, ver:8; #else @@ -272,6 +272,14 @@ struct bcr_dccm { #endif }; +struct bcr_dccm_arcv2 { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad2:12, cyc:3, pad1:1, sz1:4, sz0:4, ver:8; +#else + unsigned int ver:8, sz0:4, sz1:4, pad1:1, cyc:3, pad2:12; +#endif +}; + /* ARCompact: Both SP and DP FPU BCRs have same format */ struct bcr_fp_arcompact { #ifdef CONFIG_CPU_BIG_ENDIAN @@ -315,9 +323,9 @@ struct bcr_bpu_arcv2 { struct bcr_generic { #ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:24, ver:8; + unsigned int info:24, ver:8; #else - unsigned int ver:8, pad:24; + unsigned int ver:8, info:24; #endif }; diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h index 4fd7d62a6e30..49014f0ef36d 100644 --- a/arch/arc/include/asm/irq.h +++ b/arch/arc/include/asm/irq.h @@ -16,11 +16,9 @@ #ifdef CONFIG_ISA_ARCOMPACT #define TIMER0_IRQ 3 #define TIMER1_IRQ 4 -#define IPI_IRQ (NR_CPU_IRQS-1) /* dummy to enable SMP build for up hardware */ #else #define TIMER0_IRQ 16 #define TIMER1_IRQ 17 -#define IPI_IRQ 19 #endif #include <linux/interrupt.h> diff --git a/arch/arc/include/asm/irqflags-arcv2.h b/arch/arc/include/asm/irqflags-arcv2.h index 1fc18ee06cf2..37c2f751eebf 100644 --- a/arch/arc/include/asm/irqflags-arcv2.h +++ b/arch/arc/include/asm/irqflags-arcv2.h @@ -22,6 +22,7 @@ #define AUX_IRQ_CTRL 0x00E #define AUX_IRQ_ACT 0x043 /* Active Intr across all levels */ #define AUX_IRQ_LVL_PEND 0x200 /* Pending Intr across all levels */ +#define AUX_IRQ_HINT 0x201 /* For generating Soft Interrupts */ #define AUX_IRQ_PRIORITY 0x206 #define ICAUSE 0x40a #define AUX_IRQ_SELECT 0x40b @@ -115,6 +116,16 @@ static inline int arch_irqs_disabled(void) return arch_irqs_disabled_flags(arch_local_save_flags()); } +static inline void arc_softirq_trigger(int irq) +{ + write_aux_reg(AUX_IRQ_HINT, irq); +} + +static inline void arc_softirq_clear(int irq) +{ + write_aux_reg(AUX_IRQ_HINT, 0); +} + #else .macro IRQ_DISABLE scratch diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S index b17830294706..c1264607bbff 100644 --- a/arch/arc/kernel/entry-arcv2.S +++ b/arch/arc/kernel/entry-arcv2.S @@ -45,11 +45,12 @@ VECTOR reserved ; Reserved slots VECTOR handle_interrupt ; (16) Timer0 VECTOR handle_interrupt ; unused (Timer1) VECTOR handle_interrupt ; unused (WDT) -VECTOR handle_interrupt ; (19) ICI (inter core interrupt) -VECTOR handle_interrupt -VECTOR handle_interrupt -VECTOR handle_interrupt -VECTOR handle_interrupt ; (23) End of fixed IRQs +VECTOR handle_interrupt ; (19) Inter core Interrupt (IPI) +VECTOR handle_interrupt ; (20) perf Interrupt +VECTOR handle_interrupt ; (21) Software Triggered Intr (Self IPI) +VECTOR handle_interrupt ; unused +VECTOR handle_interrupt ; (23) unused +# End of fixed IRQs .rept CONFIG_ARC_NUMBER_OF_INTERRUPTS - 8 VECTOR handle_interrupt diff --git a/arch/arc/kernel/intc-compact.c b/arch/arc/kernel/intc-compact.c index 06bcedf19b62..224d1c3aa9c4 100644 --- a/arch/arc/kernel/intc-compact.c +++ b/arch/arc/kernel/intc-compact.c @@ -81,9 +81,6 @@ static int arc_intc_domain_map(struct irq_domain *d, unsigned int irq, { switch (irq) { case TIMER0_IRQ: -#ifdef CONFIG_SMP - case IPI_IRQ: -#endif irq_set_chip_and_handler(irq, &onchip_intc, handle_percpu_irq); break; default: diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c index bc771f58fefb..c41c364b926c 100644 --- a/arch/arc/kernel/mcip.c +++ b/arch/arc/kernel/mcip.c @@ -11,9 +11,13 @@ #include <linux/smp.h> #include <linux/irq.h> #include <linux/spinlock.h> +#include <asm/irqflags-arcv2.h> #include <asm/mcip.h> #include <asm/setup.h> +#define IPI_IRQ 19 +#define SOFTIRQ_IRQ 21 + static char smp_cpuinfo_buf[128]; static int idu_detected; @@ -22,6 +26,7 @@ static DEFINE_RAW_SPINLOCK(mcip_lock); static void mcip_setup_per_cpu(int cpu) { smp_ipi_irq_setup(cpu, IPI_IRQ); + smp_ipi_irq_setup(cpu, SOFTIRQ_IRQ); } static void mcip_ipi_send(int cpu) @@ -29,46 +34,44 @@ static void mcip_ipi_send(int cpu) unsigned long flags; int ipi_was_pending; + /* ARConnect can only send IPI to others */ + if (unlikely(cpu == raw_smp_processor_id())) { + arc_softirq_trigger(SOFTIRQ_IRQ); + return; + } + + raw_spin_lock_irqsave(&mcip_lock, flags); + /* - * NOTE: We must spin here if the other cpu hasn't yet - * serviced a previous message. This can burn lots - * of time, but we MUST follows this protocol or - * ipi messages can be lost!!! - * Also, we must release the lock in this loop because - * the other side may get to this same loop and not - * be able to ack -- thus causing deadlock. + * If receiver already has a pending interrupt, elide sending this one. + * Linux cross core calling works well with concurrent IPIs + * coalesced into one + * see arch/arc/kernel/smp.c: ipi_send_msg_one() */ + __mcip_cmd(CMD_INTRPT_READ_STATUS, cpu); + ipi_was_pending = read_aux_reg(ARC_REG_MCIP_READBACK); + if (!ipi_was_pending) + __mcip_cmd(CMD_INTRPT_GENERATE_IRQ, cpu); - do { - raw_spin_lock_irqsave(&mcip_lock, flags); - __mcip_cmd(CMD_INTRPT_READ_STATUS, cpu); - ipi_was_pending = read_aux_reg(ARC_REG_MCIP_READBACK); - if (ipi_was_pending == 0) - break; /* break out but keep lock */ - raw_spin_unlock_irqrestore(&mcip_lock, flags); - } while (1); - - __mcip_cmd(CMD_INTRPT_GENERATE_IRQ, cpu); raw_spin_unlock_irqrestore(&mcip_lock, flags); - -#ifdef CONFIG_ARC_IPI_DBG - if (ipi_was_pending) - pr_info("IPI ACK delayed from cpu %d\n", cpu); -#endif } static void mcip_ipi_clear(int irq) { unsigned int cpu, c; unsigned long flags; - unsigned int __maybe_unused copy; + + if (unlikely(irq == SOFTIRQ_IRQ)) { + arc_softirq_clear(irq); + return; + } raw_spin_lock_irqsave(&mcip_lock, flags); /* Who sent the IPI */ __mcip_cmd(CMD_INTRPT_CHECK_SOURCE, 0); - copy = cpu = read_aux_reg(ARC_REG_MCIP_READBACK); /* 1,2,4,8... */ + cpu = read_aux_reg(ARC_REG_MCIP_READBACK); /* 1,2,4,8... */ /* * In rare case, multiple concurrent IPIs sent to same target can @@ -82,12 +85,6 @@ static void mcip_ipi_clear(int irq) } while (cpu); raw_spin_unlock_irqrestore(&mcip_lock, flags); - -#ifdef CONFIG_ARC_IPI_DBG - if (c != __ffs(copy)) - pr_info("IPIs from %x coalesced to %x\n", - copy, raw_smp_processor_id()); -#endif } static void mcip_probe_n_setup(void) @@ -111,10 +108,11 @@ static void mcip_probe_n_setup(void) READ_BCR(ARC_REG_MCIP_BCR, mp); sprintf(smp_cpuinfo_buf, - "Extn [SMP]\t: ARConnect (v%d): %d cores with %s%s%s%s\n", + "Extn [SMP]\t: ARConnect (v%d): %d cores with %s%s%s%s%s\n", mp.ver, mp.num_cores, IS_AVAIL1(mp.ipi, "IPI "), IS_AVAIL1(mp.idu, "IDU "), + IS_AVAIL1(mp.llm, "LLM "), IS_AVAIL1(mp.dbg, "DEBUG "), IS_AVAIL1(mp.gfrc, "GFRC")); diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index a7edceba5f84..cdc821df1809 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -42,6 +42,53 @@ struct task_struct *_current_task[NR_CPUS]; /* For stack switching */ struct cpuinfo_arc cpuinfo_arc700[NR_CPUS]; +static void read_decode_ccm_bcr(struct cpuinfo_arc *cpu) +{ + if (is_isa_arcompact()) { + struct bcr_iccm_arcompact iccm; + struct bcr_dccm_arcompact dccm; + + READ_BCR(ARC_REG_ICCM_BUILD, iccm); + if (iccm.ver) { + cpu->iccm.sz = 4096 << iccm.sz; /* 8K to 512K */ + cpu->iccm.base_addr = iccm.base << 16; + } + + READ_BCR(ARC_REG_DCCM_BUILD, dccm); + if (dccm.ver) { + unsigned long base; + cpu->dccm.sz = 2048 << dccm.sz; /* 2K to 256K */ + + base = read_aux_reg(ARC_REG_DCCM_BASE_BUILD); + cpu->dccm.base_addr = base & ~0xF; + } + } else { + struct bcr_iccm_arcv2 iccm; + struct bcr_dccm_arcv2 dccm; + unsigned long region; + + READ_BCR(ARC_REG_ICCM_BUILD, iccm); + if (iccm.ver) { + cpu->iccm.sz = 256 << iccm.sz00; /* 512B to 16M */ + if (iccm.sz00 == 0xF && iccm.sz01 > 0) + cpu->iccm.sz <<= iccm.sz01; + + region = read_aux_reg(ARC_REG_AUX_ICCM); + cpu->iccm.base_addr = region & 0xF0000000; + } + + READ_BCR(ARC_REG_DCCM_BUILD, dccm); + if (dccm.ver) { + cpu->dccm.sz = 256 << dccm.sz0; + if (dccm.sz0 == 0xF && dccm.sz1 > 0) + cpu->dccm.sz <<= dccm.sz1; + + region = read_aux_reg(ARC_REG_AUX_DCCM); + cpu->dccm.base_addr = region & 0xF0000000; + } + } +} + static void read_arc_build_cfg_regs(void) { struct bcr_perip uncached_space; @@ -76,36 +123,11 @@ static void read_arc_build_cfg_regs(void) cpu->extn.swap = read_aux_reg(ARC_REG_SWAP_BCR) ? 1 : 0; /* 1,3 */ cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR) ? 1 : 0; cpu->extn.minmax = read_aux_reg(ARC_REG_MIXMAX_BCR) > 1 ? 1 : 0; /* 2 */ - - /* Note that we read the CCM BCRs independent of kernel config - * This is to catch the cases where user doesn't know that - * CCMs are present in hardware build - */ - { - struct bcr_iccm iccm; - struct bcr_dccm dccm; - struct bcr_dccm_base dccm_base; - unsigned int bcr_32bit_val; - - bcr_32bit_val = read_aux_reg(ARC_REG_ICCM_BCR); - if (bcr_32bit_val) { - iccm = *((struct bcr_iccm *)&bcr_32bit_val); - cpu->iccm.base_addr = iccm.base << 16; - cpu->iccm.sz = 0x2000 << (iccm.sz - 1); - } - - bcr_32bit_val = read_aux_reg(ARC_REG_DCCM_BCR); - if (bcr_32bit_val) { - dccm = *((struct bcr_dccm *)&bcr_32bit_val); - cpu->dccm.sz = 0x800 << (dccm.sz); - - READ_BCR(ARC_REG_DCCMBASE_BCR, dccm_base); - cpu->dccm.base_addr = dccm_base.addr << 8; - } - } - READ_BCR(ARC_REG_XY_MEM_BCR, cpu->extn_xymem); + /* Read CCM BCRs for boot reporting even if not enabled in Kconfig */ + read_decode_ccm_bcr(cpu); + read_decode_mmu_bcr(); read_decode_cache_bcr(); @@ -237,8 +259,6 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len) n += scnprintf(buf + n, len - n, "mpy[opt %d] ", opt); } - n += scnprintf(buf + n, len - n, "%s", - IS_USED_CFG(CONFIG_ARC_HAS_HW_MPY)); } n += scnprintf(buf + n, len - n, "%s%s%s%s%s%s%s%s\n", diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c index ef6e9e15b82a..424e937da5c8 100644 --- a/arch/arc/kernel/smp.c +++ b/arch/arc/kernel/smp.c @@ -336,11 +336,8 @@ irqreturn_t do_IPI(int irq, void *dev_id) int rc; rc = __do_IPI(msg); -#ifdef CONFIG_ARC_IPI_DBG - /* IPI received but no valid @msg */ if (rc) pr_info("IPI with bogus msg %ld in %ld\n", msg, copy); -#endif pending &= ~(1U << msg); } while (pending); diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 7a6a58ef8aaf..43788b1a1ac5 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -195,5 +195,7 @@ CFLAGS_font.o := -Dstatic= $(obj)/font.c: $(FONTC) $(call cmd,shipped) +AFLAGS_hyp-stub.o := -Wa,-march=armv7-a + $(obj)/hyp-stub.S: $(srctree)/arch/$(SRCARCH)/kernel/hyp-stub.S $(call cmd,shipped) diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi index f3db13d2d90e..0cc150b87b86 100644 --- a/arch/arm/boot/dts/am335x-bone-common.dtsi +++ b/arch/arm/boot/dts/am335x-bone-common.dtsi @@ -285,8 +285,10 @@ }; }; + +/include/ "tps65217.dtsi" + &tps { - compatible = "ti,tps65217"; /* * Configure pmic to enter OFF-state instead of SLEEP-state ("RTC-only * mode") at poweroff. Most BeagleBone versions do not support RTC-only @@ -307,17 +309,12 @@ ti,pmic-shutdown-controller; regulators { - #address-cells = <1>; - #size-cells = <0>; - dcdc1_reg: regulator@0 { - reg = <0>; regulator-name = "vdds_dpr"; regulator-always-on; }; dcdc2_reg: regulator@1 { - reg = <1>; /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ regulator-name = "vdd_mpu"; regulator-min-microvolt = <925000>; @@ -327,7 +324,6 @@ }; dcdc3_reg: regulator@2 { - reg = <2>; /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ regulator-name = "vdd_core"; regulator-min-microvolt = <925000>; @@ -337,25 +333,21 @@ }; ldo1_reg: regulator@3 { - reg = <3>; regulator-name = "vio,vrtc,vdds"; regulator-always-on; }; ldo2_reg: regulator@4 { - reg = <4>; regulator-name = "vdd_3v3aux"; regulator-always-on; }; ldo3_reg: regulator@5 { - reg = <5>; regulator-name = "vdd_1v8"; regulator-always-on; }; ldo4_reg: regulator@6 { - reg = <6>; regulator-name = "vdd_3v3a"; regulator-always-on; }; diff --git a/arch/arm/boot/dts/am335x-chilisom.dtsi b/arch/arm/boot/dts/am335x-chilisom.dtsi index fda457b07e15..857d9894103a 100644 --- a/arch/arm/boot/dts/am335x-chilisom.dtsi +++ b/arch/arm/boot/dts/am335x-chilisom.dtsi @@ -128,21 +128,16 @@ }; -&tps { - compatible = "ti,tps65217"; +/include/ "tps65217.dtsi" +&tps { regulators { - #address-cells = <1>; - #size-cells = <0>; - dcdc1_reg: regulator@0 { - reg = <0>; regulator-name = "vdds_dpr"; regulator-always-on; }; dcdc2_reg: regulator@1 { - reg = <1>; /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ regulator-name = "vdd_mpu"; regulator-min-microvolt = <925000>; @@ -152,7 +147,6 @@ }; dcdc3_reg: regulator@2 { - reg = <2>; /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ regulator-name = "vdd_core"; regulator-min-microvolt = <925000>; @@ -162,28 +156,24 @@ }; ldo1_reg: regulator@3 { - reg = <3>; regulator-name = "vio,vrtc,vdds"; regulator-boot-on; regulator-always-on; }; ldo2_reg: regulator@4 { - reg = <4>; regulator-name = "vdd_3v3aux"; regulator-boot-on; regulator-always-on; }; ldo3_reg: regulator@5 { - reg = <5>; regulator-name = "vdd_1v8"; regulator-boot-on; regulator-always-on; }; ldo4_reg: regulator@6 { - reg = <6>; regulator-name = "vdd_3v3d"; regulator-boot-on; regulator-always-on; diff --git a/arch/arm/boot/dts/am335x-nano.dts b/arch/arm/boot/dts/am335x-nano.dts index 77559a1ded60..f313999c503e 100644 --- a/arch/arm/boot/dts/am335x-nano.dts +++ b/arch/arm/boot/dts/am335x-nano.dts @@ -375,15 +375,11 @@ wp-gpios = <&gpio3 18 0>; }; -&tps { - compatible = "ti,tps65217"; +#include "tps65217.dtsi" +&tps { regulators { - #address-cells = <1>; - #size-cells = <0>; - dcdc1_reg: regulator@0 { - reg = <0>; /* +1.5V voltage with ±4% tolerance */ regulator-min-microvolt = <1450000>; regulator-max-microvolt = <1550000>; @@ -392,7 +388,6 @@ }; dcdc2_reg: regulator@1 { - reg = <1>; /* VDD_MPU voltage limits 0.95V - 1.1V with ±4% tolerance */ regulator-name = "vdd_mpu"; regulator-min-microvolt = <915000>; @@ -402,7 +397,6 @@ }; dcdc3_reg: regulator@2 { - reg = <2>; /* VDD_CORE voltage limits 0.95V - 1.1V with ±4% tolerance */ regulator-name = "vdd_core"; regulator-min-microvolt = <915000>; @@ -412,7 +406,6 @@ }; ldo1_reg: regulator@3 { - reg = <3>; /* +1.8V voltage with ±4% tolerance */ regulator-min-microvolt = <1750000>; regulator-max-microvolt = <1870000>; @@ -421,7 +414,6 @@ }; ldo2_reg: regulator@4 { - reg = <4>; /* +3.3V voltage with ±4% tolerance */ regulator-min-microvolt = <3175000>; regulator-max-microvolt = <3430000>; @@ -430,7 +422,6 @@ }; ldo3_reg: regulator@5 { - reg = <5>; /* +1.8V voltage with ±4% tolerance */ regulator-min-microvolt = <1750000>; regulator-max-microvolt = <1870000>; @@ -439,7 +430,6 @@ }; ldo4_reg: regulator@6 { - reg = <6>; /* +3.3V voltage with ±4% tolerance */ regulator-min-microvolt = <3175000>; regulator-max-microvolt = <3430000>; diff --git a/arch/arm/boot/dts/am335x-pepper.dts b/arch/arm/boot/dts/am335x-pepper.dts index 471a3a70ea1f..8867aaaec54d 100644 --- a/arch/arm/boot/dts/am335x-pepper.dts +++ b/arch/arm/boot/dts/am335x-pepper.dts @@ -420,9 +420,9 @@ vin-supply = <&vbat>; }; -&tps { - compatible = "ti,tps65217"; +/include/ "tps65217.dtsi" +&tps { backlight { isel = <1>; /* ISET1 */ fdim = <200>; /* TPS65217_BL_FDIM_200HZ */ @@ -430,17 +430,12 @@ }; regulators { - #address-cells = <1>; - #size-cells = <0>; - dcdc1_reg: regulator@0 { - reg = <0>; /* VDD_1V8 system supply */ regulator-always-on; }; dcdc2_reg: regulator@1 { - reg = <1>; /* VDD_CORE voltage limits 0.95V - 1.26V with +/-4% tolerance */ regulator-name = "vdd_core"; regulator-min-microvolt = <925000>; @@ -450,7 +445,6 @@ }; dcdc3_reg: regulator@2 { - reg = <2>; /* VDD_MPU voltage limits 0.95V - 1.1V with +/-4% tolerance */ regulator-name = "vdd_mpu"; regulator-min-microvolt = <925000>; @@ -460,21 +454,18 @@ }; ldo1_reg: regulator@3 { - reg = <3>; /* VRTC 1.8V always-on supply */ regulator-name = "vrtc,vdds"; regulator-always-on; }; ldo2_reg: regulator@4 { - reg = <4>; /* 3.3V rail */ regulator-name = "vdd_3v3aux"; regulator-always-on; }; ldo3_reg: regulator@5 { - reg = <5>; /* VDD_3V3A 3.3V rail */ regulator-name = "vdd_3v3a"; regulator-min-microvolt = <3300000>; @@ -482,7 +473,6 @@ }; ldo4_reg: regulator@6 { - reg = <6>; /* VDD_3V3B 3.3V rail */ regulator-name = "vdd_3v3b"; regulator-always-on; diff --git a/arch/arm/boot/dts/am335x-shc.dts b/arch/arm/boot/dts/am335x-shc.dts index 1b5b044fcd91..865de8500f1c 100644 --- a/arch/arm/boot/dts/am335x-shc.dts +++ b/arch/arm/boot/dts/am335x-shc.dts @@ -46,7 +46,7 @@ gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>; linux,code = <KEY_BACK>; debounce-interval = <1000>; - gpio-key,wakeup; + wakeup-source; }; front_button { @@ -54,7 +54,7 @@ gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>; linux,code = <KEY_FRONT>; debounce-interval = <1000>; - gpio-key,wakeup; + wakeup-source; }; }; diff --git a/arch/arm/boot/dts/am335x-sl50.dts b/arch/arm/boot/dts/am335x-sl50.dts index d38edfa53bb9..3303c281697b 100644 --- a/arch/arm/boot/dts/am335x-sl50.dts +++ b/arch/arm/boot/dts/am335x-sl50.dts @@ -375,19 +375,16 @@ pinctrl-0 = <&uart4_pins>; }; +#include "tps65217.dtsi" + &tps { - compatible = "ti,tps65217"; ti,pmic-shutdown-controller; interrupt-parent = <&intc>; interrupts = <7>; /* NNMI */ regulators { - #address-cells = <1>; - #size-cells = <0>; - dcdc1_reg: regulator@0 { - reg = <0>; /* VDDS_DDR */ regulator-min-microvolt = <1500000>; regulator-max-microvolt = <1500000>; @@ -395,7 +392,6 @@ }; dcdc2_reg: regulator@1 { - reg = <1>; /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ regulator-name = "vdd_mpu"; regulator-min-microvolt = <925000>; @@ -405,7 +401,6 @@ }; dcdc3_reg: regulator@2 { - reg = <2>; /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ regulator-name = "vdd_core"; regulator-min-microvolt = <925000>; @@ -415,7 +410,6 @@ }; ldo1_reg: regulator@3 { - reg = <3>; /* VRTC / VIO / VDDS*/ regulator-always-on; regulator-min-microvolt = <1800000>; @@ -423,7 +417,6 @@ }; ldo2_reg: regulator@4 { - reg = <4>; /* VDD_3V3AUX */ regulator-always-on; regulator-min-microvolt = <3300000>; @@ -431,7 +424,6 @@ }; ldo3_reg: regulator@5 { - reg = <5>; /* VDD_1V8 */ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; @@ -439,7 +431,6 @@ }; ldo4_reg: regulator@6 { - reg = <6>; /* VDD_3V3A */ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts index 36c0fa6c362a..a0986c65be0c 100644 --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts @@ -173,6 +173,8 @@ sound0_master: simple-audio-card,codec { sound-dai = <&tlv320aic3104>; + assigned-clocks = <&clkoutmux2_clk_mux>; + assigned-clock-parents = <&sys_clk2_dclk_div>; clocks = <&clkout2_clk>; }; }; @@ -796,6 +798,8 @@ pinctrl-names = "default", "sleep"; pinctrl-0 = <&mcasp3_pins_default>; pinctrl-1 = <&mcasp3_pins_sleep>; + assigned-clocks = <&mcasp3_ahclkx_mux>; + assigned-clock-parents = <&sys_clkin2>; status = "okay"; op-mode = <0>; /* MCASP_IIS_MODE */ diff --git a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts b/arch/arm/boot/dts/am57xx-cl-som-am57x.dts index 8d93882dc8d5..1c06cb76da07 100644 --- a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts +++ b/arch/arm/boot/dts/am57xx-cl-som-am57x.dts @@ -545,7 +545,7 @@ ti,debounce-tol = /bits/ 16 <10>; ti,debounce-rep = /bits/ 16 <1>; - linux,wakeup; + wakeup-source; }; }; diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 4f6ae921656f..f74d3db4846d 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -896,7 +896,6 @@ #size-cells = <1>; reg = <0x2100000 0x10000>; ranges = <0 0x2100000 0x10000>; - interrupt-parent = <&intc>; clocks = <&clks IMX6QDL_CLK_CAAM_MEM>, <&clks IMX6QDL_CLK_CAAM_ACLK>, <&clks IMX6QDL_CLK_CAAM_IPG>, diff --git a/arch/arm/boot/dts/kirkwood-ds112.dts b/arch/arm/boot/dts/kirkwood-ds112.dts index bf4143c6cb8f..b84af3da8c84 100644 --- a/arch/arm/boot/dts/kirkwood-ds112.dts +++ b/arch/arm/boot/dts/kirkwood-ds112.dts @@ -14,7 +14,7 @@ #include "kirkwood-synology.dtsi" / { - model = "Synology DS111"; + model = "Synology DS112"; compatible = "synology,ds111", "marvell,kirkwood"; memory { diff --git a/arch/arm/boot/dts/orion5x-linkstation-lswtgl.dts b/arch/arm/boot/dts/orion5x-linkstation-lswtgl.dts index 420788229e6f..aae8a7aceab7 100644 --- a/arch/arm/boot/dts/orion5x-linkstation-lswtgl.dts +++ b/arch/arm/boot/dts/orion5x-linkstation-lswtgl.dts @@ -228,6 +228,37 @@ }; }; +&devbus_bootcs { + status = "okay"; + devbus,keep-config; + + flash@0 { + compatible = "jedec-flash"; + reg = <0 0x40000>; + bank-width = <1>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + header@0 { + reg = <0 0x30000>; + read-only; + }; + + uboot@30000 { + reg = <0x30000 0xF000>; + read-only; + }; + + uboot_env@3F000 { + reg = <0x3F000 0x1000>; + }; + }; + }; +}; + &mdio { status = "okay"; diff --git a/arch/arm/boot/dts/r8a7791-porter.dts b/arch/arm/boot/dts/r8a7791-porter.dts index 6713b1ea732b..01d239c3eaaa 100644 --- a/arch/arm/boot/dts/r8a7791-porter.dts +++ b/arch/arm/boot/dts/r8a7791-porter.dts @@ -283,7 +283,6 @@ pinctrl-names = "default"; status = "okay"; - renesas,enable-gpio = <&gpio5 31 GPIO_ACTIVE_HIGH>; }; &usbphy { diff --git a/arch/arm/boot/dts/sama5d2-pinfunc.h b/arch/arm/boot/dts/sama5d2-pinfunc.h index 1afe24629d1f..b0c912feaa2f 100644 --- a/arch/arm/boot/dts/sama5d2-pinfunc.h +++ b/arch/arm/boot/dts/sama5d2-pinfunc.h @@ -90,7 +90,7 @@ #define PIN_PA14__I2SC1_MCK PINMUX_PIN(PIN_PA14, 4, 2) #define PIN_PA14__FLEXCOM3_IO2 PINMUX_PIN(PIN_PA14, 5, 1) #define PIN_PA14__D9 PINMUX_PIN(PIN_PA14, 6, 2) -#define PIN_PA15 14 +#define PIN_PA15 15 #define PIN_PA15__GPIO PINMUX_PIN(PIN_PA15, 0, 0) #define PIN_PA15__SPI0_MOSI PINMUX_PIN(PIN_PA15, 1, 1) #define PIN_PA15__TF1 PINMUX_PIN(PIN_PA15, 2, 1) diff --git a/arch/arm/boot/dts/tps65217.dtsi b/arch/arm/boot/dts/tps65217.dtsi new file mode 100644 index 000000000000..a63272422d76 --- /dev/null +++ b/arch/arm/boot/dts/tps65217.dtsi @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Integrated Power Management Chip + * http://www.ti.com/lit/ds/symlink/tps65217.pdf + */ + +&tps { + compatible = "ti,tps65217"; + + regulators { + #address-cells = <1>; + #size-cells = <0>; + + dcdc1_reg: regulator@0 { + reg = <0>; + regulator-compatible = "dcdc1"; + }; + + dcdc2_reg: regulator@1 { + reg = <1>; + regulator-compatible = "dcdc2"; + }; + + dcdc3_reg: regulator@2 { + reg = <2>; + regulator-compatible = "dcdc3"; + }; + + ldo1_reg: regulator@3 { + reg = <3>; + regulator-compatible = "ldo1"; + }; + + ldo2_reg: regulator@4 { + reg = <4>; + regulator-compatible = "ldo2"; + }; + + ldo3_reg: regulator@5 { + reg = <5>; + regulator-compatible = "ldo3"; + }; + + ldo4_reg: regulator@6 { + reg = <6>; + regulator-compatible = "ldo4"; + }; + }; +}; diff --git a/arch/arm/crypto/aes-ce-glue.c b/arch/arm/crypto/aes-ce-glue.c index b445a5d56f43..89a3a3e592d6 100644 --- a/arch/arm/crypto/aes-ce-glue.c +++ b/arch/arm/crypto/aes-ce-glue.c @@ -364,7 +364,7 @@ static struct crypto_alg aes_algs[] = { { .cra_blkcipher = { .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, + .ivsize = 0, .setkey = ce_aes_setkey, .encrypt = ecb_encrypt, .decrypt = ecb_decrypt, @@ -441,7 +441,7 @@ static struct crypto_alg aes_algs[] = { { .cra_ablkcipher = { .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, + .ivsize = 0, .setkey = ablk_set_key, .encrypt = ablk_encrypt, .decrypt = ablk_decrypt, diff --git a/arch/arm/include/asm/arch_gicv3.h b/arch/arm/include/asm/arch_gicv3.h index 7da5503c0591..e08d15184056 100644 --- a/arch/arm/include/asm/arch_gicv3.h +++ b/arch/arm/include/asm/arch_gicv3.h @@ -117,6 +117,7 @@ static inline u32 gic_read_iar(void) u32 irqstat; asm volatile("mrc " __stringify(ICC_IAR1) : "=r" (irqstat)); + dsb(sy); return irqstat; } diff --git a/arch/arm/include/asm/xen/page-coherent.h b/arch/arm/include/asm/xen/page-coherent.h index 0375c8caa061..9408a994cc91 100644 --- a/arch/arm/include/asm/xen/page-coherent.h +++ b/arch/arm/include/asm/xen/page-coherent.h @@ -35,14 +35,21 @@ static inline void xen_dma_map_page(struct device *hwdev, struct page *page, dma_addr_t dev_addr, unsigned long offset, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs) { - bool local = XEN_PFN_DOWN(dev_addr) == page_to_xen_pfn(page); + unsigned long page_pfn = page_to_xen_pfn(page); + unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr); + unsigned long compound_pages = + (1<<compound_order(page)) * XEN_PFN_PER_PAGE; + bool local = (page_pfn <= dev_pfn) && + (dev_pfn - page_pfn < compound_pages); + /* - * Dom0 is mapped 1:1, while the Linux page can be spanned accross - * multiple Xen page, it's not possible to have a mix of local and - * foreign Xen page. So if the first xen_pfn == mfn the page is local - * otherwise it's a foreign page grant-mapped in dom0. If the page is - * local we can safely call the native dma_ops function, otherwise we - * call the xen specific function. + * Dom0 is mapped 1:1, while the Linux page can span across + * multiple Xen pages, it's not possible for it to contain a + * mix of local and foreign Xen pages. So if the first xen_pfn + * == mfn the page is local otherwise it's a foreign page + * grant-mapped in dom0. If the page is local we can safely + * call the native dma_ops function, otherwise we call the xen + * specific function. */ if (local) __generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs); diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 2c5f160be65e..ad325a8c7e1e 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -88,6 +88,7 @@ obj-$(CONFIG_DEBUG_LL) += debug.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_ARM_VIRT_EXT) += hyp-stub.o +AFLAGS_hyp-stub.o :=-Wa,-march=armv7-a ifeq ($(CONFIG_ARM_PSCI),y) obj-$(CONFIG_SMP) += psci_smp.o endif diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c index 5fa69d7bae58..99361f11354a 100644 --- a/arch/arm/kvm/guest.c +++ b/arch/arm/kvm/guest.c @@ -161,7 +161,7 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) u64 val; val = kvm_arm_timer_get_reg(vcpu, reg->id); - return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)); + return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0; } static unsigned long num_core_regs(void) diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c index 7f33b2056ae6..0f6600f05137 100644 --- a/arch/arm/kvm/mmio.c +++ b/arch/arm/kvm/mmio.c @@ -206,7 +206,8 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, run->mmio.is_write = is_write; run->mmio.phys_addr = fault_ipa; run->mmio.len = len; - memcpy(run->mmio.data, data_buf, len); + if (is_write) + memcpy(run->mmio.data, data_buf, len); if (!ret) { /* We handled the access successfully in the kernel. */ diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 809827265fb3..bab814d2f37d 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -18,6 +18,7 @@ #include <asm/setup.h> #include <asm/mach/arch.h> +#include <asm/system_info.h> #include "common.h" @@ -77,12 +78,31 @@ static const char *const n900_boards_compat[] __initconst = { NULL, }; +/* Set system_rev from atags */ +static void __init rx51_set_system_rev(const struct tag *tags) +{ + const struct tag *tag; + + if (tags->hdr.tag != ATAG_CORE) + return; + + for_each_tag(tag, tags) { + if (tag->hdr.tag == ATAG_REVISION) { + system_rev = tag->u.revision.rev; + break; + } + } +} + /* Legacy userspace on Nokia N900 needs ATAGS exported in /proc/atags, * save them while the data is still not overwritten */ static void __init rx51_reserve(void) { - save_atags((const struct tag *)(PAGE_OFFSET + 0x100)); + const struct tag *tags = (const struct tag *)(PAGE_OFFSET + 0x100); + + save_atags(tags); + rx51_set_system_rev(tags); omap_reserve(); } diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 7b76ce01c21d..8633c703546a 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -101,10 +101,8 @@ static void omap2_onenand_set_async_mode(void __iomem *onenand_base) static void set_onenand_cfg(void __iomem *onenand_base) { - u32 reg; + u32 reg = ONENAND_SYS_CFG1_RDY | ONENAND_SYS_CFG1_INT; - reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); - reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9)); reg |= (latency << ONENAND_SYS_CFG1_BRL_SHIFT) | ONENAND_SYS_CFG1_BL_16; if (onenand_flags & ONENAND_FLAG_SYNCREAD) @@ -123,6 +121,7 @@ static void set_onenand_cfg(void __iomem *onenand_base) reg |= ONENAND_SYS_CFG1_VHF; else reg &= ~ONENAND_SYS_CFG1_VHF; + writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); } @@ -289,6 +288,7 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base) } } + onenand_async.sync_write = true; omap2_onenand_calc_async_timings(&t); ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_async); diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 0437537751bc..f7ff3b9dad87 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -191,12 +191,22 @@ static int _omap_device_notifier_call(struct notifier_block *nb, { struct platform_device *pdev = to_platform_device(dev); struct omap_device *od; + int err; switch (event) { case BUS_NOTIFY_DEL_DEVICE: if (pdev->archdata.od) omap_device_delete(pdev->archdata.od); break; + case BUS_NOTIFY_UNBOUND_DRIVER: + od = to_omap_device(pdev); + if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED)) { + dev_info(dev, "enabled after unload, idling\n"); + err = omap_device_idle(pdev); + if (err) + dev_err(dev, "failed to idle\n"); + } + break; case BUS_NOTIFY_ADD_DEVICE: if (pdev->dev.of_node) omap_device_build_from_dt(pdev); @@ -602,8 +612,10 @@ static int _od_runtime_resume(struct device *dev) int ret; ret = omap_device_enable(pdev); - if (ret) + if (ret) { + dev_err(dev, "use pm_runtime_put_sync_suspend() in driver?\n"); return ret; + } return pm_generic_runtime_resume(dev); } diff --git a/arch/arm/mach-shmobile/common.h b/arch/arm/mach-shmobile/common.h index 9cb11215ceba..b3a4ed5289ec 100644 --- a/arch/arm/mach-shmobile/common.h +++ b/arch/arm/mach-shmobile/common.h @@ -4,7 +4,6 @@ extern void shmobile_init_delay(void); extern void shmobile_boot_vector(void); extern unsigned long shmobile_boot_fn; -extern unsigned long shmobile_boot_arg; extern unsigned long shmobile_boot_size; extern void shmobile_smp_boot(void); extern void shmobile_smp_sleep(void); diff --git a/arch/arm/mach-shmobile/headsmp-scu.S b/arch/arm/mach-shmobile/headsmp-scu.S index fa5248c52399..5e503d91ad70 100644 --- a/arch/arm/mach-shmobile/headsmp-scu.S +++ b/arch/arm/mach-shmobile/headsmp-scu.S @@ -38,9 +38,3 @@ ENTRY(shmobile_boot_scu) b secondary_startup ENDPROC(shmobile_boot_scu) - - .text - .align 2 - .globl shmobile_scu_base -shmobile_scu_base: - .space 4 diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S index 330c1fc63197..32e0bf6e3ccb 100644 --- a/arch/arm/mach-shmobile/headsmp.S +++ b/arch/arm/mach-shmobile/headsmp.S @@ -24,7 +24,6 @@ .arm .align 12 ENTRY(shmobile_boot_vector) - ldr r0, 2f ldr r1, 1f bx r1 @@ -34,9 +33,6 @@ ENDPROC(shmobile_boot_vector) .globl shmobile_boot_fn shmobile_boot_fn: 1: .space 4 - .globl shmobile_boot_arg -shmobile_boot_arg: -2: .space 4 .globl shmobile_boot_size shmobile_boot_size: .long . - shmobile_boot_vector @@ -46,13 +42,15 @@ shmobile_boot_size: */ ENTRY(shmobile_smp_boot) - @ r0 = MPIDR_HWID_BITMASK mrc p15, 0, r1, c0, c0, 5 @ r1 = MPIDR - and r0, r1, r0 @ r0 = cpu_logical_map() value + and r0, r1, #0xffffff @ MPIDR_HWID_BITMASK + @ r0 = cpu_logical_map() value mov r1, #0 @ r1 = CPU index - adr r5, 1f @ array of per-cpu mpidr values - adr r6, 2f @ array of per-cpu functions - adr r7, 3f @ array of per-cpu arguments + adr r2, 1f + ldmia r2, {r5, r6, r7} + add r5, r5, r2 @ array of per-cpu mpidr values + add r6, r6, r2 @ array of per-cpu functions + add r7, r7, r2 @ array of per-cpu arguments shmobile_smp_boot_find_mpidr: ldr r8, [r5, r1, lsl #2] @@ -80,12 +78,18 @@ ENTRY(shmobile_smp_sleep) b shmobile_smp_boot ENDPROC(shmobile_smp_sleep) + .align 2 +1: .long shmobile_smp_mpidr - . + .long shmobile_smp_fn - 1b + .long shmobile_smp_arg - 1b + + .bss .globl shmobile_smp_mpidr shmobile_smp_mpidr: -1: .space NR_CPUS * 4 + .space NR_CPUS * 4 .globl shmobile_smp_fn shmobile_smp_fn: -2: .space NR_CPUS * 4 + .space NR_CPUS * 4 .globl shmobile_smp_arg shmobile_smp_arg: -3: .space NR_CPUS * 4 + .space NR_CPUS * 4 diff --git a/arch/arm/mach-shmobile/platsmp-apmu.c b/arch/arm/mach-shmobile/platsmp-apmu.c index 911884f7e28b..aba75c89f9c1 100644 --- a/arch/arm/mach-shmobile/platsmp-apmu.c +++ b/arch/arm/mach-shmobile/platsmp-apmu.c @@ -123,7 +123,6 @@ void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus, { /* install boot code shared by all CPUs */ shmobile_boot_fn = virt_to_phys(shmobile_smp_boot); - shmobile_boot_arg = MPIDR_HWID_BITMASK; /* perform per-cpu setup */ apmu_parse_cfg(apmu_init_cpu, apmu_config, num); diff --git a/arch/arm/mach-shmobile/platsmp-scu.c b/arch/arm/mach-shmobile/platsmp-scu.c index 64663110ab6c..081a097c9219 100644 --- a/arch/arm/mach-shmobile/platsmp-scu.c +++ b/arch/arm/mach-shmobile/platsmp-scu.c @@ -17,6 +17,9 @@ #include <asm/smp_scu.h> #include "common.h" + +void __iomem *shmobile_scu_base; + static int shmobile_smp_scu_notifier_call(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -41,7 +44,6 @@ void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus) { /* install boot code shared by all CPUs */ shmobile_boot_fn = virt_to_phys(shmobile_smp_boot); - shmobile_boot_arg = MPIDR_HWID_BITMASK; /* enable SCU and cache coherency on booting CPU */ scu_enable(shmobile_scu_base); diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c index b854fe2095ad..0b024a9dbd43 100644 --- a/arch/arm/mach-shmobile/smp-r8a7779.c +++ b/arch/arm/mach-shmobile/smp-r8a7779.c @@ -92,8 +92,6 @@ static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus) { /* Map the reset vector (in headsmp-scu.S, headsmp.S) */ __raw_writel(__pa(shmobile_boot_vector), AVECR); - shmobile_boot_fn = virt_to_phys(shmobile_boot_scu); - shmobile_boot_arg = (unsigned long)shmobile_scu_base; /* setup r8a7779 specific SCU bits */ shmobile_scu_base = IOMEM(R8A7779_SCU_BASE); diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index 4b4058db0781..66353caa35b9 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -173,7 +173,7 @@ unsigned long arch_mmap_rnd(void) { unsigned long rnd; - rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_bits) - 1); + rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1); return rnd << PAGE_SHIFT; } diff --git a/arch/arm/mm/pageattr.c b/arch/arm/mm/pageattr.c index cf30daff8932..d19b1ad29b07 100644 --- a/arch/arm/mm/pageattr.c +++ b/arch/arm/mm/pageattr.c @@ -49,6 +49,9 @@ static int change_memory_common(unsigned long addr, int numpages, WARN_ON_ONCE(1); } + if (!numpages) + return 0; + if (start < MODULES_VADDR || start >= MODULES_END) return -EINVAL; diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 307237cfe728..b5e3f6d42b88 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -88,7 +88,7 @@ Image: vmlinux Image.%: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ -zinstall install: vmlinux +zinstall install: $(Q)$(MAKE) $(build)=$(boot) $@ %.dtb: scripts diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile index abcbba2f01ba..305c552b5ec1 100644 --- a/arch/arm64/boot/Makefile +++ b/arch/arm64/boot/Makefile @@ -34,10 +34,10 @@ $(obj)/Image.lzma: $(obj)/Image FORCE $(obj)/Image.lzo: $(obj)/Image FORCE $(call if_changed,lzo) -install: $(obj)/Image +install: $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ $(obj)/Image System.map "$(INSTALL_PATH)" -zinstall: $(obj)/Image.gz +zinstall: $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ $(obj)/Image.gz System.map "$(INSTALL_PATH)" diff --git a/arch/arm64/boot/install.sh b/arch/arm64/boot/install.sh index 12ed78aa6f0c..d91e1f022573 100644 --- a/arch/arm64/boot/install.sh +++ b/arch/arm64/boot/install.sh @@ -20,6 +20,20 @@ # $4 - default install path (blank if root directory) # +verify () { + if [ ! -f "$1" ]; then + echo "" 1>&2 + echo " *** Missing file: $1" 1>&2 + echo ' *** You need to run "make" before "make install".' 1>&2 + echo "" 1>&2 + exit 1 + fi +} + +# Make sure the files actually exist +verify "$2" +verify "$3" + # User may have a custom install script if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c index 05d9e16c0dfd..7a3d22a46faf 100644 --- a/arch/arm64/crypto/aes-glue.c +++ b/arch/arm64/crypto/aes-glue.c @@ -294,7 +294,7 @@ static struct crypto_alg aes_algs[] = { { .cra_blkcipher = { .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, + .ivsize = 0, .setkey = aes_setkey, .encrypt = ecb_encrypt, .decrypt = ecb_decrypt, @@ -371,7 +371,7 @@ static struct crypto_alg aes_algs[] = { { .cra_ablkcipher = { .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, + .ivsize = 0, .setkey = ablk_set_key, .encrypt = ablk_encrypt, .decrypt = ablk_decrypt, diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index bef6e9243c63..d201d4b396d1 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -107,8 +107,6 @@ #define TCR_EL2_MASK (TCR_EL2_TG0 | TCR_EL2_SH0 | \ TCR_EL2_ORGN0 | TCR_EL2_IRGN0 | TCR_EL2_T0SZ) -#define TCR_EL2_FLAGS (TCR_EL2_RES1 | TCR_EL2_PS_40B) - /* VTCR_EL2 Registers bits */ #define VTCR_EL2_RES1 (1 << 31) #define VTCR_EL2_PS_MASK (7 << 16) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index bf464de33f52..f50608674580 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -34,13 +34,13 @@ /* * VMALLOC and SPARSEMEM_VMEMMAP ranges. * - * VMEMAP_SIZE: allows the whole VA space to be covered by a struct page array + * VMEMAP_SIZE: allows the whole linear region to be covered by a struct page array * (rounded up to PUD_SIZE). * VMALLOC_START: beginning of the kernel VA space * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space, * fixed mappings and modules */ -#define VMEMMAP_SIZE ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * sizeof(struct page), PUD_SIZE) +#define VMEMMAP_SIZE ALIGN((1UL << (VA_BITS - PAGE_SHIFT - 1)) * sizeof(struct page), PUD_SIZE) #ifndef CONFIG_KASAN #define VMALLOC_START (VA_START) @@ -51,7 +51,8 @@ #define VMALLOC_END (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K) -#define vmemmap ((struct page *)(VMALLOC_END + SZ_64K)) +#define VMEMMAP_START (VMALLOC_END + SZ_64K) +#define vmemmap ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT)) #define FIRST_USER_ADDRESS 0UL diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index 8aee3aeec3e6..c536c9e307b9 100644 --- a/arch/arm64/kernel/debug-monitors.c +++ b/arch/arm64/kernel/debug-monitors.c @@ -226,11 +226,28 @@ static int call_step_hook(struct pt_regs *regs, unsigned int esr) return retval; } +static void send_user_sigtrap(int si_code) +{ + struct pt_regs *regs = current_pt_regs(); + siginfo_t info = { + .si_signo = SIGTRAP, + .si_errno = 0, + .si_code = si_code, + .si_addr = (void __user *)instruction_pointer(regs), + }; + + if (WARN_ON(!user_mode(regs))) + return; + + if (interrupts_enabled(regs)) + local_irq_enable(); + + force_sig_info(SIGTRAP, &info, current); +} + static int single_step_handler(unsigned long addr, unsigned int esr, struct pt_regs *regs) { - siginfo_t info; - /* * If we are stepping a pending breakpoint, call the hw_breakpoint * handler first. @@ -239,11 +256,7 @@ static int single_step_handler(unsigned long addr, unsigned int esr, return 0; if (user_mode(regs)) { - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = TRAP_HWBKPT; - info.si_addr = (void __user *)instruction_pointer(regs); - force_sig_info(SIGTRAP, &info, current); + send_user_sigtrap(TRAP_HWBKPT); /* * ptrace will disable single step unless explicitly @@ -307,17 +320,8 @@ static int call_break_hook(struct pt_regs *regs, unsigned int esr) static int brk_handler(unsigned long addr, unsigned int esr, struct pt_regs *regs) { - siginfo_t info; - if (user_mode(regs)) { - info = (siginfo_t) { - .si_signo = SIGTRAP, - .si_errno = 0, - .si_code = TRAP_BRKPT, - .si_addr = (void __user *)instruction_pointer(regs), - }; - - force_sig_info(SIGTRAP, &info, current); + send_user_sigtrap(TRAP_BRKPT); } else if (call_break_hook(regs, esr) != DBG_HOOK_HANDLED) { pr_warning("Unexpected kernel BRK exception at EL1\n"); return -EFAULT; @@ -328,7 +332,6 @@ static int brk_handler(unsigned long addr, unsigned int esr, int aarch32_break_handler(struct pt_regs *regs) { - siginfo_t info; u32 arm_instr; u16 thumb_instr; bool bp = false; @@ -359,14 +362,7 @@ int aarch32_break_handler(struct pt_regs *regs) if (!bp) return -EFAULT; - info = (siginfo_t) { - .si_signo = SIGTRAP, - .si_errno = 0, - .si_code = TRAP_BRKPT, - .si_addr = pc, - }; - - force_sig_info(SIGTRAP, &info, current); + send_user_sigtrap(TRAP_BRKPT); return 0; } diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h index 999633bd7294..352f7abd91c9 100644 --- a/arch/arm64/kernel/image.h +++ b/arch/arm64/kernel/image.h @@ -89,6 +89,7 @@ __efistub_memcpy = KALLSYMS_HIDE(__pi_memcpy); __efistub_memmove = KALLSYMS_HIDE(__pi_memmove); __efistub_memset = KALLSYMS_HIDE(__pi_memset); __efistub_strlen = KALLSYMS_HIDE(__pi_strlen); +__efistub_strnlen = KALLSYMS_HIDE(__pi_strnlen); __efistub_strcmp = KALLSYMS_HIDE(__pi_strcmp); __efistub_strncmp = KALLSYMS_HIDE(__pi_strncmp); __efistub___flush_dcache_area = KALLSYMS_HIDE(__pi___flush_dcache_area); diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c index 4fad9787ab46..d9751a4769e7 100644 --- a/arch/arm64/kernel/stacktrace.c +++ b/arch/arm64/kernel/stacktrace.c @@ -44,14 +44,13 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) unsigned long irq_stack_ptr; /* - * Use raw_smp_processor_id() to avoid false-positives from - * CONFIG_DEBUG_PREEMPT. get_wchan() calls unwind_frame() on sleeping - * task stacks, we can be pre-empted in this case, so - * {raw_,}smp_processor_id() may give us the wrong value. Sleeping - * tasks can't ever be on an interrupt stack, so regardless of cpu, - * the checks will always fail. + * Switching between stacks is valid when tracing current and in + * non-preemptible context. */ - irq_stack_ptr = IRQ_STACK_PTR(raw_smp_processor_id()); + if (tsk == current && !preemptible()) + irq_stack_ptr = IRQ_STACK_PTR(smp_processor_id()); + else + irq_stack_ptr = 0; low = frame->sp; /* irq stacks are not THREAD_SIZE aligned */ @@ -64,8 +63,8 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) return -EINVAL; frame->sp = fp + 0x10; - frame->fp = *(unsigned long *)(fp); - frame->pc = *(unsigned long *)(fp + 8); + frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp)); + frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 8)); #ifdef CONFIG_FUNCTION_GRAPH_TRACER if (tsk && tsk->ret_stack && diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index cbedd724f48e..c5392081b49b 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -146,9 +146,18 @@ static void dump_instr(const char *lvl, struct pt_regs *regs) static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) { struct stackframe frame; - unsigned long irq_stack_ptr = IRQ_STACK_PTR(smp_processor_id()); + unsigned long irq_stack_ptr; int skip; + /* + * Switching between stacks is valid when tracing current and in + * non-preemptible context. + */ + if (tsk == current && !preemptible()) + irq_stack_ptr = IRQ_STACK_PTR(smp_processor_id()); + else + irq_stack_ptr = 0; + pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); if (!tsk) diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index fcb778899a38..9e54ad7c240a 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -194,7 +194,7 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) u64 val; val = kvm_arm_timer_get_reg(vcpu, reg->id); - return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)); + return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0; } /** diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S index 3e568dcd907b..d073b5a216f7 100644 --- a/arch/arm64/kvm/hyp-init.S +++ b/arch/arm64/kvm/hyp-init.S @@ -64,7 +64,7 @@ __do_hyp_init: mrs x4, tcr_el1 ldr x5, =TCR_EL2_MASK and x4, x4, x5 - ldr x5, =TCR_EL2_FLAGS + mov x5, #TCR_EL2_RES1 orr x4, x4, x5 #ifndef CONFIG_ARM64_VA_BITS_48 @@ -85,15 +85,17 @@ __do_hyp_init: ldr_l x5, idmap_t0sz bfi x4, x5, TCR_T0SZ_OFFSET, TCR_TxSZ_WIDTH #endif - msr tcr_el2, x4 - - ldr x4, =VTCR_EL2_FLAGS /* * Read the PARange bits from ID_AA64MMFR0_EL1 and set the PS bits in - * VTCR_EL2. + * TCR_EL2 and VTCR_EL2. */ mrs x5, ID_AA64MMFR0_EL1 bfi x4, x5, #16, #3 + + msr tcr_el2, x4 + + ldr x4, =VTCR_EL2_FLAGS + bfi x4, x5, #16, #3 /* * Read the VMIDBits bits from ID_AA64MMFR1_EL1 and set the VS bit in * VTCR_EL2. diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c index 9142e082f5f3..5dd2a26444ec 100644 --- a/arch/arm64/kvm/hyp/vgic-v3-sr.c +++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c @@ -149,16 +149,6 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu) switch (nr_pri_bits) { case 7: - write_gicreg(cpu_if->vgic_ap1r[3], ICH_AP1R3_EL2); - write_gicreg(cpu_if->vgic_ap1r[2], ICH_AP1R2_EL2); - case 6: - write_gicreg(cpu_if->vgic_ap1r[1], ICH_AP1R1_EL2); - default: - write_gicreg(cpu_if->vgic_ap1r[0], ICH_AP1R0_EL2); - } - - switch (nr_pri_bits) { - case 7: write_gicreg(cpu_if->vgic_ap0r[3], ICH_AP0R3_EL2); write_gicreg(cpu_if->vgic_ap0r[2], ICH_AP0R2_EL2); case 6: @@ -167,6 +157,16 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu) write_gicreg(cpu_if->vgic_ap0r[0], ICH_AP0R0_EL2); } + switch (nr_pri_bits) { + case 7: + write_gicreg(cpu_if->vgic_ap1r[3], ICH_AP1R3_EL2); + write_gicreg(cpu_if->vgic_ap1r[2], ICH_AP1R2_EL2); + case 6: + write_gicreg(cpu_if->vgic_ap1r[1], ICH_AP1R1_EL2); + default: + write_gicreg(cpu_if->vgic_ap1r[0], ICH_AP1R0_EL2); + } + switch (max_lr_idx) { case 15: write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(15)], ICH_LR15_EL2); diff --git a/arch/arm64/lib/strnlen.S b/arch/arm64/lib/strnlen.S index 2ca665711bf2..eae38da6e0bb 100644 --- a/arch/arm64/lib/strnlen.S +++ b/arch/arm64/lib/strnlen.S @@ -168,4 +168,4 @@ CPU_LE( lsr tmp2, tmp2, tmp4 ) /* Shift (tmp1 & 63). */ .Lhit_limit: mov len, limit ret -ENDPROC(strnlen) +ENDPIPROC(strnlen) diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index 331c4ca6205c..a6e757cbab77 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -933,6 +933,10 @@ static int __init __iommu_dma_init(void) ret = register_iommu_dma_ops_notifier(&platform_bus_type); if (!ret) ret = register_iommu_dma_ops_notifier(&amba_bustype); + + /* handle devices queued before this arch_initcall */ + if (!ret) + __iommu_attach_notifier(NULL, BUS_NOTIFY_ADD_DEVICE, NULL); return ret; } arch_initcall(__iommu_dma_init); diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 92ddac1e8ca2..abe2a9542b3a 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -371,6 +371,13 @@ static int __kprobes do_translation_fault(unsigned long addr, return 0; } +static int do_alignment_fault(unsigned long addr, unsigned int esr, + struct pt_regs *regs) +{ + do_bad_area(addr, esr, regs); + return 0; +} + /* * This abort handler always returns "fault". */ @@ -418,7 +425,7 @@ static struct fault_info { { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk)" }, { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk)" }, { do_bad, SIGBUS, 0, "unknown 32" }, - { do_bad, SIGBUS, BUS_ADRALN, "alignment fault" }, + { do_alignment_fault, SIGBUS, BUS_ADRALN, "alignment fault" }, { do_bad, SIGBUS, 0, "unknown 34" }, { do_bad, SIGBUS, 0, "unknown 35" }, { do_bad, SIGBUS, 0, "unknown 36" }, diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index f3b061e67bfe..7802f216a67a 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -319,8 +319,8 @@ void __init mem_init(void) #endif MLG(VMALLOC_START, VMALLOC_END), #ifdef CONFIG_SPARSEMEM_VMEMMAP - MLG((unsigned long)vmemmap, - (unsigned long)vmemmap + VMEMMAP_SIZE), + MLG(VMEMMAP_START, + VMEMMAP_START + VMEMMAP_SIZE), MLM((unsigned long)virt_to_page(PAGE_OFFSET), (unsigned long)virt_to_page(high_memory)), #endif diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c index 4c893b5189dd..232f787a088a 100644 --- a/arch/arm64/mm/mmap.c +++ b/arch/arm64/mm/mmap.c @@ -53,10 +53,10 @@ unsigned long arch_mmap_rnd(void) #ifdef CONFIG_COMPAT if (test_thread_flag(TIF_32BIT)) - rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_compat_bits) - 1); + rnd = get_random_long() & ((1UL << mmap_rnd_compat_bits) - 1); else #endif - rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_bits) - 1); + rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1); return rnd << PAGE_SHIFT; } diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index fc96e814188e..d1fc4796025e 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -108,6 +108,8 @@ CONFIG_NFT_NAT=m CONFIG_NFT_QUEUE=m CONFIG_NFT_REJECT=m CONFIG_NFT_COMPAT=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m @@ -266,6 +268,12 @@ CONFIG_L2TP=m CONFIG_BRIDGE=m CONFIG_ATALK=m CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m CONFIG_DNS_RESOLVER=y CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_DAT=y @@ -366,6 +374,7 @@ CONFIG_ARIADNE=y # CONFIG_NET_VENDOR_INTEL is not set # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NETRONOME is not set CONFIG_HYDRA=y CONFIG_APNE=y CONFIG_ZORRO8390=y diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index 05c904f08d9d..9bfe8be3658c 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -106,6 +106,8 @@ CONFIG_NFT_NAT=m CONFIG_NFT_QUEUE=m CONFIG_NFT_REJECT=m CONFIG_NFT_COMPAT=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m @@ -264,6 +266,12 @@ CONFIG_L2TP=m CONFIG_BRIDGE=m CONFIG_ATALK=m CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m CONFIG_DNS_RESOLVER=y CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_DAT=y @@ -344,6 +352,7 @@ CONFIG_VETH=m # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set # CONFIG_NET_VENDOR_QUALCOMM is not set # CONFIG_NET_VENDOR_RENESAS is not set # CONFIG_NET_VENDOR_ROCKER is not set diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index d572b731c510..ebdcfae55580 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -106,6 +106,8 @@ CONFIG_NFT_NAT=m CONFIG_NFT_QUEUE=m CONFIG_NFT_REJECT=m CONFIG_NFT_COMPAT=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m @@ -264,6 +266,12 @@ CONFIG_L2TP=m CONFIG_BRIDGE=m CONFIG_ATALK=m CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m CONFIG_DNS_RESOLVER=y CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_DAT=y @@ -353,6 +361,7 @@ CONFIG_ATARILANCE=y # CONFIG_NET_VENDOR_INTEL is not set # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NETRONOME is not set CONFIG_NE2000=y # CONFIG_NET_VENDOR_QUALCOMM is not set # CONFIG_NET_VENDOR_RENESAS is not set diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index 11a30c65ad44..8acc65e54995 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -104,6 +104,8 @@ CONFIG_NFT_NAT=m CONFIG_NFT_QUEUE=m CONFIG_NFT_REJECT=m CONFIG_NFT_COMPAT=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m @@ -262,6 +264,12 @@ CONFIG_L2TP=m CONFIG_BRIDGE=m CONFIG_ATALK=m CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m CONFIG_DNS_RESOLVER=y CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_DAT=y @@ -343,6 +351,7 @@ CONFIG_BVME6000_NET=y # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set # CONFIG_NET_VENDOR_QUALCOMM is not set # CONFIG_NET_VENDOR_RENESAS is not set # CONFIG_NET_VENDOR_ROCKER is not set diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index 6630a5154b9d..0c6a3d52b26e 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -106,6 +106,8 @@ CONFIG_NFT_NAT=m CONFIG_NFT_QUEUE=m CONFIG_NFT_REJECT=m CONFIG_NFT_COMPAT=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m @@ -264,6 +266,12 @@ CONFIG_L2TP=m CONFIG_BRIDGE=m CONFIG_ATALK=m CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m CONFIG_DNS_RESOLVER=y CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_DAT=y @@ -345,6 +353,7 @@ CONFIG_HPLANCE=y # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set # CONFIG_NET_VENDOR_QUALCOMM is not set # CONFIG_NET_VENDOR_RENESAS is not set # CONFIG_NET_VENDOR_ROCKER is not set diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index 1d90b71d0903..12a8a6cb32f4 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -105,6 +105,8 @@ CONFIG_NFT_NAT=m CONFIG_NFT_QUEUE=m CONFIG_NFT_REJECT=m CONFIG_NFT_COMPAT=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m @@ -266,6 +268,12 @@ CONFIG_DEV_APPLETALK=m CONFIG_IPDDP=m CONFIG_IPDDP_ENCAP=y CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m CONFIG_DNS_RESOLVER=y CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_DAT=y @@ -362,6 +370,7 @@ CONFIG_MAC89x0=y # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MICREL is not set CONFIG_MACSONIC=y +# CONFIG_NET_VENDOR_NETRONOME is not set CONFIG_MAC8390=y # CONFIG_NET_VENDOR_QUALCOMM is not set # CONFIG_NET_VENDOR_RENESAS is not set diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index 1fd21c1ca87f..64ff2dcb34c8 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig @@ -115,6 +115,8 @@ CONFIG_NFT_NAT=m CONFIG_NFT_QUEUE=m CONFIG_NFT_REJECT=m CONFIG_NFT_COMPAT=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m @@ -276,6 +278,12 @@ CONFIG_DEV_APPLETALK=m CONFIG_IPDDP=m CONFIG_IPDDP_ENCAP=y CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m CONFIG_DNS_RESOLVER=y CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_DAT=y @@ -404,6 +412,7 @@ CONFIG_MVME16x_NET=y # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MICREL is not set CONFIG_MACSONIC=y +# CONFIG_NET_VENDOR_NETRONOME is not set CONFIG_HYDRA=y CONFIG_MAC8390=y CONFIG_NE2000=y diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index 74e10f79d7b1..07fc6abcfe0c 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -103,6 +103,8 @@ CONFIG_NFT_NAT=m CONFIG_NFT_QUEUE=m CONFIG_NFT_REJECT=m CONFIG_NFT_COMPAT=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m @@ -261,6 +263,12 @@ CONFIG_L2TP=m CONFIG_BRIDGE=m CONFIG_ATALK=m CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m CONFIG_DNS_RESOLVER=y CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_DAT=y @@ -343,6 +351,7 @@ CONFIG_MVME147_NET=y # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set # CONFIG_NET_VENDOR_QUALCOMM is not set # CONFIG_NET_VENDOR_RENESAS is not set # CONFIG_NET_VENDOR_ROCKER is not set diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index 7034e716f166..69903ded88f7 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -104,6 +104,8 @@ CONFIG_NFT_NAT=m CONFIG_NFT_QUEUE=m CONFIG_NFT_REJECT=m CONFIG_NFT_COMPAT=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m @@ -262,6 +264,12 @@ CONFIG_L2TP=m CONFIG_BRIDGE=m CONFIG_ATALK=m CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m CONFIG_DNS_RESOLVER=y CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_DAT=y @@ -343,6 +351,7 @@ CONFIG_MVME16x_NET=y # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set # CONFIG_NET_VENDOR_QUALCOMM is not set # CONFIG_NET_VENDOR_RENESAS is not set # CONFIG_NET_VENDOR_ROCKER is not set diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index f7deb5f702a6..bd8401686dde 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -104,6 +104,8 @@ CONFIG_NFT_NAT=m CONFIG_NFT_QUEUE=m CONFIG_NFT_REJECT=m CONFIG_NFT_COMPAT=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m @@ -262,6 +264,12 @@ CONFIG_L2TP=m CONFIG_BRIDGE=m CONFIG_ATALK=m CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m CONFIG_DNS_RESOLVER=y CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_DAT=y @@ -352,6 +360,7 @@ CONFIG_VETH=m # CONFIG_NET_VENDOR_INTEL is not set # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NETRONOME is not set CONFIG_NE2000=y # CONFIG_NET_VENDOR_QUALCOMM is not set # CONFIG_NET_VENDOR_RENESAS is not set diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index 0ce79eb0d805..5f9fb3ab9636 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -101,6 +101,8 @@ CONFIG_NFT_NAT=m CONFIG_NFT_QUEUE=m CONFIG_NFT_REJECT=m CONFIG_NFT_COMPAT=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m @@ -259,6 +261,12 @@ CONFIG_L2TP=m CONFIG_BRIDGE=m CONFIG_ATALK=m CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m CONFIG_DNS_RESOLVER=y CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_DAT=y @@ -340,6 +348,7 @@ CONFIG_SUN3_82586=y # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set # CONFIG_NET_VENDOR_QUALCOMM is not set # CONFIG_NET_VENDOR_RENESAS is not set # CONFIG_NET_VENDOR_ROCKER is not set diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index 4cb787e4991f..5d1c674530e2 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -101,6 +101,8 @@ CONFIG_NFT_NAT=m CONFIG_NFT_QUEUE=m CONFIG_NFT_REJECT=m CONFIG_NFT_COMPAT=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m @@ -259,6 +261,12 @@ CONFIG_L2TP=m CONFIG_BRIDGE=m CONFIG_ATALK=m CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m CONFIG_DNS_RESOLVER=y CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_DAT=y @@ -341,6 +349,7 @@ CONFIG_SUN3LANCE=y # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set # CONFIG_NET_VENDOR_QUALCOMM is not set # CONFIG_NET_VENDOR_RENESAS is not set # CONFIG_NET_VENDOR_ROCKER is not set diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index f9d96bf86910..bafaff6dcd7b 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h @@ -4,7 +4,7 @@ #include <uapi/asm/unistd.h> -#define NR_syscalls 376 +#define NR_syscalls 377 #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_STAT diff --git a/arch/m68k/include/uapi/asm/unistd.h b/arch/m68k/include/uapi/asm/unistd.h index 36cf129de663..0ca729665f29 100644 --- a/arch/m68k/include/uapi/asm/unistd.h +++ b/arch/m68k/include/uapi/asm/unistd.h @@ -381,5 +381,6 @@ #define __NR_userfaultfd 373 #define __NR_membarrier 374 #define __NR_mlock2 375 +#define __NR_copy_file_range 376 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */ diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S index 282cd903f4c4..8bb94261ff97 100644 --- a/arch/m68k/kernel/syscalltable.S +++ b/arch/m68k/kernel/syscalltable.S @@ -396,3 +396,4 @@ ENTRY(sys_call_table) .long sys_userfaultfd .long sys_membarrier .long sys_mlock2 /* 375 */ + .long sys_copy_file_range diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c index 8c6d76c9b2d6..d9907e57e9b9 100644 --- a/arch/mips/jz4740/gpio.c +++ b/arch/mips/jz4740/gpio.c @@ -270,7 +270,7 @@ uint32_t jz_gpio_port_get_value(int port, uint32_t mask) } EXPORT_SYMBOL(jz_gpio_port_get_value); -#define IRQ_TO_BIT(irq) BIT(irq_to_gpio(irq) & 0x1f) +#define IRQ_TO_BIT(irq) BIT((irq - JZ4740_IRQ_GPIO(0)) & 0x1f) static void jz_gpio_check_trigger_both(struct jz_gpio_chip *chip, unsigned int irq) { diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S index 5ce3b746cedc..b4ac6374a38f 100644 --- a/arch/mips/kernel/r2300_fpu.S +++ b/arch/mips/kernel/r2300_fpu.S @@ -125,7 +125,7 @@ LEAF(_restore_fp_context) END(_restore_fp_context) .set reorder - .type fault@function + .type fault, @function .ent fault fault: li v0, -EFAULT jr ra diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S index f09546ee2cdc..17732f876eff 100644 --- a/arch/mips/kernel/r4k_fpu.S +++ b/arch/mips/kernel/r4k_fpu.S @@ -358,7 +358,7 @@ LEAF(_restore_msa_all_upper) .set reorder - .type fault@function + .type fault, @function .ent fault fault: li v0, -EFAULT # failure jr ra diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index ae790c575d4f..bf14da9f3e33 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -690,15 +690,15 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode) asmlinkage void do_ov(struct pt_regs *regs) { enum ctx_state prev_state; - siginfo_t info; + siginfo_t info = { + .si_signo = SIGFPE, + .si_code = FPE_INTOVF, + .si_addr = (void __user *)regs->cp0_epc, + }; prev_state = exception_enter(); die_if_kernel("Integer overflow", regs); - info.si_code = FPE_INTOVF; - info.si_signo = SIGFPE; - info.si_errno = 0; - info.si_addr = (void __user *) regs->cp0_epc; force_sig_info(SIGFPE, &info, current); exception_exit(prev_state); } @@ -874,7 +874,7 @@ out: void do_trap_or_bp(struct pt_regs *regs, unsigned int code, const char *str) { - siginfo_t info; + siginfo_t info = { 0 }; char b[40]; #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP @@ -903,7 +903,6 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code, else info.si_code = FPE_INTOVF; info.si_signo = SIGFPE; - info.si_errno = 0; info.si_addr = (void __user *) regs->cp0_epc; force_sig_info(SIGFPE, &info, current); break; diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index 8bc3977576e6..3110447ab1e9 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c @@ -702,7 +702,7 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu, } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) { void __user *uaddr = (void __user *)(long)reg->addr; - return copy_to_user(uaddr, vs, 16); + return copy_to_user(uaddr, vs, 16) ? -EFAULT : 0; } else { return -EINVAL; } @@ -732,7 +732,7 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu, } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) { void __user *uaddr = (void __user *)(long)reg->addr; - return copy_from_user(vs, uaddr, 16); + return copy_from_user(vs, uaddr, 16) ? -EFAULT : 0; } else { return -EINVAL; } diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c index 5c81fdd032c3..353037699512 100644 --- a/arch/mips/mm/mmap.c +++ b/arch/mips/mm/mmap.c @@ -146,7 +146,7 @@ unsigned long arch_mmap_rnd(void) { unsigned long rnd; - rnd = (unsigned long)get_random_int(); + rnd = get_random_long(); rnd <<= PAGE_SHIFT; if (TASK_IS_32BIT_ADDR) rnd &= 0xfffffful; @@ -174,7 +174,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm) static inline unsigned long brk_rnd(void) { - unsigned long rnd = get_random_int(); + unsigned long rnd = get_random_long(); rnd = rnd << PAGE_SHIFT; /* 8MB for 32bit, 256MB for 64bit */ diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c index 249647578e58..91dec32c77b7 100644 --- a/arch/mips/mm/sc-mips.c +++ b/arch/mips/mm/sc-mips.c @@ -164,11 +164,13 @@ static int __init mips_sc_probe_cm3(void) sets = cfg & CM_GCR_L2_CONFIG_SET_SIZE_MSK; sets >>= CM_GCR_L2_CONFIG_SET_SIZE_SHF; - c->scache.sets = 64 << sets; + if (sets) + c->scache.sets = 64 << sets; line_sz = cfg & CM_GCR_L2_CONFIG_LINE_SIZE_MSK; line_sz >>= CM_GCR_L2_CONFIG_LINE_SIZE_SHF; - c->scache.linesz = 2 << line_sz; + if (line_sz) + c->scache.linesz = 2 << line_sz; assoc = cfg & CM_GCR_L2_CONFIG_ASSOC_MSK; assoc >>= CM_GCR_L2_CONFIG_ASSOC_SHF; @@ -176,9 +178,12 @@ static int __init mips_sc_probe_cm3(void) c->scache.waysize = c->scache.sets * c->scache.linesz; c->scache.waybit = __ffs(c->scache.waysize); - c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; + if (c->scache.linesz) { + c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; + return 1; + } - return 1; + return 0; } static inline int __init mips_sc_probe(void) diff --git a/arch/parisc/include/asm/floppy.h b/arch/parisc/include/asm/floppy.h index f84ff12574b7..6d8276cd25ca 100644 --- a/arch/parisc/include/asm/floppy.h +++ b/arch/parisc/include/asm/floppy.h @@ -33,7 +33,7 @@ * floppy accesses go through the track buffer. */ #define _CROSS_64KB(a,s,vdma) \ -(!vdma && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64)) +(!(vdma) && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64)) #define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1) diff --git a/arch/parisc/include/uapi/asm/unistd.h b/arch/parisc/include/uapi/asm/unistd.h index 35bdccbb2036..b75039f92116 100644 --- a/arch/parisc/include/uapi/asm/unistd.h +++ b/arch/parisc/include/uapi/asm/unistd.h @@ -361,8 +361,9 @@ #define __NR_membarrier (__NR_Linux + 343) #define __NR_userfaultfd (__NR_Linux + 344) #define __NR_mlock2 (__NR_Linux + 345) +#define __NR_copy_file_range (__NR_Linux + 346) -#define __NR_Linux_syscalls (__NR_mlock2 + 1) +#define __NR_Linux_syscalls (__NR_copy_file_range + 1) #define __IGNORE_select /* newselect */ diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 9585c81f755f..ce0b2b4075c7 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -269,14 +269,19 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, long do_syscall_trace_enter(struct pt_regs *regs) { - long ret = 0; - /* Do the secure computing check first. */ secure_computing_strict(regs->gr[20]); if (test_thread_flag(TIF_SYSCALL_TRACE) && - tracehook_report_syscall_entry(regs)) - ret = -1L; + tracehook_report_syscall_entry(regs)) { + /* + * Tracing decided this syscall should not happen or the + * debugger stored an invalid system call number. Skip + * the system call and the system call restart handling. + */ + regs->gr[20] = -1UL; + goto out; + } #ifdef CONFIG_64BIT if (!is_compat_task()) @@ -290,7 +295,8 @@ long do_syscall_trace_enter(struct pt_regs *regs) regs->gr[24] & 0xffffffff, regs->gr[23] & 0xffffffff); - return ret ? : regs->gr[20]; +out: + return regs->gr[20]; } void do_syscall_trace_exit(struct pt_regs *regs) diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 3fbd7252a4b2..fbafa0d0e2bf 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -343,7 +343,7 @@ tracesys_next: #endif comiclr,>>= __NR_Linux_syscalls, %r20, %r0 - b,n .Lsyscall_nosys + b,n .Ltracesys_nosys LDREGX %r20(%r19), %r19 @@ -359,6 +359,9 @@ tracesys_next: be 0(%sr7,%r19) ldo R%tracesys_exit(%r2),%r2 +.Ltracesys_nosys: + ldo -ENOSYS(%r0),%r28 /* set errno */ + /* Do *not* call this function on the gateway page, because it makes a direct call to syscall_trace. */ diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index d4ffcfbc9885..585d50fc75c0 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -441,6 +441,7 @@ ENTRY_SAME(membarrier) ENTRY_SAME(userfaultfd) ENTRY_SAME(mlock2) /* 345 */ + ENTRY_SAME(copy_file_range) .ifne (. - 90b) - (__NR_Linux_syscalls * (91b - 90b)) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index e4824fd04bb7..9faa18c4f3f7 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -557,7 +557,7 @@ choice config PPC_4K_PAGES bool "4k page size" - select HAVE_ARCH_SOFT_DIRTY if CHECKPOINT_RESTORE && PPC_BOOK3S + select HAVE_ARCH_SOFT_DIRTY if PPC_BOOK3S_64 config PPC_16K_PAGES bool "16k page size" @@ -566,7 +566,7 @@ config PPC_16K_PAGES config PPC_64K_PAGES bool "64k page size" depends on !PPC_FSL_BOOK3E && (44x || PPC_STD_MMU_64 || PPC_BOOK3E_64) - select HAVE_ARCH_SOFT_DIRTY if CHECKPOINT_RESTORE && PPC_BOOK3S + select HAVE_ARCH_SOFT_DIRTY if PPC_BOOK3S_64 config PPC_256K_PAGES bool "256k page size" diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h index 8d1c41d28318..ac07a30a7934 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h @@ -281,6 +281,10 @@ extern pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp); extern void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp); +#define __HAVE_ARCH_PMDP_HUGE_SPLIT_PREPARE +extern void pmdp_huge_split_prepare(struct vm_area_struct *vma, + unsigned long address, pmd_t *pmdp); + #define pmd_move_must_withdraw pmd_move_must_withdraw struct spinlock; static inline int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl, diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index c5eb86f3d452..867c39b45df6 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -81,6 +81,7 @@ struct pci_dn; #define EEH_PE_KEEP (1 << 8) /* Keep PE on hotplug */ #define EEH_PE_CFG_RESTRICTED (1 << 9) /* Block config on error */ #define EEH_PE_REMOVED (1 << 10) /* Removed permanently */ +#define EEH_PE_PRI_BUS (1 << 11) /* Cached primary bus */ struct eeh_pe { int type; /* PE type: PHB/Bus/Device */ diff --git a/arch/powerpc/include/asm/trace.h b/arch/powerpc/include/asm/trace.h index 8e86b48d0369..32e36b16773f 100644 --- a/arch/powerpc/include/asm/trace.h +++ b/arch/powerpc/include/asm/trace.h @@ -57,12 +57,14 @@ DEFINE_EVENT(ppc64_interrupt_class, timer_interrupt_exit, extern void hcall_tracepoint_regfunc(void); extern void hcall_tracepoint_unregfunc(void); -TRACE_EVENT_FN(hcall_entry, +TRACE_EVENT_FN_COND(hcall_entry, TP_PROTO(unsigned long opcode, unsigned long *args), TP_ARGS(opcode, args), + TP_CONDITION(cpu_online(raw_smp_processor_id())), + TP_STRUCT__entry( __field(unsigned long, opcode) ), @@ -76,13 +78,15 @@ TRACE_EVENT_FN(hcall_entry, hcall_tracepoint_regfunc, hcall_tracepoint_unregfunc ); -TRACE_EVENT_FN(hcall_exit, +TRACE_EVENT_FN_COND(hcall_exit, TP_PROTO(unsigned long opcode, unsigned long retval, unsigned long *retbuf), TP_ARGS(opcode, retval, retbuf), + TP_CONDITION(cpu_online(raw_smp_processor_id())), + TP_STRUCT__entry( __field(unsigned long, opcode) __field(unsigned long, retval) diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 938742135ee0..650cfb31ea3d 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c @@ -418,8 +418,7 @@ static void *eeh_rmv_device(void *data, void *userdata) eeh_pcid_put(dev); if (driver->err_handler && driver->err_handler->error_detected && - driver->err_handler->slot_reset && - driver->err_handler->resume) + driver->err_handler->slot_reset) return NULL; } @@ -564,6 +563,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus) */ eeh_pe_state_mark(pe, EEH_PE_KEEP); if (bus) { + eeh_pe_state_clear(pe, EEH_PE_PRI_BUS); pci_lock_rescan_remove(); pcibios_remove_pci_devices(bus); pci_unlock_rescan_remove(); @@ -803,6 +803,7 @@ perm_error: * the their PCI config any more. */ if (frozen_bus) { + eeh_pe_state_clear(pe, EEH_PE_PRI_BUS); eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED); pci_lock_rescan_remove(); @@ -886,6 +887,7 @@ static void eeh_handle_special_event(void) continue; /* Notify all devices to be down */ + eeh_pe_state_clear(pe, EEH_PE_PRI_BUS); bus = eeh_pe_bus_get(phb_pe); eeh_pe_dev_traverse(pe, eeh_report_failure, NULL); diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index ca9e5371930e..98f81800e00c 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c @@ -928,7 +928,7 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe) bus = pe->phb->bus; } else if (pe->type & EEH_PE_BUS || pe->type & EEH_PE_DEVICE) { - if (pe->bus) { + if (pe->state & EEH_PE_PRI_BUS) { bus = pe->bus; goto out; } diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c index 05e804cdecaa..aec9a1b1d25b 100644 --- a/arch/powerpc/kernel/hw_breakpoint.c +++ b/arch/powerpc/kernel/hw_breakpoint.c @@ -109,8 +109,9 @@ void arch_unregister_hw_breakpoint(struct perf_event *bp) * If the breakpoint is unregistered between a hw_breakpoint_handler() * and the single_step_dabr_instruction(), then cleanup the breakpoint * restoration variables to prevent dangling pointers. + * FIXME, this should not be using bp->ctx at all! Sayeth peterz. */ - if (bp->ctx && bp->ctx->task) + if (bp->ctx && bp->ctx->task && bp->ctx->task != ((void *)-1L)) bp->ctx->task->thread.last_hit_ubp = NULL; } diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index ac64ffdb52c8..08b7a40de5f8 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -340,7 +340,7 @@ static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab) if (name[0] == '.') { if (strcmp(name+1, "TOC.") == 0) syms[i].st_shndx = SHN_ABS; - memmove(name, name+1, strlen(name)); + syms[i].st_name++; } } } diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index dccc87e8fee5..3c5736e52a14 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1768,9 +1768,9 @@ static inline unsigned long brk_rnd(void) /* 8MB for 32bit, 1GB for 64bit */ if (is_32bit_task()) - rnd = (long)(get_random_int() % (1<<(23-PAGE_SHIFT))); + rnd = (get_random_long() % (1UL<<(23-PAGE_SHIFT))); else - rnd = (long)(get_random_int() % (1<<(30-PAGE_SHIFT))); + rnd = (get_random_long() % (1UL<<(30-PAGE_SHIFT))); return rnd << PAGE_SHIFT; } diff --git a/arch/powerpc/mm/hash64_64k.c b/arch/powerpc/mm/hash64_64k.c index 0762c1e08c88..edb09912f0c9 100644 --- a/arch/powerpc/mm/hash64_64k.c +++ b/arch/powerpc/mm/hash64_64k.c @@ -111,7 +111,13 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, */ if (!(old_pte & _PAGE_COMBO)) { flush_hash_page(vpn, rpte, MMU_PAGE_64K, ssize, flags); - old_pte &= ~_PAGE_HASHPTE | _PAGE_F_GIX | _PAGE_F_SECOND; + /* + * clear the old slot details from the old and new pte. + * On hash insert failure we use old pte value and we don't + * want slot information there if we have a insert failure. + */ + old_pte &= ~(_PAGE_HASHPTE | _PAGE_F_GIX | _PAGE_F_SECOND); + new_pte &= ~(_PAGE_HASHPTE | _PAGE_F_GIX | _PAGE_F_SECOND); goto htab_insert_hpte; } /* diff --git a/arch/powerpc/mm/hugepage-hash64.c b/arch/powerpc/mm/hugepage-hash64.c index 49b152b0f926..eb2accdd76fd 100644 --- a/arch/powerpc/mm/hugepage-hash64.c +++ b/arch/powerpc/mm/hugepage-hash64.c @@ -78,9 +78,19 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, * base page size. This is because demote_segment won't flush * hash page table entries. */ - if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO)) + if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO)) { flush_hash_hugepage(vsid, ea, pmdp, MMU_PAGE_64K, ssize, flags); + /* + * With THP, we also clear the slot information with + * respect to all the 64K hash pte mapping the 16MB + * page. They are all invalid now. This make sure we + * don't find the slot valid when we fault with 4k + * base page size. + * + */ + memset(hpte_slot_array, 0, PTE_FRAG_SIZE); + } } valid = hpte_valid(hpte_slot_array, index); diff --git a/arch/powerpc/mm/hugetlbpage-book3e.c b/arch/powerpc/mm/hugetlbpage-book3e.c index 7e6d0880813f..83a8be791e06 100644 --- a/arch/powerpc/mm/hugetlbpage-book3e.c +++ b/arch/powerpc/mm/hugetlbpage-book3e.c @@ -8,6 +8,8 @@ #include <linux/mm.h> #include <linux/hugetlb.h> +#include <asm/mmu.h> + #ifdef CONFIG_PPC_FSL_BOOK3E #ifdef CONFIG_PPC64 static inline int tlb1_next(void) @@ -60,6 +62,14 @@ static inline void book3e_tlb_lock(void) unsigned long tmp; int token = smp_processor_id() + 1; + /* + * Besides being unnecessary in the absence of SMT, this + * check prevents trying to do lbarx/stbcx. on e5500 which + * doesn't implement either feature. + */ + if (!cpu_has_feature(CPU_FTR_SMT)) + return; + asm volatile("1: lbarx %0, 0, %1;" "cmpwi %0, 0;" "bne 2f;" @@ -80,6 +90,9 @@ static inline void book3e_tlb_unlock(void) { struct paca_struct *paca = get_paca(); + if (!cpu_has_feature(CPU_FTR_SMT)) + return; + isync(); paca->tcd_ptr->lock = 0; } diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c index 0f0502e12f6c..4087705ba90f 100644 --- a/arch/powerpc/mm/mmap.c +++ b/arch/powerpc/mm/mmap.c @@ -59,9 +59,9 @@ unsigned long arch_mmap_rnd(void) /* 8MB for 32bit, 1GB for 64bit */ if (is_32bit_task()) - rnd = (unsigned long)get_random_int() % (1<<(23-PAGE_SHIFT)); + rnd = get_random_long() % (1<<(23-PAGE_SHIFT)); else - rnd = (unsigned long)get_random_int() % (1<<(30-PAGE_SHIFT)); + rnd = get_random_long() % (1UL<<(30-PAGE_SHIFT)); return rnd << PAGE_SHIFT; } diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 3124a20d0fab..cdf2123d46db 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c @@ -646,6 +646,28 @@ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp) return pgtable; } +void pmdp_huge_split_prepare(struct vm_area_struct *vma, + unsigned long address, pmd_t *pmdp) +{ + VM_BUG_ON(address & ~HPAGE_PMD_MASK); + VM_BUG_ON(REGION_ID(address) != USER_REGION_ID); + + /* + * We can't mark the pmd none here, because that will cause a race + * against exit_mmap. We need to continue mark pmd TRANS HUGE, while + * we spilt, but at the same time we wan't rest of the ppc64 code + * not to insert hash pte on this, because we will be modifying + * the deposited pgtable in the caller of this function. Hence + * clear the _PAGE_USER so that we move the fault handling to + * higher level function and that will serialize against ptl. + * We need to flush existing hash pte entries here even though, + * the translation is still valid, because we will withdraw + * pgtable_t after this. + */ + pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_USER, 0); +} + + /* * set a new huge pmd. We should not be called for updating * an existing pmd entry. That should go via pmd_hugepage_update. @@ -663,10 +685,20 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, return set_pte_at(mm, addr, pmdp_ptep(pmdp), pmd_pte(pmd)); } +/* + * We use this to invalidate a pmdp entry before switching from a + * hugepte to regular pmd entry. + */ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp) { pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, 0); + + /* + * This ensures that generic code that rely on IRQ disabling + * to prevent a parallel THP split work as expected. + */ + kick_all_cpus_sync(); } /* diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 5f152b95ca0c..87f47e55aab6 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -444,9 +444,12 @@ static void *pnv_eeh_probe(struct pci_dn *pdn, void *data) * PCI devices of the PE are expected to be removed prior * to PE reset. */ - if (!edev->pe->bus) + if (!(edev->pe->state & EEH_PE_PRI_BUS)) { edev->pe->bus = pci_find_bus(hose->global_number, pdn->busno); + if (edev->pe->bus) + edev->pe->state |= EEH_PE_PRI_BUS; + } /* * Enable EEH explicitly so that we will do EEH check diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 573ae1994097..f90dc04395bf 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -3180,6 +3180,7 @@ static void pnv_pci_ioda_shutdown(struct pci_controller *hose) static const struct pci_controller_ops pnv_pci_ioda_controller_ops = { .dma_dev_setup = pnv_pci_dma_dev_setup, + .dma_bus_setup = pnv_pci_dma_bus_setup, #ifdef CONFIG_PCI_MSI .setup_msi_irqs = pnv_setup_msi_irqs, .teardown_msi_irqs = pnv_teardown_msi_irqs, diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 2f55c86df703..b1ef84a6c9d1 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -599,6 +599,9 @@ int pnv_tce_build(struct iommu_table *tbl, long index, long npages, u64 rpn = __pa(uaddr) >> tbl->it_page_shift; long i; + if (proto_tce & TCE_PCI_WRITE) + proto_tce |= TCE_PCI_READ; + for (i = 0; i < npages; i++) { unsigned long newtce = proto_tce | ((rpn + i) << tbl->it_page_shift); @@ -620,6 +623,9 @@ int pnv_tce_xchg(struct iommu_table *tbl, long index, BUG_ON(*hpa & ~IOMMU_PAGE_MASK(tbl)); + if (newtce & TCE_PCI_WRITE) + newtce |= TCE_PCI_READ; + oldtce = xchg(pnv_tce(tbl, idx), cpu_to_be64(newtce)); *hpa = be64_to_cpu(oldtce) & ~(TCE_PCI_READ | TCE_PCI_WRITE); *direction = iommu_tce_direction(oldtce); @@ -760,6 +766,26 @@ void pnv_pci_dma_dev_setup(struct pci_dev *pdev) phb->dma_dev_setup(phb, pdev); } +void pnv_pci_dma_bus_setup(struct pci_bus *bus) +{ + struct pci_controller *hose = bus->sysdata; + struct pnv_phb *phb = hose->private_data; + struct pnv_ioda_pe *pe; + + list_for_each_entry(pe, &phb->ioda.pe_list, list) { + if (!(pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL))) + continue; + + if (!pe->pbus) + continue; + + if (bus->number == ((pe->rid >> 8) & 0xFF)) { + pe->pbus = bus; + break; + } + } +} + void pnv_pci_shutdown(void) { struct pci_controller *hose; diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 7f56313e8d72..00691a9b99af 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -242,6 +242,7 @@ extern void pnv_pci_reset_secondary_bus(struct pci_dev *dev); extern int pnv_eeh_phb_reset(struct pci_controller *hose, int option); extern void pnv_pci_dma_dev_setup(struct pci_dev *pdev); +extern void pnv_pci_dma_bus_setup(struct pci_bus *bus); extern int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type); extern void pnv_teardown_msi_irqs(struct pci_dev *pdev); diff --git a/arch/s390/include/asm/fpu/internal.h b/arch/s390/include/asm/fpu/internal.h index ea91ddfe54eb..629c90865a07 100644 --- a/arch/s390/include/asm/fpu/internal.h +++ b/arch/s390/include/asm/fpu/internal.h @@ -40,6 +40,7 @@ static inline void convert_fp_to_vx(__vector128 *vxrs, freg_t *fprs) static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu) { fpregs->pad = 0; + fpregs->fpc = fpu->fpc; if (MACHINE_HAS_VX) convert_vx_to_fp((freg_t *)&fpregs->fprs, fpu->vxrs); else @@ -49,6 +50,7 @@ static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu) static inline void fpregs_load(_s390_fp_regs *fpregs, struct fpu *fpu) { + fpu->fpc = fpregs->fpc; if (MACHINE_HAS_VX) convert_fp_to_vx(fpu->vxrs, (freg_t *)&fpregs->fprs); else diff --git a/arch/s390/include/asm/livepatch.h b/arch/s390/include/asm/livepatch.h index 7aa799134a11..a52b6cca873d 100644 --- a/arch/s390/include/asm/livepatch.h +++ b/arch/s390/include/asm/livepatch.h @@ -37,7 +37,7 @@ static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip) regs->psw.addr = ip; } #else -#error Live patching support is disabled; check CONFIG_LIVEPATCH +#error Include linux/livepatch.h, not asm/livepatch.h #endif #endif diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 66c94417c0ba..4af60374eba0 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -271,7 +271,7 @@ static int restore_sigregs_ext32(struct pt_regs *regs, /* Restore high gprs from signal stack */ if (__copy_from_user(&gprs_high, &sregs_ext->gprs_high, - sizeof(&sregs_ext->gprs_high))) + sizeof(sregs_ext->gprs_high))) return -EFAULT; for (i = 0; i < NUM_GPRS; i++) *(__u32 *)®s->gprs[i] = gprs_high[i]; diff --git a/arch/s390/kernel/perf_event.c b/arch/s390/kernel/perf_event.c index cfcba2dd9bb5..0943b11a2f6e 100644 --- a/arch/s390/kernel/perf_event.c +++ b/arch/s390/kernel/perf_event.c @@ -260,12 +260,13 @@ static unsigned long __store_trace(struct perf_callchain_entry *entry, void perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) { - unsigned long head; + unsigned long head, frame_size; struct stack_frame *head_sf; if (user_mode(regs)) return; + frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs); head = regs->gprs[15]; head_sf = (struct stack_frame *) head; @@ -273,8 +274,9 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry, return; head = head_sf->back_chain; - head = __store_trace(entry, head, S390_lowcore.async_stack - ASYNC_SIZE, - S390_lowcore.async_stack); + head = __store_trace(entry, head, + S390_lowcore.async_stack + frame_size - ASYNC_SIZE, + S390_lowcore.async_stack + frame_size); __store_trace(entry, head, S390_lowcore.thread_info, S390_lowcore.thread_info + THREAD_SIZE); diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c index 5acba3cb7220..8f64ebd63767 100644 --- a/arch/s390/kernel/stacktrace.c +++ b/arch/s390/kernel/stacktrace.c @@ -59,26 +59,32 @@ static unsigned long save_context_stack(struct stack_trace *trace, } } -void save_stack_trace(struct stack_trace *trace) +static void __save_stack_trace(struct stack_trace *trace, unsigned long sp) { - register unsigned long sp asm ("15"); - unsigned long orig_sp, new_sp; + unsigned long new_sp, frame_size; - orig_sp = sp; - new_sp = save_context_stack(trace, orig_sp, - S390_lowcore.panic_stack - PAGE_SIZE, - S390_lowcore.panic_stack, 1); - if (new_sp != orig_sp) - return; + frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs); + new_sp = save_context_stack(trace, sp, + S390_lowcore.panic_stack + frame_size - PAGE_SIZE, + S390_lowcore.panic_stack + frame_size, 1); new_sp = save_context_stack(trace, new_sp, - S390_lowcore.async_stack - ASYNC_SIZE, - S390_lowcore.async_stack, 1); - if (new_sp != orig_sp) - return; + S390_lowcore.async_stack + frame_size - ASYNC_SIZE, + S390_lowcore.async_stack + frame_size, 1); save_context_stack(trace, new_sp, S390_lowcore.thread_info, S390_lowcore.thread_info + THREAD_SIZE, 1); } + +void save_stack_trace(struct stack_trace *trace) +{ + register unsigned long r15 asm ("15"); + unsigned long sp; + + sp = r15; + __save_stack_trace(trace, sp); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; +} EXPORT_SYMBOL_GPL(save_stack_trace); void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) @@ -86,6 +92,10 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) unsigned long sp, low, high; sp = tsk->thread.ksp; + if (tsk == current) { + /* Get current stack pointer. */ + asm volatile("la %0,0(15)" : "=a" (sp)); + } low = (unsigned long) task_stack_page(tsk); high = (unsigned long) task_pt_regs(tsk); save_context_stack(trace, sp, low, high, 0); @@ -93,3 +103,14 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) trace->entries[trace->nr_entries++] = ULONG_MAX; } EXPORT_SYMBOL_GPL(save_stack_trace_tsk); + +void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) +{ + unsigned long sp; + + sp = kernel_stack_pointer(regs); + __save_stack_trace(trace, sp); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; +} +EXPORT_SYMBOL_GPL(save_stack_trace_regs); diff --git a/arch/s390/kernel/trace.c b/arch/s390/kernel/trace.c index 21a5df99552b..dde7654f5c68 100644 --- a/arch/s390/kernel/trace.c +++ b/arch/s390/kernel/trace.c @@ -18,6 +18,9 @@ void trace_s390_diagnose_norecursion(int diag_nr) unsigned long flags; unsigned int *depth; + /* Avoid lockdep recursion. */ + if (IS_ENABLED(CONFIG_LOCKDEP)) + return; local_irq_save(flags); depth = this_cpu_ptr(&diagnose_trace_depth); if (*depth == 0) { diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c index fec59c067d0d..792f9c63fbca 100644 --- a/arch/s390/mm/maccess.c +++ b/arch/s390/mm/maccess.c @@ -93,15 +93,19 @@ static int __memcpy_real(void *dest, void *src, size_t count) */ int memcpy_real(void *dest, void *src, size_t count) { + int irqs_disabled, rc; unsigned long flags; - int rc; if (!count) return 0; - local_irq_save(flags); - __arch_local_irq_stnsm(0xfbUL); + flags = __arch_local_irq_stnsm(0xf8UL); + irqs_disabled = arch_irqs_disabled_flags(flags); + if (!irqs_disabled) + trace_hardirqs_off(); rc = __memcpy_real(dest, src, count); - local_irq_restore(flags); + if (!irqs_disabled) + trace_hardirqs_on(); + __arch_local_irq_ssm(flags); return rc; } diff --git a/arch/s390/oprofile/backtrace.c b/arch/s390/oprofile/backtrace.c index fe0bfe370c45..1884e1759529 100644 --- a/arch/s390/oprofile/backtrace.c +++ b/arch/s390/oprofile/backtrace.c @@ -54,12 +54,13 @@ __show_trace(unsigned int *depth, unsigned long sp, void s390_backtrace(struct pt_regs * const regs, unsigned int depth) { - unsigned long head; + unsigned long head, frame_size; struct stack_frame* head_sf; if (user_mode(regs)) return; + frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs); head = regs->gprs[15]; head_sf = (struct stack_frame*)head; @@ -68,8 +69,9 @@ void s390_backtrace(struct pt_regs * const regs, unsigned int depth) head = head_sf->back_chain; - head = __show_trace(&depth, head, S390_lowcore.async_stack - ASYNC_SIZE, - S390_lowcore.async_stack); + head = __show_trace(&depth, head, + S390_lowcore.async_stack + frame_size - ASYNC_SIZE, + S390_lowcore.async_stack + frame_size); __show_trace(&depth, head, S390_lowcore.thread_info, S390_lowcore.thread_info + THREAD_SIZE); diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile index eaee14637d93..8496a074bd0e 100644 --- a/arch/sparc/Makefile +++ b/arch/sparc/Makefile @@ -24,7 +24,13 @@ LDFLAGS := -m elf32_sparc export BITS := 32 UTS_MACHINE := sparc +# We are adding -Wa,-Av8 to KBUILD_CFLAGS to deal with a specs bug in some +# versions of gcc. Some gcc versions won't pass -Av8 to binutils when you +# give -mcpu=v8. This silently worked with older bintutils versions but +# does not any more. KBUILD_CFLAGS += -m32 -mcpu=v8 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7 +KBUILD_CFLAGS += -Wa,-Av8 + KBUILD_AFLAGS += -m32 -Wa,-Av8 else diff --git a/arch/sparc/include/uapi/asm/unistd.h b/arch/sparc/include/uapi/asm/unistd.h index 1c26d440d288..b6de8b10a55b 100644 --- a/arch/sparc/include/uapi/asm/unistd.h +++ b/arch/sparc/include/uapi/asm/unistd.h @@ -422,8 +422,9 @@ #define __NR_listen 354 #define __NR_setsockopt 355 #define __NR_mlock2 356 +#define __NR_copy_file_range 357 -#define NR_syscalls 357 +#define NR_syscalls 358 /* Bitmask values returned from kern_features system call. */ #define KERN_FEATURE_MIXED_MODE_STACK 0x00000001 diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 33c02b15f478..a83707c83be8 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -948,7 +948,24 @@ linux_syscall_trace: cmp %o0, 0 bne 3f mov -ENOSYS, %o0 + + /* Syscall tracing can modify the registers. */ + ld [%sp + STACKFRAME_SZ + PT_G1], %g1 + sethi %hi(sys_call_table), %l7 + ld [%sp + STACKFRAME_SZ + PT_I0], %i0 + or %l7, %lo(sys_call_table), %l7 + ld [%sp + STACKFRAME_SZ + PT_I1], %i1 + ld [%sp + STACKFRAME_SZ + PT_I2], %i2 + ld [%sp + STACKFRAME_SZ + PT_I3], %i3 + ld [%sp + STACKFRAME_SZ + PT_I4], %i4 + ld [%sp + STACKFRAME_SZ + PT_I5], %i5 + cmp %g1, NR_syscalls + bgeu 3f + mov -ENOSYS, %o0 + + sll %g1, 2, %l4 mov %i0, %o0 + ld [%l7 + %l4], %l7 mov %i1, %o1 mov %i2, %o2 mov %i3, %o3 diff --git a/arch/sparc/kernel/hvcalls.S b/arch/sparc/kernel/hvcalls.S index afbaba52d2f1..d127130bf424 100644 --- a/arch/sparc/kernel/hvcalls.S +++ b/arch/sparc/kernel/hvcalls.S @@ -338,8 +338,9 @@ ENTRY(sun4v_mach_set_watchdog) mov %o1, %o4 mov HV_FAST_MACH_SET_WATCHDOG, %o5 ta HV_FAST_TRAP + brnz,a,pn %o4, 0f stx %o1, [%o4] - retl +0: retl nop ENDPROC(sun4v_mach_set_watchdog) diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index d88beff47bab..39aaec173f66 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -52,7 +52,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs) unsigned char fenab; int err; - flush_user_windows(); + synchronize_user_stack(); if (get_thread_wsaved() || (((unsigned long)ucp) & (sizeof(unsigned long)-1)) || (!__access_ok(ucp, sizeof(*ucp)))) diff --git a/arch/sparc/kernel/sparc_ksyms_64.c b/arch/sparc/kernel/sparc_ksyms_64.c index a92d5d2c46a3..9e034f29dcc5 100644 --- a/arch/sparc/kernel/sparc_ksyms_64.c +++ b/arch/sparc/kernel/sparc_ksyms_64.c @@ -37,6 +37,7 @@ EXPORT_SYMBOL(sun4v_niagara_getperf); EXPORT_SYMBOL(sun4v_niagara_setperf); EXPORT_SYMBOL(sun4v_niagara2_getperf); EXPORT_SYMBOL(sun4v_niagara2_setperf); +EXPORT_SYMBOL(sun4v_mach_set_watchdog); /* from hweight.S */ EXPORT_SYMBOL(__arch_hweight8); diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index c690c8e16a96..b489e9759518 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -264,7 +264,7 @@ static unsigned long mmap_rnd(void) unsigned long rnd = 0UL; if (current->flags & PF_RANDOMIZE) { - unsigned long val = get_random_int(); + unsigned long val = get_random_long(); if (test_thread_flag(TIF_32BIT)) rnd = (val % (1UL << (23UL-PAGE_SHIFT))); else diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S index bb0008927598..c4a1b5c40e4e 100644 --- a/arch/sparc/kernel/syscalls.S +++ b/arch/sparc/kernel/syscalls.S @@ -158,7 +158,25 @@ linux_syscall_trace32: add %sp, PTREGS_OFF, %o0 brnz,pn %o0, 3f mov -ENOSYS, %o0 + + /* Syscall tracing can modify the registers. */ + ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 + sethi %hi(sys_call_table32), %l7 + ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0 + or %l7, %lo(sys_call_table32), %l7 + ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1 + ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2 + ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3 + ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4 + ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5 + + cmp %g1, NR_syscalls + bgeu,pn %xcc, 3f + mov -ENOSYS, %o0 + + sll %g1, 2, %l4 srl %i0, 0, %o0 + lduw [%l7 + %l4], %l7 srl %i4, 0, %o4 srl %i1, 0, %o1 srl %i2, 0, %o2 @@ -170,7 +188,25 @@ linux_syscall_trace: add %sp, PTREGS_OFF, %o0 brnz,pn %o0, 3f mov -ENOSYS, %o0 + + /* Syscall tracing can modify the registers. */ + ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 + sethi %hi(sys_call_table64), %l7 + ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0 + or %l7, %lo(sys_call_table64), %l7 + ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1 + ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2 + ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3 + ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4 + ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5 + + cmp %g1, NR_syscalls + bgeu,pn %xcc, 3f + mov -ENOSYS, %o0 + + sll %g1, 2, %l4 mov %i0, %o0 + lduw [%l7 + %l4], %l7 mov %i1, %o1 mov %i2, %o2 mov %i3, %o3 diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index e663b6c78de2..6c3dd6c52f8b 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S @@ -88,4 +88,4 @@ sys_call_table: /*340*/ .long sys_ni_syscall, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr /*345*/ .long sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf /*350*/ .long sys_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen -/*355*/ .long sys_setsockopt, sys_mlock2 +/*355*/ .long sys_setsockopt, sys_mlock2, sys_copy_file_range diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index 1557121f4cdc..12b524cfcfa0 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -89,7 +89,7 @@ sys_call_table32: /*340*/ .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr .word sys32_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf /*350*/ .word sys32_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen - .word compat_sys_setsockopt, sys_mlock2 + .word compat_sys_setsockopt, sys_mlock2, sys_copy_file_range #endif /* CONFIG_COMPAT */ @@ -170,4 +170,4 @@ sys_call_table: /*340*/ .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr .word sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf /*350*/ .word sys64_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen - .word sys_setsockopt, sys_mlock2 + .word sys_setsockopt, sys_mlock2, sys_copy_file_range diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index 9bdf67a092a5..b60a9f8cda75 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c @@ -12,6 +12,7 @@ #include <skas.h> void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); static void kill_off_processes(void) { diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c index fc8be0e3a4ff..57acbd67d85d 100644 --- a/arch/um/kernel/signal.c +++ b/arch/um/kernel/signal.c @@ -69,7 +69,7 @@ void do_signal(struct pt_regs *regs) struct ksignal ksig; int handled_sig = 0; - if (get_signal(&ksig)) { + while (get_signal(&ksig)) { handled_sig = 1; /* Whee! Actually deliver the signal. */ handle_signal(&ksig, regs); diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index 4c5228352744..66350e6a6ca5 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -294,6 +294,7 @@ sysenter_past_esp: pushl $__USER_DS /* pt_regs->ss */ pushl %ebp /* pt_regs->sp (stashed in bp) */ pushfl /* pt_regs->flags (except IF = 0) */ + ASM_CLAC /* Clear AC after saving FLAGS */ orl $X86_EFLAGS_IF, (%esp) /* Fix IF */ pushl $__USER_CS /* pt_regs->cs */ pushl $0 /* pt_regs->ip = 0 (placeholder) */ diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S index ff1c6d61f332..3c990eeee40b 100644 --- a/arch/x86/entry/entry_64_compat.S +++ b/arch/x86/entry/entry_64_compat.S @@ -261,6 +261,7 @@ ENTRY(entry_INT80_compat) * Interrupts are off on entry. */ PARAVIRT_ADJUST_EXCEPTION_FRAME + ASM_CLAC /* Do this early to minimize exposure */ SWAPGS /* diff --git a/arch/x86/include/asm/livepatch.h b/arch/x86/include/asm/livepatch.h index 19c099afa861..e795f5274217 100644 --- a/arch/x86/include/asm/livepatch.h +++ b/arch/x86/include/asm/livepatch.h @@ -41,7 +41,7 @@ static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip) regs->ip = ip; } #else -#error Live patching support is disabled; check CONFIG_LIVEPATCH +#error Include linux/livepatch.h, not asm/livepatch.h #endif #endif /* _ASM_X86_LIVEPATCH_H */ diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h index 46873fbd44e1..d08eacd298c2 100644 --- a/arch/x86/include/asm/pci_x86.h +++ b/arch/x86/include/asm/pci_x86.h @@ -93,6 +93,8 @@ extern raw_spinlock_t pci_config_lock; extern int (*pcibios_enable_irq)(struct pci_dev *dev); extern void (*pcibios_disable_irq)(struct pci_dev *dev); +extern bool mp_should_keep_irq(struct device *dev); + struct pci_raw_ops { int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn, int reg, int len, u32 *val); diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h index f5dcb5204dcd..3fe0eac59462 100644 --- a/arch/x86/include/asm/uaccess_32.h +++ b/arch/x86/include/asm/uaccess_32.h @@ -48,20 +48,28 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) switch (n) { case 1: + __uaccess_begin(); __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret, 1); + __uaccess_end(); return ret; case 2: + __uaccess_begin(); __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret, 2); + __uaccess_end(); return ret; case 4: + __uaccess_begin(); __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret, 4); + __uaccess_end(); return ret; case 8: + __uaccess_begin(); __put_user_size(*(u64 *)from, (u64 __user *)to, 8, ret, 8); + __uaccess_end(); return ret; } } @@ -103,13 +111,19 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) switch (n) { case 1: + __uaccess_begin(); __get_user_size(*(u8 *)to, from, 1, ret, 1); + __uaccess_end(); return ret; case 2: + __uaccess_begin(); __get_user_size(*(u16 *)to, from, 2, ret, 2); + __uaccess_end(); return ret; case 4: + __uaccess_begin(); __get_user_size(*(u32 *)to, from, 4, ret, 4); + __uaccess_end(); return ret; } } @@ -148,13 +162,19 @@ __copy_from_user(void *to, const void __user *from, unsigned long n) switch (n) { case 1: + __uaccess_begin(); __get_user_size(*(u8 *)to, from, 1, ret, 1); + __uaccess_end(); return ret; case 2: + __uaccess_begin(); __get_user_size(*(u16 *)to, from, 2, ret, 2); + __uaccess_end(); return ret; case 4: + __uaccess_begin(); __get_user_size(*(u32 *)to, from, 4, ret, 4); + __uaccess_end(); return ret; } } @@ -170,13 +190,19 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to, switch (n) { case 1: + __uaccess_begin(); __get_user_size(*(u8 *)to, from, 1, ret, 1); + __uaccess_end(); return ret; case 2: + __uaccess_begin(); __get_user_size(*(u16 *)to, from, 2, ret, 2); + __uaccess_end(); return ret; case 4: + __uaccess_begin(); __get_user_size(*(u32 *)to, from, 4, ret, 4); + __uaccess_end(); return ret; } } diff --git a/arch/x86/include/asm/xen/pci.h b/arch/x86/include/asm/xen/pci.h index 968d57dd54c9..f320ee32d5a1 100644 --- a/arch/x86/include/asm/xen/pci.h +++ b/arch/x86/include/asm/xen/pci.h @@ -57,7 +57,7 @@ static inline int xen_pci_frontend_enable_msi(struct pci_dev *dev, { if (xen_pci_frontend && xen_pci_frontend->enable_msi) return xen_pci_frontend->enable_msi(dev, vectors); - return -ENODEV; + return -ENOSYS; } static inline void xen_pci_frontend_disable_msi(struct pci_dev *dev) { @@ -69,7 +69,7 @@ static inline int xen_pci_frontend_enable_msix(struct pci_dev *dev, { if (xen_pci_frontend && xen_pci_frontend->enable_msix) return xen_pci_frontend->enable_msix(dev, vectors, nvec); - return -ENODEV; + return -ENOSYS; } static inline void xen_pci_frontend_disable_msix(struct pci_dev *dev) { diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index d1daead5fcdd..adb3eaf8fe2a 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -16,6 +16,7 @@ #include <asm/cacheflush.h> #include <asm/realmode.h> +#include <linux/ftrace.h> #include "../../realmode/rm/wakeup.h" #include "sleep.h" @@ -107,7 +108,13 @@ int x86_acpi_suspend_lowlevel(void) saved_magic = 0x123456789abcdef0L; #endif /* CONFIG_64BIT */ + /* + * Pause/unpause graph tracing around do_suspend_lowlevel as it has + * inconsistent call/return info after it jumps to the wakeup vector. + */ + pause_graph_tracing(); do_suspend_lowlevel(); + unpause_graph_tracing(); return 0; } diff --git a/arch/x86/kernel/cpu/perf_event_amd_uncore.c b/arch/x86/kernel/cpu/perf_event_amd_uncore.c index 49742746a6c9..8836fc9fa84b 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_amd_uncore.c @@ -323,6 +323,8 @@ static int amd_uncore_cpu_up_prepare(unsigned int cpu) return 0; fail: + if (amd_uncore_nb) + *per_cpu_ptr(amd_uncore_nb, cpu) = NULL; kfree(uncore_nb); return -ENOMEM; } diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 1505587d06e9..b9b09fec173b 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -650,10 +650,10 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt, u16 sel; la = seg_base(ctxt, addr.seg) + addr.ea; - *linear = la; *max_size = 0; switch (mode) { case X86EMUL_MODE_PROT64: + *linear = la; if (is_noncanonical_address(la)) goto bad; @@ -662,6 +662,7 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt, goto bad; break; default: + *linear = la = (u32)la; usable = ctxt->ops->get_segment(ctxt, &sel, &desc, NULL, addr.seg); if (!usable) @@ -689,7 +690,6 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt, if (size > *max_size) goto bad; } - la &= (u32)-1; break; } if (insn_aligned(ctxt, size) && ((la & (size - 1)) != 0)) diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 6c9fed957cce..2ce4f05e81d3 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -249,7 +249,7 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu, return ret; kvm_vcpu_mark_page_dirty(vcpu, table_gfn); - walker->ptes[level] = pte; + walker->ptes[level - 1] = pte; } return 0; } diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index e2951b6edbbc..0ff453749a90 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -596,6 +596,8 @@ struct vcpu_vmx { /* Support for PML */ #define PML_ENTITY_NUM 512 struct page *pml_pg; + + u64 current_tsc_ratio; }; enum segment_cache_field { @@ -2127,14 +2129,16 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp); vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */ - /* Setup TSC multiplier */ - if (cpu_has_vmx_tsc_scaling()) - vmcs_write64(TSC_MULTIPLIER, - vcpu->arch.tsc_scaling_ratio); - vmx->loaded_vmcs->cpu = cpu; } + /* Setup TSC multiplier */ + if (kvm_has_tsc_control && + vmx->current_tsc_ratio != vcpu->arch.tsc_scaling_ratio) { + vmx->current_tsc_ratio = vcpu->arch.tsc_scaling_ratio; + vmcs_write64(TSC_MULTIPLIER, vmx->current_tsc_ratio); + } + vmx_vcpu_pi_load(vcpu, cpu); } diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 4244c2baf57d..eaf6ee8c28b8 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6618,12 +6618,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) * KVM_DEBUGREG_WONT_EXIT again. */ if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) { - int i; - WARN_ON(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP); kvm_x86_ops->sync_dirty_debug_regs(vcpu); - for (i = 0; i < KVM_NR_DB_REGS; i++) - vcpu->arch.eff_db[i] = vcpu->arch.db[i]; + kvm_update_dr0123(vcpu); + kvm_update_dr6(vcpu); + kvm_update_dr7(vcpu); + vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_RELOAD; } /* diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c index 6d5eb5900372..d8a798d8bf50 100644 --- a/arch/x86/mm/gup.c +++ b/arch/x86/mm/gup.c @@ -102,7 +102,6 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr, return 0; } - page = pte_page(pte); if (pte_devmap(pte)) { pgmap = get_dev_pagemap(pte_pfn(pte), pgmap); if (unlikely(!pgmap)) { @@ -115,6 +114,7 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr, return 0; } VM_BUG_ON(!pfn_valid(pte_pfn(pte))); + page = pte_page(pte); get_page(page); put_dev_pagemap(pgmap); SetPageReferenced(page); diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c index 96bd1e2bffaf..72bb52f93c3d 100644 --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c @@ -71,12 +71,12 @@ unsigned long arch_mmap_rnd(void) if (mmap_is_ia32()) #ifdef CONFIG_COMPAT - rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_compat_bits) - 1); + rnd = get_random_long() & ((1UL << mmap_rnd_compat_bits) - 1); #else - rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_bits) - 1); + rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1); #endif else - rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_bits) - 1); + rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1); return rnd << PAGE_SHIFT; } diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c index b2fd67da1701..ef05755a1900 100644 --- a/arch/x86/mm/mpx.c +++ b/arch/x86/mm/mpx.c @@ -123,7 +123,7 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs, break; } - if (regno > nr_registers) { + if (regno >= nr_registers) { WARN_ONCE(1, "decoded an instruction with an invalid register"); return -EINVAL; } diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 2440814b0069..9cf96d82147a 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -419,24 +419,30 @@ pmd_t *lookup_pmd_address(unsigned long address) phys_addr_t slow_virt_to_phys(void *__virt_addr) { unsigned long virt_addr = (unsigned long)__virt_addr; - unsigned long phys_addr, offset; + phys_addr_t phys_addr; + unsigned long offset; enum pg_level level; pte_t *pte; pte = lookup_address(virt_addr, &level); BUG_ON(!pte); + /* + * pXX_pfn() returns unsigned long, which must be cast to phys_addr_t + * before being left-shifted PAGE_SHIFT bits -- this trick is to + * make 32-PAE kernel work correctly. + */ switch (level) { case PG_LEVEL_1G: - phys_addr = pud_pfn(*(pud_t *)pte) << PAGE_SHIFT; + phys_addr = (phys_addr_t)pud_pfn(*(pud_t *)pte) << PAGE_SHIFT; offset = virt_addr & ~PUD_PAGE_MASK; break; case PG_LEVEL_2M: - phys_addr = pmd_pfn(*(pmd_t *)pte) << PAGE_SHIFT; + phys_addr = (phys_addr_t)pmd_pfn(*(pmd_t *)pte) << PAGE_SHIFT; offset = virt_addr & ~PMD_PAGE_MASK; break; default: - phys_addr = pte_pfn(*pte) << PAGE_SHIFT; + phys_addr = (phys_addr_t)pte_pfn(*pte) << PAGE_SHIFT; offset = virt_addr & ~PAGE_MASK; } diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 2879efc73a96..d34b5118b4e8 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -711,28 +711,22 @@ int pcibios_add_device(struct pci_dev *dev) return 0; } -int pcibios_alloc_irq(struct pci_dev *dev) +int pcibios_enable_device(struct pci_dev *dev, int mask) { - /* - * If the PCI device was already claimed by core code and has - * MSI enabled, probing of the pcibios IRQ will overwrite - * dev->irq. So bail out if MSI is already enabled. - */ - if (pci_dev_msi_enabled(dev)) - return -EBUSY; + int err; - return pcibios_enable_irq(dev); -} + if ((err = pci_enable_resources(dev, mask)) < 0) + return err; -void pcibios_free_irq(struct pci_dev *dev) -{ - if (pcibios_disable_irq) - pcibios_disable_irq(dev); + if (!pci_dev_msi_enabled(dev)) + return pcibios_enable_irq(dev); + return 0; } -int pcibios_enable_device(struct pci_dev *dev, int mask) +void pcibios_disable_device (struct pci_dev *dev) { - return pci_enable_resources(dev, mask); + if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq) + pcibios_disable_irq(dev); } int pci_ext_cfg_avail(void) diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c index 0d24e7c10145..8b93e634af84 100644 --- a/arch/x86/pci/intel_mid_pci.c +++ b/arch/x86/pci/intel_mid_pci.c @@ -215,7 +215,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev) int polarity; int ret; - if (pci_has_managed_irq(dev)) + if (dev->irq_managed && dev->irq > 0) return 0; switch (intel_mid_identify_cpu()) { @@ -256,13 +256,10 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev) static void intel_mid_pci_irq_disable(struct pci_dev *dev) { - if (pci_has_managed_irq(dev)) { + if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed && + dev->irq > 0) { mp_unmap_irq(dev->irq); dev->irq_managed = 0; - /* - * Don't reset dev->irq here, otherwise - * intel_mid_pci_irq_enable() will fail on next call. - */ } } diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index 32e70343e6fd..9bd115484745 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c @@ -1202,7 +1202,7 @@ static int pirq_enable_irq(struct pci_dev *dev) struct pci_dev *temp_dev; int irq; - if (pci_has_managed_irq(dev)) + if (dev->irq_managed && dev->irq > 0) return 0; irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, @@ -1230,7 +1230,8 @@ static int pirq_enable_irq(struct pci_dev *dev) } dev = temp_dev; if (irq >= 0) { - pci_set_managed_irq(dev, irq); + dev->irq_managed = 1; + dev->irq = irq; dev_info(&dev->dev, "PCI->APIC IRQ transform: " "INT %c -> IRQ %d\n", 'A' + pin - 1, irq); return 0; @@ -1256,10 +1257,24 @@ static int pirq_enable_irq(struct pci_dev *dev) return 0; } +bool mp_should_keep_irq(struct device *dev) +{ + if (dev->power.is_prepared) + return true; +#ifdef CONFIG_PM + if (dev->power.runtime_status == RPM_SUSPENDING) + return true; +#endif + + return false; +} + static void pirq_disable_irq(struct pci_dev *dev) { - if (io_apic_assign_pci_irqs && pci_has_managed_irq(dev)) { + if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) && + dev->irq_managed && dev->irq) { mp_unmap_irq(dev->irq); - pci_reset_managed_irq(dev); + dev->irq = 0; + dev->irq_managed = 0; } } diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index ff31ab464213..beac4dfdade6 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -196,7 +196,10 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) return 0; error: - dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n"); + if (ret == -ENOSYS) + dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n"); + else if (ret) + dev_err(&dev->dev, "Xen PCI frontend error: %d!\n", ret); free: kfree(v); return ret; diff --git a/arch/x86/platform/intel-quark/imr.c b/arch/x86/platform/intel-quark/imr.c index c61b6c332e97..bfadcd0f4944 100644 --- a/arch/x86/platform/intel-quark/imr.c +++ b/arch/x86/platform/intel-quark/imr.c @@ -592,14 +592,14 @@ static void __init imr_fixup_memmap(struct imr_device *idev) end = (unsigned long)__end_rodata - 1; /* - * Setup a locked IMR around the physical extent of the kernel + * Setup an unlocked IMR around the physical extent of the kernel * from the beginning of the .text secton to the end of the * .rodata section as one physically contiguous block. * * We don't round up @size since it is already PAGE_SIZE aligned. * See vmlinux.lds.S for details. */ - ret = imr_add_range(base, size, IMR_CPU, IMR_CPU, true); + ret = imr_add_range(base, size, IMR_CPU, IMR_CPU, false); if (ret < 0) { pr_err("unable to setup IMR for kernel: %zu KiB (%lx - %lx)\n", size / 1024, start, end); diff --git a/arch/x86/um/os-Linux/task_size.c b/arch/x86/um/os-Linux/task_size.c index 8502ad30e61b..5adb6a2fd117 100644 --- a/arch/x86/um/os-Linux/task_size.c +++ b/arch/x86/um/os-Linux/task_size.c @@ -109,7 +109,7 @@ unsigned long os_get_top_address(void) exit(1); } - printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT); + printf("0x%lx\n", bottom << UM_KERN_PAGE_SHIFT); printf("Locating the top of the address space ... "); fflush(stdout); @@ -134,7 +134,7 @@ out: exit(1); } top <<= UM_KERN_PAGE_SHIFT; - printf("0x%x\n", top); + printf("0x%lx\n", top); return top; } diff --git a/block/Kconfig b/block/Kconfig index 161491d0a879..0363cd731320 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -88,6 +88,19 @@ config BLK_DEV_INTEGRITY T10/SCSI Data Integrity Field or the T13/ATA External Path Protection. If in doubt, say N. +config BLK_DEV_DAX + bool "Block device DAX support" + depends on FS_DAX + depends on BROKEN + help + When DAX support is available (CONFIG_FS_DAX) raw block + devices can also support direct userspace access to the + storage capacity via MMAP(2) similar to a file on a + DAX-enabled filesystem. However, the DAX I/O-path disables + some standard I/O-statistics, and the MMAP(2) path has some + operational differences due to bypassing the page + cache. If in doubt, say N. + config BLK_DEV_THROTTLING bool "Block layer bio throttling support" depends on BLK_CGROUP=y diff --git a/block/bio.c b/block/bio.c index dbabd48b1934..cf7591551b17 100644 --- a/block/bio.c +++ b/block/bio.c @@ -874,7 +874,7 @@ int submit_bio_wait(int rw, struct bio *bio) bio->bi_private = &ret; bio->bi_end_io = submit_bio_wait_endio; submit_bio(rw, bio); - wait_for_completion(&ret.event); + wait_for_completion_io(&ret.event); return ret.error; } @@ -1090,9 +1090,12 @@ int bio_uncopy_user(struct bio *bio) if (!bio_flagged(bio, BIO_NULL_MAPPED)) { /* * if we're in a workqueue, the request is orphaned, so - * don't copy into a random user address space, just free. + * don't copy into a random user address space, just free + * and return -EINTR so user space doesn't expect any data. */ - if (current->mm && bio_data_dir(bio) == READ) + if (!current->mm) + ret = -EINTR; + else if (bio_data_dir(bio) == READ) ret = bio_copy_to_iter(bio, bmd->iter); if (bmd->is_our_pages) bio_free_pages(bio); diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 5a37188b559f..66e6f1aae02e 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -788,6 +788,7 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, { struct gendisk *disk; struct blkcg_gq *blkg; + struct module *owner; unsigned int major, minor; int key_len, part, ret; char *body; @@ -804,7 +805,9 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, if (!disk) return -ENODEV; if (part) { + owner = disk->fops->owner; put_disk(disk); + module_put(owner); return -ENODEV; } @@ -820,7 +823,9 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, ret = PTR_ERR(blkg); rcu_read_unlock(); spin_unlock_irq(disk->queue->queue_lock); + owner = disk->fops->owner; put_disk(disk); + module_put(owner); /* * If queue was bypassing, we should retry. Do so after a * short msleep(). It isn't strictly necessary but queue @@ -851,9 +856,13 @@ EXPORT_SYMBOL_GPL(blkg_conf_prep); void blkg_conf_finish(struct blkg_conf_ctx *ctx) __releases(ctx->disk->queue->queue_lock) __releases(rcu) { + struct module *owner; + spin_unlock_irq(ctx->disk->queue->queue_lock); rcu_read_unlock(); + owner = ctx->disk->fops->owner; put_disk(ctx->disk); + module_put(owner); } EXPORT_SYMBOL_GPL(blkg_conf_finish); diff --git a/block/blk-map.c b/block/blk-map.c index f565e11f465a..a54f0543b956 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -57,6 +57,49 @@ static int __blk_rq_unmap_user(struct bio *bio) return ret; } +static int __blk_rq_map_user_iov(struct request *rq, + struct rq_map_data *map_data, struct iov_iter *iter, + gfp_t gfp_mask, bool copy) +{ + struct request_queue *q = rq->q; + struct bio *bio, *orig_bio; + int ret; + + if (copy) + bio = bio_copy_user_iov(q, map_data, iter, gfp_mask); + else + bio = bio_map_user_iov(q, iter, gfp_mask); + + if (IS_ERR(bio)) + return PTR_ERR(bio); + + if (map_data && map_data->null_mapped) + bio_set_flag(bio, BIO_NULL_MAPPED); + + iov_iter_advance(iter, bio->bi_iter.bi_size); + if (map_data) + map_data->offset += bio->bi_iter.bi_size; + + orig_bio = bio; + blk_queue_bounce(q, &bio); + + /* + * We link the bounce buffer in and could have to traverse it + * later so we have to get a ref to prevent it from being freed + */ + bio_get(bio); + + ret = blk_rq_append_bio(q, rq, bio); + if (ret) { + bio_endio(bio); + __blk_rq_unmap_user(orig_bio); + bio_put(bio); + return ret; + } + + return 0; +} + /** * blk_rq_map_user_iov - map user data to a request, for REQ_TYPE_BLOCK_PC usage * @q: request queue where request should be inserted @@ -82,10 +125,11 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, struct rq_map_data *map_data, const struct iov_iter *iter, gfp_t gfp_mask) { - struct bio *bio; - int unaligned = 0; - struct iov_iter i; struct iovec iov, prv = {.iov_base = NULL, .iov_len = 0}; + bool copy = (q->dma_pad_mask & iter->count) || map_data; + struct bio *bio = NULL; + struct iov_iter i; + int ret; if (!iter || !iter->count) return -EINVAL; @@ -101,42 +145,29 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, */ if ((uaddr & queue_dma_alignment(q)) || iovec_gap_to_prv(q, &prv, &iov)) - unaligned = 1; + copy = true; prv.iov_base = iov.iov_base; prv.iov_len = iov.iov_len; } - if (unaligned || (q->dma_pad_mask & iter->count) || map_data) - bio = bio_copy_user_iov(q, map_data, iter, gfp_mask); - else - bio = bio_map_user_iov(q, iter, gfp_mask); - - if (IS_ERR(bio)) - return PTR_ERR(bio); - - if (map_data && map_data->null_mapped) - bio_set_flag(bio, BIO_NULL_MAPPED); - - if (bio->bi_iter.bi_size != iter->count) { - /* - * Grab an extra reference to this bio, as bio_unmap_user() - * expects to be able to drop it twice as it happens on the - * normal IO completion path - */ - bio_get(bio); - bio_endio(bio); - __blk_rq_unmap_user(bio); - return -EINVAL; - } + i = *iter; + do { + ret =__blk_rq_map_user_iov(rq, map_data, &i, gfp_mask, copy); + if (ret) + goto unmap_rq; + if (!bio) + bio = rq->bio; + } while (iov_iter_count(&i)); if (!bio_flagged(bio, BIO_USER_MAPPED)) rq->cmd_flags |= REQ_COPY_USER; - - blk_queue_bounce(q, &bio); - bio_get(bio); - blk_rq_bio_prep(q, rq, bio); return 0; + +unmap_rq: + __blk_rq_unmap_user(bio); + rq->bio = NULL; + return -EINVAL; } EXPORT_SYMBOL(blk_rq_map_user_iov); diff --git a/block/blk-merge.c b/block/blk-merge.c index 888a7fec81f7..261353166dcf 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -304,7 +304,6 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio, struct bio *nxt) { struct bio_vec end_bv = { NULL }, nxt_bv; - struct bvec_iter iter; if (!blk_queue_cluster(q)) return 0; @@ -316,11 +315,8 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio, if (!bio_has_data(bio)) return 1; - bio_for_each_segment(end_bv, bio, iter) - if (end_bv.bv_len == iter.bi_size) - break; - - nxt_bv = bio_iovec(nxt); + bio_get_last_bvec(bio, &end_bv); + bio_get_first_bvec(nxt, &nxt_bv); if (!BIOVEC_PHYS_MERGEABLE(&end_bv, &nxt_bv)) return 0; diff --git a/block/blk-mq.c b/block/blk-mq.c index 4c0622fae413..56c0a726b619 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -599,8 +599,10 @@ static void blk_mq_check_expired(struct blk_mq_hw_ctx *hctx, * If a request wasn't started before the queue was * marked dying, kill it here or it'll go unnoticed. */ - if (unlikely(blk_queue_dying(rq->q))) - blk_mq_complete_request(rq, -EIO); + if (unlikely(blk_queue_dying(rq->q))) { + rq->errors = -EIO; + blk_mq_end_request(rq, rq->errors); + } return; } diff --git a/block/blk-settings.c b/block/blk-settings.c index dd4973583978..c7bb666aafd1 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -91,8 +91,8 @@ void blk_set_default_limits(struct queue_limits *lim) lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK; lim->virt_boundary_mask = 0; lim->max_segment_size = BLK_MAX_SEGMENT_SIZE; - lim->max_sectors = lim->max_dev_sectors = lim->max_hw_sectors = - BLK_SAFE_MAX_SECTORS; + lim->max_sectors = lim->max_hw_sectors = BLK_SAFE_MAX_SECTORS; + lim->max_dev_sectors = 0; lim->chunk_sectors = 0; lim->max_write_same_sectors = 0; lim->max_discard_sectors = 0; diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index e140cc487ce1..dd93763057ce 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -147,10 +147,9 @@ static ssize_t queue_discard_granularity_show(struct request_queue *q, char *pag static ssize_t queue_discard_max_hw_show(struct request_queue *q, char *page) { - unsigned long long val; - val = q->limits.max_hw_discard_sectors << 9; - return sprintf(page, "%llu\n", val); + return sprintf(page, "%llu\n", + (unsigned long long)q->limits.max_hw_discard_sectors << 9); } static ssize_t queue_discard_max_show(struct request_queue *q, char *page) diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index a753df2b3fc2..d0dd7882d8c7 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c @@ -39,7 +39,6 @@ struct deadline_data { */ struct request *next_rq[2]; unsigned int batching; /* number of sequential requests made */ - sector_t last_sector; /* head position */ unsigned int starved; /* times reads have starved writes */ /* @@ -210,8 +209,6 @@ deadline_move_request(struct deadline_data *dd, struct request *rq) dd->next_rq[WRITE] = NULL; dd->next_rq[data_dir] = deadline_latter_request(rq); - dd->last_sector = rq_end_sector(rq); - /* * take it off the sort and fifo list, move * to dispatch queue diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c index ad6d8c6b777e..35947ac87644 100644 --- a/drivers/acpi/nfit.c +++ b/drivers/acpi/nfit.c @@ -469,37 +469,16 @@ static void nfit_mem_find_spa_bdw(struct acpi_nfit_desc *acpi_desc, nfit_mem->bdw = NULL; } -static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc, +static void nfit_mem_init_bdw(struct acpi_nfit_desc *acpi_desc, struct nfit_mem *nfit_mem, struct acpi_nfit_system_address *spa) { u16 dcr = __to_nfit_memdev(nfit_mem)->region_index; struct nfit_memdev *nfit_memdev; struct nfit_flush *nfit_flush; - struct nfit_dcr *nfit_dcr; struct nfit_bdw *nfit_bdw; struct nfit_idt *nfit_idt; u16 idt_idx, range_index; - list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) { - if (nfit_dcr->dcr->region_index != dcr) - continue; - nfit_mem->dcr = nfit_dcr->dcr; - break; - } - - if (!nfit_mem->dcr) { - dev_dbg(acpi_desc->dev, "SPA %d missing:%s%s\n", - spa->range_index, __to_nfit_memdev(nfit_mem) - ? "" : " MEMDEV", nfit_mem->dcr ? "" : " DCR"); - return -ENODEV; - } - - /* - * We've found enough to create an nvdimm, optionally - * find an associated BDW - */ - list_add(&nfit_mem->list, &acpi_desc->dimms); - list_for_each_entry(nfit_bdw, &acpi_desc->bdws, list) { if (nfit_bdw->bdw->region_index != dcr) continue; @@ -508,12 +487,12 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc, } if (!nfit_mem->bdw) - return 0; + return; nfit_mem_find_spa_bdw(acpi_desc, nfit_mem); if (!nfit_mem->spa_bdw) - return 0; + return; range_index = nfit_mem->spa_bdw->range_index; list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) { @@ -538,8 +517,6 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc, } break; } - - return 0; } static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, @@ -548,7 +525,6 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, struct nfit_mem *nfit_mem, *found; struct nfit_memdev *nfit_memdev; int type = nfit_spa_type(spa); - u16 dcr; switch (type) { case NFIT_SPA_DCR: @@ -559,14 +535,18 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, } list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) { - int rc; + struct nfit_dcr *nfit_dcr; + u32 device_handle; + u16 dcr; if (nfit_memdev->memdev->range_index != spa->range_index) continue; found = NULL; dcr = nfit_memdev->memdev->region_index; + device_handle = nfit_memdev->memdev->device_handle; list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) - if (__to_nfit_memdev(nfit_mem)->region_index == dcr) { + if (__to_nfit_memdev(nfit_mem)->device_handle + == device_handle) { found = nfit_mem; break; } @@ -579,6 +559,31 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, if (!nfit_mem) return -ENOMEM; INIT_LIST_HEAD(&nfit_mem->list); + list_add(&nfit_mem->list, &acpi_desc->dimms); + } + + list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) { + if (nfit_dcr->dcr->region_index != dcr) + continue; + /* + * Record the control region for the dimm. For + * the ACPI 6.1 case, where there are separate + * control regions for the pmem vs blk + * interfaces, be sure to record the extended + * blk details. + */ + if (!nfit_mem->dcr) + nfit_mem->dcr = nfit_dcr->dcr; + else if (nfit_mem->dcr->windows == 0 + && nfit_dcr->dcr->windows) + nfit_mem->dcr = nfit_dcr->dcr; + break; + } + + if (dcr && !nfit_mem->dcr) { + dev_err(acpi_desc->dev, "SPA %d missing DCR %d\n", + spa->range_index, dcr); + return -ENODEV; } if (type == NFIT_SPA_DCR) { @@ -595,6 +600,7 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, nfit_mem->idt_dcr = nfit_idt->idt; break; } + nfit_mem_init_bdw(acpi_desc, nfit_mem, spa); } else { /* * A single dimm may belong to multiple SPA-PM @@ -603,13 +609,6 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, */ nfit_mem->memdev_pmem = nfit_memdev->memdev; } - - if (found) - continue; - - rc = nfit_mem_add(acpi_desc, nfit_mem, spa); - if (rc) - return rc; } return 0; @@ -1504,9 +1503,7 @@ static int ars_do_start(struct nvdimm_bus_descriptor *nd_desc, case 1: /* ARS unsupported, but we should never get here */ return 0; - case 2: - return -EINVAL; - case 3: + case 6: /* ARS is in progress */ msleep(1000); break; @@ -1517,13 +1514,13 @@ static int ars_do_start(struct nvdimm_bus_descriptor *nd_desc, } static int ars_get_status(struct nvdimm_bus_descriptor *nd_desc, - struct nd_cmd_ars_status *cmd) + struct nd_cmd_ars_status *cmd, u32 size) { int rc; while (1) { rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_ARS_STATUS, cmd, - sizeof(*cmd)); + size); if (rc || cmd->status & 0xffff) return -ENXIO; @@ -1538,6 +1535,8 @@ static int ars_get_status(struct nvdimm_bus_descriptor *nd_desc, case 2: /* No ARS performed for the current boot */ return 0; + case 3: + /* TODO: error list overflow support */ default: return -ENXIO; } @@ -1581,6 +1580,7 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc, struct nd_cmd_ars_start *ars_start = NULL; struct nd_cmd_ars_cap *ars_cap = NULL; u64 start, len, cur, remaining; + u32 ars_status_size; int rc; ars_cap = kzalloc(sizeof(*ars_cap), GFP_KERNEL); @@ -1590,14 +1590,21 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc, start = ndr_desc->res->start; len = ndr_desc->res->end - ndr_desc->res->start + 1; + /* + * If ARS is unimplemented, unsupported, or if the 'Persistent Memory + * Scrub' flag in extended status is not set, skip this but continue + * initialization + */ rc = ars_get_cap(nd_desc, ars_cap, start, len); + if (rc == -ENOTTY) { + dev_dbg(acpi_desc->dev, + "Address Range Scrub is not implemented, won't create an error list\n"); + rc = 0; + goto out; + } if (rc) goto out; - /* - * If ARS is unsupported, or if the 'Persistent Memory Scrub' flag in - * extended status is not set, skip this but continue initialization - */ if ((ars_cap->status & 0xffff) || !(ars_cap->status >> 16 & ND_ARS_PERSISTENT)) { dev_warn(acpi_desc->dev, @@ -1610,14 +1617,14 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc, * Check if a full-range ARS has been run. If so, use those results * without having to start a new ARS. */ - ars_status = kzalloc(ars_cap->max_ars_out + sizeof(*ars_status), - GFP_KERNEL); + ars_status_size = ars_cap->max_ars_out; + ars_status = kzalloc(ars_status_size, GFP_KERNEL); if (!ars_status) { rc = -ENOMEM; goto out; } - rc = ars_get_status(nd_desc, ars_status); + rc = ars_get_status(nd_desc, ars_status, ars_status_size); if (rc) goto out; @@ -1647,7 +1654,7 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc, if (rc) goto out; - rc = ars_get_status(nd_desc, ars_status); + rc = ars_get_status(nd_desc, ars_status, ars_status_size); if (rc) goto out; diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index d30184c7f3bc..c8e169e46673 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -406,7 +406,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) return 0; } - if (pci_has_managed_irq(dev)) + if (dev->irq_managed && dev->irq > 0) return 0; entry = acpi_pci_irq_lookup(dev, pin); @@ -451,7 +451,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev) kfree(entry); return rc; } - pci_set_managed_irq(dev, rc); + dev->irq = rc; + dev->irq_managed = 1; if (link) snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link); @@ -474,9 +475,17 @@ void acpi_pci_irq_disable(struct pci_dev *dev) u8 pin; pin = dev->pin; - if (!pin || !pci_has_managed_irq(dev)) + if (!pin || !dev->irq_managed || dev->irq <= 0) return; + /* Keep IOAPIC pin configuration when suspending */ + if (dev->dev.power.is_prepared) + return; +#ifdef CONFIG_PM + if (dev->dev.power.runtime_status == RPM_SUSPENDING) + return; +#endif + entry = acpi_pci_irq_lookup(dev, pin); if (!entry) return; @@ -496,6 +505,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev) dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin)); if (gsi >= 0) { acpi_unregister_gsi(gsi); - pci_reset_managed_irq(dev); + dev->irq_managed = 0; } } diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index fa2863567eed..ededa909df2f 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -4,7 +4,6 @@ * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2002 Dominik Brodowski <devel@brodo.de> - * Copyright (c) 2015, The Linux Foundation. All rights reserved. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -438,6 +437,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) * enabled system. */ +#define ACPI_MAX_IRQS 256 #define ACPI_MAX_ISA_IRQ 16 #define PIRQ_PENALTY_PCI_AVAILABLE (0) @@ -447,7 +447,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) #define PIRQ_PENALTY_ISA_USED (16*16*16*16*16) #define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16) -static int acpi_irq_isa_penalty[ACPI_MAX_ISA_IRQ] = { +static int acpi_irq_penalty[ACPI_MAX_IRQS] = { PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */ PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */ PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */ @@ -464,68 +464,9 @@ static int acpi_irq_isa_penalty[ACPI_MAX_ISA_IRQ] = { PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */ + /* >IRQ15 */ }; -struct irq_penalty_info { - int irq; - int penalty; - struct list_head node; -}; - -static LIST_HEAD(acpi_irq_penalty_list); - -static int acpi_irq_get_penalty(int irq) -{ - struct irq_penalty_info *irq_info; - - if (irq < ACPI_MAX_ISA_IRQ) - return acpi_irq_isa_penalty[irq]; - - list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) { - if (irq_info->irq == irq) - return irq_info->penalty; - } - - return 0; -} - -static int acpi_irq_set_penalty(int irq, int new_penalty) -{ - struct irq_penalty_info *irq_info; - - /* see if this is a ISA IRQ */ - if (irq < ACPI_MAX_ISA_IRQ) { - acpi_irq_isa_penalty[irq] = new_penalty; - return 0; - } - - /* next, try to locate from the dynamic list */ - list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) { - if (irq_info->irq == irq) { - irq_info->penalty = new_penalty; - return 0; - } - } - - /* nope, let's allocate a slot for this IRQ */ - irq_info = kzalloc(sizeof(*irq_info), GFP_KERNEL); - if (!irq_info) - return -ENOMEM; - - irq_info->irq = irq; - irq_info->penalty = new_penalty; - list_add_tail(&irq_info->node, &acpi_irq_penalty_list); - - return 0; -} - -static void acpi_irq_add_penalty(int irq, int penalty) -{ - int curpen = acpi_irq_get_penalty(irq); - - acpi_irq_set_penalty(irq, curpen + penalty); -} - int __init acpi_irq_penalty_init(void) { struct acpi_pci_link *link; @@ -546,16 +487,15 @@ int __init acpi_irq_penalty_init(void) link->irq.possible_count; for (i = 0; i < link->irq.possible_count; i++) { - if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) { - int irqpos = link->irq.possible[i]; - - acpi_irq_add_penalty(irqpos, penalty); - } + if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) + acpi_irq_penalty[link->irq. + possible[i]] += + penalty; } } else if (link->irq.active) { - acpi_irq_add_penalty(link->irq.active, - PIRQ_PENALTY_PCI_POSSIBLE); + acpi_irq_penalty[link->irq.active] += + PIRQ_PENALTY_PCI_POSSIBLE; } } @@ -607,12 +547,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) * the use of IRQs 9, 10, 11, and >15. */ for (i = (link->irq.possible_count - 1); i >= 0; i--) { - if (acpi_irq_get_penalty(irq) > - acpi_irq_get_penalty(link->irq.possible[i])) + if (acpi_irq_penalty[irq] > + acpi_irq_penalty[link->irq.possible[i]]) irq = link->irq.possible[i]; } } - if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) { + if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) { printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. " "Try pci=noacpi or acpi=off\n", acpi_device_name(link->device), @@ -628,8 +568,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) acpi_device_bid(link->device)); return -ENODEV; } else { - acpi_irq_add_penalty(link->irq.active, PIRQ_PENALTY_PCI_USING); - + acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING; printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n", acpi_device_name(link->device), acpi_device_bid(link->device), link->irq.active); @@ -839,7 +778,7 @@ static void acpi_pci_link_remove(struct acpi_device *device) } /* - * modify penalty from cmdline + * modify acpi_irq_penalty[] from cmdline */ static int __init acpi_irq_penalty_update(char *str, int used) { @@ -857,10 +796,13 @@ static int __init acpi_irq_penalty_update(char *str, int used) if (irq < 0) continue; + if (irq >= ARRAY_SIZE(acpi_irq_penalty)) + continue; + if (used) - acpi_irq_add_penalty(irq, PIRQ_PENALTY_ISA_USED); + acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; else - acpi_irq_set_penalty(irq, PIRQ_PENALTY_PCI_AVAILABLE); + acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE; if (retval != 2) /* no next number */ break; @@ -877,15 +819,18 @@ static int __init acpi_irq_penalty_update(char *str, int used) */ void acpi_penalize_isa_irq(int irq, int active) { - if (irq >= 0) - acpi_irq_add_penalty(irq, active ? - PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING); + if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) { + if (active) + acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; + else + acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; + } } bool acpi_isa_irq_available(int irq) { - return irq >= 0 && - (acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS); + return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) || + acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS); } /* @@ -895,18 +840,13 @@ bool acpi_isa_irq_available(int irq) */ void acpi_penalize_sci_irq(int irq, int trigger, int polarity) { - int penalty; - - if (irq < 0) - return; - - if (trigger != ACPI_MADT_TRIGGER_LEVEL || - polarity != ACPI_MADT_POLARITY_ACTIVE_LOW) - penalty = PIRQ_PENALTY_ISA_ALWAYS; - else - penalty = PIRQ_PENALTY_PCI_USING; - - acpi_irq_add_penalty(irq, penalty); + if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) { + if (trigger != ACPI_MADT_TRIGGER_LEVEL || + polarity != ACPI_MADT_POLARITY_ACTIVE_LOW) + acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_ALWAYS; + else + acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; + } } /* diff --git a/drivers/android/binder.c b/drivers/android/binder.c index a39e85f9efa9..7d00b7a015ea 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2074,7 +2074,7 @@ static int binder_thread_write(struct binder_proc *proc, if (get_user(cookie, (binder_uintptr_t __user *)ptr)) return -EFAULT; - ptr += sizeof(void *); + ptr += sizeof(cookie); list_for_each_entry(w, &proc->delivered_death, entry) { struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work); diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 546a3692774f..146dc0b8ec61 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -367,15 +367,21 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */ { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */ { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/ { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/ { PCI_VDEVICE(INTEL, 0xa184), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa18e), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/ { PCI_VDEVICE(INTEL, 0xa204), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa20e), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, @@ -1325,6 +1331,44 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host) {} #endif +#ifdef CONFIG_ARM64 +/* + * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently. + * Workaround is to make sure all pending IRQs are served before leaving + * handler. + */ +static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) +{ + struct ata_host *host = dev_instance; + struct ahci_host_priv *hpriv; + unsigned int rc = 0; + void __iomem *mmio; + u32 irq_stat, irq_masked; + unsigned int handled = 1; + + VPRINTK("ENTER\n"); + hpriv = host->private_data; + mmio = hpriv->mmio; + irq_stat = readl(mmio + HOST_IRQ_STAT); + if (!irq_stat) + return IRQ_NONE; + + do { + irq_masked = irq_stat & hpriv->port_map; + spin_lock(&host->lock); + rc = ahci_handle_port_intr(host, irq_masked); + if (!rc) + handled = 0; + writel(irq_stat, mmio + HOST_IRQ_STAT); + irq_stat = readl(mmio + HOST_IRQ_STAT); + spin_unlock(&host->lock); + } while (irq_stat); + VPRINTK("EXIT\n"); + + return IRQ_RETVAL(handled); +} +#endif + /* * ahci_init_msix() - optionally enable per-port MSI-X otherwise defer * to single msi. @@ -1560,6 +1604,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (ahci_broken_devslp(pdev)) hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; +#ifdef CONFIG_ARM64 + if (pdev->vendor == 0x177d && pdev->device == 0xa01c) + hpriv->irq_handler = ahci_thunderx_irq_handler; +#endif + /* save initial config */ ahci_pci_save_initial_config(pdev, hpriv); diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index a44c75d4c284..167ba7e3b92e 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -240,8 +240,7 @@ enum { error-handling stage) */ AHCI_HFLAG_NO_DEVSLP = (1 << 17), /* no device sleep */ AHCI_HFLAG_NO_FBS = (1 << 18), /* no FBS */ - AHCI_HFLAG_EDGE_IRQ = (1 << 19), /* HOST_IRQ_STAT behaves as - Edge Triggered */ + #ifdef CONFIG_PCI_MSI AHCI_HFLAG_MULTI_MSI = (1 << 20), /* multiple PCI MSIs */ AHCI_HFLAG_MULTI_MSIX = (1 << 21), /* per-port MSI-X */ @@ -361,6 +360,7 @@ struct ahci_host_priv { * be overridden anytime before the host is activated. */ void (*start_engine)(struct ata_port *ap); + irqreturn_t (*irq_handler)(int irq, void *dev_instance); }; #ifdef CONFIG_PCI_MSI @@ -424,6 +424,7 @@ int ahci_reset_em(struct ata_host *host); void ahci_print_info(struct ata_host *host, const char *scc_s); int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht); void ahci_error_handler(struct ata_port *ap); +u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked); static inline void __iomem *__ahci_port_base(struct ata_host *host, unsigned int port_no) diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c index e2c6d9e0c5ac..8e3f7faf00d3 100644 --- a/drivers/ata/ahci_xgene.c +++ b/drivers/ata/ahci_xgene.c @@ -548,6 +548,88 @@ softreset_retry: return rc; } +/** + * xgene_ahci_handle_broken_edge_irq - Handle the broken irq. + * @ata_host: Host that recieved the irq + * @irq_masked: HOST_IRQ_STAT value + * + * For hardware with broken edge trigger latch + * the HOST_IRQ_STAT register misses the edge interrupt + * when clearing of HOST_IRQ_STAT register and hardware + * reporting the PORT_IRQ_STAT register at the + * same clock cycle. + * As such, the algorithm below outlines the workaround. + * + * 1. Read HOST_IRQ_STAT register and save the state. + * 2. Clear the HOST_IRQ_STAT register. + * 3. Read back the HOST_IRQ_STAT register. + * 4. If HOST_IRQ_STAT register equals to zero, then + * traverse the rest of port's PORT_IRQ_STAT register + * to check if an interrupt is triggered at that point else + * go to step 6. + * 5. If PORT_IRQ_STAT register of rest ports is not equal to zero + * then update the state of HOST_IRQ_STAT saved in step 1. + * 6. Handle port interrupts. + * 7. Exit + */ +static int xgene_ahci_handle_broken_edge_irq(struct ata_host *host, + u32 irq_masked) +{ + struct ahci_host_priv *hpriv = host->private_data; + void __iomem *port_mmio; + int i; + + if (!readl(hpriv->mmio + HOST_IRQ_STAT)) { + for (i = 0; i < host->n_ports; i++) { + if (irq_masked & (1 << i)) + continue; + + port_mmio = ahci_port_base(host->ports[i]); + if (readl(port_mmio + PORT_IRQ_STAT)) + irq_masked |= (1 << i); + } + } + + return ahci_handle_port_intr(host, irq_masked); +} + +static irqreturn_t xgene_ahci_irq_intr(int irq, void *dev_instance) +{ + struct ata_host *host = dev_instance; + struct ahci_host_priv *hpriv; + unsigned int rc = 0; + void __iomem *mmio; + u32 irq_stat, irq_masked; + + VPRINTK("ENTER\n"); + + hpriv = host->private_data; + mmio = hpriv->mmio; + + /* sigh. 0xffffffff is a valid return from h/w */ + irq_stat = readl(mmio + HOST_IRQ_STAT); + if (!irq_stat) + return IRQ_NONE; + + irq_masked = irq_stat & hpriv->port_map; + + spin_lock(&host->lock); + + /* + * HOST_IRQ_STAT behaves as edge triggered latch meaning that + * it should be cleared before all the port events are cleared. + */ + writel(irq_stat, mmio + HOST_IRQ_STAT); + + rc = xgene_ahci_handle_broken_edge_irq(host, irq_masked); + + spin_unlock(&host->lock); + + VPRINTK("EXIT\n"); + + return IRQ_RETVAL(rc); +} + static struct ata_port_operations xgene_ahci_v1_ops = { .inherits = &ahci_ops, .host_stop = xgene_ahci_host_stop, @@ -779,7 +861,8 @@ skip_clk_phy: hpriv->flags = AHCI_HFLAG_NO_NCQ; break; case XGENE_AHCI_V2: - hpriv->flags |= AHCI_HFLAG_YES_FBS | AHCI_HFLAG_EDGE_IRQ; + hpriv->flags |= AHCI_HFLAG_YES_FBS; + hpriv->irq_handler = xgene_ahci_irq_intr; break; default: break; diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 402967902cbe..85ea5142a095 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -113,6 +113,7 @@ static ssize_t ahci_store_em_buffer(struct device *dev, const char *buf, size_t size); static ssize_t ahci_show_em_supported(struct device *dev, struct device_attribute *attr, char *buf); +static irqreturn_t ahci_single_level_irq_intr(int irq, void *dev_instance); static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL); static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL); @@ -512,6 +513,9 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv) if (!hpriv->start_engine) hpriv->start_engine = ahci_start_engine; + + if (!hpriv->irq_handler) + hpriv->irq_handler = ahci_single_level_irq_intr; } EXPORT_SYMBOL_GPL(ahci_save_initial_config); @@ -1164,8 +1168,7 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap, /* mark esata ports */ tmp = readl(port_mmio + PORT_CMD); - if ((tmp & PORT_CMD_HPCP) || - ((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS))) + if ((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS)) ap->pflags |= ATA_PFLAG_EXTERNAL; } @@ -1846,7 +1849,7 @@ static irqreturn_t ahci_multi_irqs_intr_hard(int irq, void *dev_instance) return IRQ_HANDLED; } -static u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked) +u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked) { unsigned int i, handled = 0; @@ -1872,43 +1875,7 @@ static u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked) return handled; } - -static irqreturn_t ahci_single_edge_irq_intr(int irq, void *dev_instance) -{ - struct ata_host *host = dev_instance; - struct ahci_host_priv *hpriv; - unsigned int rc = 0; - void __iomem *mmio; - u32 irq_stat, irq_masked; - - VPRINTK("ENTER\n"); - - hpriv = host->private_data; - mmio = hpriv->mmio; - - /* sigh. 0xffffffff is a valid return from h/w */ - irq_stat = readl(mmio + HOST_IRQ_STAT); - if (!irq_stat) - return IRQ_NONE; - - irq_masked = irq_stat & hpriv->port_map; - - spin_lock(&host->lock); - - /* - * HOST_IRQ_STAT behaves as edge triggered latch meaning that - * it should be cleared before all the port events are cleared. - */ - writel(irq_stat, mmio + HOST_IRQ_STAT); - - rc = ahci_handle_port_intr(host, irq_masked); - - spin_unlock(&host->lock); - - VPRINTK("EXIT\n"); - - return IRQ_RETVAL(rc); -} +EXPORT_SYMBOL_GPL(ahci_handle_port_intr); static irqreturn_t ahci_single_level_irq_intr(int irq, void *dev_instance) { @@ -2535,14 +2502,18 @@ int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht) int irq = hpriv->irq; int rc; - if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX)) + if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX)) { + if (hpriv->irq_handler) + dev_warn(host->dev, "both AHCI_HFLAG_MULTI_MSI flag set \ + and custom irq handler implemented\n"); + rc = ahci_host_activate_multi_irqs(host, sht); - else if (hpriv->flags & AHCI_HFLAG_EDGE_IRQ) - rc = ata_host_activate(host, irq, ahci_single_edge_irq_intr, - IRQF_SHARED, sht); - else - rc = ata_host_activate(host, irq, ahci_single_level_irq_intr, + } else { + rc = ata_host_activate(host, irq, hpriv->irq_handler, IRQF_SHARED, sht); + } + + return rc; } EXPORT_SYMBOL_GPL(ahci_host_activate); diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 7e959f90c020..e417e1a1d02c 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -675,19 +675,18 @@ static int ata_ioc32(struct ata_port *ap) int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev, int cmd, void __user *arg) { - int val = -EINVAL, rc = -EINVAL; + unsigned long val; + int rc = -EINVAL; unsigned long flags; switch (cmd) { - case ATA_IOC_GET_IO32: + case HDIO_GET_32BIT: spin_lock_irqsave(ap->lock, flags); val = ata_ioc32(ap); spin_unlock_irqrestore(ap->lock, flags); - if (copy_to_user(arg, &val, 1)) - return -EFAULT; - return 0; + return put_user(val, (unsigned long __user *)arg); - case ATA_IOC_SET_IO32: + case HDIO_SET_32BIT: val = (unsigned long) arg; rc = 0; spin_lock_irqsave(ap->lock, flags); diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index 12fe0f3bb7e9..c8b6a780a290 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -32,6 +32,8 @@ #include <linux/libata.h> #include <scsi/scsi_host.h> +#include <asm/mach-rc32434/rb.h> + #define DRV_NAME "pata-rb532-cf" #define DRV_VERSION "0.1.0" #define DRV_DESC "PATA driver for RouterBOARD 532 Compact Flash" @@ -107,6 +109,7 @@ static int rb532_pata_driver_probe(struct platform_device *pdev) int gpio; struct resource *res; struct ata_host *ah; + struct cf_device *pdata; struct rb532_cf_info *info; int ret; @@ -122,7 +125,13 @@ static int rb532_pata_driver_probe(struct platform_device *pdev) return -ENOENT; } - gpio = irq_to_gpio(irq); + pdata = dev_get_platdata(&pdev->dev); + if (!pdata) { + dev_err(&pdev->dev, "no platform data specified\n"); + return -EINVAL; + } + + gpio = pdata->gpio_pin; if (gpio < 0) { dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq); return -ENOENT; diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 9e251201dd48..84708a5f8c52 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -866,7 +866,7 @@ static void set_fdc(int drive) } /* locks the driver */ -static int lock_fdc(int drive, bool interruptible) +static int lock_fdc(int drive) { if (WARN(atomic_read(&usage_count) == 0, "Trying to lock fdc while usage count=0\n")) @@ -2173,7 +2173,7 @@ static int do_format(int drive, struct format_descr *tmp_format_req) { int ret; - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; set_floppy(drive); @@ -2960,7 +2960,7 @@ static int user_reset_fdc(int drive, int arg, bool interruptible) { int ret; - if (lock_fdc(drive, interruptible)) + if (lock_fdc(drive)) return -EINTR; if (arg == FD_RESET_ALWAYS) @@ -3243,7 +3243,7 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g, if (!capable(CAP_SYS_ADMIN)) return -EPERM; mutex_lock(&open_lock); - if (lock_fdc(drive, true)) { + if (lock_fdc(drive)) { mutex_unlock(&open_lock); return -EINTR; } @@ -3263,7 +3263,7 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g, } else { int oldStretch; - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; if (cmd != FDDEFPRM) { /* notice a disk change immediately, else @@ -3349,7 +3349,7 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g) if (type) *g = &floppy_type[type]; else { - if (lock_fdc(drive, false)) + if (lock_fdc(drive)) return -EINTR; if (poll_drive(false, 0) == -EINTR) return -EINTR; @@ -3433,7 +3433,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int if (UDRS->fd_ref != 1) /* somebody else has this drive open */ return -EBUSY; - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; /* do the actual eject. Fails on @@ -3445,7 +3445,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int process_fd_request(); return ret; case FDCLRPRM: - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; current_type[drive] = NULL; floppy_sizes[drive] = MAX_DISK_SIZE << 1; @@ -3467,7 +3467,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int UDP->flags &= ~FTD_MSG; return 0; case FDFMTBEG: - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) return -EINTR; @@ -3484,7 +3484,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int return do_format(drive, &inparam.f); case FDFMTEND: case FDFLUSH: - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; return invalidate_drive(bdev); case FDSETEMSGTRESH: @@ -3507,7 +3507,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int outparam = UDP; break; case FDPOLLDRVSTAT: - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) return -EINTR; @@ -3530,7 +3530,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int case FDRAWCMD: if (type) return -EINVAL; - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; set_floppy(drive); i = raw_cmd_ioctl(cmd, (void __user *)param); @@ -3539,7 +3539,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int process_fd_request(); return i; case FDTWADDLE: - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; twaddle(); process_fd_request(); @@ -3663,6 +3663,11 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) opened_bdev[drive] = bdev; + if (!(mode & (FMODE_READ|FMODE_WRITE))) { + res = -EINVAL; + goto out; + } + res = -ENXIO; if (!floppy_track_buffer) { @@ -3706,21 +3711,20 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) if (UFDCS->rawcmd == 1) UFDCS->rawcmd = 2; - if (!(mode & FMODE_NDELAY)) { - if (mode & (FMODE_READ|FMODE_WRITE)) { - UDRS->last_checked = 0; - clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); - check_disk_change(bdev); - if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) - goto out; - if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) - goto out; - } - res = -EROFS; - if ((mode & FMODE_WRITE) && - !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags)) - goto out; - } + UDRS->last_checked = 0; + clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); + check_disk_change(bdev); + if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) + goto out; + if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) + goto out; + + res = -EROFS; + + if ((mode & FMODE_WRITE) && + !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags)) + goto out; + mutex_unlock(&open_lock); mutex_unlock(&floppy_mutex); return 0; @@ -3748,7 +3752,8 @@ static unsigned int floppy_check_events(struct gendisk *disk, return DISK_EVENT_MEDIA_CHANGE; if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) { - lock_fdc(drive, false); + if (lock_fdc(drive)) + return -EINTR; poll_drive(false, 0); process_fd_request(); } @@ -3847,7 +3852,9 @@ static int floppy_revalidate(struct gendisk *disk) "VFS: revalidate called on non-open device.\n")) return -EFAULT; - lock_fdc(drive, false); + res = lock_fdc(drive); + if (res) + return res; cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || test_bit(FD_VERIFY_BIT, &UDRS->flags)); if (!(cf || test_bit(drive, &fake_change) || drive_no_geom(drive))) { diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index 8ba1e97d573c..64a7b5971b57 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c @@ -478,7 +478,7 @@ static int null_lnvm_id(struct nvm_dev *dev, struct nvm_id *id) id->ver_id = 0x1; id->vmnt = 0; id->cgrps = 1; - id->cap = 0x3; + id->cap = 0x2; id->dom = 0x1; id->ppaf.blk_offset = 0; @@ -707,9 +707,7 @@ static int null_add_dev(void) queue_flag_set_unlocked(QUEUE_FLAG_NONROT, nullb->q); queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, nullb->q); - mutex_lock(&lock); - list_add_tail(&nullb->list, &nullb_list); nullb->index = nullb_indexes++; mutex_unlock(&lock); @@ -743,6 +741,10 @@ static int null_add_dev(void) strncpy(disk->disk_name, nullb->disk_name, DISK_NAME_LEN); add_disk(disk); + + mutex_lock(&lock); + list_add_tail(&nullb->list, &nullb_list); + mutex_unlock(&lock); done: return 0; diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 8a8dc91c39f7..83eb9e6bf8b0 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -1873,6 +1873,43 @@ again: return err; } +static int negotiate_mq(struct blkfront_info *info) +{ + unsigned int backend_max_queues = 0; + int err; + unsigned int i; + + BUG_ON(info->nr_rings); + + /* Check if backend supports multiple queues. */ + err = xenbus_scanf(XBT_NIL, info->xbdev->otherend, + "multi-queue-max-queues", "%u", &backend_max_queues); + if (err < 0) + backend_max_queues = 1; + + info->nr_rings = min(backend_max_queues, xen_blkif_max_queues); + /* We need at least one ring. */ + if (!info->nr_rings) + info->nr_rings = 1; + + info->rinfo = kzalloc(sizeof(struct blkfront_ring_info) * info->nr_rings, GFP_KERNEL); + if (!info->rinfo) { + xenbus_dev_fatal(info->xbdev, -ENOMEM, "allocating ring_info structure"); + return -ENOMEM; + } + + for (i = 0; i < info->nr_rings; i++) { + struct blkfront_ring_info *rinfo; + + rinfo = &info->rinfo[i]; + INIT_LIST_HEAD(&rinfo->indirect_pages); + INIT_LIST_HEAD(&rinfo->grants); + rinfo->dev_info = info; + INIT_WORK(&rinfo->work, blkif_restart_queue); + spin_lock_init(&rinfo->ring_lock); + } + return 0; +} /** * Entry point to this code when a new device is created. Allocate the basic * structures and the ring buffer for communication with the backend, and @@ -1883,9 +1920,7 @@ static int blkfront_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int err, vdevice; - unsigned int r_index; struct blkfront_info *info; - unsigned int backend_max_queues = 0; /* FIXME: Use dynamic device id if this is not set. */ err = xenbus_scanf(XBT_NIL, dev->nodename, @@ -1936,33 +1971,10 @@ static int blkfront_probe(struct xenbus_device *dev, } info->xbdev = dev; - /* Check if backend supports multiple queues. */ - err = xenbus_scanf(XBT_NIL, info->xbdev->otherend, - "multi-queue-max-queues", "%u", &backend_max_queues); - if (err < 0) - backend_max_queues = 1; - - info->nr_rings = min(backend_max_queues, xen_blkif_max_queues); - /* We need at least one ring. */ - if (!info->nr_rings) - info->nr_rings = 1; - - info->rinfo = kzalloc(sizeof(struct blkfront_ring_info) * info->nr_rings, GFP_KERNEL); - if (!info->rinfo) { - xenbus_dev_fatal(dev, -ENOMEM, "allocating ring_info structure"); + err = negotiate_mq(info); + if (err) { kfree(info); - return -ENOMEM; - } - - for (r_index = 0; r_index < info->nr_rings; r_index++) { - struct blkfront_ring_info *rinfo; - - rinfo = &info->rinfo[r_index]; - INIT_LIST_HEAD(&rinfo->indirect_pages); - INIT_LIST_HEAD(&rinfo->grants); - rinfo->dev_info = info; - INIT_WORK(&rinfo->work, blkif_restart_queue); - spin_lock_init(&rinfo->ring_lock); + return err; } mutex_init(&info->mutex); @@ -2123,12 +2135,16 @@ static int blkif_recover(struct blkfront_info *info) static int blkfront_resume(struct xenbus_device *dev) { struct blkfront_info *info = dev_get_drvdata(&dev->dev); - int err; + int err = 0; dev_dbg(&dev->dev, "blkfront_resume: %s\n", dev->nodename); blkif_free(info, info->connected == BLKIF_STATE_CONNECTED); + err = negotiate_mq(info); + if (err) + return err; + err = talk_to_blkback(dev, info); /* diff --git a/drivers/char/random.c b/drivers/char/random.c index d0da5d852d41..b583e5336630 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1819,6 +1819,28 @@ unsigned int get_random_int(void) EXPORT_SYMBOL(get_random_int); /* + * Same as get_random_int(), but returns unsigned long. + */ +unsigned long get_random_long(void) +{ + __u32 *hash; + unsigned long ret; + + if (arch_get_random_long(&ret)) + return ret; + + hash = get_cpu_var(get_random_int_hash); + + hash[0] += current->pid + jiffies + random_get_entropy(); + md5_transform(hash, random_int_secret); + ret = *(unsigned long *)hash; + put_cpu_var(get_random_int_hash); + + return ret; +} +EXPORT_SYMBOL(get_random_long); + +/* * randomize_range() returns a start address such that * * [...... <range> .....] diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index b038e3666058..bae4be6501df 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -43,7 +43,7 @@ obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o obj-$(CONFIG_ARCH_STM32) += clk-stm32f4.o -obj-$(CONFIG_ARCH_TANGOX) += clk-tango4.o +obj-$(CONFIG_ARCH_TANGO) += clk-tango4.o obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o obj-$(CONFIG_ARCH_U300) += clk-u300.o obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c index 19fed65587e8..7b09a265d79f 100644 --- a/drivers/clk/clk-gpio.c +++ b/drivers/clk/clk-gpio.c @@ -289,7 +289,7 @@ static void __init of_gpio_clk_setup(struct device_node *node, num_parents = of_clk_get_parent_count(node); if (num_parents < 0) - return; + num_parents = 0; data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) diff --git a/drivers/clk/clk-scpi.c b/drivers/clk/clk-scpi.c index cd0f2726f5e0..89e9ca78bb94 100644 --- a/drivers/clk/clk-scpi.c +++ b/drivers/clk/clk-scpi.c @@ -299,7 +299,7 @@ static int scpi_clocks_probe(struct platform_device *pdev) /* Add the virtual cpufreq device */ cpufreq_dev = platform_device_register_simple("scpi-cpufreq", -1, NULL, 0); - if (!cpufreq_dev) + if (IS_ERR(cpufreq_dev)) pr_warn("unable to register cpufreq device"); return 0; diff --git a/drivers/clk/mvebu/dove-divider.c b/drivers/clk/mvebu/dove-divider.c index d5c5bfa35a5a..3e0b52daa35f 100644 --- a/drivers/clk/mvebu/dove-divider.c +++ b/drivers/clk/mvebu/dove-divider.c @@ -247,7 +247,7 @@ static struct clk_onecell_data dove_divider_data = { void __init dove_divider_clk_init(struct device_node *np) { - void *base; + void __iomem *base; base = of_iomap(np, 0); if (WARN_ON(!base)) diff --git a/drivers/clk/qcom/gcc-apq8084.c b/drivers/clk/qcom/gcc-apq8084.c index cf73e539e9f6..070037a29ea5 100644 --- a/drivers/clk/qcom/gcc-apq8084.c +++ b/drivers/clk/qcom/gcc-apq8084.c @@ -3587,7 +3587,6 @@ static const struct regmap_config gcc_apq8084_regmap_config = { .val_bits = 32, .max_register = 0x1fc0, .fast_io = true, - .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc gcc_apq8084_desc = { diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c index b692ae881d6a..dd5402bac620 100644 --- a/drivers/clk/qcom/gcc-ipq806x.c +++ b/drivers/clk/qcom/gcc-ipq806x.c @@ -3005,7 +3005,6 @@ static const struct regmap_config gcc_ipq806x_regmap_config = { .val_bits = 32, .max_register = 0x3e40, .fast_io = true, - .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc gcc_ipq806x_desc = { diff --git a/drivers/clk/qcom/gcc-msm8660.c b/drivers/clk/qcom/gcc-msm8660.c index f6a2b14dfec4..ad413036f7c7 100644 --- a/drivers/clk/qcom/gcc-msm8660.c +++ b/drivers/clk/qcom/gcc-msm8660.c @@ -2702,7 +2702,6 @@ static const struct regmap_config gcc_msm8660_regmap_config = { .val_bits = 32, .max_register = 0x363c, .fast_io = true, - .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc gcc_msm8660_desc = { diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c index e3bf09d7d0ef..8cc9b2868b41 100644 --- a/drivers/clk/qcom/gcc-msm8916.c +++ b/drivers/clk/qcom/gcc-msm8916.c @@ -3336,7 +3336,6 @@ static const struct regmap_config gcc_msm8916_regmap_config = { .val_bits = 32, .max_register = 0x80000, .fast_io = true, - .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc gcc_msm8916_desc = { diff --git a/drivers/clk/qcom/gcc-msm8960.c b/drivers/clk/qcom/gcc-msm8960.c index f31111e32d44..983dd7dc89a7 100644 --- a/drivers/clk/qcom/gcc-msm8960.c +++ b/drivers/clk/qcom/gcc-msm8960.c @@ -3468,7 +3468,6 @@ static const struct regmap_config gcc_msm8960_regmap_config = { .val_bits = 32, .max_register = 0x3660, .fast_io = true, - .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct regmap_config gcc_apq8064_regmap_config = { @@ -3477,7 +3476,6 @@ static const struct regmap_config gcc_apq8064_regmap_config = { .val_bits = 32, .max_register = 0x3880, .fast_io = true, - .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc gcc_msm8960_desc = { diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c index df164d618e34..335952db309b 100644 --- a/drivers/clk/qcom/gcc-msm8974.c +++ b/drivers/clk/qcom/gcc-msm8974.c @@ -2680,7 +2680,6 @@ static const struct regmap_config gcc_msm8974_regmap_config = { .val_bits = 32, .max_register = 0x1fc0, .fast_io = true, - .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc gcc_msm8974_desc = { diff --git a/drivers/clk/qcom/lcc-ipq806x.c b/drivers/clk/qcom/lcc-ipq806x.c index 62e79fadd5f7..db3998e5e2d8 100644 --- a/drivers/clk/qcom/lcc-ipq806x.c +++ b/drivers/clk/qcom/lcc-ipq806x.c @@ -419,7 +419,6 @@ static const struct regmap_config lcc_ipq806x_regmap_config = { .val_bits = 32, .max_register = 0xfc, .fast_io = true, - .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc lcc_ipq806x_desc = { diff --git a/drivers/clk/qcom/lcc-msm8960.c b/drivers/clk/qcom/lcc-msm8960.c index bf95bb0ea1b8..4fcf9d1d233c 100644 --- a/drivers/clk/qcom/lcc-msm8960.c +++ b/drivers/clk/qcom/lcc-msm8960.c @@ -524,7 +524,6 @@ static const struct regmap_config lcc_msm8960_regmap_config = { .val_bits = 32, .max_register = 0xfc, .fast_io = true, - .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc lcc_msm8960_desc = { diff --git a/drivers/clk/qcom/mmcc-apq8084.c b/drivers/clk/qcom/mmcc-apq8084.c index 1e703fda8a0f..30777f9f1a43 100644 --- a/drivers/clk/qcom/mmcc-apq8084.c +++ b/drivers/clk/qcom/mmcc-apq8084.c @@ -3368,7 +3368,6 @@ static const struct regmap_config mmcc_apq8084_regmap_config = { .val_bits = 32, .max_register = 0x5104, .fast_io = true, - .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc mmcc_apq8084_desc = { diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c index d73a048d3b9d..00e36192a1de 100644 --- a/drivers/clk/qcom/mmcc-msm8960.c +++ b/drivers/clk/qcom/mmcc-msm8960.c @@ -3029,7 +3029,6 @@ static const struct regmap_config mmcc_msm8960_regmap_config = { .val_bits = 32, .max_register = 0x334, .fast_io = true, - .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct regmap_config mmcc_apq8064_regmap_config = { @@ -3038,7 +3037,6 @@ static const struct regmap_config mmcc_apq8064_regmap_config = { .val_bits = 32, .max_register = 0x350, .fast_io = true, - .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc mmcc_msm8960_desc = { diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c index bbe28ed93669..9d790bcadf25 100644 --- a/drivers/clk/qcom/mmcc-msm8974.c +++ b/drivers/clk/qcom/mmcc-msm8974.c @@ -2594,7 +2594,6 @@ static const struct regmap_config mmcc_msm8974_regmap_config = { .val_bits = 32, .max_register = 0x5104, .fast_io = true, - .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc mmcc_msm8974_desc = { diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index ebce98033fbb..bc7fbac83ab7 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -133,7 +133,7 @@ PNAME(mux_spdif_p) = { "spdif_src", "spdif_frac", "xin12m" }; PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" }; PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" }; PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" }; -PNAME(mux_mac_p) = { "mac_pll_src", "ext_gmac" }; +PNAME(mux_mac_p) = { "mac_pll_src", "rmii_clkin" }; PNAME(mux_dclk_p) = { "dclk_lcdc", "dclk_cru" }; static struct rockchip_pll_clock rk3036_pll_clks[] __initdata = { @@ -224,16 +224,16 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKGATE_CON(2), 2, GFLAGS), COMPOSITE_NODIV(SCLK_TIMER0, "sclk_timer0", mux_timer_p, CLK_IGNORE_UNUSED, - RK2928_CLKSEL_CON(2), 4, 1, DFLAGS, + RK2928_CLKSEL_CON(2), 4, 1, MFLAGS, RK2928_CLKGATE_CON(1), 0, GFLAGS), COMPOSITE_NODIV(SCLK_TIMER1, "sclk_timer1", mux_timer_p, CLK_IGNORE_UNUSED, - RK2928_CLKSEL_CON(2), 5, 1, DFLAGS, + RK2928_CLKSEL_CON(2), 5, 1, MFLAGS, RK2928_CLKGATE_CON(1), 1, GFLAGS), COMPOSITE_NODIV(SCLK_TIMER2, "sclk_timer2", mux_timer_p, CLK_IGNORE_UNUSED, - RK2928_CLKSEL_CON(2), 6, 1, DFLAGS, + RK2928_CLKSEL_CON(2), 6, 1, MFLAGS, RK2928_CLKGATE_CON(2), 4, GFLAGS), COMPOSITE_NODIV(SCLK_TIMER3, "sclk_timer3", mux_timer_p, CLK_IGNORE_UNUSED, - RK2928_CLKSEL_CON(2), 7, 1, DFLAGS, + RK2928_CLKSEL_CON(2), 7, 1, MFLAGS, RK2928_CLKGATE_CON(2), 5, GFLAGS), MUX(0, "uart_pll_clk", mux_pll_src_apll_dpll_gpll_usb480m_p, 0, @@ -242,11 +242,11 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKSEL_CON(13), 0, 7, DFLAGS, RK2928_CLKGATE_CON(1), 8, GFLAGS), COMPOSITE_NOMUX(0, "uart1_src", "uart_pll_clk", 0, - RK2928_CLKSEL_CON(13), 0, 7, DFLAGS, - RK2928_CLKGATE_CON(1), 8, GFLAGS), + RK2928_CLKSEL_CON(14), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(1), 10, GFLAGS), COMPOSITE_NOMUX(0, "uart2_src", "uart_pll_clk", 0, - RK2928_CLKSEL_CON(13), 0, 7, DFLAGS, - RK2928_CLKGATE_CON(1), 8, GFLAGS), + RK2928_CLKSEL_CON(15), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(1), 12, GFLAGS), COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(17), 0, RK2928_CLKGATE_CON(1), 9, GFLAGS, @@ -279,13 +279,13 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKGATE_CON(3), 2, GFLAGS), COMPOSITE_NODIV(0, "sclk_sdmmc_src", mux_mmc_src_p, 0, - RK2928_CLKSEL_CON(12), 8, 2, DFLAGS, + RK2928_CLKSEL_CON(12), 8, 2, MFLAGS, RK2928_CLKGATE_CON(2), 11, GFLAGS), DIV(SCLK_SDMMC, "sclk_sdmmc", "sclk_sdmmc_src", 0, RK2928_CLKSEL_CON(11), 0, 7, DFLAGS), COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0, - RK2928_CLKSEL_CON(12), 10, 2, DFLAGS, + RK2928_CLKSEL_CON(12), 10, 2, MFLAGS, RK2928_CLKGATE_CON(2), 13, GFLAGS), DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0, RK2928_CLKSEL_CON(11), 8, 7, DFLAGS), @@ -344,12 +344,12 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKGATE_CON(10), 5, GFLAGS), COMPOSITE_NOGATE(0, "mac_pll_src", mux_pll_src_3plls_p, 0, - RK2928_CLKSEL_CON(21), 0, 2, MFLAGS, 4, 5, DFLAGS), + RK2928_CLKSEL_CON(21), 0, 2, MFLAGS, 9, 5, DFLAGS), MUX(SCLK_MACREF, "mac_clk_ref", mux_mac_p, CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(21), 3, 1, MFLAGS), COMPOSITE_NOMUX(SCLK_MAC, "mac_clk", "mac_clk_ref", 0, - RK2928_CLKSEL_CON(21), 9, 5, DFLAGS, + RK2928_CLKSEL_CON(21), 4, 5, DFLAGS, RK2928_CLKGATE_CON(2), 6, GFLAGS), MUX(SCLK_HDMI, "dclk_hdmi", mux_dclk_p, 0, diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index be0ede522269..21f3ea909fab 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -780,13 +780,13 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK3368_CLKGATE_CON(20), 0, GFLAGS), /* pclk_pd_alive gates */ - GATE(PCLK_TIMER1, "pclk_timer1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 8, GFLAGS), - GATE(PCLK_TIMER0, "pclk_timer0", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 7, GFLAGS), - GATE(0, "pclk_alive_niu", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 12, GFLAGS), - GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 11, GFLAGS), - GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 3, GFLAGS), - GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 2, GFLAGS), - GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 1, GFLAGS), + GATE(PCLK_TIMER1, "pclk_timer1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 13, GFLAGS), + GATE(PCLK_TIMER0, "pclk_timer0", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 12, GFLAGS), + GATE(0, "pclk_alive_niu", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(22), 9, GFLAGS), + GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(22), 8, GFLAGS), + GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 3, GFLAGS), + GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 2, GFLAGS), + GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 1, GFLAGS), /* * pclk_vio gates @@ -796,12 +796,12 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { GATE(0, "pclk_dphytx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS), /* pclk_pd_pmu gates */ - GATE(PCLK_PMUGRF, "pclk_pmugrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 0, GFLAGS), - GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3368_CLKGATE_CON(17), 4, GFLAGS), - GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 3, GFLAGS), - GATE(0, "pclk_pmu_noc", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 2, GFLAGS), - GATE(0, "pclk_intmem1", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 1, GFLAGS), - GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 2, GFLAGS), + GATE(PCLK_PMUGRF, "pclk_pmugrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 5, GFLAGS), + GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3368_CLKGATE_CON(23), 4, GFLAGS), + GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 3, GFLAGS), + GATE(0, "pclk_pmu_noc", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 2, GFLAGS), + GATE(0, "pclk_intmem1", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 1, GFLAGS), + GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 0, GFLAGS), /* timer gates */ GATE(0, "sclk_timer15", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 11, GFLAGS), diff --git a/drivers/clk/tegra/clk-emc.c b/drivers/clk/tegra/clk-emc.c index e1fe8f35d45c..74e7544f861b 100644 --- a/drivers/clk/tegra/clk-emc.c +++ b/drivers/clk/tegra/clk-emc.c @@ -450,8 +450,10 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra, struct emc_timing *timing = tegra->timings + (i++); err = load_one_timing_from_dt(tegra, timing, child); - if (err) + if (err) { + of_node_put(child); return err; + } timing->ram_code = ram_code; } @@ -499,9 +501,9 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np, * fuses until the apbmisc driver is loaded. */ err = load_timings_from_dt(tegra, node, node_ram_code); + of_node_put(node); if (err) return ERR_PTR(err); - of_node_put(node); break; } diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h index 19ce0738ee76..62ea38187b71 100644 --- a/drivers/clk/tegra/clk-id.h +++ b/drivers/clk/tegra/clk-id.h @@ -11,6 +11,7 @@ enum clk_id { tegra_clk_afi, tegra_clk_amx, tegra_clk_amx1, + tegra_clk_apb2ape, tegra_clk_apbdma, tegra_clk_apbif, tegra_clk_ape, diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index a534bfab30b3..6ac3f843e7ca 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -86,15 +86,21 @@ #define PLLE_SS_DISABLE (PLLE_SS_CNTL_BYPASS_SS | PLLE_SS_CNTL_INTERP_RESET |\ PLLE_SS_CNTL_SSC_BYP) #define PLLE_SS_MAX_MASK 0x1ff -#define PLLE_SS_MAX_VAL 0x25 +#define PLLE_SS_MAX_VAL_TEGRA114 0x25 +#define PLLE_SS_MAX_VAL_TEGRA210 0x21 #define PLLE_SS_INC_MASK (0xff << 16) #define PLLE_SS_INC_VAL (0x1 << 16) #define PLLE_SS_INCINTRV_MASK (0x3f << 24) -#define PLLE_SS_INCINTRV_VAL (0x20 << 24) +#define PLLE_SS_INCINTRV_VAL_TEGRA114 (0x20 << 24) +#define PLLE_SS_INCINTRV_VAL_TEGRA210 (0x23 << 24) #define PLLE_SS_COEFFICIENTS_MASK \ (PLLE_SS_MAX_MASK | PLLE_SS_INC_MASK | PLLE_SS_INCINTRV_MASK) -#define PLLE_SS_COEFFICIENTS_VAL \ - (PLLE_SS_MAX_VAL | PLLE_SS_INC_VAL | PLLE_SS_INCINTRV_VAL) +#define PLLE_SS_COEFFICIENTS_VAL_TEGRA114 \ + (PLLE_SS_MAX_VAL_TEGRA114 | PLLE_SS_INC_VAL |\ + PLLE_SS_INCINTRV_VAL_TEGRA114) +#define PLLE_SS_COEFFICIENTS_VAL_TEGRA210 \ + (PLLE_SS_MAX_VAL_TEGRA210 | PLLE_SS_INC_VAL |\ + PLLE_SS_INCINTRV_VAL_TEGRA210) #define PLLE_AUX_PLLP_SEL BIT(2) #define PLLE_AUX_USE_LOCKDET BIT(3) @@ -880,7 +886,7 @@ static int clk_plle_training(struct tegra_clk_pll *pll) static int clk_plle_enable(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); - unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk)); + unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); struct tegra_clk_pll_freq_table sel; u32 val; int err; @@ -1378,7 +1384,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) u32 val; int ret; unsigned long flags = 0; - unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk)); + unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate)) return -EINVAL; @@ -1401,7 +1407,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) val |= PLLE_MISC_IDDQ_SW_CTRL; val &= ~PLLE_MISC_IDDQ_SW_VALUE; val |= PLLE_MISC_PLLE_PTS; - val |= PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK; + val &= ~(PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK); pll_writel_misc(val, pll); udelay(5); @@ -1428,7 +1434,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) val = pll_readl(PLLE_SS_CTRL, pll); val &= ~(PLLE_SS_CNTL_CENTER | PLLE_SS_CNTL_INVERT); val &= ~PLLE_SS_COEFFICIENTS_MASK; - val |= PLLE_SS_COEFFICIENTS_VAL; + val |= PLLE_SS_COEFFICIENTS_VAL_TEGRA114; pll_writel(val, PLLE_SS_CTRL, pll); val &= ~(PLLE_SS_CNTL_SSC_BYP | PLLE_SS_CNTL_BYPASS_SS); pll_writel(val, PLLE_SS_CTRL, pll); @@ -2012,9 +2018,9 @@ static int clk_plle_tegra210_enable(struct clk_hw *hw) struct tegra_clk_pll *pll = to_clk_pll(hw); struct tegra_clk_pll_freq_table sel; u32 val; - int ret; + int ret = 0; unsigned long flags = 0; - unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk)); + unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate)) return -EINVAL; @@ -2022,22 +2028,20 @@ static int clk_plle_tegra210_enable(struct clk_hw *hw) if (pll->lock) spin_lock_irqsave(pll->lock, flags); + val = pll_readl(pll->params->aux_reg, pll); + if (val & PLLE_AUX_SEQ_ENABLE) + goto out; + val = pll_readl_base(pll); val &= ~BIT(30); /* Disable lock override */ pll_writel_base(val, pll); - val = pll_readl(pll->params->aux_reg, pll); - val |= PLLE_AUX_ENABLE_SWCTL; - val &= ~PLLE_AUX_SEQ_ENABLE; - pll_writel(val, pll->params->aux_reg, pll); - udelay(1); - val = pll_readl_misc(pll); val |= PLLE_MISC_LOCK_ENABLE; val |= PLLE_MISC_IDDQ_SW_CTRL; val &= ~PLLE_MISC_IDDQ_SW_VALUE; val |= PLLE_MISC_PLLE_PTS; - val |= PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK; + val &= ~(PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK); pll_writel_misc(val, pll); udelay(5); @@ -2067,7 +2071,7 @@ static int clk_plle_tegra210_enable(struct clk_hw *hw) val = pll_readl(PLLE_SS_CTRL, pll); val &= ~(PLLE_SS_CNTL_CENTER | PLLE_SS_CNTL_INVERT); val &= ~PLLE_SS_COEFFICIENTS_MASK; - val |= PLLE_SS_COEFFICIENTS_VAL; + val |= PLLE_SS_COEFFICIENTS_VAL_TEGRA210; pll_writel(val, PLLE_SS_CTRL, pll); val &= ~(PLLE_SS_CNTL_SSC_BYP | PLLE_SS_CNTL_BYPASS_SS); pll_writel(val, PLLE_SS_CTRL, pll); @@ -2104,15 +2108,25 @@ static void clk_plle_tegra210_disable(struct clk_hw *hw) if (pll->lock) spin_lock_irqsave(pll->lock, flags); + /* If PLLE HW sequencer is enabled, SW should not disable PLLE */ + val = pll_readl(pll->params->aux_reg, pll); + if (val & PLLE_AUX_SEQ_ENABLE) + goto out; + val = pll_readl_base(pll); val &= ~PLLE_BASE_ENABLE; pll_writel_base(val, pll); + val = pll_readl(pll->params->aux_reg, pll); + val |= PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL; + pll_writel(val, pll->params->aux_reg, pll); + val = pll_readl_misc(pll); val |= PLLE_MISC_IDDQ_SW_CTRL | PLLE_MISC_IDDQ_SW_VALUE; pll_writel_misc(val, pll); udelay(1); +out: if (pll->lock) spin_unlock_irqrestore(pll->lock, flags); } diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 6ad381a888a6..ea2b9cbf9e70 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -773,7 +773,7 @@ static struct tegra_periph_init_data periph_clks[] = { XUSB("xusb_dev_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src), XUSB("xusb_dev_src", mux_clkm_pllp_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src_8), MUX8("dbgapb", mux_pllp_clkm_2, CLK_SOURCE_DBGAPB, 185, TEGRA_PERIPH_NO_RESET, tegra_clk_dbgapb), - MUX8("msenc", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVENC, 219, 0, tegra_clk_nvenc), + MUX8("nvenc", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVENC, 219, 0, tegra_clk_nvenc), MUX8("nvdec", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVDEC, 194, 0, tegra_clk_nvdec), MUX8("nvjpg", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVJPG, 195, 0, tegra_clk_nvjpg), MUX8("ape", mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm, CLK_SOURCE_APE, 198, TEGRA_PERIPH_ON_APB, tegra_clk_ape), @@ -782,7 +782,7 @@ static struct tegra_periph_init_data periph_clks[] = { NODIV("sor1", mux_clkm_sor1_brick_sor1_src, CLK_SOURCE_SOR1, 15, MASK(1), 183, 0, tegra_clk_sor1, &sor1_lock), MUX8("sdmmc_legacy", mux_pllp_out3_clkm_pllp_pllc4, CLK_SOURCE_SDMMC_LEGACY, 193, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_sdmmc_legacy), MUX8("qspi", mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_QSPI, 211, TEGRA_PERIPH_ON_APB, tegra_clk_qspi), - MUX("vii2c", mux_pllp_pllc_clkm, CLK_SOURCE_VI_I2C, 208, TEGRA_PERIPH_ON_APB, tegra_clk_vi_i2c), + I2C("vii2c", mux_pllp_pllc_clkm, CLK_SOURCE_VI_I2C, 208, tegra_clk_vi_i2c), MUX("mipibif", mux_pllp_clkm, CLK_SOURCE_MIPIBIF, 173, TEGRA_PERIPH_ON_APB, tegra_clk_mipibif), MUX("uartape", mux_pllp_pllc_clkm, CLK_SOURCE_UARTAPE, 212, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_uartape), MUX8("tsecb", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_TSECB, 206, 0, tegra_clk_tsecb), @@ -829,6 +829,7 @@ static struct tegra_periph_init_data gate_clks[] = { GATE("xusb_gate", "osc", 143, 0, tegra_clk_xusb_gate, 0), GATE("pll_p_out_cpu", "pll_p", 223, 0, tegra_clk_pll_p_out_cpu, 0), GATE("pll_p_out_adsp", "pll_p", 187, 0, tegra_clk_pll_p_out_adsp, 0), + GATE("apb2ape", "clk_m", 107, 0, tegra_clk_apb2ape, 0), }; static struct tegra_periph_init_data div_clks[] = { diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c index 4559a20e3af6..474de0f0c26d 100644 --- a/drivers/clk/tegra/clk-tegra-super-gen4.c +++ b/drivers/clk/tegra/clk-tegra-super-gen4.c @@ -67,7 +67,7 @@ static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", "pll_p", "pll_p_out4", "unused", "unused", "pll_x", "pll_x_out0" }; -const struct tegra_super_gen_info tegra_super_gen_info_gen4 = { +static const struct tegra_super_gen_info tegra_super_gen_info_gen4 = { .gen = gen4, .sclk_parents = sclk_parents, .cclk_g_parents = cclk_g_parents, @@ -93,7 +93,7 @@ static const char *cclk_lp_parents_gen5[] = { "clk_m", "unused", "clk_32k", "unu "unused", "unused", "unused", "unused", "dfllCPU_out" }; -const struct tegra_super_gen_info tegra_super_gen_info_gen5 = { +static const struct tegra_super_gen_info tegra_super_gen_info_gen5 = { .gen = gen5, .sclk_parents = sclk_parents_gen5, .cclk_g_parents = cclk_g_parents_gen5, @@ -171,7 +171,7 @@ static void __init tegra_sclk_init(void __iomem *clk_base, *dt_clk = clk; } -void __init tegra_super_clk_init(void __iomem *clk_base, +static void __init tegra_super_clk_init(void __iomem *clk_base, void __iomem *pmc_base, struct tegra_clk *tegra_clks, struct tegra_clk_pll_params *params, diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 58514c44ea83..637041fd53ad 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -59,8 +59,8 @@ #define PLLC3_MISC3 0x50c #define PLLM_BASE 0x90 -#define PLLM_MISC0 0x9c #define PLLM_MISC1 0x98 +#define PLLM_MISC2 0x9c #define PLLP_BASE 0xa0 #define PLLP_MISC0 0xac #define PLLP_MISC1 0x680 @@ -99,7 +99,7 @@ #define PLLC4_MISC0 0x5a8 #define PLLC4_OUT 0x5e4 #define PLLMB_BASE 0x5e8 -#define PLLMB_MISC0 0x5ec +#define PLLMB_MISC1 0x5ec #define PLLA1_BASE 0x6a4 #define PLLA1_MISC0 0x6a8 #define PLLA1_MISC1 0x6ac @@ -243,7 +243,8 @@ static unsigned long tegra210_input_freq[] = { }; static const char *mux_pllmcp_clkm[] = { - "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_c2", "pll_c3", + "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_mb", "pll_mb", + "pll_p", }; #define mux_pllmcp_clkm_idx NULL @@ -367,12 +368,12 @@ static const char *mux_pllmcp_clkm[] = { /* PLLMB */ #define PLLMB_BASE_LOCK (1 << 27) -#define PLLMB_MISC0_LOCK_OVERRIDE (1 << 18) -#define PLLMB_MISC0_IDDQ (1 << 17) -#define PLLMB_MISC0_LOCK_ENABLE (1 << 16) +#define PLLMB_MISC1_LOCK_OVERRIDE (1 << 18) +#define PLLMB_MISC1_IDDQ (1 << 17) +#define PLLMB_MISC1_LOCK_ENABLE (1 << 16) -#define PLLMB_MISC0_DEFAULT_VALUE 0x00030000 -#define PLLMB_MISC0_WRITE_MASK 0x0007ffff +#define PLLMB_MISC1_DEFAULT_VALUE 0x00030000 +#define PLLMB_MISC1_WRITE_MASK 0x0007ffff /* PLLP */ #define PLLP_BASE_OVERRIDE (1 << 28) @@ -457,7 +458,8 @@ static void pllcx_check_defaults(struct tegra_clk_pll_params *params) PLLCX_MISC3_WRITE_MASK); } -void tegra210_pllcx_set_defaults(const char *name, struct tegra_clk_pll *pllcx) +static void tegra210_pllcx_set_defaults(const char *name, + struct tegra_clk_pll *pllcx) { pllcx->params->defaults_set = true; @@ -482,22 +484,22 @@ void tegra210_pllcx_set_defaults(const char *name, struct tegra_clk_pll *pllcx) udelay(1); } -void _pllc_set_defaults(struct tegra_clk_pll *pllcx) +static void _pllc_set_defaults(struct tegra_clk_pll *pllcx) { tegra210_pllcx_set_defaults("PLL_C", pllcx); } -void _pllc2_set_defaults(struct tegra_clk_pll *pllcx) +static void _pllc2_set_defaults(struct tegra_clk_pll *pllcx) { tegra210_pllcx_set_defaults("PLL_C2", pllcx); } -void _pllc3_set_defaults(struct tegra_clk_pll *pllcx) +static void _pllc3_set_defaults(struct tegra_clk_pll *pllcx) { tegra210_pllcx_set_defaults("PLL_C3", pllcx); } -void _plla1_set_defaults(struct tegra_clk_pll *pllcx) +static void _plla1_set_defaults(struct tegra_clk_pll *pllcx) { tegra210_pllcx_set_defaults("PLL_A1", pllcx); } @@ -507,7 +509,7 @@ void _plla1_set_defaults(struct tegra_clk_pll *pllcx) * PLL with dynamic ramp and fractional SDM. Dynamic ramp is not used. * Fractional SDM is allowed to provide exact audio rates. */ -void tegra210_plla_set_defaults(struct tegra_clk_pll *plla) +static void tegra210_plla_set_defaults(struct tegra_clk_pll *plla) { u32 mask; u32 val = readl_relaxed(clk_base + plla->params->base_reg); @@ -559,7 +561,7 @@ void tegra210_plla_set_defaults(struct tegra_clk_pll *plla) * PLLD * PLL with fractional SDM. */ -void tegra210_plld_set_defaults(struct tegra_clk_pll *plld) +static void tegra210_plld_set_defaults(struct tegra_clk_pll *plld) { u32 val; u32 mask = 0xffff; @@ -698,7 +700,7 @@ static void plldss_defaults(const char *pll_name, struct tegra_clk_pll *plldss, udelay(1); } -void tegra210_plld2_set_defaults(struct tegra_clk_pll *plld2) +static void tegra210_plld2_set_defaults(struct tegra_clk_pll *plld2) { plldss_defaults("PLL_D2", plld2, PLLD2_MISC0_DEFAULT_VALUE, PLLD2_MISC1_CFG_DEFAULT_VALUE, @@ -706,7 +708,7 @@ void tegra210_plld2_set_defaults(struct tegra_clk_pll *plld2) PLLD2_MISC3_CTRL2_DEFAULT_VALUE); } -void tegra210_plldp_set_defaults(struct tegra_clk_pll *plldp) +static void tegra210_plldp_set_defaults(struct tegra_clk_pll *plldp) { plldss_defaults("PLL_DP", plldp, PLLDP_MISC0_DEFAULT_VALUE, PLLDP_MISC1_CFG_DEFAULT_VALUE, @@ -719,7 +721,7 @@ void tegra210_plldp_set_defaults(struct tegra_clk_pll *plldp) * Base and misc0 layout is the same as PLLD2/PLLDP, but no SDM/SSC support. * VCO is exposed to the clock tree via fixed 1/3 and 1/5 dividers. */ -void tegra210_pllc4_set_defaults(struct tegra_clk_pll *pllc4) +static void tegra210_pllc4_set_defaults(struct tegra_clk_pll *pllc4) { plldss_defaults("PLL_C4", pllc4, PLLC4_MISC0_DEFAULT_VALUE, 0, 0, 0); } @@ -728,7 +730,7 @@ void tegra210_pllc4_set_defaults(struct tegra_clk_pll *pllc4) * PLLRE * VCO is exposed to the clock tree directly along with post-divider output */ -void tegra210_pllre_set_defaults(struct tegra_clk_pll *pllre) +static void tegra210_pllre_set_defaults(struct tegra_clk_pll *pllre) { u32 mask; u32 val = readl_relaxed(clk_base + pllre->params->base_reg); @@ -780,13 +782,13 @@ static void pllx_get_dyn_steps(struct clk_hw *hw, u32 *step_a, u32 *step_b) { unsigned long input_rate; - if (!IS_ERR_OR_NULL(hw->clk)) { + /* cf rate */ + if (!IS_ERR_OR_NULL(hw->clk)) input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); - /* cf rate */ - input_rate /= tegra_pll_get_fixed_mdiv(hw, input_rate); - } else { + else input_rate = 38400000; - } + + input_rate /= tegra_pll_get_fixed_mdiv(hw, input_rate); switch (input_rate) { case 12000000: @@ -841,7 +843,7 @@ static void pllx_check_defaults(struct tegra_clk_pll *pll) PLLX_MISC5_WRITE_MASK); } -void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx) +static void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx) { u32 val; u32 step_a, step_b; @@ -901,7 +903,7 @@ void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx) } /* PLLMB */ -void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb) +static void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb) { u32 mask, val = readl_relaxed(clk_base + pllmb->params->base_reg); @@ -914,15 +916,15 @@ void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb) * PLL is ON: check if defaults already set, then set those * that can be updated in flight. */ - val = PLLMB_MISC0_DEFAULT_VALUE & (~PLLMB_MISC0_IDDQ); - mask = PLLMB_MISC0_LOCK_ENABLE | PLLMB_MISC0_LOCK_OVERRIDE; + val = PLLMB_MISC1_DEFAULT_VALUE & (~PLLMB_MISC1_IDDQ); + mask = PLLMB_MISC1_LOCK_ENABLE | PLLMB_MISC1_LOCK_OVERRIDE; _pll_misc_chk_default(clk_base, pllmb->params, 0, val, - ~mask & PLLMB_MISC0_WRITE_MASK); + ~mask & PLLMB_MISC1_WRITE_MASK); /* Enable lock detect */ val = readl_relaxed(clk_base + pllmb->params->ext_misc_reg[0]); val &= ~mask; - val |= PLLMB_MISC0_DEFAULT_VALUE & mask; + val |= PLLMB_MISC1_DEFAULT_VALUE & mask; writel_relaxed(val, clk_base + pllmb->params->ext_misc_reg[0]); udelay(1); @@ -930,7 +932,7 @@ void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb) } /* set IDDQ, enable lock detect */ - writel_relaxed(PLLMB_MISC0_DEFAULT_VALUE, + writel_relaxed(PLLMB_MISC1_DEFAULT_VALUE, clk_base + pllmb->params->ext_misc_reg[0]); udelay(1); } @@ -960,7 +962,7 @@ static void pllp_check_defaults(struct tegra_clk_pll *pll, bool enabled) ~mask & PLLP_MISC1_WRITE_MASK); } -void tegra210_pllp_set_defaults(struct tegra_clk_pll *pllp) +static void tegra210_pllp_set_defaults(struct tegra_clk_pll *pllp) { u32 mask; u32 val = readl_relaxed(clk_base + pllp->params->base_reg); @@ -1022,7 +1024,7 @@ static void pllu_check_defaults(struct tegra_clk_pll *pll, bool hw_control) ~mask & PLLU_MISC1_WRITE_MASK); } -void tegra210_pllu_set_defaults(struct tegra_clk_pll *pllu) +static void tegra210_pllu_set_defaults(struct tegra_clk_pll *pllu) { u32 val = readl_relaxed(clk_base + pllu->params->base_reg); @@ -1212,8 +1214,9 @@ static void tegra210_clk_pll_set_gain(struct tegra_clk_pll_freq_table *cfg) cfg->m *= PLL_SDM_COEFF; } -unsigned long tegra210_clk_adjust_vco_min(struct tegra_clk_pll_params *params, - unsigned long parent_rate) +static unsigned long +tegra210_clk_adjust_vco_min(struct tegra_clk_pll_params *params, + unsigned long parent_rate) { unsigned long vco_min = params->vco_min; @@ -1386,7 +1389,7 @@ static struct tegra_clk_pll_params pll_c_params = { .mdiv_default = 3, .div_nmp = &pllc_nmp, .freq_table = pll_cx_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .set_defaults = _pllc_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1425,7 +1428,7 @@ static struct tegra_clk_pll_params pll_c2_params = { .ext_misc_reg[2] = PLLC2_MISC2, .ext_misc_reg[3] = PLLC2_MISC3, .freq_table = pll_cx_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .set_defaults = _pllc2_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1455,7 +1458,7 @@ static struct tegra_clk_pll_params pll_c3_params = { .ext_misc_reg[2] = PLLC3_MISC2, .ext_misc_reg[3] = PLLC3_MISC3, .freq_table = pll_cx_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .set_defaults = _pllc3_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1505,7 +1508,6 @@ static struct tegra_clk_pll_params pll_c4_vco_params = { .base_reg = PLLC4_BASE, .misc_reg = PLLC4_MISC0, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE, .lock_delay = 300, .max_p = PLL_QLIN_PDIV_MAX, .ext_misc_reg[0] = PLLC4_MISC0, @@ -1517,8 +1519,7 @@ static struct tegra_clk_pll_params pll_c4_vco_params = { .div_nmp = &pllss_nmp, .freq_table = pll_c4_vco_freq_table, .set_defaults = tegra210_pllc4_set_defaults, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE | - TEGRA_PLL_VCO_OUT, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_VCO_OUT, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1559,15 +1560,15 @@ static struct tegra_clk_pll_params pll_m_params = { .vco_min = 800000000, .vco_max = 1866000000, .base_reg = PLLM_BASE, - .misc_reg = PLLM_MISC1, + .misc_reg = PLLM_MISC2, .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLLM_MISC_LOCK_ENABLE, .lock_delay = 300, - .iddq_reg = PLLM_MISC0, + .iddq_reg = PLLM_MISC2, .iddq_bit_idx = PLLM_IDDQ_BIT, .max_p = PLL_QLIN_PDIV_MAX, - .ext_misc_reg[0] = PLLM_MISC0, - .ext_misc_reg[0] = PLLM_MISC1, + .ext_misc_reg[0] = PLLM_MISC2, + .ext_misc_reg[1] = PLLM_MISC1, .round_p_to_pdiv = pll_qlin_p_to_pdiv, .pdiv_tohw = pll_qlin_pdiv_to_hw, .div_nmp = &pllm_nmp, @@ -1586,19 +1587,18 @@ static struct tegra_clk_pll_params pll_mb_params = { .vco_min = 800000000, .vco_max = 1866000000, .base_reg = PLLMB_BASE, - .misc_reg = PLLMB_MISC0, + .misc_reg = PLLMB_MISC1, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLMB_MISC_LOCK_ENABLE, .lock_delay = 300, - .iddq_reg = PLLMB_MISC0, + .iddq_reg = PLLMB_MISC1, .iddq_bit_idx = PLLMB_IDDQ_BIT, .max_p = PLL_QLIN_PDIV_MAX, - .ext_misc_reg[0] = PLLMB_MISC0, + .ext_misc_reg[0] = PLLMB_MISC1, .round_p_to_pdiv = pll_qlin_p_to_pdiv, .pdiv_tohw = pll_qlin_pdiv_to_hw, .div_nmp = &pllm_nmp, .freq_table = pll_m_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .set_defaults = tegra210_pllmb_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1671,7 +1671,6 @@ static struct tegra_clk_pll_params pll_re_vco_params = { .base_reg = PLLRE_BASE, .misc_reg = PLLRE_MISC0, .lock_mask = PLLRE_MISC_LOCK, - .lock_enable_bit_idx = PLLRE_MISC_LOCK_ENABLE, .lock_delay = 300, .max_p = PLL_QLIN_PDIV_MAX, .ext_misc_reg[0] = PLLRE_MISC0, @@ -1681,8 +1680,7 @@ static struct tegra_clk_pll_params pll_re_vco_params = { .pdiv_tohw = pll_qlin_pdiv_to_hw, .div_nmp = &pllre_nmp, .freq_table = pll_re_vco_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_LOCK_MISC | - TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_VCO_OUT, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_LOCK_MISC | TEGRA_PLL_VCO_OUT, .set_defaults = tegra210_pllre_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1712,7 +1710,6 @@ static struct tegra_clk_pll_params pll_p_params = { .base_reg = PLLP_BASE, .misc_reg = PLLP_MISC0, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLP_MISC_LOCK_ENABLE, .lock_delay = 300, .iddq_reg = PLLP_MISC0, .iddq_bit_idx = PLLXP_IDDQ_BIT, @@ -1721,8 +1718,7 @@ static struct tegra_clk_pll_params pll_p_params = { .div_nmp = &pllp_nmp, .freq_table = pll_p_freq_table, .fixed_rate = 408000000, - .flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK | - TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_VCO_OUT, + .flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK | TEGRA_PLL_VCO_OUT, .set_defaults = tegra210_pllp_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1750,7 +1746,7 @@ static struct tegra_clk_pll_params pll_a1_params = { .ext_misc_reg[2] = PLLA1_MISC2, .ext_misc_reg[3] = PLLA1_MISC3, .freq_table = pll_cx_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .set_defaults = _plla1_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1787,7 +1783,6 @@ static struct tegra_clk_pll_params pll_a_params = { .base_reg = PLLA_BASE, .misc_reg = PLLA_MISC0, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLA_MISC_LOCK_ENABLE, .lock_delay = 300, .round_p_to_pdiv = pll_qlin_p_to_pdiv, .pdiv_tohw = pll_qlin_pdiv_to_hw, @@ -1802,8 +1797,7 @@ static struct tegra_clk_pll_params pll_a_params = { .ext_misc_reg[1] = PLLA_MISC1, .ext_misc_reg[2] = PLLA_MISC2, .freq_table = pll_a_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_MDIV_NEW | - TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_MDIV_NEW, .set_defaults = tegra210_plla_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, .set_gain = tegra210_clk_pll_set_gain, @@ -1836,7 +1830,6 @@ static struct tegra_clk_pll_params pll_d_params = { .base_reg = PLLD_BASE, .misc_reg = PLLD_MISC0, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLD_MISC_LOCK_ENABLE, .lock_delay = 1000, .iddq_reg = PLLD_MISC0, .iddq_bit_idx = PLLD_IDDQ_BIT, @@ -1850,7 +1843,7 @@ static struct tegra_clk_pll_params pll_d_params = { .ext_misc_reg[0] = PLLD_MISC0, .ext_misc_reg[1] = PLLD_MISC1, .freq_table = pll_d_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .mdiv_default = 1, .set_defaults = tegra210_plld_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, @@ -1876,7 +1869,6 @@ static struct tegra_clk_pll_params pll_d2_params = { .base_reg = PLLD2_BASE, .misc_reg = PLLD2_MISC0, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE, .lock_delay = 300, .iddq_reg = PLLD2_BASE, .iddq_bit_idx = PLLSS_IDDQ_BIT, @@ -1897,7 +1889,7 @@ static struct tegra_clk_pll_params pll_d2_params = { .mdiv_default = 1, .freq_table = tegra210_pll_d2_freq_table, .set_defaults = tegra210_plld2_set_defaults, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .calc_rate = tegra210_pll_fixed_mdiv_cfg, .set_gain = tegra210_clk_pll_set_gain, .adjust_vco = tegra210_clk_adjust_vco_min, @@ -1920,7 +1912,6 @@ static struct tegra_clk_pll_params pll_dp_params = { .base_reg = PLLDP_BASE, .misc_reg = PLLDP_MISC, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE, .lock_delay = 300, .iddq_reg = PLLDP_BASE, .iddq_bit_idx = PLLSS_IDDQ_BIT, @@ -1941,7 +1932,7 @@ static struct tegra_clk_pll_params pll_dp_params = { .mdiv_default = 1, .freq_table = pll_dp_freq_table, .set_defaults = tegra210_plldp_set_defaults, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .calc_rate = tegra210_pll_fixed_mdiv_cfg, .set_gain = tegra210_clk_pll_set_gain, .adjust_vco = tegra210_clk_adjust_vco_min, @@ -1973,7 +1964,6 @@ static struct tegra_clk_pll_params pll_u_vco_params = { .base_reg = PLLU_BASE, .misc_reg = PLLU_MISC0, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLU_MISC_LOCK_ENABLE, .lock_delay = 1000, .iddq_reg = PLLU_MISC0, .iddq_bit_idx = PLLU_IDDQ_BIT, @@ -1983,8 +1973,7 @@ static struct tegra_clk_pll_params pll_u_vco_params = { .pdiv_tohw = pll_qlin_pdiv_to_hw, .div_nmp = &pllu_nmp, .freq_table = pll_u_freq_table, - .flags = TEGRA_PLLU | TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE | - TEGRA_PLL_VCO_OUT, + .flags = TEGRA_PLLU | TEGRA_PLL_USE_LOCK | TEGRA_PLL_VCO_OUT, .set_defaults = tegra210_pllu_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -2218,6 +2207,7 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = { [tegra_clk_pll_c4_out1] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT1, .present = true }, [tegra_clk_pll_c4_out2] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT2, .present = true }, [tegra_clk_pll_c4_out3] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT3, .present = true }, + [tegra_clk_apb2ape] = { .dt_id = TEGRA210_CLK_APB2APE, .present = true }, }; static struct tegra_devclk devclks[] __initdata = { @@ -2519,7 +2509,7 @@ static void __init tegra210_pll_init(void __iomem *clk_base, /* PLLU_VCO */ val = readl(clk_base + pll_u_vco_params.base_reg); - val &= ~BIT(24); /* disable PLLU_OVERRIDE */ + val &= ~PLLU_BASE_OVERRIDE; /* disable PLLU_OVERRIDE */ writel(val, clk_base + pll_u_vco_params.base_reg); clk = tegra_clk_register_pllre("pll_u_vco", "pll_ref", clk_base, pmc, @@ -2738,8 +2728,6 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA210_CLK_DFLL_REF, TEGRA210_CLK_PLL_P, 51000000, 1 }, { TEGRA210_CLK_SBC4, TEGRA210_CLK_PLL_P, 12000000, 1 }, { TEGRA210_CLK_PLL_RE_VCO, TEGRA210_CLK_CLK_MAX, 672000000, 1 }, - { TEGRA210_CLK_PLL_U_OUT1, TEGRA210_CLK_CLK_MAX, 48000000, 1 }, - { TEGRA210_CLK_PLL_U_OUT2, TEGRA210_CLK_CLK_MAX, 60000000, 1 }, { TEGRA210_CLK_XUSB_GATE, TEGRA210_CLK_CLK_MAX, 0, 1 }, { TEGRA210_CLK_XUSB_SS_SRC, TEGRA210_CLK_PLL_U_480M, 120000000, 0 }, { TEGRA210_CLK_XUSB_FS_SRC, TEGRA210_CLK_PLL_U_48M, 48000000, 0 }, diff --git a/drivers/clk/ti/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c index 1c300388782b..cc739291a3ce 100644 --- a/drivers/clk/ti/dpll3xxx.c +++ b/drivers/clk/ti/dpll3xxx.c @@ -460,7 +460,8 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw) parent = clk_hw_get_parent(hw); - if (clk_hw_get_rate(hw) == clk_get_rate(dd->clk_bypass)) { + if (clk_hw_get_rate(hw) == + clk_hw_get_rate(__clk_get_hw(dd->clk_bypass))) { WARN_ON(parent != __clk_get_hw(dd->clk_bypass)); r = _omap3_noncore_dpll_bypass(clk); } else { diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index e62f8cb2c9b5..3bca438ecd19 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c @@ -78,6 +78,9 @@ static int vco_set(struct clk_icst *icst, struct icst_vco vco) ret = regmap_read(icst->map, icst->vcoreg_off, &val); if (ret) return ret; + + /* Mask the 18 bits used by the VCO */ + val &= ~0x7ffff; val |= vco.v | (vco.r << 9) | (vco.s << 16); /* This magic unlocks the VCO so it can be controlled */ diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 659879a56dba..f93511031177 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -296,6 +296,7 @@ endif config QORIQ_CPUFREQ tristate "CPU frequency scaling driver for Freescale QorIQ SoCs" depends on OF && COMMON_CLK && (PPC_E500MC || ARM) + depends on !CPU_THERMAL || THERMAL select CLK_QORIQ help This adds the CPUFreq driver support for Freescale QorIQ SoCs diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 0031069b64c9..14b1f9393b05 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -84,10 +84,10 @@ config ARM_KIRKWOOD_CPUFREQ SoCs. config ARM_MT8173_CPUFREQ - bool "Mediatek MT8173 CPUFreq support" + tristate "Mediatek MT8173 CPUFreq support" depends on ARCH_MEDIATEK && REGULATOR depends on ARM64 || (ARM_CPU_TOPOLOGY && COMPILE_TEST) - depends on !CPU_THERMAL || THERMAL=y + depends on !CPU_THERMAL || THERMAL select PM_OPP help This adds the CPUFreq driver support for Mediatek MT8173 SoC. diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c index 1efba340456d..2058e6d292ce 100644 --- a/drivers/cpufreq/mt8173-cpufreq.c +++ b/drivers/cpufreq/mt8173-cpufreq.c @@ -17,6 +17,7 @@ #include <linux/cpu_cooling.h> #include <linux/cpufreq.h> #include <linux/cpumask.h> +#include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_opp.h> diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index 848b93ee930f..fe9dce0245bf 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c @@ -500,6 +500,8 @@ static int tegra_devfreq_target(struct device *dev, unsigned long *freq, clk_set_min_rate(tegra->emc_clock, rate); clk_set_rate(tegra->emc_clock, 0); + *freq = rate; + return 0; } diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index e893318560db..5ad0ec1f0e29 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -156,7 +156,6 @@ static void dwc_initialize(struct dw_dma_chan *dwc) /* Enable interrupts */ channel_set_bit(dw, MASK.XFER, dwc->mask); - channel_set_bit(dw, MASK.BLOCK, dwc->mask); channel_set_bit(dw, MASK.ERROR, dwc->mask); dwc->initialized = true; @@ -588,6 +587,9 @@ static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc, spin_unlock_irqrestore(&dwc->lock, flags); } + + /* Re-enable interrupts */ + channel_set_bit(dw, MASK.BLOCK, dwc->mask); } /* ------------------------------------------------------------------------- */ @@ -618,11 +620,8 @@ static void dw_dma_tasklet(unsigned long data) dwc_scan_descriptors(dw, dwc); } - /* - * Re-enable interrupts. - */ + /* Re-enable interrupts */ channel_set_bit(dw, MASK.XFER, dw->all_chan_mask); - channel_set_bit(dw, MASK.BLOCK, dw->all_chan_mask); channel_set_bit(dw, MASK.ERROR, dw->all_chan_mask); } @@ -1261,6 +1260,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan) int dw_dma_cyclic_start(struct dma_chan *chan) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + struct dw_dma *dw = to_dw_dma(chan->device); unsigned long flags; if (!test_bit(DW_DMA_IS_CYCLIC, &dwc->flags)) { @@ -1269,7 +1269,12 @@ int dw_dma_cyclic_start(struct dma_chan *chan) } spin_lock_irqsave(&dwc->lock, flags); + + /* Enable interrupts to perform cyclic transfer */ + channel_set_bit(dw, MASK.BLOCK, dwc->mask); + dwc_dostart(dwc, dwc->cdesc->desc[0]); + spin_unlock_irqrestore(&dwc->lock, flags); return 0; diff --git a/drivers/dma/dw/pci.c b/drivers/dma/dw/pci.c index 4c30fdd092b3..358f9689a3f5 100644 --- a/drivers/dma/dw/pci.c +++ b/drivers/dma/dw/pci.c @@ -108,6 +108,10 @@ static const struct pci_device_id dw_pci_id_table[] = { /* Haswell */ { PCI_VDEVICE(INTEL, 0x9c60) }, + + /* Broadwell */ + { PCI_VDEVICE(INTEL, 0x9ce0) }, + { } }; MODULE_DEVICE_TABLE(pci, dw_pci_id_table); diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c index d92d65549406..e3d7fcb69b4c 100644 --- a/drivers/dma/edma.c +++ b/drivers/dma/edma.c @@ -113,6 +113,9 @@ #define GET_NUM_REGN(x) ((x & 0x300000) >> 20) /* bits 20-21 */ #define CHMAP_EXIST BIT(24) +/* CCSTAT register */ +#define EDMA_CCSTAT_ACTV BIT(4) + /* * Max of 20 segments per channel to conserve PaRAM slots * Also note that MAX_NR_SG should be atleast the no.of periods @@ -1680,9 +1683,20 @@ static void edma_issue_pending(struct dma_chan *chan) spin_unlock_irqrestore(&echan->vchan.lock, flags); } +/* + * This limit exists to avoid a possible infinite loop when waiting for proof + * that a particular transfer is completed. This limit can be hit if there + * are large bursts to/from slow devices or the CPU is never able to catch + * the DMA hardware idle. On an AM335x transfering 48 bytes from the UART + * RX-FIFO, as many as 55 loops have been seen. + */ +#define EDMA_MAX_TR_WAIT_LOOPS 1000 + static u32 edma_residue(struct edma_desc *edesc) { bool dst = edesc->direction == DMA_DEV_TO_MEM; + int loop_count = EDMA_MAX_TR_WAIT_LOOPS; + struct edma_chan *echan = edesc->echan; struct edma_pset *pset = edesc->pset; dma_addr_t done, pos; int i; @@ -1691,7 +1705,32 @@ static u32 edma_residue(struct edma_desc *edesc) * We always read the dst/src position from the first RamPar * pset. That's the one which is active now. */ - pos = edma_get_position(edesc->echan->ecc, edesc->echan->slot[0], dst); + pos = edma_get_position(echan->ecc, echan->slot[0], dst); + + /* + * "pos" may represent a transfer request that is still being + * processed by the EDMACC or EDMATC. We will busy wait until + * any one of the situations occurs: + * 1. the DMA hardware is idle + * 2. a new transfer request is setup + * 3. we hit the loop limit + */ + while (edma_read(echan->ecc, EDMA_CCSTAT) & EDMA_CCSTAT_ACTV) { + /* check if a new transfer request is setup */ + if (edma_get_position(echan->ecc, + echan->slot[0], dst) != pos) { + break; + } + + if (!--loop_count) { + dev_dbg_ratelimited(echan->vchan.chan.device->dev, + "%s: timeout waiting for PaRAM update\n", + __func__); + break; + } + + cpu_relax(); + } /* * Cyclic is simple. Just subtract pset[0].addr from pos. diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index 1d5df2ef148b..21539d5c54c3 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -861,32 +861,42 @@ void ioat_timer_event(unsigned long data) return; } + spin_lock_bh(&ioat_chan->cleanup_lock); + + /* handle the no-actives case */ + if (!ioat_ring_active(ioat_chan)) { + spin_lock_bh(&ioat_chan->prep_lock); + check_active(ioat_chan); + spin_unlock_bh(&ioat_chan->prep_lock); + spin_unlock_bh(&ioat_chan->cleanup_lock); + return; + } + /* if we haven't made progress and we have already * acknowledged a pending completion once, then be more * forceful with a restart */ - spin_lock_bh(&ioat_chan->cleanup_lock); if (ioat_cleanup_preamble(ioat_chan, &phys_complete)) __cleanup(ioat_chan, phys_complete); else if (test_bit(IOAT_COMPLETION_ACK, &ioat_chan->state)) { + u32 chanerr; + + chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET); + dev_warn(to_dev(ioat_chan), "Restarting channel...\n"); + dev_warn(to_dev(ioat_chan), "CHANSTS: %#Lx CHANERR: %#x\n", + status, chanerr); + dev_warn(to_dev(ioat_chan), "Active descriptors: %d\n", + ioat_ring_active(ioat_chan)); + spin_lock_bh(&ioat_chan->prep_lock); ioat_restart_channel(ioat_chan); spin_unlock_bh(&ioat_chan->prep_lock); spin_unlock_bh(&ioat_chan->cleanup_lock); return; - } else { + } else set_bit(IOAT_COMPLETION_ACK, &ioat_chan->state); - mod_timer(&ioat_chan->timer, jiffies + COMPLETION_TIMEOUT); - } - - if (ioat_ring_active(ioat_chan)) - mod_timer(&ioat_chan->timer, jiffies + COMPLETION_TIMEOUT); - else { - spin_lock_bh(&ioat_chan->prep_lock); - check_active(ioat_chan); - spin_unlock_bh(&ioat_chan->prep_lock); - } + mod_timer(&ioat_chan->timer, jiffies + COMPLETION_TIMEOUT); spin_unlock_bh(&ioat_chan->cleanup_lock); } diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c index f2a0310ae771..debca824bed6 100644 --- a/drivers/dma/pxa_dma.c +++ b/drivers/dma/pxa_dma.c @@ -583,6 +583,8 @@ static void set_updater_desc(struct pxad_desc_sw *sw_desc, (PXA_DCMD_LENGTH & sizeof(u32)); if (flags & DMA_PREP_INTERRUPT) updater->dcmd |= PXA_DCMD_ENDIRQEN; + if (sw_desc->cyclic) + sw_desc->hw_desc[sw_desc->nb_desc - 2]->ddadr = sw_desc->first; } static bool is_desc_completed(struct virt_dma_desc *vd) @@ -673,6 +675,10 @@ static irqreturn_t pxad_chan_handler(int irq, void *dev_id) dev_dbg(&chan->vc.chan.dev->device, "%s(): checking txd %p[%x]: completed=%d\n", __func__, vd, vd->tx.cookie, is_desc_completed(vd)); + if (to_pxad_sw_desc(vd)->cyclic) { + vchan_cyclic_callback(vd); + break; + } if (is_desc_completed(vd)) { list_del(&vd->node); vchan_cookie_complete(vd); @@ -1080,7 +1086,7 @@ pxad_prep_dma_cyclic(struct dma_chan *dchan, return NULL; pxad_get_config(chan, dir, &dcmd, &dsadr, &dtadr); - dcmd |= PXA_DCMD_ENDIRQEN | (PXA_DCMD_LENGTH | period_len); + dcmd |= PXA_DCMD_ENDIRQEN | (PXA_DCMD_LENGTH & period_len); dev_dbg(&chan->vc.chan.dev->device, "%s(): buf_addr=0x%lx len=%zu period=%zu dir=%d flags=%lx\n", __func__, (unsigned long)buf_addr, len, period_len, dir, flags); diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index cf41440aff91..d9ab0cd1d205 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -196,6 +196,44 @@ static int gpio_rcar_irq_set_wake(struct irq_data *d, unsigned int on) return 0; } +static void gpio_rcar_irq_bus_lock(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct gpio_rcar_priv *p = gpiochip_get_data(gc); + + pm_runtime_get_sync(&p->pdev->dev); +} + +static void gpio_rcar_irq_bus_sync_unlock(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct gpio_rcar_priv *p = gpiochip_get_data(gc); + + pm_runtime_put(&p->pdev->dev); +} + + +static int gpio_rcar_irq_request_resources(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct gpio_rcar_priv *p = gpiochip_get_data(gc); + int error; + + error = pm_runtime_get_sync(&p->pdev->dev); + if (error < 0) + return error; + + return 0; +} + +static void gpio_rcar_irq_release_resources(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct gpio_rcar_priv *p = gpiochip_get_data(gc); + + pm_runtime_put(&p->pdev->dev); +} + static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) { struct gpio_rcar_priv *p = dev_id; @@ -450,6 +488,10 @@ static int gpio_rcar_probe(struct platform_device *pdev) irq_chip->irq_unmask = gpio_rcar_irq_enable; irq_chip->irq_set_type = gpio_rcar_irq_set_type; irq_chip->irq_set_wake = gpio_rcar_irq_set_wake; + irq_chip->irq_bus_lock = gpio_rcar_irq_bus_lock; + irq_chip->irq_bus_sync_unlock = gpio_rcar_irq_bus_sync_unlock; + irq_chip->irq_request_resources = gpio_rcar_irq_request_resources; + irq_chip->irq_release_resources = gpio_rcar_irq_release_resources; irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND; ret = gpiochip_add_data(gpio_chip, p); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 89c3dd62ba21..119cdc2c43e7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -77,7 +77,7 @@ void amdgpu_connector_hotplug(struct drm_connector *connector) } else if (amdgpu_atombios_dp_needs_link_train(amdgpu_connector)) { /* Don't try to start link training before we * have the dpcd */ - if (!amdgpu_atombios_dp_get_dpcd(amdgpu_connector)) + if (amdgpu_atombios_dp_get_dpcd(amdgpu_connector)) return; /* set it to OFF so that drm_helper_connector_dpms() diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index acd066d0a805..8297bc319369 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -72,8 +72,8 @@ static void amdgpu_flip_work_func(struct work_struct *__work) struct drm_crtc *crtc = &amdgpuCrtc->base; unsigned long flags; - unsigned i; - int vpos, hpos, stat, min_udelay; + unsigned i, repcnt = 4; + int vpos, hpos, stat, min_udelay = 0; struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id]; amdgpu_flip_wait_fence(adev, &work->excl); @@ -96,7 +96,7 @@ static void amdgpu_flip_work_func(struct work_struct *__work) * In practice this won't execute very often unless on very fast * machines because the time window for this to happen is very small. */ - for (;;) { + while (amdgpuCrtc->enabled && repcnt--) { /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank * start in hpos, and to the "fudged earlier" vblank start in * vpos. @@ -114,10 +114,22 @@ static void amdgpu_flip_work_func(struct work_struct *__work) /* Sleep at least until estimated real start of hw vblank */ spin_unlock_irqrestore(&crtc->dev->event_lock, flags); min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5); + if (min_udelay > vblank->framedur_ns / 2000) { + /* Don't wait ridiculously long - something is wrong */ + repcnt = 0; + break; + } usleep_range(min_udelay, 2 * min_udelay); spin_lock_irqsave(&crtc->dev->event_lock, flags); }; + if (!repcnt) + DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, " + "framedur %d, linedur %d, stat %d, vpos %d, " + "hpos %d\n", work->crtc_id, min_udelay, + vblank->framedur_ns / 1000, + vblank->linedur_ns / 1000, stat, vpos, hpos); + /* do the flip (mmio) */ adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base); /* set the flip status */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 7380f782cd14..d20c2a8929cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -596,7 +596,8 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, break; } ttm_eu_backoff_reservation(&ticket, &list); - if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE)) + if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) && + !amdgpu_vm_debug) amdgpu_gem_va_update_vm(adev, bo_va, args->operation); drm_gem_object_unreference_unlocked(gobj); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 7d8d84eaea4a..95a4a25d8df9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -113,6 +113,10 @@ static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; + if ((adev->flags & AMD_IS_PX) && + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) + return snprintf(buf, PAGE_SIZE, "off\n"); + if (adev->pp_enabled) { enum amd_dpm_forced_level level; @@ -140,6 +144,11 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, enum amdgpu_dpm_forced_level level; int ret = 0; + /* Can't force performance level when the card is off */ + if ((adev->flags & AMD_IS_PX) && + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) + return -EINVAL; + if (strncmp("low", buf, strlen("low")) == 0) { level = AMDGPU_DPM_FORCED_LEVEL_LOW; } else if (strncmp("high", buf, strlen("high")) == 0) { @@ -157,6 +166,7 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, mutex_lock(&adev->pm.mutex); if (adev->pm.dpm.thermal_active) { count = -EINVAL; + mutex_unlock(&adev->pm.mutex); goto fail; } ret = amdgpu_dpm_force_performance_level(adev, level); @@ -167,8 +177,6 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, mutex_unlock(&adev->pm.mutex); } fail: - mutex_unlock(&adev->pm.mutex); - return count; } @@ -182,8 +190,14 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, char *buf) { struct amdgpu_device *adev = dev_get_drvdata(dev); + struct drm_device *ddev = adev->ddev; int temp; + /* Can't get temperature when the card is off */ + if ((adev->flags & AMD_IS_PX) && + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) + return -EINVAL; + if (!adev->pp_enabled && !adev->pm.funcs->get_temperature) temp = 0; else @@ -634,11 +648,6 @@ force: /* update display watermarks based on new power state */ amdgpu_display_bandwidth_update(adev); - /* update displays */ - amdgpu_dpm_display_configuration_changed(adev); - - adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; - adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; /* wait for the rings to drain */ for (i = 0; i < AMDGPU_MAX_RINGS; i++) { @@ -655,6 +664,12 @@ force: amdgpu_dpm_post_set_power_state(adev); + /* update displays */ + amdgpu_dpm_display_configuration_changed(adev); + + adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; + adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; + if (adev->pm.funcs->force_performance_level) { if (adev->pm.dpm.thermal_active) { enum amdgpu_dpm_forced_level level = adev->pm.dpm.forced_level; @@ -847,12 +862,16 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; struct amdgpu_device *adev = dev->dev_private; + struct drm_device *ddev = adev->ddev; if (!adev->pm.dpm_enabled) { seq_printf(m, "dpm not enabled\n"); return 0; } - if (adev->pp_enabled) { + if ((adev->flags & AMD_IS_PX) && + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) { + seq_printf(m, "PX asic powered off\n"); + } else if (adev->pp_enabled) { amdgpu_dpm_debugfs_print_current_performance_level(adev, m); } else { mutex_lock(&adev->pm.mutex); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c index b9d0d55f6b47..3cb6d6c413c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c @@ -143,8 +143,10 @@ static int amdgpu_pp_late_init(void *handle) adev->powerplay.pp_handle); #ifdef CONFIG_DRM_AMD_POWERPLAY - if (adev->pp_enabled) + if (adev->pp_enabled) { amdgpu_pm_sysfs_init(adev); + amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_COMPLETE_INIT, NULL, NULL); + } #endif return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 6442a06d6fdc..1cbb16e15307 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -712,7 +712,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm) 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); if (pci_dma_mapping_error(adev->pdev, gtt->ttm.dma_address[i])) { - while (--i) { + while (i--) { pci_unmap_page(adev->pdev, gtt->ttm.dma_address[i], PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); gtt->ttm.dma_address[i] = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c index 9056355309d1..e7ef2261ff4a 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c @@ -2202,8 +2202,7 @@ static void cz_dpm_powergate_vce(struct amdgpu_device *adev, bool gate) AMD_PG_STATE_GATE); cz_enable_vce_dpm(adev, false); - /* TODO: to figure out why vce can't be poweroff. */ - /* cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerOFF); */ + cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerOFF); pi->vce_power_gated = true; } else { cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerON); @@ -2226,10 +2225,8 @@ static void cz_dpm_powergate_vce(struct amdgpu_device *adev, bool gate) } } else { /*pi->caps_vce_pg*/ cz_update_vce_dpm(adev); - cz_enable_vce_dpm(adev, true); + cz_enable_vce_dpm(adev, !gate); } - - return; } const struct amd_ip_funcs cz_dpm_ip_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 7732059ae30f..06602df707f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -3628,6 +3628,19 @@ static void gfx_v7_0_ring_emit_vm_flush(struct amdgpu_ring *ring, unsigned vm_id, uint64_t pd_addr) { int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX); + uint32_t seq = ring->fence_drv.sync_seq; + uint64_t addr = ring->fence_drv.gpu_addr; + + amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5)); + amdgpu_ring_write(ring, (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */ + WAIT_REG_MEM_FUNCTION(3) | /* equal */ + WAIT_REG_MEM_ENGINE(usepfp))); /* pfp or me */ + amdgpu_ring_write(ring, addr & 0xfffffffc); + amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff); + amdgpu_ring_write(ring, seq); + amdgpu_ring_write(ring, 0xffffffff); + amdgpu_ring_write(ring, 4); /* poll interval */ + if (usepfp) { /* synce CE with ME to prevent CE fetch CEIB before context switch done */ amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 8f8ec37ecd88..7086ac17abee 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -4809,7 +4809,8 @@ static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring, amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5)); amdgpu_ring_write(ring, (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */ - WAIT_REG_MEM_FUNCTION(3))); /* equal */ + WAIT_REG_MEM_FUNCTION(3) | /* equal */ + WAIT_REG_MEM_ENGINE(usepfp))); /* pfp or me */ amdgpu_ring_write(ring, addr & 0xfffffffc); amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff); amdgpu_ring_write(ring, seq); @@ -4995,7 +4996,7 @@ static int gfx_v8_0_set_priv_reg_fault_state(struct amdgpu_device *adev, case AMDGPU_IRQ_STATE_ENABLE: cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0); cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0, - PRIV_REG_INT_ENABLE, 0); + PRIV_REG_INT_ENABLE, 1); WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl); break; default: diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index aa67244a77ae..589599f66fcc 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -402,8 +402,11 @@ int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input, data.requested_ui_label = power_state_convert(ps); ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); + break; } - break; + case AMD_PP_EVENT_COMPLETE_INIT: + ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); + break; default: break; } diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c index 83be3cf210e0..6b52c78cb404 100644 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c @@ -165,6 +165,7 @@ const struct action_chain resume_action_chain = { }; static const pem_event_action *complete_init_event[] = { + unblock_adjust_power_state_tasks, adjust_power_state_tasks, enable_gfx_clock_gating_tasks, enable_gfx_voltage_island_power_gating_tasks, diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c index 52a3efc97f05..46410e3c7349 100644 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c @@ -31,7 +31,7 @@ static int pem_init(struct pp_eventmgr *eventmgr) { int result = 0; - struct pem_event_data event_data; + struct pem_event_data event_data = { {0} }; /* Initialize PowerPlay feature info */ pem_init_feature_info(eventmgr); @@ -52,7 +52,7 @@ static int pem_init(struct pp_eventmgr *eventmgr) static void pem_fini(struct pp_eventmgr *eventmgr) { - struct pem_event_data event_data; + struct pem_event_data event_data = { {0} }; pem_uninit_featureInfo(eventmgr); pem_unregister_interrupts(eventmgr); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c index ad7700822a1c..ff08ce41bde9 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c @@ -226,7 +226,7 @@ int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) } } else { cz_dpm_update_vce_dpm(hwmgr); - cz_enable_disable_vce_dpm(hwmgr, true); + cz_enable_disable_vce_dpm(hwmgr, !bgate); return 0; } diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 9759009d1da3..b1480acbb3c3 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -227,7 +227,7 @@ static int ast_get_dram_info(struct drm_device *dev) } while (ast_read32(ast, 0x10000) != 0x01); data = ast_read32(ast, 0x10004); - if (data & 0x400) + if (data & 0x40) ast->dram_bus_width = 16; else ast->dram_bus_width = 32; diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 3f74193885f1..9a7b44616b55 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -65,8 +65,6 @@ drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state) */ state->allow_modeset = true; - state->num_connector = ACCESS_ONCE(dev->mode_config.num_connector); - state->crtcs = kcalloc(dev->mode_config.num_crtc, sizeof(*state->crtcs), GFP_KERNEL); if (!state->crtcs) @@ -83,16 +81,6 @@ drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state) sizeof(*state->plane_states), GFP_KERNEL); if (!state->plane_states) goto fail; - state->connectors = kcalloc(state->num_connector, - sizeof(*state->connectors), - GFP_KERNEL); - if (!state->connectors) - goto fail; - state->connector_states = kcalloc(state->num_connector, - sizeof(*state->connector_states), - GFP_KERNEL); - if (!state->connector_states) - goto fail; state->dev = dev; @@ -823,19 +811,27 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, index = drm_connector_index(connector); - /* - * Construction of atomic state updates can race with a connector - * hot-add which might overflow. In this case flip the table and just - * restart the entire ioctl - no one is fast enough to livelock a cpu - * with physical hotplug events anyway. - * - * Note that we only grab the indexes once we have the right lock to - * prevent hotplug/unplugging of connectors. So removal is no problem, - * at most the array is a bit too large. - */ if (index >= state->num_connector) { - DRM_DEBUG_ATOMIC("Hot-added connector would overflow state array, restarting\n"); - return ERR_PTR(-EAGAIN); + struct drm_connector **c; + struct drm_connector_state **cs; + int alloc = max(index + 1, config->num_connector); + + c = krealloc(state->connectors, alloc * sizeof(*state->connectors), GFP_KERNEL); + if (!c) + return ERR_PTR(-ENOMEM); + + state->connectors = c; + memset(&state->connectors[state->num_connector], 0, + sizeof(*state->connectors) * (alloc - state->num_connector)); + + cs = krealloc(state->connector_states, alloc * sizeof(*state->connector_states), GFP_KERNEL); + if (!cs) + return ERR_PTR(-ENOMEM); + + state->connector_states = cs; + memset(&state->connector_states[state->num_connector], 0, + sizeof(*state->connector_states) * (alloc - state->num_connector)); + state->num_connector = alloc; } if (state->connector_states[index]) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 7c523060a076..4f2d3e161593 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1493,7 +1493,7 @@ void drm_atomic_helper_swap_state(struct drm_device *dev, { int i; - for (i = 0; i < dev->mode_config.num_connector; i++) { + for (i = 0; i < state->num_connector; i++) { struct drm_connector *connector = state->connectors[i]; if (!connector) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index d40bab29747e..f6191215b2cb 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -918,12 +918,19 @@ int drm_connector_init(struct drm_device *dev, connector->base.properties = &connector->properties; connector->dev = dev; connector->funcs = funcs; + + connector->connector_id = ida_simple_get(&config->connector_ida, 0, 0, GFP_KERNEL); + if (connector->connector_id < 0) { + ret = connector->connector_id; + goto out_put; + } + connector->connector_type = connector_type; connector->connector_type_id = ida_simple_get(connector_ida, 1, 0, GFP_KERNEL); if (connector->connector_type_id < 0) { ret = connector->connector_type_id; - goto out_put; + goto out_put_id; } connector->name = kasprintf(GFP_KERNEL, "%s-%d", @@ -931,7 +938,7 @@ int drm_connector_init(struct drm_device *dev, connector->connector_type_id); if (!connector->name) { ret = -ENOMEM; - goto out_put; + goto out_put_type_id; } INIT_LIST_HEAD(&connector->probed_modes); @@ -959,7 +966,12 @@ int drm_connector_init(struct drm_device *dev, } connector->debugfs_entry = NULL; - +out_put_type_id: + if (ret) + ida_remove(connector_ida, connector->connector_type_id); +out_put_id: + if (ret) + ida_remove(&config->connector_ida, connector->connector_id); out_put: if (ret) drm_mode_object_put(dev, &connector->base); @@ -996,6 +1008,9 @@ void drm_connector_cleanup(struct drm_connector *connector) ida_remove(&drm_connector_enum_list[connector->connector_type].ida, connector->connector_type_id); + ida_remove(&dev->mode_config.connector_ida, + connector->connector_id); + kfree(connector->display_info.bus_formats); drm_mode_object_put(dev, &connector->base); kfree(connector->name); @@ -1013,32 +1028,6 @@ void drm_connector_cleanup(struct drm_connector *connector) EXPORT_SYMBOL(drm_connector_cleanup); /** - * drm_connector_index - find the index of a registered connector - * @connector: connector to find index for - * - * Given a registered connector, return the index of that connector within a DRM - * device's list of connectors. - */ -unsigned int drm_connector_index(struct drm_connector *connector) -{ - unsigned int index = 0; - struct drm_connector *tmp; - struct drm_mode_config *config = &connector->dev->mode_config; - - WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); - - drm_for_each_connector(tmp, connector->dev) { - if (tmp == connector) - return index; - - index++; - } - - BUG(); -} -EXPORT_SYMBOL(drm_connector_index); - -/** * drm_connector_register - register a connector * @connector: the connector to register * @@ -5789,6 +5778,7 @@ void drm_mode_config_init(struct drm_device *dev) INIT_LIST_HEAD(&dev->mode_config.plane_list); idr_init(&dev->mode_config.crtc_idr); idr_init(&dev->mode_config.tile_idr); + ida_init(&dev->mode_config.connector_ida); drm_modeset_lock_all(dev); drm_mode_create_standard_properties(dev); @@ -5869,6 +5859,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) crtc->funcs->destroy(crtc); } + ida_destroy(&dev->mode_config.connector_ida); idr_destroy(&dev->mode_config.tile_idr); idr_destroy(&dev->mode_config.crtc_idr); drm_modeset_lock_fini(&dev->mode_config.connection_mutex); diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 8ae13de272c4..27fbd79d0daf 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1159,11 +1159,13 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, drm_dp_put_port(port); goto out; } - - drm_mode_connector_set_tile_property(port->connector); - + if (port->port_num >= DP_MST_LOGICAL_PORT_0) { + port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc); + drm_mode_connector_set_tile_property(port->connector); + } (*mstb->mgr->cbs->register_connector)(port->connector); } + out: /* put reference to this port */ drm_dp_put_port(port); @@ -1188,8 +1190,8 @@ static void drm_dp_update_port(struct drm_dp_mst_branch *mstb, port->ddps = conn_stat->displayport_device_plug_status; if (old_ddps != port->ddps) { - dowork = true; if (port->ddps) { + dowork = true; } else { port->available_pbn = 0; } @@ -1294,13 +1296,8 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m if (port->input) continue; - if (!port->ddps) { - if (port->cached_edid) { - kfree(port->cached_edid); - port->cached_edid = NULL; - } + if (!port->ddps) continue; - } if (!port->available_pbn) drm_dp_send_enum_path_resources(mgr, mstb, port); @@ -1311,12 +1308,6 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m drm_dp_check_and_send_link_address(mgr, mstb_child); drm_dp_put_mst_branch_device(mstb_child); } - } else if (port->pdt == DP_PEER_DEVICE_SST_SINK || - port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV) { - if (!port->cached_edid) { - port->cached_edid = - drm_get_edid(port->connector, &port->aux.ddc); - } } } } @@ -1336,8 +1327,6 @@ static void drm_dp_mst_link_probe_work(struct work_struct *work) drm_dp_check_and_send_link_address(mgr, mstb); drm_dp_put_mst_branch_device(mstb); } - - (*mgr->cbs->hotplug)(mgr); } static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr, @@ -1597,6 +1586,7 @@ static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr, for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) { drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]); } + (*mgr->cbs->hotplug)(mgr); } } else { mstb->link_address_sent = false; @@ -2293,6 +2283,8 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) drm_dp_update_port(mstb, &msg.u.conn_stat); DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type); + (*mgr->cbs->hotplug)(mgr); + } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) { drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false); if (!mstb) @@ -2379,6 +2371,10 @@ enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector case DP_PEER_DEVICE_SST_SINK: status = connector_status_connected; + /* for logical ports - cache the EDID */ + if (port->port_num >= 8 && !port->cached_edid) { + port->cached_edid = drm_get_edid(connector, &port->aux.ddc); + } break; case DP_PEER_DEVICE_DP_LEGACY_CONV: if (port->ldps) @@ -2433,7 +2429,10 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_ if (port->cached_edid) edid = drm_edid_duplicate(port->cached_edid); - + else { + edid = drm_get_edid(connector, &port->aux.ddc); + drm_mode_connector_set_tile_property(connector); + } port->has_audio = drm_detect_monitor_audio(edid); drm_dp_put_port(port); return edid; diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index d12a4efa651b..1fe14579e8c9 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -224,6 +224,64 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, diff = (flags & DRM_CALLED_FROM_VBLIRQ) != 0; } + /* + * Within a drm_vblank_pre_modeset - drm_vblank_post_modeset + * interval? If so then vblank irqs keep running and it will likely + * happen that the hardware vblank counter is not trustworthy as it + * might reset at some point in that interval and vblank timestamps + * are not trustworthy either in that interval. Iow. this can result + * in a bogus diff >> 1 which must be avoided as it would cause + * random large forward jumps of the software vblank counter. + */ + if (diff > 1 && (vblank->inmodeset & 0x2)) { + DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u" + " due to pre-modeset.\n", pipe, diff); + diff = 1; + } + + /* + * FIMXE: Need to replace this hack with proper seqlocks. + * + * Restrict the bump of the software vblank counter to a safe maximum + * value of +1 whenever there is the possibility that concurrent readers + * of vblank timestamps could be active at the moment, as the current + * implementation of the timestamp caching and updating is not safe + * against concurrent readers for calls to store_vblank() with a bump + * of anything but +1. A bump != 1 would very likely return corrupted + * timestamps to userspace, because the same slot in the cache could + * be concurrently written by store_vblank() and read by one of those + * readers without the read-retry logic detecting the collision. + * + * Concurrent readers can exist when we are called from the + * drm_vblank_off() or drm_vblank_on() functions and other non-vblank- + * irq callers. However, all those calls to us are happening with the + * vbl_lock locked to prevent drm_vblank_get(), so the vblank refcount + * can't increase while we are executing. Therefore a zero refcount at + * this point is safe for arbitrary counter bumps if we are called + * outside vblank irq, a non-zero count is not 100% safe. Unfortunately + * we must also accept a refcount of 1, as whenever we are called from + * drm_vblank_get() -> drm_vblank_enable() the refcount will be 1 and + * we must let that one pass through in order to not lose vblank counts + * during vblank irq off - which would completely defeat the whole + * point of this routine. + * + * Whenever we are called from vblank irq, we have to assume concurrent + * readers exist or can show up any time during our execution, even if + * the refcount is currently zero, as vblank irqs are usually only + * enabled due to the presence of readers, and because when we are called + * from vblank irq we can't hold the vbl_lock to protect us from sudden + * bumps in vblank refcount. Therefore also restrict bumps to +1 when + * called from vblank irq. + */ + if ((diff > 1) && (atomic_read(&vblank->refcount) > 1 || + (flags & DRM_CALLED_FROM_VBLIRQ))) { + DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u " + "refcount %u, vblirq %u\n", pipe, diff, + atomic_read(&vblank->refcount), + (flags & DRM_CALLED_FROM_VBLIRQ) != 0); + diff = 1; + } + DRM_DEBUG_VBL("updating vblank count on crtc %u:" " current=%u, diff=%u, hw=%u hw_last=%u\n", pipe, vblank->count, diff, cur_vblank, vblank->last); @@ -1316,7 +1374,13 @@ void drm_vblank_off(struct drm_device *dev, unsigned int pipe) spin_lock_irqsave(&dev->event_lock, irqflags); spin_lock(&dev->vbl_lock); - vblank_disable_and_save(dev, pipe); + DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n", + pipe, vblank->enabled, vblank->inmodeset); + + /* Avoid redundant vblank disables without previous drm_vblank_on(). */ + if (drm_core_check_feature(dev, DRIVER_ATOMIC) || !vblank->inmodeset) + vblank_disable_and_save(dev, pipe); + wake_up(&vblank->queue); /* @@ -1418,6 +1482,9 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe) return; spin_lock_irqsave(&dev->vbl_lock, irqflags); + DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n", + pipe, vblank->enabled, vblank->inmodeset); + /* Drop our private "prevent drm_vblank_get" refcount */ if (vblank->inmodeset) { atomic_dec(&vblank->refcount); @@ -1430,8 +1497,7 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe) * re-enable interrupts if there are users left, or the * user wishes vblank interrupts to be enabled all the time. */ - if (atomic_read(&vblank->refcount) != 0 || - (!dev->vblank_disable_immediate && drm_vblank_offdelay == 0)) + if (atomic_read(&vblank->refcount) != 0 || drm_vblank_offdelay == 0) WARN_ON(drm_vblank_enable(dev, pipe)); spin_unlock_irqrestore(&dev->vbl_lock, irqflags); } @@ -1526,6 +1592,7 @@ void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe) if (vblank->inmodeset) { spin_lock_irqsave(&dev->vbl_lock, irqflags); dev->vblank_disable_allowed = true; + drm_reset_vblank_timestamp(dev, pipe); spin_unlock_irqrestore(&dev->vbl_lock, irqflags); if (vblank->inmodeset & 0x2) diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 83efca941388..f17d39279596 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -1,6 +1,6 @@ config DRM_EXYNOS tristate "DRM Support for Samsung SoC EXYNOS Series" - depends on OF && DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM) + depends on OF && DRM && (ARCH_S3C64XX || ARCH_EXYNOS || ARCH_MULTIPLATFORM) select DRM_KMS_HELPER select DRM_KMS_FB_HELPER select FB_CFB_FILLRECT diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 1bf6a21130c7..162ab93e99cb 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -93,7 +93,7 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc) if (test_bit(BIT_SUSPENDED, &ctx->flags)) return -EPERM; - if (test_and_set_bit(BIT_IRQS_ENABLED, &ctx->flags)) { + if (!test_and_set_bit(BIT_IRQS_ENABLED, &ctx->flags)) { val = VIDINTCON0_INTEN; if (ctx->out_type == IFTYPE_I80) val |= VIDINTCON0_FRAMEDONE; @@ -402,8 +402,6 @@ static void decon_enable(struct exynos_drm_crtc *crtc) decon_enable_vblank(ctx->crtc); decon_commit(ctx->crtc); - - set_bit(BIT_SUSPENDED, &ctx->flags); } static void decon_disable(struct exynos_drm_crtc *crtc) @@ -582,9 +580,9 @@ out: static int exynos5433_decon_suspend(struct device *dev) { struct decon_context *ctx = dev_get_drvdata(dev); - int i; + int i = ARRAY_SIZE(decon_clks_name); - for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) + while (--i >= 0) clk_disable_unprepare(ctx->clks[i]); return 0; diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index e977a81af2e6..26e81d191f56 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1782,6 +1782,7 @@ static int exynos_dsi_bind(struct device *dev, struct device *master, bridge = of_drm_find_bridge(dsi->bridge_node); if (bridge) { + encoder->bridge = bridge; drm_bridge_attach(drm_dev, bridge); } diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index f6118baa8e3e..8baabd813ff5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -50,7 +50,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info, if (vm_size > exynos_gem->size) return -EINVAL; - ret = dma_mmap_attrs(helper->dev->dev, vma, exynos_gem->pages, + ret = dma_mmap_attrs(helper->dev->dev, vma, exynos_gem->cookie, exynos_gem->dma_addr, exynos_gem->size, &exynos_gem->dma_attrs); if (ret < 0) { diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c index c747824f3c98..8a4f4a0211d0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c @@ -1723,7 +1723,7 @@ static int fimc_probe(struct platform_device *pdev) goto err_put_clk; } - DRM_DEBUG_KMS("id[%d]ippdrv[0x%x]\n", ctx->id, (int)ippdrv); + DRM_DEBUG_KMS("id[%d]ippdrv[%p]\n", ctx->id, ippdrv); spin_lock_init(&ctx->lock); platform_set_drvdata(pdev, ctx); diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index c17efdb238a6..8dfe6e113a88 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -1166,7 +1166,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, goto err_free_event; } - cmd = (struct drm_exynos_g2d_cmd *)(uint32_t)req->cmd; + cmd = (struct drm_exynos_g2d_cmd *)(unsigned long)req->cmd; if (copy_from_user(cmdlist->data + cmdlist->last, (void __user *)cmd, @@ -1184,7 +1184,8 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, if (req->cmd_buf_nr) { struct drm_exynos_g2d_cmd *cmd_buf; - cmd_buf = (struct drm_exynos_g2d_cmd *)(uint32_t)req->cmd_buf; + cmd_buf = (struct drm_exynos_g2d_cmd *) + (unsigned long)req->cmd_buf; if (copy_from_user(cmdlist->data + cmdlist->last, (void __user *)cmd_buf, diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 32358c5e3db4..26b5e4bd55b6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -218,7 +218,7 @@ static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev, return ERR_PTR(ret); } - DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp); + DRM_DEBUG_KMS("created file object = %p\n", obj->filp); return exynos_gem; } @@ -335,7 +335,7 @@ static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem, if (vm_size > exynos_gem->size) return -EINVAL; - ret = dma_mmap_attrs(drm_dev->dev, vma, exynos_gem->pages, + ret = dma_mmap_attrs(drm_dev->dev, vma, exynos_gem->cookie, exynos_gem->dma_addr, exynos_gem->size, &exynos_gem->dma_attrs); if (ret < 0) { diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c index 7aecd23cfa11..5d20da8f957e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c @@ -1723,7 +1723,7 @@ static int gsc_probe(struct platform_device *pdev) return ret; } - DRM_DEBUG_KMS("id[%d]ippdrv[0x%x]\n", ctx->id, (int)ippdrv); + DRM_DEBUG_KMS("id[%d]ippdrv[%p]\n", ctx->id, ippdrv); mutex_init(&ctx->lock); platform_set_drvdata(pdev, ctx); diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index 67d24236e745..95eeb9116f10 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -208,7 +208,7 @@ static struct exynos_drm_ippdrv *ipp_find_drv_by_handle(u32 prop_id) * e.g PAUSE state, queue buf, command control. */ list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) { - DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]\n", count++, (int)ippdrv); + DRM_DEBUG_KMS("count[%d]ippdrv[%p]\n", count++, ippdrv); mutex_lock(&ippdrv->cmd_lock); list_for_each_entry(c_node, &ippdrv->cmd_list, list) { @@ -388,8 +388,8 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data, } property->prop_id = ret; - DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[0x%x]\n", - property->prop_id, property->cmd, (int)ippdrv); + DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[%p]\n", + property->prop_id, property->cmd, ippdrv); /* stored property information and ippdrv in private data */ c_node->property = *property; @@ -518,7 +518,7 @@ static int ipp_put_mem_node(struct drm_device *drm_dev, { int i; - DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node); + DRM_DEBUG_KMS("node[%p]\n", m_node); if (!m_node) { DRM_ERROR("invalid dequeue node.\n"); @@ -562,7 +562,7 @@ static struct drm_exynos_ipp_mem_node m_node->buf_id = qbuf->buf_id; INIT_LIST_HEAD(&m_node->list); - DRM_DEBUG_KMS("m_node[0x%x]ops_id[%d]\n", (int)m_node, qbuf->ops_id); + DRM_DEBUG_KMS("m_node[%p]ops_id[%d]\n", m_node, qbuf->ops_id); DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]\n", qbuf->prop_id, m_node->buf_id); for_each_ipp_planar(i) { @@ -582,8 +582,8 @@ static struct drm_exynos_ipp_mem_node buf_info->handles[i] = qbuf->handle[i]; buf_info->base[i] = *addr; - DRM_DEBUG_KMS("i[%d]base[0x%x]hd[0x%lx]\n", i, - buf_info->base[i], buf_info->handles[i]); + DRM_DEBUG_KMS("i[%d]base[%pad]hd[0x%lx]\n", i, + &buf_info->base[i], buf_info->handles[i]); } } @@ -664,7 +664,7 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node, mutex_lock(&c_node->event_lock); list_for_each_entry_safe(e, te, &c_node->event_list, base.link) { - DRM_DEBUG_KMS("count[%d]e[0x%x]\n", count++, (int)e); + DRM_DEBUG_KMS("count[%d]e[%p]\n", count++, e); /* * qbuf == NULL condition means all event deletion. @@ -755,7 +755,7 @@ static struct drm_exynos_ipp_mem_node /* find memory node from memory list */ list_for_each_entry(m_node, head, list) { - DRM_DEBUG_KMS("count[%d]m_node[0x%x]\n", count++, (int)m_node); + DRM_DEBUG_KMS("count[%d]m_node[%p]\n", count++, m_node); /* compare buffer id */ if (m_node->buf_id == qbuf->buf_id) @@ -772,7 +772,7 @@ static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv, struct exynos_drm_ipp_ops *ops = NULL; int ret = 0; - DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node); + DRM_DEBUG_KMS("node[%p]\n", m_node); if (!m_node) { DRM_ERROR("invalid queue node.\n"); @@ -1237,7 +1237,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv, m_node = list_first_entry(head, struct drm_exynos_ipp_mem_node, list); - DRM_DEBUG_KMS("m_node[0x%x]\n", (int)m_node); + DRM_DEBUG_KMS("m_node[%p]\n", m_node); ret = ipp_set_mem_node(ippdrv, c_node, m_node); if (ret) { @@ -1610,8 +1610,8 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev) } ippdrv->prop_list.ipp_id = ret; - DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]ipp_id[%d]\n", - count++, (int)ippdrv, ret); + DRM_DEBUG_KMS("count[%d]ippdrv[%p]ipp_id[%d]\n", + count++, ippdrv, ret); /* store parent device for node */ ippdrv->parent_dev = dev; @@ -1668,7 +1668,7 @@ static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev, file_priv->ipp_dev = dev; - DRM_DEBUG_KMS("done priv[0x%x]\n", (int)dev); + DRM_DEBUG_KMS("done priv[%p]\n", dev); return 0; } @@ -1685,8 +1685,8 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev, mutex_lock(&ippdrv->cmd_lock); list_for_each_entry_safe(c_node, tc_node, &ippdrv->cmd_list, list) { - DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]\n", - count++, (int)ippdrv); + DRM_DEBUG_KMS("count[%d]ippdrv[%p]\n", + count++, ippdrv); if (c_node->filp == file) { /* diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c index 4eaef36aec5a..9869d70e9e54 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c @@ -18,6 +18,7 @@ #include <linux/of.h> #include <linux/of_graph.h> #include <linux/clk.h> +#include <linux/component.h> #include <drm/drmP.h> #include <linux/mfd/syscon.h> #include <linux/regmap.h> @@ -306,9 +307,9 @@ exit: return ret; } -void mic_disable(struct drm_bridge *bridge) { } +static void mic_disable(struct drm_bridge *bridge) { } -void mic_post_disable(struct drm_bridge *bridge) +static void mic_post_disable(struct drm_bridge *bridge) { struct exynos_mic *mic = bridge->driver_private; int i; @@ -328,7 +329,7 @@ already_disabled: mutex_unlock(&mic_mutex); } -void mic_pre_enable(struct drm_bridge *bridge) +static void mic_pre_enable(struct drm_bridge *bridge) { struct exynos_mic *mic = bridge->driver_private; int ret, i; @@ -371,11 +372,35 @@ already_enabled: mutex_unlock(&mic_mutex); } -void mic_enable(struct drm_bridge *bridge) { } +static void mic_enable(struct drm_bridge *bridge) { } -void mic_destroy(struct drm_bridge *bridge) +static const struct drm_bridge_funcs mic_bridge_funcs = { + .disable = mic_disable, + .post_disable = mic_post_disable, + .pre_enable = mic_pre_enable, + .enable = mic_enable, +}; + +static int exynos_mic_bind(struct device *dev, struct device *master, + void *data) { - struct exynos_mic *mic = bridge->driver_private; + struct exynos_mic *mic = dev_get_drvdata(dev); + int ret; + + mic->bridge.funcs = &mic_bridge_funcs; + mic->bridge.of_node = dev->of_node; + mic->bridge.driver_private = mic; + ret = drm_bridge_add(&mic->bridge); + if (ret) + DRM_ERROR("mic: Failed to add MIC to the global bridge list\n"); + + return ret; +} + +static void exynos_mic_unbind(struct device *dev, struct device *master, + void *data) +{ + struct exynos_mic *mic = dev_get_drvdata(dev); int i; mutex_lock(&mic_mutex); @@ -387,16 +412,16 @@ void mic_destroy(struct drm_bridge *bridge) already_disabled: mutex_unlock(&mic_mutex); + + drm_bridge_remove(&mic->bridge); } -static const struct drm_bridge_funcs mic_bridge_funcs = { - .disable = mic_disable, - .post_disable = mic_post_disable, - .pre_enable = mic_pre_enable, - .enable = mic_enable, +static const struct component_ops exynos_mic_component_ops = { + .bind = exynos_mic_bind, + .unbind = exynos_mic_unbind, }; -int exynos_mic_probe(struct platform_device *pdev) +static int exynos_mic_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct exynos_mic *mic; @@ -435,17 +460,8 @@ int exynos_mic_probe(struct platform_device *pdev) goto err; } - mic->bridge.funcs = &mic_bridge_funcs; - mic->bridge.of_node = dev->of_node; - mic->bridge.driver_private = mic; - ret = drm_bridge_add(&mic->bridge); - if (ret) { - DRM_ERROR("mic: Failed to add MIC to the global bridge list\n"); - goto err; - } - for (i = 0; i < NUM_CLKS; i++) { - mic->clks[i] = of_clk_get_by_name(dev->of_node, clk_names[i]); + mic->clks[i] = devm_clk_get(dev, clk_names[i]); if (IS_ERR(mic->clks[i])) { DRM_ERROR("mic: Failed to get clock (%s)\n", clk_names[i]); @@ -454,7 +470,10 @@ int exynos_mic_probe(struct platform_device *pdev) } } + platform_set_drvdata(pdev, mic); + DRM_DEBUG_KMS("MIC has been probed\n"); + return component_add(dev, &exynos_mic_component_ops); err: return ret; @@ -462,14 +481,7 @@ err: static int exynos_mic_remove(struct platform_device *pdev) { - struct exynos_mic *mic = platform_get_drvdata(pdev); - int i; - - drm_bridge_remove(&mic->bridge); - - for (i = NUM_CLKS - 1; i > -1; i--) - clk_put(mic->clks[i]); - + component_del(&pdev->dev, &exynos_mic_component_ops); return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c index bea0f7826d30..ce59f4443394 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c +++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c @@ -754,7 +754,7 @@ static int rotator_probe(struct platform_device *pdev) goto err_ippdrv_register; } - DRM_DEBUG_KMS("ippdrv[0x%x]\n", (int)ippdrv); + DRM_DEBUG_KMS("ippdrv[%p]\n", ippdrv); platform_set_drvdata(pdev, rot); diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 62ac4e5fa51d..b605bd7395ec 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -223,7 +223,7 @@ static void vidi_fake_vblank_handler(struct work_struct *work) } } -static int vidi_show_connection(struct device *dev, +static ssize_t vidi_show_connection(struct device *dev, struct device_attribute *attr, char *buf) { struct vidi_context *ctx = dev_get_drvdata(dev); @@ -238,7 +238,7 @@ static int vidi_show_connection(struct device *dev, return rc; } -static int vidi_store_connection(struct device *dev, +static ssize_t vidi_store_connection(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -294,7 +294,9 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, } if (vidi->connection) { - struct edid *raw_edid = (struct edid *)(uint32_t)vidi->edid; + struct edid *raw_edid; + + raw_edid = (struct edid *)(unsigned long)vidi->edid; if (!drm_edid_is_valid(raw_edid)) { DRM_DEBUG_KMS("edid data is invalid.\n"); return -EINVAL; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0fc38bb7276c..cf39ed3133d6 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -825,8 +825,11 @@ static int i915_interrupt_info(struct seq_file *m, void *data) } for_each_pipe(dev_priv, pipe) { - if (!intel_display_power_is_enabled(dev_priv, - POWER_DOMAIN_PIPE(pipe))) { + enum intel_display_power_domain power_domain; + + power_domain = POWER_DOMAIN_PIPE(pipe); + if (!intel_display_power_get_if_enabled(dev_priv, + power_domain)) { seq_printf(m, "Pipe %c power disabled\n", pipe_name(pipe)); continue; @@ -840,6 +843,8 @@ static int i915_interrupt_info(struct seq_file *m, void *data) seq_printf(m, "Pipe %c IER:\t%08x\n", pipe_name(pipe), I915_READ(GEN8_DE_PIPE_IER(pipe))); + + intel_display_power_put(dev_priv, power_domain); } seq_printf(m, "Display Engine port interrupt mask:\t%08x\n", @@ -3985,6 +3990,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; struct intel_crtc *crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe)); + enum intel_display_power_domain power_domain; u32 val = 0; /* shut up gcc */ int ret; @@ -3995,7 +4001,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, if (pipe_crc->source && source) return -EINVAL; - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) { + power_domain = POWER_DOMAIN_PIPE(pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) { DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n"); return -EIO; } @@ -4012,7 +4019,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, ret = ivb_pipe_crc_ctl_reg(dev, pipe, &source, &val); if (ret != 0) - return ret; + goto out; /* none -> real source transition */ if (source) { @@ -4024,8 +4031,10 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, entries = kcalloc(INTEL_PIPE_CRC_ENTRIES_NR, sizeof(pipe_crc->entries[0]), GFP_KERNEL); - if (!entries) - return -ENOMEM; + if (!entries) { + ret = -ENOMEM; + goto out; + } /* * When IPS gets enabled, the pipe CRC changes. Since IPS gets @@ -4081,7 +4090,12 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, hsw_enable_ips(crtc); } - return 0; + ret = 0; + +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } /* diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e7cd311e9fbb..b0847b915545 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -751,6 +751,7 @@ struct intel_csr { uint32_t mmio_count; i915_reg_t mmioaddr[8]; uint32_t mmiodata[8]; + uint32_t dc_state; }; #define DEV_INFO_FOR_EACH_FLAG(func, sep) \ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b9a564b76528..4897728713f6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3287,19 +3287,20 @@ enum skl_disp_power_wells { #define PORT_HOTPLUG_STAT _MMIO(dev_priv->info.display_mmio_offset + 0x61114) /* - * HDMI/DP bits are gen4+ + * HDMI/DP bits are g4x+ * * WARNING: Bspec for hpd status bits on gen4 seems to be completely confused. * Please check the detailed lore in the commit message for for experimental * evidence. */ -#define PORTD_HOTPLUG_LIVE_STATUS_G4X (1 << 29) +/* Bspec says GM45 should match G4X/VLV/CHV, but reality disagrees */ +#define PORTD_HOTPLUG_LIVE_STATUS_GM45 (1 << 29) +#define PORTC_HOTPLUG_LIVE_STATUS_GM45 (1 << 28) +#define PORTB_HOTPLUG_LIVE_STATUS_GM45 (1 << 27) +/* G4X/VLV/CHV DP/HDMI bits again match Bspec */ +#define PORTD_HOTPLUG_LIVE_STATUS_G4X (1 << 27) #define PORTC_HOTPLUG_LIVE_STATUS_G4X (1 << 28) -#define PORTB_HOTPLUG_LIVE_STATUS_G4X (1 << 27) -/* VLV DP/HDMI bits again match Bspec */ -#define PORTD_HOTPLUG_LIVE_STATUS_VLV (1 << 27) -#define PORTC_HOTPLUG_LIVE_STATUS_VLV (1 << 28) -#define PORTB_HOTPLUG_LIVE_STATUS_VLV (1 << 29) +#define PORTB_HOTPLUG_LIVE_STATUS_G4X (1 << 29) #define PORTD_HOTPLUG_INT_STATUS (3 << 21) #define PORTD_HOTPLUG_INT_LONG_PULSE (2 << 21) #define PORTD_HOTPLUG_INT_SHORT_PULSE (1 << 21) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 9c89df1af036..a7b4a524fadd 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -71,22 +71,29 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder, struct intel_crt *crt = intel_encoder_to_crt(encoder); enum intel_display_power_domain power_domain; u32 tmp; + bool ret; power_domain = intel_display_port_power_domain(encoder); - if (!intel_display_power_is_enabled(dev_priv, power_domain)) + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; + ret = false; + tmp = I915_READ(crt->adpa_reg); if (!(tmp & ADPA_DAC_ENABLE)) - return false; + goto out; if (HAS_PCH_CPT(dev)) *pipe = PORT_TO_PIPE_CPT(tmp); else *pipe = PORT_TO_PIPE(tmp); - return true; + ret = true; +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } static unsigned int intel_crt_get_flags(struct intel_encoder *encoder) diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 9bb63a85997a..647d85e77c2f 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -240,6 +240,8 @@ void intel_csr_load_program(struct drm_i915_private *dev_priv) I915_WRITE(dev_priv->csr.mmioaddr[i], dev_priv->csr.mmiodata[i]); } + + dev_priv->csr.dc_state = 0; } static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 54a165b9c92d..0f3df2c39f7c 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1969,13 +1969,16 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector) enum transcoder cpu_transcoder; enum intel_display_power_domain power_domain; uint32_t tmp; + bool ret; power_domain = intel_display_port_power_domain(intel_encoder); - if (!intel_display_power_is_enabled(dev_priv, power_domain)) + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; - if (!intel_encoder->get_hw_state(intel_encoder, &pipe)) - return false; + if (!intel_encoder->get_hw_state(intel_encoder, &pipe)) { + ret = false; + goto out; + } if (port == PORT_A) cpu_transcoder = TRANSCODER_EDP; @@ -1987,23 +1990,33 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector) switch (tmp & TRANS_DDI_MODE_SELECT_MASK) { case TRANS_DDI_MODE_SELECT_HDMI: case TRANS_DDI_MODE_SELECT_DVI: - return (type == DRM_MODE_CONNECTOR_HDMIA); + ret = type == DRM_MODE_CONNECTOR_HDMIA; + break; case TRANS_DDI_MODE_SELECT_DP_SST: - if (type == DRM_MODE_CONNECTOR_eDP) - return true; - return (type == DRM_MODE_CONNECTOR_DisplayPort); + ret = type == DRM_MODE_CONNECTOR_eDP || + type == DRM_MODE_CONNECTOR_DisplayPort; + break; + case TRANS_DDI_MODE_SELECT_DP_MST: /* if the transcoder is in MST state then * connector isn't connected */ - return false; + ret = false; + break; case TRANS_DDI_MODE_SELECT_FDI: - return (type == DRM_MODE_CONNECTOR_VGA); + ret = type == DRM_MODE_CONNECTOR_VGA; + break; default: - return false; + ret = false; + break; } + +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } bool intel_ddi_get_hw_state(struct intel_encoder *encoder, @@ -2015,15 +2028,18 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum intel_display_power_domain power_domain; u32 tmp; int i; + bool ret; power_domain = intel_display_port_power_domain(encoder); - if (!intel_display_power_is_enabled(dev_priv, power_domain)) + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; + ret = false; + tmp = I915_READ(DDI_BUF_CTL(port)); if (!(tmp & DDI_BUF_CTL_ENABLE)) - return false; + goto out; if (port == PORT_A) { tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)); @@ -2041,25 +2057,32 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder, break; } - return true; - } else { - for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) { - tmp = I915_READ(TRANS_DDI_FUNC_CTL(i)); + ret = true; - if ((tmp & TRANS_DDI_PORT_MASK) - == TRANS_DDI_SELECT_PORT(port)) { - if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_DP_MST) - return false; + goto out; + } - *pipe = i; - return true; - } + for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) { + tmp = I915_READ(TRANS_DDI_FUNC_CTL(i)); + + if ((tmp & TRANS_DDI_PORT_MASK) == TRANS_DDI_SELECT_PORT(port)) { + if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == + TRANS_DDI_MODE_SELECT_DP_MST) + goto out; + + *pipe = i; + ret = true; + + goto out; } } DRM_DEBUG_KMS("No pipe for ddi port %c found\n", port_name(port)); - return false; +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc) @@ -2508,12 +2531,14 @@ static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv, { uint32_t val; - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS)) + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) return false; val = I915_READ(WRPLL_CTL(pll->id)); hw_state->wrpll = val; + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + return val & WRPLL_PLL_ENABLE; } @@ -2523,12 +2548,14 @@ static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv, { uint32_t val; - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS)) + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) return false; val = I915_READ(SPLL_CTL); hw_state->spll = val; + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + return val & SPLL_PLL_ENABLE; } @@ -2645,16 +2672,19 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, uint32_t val; unsigned int dpll; const struct skl_dpll_regs *regs = skl_dpll_regs; + bool ret; - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS)) + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) return false; + ret = false; + /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */ dpll = pll->id + 1; val = I915_READ(regs[pll->id].ctl); if (!(val & LCPLL_PLL_ENABLE)) - return false; + goto out; val = I915_READ(DPLL_CTRL1); hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f; @@ -2664,8 +2694,12 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1); hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2); } + ret = true; - return true; +out: + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + + return ret; } static void skl_shared_dplls_init(struct drm_i915_private *dev_priv) @@ -2932,13 +2966,16 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, { enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ uint32_t val; + bool ret; - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS)) + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) return false; + ret = false; + val = I915_READ(BXT_PORT_PLL_ENABLE(port)); if (!(val & PORT_PLL_ENABLE)) - return false; + goto out; hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port)); hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK; @@ -2985,7 +3022,12 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, I915_READ(BXT_PORT_PCS_DW12_LN23(port))); hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD; - return true; + ret = true; + +out: + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + + return ret; } static void bxt_shared_dplls_init(struct drm_i915_private *dev_priv) @@ -3120,11 +3162,15 @@ bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv, { u32 temp; - if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) { + if (intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_AUDIO)) { temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); + + intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO); + if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe)) return true; } + return false; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5feb65725c04..46947fffd599 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1351,18 +1351,21 @@ void assert_pipe(struct drm_i915_private *dev_priv, bool cur_state; enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, pipe); + enum intel_display_power_domain power_domain; /* if we need the pipe quirk it must be always on */ if ((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) || (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE)) state = true; - if (!intel_display_power_is_enabled(dev_priv, - POWER_DOMAIN_TRANSCODER(cpu_transcoder))) { - cur_state = false; - } else { + power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder); + if (intel_display_power_get_if_enabled(dev_priv, power_domain)) { u32 val = I915_READ(PIPECONF(cpu_transcoder)); cur_state = !!(val & PIPECONF_ENABLE); + + intel_display_power_put(dev_priv, power_domain); + } else { + cur_state = false; } I915_STATE_WARN(cur_state != state, @@ -8171,18 +8174,22 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + enum intel_display_power_domain power_domain; uint32_t tmp; + bool ret; - if (!intel_display_power_is_enabled(dev_priv, - POWER_DOMAIN_PIPE(crtc->pipe))) + power_domain = POWER_DOMAIN_PIPE(crtc->pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; pipe_config->shared_dpll = DPLL_ID_PRIVATE; + ret = false; + tmp = I915_READ(PIPECONF(crtc->pipe)); if (!(tmp & PIPECONF_ENABLE)) - return false; + goto out; if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { switch (tmp & PIPECONF_BPC_MASK) { @@ -8262,7 +8269,12 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock / pipe_config->pixel_multiplier; - return true; + ret = true; + +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } static void ironlake_init_pch_refclk(struct drm_device *dev) @@ -9366,18 +9378,21 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + enum intel_display_power_domain power_domain; uint32_t tmp; + bool ret; - if (!intel_display_power_is_enabled(dev_priv, - POWER_DOMAIN_PIPE(crtc->pipe))) + power_domain = POWER_DOMAIN_PIPE(crtc->pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; pipe_config->shared_dpll = DPLL_ID_PRIVATE; + ret = false; tmp = I915_READ(PIPECONF(crtc->pipe)); if (!(tmp & PIPECONF_ENABLE)) - return false; + goto out; switch (tmp & PIPECONF_BPC_MASK) { case PIPECONF_6BPC: @@ -9440,7 +9455,12 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, ironlake_get_pfit_config(crtc, pipe_config); - return true; + ret = true; + +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) @@ -9950,12 +9970,17 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - enum intel_display_power_domain pfit_domain; + enum intel_display_power_domain power_domain; + unsigned long power_domain_mask; uint32_t tmp; + bool ret; - if (!intel_display_power_is_enabled(dev_priv, - POWER_DOMAIN_PIPE(crtc->pipe))) + power_domain = POWER_DOMAIN_PIPE(crtc->pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; + power_domain_mask = BIT(power_domain); + + ret = false; pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; pipe_config->shared_dpll = DPLL_ID_PRIVATE; @@ -9982,13 +10007,14 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, pipe_config->cpu_transcoder = TRANSCODER_EDP; } - if (!intel_display_power_is_enabled(dev_priv, - POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder))) - return false; + power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) + goto out; + power_domain_mask |= BIT(power_domain); tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder)); if (!(tmp & PIPECONF_ENABLE)) - return false; + goto out; haswell_get_ddi_port_state(crtc, pipe_config); @@ -9998,14 +10024,14 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, skl_init_scalers(dev, crtc, pipe_config); } - pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe); - if (INTEL_INFO(dev)->gen >= 9) { pipe_config->scaler_state.scaler_id = -1; pipe_config->scaler_state.scaler_users &= ~(1 << SKL_CRTC_INDEX); } - if (intel_display_power_is_enabled(dev_priv, pfit_domain)) { + power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe); + if (intel_display_power_get_if_enabled(dev_priv, power_domain)) { + power_domain_mask |= BIT(power_domain); if (INTEL_INFO(dev)->gen >= 9) skylake_get_pfit_config(crtc, pipe_config); else @@ -10023,7 +10049,13 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, pipe_config->pixel_multiplier = 1; } - return true; + ret = true; + +out: + for_each_power_domain(power_domain, power_domain_mask) + intel_display_power_put(dev_priv, power_domain); + + return ret; } static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on) @@ -13630,7 +13662,7 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv, { uint32_t val; - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS)) + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) return false; val = I915_READ(PCH_DPLL(pll->id)); @@ -13638,6 +13670,8 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv, hw_state->fp0 = I915_READ(PCH_FP0(pll->id)); hw_state->fp1 = I915_READ(PCH_FP1(pll->id)); + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + return val & DPLL_VCO_ENABLE; } @@ -15568,10 +15602,12 @@ void i915_redisable_vga(struct drm_device *dev) * level, just check if the power well is enabled instead of trying to * follow the "don't touch the power well if we don't need it" policy * the rest of the driver uses. */ - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_VGA)) + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_VGA)) return; i915_redisable_vga_power_on(dev); + + intel_display_power_put(dev_priv, POWER_DOMAIN_VGA); } static bool primary_get_hw_state(struct intel_plane *plane) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 796e3d313cb9..1d8de43bed56 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2362,15 +2362,18 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = dev->dev_private; enum intel_display_power_domain power_domain; u32 tmp; + bool ret; power_domain = intel_display_port_power_domain(encoder); - if (!intel_display_power_is_enabled(dev_priv, power_domain)) + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; + ret = false; + tmp = I915_READ(intel_dp->output_reg); if (!(tmp & DP_PORT_EN)) - return false; + goto out; if (IS_GEN7(dev) && port == PORT_A) { *pipe = PORT_TO_PIPE_CPT(tmp); @@ -2381,7 +2384,9 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, u32 trans_dp = I915_READ(TRANS_DP_CTL(p)); if (TRANS_DP_PIPE_TO_PORT(trans_dp) == port) { *pipe = p; - return true; + ret = true; + + goto out; } } @@ -2393,7 +2398,12 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, *pipe = PORT_TO_PIPE(tmp); } - return true; + ret = true; + +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } static void intel_dp_get_config(struct intel_encoder *encoder, @@ -4493,20 +4503,20 @@ static bool g4x_digital_port_connected(struct drm_i915_private *dev_priv, return I915_READ(PORT_HOTPLUG_STAT) & bit; } -static bool vlv_digital_port_connected(struct drm_i915_private *dev_priv, - struct intel_digital_port *port) +static bool gm45_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port) { u32 bit; switch (port->port) { case PORT_B: - bit = PORTB_HOTPLUG_LIVE_STATUS_VLV; + bit = PORTB_HOTPLUG_LIVE_STATUS_GM45; break; case PORT_C: - bit = PORTC_HOTPLUG_LIVE_STATUS_VLV; + bit = PORTC_HOTPLUG_LIVE_STATUS_GM45; break; case PORT_D: - bit = PORTD_HOTPLUG_LIVE_STATUS_VLV; + bit = PORTD_HOTPLUG_LIVE_STATUS_GM45; break; default: MISSING_CASE(port->port); @@ -4558,8 +4568,8 @@ bool intel_digital_port_connected(struct drm_i915_private *dev_priv, return cpt_digital_port_connected(dev_priv, port); else if (IS_BROXTON(dev_priv)) return bxt_digital_port_connected(dev_priv, port); - else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - return vlv_digital_port_connected(dev_priv, port); + else if (IS_GM45(dev_priv)) + return gm45_digital_port_connected(dev_priv, port); else return g4x_digital_port_connected(dev_priv, port); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ea5415851c6e..df7f3cb66056 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1428,6 +1428,8 @@ bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain); void intel_display_power_get(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain); +bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv, + enum intel_display_power_domain domain); void intel_display_power_put(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain); @@ -1514,6 +1516,7 @@ enable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv) enable_rpm_wakeref_asserts(dev_priv) void intel_runtime_pm_get(struct drm_i915_private *dev_priv); +bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv); void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv); void intel_runtime_pm_put(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 44742fa2f616..0193c62a53ef 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -664,13 +664,16 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, struct drm_device *dev = encoder->base.dev; enum intel_display_power_domain power_domain; enum port port; + bool ret; DRM_DEBUG_KMS("\n"); power_domain = intel_display_port_power_domain(encoder); - if (!intel_display_power_is_enabled(dev_priv, power_domain)) + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; + ret = false; + /* XXX: this only works for one DSI output */ for_each_dsi_port(port, intel_dsi->ports) { i915_reg_t ctrl_reg = IS_BROXTON(dev) ? @@ -691,12 +694,16 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, if (dpi_enabled || (func & CMD_MODE_DATA_WIDTH_MASK)) { if (I915_READ(MIPI_DEVICE_READY(port)) & DEVICE_READY) { *pipe = port == PORT_A ? PIPE_A : PIPE_B; - return true; + ret = true; + + goto out; } } } +out: + intel_display_power_put(dev_priv, power_domain); - return false; + return ret; } static void intel_dsi_get_config(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 4a77639a489d..cb5d1b15755c 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -880,15 +880,18 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder, struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); enum intel_display_power_domain power_domain; u32 tmp; + bool ret; power_domain = intel_display_port_power_domain(encoder); - if (!intel_display_power_is_enabled(dev_priv, power_domain)) + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; + ret = false; + tmp = I915_READ(intel_hdmi->hdmi_reg); if (!(tmp & SDVO_ENABLE)) - return false; + goto out; if (HAS_PCH_CPT(dev)) *pipe = PORT_TO_PIPE_CPT(tmp); @@ -897,7 +900,12 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder, else *pipe = PORT_TO_PIPE(tmp); - return true; + ret = true; + +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } static void intel_hdmi_get_config(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 0da0240caf81..bc04d8d29acb 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -75,22 +75,30 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder, struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); enum intel_display_power_domain power_domain; u32 tmp; + bool ret; power_domain = intel_display_port_power_domain(encoder); - if (!intel_display_power_is_enabled(dev_priv, power_domain)) + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; + ret = false; + tmp = I915_READ(lvds_encoder->reg); if (!(tmp & LVDS_PORT_EN)) - return false; + goto out; if (HAS_PCH_CPT(dev)) *pipe = PORT_TO_PIPE_CPT(tmp); else *pipe = PORT_TO_PIPE(tmp); - return true; + ret = true; + +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } static void intel_lvds_get_config(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a234687792f0..b28c29f20e75 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2829,7 +2829,10 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, memset(ddb, 0, sizeof(*ddb)); for_each_pipe(dev_priv, pipe) { - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) + enum intel_display_power_domain power_domain; + + power_domain = POWER_DOMAIN_PIPE(pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) continue; for_each_plane(dev_priv, pipe, plane) { @@ -2841,6 +2844,8 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, val = I915_READ(CUR_BUF_CFG(pipe)); skl_ddb_entry_init_from_hw(&ddb->plane[pipe][PLANE_CURSOR], val); + + intel_display_power_put(dev_priv, power_domain); } } diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index ddbdbffe829a..4f43d9b32e66 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -470,6 +470,43 @@ static void gen9_set_dc_state_debugmask_memory_up( } } +static void gen9_write_dc_state(struct drm_i915_private *dev_priv, + u32 state) +{ + int rewrites = 0; + int rereads = 0; + u32 v; + + I915_WRITE(DC_STATE_EN, state); + + /* It has been observed that disabling the dc6 state sometimes + * doesn't stick and dmc keeps returning old value. Make sure + * the write really sticks enough times and also force rewrite until + * we are confident that state is exactly what we want. + */ + do { + v = I915_READ(DC_STATE_EN); + + if (v != state) { + I915_WRITE(DC_STATE_EN, state); + rewrites++; + rereads = 0; + } else if (rereads++ > 5) { + break; + } + + } while (rewrites < 100); + + if (v != state) + DRM_ERROR("Writing dc state to 0x%x failed, now 0x%x\n", + state, v); + + /* Most of the times we need one retry, avoid spam */ + if (rewrites > 1) + DRM_DEBUG_KMS("Rewrote dc state to 0x%x %d times\n", + state, rewrites); +} + static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state) { uint32_t val; @@ -494,10 +531,18 @@ static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state) val = I915_READ(DC_STATE_EN); DRM_DEBUG_KMS("Setting DC state from %02x to %02x\n", val & mask, state); + + /* Check if DMC is ignoring our DC state requests */ + if ((val & mask) != dev_priv->csr.dc_state) + DRM_ERROR("DC state mismatch (0x%x -> 0x%x)\n", + dev_priv->csr.dc_state, val & mask); + val &= ~mask; val |= state; - I915_WRITE(DC_STATE_EN, val); - POSTING_READ(DC_STATE_EN); + + gen9_write_dc_state(dev_priv, val); + + dev_priv->csr.dc_state = val & mask; } void bxt_enable_dc9(struct drm_i915_private *dev_priv) @@ -1442,6 +1487,22 @@ static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv, chv_set_pipe_power_well(dev_priv, power_well, false); } +static void +__intel_display_power_get_domain(struct drm_i915_private *dev_priv, + enum intel_display_power_domain domain) +{ + struct i915_power_domains *power_domains = &dev_priv->power_domains; + struct i915_power_well *power_well; + int i; + + for_each_power_well(i, power_well, BIT(domain), power_domains) { + if (!power_well->count++) + intel_power_well_enable(dev_priv, power_well); + } + + power_domains->domain_use_count[domain]++; +} + /** * intel_display_power_get - grab a power domain reference * @dev_priv: i915 device instance @@ -1457,24 +1518,53 @@ static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv, void intel_display_power_get(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain) { - struct i915_power_domains *power_domains; - struct i915_power_well *power_well; - int i; + struct i915_power_domains *power_domains = &dev_priv->power_domains; intel_runtime_pm_get(dev_priv); - power_domains = &dev_priv->power_domains; + mutex_lock(&power_domains->lock); + + __intel_display_power_get_domain(dev_priv, domain); + + mutex_unlock(&power_domains->lock); +} + +/** + * intel_display_power_get_if_enabled - grab a reference for an enabled display power domain + * @dev_priv: i915 device instance + * @domain: power domain to reference + * + * This function grabs a power domain reference for @domain and ensures that the + * power domain and all its parents are powered up. Therefore users should only + * grab a reference to the innermost power domain they need. + * + * Any power domain reference obtained by this function must have a symmetric + * call to intel_display_power_put() to release the reference again. + */ +bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv, + enum intel_display_power_domain domain) +{ + struct i915_power_domains *power_domains = &dev_priv->power_domains; + bool is_enabled; + + if (!intel_runtime_pm_get_if_in_use(dev_priv)) + return false; mutex_lock(&power_domains->lock); - for_each_power_well(i, power_well, BIT(domain), power_domains) { - if (!power_well->count++) - intel_power_well_enable(dev_priv, power_well); + if (__intel_display_power_is_enabled(dev_priv, domain)) { + __intel_display_power_get_domain(dev_priv, domain); + is_enabled = true; + } else { + is_enabled = false; } - power_domains->domain_use_count[domain]++; - mutex_unlock(&power_domains->lock); + + if (!is_enabled) + intel_runtime_pm_put(dev_priv); + + return is_enabled; } /** @@ -2213,15 +2303,15 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume) */ void intel_power_domains_suspend(struct drm_i915_private *dev_priv) { - if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) - skl_display_core_uninit(dev_priv); - /* * Even if power well support was disabled we still want to disable * power wells while we are system suspended. */ if (!i915.disable_power_well) intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); + + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) + skl_display_core_uninit(dev_priv); } /** @@ -2246,6 +2336,41 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv) } /** + * intel_runtime_pm_get_if_in_use - grab a runtime pm reference if device in use + * @dev_priv: i915 device instance + * + * This function grabs a device-level runtime pm reference if the device is + * already in use and ensures that it is powered up. + * + * Any runtime pm reference obtained by this function must have a symmetric + * call to intel_runtime_pm_put() to release the reference again. + */ +bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + struct device *device = &dev->pdev->dev; + + if (IS_ENABLED(CONFIG_PM)) { + int ret = pm_runtime_get_if_in_use(device); + + /* + * In cases runtime PM is disabled by the RPM core and we get + * an -EINVAL return value we are not supposed to call this + * function, since the power state is undefined. This applies + * atm to the late/early system suspend/resume handlers. + */ + WARN_ON_ONCE(ret < 0); + if (ret <= 0) + return false; + } + + atomic_inc(&dev_priv->pm.wakeref_count); + assert_rpm_wakelock_held(dev_priv); + + return true; +} + +/** * intel_runtime_pm_get_noresume - grab a runtime pm reference * @dev_priv: i915 device instance * diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 78f520d05de9..e3acc35e3805 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1520,7 +1520,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) DMA_BIDIRECTIONAL); if (dma_mapping_error(pdev, addr)) { - while (--i) { + while (i--) { dma_unmap_page(pdev, ttm_dma->dma_address[i], PAGE_SIZE, DMA_BIDIRECTIONAL); ttm_dma->dma_address[i] = 0; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 24be27d3cd18..20935eb2a09e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -635,10 +635,6 @@ nouveau_display_resume(struct drm_device *dev, bool runtime) nv_crtc->lut.depth = 0; } - /* Make sure that drm and hw vblank irqs get resumed if needed. */ - for (head = 0; head < dev->mode_config.num_crtc; head++) - drm_vblank_on(dev, head); - /* This should ensure we don't hit a locking problem when someone * wakes us up via a connector. We should never go into suspend * while the display is on anyways. @@ -648,6 +644,10 @@ nouveau_display_resume(struct drm_device *dev, bool runtime) drm_helper_resume_force_mode(dev); + /* Make sure that drm and hw vblank irqs get resumed if needed. */ + for (head = 0; head < dev->mode_config.num_crtc; head++) + drm_vblank_on(dev, head); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c index 8a70cec59bcd..2dfe58af12e4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_platform.c +++ b/drivers/gpu/drm/nouveau/nouveau_platform.c @@ -24,7 +24,7 @@ static int nouveau_platform_probe(struct platform_device *pdev) { const struct nvkm_device_tegra_func *func; - struct nvkm_device *device; + struct nvkm_device *device = NULL; struct drm_device *drm; int ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c index 7f8a42721eb2..e7e581d6a8ff 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c @@ -252,32 +252,40 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL))) return -ENOMEM; - *pdevice = &tdev->device; + tdev->func = func; tdev->pdev = pdev; tdev->irq = -1; tdev->vdd = devm_regulator_get(&pdev->dev, "vdd"); - if (IS_ERR(tdev->vdd)) - return PTR_ERR(tdev->vdd); + if (IS_ERR(tdev->vdd)) { + ret = PTR_ERR(tdev->vdd); + goto free; + } tdev->rst = devm_reset_control_get(&pdev->dev, "gpu"); - if (IS_ERR(tdev->rst)) - return PTR_ERR(tdev->rst); + if (IS_ERR(tdev->rst)) { + ret = PTR_ERR(tdev->rst); + goto free; + } tdev->clk = devm_clk_get(&pdev->dev, "gpu"); - if (IS_ERR(tdev->clk)) - return PTR_ERR(tdev->clk); + if (IS_ERR(tdev->clk)) { + ret = PTR_ERR(tdev->clk); + goto free; + } tdev->clk_pwr = devm_clk_get(&pdev->dev, "pwr"); - if (IS_ERR(tdev->clk_pwr)) - return PTR_ERR(tdev->clk_pwr); + if (IS_ERR(tdev->clk_pwr)) { + ret = PTR_ERR(tdev->clk_pwr); + goto free; + } nvkm_device_tegra_probe_iommu(tdev); ret = nvkm_device_tegra_power_up(tdev); if (ret) - return ret; + goto remove; tdev->gpu_speedo = tegra_sku_info.gpu_speedo_value; ret = nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev, @@ -285,9 +293,19 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, cfg, dbg, detect, mmio, subdev_mask, &tdev->device); if (ret) - return ret; + goto powerdown; + + *pdevice = &tdev->device; return 0; + +powerdown: + nvkm_device_tegra_power_down(tdev); +remove: + nvkm_device_tegra_remove_iommu(tdev); +free: + kfree(tdev); + return ret; } #else int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c index 74e2f7c6c07e..9688970eca47 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c @@ -328,6 +328,7 @@ nvkm_dp_train(struct work_struct *w) .outp = outp, }, *dp = &_dp; u32 datarate = 0; + u8 pwr; int ret; if (!outp->base.info.location && disp->func->sor.magic) @@ -355,6 +356,15 @@ nvkm_dp_train(struct work_struct *w) /* disable link interrupt handling during link training */ nvkm_notify_put(&outp->irq); + /* ensure sink is not in a low-power state */ + if (!nvkm_rdaux(outp->aux, DPCD_SC00, &pwr, 1)) { + if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) { + pwr &= ~DPCD_SC00_SET_POWER; + pwr |= DPCD_SC00_SET_POWER_D0; + nvkm_wraux(outp->aux, DPCD_SC00, &pwr, 1); + } + } + /* enable down-spreading and execute pre-train script from vbios */ dp_link_train_init(dp, outp->dpcd[3] & 0x01); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h index 9596290329c7..6e10c5e0ef11 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h @@ -71,5 +71,11 @@ #define DPCD_LS0C_LANE1_POST_CURSOR2 0x0c #define DPCD_LS0C_LANE0_POST_CURSOR2 0x03 +/* DPCD Sink Control */ +#define DPCD_SC00 0x00600 +#define DPCD_SC00_SET_POWER 0x03 +#define DPCD_SC00_SET_POWER_D0 0x01 +#define DPCD_SC00_SET_POWER_D3 0x03 + void nvkm_dp_train(struct work_struct *); #endif diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c index 2ae8577497ca..7c2e78201ead 100644 --- a/drivers/gpu/drm/qxl/qxl_ioctl.c +++ b/drivers/gpu/drm/qxl/qxl_ioctl.c @@ -168,7 +168,8 @@ static int qxl_process_single_command(struct qxl_device *qdev, cmd->command_size)) return -EFAULT; - reloc_info = kmalloc(sizeof(struct qxl_reloc_info) * cmd->relocs_num, GFP_KERNEL); + reloc_info = kmalloc_array(cmd->relocs_num, + sizeof(struct qxl_reloc_info), GFP_KERNEL); if (!reloc_info) return -ENOMEM; diff --git a/drivers/gpu/drm/qxl/qxl_prime.c b/drivers/gpu/drm/qxl/qxl_prime.c index 3d031b50a8fd..9f029dda1f07 100644 --- a/drivers/gpu/drm/qxl/qxl_prime.c +++ b/drivers/gpu/drm/qxl/qxl_prime.c @@ -68,5 +68,5 @@ int qxl_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *area) { WARN_ONCE(1, "not implemented"); - return ENOSYS; + return -ENOSYS; } diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 298ea1c453c3..2b9ba03a7c1a 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -403,7 +403,8 @@ static void radeon_flip_work_func(struct work_struct *__work) struct drm_crtc *crtc = &radeon_crtc->base; unsigned long flags; int r; - int vpos, hpos, stat, min_udelay; + int vpos, hpos, stat, min_udelay = 0; + unsigned repcnt = 4; struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id]; down_read(&rdev->exclusive_lock); @@ -454,7 +455,7 @@ static void radeon_flip_work_func(struct work_struct *__work) * In practice this won't execute very often unless on very fast * machines because the time window for this to happen is very small. */ - for (;;) { + while (radeon_crtc->enabled && repcnt--) { /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank * start in hpos, and to the "fudged earlier" vblank start in * vpos. @@ -472,10 +473,22 @@ static void radeon_flip_work_func(struct work_struct *__work) /* Sleep at least until estimated real start of hw vblank */ spin_unlock_irqrestore(&crtc->dev->event_lock, flags); min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5); + if (min_udelay > vblank->framedur_ns / 2000) { + /* Don't wait ridiculously long - something is wrong */ + repcnt = 0; + break; + } usleep_range(min_udelay, 2 * min_udelay); spin_lock_irqsave(&crtc->dev->event_lock, flags); }; + if (!repcnt) + DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, " + "framedur %d, linedur %d, stat %d, vpos %d, " + "hpos %d\n", work->crtc_id, min_udelay, + vblank->framedur_ns / 1000, + vblank->linedur_ns / 1000, stat, vpos, hpos); + /* do the flip (mmio) */ radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base); diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 460c8f2989da..0f14d897baf9 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -276,8 +276,12 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) if (rdev->irq.installed) { for (i = 0; i < rdev->num_crtc; i++) { if (rdev->pm.active_crtcs & (1 << i)) { - rdev->pm.req_vblank |= (1 << i); - drm_vblank_get(rdev->ddev, i); + /* This can fail if a modeset is in progress */ + if (drm_vblank_get(rdev->ddev, i) == 0) + rdev->pm.req_vblank |= (1 << i); + else + DRM_DEBUG_DRIVER("crtc %d no vblank, can glitch\n", + i); } } } @@ -1075,12 +1079,6 @@ force: /* update display watermarks based on new power state */ radeon_bandwidth_update(rdev); - /* update displays */ - radeon_dpm_display_configuration_changed(rdev); - - rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs; - rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count; - rdev->pm.dpm.single_display = single_display; /* wait for the rings to drain */ for (i = 0; i < RADEON_NUM_RINGS; i++) { @@ -1097,6 +1095,13 @@ force: radeon_dpm_post_set_power_state(rdev); + /* update displays */ + radeon_dpm_display_configuration_changed(rdev); + + rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs; + rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count; + rdev->pm.dpm.single_display = single_display; + if (rdev->asic->dpm.force_performance_level) { if (rdev->pm.dpm.thermal_active) { enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index e34307459e50..e06ac546a90f 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -758,7 +758,7 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm) 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); if (pci_dma_mapping_error(rdev->pdev, gtt->ttm.dma_address[i])) { - while (--i) { + while (i--) { pci_unmap_page(rdev->pdev, gtt->ttm.dma_address[i], PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); gtt->ttm.dma_address[i] = 0; diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 18dfe3ec9a62..22278bcfc60e 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -215,7 +215,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size, struct drm_gem_cma_object *cma_obj; if (size == 0) - return NULL; + return ERR_PTR(-EINVAL); /* First, try to get a vc4_bo from the kernel BO cache. */ if (from_cache) { @@ -237,7 +237,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size, if (IS_ERR(cma_obj)) { DRM_ERROR("Failed to allocate from CMA:\n"); vc4_bo_stats_dump(vc4); - return NULL; + return ERR_PTR(-ENOMEM); } } @@ -259,8 +259,8 @@ int vc4_dumb_create(struct drm_file *file_priv, args->size = args->pitch * args->height; bo = vc4_bo_create(dev, args->size, false); - if (!bo) - return -ENOMEM; + if (IS_ERR(bo)) + return PTR_ERR(bo); ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle); drm_gem_object_unreference_unlocked(&bo->base.base); @@ -443,8 +443,8 @@ int vc4_create_bo_ioctl(struct drm_device *dev, void *data, * get zeroed, and that might leak data between users. */ bo = vc4_bo_create(dev, args->size, false); - if (!bo) - return -ENOMEM; + if (IS_ERR(bo)) + return PTR_ERR(bo); ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle); drm_gem_object_unreference_unlocked(&bo->base.base); @@ -496,8 +496,8 @@ vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data, } bo = vc4_bo_create(dev, args->size, true); - if (!bo) - return -ENOMEM; + if (IS_ERR(bo)) + return PTR_ERR(bo); ret = copy_from_user(bo->base.vaddr, (void __user *)(uintptr_t)args->data, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 080865ec2bae..51a63330d4f8 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -91,8 +91,12 @@ struct vc4_dev { struct vc4_bo *overflow_mem; struct work_struct overflow_mem_work; + int power_refcount; + + /* Mutex controlling the power refcount. */ + struct mutex power_lock; + struct { - uint32_t last_ct0ca, last_ct1ca; struct timer_list timer; struct work_struct reset_work; } hangcheck; @@ -142,6 +146,7 @@ struct vc4_seqno_cb { }; struct vc4_v3d { + struct vc4_dev *vc4; struct platform_device *pdev; void __iomem *regs; }; @@ -192,6 +197,11 @@ struct vc4_exec_info { /* Sequence number for this bin/render job. */ uint64_t seqno; + /* Last current addresses the hardware was processing when the + * hangcheck timer checked on us. + */ + uint32_t last_ct0ca, last_ct1ca; + /* Kernel-space copy of the ioctl arguments */ struct drm_vc4_submit_cl *args; @@ -434,7 +444,6 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, extern struct platform_driver vc4_v3d_driver; int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused); int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused); -int vc4_v3d_set_power(struct vc4_dev *vc4, bool on); /* vc4_validate.c */ int diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 48ce30a6f4b5..202aa1544acc 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -23,6 +23,7 @@ #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/device.h> #include <linux/io.h> @@ -228,8 +229,16 @@ vc4_reset(struct drm_device *dev) struct vc4_dev *vc4 = to_vc4_dev(dev); DRM_INFO("Resetting GPU.\n"); - vc4_v3d_set_power(vc4, false); - vc4_v3d_set_power(vc4, true); + + mutex_lock(&vc4->power_lock); + if (vc4->power_refcount) { + /* Power the device off and back on the by dropping the + * reference on runtime PM. + */ + pm_runtime_put_sync_suspend(&vc4->v3d->pdev->dev); + pm_runtime_get_sync(&vc4->v3d->pdev->dev); + } + mutex_unlock(&vc4->power_lock); vc4_irq_reset(dev); @@ -257,10 +266,17 @@ vc4_hangcheck_elapsed(unsigned long data) struct drm_device *dev = (struct drm_device *)data; struct vc4_dev *vc4 = to_vc4_dev(dev); uint32_t ct0ca, ct1ca; + unsigned long irqflags; + struct vc4_exec_info *exec; + + spin_lock_irqsave(&vc4->job_lock, irqflags); + exec = vc4_first_job(vc4); /* If idle, we can stop watching for hangs. */ - if (list_empty(&vc4->job_list)) + if (!exec) { + spin_unlock_irqrestore(&vc4->job_lock, irqflags); return; + } ct0ca = V3D_READ(V3D_CTNCA(0)); ct1ca = V3D_READ(V3D_CTNCA(1)); @@ -268,14 +284,16 @@ vc4_hangcheck_elapsed(unsigned long data) /* If we've made any progress in execution, rearm the timer * and wait. */ - if (ct0ca != vc4->hangcheck.last_ct0ca || - ct1ca != vc4->hangcheck.last_ct1ca) { - vc4->hangcheck.last_ct0ca = ct0ca; - vc4->hangcheck.last_ct1ca = ct1ca; + if (ct0ca != exec->last_ct0ca || ct1ca != exec->last_ct1ca) { + exec->last_ct0ca = ct0ca; + exec->last_ct1ca = ct1ca; + spin_unlock_irqrestore(&vc4->job_lock, irqflags); vc4_queue_hangcheck(dev); return; } + spin_unlock_irqrestore(&vc4->job_lock, irqflags); + /* We've gone too long with no progress, reset. This has to * be done from a work struct, since resetting can sleep and * this timer hook isn't allowed to. @@ -340,12 +358,7 @@ vc4_wait_for_seqno(struct drm_device *dev, uint64_t seqno, uint64_t timeout_ns, finish_wait(&vc4->job_wait_queue, &wait); trace_vc4_wait_for_seqno_end(dev, seqno); - if (ret && ret != -ERESTARTSYS) { - DRM_ERROR("timeout waiting for render thread idle\n"); - return ret; - } - - return 0; + return ret; } static void @@ -578,9 +591,9 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec) } bo = vc4_bo_create(dev, exec_size, true); - if (!bo) { + if (IS_ERR(bo)) { DRM_ERROR("Couldn't allocate BO for binning\n"); - ret = -ENOMEM; + ret = PTR_ERR(bo); goto fail; } exec->exec_bo = &bo->base; @@ -617,6 +630,7 @@ fail: static void vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec) { + struct vc4_dev *vc4 = to_vc4_dev(dev); unsigned i; /* Need the struct lock for drm_gem_object_unreference(). */ @@ -635,6 +649,11 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec) } mutex_unlock(&dev->struct_mutex); + mutex_lock(&vc4->power_lock); + if (--vc4->power_refcount == 0) + pm_runtime_put(&vc4->v3d->pdev->dev); + mutex_unlock(&vc4->power_lock); + kfree(exec); } @@ -746,6 +765,9 @@ vc4_wait_bo_ioctl(struct drm_device *dev, void *data, struct drm_gem_object *gem_obj; struct vc4_bo *bo; + if (args->pad != 0) + return -EINVAL; + gem_obj = drm_gem_object_lookup(dev, file_priv, args->handle); if (!gem_obj) { DRM_ERROR("Failed to look up GEM BO %d\n", args->handle); @@ -772,7 +794,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, struct vc4_dev *vc4 = to_vc4_dev(dev); struct drm_vc4_submit_cl *args = data; struct vc4_exec_info *exec; - int ret; + int ret = 0; if ((args->flags & ~VC4_SUBMIT_CL_USE_CLEAR_COLOR) != 0) { DRM_ERROR("Unknown flags: 0x%02x\n", args->flags); @@ -785,6 +807,15 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, return -ENOMEM; } + mutex_lock(&vc4->power_lock); + if (vc4->power_refcount++ == 0) + ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); + mutex_unlock(&vc4->power_lock); + if (ret < 0) { + kfree(exec); + return ret; + } + exec->args = args; INIT_LIST_HEAD(&exec->unref_list); @@ -839,6 +870,8 @@ vc4_gem_init(struct drm_device *dev) (unsigned long)dev); INIT_WORK(&vc4->job_done_work, vc4_job_done_work); + + mutex_init(&vc4->power_lock); } void diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c index b68060e758db..78a21357fb2d 100644 --- a/drivers/gpu/drm/vc4/vc4_irq.c +++ b/drivers/gpu/drm/vc4/vc4_irq.c @@ -57,7 +57,7 @@ vc4_overflow_mem_work(struct work_struct *work) struct vc4_bo *bo; bo = vc4_bo_create(dev, 256 * 1024, true); - if (!bo) { + if (IS_ERR(bo)) { DRM_ERROR("Couldn't allocate binner overflow mem\n"); return; } diff --git a/drivers/gpu/drm/vc4/vc4_render_cl.c b/drivers/gpu/drm/vc4/vc4_render_cl.c index 8a2a312e2c1b..0f12418725e5 100644 --- a/drivers/gpu/drm/vc4/vc4_render_cl.c +++ b/drivers/gpu/drm/vc4/vc4_render_cl.c @@ -316,20 +316,11 @@ static int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec, size += xtiles * ytiles * loop_body_size; setup->rcl = &vc4_bo_create(dev, size, true)->base; - if (!setup->rcl) - return -ENOMEM; + if (IS_ERR(setup->rcl)) + return PTR_ERR(setup->rcl); list_add_tail(&to_vc4_bo(&setup->rcl->base)->unref_head, &exec->unref_list); - rcl_u8(setup, VC4_PACKET_TILE_RENDERING_MODE_CONFIG); - rcl_u32(setup, - (setup->color_write ? (setup->color_write->paddr + - args->color_write.offset) : - 0)); - rcl_u16(setup, args->width); - rcl_u16(setup, args->height); - rcl_u16(setup, args->color_write.bits); - /* The tile buffer gets cleared when the previous tile is stored. If * the clear values changed between frames, then the tile buffer has * stale clear values in it, so we have to do a store in None mode (no @@ -349,6 +340,15 @@ static int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec, rcl_u32(setup, 0); /* no address, since we're in None mode */ } + rcl_u8(setup, VC4_PACKET_TILE_RENDERING_MODE_CONFIG); + rcl_u32(setup, + (setup->color_write ? (setup->color_write->paddr + + args->color_write.offset) : + 0)); + rcl_u16(setup, args->width); + rcl_u16(setup, args->height); + rcl_u16(setup, args->color_write.bits); + for (y = min_y_tile; y <= max_y_tile; y++) { for (x = min_x_tile; x <= max_x_tile; x++) { bool first = (x == min_x_tile && y == min_y_tile); diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index 314ff71db978..31de5d17bc85 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -17,6 +17,7 @@ */ #include "linux/component.h" +#include "linux/pm_runtime.h" #include "vc4_drv.h" #include "vc4_regs.h" @@ -144,18 +145,6 @@ int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused) } #endif /* CONFIG_DEBUG_FS */ -int -vc4_v3d_set_power(struct vc4_dev *vc4, bool on) -{ - /* XXX: This interface is needed for GPU reset, and the way to - * do it is to turn our power domain off and back on. We - * can't just reset from within the driver, because the reset - * bits are in the power domain's register area, and get set - * during the poweron process. - */ - return 0; -} - static void vc4_v3d_init_hw(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -167,6 +156,29 @@ static void vc4_v3d_init_hw(struct drm_device *dev) V3D_WRITE(V3D_VPMBASE, 0); } +#ifdef CONFIG_PM +static int vc4_v3d_runtime_suspend(struct device *dev) +{ + struct vc4_v3d *v3d = dev_get_drvdata(dev); + struct vc4_dev *vc4 = v3d->vc4; + + vc4_irq_uninstall(vc4->dev); + + return 0; +} + +static int vc4_v3d_runtime_resume(struct device *dev) +{ + struct vc4_v3d *v3d = dev_get_drvdata(dev); + struct vc4_dev *vc4 = v3d->vc4; + + vc4_v3d_init_hw(vc4->dev); + vc4_irq_postinstall(vc4->dev); + + return 0; +} +#endif + static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); @@ -179,6 +191,8 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) if (!v3d) return -ENOMEM; + dev_set_drvdata(dev, v3d); + v3d->pdev = pdev; v3d->regs = vc4_ioremap_regs(pdev, 0); @@ -186,6 +200,7 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) return PTR_ERR(v3d->regs); vc4->v3d = v3d; + v3d->vc4 = vc4; if (V3D_READ(V3D_IDENT0) != V3D_EXPECTED_IDENT0) { DRM_ERROR("V3D_IDENT0 read 0x%08x instead of 0x%08x\n", @@ -207,6 +222,8 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) return ret; } + pm_runtime_enable(dev); + return 0; } @@ -216,6 +233,8 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master, struct drm_device *drm = dev_get_drvdata(master); struct vc4_dev *vc4 = to_vc4_dev(drm); + pm_runtime_disable(dev); + drm_irq_uninstall(drm); /* Disable the binner's overflow memory address, so the next @@ -228,6 +247,10 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master, vc4->v3d = NULL; } +static const struct dev_pm_ops vc4_v3d_pm_ops = { + SET_RUNTIME_PM_OPS(vc4_v3d_runtime_suspend, vc4_v3d_runtime_resume, NULL) +}; + static const struct component_ops vc4_v3d_ops = { .bind = vc4_v3d_bind, .unbind = vc4_v3d_unbind, @@ -255,5 +278,6 @@ struct platform_driver vc4_v3d_driver = { .driver = { .name = "vc4_v3d", .of_match_table = vc4_v3d_dt_match, + .pm = &vc4_v3d_pm_ops, }, }; diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c index e26d9f6face3..24c2c746e8f3 100644 --- a/drivers/gpu/drm/vc4/vc4_validate.c +++ b/drivers/gpu/drm/vc4/vc4_validate.c @@ -401,8 +401,8 @@ validate_tile_binning_config(VALIDATE_ARGS) tile_bo = vc4_bo_create(dev, exec->tile_alloc_offset + tile_alloc_size, true); exec->tile_bo = &tile_bo->base; - if (!exec->tile_bo) - return -ENOMEM; + if (IS_ERR(exec->tile_bo)) + return PTR_ERR(exec->tile_bo); list_add_tail(&tile_bo->unref_head, &exec->unref_list); /* tile alloc address. */ diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c index da462afcb225..dd2dbb9746ce 100644 --- a/drivers/gpu/host1x/bus.c +++ b/drivers/gpu/host1x/bus.c @@ -18,6 +18,7 @@ #include <linux/host1x.h> #include <linux/of.h> #include <linux/slab.h> +#include <linux/of_device.h> #include "bus.h" #include "dev.h" @@ -394,6 +395,7 @@ static int host1x_device_add(struct host1x *host1x, device->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask; device->dev.dma_mask = &device->dev.coherent_dma_mask; dev_set_name(&device->dev, "%s", driver->driver.name); + of_dma_configure(&device->dev, host1x->dev->of_node); device->dev.release = host1x_device_release; device->dev.bus = &host1x_bus_type; device->dev.parent = host1x->dev; diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index 314bf3718cc7..ff348690df94 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -23,6 +23,7 @@ #include <linux/of_device.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/dma-mapping.h> #define CREATE_TRACE_POINTS #include <trace/events/host1x.h> @@ -68,6 +69,7 @@ static const struct host1x_info host1x01_info = { .nb_bases = 8, .init = host1x01_init, .sync_offset = 0x3000, + .dma_mask = DMA_BIT_MASK(32), }; static const struct host1x_info host1x02_info = { @@ -77,6 +79,7 @@ static const struct host1x_info host1x02_info = { .nb_bases = 12, .init = host1x02_init, .sync_offset = 0x3000, + .dma_mask = DMA_BIT_MASK(32), }; static const struct host1x_info host1x04_info = { @@ -86,6 +89,7 @@ static const struct host1x_info host1x04_info = { .nb_bases = 64, .init = host1x04_init, .sync_offset = 0x2100, + .dma_mask = DMA_BIT_MASK(34), }; static const struct host1x_info host1x05_info = { @@ -95,6 +99,7 @@ static const struct host1x_info host1x05_info = { .nb_bases = 64, .init = host1x05_init, .sync_offset = 0x2100, + .dma_mask = DMA_BIT_MASK(34), }; static struct of_device_id host1x_of_match[] = { @@ -148,6 +153,8 @@ static int host1x_probe(struct platform_device *pdev) if (IS_ERR(host->regs)) return PTR_ERR(host->regs); + dma_set_mask_and_coherent(host->dev, host->info->dma_mask); + if (host->info->init) { err = host->info->init(host); if (err) diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index 0b6e8e9629c5..dace124994bb 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h @@ -96,6 +96,7 @@ struct host1x_info { int nb_mlocks; /* host1x: number of mlocks */ int (*init)(struct host1x *); /* initialize per SoC ops */ int sync_offset; + u64 dma_mask; /* mask of addressable memory */ }; struct host1x { diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c index f155b8380481..2b3105c8aed3 100644 --- a/drivers/hwmon/ads1015.c +++ b/drivers/hwmon/ads1015.c @@ -126,7 +126,7 @@ static int ads1015_reg_to_mv(struct i2c_client *client, unsigned int channel, struct ads1015_data *data = i2c_get_clientdata(client); unsigned int pga = data->channel_data[channel].pga; int fullscale = fullscale_table[pga]; - const unsigned mask = data->id == ads1115 ? 0x7fff : 0x7ff0; + const int mask = data->id == ads1115 ? 0x7fff : 0x7ff0; return DIV_ROUND_CLOSEST(reg * fullscale, mask); } diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c index 82de3deeb18a..685568b1236d 100644 --- a/drivers/hwmon/gpio-fan.c +++ b/drivers/hwmon/gpio-fan.c @@ -406,16 +406,11 @@ static int gpio_fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long *state) { struct gpio_fan_data *fan_data = cdev->devdata; - int r; if (!fan_data) return -EINVAL; - r = get_fan_speed_index(fan_data); - if (r < 0) - return r; - - *state = r; + *state = fan_data->speed_index; return 0; } diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index 3711df1d4526..4a45408dd820 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c @@ -586,8 +586,7 @@ static int brcmstb_i2c_probe(struct platform_device *pdev) if (!dev) return -ENOMEM; - dev->bsc_regmap = devm_kzalloc(&pdev->dev, sizeof(struct bsc_regs *), - GFP_KERNEL); + dev->bsc_regmap = devm_kzalloc(&pdev->dev, sizeof(*dev->bsc_regmap), GFP_KERNEL); if (!dev->bsc_regmap) return -ENOMEM; diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index f62d69799a9c..27fa0cb09538 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1271,6 +1271,8 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) switch (dev->device) { case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS: + case PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS: + case PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS: case PCI_DEVICE_ID_INTEL_DNV_SMBUS: priv->features |= FEATURE_I2C_BLOCK_READ; priv->features |= FEATURE_IRQ; diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 08d26ba61ed3..13c45296ce5b 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1450,7 +1450,8 @@ omap_i2c_probe(struct platform_device *pdev) err_unuse_clocks: omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, 0); - pm_runtime_put(omap->dev); + pm_runtime_dont_use_autosuspend(omap->dev); + pm_runtime_put_sync(omap->dev); pm_runtime_disable(&pdev->dev); err_free_mem: @@ -1468,6 +1469,7 @@ static int omap_i2c_remove(struct platform_device *pdev) return ret; omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, 0); + pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); return 0; diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c index f3e5ff8522f0..213ba55e17c3 100644 --- a/drivers/i2c/busses/i2c-uniphier-f.c +++ b/drivers/i2c/busses/i2c-uniphier-f.c @@ -467,7 +467,7 @@ static int uniphier_fi2c_clk_init(struct device *dev, bus_speed = UNIPHIER_FI2C_DEFAULT_SPEED; if (!bus_speed) { - dev_err(dev, "clock-freqyency should not be zero\n"); + dev_err(dev, "clock-frequency should not be zero\n"); return -EINVAL; } diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c index 1f4f3f53819c..89eaa8a7e1e0 100644 --- a/drivers/i2c/busses/i2c-uniphier.c +++ b/drivers/i2c/busses/i2c-uniphier.c @@ -328,7 +328,7 @@ static int uniphier_i2c_clk_init(struct device *dev, bus_speed = UNIPHIER_I2C_DEFAULT_SPEED; if (!bus_speed) { - dev_err(dev, "clock-freqyency should not be zero\n"); + dev_err(dev, "clock-frequency should not be zero\n"); return -EINVAL; } diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index 00da80e02154..94b80a51ab68 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -358,6 +358,7 @@ int ib_register_device(struct ib_device *device, ret = device->query_device(device, &device->attrs, &uhw); if (ret) { printk(KERN_WARNING "Couldn't query the device attributes\n"); + ib_cache_cleanup_one(device); goto out; } diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index f334090bb612..1e37f3515d98 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c @@ -1071,7 +1071,7 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num, } } - if (rec->hop_limit > 1 || use_roce) { + if (rec->hop_limit > 0 || use_roce) { ah_attr->ah_flags = IB_AH_GRH; ah_attr->grh.dgid = rec->dgid; diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 6ffc9c4e93af..6c6fbff19752 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1970,7 +1970,8 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, resp_size); INIT_UDATA(&uhw, buf + sizeof(cmd), (unsigned long)cmd.response + resp_size, - in_len - sizeof(cmd), out_len - resp_size); + in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr), + out_len - resp_size); memset(&cmd_ex, 0, sizeof(cmd_ex)); cmd_ex.user_handle = cmd.user_handle; @@ -3413,7 +3414,8 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, INIT_UDATA(&udata, buf + sizeof cmd, (unsigned long) cmd.response + sizeof resp, - in_len - sizeof cmd, out_len - sizeof resp); + in_len - sizeof cmd - sizeof(struct ib_uverbs_cmd_hdr), + out_len - sizeof resp); ret = __uverbs_create_xsrq(file, ib_dev, &xcmd, &udata); if (ret) @@ -3439,7 +3441,8 @@ ssize_t ib_uverbs_create_xsrq(struct ib_uverbs_file *file, INIT_UDATA(&udata, buf + sizeof cmd, (unsigned long) cmd.response + sizeof resp, - in_len - sizeof cmd, out_len - sizeof resp); + in_len - sizeof cmd - sizeof(struct ib_uverbs_cmd_hdr), + out_len - sizeof resp); ret = __uverbs_create_xsrq(file, ib_dev, &cmd, &udata); if (ret) diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 26833bfa639b..d68f506c1922 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -817,17 +817,48 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; } -static void edit_counter(struct mlx4_counter *cnt, - struct ib_pma_portcounters *pma_cnt) +static void edit_counter(struct mlx4_counter *cnt, void *counters, + __be16 attr_id) { - ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_data, - (be64_to_cpu(cnt->tx_bytes) >> 2)); - ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_data, - (be64_to_cpu(cnt->rx_bytes) >> 2)); - ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_packets, - be64_to_cpu(cnt->tx_frames)); - ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_packets, - be64_to_cpu(cnt->rx_frames)); + switch (attr_id) { + case IB_PMA_PORT_COUNTERS: + { + struct ib_pma_portcounters *pma_cnt = + (struct ib_pma_portcounters *)counters; + + ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_data, + (be64_to_cpu(cnt->tx_bytes) >> 2)); + ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_data, + (be64_to_cpu(cnt->rx_bytes) >> 2)); + ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_packets, + be64_to_cpu(cnt->tx_frames)); + ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_packets, + be64_to_cpu(cnt->rx_frames)); + break; + } + case IB_PMA_PORT_COUNTERS_EXT: + { + struct ib_pma_portcounters_ext *pma_cnt_ext = + (struct ib_pma_portcounters_ext *)counters; + + pma_cnt_ext->port_xmit_data = + cpu_to_be64(be64_to_cpu(cnt->tx_bytes) >> 2); + pma_cnt_ext->port_rcv_data = + cpu_to_be64(be64_to_cpu(cnt->rx_bytes) >> 2); + pma_cnt_ext->port_xmit_packets = cnt->tx_frames; + pma_cnt_ext->port_rcv_packets = cnt->rx_frames; + break; + } + } +} + +static int iboe_process_mad_port_info(void *out_mad) +{ + struct ib_class_port_info cpi = {}; + + cpi.capability_mask = IB_PMA_CLASS_CAP_EXT_WIDTH; + memcpy(out_mad, &cpi, sizeof(cpi)); + return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; } static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, @@ -842,6 +873,9 @@ static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_PERF_MGMT) return -EINVAL; + if (in_mad->mad_hdr.attr_id == IB_PMA_CLASS_PORT_INFO) + return iboe_process_mad_port_info((void *)(out_mad->data + 40)); + memset(&counter_stats, 0, sizeof(counter_stats)); mutex_lock(&dev->counters_table[port_num - 1].mutex); list_for_each_entry(tmp_counter, @@ -863,7 +897,8 @@ static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, switch (counter_stats.counter_mode & 0xf) { case 0: edit_counter(&counter_stats, - (void *)(out_mad->data + 40)); + (void *)(out_mad->data + 40), + in_mad->mad_hdr.attr_id); err = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; break; default: @@ -894,8 +929,10 @@ int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, */ if (link == IB_LINK_LAYER_INFINIBAND) { if (mlx4_is_slave(dev->dev) && - in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT && - in_mad->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS) + (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT && + (in_mad->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS || + in_mad->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS_EXT || + in_mad->mad_hdr.attr_id == IB_PMA_CLASS_PORT_INFO))) return iboe_process_mad(ibdev, mad_flags, port_num, in_wc, in_grh, in_mad, out_mad); diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index bc5536f00b6c..fd97534762b8 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -1681,9 +1681,12 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, } if (qp->ibqp.uobject) - context->usr_page = cpu_to_be32(to_mucontext(ibqp->uobject->context)->uar.index); + context->usr_page = cpu_to_be32( + mlx4_to_hw_uar_index(dev->dev, + to_mucontext(ibqp->uobject->context)->uar.index)); else - context->usr_page = cpu_to_be32(dev->priv_uar.index); + context->usr_page = cpu_to_be32( + mlx4_to_hw_uar_index(dev->dev, dev->priv_uar.index)); if (attr_mask & IB_QP_DEST_QPN) context->remote_qpn = cpu_to_be32(attr->dest_qp_num); diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c index 4659256cd95e..3b2ddd64a371 100644 --- a/drivers/infiniband/hw/mlx5/srq.c +++ b/drivers/infiniband/hw/mlx5/srq.c @@ -75,7 +75,8 @@ static void mlx5_ib_srq_event(struct mlx5_core_srq *srq, enum mlx5_event type) static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq, struct mlx5_create_srq_mbox_in **in, - struct ib_udata *udata, int buf_size, int *inlen) + struct ib_udata *udata, int buf_size, int *inlen, + int is_xrc) { struct mlx5_ib_dev *dev = to_mdev(pd->device); struct mlx5_ib_create_srq ucmd = {}; @@ -87,13 +88,8 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq, int ncont; u32 offset; u32 uidx = MLX5_IB_DEFAULT_UIDX; - int drv_data = udata->inlen - sizeof(struct ib_uverbs_cmd_hdr); - if (drv_data < 0) - return -EINVAL; - - ucmdlen = (drv_data < sizeof(ucmd)) ? - drv_data : sizeof(ucmd); + ucmdlen = min(udata->inlen, sizeof(ucmd)); if (ib_copy_from_udata(&ucmd, udata, ucmdlen)) { mlx5_ib_dbg(dev, "failed copy udata\n"); @@ -103,15 +99,17 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq, if (ucmd.reserved0 || ucmd.reserved1) return -EINVAL; - if (drv_data > sizeof(ucmd) && + if (udata->inlen > sizeof(ucmd) && !ib_is_udata_cleared(udata, sizeof(ucmd), - drv_data - sizeof(ucmd))) + udata->inlen - sizeof(ucmd))) return -EINVAL; - err = get_srq_user_index(to_mucontext(pd->uobject->context), - &ucmd, udata->inlen, &uidx); - if (err) - return err; + if (is_xrc) { + err = get_srq_user_index(to_mucontext(pd->uobject->context), + &ucmd, udata->inlen, &uidx); + if (err) + return err; + } srq->wq_sig = !!(ucmd.flags & MLX5_SRQ_FLAG_SIGNATURE); @@ -151,7 +149,8 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq, (*in)->ctx.log_pg_sz = page_shift - MLX5_ADAPTER_PAGE_SHIFT; (*in)->ctx.pgoff_cqn = cpu_to_be32(offset << 26); - if (MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1) { + if ((MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1) && + is_xrc){ xsrqc = MLX5_ADDR_OF(create_xrc_srq_in, *in, xrc_srq_context_entry); MLX5_SET(xrc_srqc, xsrqc, user_index, uidx); @@ -170,7 +169,7 @@ err_umem: static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq, struct mlx5_create_srq_mbox_in **in, int buf_size, - int *inlen) + int *inlen, int is_xrc) { int err; int i; @@ -224,7 +223,8 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq, (*in)->ctx.log_pg_sz = page_shift - MLX5_ADAPTER_PAGE_SHIFT; - if (MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1) { + if ((MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1) && + is_xrc){ xsrqc = MLX5_ADDR_OF(create_xrc_srq_in, *in, xrc_srq_context_entry); /* 0xffffff means we ask to work with cqe version 0 */ @@ -302,10 +302,14 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd, desc_size, init_attr->attr.max_wr, srq->msrq.max, srq->msrq.max_gs, srq->msrq.max_avail_gather); + is_xrc = (init_attr->srq_type == IB_SRQT_XRC); + if (pd->uobject) - err = create_srq_user(pd, srq, &in, udata, buf_size, &inlen); + err = create_srq_user(pd, srq, &in, udata, buf_size, &inlen, + is_xrc); else - err = create_srq_kernel(dev, srq, &in, buf_size, &inlen); + err = create_srq_kernel(dev, srq, &in, buf_size, &inlen, + is_xrc); if (err) { mlx5_ib_warn(dev, "create srq %s failed, err %d\n", @@ -313,7 +317,6 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd, goto err_srq; } - is_xrc = (init_attr->srq_type == IB_SRQT_XRC); in->ctx.state_log_sz = ilog2(srq->msrq.max); flgs = ((srq->msrq.wqe_shift - 4) | (is_xrc << 5) | (srq->wq_sig << 7)) << 24; xrcdn = 0; diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h index 040bb8b5cb15..12503f15fbd6 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma.h @@ -323,9 +323,6 @@ struct ocrdma_cq { */ u32 max_hw_cqe; bool phase_change; - bool deferred_arm, deferred_sol; - bool first_arm; - spinlock_t cq_lock ____cacheline_aligned; /* provide synchronization * to cq polling */ diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index 37620b4baafb..12420e4ecf3d 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -1094,7 +1094,6 @@ struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev, spin_lock_init(&cq->comp_handler_lock); INIT_LIST_HEAD(&cq->sq_head); INIT_LIST_HEAD(&cq->rq_head); - cq->first_arm = true; if (ib_ctx) { uctx = get_ocrdma_ucontext(ib_ctx); @@ -2910,12 +2909,9 @@ expand_cqe: } stop_cqe: cq->getp = cur_getp; - if (cq->deferred_arm || polled_hw_cqes) { - ocrdma_ring_cq_db(dev, cq->id, cq->deferred_arm, - cq->deferred_sol, polled_hw_cqes); - cq->deferred_arm = false; - cq->deferred_sol = false; - } + + if (polled_hw_cqes) + ocrdma_ring_cq_db(dev, cq->id, false, false, polled_hw_cqes); return i; } @@ -2999,13 +2995,7 @@ int ocrdma_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags cq_flags) if (cq_flags & IB_CQ_SOLICITED) sol_needed = true; - if (cq->first_arm) { - ocrdma_ring_cq_db(dev, cq_id, arm_needed, sol_needed, 0); - cq->first_arm = false; - } - - cq->deferred_arm = true; - cq->deferred_sol = sol_needed; + ocrdma_ring_cq_db(dev, cq_id, arm_needed, sol_needed, 0); spin_unlock_irqrestore(&cq->cq_lock, flags); return 0; diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index e5e223938eec..374c129219ef 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -114,6 +114,7 @@ struct kmem_cache *amd_iommu_irq_cache; static void update_domain(struct protection_domain *domain); static int protection_domain_init(struct protection_domain *domain); +static void detach_device(struct device *dev); /* * For dynamic growth the aperture size is split into ranges of 128MB of @@ -384,6 +385,9 @@ static void iommu_uninit_device(struct device *dev) if (!dev_data) return; + if (dev_data->domain) + detach_device(dev); + iommu_device_unlink(amd_iommu_rlookup_table[dev_data->devid]->iommu_dev, dev); diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 013bdfff2d4d..bf4959f4225b 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -228,6 +228,10 @@ static int amd_iommu_enable_interrupts(void); static int __init iommu_go_to_state(enum iommu_init_state state); static void init_device_table_dma(void); +static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu, + u8 bank, u8 cntr, u8 fxn, + u64 *value, bool is_write); + static inline void update_last_devid(u16 devid) { if (devid > amd_iommu_last_bdf) @@ -1016,6 +1020,34 @@ static void amd_iommu_erratum_746_workaround(struct amd_iommu *iommu) } /* + * Family15h Model 30h-3fh (IOMMU Mishandles ATS Write Permission) + * Workaround: + * BIOS should enable ATS write permission check by setting + * L2_DEBUG_3[AtsIgnoreIWDis](D0F2xF4_x47[0]) = 1b + */ +static void amd_iommu_ats_write_check_workaround(struct amd_iommu *iommu) +{ + u32 value; + + if ((boot_cpu_data.x86 != 0x15) || + (boot_cpu_data.x86_model < 0x30) || + (boot_cpu_data.x86_model > 0x3f)) + return; + + /* Test L2_DEBUG_3[AtsIgnoreIWDis] == 1 */ + value = iommu_read_l2(iommu, 0x47); + + if (value & BIT(0)) + return; + + /* Set L2_DEBUG_3[AtsIgnoreIWDis] = 1 */ + iommu_write_l2(iommu, 0x47, value | BIT(0)); + + pr_info("AMD-Vi: Applying ATS write check workaround for IOMMU at %s\n", + dev_name(&iommu->dev->dev)); +} + +/* * This function clues the initialization function for one IOMMU * together and also allocates the command buffer and programs the * hardware. It does NOT enable the IOMMU. This is done afterwards. @@ -1142,8 +1174,8 @@ static void init_iommu_perf_ctr(struct amd_iommu *iommu) amd_iommu_pc_present = true; /* Check if the performance counters can be written to */ - if ((0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val, true)) || - (0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val2, false)) || + if ((0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val, true)) || + (0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val2, false)) || (val != val2)) { pr_err("AMD-Vi: Unable to write to IOMMU perf counter.\n"); amd_iommu_pc_present = false; @@ -1284,6 +1316,7 @@ static int iommu_init_pci(struct amd_iommu *iommu) } amd_iommu_erratum_746_workaround(iommu); + amd_iommu_ats_write_check_workaround(iommu); iommu->iommu_dev = iommu_device_create(&iommu->dev->dev, iommu, amd_iommu_groups, "ivhd%d", @@ -2283,22 +2316,15 @@ u8 amd_iommu_pc_get_max_counters(u16 devid) } EXPORT_SYMBOL(amd_iommu_pc_get_max_counters); -int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, +static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu, + u8 bank, u8 cntr, u8 fxn, u64 *value, bool is_write) { - struct amd_iommu *iommu; u32 offset; u32 max_offset_lim; - /* Make sure the IOMMU PC resource is available */ - if (!amd_iommu_pc_present) - return -ENODEV; - - /* Locate the iommu associated with the device ID */ - iommu = amd_iommu_rlookup_table[devid]; - /* Check for valid iommu and pc register indexing */ - if (WARN_ON((iommu == NULL) || (fxn > 0x28) || (fxn & 7))) + if (WARN_ON((fxn > 0x28) || (fxn & 7))) return -ENODEV; offset = (u32)(((0x40|bank) << 12) | (cntr << 8) | fxn); @@ -2322,3 +2348,16 @@ int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, return 0; } EXPORT_SYMBOL(amd_iommu_pc_get_set_reg_val); + +int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, + u64 *value, bool is_write) +{ + struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; + + /* Make sure the IOMMU PC resource is available */ + if (!amd_iommu_pc_present || iommu == NULL) + return -ENODEV; + + return iommu_pc_get_set_reg_val(iommu, bank, cntr, fxn, + value, is_write); +} diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 62a400c5ba06..8ffd7568fc91 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -329,7 +329,8 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb, /* Only care about add/remove events for physical functions */ if (pdev->is_virtfn) return NOTIFY_DONE; - if (action != BUS_NOTIFY_ADD_DEVICE && action != BUS_NOTIFY_DEL_DEVICE) + if (action != BUS_NOTIFY_ADD_DEVICE && + action != BUS_NOTIFY_REMOVED_DEVICE) return NOTIFY_DONE; info = dmar_alloc_pci_notify_info(pdev, action); @@ -339,7 +340,7 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb, down_write(&dmar_global_lock); if (action == BUS_NOTIFY_ADD_DEVICE) dmar_pci_bus_add_dev(info); - else if (action == BUS_NOTIFY_DEL_DEVICE) + else if (action == BUS_NOTIFY_REMOVED_DEVICE) dmar_pci_bus_del_dev(info); up_write(&dmar_global_lock); @@ -1353,7 +1354,7 @@ void dmar_disable_qi(struct intel_iommu *iommu) raw_spin_lock_irqsave(&iommu->register_lock, flags); - sts = dmar_readq(iommu->reg + DMAR_GSTS_REG); + sts = readl(iommu->reg + DMAR_GSTS_REG); if (!(sts & DMA_GSTS_QIES)) goto end; diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 986a53e3eb96..a2e1b7f14df2 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4367,7 +4367,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info) rmrru->devices_cnt); if(ret < 0) return ret; - } else if (info->event == BUS_NOTIFY_DEL_DEVICE) { + } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) { dmar_remove_dev_scope(info, rmrr->segment, rmrru->devices, rmrru->devices_cnt); } @@ -4387,7 +4387,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info) break; else if(ret < 0) return ret; - } else if (info->event == BUS_NOTIFY_DEL_DEVICE) { + } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) { if (dmar_remove_dev_scope(info, atsr->segment, atsru->devices, atsru->devices_cnt)) break; diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index 50464833d0b8..d9939fa9b588 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c @@ -249,12 +249,30 @@ static void intel_flush_pasid_dev(struct intel_svm *svm, struct intel_svm_dev *s static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm) { struct intel_svm *svm = container_of(mn, struct intel_svm, notifier); + struct intel_svm_dev *sdev; + /* This might end up being called from exit_mmap(), *before* the page + * tables are cleared. And __mmu_notifier_release() will delete us from + * the list of notifiers so that our invalidate_range() callback doesn't + * get called when the page tables are cleared. So we need to protect + * against hardware accessing those page tables. + * + * We do it by clearing the entry in the PASID table and then flushing + * the IOTLB and the PASID table caches. This might upset hardware; + * perhaps we'll want to point the PASID to a dummy PGD (like the zero + * page) so that we end up taking a fault that the hardware really + * *has* to handle gracefully without affecting other processes. + */ svm->iommu->pasid_table[svm->pasid].val = 0; + wmb(); + + rcu_read_lock(); + list_for_each_entry_rcu(sdev, &svm->devs, list) { + intel_flush_pasid_dev(svm, sdev, svm->pasid); + intel_flush_svm_range_dev(svm, sdev, 0, -1, 0, !svm->mm); + } + rcu_read_unlock(); - /* There's no need to do any flush because we can't get here if there - * are any devices left anyway. */ - WARN_ON(!list_empty(&svm->devs)); } static const struct mmu_notifier_ops intel_mmuops = { @@ -379,7 +397,6 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_ goto out; } iommu->pasid_table[svm->pasid].val = (u64)__pa(mm->pgd) | 1; - mm = NULL; } else iommu->pasid_table[svm->pasid].val = (u64)__pa(init_mm.pgd) | 1 | (1ULL << 11); wmb(); @@ -442,11 +459,11 @@ int intel_svm_unbind_mm(struct device *dev, int pasid) kfree_rcu(sdev, rcu); if (list_empty(&svm->devs)) { - mmu_notifier_unregister(&svm->notifier, svm->mm); idr_remove(&svm->iommu->pasid_idr, svm->pasid); if (svm->mm) - mmput(svm->mm); + mmu_notifier_unregister(&svm->notifier, svm->mm); + /* We mandate that no page faults may be outstanding * for the PASID when intel_svm_unbind_mm() is called. * If that is not obeyed, subtle errors will happen. @@ -507,6 +524,10 @@ static irqreturn_t prq_event_thread(int irq, void *d) struct intel_svm *svm = NULL; int head, tail, handled = 0; + /* Clear PPR bit before reading head/tail registers, to + * ensure that we get a new interrupt if needed. */ + writel(DMA_PRS_PPR, iommu->reg + DMAR_PRS_REG); + tail = dmar_readq(iommu->reg + DMAR_PQT_REG) & PRQ_RING_MASK; head = dmar_readq(iommu->reg + DMAR_PQH_REG) & PRQ_RING_MASK; while (head != tail) { @@ -551,6 +572,9 @@ static irqreturn_t prq_event_thread(int irq, void *d) * any faults on kernel addresses. */ if (!svm->mm) goto bad_req; + /* If the mm is already defunct, don't handle faults. */ + if (!atomic_inc_not_zero(&svm->mm->mm_users)) + goto bad_req; down_read(&svm->mm->mmap_sem); vma = find_extend_vma(svm->mm, address); if (!vma || address < vma->vm_start) @@ -567,6 +591,7 @@ static irqreturn_t prq_event_thread(int irq, void *d) result = QI_RESP_SUCCESS; invalid: up_read(&svm->mm->mmap_sem); + mmput(svm->mm); bad_req: /* Accounting for major/minor faults? */ rcu_read_lock(); diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index c12ba4516df2..ac596928f6b4 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -629,7 +629,7 @@ static void iommu_disable_irq_remapping(struct intel_iommu *iommu) raw_spin_lock_irqsave(&iommu->register_lock, flags); - sts = dmar_readq(iommu->reg + DMAR_GSTS_REG); + sts = readl(iommu->reg + DMAR_GSTS_REG); if (!(sts & DMA_GSTS_IRES)) goto end; diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 0a73632b28d5..43dfd15c1dd2 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -78,6 +78,9 @@ struct its_node { #define ITS_ITT_ALIGN SZ_256 +/* Convert page order to size in bytes */ +#define PAGE_ORDER_TO_SIZE(o) (PAGE_SIZE << (o)) + struct event_lpi_map { unsigned long *lpi_map; u16 *col_map; @@ -600,11 +603,6 @@ static void its_unmask_irq(struct irq_data *d) lpi_set_config(d, true); } -static void its_eoi_irq(struct irq_data *d) -{ - gic_write_eoir(d->hwirq); -} - static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) { @@ -641,7 +639,7 @@ static struct irq_chip its_irq_chip = { .name = "ITS", .irq_mask = its_mask_irq, .irq_unmask = its_unmask_irq, - .irq_eoi = its_eoi_irq, + .irq_eoi = irq_chip_eoi_parent, .irq_set_affinity = its_set_affinity, .irq_compose_msi_msg = its_irq_compose_msi_msg, }; @@ -846,7 +844,6 @@ static int its_alloc_tables(const char *node_name, struct its_node *its) u64 type = GITS_BASER_TYPE(val); u64 entry_size = GITS_BASER_ENTRY_SIZE(val); int order = get_order(psz); - int alloc_size; int alloc_pages; u64 tmp; void *base; @@ -878,9 +875,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its) } } - alloc_size = (1 << order) * PAGE_SIZE; retry_alloc_baser: - alloc_pages = (alloc_size / psz); + alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz); if (alloc_pages > GITS_BASER_PAGES_MAX) { alloc_pages = GITS_BASER_PAGES_MAX; order = get_order(GITS_BASER_PAGES_MAX * psz); @@ -933,7 +929,7 @@ retry_baser: shr = tmp & GITS_BASER_SHAREABILITY_MASK; if (!shr) { cache = GITS_BASER_nC; - __flush_dcache_area(base, alloc_size); + __flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order)); } goto retry_baser; } @@ -966,7 +962,7 @@ retry_baser: } pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n", - (int)(alloc_size / entry_size), + (int)(PAGE_ORDER_TO_SIZE(order) / entry_size), its_base_type_string[type], (unsigned long)virt_to_phys(base), psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT); diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 2a506fe0c8a4..d1f8ab915b15 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -373,13 +373,7 @@ static void gigaset_freecshw(struct cardstate *cs) static void gigaset_device_release(struct device *dev) { - struct cardstate *cs = dev_get_drvdata(dev); - - if (!cs) - return; - dev_set_drvdata(dev, NULL); - kfree(cs->hw.ser); - cs->hw.ser = NULL; + kfree(container_of(dev, struct ser_cardstate, dev.dev)); } /* @@ -408,7 +402,6 @@ static int gigaset_initcshw(struct cardstate *cs) cs->hw.ser = NULL; return rc; } - dev_set_drvdata(&cs->hw.ser->dev.dev, cs); tasklet_init(&cs->write_tasklet, gigaset_modem_fill, (unsigned long) cs); diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c index 8e2944784e00..afde4edef9ae 100644 --- a/drivers/isdn/hardware/mISDN/netjet.c +++ b/drivers/isdn/hardware/mISDN/netjet.c @@ -392,7 +392,7 @@ read_dma(struct tiger_ch *bc, u32 idx, int cnt) } stat = bchannel_get_rxbuf(&bc->bch, cnt); /* only transparent use the count here, HDLC overun is detected later */ - if (stat == ENOMEM) { + if (stat == -ENOMEM) { pr_warning("%s.B%d: No memory for %d bytes\n", card->name, bc->bch.nr, cnt); return; diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index 33224cb91c5b..9f6acd5d1d2e 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -572,11 +572,13 @@ int nvm_register(struct request_queue *q, char *disk_name, } } - ret = nvm_get_sysblock(dev, &dev->sb); - if (!ret) - pr_err("nvm: device not initialized.\n"); - else if (ret < 0) - pr_err("nvm: err (%d) on device initialization\n", ret); + if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT) { + ret = nvm_get_sysblock(dev, &dev->sb); + if (!ret) + pr_err("nvm: device not initialized.\n"); + else if (ret < 0) + pr_err("nvm: err (%d) on device initialization\n", ret); + } /* register device with a supported media manager */ down_write(&nvm_lock); @@ -1055,9 +1057,11 @@ static long __nvm_ioctl_dev_init(struct nvm_ioctl_dev_init *init) strncpy(info.mmtype, init->mmtype, NVM_MMTYPE_LEN); info.fs_ppa.ppa = -1; - ret = nvm_init_sysblock(dev, &info); - if (ret) - return ret; + if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT) { + ret = nvm_init_sysblock(dev, &info); + if (ret) + return ret; + } memcpy(&dev->sb, &info, sizeof(struct nvm_sb_info)); @@ -1117,7 +1121,10 @@ static long nvm_ioctl_dev_factory(struct file *file, void __user *arg) dev->mt = NULL; } - return nvm_dev_factory(dev, fact.flags); + if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT) + return nvm_dev_factory(dev, fact.flags); + + return 0; } static long nvm_ctl_ioctl(struct file *file, uint cmd, unsigned long arg) diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c index d8c75958ced3..307db1ea22de 100644 --- a/drivers/lightnvm/rrpc.c +++ b/drivers/lightnvm/rrpc.c @@ -300,8 +300,10 @@ static int rrpc_move_valid_pages(struct rrpc *rrpc, struct rrpc_block *rblk) } page = mempool_alloc(rrpc->page_pool, GFP_NOIO); - if (!page) + if (!page) { + bio_put(bio); return -ENOMEM; + } while ((slot = find_first_zero_bit(rblk->invalid_pages, nr_pgs_per_blk)) < nr_pgs_per_blk) { diff --git a/drivers/lightnvm/rrpc.h b/drivers/lightnvm/rrpc.h index ef13ac7700c8..f7b37336353f 100644 --- a/drivers/lightnvm/rrpc.h +++ b/drivers/lightnvm/rrpc.h @@ -174,8 +174,7 @@ static inline sector_t rrpc_get_sector(sector_t laddr) static inline int request_intersects(struct rrpc_inflight_rq *r, sector_t laddr_start, sector_t laddr_end) { - return (laddr_end >= r->l_start && laddr_end <= r->l_end) && - (laddr_start >= r->l_start && laddr_start <= r->l_end); + return (laddr_end >= r->l_start) && (laddr_start <= r->l_end); } static int __rrpc_lock_laddr(struct rrpc *rrpc, sector_t laddr, @@ -184,6 +183,8 @@ static int __rrpc_lock_laddr(struct rrpc *rrpc, sector_t laddr, sector_t laddr_end = laddr + pages - 1; struct rrpc_inflight_rq *rtmp; + WARN_ON(irqs_disabled()); + spin_lock_irq(&rrpc->inflights.lock); list_for_each_entry(rtmp, &rrpc->inflights.reqs, list) { if (unlikely(request_intersects(rtmp, laddr, laddr_end))) { diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 5df40480228b..dd834927bc66 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1191,6 +1191,8 @@ static void dm_unprep_request(struct request *rq) if (clone) free_rq_clone(clone); + else if (!tio->md->queue->mq_ops) + free_rq_tio(tio); } /* diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c index 7e9cbf757e95..fb7ed730d932 100644 --- a/drivers/media/i2c/adp1653.c +++ b/drivers/media/i2c/adp1653.c @@ -497,7 +497,7 @@ static int adp1653_probe(struct i2c_client *client, if (!client->dev.platform_data) { dev_err(&client->dev, "Neither DT not platform data provided\n"); - return EINVAL; + return -EINVAL; } flash->platform_data = client->dev.platform_data; } diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index f8dd7505b529..e1719ffdfb3d 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -1960,10 +1960,9 @@ static int adv76xx_isr(struct v4l2_subdev *sd, u32 status, bool *handled) } /* tx 5v detect */ - tx_5v = io_read(sd, 0x70) & info->cable_det_mask; + tx_5v = irq_reg_0x70 & info->cable_det_mask; if (tx_5v) { v4l2_dbg(1, debug, sd, "%s: tx_5v: 0x%x\n", __func__, tx_5v); - io_write(sd, 0x71, tx_5v); adv76xx_s_detect_tx_5v_ctrl(sd); if (handled) *handled = true; diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 8c54fd21022e..a13625722848 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -1843,8 +1843,7 @@ static void au0828_analog_create_entities(struct au0828_dev *dev) ent->function = MEDIA_ENT_F_CONN_RF; break; default: /* AU0828_VMUX_DEBUG */ - ent->function = MEDIA_ENT_F_CONN_TEST; - break; + continue; } ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]); diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 4c1903f781fc..0c6c17a1c59e 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -415,7 +415,7 @@ static int cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev) delta = mftb() - psl_tb; if (delta < 0) delta = -delta; - } while (cputime_to_usecs(delta) > 16); + } while (tb_to_ns(delta) > 16000); return 0; } diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index b6639ea0bf18..f6e4d9718035 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2232,6 +2232,7 @@ err_irq: dma_release_channel(host->tx_chan); if (host->rx_chan) dma_release_channel(host->rx_chan); + pm_runtime_dont_use_autosuspend(host->dev); pm_runtime_put_sync(host->dev); pm_runtime_disable(host->dev); if (host->dbclk) @@ -2253,6 +2254,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) dma_release_channel(host->tx_chan); dma_release_channel(host->rx_chan); + pm_runtime_dont_use_autosuspend(host->dev); pm_runtime_put_sync(host->dev); pm_runtime_disable(host->dev); device_init_wakeup(&pdev->dev, false); diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index 2a1b6e037e1a..0134ba32a057 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c @@ -193,7 +193,7 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, vol->changing_leb = 1; vol->ch_lnum = req->lnum; - vol->upd_buf = vmalloc(req->bytes); + vol->upd_buf = vmalloc(ALIGN((int)req->bytes, ubi->min_io_size)); if (!vol->upd_buf) return -ENOMEM; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 56b560558884..b7f1a9919033 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -214,6 +214,8 @@ static void bond_uninit(struct net_device *bond_dev); static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev, struct rtnl_link_stats64 *stats); static void bond_slave_arr_handler(struct work_struct *work); +static bool bond_time_in_interval(struct bonding *bond, unsigned long last_act, + int mod); /*---------------------------- General routines -----------------------------*/ @@ -2127,6 +2129,7 @@ static void bond_miimon_commit(struct bonding *bond) continue; case BOND_LINK_UP: + bond_update_speed_duplex(slave); bond_set_slave_link_state(slave, BOND_LINK_UP, BOND_SLAVE_NOTIFY_NOW); slave->last_link_up = jiffies; @@ -2459,7 +2462,7 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, struct slave *slave) { struct arphdr *arp = (struct arphdr *)skb->data; - struct slave *curr_active_slave; + struct slave *curr_active_slave, *curr_arp_slave; unsigned char *arp_ptr; __be32 sip, tip; int alen, is_arp = skb->protocol == __cpu_to_be16(ETH_P_ARP); @@ -2506,26 +2509,41 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, &sip, &tip); curr_active_slave = rcu_dereference(bond->curr_active_slave); + curr_arp_slave = rcu_dereference(bond->current_arp_slave); - /* Backup slaves won't see the ARP reply, but do come through - * here for each ARP probe (so we swap the sip/tip to validate - * the probe). In a "redundant switch, common router" type of - * configuration, the ARP probe will (hopefully) travel from - * the active, through one switch, the router, then the other - * switch before reaching the backup. + /* We 'trust' the received ARP enough to validate it if: + * + * (a) the slave receiving the ARP is active (which includes the + * current ARP slave, if any), or + * + * (b) the receiving slave isn't active, but there is a currently + * active slave and it received valid arp reply(s) after it became + * the currently active slave, or + * + * (c) there is an ARP slave that sent an ARP during the prior ARP + * interval, and we receive an ARP reply on any slave. We accept + * these because switch FDB update delays may deliver the ARP + * reply to a slave other than the sender of the ARP request. * - * We 'trust' the arp requests if there is an active slave and - * it received valid arp reply(s) after it became active. This - * is done to avoid endless looping when we can't reach the + * Note: for (b), backup slaves are receiving the broadcast ARP + * request, not a reply. This request passes from the sending + * slave through the L2 switch(es) to the receiving slave. Since + * this is checking the request, sip/tip are swapped for + * validation. + * + * This is done to avoid endless looping when we can't reach the * arp_ip_target and fool ourselves with our own arp requests. */ - if (bond_is_active_slave(slave)) bond_validate_arp(bond, slave, sip, tip); else if (curr_active_slave && time_after(slave_last_rx(bond, curr_active_slave), curr_active_slave->last_link_up)) bond_validate_arp(bond, slave, tip, sip); + else if (curr_arp_slave && (arp->ar_op == htons(ARPOP_REPLY)) && + bond_time_in_interval(bond, + dev_trans_start(curr_arp_slave->dev), 1)) + bond_validate_arp(bond, slave, sip, tip); out_unlock: if (arp != (struct arphdr *)skb->data) diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index fc5b75675cd8..eb7192fab593 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -117,6 +117,9 @@ MODULE_LICENSE("GPL v2"); */ #define EMS_USB_ARM7_CLOCK 8000000 +#define CPC_TX_QUEUE_TRIGGER_LOW 25 +#define CPC_TX_QUEUE_TRIGGER_HIGH 35 + /* * CAN-Message representation in a CPC_MSG. Message object type is * CPC_MSG_TYPE_CAN_FRAME or CPC_MSG_TYPE_RTR_FRAME or @@ -278,6 +281,11 @@ static void ems_usb_read_interrupt_callback(struct urb *urb) switch (urb->status) { case 0: dev->free_slots = dev->intr_in_buffer[1]; + if(dev->free_slots > CPC_TX_QUEUE_TRIGGER_HIGH){ + if (netif_queue_stopped(netdev)){ + netif_wake_queue(netdev); + } + } break; case -ECONNRESET: /* unlink */ @@ -526,8 +534,6 @@ static void ems_usb_write_bulk_callback(struct urb *urb) /* Release context */ context->echo_index = MAX_TX_URBS; - if (netif_queue_stopped(netdev)) - netif_wake_queue(netdev); } /* @@ -587,7 +593,7 @@ static int ems_usb_start(struct ems_usb *dev) int err, i; dev->intr_in_buffer[0] = 0; - dev->free_slots = 15; /* initial size */ + dev->free_slots = 50; /* initial size */ for (i = 0; i < MAX_RX_URBS; i++) { struct urb *urb = NULL; @@ -835,7 +841,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne /* Slow down tx path */ if (atomic_read(&dev->active_tx_urbs) >= MAX_TX_URBS || - dev->free_slots < 5) { + dev->free_slots < CPC_TX_QUEUE_TRIGGER_LOW) { netif_stop_queue(netdev); } } diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index cc6c54553418..a47f52f44b0d 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -25,6 +25,7 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = { { PORT_SWITCH_ID_6172, "Marvell 88E6172" }, { PORT_SWITCH_ID_6176, "Marvell 88E6176" }, + { PORT_SWITCH_ID_6240, "Marvell 88E6240" }, { PORT_SWITCH_ID_6320, "Marvell 88E6320" }, { PORT_SWITCH_ID_6320_A1, "Marvell 88E6320 (A1)" }, { PORT_SWITCH_ID_6320_A2, "Marvell 88e6320 (A2)" }, diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index cf34681af4f6..512c8c0be1b4 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1555,7 +1555,7 @@ static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid) if (vlan.vid != vid || !vlan.valid || vlan.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) - return -ENOENT; + return -EOPNOTSUPP; vlan.data[port] = GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER; @@ -1582,6 +1582,7 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + const u16 defpvid = 4000 + ds->index * DSA_MAX_PORTS + port; u16 pvid, vid; int err = 0; @@ -1597,7 +1598,8 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, goto unlock; if (vid == pvid) { - err = _mv88e6xxx_port_pvid_set(ds, port, 0); + /* restore reserved VLAN ID */ + err = _mv88e6xxx_port_pvid_set(ds, port, defpvid); if (err) goto unlock; } @@ -1889,26 +1891,20 @@ unlock: int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, u32 members) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - const u16 pvid = 4000 + ds->index * DSA_MAX_PORTS + port; - int err; - - /* The port joined a bridge, so leave its reserved VLAN */ - mutex_lock(&ps->smi_mutex); - err = _mv88e6xxx_port_vlan_del(ds, port, pvid); - if (!err) - err = _mv88e6xxx_port_pvid_set(ds, port, 0); - mutex_unlock(&ps->smi_mutex); - return err; + return 0; } int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port, u32 members) { + return 0; +} + +static int mv88e6xxx_setup_port_default_vlan(struct dsa_switch *ds, int port) +{ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); const u16 pvid = 4000 + ds->index * DSA_MAX_PORTS + port; int err; - /* The port left the bridge, so join its reserved VLAN */ mutex_lock(&ps->smi_mutex); err = _mv88e6xxx_port_vlan_add(ds, port, pvid, true); if (!err) @@ -2192,8 +2188,7 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds) if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i)) continue; - /* setup the unbridged state */ - ret = mv88e6xxx_port_bridge_leave(ds, i, 0); + ret = mv88e6xxx_setup_port_default_vlan(ds, i); if (ret < 0) return ret; } diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c index 2777289a26c0..2f79d29f17f2 100644 --- a/drivers/net/ethernet/8390/pcnet_cs.c +++ b/drivers/net/ethernet/8390/pcnet_cs.c @@ -1501,6 +1501,7 @@ static const struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030a), PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103), PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121), + PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0009), PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941), PCMCIA_DEVICE_PROD_ID1234("Socket", "CF 10/100 Ethernet Card", "Revision B", "05/11/06", 0xb38bcc2e, 0x4de88352, 0xeaca6c8d, 0x7e57c22e), PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b), diff --git a/drivers/net/ethernet/agere/et131x.c b/drivers/net/ethernet/agere/et131x.c index 3f3bcbea15bd..0907ab6ff309 100644 --- a/drivers/net/ethernet/agere/et131x.c +++ b/drivers/net/ethernet/agere/et131x.c @@ -2380,7 +2380,7 @@ static int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter) sizeof(u32), &tx_ring->tx_status_pa, GFP_KERNEL); - if (!tx_ring->tx_status_pa) { + if (!tx_ring->tx_status) { dev_err(&adapter->pdev->dev, "Cannot alloc memory for Tx status block\n"); return -ENOMEM; diff --git a/drivers/net/ethernet/amd/am79c961a.c b/drivers/net/ethernet/amd/am79c961a.c index 87e727b921dc..fcdf5dda448f 100644 --- a/drivers/net/ethernet/amd/am79c961a.c +++ b/drivers/net/ethernet/amd/am79c961a.c @@ -50,8 +50,8 @@ static const char version[] = static void write_rreg(u_long base, u_int reg, u_int val) { asm volatile( - "str%?h %1, [%2] @ NET_RAP\n\t" - "str%?h %0, [%2, #-4] @ NET_RDP" + "strh %1, [%2] @ NET_RAP\n\t" + "strh %0, [%2, #-4] @ NET_RDP" : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464)); } @@ -60,8 +60,8 @@ static inline unsigned short read_rreg(u_long base_addr, u_int reg) { unsigned short v; asm volatile( - "str%?h %1, [%2] @ NET_RAP\n\t" - "ldr%?h %0, [%2, #-4] @ NET_RDP" + "strh %1, [%2] @ NET_RAP\n\t" + "ldrh %0, [%2, #-4] @ NET_RDP" : "=r" (v) : "r" (reg), "r" (ISAIO_BASE + 0x0464)); return v; @@ -70,8 +70,8 @@ static inline unsigned short read_rreg(u_long base_addr, u_int reg) static inline void write_ireg(u_long base, u_int reg, u_int val) { asm volatile( - "str%?h %1, [%2] @ NET_RAP\n\t" - "str%?h %0, [%2, #8] @ NET_IDP" + "strh %1, [%2] @ NET_RAP\n\t" + "strh %0, [%2, #8] @ NET_IDP" : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464)); } @@ -80,8 +80,8 @@ static inline unsigned short read_ireg(u_long base_addr, u_int reg) { u_short v; asm volatile( - "str%?h %1, [%2] @ NAT_RAP\n\t" - "ldr%?h %0, [%2, #8] @ NET_IDP\n\t" + "strh %1, [%2] @ NAT_RAP\n\t" + "ldrh %0, [%2, #8] @ NET_IDP\n\t" : "=r" (v) : "r" (reg), "r" (ISAIO_BASE + 0x0464)); return v; @@ -96,7 +96,7 @@ am_writebuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigne offset = ISAMEM_BASE + (offset << 1); length = (length + 1) & ~1; if ((int)buf & 2) { - asm volatile("str%?h %2, [%0], #4" + asm volatile("strh %2, [%0], #4" : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8))); buf += 2; length -= 2; @@ -104,20 +104,20 @@ am_writebuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigne while (length > 8) { register unsigned int tmp asm("r2"), tmp2 asm("r3"); asm volatile( - "ldm%?ia %0!, {%1, %2}" + "ldmia %0!, {%1, %2}" : "+r" (buf), "=&r" (tmp), "=&r" (tmp2)); length -= 8; asm volatile( - "str%?h %1, [%0], #4\n\t" - "mov%? %1, %1, lsr #16\n\t" - "str%?h %1, [%0], #4\n\t" - "str%?h %2, [%0], #4\n\t" - "mov%? %2, %2, lsr #16\n\t" - "str%?h %2, [%0], #4" + "strh %1, [%0], #4\n\t" + "mov %1, %1, lsr #16\n\t" + "strh %1, [%0], #4\n\t" + "strh %2, [%0], #4\n\t" + "mov %2, %2, lsr #16\n\t" + "strh %2, [%0], #4" : "+r" (offset), "=&r" (tmp), "=&r" (tmp2)); } while (length > 0) { - asm volatile("str%?h %2, [%0], #4" + asm volatile("strh %2, [%0], #4" : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8))); buf += 2; length -= 2; @@ -132,23 +132,23 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned if ((int)buf & 2) { unsigned int tmp; asm volatile( - "ldr%?h %2, [%0], #4\n\t" - "str%?b %2, [%1], #1\n\t" - "mov%? %2, %2, lsr #8\n\t" - "str%?b %2, [%1], #1" + "ldrh %2, [%0], #4\n\t" + "strb %2, [%1], #1\n\t" + "mov %2, %2, lsr #8\n\t" + "strb %2, [%1], #1" : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf)); length -= 2; } while (length > 8) { register unsigned int tmp asm("r2"), tmp2 asm("r3"), tmp3; asm volatile( - "ldr%?h %2, [%0], #4\n\t" - "ldr%?h %4, [%0], #4\n\t" - "ldr%?h %3, [%0], #4\n\t" - "orr%? %2, %2, %4, lsl #16\n\t" - "ldr%?h %4, [%0], #4\n\t" - "orr%? %3, %3, %4, lsl #16\n\t" - "stm%?ia %1!, {%2, %3}" + "ldrh %2, [%0], #4\n\t" + "ldrh %4, [%0], #4\n\t" + "ldrh %3, [%0], #4\n\t" + "orr %2, %2, %4, lsl #16\n\t" + "ldrh %4, [%0], #4\n\t" + "orr %3, %3, %4, lsl #16\n\t" + "stmia %1!, {%2, %3}" : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3) : "0" (offset), "1" (buf)); length -= 8; @@ -156,10 +156,10 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned while (length > 0) { unsigned int tmp; asm volatile( - "ldr%?h %2, [%0], #4\n\t" - "str%?b %2, [%1], #1\n\t" - "mov%? %2, %2, lsr #8\n\t" - "str%?b %2, [%1], #1" + "ldrh %2, [%0], #4\n\t" + "strb %2, [%1], #1\n\t" + "mov %2, %2, lsr #8\n\t" + "strb %2, [%1], #1" : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf)); length -= 2; } diff --git a/drivers/net/ethernet/amd/lance.c b/drivers/net/ethernet/amd/lance.c index 256f590f6bb1..3a7ebfdda57d 100644 --- a/drivers/net/ethernet/amd/lance.c +++ b/drivers/net/ethernet/amd/lance.c @@ -547,8 +547,8 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int /* Make certain the data structures used by the LANCE are aligned and DMAble. */ lp = kzalloc(sizeof(*lp), GFP_DMA | GFP_KERNEL); - if(lp==NULL) - return -ENODEV; + if (!lp) + return -ENOMEM; if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp); dev->ml_priv = lp; lp->name = chipname; diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index abe1eabc0171..6446af1403f7 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c @@ -163,7 +163,7 @@ static void arc_emac_tx_clean(struct net_device *ndev) struct sk_buff *skb = tx_buff->skb; unsigned int info = le32_to_cpu(txbd->info); - if ((info & FOR_EMAC) || !txbd->data) + if ((info & FOR_EMAC) || !txbd->data || !skb) break; if (unlikely(info & (DROP | DEFR | LTCL | UFLO))) { @@ -191,6 +191,7 @@ static void arc_emac_tx_clean(struct net_device *ndev) txbd->data = 0; txbd->info = 0; + tx_buff->skb = NULL; *txbd_dirty = (*txbd_dirty + 1) % TX_BD_NUM; } @@ -446,6 +447,9 @@ static int arc_emac_open(struct net_device *ndev) *last_rx_bd = (*last_rx_bd + 1) % RX_BD_NUM; } + priv->txbd_curr = 0; + priv->txbd_dirty = 0; + /* Clean Tx BD's */ memset(priv->txbd, 0, TX_RING_SZ); @@ -514,6 +518,64 @@ static void arc_emac_set_rx_mode(struct net_device *ndev) } /** + * arc_free_tx_queue - free skb from tx queue + * @ndev: Pointer to the network device. + * + * This function must be called while EMAC disable + */ +static void arc_free_tx_queue(struct net_device *ndev) +{ + struct arc_emac_priv *priv = netdev_priv(ndev); + unsigned int i; + + for (i = 0; i < TX_BD_NUM; i++) { + struct arc_emac_bd *txbd = &priv->txbd[i]; + struct buffer_state *tx_buff = &priv->tx_buff[i]; + + if (tx_buff->skb) { + dma_unmap_single(&ndev->dev, dma_unmap_addr(tx_buff, addr), + dma_unmap_len(tx_buff, len), DMA_TO_DEVICE); + + /* return the sk_buff to system */ + dev_kfree_skb_irq(tx_buff->skb); + } + + txbd->info = 0; + txbd->data = 0; + tx_buff->skb = NULL; + } +} + +/** + * arc_free_rx_queue - free skb from rx queue + * @ndev: Pointer to the network device. + * + * This function must be called while EMAC disable + */ +static void arc_free_rx_queue(struct net_device *ndev) +{ + struct arc_emac_priv *priv = netdev_priv(ndev); + unsigned int i; + + for (i = 0; i < RX_BD_NUM; i++) { + struct arc_emac_bd *rxbd = &priv->rxbd[i]; + struct buffer_state *rx_buff = &priv->rx_buff[i]; + + if (rx_buff->skb) { + dma_unmap_single(&ndev->dev, dma_unmap_addr(rx_buff, addr), + dma_unmap_len(rx_buff, len), DMA_FROM_DEVICE); + + /* return the sk_buff to system */ + dev_kfree_skb_irq(rx_buff->skb); + } + + rxbd->info = 0; + rxbd->data = 0; + rx_buff->skb = NULL; + } +} + +/** * arc_emac_stop - Close the network device. * @ndev: Pointer to the network device. * @@ -534,6 +596,10 @@ static int arc_emac_stop(struct net_device *ndev) /* Disable EMAC */ arc_reg_clr(priv, R_CTRL, EN_MASK); + /* Return the sk_buff to system */ + arc_free_tx_queue(ndev); + arc_free_rx_queue(ndev); + return 0; } @@ -610,7 +676,6 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) dma_unmap_addr_set(&priv->tx_buff[*txbd_curr], addr, addr); dma_unmap_len_set(&priv->tx_buff[*txbd_curr], len, len); - priv->tx_buff[*txbd_curr].skb = skb; priv->txbd[*txbd_curr].data = cpu_to_le32(addr); /* Make sure pointer to data buffer is set */ @@ -620,6 +685,11 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) *info = cpu_to_le32(FOR_EMAC | FIRST_OR_LAST_MASK | len); + /* Make sure info word is set */ + wmb(); + + priv->tx_buff[*txbd_curr].skb = skb; + /* Increment index to point to the next BD */ *txbd_curr = (*txbd_curr + 1) % TX_BD_NUM; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index d946bba43726..1fb80100e5e7 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -6185,26 +6185,80 @@ static int bnx2x_format_ver(u32 num, u8 *str, u16 *len) shift -= 4; digit = ((num & mask) >> shift); if (digit == 0 && remove_leading_zeros) { - mask = mask >> 4; - continue; - } else if (digit < 0xa) - *str_ptr = digit + '0'; - else - *str_ptr = digit - 0xa + 'a'; - remove_leading_zeros = 0; - str_ptr++; - (*len)--; + *str_ptr = '0'; + } else { + if (digit < 0xa) + *str_ptr = digit + '0'; + else + *str_ptr = digit - 0xa + 'a'; + + remove_leading_zeros = 0; + str_ptr++; + (*len)--; + } mask = mask >> 4; if (shift == 4*4) { + if (remove_leading_zeros) { + str_ptr++; + (*len)--; + } *str_ptr = '.'; str_ptr++; (*len)--; remove_leading_zeros = 1; } } + if (remove_leading_zeros) + (*len)--; return 0; } +static int bnx2x_3_seq_format_ver(u32 num, u8 *str, u16 *len) +{ + u8 *str_ptr = str; + u32 mask = 0x00f00000; + u8 shift = 8*3; + u8 digit; + u8 remove_leading_zeros = 1; + + if (*len < 10) { + /* Need more than 10chars for this format */ + *str_ptr = '\0'; + (*len)--; + return -EINVAL; + } + + while (shift > 0) { + shift -= 4; + digit = ((num & mask) >> shift); + if (digit == 0 && remove_leading_zeros) { + *str_ptr = '0'; + } else { + if (digit < 0xa) + *str_ptr = digit + '0'; + else + *str_ptr = digit - 0xa + 'a'; + + remove_leading_zeros = 0; + str_ptr++; + (*len)--; + } + mask = mask >> 4; + if ((shift == 4*4) || (shift == 4*2)) { + if (remove_leading_zeros) { + str_ptr++; + (*len)--; + } + *str_ptr = '.'; + str_ptr++; + (*len)--; + remove_leading_zeros = 1; + } + } + if (remove_leading_zeros) + (*len)--; + return 0; +} static int bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len) { @@ -9677,8 +9731,9 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy, if (bnx2x_is_8483x_8485x(phy)) { bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, 0x400f, &fw_ver1); - bnx2x_save_spirom_version(bp, port, fw_ver1 & 0xfff, - phy->ver_addr); + if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) + fw_ver1 &= 0xfff; + bnx2x_save_spirom_version(bp, port, fw_ver1, phy->ver_addr); } else { /* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */ /* (1) set reg 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */ @@ -9732,16 +9787,32 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy, static void bnx2x_848xx_set_led(struct bnx2x *bp, struct bnx2x_phy *phy) { - u16 val, offset, i; + u16 val, led3_blink_rate, offset, i; static struct bnx2x_reg_set reg_set[] = { {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0080}, {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED2_MASK, 0x0018}, {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_MASK, 0x0006}, - {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_BLINK, 0x0000}, {MDIO_PMA_DEVAD, MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH, MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ}, {MDIO_AN_DEVAD, 0xFFFB, 0xFFFD} }; + + if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) { + /* Set LED5 source */ + bnx2x_cl45_write(bp, phy, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_8481_LED5_MASK, + 0x90); + led3_blink_rate = 0x000f; + } else { + led3_blink_rate = 0x0000; + } + /* Set LED3 BLINK */ + bnx2x_cl45_write(bp, phy, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_8481_LED3_BLINK, + led3_blink_rate); + /* PHYC_CTL_LED_CTL */ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, @@ -9749,6 +9820,9 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp, val &= 0xFE00; val |= 0x0092; + if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) + val |= 2 << 12; /* LED5 ON based on source */ + bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LINK_SIGNAL, val); @@ -9762,10 +9836,17 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp, else offset = MDIO_PMA_REG_84823_CTL_LED_CTL_1; - /* stretch_en for LED3*/ + if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) + val = MDIO_PMA_REG_84858_ALLOW_GPHY_ACT | + MDIO_PMA_REG_84823_LED3_STRETCH_EN; + else + val = MDIO_PMA_REG_84823_LED3_STRETCH_EN; + + /* stretch_en for LEDs */ bnx2x_cl45_read_or_write(bp, phy, - MDIO_PMA_DEVAD, offset, - MDIO_PMA_REG_84823_LED3_STRETCH_EN); + MDIO_PMA_DEVAD, + offset, + val); } static void bnx2x_848xx_specific_func(struct bnx2x_phy *phy, @@ -9775,7 +9856,7 @@ static void bnx2x_848xx_specific_func(struct bnx2x_phy *phy, struct bnx2x *bp = params->bp; switch (action) { case PHY_INIT: - if (!bnx2x_is_8483x_8485x(phy)) { + if (bnx2x_is_8483x_8485x(phy)) { /* Save spirom version */ bnx2x_save_848xx_spirom_version(phy, bp, params->port); } @@ -10036,15 +10117,20 @@ static int bnx2x_84858_cmd_hdlr(struct bnx2x_phy *phy, static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy, struct link_params *params, u16 fw_cmd, - u16 cmd_args[], int argc) + u16 cmd_args[], int argc, int process) { int idx; u16 val; struct bnx2x *bp = params->bp; - /* Write CMD_OPEN_OVERRIDE to STATUS reg */ - bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, - MDIO_848xx_CMD_HDLR_STATUS, - PHY84833_STATUS_CMD_OPEN_OVERRIDE); + int rc = 0; + + if (process == PHY84833_MB_PROCESS2) { + /* Write CMD_OPEN_OVERRIDE to STATUS reg */ + bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, + MDIO_848xx_CMD_HDLR_STATUS, + PHY84833_STATUS_CMD_OPEN_OVERRIDE); + } + for (idx = 0; idx < PHY848xx_CMDHDLR_WAIT; idx++) { bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, MDIO_848xx_CMD_HDLR_STATUS, &val); @@ -10054,15 +10140,27 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy, } if (idx >= PHY848xx_CMDHDLR_WAIT) { DP(NETIF_MSG_LINK, "FW cmd: FW not ready.\n"); + /* if the status is CMD_COMPLETE_PASS or CMD_COMPLETE_ERROR + * clear the status to CMD_CLEAR_COMPLETE + */ + if (val == PHY84833_STATUS_CMD_COMPLETE_PASS || + val == PHY84833_STATUS_CMD_COMPLETE_ERROR) { + bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, + MDIO_848xx_CMD_HDLR_STATUS, + PHY84833_STATUS_CMD_CLEAR_COMPLETE); + } return -EINVAL; } - - /* Prepare argument(s) and issue command */ - for (idx = 0; idx < argc; idx++) { - bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, - MDIO_848xx_CMD_HDLR_DATA1 + idx, - cmd_args[idx]); + if (process == PHY84833_MB_PROCESS1 || + process == PHY84833_MB_PROCESS2) { + /* Prepare argument(s) */ + for (idx = 0; idx < argc; idx++) { + bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, + MDIO_848xx_CMD_HDLR_DATA1 + idx, + cmd_args[idx]); + } } + bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, MDIO_848xx_CMD_HDLR_COMMAND, fw_cmd); for (idx = 0; idx < PHY848xx_CMDHDLR_WAIT; idx++) { @@ -10076,24 +10174,30 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy, if ((idx >= PHY848xx_CMDHDLR_WAIT) || (val == PHY84833_STATUS_CMD_COMPLETE_ERROR)) { DP(NETIF_MSG_LINK, "FW cmd failed.\n"); - return -EINVAL; + rc = -EINVAL; } - /* Gather returning data */ - for (idx = 0; idx < argc; idx++) { - bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, - MDIO_848xx_CMD_HDLR_DATA1 + idx, - &cmd_args[idx]); + if (process == PHY84833_MB_PROCESS3 && rc == 0) { + /* Gather returning data */ + for (idx = 0; idx < argc; idx++) { + bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, + MDIO_848xx_CMD_HDLR_DATA1 + idx, + &cmd_args[idx]); + } } - bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, - MDIO_848xx_CMD_HDLR_STATUS, - PHY84833_STATUS_CMD_CLEAR_COMPLETE); - return 0; + if (val == PHY84833_STATUS_CMD_COMPLETE_ERROR || + val == PHY84833_STATUS_CMD_COMPLETE_PASS) { + bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, + MDIO_848xx_CMD_HDLR_STATUS, + PHY84833_STATUS_CMD_CLEAR_COMPLETE); + } + return rc; } static int bnx2x_848xx_cmd_hdlr(struct bnx2x_phy *phy, struct link_params *params, u16 fw_cmd, - u16 cmd_args[], int argc) + u16 cmd_args[], int argc, + int process) { struct bnx2x *bp = params->bp; @@ -10106,7 +10210,7 @@ static int bnx2x_848xx_cmd_hdlr(struct bnx2x_phy *phy, argc); } else { return bnx2x_84833_cmd_hdlr(phy, params, fw_cmd, cmd_args, - argc); + argc, process); } } @@ -10133,7 +10237,7 @@ static int bnx2x_848xx_pair_swap_cfg(struct bnx2x_phy *phy, status = bnx2x_848xx_cmd_hdlr(phy, params, PHY848xx_CMD_SET_PAIR_SWAP, data, - PHY848xx_CMDHDLR_MAX_ARGS); + 2, PHY84833_MB_PROCESS2); if (status == 0) DP(NETIF_MSG_LINK, "Pairswap OK, val=0x%x\n", data[1]); @@ -10222,8 +10326,8 @@ static int bnx2x_8483x_disable_eee(struct bnx2x_phy *phy, DP(NETIF_MSG_LINK, "Don't Advertise 10GBase-T EEE\n"); /* Prevent Phy from working in EEE and advertising it */ - rc = bnx2x_848xx_cmd_hdlr(phy, params, - PHY848xx_CMD_SET_EEE_MODE, &cmd_args, 1); + rc = bnx2x_848xx_cmd_hdlr(phy, params, PHY848xx_CMD_SET_EEE_MODE, + &cmd_args, 1, PHY84833_MB_PROCESS1); if (rc) { DP(NETIF_MSG_LINK, "EEE disable failed.\n"); return rc; @@ -10240,8 +10344,8 @@ static int bnx2x_8483x_enable_eee(struct bnx2x_phy *phy, struct bnx2x *bp = params->bp; u16 cmd_args = 1; - rc = bnx2x_848xx_cmd_hdlr(phy, params, - PHY848xx_CMD_SET_EEE_MODE, &cmd_args, 1); + rc = bnx2x_848xx_cmd_hdlr(phy, params, PHY848xx_CMD_SET_EEE_MODE, + &cmd_args, 1, PHY84833_MB_PROCESS1); if (rc) { DP(NETIF_MSG_LINK, "EEE enable failed.\n"); return rc; @@ -10362,7 +10466,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy, cmd_args[3] = PHY84833_CONSTANT_LATENCY; rc = bnx2x_848xx_cmd_hdlr(phy, params, PHY848xx_CMD_SET_EEE_MODE, cmd_args, - PHY848xx_CMDHDLR_MAX_ARGS); + 4, PHY84833_MB_PROCESS1); if (rc) DP(NETIF_MSG_LINK, "Cfg AutogrEEEn failed.\n"); } @@ -10416,6 +10520,32 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy, vars->eee_status &= ~SHMEM_EEE_SUPPORTED_MASK; } + if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) { + /* Additional settings for jumbo packets in 1000BASE-T mode */ + /* Allow rx extended length */ + bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_8481_AUX_CTRL, &val); + val |= 0x4000; + bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_8481_AUX_CTRL, val); + /* TX FIFO Elasticity LSB */ + bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_8481_1G_100T_EXT_CTRL, &val); + val |= 0x1; + bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_8481_1G_100T_EXT_CTRL, val); + /* TX FIFO Elasticity MSB */ + /* Enable expansion register 0x46 (Pattern Generator status) */ + bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_8481_EXPANSION_REG_ACCESS, 0xf46); + + bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_8481_EXPANSION_REG_RD_RW, &val); + val |= 0x4000; + bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_8481_EXPANSION_REG_RD_RW, val); + } + if (bnx2x_is_8483x_8485x(phy)) { /* Bring PHY out of super isolate mode as the final step. */ bnx2x_cl45_read_and_write(bp, phy, @@ -10555,6 +10685,17 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy, return link_up; } +static int bnx2x_8485x_format_ver(u32 raw_ver, u8 *str, u16 *len) +{ + int status = 0; + u32 num; + + num = ((raw_ver & 0xF80) >> 7) << 16 | ((raw_ver & 0x7F) << 8) | + ((raw_ver & 0xF000) >> 12); + status = bnx2x_3_seq_format_ver(num, str, len); + return status; +} + static int bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len) { int status = 0; @@ -10651,10 +10792,25 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, 0x0); } else { + /* LED 1 OFF */ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0); + + if (phy->type == + PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) { + /* LED 2 OFF */ + bnx2x_cl45_write(bp, phy, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_8481_LED2_MASK, + 0x0); + /* LED 3 OFF */ + bnx2x_cl45_write(bp, phy, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_8481_LED3_MASK, + 0x0); + } } break; case LED_MODE_FRONT_PANEL_OFF: @@ -10713,6 +10869,19 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, MDIO_PMA_REG_8481_SIGNAL_MASK, 0x0); } + if (phy->type == + PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) { + /* LED 2 OFF */ + bnx2x_cl45_write(bp, phy, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_8481_LED2_MASK, + 0x0); + /* LED 3 OFF */ + bnx2x_cl45_write(bp, phy, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_8481_LED3_MASK, + 0x0); + } } break; case LED_MODE_ON: @@ -10776,6 +10945,25 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, params->port*4, NIG_MASK_MI_INT); } + } + if (phy->type == + PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) { + /* Tell LED3 to constant on */ + bnx2x_cl45_read(bp, phy, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_8481_LINK_SIGNAL, + &val); + val &= ~(7<<6); + val |= (2<<6); /* A83B[8:6]= 2 */ + bnx2x_cl45_write(bp, phy, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_8481_LINK_SIGNAL, + val); + bnx2x_cl45_write(bp, phy, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_8481_LED3_MASK, + 0x20); + } else { bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_SIGNAL_MASK, @@ -10854,6 +11042,17 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, MDIO_PMA_REG_8481_LINK_SIGNAL, val); if (phy->type == + PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) { + bnx2x_cl45_write(bp, phy, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_8481_LED2_MASK, + 0x18); + bnx2x_cl45_write(bp, phy, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_8481_LED3_MASK, + 0x06); + } + if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) { /* Restore LED4 source to external link, * and re-enable interrupts. @@ -11982,7 +12181,7 @@ static const struct bnx2x_phy phy_84858 = { .read_status = (read_status_t)bnx2x_848xx_read_status, .link_reset = (link_reset_t)bnx2x_848x3_link_reset, .config_loopback = (config_loopback_t)NULL, - .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver, + .format_fw_ver = (format_fw_ver_t)bnx2x_8485x_format_ver, .hw_reset = (hw_reset_t)bnx2x_84833_hw_reset_phy, .set_link_led = (set_link_led_t)bnx2x_848xx_set_link_led, .phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func @@ -13807,8 +14006,10 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars) if (CHIP_IS_E3(bp)) { struct bnx2x_phy *phy = ¶ms->phy[INT_PHY]; bnx2x_set_aer_mmd(params, phy); - if ((phy->supported & SUPPORTED_20000baseKR2_Full) && - (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) + if (((phy->req_line_speed == SPEED_AUTO_NEG) && + (phy->speed_cap_mask & + PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) || + (phy->req_line_speed == SPEED_20000)) bnx2x_check_kr2_wa(params, vars, phy); bnx2x_check_over_curr(params, vars); if (vars->rx_tx_asic_rst) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h index 4dead49bd5cb..a43dea259b12 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h @@ -7296,6 +7296,8 @@ Theotherbitsarereservedandshouldbezero*/ #define MDIO_PMA_REG_84823_CTL_LED_CTL_1 0xa8e3 #define MDIO_PMA_REG_84833_CTL_LED_CTL_1 0xa8ec #define MDIO_PMA_REG_84823_LED3_STRETCH_EN 0x0080 +/* BCM84858 only */ +#define MDIO_PMA_REG_84858_ALLOW_GPHY_ACT 0x8000 /* BCM84833 only */ #define MDIO_84833_TOP_CFG_FW_REV 0x400f @@ -7337,6 +7339,10 @@ Theotherbitsarereservedandshouldbezero*/ #define PHY84833_STATUS_CMD_NOT_OPEN_FOR_CMDS 0x0040 #define PHY84833_STATUS_CMD_CLEAR_COMPLETE 0x0080 #define PHY84833_STATUS_CMD_OPEN_OVERRIDE 0xa5a5 +/* Mailbox Process */ +#define PHY84833_MB_PROCESS1 1 +#define PHY84833_MB_PROCESS2 2 +#define PHY84833_MB_PROCESS3 3 /* Mailbox status set used by 84858 only */ #define PHY84858_STATUS_CMD_RECEIVED 0x0001 diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 5dc89e527e7d..8ab000dd52d9 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -69,7 +69,7 @@ MODULE_VERSION(DRV_MODULE_VERSION); #define BNXT_RX_DMA_OFFSET NET_SKB_PAD #define BNXT_RX_COPY_THRESH 256 -#define BNXT_TX_PUSH_THRESH 92 +#define BNXT_TX_PUSH_THRESH 164 enum board_idx { BCM57301, @@ -223,11 +223,12 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) } if (free_size == bp->tx_ring_size && length <= bp->tx_push_thresh) { - struct tx_push_bd *push = txr->tx_push; - struct tx_bd *tx_push = &push->txbd1; - struct tx_bd_ext *tx_push1 = &push->txbd2; - void *pdata = tx_push1 + 1; - int j; + struct tx_push_buffer *tx_push_buf = txr->tx_push; + struct tx_push_bd *tx_push = &tx_push_buf->push_bd; + struct tx_bd_ext *tx_push1 = &tx_push->txbd2; + void *pdata = tx_push_buf->data; + u64 *end; + int j, push_len; /* Set COAL_NOW to be ready quickly for the next push */ tx_push->tx_bd_len_flags_type = @@ -247,6 +248,9 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) tx_push1->tx_bd_cfa_meta = cpu_to_le32(vlan_tag_flags); tx_push1->tx_bd_cfa_action = cpu_to_le32(cfa_action); + end = PTR_ALIGN(pdata + length + 1, 8) - 1; + *end = 0; + skb_copy_from_linear_data(skb, pdata, len); pdata += len; for (j = 0; j < last_frag; j++) { @@ -261,22 +265,29 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) pdata += skb_frag_size(frag); } - memcpy(txbd, tx_push, sizeof(*txbd)); + txbd->tx_bd_len_flags_type = tx_push->tx_bd_len_flags_type; + txbd->tx_bd_haddr = txr->data_mapping; prod = NEXT_TX(prod); txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)]; memcpy(txbd, tx_push1, sizeof(*txbd)); prod = NEXT_TX(prod); - push->doorbell = + tx_push->doorbell = cpu_to_le32(DB_KEY_TX_PUSH | DB_LONG_TX_PUSH | prod); txr->tx_prod = prod; netdev_tx_sent_queue(txq, skb->len); - __iowrite64_copy(txr->tx_doorbell, push, - (length + sizeof(*push) + 8) / 8); + push_len = (length + sizeof(*tx_push) + 7) / 8; + if (push_len > 16) { + __iowrite64_copy(txr->tx_doorbell, tx_push_buf, 16); + __iowrite64_copy(txr->tx_doorbell + 4, tx_push_buf + 1, + push_len - 16); + } else { + __iowrite64_copy(txr->tx_doorbell, tx_push_buf, + push_len); + } tx_buf->is_push = 1; - goto tx_done; } @@ -1753,7 +1764,7 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp) push_size = L1_CACHE_ALIGN(sizeof(struct tx_push_bd) + bp->tx_push_thresh); - if (push_size > 128) { + if (push_size > 256) { push_size = 0; bp->tx_push_thresh = 0; } @@ -1772,7 +1783,6 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp) return rc; if (bp->tx_push_size) { - struct tx_bd *txbd; dma_addr_t mapping; /* One pre-allocated DMA buffer to backup @@ -1786,13 +1796,11 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp) if (!txr->tx_push) return -ENOMEM; - txbd = &txr->tx_push->txbd1; - mapping = txr->tx_push_mapping + sizeof(struct tx_push_bd); - txbd->tx_bd_haddr = cpu_to_le64(mapping); + txr->data_mapping = cpu_to_le64(mapping); - memset(txbd + 1, 0, sizeof(struct tx_bd_ext)); + memset(txr->tx_push, 0, sizeof(struct tx_push_bd)); } ring->queue_id = bp->q_info[j].queue_id; if (i % bp->tx_nr_rings_per_tc == (bp->tx_nr_rings_per_tc - 1)) @@ -4546,20 +4554,18 @@ static int bnxt_update_phy_setting(struct bnxt *bp) if (!(link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) && link_info->force_pause_setting != link_info->req_flow_ctrl) update_pause = true; - if (link_info->req_duplex != link_info->duplex_setting) - update_link = true; if (!(link_info->autoneg & BNXT_AUTONEG_SPEED)) { if (BNXT_AUTO_MODE(link_info->auto_mode)) update_link = true; if (link_info->req_link_speed != link_info->force_link_speed) update_link = true; + if (link_info->req_duplex != link_info->duplex_setting) + update_link = true; } else { if (link_info->auto_mode == BNXT_LINK_AUTO_NONE) update_link = true; if (link_info->advertising != link_info->auto_link_speeds) update_link = true; - if (link_info->req_link_speed != link_info->auto_link_speed) - update_link = true; } if (update_link) @@ -4636,7 +4642,7 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) if (link_re_init) { rc = bnxt_update_phy_setting(bp); if (rc) - goto open_err; + netdev_warn(bp->dev, "failed to update phy settings\n"); } if (irq_re_init) { @@ -4654,6 +4660,7 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) /* Enable TX queues */ bnxt_tx_enable(bp); mod_timer(&bp->timer, jiffies + bp->current_interval); + bnxt_update_link(bp, true); return 0; @@ -5670,22 +5677,16 @@ static int bnxt_probe_phy(struct bnxt *bp) } /*initialize the ethool setting copy with NVM settings */ - if (BNXT_AUTO_MODE(link_info->auto_mode)) - link_info->autoneg |= BNXT_AUTONEG_SPEED; - - if (link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) { - if (link_info->auto_pause_setting == BNXT_LINK_PAUSE_BOTH) - link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL; + if (BNXT_AUTO_MODE(link_info->auto_mode)) { + link_info->autoneg = BNXT_AUTONEG_SPEED | + BNXT_AUTONEG_FLOW_CTRL; + link_info->advertising = link_info->auto_link_speeds; link_info->req_flow_ctrl = link_info->auto_pause_setting; - } else if (link_info->force_pause_setting & BNXT_LINK_PAUSE_BOTH) { + } else { + link_info->req_link_speed = link_info->force_link_speed; + link_info->req_duplex = link_info->duplex_setting; link_info->req_flow_ctrl = link_info->force_pause_setting; } - link_info->req_duplex = link_info->duplex_setting; - if (link_info->autoneg & BNXT_AUTONEG_SPEED) - link_info->req_link_speed = link_info->auto_link_speed; - else - link_info->req_link_speed = link_info->force_link_speed; - link_info->advertising = link_info->auto_link_speeds; snprintf(phy_ver, PHY_VER_STR_LEN, " ph %d.%d.%d", link_info->phy_ver[0], link_info->phy_ver[1], diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 8af3ca8efcef..2be51b332652 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -411,8 +411,8 @@ struct rx_tpa_end_cmp_ext { #define BNXT_NUM_TESTS(bp) 0 -#define BNXT_DEFAULT_RX_RING_SIZE 1023 -#define BNXT_DEFAULT_TX_RING_SIZE 512 +#define BNXT_DEFAULT_RX_RING_SIZE 511 +#define BNXT_DEFAULT_TX_RING_SIZE 511 #define MAX_TPA 64 @@ -523,10 +523,16 @@ struct bnxt_ring_struct { struct tx_push_bd { __le32 doorbell; - struct tx_bd txbd1; + __le32 tx_bd_len_flags_type; + u32 tx_bd_opaque; struct tx_bd_ext txbd2; }; +struct tx_push_buffer { + struct tx_push_bd push_bd; + u32 data[25]; +}; + struct bnxt_tx_ring_info { struct bnxt_napi *bnapi; u16 tx_prod; @@ -538,8 +544,9 @@ struct bnxt_tx_ring_info { dma_addr_t tx_desc_mapping[MAX_TX_PAGES]; - struct tx_push_bd *tx_push; + struct tx_push_buffer *tx_push; dma_addr_t tx_push_mapping; + __le64 data_mapping; #define BNXT_DEV_STATE_CLOSING 0x1 u32 dev_state; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 922b898e7a32..3238817dfd5f 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -486,15 +486,8 @@ static u32 bnxt_fw_to_ethtool_support_spds(struct bnxt_link_info *link_info) speed_mask |= SUPPORTED_2500baseX_Full; if (fw_speeds & BNXT_LINK_SPEED_MSK_10GB) speed_mask |= SUPPORTED_10000baseT_Full; - /* TODO: support 25GB, 50GB with different cable type */ - if (fw_speeds & BNXT_LINK_SPEED_MSK_20GB) - speed_mask |= SUPPORTED_20000baseMLD2_Full | - SUPPORTED_20000baseKR2_Full; if (fw_speeds & BNXT_LINK_SPEED_MSK_40GB) - speed_mask |= SUPPORTED_40000baseKR4_Full | - SUPPORTED_40000baseCR4_Full | - SUPPORTED_40000baseSR4_Full | - SUPPORTED_40000baseLR4_Full; + speed_mask |= SUPPORTED_40000baseCR4_Full; return speed_mask; } @@ -514,15 +507,8 @@ static u32 bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info) speed_mask |= ADVERTISED_2500baseX_Full; if (fw_speeds & BNXT_LINK_SPEED_MSK_10GB) speed_mask |= ADVERTISED_10000baseT_Full; - /* TODO: how to advertise 20, 25, 40, 50GB with different cable type ?*/ - if (fw_speeds & BNXT_LINK_SPEED_MSK_20GB) - speed_mask |= ADVERTISED_20000baseMLD2_Full | - ADVERTISED_20000baseKR2_Full; if (fw_speeds & BNXT_LINK_SPEED_MSK_40GB) - speed_mask |= ADVERTISED_40000baseKR4_Full | - ADVERTISED_40000baseCR4_Full | - ADVERTISED_40000baseSR4_Full | - ADVERTISED_40000baseLR4_Full; + speed_mask |= ADVERTISED_40000baseCR4_Full; return speed_mask; } @@ -557,11 +543,12 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) u16 ethtool_speed; cmd->supported = bnxt_fw_to_ethtool_support_spds(link_info); + cmd->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; if (link_info->auto_link_speeds) cmd->supported |= SUPPORTED_Autoneg; - if (BNXT_AUTO_MODE(link_info->auto_mode)) { + if (link_info->autoneg) { cmd->advertising = bnxt_fw_to_ethtool_advertised_spds(link_info); cmd->advertising |= ADVERTISED_Autoneg; @@ -570,28 +557,16 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->autoneg = AUTONEG_DISABLE; cmd->advertising = 0; } - if (link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) { + if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) { if ((link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) == BNXT_LINK_PAUSE_BOTH) { cmd->advertising |= ADVERTISED_Pause; - cmd->supported |= SUPPORTED_Pause; } else { cmd->advertising |= ADVERTISED_Asym_Pause; - cmd->supported |= SUPPORTED_Asym_Pause; if (link_info->auto_pause_setting & BNXT_LINK_PAUSE_RX) cmd->advertising |= ADVERTISED_Pause; } - } else if (link_info->force_pause_setting & BNXT_LINK_PAUSE_BOTH) { - if ((link_info->force_pause_setting & BNXT_LINK_PAUSE_BOTH) == - BNXT_LINK_PAUSE_BOTH) { - cmd->supported |= SUPPORTED_Pause; - } else { - cmd->supported |= SUPPORTED_Asym_Pause; - if (link_info->force_pause_setting & - BNXT_LINK_PAUSE_RX) - cmd->supported |= SUPPORTED_Pause; - } } cmd->port = PORT_NONE; @@ -670,6 +645,9 @@ static u16 bnxt_get_fw_auto_link_speeds(u32 advertising) if (advertising & ADVERTISED_10000baseT_Full) fw_speed_mask |= BNXT_LINK_SPEED_MSK_10GB; + if (advertising & ADVERTISED_40000baseCR4_Full) + fw_speed_mask |= BNXT_LINK_SPEED_MSK_40GB; + return fw_speed_mask; } @@ -729,7 +707,7 @@ static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) speed = ethtool_cmd_speed(cmd); link_info->req_link_speed = bnxt_get_fw_speed(dev, speed); link_info->req_duplex = BNXT_LINK_DUPLEX_FULL; - link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + link_info->autoneg = 0; link_info->advertising = 0; } @@ -748,8 +726,7 @@ static void bnxt_get_pauseparam(struct net_device *dev, if (BNXT_VF(bp)) return; - epause->autoneg = !!(link_info->auto_pause_setting & - BNXT_LINK_PAUSE_BOTH); + epause->autoneg = !!(link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL); epause->rx_pause = ((link_info->pause & BNXT_LINK_PAUSE_RX) != 0); epause->tx_pause = ((link_info->pause & BNXT_LINK_PAUSE_TX) != 0); } @@ -765,6 +742,9 @@ static int bnxt_set_pauseparam(struct net_device *dev, return rc; if (epause->autoneg) { + if (!(link_info->autoneg & BNXT_AUTONEG_SPEED)) + return -EINVAL; + link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL; link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_BOTH; } else { diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index b15a60d787c7..d7e01a74e927 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -2445,8 +2445,7 @@ static void bcmgenet_irq_task(struct work_struct *work) } /* Link UP/DOWN event */ - if ((priv->hw_params->flags & GENET_HAS_MDIO_INTR) && - (priv->irq0_stat & UMAC_IRQ_LINK_EVENT)) { + if (priv->irq0_stat & UMAC_IRQ_LINK_EVENT) { phy_mac_interrupt(priv->phydev, !!(priv->irq0_stat & UMAC_IRQ_LINK_UP)); priv->irq0_stat &= ~UMAC_IRQ_LINK_EVENT; diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index 872765527081..34d269cd5579 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -1683,7 +1683,7 @@ static int octeon_setup_droq(struct octeon_device *oct, int q_no, int num_descs, dev_dbg(&oct->pci_dev->dev, "Creating Droq: %d\n", q_no); /* droq creation and local register settings. */ ret_val = octeon_create_droq(oct, q_no, num_descs, desc_size, app_ctx); - if (ret_val == -1) + if (ret_val < 0) return ret_val; if (ret_val == 1) { @@ -2524,7 +2524,7 @@ static void handle_timestamp(struct octeon_device *oct, octeon_swap_8B_data(&resp->timestamp, 1); - if (unlikely((skb_shinfo(skb)->tx_flags | SKBTX_IN_PROGRESS) != 0)) { + if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) != 0)) { struct skb_shared_hwtstamps ts; u64 ns = resp->timestamp; diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c index 4dba86eaa045..174072b3740b 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c @@ -983,5 +983,5 @@ int octeon_create_droq(struct octeon_device *oct, create_droq_fail: octeon_delete_droq(oct, q_no); - return -1; + return -ENOMEM; } diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index c24cb2a86a42..a009bc30dc4d 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -574,8 +574,7 @@ static inline void nicvf_set_rxhash(struct net_device *netdev, static void nicvf_rcv_pkt_handler(struct net_device *netdev, struct napi_struct *napi, - struct cmp_queue *cq, - struct cqe_rx_t *cqe_rx, int cqe_type) + struct cqe_rx_t *cqe_rx) { struct sk_buff *skb; struct nicvf *nic = netdev_priv(netdev); @@ -591,7 +590,7 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev, } /* Check for errors */ - err = nicvf_check_cqe_rx_errs(nic, cq, cqe_rx); + err = nicvf_check_cqe_rx_errs(nic, cqe_rx); if (err && !cqe_rx->rb_cnt) return; @@ -682,8 +681,7 @@ loop: cq_idx, cq_desc->cqe_type); switch (cq_desc->cqe_type) { case CQE_TYPE_RX: - nicvf_rcv_pkt_handler(netdev, napi, cq, - cq_desc, CQE_TYPE_RX); + nicvf_rcv_pkt_handler(netdev, napi, cq_desc); work_done++; break; case CQE_TYPE_SEND: @@ -1125,7 +1123,6 @@ int nicvf_stop(struct net_device *netdev) /* Clear multiqset info */ nic->pnicvf = nic; - nic->sqs_count = 0; return 0; } @@ -1354,6 +1351,9 @@ void nicvf_update_stats(struct nicvf *nic) drv_stats->tx_frames_ok = stats->tx_ucast_frames_ok + stats->tx_bcast_frames_ok + stats->tx_mcast_frames_ok; + drv_stats->rx_frames_ok = stats->rx_ucast_frames + + stats->rx_bcast_frames + + stats->rx_mcast_frames; drv_stats->rx_drops = stats->rx_drop_red + stats->rx_drop_overrun; drv_stats->tx_drops = stats->tx_drops; @@ -1538,6 +1538,9 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) nicvf_send_vf_struct(nic); + if (!pass1_silicon(nic->pdev)) + nic->hw_tso = true; + /* Check if this VF is in QS only mode */ if (nic->sqs_mode) return 0; @@ -1557,9 +1560,6 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; - if (!pass1_silicon(nic->pdev)) - nic->hw_tso = true; - netdev->netdev_ops = &nicvf_netdev_ops; netdev->watchdog_timeo = NICVF_TX_TIMEOUT; diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index d0d1b5490061..767347b1f631 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -1329,16 +1329,12 @@ void nicvf_update_sq_stats(struct nicvf *nic, int sq_idx) } /* Check for errors in the receive cmp.queue entry */ -int nicvf_check_cqe_rx_errs(struct nicvf *nic, - struct cmp_queue *cq, struct cqe_rx_t *cqe_rx) +int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx) { struct nicvf_hw_stats *stats = &nic->hw_stats; - struct nicvf_drv_stats *drv_stats = &nic->drv_stats; - if (!cqe_rx->err_level && !cqe_rx->err_opcode) { - drv_stats->rx_frames_ok++; + if (!cqe_rx->err_level && !cqe_rx->err_opcode) return 0; - } if (netif_msg_rx_err(nic)) netdev_err(nic->netdev, diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h index c5030a7f213a..6673e1133523 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h @@ -338,8 +338,7 @@ u64 nicvf_queue_reg_read(struct nicvf *nic, /* Stats */ void nicvf_update_rq_stats(struct nicvf *nic, int rq_idx); void nicvf_update_sq_stats(struct nicvf *nic, int sq_idx); -int nicvf_check_cqe_rx_errs(struct nicvf *nic, - struct cmp_queue *cq, struct cqe_rx_t *cqe_rx); +int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx); int nicvf_check_cqe_tx_errs(struct nicvf *nic, struct cmp_queue *cq, struct cqe_send_t *cqe_tx); #endif /* NICVF_QUEUES_H */ diff --git a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c index ee04caa6c4d8..a89721fad633 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c @@ -681,6 +681,24 @@ int t3_seeprom_wp(struct adapter *adapter, int enable) return t3_seeprom_write(adapter, EEPROM_STAT_ADDR, enable ? 0xc : 0); } +static int vpdstrtouint(char *s, int len, unsigned int base, unsigned int *val) +{ + char tok[len + 1]; + + memcpy(tok, s, len); + tok[len] = 0; + return kstrtouint(strim(tok), base, val); +} + +static int vpdstrtou16(char *s, int len, unsigned int base, u16 *val) +{ + char tok[len + 1]; + + memcpy(tok, s, len); + tok[len] = 0; + return kstrtou16(strim(tok), base, val); +} + /** * get_vpd_params - read VPD parameters from VPD EEPROM * @adapter: adapter to read @@ -709,19 +727,19 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p) return ret; } - ret = kstrtouint(vpd.cclk_data, 10, &p->cclk); + ret = vpdstrtouint(vpd.cclk_data, vpd.cclk_len, 10, &p->cclk); if (ret) return ret; - ret = kstrtouint(vpd.mclk_data, 10, &p->mclk); + ret = vpdstrtouint(vpd.mclk_data, vpd.mclk_len, 10, &p->mclk); if (ret) return ret; - ret = kstrtouint(vpd.uclk_data, 10, &p->uclk); + ret = vpdstrtouint(vpd.uclk_data, vpd.uclk_len, 10, &p->uclk); if (ret) return ret; - ret = kstrtouint(vpd.mdc_data, 10, &p->mdc); + ret = vpdstrtouint(vpd.mdc_data, vpd.mdc_len, 10, &p->mdc); if (ret) return ret; - ret = kstrtouint(vpd.mt_data, 10, &p->mem_timing); + ret = vpdstrtouint(vpd.mt_data, vpd.mt_len, 10, &p->mem_timing); if (ret) return ret; memcpy(p->sn, vpd.sn_data, SERNUM_LEN); @@ -733,10 +751,12 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p) } else { p->port_type[0] = hex_to_bin(vpd.port0_data[0]); p->port_type[1] = hex_to_bin(vpd.port1_data[0]); - ret = kstrtou16(vpd.xaui0cfg_data, 16, &p->xauicfg[0]); + ret = vpdstrtou16(vpd.xaui0cfg_data, vpd.xaui0cfg_len, 16, + &p->xauicfg[0]); if (ret) return ret; - ret = kstrtou16(vpd.xaui1cfg_data, 16, &p->xauicfg[1]); + ret = vpdstrtou16(vpd.xaui1cfg_data, vpd.xaui1cfg_len, 16, + &p->xauicfg[1]); if (ret) return ret; } diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h b/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h index a8dda635456d..06bc2d2e7a73 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h @@ -165,6 +165,7 @@ CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN CH_PCI_ID_TABLE_FENTRY(0x5098), /* Custom 2x40G QSFP */ CH_PCI_ID_TABLE_FENTRY(0x5099), /* Custom 2x40G QSFP */ CH_PCI_ID_TABLE_FENTRY(0x509a), /* Custom T520-CR */ + CH_PCI_ID_TABLE_FENTRY(0x509b), /* Custom T540-CR LOM */ /* T6 adapters: */ diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index cf94b72dbacd..48d91941408d 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -128,7 +128,6 @@ struct board_info { struct resource *data_res; struct resource *addr_req; /* resources requested */ struct resource *data_req; - struct resource *irq_res; int irq_wake; @@ -1300,22 +1299,16 @@ static int dm9000_open(struct net_device *dev) { struct board_info *db = netdev_priv(dev); - unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK; if (netif_msg_ifup(db)) dev_dbg(db->dev, "enabling %s\n", dev->name); - /* If there is no IRQ type specified, default to something that - * may work, and tell the user that this is a problem */ - - if (irqflags == IRQF_TRIGGER_NONE) - irqflags = irq_get_trigger_type(dev->irq); - - if (irqflags == IRQF_TRIGGER_NONE) + /* If there is no IRQ type specified, tell the user that this is a + * problem + */ + if (irq_get_trigger_type(dev->irq) == IRQF_TRIGGER_NONE) dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n"); - irqflags |= IRQF_SHARED; - /* GPIO0 on pre-activate PHY, Reg 1F is not set by reset */ iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */ mdelay(1); /* delay needs by DM9000B */ @@ -1323,7 +1316,8 @@ dm9000_open(struct net_device *dev) /* Initialize DM9000 board */ dm9000_init_dm9000(dev); - if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev)) + if (request_irq(dev->irq, dm9000_interrupt, IRQF_SHARED, + dev->name, dev)) return -EAGAIN; /* Now that we have an interrupt handler hooked up we can unmask * our interrupts @@ -1500,15 +1494,22 @@ dm9000_probe(struct platform_device *pdev) db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (db->addr_res == NULL || db->data_res == NULL || - db->irq_res == NULL) { - dev_err(db->dev, "insufficient resources\n"); + if (!db->addr_res || !db->data_res) { + dev_err(db->dev, "insufficient resources addr=%p data=%p\n", + db->addr_res, db->data_res); ret = -ENOENT; goto out; } + ndev->irq = platform_get_irq(pdev, 0); + if (ndev->irq < 0) { + dev_err(db->dev, "interrupt resource unavailable: %d\n", + ndev->irq); + ret = ndev->irq; + goto out; + } + db->irq_wake = platform_get_irq(pdev, 1); if (db->irq_wake >= 0) { dev_dbg(db->dev, "wakeup irq %d\n", db->irq_wake); @@ -1570,7 +1571,6 @@ dm9000_probe(struct platform_device *pdev) /* fill in parameters for net-dev structure */ ndev->base_addr = (unsigned long)db->io_addr; - ndev->irq = db->irq_res->start; /* ensure at least we have a default set of IO routines */ dm9000_set_io(db, iosize); diff --git a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c index a7139f588ad2..678f5018d0be 100644 --- a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c +++ b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c @@ -469,8 +469,8 @@ static int fmvj18x_config(struct pcmcia_device *link) goto failed; } /* Read MACID from CIS */ - for (i = 5; i < 11; i++) - dev->dev_addr[i] = buf[i]; + for (i = 0; i < 6; i++) + dev->dev_addr[i] = buf[i + 5]; kfree(buf); } else { if (pcmcia_get_mac_from_cis(link, dev)) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 662c2ee268c7..b0ae69f84493 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -370,6 +370,11 @@ struct mvneta_port { struct net_device *dev; struct notifier_block cpu_notifier; int rxq_def; + /* Protect the access to the percpu interrupt registers, + * ensuring that the configuration remains coherent. + */ + spinlock_t lock; + bool is_stopped; /* Core clock */ struct clk *clk; @@ -1038,6 +1043,43 @@ static void mvneta_set_autoneg(struct mvneta_port *pp, int enable) } } +static void mvneta_percpu_unmask_interrupt(void *arg) +{ + struct mvneta_port *pp = arg; + + /* All the queue are unmasked, but actually only the ones + * mapped to this CPU will be unmasked + */ + mvreg_write(pp, MVNETA_INTR_NEW_MASK, + MVNETA_RX_INTR_MASK_ALL | + MVNETA_TX_INTR_MASK_ALL | + MVNETA_MISCINTR_INTR_MASK); +} + +static void mvneta_percpu_mask_interrupt(void *arg) +{ + struct mvneta_port *pp = arg; + + /* All the queue are masked, but actually only the ones + * mapped to this CPU will be masked + */ + mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); + mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); + mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); +} + +static void mvneta_percpu_clear_intr_cause(void *arg) +{ + struct mvneta_port *pp = arg; + + /* All the queue are cleared, but actually only the ones + * mapped to this CPU will be cleared + */ + mvreg_write(pp, MVNETA_INTR_NEW_CAUSE, 0); + mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0); + mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0); +} + /* This method sets defaults to the NETA port: * Clears interrupt Cause and Mask registers. * Clears all MAC tables. @@ -1055,14 +1097,10 @@ static void mvneta_defaults_set(struct mvneta_port *pp) int max_cpu = num_present_cpus(); /* Clear all Cause registers */ - mvreg_write(pp, MVNETA_INTR_NEW_CAUSE, 0); - mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0); - mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0); + on_each_cpu(mvneta_percpu_clear_intr_cause, pp, true); /* Mask all interrupts */ - mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); - mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); - mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); + on_each_cpu(mvneta_percpu_mask_interrupt, pp, true); mvreg_write(pp, MVNETA_INTR_ENABLE, 0); /* Enable MBUS Retry bit16 */ @@ -2528,34 +2566,9 @@ static int mvneta_setup_txqs(struct mvneta_port *pp) return 0; } -static void mvneta_percpu_unmask_interrupt(void *arg) -{ - struct mvneta_port *pp = arg; - - /* All the queue are unmasked, but actually only the ones - * maped to this CPU will be unmasked - */ - mvreg_write(pp, MVNETA_INTR_NEW_MASK, - MVNETA_RX_INTR_MASK_ALL | - MVNETA_TX_INTR_MASK_ALL | - MVNETA_MISCINTR_INTR_MASK); -} - -static void mvneta_percpu_mask_interrupt(void *arg) -{ - struct mvneta_port *pp = arg; - - /* All the queue are masked, but actually only the ones - * maped to this CPU will be masked - */ - mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); - mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); - mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); -} - static void mvneta_start_dev(struct mvneta_port *pp) { - unsigned int cpu; + int cpu; mvneta_max_rx_size_set(pp, pp->pkt_size); mvneta_txq_max_tx_size_set(pp, pp->pkt_size); @@ -2564,16 +2577,15 @@ static void mvneta_start_dev(struct mvneta_port *pp) mvneta_port_enable(pp); /* Enable polling on the port */ - for_each_present_cpu(cpu) { + for_each_online_cpu(cpu) { struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu); napi_enable(&port->napi); } /* Unmask interrupts. It has to be done from each CPU */ - for_each_online_cpu(cpu) - smp_call_function_single(cpu, mvneta_percpu_unmask_interrupt, - pp, true); + on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true); + mvreg_write(pp, MVNETA_INTR_MISC_MASK, MVNETA_CAUSE_PHY_STATUS_CHANGE | MVNETA_CAUSE_LINK_CHANGE | @@ -2589,7 +2601,7 @@ static void mvneta_stop_dev(struct mvneta_port *pp) phy_stop(pp->phy_dev); - for_each_present_cpu(cpu) { + for_each_online_cpu(cpu) { struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu); napi_disable(&port->napi); @@ -2604,13 +2616,10 @@ static void mvneta_stop_dev(struct mvneta_port *pp) mvneta_port_disable(pp); /* Clear all ethernet port interrupts */ - mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0); - mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0); + on_each_cpu(mvneta_percpu_clear_intr_cause, pp, true); /* Mask all ethernet port interrupts */ - mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); - mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); - mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); + on_each_cpu(mvneta_percpu_mask_interrupt, pp, true); mvneta_tx_reset(pp); mvneta_rx_reset(pp); @@ -2847,11 +2856,20 @@ static void mvneta_percpu_disable(void *arg) disable_percpu_irq(pp->dev->irq); } +/* Electing a CPU must be done in an atomic way: it should be done + * after or before the removal/insertion of a CPU and this function is + * not reentrant. + */ static void mvneta_percpu_elect(struct mvneta_port *pp) { - int online_cpu_idx, max_cpu, cpu, i = 0; + int elected_cpu = 0, max_cpu, cpu, i = 0; + + /* Use the cpu associated to the rxq when it is online, in all + * the other cases, use the cpu 0 which can't be offline. + */ + if (cpu_online(pp->rxq_def)) + elected_cpu = pp->rxq_def; - online_cpu_idx = pp->rxq_def % num_online_cpus(); max_cpu = num_present_cpus(); for_each_online_cpu(cpu) { @@ -2862,7 +2880,7 @@ static void mvneta_percpu_elect(struct mvneta_port *pp) if ((rxq % max_cpu) == cpu) rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq); - if (i == online_cpu_idx) + if (cpu == elected_cpu) /* Map the default receive queue queue to the * elected CPU */ @@ -2873,7 +2891,7 @@ static void mvneta_percpu_elect(struct mvneta_port *pp) * the CPU bound to the default RX queue */ if (txq_number == 1) - txq_map = (i == online_cpu_idx) ? + txq_map = (cpu == elected_cpu) ? MVNETA_CPU_TXQ_ACCESS(1) : 0; else txq_map = mvreg_read(pp, MVNETA_CPU_MAP(cpu)) & @@ -2902,6 +2920,14 @@ static int mvneta_percpu_notifier(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: case CPU_ONLINE_FROZEN: + spin_lock(&pp->lock); + /* Configuring the driver for a new CPU while the + * driver is stopping is racy, so just avoid it. + */ + if (pp->is_stopped) { + spin_unlock(&pp->lock); + break; + } netif_tx_stop_all_queues(pp->dev); /* We have to synchronise on tha napi of each CPU @@ -2917,9 +2943,7 @@ static int mvneta_percpu_notifier(struct notifier_block *nfb, } /* Mask all ethernet port interrupts */ - mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); - mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); - mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); + on_each_cpu(mvneta_percpu_mask_interrupt, pp, true); napi_enable(&port->napi); @@ -2934,27 +2958,25 @@ static int mvneta_percpu_notifier(struct notifier_block *nfb, */ mvneta_percpu_elect(pp); - /* Unmask all ethernet port interrupts, as this - * notifier is called for each CPU then the CPU to - * Queue mapping is applied - */ - mvreg_write(pp, MVNETA_INTR_NEW_MASK, - MVNETA_RX_INTR_MASK(rxq_number) | - MVNETA_TX_INTR_MASK(txq_number) | - MVNETA_MISCINTR_INTR_MASK); + /* Unmask all ethernet port interrupts */ + on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true); mvreg_write(pp, MVNETA_INTR_MISC_MASK, MVNETA_CAUSE_PHY_STATUS_CHANGE | MVNETA_CAUSE_LINK_CHANGE | MVNETA_CAUSE_PSC_SYNC_CHANGE); netif_tx_start_all_queues(pp->dev); + spin_unlock(&pp->lock); break; case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE_FROZEN: netif_tx_stop_all_queues(pp->dev); + /* Thanks to this lock we are sure that any pending + * cpu election is done + */ + spin_lock(&pp->lock); /* Mask all ethernet port interrupts */ - mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); - mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); - mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); + on_each_cpu(mvneta_percpu_mask_interrupt, pp, true); + spin_unlock(&pp->lock); napi_synchronize(&port->napi); napi_disable(&port->napi); @@ -2968,12 +2990,11 @@ static int mvneta_percpu_notifier(struct notifier_block *nfb, case CPU_DEAD: case CPU_DEAD_FROZEN: /* Check if a new CPU must be elected now this on is down */ + spin_lock(&pp->lock); mvneta_percpu_elect(pp); + spin_unlock(&pp->lock); /* Unmask all ethernet port interrupts */ - mvreg_write(pp, MVNETA_INTR_NEW_MASK, - MVNETA_RX_INTR_MASK(rxq_number) | - MVNETA_TX_INTR_MASK(txq_number) | - MVNETA_MISCINTR_INTR_MASK); + on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true); mvreg_write(pp, MVNETA_INTR_MISC_MASK, MVNETA_CAUSE_PHY_STATUS_CHANGE | MVNETA_CAUSE_LINK_CHANGE | @@ -2988,7 +3009,7 @@ static int mvneta_percpu_notifier(struct notifier_block *nfb, static int mvneta_open(struct net_device *dev) { struct mvneta_port *pp = netdev_priv(dev); - int ret, cpu; + int ret; pp->pkt_size = MVNETA_RX_PKT_SIZE(pp->dev->mtu); pp->frag_size = SKB_DATA_ALIGN(MVNETA_RX_BUF_SIZE(pp->pkt_size)) + @@ -3010,22 +3031,12 @@ static int mvneta_open(struct net_device *dev) goto err_cleanup_txqs; } - /* Even though the documentation says that request_percpu_irq - * doesn't enable the interrupts automatically, it actually - * does so on the local CPU. - * - * Make sure it's disabled. - */ - mvneta_percpu_disable(pp); - /* Enable per-CPU interrupt on all the CPU to handle our RX * queue interrupts */ - for_each_online_cpu(cpu) - smp_call_function_single(cpu, mvneta_percpu_enable, - pp, true); - + on_each_cpu(mvneta_percpu_enable, pp, true); + pp->is_stopped = false; /* Register a CPU notifier to handle the case where our CPU * might be taken offline. */ @@ -3057,13 +3068,20 @@ err_cleanup_rxqs: static int mvneta_stop(struct net_device *dev) { struct mvneta_port *pp = netdev_priv(dev); - int cpu; + /* Inform that we are stopping so we don't want to setup the + * driver for new CPUs in the notifiers + */ + spin_lock(&pp->lock); + pp->is_stopped = true; mvneta_stop_dev(pp); mvneta_mdio_remove(pp); unregister_cpu_notifier(&pp->cpu_notifier); - for_each_present_cpu(cpu) - smp_call_function_single(cpu, mvneta_percpu_disable, pp, true); + /* Now that the notifier are unregistered, we can release le + * lock + */ + spin_unlock(&pp->lock); + on_each_cpu(mvneta_percpu_disable, pp, true); free_percpu_irq(dev->irq, pp->ports); mvneta_cleanup_rxqs(pp); mvneta_cleanup_txqs(pp); @@ -3312,9 +3330,7 @@ static int mvneta_config_rss(struct mvneta_port *pp) netif_tx_stop_all_queues(pp->dev); - for_each_online_cpu(cpu) - smp_call_function_single(cpu, mvneta_percpu_mask_interrupt, - pp, true); + on_each_cpu(mvneta_percpu_mask_interrupt, pp, true); /* We have to synchronise on the napi of each CPU */ for_each_online_cpu(cpu) { @@ -3335,7 +3351,9 @@ static int mvneta_config_rss(struct mvneta_port *pp) mvreg_write(pp, MVNETA_PORT_CONFIG, val); /* Update the elected CPU matching the new rxq_def */ + spin_lock(&pp->lock); mvneta_percpu_elect(pp); + spin_unlock(&pp->lock); /* We have to synchronise on the napi of each CPU */ for_each_online_cpu(cpu) { diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index a4beccf1fd46..c797971aefab 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c @@ -3061,7 +3061,7 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2 *priv, int port, pe = kzalloc(sizeof(*pe), GFP_KERNEL); if (!pe) - return -1; + return -ENOMEM; mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC); pe->index = tid; @@ -3077,7 +3077,7 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2 *priv, int port, if (pmap == 0) { if (add) { kfree(pe); - return -1; + return -EINVAL; } mvpp2_prs_hw_inv(priv, pe->index); priv->prs_shadow[pe->index].valid = false; diff --git a/drivers/net/ethernet/mellanox/mlx4/catas.c b/drivers/net/ethernet/mellanox/mlx4/catas.c index 715de8affcc9..c7e939945259 100644 --- a/drivers/net/ethernet/mellanox/mlx4/catas.c +++ b/drivers/net/ethernet/mellanox/mlx4/catas.c @@ -182,10 +182,17 @@ void mlx4_enter_error_state(struct mlx4_dev_persistent *persist) err = mlx4_reset_slave(dev); else err = mlx4_reset_master(dev); - BUG_ON(err != 0); + if (!err) { + mlx4_err(dev, "device was reset successfully\n"); + } else { + /* EEH could have disabled the PCI channel during reset. That's + * recoverable and the PCI error flow will handle it. + */ + if (!pci_channel_offline(dev->persist->pdev)) + BUG_ON(1); + } dev->persist->state |= MLX4_DEVICE_STATE_INTERNAL_ERROR; - mlx4_err(dev, "device was reset successfully\n"); mutex_unlock(&persist->device_state_mutex); /* At that step HW was already reset, now notify clients */ diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c index 3348e646db70..a849da92f857 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/cq.c @@ -318,7 +318,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, if (timestamp_en) cq_context->flags |= cpu_to_be32(1 << 19); - cq_context->logsize_usrpage = cpu_to_be32((ilog2(nent) << 24) | uar->index); + cq_context->logsize_usrpage = + cpu_to_be32((ilog2(nent) << 24) | + mlx4_to_hw_uar_index(dev, uar->index)); cq_context->comp_eqn = priv->eq_table.eq[MLX4_CQ_TO_EQ_VECTOR(vector)].eqn; cq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c index 038f9ce391e6..1494997c4f7e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c @@ -236,6 +236,24 @@ static const struct ptp_clock_info mlx4_en_ptp_clock_info = { .enable = mlx4_en_phc_enable, }; +#define MLX4_EN_WRAP_AROUND_SEC 10ULL + +/* This function calculates the max shift that enables the user range + * of MLX4_EN_WRAP_AROUND_SEC values in the cycles register. + */ +static u32 freq_to_shift(u16 freq) +{ + u32 freq_khz = freq * 1000; + u64 max_val_cycles = freq_khz * 1000 * MLX4_EN_WRAP_AROUND_SEC; + u64 max_val_cycles_rounded = is_power_of_2(max_val_cycles + 1) ? + max_val_cycles : roundup_pow_of_two(max_val_cycles) - 1; + /* calculate max possible multiplier in order to fit in 64bit */ + u64 max_mul = div_u64(0xffffffffffffffffULL, max_val_cycles_rounded); + + /* This comes from the reverse of clocksource_khz2mult */ + return ilog2(div_u64(max_mul * freq_khz, 1000000)); +} + void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev) { struct mlx4_dev *dev = mdev->dev; @@ -254,12 +272,7 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev) memset(&mdev->cycles, 0, sizeof(mdev->cycles)); mdev->cycles.read = mlx4_en_read_clock; mdev->cycles.mask = CLOCKSOURCE_MASK(48); - /* Using shift to make calculation more accurate. Since current HW - * clock frequency is 427 MHz, and cycles are given using a 48 bits - * register, the biggest shift when calculating using u64, is 14 - * (max_cycles * multiplier < 2^64) - */ - mdev->cycles.shift = 14; + mdev->cycles.shift = freq_to_shift(dev->caps.hca_core_clock); mdev->cycles.mult = clocksource_khz2mult(1000 * dev->caps.hca_core_clock, mdev->cycles.shift); mdev->nominal_c_mult = mdev->cycles.mult; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 0c7e3f69a73b..f191a1612589 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2344,8 +2344,6 @@ out: /* set offloads */ priv->dev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO | NETIF_F_GSO_UDP_TUNNEL; - priv->dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL; - priv->dev->features |= NETIF_F_GSO_UDP_TUNNEL; } static void mlx4_en_del_vxlan_offloads(struct work_struct *work) @@ -2356,8 +2354,6 @@ static void mlx4_en_del_vxlan_offloads(struct work_struct *work) /* unset offloads */ priv->dev->hw_enc_features &= ~(NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO | NETIF_F_GSO_UDP_TUNNEL); - priv->dev->hw_features &= ~NETIF_F_GSO_UDP_TUNNEL; - priv->dev->features &= ~NETIF_F_GSO_UDP_TUNNEL; ret = mlx4_SET_PORT_VXLAN(priv->mdev->dev, priv->port, VXLAN_STEER_BY_OUTER_MAC, 0); @@ -2980,6 +2976,11 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, priv->rss_hash_fn = ETH_RSS_HASH_TOP; } + if (mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) { + dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL; + dev->features |= NETIF_F_GSO_UDP_TUNNEL; + } + mdev->pndev[port] = dev; mdev->upper[port] = NULL; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_port.c b/drivers/net/ethernet/mellanox/mlx4/en_port.c index ee99e67187f5..3904b5fc0b7c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_port.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_port.c @@ -238,11 +238,11 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset) stats->collisions = 0; stats->rx_dropped = be32_to_cpu(mlx4_en_stats->RDROP); stats->rx_length_errors = be32_to_cpu(mlx4_en_stats->RdropLength); - stats->rx_over_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw); + stats->rx_over_errors = 0; stats->rx_crc_errors = be32_to_cpu(mlx4_en_stats->RCRC); stats->rx_frame_errors = 0; stats->rx_fifo_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw); - stats->rx_missed_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw); + stats->rx_missed_errors = 0; stats->tx_aborted_errors = 0; stats->tx_carrier_errors = 0; stats->tx_fifo_errors = 0; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_resources.c b/drivers/net/ethernet/mellanox/mlx4/en_resources.c index 12aab5a659d3..02e925d6f734 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_resources.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_resources.c @@ -58,7 +58,8 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride, } else { context->sq_size_stride = ilog2(TXBB_SIZE) - 4; } - context->usr_page = cpu_to_be32(mdev->priv_uar.index); + context->usr_page = cpu_to_be32(mlx4_to_hw_uar_index(mdev->dev, + mdev->priv_uar.index)); context->local_qpn = cpu_to_be32(qpn); context->pri_path.ackto = 1 & 0x07; context->pri_path.sched_queue = 0x83 | (priv->port - 1) << 6; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 4421bf5463f6..e0946ab22010 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -213,7 +213,9 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv, mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn, ring->cqn, user_prio, &ring->context); if (ring->bf_alloced) - ring->context.usr_page = cpu_to_be32(ring->bf.uar->index); + ring->context.usr_page = + cpu_to_be32(mlx4_to_hw_uar_index(mdev->dev, + ring->bf.uar->index)); err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context, &ring->qp, &ring->qp_state); diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 4696053165f8..f613977455e0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -940,9 +940,10 @@ static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq) if (!priv->eq_table.uar_map[index]) { priv->eq_table.uar_map[index] = - ioremap(pci_resource_start(dev->persist->pdev, 2) + - ((eq->eqn / 4) << PAGE_SHIFT), - PAGE_SIZE); + ioremap( + pci_resource_start(dev->persist->pdev, 2) + + ((eq->eqn / 4) << (dev->uar_page_shift)), + (1 << (dev->uar_page_shift))); if (!priv->eq_table.uar_map[index]) { mlx4_err(dev, "Couldn't map EQ doorbell for EQN 0x%06x\n", eq->eqn); diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index f1b6d219e445..2cc3c626c3fe 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -168,6 +168,20 @@ struct mlx4_port_config { static atomic_t pf_loading = ATOMIC_INIT(0); +static inline void mlx4_set_num_reserved_uars(struct mlx4_dev *dev, + struct mlx4_dev_cap *dev_cap) +{ + /* The reserved_uars is calculated by system page size unit. + * Therefore, adjustment is added when the uar page size is less + * than the system page size + */ + dev->caps.reserved_uars = + max_t(int, + mlx4_get_num_reserved_uar(dev), + dev_cap->reserved_uars / + (1 << (PAGE_SHIFT - dev->uar_page_shift))); +} + int mlx4_check_port_params(struct mlx4_dev *dev, enum mlx4_port_type *port_type) { @@ -386,8 +400,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.reserved_mtts = dev_cap->reserved_mtts; dev->caps.reserved_mrws = dev_cap->reserved_mrws; - /* The first 128 UARs are used for EQ doorbells */ - dev->caps.reserved_uars = max_t(int, 128, dev_cap->reserved_uars); dev->caps.reserved_pds = dev_cap->reserved_pds; dev->caps.reserved_xrcds = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ? dev_cap->reserved_xrcds : 0; @@ -405,6 +417,15 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.max_gso_sz = dev_cap->max_gso_sz; dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz; + /* Save uar page shift */ + if (!mlx4_is_slave(dev)) { + /* Virtual PCI function needs to determine UAR page size from + * firmware. Only master PCI function can set the uar page size + */ + dev->uar_page_shift = DEFAULT_UAR_PAGE_SHIFT; + mlx4_set_num_reserved_uars(dev, dev_cap); + } + if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PHV_EN) { struct mlx4_init_hca_param hca_param; @@ -815,16 +836,25 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) return -ENODEV; } - /* slave gets uar page size from QUERY_HCA fw command */ - dev->caps.uar_page_size = 1 << (hca_param.uar_page_sz + 12); + /* Set uar_page_shift for VF */ + dev->uar_page_shift = hca_param.uar_page_sz + 12; - /* TODO: relax this assumption */ - if (dev->caps.uar_page_size != PAGE_SIZE) { - mlx4_err(dev, "UAR size:%d != kernel PAGE_SIZE of %ld\n", - dev->caps.uar_page_size, PAGE_SIZE); - return -ENODEV; + /* Make sure the master uar page size is valid */ + if (dev->uar_page_shift > PAGE_SHIFT) { + mlx4_err(dev, + "Invalid configuration: uar page size is larger than system page size\n"); + return -ENODEV; } + /* Set reserved_uars based on the uar_page_shift */ + mlx4_set_num_reserved_uars(dev, &dev_cap); + + /* Although uar page size in FW differs from system page size, + * upper software layers (mlx4_ib, mlx4_en and part of mlx4_core) + * still works with assumption that uar page size == system page size + */ + dev->caps.uar_page_size = PAGE_SIZE; + memset(&func_cap, 0, sizeof(func_cap)); err = mlx4_QUERY_FUNC_CAP(dev, 0, &func_cap); if (err) { @@ -2179,8 +2209,12 @@ static int mlx4_init_hca(struct mlx4_dev *dev) dev->caps.max_fmr_maps = (1 << (32 - ilog2(dev->caps.num_mpts))) - 1; - init_hca.log_uar_sz = ilog2(dev->caps.num_uars); - init_hca.uar_page_sz = PAGE_SHIFT - 12; + /* Always set UAR page size 4KB, set log_uar_sz accordingly */ + init_hca.log_uar_sz = ilog2(dev->caps.num_uars) + + PAGE_SHIFT - + DEFAULT_UAR_PAGE_SHIFT; + init_hca.uar_page_sz = DEFAULT_UAR_PAGE_SHIFT - 12; + init_hca.mw_enabled = 0; if (dev->caps.flags & MLX4_DEV_CAP_FLAG_MEM_WINDOW || dev->caps.bmme_flags & MLX4_BMME_FLAG_TYPE_2_WIN) diff --git a/drivers/net/ethernet/mellanox/mlx4/pd.c b/drivers/net/ethernet/mellanox/mlx4/pd.c index 609c59dc854e..b3cc3ab63799 100644 --- a/drivers/net/ethernet/mellanox/mlx4/pd.c +++ b/drivers/net/ethernet/mellanox/mlx4/pd.c @@ -269,9 +269,15 @@ EXPORT_SYMBOL_GPL(mlx4_bf_free); int mlx4_init_uar_table(struct mlx4_dev *dev) { - if (dev->caps.num_uars <= 128) { - mlx4_err(dev, "Only %d UAR pages (need more than 128)\n", - dev->caps.num_uars); + int num_reserved_uar = mlx4_get_num_reserved_uar(dev); + + mlx4_dbg(dev, "uar_page_shift = %d", dev->uar_page_shift); + mlx4_dbg(dev, "Effective reserved_uars=%d", dev->caps.reserved_uars); + + if (dev->caps.num_uars <= num_reserved_uar) { + mlx4_err( + dev, "Only %d UAR pages (need more than %d)\n", + dev->caps.num_uars, num_reserved_uar); mlx4_err(dev, "Increase firmware log2_uar_bar_megabytes?\n"); return -ENODEV; } diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index b46dbe29ef6c..25ce1b030a00 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -915,11 +915,13 @@ static int handle_existing_counter(struct mlx4_dev *dev, u8 slave, int port, spin_lock_irq(mlx4_tlock(dev)); r = find_res(dev, counter_index, RES_COUNTER); - if (!r || r->owner != slave) + if (!r || r->owner != slave) { ret = -EINVAL; - counter = container_of(r, struct res_counter, com); - if (!counter->port) - counter->port = port; + } else { + counter = container_of(r, struct res_counter, com); + if (!counter->port) + counter->port = port; + } spin_unlock_irq(mlx4_tlock(dev)); return ret; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 6a3e430f1062..d4e1c3045200 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2024,18 +2024,37 @@ static int mlx5e_get_vf_stats(struct net_device *dev, vf_stats); } -static struct net_device_ops mlx5e_netdev_ops = { +static const struct net_device_ops mlx5e_netdev_ops_basic = { .ndo_open = mlx5e_open, .ndo_stop = mlx5e_close, .ndo_start_xmit = mlx5e_xmit, .ndo_get_stats64 = mlx5e_get_stats, .ndo_set_rx_mode = mlx5e_set_rx_mode, .ndo_set_mac_address = mlx5e_set_mac, - .ndo_vlan_rx_add_vid = mlx5e_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = mlx5e_vlan_rx_kill_vid, + .ndo_vlan_rx_add_vid = mlx5e_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = mlx5e_vlan_rx_kill_vid, .ndo_set_features = mlx5e_set_features, - .ndo_change_mtu = mlx5e_change_mtu, - .ndo_do_ioctl = mlx5e_ioctl, + .ndo_change_mtu = mlx5e_change_mtu, + .ndo_do_ioctl = mlx5e_ioctl, +}; + +static const struct net_device_ops mlx5e_netdev_ops_sriov = { + .ndo_open = mlx5e_open, + .ndo_stop = mlx5e_close, + .ndo_start_xmit = mlx5e_xmit, + .ndo_get_stats64 = mlx5e_get_stats, + .ndo_set_rx_mode = mlx5e_set_rx_mode, + .ndo_set_mac_address = mlx5e_set_mac, + .ndo_vlan_rx_add_vid = mlx5e_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = mlx5e_vlan_rx_kill_vid, + .ndo_set_features = mlx5e_set_features, + .ndo_change_mtu = mlx5e_change_mtu, + .ndo_do_ioctl = mlx5e_ioctl, + .ndo_set_vf_mac = mlx5e_set_vf_mac, + .ndo_set_vf_vlan = mlx5e_set_vf_vlan, + .ndo_get_vf_config = mlx5e_get_vf_config, + .ndo_set_vf_link_state = mlx5e_set_vf_link_state, + .ndo_get_vf_stats = mlx5e_get_vf_stats, }; static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev) @@ -2137,18 +2156,11 @@ static void mlx5e_build_netdev(struct net_device *netdev) SET_NETDEV_DEV(netdev, &mdev->pdev->dev); - if (priv->params.num_tc > 1) - mlx5e_netdev_ops.ndo_select_queue = mlx5e_select_queue; - - if (MLX5_CAP_GEN(mdev, vport_group_manager)) { - mlx5e_netdev_ops.ndo_set_vf_mac = mlx5e_set_vf_mac; - mlx5e_netdev_ops.ndo_set_vf_vlan = mlx5e_set_vf_vlan; - mlx5e_netdev_ops.ndo_get_vf_config = mlx5e_get_vf_config; - mlx5e_netdev_ops.ndo_set_vf_link_state = mlx5e_set_vf_link_state; - mlx5e_netdev_ops.ndo_get_vf_stats = mlx5e_get_vf_stats; - } + if (MLX5_CAP_GEN(mdev, vport_group_manager)) + netdev->netdev_ops = &mlx5e_netdev_ops_sriov; + else + netdev->netdev_ops = &mlx5e_netdev_ops_basic; - netdev->netdev_ops = &mlx5e_netdev_ops; netdev->watchdog_timeo = 15 * HZ; netdev->ethtool_ops = &mlx5e_ethtool_ops; diff --git a/drivers/net/ethernet/mellanox/mlxsw/port.h b/drivers/net/ethernet/mellanox/mlxsw/port.h index 726f5435b32f..ae65b9940aed 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/port.h +++ b/drivers/net/ethernet/mellanox/mlxsw/port.h @@ -49,7 +49,7 @@ #define MLXSW_PORT_MID 0xd000 #define MLXSW_PORT_MAX_PHY_PORTS 0x40 -#define MLXSW_PORT_MAX_PORTS MLXSW_PORT_MAX_PHY_PORTS +#define MLXSW_PORT_MAX_PORTS (MLXSW_PORT_MAX_PHY_PORTS + 1) #define MLXSW_PORT_DEVID_BITS_OFFSET 10 #define MLXSW_PORT_PHY_BITS_OFFSET 4 diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index bb77e2207804..ffe4c0305733 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -873,6 +873,62 @@ static inline void mlxsw_reg_spvm_pack(char *payload, u8 local_port, } } +/* SPAFT - Switch Port Acceptable Frame Types + * ------------------------------------------ + * The Switch Port Acceptable Frame Types register configures the frame + * admittance of the port. + */ +#define MLXSW_REG_SPAFT_ID 0x2010 +#define MLXSW_REG_SPAFT_LEN 0x08 + +static const struct mlxsw_reg_info mlxsw_reg_spaft = { + .id = MLXSW_REG_SPAFT_ID, + .len = MLXSW_REG_SPAFT_LEN, +}; + +/* reg_spaft_local_port + * Local port number. + * Access: Index + * + * Note: CPU port is not supported (all tag types are allowed). + */ +MLXSW_ITEM32(reg, spaft, local_port, 0x00, 16, 8); + +/* reg_spaft_sub_port + * Virtual port within the physical port. + * Should be set to 0 when virtual ports are not enabled on the port. + * Access: RW + */ +MLXSW_ITEM32(reg, spaft, sub_port, 0x00, 8, 8); + +/* reg_spaft_allow_untagged + * When set, untagged frames on the ingress are allowed (default). + * Access: RW + */ +MLXSW_ITEM32(reg, spaft, allow_untagged, 0x04, 31, 1); + +/* reg_spaft_allow_prio_tagged + * When set, priority tagged frames on the ingress are allowed (default). + * Access: RW + */ +MLXSW_ITEM32(reg, spaft, allow_prio_tagged, 0x04, 30, 1); + +/* reg_spaft_allow_tagged + * When set, tagged frames on the ingress are allowed (default). + * Access: RW + */ +MLXSW_ITEM32(reg, spaft, allow_tagged, 0x04, 29, 1); + +static inline void mlxsw_reg_spaft_pack(char *payload, u8 local_port, + bool allow_untagged) +{ + MLXSW_REG_ZERO(spaft, payload); + mlxsw_reg_spaft_local_port_set(payload, local_port); + mlxsw_reg_spaft_allow_untagged_set(payload, allow_untagged); + mlxsw_reg_spaft_allow_prio_tagged_set(payload, true); + mlxsw_reg_spaft_allow_tagged_set(payload, true); +} + /* SFGC - Switch Flooding Group Configuration * ------------------------------------------ * The following register controls the association of flooding tables and MIDs @@ -3203,6 +3259,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "SPVID"; case MLXSW_REG_SPVM_ID: return "SPVM"; + case MLXSW_REG_SPAFT_ID: + return "SPAFT"; case MLXSW_REG_SFGC_ID: return "SFGC"; case MLXSW_REG_SFTR_ID: diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 217856bdd400..09ce451c283b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2123,6 +2123,8 @@ static int mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port, if (flush_fdb && mlxsw_sp_port_fdb_flush(mlxsw_sp_port)) netdev_err(mlxsw_sp_port->dev, "Failed to flush FDB\n"); + mlxsw_sp_port_pvid_set(mlxsw_sp_port, 1); + mlxsw_sp_port->learning = 0; mlxsw_sp_port->learning_sync = 0; mlxsw_sp_port->uc_flood = 0; @@ -2746,6 +2748,13 @@ static int mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport, goto err_vport_flood_set; } + err = mlxsw_sp_port_stp_state_set(mlxsw_sp_vport, vid, + MLXSW_REG_SPMS_STATE_FORWARDING); + if (err) { + netdev_err(dev, "Failed to set STP state\n"); + goto err_port_stp_state_set; + } + if (flush_fdb && mlxsw_sp_vport_fdb_flush(mlxsw_sp_vport)) netdev_err(dev, "Failed to flush FDB\n"); @@ -2763,6 +2772,7 @@ static int mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport, return 0; +err_port_stp_state_set: err_vport_flood_set: err_port_vid_learning_set: err_port_vid_to_fid_validate: diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 7f42eb1c320e..3b89ed2f3c76 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -254,5 +254,6 @@ int mlxsw_sp_port_kill_vid(struct net_device *dev, int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 vfid, bool set, bool only_uc); void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port); +int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid); #endif diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index e492ca2cdecd..7b56098acc58 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -370,7 +370,8 @@ static int mlxsw_sp_port_attr_set(struct net_device *dev, return err; } -static int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) +static int __mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, + u16 vid) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; char spvid_pl[MLXSW_REG_SPVID_LEN]; @@ -379,6 +380,53 @@ static int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvid), spvid_pl); } +static int mlxsw_sp_port_allow_untagged_set(struct mlxsw_sp_port *mlxsw_sp_port, + bool allow) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char spaft_pl[MLXSW_REG_SPAFT_LEN]; + + mlxsw_reg_spaft_pack(spaft_pl, mlxsw_sp_port->local_port, allow); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spaft), spaft_pl); +} + +int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) +{ + struct net_device *dev = mlxsw_sp_port->dev; + int err; + + if (!vid) { + err = mlxsw_sp_port_allow_untagged_set(mlxsw_sp_port, false); + if (err) { + netdev_err(dev, "Failed to disallow untagged traffic\n"); + return err; + } + } else { + err = __mlxsw_sp_port_pvid_set(mlxsw_sp_port, vid); + if (err) { + netdev_err(dev, "Failed to set PVID\n"); + return err; + } + + /* Only allow if not already allowed. */ + if (!mlxsw_sp_port->pvid) { + err = mlxsw_sp_port_allow_untagged_set(mlxsw_sp_port, + true); + if (err) { + netdev_err(dev, "Failed to allow untagged traffic\n"); + goto err_port_allow_untagged_set; + } + } + } + + mlxsw_sp_port->pvid = vid; + return 0; + +err_port_allow_untagged_set: + __mlxsw_sp_port_pvid_set(mlxsw_sp_port, mlxsw_sp_port->pvid); + return err; +} + static int mlxsw_sp_fid_create(struct mlxsw_sp *mlxsw_sp, u16 fid) { char sfmr_pl[MLXSW_REG_SFMR_LEN]; @@ -540,7 +588,12 @@ static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port, netdev_err(dev, "Unable to add PVID %d\n", vid_begin); goto err_port_pvid_set; } - mlxsw_sp_port->pvid = vid_begin; + } else if (!flag_pvid && old_pvid >= vid_begin && old_pvid <= vid_end) { + err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, 0); + if (err) { + netdev_err(dev, "Unable to del PVID\n"); + goto err_port_pvid_set; + } } /* Changing activity bits only if HW operation succeded */ @@ -892,20 +945,18 @@ static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port, return err; } + if (init) + goto out; + pvid = mlxsw_sp_port->pvid; - if (pvid >= vid_begin && pvid <= vid_end && pvid != 1) { - /* Default VLAN is always 1 */ - err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, 1); + if (pvid >= vid_begin && pvid <= vid_end) { + err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, 0); if (err) { netdev_err(dev, "Unable to del PVID %d\n", pvid); return err; } - mlxsw_sp_port->pvid = 1; } - if (init) - goto out; - err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid_begin, vid_end, false, false); if (err) { diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 17d5571d0432..537974cfd427 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -6137,28 +6137,28 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp) sw_cnt_1ms_ini = 16000000/rg_saw_cnt; sw_cnt_1ms_ini &= 0x0fff; data = r8168_mac_ocp_read(tp, 0xd412); - data &= 0x0fff; + data &= ~0x0fff; data |= sw_cnt_1ms_ini; r8168_mac_ocp_write(tp, 0xd412, data); } data = r8168_mac_ocp_read(tp, 0xe056); - data &= 0xf0; - data |= 0x07; + data &= ~0xf0; + data |= 0x70; r8168_mac_ocp_write(tp, 0xe056, data); data = r8168_mac_ocp_read(tp, 0xe052); - data &= 0x8008; - data |= 0x6000; + data &= ~0x6000; + data |= 0x8008; r8168_mac_ocp_write(tp, 0xe052, data); data = r8168_mac_ocp_read(tp, 0xe0d6); - data &= 0x01ff; + data &= ~0x01ff; data |= 0x017f; r8168_mac_ocp_write(tp, 0xe0d6, data); data = r8168_mac_ocp_read(tp, 0xd420); - data &= 0x0fff; + data &= ~0x0fff; data |= 0x047f; r8168_mac_ocp_write(tp, 0xd420, data); diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index ac43ed914fcf..744d7806a9ee 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -1139,7 +1139,8 @@ static int ravb_set_ringparam(struct net_device *ndev, if (netif_running(ndev)) { netif_device_detach(ndev); /* Stop PTP Clock driver */ - ravb_ptp_stop(ndev); + if (priv->chip_id == RCAR_GEN2) + ravb_ptp_stop(ndev); /* Wait for DMA stopping */ error = ravb_stop_dma(ndev); if (error) { @@ -1170,7 +1171,8 @@ static int ravb_set_ringparam(struct net_device *ndev, ravb_emac_init(ndev); /* Initialise PTP Clock driver */ - ravb_ptp_init(ndev, priv->pdev); + if (priv->chip_id == RCAR_GEN2) + ravb_ptp_init(ndev, priv->pdev); netif_device_attach(ndev); } @@ -1298,7 +1300,8 @@ static void ravb_tx_timeout_work(struct work_struct *work) netif_tx_stop_all_queues(ndev); /* Stop PTP Clock driver */ - ravb_ptp_stop(ndev); + if (priv->chip_id == RCAR_GEN2) + ravb_ptp_stop(ndev); /* Wait for DMA stopping */ ravb_stop_dma(ndev); @@ -1311,7 +1314,8 @@ static void ravb_tx_timeout_work(struct work_struct *work) ravb_emac_init(ndev); /* Initialise PTP Clock driver */ - ravb_ptp_init(ndev, priv->pdev); + if (priv->chip_id == RCAR_GEN2) + ravb_ptp_init(ndev, priv->pdev); netif_tx_start_all_queues(ndev); } @@ -1814,10 +1818,6 @@ static int ravb_probe(struct platform_device *pdev) CCC_OPC_CONFIG | CCC_GAC | CCC_CSEL_HPB, CCC); } - /* Set CSEL value */ - ravb_write(ndev, (ravb_read(ndev, CCC) & ~CCC_CSEL) | CCC_CSEL_HPB, - CCC); - /* Set GTI value */ error = ravb_set_gti(ndev); if (error) diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 0e2fc1a844ab..db7db8ac4ca3 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -2342,8 +2342,8 @@ static int smc_drv_probe(struct platform_device *pdev) } ndev->irq = platform_get_irq(pdev, 0); - if (ndev->irq <= 0) { - ret = -ENODEV; + if (ndev->irq < 0) { + ret = ndev->irq; goto out_release_io; } /* diff --git a/drivers/net/ethernet/ti/cpsw-phy-sel.c b/drivers/net/ethernet/ti/cpsw-phy-sel.c index e9cc61e1ec74..c3e85acfdc70 100644 --- a/drivers/net/ethernet/ti/cpsw-phy-sel.c +++ b/drivers/net/ethernet/ti/cpsw-phy-sel.c @@ -63,8 +63,12 @@ static void cpsw_gmii_sel_am3352(struct cpsw_phy_sel_priv *priv, mode = AM33XX_GMII_SEL_MODE_RGMII; break; - case PHY_INTERFACE_MODE_MII: default: + dev_warn(priv->dev, + "Unsupported PHY mode: \"%s\". Defaulting to MII.\n", + phy_modes(phy_mode)); + /* fallthrough */ + case PHY_INTERFACE_MODE_MII: mode = AM33XX_GMII_SEL_MODE_MII; break; }; @@ -106,8 +110,12 @@ static void cpsw_gmii_sel_dra7xx(struct cpsw_phy_sel_priv *priv, mode = AM33XX_GMII_SEL_MODE_RGMII; break; - case PHY_INTERFACE_MODE_MII: default: + dev_warn(priv->dev, + "Unsupported PHY mode: \"%s\". Defaulting to MII.\n", + phy_modes(phy_mode)); + /* fallthrough */ + case PHY_INTERFACE_MODE_MII: mode = AM33XX_GMII_SEL_MODE_MII; break; }; diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index c61d66d38634..029841f98c32 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -117,21 +117,17 @@ static void get_pkt_info(dma_addr_t *buff, u32 *buff_len, dma_addr_t *ndesc, *ndesc = le32_to_cpu(desc->next_desc); } -static void get_pad_info(u32 *pad0, u32 *pad1, u32 *pad2, struct knav_dma_desc *desc) +static u32 get_sw_data(int index, struct knav_dma_desc *desc) { - *pad0 = le32_to_cpu(desc->pad[0]); - *pad1 = le32_to_cpu(desc->pad[1]); - *pad2 = le32_to_cpu(desc->pad[2]); + /* No Endian conversion needed as this data is untouched by hw */ + return desc->sw_data[index]; } -static void get_pad_ptr(void **padptr, struct knav_dma_desc *desc) -{ - u64 pad64; - - pad64 = le32_to_cpu(desc->pad[0]) + - ((u64)le32_to_cpu(desc->pad[1]) << 32); - *padptr = (void *)(uintptr_t)pad64; -} +/* use these macros to get sw data */ +#define GET_SW_DATA0(desc) get_sw_data(0, desc) +#define GET_SW_DATA1(desc) get_sw_data(1, desc) +#define GET_SW_DATA2(desc) get_sw_data(2, desc) +#define GET_SW_DATA3(desc) get_sw_data(3, desc) static void get_org_pkt_info(dma_addr_t *buff, u32 *buff_len, struct knav_dma_desc *desc) @@ -163,13 +159,18 @@ static void set_desc_info(u32 desc_info, u32 pkt_info, desc->packet_info = cpu_to_le32(pkt_info); } -static void set_pad_info(u32 pad0, u32 pad1, u32 pad2, struct knav_dma_desc *desc) +static void set_sw_data(int index, u32 data, struct knav_dma_desc *desc) { - desc->pad[0] = cpu_to_le32(pad0); - desc->pad[1] = cpu_to_le32(pad1); - desc->pad[2] = cpu_to_le32(pad1); + /* No Endian conversion needed as this data is untouched by hw */ + desc->sw_data[index] = data; } +/* use these macros to set sw data */ +#define SET_SW_DATA0(data, desc) set_sw_data(0, data, desc) +#define SET_SW_DATA1(data, desc) set_sw_data(1, data, desc) +#define SET_SW_DATA2(data, desc) set_sw_data(2, data, desc) +#define SET_SW_DATA3(data, desc) set_sw_data(3, data, desc) + static void set_org_pkt_info(dma_addr_t buff, u32 buff_len, struct knav_dma_desc *desc) { @@ -581,7 +582,6 @@ static void netcp_free_rx_desc_chain(struct netcp_intf *netcp, dma_addr_t dma_desc, dma_buf; unsigned int buf_len, dma_sz = sizeof(*ndesc); void *buf_ptr; - u32 pad[2]; u32 tmp; get_words(&dma_desc, 1, &desc->next_desc); @@ -593,14 +593,20 @@ static void netcp_free_rx_desc_chain(struct netcp_intf *netcp, break; } get_pkt_info(&dma_buf, &tmp, &dma_desc, ndesc); - get_pad_ptr(&buf_ptr, ndesc); + /* warning!!!! We are retrieving the virtual ptr in the sw_data + * field as a 32bit value. Will not work on 64bit machines + */ + buf_ptr = (void *)GET_SW_DATA0(ndesc); + buf_len = (int)GET_SW_DATA1(desc); dma_unmap_page(netcp->dev, dma_buf, PAGE_SIZE, DMA_FROM_DEVICE); __free_page(buf_ptr); knav_pool_desc_put(netcp->rx_pool, desc); } - - get_pad_info(&pad[0], &pad[1], &buf_len, desc); - buf_ptr = (void *)(uintptr_t)(pad[0] + ((u64)pad[1] << 32)); + /* warning!!!! We are retrieving the virtual ptr in the sw_data + * field as a 32bit value. Will not work on 64bit machines + */ + buf_ptr = (void *)GET_SW_DATA0(desc); + buf_len = (int)GET_SW_DATA1(desc); if (buf_ptr) netcp_frag_free(buf_len <= PAGE_SIZE, buf_ptr); @@ -639,7 +645,6 @@ static int netcp_process_one_rx_packet(struct netcp_intf *netcp) dma_addr_t dma_desc, dma_buff; struct netcp_packet p_info; struct sk_buff *skb; - u32 pad[2]; void *org_buf_ptr; dma_desc = knav_queue_pop(netcp->rx_queue, &dma_sz); @@ -653,8 +658,11 @@ static int netcp_process_one_rx_packet(struct netcp_intf *netcp) } get_pkt_info(&dma_buff, &buf_len, &dma_desc, desc); - get_pad_info(&pad[0], &pad[1], &org_buf_len, desc); - org_buf_ptr = (void *)(uintptr_t)(pad[0] + ((u64)pad[1] << 32)); + /* warning!!!! We are retrieving the virtual ptr in the sw_data + * field as a 32bit value. Will not work on 64bit machines + */ + org_buf_ptr = (void *)GET_SW_DATA0(desc); + org_buf_len = (int)GET_SW_DATA1(desc); if (unlikely(!org_buf_ptr)) { dev_err(netcp->ndev_dev, "NULL bufptr in desc\n"); @@ -679,7 +687,6 @@ static int netcp_process_one_rx_packet(struct netcp_intf *netcp) /* Fill in the page fragment list */ while (dma_desc) { struct page *page; - void *ptr; ndesc = knav_pool_desc_unmap(netcp->rx_pool, dma_desc, dma_sz); if (unlikely(!ndesc)) { @@ -688,8 +695,10 @@ static int netcp_process_one_rx_packet(struct netcp_intf *netcp) } get_pkt_info(&dma_buff, &buf_len, &dma_desc, ndesc); - get_pad_ptr(&ptr, ndesc); - page = ptr; + /* warning!!!! We are retrieving the virtual ptr in the sw_data + * field as a 32bit value. Will not work on 64bit machines + */ + page = (struct page *)GET_SW_DATA0(desc); if (likely(dma_buff && buf_len && page)) { dma_unmap_page(netcp->dev, dma_buff, PAGE_SIZE, @@ -777,7 +786,10 @@ static void netcp_free_rx_buf(struct netcp_intf *netcp, int fdq) } get_org_pkt_info(&dma, &buf_len, desc); - get_pad_ptr(&buf_ptr, desc); + /* warning!!!! We are retrieving the virtual ptr in the sw_data + * field as a 32bit value. Will not work on 64bit machines + */ + buf_ptr = (void *)GET_SW_DATA0(desc); if (unlikely(!dma)) { dev_err(netcp->ndev_dev, "NULL orig_buff in desc\n"); @@ -829,7 +841,7 @@ static int netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq) struct page *page; dma_addr_t dma; void *bufptr; - u32 pad[3]; + u32 sw_data[2]; /* Allocate descriptor */ hwdesc = knav_pool_desc_get(netcp->rx_pool); @@ -846,7 +858,7 @@ static int netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq) SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); bufptr = netdev_alloc_frag(primary_buf_len); - pad[2] = primary_buf_len; + sw_data[1] = primary_buf_len; if (unlikely(!bufptr)) { dev_warn_ratelimited(netcp->ndev_dev, @@ -858,9 +870,10 @@ static int netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq) if (unlikely(dma_mapping_error(netcp->dev, dma))) goto fail; - pad[0] = lower_32_bits((uintptr_t)bufptr); - pad[1] = upper_32_bits((uintptr_t)bufptr); - + /* warning!!!! We are saving the virtual ptr in the sw_data + * field as a 32bit value. Will not work on 64bit machines + */ + sw_data[0] = (u32)bufptr; } else { /* Allocate a secondary receive queue entry */ page = alloc_page(GFP_ATOMIC | GFP_DMA | __GFP_COLD); @@ -870,9 +883,11 @@ static int netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq) } buf_len = PAGE_SIZE; dma = dma_map_page(netcp->dev, page, 0, buf_len, DMA_TO_DEVICE); - pad[0] = lower_32_bits(dma); - pad[1] = upper_32_bits(dma); - pad[2] = 0; + /* warning!!!! We are saving the virtual ptr in the sw_data + * field as a 32bit value. Will not work on 64bit machines + */ + sw_data[0] = (u32)page; + sw_data[1] = 0; } desc_info = KNAV_DMA_DESC_PS_INFO_IN_DESC; @@ -882,7 +897,8 @@ static int netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq) pkt_info |= (netcp->rx_queue_id & KNAV_DMA_DESC_RETQ_MASK) << KNAV_DMA_DESC_RETQ_SHIFT; set_org_pkt_info(dma, buf_len, hwdesc); - set_pad_info(pad[0], pad[1], pad[2], hwdesc); + SET_SW_DATA0(sw_data[0], hwdesc); + SET_SW_DATA1(sw_data[1], hwdesc); set_desc_info(desc_info, pkt_info, hwdesc); /* Push to FDQs */ @@ -971,7 +987,6 @@ static int netcp_process_tx_compl_packets(struct netcp_intf *netcp, unsigned int budget) { struct knav_dma_desc *desc; - void *ptr; struct sk_buff *skb; unsigned int dma_sz; dma_addr_t dma; @@ -988,8 +1003,10 @@ static int netcp_process_tx_compl_packets(struct netcp_intf *netcp, continue; } - get_pad_ptr(&ptr, desc); - skb = ptr; + /* warning!!!! We are retrieving the virtual ptr in the sw_data + * field as a 32bit value. Will not work on 64bit machines + */ + skb = (struct sk_buff *)GET_SW_DATA0(desc); netcp_free_tx_desc_chain(netcp, desc, dma_sz); if (!skb) { dev_err(netcp->ndev_dev, "No skb in Tx desc\n"); @@ -1194,10 +1211,10 @@ static int netcp_tx_submit_skb(struct netcp_intf *netcp, } set_words(&tmp, 1, &desc->packet_info); - tmp = lower_32_bits((uintptr_t)&skb); - set_words(&tmp, 1, &desc->pad[0]); - tmp = upper_32_bits((uintptr_t)&skb); - set_words(&tmp, 1, &desc->pad[1]); + /* warning!!!! We are saving the virtual ptr in the sw_data + * field as a 32bit value. Will not work on 64bit machines + */ + SET_SW_DATA0((u32)skb, desc); if (tx_pipe->flags & SWITCH_TO_PORT_IN_TAGINFO) { tmp = tx_pipe->switch_to_port; diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 028e3873c310..0bf7edd99573 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1039,17 +1039,34 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) return geneve_xmit_skb(skb, dev, info); } -static int geneve_change_mtu(struct net_device *dev, int new_mtu) +static int __geneve_change_mtu(struct net_device *dev, int new_mtu, bool strict) { - /* GENEVE overhead is not fixed, so we can't enforce a more - * precise max MTU. + /* The max_mtu calculation does not take account of GENEVE + * options, to avoid excluding potentially valid + * configurations. */ - if (new_mtu < 68 || new_mtu > IP_MAX_MTU) + int max_mtu = IP_MAX_MTU - GENEVE_BASE_HLEN - sizeof(struct iphdr) + - dev->hard_header_len; + + if (new_mtu < 68) return -EINVAL; + + if (new_mtu > max_mtu) { + if (strict) + return -EINVAL; + + new_mtu = max_mtu; + } + dev->mtu = new_mtu; return 0; } +static int geneve_change_mtu(struct net_device *dev, int new_mtu) +{ + return __geneve_change_mtu(dev, new_mtu, true); +} + static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) { struct ip_tunnel_info *info = skb_tunnel_info(skb); @@ -1161,6 +1178,7 @@ static void geneve_setup(struct net_device *dev) dev->hw_features |= NETIF_F_GSO_SOFTWARE; netif_keep_dst(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE; eth_hw_addr_random(dev); } @@ -1452,14 +1470,15 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name, return dev; err = geneve_configure(net, dev, &geneve_remote_unspec, - 0, 0, 0, htons(dst_port), true, 0); + 0, 0, 0, htons(dst_port), true, + GENEVE_F_UDP_ZERO_CSUM6_RX); if (err) goto err; /* openvswitch users expect packet sizes to be unrestricted, * so set the largest MTU we can. */ - err = geneve_change_mtu(dev, IP_MAX_MTU); + err = __geneve_change_mtu(dev, IP_MAX_MTU, false); if (err) goto err; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 1d3a66563bac..98e34fee45c7 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -1089,6 +1089,9 @@ static int netvsc_probe(struct hv_device *dev, net->ethtool_ops = ðtool_ops; SET_NETDEV_DEV(net, &dev->device); + /* We always need headroom for rndis header */ + net->needed_headroom = RNDIS_AND_PPI_SIZE; + /* Notify the netvsc driver of the new device */ memset(&device_info, 0, sizeof(device_info)); device_info.ring_size = ring_size; diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c index bf241a3ec5e5..db507e3bcab9 100644 --- a/drivers/net/phy/bcm7xxx.c +++ b/drivers/net/phy/bcm7xxx.c @@ -250,10 +250,6 @@ static int bcm7xxx_config_init(struct phy_device *phydev) phy_write(phydev, MII_BCM7XXX_AUX_MODE, MII_BCM7XX_64CLK_MDIO); phy_read(phydev, MII_BCM7XXX_AUX_MODE); - /* Workaround only required for 100Mbits/sec capable PHYs */ - if (phydev->supported & PHY_GBIT_FEATURES) - return 0; - /* set shadow mode 2 */ ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, MII_BCM7XXX_SHD_MODE_2, MII_BCM7XXX_SHD_MODE_2); @@ -270,7 +266,7 @@ static int bcm7xxx_config_init(struct phy_device *phydev) phy_write(phydev, MII_BCM7XXX_100TX_FALSE_CAR, 0x7555); /* reset shadow mode 2 */ - ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, MII_BCM7XXX_SHD_MODE_2, 0); + ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, MII_BCM7XXX_SHD_MODE_2); if (ret < 0) return ret; @@ -307,11 +303,6 @@ static int bcm7xxx_suspend(struct phy_device *phydev) return 0; } -static int bcm7xxx_dummy_config_init(struct phy_device *phydev) -{ - return 0; -} - #define BCM7XXX_28NM_GPHY(_oui, _name) \ { \ .phy_id = (_oui), \ @@ -337,7 +328,7 @@ static struct phy_driver bcm7xxx_driver[] = { .phy_id = PHY_ID_BCM7425, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM7425", - .features = PHY_GBIT_FEATURES | + .features = PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause, .flags = PHY_IS_INTERNAL, .config_init = bcm7xxx_config_init, @@ -349,7 +340,7 @@ static struct phy_driver bcm7xxx_driver[] = { .phy_id = PHY_ID_BCM7429, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM7429", - .features = PHY_GBIT_FEATURES | + .features = PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause, .flags = PHY_IS_INTERNAL, .config_init = bcm7xxx_config_init, @@ -361,7 +352,7 @@ static struct phy_driver bcm7xxx_driver[] = { .phy_id = PHY_ID_BCM7435, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM7435", - .features = PHY_GBIT_FEATURES | + .features = PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause, .flags = PHY_IS_INTERNAL, .config_init = bcm7xxx_config_init, @@ -369,30 +360,6 @@ static struct phy_driver bcm7xxx_driver[] = { .read_status = genphy_read_status, .suspend = bcm7xxx_suspend, .resume = bcm7xxx_config_init, -}, { - .phy_id = PHY_BCM_OUI_4, - .phy_id_mask = 0xffff0000, - .name = "Broadcom BCM7XXX 40nm", - .features = PHY_GBIT_FEATURES | - SUPPORTED_Pause | SUPPORTED_Asym_Pause, - .flags = PHY_IS_INTERNAL, - .config_init = bcm7xxx_config_init, - .config_aneg = genphy_config_aneg, - .read_status = genphy_read_status, - .suspend = bcm7xxx_suspend, - .resume = bcm7xxx_config_init, -}, { - .phy_id = PHY_BCM_OUI_5, - .phy_id_mask = 0xffffff00, - .name = "Broadcom BCM7XXX 65nm", - .features = PHY_BASIC_FEATURES | - SUPPORTED_Pause | SUPPORTED_Asym_Pause, - .flags = PHY_IS_INTERNAL, - .config_init = bcm7xxx_dummy_config_init, - .config_aneg = genphy_config_aneg, - .read_status = genphy_read_status, - .suspend = bcm7xxx_suspend, - .resume = bcm7xxx_config_init, } }; static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = { @@ -404,8 +371,6 @@ static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = { { PHY_ID_BCM7439, 0xfffffff0, }, { PHY_ID_BCM7435, 0xfffffff0, }, { PHY_ID_BCM7445, 0xfffffff0, }, - { PHY_BCM_OUI_4, 0xffff0000 }, - { PHY_BCM_OUI_5, 0xffffff00 }, { } }; diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index e3eb96443c97..ab1d0fcaf1d9 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -446,6 +446,12 @@ static int m88e1510_config_aneg(struct phy_device *phydev) if (err < 0) return err; + return 0; +} + +static int marvell_config_init(struct phy_device *phydev) +{ + /* Set registers from marvell,reg-init DT property */ return marvell_of_reg_init(phydev); } @@ -495,7 +501,7 @@ static int m88e1116r_config_init(struct phy_device *phydev) mdelay(500); - return 0; + return marvell_config_init(phydev); } static int m88e3016_config_init(struct phy_device *phydev) @@ -514,7 +520,7 @@ static int m88e3016_config_init(struct phy_device *phydev) if (reg < 0) return reg; - return 0; + return marvell_config_init(phydev); } static int m88e1111_config_init(struct phy_device *phydev) @@ -1078,6 +1084,7 @@ static struct phy_driver marvell_drivers[] = { .features = PHY_GBIT_FEATURES, .probe = marvell_probe, .flags = PHY_HAS_INTERRUPT, + .config_init = &marvell_config_init, .config_aneg = &marvell_config_aneg, .read_status = &genphy_read_status, .ack_interrupt = &marvell_ack_interrupt, @@ -1149,6 +1156,7 @@ static struct phy_driver marvell_drivers[] = { .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .probe = marvell_probe, + .config_init = &marvell_config_init, .config_aneg = &m88e1121_config_aneg, .read_status = &marvell_read_status, .ack_interrupt = &marvell_ack_interrupt, @@ -1167,6 +1175,7 @@ static struct phy_driver marvell_drivers[] = { .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .probe = marvell_probe, + .config_init = &marvell_config_init, .config_aneg = &m88e1318_config_aneg, .read_status = &marvell_read_status, .ack_interrupt = &marvell_ack_interrupt, @@ -1259,6 +1268,7 @@ static struct phy_driver marvell_drivers[] = { .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .probe = marvell_probe, + .config_init = &marvell_config_init, .config_aneg = &m88e1510_config_aneg, .read_status = &marvell_read_status, .ack_interrupt = &marvell_ack_interrupt, @@ -1277,6 +1287,7 @@ static struct phy_driver marvell_drivers[] = { .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .probe = marvell_probe, + .config_init = &marvell_config_init, .config_aneg = &m88e1510_config_aneg, .read_status = &marvell_read_status, .ack_interrupt = &marvell_ack_interrupt, diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index bad3f005faee..e551f3a89cfd 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1410,7 +1410,7 @@ int genphy_config_init(struct phy_device *phydev) features = (SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI | SUPPORTED_FIBRE | - SUPPORTED_BNC); + SUPPORTED_BNC | SUPPORTED_Pause | SUPPORTED_Asym_Pause); /* Do we support autonegotiation? */ val = phy_read(phydev, MII_BMSR); diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index f3c63022eb3c..4ddae8118c85 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -395,6 +395,8 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) if (!__pppoe_xmit(sk_pppox(relay_po), skb)) goto abort_put; + + sock_put(sk_pppox(relay_po)); } else { if (sock_queue_rcv_skb(sk, skb)) goto abort_kfree; diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 7f83504dfa69..cdde59089f72 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -395,6 +395,10 @@ config USB_NET_RNDIS_HOST The protocol specification is incomplete, and is controlled by (and for) Microsoft; it isn't an "Open" ecosystem or market. +config USB_NET_CDC_SUBSET_ENABLE + tristate + depends on USB_NET_CDC_SUBSET + config USB_NET_CDC_SUBSET tristate "Simple USB Network Links (CDC Ethernet subset)" depends on USB_USBNET @@ -413,6 +417,7 @@ config USB_NET_CDC_SUBSET config USB_ALI_M5632 bool "ALi M5632 based 'USB 2.0 Data Link' cables" depends on USB_NET_CDC_SUBSET + select USB_NET_CDC_SUBSET_ENABLE help Choose this option if you're using a host-to-host cable based on this design, which supports USB 2.0 high speed. @@ -420,6 +425,7 @@ config USB_ALI_M5632 config USB_AN2720 bool "AnchorChips 2720 based cables (Xircom PGUNET, ...)" depends on USB_NET_CDC_SUBSET + select USB_NET_CDC_SUBSET_ENABLE help Choose this option if you're using a host-to-host cable based on this design. Note that AnchorChips is now a @@ -428,6 +434,7 @@ config USB_AN2720 config USB_BELKIN bool "eTEK based host-to-host cables (Advance, Belkin, ...)" depends on USB_NET_CDC_SUBSET + select USB_NET_CDC_SUBSET_ENABLE default y help Choose this option if you're using a host-to-host cable @@ -437,6 +444,7 @@ config USB_BELKIN config USB_ARMLINUX bool "Embedded ARM Linux links (iPaq, ...)" depends on USB_NET_CDC_SUBSET + select USB_NET_CDC_SUBSET_ENABLE default y help Choose this option to support the "usb-eth" networking driver @@ -454,6 +462,7 @@ config USB_ARMLINUX config USB_EPSON2888 bool "Epson 2888 based firmware (DEVELOPMENT)" depends on USB_NET_CDC_SUBSET + select USB_NET_CDC_SUBSET_ENABLE help Choose this option to support the usb networking links used by some sample firmware from Epson. @@ -461,6 +470,7 @@ config USB_EPSON2888 config USB_KC2190 bool "KT Technology KC2190 based cables (InstaNet)" depends on USB_NET_CDC_SUBSET + select USB_NET_CDC_SUBSET_ENABLE help Choose this option if you're using a host-to-host cable with one of these chips. diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index b5f04068dbe4..37fb46aee341 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -23,7 +23,7 @@ obj-$(CONFIG_USB_NET_GL620A) += gl620a.o obj-$(CONFIG_USB_NET_NET1080) += net1080.o obj-$(CONFIG_USB_NET_PLUSB) += plusb.o obj-$(CONFIG_USB_NET_RNDIS_HOST) += rndis_host.o -obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o +obj-$(CONFIG_USB_NET_CDC_SUBSET_ENABLE) += cdc_subset.o obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o obj-$(CONFIG_USB_USBNET) += usbnet.o diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 23e9880791fc..570deef53f74 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -637,6 +637,7 @@ static const struct usb_device_id products[] = { /* 3. Combined interface devices matching on interface number */ {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ + {QMI_FIXED_INTF(0x05c6, 0x6001, 3)}, /* 4G LTE usb-modem U901 */ {QMI_FIXED_INTF(0x05c6, 0x7000, 0)}, {QMI_FIXED_INTF(0x05c6, 0x7001, 1)}, {QMI_FIXED_INTF(0x05c6, 0x7002, 1)}, diff --git a/drivers/net/vmxnet3/vmxnet3_defs.h b/drivers/net/vmxnet3/vmxnet3_defs.h index 221a53025fd0..72ba8ae7f09a 100644 --- a/drivers/net/vmxnet3/vmxnet3_defs.h +++ b/drivers/net/vmxnet3/vmxnet3_defs.h @@ -377,7 +377,7 @@ union Vmxnet3_GenericDesc { #define VMXNET3_TX_RING_MAX_SIZE 4096 #define VMXNET3_TC_RING_MAX_SIZE 4096 #define VMXNET3_RX_RING_MAX_SIZE 4096 -#define VMXNET3_RX_RING2_MAX_SIZE 2048 +#define VMXNET3_RX_RING2_MAX_SIZE 4096 #define VMXNET3_RC_RING_MAX_SIZE 8192 /* a list of reasons for queue stop */ diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h index bdb8a6c0f8aa..729c344e6774 100644 --- a/drivers/net/vmxnet3/vmxnet3_int.h +++ b/drivers/net/vmxnet3/vmxnet3_int.h @@ -69,10 +69,10 @@ /* * Version numbers */ -#define VMXNET3_DRIVER_VERSION_STRING "1.4.5.0-k" +#define VMXNET3_DRIVER_VERSION_STRING "1.4.6.0-k" /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */ -#define VMXNET3_DRIVER_VERSION_NUM 0x01040500 +#define VMXNET3_DRIVER_VERSION_NUM 0x01040600 #if defined(CONFIG_PCI_MSI) /* RSS only makes sense if MSI-X is supported. */ diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index a31cd954b308..e6944b29588e 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2171,9 +2171,11 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) #endif } - if (vxlan->flags & VXLAN_F_COLLECT_METADATA && - info && info->mode & IP_TUNNEL_INFO_TX) { - vxlan_xmit_one(skb, dev, NULL, false); + if (vxlan->flags & VXLAN_F_COLLECT_METADATA) { + if (info && info->mode & IP_TUNNEL_INFO_TX) + vxlan_xmit_one(skb, dev, NULL, false); + else + kfree_skb(skb); return NETDEV_TX_OK; } @@ -2537,6 +2539,7 @@ static void vxlan_setup(struct net_device *dev) dev->hw_features |= NETIF_F_GSO_SOFTWARE; dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; netif_keep_dst(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE; INIT_LIST_HEAD(&vxlan->next); diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 7a72407208b1..629225980463 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -1626,7 +1626,7 @@ try: if (state & Xpr) { void __iomem *scc_addr; unsigned long ring; - int i; + unsigned int i; /* * - the busy condition happens (sometimes); diff --git a/drivers/net/wireless/intel/iwlwifi/Kconfig b/drivers/net/wireless/intel/iwlwifi/Kconfig index 866067789330..7438fbeef744 100644 --- a/drivers/net/wireless/intel/iwlwifi/Kconfig +++ b/drivers/net/wireless/intel/iwlwifi/Kconfig @@ -53,7 +53,6 @@ config IWLWIFI_LEDS config IWLDVM tristate "Intel Wireless WiFi DVM Firmware support" - depends on m help This is the driver that supports the DVM firmware. The list of the devices that use this firmware is available here: diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c index c84a0299d43e..bce9b3420a13 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c @@ -7,6 +7,7 @@ * * Copyright(c) 2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -70,12 +71,15 @@ /* Highest firmware API version supported */ #define IWL8000_UCODE_API_MAX 20 +#define IWL8265_UCODE_API_MAX 20 /* Oldest version we won't warn about */ #define IWL8000_UCODE_API_OK 13 +#define IWL8265_UCODE_API_OK 20 /* Lowest firmware API version supported */ #define IWL8000_UCODE_API_MIN 13 +#define IWL8265_UCODE_API_MIN 20 /* NVM versions */ #define IWL8000_NVM_VERSION 0x0a1d @@ -93,6 +97,10 @@ #define IWL8000_MODULE_FIRMWARE(api) \ IWL8000_FW_PRE "-" __stringify(api) ".ucode" +#define IWL8265_FW_PRE "iwlwifi-8265-" +#define IWL8265_MODULE_FIRMWARE(api) \ + IWL8265_FW_PRE __stringify(api) ".ucode" + #define NVM_HW_SECTION_NUM_FAMILY_8000 10 #define DEFAULT_NVM_FILE_FAMILY_8000B "nvmData-8000B" #define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C" @@ -144,10 +152,7 @@ static const struct iwl_tt_params iwl8000_tt_params = { .support_tx_backoff = true, }; -#define IWL_DEVICE_8000 \ - .ucode_api_max = IWL8000_UCODE_API_MAX, \ - .ucode_api_ok = IWL8000_UCODE_API_OK, \ - .ucode_api_min = IWL8000_UCODE_API_MIN, \ +#define IWL_DEVICE_8000_COMMON \ .device_family = IWL_DEVICE_FAMILY_8000, \ .max_inst_size = IWL60_RTC_INST_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \ @@ -167,10 +172,28 @@ static const struct iwl_tt_params iwl8000_tt_params = { .thermal_params = &iwl8000_tt_params, \ .apmg_not_supported = true +#define IWL_DEVICE_8000 \ + IWL_DEVICE_8000_COMMON, \ + .ucode_api_max = IWL8000_UCODE_API_MAX, \ + .ucode_api_ok = IWL8000_UCODE_API_OK, \ + .ucode_api_min = IWL8000_UCODE_API_MIN \ + +#define IWL_DEVICE_8260 \ + IWL_DEVICE_8000_COMMON, \ + .ucode_api_max = IWL8000_UCODE_API_MAX, \ + .ucode_api_ok = IWL8000_UCODE_API_OK, \ + .ucode_api_min = IWL8000_UCODE_API_MIN \ + +#define IWL_DEVICE_8265 \ + IWL_DEVICE_8000_COMMON, \ + .ucode_api_max = IWL8265_UCODE_API_MAX, \ + .ucode_api_ok = IWL8265_UCODE_API_OK, \ + .ucode_api_min = IWL8265_UCODE_API_MIN \ + const struct iwl_cfg iwl8260_2n_cfg = { .name = "Intel(R) Dual Band Wireless N 8260", .fw_name_pre = IWL8000_FW_PRE, - IWL_DEVICE_8000, + IWL_DEVICE_8260, .ht_params = &iwl8000_ht_params, .nvm_ver = IWL8000_NVM_VERSION, .nvm_calib_ver = IWL8000_TX_POWER_VERSION, @@ -179,7 +202,7 @@ const struct iwl_cfg iwl8260_2n_cfg = { const struct iwl_cfg iwl8260_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 8260", .fw_name_pre = IWL8000_FW_PRE, - IWL_DEVICE_8000, + IWL_DEVICE_8260, .ht_params = &iwl8000_ht_params, .nvm_ver = IWL8000_NVM_VERSION, .nvm_calib_ver = IWL8000_TX_POWER_VERSION, @@ -188,8 +211,8 @@ const struct iwl_cfg iwl8260_2ac_cfg = { const struct iwl_cfg iwl8265_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 8265", - .fw_name_pre = IWL8000_FW_PRE, - IWL_DEVICE_8000, + .fw_name_pre = IWL8265_FW_PRE, + IWL_DEVICE_8265, .ht_params = &iwl8000_ht_params, .nvm_ver = IWL8000_NVM_VERSION, .nvm_calib_ver = IWL8000_TX_POWER_VERSION, @@ -209,7 +232,7 @@ const struct iwl_cfg iwl4165_2ac_cfg = { const struct iwl_cfg iwl8260_2ac_sdio_cfg = { .name = "Intel(R) Dual Band Wireless-AC 8260", .fw_name_pre = IWL8000_FW_PRE, - IWL_DEVICE_8000, + IWL_DEVICE_8260, .ht_params = &iwl8000_ht_params, .nvm_ver = IWL8000_NVM_VERSION, .nvm_calib_ver = IWL8000_TX_POWER_VERSION, @@ -236,3 +259,4 @@ const struct iwl_cfg iwl4165_2ac_sdio_cfg = { }; MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK)); +MODULE_FIRMWARE(IWL8265_MODULE_FIRMWARE(IWL8265_UCODE_API_OK)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 7acb49075683..ab4c2a0470b2 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -243,8 +243,10 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) { char rev_step = 'A' + CSR_HW_REV_STEP(drv->trans->hw_rev); - snprintf(drv->firmware_name, sizeof(drv->firmware_name), - "%s%c-%s.ucode", name_pre, rev_step, tag); + if (rev_step != 'A') + snprintf(drv->firmware_name, + sizeof(drv->firmware_name), "%s%c-%s.ucode", + name_pre, rev_step, tag); } IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n", diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 9a15642f80dd..ea1e177c2ea1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -1298,6 +1298,10 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, return -EBUSY; } + /* we don't support "match all" in the firmware */ + if (!req->n_match_sets) + return -EOPNOTSUPP; + ret = iwl_mvm_check_running_scans(mvm, type); if (ret) return ret; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index cc3888e2700d..73c95594eabe 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -490,6 +490,15 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans) iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); } +static inline void iwl_enable_fw_load_int(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + + IWL_DEBUG_ISR(trans, "Enabling FW load interrupt\n"); + trans_pcie->inta_mask = CSR_INT_BIT_FH_TX; + iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); +} + static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index ccafbd8cf4b3..152cf9ad9566 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -1438,9 +1438,11 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) inta & ~trans_pcie->inta_mask); } - /* Re-enable all interrupts */ - /* only Re-enable if disabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &trans->status)) + /* we are loading the firmware, enable FH_TX interrupt only */ + if (handled & CSR_INT_BIT_FH_TX) + iwl_enable_fw_load_int(trans); + /* only Re-enable all interrupt if disabled by irq */ + else if (test_bit(STATUS_INT_ENABLED, &trans->status)) iwl_enable_interrupts(trans); /* Re-enable RF_KILL if it occurred */ else if (handled & CSR_INT_BIT_RF_KILL) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index d60a467a983c..5a854c609477 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1021,82 +1021,6 @@ static int iwl_pcie_load_given_ucode_8000(struct iwl_trans *trans, &first_ucode_section); } -static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, - const struct fw_img *fw, bool run_in_rfkill) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - bool hw_rfkill; - int ret; - - mutex_lock(&trans_pcie->mutex); - - /* Someone called stop_device, don't try to start_fw */ - if (trans_pcie->is_down) { - IWL_WARN(trans, - "Can't start_fw since the HW hasn't been started\n"); - ret = EIO; - goto out; - } - - /* This may fail if AMT took ownership of the device */ - if (iwl_pcie_prepare_card_hw(trans)) { - IWL_WARN(trans, "Exit HW not ready\n"); - ret = -EIO; - goto out; - } - - iwl_enable_rfkill_int(trans); - - /* If platform's RF_KILL switch is NOT set to KILL */ - hw_rfkill = iwl_is_rfkill_set(trans); - if (hw_rfkill) - set_bit(STATUS_RFKILL, &trans->status); - else - clear_bit(STATUS_RFKILL, &trans->status); - iwl_trans_pcie_rf_kill(trans, hw_rfkill); - if (hw_rfkill && !run_in_rfkill) { - ret = -ERFKILL; - goto out; - } - - iwl_write32(trans, CSR_INT, 0xFFFFFFFF); - - ret = iwl_pcie_nic_init(trans); - if (ret) { - IWL_ERR(trans, "Unable to init nic\n"); - goto out; - } - - /* make sure rfkill handshake bits are cleared */ - iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - - /* clear (again), then enable host interrupts */ - iwl_write32(trans, CSR_INT, 0xFFFFFFFF); - iwl_enable_interrupts(trans); - - /* really make sure rfkill handshake bits are cleared */ - iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - - /* Load the given image to the HW */ - if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) - ret = iwl_pcie_load_given_ucode_8000(trans, fw); - else - ret = iwl_pcie_load_given_ucode(trans, fw); - -out: - mutex_unlock(&trans_pcie->mutex); - return ret; -} - -static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr) -{ - iwl_pcie_reset_ict(trans); - iwl_pcie_tx_start(trans, scd_addr); -} - static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -1127,7 +1051,8 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) * already dead. */ if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) { - IWL_DEBUG_INFO(trans, "DEVICE_ENABLED bit was set and is now cleared\n"); + IWL_DEBUG_INFO(trans, + "DEVICE_ENABLED bit was set and is now cleared\n"); iwl_pcie_tx_stop(trans); iwl_pcie_rx_stop(trans); @@ -1161,7 +1086,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) iwl_disable_interrupts(trans); spin_unlock(&trans_pcie->irq_lock); - /* clear all status bits */ clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); clear_bit(STATUS_INT_ENABLED, &trans->status); @@ -1194,10 +1118,116 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) if (hw_rfkill != was_hw_rfkill) iwl_trans_pcie_rf_kill(trans, hw_rfkill); - /* re-take ownership to prevent other users from stealing the deivce */ + /* re-take ownership to prevent other users from stealing the device */ iwl_pcie_prepare_card_hw(trans); } +static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, + const struct fw_img *fw, bool run_in_rfkill) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + bool hw_rfkill; + int ret; + + /* This may fail if AMT took ownership of the device */ + if (iwl_pcie_prepare_card_hw(trans)) { + IWL_WARN(trans, "Exit HW not ready\n"); + ret = -EIO; + goto out; + } + + iwl_enable_rfkill_int(trans); + + iwl_write32(trans, CSR_INT, 0xFFFFFFFF); + + /* + * We enabled the RF-Kill interrupt and the handler may very + * well be running. Disable the interrupts to make sure no other + * interrupt can be fired. + */ + iwl_disable_interrupts(trans); + + /* Make sure it finished running */ + synchronize_irq(trans_pcie->pci_dev->irq); + + mutex_lock(&trans_pcie->mutex); + + /* If platform's RF_KILL switch is NOT set to KILL */ + hw_rfkill = iwl_is_rfkill_set(trans); + if (hw_rfkill) + set_bit(STATUS_RFKILL, &trans->status); + else + clear_bit(STATUS_RFKILL, &trans->status); + iwl_trans_pcie_rf_kill(trans, hw_rfkill); + if (hw_rfkill && !run_in_rfkill) { + ret = -ERFKILL; + goto out; + } + + /* Someone called stop_device, don't try to start_fw */ + if (trans_pcie->is_down) { + IWL_WARN(trans, + "Can't start_fw since the HW hasn't been started\n"); + ret = -EIO; + goto out; + } + + /* make sure rfkill handshake bits are cleared */ + iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); + + /* clear (again), then enable host interrupts */ + iwl_write32(trans, CSR_INT, 0xFFFFFFFF); + + ret = iwl_pcie_nic_init(trans); + if (ret) { + IWL_ERR(trans, "Unable to init nic\n"); + goto out; + } + + /* + * Now, we load the firmware and don't want to be interrupted, even + * by the RF-Kill interrupt (hence mask all the interrupt besides the + * FH_TX interrupt which is needed to load the firmware). If the + * RF-Kill switch is toggled, we will find out after having loaded + * the firmware and return the proper value to the caller. + */ + iwl_enable_fw_load_int(trans); + + /* really make sure rfkill handshake bits are cleared */ + iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + + /* Load the given image to the HW */ + if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) + ret = iwl_pcie_load_given_ucode_8000(trans, fw); + else + ret = iwl_pcie_load_given_ucode(trans, fw); + iwl_enable_interrupts(trans); + + /* re-check RF-Kill state since we may have missed the interrupt */ + hw_rfkill = iwl_is_rfkill_set(trans); + if (hw_rfkill) + set_bit(STATUS_RFKILL, &trans->status); + else + clear_bit(STATUS_RFKILL, &trans->status); + + iwl_trans_pcie_rf_kill(trans, hw_rfkill); + if (hw_rfkill && !run_in_rfkill) + ret = -ERFKILL; + +out: + mutex_unlock(&trans_pcie->mutex); + return ret; +} + +static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr) +{ + iwl_pcie_reset_ict(trans); + iwl_pcie_tx_start(trans, scd_addr); +} + static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); diff --git a/drivers/net/wireless/realtek/rtlwifi/rc.c b/drivers/net/wireless/realtek/rtlwifi/rc.c index 74c14ce28238..28f7010e7108 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rc.c +++ b/drivers/net/wireless/realtek/rtlwifi/rc.c @@ -138,6 +138,11 @@ static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv, ((wireless_mode == WIRELESS_MODE_N_5G) || (wireless_mode == WIRELESS_MODE_N_24G))) rate->flags |= IEEE80211_TX_RC_MCS; + if (sta && sta->vht_cap.vht_supported && + (wireless_mode == WIRELESS_MODE_AC_5G || + wireless_mode == WIRELESS_MODE_AC_24G || + wireless_mode == WIRELESS_MODE_AC_ONLY)) + rate->flags |= IEEE80211_TX_RC_VHT_MCS; } } diff --git a/drivers/net/wireless/ti/wlcore/io.c b/drivers/net/wireless/ti/wlcore/io.c index 9ac118e727e9..564ca750c5ee 100644 --- a/drivers/net/wireless/ti/wlcore/io.c +++ b/drivers/net/wireless/ti/wlcore/io.c @@ -175,14 +175,14 @@ int wlcore_set_partition(struct wl1271 *wl, if (ret < 0) goto out; + /* We don't need the size of the last partition, as it is + * automatically calculated based on the total memory size and + * the sizes of the previous partitions. + */ ret = wlcore_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); if (ret < 0) goto out; - ret = wlcore_raw_write32(wl, HW_PART3_SIZE_ADDR, p->mem3.size); - if (ret < 0) - goto out; - out: return ret; } diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h index 6c257b54f415..10cf3747694d 100644 --- a/drivers/net/wireless/ti/wlcore/io.h +++ b/drivers/net/wireless/ti/wlcore/io.h @@ -36,8 +36,8 @@ #define HW_PART1_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 12) #define HW_PART2_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 16) #define HW_PART2_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 20) -#define HW_PART3_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 24) -#define HW_PART3_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 28) +#define HW_PART3_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 24) + #define HW_ACCESS_REGISTER_SIZE 4 #define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index 7e2c43f701bc..5d28e9405f32 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -382,18 +382,18 @@ static const struct nd_cmd_desc __nd_cmd_bus_descs[] = { [ND_CMD_ARS_CAP] = { .in_num = 2, .in_sizes = { 8, 8, }, - .out_num = 2, - .out_sizes = { 4, 4, }, + .out_num = 4, + .out_sizes = { 4, 4, 4, 4, }, }, [ND_CMD_ARS_START] = { - .in_num = 4, - .in_sizes = { 8, 8, 2, 6, }, - .out_num = 1, - .out_sizes = { 4, }, + .in_num = 5, + .in_sizes = { 8, 8, 2, 1, 5, }, + .out_num = 2, + .out_sizes = { 4, 4, }, }, [ND_CMD_ARS_STATUS] = { - .out_num = 2, - .out_sizes = { 4, UINT_MAX, }, + .out_num = 3, + .out_sizes = { 4, 4, UINT_MAX, }, }, }; @@ -442,8 +442,8 @@ u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd, return in_field[1]; else if (nvdimm && cmd == ND_CMD_VENDOR && idx == 2) return out_field[1]; - else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 1) - return ND_CMD_ARS_STATUS_MAX; + else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2) + return out_field[1] - 8; return UINT_MAX; } diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 7edf31671dab..8d0b54670184 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -41,7 +41,7 @@ struct pmem_device { phys_addr_t phys_addr; /* when non-zero this device is hosting a 'pfn' instance */ phys_addr_t data_offset; - unsigned long pfn_flags; + u64 pfn_flags; void __pmem *virt_addr; size_t size; struct badblocks bb; diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig index 5d6237391dcd..b586d84f2518 100644 --- a/drivers/nvme/host/Kconfig +++ b/drivers/nvme/host/Kconfig @@ -17,5 +17,6 @@ config BLK_DEV_NVME_SCSI and block devices nodes, as well a a translation for a small number of selected SCSI commands to NVMe commands to the NVMe driver. If you don't know what this means you probably want - to say N here, and if you know what it means you probably - want to say N as well. + to say N here, unless you run a distro that abuses the SCSI + emulation to provide stable device names for mount by id, like + some OpenSuSE and SLES versions. diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index c5bf001af559..03c46412fff4 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -55,8 +55,9 @@ static void nvme_free_ns(struct kref *kref) ns->disk->private_data = NULL; spin_unlock(&dev_list_lock); - nvme_put_ctrl(ns->ctrl); put_disk(ns->disk); + ida_simple_remove(&ns->ctrl->ns_ida, ns->instance); + nvme_put_ctrl(ns->ctrl); kfree(ns); } @@ -183,7 +184,7 @@ int __nvme_submit_user_cmd(struct request_queue *q, struct nvme_command *cmd, goto out_unmap; } - if (meta_buffer) { + if (meta_buffer && meta_len) { struct bio_integrity_payload *bip; meta = kmalloc(meta_len, GFP_KERNEL); @@ -373,6 +374,8 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) if (copy_from_user(&io, uio, sizeof(io))) return -EFAULT; + if (io.flags) + return -EINVAL; switch (io.opcode) { case nvme_cmd_write: @@ -424,6 +427,8 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns, return -EACCES; if (copy_from_user(&cmd, ucmd, sizeof(cmd))) return -EFAULT; + if (cmd.flags) + return -EINVAL; memset(&c, 0, sizeof(c)); c.common.opcode = cmd.opcode; @@ -556,6 +561,10 @@ static int nvme_revalidate_disk(struct gendisk *disk) u16 old_ms; unsigned short bs; + if (test_bit(NVME_NS_DEAD, &ns->flags)) { + set_capacity(disk, 0); + return -ENODEV; + } if (nvme_identify_ns(ns->ctrl, ns->ns_id, &id)) { dev_warn(ns->ctrl->dev, "%s: Identify failure nvme%dn%d\n", __func__, ns->ctrl->instance, ns->ns_id); @@ -831,6 +840,23 @@ int nvme_shutdown_ctrl(struct nvme_ctrl *ctrl) return ret; } +static void nvme_set_queue_limits(struct nvme_ctrl *ctrl, + struct request_queue *q) +{ + if (ctrl->max_hw_sectors) { + u32 max_segments = + (ctrl->max_hw_sectors / (ctrl->page_size >> 9)) + 1; + + blk_queue_max_hw_sectors(q, ctrl->max_hw_sectors); + blk_queue_max_segments(q, min_t(u32, max_segments, USHRT_MAX)); + } + if (ctrl->stripe_size) + blk_queue_chunk_sectors(q, ctrl->stripe_size >> 9); + if (ctrl->vwc & NVME_CTRL_VWC_PRESENT) + blk_queue_flush(q, REQ_FLUSH | REQ_FUA); + blk_queue_virt_boundary(q, ctrl->page_size - 1); +} + /* * Initialize the cached copies of the Identify data and various controller * register in our nvme_ctrl structure. This should be called as soon as @@ -888,6 +914,8 @@ int nvme_init_identify(struct nvme_ctrl *ctrl) } } + nvme_set_queue_limits(ctrl, ctrl->admin_q); + kfree(id); return 0; } @@ -1118,10 +1146,13 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid) if (!ns) return; + ns->instance = ida_simple_get(&ctrl->ns_ida, 1, 0, GFP_KERNEL); + if (ns->instance < 0) + goto out_free_ns; + ns->queue = blk_mq_init_queue(ctrl->tagset); if (IS_ERR(ns->queue)) - goto out_free_ns; - queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, ns->queue); + goto out_release_instance; queue_flag_set_unlocked(QUEUE_FLAG_NONROT, ns->queue); ns->queue->queuedata = ns; ns->ctrl = ctrl; @@ -1135,17 +1166,9 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid) ns->disk = disk; ns->lba_shift = 9; /* set to a default value for 512 until disk is validated */ + blk_queue_logical_block_size(ns->queue, 1 << ns->lba_shift); - if (ctrl->max_hw_sectors) { - blk_queue_max_hw_sectors(ns->queue, ctrl->max_hw_sectors); - blk_queue_max_segments(ns->queue, - (ctrl->max_hw_sectors / (ctrl->page_size >> 9)) + 1); - } - if (ctrl->stripe_size) - blk_queue_chunk_sectors(ns->queue, ctrl->stripe_size >> 9); - if (ctrl->vwc & NVME_CTRL_VWC_PRESENT) - blk_queue_flush(ns->queue, REQ_FLUSH | REQ_FUA); - blk_queue_virt_boundary(ns->queue, ctrl->page_size - 1); + nvme_set_queue_limits(ctrl, ns->queue); disk->major = nvme_major; disk->first_minor = 0; @@ -1154,7 +1177,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid) disk->queue = ns->queue; disk->driverfs_dev = ctrl->device; disk->flags = GENHD_FL_EXT_DEVT; - sprintf(disk->disk_name, "nvme%dn%d", ctrl->instance, nsid); + sprintf(disk->disk_name, "nvme%dn%d", ctrl->instance, ns->instance); if (nvme_revalidate_disk(ns->disk)) goto out_free_disk; @@ -1174,40 +1197,29 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid) kfree(disk); out_free_queue: blk_cleanup_queue(ns->queue); + out_release_instance: + ida_simple_remove(&ctrl->ns_ida, ns->instance); out_free_ns: kfree(ns); } static void nvme_ns_remove(struct nvme_ns *ns) { - bool kill = nvme_io_incapable(ns->ctrl) && - !blk_queue_dying(ns->queue); - - lockdep_assert_held(&ns->ctrl->namespaces_mutex); - - if (kill) { - blk_set_queue_dying(ns->queue); + if (test_and_set_bit(NVME_NS_REMOVING, &ns->flags)) + return; - /* - * The controller was shutdown first if we got here through - * device removal. The shutdown may requeue outstanding - * requests. These need to be aborted immediately so - * del_gendisk doesn't block indefinitely for their completion. - */ - blk_mq_abort_requeue_list(ns->queue); - } if (ns->disk->flags & GENHD_FL_UP) { if (blk_get_integrity(ns->disk)) blk_integrity_unregister(ns->disk); sysfs_remove_group(&disk_to_dev(ns->disk)->kobj, &nvme_ns_attr_group); del_gendisk(ns->disk); - } - if (kill || !blk_queue_dying(ns->queue)) { blk_mq_abort_requeue_list(ns->queue); blk_cleanup_queue(ns->queue); } + mutex_lock(&ns->ctrl->namespaces_mutex); list_del_init(&ns->list); + mutex_unlock(&ns->ctrl->namespaces_mutex); nvme_put_ns(ns); } @@ -1301,10 +1313,8 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl) { struct nvme_ns *ns, *next; - mutex_lock(&ctrl->namespaces_mutex); list_for_each_entry_safe(ns, next, &ctrl->namespaces, list) nvme_ns_remove(ns); - mutex_unlock(&ctrl->namespaces_mutex); } static DEFINE_IDA(nvme_instance_ida); @@ -1351,6 +1361,7 @@ static void nvme_free_ctrl(struct kref *kref) put_device(ctrl->device); nvme_release_instance(ctrl); + ida_destroy(&ctrl->ns_ida); ctrl->ops->free_ctrl(ctrl); } @@ -1391,6 +1402,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, } get_device(ctrl->device); dev_set_drvdata(ctrl->device, ctrl); + ida_init(&ctrl->ns_ida); spin_lock(&dev_list_lock); list_add_tail(&ctrl->node, &nvme_ctrl_list); @@ -1403,6 +1415,38 @@ out: return ret; } +/** + * nvme_kill_queues(): Ends all namespace queues + * @ctrl: the dead controller that needs to end + * + * Call this function when the driver determines it is unable to get the + * controller in a state capable of servicing IO. + */ +void nvme_kill_queues(struct nvme_ctrl *ctrl) +{ + struct nvme_ns *ns; + + mutex_lock(&ctrl->namespaces_mutex); + list_for_each_entry(ns, &ctrl->namespaces, list) { + if (!kref_get_unless_zero(&ns->kref)) + continue; + + /* + * Revalidating a dead namespace sets capacity to 0. This will + * end buffered writers dirtying pages that can't be synced. + */ + if (!test_and_set_bit(NVME_NS_DEAD, &ns->flags)) + revalidate_disk(ns->disk); + + blk_set_queue_dying(ns->queue); + blk_mq_abort_requeue_list(ns->queue); + blk_mq_start_stopped_hw_queues(ns->queue, true); + + nvme_put_ns(ns); + } + mutex_unlock(&ctrl->namespaces_mutex); +} + void nvme_stop_queues(struct nvme_ctrl *ctrl) { struct nvme_ns *ns; diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c index 5cd3725e2fa4..6bb15e4926dc 100644 --- a/drivers/nvme/host/lightnvm.c +++ b/drivers/nvme/host/lightnvm.c @@ -146,9 +146,10 @@ struct nvme_nvm_command { }; }; +#define NVME_NVM_LP_MLC_PAIRS 886 struct nvme_nvm_lp_mlc { __u16 num_pairs; - __u8 pairs[886]; + __u8 pairs[NVME_NVM_LP_MLC_PAIRS]; }; struct nvme_nvm_lp_tbl { @@ -282,9 +283,14 @@ static int init_grps(struct nvm_id *nvm_id, struct nvme_nvm_id *nvme_nvm_id) memcpy(dst->lptbl.id, src->lptbl.id, 8); dst->lptbl.mlc.num_pairs = le16_to_cpu(src->lptbl.mlc.num_pairs); - /* 4 bits per pair */ + + if (dst->lptbl.mlc.num_pairs > NVME_NVM_LP_MLC_PAIRS) { + pr_err("nvm: number of MLC pairs not supported\n"); + return -EINVAL; + } + memcpy(dst->lptbl.mlc.pairs, src->lptbl.mlc.pairs, - dst->lptbl.mlc.num_pairs >> 1); + dst->lptbl.mlc.num_pairs); } } diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 4fb5bb737868..fb15ba5f5d19 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -72,6 +72,7 @@ struct nvme_ctrl { struct mutex namespaces_mutex; struct device *device; /* char device */ struct list_head node; + struct ida ns_ida; char name[12]; char serial[20]; @@ -102,6 +103,7 @@ struct nvme_ns { struct request_queue *queue; struct gendisk *disk; struct kref kref; + int instance; u8 eui[8]; u8 uuid[16]; @@ -112,6 +114,11 @@ struct nvme_ns { bool ext; u8 pi_type; int type; + unsigned long flags; + +#define NVME_NS_REMOVING 0 +#define NVME_NS_DEAD 1 + u64 mode_select_num_blocks; u32 mode_select_block_len; }; @@ -139,9 +146,9 @@ static inline bool nvme_io_incapable(struct nvme_ctrl *ctrl) u32 val = 0; if (ctrl->ops->io_incapable(ctrl)) - return false; + return true; if (ctrl->ops->reg_read32(ctrl, NVME_REG_CSTS, &val)) - return false; + return true; return val & NVME_CSTS_CFS; } @@ -240,6 +247,7 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl); void nvme_stop_queues(struct nvme_ctrl *ctrl); void nvme_start_queues(struct nvme_ctrl *ctrl); +void nvme_kill_queues(struct nvme_ctrl *ctrl); struct request *nvme_alloc_request(struct request_queue *q, struct nvme_command *cmd, unsigned int flags); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 72ef8322d32a..680f5780750c 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -86,7 +86,6 @@ struct nvme_queue; static int nvme_reset(struct nvme_dev *dev); static void nvme_process_cq(struct nvme_queue *nvmeq); -static void nvme_remove_dead_ctrl(struct nvme_dev *dev); static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown); /* @@ -120,6 +119,7 @@ struct nvme_dev { unsigned long flags; #define NVME_CTRL_RESETTING 0 +#define NVME_CTRL_REMOVING 1 struct nvme_ctrl ctrl; struct completion ioq_wait; @@ -286,6 +286,17 @@ static int nvme_init_request(void *data, struct request *req, return 0; } +static void nvme_queue_scan(struct nvme_dev *dev) +{ + /* + * Do not queue new scan work when a controller is reset during + * removal. + */ + if (test_bit(NVME_CTRL_REMOVING, &dev->flags)) + return; + queue_work(nvme_workq, &dev->scan_work); +} + static void nvme_complete_async_event(struct nvme_dev *dev, struct nvme_completion *cqe) { @@ -300,7 +311,7 @@ static void nvme_complete_async_event(struct nvme_dev *dev, switch (result & 0xff07) { case NVME_AER_NOTICE_NS_CHANGED: dev_info(dev->dev, "rescanning\n"); - queue_work(nvme_workq, &dev->scan_work); + nvme_queue_scan(dev); default: dev_warn(dev->dev, "async event result %08x\n", result); } @@ -678,6 +689,14 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, blk_mq_start_request(req); spin_lock_irq(&nvmeq->q_lock); + if (unlikely(nvmeq->cq_vector < 0)) { + if (ns && !test_bit(NVME_NS_DEAD, &ns->flags)) + ret = BLK_MQ_RQ_QUEUE_BUSY; + else + ret = BLK_MQ_RQ_QUEUE_ERROR; + spin_unlock_irq(&nvmeq->q_lock); + goto out; + } __nvme_submit_cmd(nvmeq, &cmnd); nvme_process_cq(nvmeq); spin_unlock_irq(&nvmeq->q_lock); @@ -999,7 +1018,7 @@ static void nvme_cancel_queue_ios(struct request *req, void *data, bool reserved if (!blk_mq_request_started(req)) return; - dev_warn(nvmeq->q_dmadev, + dev_dbg_ratelimited(nvmeq->q_dmadev, "Cancelling I/O %d QID %d\n", req->tag, nvmeq->qid); status = NVME_SC_ABORT_REQ; @@ -1245,6 +1264,12 @@ static struct blk_mq_ops nvme_mq_ops = { static void nvme_dev_remove_admin(struct nvme_dev *dev) { if (dev->ctrl.admin_q && !blk_queue_dying(dev->ctrl.admin_q)) { + /* + * If the controller was reset during removal, it's possible + * user requests may be waiting on a stopped queue. Start the + * queue to flush these to completion. + */ + blk_mq_start_stopped_hw_queues(dev->ctrl.admin_q, true); blk_cleanup_queue(dev->ctrl.admin_q); blk_mq_free_tag_set(&dev->admin_tagset); } @@ -1685,14 +1710,14 @@ static int nvme_dev_add(struct nvme_dev *dev) return 0; dev->ctrl.tagset = &dev->tagset; } - queue_work(nvme_workq, &dev->scan_work); + nvme_queue_scan(dev); return 0; } -static int nvme_dev_map(struct nvme_dev *dev) +static int nvme_pci_enable(struct nvme_dev *dev) { u64 cap; - int bars, result = -ENOMEM; + int result = -ENOMEM; struct pci_dev *pdev = to_pci_dev(dev->dev); if (pci_enable_device_mem(pdev)) @@ -1700,24 +1725,14 @@ static int nvme_dev_map(struct nvme_dev *dev) dev->entry[0].vector = pdev->irq; pci_set_master(pdev); - bars = pci_select_bars(pdev, IORESOURCE_MEM); - if (!bars) - goto disable_pci; - - if (pci_request_selected_regions(pdev, bars, "nvme")) - goto disable_pci; if (dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64)) && dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(32))) goto disable; - dev->bar = ioremap(pci_resource_start(pdev, 0), 8192); - if (!dev->bar) - goto disable; - if (readl(dev->bar + NVME_REG_CSTS) == -1) { result = -ENODEV; - goto unmap; + goto disable; } /* @@ -1727,7 +1742,7 @@ static int nvme_dev_map(struct nvme_dev *dev) if (!pdev->irq) { result = pci_enable_msix(pdev, dev->entry, 1); if (result < 0) - goto unmap; + goto disable; } cap = lo_hi_readq(dev->bar + NVME_REG_CAP); @@ -1754,18 +1769,20 @@ static int nvme_dev_map(struct nvme_dev *dev) pci_save_state(pdev); return 0; - unmap: - iounmap(dev->bar); - dev->bar = NULL; disable: - pci_release_regions(pdev); - disable_pci: pci_disable_device(pdev); return result; } static void nvme_dev_unmap(struct nvme_dev *dev) { + if (dev->bar) + iounmap(dev->bar); + pci_release_regions(to_pci_dev(dev->dev)); +} + +static void nvme_pci_disable(struct nvme_dev *dev) +{ struct pci_dev *pdev = to_pci_dev(dev->dev); if (pdev->msi_enabled) @@ -1773,12 +1790,6 @@ static void nvme_dev_unmap(struct nvme_dev *dev) else if (pdev->msix_enabled) pci_disable_msix(pdev); - if (dev->bar) { - iounmap(dev->bar); - dev->bar = NULL; - pci_release_regions(pdev); - } - if (pci_is_enabled(pdev)) { pci_disable_pcie_error_reporting(pdev); pci_disable_device(pdev); @@ -1837,7 +1848,7 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) nvme_dev_list_remove(dev); mutex_lock(&dev->shutdown_lock); - if (dev->bar) { + if (pci_is_enabled(to_pci_dev(dev->dev))) { nvme_stop_queues(&dev->ctrl); csts = readl(dev->bar + NVME_REG_CSTS); } @@ -1850,7 +1861,7 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) nvme_disable_io_queues(dev); nvme_disable_admin_queue(dev, shutdown); } - nvme_dev_unmap(dev); + nvme_pci_disable(dev); for (i = dev->queue_count - 1; i >= 0; i--) nvme_clear_queue(dev->queues[i]); @@ -1894,10 +1905,20 @@ static void nvme_pci_free_ctrl(struct nvme_ctrl *ctrl) kfree(dev); } +static void nvme_remove_dead_ctrl(struct nvme_dev *dev, int status) +{ + dev_warn(dev->dev, "Removing after probe failure status: %d\n", status); + + kref_get(&dev->ctrl.kref); + nvme_dev_disable(dev, false); + if (!schedule_work(&dev->remove_work)) + nvme_put_ctrl(&dev->ctrl); +} + static void nvme_reset_work(struct work_struct *work) { struct nvme_dev *dev = container_of(work, struct nvme_dev, reset_work); - int result; + int result = -ENODEV; if (WARN_ON(test_bit(NVME_CTRL_RESETTING, &dev->flags))) goto out; @@ -1906,37 +1927,37 @@ static void nvme_reset_work(struct work_struct *work) * If we're called to reset a live controller first shut it down before * moving on. */ - if (dev->bar) + if (dev->ctrl.ctrl_config & NVME_CC_ENABLE) nvme_dev_disable(dev, false); set_bit(NVME_CTRL_RESETTING, &dev->flags); - result = nvme_dev_map(dev); + result = nvme_pci_enable(dev); if (result) goto out; result = nvme_configure_admin_queue(dev); if (result) - goto unmap; + goto out; nvme_init_queue(dev->queues[0], 0); result = nvme_alloc_admin_tags(dev); if (result) - goto disable; + goto out; result = nvme_init_identify(&dev->ctrl); if (result) - goto free_tags; + goto out; result = nvme_setup_io_queues(dev); if (result) - goto free_tags; + goto out; dev->ctrl.event_limit = NVME_NR_AEN_COMMANDS; result = nvme_dev_list_add(dev); if (result) - goto remove; + goto out; /* * Keep the controller around but remove all namespaces if we don't have @@ -1953,19 +1974,8 @@ static void nvme_reset_work(struct work_struct *work) clear_bit(NVME_CTRL_RESETTING, &dev->flags); return; - remove: - nvme_dev_list_remove(dev); - free_tags: - nvme_dev_remove_admin(dev); - blk_put_queue(dev->ctrl.admin_q); - dev->ctrl.admin_q = NULL; - dev->queues[0]->tags = NULL; - disable: - nvme_disable_admin_queue(dev, false); - unmap: - nvme_dev_unmap(dev); out: - nvme_remove_dead_ctrl(dev); + nvme_remove_dead_ctrl(dev, result); } static void nvme_remove_dead_ctrl_work(struct work_struct *work) @@ -1973,19 +1983,12 @@ static void nvme_remove_dead_ctrl_work(struct work_struct *work) struct nvme_dev *dev = container_of(work, struct nvme_dev, remove_work); struct pci_dev *pdev = to_pci_dev(dev->dev); + nvme_kill_queues(&dev->ctrl); if (pci_get_drvdata(pdev)) pci_stop_and_remove_bus_device_locked(pdev); nvme_put_ctrl(&dev->ctrl); } -static void nvme_remove_dead_ctrl(struct nvme_dev *dev) -{ - dev_warn(dev->dev, "Removing after probe failure\n"); - kref_get(&dev->ctrl.kref); - if (!schedule_work(&dev->remove_work)) - nvme_put_ctrl(&dev->ctrl); -} - static int nvme_reset(struct nvme_dev *dev) { if (!dev->ctrl.admin_q || blk_queue_dying(dev->ctrl.admin_q)) @@ -2037,6 +2040,27 @@ static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = { .free_ctrl = nvme_pci_free_ctrl, }; +static int nvme_dev_map(struct nvme_dev *dev) +{ + int bars; + struct pci_dev *pdev = to_pci_dev(dev->dev); + + bars = pci_select_bars(pdev, IORESOURCE_MEM); + if (!bars) + return -ENODEV; + if (pci_request_selected_regions(pdev, bars, "nvme")) + return -ENODEV; + + dev->bar = ioremap(pci_resource_start(pdev, 0), 8192); + if (!dev->bar) + goto release; + + return 0; + release: + pci_release_regions(pdev); + return -ENODEV; +} + static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int node, result = -ENOMEM; @@ -2061,6 +2085,10 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) dev->dev = get_device(&pdev->dev); pci_set_drvdata(pdev, dev); + result = nvme_dev_map(dev); + if (result) + goto free; + INIT_LIST_HEAD(&dev->node); INIT_WORK(&dev->scan_work, nvme_dev_scan); INIT_WORK(&dev->reset_work, nvme_reset_work); @@ -2084,6 +2112,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) nvme_release_prp_pools(dev); put_pci: put_device(dev->dev); + nvme_dev_unmap(dev); free: kfree(dev->queues); kfree(dev->entry); @@ -2107,24 +2136,27 @@ static void nvme_shutdown(struct pci_dev *pdev) nvme_dev_disable(dev, true); } +/* + * The driver's remove may be called on a device in a partially initialized + * state. This function must not have any dependencies on the device state in + * order to proceed. + */ static void nvme_remove(struct pci_dev *pdev) { struct nvme_dev *dev = pci_get_drvdata(pdev); - spin_lock(&dev_list_lock); - list_del_init(&dev->node); - spin_unlock(&dev_list_lock); - + set_bit(NVME_CTRL_REMOVING, &dev->flags); pci_set_drvdata(pdev, NULL); - flush_work(&dev->reset_work); flush_work(&dev->scan_work); nvme_remove_namespaces(&dev->ctrl); nvme_uninit_ctrl(&dev->ctrl); nvme_dev_disable(dev, true); + flush_work(&dev->reset_work); nvme_dev_remove_admin(dev); nvme_free_queues(dev, 0); nvme_release_cmb(dev); nvme_release_prp_pools(dev); + nvme_dev_unmap(dev); nvme_put_ctrl(&dev->ctrl); } diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 7ee21ae305ae..e7bfc175b8e1 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -635,6 +635,13 @@ static u32 __of_msi_map_rid(struct device *dev, struct device_node **np, msi_base = be32_to_cpup(msi_map + 2); rid_len = be32_to_cpup(msi_map + 3); + if (rid_base & ~map_mask) { + dev_err(parent_dev, + "Invalid msi-map translation - msi-map-mask (0x%x) ignores rid-base (0x%x)\n", + map_mask, rid_base); + return rid_out; + } + msi_controller_node = of_find_node_by_phandle(phandle); matched = (masked_rid >= rid_base && @@ -654,7 +661,7 @@ static u32 __of_msi_map_rid(struct device *dev, struct device_node **np, if (!matched) return rid_out; - rid_out = masked_rid + msi_base; + rid_out = masked_rid - rid_base + msi_base; dev_dbg(dev, "msi-map at: %s, using mask %08x, rid-base: %08x, msi-base: %08x, length: %08x, rid: %08x -> %08x\n", dev_name(parent_dev), map_mask, rid_base, msi_base, diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 75a605426538..d1cdd9c992ac 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -14,6 +14,7 @@ config PCI_DRA7XX config PCI_MVEBU bool "Marvell EBU PCIe controller" depends on ARCH_MVEBU || ARCH_DOVE + depends on ARM depends on OF config PCIE_DW diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c index ed34c9520a02..6153853ca9c3 100644 --- a/drivers/pci/host/pci-keystone-dw.c +++ b/drivers/pci/host/pci-keystone-dw.c @@ -58,11 +58,6 @@ #define to_keystone_pcie(x) container_of(x, struct keystone_pcie, pp) -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys) -{ - return sys->private_data; -} - static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset, u32 *bit_pos) { @@ -108,7 +103,7 @@ static void ks_dw_pcie_msi_irq_ack(struct irq_data *d) struct pcie_port *pp; msi = irq_data_get_msi_desc(d); - pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi)); + pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi); ks_pcie = to_keystone_pcie(pp); offset = d->irq - irq_linear_revmap(pp->irq_domain, 0); update_reg_offset_bit_pos(offset, ®_offset, &bit_pos); @@ -146,7 +141,7 @@ static void ks_dw_pcie_msi_irq_mask(struct irq_data *d) u32 offset; msi = irq_data_get_msi_desc(d); - pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi)); + pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi); ks_pcie = to_keystone_pcie(pp); offset = d->irq - irq_linear_revmap(pp->irq_domain, 0); @@ -167,7 +162,7 @@ static void ks_dw_pcie_msi_irq_unmask(struct irq_data *d) u32 offset; msi = irq_data_get_msi_desc(d); - pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi)); + pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi); ks_pcie = to_keystone_pcie(pp); offset = d->irq - irq_linear_revmap(pp->irq_domain, 0); diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c index 3923bed93c7e..f39961bcf7aa 100644 --- a/drivers/pci/host/pci-layerscape.c +++ b/drivers/pci/host/pci-layerscape.c @@ -77,6 +77,16 @@ static void ls_pcie_fix_class(struct ls_pcie *pcie) iowrite16(PCI_CLASS_BRIDGE_PCI, pcie->dbi + PCI_CLASS_DEVICE); } +/* Drop MSG TLP except for Vendor MSG */ +static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie) +{ + u32 val; + + val = ioread32(pcie->dbi + PCIE_STRFMR1); + val &= 0xDFFFFFFF; + iowrite32(val, pcie->dbi + PCIE_STRFMR1); +} + static int ls1021_pcie_link_up(struct pcie_port *pp) { u32 state; @@ -97,7 +107,7 @@ static int ls1021_pcie_link_up(struct pcie_port *pp) static void ls1021_pcie_host_init(struct pcie_port *pp) { struct ls_pcie *pcie = to_ls_pcie(pp); - u32 val, index[2]; + u32 index[2]; pcie->scfg = syscon_regmap_lookup_by_phandle(pp->dev->of_node, "fsl,pcie-scfg"); @@ -116,13 +126,7 @@ static void ls1021_pcie_host_init(struct pcie_port *pp) dw_pcie_setup_rc(pp); - /* - * LS1021A Workaround for internal TKT228622 - * to fix the INTx hang issue - */ - val = ioread32(pcie->dbi + PCIE_STRFMR1); - val &= 0xffff; - iowrite32(val, pcie->dbi + PCIE_STRFMR1); + ls_pcie_drop_msg_tlp(pcie); } static int ls_pcie_link_up(struct pcie_port *pp) @@ -147,6 +151,7 @@ static void ls_pcie_host_init(struct pcie_port *pp) iowrite32(1, pcie->dbi + PCIE_DBI_RO_WR_EN); ls_pcie_fix_class(pcie); ls_pcie_clear_multifunction(pcie); + ls_pcie_drop_msg_tlp(pcie); iowrite32(0, pcie->dbi + PCIE_DBI_RO_WR_EN); } diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index c777b97207d5..5f70fee59a94 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c @@ -53,7 +53,7 @@ struct pcifront_device { }; struct pcifront_sd { - int domain; + struct pci_sysdata sd; struct pcifront_device *pdev; }; @@ -67,7 +67,9 @@ static inline void pcifront_init_sd(struct pcifront_sd *sd, unsigned int domain, unsigned int bus, struct pcifront_device *pdev) { - sd->domain = domain; + /* Because we do not expose that information via XenBus. */ + sd->sd.node = first_online_node; + sd->sd.domain = domain; sd->pdev = pdev; } @@ -468,8 +470,8 @@ static int pcifront_scan_root(struct pcifront_device *pdev, dev_info(&pdev->xdev->dev, "Creating PCI Frontend Bus %04x:%02x\n", domain, bus); - bus_entry = kmalloc(sizeof(*bus_entry), GFP_KERNEL); - sd = kmalloc(sizeof(*sd), GFP_KERNEL); + bus_entry = kzalloc(sizeof(*bus_entry), GFP_KERNEL); + sd = kzalloc(sizeof(*sd), GFP_KERNEL); if (!bus_entry || !sd) { err = -ENOMEM; goto err_out; diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 16d48a4ed225..e96e86d2e745 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -347,6 +347,7 @@ static int mtk_pconf_parse_conf(struct pinctrl_dev *pctldev, ret = mtk_pconf_set_pull_select(pctl, pin, true, false, arg); break; case PIN_CONFIG_INPUT_ENABLE: + mtk_pmx_gpio_set_direction(pctldev, NULL, pin, true); ret = mtk_pconf_set_ies_smt(pctl, pin, arg, param); break; case PIN_CONFIG_OUTPUT: @@ -354,6 +355,7 @@ static int mtk_pconf_parse_conf(struct pinctrl_dev *pctldev, ret = mtk_pmx_gpio_set_direction(pctldev, NULL, pin, false); break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: + mtk_pmx_gpio_set_direction(pctldev, NULL, pin, true); ret = mtk_pconf_set_ies_smt(pctl, pin, arg, param); break; case PIN_CONFIG_DRIVE_STRENGTH: diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c index e4d473811bb3..3ef798fac81b 100644 --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c @@ -666,16 +666,19 @@ int mvebu_pinctrl_probe(struct platform_device *pdev) struct mvebu_mpp_ctrl_setting *set = &mode->settings[0]; struct mvebu_pinctrl_group *grp; unsigned num_settings; + unsigned supp_settings; - for (num_settings = 0; ; set++) { + for (num_settings = 0, supp_settings = 0; ; set++) { if (!set->name) break; + num_settings++; + /* skip unsupported settings for this variant */ if (pctl->variant && !(pctl->variant & set->variant)) continue; - num_settings++; + supp_settings++; /* find gpio/gpo/gpi settings */ if (strcmp(set->name, "gpio") == 0) @@ -688,7 +691,7 @@ int mvebu_pinctrl_probe(struct platform_device *pdev) } /* skip modes with no settings for this variant */ - if (!num_settings) + if (!supp_settings) continue; grp = mvebu_pinctrl_find_group_by_pid(pctl, mode->pid); diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c index 085e60106ec2..1f7469c9857d 100644 --- a/drivers/pinctrl/nomadik/pinctrl-abx500.c +++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c @@ -191,6 +191,7 @@ static void abx500_gpio_set(struct gpio_chip *chip, unsigned offset, int val) dev_err(pct->dev, "%s write failed (%d)\n", __func__, ret); } +#ifdef CONFIG_DEBUG_FS static int abx500_get_pull_updown(struct abx500_pinctrl *pct, int offset, enum abx500_gpio_pull_updown *pull_updown) { @@ -226,6 +227,7 @@ out: return ret; } +#endif static int abx500_set_pull_updown(struct abx500_pinctrl *pct, int offset, enum abx500_gpio_pull_updown val) @@ -468,6 +470,7 @@ out: return ret; } +#ifdef CONFIG_DEBUG_FS static int abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip, unsigned gpio) { @@ -553,8 +556,6 @@ out: return ret; } -#ifdef CONFIG_DEBUG_FS - #include <linux/seq_file.h> static void abx500_gpio_dbg_show_one(struct seq_file *s, diff --git a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c index d90e205cf809..216f227c6009 100644 --- a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c +++ b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c @@ -426,6 +426,7 @@ int pxa2xx_pinctrl_init(struct platform_device *pdev, return 0; } +EXPORT_SYMBOL(pxa2xx_pinctrl_init); int pxa2xx_pinctrl_exit(struct platform_device *pdev) { diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index f67b1e958589..5cc97f85db02 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -514,25 +514,35 @@ static const struct pinconf_ops samsung_pinconf_ops = { .pin_config_group_set = samsung_pinconf_group_set, }; -/* gpiolib gpio_set callback function */ -static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) +/* + * The samsung_gpio_set_vlaue() should be called with "bank->slock" held + * to avoid race condition. + */ +static void samsung_gpio_set_value(struct gpio_chip *gc, + unsigned offset, int value) { struct samsung_pin_bank *bank = gpiochip_get_data(gc); const struct samsung_pin_bank_type *type = bank->type; - unsigned long flags; void __iomem *reg; u32 data; reg = bank->drvdata->virt_base + bank->pctl_offset; - spin_lock_irqsave(&bank->slock, flags); - data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]); data &= ~(1 << offset); if (value) data |= 1 << offset; writel(data, reg + type->reg_offset[PINCFG_TYPE_DAT]); +} + +/* gpiolib gpio_set callback function */ +static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) +{ + struct samsung_pin_bank *bank = gpiochip_get_data(gc); + unsigned long flags; + spin_lock_irqsave(&bank->slock, flags); + samsung_gpio_set_value(gc, offset, value); spin_unlock_irqrestore(&bank->slock, flags); } @@ -553,6 +563,8 @@ static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset) } /* + * The samsung_gpio_set_direction() should be called with "bank->slock" held + * to avoid race condition. * The calls to gpio_direction_output() and gpio_direction_input() * leads to this function call. */ @@ -564,7 +576,6 @@ static int samsung_gpio_set_direction(struct gpio_chip *gc, struct samsung_pinctrl_drv_data *drvdata; void __iomem *reg; u32 data, mask, shift; - unsigned long flags; bank = gpiochip_get_data(gc); type = bank->type; @@ -581,31 +592,42 @@ static int samsung_gpio_set_direction(struct gpio_chip *gc, reg += 4; } - spin_lock_irqsave(&bank->slock, flags); - data = readl(reg); data &= ~(mask << shift); if (!input) data |= FUNC_OUTPUT << shift; writel(data, reg); - spin_unlock_irqrestore(&bank->slock, flags); - return 0; } /* gpiolib gpio_direction_input callback function. */ static int samsung_gpio_direction_input(struct gpio_chip *gc, unsigned offset) { - return samsung_gpio_set_direction(gc, offset, true); + struct samsung_pin_bank *bank = gpiochip_get_data(gc); + unsigned long flags; + int ret; + + spin_lock_irqsave(&bank->slock, flags); + ret = samsung_gpio_set_direction(gc, offset, true); + spin_unlock_irqrestore(&bank->slock, flags); + return ret; } /* gpiolib gpio_direction_output callback function. */ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset, int value) { - samsung_gpio_set(gc, offset, value); - return samsung_gpio_set_direction(gc, offset, false); + struct samsung_pin_bank *bank = gpiochip_get_data(gc); + unsigned long flags; + int ret; + + spin_lock_irqsave(&bank->slock, flags); + samsung_gpio_set_value(gc, offset, value); + ret = samsung_gpio_set_direction(gc, offset, false); + spin_unlock_irqrestore(&bank->slock, flags); + + return ret; } /* diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c index 77d4cf047cee..11760bbe9d51 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c @@ -492,6 +492,7 @@ static const struct sunxi_pinctrl_desc sun8i_h3_pinctrl_data = { .pins = sun8i_h3_pins, .npins = ARRAY_SIZE(sun8i_h3_pins), .irq_banks = 2, + .irq_read_needs_mux = true }; static int sun8i_h3_pinctrl_probe(struct platform_device *pdev) diff --git a/drivers/power/bq27xxx_battery_i2c.c b/drivers/power/bq27xxx_battery_i2c.c index 9429e66be096..8eafc6f0df88 100644 --- a/drivers/power/bq27xxx_battery_i2c.c +++ b/drivers/power/bq27xxx_battery_i2c.c @@ -21,6 +21,9 @@ #include <linux/power/bq27xxx_battery.h> +static DEFINE_IDR(battery_id); +static DEFINE_MUTEX(battery_mutex); + static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data) { struct bq27xxx_device_info *di = data; @@ -70,19 +73,33 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client, { struct bq27xxx_device_info *di; int ret; + char *name; + int num; + + /* Get new ID for the new battery device */ + mutex_lock(&battery_mutex); + num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL); + mutex_unlock(&battery_mutex); + if (num < 0) + return num; + + name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num); + if (!name) + goto err_mem; di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL); if (!di) - return -ENOMEM; + goto err_mem; + di->id = num; di->dev = &client->dev; di->chip = id->driver_data; - di->name = id->name; + di->name = name; di->bus.read = bq27xxx_battery_i2c_read; ret = bq27xxx_battery_setup(di); if (ret) - return ret; + goto err_failed; /* Schedule a polling after about 1 min */ schedule_delayed_work(&di->work, 60 * HZ); @@ -103,6 +120,16 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client, } return 0; + +err_mem: + ret = -ENOMEM; + +err_failed: + mutex_lock(&battery_mutex); + idr_remove(&battery_id, num); + mutex_unlock(&battery_mutex); + + return ret; } static int bq27xxx_battery_i2c_remove(struct i2c_client *client) @@ -111,6 +138,10 @@ static int bq27xxx_battery_i2c_remove(struct i2c_client *client) bq27xxx_battery_teardown(di); + mutex_lock(&battery_mutex); + idr_remove(&battery_id, di->id); + mutex_unlock(&battery_mutex); + return 0; } diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 41605dac8309..c78db05e75b1 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -3035,6 +3035,7 @@ static void dasd_setup_queue(struct dasd_block *block) max = block->base->discipline->max_blocks << block->s2b_shift; } queue_flag_set_unlocked(QUEUE_FLAG_NONROT, block->request_queue); + block->request_queue->limits.max_dev_sectors = max; blk_queue_logical_block_size(block->request_queue, block->bp_block); blk_queue_max_hw_sectors(block->request_queue, max); diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 184b1dbeb554..286782c60da4 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c @@ -264,8 +264,10 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) spin_unlock_irqrestore(&lcu->lock, flags); cancel_work_sync(&lcu->suc_data.worker); spin_lock_irqsave(&lcu->lock, flags); - if (device == lcu->suc_data.device) + if (device == lcu->suc_data.device) { + dasd_put_device(device); lcu->suc_data.device = NULL; + } } was_pending = 0; if (device == lcu->ruac_data.device) { @@ -273,8 +275,10 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) was_pending = 1; cancel_delayed_work_sync(&lcu->ruac_data.dwork); spin_lock_irqsave(&lcu->lock, flags); - if (device == lcu->ruac_data.device) + if (device == lcu->ruac_data.device) { + dasd_put_device(device); lcu->ruac_data.device = NULL; + } } private->lcu = NULL; spin_unlock_irqrestore(&lcu->lock, flags); @@ -549,8 +553,10 @@ static void lcu_update_work(struct work_struct *work) if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) { DBF_DEV_EVENT(DBF_WARNING, device, "could not update" " alias data in lcu (rc = %d), retry later", rc); - schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ); + if (!schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ)) + dasd_put_device(device); } else { + dasd_put_device(device); lcu->ruac_data.device = NULL; lcu->flags &= ~UPDATE_PENDING; } @@ -593,8 +599,10 @@ static int _schedule_lcu_update(struct alias_lcu *lcu, */ if (!usedev) return -EINVAL; + dasd_get_device(usedev); lcu->ruac_data.device = usedev; - schedule_delayed_work(&lcu->ruac_data.dwork, 0); + if (!schedule_delayed_work(&lcu->ruac_data.dwork, 0)) + dasd_put_device(usedev); return 0; } @@ -723,7 +731,7 @@ static int reset_summary_unit_check(struct alias_lcu *lcu, ASCEBC((char *) &cqr->magic, 4); ccw = cqr->cpaddr; ccw->cmd_code = DASD_ECKD_CCW_RSCK; - ccw->flags = 0 ; + ccw->flags = CCW_FLAG_SLI; ccw->count = 16; ccw->cda = (__u32)(addr_t) cqr->data; ((char *)cqr->data)[0] = reason; @@ -930,6 +938,7 @@ static void summary_unit_check_handling_work(struct work_struct *work) /* 3. read new alias configuration */ _schedule_lcu_update(lcu, device); lcu->suc_data.device = NULL; + dasd_put_device(device); spin_unlock_irqrestore(&lcu->lock, flags); } @@ -989,6 +998,8 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device, } lcu->suc_data.reason = reason; lcu->suc_data.device = device; + dasd_get_device(device); spin_unlock(&lcu->lock); - schedule_work(&lcu->suc_data.worker); + if (!schedule_work(&lcu->suc_data.worker)) + dasd_put_device(device); }; diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 3b3e0998fa6e..d6a691e27d33 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4002,6 +4002,7 @@ static ssize_t ipr_store_update_fw(struct device *dev, struct ipr_sglist *sglist; char fname[100]; char *src; + char *endline; int result, dnld_size; if (!capable(CAP_SYS_ADMIN)) @@ -4009,6 +4010,10 @@ static ssize_t ipr_store_update_fw(struct device *dev, snprintf(fname, sizeof(fname), "%s", buf); + endline = strchr(fname, '\n'); + if (endline) + *endline = '\0'; + if (request_firmware(&fw_entry, fname, &ioa_cfg->pdev->dev)) { dev_err(&ioa_cfg->pdev->dev, "Firmware file %s not found\n", fname); return -EIO; diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index da2e068ee47d..bbfbfd9e5aa3 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -206,6 +206,7 @@ static struct { {"iRiver", "iFP Mass Driver", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36}, {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN}, {"Marvell", "Console", NULL, BLIST_SKIP_VPD_PAGES}, + {"Marvell", "91xx Config", "1.01", BLIST_SKIP_VPD_PAGES}, {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"MATSHITA", "DMC-LC5", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36}, {"MATSHITA", "DMC-LC40", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36}, diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index fa6b2c4eb7a2..8c6e31874171 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1344,6 +1344,7 @@ scsi_prep_return(struct request_queue *q, struct request *req, int ret) switch (ret) { case BLKPREP_KILL: + case BLKPREP_INVALID: req->errors = DID_NO_CONNECT << 16; /* release the command and kill it */ if (req->special) { diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 4f18a851e2c7..00bc7218a7f8 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1272,16 +1272,18 @@ static void __scsi_remove_target(struct scsi_target *starget) void scsi_remove_target(struct device *dev) { struct Scsi_Host *shost = dev_to_shost(dev->parent); - struct scsi_target *starget; + struct scsi_target *starget, *last_target = NULL; unsigned long flags; restart: spin_lock_irqsave(shost->host_lock, flags); list_for_each_entry(starget, &shost->__targets, siblings) { - if (starget->state == STARGET_DEL) + if (starget->state == STARGET_DEL || + starget == last_target) continue; if (starget->dev.parent == dev || &starget->dev == dev) { kref_get(&starget->reap_ref); + last_target = starget; spin_unlock_irqrestore(shost->host_lock, flags); __scsi_remove_target(starget); scsi_target_reap(starget); diff --git a/drivers/sh/pm_runtime.c b/drivers/sh/pm_runtime.c index 91a003011acf..a9bac3bf20de 100644 --- a/drivers/sh/pm_runtime.c +++ b/drivers/sh/pm_runtime.c @@ -34,7 +34,7 @@ static struct pm_clk_notifier_block platform_bus_notifier = { static int __init sh_pm_runtime_init(void) { - if (IS_ENABLED(CONFIG_ARCH_SHMOBILE)) { + if (IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_ARCH_SHMOBILE)) { if (!of_find_compatible_node(NULL, NULL, "renesas,cpg-mstp-clocks")) return 0; diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index aebad36391c9..8feac599e9ab 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1571,6 +1571,7 @@ static int atmel_spi_probe(struct platform_device *pdev) as->use_cs_gpios = true; if (atmel_spi_is_v2(as) && + pdev->dev.of_node && !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) { as->use_cs_gpios = false; master->num_chipselect = 4; diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index 7de6f8472a81..ecc73c0a97cf 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -73,8 +73,8 @@ /* Bitfields in CNTL1 */ #define BCM2835_AUX_SPI_CNTL1_CSHIGH 0x00000700 -#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000080 -#define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000040 +#define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000080 +#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000040 #define BCM2835_AUX_SPI_CNTL1_MSBF_IN 0x00000002 #define BCM2835_AUX_SPI_CNTL1_KEEP_IN 0x00000001 diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 7fd6a4c009d2..7cb0c1921495 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -84,7 +84,7 @@ struct fsl_espi_transfer { /* SPCOM register values */ #define SPCOM_CS(x) ((x) << 30) #define SPCOM_TRANLEN(x) ((x) << 0) -#define SPCOM_TRANLEN_MAX 0xFFFF /* Max transaction length */ +#define SPCOM_TRANLEN_MAX 0x10000 /* Max transaction length */ #define AUTOSUSPEND_TIMEOUT 2000 @@ -233,7 +233,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) reinit_completion(&mpc8xxx_spi->done); /* Set SPCOM[CS] and SPCOM[TRANLEN] field */ - if ((t->len - 1) > SPCOM_TRANLEN_MAX) { + if (t->len > SPCOM_TRANLEN_MAX) { dev_err(mpc8xxx_spi->dev, "Transaction length (%d)" " beyond the SPCOM[TRANLEN] field\n", t->len); return -EINVAL; diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index d98c33cb64f9..6a4ff27f4357 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -929,7 +929,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, tx->sgl, tx->nents, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_tx) - goto no_dma; + goto tx_nodma; desc_tx->callback = spi_imx_dma_tx_callback; desc_tx->callback_param = (void *)spi_imx; @@ -941,7 +941,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, rx->sgl, rx->nents, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_rx) - goto no_dma; + goto rx_nodma; desc_rx->callback = spi_imx_dma_rx_callback; desc_rx->callback_param = (void *)spi_imx; @@ -1008,7 +1008,9 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, return ret; -no_dma: +rx_nodma: + dmaengine_terminate_all(master->dma_tx); +tx_nodma: pr_warn_once("%s %s: DMA not available, falling back to PIO\n", dev_driver_string(&master->dev), dev_name(&master->dev)); diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c index 894616f687b0..cf4bb36bee25 100644 --- a/drivers/spi/spi-loopback-test.c +++ b/drivers/spi/spi-loopback-test.c @@ -761,6 +761,7 @@ static int spi_test_run_iter(struct spi_device *spi, test.iterate_transfer_mask = 1; /* count number of transfers with tx/rx_buf != NULL */ + rx_count = tx_count = 0; for (i = 0; i < test.transfer_count; i++) { if (test.transfers[i].tx_buf) tx_count++; diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 7273820275e9..0caa3c8bef46 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1490,6 +1490,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev) return status; disable_pm: + pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); free_master: spi_master_put(master); @@ -1501,6 +1503,7 @@ static int omap2_mcspi_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct omap2_mcspi *mcspi = spi_master_get_devdata(master); + pm_runtime_dont_use_autosuspend(mcspi->dev); pm_runtime_put_sync(mcspi->dev); pm_runtime_disable(&pdev->dev); diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index 3ec7e65a3ffa..db49af90217e 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -147,7 +147,7 @@ static int vpfe_prepare_pipeline(struct vpfe_video_device *video) mutex_lock(&mdev->graph_mutex); ret = media_entity_graph_walk_init(&graph, entity->graph_obj.mdev); if (ret) { - mutex_unlock(&video->lock); + mutex_unlock(&mdev->graph_mutex); return -ENOMEM; } media_entity_graph_walk_start(&graph, entity); diff --git a/drivers/usb/chipidea/ci_hdrc_pci.c b/drivers/usb/chipidea/ci_hdrc_pci.c index b59195edf636..b635ab67490d 100644 --- a/drivers/usb/chipidea/ci_hdrc_pci.c +++ b/drivers/usb/chipidea/ci_hdrc_pci.c @@ -85,8 +85,8 @@ static int ci_hdrc_pci_probe(struct pci_dev *pdev, /* register a nop PHY */ ci->phy = usb_phy_generic_register(); - if (!ci->phy) - return -ENOMEM; + if (IS_ERR(ci->phy)) + return PTR_ERR(ci->phy); memset(res, 0, sizeof(res)); res[0].start = pci_resource_start(pdev, 0); diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index a4f7db2e18dd..df47110bad2d 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -100,6 +100,9 @@ static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf, if (sscanf(buf, "%u", &mode) != 1) return -EINVAL; + if (mode > 255) + return -EBADRQC; + pm_runtime_get_sync(ci->dev); spin_lock_irqsave(&ci->lock, flags); ret = hw_port_test_set(ci, mode); diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c index 45f86da1d6d3..03b6743461d1 100644 --- a/drivers/usb/chipidea/otg.c +++ b/drivers/usb/chipidea/otg.c @@ -158,7 +158,7 @@ static void ci_otg_work(struct work_struct *work) int ci_hdrc_otg_init(struct ci_hdrc *ci) { INIT_WORK(&ci->work, ci_otg_work); - ci->wq = create_singlethread_workqueue("ci_otg"); + ci->wq = create_freezable_workqueue("ci_otg"); if (!ci->wq) { dev_err(ci->dev, "can't create workqueue\n"); return -ENODEV; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 350dcd9af5d8..51b436918f78 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -5401,6 +5401,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) } bos = udev->bos; + udev->bos = NULL; for (i = 0; i < SET_CONFIG_TRIES; ++i) { @@ -5493,11 +5494,8 @@ done: usb_set_usb2_hardware_lpm(udev, 1); usb_unlocked_enable_lpm(udev); usb_enable_ltm(udev); - /* release the new BOS descriptor allocated by hub_port_init() */ - if (udev->bos != bos) { - usb_release_bos_descriptor(udev); - udev->bos = bos; - } + usb_release_bos_descriptor(udev); + udev->bos = bos; return 0; re_enumerate: diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig index fd95ba6ec317..f0decc0d69b5 100644 --- a/drivers/usb/dwc2/Kconfig +++ b/drivers/usb/dwc2/Kconfig @@ -1,5 +1,6 @@ config USB_DWC2 tristate "DesignWare USB2 DRD Core Support" + depends on HAS_DMA depends on USB || USB_GADGET help Say Y here if your system has a Dual Role Hi-Speed USB diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index e991d55914db..46c4ba75dc2a 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -619,6 +619,12 @@ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg) __func__, hsotg->dr_mode); break; } + + /* + * NOTE: This is required for some rockchip soc based + * platforms. + */ + msleep(50); } /* diff --git a/drivers/usb/dwc2/hcd_ddma.c b/drivers/usb/dwc2/hcd_ddma.c index 36606fc33c0d..a41274aa52ad 100644 --- a/drivers/usb/dwc2/hcd_ddma.c +++ b/drivers/usb/dwc2/hcd_ddma.c @@ -1174,14 +1174,11 @@ static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg, failed = dwc2_update_non_isoc_urb_state_ddma(hsotg, chan, qtd, dma_desc, halt_status, n_bytes, xfer_done); - if (*xfer_done && urb->status != -EINPROGRESS) - failed = 1; - - if (failed) { + if (failed || (*xfer_done && urb->status != -EINPROGRESS)) { dwc2_host_complete(hsotg, qtd, urb->status); dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); - dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x status=%08x\n", - failed, *xfer_done, urb->status); + dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x\n", + failed, *xfer_done); return failed; } @@ -1236,21 +1233,23 @@ static void dwc2_complete_non_isoc_xfer_ddma(struct dwc2_hsotg *hsotg, list_for_each_safe(qtd_item, qtd_tmp, &qh->qtd_list) { int i; + int qtd_desc_count; qtd = list_entry(qtd_item, struct dwc2_qtd, qtd_list_entry); xfer_done = 0; + qtd_desc_count = qtd->n_desc; - for (i = 0; i < qtd->n_desc; i++) { + for (i = 0; i < qtd_desc_count; i++) { if (dwc2_process_non_isoc_desc(hsotg, chan, chnum, qtd, desc_num, halt_status, - &xfer_done)) { - qtd = NULL; - break; - } + &xfer_done)) + goto stop_scan; + desc_num++; } } +stop_scan: if (qh->ep_type != USB_ENDPOINT_XFER_CONTROL) { /* * Resetting the data toggle for bulk and interrupt endpoints @@ -1258,7 +1257,7 @@ static void dwc2_complete_non_isoc_xfer_ddma(struct dwc2_hsotg *hsotg, */ if (halt_status == DWC2_HC_XFER_STALL) qh->data_toggle = DWC2_HC_PID_DATA0; - else if (qtd) + else dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd); } diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index f8253803a050..cadba8b13c48 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c @@ -525,11 +525,19 @@ void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg, u32 pid = (hctsiz & TSIZ_SC_MC_PID_MASK) >> TSIZ_SC_MC_PID_SHIFT; if (chan->ep_type != USB_ENDPOINT_XFER_CONTROL) { + if (WARN(!chan || !chan->qh, + "chan->qh must be specified for non-control eps\n")) + return; + if (pid == TSIZ_SC_MC_PID_DATA0) chan->qh->data_toggle = DWC2_HC_PID_DATA0; else chan->qh->data_toggle = DWC2_HC_PID_DATA1; } else { + if (WARN(!qtd, + "qtd must be specified for control eps\n")) + return; + if (pid == TSIZ_SC_MC_PID_DATA0) qtd->data_toggle = DWC2_HC_PID_DATA0; else diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 29130682e547..e4f8b90d9627 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -856,7 +856,6 @@ struct dwc3 { unsigned pullups_connected:1; unsigned resize_fifos:1; unsigned setup_packet_pending:1; - unsigned start_config_issued:1; unsigned three_stage_setup:1; unsigned usb3_lpm_capable:1; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 3a9354abcb68..8d6b75c2f53b 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -555,7 +555,6 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) int ret; u32 reg; - dwc->start_config_issued = false; cfg = le16_to_cpu(ctrl->wValue); switch (state) { @@ -737,10 +736,6 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY"); ret = dwc3_ep0_set_isoch_delay(dwc, ctrl); break; - case USB_REQ_SET_INTERFACE: - dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_INTERFACE"); - dwc->start_config_issued = false; - /* Fall through */ default: dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver"); ret = dwc3_ep0_delegate_req(dwc, ctrl); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 7d1dd82a95ac..2363bad45af8 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -385,24 +385,66 @@ static void dwc3_free_trb_pool(struct dwc3_ep *dep) dep->trb_pool_dma = 0; } +static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep); + +/** + * dwc3_gadget_start_config - Configure EP resources + * @dwc: pointer to our controller context structure + * @dep: endpoint that is being enabled + * + * The assignment of transfer resources cannot perfectly follow the + * data book due to the fact that the controller driver does not have + * all knowledge of the configuration in advance. It is given this + * information piecemeal by the composite gadget framework after every + * SET_CONFIGURATION and SET_INTERFACE. Trying to follow the databook + * programming model in this scenario can cause errors. For two + * reasons: + * + * 1) The databook says to do DEPSTARTCFG for every SET_CONFIGURATION + * and SET_INTERFACE (8.1.5). This is incorrect in the scenario of + * multiple interfaces. + * + * 2) The databook does not mention doing more DEPXFERCFG for new + * endpoint on alt setting (8.1.6). + * + * The following simplified method is used instead: + * + * All hardware endpoints can be assigned a transfer resource and this + * setting will stay persistent until either a core reset or + * hibernation. So whenever we do a DEPSTARTCFG(0) we can go ahead and + * do DEPXFERCFG for every hardware endpoint as well. We are + * guaranteed that there are as many transfer resources as endpoints. + * + * This function is called for each endpoint when it is being enabled + * but is triggered only when called for EP0-out, which always happens + * first, and which should only happen in one of the above conditions. + */ static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep) { struct dwc3_gadget_ep_cmd_params params; u32 cmd; + int i; + int ret; + + if (dep->number) + return 0; memset(¶ms, 0x00, sizeof(params)); + cmd = DWC3_DEPCMD_DEPSTARTCFG; - if (dep->number != 1) { - cmd = DWC3_DEPCMD_DEPSTARTCFG; - /* XferRscIdx == 0 for ep0 and 2 for the remaining */ - if (dep->number > 1) { - if (dwc->start_config_issued) - return 0; - dwc->start_config_issued = true; - cmd |= DWC3_DEPCMD_PARAM(2); - } + ret = dwc3_send_gadget_ep_cmd(dwc, 0, cmd, ¶ms); + if (ret) + return ret; - return dwc3_send_gadget_ep_cmd(dwc, 0, cmd, ¶ms); + for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) { + struct dwc3_ep *dep = dwc->eps[i]; + + if (!dep) + continue; + + ret = dwc3_gadget_set_xfer_resource(dwc, dep); + if (ret) + return ret; } return 0; @@ -516,10 +558,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, struct dwc3_trb *trb_st_hw; struct dwc3_trb *trb_link; - ret = dwc3_gadget_set_xfer_resource(dwc, dep); - if (ret) - return ret; - dep->endpoint.desc = desc; dep->comp_desc = comp_desc; dep->type = usb_endpoint_type(desc); @@ -1636,8 +1674,6 @@ static int dwc3_gadget_start(struct usb_gadget *g, } dwc3_writel(dwc->regs, DWC3_DCFG, reg); - dwc->start_config_issued = false; - /* Start with SuperSpeed Default */ dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); @@ -2237,7 +2273,6 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_DCTL, reg); dwc3_disconnect_gadget(dwc); - dwc->start_config_issued = false; dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->setup_packet_pending = false; @@ -2288,7 +2323,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) dwc3_stop_active_transfers(dwc); dwc3_clear_stall_all_ep(dwc); - dwc->start_config_issued = false; /* Reset device address to zero */ reg = dwc3_readl(dwc->regs, DWC3_DCFG); diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 7e179f81d05c..87fb0fd6aaab 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -130,7 +130,8 @@ struct dev_data { setup_can_stall : 1, setup_out_ready : 1, setup_out_error : 1, - setup_abort : 1; + setup_abort : 1, + gadget_registered : 1; unsigned setup_wLength; /* the rest is basically write-once */ @@ -1179,7 +1180,8 @@ dev_release (struct inode *inode, struct file *fd) /* closing ep0 === shutdown all */ - usb_gadget_unregister_driver (&gadgetfs_driver); + if (dev->gadget_registered) + usb_gadget_unregister_driver (&gadgetfs_driver); /* at this point "good" hardware has disconnected the * device from USB; the host won't see it any more. @@ -1847,6 +1849,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) * kick in after the ep0 descriptor is closed. */ value = len; + dev->gadget_registered = true; } return value; diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c index 53c0692f1b09..93d28cb00b76 100644 --- a/drivers/usb/gadget/udc/fsl_qe_udc.c +++ b/drivers/usb/gadget/udc/fsl_qe_udc.c @@ -2340,7 +2340,7 @@ static struct qe_udc *qe_udc_config(struct platform_device *ofdev) { struct qe_udc *udc; struct device_node *np = ofdev->dev.of_node; - unsigned int tmp_addr = 0; + unsigned long tmp_addr = 0; struct usb_device_para __iomem *usbpram; unsigned int i; u64 size; diff --git a/drivers/usb/gadget/udc/net2280.h b/drivers/usb/gadget/udc/net2280.h index 4dff60d34f73..0d32052bf16f 100644 --- a/drivers/usb/gadget/udc/net2280.h +++ b/drivers/usb/gadget/udc/net2280.h @@ -369,9 +369,20 @@ static inline void set_max_speed(struct net2280_ep *ep, u32 max) static const u32 ep_enhanced[9] = { 0x10, 0x60, 0x30, 0x80, 0x50, 0x20, 0x70, 0x40, 0x90 }; - if (ep->dev->enhanced_mode) + if (ep->dev->enhanced_mode) { reg = ep_enhanced[ep->num]; - else{ + switch (ep->dev->gadget.speed) { + case USB_SPEED_SUPER: + reg += 2; + break; + case USB_SPEED_FULL: + reg += 1; + break; + case USB_SPEED_HIGH: + default: + break; + } + } else { reg = (ep->num + 1) * 0x10; if (ep->dev->gadget.speed != USB_SPEED_HIGH) reg += 1; diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index fd73a3ea07c2..b86a6f03592e 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -413,9 +413,10 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, if (!driver->udc_name || strcmp(driver->udc_name, dev_name(&udc->dev)) == 0) { ret = udc_bind_to_driver(udc, driver); + if (ret != -EPROBE_DEFER) + list_del(&driver->pending); if (ret) goto err4; - list_del(&driver->pending); break; } } diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 795a45b1b25b..58487a473521 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -662,7 +662,7 @@ static int musb_tx_dma_set_mode_mentor(struct dma_controller *dma, csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE); csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */ } - channel->desired_mode = mode; + channel->desired_mode = *mode; musb_writew(epio, MUSB_TXCSR, csr); return 0; @@ -2003,10 +2003,8 @@ void musb_host_rx(struct musb *musb, u8 epnum) qh->offset, urb->transfer_buffer_length); - done = musb_rx_dma_in_inventra_cppi41(c, hw_ep, qh, - urb, xfer_len, - iso_err); - if (done) + if (musb_rx_dma_in_inventra_cppi41(c, hw_ep, qh, urb, + xfer_len, iso_err)) goto finish; else dev_err(musb->controller, "error: rx_dma failed\n"); diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 970a30e155cb..72b387d592c2 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -757,14 +757,8 @@ static int msm_otg_set_host(struct usb_otg *otg, struct usb_bus *host) otg->host = host; dev_dbg(otg->usb_phy->dev, "host driver registered w/ tranceiver\n"); - /* - * Kick the state machine work, if peripheral is not supported - * or peripheral is already registered with us. - */ - if (motg->pdata->mode == USB_DR_MODE_HOST || otg->gadget) { - pm_runtime_get_sync(otg->usb_phy->dev); - schedule_work(&motg->sm_work); - } + pm_runtime_get_sync(otg->usb_phy->dev); + schedule_work(&motg->sm_work); return 0; } @@ -827,14 +821,8 @@ static int msm_otg_set_peripheral(struct usb_otg *otg, dev_dbg(otg->usb_phy->dev, "peripheral driver registered w/ tranceiver\n"); - /* - * Kick the state machine work, if host is not supported - * or host is already registered with us. - */ - if (motg->pdata->mode == USB_DR_MODE_PERIPHERAL || otg->host) { - pm_runtime_get_sync(otg->usb_phy->dev); - schedule_work(&motg->sm_work); - } + pm_runtime_get_sync(otg->usb_phy->dev); + schedule_work(&motg->sm_work); return 0; } diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index f612dda9c977..56ecb8b5115d 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -475,22 +475,6 @@ config USB_SERIAL_MOS7840 To compile this driver as a module, choose M here: the module will be called mos7840. If unsure, choose N. -config USB_SERIAL_MXUPORT11 - tristate "USB Moxa UPORT 11x0 Serial Driver" - ---help--- - Say Y here if you want to use a MOXA UPort 11x0 Serial hub. - - This driver supports: - - - UPort 1110 : 1 port RS-232 USB to Serial Hub. - - UPort 1130 : 1 port RS-422/485 USB to Serial Hub. - - UPort 1130I : 1 port RS-422/485 USB to Serial Hub with Isolation. - - UPort 1150 : 1 port RS-232/422/485 USB to Serial Hub. - - UPort 1150I : 1 port RS-232/422/485 USB to Serial Hub with Isolation. - - To compile this driver as a module, choose M here: the - module will be called mxu11x0. - config USB_SERIAL_MXUPORT tristate "USB Moxa UPORT Serial Driver" ---help--- diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index f3fa5e53702d..349d9df0895f 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -38,7 +38,6 @@ obj-$(CONFIG_USB_SERIAL_METRO) += metro-usb.o obj-$(CONFIG_USB_SERIAL_MOS7720) += mos7720.o obj-$(CONFIG_USB_SERIAL_MOS7840) += mos7840.o obj-$(CONFIG_USB_SERIAL_MXUPORT) += mxuport.o -obj-$(CONFIG_USB_SERIAL_MXUPORT11) += mxu11x0.o obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o obj-$(CONFIG_USB_SERIAL_OPTICON) += opticon.o diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 987813b8a7f9..73a366de5102 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -163,6 +163,9 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ { USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */ + { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */ + { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */ + { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */ { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ { USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */ diff --git a/drivers/usb/serial/mxu11x0.c b/drivers/usb/serial/mxu11x0.c deleted file mode 100644 index 619607323bfd..000000000000 --- a/drivers/usb/serial/mxu11x0.c +++ /dev/null @@ -1,1006 +0,0 @@ -/* - * USB Moxa UPORT 11x0 Serial Driver - * - * Copyright (C) 2007 MOXA Technologies Co., Ltd. - * Copyright (C) 2015 Mathieu Othacehe <m.othacehe@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * - * Supports the following Moxa USB to serial converters: - * UPort 1110, 1 port RS-232 USB to Serial Hub. - * UPort 1130, 1 port RS-422/485 USB to Serial Hub. - * UPort 1130I, 1 port RS-422/485 USB to Serial Hub with isolation - * protection. - * UPort 1150, 1 port RS-232/422/485 USB to Serial Hub. - * UPort 1150I, 1 port RS-232/422/485 USB to Serial Hub with isolation - * protection. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/firmware.h> -#include <linux/jiffies.h> -#include <linux/serial.h> -#include <linux/serial_reg.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/mutex.h> -#include <linux/tty.h> -#include <linux/tty_driver.h> -#include <linux/tty_flip.h> -#include <linux/uaccess.h> -#include <linux/usb.h> -#include <linux/usb/serial.h> - -/* Vendor and product ids */ -#define MXU1_VENDOR_ID 0x110a -#define MXU1_1110_PRODUCT_ID 0x1110 -#define MXU1_1130_PRODUCT_ID 0x1130 -#define MXU1_1150_PRODUCT_ID 0x1150 -#define MXU1_1151_PRODUCT_ID 0x1151 -#define MXU1_1131_PRODUCT_ID 0x1131 - -/* Commands */ -#define MXU1_GET_VERSION 0x01 -#define MXU1_GET_PORT_STATUS 0x02 -#define MXU1_GET_PORT_DEV_INFO 0x03 -#define MXU1_GET_CONFIG 0x04 -#define MXU1_SET_CONFIG 0x05 -#define MXU1_OPEN_PORT 0x06 -#define MXU1_CLOSE_PORT 0x07 -#define MXU1_START_PORT 0x08 -#define MXU1_STOP_PORT 0x09 -#define MXU1_TEST_PORT 0x0A -#define MXU1_PURGE_PORT 0x0B -#define MXU1_RESET_EXT_DEVICE 0x0C -#define MXU1_GET_OUTQUEUE 0x0D -#define MXU1_WRITE_DATA 0x80 -#define MXU1_READ_DATA 0x81 -#define MXU1_REQ_TYPE_CLASS 0x82 - -/* Module identifiers */ -#define MXU1_I2C_PORT 0x01 -#define MXU1_IEEE1284_PORT 0x02 -#define MXU1_UART1_PORT 0x03 -#define MXU1_UART2_PORT 0x04 -#define MXU1_RAM_PORT 0x05 - -/* Modem status */ -#define MXU1_MSR_DELTA_CTS 0x01 -#define MXU1_MSR_DELTA_DSR 0x02 -#define MXU1_MSR_DELTA_RI 0x04 -#define MXU1_MSR_DELTA_CD 0x08 -#define MXU1_MSR_CTS 0x10 -#define MXU1_MSR_DSR 0x20 -#define MXU1_MSR_RI 0x40 -#define MXU1_MSR_CD 0x80 -#define MXU1_MSR_DELTA_MASK 0x0F -#define MXU1_MSR_MASK 0xF0 - -/* Line status */ -#define MXU1_LSR_OVERRUN_ERROR 0x01 -#define MXU1_LSR_PARITY_ERROR 0x02 -#define MXU1_LSR_FRAMING_ERROR 0x04 -#define MXU1_LSR_BREAK 0x08 -#define MXU1_LSR_ERROR 0x0F -#define MXU1_LSR_RX_FULL 0x10 -#define MXU1_LSR_TX_EMPTY 0x20 - -/* Modem control */ -#define MXU1_MCR_LOOP 0x04 -#define MXU1_MCR_DTR 0x10 -#define MXU1_MCR_RTS 0x20 - -/* Mask settings */ -#define MXU1_UART_ENABLE_RTS_IN 0x0001 -#define MXU1_UART_DISABLE_RTS 0x0002 -#define MXU1_UART_ENABLE_PARITY_CHECKING 0x0008 -#define MXU1_UART_ENABLE_DSR_OUT 0x0010 -#define MXU1_UART_ENABLE_CTS_OUT 0x0020 -#define MXU1_UART_ENABLE_X_OUT 0x0040 -#define MXU1_UART_ENABLE_XA_OUT 0x0080 -#define MXU1_UART_ENABLE_X_IN 0x0100 -#define MXU1_UART_ENABLE_DTR_IN 0x0800 -#define MXU1_UART_DISABLE_DTR 0x1000 -#define MXU1_UART_ENABLE_MS_INTS 0x2000 -#define MXU1_UART_ENABLE_AUTO_START_DMA 0x4000 -#define MXU1_UART_SEND_BREAK_SIGNAL 0x8000 - -/* Parity */ -#define MXU1_UART_NO_PARITY 0x00 -#define MXU1_UART_ODD_PARITY 0x01 -#define MXU1_UART_EVEN_PARITY 0x02 -#define MXU1_UART_MARK_PARITY 0x03 -#define MXU1_UART_SPACE_PARITY 0x04 - -/* Stop bits */ -#define MXU1_UART_1_STOP_BITS 0x00 -#define MXU1_UART_1_5_STOP_BITS 0x01 -#define MXU1_UART_2_STOP_BITS 0x02 - -/* Bits per character */ -#define MXU1_UART_5_DATA_BITS 0x00 -#define MXU1_UART_6_DATA_BITS 0x01 -#define MXU1_UART_7_DATA_BITS 0x02 -#define MXU1_UART_8_DATA_BITS 0x03 - -/* Operation modes */ -#define MXU1_UART_232 0x00 -#define MXU1_UART_485_RECEIVER_DISABLED 0x01 -#define MXU1_UART_485_RECEIVER_ENABLED 0x02 - -/* Pipe transfer mode and timeout */ -#define MXU1_PIPE_MODE_CONTINUOUS 0x01 -#define MXU1_PIPE_MODE_MASK 0x03 -#define MXU1_PIPE_TIMEOUT_MASK 0x7C -#define MXU1_PIPE_TIMEOUT_ENABLE 0x80 - -/* Config struct */ -struct mxu1_uart_config { - __be16 wBaudRate; - __be16 wFlags; - u8 bDataBits; - u8 bParity; - u8 bStopBits; - char cXon; - char cXoff; - u8 bUartMode; -} __packed; - -/* Purge modes */ -#define MXU1_PURGE_OUTPUT 0x00 -#define MXU1_PURGE_INPUT 0x80 - -/* Read/Write data */ -#define MXU1_RW_DATA_ADDR_SFR 0x10 -#define MXU1_RW_DATA_ADDR_IDATA 0x20 -#define MXU1_RW_DATA_ADDR_XDATA 0x30 -#define MXU1_RW_DATA_ADDR_CODE 0x40 -#define MXU1_RW_DATA_ADDR_GPIO 0x50 -#define MXU1_RW_DATA_ADDR_I2C 0x60 -#define MXU1_RW_DATA_ADDR_FLASH 0x70 -#define MXU1_RW_DATA_ADDR_DSP 0x80 - -#define MXU1_RW_DATA_UNSPECIFIED 0x00 -#define MXU1_RW_DATA_BYTE 0x01 -#define MXU1_RW_DATA_WORD 0x02 -#define MXU1_RW_DATA_DOUBLE_WORD 0x04 - -struct mxu1_write_data_bytes { - u8 bAddrType; - u8 bDataType; - u8 bDataCounter; - __be16 wBaseAddrHi; - __be16 wBaseAddrLo; - u8 bData[0]; -} __packed; - -/* Interrupt codes */ -#define MXU1_CODE_HARDWARE_ERROR 0xFF -#define MXU1_CODE_DATA_ERROR 0x03 -#define MXU1_CODE_MODEM_STATUS 0x04 - -static inline int mxu1_get_func_from_code(unsigned char code) -{ - return code & 0x0f; -} - -/* Download firmware max packet size */ -#define MXU1_DOWNLOAD_MAX_PACKET_SIZE 64 - -/* Firmware image header */ -struct mxu1_firmware_header { - __le16 wLength; - u8 bCheckSum; -} __packed; - -#define MXU1_UART_BASE_ADDR 0xFFA0 -#define MXU1_UART_OFFSET_MCR 0x0004 - -#define MXU1_BAUD_BASE 923077 - -#define MXU1_TRANSFER_TIMEOUT 2 -#define MXU1_DOWNLOAD_TIMEOUT 1000 -#define MXU1_DEFAULT_CLOSING_WAIT 4000 /* in .01 secs */ - -struct mxu1_port { - u8 msr; - u8 mcr; - u8 uart_mode; - spinlock_t spinlock; /* Protects msr */ - struct mutex mutex; /* Protects mcr */ - bool send_break; -}; - -struct mxu1_device { - u16 mxd_model; -}; - -static const struct usb_device_id mxu1_idtable[] = { - { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1110_PRODUCT_ID) }, - { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1130_PRODUCT_ID) }, - { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1150_PRODUCT_ID) }, - { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1151_PRODUCT_ID) }, - { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1131_PRODUCT_ID) }, - { } -}; - -MODULE_DEVICE_TABLE(usb, mxu1_idtable); - -/* Write the given buffer out to the control pipe. */ -static int mxu1_send_ctrl_data_urb(struct usb_serial *serial, - u8 request, - u16 value, u16 index, - void *data, size_t size) -{ - int status; - - status = usb_control_msg(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - request, - (USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE), value, index, - data, size, - USB_CTRL_SET_TIMEOUT); - if (status < 0) { - dev_err(&serial->interface->dev, - "%s - usb_control_msg failed: %d\n", - __func__, status); - return status; - } - - if (status != size) { - dev_err(&serial->interface->dev, - "%s - short write (%d / %zd)\n", - __func__, status, size); - return -EIO; - } - - return 0; -} - -/* Send a vendor request without any data */ -static int mxu1_send_ctrl_urb(struct usb_serial *serial, - u8 request, u16 value, u16 index) -{ - return mxu1_send_ctrl_data_urb(serial, request, value, index, - NULL, 0); -} - -static int mxu1_download_firmware(struct usb_serial *serial, - const struct firmware *fw_p) -{ - int status = 0; - int buffer_size; - int pos; - int len; - int done; - u8 cs = 0; - u8 *buffer; - struct usb_device *dev = serial->dev; - struct mxu1_firmware_header *header; - unsigned int pipe; - - pipe = usb_sndbulkpipe(dev, serial->port[0]->bulk_out_endpointAddress); - - buffer_size = fw_p->size + sizeof(*header); - buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - - memcpy(buffer, fw_p->data, fw_p->size); - memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size); - - for (pos = sizeof(*header); pos < buffer_size; pos++) - cs = (u8)(cs + buffer[pos]); - - header = (struct mxu1_firmware_header *)buffer; - header->wLength = cpu_to_le16(buffer_size - sizeof(*header)); - header->bCheckSum = cs; - - dev_dbg(&dev->dev, "%s - downloading firmware\n", __func__); - - for (pos = 0; pos < buffer_size; pos += done) { - len = min(buffer_size - pos, MXU1_DOWNLOAD_MAX_PACKET_SIZE); - - status = usb_bulk_msg(dev, pipe, buffer + pos, len, &done, - MXU1_DOWNLOAD_TIMEOUT); - if (status) - break; - } - - kfree(buffer); - - if (status) { - dev_err(&dev->dev, "failed to download firmware: %d\n", status); - return status; - } - - msleep_interruptible(100); - usb_reset_device(dev); - - dev_dbg(&dev->dev, "%s - download successful\n", __func__); - - return 0; -} - -static int mxu1_port_probe(struct usb_serial_port *port) -{ - struct mxu1_port *mxport; - struct mxu1_device *mxdev; - - if (!port->interrupt_in_urb) { - dev_err(&port->dev, "no interrupt urb\n"); - return -ENODEV; - } - - mxport = kzalloc(sizeof(struct mxu1_port), GFP_KERNEL); - if (!mxport) - return -ENOMEM; - - spin_lock_init(&mxport->spinlock); - mutex_init(&mxport->mutex); - - mxdev = usb_get_serial_data(port->serial); - - switch (mxdev->mxd_model) { - case MXU1_1110_PRODUCT_ID: - case MXU1_1150_PRODUCT_ID: - case MXU1_1151_PRODUCT_ID: - mxport->uart_mode = MXU1_UART_232; - break; - case MXU1_1130_PRODUCT_ID: - case MXU1_1131_PRODUCT_ID: - mxport->uart_mode = MXU1_UART_485_RECEIVER_DISABLED; - break; - } - - usb_set_serial_port_data(port, mxport); - - port->port.closing_wait = - msecs_to_jiffies(MXU1_DEFAULT_CLOSING_WAIT * 10); - port->port.drain_delay = 1; - - return 0; -} - -static int mxu1_port_remove(struct usb_serial_port *port) -{ - struct mxu1_port *mxport; - - mxport = usb_get_serial_port_data(port); - kfree(mxport); - - return 0; -} - -static int mxu1_startup(struct usb_serial *serial) -{ - struct mxu1_device *mxdev; - struct usb_device *dev = serial->dev; - struct usb_host_interface *cur_altsetting; - char fw_name[32]; - const struct firmware *fw_p = NULL; - int err; - - dev_dbg(&serial->interface->dev, "%s - product 0x%04X, num configurations %d, configuration value %d\n", - __func__, le16_to_cpu(dev->descriptor.idProduct), - dev->descriptor.bNumConfigurations, - dev->actconfig->desc.bConfigurationValue); - - /* create device structure */ - mxdev = kzalloc(sizeof(struct mxu1_device), GFP_KERNEL); - if (!mxdev) - return -ENOMEM; - - usb_set_serial_data(serial, mxdev); - - mxdev->mxd_model = le16_to_cpu(dev->descriptor.idProduct); - - cur_altsetting = serial->interface->cur_altsetting; - - /* if we have only 1 configuration, download firmware */ - if (cur_altsetting->desc.bNumEndpoints == 1) { - - snprintf(fw_name, - sizeof(fw_name), - "moxa/moxa-%04x.fw", - mxdev->mxd_model); - - err = request_firmware(&fw_p, fw_name, &serial->interface->dev); - if (err) { - dev_err(&serial->interface->dev, "failed to request firmware: %d\n", - err); - goto err_free_mxdev; - } - - err = mxu1_download_firmware(serial, fw_p); - if (err) - goto err_release_firmware; - - /* device is being reset */ - err = -ENODEV; - goto err_release_firmware; - } - - return 0; - -err_release_firmware: - release_firmware(fw_p); -err_free_mxdev: - kfree(mxdev); - - return err; -} - -static void mxu1_release(struct usb_serial *serial) -{ - struct mxu1_device *mxdev; - - mxdev = usb_get_serial_data(serial); - kfree(mxdev); -} - -static int mxu1_write_byte(struct usb_serial_port *port, u32 addr, - u8 mask, u8 byte) -{ - int status; - size_t size; - struct mxu1_write_data_bytes *data; - - dev_dbg(&port->dev, "%s - addr 0x%08X, mask 0x%02X, byte 0x%02X\n", - __func__, addr, mask, byte); - - size = sizeof(struct mxu1_write_data_bytes) + 2; - data = kzalloc(size, GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->bAddrType = MXU1_RW_DATA_ADDR_XDATA; - data->bDataType = MXU1_RW_DATA_BYTE; - data->bDataCounter = 1; - data->wBaseAddrHi = cpu_to_be16(addr >> 16); - data->wBaseAddrLo = cpu_to_be16(addr); - data->bData[0] = mask; - data->bData[1] = byte; - - status = mxu1_send_ctrl_data_urb(port->serial, MXU1_WRITE_DATA, 0, - MXU1_RAM_PORT, data, size); - if (status < 0) - dev_err(&port->dev, "%s - failed: %d\n", __func__, status); - - kfree(data); - - return status; -} - -static int mxu1_set_mcr(struct usb_serial_port *port, unsigned int mcr) -{ - int status; - - status = mxu1_write_byte(port, - MXU1_UART_BASE_ADDR + MXU1_UART_OFFSET_MCR, - MXU1_MCR_RTS | MXU1_MCR_DTR | MXU1_MCR_LOOP, - mcr); - return status; -} - -static void mxu1_set_termios(struct tty_struct *tty, - struct usb_serial_port *port, - struct ktermios *old_termios) -{ - struct mxu1_port *mxport = usb_get_serial_port_data(port); - struct mxu1_uart_config *config; - tcflag_t cflag, iflag; - speed_t baud; - int status; - unsigned int mcr; - - cflag = tty->termios.c_cflag; - iflag = tty->termios.c_iflag; - - if (old_termios && - !tty_termios_hw_change(&tty->termios, old_termios) && - tty->termios.c_iflag == old_termios->c_iflag) { - dev_dbg(&port->dev, "%s - nothing to change\n", __func__); - return; - } - - dev_dbg(&port->dev, - "%s - cflag 0x%08x, iflag 0x%08x\n", __func__, cflag, iflag); - - if (old_termios) { - dev_dbg(&port->dev, "%s - old cflag 0x%08x, old iflag 0x%08x\n", - __func__, - old_termios->c_cflag, - old_termios->c_iflag); - } - - config = kzalloc(sizeof(*config), GFP_KERNEL); - if (!config) - return; - - /* these flags must be set */ - config->wFlags |= MXU1_UART_ENABLE_MS_INTS; - config->wFlags |= MXU1_UART_ENABLE_AUTO_START_DMA; - if (mxport->send_break) - config->wFlags |= MXU1_UART_SEND_BREAK_SIGNAL; - config->bUartMode = mxport->uart_mode; - - switch (C_CSIZE(tty)) { - case CS5: - config->bDataBits = MXU1_UART_5_DATA_BITS; - break; - case CS6: - config->bDataBits = MXU1_UART_6_DATA_BITS; - break; - case CS7: - config->bDataBits = MXU1_UART_7_DATA_BITS; - break; - default: - case CS8: - config->bDataBits = MXU1_UART_8_DATA_BITS; - break; - } - - if (C_PARENB(tty)) { - config->wFlags |= MXU1_UART_ENABLE_PARITY_CHECKING; - if (C_CMSPAR(tty)) { - if (C_PARODD(tty)) - config->bParity = MXU1_UART_MARK_PARITY; - else - config->bParity = MXU1_UART_SPACE_PARITY; - } else { - if (C_PARODD(tty)) - config->bParity = MXU1_UART_ODD_PARITY; - else - config->bParity = MXU1_UART_EVEN_PARITY; - } - } else { - config->bParity = MXU1_UART_NO_PARITY; - } - - if (C_CSTOPB(tty)) - config->bStopBits = MXU1_UART_2_STOP_BITS; - else - config->bStopBits = MXU1_UART_1_STOP_BITS; - - if (C_CRTSCTS(tty)) { - /* RTS flow control must be off to drop RTS for baud rate B0 */ - if (C_BAUD(tty) != B0) - config->wFlags |= MXU1_UART_ENABLE_RTS_IN; - config->wFlags |= MXU1_UART_ENABLE_CTS_OUT; - } - - if (I_IXOFF(tty) || I_IXON(tty)) { - config->cXon = START_CHAR(tty); - config->cXoff = STOP_CHAR(tty); - - if (I_IXOFF(tty)) - config->wFlags |= MXU1_UART_ENABLE_X_IN; - - if (I_IXON(tty)) - config->wFlags |= MXU1_UART_ENABLE_X_OUT; - } - - baud = tty_get_baud_rate(tty); - if (!baud) - baud = 9600; - config->wBaudRate = MXU1_BAUD_BASE / baud; - - dev_dbg(&port->dev, "%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d\n", - __func__, baud, config->wBaudRate, config->wFlags, - config->bDataBits, config->bParity, config->bStopBits, - config->cXon, config->cXoff, config->bUartMode); - - cpu_to_be16s(&config->wBaudRate); - cpu_to_be16s(&config->wFlags); - - status = mxu1_send_ctrl_data_urb(port->serial, MXU1_SET_CONFIG, 0, - MXU1_UART1_PORT, config, - sizeof(*config)); - if (status) - dev_err(&port->dev, "cannot set config: %d\n", status); - - mutex_lock(&mxport->mutex); - mcr = mxport->mcr; - - if (C_BAUD(tty) == B0) - mcr &= ~(MXU1_MCR_DTR | MXU1_MCR_RTS); - else if (old_termios && (old_termios->c_cflag & CBAUD) == B0) - mcr |= MXU1_MCR_DTR | MXU1_MCR_RTS; - - status = mxu1_set_mcr(port, mcr); - if (status) - dev_err(&port->dev, "cannot set modem control: %d\n", status); - else - mxport->mcr = mcr; - - mutex_unlock(&mxport->mutex); - - kfree(config); -} - -static int mxu1_get_serial_info(struct usb_serial_port *port, - struct serial_struct __user *ret_arg) -{ - struct serial_struct ret_serial; - unsigned cwait; - - if (!ret_arg) - return -EFAULT; - - cwait = port->port.closing_wait; - if (cwait != ASYNC_CLOSING_WAIT_NONE) - cwait = jiffies_to_msecs(cwait) / 10; - - memset(&ret_serial, 0, sizeof(ret_serial)); - - ret_serial.type = PORT_16550A; - ret_serial.line = port->minor; - ret_serial.port = 0; - ret_serial.xmit_fifo_size = port->bulk_out_size; - ret_serial.baud_base = MXU1_BAUD_BASE; - ret_serial.close_delay = 5*HZ; - ret_serial.closing_wait = cwait; - - if (copy_to_user(ret_arg, &ret_serial, sizeof(*ret_arg))) - return -EFAULT; - - return 0; -} - - -static int mxu1_set_serial_info(struct usb_serial_port *port, - struct serial_struct __user *new_arg) -{ - struct serial_struct new_serial; - unsigned cwait; - - if (copy_from_user(&new_serial, new_arg, sizeof(new_serial))) - return -EFAULT; - - cwait = new_serial.closing_wait; - if (cwait != ASYNC_CLOSING_WAIT_NONE) - cwait = msecs_to_jiffies(10 * new_serial.closing_wait); - - port->port.closing_wait = cwait; - - return 0; -} - -static int mxu1_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct usb_serial_port *port = tty->driver_data; - - switch (cmd) { - case TIOCGSERIAL: - return mxu1_get_serial_info(port, - (struct serial_struct __user *)arg); - case TIOCSSERIAL: - return mxu1_set_serial_info(port, - (struct serial_struct __user *)arg); - } - - return -ENOIOCTLCMD; -} - -static int mxu1_tiocmget(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - struct mxu1_port *mxport = usb_get_serial_port_data(port); - unsigned int result; - unsigned int msr; - unsigned int mcr; - unsigned long flags; - - mutex_lock(&mxport->mutex); - spin_lock_irqsave(&mxport->spinlock, flags); - - msr = mxport->msr; - mcr = mxport->mcr; - - spin_unlock_irqrestore(&mxport->spinlock, flags); - mutex_unlock(&mxport->mutex); - - result = ((mcr & MXU1_MCR_DTR) ? TIOCM_DTR : 0) | - ((mcr & MXU1_MCR_RTS) ? TIOCM_RTS : 0) | - ((mcr & MXU1_MCR_LOOP) ? TIOCM_LOOP : 0) | - ((msr & MXU1_MSR_CTS) ? TIOCM_CTS : 0) | - ((msr & MXU1_MSR_CD) ? TIOCM_CAR : 0) | - ((msr & MXU1_MSR_RI) ? TIOCM_RI : 0) | - ((msr & MXU1_MSR_DSR) ? TIOCM_DSR : 0); - - dev_dbg(&port->dev, "%s - 0x%04X\n", __func__, result); - - return result; -} - -static int mxu1_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct usb_serial_port *port = tty->driver_data; - struct mxu1_port *mxport = usb_get_serial_port_data(port); - int err; - unsigned int mcr; - - mutex_lock(&mxport->mutex); - mcr = mxport->mcr; - - if (set & TIOCM_RTS) - mcr |= MXU1_MCR_RTS; - if (set & TIOCM_DTR) - mcr |= MXU1_MCR_DTR; - if (set & TIOCM_LOOP) - mcr |= MXU1_MCR_LOOP; - - if (clear & TIOCM_RTS) - mcr &= ~MXU1_MCR_RTS; - if (clear & TIOCM_DTR) - mcr &= ~MXU1_MCR_DTR; - if (clear & TIOCM_LOOP) - mcr &= ~MXU1_MCR_LOOP; - - err = mxu1_set_mcr(port, mcr); - if (!err) - mxport->mcr = mcr; - - mutex_unlock(&mxport->mutex); - - return err; -} - -static void mxu1_break(struct tty_struct *tty, int break_state) -{ - struct usb_serial_port *port = tty->driver_data; - struct mxu1_port *mxport = usb_get_serial_port_data(port); - - if (break_state == -1) - mxport->send_break = true; - else - mxport->send_break = false; - - mxu1_set_termios(tty, port, NULL); -} - -static int mxu1_open(struct tty_struct *tty, struct usb_serial_port *port) -{ - struct mxu1_port *mxport = usb_get_serial_port_data(port); - struct usb_serial *serial = port->serial; - int status; - u16 open_settings; - - open_settings = (MXU1_PIPE_MODE_CONTINUOUS | - MXU1_PIPE_TIMEOUT_ENABLE | - (MXU1_TRANSFER_TIMEOUT << 2)); - - mxport->msr = 0; - - status = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); - if (status) { - dev_err(&port->dev, "failed to submit interrupt urb: %d\n", - status); - return status; - } - - if (tty) - mxu1_set_termios(tty, port, NULL); - - status = mxu1_send_ctrl_urb(serial, MXU1_OPEN_PORT, - open_settings, MXU1_UART1_PORT); - if (status) { - dev_err(&port->dev, "cannot send open command: %d\n", status); - goto unlink_int_urb; - } - - status = mxu1_send_ctrl_urb(serial, MXU1_START_PORT, - 0, MXU1_UART1_PORT); - if (status) { - dev_err(&port->dev, "cannot send start command: %d\n", status); - goto unlink_int_urb; - } - - status = mxu1_send_ctrl_urb(serial, MXU1_PURGE_PORT, - MXU1_PURGE_INPUT, MXU1_UART1_PORT); - if (status) { - dev_err(&port->dev, "cannot clear input buffers: %d\n", - status); - - goto unlink_int_urb; - } - - status = mxu1_send_ctrl_urb(serial, MXU1_PURGE_PORT, - MXU1_PURGE_OUTPUT, MXU1_UART1_PORT); - if (status) { - dev_err(&port->dev, "cannot clear output buffers: %d\n", - status); - - goto unlink_int_urb; - } - - /* - * reset the data toggle on the bulk endpoints to work around bug in - * host controllers where things get out of sync some times - */ - usb_clear_halt(serial->dev, port->write_urb->pipe); - usb_clear_halt(serial->dev, port->read_urb->pipe); - - if (tty) - mxu1_set_termios(tty, port, NULL); - - status = mxu1_send_ctrl_urb(serial, MXU1_OPEN_PORT, - open_settings, MXU1_UART1_PORT); - if (status) { - dev_err(&port->dev, "cannot send open command: %d\n", status); - goto unlink_int_urb; - } - - status = mxu1_send_ctrl_urb(serial, MXU1_START_PORT, - 0, MXU1_UART1_PORT); - if (status) { - dev_err(&port->dev, "cannot send start command: %d\n", status); - goto unlink_int_urb; - } - - status = usb_serial_generic_open(tty, port); - if (status) - goto unlink_int_urb; - - return 0; - -unlink_int_urb: - usb_kill_urb(port->interrupt_in_urb); - - return status; -} - -static void mxu1_close(struct usb_serial_port *port) -{ - int status; - - usb_serial_generic_close(port); - usb_kill_urb(port->interrupt_in_urb); - - status = mxu1_send_ctrl_urb(port->serial, MXU1_CLOSE_PORT, - 0, MXU1_UART1_PORT); - if (status) { - dev_err(&port->dev, "failed to send close port command: %d\n", - status); - } -} - -static void mxu1_handle_new_msr(struct usb_serial_port *port, u8 msr) -{ - struct mxu1_port *mxport = usb_get_serial_port_data(port); - struct async_icount *icount; - unsigned long flags; - - dev_dbg(&port->dev, "%s - msr 0x%02X\n", __func__, msr); - - spin_lock_irqsave(&mxport->spinlock, flags); - mxport->msr = msr & MXU1_MSR_MASK; - spin_unlock_irqrestore(&mxport->spinlock, flags); - - if (msr & MXU1_MSR_DELTA_MASK) { - icount = &port->icount; - if (msr & MXU1_MSR_DELTA_CTS) - icount->cts++; - if (msr & MXU1_MSR_DELTA_DSR) - icount->dsr++; - if (msr & MXU1_MSR_DELTA_CD) - icount->dcd++; - if (msr & MXU1_MSR_DELTA_RI) - icount->rng++; - - wake_up_interruptible(&port->port.delta_msr_wait); - } -} - -static void mxu1_interrupt_callback(struct urb *urb) -{ - struct usb_serial_port *port = urb->context; - unsigned char *data = urb->transfer_buffer; - int length = urb->actual_length; - int function; - int status; - u8 msr; - - switch (urb->status) { - case 0: - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - dev_dbg(&port->dev, "%s - urb shutting down: %d\n", - __func__, urb->status); - return; - default: - dev_dbg(&port->dev, "%s - nonzero urb status: %d\n", - __func__, urb->status); - goto exit; - } - - if (length != 2) { - dev_dbg(&port->dev, "%s - bad packet size: %d\n", - __func__, length); - goto exit; - } - - if (data[0] == MXU1_CODE_HARDWARE_ERROR) { - dev_err(&port->dev, "hardware error: %d\n", data[1]); - goto exit; - } - - function = mxu1_get_func_from_code(data[0]); - - dev_dbg(&port->dev, "%s - function %d, data 0x%02X\n", - __func__, function, data[1]); - - switch (function) { - case MXU1_CODE_DATA_ERROR: - dev_dbg(&port->dev, "%s - DATA ERROR, data 0x%02X\n", - __func__, data[1]); - break; - - case MXU1_CODE_MODEM_STATUS: - msr = data[1]; - mxu1_handle_new_msr(port, msr); - break; - - default: - dev_err(&port->dev, "unknown interrupt code: 0x%02X\n", - data[1]); - break; - } - -exit: - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) { - dev_err(&port->dev, "resubmit interrupt urb failed: %d\n", - status); - } -} - -static struct usb_serial_driver mxu11x0_device = { - .driver = { - .owner = THIS_MODULE, - .name = "mxu11x0", - }, - .description = "MOXA UPort 11x0", - .id_table = mxu1_idtable, - .num_ports = 1, - .port_probe = mxu1_port_probe, - .port_remove = mxu1_port_remove, - .attach = mxu1_startup, - .release = mxu1_release, - .open = mxu1_open, - .close = mxu1_close, - .ioctl = mxu1_ioctl, - .set_termios = mxu1_set_termios, - .tiocmget = mxu1_tiocmget, - .tiocmset = mxu1_tiocmset, - .tiocmiwait = usb_serial_generic_tiocmiwait, - .get_icount = usb_serial_generic_get_icount, - .break_ctl = mxu1_break, - .read_int_callback = mxu1_interrupt_callback, -}; - -static struct usb_serial_driver *const serial_drivers[] = { - &mxu11x0_device, NULL -}; - -module_usb_serial_driver(serial_drivers, mxu1_idtable); - -MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>"); -MODULE_DESCRIPTION("MOXA UPort 11x0 USB to Serial Hub Driver"); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("moxa/moxa-1110.fw"); -MODULE_FIRMWARE("moxa/moxa-1130.fw"); -MODULE_FIRMWARE("moxa/moxa-1131.fw"); -MODULE_FIRMWARE("moxa/moxa-1150.fw"); -MODULE_FIRMWARE("moxa/moxa-1151.fw"); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index db86e512e0fc..348e19834b83 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -270,6 +270,7 @@ static void option_instat_callback(struct urb *urb); #define TELIT_PRODUCT_UE910_V2 0x1012 #define TELIT_PRODUCT_LE922_USBCFG0 0x1042 #define TELIT_PRODUCT_LE922_USBCFG3 0x1043 +#define TELIT_PRODUCT_LE922_USBCFG5 0x1045 #define TELIT_PRODUCT_LE920 0x1200 #define TELIT_PRODUCT_LE910 0x1201 @@ -315,6 +316,7 @@ static void option_instat_callback(struct urb *urb); #define TOSHIBA_PRODUCT_G450 0x0d45 #define ALINK_VENDOR_ID 0x1e0e +#define SIMCOM_PRODUCT_SIM7100E 0x9001 /* Yes, ALINK_VENDOR_ID */ #define ALINK_PRODUCT_PH300 0x9100 #define ALINK_PRODUCT_3GU 0x9200 @@ -607,6 +609,10 @@ static const struct option_blacklist_info zte_1255_blacklist = { .reserved = BIT(3) | BIT(4), }; +static const struct option_blacklist_info simcom_sim7100e_blacklist = { + .reserved = BIT(5) | BIT(6), +}; + static const struct option_blacklist_info telit_le910_blacklist = { .sendsetup = BIT(0), .reserved = BIT(1) | BIT(2), @@ -1122,9 +1128,13 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) }, { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) }, { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */ + { USB_DEVICE_AND_INTERFACE_INFO(QUALCOMM_VENDOR_ID, 0x6001, 0xff, 0xff, 0xff), /* 4G LTE usb-modem U901 */ + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */ + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9003), /* Quectel UC20 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003), @@ -1176,6 +1186,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3), .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG5, 0xff), + .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910), .driver_info = (kernel_ulong_t)&telit_le910_blacklist }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), @@ -1645,6 +1657,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) }, { USB_DEVICE(ALINK_VENDOR_ID, ALINK_PRODUCT_PH300) }, { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) }, + { USB_DEVICE(ALINK_VENDOR_ID, SIMCOM_PRODUCT_SIM7100E), + .driver_info = (kernel_ulong_t)&simcom_sim7100e_blacklist }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist }, diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 9919d2a9faf2..1bc6089b9008 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -157,14 +157,17 @@ static const struct usb_device_id id_table[] = { {DEVICE_SWI(0x1199, 0x9056)}, /* Sierra Wireless Modem */ {DEVICE_SWI(0x1199, 0x9060)}, /* Sierra Wireless Modem */ {DEVICE_SWI(0x1199, 0x9061)}, /* Sierra Wireless Modem */ - {DEVICE_SWI(0x1199, 0x9070)}, /* Sierra Wireless MC74xx/EM74xx */ - {DEVICE_SWI(0x1199, 0x9071)}, /* Sierra Wireless MC74xx/EM74xx */ + {DEVICE_SWI(0x1199, 0x9070)}, /* Sierra Wireless MC74xx */ + {DEVICE_SWI(0x1199, 0x9071)}, /* Sierra Wireless MC74xx */ + {DEVICE_SWI(0x1199, 0x9078)}, /* Sierra Wireless EM74xx */ + {DEVICE_SWI(0x1199, 0x9079)}, /* Sierra Wireless EM74xx */ {DEVICE_SWI(0x413c, 0x81a2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a8)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a9)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81b1)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */ + {DEVICE_SWI(0x413c, 0x81b3)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */ /* Huawei devices */ {DEVICE_HWI(0x03f0, 0x581d)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */ diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 2760a7ba3f30..8c80a48e3233 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -446,7 +446,8 @@ static long vfio_pci_ioctl(void *device_data, info.num_regions = VFIO_PCI_NUM_REGIONS; info.num_irqs = VFIO_PCI_NUM_IRQS; - return copy_to_user((void __user *)arg, &info, minsz); + return copy_to_user((void __user *)arg, &info, minsz) ? + -EFAULT : 0; } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) { struct pci_dev *pdev = vdev->pdev; @@ -520,7 +521,8 @@ static long vfio_pci_ioctl(void *device_data, return -EINVAL; } - return copy_to_user((void __user *)arg, &info, minsz); + return copy_to_user((void __user *)arg, &info, minsz) ? + -EFAULT : 0; } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) { struct vfio_irq_info info; @@ -555,7 +557,8 @@ static long vfio_pci_ioctl(void *device_data, else info.flags |= VFIO_IRQ_INFO_NORESIZE; - return copy_to_user((void __user *)arg, &info, minsz); + return copy_to_user((void __user *)arg, &info, minsz) ? + -EFAULT : 0; } else if (cmd == VFIO_DEVICE_SET_IRQS) { struct vfio_irq_set hdr; diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c index 418cdd9ba3f4..e65b142d3422 100644 --- a/drivers/vfio/platform/vfio_platform_common.c +++ b/drivers/vfio/platform/vfio_platform_common.c @@ -219,7 +219,8 @@ static long vfio_platform_ioctl(void *device_data, info.num_regions = vdev->num_regions; info.num_irqs = vdev->num_irqs; - return copy_to_user((void __user *)arg, &info, minsz); + return copy_to_user((void __user *)arg, &info, minsz) ? + -EFAULT : 0; } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) { struct vfio_region_info info; @@ -240,7 +241,8 @@ static long vfio_platform_ioctl(void *device_data, info.size = vdev->regions[info.index].size; info.flags = vdev->regions[info.index].flags; - return copy_to_user((void __user *)arg, &info, minsz); + return copy_to_user((void __user *)arg, &info, minsz) ? + -EFAULT : 0; } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) { struct vfio_irq_info info; @@ -259,7 +261,8 @@ static long vfio_platform_ioctl(void *device_data, info.flags = vdev->irqs[info.index].flags; info.count = vdev->irqs[info.index].count; - return copy_to_user((void __user *)arg, &info, minsz); + return copy_to_user((void __user *)arg, &info, minsz) ? + -EFAULT : 0; } else if (cmd == VFIO_DEVICE_SET_IRQS) { struct vfio_irq_set hdr; diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 6f1ea3dddbad..75b24e93cedb 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -999,7 +999,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data, info.iova_pgsizes = vfio_pgsize_bitmap(iommu); - return copy_to_user((void __user *)arg, &info, minsz); + return copy_to_user((void __user *)arg, &info, minsz) ? + -EFAULT : 0; } else if (cmd == VFIO_IOMMU_MAP_DMA) { struct vfio_iommu_type1_dma_map map; @@ -1032,7 +1033,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data, if (ret) return ret; - return copy_to_user((void __user *)arg, &unmap, minsz); + return copy_to_user((void __user *)arg, &unmap, minsz) ? + -EFAULT : 0; } return -ENOTTY; diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index ad2146a9ab2d..236553e81027 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -1156,6 +1156,8 @@ int vhost_init_used(struct vhost_virtqueue *vq) { __virtio16 last_used_idx; int r; + bool is_le = vq->is_le; + if (!vq->private_data) { vq->is_le = virtio_legacy_is_little_endian(); return 0; @@ -1165,15 +1167,20 @@ int vhost_init_used(struct vhost_virtqueue *vq) r = vhost_update_used_flags(vq); if (r) - return r; + goto err; vq->signalled_used_valid = false; - if (!access_ok(VERIFY_READ, &vq->used->idx, sizeof vq->used->idx)) - return -EFAULT; + if (!access_ok(VERIFY_READ, &vq->used->idx, sizeof vq->used->idx)) { + r = -EFAULT; + goto err; + } r = __get_user(last_used_idx, &vq->used->idx); if (r) - return r; + goto err; vq->last_used_idx = vhost16_to_cpu(vq, last_used_idx); return 0; +err: + vq->is_le = is_le; + return r; } EXPORT_SYMBOL_GPL(vhost_init_used); diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 92f394927f24..6e92917ba77a 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -709,6 +709,7 @@ static int con2fb_acquire_newinfo(struct vc_data *vc, struct fb_info *info, } if (!err) { + ops->cur_blink_jiffies = HZ / 5; info->fbcon_par = ops; if (vc) @@ -956,6 +957,7 @@ static const char *fbcon_startup(void) ops->currcon = -1; ops->graphics = 1; ops->cur_rotate = -1; + ops->cur_blink_jiffies = HZ / 5; info->fbcon_par = ops; p->con_rotate = initial_rotation; set_blitting_type(vc, info); diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index c0c11fad4611..7760fc1a2218 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c @@ -679,7 +679,7 @@ int virtio_pci_modern_probe(struct virtio_pci_device *vp_dev) pci_read_config_dword(pci_dev, notify + offsetof(struct virtio_pci_notify_cap, - cap.length), + cap.offset), ¬ify_offset); /* We don't know how many VQs we'll map, ahead of the time. diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 0f6d8515ba4f..80825a7e8e48 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1569,6 +1569,17 @@ config WATCHDOG_RIO machines. The watchdog timeout period is normally one minute but can be changed with a boot-time parameter. +config WATCHDOG_SUN4V + tristate "Sun4v Watchdog support" + select WATCHDOG_CORE + depends on SPARC64 + help + Say Y here to support the hypervisor watchdog capability embedded + in the SPARC sun4v architecture. + + To compile this driver as a module, choose M here. The module will + be called sun4v_wdt. + # XTENSA Architecture # Xen Architecture diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index f566753256ab..f6a6a387c6c7 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -179,6 +179,7 @@ obj-$(CONFIG_SH_WDT) += shwdt.o obj-$(CONFIG_WATCHDOG_RIO) += riowd.o obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o +obj-$(CONFIG_WATCHDOG_SUN4V) += sun4v_wdt.o # XTENSA Architecture diff --git a/drivers/watchdog/sun4v_wdt.c b/drivers/watchdog/sun4v_wdt.c new file mode 100644 index 000000000000..1467fe50a76f --- /dev/null +++ b/drivers/watchdog/sun4v_wdt.c @@ -0,0 +1,191 @@ +/* + * sun4v watchdog timer + * (c) Copyright 2016 Oracle Corporation + * + * Implement a simple watchdog driver using the built-in sun4v hypervisor + * watchdog support. If time expires, the hypervisor stops or bounces + * the guest domain. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/watchdog.h> +#include <asm/hypervisor.h> +#include <asm/mdesc.h> + +#define WDT_TIMEOUT 60 +#define WDT_MAX_TIMEOUT 31536000 +#define WDT_MIN_TIMEOUT 1 +#define WDT_DEFAULT_RESOLUTION_MS 1000 /* 1 second */ + +static unsigned int timeout; +module_param(timeout, uint, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=" + __MODULE_STRING(WDT_TIMEOUT) ")"); + +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, S_IRUGO); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +static int sun4v_wdt_stop(struct watchdog_device *wdd) +{ + sun4v_mach_set_watchdog(0, NULL); + + return 0; +} + +static int sun4v_wdt_ping(struct watchdog_device *wdd) +{ + int hverr; + + /* + * HV watchdog timer will round up the timeout + * passed in to the nearest multiple of the + * watchdog resolution in milliseconds. + */ + hverr = sun4v_mach_set_watchdog(wdd->timeout * 1000, NULL); + if (hverr == HV_EINVAL) + return -EINVAL; + + return 0; +} + +static int sun4v_wdt_set_timeout(struct watchdog_device *wdd, + unsigned int timeout) +{ + wdd->timeout = timeout; + + return 0; +} + +static const struct watchdog_info sun4v_wdt_ident = { + .options = WDIOF_SETTIMEOUT | + WDIOF_MAGICCLOSE | + WDIOF_KEEPALIVEPING, + .identity = "sun4v hypervisor watchdog", + .firmware_version = 0, +}; + +static struct watchdog_ops sun4v_wdt_ops = { + .owner = THIS_MODULE, + .start = sun4v_wdt_ping, + .stop = sun4v_wdt_stop, + .ping = sun4v_wdt_ping, + .set_timeout = sun4v_wdt_set_timeout, +}; + +static struct watchdog_device wdd = { + .info = &sun4v_wdt_ident, + .ops = &sun4v_wdt_ops, + .min_timeout = WDT_MIN_TIMEOUT, + .max_timeout = WDT_MAX_TIMEOUT, + .timeout = WDT_TIMEOUT, +}; + +static int __init sun4v_wdt_init(void) +{ + struct mdesc_handle *handle; + u64 node; + const u64 *value; + int err = 0; + unsigned long major = 1, minor = 1; + + /* + * There are 2 properties that can be set from the control + * domain for the watchdog. + * watchdog-resolution + * watchdog-max-timeout + * + * We can expect a handle to be returned otherwise something + * serious is wrong. Correct to return -ENODEV here. + */ + + handle = mdesc_grab(); + if (!handle) + return -ENODEV; + + node = mdesc_node_by_name(handle, MDESC_NODE_NULL, "platform"); + err = -ENODEV; + if (node == MDESC_NODE_NULL) + goto out_release; + + /* + * This is a safe way to validate if we are on the right + * platform. + */ + if (sun4v_hvapi_register(HV_GRP_CORE, major, &minor)) + goto out_hv_unreg; + + /* Allow value of watchdog-resolution up to 1s (default) */ + value = mdesc_get_property(handle, node, "watchdog-resolution", NULL); + err = -EINVAL; + if (value) { + if (*value == 0 || + *value > WDT_DEFAULT_RESOLUTION_MS) + goto out_hv_unreg; + } + + value = mdesc_get_property(handle, node, "watchdog-max-timeout", NULL); + if (value) { + /* + * If the property value (in ms) is smaller than + * min_timeout, return -EINVAL. + */ + if (*value < wdd.min_timeout * 1000) + goto out_hv_unreg; + + /* + * If the property value is smaller than + * default max_timeout then set watchdog max_timeout to + * the value of the property in seconds. + */ + if (*value < wdd.max_timeout * 1000) + wdd.max_timeout = *value / 1000; + } + + watchdog_init_timeout(&wdd, timeout, NULL); + + watchdog_set_nowayout(&wdd, nowayout); + + err = watchdog_register_device(&wdd); + if (err) + goto out_hv_unreg; + + pr_info("initialized (timeout=%ds, nowayout=%d)\n", + wdd.timeout, nowayout); + + mdesc_release(handle); + + return 0; + +out_hv_unreg: + sun4v_hvapi_unregister(HV_GRP_CORE); + +out_release: + mdesc_release(handle); + return err; +} + +static void __exit sun4v_wdt_exit(void) +{ + sun4v_hvapi_unregister(HV_GRP_CORE); + watchdog_unregister_device(&wdd); +} + +module_init(sun4v_wdt_init); +module_exit(sun4v_wdt_exit); + +MODULE_AUTHOR("Wim Coekaerts <wim.coekaerts@oracle.com>"); +MODULE_DESCRIPTION("sun4v watchdog driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c index 73dafdc494aa..fb0221434f81 100644 --- a/drivers/xen/xen-pciback/pciback_ops.c +++ b/drivers/xen/xen-pciback/pciback_ops.c @@ -227,8 +227,9 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, /* * PCI_COMMAND_MEMORY must be enabled, otherwise we may not be able * to access the BARs where the MSI-X entries reside. + * But VF devices are unique in which the PF needs to be checked. */ - pci_read_config_word(dev, PCI_COMMAND, &cmd); + pci_read_config_word(pci_physfn(dev), PCI_COMMAND, &cmd); if (dev->msi_enabled || !(cmd & PCI_COMMAND_MEMORY)) return -ENXIO; @@ -332,6 +333,9 @@ void xen_pcibk_do_op(struct work_struct *data) struct xen_pcibk_dev_data *dev_data = NULL; struct xen_pci_op *op = &pdev->op; int test_intx = 0; +#ifdef CONFIG_PCI_MSI + unsigned int nr = 0; +#endif *op = pdev->sh_info->op; barrier(); @@ -360,6 +364,7 @@ void xen_pcibk_do_op(struct work_struct *data) op->err = xen_pcibk_disable_msi(pdev, dev, op); break; case XEN_PCI_OP_enable_msix: + nr = op->value; op->err = xen_pcibk_enable_msix(pdev, dev, op); break; case XEN_PCI_OP_disable_msix: @@ -382,7 +387,7 @@ void xen_pcibk_do_op(struct work_struct *data) if (op->cmd == XEN_PCI_OP_enable_msix && op->err == 0) { unsigned int i; - for (i = 0; i < op->value; i++) + for (i = 0; i < nr; i++) pdev->sh_info->op.msix_entries[i].vector = op->msix_entries[i].vector; } diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c index ad4eb1024d1f..c46ee189466f 100644 --- a/drivers/xen/xen-scsiback.c +++ b/drivers/xen/xen-scsiback.c @@ -849,15 +849,31 @@ static int scsiback_map(struct vscsibk_info *info) } /* + Check for a translation entry being present +*/ +static struct v2p_entry *scsiback_chk_translation_entry( + struct vscsibk_info *info, struct ids_tuple *v) +{ + struct list_head *head = &(info->v2p_entry_lists); + struct v2p_entry *entry; + + list_for_each_entry(entry, head, l) + if ((entry->v.chn == v->chn) && + (entry->v.tgt == v->tgt) && + (entry->v.lun == v->lun)) + return entry; + + return NULL; +} + +/* Add a new translation entry */ static int scsiback_add_translation_entry(struct vscsibk_info *info, char *phy, struct ids_tuple *v) { int err = 0; - struct v2p_entry *entry; struct v2p_entry *new; - struct list_head *head = &(info->v2p_entry_lists); unsigned long flags; char *lunp; unsigned long long unpacked_lun; @@ -917,15 +933,10 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info, spin_lock_irqsave(&info->v2p_lock, flags); /* Check double assignment to identical virtual ID */ - list_for_each_entry(entry, head, l) { - if ((entry->v.chn == v->chn) && - (entry->v.tgt == v->tgt) && - (entry->v.lun == v->lun)) { - pr_warn("Virtual ID is already used. Assignment was not performed.\n"); - err = -EEXIST; - goto out; - } - + if (scsiback_chk_translation_entry(info, v)) { + pr_warn("Virtual ID is already used. Assignment was not performed.\n"); + err = -EEXIST; + goto out; } /* Create a new translation entry and add to the list */ @@ -933,18 +944,18 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info, new->v = *v; new->tpg = tpg; new->lun = unpacked_lun; - list_add_tail(&new->l, head); + list_add_tail(&new->l, &info->v2p_entry_lists); out: spin_unlock_irqrestore(&info->v2p_lock, flags); out_free: - mutex_lock(&tpg->tv_tpg_mutex); - tpg->tv_tpg_fe_count--; - mutex_unlock(&tpg->tv_tpg_mutex); - - if (err) + if (err) { + mutex_lock(&tpg->tv_tpg_mutex); + tpg->tv_tpg_fe_count--; + mutex_unlock(&tpg->tv_tpg_mutex); kfree(new); + } return err; } @@ -956,39 +967,40 @@ static void __scsiback_del_translation_entry(struct v2p_entry *entry) } /* - Delete the translation entry specfied + Delete the translation entry specified */ static int scsiback_del_translation_entry(struct vscsibk_info *info, struct ids_tuple *v) { struct v2p_entry *entry; - struct list_head *head = &(info->v2p_entry_lists); unsigned long flags; + int ret = 0; spin_lock_irqsave(&info->v2p_lock, flags); /* Find out the translation entry specified */ - list_for_each_entry(entry, head, l) { - if ((entry->v.chn == v->chn) && - (entry->v.tgt == v->tgt) && - (entry->v.lun == v->lun)) { - goto found; - } - } - - spin_unlock_irqrestore(&info->v2p_lock, flags); - return 1; - -found: - /* Delete the translation entry specfied */ - __scsiback_del_translation_entry(entry); + entry = scsiback_chk_translation_entry(info, v); + if (entry) + __scsiback_del_translation_entry(entry); + else + ret = -ENOENT; spin_unlock_irqrestore(&info->v2p_lock, flags); - return 0; + return ret; } static void scsiback_do_add_lun(struct vscsibk_info *info, const char *state, char *phy, struct ids_tuple *vir, int try) { + struct v2p_entry *entry; + unsigned long flags; + + if (try) { + spin_lock_irqsave(&info->v2p_lock, flags); + entry = scsiback_chk_translation_entry(info, vir); + spin_unlock_irqrestore(&info->v2p_lock, flags); + if (entry) + return; + } if (!scsiback_add_translation_entry(info, phy, vir)) { if (xenbus_printf(XBT_NIL, info->dev->nodename, state, "%d", XenbusStateInitialised)) { diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c index 9433e46518c8..912b64edb42b 100644 --- a/drivers/xen/xenbus/xenbus_dev_frontend.c +++ b/drivers/xen/xenbus/xenbus_dev_frontend.c @@ -188,6 +188,8 @@ static int queue_reply(struct list_head *queue, const void *data, size_t len) if (len == 0) return 0; + if (len > XENSTORE_PAYLOAD_MAX) + return -EINVAL; rb = kmalloc(sizeof(*rb) + len, GFP_KERNEL); if (rb == NULL) diff --git a/fs/affs/file.c b/fs/affs/file.c index 0548c53f41d5..22fc7c802d69 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -511,8 +511,6 @@ affs_do_readpage_ofs(struct page *page, unsigned to) pr_debug("%s(%lu, %ld, 0, %d)\n", __func__, inode->i_ino, page->index, to); BUG_ON(to > PAGE_CACHE_SIZE); - kmap(page); - data = page_address(page); bsize = AFFS_SB(sb)->s_data_blksize; tmp = page->index << PAGE_CACHE_SHIFT; bidx = tmp / bsize; @@ -524,14 +522,15 @@ affs_do_readpage_ofs(struct page *page, unsigned to) return PTR_ERR(bh); tmp = min(bsize - boff, to - pos); BUG_ON(pos + tmp > to || tmp > bsize); + data = kmap_atomic(page); memcpy(data + pos, AFFS_DATA(bh) + boff, tmp); + kunmap_atomic(data); affs_brelse(bh); bidx++; pos += tmp; boff = 0; } flush_dcache_page(page); - kunmap(page); return 0; } diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 051ea4809c14..7d914c67a9d0 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -653,7 +653,7 @@ static unsigned long randomize_stack_top(unsigned long stack_top) if ((current->flags & PF_RANDOMIZE) && !(current->personality & ADDR_NO_RANDOMIZE)) { - random_variable = (unsigned long) get_random_int(); + random_variable = get_random_long(); random_variable &= STACK_RND_MASK; random_variable <<= PAGE_SHIFT; } diff --git a/fs/block_dev.c b/fs/block_dev.c index 39b3a174a425..826b164a4b5b 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1201,7 +1201,11 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) bdev->bd_disk = disk; bdev->bd_queue = disk->queue; bdev->bd_contains = bdev; - bdev->bd_inode->i_flags = disk->fops->direct_access ? S_DAX : 0; + if (IS_ENABLED(CONFIG_BLK_DEV_DAX) && disk->fops->direct_access) + bdev->bd_inode->i_flags = S_DAX; + else + bdev->bd_inode->i_flags = 0; + if (!partno) { ret = -ENXIO; bdev->bd_part = disk_get_part(disk, partno); @@ -1693,13 +1697,24 @@ static int blkdev_releasepage(struct page *page, gfp_t wait) return try_to_free_buffers(page); } +static int blkdev_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + if (dax_mapping(mapping)) { + struct block_device *bdev = I_BDEV(mapping->host); + + return dax_writeback_mapping_range(mapping, bdev, wbc); + } + return generic_writepages(mapping, wbc); +} + static const struct address_space_operations def_blk_aops = { .readpage = blkdev_readpage, .readpages = blkdev_readpages, .writepage = blkdev_writepage, .write_begin = blkdev_write_begin, .write_end = blkdev_write_end, - .writepages = generic_writepages, + .writepages = blkdev_writepages, .releasepage = blkdev_releasepage, .direct_IO = blkdev_direct_IO, .is_dirty_writeback = buffer_check_dirty_writeback, diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 151b7c71b868..d96f5cf38a2d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7986,6 +7986,7 @@ static void btrfs_endio_direct_read(struct bio *bio) kfree(dip); + dio_bio->bi_error = bio->bi_error; dio_end_io(dio_bio, bio->bi_error); if (io_bio->end_io) @@ -8040,6 +8041,7 @@ static void btrfs_endio_direct_write(struct bio *bio) kfree(dip); + dio_bio->bi_error = bio->bi_error; dio_end_io(dio_bio, bio->bi_error); bio_put(bio); } diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 7cf8509deda7..2c849b08a91b 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c @@ -310,8 +310,16 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root) set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state); err = btrfs_insert_fs_root(root->fs_info, root); + /* + * The root might have been inserted already, as before we look + * for orphan roots, log replay might have happened, which + * triggers a transaction commit and qgroup accounting, which + * in turn reads and inserts fs roots while doing backref + * walking. + */ + if (err == -EEXIST) + err = 0; if (err) { - BUG_ON(err == -EEXIST); btrfs_free_fs_root(root); break; } diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index c22213789090..19adeb0ef82a 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -1756,6 +1756,10 @@ int ceph_pool_perm_check(struct ceph_inode_info *ci, int need) u32 pool; int ret, flags; + /* does not support pool namespace yet */ + if (ci->i_pool_ns_len) + return -EIO; + if (ceph_test_mount_opt(ceph_inode_to_client(&ci->vfs_inode), NOPOOLPERM)) return 0; diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index cdbf8cf3d52c..6fe0ad26a7df 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -2753,7 +2753,8 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc, void *inline_data, int inline_len, struct ceph_buffer *xattr_buf, struct ceph_mds_session *session, - struct ceph_cap *cap, int issued) + struct ceph_cap *cap, int issued, + u32 pool_ns_len) __releases(ci->i_ceph_lock) __releases(mdsc->snap_rwsem) { @@ -2873,6 +2874,8 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc, if (newcaps & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR)) { /* file layout may have changed */ ci->i_layout = grant->layout; + ci->i_pool_ns_len = pool_ns_len; + /* size/truncate_seq? */ queue_trunc = ceph_fill_file_size(inode, issued, le32_to_cpu(grant->truncate_seq), @@ -3411,6 +3414,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, u32 inline_len = 0; void *snaptrace; size_t snaptrace_len; + u32 pool_ns_len = 0; void *p, *end; dout("handle_caps from mds%d\n", mds); @@ -3463,6 +3467,21 @@ void ceph_handle_caps(struct ceph_mds_session *session, p += inline_len; } + if (le16_to_cpu(msg->hdr.version) >= 8) { + u64 flush_tid; + u32 caller_uid, caller_gid; + u32 osd_epoch_barrier; + /* version >= 5 */ + ceph_decode_32_safe(&p, end, osd_epoch_barrier, bad); + /* version >= 6 */ + ceph_decode_64_safe(&p, end, flush_tid, bad); + /* version >= 7 */ + ceph_decode_32_safe(&p, end, caller_uid, bad); + ceph_decode_32_safe(&p, end, caller_gid, bad); + /* version >= 8 */ + ceph_decode_32_safe(&p, end, pool_ns_len, bad); + } + /* lookup ino */ inode = ceph_find_inode(sb, vino); ci = ceph_inode(inode); @@ -3518,7 +3537,8 @@ void ceph_handle_caps(struct ceph_mds_session *session, &cap, &issued); handle_cap_grant(mdsc, inode, h, inline_version, inline_data, inline_len, - msg->middle, session, cap, issued); + msg->middle, session, cap, issued, + pool_ns_len); if (realm) ceph_put_snap_realm(mdsc, realm); goto done_unlocked; @@ -3542,7 +3562,8 @@ void ceph_handle_caps(struct ceph_mds_session *session, issued |= __ceph_caps_dirty(ci); handle_cap_grant(mdsc, inode, h, inline_version, inline_data, inline_len, - msg->middle, session, cap, issued); + msg->middle, session, cap, issued, + pool_ns_len); goto done_unlocked; case CEPH_CAP_OP_FLUSH_ACK: diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index fb4ba2e4e2a5..5849b88bbed3 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -396,6 +396,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb) ci->i_symlink = NULL; memset(&ci->i_dir_layout, 0, sizeof(ci->i_dir_layout)); + ci->i_pool_ns_len = 0; ci->i_fragtree = RB_ROOT; mutex_init(&ci->i_fragtree_mutex); @@ -756,6 +757,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page, if (ci->i_layout.fl_pg_pool != info->layout.fl_pg_pool) ci->i_ceph_flags &= ~CEPH_I_POOL_PERM; ci->i_layout = info->layout; + ci->i_pool_ns_len = iinfo->pool_ns_len; queue_trunc = ceph_fill_file_size(inode, issued, le32_to_cpu(info->truncate_seq), diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index e7b130a637f9..911d64d865f1 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -100,6 +100,14 @@ static int parse_reply_info_in(void **p, void *end, } else info->inline_version = CEPH_INLINE_NONE; + if (features & CEPH_FEATURE_FS_FILE_LAYOUT_V2) { + ceph_decode_32_safe(p, end, info->pool_ns_len, bad); + ceph_decode_need(p, end, info->pool_ns_len, bad); + *p += info->pool_ns_len; + } else { + info->pool_ns_len = 0; + } + return 0; bad: return err; @@ -2298,6 +2306,14 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc, ceph_get_cap_refs(ceph_inode(req->r_old_dentry_dir), CEPH_CAP_PIN); + /* deny access to directories with pool_ns layouts */ + if (req->r_inode && S_ISDIR(req->r_inode->i_mode) && + ceph_inode(req->r_inode)->i_pool_ns_len) + return -EIO; + if (req->r_locked_dir && + ceph_inode(req->r_locked_dir)->i_pool_ns_len) + return -EIO; + /* issue */ mutex_lock(&mdsc->mutex); __register_request(mdsc, req, dir); diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index ccf11ef0ca87..37712ccffcc6 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -44,6 +44,7 @@ struct ceph_mds_reply_info_in { u64 inline_version; u32 inline_len; char *inline_data; + u32 pool_ns_len; }; /* diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 75b7d125ce66..9c458eb52245 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -287,6 +287,7 @@ struct ceph_inode_info { struct ceph_dir_layout i_dir_layout; struct ceph_file_layout i_layout; + size_t i_pool_ns_len; char *i_symlink; /* for dirs */ diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 7dc886c9a78f..e956cba94338 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -175,7 +175,7 @@ char *cifs_compose_mount_options(const char *sb_mountdata, * string to the length of the original string to allow for worst case. */ md_len = strlen(sb_mountdata) + INET6_ADDRSTRLEN; - mountdata = kzalloc(md_len + 1, GFP_KERNEL); + mountdata = kzalloc(md_len + sizeof("ip=") + 1, GFP_KERNEL); if (mountdata == NULL) { rc = -ENOMEM; goto compose_mount_options_err; diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index afa09fce8151..e682b36a210f 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -714,7 +714,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL); if (!ses->auth_key.response) { - rc = ENOMEM; + rc = -ENOMEM; ses->auth_key.len = 0; goto setup_ntlmv2_rsp_ret; } diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index c48ca13673e3..2eea40353e60 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -1013,7 +1013,6 @@ const struct file_operations cifs_file_strict_ops = { .llseek = cifs_llseek, .unlocked_ioctl = cifs_ioctl, .clone_file_range = cifs_clone_file_range, - .clone_file_range = cifs_clone_file_range, .setlease = cifs_setlease, .fallocate = cifs_fallocate, }; diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 68c4547528c4..83aac8ba50b0 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -31,19 +31,15 @@ * so that it will fit. We use hash_64 to convert the value to 31 bits, and * then add 1, to ensure that we don't end up with a 0 as the value. */ -#if BITS_PER_LONG == 64 static inline ino_t cifs_uniqueid_to_ino_t(u64 fileid) { + if ((sizeof(ino_t)) < (sizeof(u64))) + return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1; + return (ino_t)fileid; + } -#else -static inline ino_t -cifs_uniqueid_to_ino_t(u64 fileid) -{ - return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1; -} -#endif extern struct file_system_type cifs_fs_type; extern const struct address_space_operations cifs_addr_ops; diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 90b4f9f7de66..76fcb50295a3 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1396,11 +1396,10 @@ openRetry: * current bigbuf. */ static int -cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) +discard_remaining_data(struct TCP_Server_Info *server) { unsigned int rfclen = get_rfc1002_length(server->smallbuf); int remaining = rfclen + 4 - server->total_read; - struct cifs_readdata *rdata = mid->callback_data; while (remaining > 0) { int length; @@ -1414,10 +1413,20 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) remaining -= length; } - dequeue_mid(mid, rdata->result); return 0; } +static int +cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) +{ + int length; + struct cifs_readdata *rdata = mid->callback_data; + + length = discard_remaining_data(server); + dequeue_mid(mid, rdata->result); + return length; +} + int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) { @@ -1446,6 +1455,12 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) return length; server->total_read += length; + if (server->ops->is_status_pending && + server->ops->is_status_pending(buf, server, 0)) { + discard_remaining_data(server); + return -1; + } + /* Was the SMB read successful? */ rdata->result = server->ops->map_error(buf, false); if (rdata->result != 0) { diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 4fbd92d2e113..a763cd3d9e7c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2999,8 +2999,7 @@ ip_rfc1001_connect(struct TCP_Server_Info *server) if (ses_init_buf) { ses_init_buf->trailer.session_req.called_len = 32; - if (server->server_RFC1001_name && - server->server_RFC1001_name[0] != 0) + if (server->server_RFC1001_name[0] != 0) rfc1002mangle(ses_init_buf->trailer. session_req.called_name, server->server_RFC1001_name, diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 10f8d5cf5681..42e1f440eb1e 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -1106,21 +1106,25 @@ parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp, { char *data_offset; struct create_context *cc; - unsigned int next = 0; + unsigned int next; + unsigned int remaining; char *name; data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset); + remaining = le32_to_cpu(rsp->CreateContextsLength); cc = (struct create_context *)data_offset; - do { - cc = (struct create_context *)((char *)cc + next); + while (remaining >= sizeof(struct create_context)) { name = le16_to_cpu(cc->NameOffset) + (char *)cc; - if (le16_to_cpu(cc->NameLength) != 4 || - strncmp(name, "RqLs", 4)) { - next = le32_to_cpu(cc->Next); - continue; - } - return server->ops->parse_lease_buf(cc, epoch); - } while (next != 0); + if (le16_to_cpu(cc->NameLength) == 4 && + strncmp(name, "RqLs", 4) == 0) + return server->ops->parse_lease_buf(cc, epoch); + + next = le32_to_cpu(cc->Next); + if (!next) + break; + remaining -= next; + cc = (struct create_context *)((char *)cc + next); + } return 0; } @@ -79,15 +79,14 @@ struct page *read_dax_sector(struct block_device *bdev, sector_t n) } /* - * dax_clear_blocks() is called from within transaction context from XFS, + * dax_clear_sectors() is called from within transaction context from XFS, * and hence this means the stack from this point must follow GFP_NOFS * semantics for all operations. */ -int dax_clear_blocks(struct inode *inode, sector_t block, long _size) +int dax_clear_sectors(struct block_device *bdev, sector_t _sector, long _size) { - struct block_device *bdev = inode->i_sb->s_bdev; struct blk_dax_ctl dax = { - .sector = block << (inode->i_blkbits - 9), + .sector = _sector, .size = _size, }; @@ -109,7 +108,7 @@ int dax_clear_blocks(struct inode *inode, sector_t block, long _size) wmb_pmem(); return 0; } -EXPORT_SYMBOL_GPL(dax_clear_blocks); +EXPORT_SYMBOL_GPL(dax_clear_sectors); /* the clear_pmem() calls are ordered by a wmb_pmem() in the caller */ static void dax_new_buf(void __pmem *addr, unsigned size, unsigned first, @@ -485,11 +484,10 @@ static int dax_writeback_one(struct block_device *bdev, * end]. This is required by data integrity operations to ensure file data is * on persistent storage prior to completion of the operation. */ -int dax_writeback_mapping_range(struct address_space *mapping, loff_t start, - loff_t end) +int dax_writeback_mapping_range(struct address_space *mapping, + struct block_device *bdev, struct writeback_control *wbc) { struct inode *inode = mapping->host; - struct block_device *bdev = inode->i_sb->s_bdev; pgoff_t start_index, end_index, pmd_index; pgoff_t indices[PAGEVEC_SIZE]; struct pagevec pvec; @@ -500,8 +498,11 @@ int dax_writeback_mapping_range(struct address_space *mapping, loff_t start, if (WARN_ON_ONCE(inode->i_blkbits != PAGE_SHIFT)) return -EIO; - start_index = start >> PAGE_CACHE_SHIFT; - end_index = end >> PAGE_CACHE_SHIFT; + if (!mapping->nrexceptional || wbc->sync_mode != WB_SYNC_ALL) + return 0; + + start_index = wbc->range_start >> PAGE_CACHE_SHIFT; + end_index = wbc->range_end >> PAGE_CACHE_SHIFT; pmd_index = DAX_PMD_INDEX(start_index); rcu_read_lock(); diff --git a/fs/dcache.c b/fs/dcache.c index 92d5140de851..2398f9f94337 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -269,9 +269,6 @@ static inline int dname_external(const struct dentry *dentry) return dentry->d_name.name != dentry->d_iname; } -/* - * Make sure other CPUs see the inode attached before the type is set. - */ static inline void __d_set_inode_and_type(struct dentry *dentry, struct inode *inode, unsigned type_flags) @@ -279,28 +276,18 @@ static inline void __d_set_inode_and_type(struct dentry *dentry, unsigned flags; dentry->d_inode = inode; - smp_wmb(); flags = READ_ONCE(dentry->d_flags); flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU); flags |= type_flags; WRITE_ONCE(dentry->d_flags, flags); } -/* - * Ideally, we want to make sure that other CPUs see the flags cleared before - * the inode is detached, but this is really a violation of RCU principles - * since the ordering suggests we should always set inode before flags. - * - * We should instead replace or discard the entire dentry - but that sucks - * performancewise on mass deletion/rename. - */ static inline void __d_clear_type_and_inode(struct dentry *dentry) { unsigned flags = READ_ONCE(dentry->d_flags); flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU); WRITE_ONCE(dentry->d_flags, flags); - smp_wmb(); dentry->d_inode = NULL; } @@ -370,9 +357,11 @@ static void dentry_unlink_inode(struct dentry * dentry) __releases(dentry->d_inode->i_lock) { struct inode *inode = dentry->d_inode; + + raw_write_seqcount_begin(&dentry->d_seq); __d_clear_type_and_inode(dentry); hlist_del_init(&dentry->d_u.d_alias); - dentry_rcuwalk_invalidate(dentry); + raw_write_seqcount_end(&dentry->d_seq); spin_unlock(&dentry->d_lock); spin_unlock(&inode->i_lock); if (!inode->i_nlink) @@ -1758,8 +1747,9 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode) spin_lock(&dentry->d_lock); if (inode) hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry); + raw_write_seqcount_begin(&dentry->d_seq); __d_set_inode_and_type(dentry, inode, add_flags); - dentry_rcuwalk_invalidate(dentry); + raw_write_seqcount_end(&dentry->d_seq); spin_unlock(&dentry->d_lock); fsnotify_d_instantiate(dentry, inode); } diff --git a/fs/direct-io.c b/fs/direct-io.c index 1b2f7ffc8b84..d6a9012d42ad 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -472,8 +472,8 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio) dio->io_error = -EIO; if (dio->is_async && dio->rw == READ && dio->should_dirty) { - bio_check_pages_dirty(bio); /* transfers ownership */ err = bio->bi_error; + bio_check_pages_dirty(bio); /* transfers ownership */ } else { bio_for_each_segment_all(bvec, bio, i) { struct page *page = bvec->bv_page; diff --git a/fs/ext2/file.c b/fs/ext2/file.c index 2c88d683cd91..c1400b109805 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c @@ -80,23 +80,6 @@ static int ext2_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr, return ret; } -static int ext2_dax_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - struct inode *inode = file_inode(vma->vm_file); - struct ext2_inode_info *ei = EXT2_I(inode); - int ret; - - sb_start_pagefault(inode->i_sb); - file_update_time(vma->vm_file); - down_read(&ei->dax_sem); - - ret = __dax_mkwrite(vma, vmf, ext2_get_block, NULL); - - up_read(&ei->dax_sem); - sb_end_pagefault(inode->i_sb); - return ret; -} - static int ext2_dax_pfn_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) { @@ -124,7 +107,7 @@ static int ext2_dax_pfn_mkwrite(struct vm_area_struct *vma, static const struct vm_operations_struct ext2_dax_vm_ops = { .fault = ext2_dax_fault, .pmd_fault = ext2_dax_pmd_fault, - .page_mkwrite = ext2_dax_mkwrite, + .page_mkwrite = ext2_dax_fault, .pfn_mkwrite = ext2_dax_pfn_mkwrite, }; diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 338eefda70c6..6bd58e6ff038 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -737,8 +737,10 @@ static int ext2_get_blocks(struct inode *inode, * so that it's not found by another thread before it's * initialised */ - err = dax_clear_blocks(inode, le32_to_cpu(chain[depth-1].key), - 1 << inode->i_blkbits); + err = dax_clear_sectors(inode->i_sb->s_bdev, + le32_to_cpu(chain[depth-1].key) << + (inode->i_blkbits - 9), + 1 << inode->i_blkbits); if (err) { mutex_unlock(&ei->truncate_mutex); goto cleanup; @@ -874,6 +876,14 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset) static int ext2_writepages(struct address_space *mapping, struct writeback_control *wbc) { +#ifdef CONFIG_FS_DAX + if (dax_mapping(mapping)) { + return dax_writeback_mapping_range(mapping, + mapping->host->i_sb->s_bdev, + wbc); + } +#endif + return mpage_writepages(mapping, wbc, ext2_get_block); } @@ -1296,7 +1306,7 @@ void ext2_set_inode_flags(struct inode *inode) inode->i_flags |= S_NOATIME; if (flags & EXT2_DIRSYNC_FL) inode->i_flags |= S_DIRSYNC; - if (test_opt(inode->i_sb, DAX)) + if (test_opt(inode->i_sb, DAX) && S_ISREG(inode->i_mode)) inode->i_flags |= S_DAX; } diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index ec0668a60678..fe1f50fe764f 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -191,7 +191,6 @@ static int ext4_init_block_bitmap(struct super_block *sb, /* If checksum is bad mark all blocks used to prevent allocation * essentially implementing a per-group read-only flag. */ if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) { - ext4_error(sb, "Checksum bad for group %u", block_group); grp = ext4_get_group_info(sb, block_group); if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) percpu_counter_sub(&sbi->s_freeclusters_counter, @@ -442,14 +441,16 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) } ext4_lock_group(sb, block_group); if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { - err = ext4_init_block_bitmap(sb, bh, block_group, desc); set_bitmap_uptodate(bh); set_buffer_uptodate(bh); ext4_unlock_group(sb, block_group); unlock_buffer(bh); - if (err) + if (err) { + ext4_error(sb, "Failed to init block bitmap for group " + "%u: %d", block_group, err); goto out; + } goto verify; } ext4_unlock_group(sb, block_group); diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c index c8021208a7eb..38f7562489bb 100644 --- a/fs/ext4/crypto.c +++ b/fs/ext4/crypto.c @@ -467,3 +467,59 @@ uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size) return size; return 0; } + +/* + * Validate dentries for encrypted directories to make sure we aren't + * potentially caching stale data after a key has been added or + * removed. + */ +static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags) +{ + struct inode *dir = d_inode(dentry->d_parent); + struct ext4_crypt_info *ci = EXT4_I(dir)->i_crypt_info; + int dir_has_key, cached_with_key; + + if (!ext4_encrypted_inode(dir)) + return 0; + + if (ci && ci->ci_keyring_key && + (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) | + (1 << KEY_FLAG_REVOKED) | + (1 << KEY_FLAG_DEAD)))) + ci = NULL; + + /* this should eventually be an flag in d_flags */ + cached_with_key = dentry->d_fsdata != NULL; + dir_has_key = (ci != NULL); + + /* + * If the dentry was cached without the key, and it is a + * negative dentry, it might be a valid name. We can't check + * if the key has since been made available due to locking + * reasons, so we fail the validation so ext4_lookup() can do + * this check. + * + * We also fail the validation if the dentry was created with + * the key present, but we no longer have the key, or vice versa. + */ + if ((!cached_with_key && d_is_negative(dentry)) || + (!cached_with_key && dir_has_key) || + (cached_with_key && !dir_has_key)) { +#if 0 /* Revalidation debug */ + char buf[80]; + char *cp = simple_dname(dentry, buf, sizeof(buf)); + + if (IS_ERR(cp)) + cp = (char *) "???"; + pr_err("revalidate: %s %p %d %d %d\n", cp, dentry->d_fsdata, + cached_with_key, d_is_negative(dentry), + dir_has_key); +#endif + return 0; + } + return 1; +} + +const struct dentry_operations ext4_encrypted_d_ops = { + .d_revalidate = ext4_d_revalidate, +}; diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index 1d1bca74f844..33f5e2a50cf8 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c @@ -111,6 +111,12 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx) int dir_has_error = 0; struct ext4_str fname_crypto_str = {.name = NULL, .len = 0}; + if (ext4_encrypted_inode(inode)) { + err = ext4_get_encryption_info(inode); + if (err && err != -ENOKEY) + return err; + } + if (is_dx_dir(inode)) { err = ext4_dx_readdir(file, ctx); if (err != ERR_BAD_DX_DIR) { @@ -157,8 +163,11 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx) index, 1); file->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT; bh = ext4_bread(NULL, inode, map.m_lblk, 0); - if (IS_ERR(bh)) - return PTR_ERR(bh); + if (IS_ERR(bh)) { + err = PTR_ERR(bh); + bh = NULL; + goto errout; + } } if (!bh) { diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 0662b285dc8a..157b458a69d4 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2302,6 +2302,7 @@ struct page *ext4_encrypt(struct inode *inode, int ext4_decrypt(struct page *page); int ext4_encrypted_zeroout(struct inode *inode, ext4_lblk_t lblk, ext4_fsblk_t pblk, ext4_lblk_t len); +extern const struct dentry_operations ext4_encrypted_d_ops; #ifdef CONFIG_EXT4_FS_ENCRYPTION int ext4_init_crypto(void); diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 0ffabaf90aa5..3753ceb0b0dd 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3928,7 +3928,7 @@ static int convert_initialized_extent(handle_t *handle, struct inode *inode, struct ext4_map_blocks *map, struct ext4_ext_path **ppath, int flags, - unsigned int allocated, ext4_fsblk_t newblock) + unsigned int allocated) { struct ext4_ext_path *path = *ppath; struct ext4_extent *ex; @@ -4347,7 +4347,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN)) { allocated = convert_initialized_extent( handle, inode, map, &path, - flags, allocated, newblock); + flags, allocated); goto out2; } else if (!ext4_ext_is_unwritten(ex)) goto out; diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 1126436dada1..4cd318f31cbe 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -262,23 +262,8 @@ static int ext4_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr, return result; } -static int ext4_dax_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - int err; - struct inode *inode = file_inode(vma->vm_file); - - sb_start_pagefault(inode->i_sb); - file_update_time(vma->vm_file); - down_read(&EXT4_I(inode)->i_mmap_sem); - err = __dax_mkwrite(vma, vmf, ext4_dax_mmap_get_block, NULL); - up_read(&EXT4_I(inode)->i_mmap_sem); - sb_end_pagefault(inode->i_sb); - - return err; -} - /* - * Handle write fault for VM_MIXEDMAP mappings. Similarly to ext4_dax_mkwrite() + * Handle write fault for VM_MIXEDMAP mappings. Similarly to ext4_dax_fault() * handler we check for races agaist truncate. Note that since we cycle through * i_mmap_sem, we are sure that also any hole punching that began before we * were called is finished by now and so if it included part of the file we @@ -311,7 +296,7 @@ static int ext4_dax_pfn_mkwrite(struct vm_area_struct *vma, static const struct vm_operations_struct ext4_dax_vm_ops = { .fault = ext4_dax_fault, .pmd_fault = ext4_dax_pmd_fault, - .page_mkwrite = ext4_dax_mkwrite, + .page_mkwrite = ext4_dax_fault, .pfn_mkwrite = ext4_dax_pfn_mkwrite, }; #else @@ -350,6 +335,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp) struct super_block *sb = inode->i_sb; struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); struct vfsmount *mnt = filp->f_path.mnt; + struct inode *dir = filp->f_path.dentry->d_parent->d_inode; struct path path; char buf[64], *cp; int ret; @@ -393,6 +379,14 @@ static int ext4_file_open(struct inode * inode, struct file * filp) if (ext4_encryption_info(inode) == NULL) return -ENOKEY; } + if (ext4_encrypted_inode(dir) && + !ext4_is_child_context_consistent_with_parent(dir, inode)) { + ext4_warning(inode->i_sb, + "Inconsistent encryption contexts: %lu/%lu\n", + (unsigned long) dir->i_ino, + (unsigned long) inode->i_ino); + return -EPERM; + } /* * Set up the jbd2_inode if we are opening the inode for * writing and the journal is present diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 3fcfd50a2e8a..acc0ad56bf2f 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -76,7 +76,6 @@ static int ext4_init_inode_bitmap(struct super_block *sb, /* If checksum is bad mark all blocks and inodes use to prevent * allocation, essentially implementing a per-group read-only flag. */ if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) { - ext4_error(sb, "Checksum bad for group %u", block_group); grp = ext4_get_group_info(sb, block_group); if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) percpu_counter_sub(&sbi->s_freeclusters_counter, @@ -191,8 +190,11 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) set_buffer_verified(bh); ext4_unlock_group(sb, block_group); unlock_buffer(bh); - if (err) + if (err) { + ext4_error(sb, "Failed to init inode bitmap for group " + "%u: %d", block_group, err); goto out; + } return bh; } ext4_unlock_group(sb, block_group); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 83bc8bfb3bea..aee960b1af34 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -686,6 +686,34 @@ out_sem: return retval; } +/* + * Update EXT4_MAP_FLAGS in bh->b_state. For buffer heads attached to pages + * we have to be careful as someone else may be manipulating b_state as well. + */ +static void ext4_update_bh_state(struct buffer_head *bh, unsigned long flags) +{ + unsigned long old_state; + unsigned long new_state; + + flags &= EXT4_MAP_FLAGS; + + /* Dummy buffer_head? Set non-atomically. */ + if (!bh->b_page) { + bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | flags; + return; + } + /* + * Someone else may be modifying b_state. Be careful! This is ugly but + * once we get rid of using bh as a container for mapping information + * to pass to / from get_block functions, this can go away. + */ + do { + old_state = READ_ONCE(bh->b_state); + new_state = (old_state & ~EXT4_MAP_FLAGS) | flags; + } while (unlikely( + cmpxchg(&bh->b_state, old_state, new_state) != old_state)); +} + /* Maximum number of blocks we map for direct IO at once. */ #define DIO_MAX_BLOCKS 4096 @@ -722,7 +750,7 @@ static int _ext4_get_block(struct inode *inode, sector_t iblock, ext4_io_end_t *io_end = ext4_inode_aio(inode); map_bh(bh, inode->i_sb, map.m_pblk); - bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags; + ext4_update_bh_state(bh, map.m_flags); if (io_end && io_end->flag & EXT4_IO_END_UNWRITTEN) set_buffer_defer_completion(bh); bh->b_size = inode->i_sb->s_blocksize * map.m_len; @@ -1685,7 +1713,7 @@ int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, return ret; map_bh(bh, inode->i_sb, map.m_pblk); - bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags; + ext4_update_bh_state(bh, map.m_flags); if (buffer_unwritten(bh)) { /* A delayed write to unwritten bh should be marked @@ -2450,6 +2478,10 @@ static int ext4_writepages(struct address_space *mapping, trace_ext4_writepages(inode, wbc); + if (dax_mapping(mapping)) + return dax_writeback_mapping_range(mapping, inode->i_sb->s_bdev, + wbc); + /* * No pages to write? This is mainly a kludge to avoid starting * a transaction for special inodes like journal inode on last iput() @@ -3253,29 +3285,29 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter, * case, we allocate an io_end structure to hook to the iocb. */ iocb->private = NULL; - ext4_inode_aio_set(inode, NULL); - if (!is_sync_kiocb(iocb)) { - io_end = ext4_init_io_end(inode, GFP_NOFS); - if (!io_end) { - ret = -ENOMEM; - goto retake_lock; - } - /* - * Grab reference for DIO. Will be dropped in ext4_end_io_dio() - */ - iocb->private = ext4_get_io_end(io_end); - /* - * we save the io structure for current async direct - * IO, so that later ext4_map_blocks() could flag the - * io structure whether there is a unwritten extents - * needs to be converted when IO is completed. - */ - ext4_inode_aio_set(inode, io_end); - } - if (overwrite) { get_block_func = ext4_get_block_overwrite; } else { + ext4_inode_aio_set(inode, NULL); + if (!is_sync_kiocb(iocb)) { + io_end = ext4_init_io_end(inode, GFP_NOFS); + if (!io_end) { + ret = -ENOMEM; + goto retake_lock; + } + /* + * Grab reference for DIO. Will be dropped in + * ext4_end_io_dio() + */ + iocb->private = ext4_get_io_end(io_end); + /* + * we save the io structure for current async direct + * IO, so that later ext4_map_blocks() could flag the + * io structure whether there is a unwritten extents + * needs to be converted when IO is completed. + */ + ext4_inode_aio_set(inode, io_end); + } get_block_func = ext4_get_block_write; dio_flags = DIO_LOCKING; } @@ -4127,7 +4159,7 @@ void ext4_set_inode_flags(struct inode *inode) new_fl |= S_NOATIME; if (flags & EXT4_DIRSYNC_FL) new_fl |= S_DIRSYNC; - if (test_opt(inode->i_sb, DAX)) + if (test_opt(inode->i_sb, DAX) && S_ISREG(inode->i_mode)) new_fl |= S_DAX; inode_set_flags(inode, new_fl, S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_DAX); diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 0f6c36922c24..eae5917c534e 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -208,7 +208,7 @@ static int ext4_ioctl_setflags(struct inode *inode, { struct ext4_inode_info *ei = EXT4_I(inode); handle_t *handle = NULL; - int err = EPERM, migrate = 0; + int err = -EPERM, migrate = 0; struct ext4_iloc iloc; unsigned int oldflags, mask, i; unsigned int jflag; @@ -583,6 +583,11 @@ group_extend_out: "Online defrag not supported with bigalloc"); err = -EOPNOTSUPP; goto mext_out; + } else if (IS_DAX(inode)) { + ext4_msg(sb, KERN_ERR, + "Online defrag not supported with DAX"); + err = -EOPNOTSUPP; + goto mext_out; } err = mnt_want_write_file(filp); diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 61eaf74dca37..4424b7bf8ac6 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -2285,7 +2285,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v) if (group == 0) seq_puts(seq, "#group: free frags first [" " 2^0 2^1 2^2 2^3 2^4 2^5 2^6 " - " 2^7 2^8 2^9 2^10 2^11 2^12 2^13 ]"); + " 2^7 2^8 2^9 2^10 2^11 2^12 2^13 ]\n"); i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) + sizeof(struct ext4_group_info); diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index fb6f11709ae6..e032a0423e35 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -265,11 +265,12 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, ext4_lblk_t orig_blk_offset, donor_blk_offset; unsigned long blocksize = orig_inode->i_sb->s_blocksize; unsigned int tmp_data_size, data_size, replaced_size; - int err2, jblocks, retries = 0; + int i, err2, jblocks, retries = 0; int replaced_count = 0; int from = data_offset_in_page << orig_inode->i_blkbits; int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits; struct super_block *sb = orig_inode->i_sb; + struct buffer_head *bh = NULL; /* * It needs twice the amount of ordinary journal buffers because @@ -380,8 +381,16 @@ data_copy: } /* Perform all necessary steps similar write_begin()/write_end() * but keeping in mind that i_size will not change */ - *err = __block_write_begin(pagep[0], from, replaced_size, - ext4_get_block); + if (!page_has_buffers(pagep[0])) + create_empty_buffers(pagep[0], 1 << orig_inode->i_blkbits, 0); + bh = page_buffers(pagep[0]); + for (i = 0; i < data_offset_in_page; i++) + bh = bh->b_this_page; + for (i = 0; i < block_len_in_page; i++) { + *err = ext4_get_block(orig_inode, orig_blk_offset + i, bh, 0); + if (*err < 0) + break; + } if (!*err) *err = block_commit_write(pagep[0], from, from + replaced_size); diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 06574dd77614..48e4b8907826 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1558,6 +1558,24 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi struct ext4_dir_entry_2 *de; struct buffer_head *bh; + if (ext4_encrypted_inode(dir)) { + int res = ext4_get_encryption_info(dir); + + /* + * This should be a properly defined flag for + * dentry->d_flags when we uplift this to the VFS. + * d_fsdata is set to (void *) 1 if if the dentry is + * created while the directory was encrypted and we + * don't have access to the key. + */ + dentry->d_fsdata = NULL; + if (ext4_encryption_info(dir)) + dentry->d_fsdata = (void *) 1; + d_set_d_op(dentry, &ext4_encrypted_d_ops); + if (res && res != -ENOKEY) + return ERR_PTR(res); + } + if (dentry->d_name.len > EXT4_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); @@ -1585,11 +1603,15 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi return ERR_PTR(-EFSCORRUPTED); } if (!IS_ERR(inode) && ext4_encrypted_inode(dir) && - (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode)) && + (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) && !ext4_is_child_context_consistent_with_parent(dir, inode)) { + int nokey = ext4_encrypted_inode(inode) && + !ext4_encryption_info(inode); + iput(inode); + if (nokey) + return ERR_PTR(-ENOKEY); ext4_warning(inode->i_sb, "Inconsistent encryption contexts: %lu/%lu\n", (unsigned long) dir->i_ino, diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index ad62d7acc315..34038e3598d5 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -198,7 +198,7 @@ static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned long flexbg_size) if (flex_gd == NULL) goto out3; - if (flexbg_size >= UINT_MAX / sizeof(struct ext4_new_flex_group_data)) + if (flexbg_size >= UINT_MAX / sizeof(struct ext4_new_group_data)) goto out2; flex_gd->count = flexbg_size; diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 6915c950e6e8..5c46ed9f3e14 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -223,6 +223,9 @@ static void wb_wait_for_completion(struct backing_dev_info *bdi, #define WB_FRN_HIST_MAX_SLOTS (WB_FRN_HIST_THR_SLOTS / 2 + 1) /* one round can affect upto 5 slots */ +static atomic_t isw_nr_in_flight = ATOMIC_INIT(0); +static struct workqueue_struct *isw_wq; + void __inode_attach_wb(struct inode *inode, struct page *page) { struct backing_dev_info *bdi = inode_to_bdi(inode); @@ -424,6 +427,8 @@ skip_switch: iput(inode); kfree(isw); + + atomic_dec(&isw_nr_in_flight); } static void inode_switch_wbs_rcu_fn(struct rcu_head *rcu_head) @@ -433,7 +438,7 @@ static void inode_switch_wbs_rcu_fn(struct rcu_head *rcu_head) /* needs to grab bh-unsafe locks, bounce to work item */ INIT_WORK(&isw->work, inode_switch_wbs_work_fn); - schedule_work(&isw->work); + queue_work(isw_wq, &isw->work); } /** @@ -469,7 +474,8 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id) /* while holding I_WB_SWITCH, no one else can update the association */ spin_lock(&inode->i_lock); - if (inode->i_state & (I_WB_SWITCH | I_FREEING) || + if (!(inode->i_sb->s_flags & MS_ACTIVE) || + inode->i_state & (I_WB_SWITCH | I_FREEING) || inode_to_wb(inode) == isw->new_wb) { spin_unlock(&inode->i_lock); goto out_free; @@ -480,6 +486,8 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id) ihold(inode); isw->inode = inode; + atomic_inc(&isw_nr_in_flight); + /* * In addition to synchronizing among switchers, I_WB_SWITCH tells * the RCU protected stat update paths to grab the mapping's @@ -840,6 +848,33 @@ restart: wb_put(last_wb); } +/** + * cgroup_writeback_umount - flush inode wb switches for umount + * + * This function is called when a super_block is about to be destroyed and + * flushes in-flight inode wb switches. An inode wb switch goes through + * RCU and then workqueue, so the two need to be flushed in order to ensure + * that all previously scheduled switches are finished. As wb switches are + * rare occurrences and synchronize_rcu() can take a while, perform + * flushing iff wb switches are in flight. + */ +void cgroup_writeback_umount(void) +{ + if (atomic_read(&isw_nr_in_flight)) { + synchronize_rcu(); + flush_workqueue(isw_wq); + } +} + +static int __init cgroup_writeback_init(void) +{ + isw_wq = alloc_workqueue("inode_switch_wbs", 0, 0); + if (!isw_wq) + return -ENOMEM; + return 0; +} +fs_initcall(cgroup_writeback_init); + #else /* CONFIG_CGROUP_WRITEBACK */ static struct bdi_writeback * diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index 506765afa1a3..bb8d67e2740a 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c @@ -376,12 +376,11 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry) struct inode *inode = d_inode(dentry); dnode_secno dno; int r; - int rep = 0; int err; hpfs_lock(dir->i_sb); hpfs_adjust_length(name, &len); -again: + err = -ENOENT; de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh); if (!de) @@ -401,33 +400,9 @@ again: hpfs_error(dir->i_sb, "there was error when removing dirent"); err = -EFSERROR; break; - case 2: /* no space for deleting, try to truncate file */ - + case 2: /* no space for deleting */ err = -ENOSPC; - if (rep++) - break; - - dentry_unhash(dentry); - if (!d_unhashed(dentry)) { - hpfs_unlock(dir->i_sb); - return -ENOSPC; - } - if (generic_permission(inode, MAY_WRITE) || - !S_ISREG(inode->i_mode) || - get_write_access(inode)) { - d_rehash(dentry); - } else { - struct iattr newattrs; - /*pr_info("truncating file before delete.\n");*/ - newattrs.ia_size = 0; - newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; - err = notify_change(dentry, &newattrs, NULL); - put_write_access(inode); - if (!err) - goto again; - } - hpfs_unlock(dir->i_sb); - return -ENOSPC; + break; default: drop_nlink(inode); err = 0; diff --git a/fs/inode.c b/fs/inode.c index 9f62db3bcc3e..69b8b526c194 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -154,6 +154,12 @@ int inode_init_always(struct super_block *sb, struct inode *inode) inode->i_rdev = 0; inode->dirtied_when = 0; +#ifdef CONFIG_CGROUP_WRITEBACK + inode->i_wb_frn_winner = 0; + inode->i_wb_frn_avg_time = 0; + inode->i_wb_frn_history = 0; +#endif + if (security_inode_alloc(inode)) goto out; spin_lock_init(&inode->i_lock); diff --git a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking index 3ea36554107f..8918ac905a3b 100644 --- a/fs/jffs2/README.Locking +++ b/fs/jffs2/README.Locking @@ -2,10 +2,6 @@ JFFS2 LOCKING DOCUMENTATION --------------------------- -At least theoretically, JFFS2 does not require the Big Kernel Lock -(BKL), which was always helpfully obtained for it by Linux 2.4 VFS -code. It has its own locking, as described below. - This document attempts to describe the existing locking rules for JFFS2. It is not expected to remain perfectly up to date, but ought to be fairly close. @@ -69,6 +65,7 @@ Ordering constraints: any f->sem held. 2. Never attempt to lock two file mutexes in one thread. No ordering rules have been made for doing so. + 3. Never lock a page cache page with f->sem held. erase_completion_lock spinlock diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index 0ae91ad6df2d..b288c8ae1236 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -50,7 +50,8 @@ next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c) static void jffs2_build_inode_pass1(struct jffs2_sb_info *c, - struct jffs2_inode_cache *ic) + struct jffs2_inode_cache *ic, + int *dir_hardlinks) { struct jffs2_full_dirent *fd; @@ -69,19 +70,21 @@ static void jffs2_build_inode_pass1(struct jffs2_sb_info *c, dbg_fsbuild("child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n", fd->name, fd->ino, ic->ino); jffs2_mark_node_obsolete(c, fd->raw); + /* Clear the ic/raw union so it doesn't cause problems later. */ + fd->ic = NULL; continue; } + /* From this point, fd->raw is no longer used so we can set fd->ic */ + fd->ic = child_ic; + child_ic->pino_nlink++; + /* If we appear (at this stage) to have hard-linked directories, + * set a flag to trigger a scan later */ if (fd->type == DT_DIR) { - if (child_ic->pino_nlink) { - JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", - fd->name, fd->ino, ic->ino); - /* TODO: What do we do about it? */ - } else { - child_ic->pino_nlink = ic->ino; - } - } else - child_ic->pino_nlink++; + child_ic->flags |= INO_FLAGS_IS_DIR; + if (child_ic->pino_nlink > 1) + *dir_hardlinks = 1; + } dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino); /* Can't free scan_dents so far. We might need them in pass 2 */ @@ -95,8 +98,7 @@ static void jffs2_build_inode_pass1(struct jffs2_sb_info *c, */ static int jffs2_build_filesystem(struct jffs2_sb_info *c) { - int ret; - int i; + int ret, i, dir_hardlinks = 0; struct jffs2_inode_cache *ic; struct jffs2_full_dirent *fd; struct jffs2_full_dirent *dead_fds = NULL; @@ -120,7 +122,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) /* Now scan the directory tree, increasing nlink according to every dirent found. */ for_each_inode(i, c, ic) { if (ic->scan_dents) { - jffs2_build_inode_pass1(c, ic); + jffs2_build_inode_pass1(c, ic, &dir_hardlinks); cond_resched(); } } @@ -156,6 +158,20 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) } dbg_fsbuild("pass 2a complete\n"); + + if (dir_hardlinks) { + /* If we detected directory hardlinks earlier, *hopefully* + * they are gone now because some of the links were from + * dead directories which still had some old dirents lying + * around and not yet garbage-collected, but which have + * been discarded above. So clear the pino_nlink field + * in each directory, so that the final scan below can + * print appropriate warnings. */ + for_each_inode(i, c, ic) { + if (ic->flags & INO_FLAGS_IS_DIR) + ic->pino_nlink = 0; + } + } dbg_fsbuild("freeing temporary data structures\n"); /* Finally, we can scan again and free the dirent structs */ @@ -163,6 +179,33 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) while(ic->scan_dents) { fd = ic->scan_dents; ic->scan_dents = fd->next; + /* We do use the pino_nlink field to count nlink of + * directories during fs build, so set it to the + * parent ino# now. Now that there's hopefully only + * one. */ + if (fd->type == DT_DIR) { + if (!fd->ic) { + /* We'll have complained about it and marked the coresponding + raw node obsolete already. Just skip it. */ + continue; + } + + /* We *have* to have set this in jffs2_build_inode_pass1() */ + BUG_ON(!(fd->ic->flags & INO_FLAGS_IS_DIR)); + + /* We clear ic->pino_nlink ∀ directories' ic *only* if dir_hardlinks + * is set. Otherwise, we know this should never trigger anyway, so + * we don't do the check. And ic->pino_nlink still contains the nlink + * value (which is 1). */ + if (dir_hardlinks && fd->ic->pino_nlink) { + JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u is also hard linked from dir ino #%u\n", + fd->name, fd->ino, ic->ino, fd->ic->pino_nlink); + /* Should we unlink it from its previous parent? */ + } + + /* For directories, ic->pino_nlink holds that parent inode # */ + fd->ic->pino_nlink = ic->ino; + } jffs2_free_full_dirent(fd); } ic->scan_dents = NULL; @@ -241,11 +284,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, /* Reduce nlink of the child. If it's now zero, stick it on the dead_fds list to be cleaned up later. Else just free the fd */ - - if (fd->type == DT_DIR) - child_ic->pino_nlink = 0; - else - child_ic->pino_nlink--; + child_ic->pino_nlink--; if (!child_ic->pino_nlink) { dbg_fsbuild("inode #%u (\"%s\") now has no links; adding to dead_fds list.\n", diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index c5ac5944bc1b..cad86bac3453 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -137,39 +137,33 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, struct page *pg; struct inode *inode = mapping->host; struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); - struct jffs2_raw_inode ri; - uint32_t alloc_len = 0; pgoff_t index = pos >> PAGE_CACHE_SHIFT; uint32_t pageofs = index << PAGE_CACHE_SHIFT; int ret = 0; - jffs2_dbg(1, "%s()\n", __func__); - - if (pageofs > inode->i_size) { - ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, - ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); - if (ret) - return ret; - } - - mutex_lock(&f->sem); pg = grab_cache_page_write_begin(mapping, index, flags); - if (!pg) { - if (alloc_len) - jffs2_complete_reservation(c); - mutex_unlock(&f->sem); + if (!pg) return -ENOMEM; - } *pagep = pg; - if (alloc_len) { + jffs2_dbg(1, "%s()\n", __func__); + + if (pageofs > inode->i_size) { /* Make new hole frag from old EOF to new page */ + struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); + struct jffs2_raw_inode ri; struct jffs2_full_dnode *fn; + uint32_t alloc_len; jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", (unsigned int)inode->i_size, pageofs); + ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); + if (ret) + goto out_page; + + mutex_lock(&f->sem); memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); @@ -196,6 +190,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, if (IS_ERR(fn)) { ret = PTR_ERR(fn); jffs2_complete_reservation(c); + mutex_unlock(&f->sem); goto out_page; } ret = jffs2_add_full_dnode_to_inode(c, f, fn); @@ -210,10 +205,12 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, jffs2_mark_node_obsolete(c, fn->raw); jffs2_free_full_dnode(fn); jffs2_complete_reservation(c); + mutex_unlock(&f->sem); goto out_page; } jffs2_complete_reservation(c); inode->i_size = pageofs; + mutex_unlock(&f->sem); } /* @@ -222,18 +219,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, * case of a short-copy. */ if (!PageUptodate(pg)) { + mutex_lock(&f->sem); ret = jffs2_do_readpage_nolock(inode, pg); + mutex_unlock(&f->sem); if (ret) goto out_page; } - mutex_unlock(&f->sem); jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags); return ret; out_page: unlock_page(pg); page_cache_release(pg); - mutex_unlock(&f->sem); return ret; } diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 5a2dec2b064c..95d5880a63ee 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -1296,14 +1296,17 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era BUG_ON(start > orig_start); } - /* First, use readpage() to read the appropriate page into the page cache */ - /* Q: What happens if we actually try to GC the _same_ page for which commit_write() - * triggered garbage collection in the first place? - * A: I _think_ it's OK. read_cache_page shouldn't deadlock, we'll write out the - * page OK. We'll actually write it out again in commit_write, which is a little - * suboptimal, but at least we're correct. - */ + /* The rules state that we must obtain the page lock *before* f->sem, so + * drop f->sem temporarily. Since we also hold c->alloc_sem, nothing's + * actually going to *change* so we're safe; we only allow reading. + * + * It is important to note that jffs2_write_begin() will ensure that its + * page is marked Uptodate before allocating space. That means that if we + * end up here trying to GC the *same* page that jffs2_write_begin() is + * trying to write out, read_cache_page() will not deadlock. */ + mutex_unlock(&f->sem); pg_ptr = jffs2_gc_fetch_page(c, f, start, &pg); + mutex_lock(&f->sem); if (IS_ERR(pg_ptr)) { pr_warn("read_cache_page() returned error: %ld\n", diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index fa35ff79ab35..0637271f3770 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -194,6 +194,7 @@ struct jffs2_inode_cache { #define INO_STATE_CLEARING 6 /* In clear_inode() */ #define INO_FLAGS_XATTR_CHECKED 0x01 /* has no duplicate xattr_ref */ +#define INO_FLAGS_IS_DIR 0x02 /* is a directory */ #define RAWNODE_CLASS_INODE_CACHE 0 #define RAWNODE_CLASS_XATTR_DATUM 1 @@ -249,7 +250,10 @@ struct jffs2_readinode_info struct jffs2_full_dirent { - struct jffs2_raw_node_ref *raw; + union { + struct jffs2_raw_node_ref *raw; + struct jffs2_inode_cache *ic; /* Just during part of build */ + }; struct jffs2_full_dirent *next; uint32_t version; uint32_t ino; /* == zero for unlink */ diff --git a/fs/namei.c b/fs/namei.c index f624d132e01e..9c590e0f66e9 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1712,6 +1712,11 @@ static inline int should_follow_link(struct nameidata *nd, struct path *link, return 0; if (!follow) return 0; + /* make sure that d_is_symlink above matches inode */ + if (nd->flags & LOOKUP_RCU) { + if (read_seqcount_retry(&link->dentry->d_seq, seq)) + return -ECHILD; + } return pick_link(nd, link, inode, seq); } @@ -1743,11 +1748,11 @@ static int walk_component(struct nameidata *nd, int flags) if (err < 0) return err; - inode = d_backing_inode(path.dentry); seq = 0; /* we are already out of RCU mode */ err = -ENOENT; if (d_is_negative(path.dentry)) goto out_path_put; + inode = d_backing_inode(path.dentry); } if (flags & WALK_PUT) @@ -3192,12 +3197,12 @@ retry_lookup: return error; BUG_ON(nd->flags & LOOKUP_RCU); - inode = d_backing_inode(path.dentry); seq = 0; /* out of RCU mode, so the value doesn't matter */ if (unlikely(d_is_negative(path.dentry))) { path_to_nameidata(&path, nd); return -ENOENT; } + inode = d_backing_inode(path.dentry); finish_lookup: if (nd->depth) put_link(nd); @@ -3206,11 +3211,6 @@ finish_lookup: if (unlikely(error)) return error; - if (unlikely(d_is_symlink(path.dentry)) && !(open_flag & O_PATH)) { - path_to_nameidata(&path, nd); - return -ELOOP; - } - if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path.mnt) { path_to_nameidata(&path, nd); } else { @@ -3229,6 +3229,10 @@ finish_open: return error; } audit_inode(nd->name, nd->path.dentry, 0); + if (unlikely(d_is_symlink(nd->path.dentry)) && !(open_flag & O_PATH)) { + error = -ELOOP; + goto out; + } error = -EISDIR; if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry)) goto out; @@ -3273,6 +3277,10 @@ opened: goto exit_fput; } out: + if (unlikely(error > 0)) { + WARN_ON(1); + error = -EINVAL; + } if (got_write) mnt_drop_write(nd->path.mnt); path_put(&save_parent); diff --git a/fs/nfs/blocklayout/extent_tree.c b/fs/nfs/blocklayout/extent_tree.c index c59a59c37f3d..35ab51c04814 100644 --- a/fs/nfs/blocklayout/extent_tree.c +++ b/fs/nfs/blocklayout/extent_tree.c @@ -476,6 +476,7 @@ static void ext_tree_free_commitdata(struct nfs4_layoutcommit_args *arg, for (i = 0; i < nr_pages; i++) put_page(arg->layoutupdate_pages[i]); + vfree(arg->start_p); kfree(arg->layoutupdate_pages); } else { put_page(arg->layoutupdate_page); @@ -559,10 +560,15 @@ retry: if (unlikely(arg->layoutupdate_pages != &arg->layoutupdate_page)) { void *p = start_p, *end = p + arg->layoutupdate_len; + struct page *page = NULL; int i = 0; - for ( ; p < end; p += PAGE_SIZE) - arg->layoutupdate_pages[i++] = vmalloc_to_page(p); + arg->start_p = start_p; + for ( ; p < end; p += PAGE_SIZE) { + page = vmalloc_to_page(p); + arg->layoutupdate_pages[i++] = page; + get_page(page); + } } dprintk("%s found %zu ranges\n", __func__, count); diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index bd25dc7077f7..dff83460e5a6 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c @@ -16,29 +16,8 @@ #define NFSDBG_FACILITY NFSDBG_PROC -static int nfs42_set_rw_stateid(nfs4_stateid *dst, struct file *file, - fmode_t fmode) -{ - struct nfs_open_context *open; - struct nfs_lock_context *lock; - int ret; - - open = get_nfs_open_context(nfs_file_open_context(file)); - lock = nfs_get_lock_context(open); - if (IS_ERR(lock)) { - put_nfs_open_context(open); - return PTR_ERR(lock); - } - - ret = nfs4_set_rw_stateid(dst, open, lock, fmode); - - nfs_put_lock_context(lock); - put_nfs_open_context(open); - return ret; -} - static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, - loff_t offset, loff_t len) + struct nfs_lock_context *lock, loff_t offset, loff_t len) { struct inode *inode = file_inode(filep); struct nfs_server *server = NFS_SERVER(inode); @@ -56,7 +35,8 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, msg->rpc_argp = &args; msg->rpc_resp = &res; - status = nfs42_set_rw_stateid(&args.falloc_stateid, filep, FMODE_WRITE); + status = nfs4_set_rw_stateid(&args.falloc_stateid, lock->open_context, + lock, FMODE_WRITE); if (status) return status; @@ -78,15 +58,26 @@ static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, { struct nfs_server *server = NFS_SERVER(file_inode(filep)); struct nfs4_exception exception = { }; + struct nfs_lock_context *lock; int err; + lock = nfs_get_lock_context(nfs_file_open_context(filep)); + if (IS_ERR(lock)) + return PTR_ERR(lock); + + exception.inode = file_inode(filep); + exception.state = lock->open_context->state; + do { - err = _nfs42_proc_fallocate(msg, filep, offset, len); - if (err == -ENOTSUPP) - return -EOPNOTSUPP; + err = _nfs42_proc_fallocate(msg, filep, lock, offset, len); + if (err == -ENOTSUPP) { + err = -EOPNOTSUPP; + break; + } err = nfs4_handle_exception(server, err, &exception); } while (exception.retry); + nfs_put_lock_context(lock); return err; } @@ -135,7 +126,8 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len) return err; } -static loff_t _nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) +static loff_t _nfs42_proc_llseek(struct file *filep, + struct nfs_lock_context *lock, loff_t offset, int whence) { struct inode *inode = file_inode(filep); struct nfs42_seek_args args = { @@ -156,7 +148,8 @@ static loff_t _nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) if (!nfs_server_capable(inode, NFS_CAP_SEEK)) return -ENOTSUPP; - status = nfs42_set_rw_stateid(&args.sa_stateid, filep, FMODE_READ); + status = nfs4_set_rw_stateid(&args.sa_stateid, lock->open_context, + lock, FMODE_READ); if (status) return status; @@ -175,17 +168,28 @@ loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) { struct nfs_server *server = NFS_SERVER(file_inode(filep)); struct nfs4_exception exception = { }; + struct nfs_lock_context *lock; loff_t err; + lock = nfs_get_lock_context(nfs_file_open_context(filep)); + if (IS_ERR(lock)) + return PTR_ERR(lock); + + exception.inode = file_inode(filep); + exception.state = lock->open_context->state; + do { - err = _nfs42_proc_llseek(filep, offset, whence); + err = _nfs42_proc_llseek(filep, lock, offset, whence); if (err >= 0) break; - if (err == -ENOTSUPP) - return -EOPNOTSUPP; + if (err == -ENOTSUPP) { + err = -EOPNOTSUPP; + break; + } err = nfs4_handle_exception(server, err, &exception); } while (exception.retry); + nfs_put_lock_context(lock); return err; } @@ -298,8 +302,9 @@ int nfs42_proc_layoutstats_generic(struct nfs_server *server, } static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f, - struct file *dst_f, loff_t src_offset, - loff_t dst_offset, loff_t count) + struct file *dst_f, struct nfs_lock_context *src_lock, + struct nfs_lock_context *dst_lock, loff_t src_offset, + loff_t dst_offset, loff_t count) { struct inode *src_inode = file_inode(src_f); struct inode *dst_inode = file_inode(dst_f); @@ -320,11 +325,13 @@ static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f, msg->rpc_argp = &args; msg->rpc_resp = &res; - status = nfs42_set_rw_stateid(&args.src_stateid, src_f, FMODE_READ); + status = nfs4_set_rw_stateid(&args.src_stateid, src_lock->open_context, + src_lock, FMODE_READ); if (status) return status; - status = nfs42_set_rw_stateid(&args.dst_stateid, dst_f, FMODE_WRITE); + status = nfs4_set_rw_stateid(&args.dst_stateid, dst_lock->open_context, + dst_lock, FMODE_WRITE); if (status) return status; @@ -349,22 +356,48 @@ int nfs42_proc_clone(struct file *src_f, struct file *dst_f, }; struct inode *inode = file_inode(src_f); struct nfs_server *server = NFS_SERVER(file_inode(src_f)); - struct nfs4_exception exception = { }; - int err; + struct nfs_lock_context *src_lock; + struct nfs_lock_context *dst_lock; + struct nfs4_exception src_exception = { }; + struct nfs4_exception dst_exception = { }; + int err, err2; if (!nfs_server_capable(inode, NFS_CAP_CLONE)) return -EOPNOTSUPP; + src_lock = nfs_get_lock_context(nfs_file_open_context(src_f)); + if (IS_ERR(src_lock)) + return PTR_ERR(src_lock); + + src_exception.inode = file_inode(src_f); + src_exception.state = src_lock->open_context->state; + + dst_lock = nfs_get_lock_context(nfs_file_open_context(dst_f)); + if (IS_ERR(dst_lock)) { + err = PTR_ERR(dst_lock); + goto out_put_src_lock; + } + + dst_exception.inode = file_inode(dst_f); + dst_exception.state = dst_lock->open_context->state; + do { - err = _nfs42_proc_clone(&msg, src_f, dst_f, src_offset, - dst_offset, count); + err = _nfs42_proc_clone(&msg, src_f, dst_f, src_lock, dst_lock, + src_offset, dst_offset, count); if (err == -ENOTSUPP || err == -EOPNOTSUPP) { NFS_SERVER(inode)->caps &= ~NFS_CAP_CLONE; - return -EOPNOTSUPP; + err = -EOPNOTSUPP; + break; } - err = nfs4_handle_exception(server, err, &exception); - } while (exception.retry); - return err; + err2 = nfs4_handle_exception(server, err, &src_exception); + err = nfs4_handle_exception(server, err, &dst_exception); + if (!err) + err = err2; + } while (src_exception.retry || dst_exception.retry); + nfs_put_lock_context(dst_lock); +out_put_src_lock: + nfs_put_lock_context(src_lock); + return err; } diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 4bfc33ad0563..14881594dd07 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2466,9 +2466,9 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, dentry = d_add_unique(dentry, igrab(state->inode)); if (dentry == NULL) { dentry = opendata->dentry; - } else if (dentry != ctx->dentry) { + } else { dput(ctx->dentry); - ctx->dentry = dget(dentry); + ctx->dentry = dentry; } nfs_set_verifier(dentry, nfs_save_change_attribute(d_inode(opendata->dir))); diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 482b6e94bb37..2fa483e6dbe2 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -252,6 +252,27 @@ pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo) } } +/* + * Mark a pnfs_layout_hdr and all associated layout segments as invalid + * + * In order to continue using the pnfs_layout_hdr, a full recovery + * is required. + * Note that caller must hold inode->i_lock. + */ +static int +pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo, + struct list_head *lseg_list) +{ + struct pnfs_layout_range range = { + .iomode = IOMODE_ANY, + .offset = 0, + .length = NFS4_MAX_UINT64, + }; + + set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); + return pnfs_mark_matching_lsegs_invalid(lo, lseg_list, &range); +} + static int pnfs_iomode_to_fail_bit(u32 iomode) { @@ -554,9 +575,8 @@ pnfs_destroy_layout(struct nfs_inode *nfsi) spin_lock(&nfsi->vfs_inode.i_lock); lo = nfsi->layout; if (lo) { - lo->plh_block_lgets++; /* permanently block new LAYOUTGETs */ - pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL); pnfs_get_layout_hdr(lo); + pnfs_mark_layout_stateid_invalid(lo, &tmp_list); pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RO_FAILED); pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RW_FAILED); spin_unlock(&nfsi->vfs_inode.i_lock); @@ -617,11 +637,6 @@ pnfs_layout_free_bulk_destroy_list(struct list_head *layout_list, { struct pnfs_layout_hdr *lo; struct inode *inode; - struct pnfs_layout_range range = { - .iomode = IOMODE_ANY, - .offset = 0, - .length = NFS4_MAX_UINT64, - }; LIST_HEAD(lseg_list); int ret = 0; @@ -636,11 +651,11 @@ pnfs_layout_free_bulk_destroy_list(struct list_head *layout_list, spin_lock(&inode->i_lock); list_del_init(&lo->plh_bulk_destroy); - lo->plh_block_lgets++; /* permanently block new LAYOUTGETs */ - if (is_bulk_recall) - set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); - if (pnfs_mark_matching_lsegs_invalid(lo, &lseg_list, &range)) + if (pnfs_mark_layout_stateid_invalid(lo, &lseg_list)) { + if (is_bulk_recall) + set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); ret = -EAGAIN; + } spin_unlock(&inode->i_lock); pnfs_free_lseg_list(&lseg_list); /* Free all lsegs that are attached to commit buckets */ @@ -1738,8 +1753,19 @@ pnfs_set_plh_return_iomode(struct pnfs_layout_hdr *lo, enum pnfs_iomode iomode) if (lo->plh_return_iomode != 0) iomode = IOMODE_ANY; lo->plh_return_iomode = iomode; + set_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags); } +/** + * pnfs_mark_matching_lsegs_return - Free or return matching layout segments + * @lo: pointer to layout header + * @tmp_list: list header to be used with pnfs_free_lseg_list() + * @return_range: describe layout segment ranges to be returned + * + * This function is mainly intended for use by layoutrecall. It attempts + * to free the layout segment immediately, or else to mark it for return + * as soon as its reference count drops to zero. + */ int pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, struct list_head *tmp_list, @@ -1762,12 +1788,11 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, lseg, lseg->pls_range.iomode, lseg->pls_range.offset, lseg->pls_range.length); + if (mark_lseg_invalid(lseg, tmp_list)) + continue; + remaining++; set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags); pnfs_set_plh_return_iomode(lo, return_range->iomode); - if (!mark_lseg_invalid(lseg, tmp_list)) - remaining++; - set_bit(NFS_LAYOUT_RETURN_REQUESTED, - &lo->plh_flags); } return remaining; } diff --git a/fs/notify/mark.c b/fs/notify/mark.c index cfcbf114676e..7115c5d7d373 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c @@ -91,7 +91,14 @@ #include <linux/fsnotify_backend.h> #include "fsnotify.h" +#define FSNOTIFY_REAPER_DELAY (1) /* 1 jiffy */ + struct srcu_struct fsnotify_mark_srcu; +static DEFINE_SPINLOCK(destroy_lock); +static LIST_HEAD(destroy_list); + +static void fsnotify_mark_destroy(struct work_struct *work); +static DECLARE_DELAYED_WORK(reaper_work, fsnotify_mark_destroy); void fsnotify_get_mark(struct fsnotify_mark *mark) { @@ -165,19 +172,10 @@ void fsnotify_detach_mark(struct fsnotify_mark *mark) atomic_dec(&group->num_marks); } -static void -fsnotify_mark_free_rcu(struct rcu_head *rcu) -{ - struct fsnotify_mark *mark; - - mark = container_of(rcu, struct fsnotify_mark, g_rcu); - fsnotify_put_mark(mark); -} - /* - * Free fsnotify mark. The freeing is actually happening from a call_srcu - * callback. Caller must have a reference to the mark or be protected by - * fsnotify_mark_srcu. + * Free fsnotify mark. The freeing is actually happening from a kthread which + * first waits for srcu period end. Caller must have a reference to the mark + * or be protected by fsnotify_mark_srcu. */ void fsnotify_free_mark(struct fsnotify_mark *mark) { @@ -192,7 +190,11 @@ void fsnotify_free_mark(struct fsnotify_mark *mark) mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE; spin_unlock(&mark->lock); - call_srcu(&fsnotify_mark_srcu, &mark->g_rcu, fsnotify_mark_free_rcu); + spin_lock(&destroy_lock); + list_add(&mark->g_list, &destroy_list); + spin_unlock(&destroy_lock); + queue_delayed_work(system_unbound_wq, &reaper_work, + FSNOTIFY_REAPER_DELAY); /* * Some groups like to know that marks are being freed. This is a @@ -388,7 +390,12 @@ err: spin_unlock(&mark->lock); - call_srcu(&fsnotify_mark_srcu, &mark->g_rcu, fsnotify_mark_free_rcu); + spin_lock(&destroy_lock); + list_add(&mark->g_list, &destroy_list); + spin_unlock(&destroy_lock); + queue_delayed_work(system_unbound_wq, &reaper_work, + FSNOTIFY_REAPER_DELAY); + return ret; } @@ -491,3 +498,21 @@ void fsnotify_init_mark(struct fsnotify_mark *mark, atomic_set(&mark->refcnt, 1); mark->free_mark = free_mark; } + +static void fsnotify_mark_destroy(struct work_struct *work) +{ + struct fsnotify_mark *mark, *next; + struct list_head private_destroy_list; + + spin_lock(&destroy_lock); + /* exchange the list head */ + list_replace_init(&destroy_list, &private_destroy_list); + spin_unlock(&destroy_lock); + + synchronize_srcu(&fsnotify_mark_srcu); + + list_for_each_entry_safe(mark, next, &private_destroy_list, g_list) { + list_del_init(&mark->g_list); + fsnotify_put_mark(mark); + } +} diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 794fd1587f34..cda0361e95a4 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -956,6 +956,7 @@ clean_orphan: tmp_ret = ocfs2_del_inode_from_orphan(osb, inode, di_bh, update_isize, end); if (tmp_ret < 0) { + ocfs2_inode_unlock(inode, 1); ret = tmp_ret; mlog_errno(ret); brelse(di_bh); diff --git a/fs/pnode.c b/fs/pnode.c index 6367e1e435c6..c524fdddc7fb 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -202,6 +202,11 @@ static struct mount *last_dest, *last_source, *dest_master; static struct mountpoint *mp; static struct hlist_head *list; +static inline bool peers(struct mount *m1, struct mount *m2) +{ + return m1->mnt_group_id == m2->mnt_group_id && m1->mnt_group_id; +} + static int propagate_one(struct mount *m) { struct mount *child; @@ -212,7 +217,7 @@ static int propagate_one(struct mount *m) /* skip if mountpoint isn't covered by it */ if (!is_subdir(mp->m_dentry, m->mnt.mnt_root)) return 0; - if (m->mnt_group_id == last_dest->mnt_group_id) { + if (peers(m, last_dest)) { type = CL_MAKE_SHARED; } else { struct mount *n, *p; @@ -223,7 +228,7 @@ static int propagate_one(struct mount *m) last_source = last_source->mnt_master; last_dest = last_source->mnt_parent; } - if (n->mnt_group_id != last_dest->mnt_group_id) { + if (!peers(n, last_dest)) { last_source = last_source->mnt_master; last_dest = last_source->mnt_parent; } diff --git a/fs/read_write.c b/fs/read_write.c index 324ec271cc4e..dadf24e5c95b 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -17,6 +17,7 @@ #include <linux/splice.h> #include <linux/compat.h> #include <linux/mount.h> +#include <linux/fs.h> #include "internal.h" #include <asm/uaccess.h> @@ -183,7 +184,7 @@ loff_t no_seek_end_llseek(struct file *file, loff_t offset, int whence) switch (whence) { case SEEK_SET: case SEEK_CUR: return generic_file_llseek_size(file, offset, whence, - ~0ULL, 0); + OFFSET_MAX, 0); default: return -EINVAL; } @@ -1532,10 +1533,12 @@ int vfs_clone_file_range(struct file *file_in, loff_t pos_in, if (!(file_in->f_mode & FMODE_READ) || !(file_out->f_mode & FMODE_WRITE) || - (file_out->f_flags & O_APPEND) || - !file_in->f_op->clone_file_range) + (file_out->f_flags & O_APPEND)) return -EBADF; + if (!file_in->f_op->clone_file_range) + return -EOPNOTSUPP; + ret = clone_verify_area(file_in, pos_in, len, false); if (ret) return ret; diff --git a/fs/super.c b/fs/super.c index 1182af8fd5ff..74914b1bae70 100644 --- a/fs/super.c +++ b/fs/super.c @@ -415,6 +415,7 @@ void generic_shutdown_super(struct super_block *sb) sb->s_flags &= ~MS_ACTIVE; fsnotify_unmount_inodes(sb); + cgroup_writeback_umount(); evict_inodes(sb); diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index 50311703135b..66cdb44616d5 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -287,6 +287,12 @@ int handle_userfault(struct vm_area_struct *vma, unsigned long address, goto out; /* + * We don't do userfault handling for the final child pid update. + */ + if (current->flags & PF_EXITING) + goto out; + + /* * Check that we can return VM_FAULT_RETRY. * * NOTE: it should become possible to return VM_FAULT_RETRY diff --git a/fs/xattr.c b/fs/xattr.c index 07d0e47f6a7f..4861322e28e8 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -940,7 +940,7 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs, bool trusted = capable(CAP_SYS_ADMIN); struct simple_xattr *xattr; ssize_t remaining_size = size; - int err; + int err = 0; #ifdef CONFIG_FS_POSIX_ACL if (inode->i_acl) { @@ -965,11 +965,11 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs, err = xattr_list_one(&buffer, &remaining_size, xattr->name); if (err) - return err; + break; } spin_unlock(&xattrs->lock); - return size - remaining_size; + return err ? err : size - remaining_size; } /* diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 379c089fb051..a9ebabfe7587 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -55,7 +55,7 @@ xfs_count_page_state( } while ((bh = bh->b_this_page) != head); } -STATIC struct block_device * +struct block_device * xfs_find_bdev_for_inode( struct inode *inode) { @@ -1208,6 +1208,10 @@ xfs_vm_writepages( struct writeback_control *wbc) { xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED); + if (dax_mapping(mapping)) + return dax_writeback_mapping_range(mapping, + xfs_find_bdev_for_inode(mapping->host), wbc); + return generic_writepages(mapping, wbc); } diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h index f6ffc9ae5ceb..a4343c63fb38 100644 --- a/fs/xfs/xfs_aops.h +++ b/fs/xfs/xfs_aops.h @@ -62,5 +62,6 @@ int xfs_get_blocks_dax_fault(struct inode *inode, sector_t offset, struct buffer_head *map_bh, int create); extern void xfs_count_page_state(struct page *, int *, int *); +extern struct block_device *xfs_find_bdev_for_inode(struct inode *); #endif /* __XFS_AOPS_H__ */ diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 45ec9e40150c..6c876012b2e5 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -75,7 +75,8 @@ xfs_zero_extent( ssize_t size = XFS_FSB_TO_B(mp, count_fsb); if (IS_DAX(VFS_I(ip))) - return dax_clear_blocks(VFS_I(ip), block, size); + return dax_clear_sectors(xfs_find_bdev_for_inode(VFS_I(ip)), + sector, size); /* * let the block layer decide on the fastest method of diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 0b3c0d39ef75..c370b261c720 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -239,6 +239,14 @@ extern void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp); #endif +#ifndef __HAVE_ARCH_PMDP_HUGE_SPLIT_PREPARE +static inline void pmdp_huge_split_prepare(struct vm_area_struct *vma, + unsigned long address, pmd_t *pmdp) +{ + +} +#endif + #ifndef __HAVE_ARCH_PTE_SAME static inline int pte_same(pte_t pte_a, pte_t pte_b) { diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c65a212db77e..c5b4b81a831b 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1166,6 +1166,7 @@ struct drm_connector { struct drm_mode_object base; char *name; + int connector_id; int connector_type; int connector_type_id; bool interlace_allowed; @@ -2047,6 +2048,7 @@ struct drm_mode_config { struct list_head fb_list; int num_connector; + struct ida connector_ida; struct list_head connector_list; int num_encoder; struct list_head encoder_list; @@ -2200,7 +2202,11 @@ int drm_connector_register(struct drm_connector *connector); void drm_connector_unregister(struct drm_connector *connector); extern void drm_connector_cleanup(struct drm_connector *connector); -extern unsigned int drm_connector_index(struct drm_connector *connector); +static inline unsigned drm_connector_index(struct drm_connector *connector) +{ + return connector->connector_id; +} + /* helper to unplug all connectors from sysfs for device */ extern void drm_connector_unplug_all(struct drm_device *dev); diff --git a/include/dt-bindings/clock/tegra210-car.h b/include/dt-bindings/clock/tegra210-car.h index 6f45aea49e4f..0a05b0d36ae7 100644 --- a/include/dt-bindings/clock/tegra210-car.h +++ b/include/dt-bindings/clock/tegra210-car.h @@ -126,7 +126,7 @@ /* 104 */ /* 105 */ #define TEGRA210_CLK_D_AUDIO 106 -/* 107 ( affects abp -> ape) */ +#define TEGRA210_CLK_APB2APE 107 /* 108 */ /* 109 */ /* 110 */ diff --git a/include/linux/ata.h b/include/linux/ata.h index d2992bfa1706..c1a2f345cbe6 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -487,8 +487,8 @@ enum ata_tf_protocols { }; enum ata_ioctls { - ATA_IOC_GET_IO32 = 0x309, - ATA_IOC_SET_IO32 = 0x324, + ATA_IOC_GET_IO32 = 0x309, /* HDIO_GET_32BIT */ + ATA_IOC_SET_IO32 = 0x324, /* HDIO_SET_32BIT */ }; /* core structures */ diff --git a/include/linux/bio.h b/include/linux/bio.h index 5349e6816cbb..cb6888824108 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -310,6 +310,43 @@ static inline void bio_clear_flag(struct bio *bio, unsigned int bit) bio->bi_flags &= ~(1U << bit); } +static inline void bio_get_first_bvec(struct bio *bio, struct bio_vec *bv) +{ + *bv = bio_iovec(bio); +} + +static inline void bio_get_last_bvec(struct bio *bio, struct bio_vec *bv) +{ + struct bvec_iter iter = bio->bi_iter; + int idx; + + if (!bio_flagged(bio, BIO_CLONED)) { + *bv = bio->bi_io_vec[bio->bi_vcnt - 1]; + return; + } + + if (unlikely(!bio_multiple_segments(bio))) { + *bv = bio_iovec(bio); + return; + } + + bio_advance_iter(bio, &iter, iter.bi_size); + + if (!iter.bi_bvec_done) + idx = iter.bi_idx - 1; + else /* in the middle of bvec */ + idx = iter.bi_idx; + + *bv = bio->bi_io_vec[idx]; + + /* + * iter.bi_bvec_done records actual length of the last bvec + * if this bio ends in the middle of one io vector + */ + if (iter.bi_bvec_done) + bv->bv_len = iter.bi_bvec_done; +} + enum bip_flags { BIP_BLOCK_INTEGRITY = 1 << 0, /* block layer owns integrity data */ BIP_MAPPED_INTEGRITY = 1 << 1, /* ref tag has been remapped */ diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 4571ef1a12a9..413c84fbc4ed 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -895,7 +895,7 @@ static inline unsigned int blk_rq_get_max_sectors(struct request *rq) { struct request_queue *q = rq->q; - if (unlikely(rq->cmd_type == REQ_TYPE_BLOCK_PC)) + if (unlikely(rq->cmd_type != REQ_TYPE_FS)) return q->limits.max_hw_sectors; if (!q->limits.chunk_sectors || (rq->cmd_flags & REQ_DISCARD)) @@ -1372,6 +1372,13 @@ static inline void put_dev_sector(Sector p) page_cache_release(p.v); } +static inline bool __bvec_gap_to_prev(struct request_queue *q, + struct bio_vec *bprv, unsigned int offset) +{ + return offset || + ((bprv->bv_offset + bprv->bv_len) & queue_virt_boundary(q)); +} + /* * Check if adding a bio_vec after bprv with offset would create a gap in * the SG list. Most drivers don't care about this, but some do. @@ -1381,18 +1388,22 @@ static inline bool bvec_gap_to_prev(struct request_queue *q, { if (!queue_virt_boundary(q)) return false; - return offset || - ((bprv->bv_offset + bprv->bv_len) & queue_virt_boundary(q)); + return __bvec_gap_to_prev(q, bprv, offset); } static inline bool bio_will_gap(struct request_queue *q, struct bio *prev, struct bio *next) { - if (!bio_has_data(prev)) - return false; + if (bio_has_data(prev) && queue_virt_boundary(q)) { + struct bio_vec pb, nb; + + bio_get_last_bvec(prev, &pb); + bio_get_first_bvec(next, &nb); - return bvec_gap_to_prev(q, &prev->bi_io_vec[prev->bi_vcnt - 1], - next->bi_io_vec[0].bv_offset); + return __bvec_gap_to_prev(q, &pb, nb.bv_offset); + } + + return false; } static inline bool req_gap_back_merge(struct request *req, struct bio *bio) diff --git a/include/linux/ceph/ceph_features.h b/include/linux/ceph/ceph_features.h index c1ef6f14e7be..15151f3c4120 100644 --- a/include/linux/ceph/ceph_features.h +++ b/include/linux/ceph/ceph_features.h @@ -75,6 +75,7 @@ #define CEPH_FEATURE_CRUSH_TUNABLES5 (1ULL<<58) /* chooseleaf stable mode */ // duplicated since it was introduced at the same time as CEPH_FEATURE_CRUSH_TUNABLES5 #define CEPH_FEATURE_NEW_OSDOPREPLY_ENCODING (1ULL<<58) /* New, v7 encoding */ +#define CEPH_FEATURE_FS_FILE_LAYOUT_V2 (1ULL<<58) /* file_layout_t */ /* * The introduction of CEPH_FEATURE_OSD_SNAPMAPPER caused the feature diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 00b042c49ccd..48f5aab117ae 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -144,7 +144,7 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); */ #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) #define __trace_if(cond) \ - if (__builtin_constant_p((cond)) ? !!(cond) : \ + if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ ({ \ int ______r; \ static struct ftrace_branch_data \ diff --git a/include/linux/dax.h b/include/linux/dax.h index 818e45078929..636dd59ab505 100644 --- a/include/linux/dax.h +++ b/include/linux/dax.h @@ -7,7 +7,7 @@ ssize_t dax_do_io(struct kiocb *, struct inode *, struct iov_iter *, loff_t, get_block_t, dio_iodone_t, int flags); -int dax_clear_blocks(struct inode *, sector_t block, long size); +int dax_clear_sectors(struct block_device *bdev, sector_t _sector, long _size); int dax_zero_page_range(struct inode *, loff_t from, unsigned len, get_block_t); int dax_truncate_page(struct inode *, loff_t from, get_block_t); int dax_fault(struct vm_area_struct *, struct vm_fault *, get_block_t, @@ -52,6 +52,8 @@ static inline bool dax_mapping(struct address_space *mapping) { return mapping->host && IS_DAX(mapping->host); } -int dax_writeback_mapping_range(struct address_space *mapping, loff_t start, - loff_t end); + +struct writeback_control; +int dax_writeback_mapping_range(struct address_space *mapping, + struct block_device *bdev, struct writeback_control *wbc); #endif diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 7781ce110503..c4b5f4b3f8f8 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -409,9 +409,7 @@ static inline bool d_mountpoint(const struct dentry *dentry) */ static inline unsigned __d_entry_type(const struct dentry *dentry) { - unsigned type = READ_ONCE(dentry->d_flags); - smp_rmb(); - return type & DCACHE_ENTRY_TYPE; + return dentry->d_flags & DCACHE_ENTRY_TYPE; } static inline bool d_is_miss(const struct dentry *dentry) diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 6b7e89f45aa4..533c4408529a 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -220,10 +220,7 @@ struct fsnotify_mark { /* List of marks by group->i_fsnotify_marks. Also reused for queueing * mark into destroy_list when it's waiting for the end of SRCU period * before it can be freed. [group->mark_mutex] */ - union { - struct list_head g_list; - struct rcu_head g_rcu; - }; + struct list_head g_list; /* Protects inode / mnt pointers, flags, masks */ spinlock_t lock; /* List of marks for inode / vfsmount [obj_lock] */ diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 81de7123959d..c2b340e23f62 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -603,6 +603,7 @@ extern int ftrace_arch_read_dyn_info(char *buf, int size); extern int skip_trace(unsigned long ip); extern void ftrace_module_init(struct module *mod); +extern void ftrace_module_enable(struct module *mod); extern void ftrace_release_mod(struct module *mod); extern void ftrace_disable_daemon(void); @@ -612,8 +613,9 @@ static inline int skip_trace(unsigned long ip) { return 0; } static inline int ftrace_force_update(void) { return 0; } static inline void ftrace_disable_daemon(void) { } static inline void ftrace_enable_daemon(void) { } -static inline void ftrace_release_mod(struct module *mod) {} -static inline void ftrace_module_init(struct module *mod) {} +static inline void ftrace_module_init(struct module *mod) { } +static inline void ftrace_module_enable(struct module *mod) { } +static inline void ftrace_release_mod(struct module *mod) { } static inline __init int register_ftrace_command(struct ftrace_func_command *cmd) { return -EINVAL; diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 821273ca4873..2d9b650047a5 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -235,6 +235,9 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) /* low 64 bit */ #define dma_frcd_page_addr(d) (d & (((u64)-1) << PAGE_SHIFT)) +/* PRS_REG */ +#define DMA_PRS_PPR ((u32)1) + #define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \ do { \ cycles_t start_time = get_cycles(); \ diff --git a/include/linux/libata.h b/include/linux/libata.h index bec2abbd7ab2..2c4ebef79d0c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -720,7 +720,7 @@ struct ata_device { union { u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */ - }; + } ____cacheline_aligned; /* DEVSLP Timing Variables from Identify Device Data Log */ u8 devslp_timing[ATA_LOG_DEVSLP_SIZE]; diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h index bed40dff0e86..141ffdd59960 100644 --- a/include/linux/libnvdimm.h +++ b/include/linux/libnvdimm.h @@ -26,9 +26,8 @@ enum { /* need to set a limit somewhere, but yes, this is likely overkill */ ND_IOCTL_MAX_BUFLEN = SZ_4M, - ND_CMD_MAX_ELEM = 4, + ND_CMD_MAX_ELEM = 5, ND_CMD_MAX_ENVELOPE = 16, - ND_CMD_ARS_STATUS_MAX = SZ_4K, ND_MAX_MAPPINGS = 32, /* region flag indicating to direct-map persistent memory by default */ diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index d6750111e48e..2190419bdf0a 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -135,6 +135,10 @@ enum { /* Memory types */ NVM_ID_FMTYPE_SLC = 0, NVM_ID_FMTYPE_MLC = 1, + + /* Device capabilities */ + NVM_ID_DCAP_BBLKMGMT = 0x1, + NVM_UD_DCAP_ECC = 0x2, }; struct nvm_id_lp_mlc { diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 430a929f048b..a0e8cc8dcc67 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -44,6 +44,8 @@ #include <linux/timecounter.h> +#define DEFAULT_UAR_PAGE_SHIFT 12 + #define MAX_MSIX_P_PORT 17 #define MAX_MSIX 64 #define MIN_MSIX_P_PORT 5 @@ -856,6 +858,7 @@ struct mlx4_dev { u64 regid_promisc_array[MLX4_MAX_PORTS + 1]; u64 regid_allmulti_array[MLX4_MAX_PORTS + 1]; struct mlx4_vf_dev *dev_vfs; + u8 uar_page_shift; }; struct mlx4_clock_params { @@ -1528,4 +1531,14 @@ int mlx4_ACCESS_PTYS_REG(struct mlx4_dev *dev, int mlx4_get_internal_clock_params(struct mlx4_dev *dev, struct mlx4_clock_params *params); +static inline int mlx4_to_hw_uar_index(struct mlx4_dev *dev, int index) +{ + return (index << (PAGE_SHIFT - dev->uar_page_shift)); +} + +static inline int mlx4_get_num_reserved_uar(struct mlx4_dev *dev) +{ + /* The first 128 UARs are used for EQ doorbells */ + return (128 >> (PAGE_SHIFT - dev->uar_page_shift)); +} #endif /* MLX4_DEVICE_H */ diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 231ab6bcea76..51f1e540fc2b 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -207,15 +207,15 @@ struct mlx5_ifc_flow_table_fields_supported_bits { u8 outer_dmac[0x1]; u8 outer_smac[0x1]; u8 outer_ether_type[0x1]; - u8 reserved_0[0x1]; + u8 reserved_at_3[0x1]; u8 outer_first_prio[0x1]; u8 outer_first_cfi[0x1]; u8 outer_first_vid[0x1]; - u8 reserved_1[0x1]; + u8 reserved_at_7[0x1]; u8 outer_second_prio[0x1]; u8 outer_second_cfi[0x1]; u8 outer_second_vid[0x1]; - u8 reserved_2[0x1]; + u8 reserved_at_b[0x1]; u8 outer_sip[0x1]; u8 outer_dip[0x1]; u8 outer_frag[0x1]; @@ -230,21 +230,21 @@ struct mlx5_ifc_flow_table_fields_supported_bits { u8 outer_gre_protocol[0x1]; u8 outer_gre_key[0x1]; u8 outer_vxlan_vni[0x1]; - u8 reserved_3[0x5]; + u8 reserved_at_1a[0x5]; u8 source_eswitch_port[0x1]; u8 inner_dmac[0x1]; u8 inner_smac[0x1]; u8 inner_ether_type[0x1]; - u8 reserved_4[0x1]; + u8 reserved_at_23[0x1]; u8 inner_first_prio[0x1]; u8 inner_first_cfi[0x1]; u8 inner_first_vid[0x1]; - u8 reserved_5[0x1]; + u8 reserved_at_27[0x1]; u8 inner_second_prio[0x1]; u8 inner_second_cfi[0x1]; u8 inner_second_vid[0x1]; - u8 reserved_6[0x1]; + u8 reserved_at_2b[0x1]; u8 inner_sip[0x1]; u8 inner_dip[0x1]; u8 inner_frag[0x1]; @@ -256,37 +256,37 @@ struct mlx5_ifc_flow_table_fields_supported_bits { u8 inner_tcp_sport[0x1]; u8 inner_tcp_dport[0x1]; u8 inner_tcp_flags[0x1]; - u8 reserved_7[0x9]; + u8 reserved_at_37[0x9]; - u8 reserved_8[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_flow_table_prop_layout_bits { u8 ft_support[0x1]; - u8 reserved_0[0x2]; + u8 reserved_at_1[0x2]; u8 flow_modify_en[0x1]; u8 modify_root[0x1]; u8 identified_miss_table_mode[0x1]; u8 flow_table_modify[0x1]; - u8 reserved_1[0x19]; + u8 reserved_at_7[0x19]; - u8 reserved_2[0x2]; + u8 reserved_at_20[0x2]; u8 log_max_ft_size[0x6]; - u8 reserved_3[0x10]; + u8 reserved_at_28[0x10]; u8 max_ft_level[0x8]; - u8 reserved_4[0x20]; + u8 reserved_at_40[0x20]; - u8 reserved_5[0x18]; + u8 reserved_at_60[0x18]; u8 log_max_ft_num[0x8]; - u8 reserved_6[0x18]; + u8 reserved_at_80[0x18]; u8 log_max_destination[0x8]; - u8 reserved_7[0x18]; + u8 reserved_at_a0[0x18]; u8 log_max_flow[0x8]; - u8 reserved_8[0x40]; + u8 reserved_at_c0[0x40]; struct mlx5_ifc_flow_table_fields_supported_bits ft_field_support; @@ -298,13 +298,13 @@ struct mlx5_ifc_odp_per_transport_service_cap_bits { u8 receive[0x1]; u8 write[0x1]; u8 read[0x1]; - u8 reserved_0[0x1]; + u8 reserved_at_4[0x1]; u8 srq_receive[0x1]; - u8 reserved_1[0x1a]; + u8 reserved_at_6[0x1a]; }; struct mlx5_ifc_ipv4_layout_bits { - u8 reserved_0[0x60]; + u8 reserved_at_0[0x60]; u8 ipv4[0x20]; }; @@ -316,7 +316,7 @@ struct mlx5_ifc_ipv6_layout_bits { union mlx5_ifc_ipv6_layout_ipv4_layout_auto_bits { struct mlx5_ifc_ipv6_layout_bits ipv6_layout; struct mlx5_ifc_ipv4_layout_bits ipv4_layout; - u8 reserved_0[0x80]; + u8 reserved_at_0[0x80]; }; struct mlx5_ifc_fte_match_set_lyr_2_4_bits { @@ -336,15 +336,15 @@ struct mlx5_ifc_fte_match_set_lyr_2_4_bits { u8 ip_dscp[0x6]; u8 ip_ecn[0x2]; u8 vlan_tag[0x1]; - u8 reserved_0[0x1]; + u8 reserved_at_91[0x1]; u8 frag[0x1]; - u8 reserved_1[0x4]; + u8 reserved_at_93[0x4]; u8 tcp_flags[0x9]; u8 tcp_sport[0x10]; u8 tcp_dport[0x10]; - u8 reserved_2[0x20]; + u8 reserved_at_c0[0x20]; u8 udp_sport[0x10]; u8 udp_dport[0x10]; @@ -355,9 +355,9 @@ struct mlx5_ifc_fte_match_set_lyr_2_4_bits { }; struct mlx5_ifc_fte_match_set_misc_bits { - u8 reserved_0[0x20]; + u8 reserved_at_0[0x20]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 source_port[0x10]; u8 outer_second_prio[0x3]; @@ -369,31 +369,31 @@ struct mlx5_ifc_fte_match_set_misc_bits { u8 outer_second_vlan_tag[0x1]; u8 inner_second_vlan_tag[0x1]; - u8 reserved_2[0xe]; + u8 reserved_at_62[0xe]; u8 gre_protocol[0x10]; u8 gre_key_h[0x18]; u8 gre_key_l[0x8]; u8 vxlan_vni[0x18]; - u8 reserved_3[0x8]; + u8 reserved_at_b8[0x8]; - u8 reserved_4[0x20]; + u8 reserved_at_c0[0x20]; - u8 reserved_5[0xc]; + u8 reserved_at_e0[0xc]; u8 outer_ipv6_flow_label[0x14]; - u8 reserved_6[0xc]; + u8 reserved_at_100[0xc]; u8 inner_ipv6_flow_label[0x14]; - u8 reserved_7[0xe0]; + u8 reserved_at_120[0xe0]; }; struct mlx5_ifc_cmd_pas_bits { u8 pa_h[0x20]; u8 pa_l[0x14]; - u8 reserved_0[0xc]; + u8 reserved_at_34[0xc]; }; struct mlx5_ifc_uint64_bits { @@ -418,31 +418,31 @@ enum { struct mlx5_ifc_ads_bits { u8 fl[0x1]; u8 free_ar[0x1]; - u8 reserved_0[0xe]; + u8 reserved_at_2[0xe]; u8 pkey_index[0x10]; - u8 reserved_1[0x8]; + u8 reserved_at_20[0x8]; u8 grh[0x1]; u8 mlid[0x7]; u8 rlid[0x10]; u8 ack_timeout[0x5]; - u8 reserved_2[0x3]; + u8 reserved_at_45[0x3]; u8 src_addr_index[0x8]; - u8 reserved_3[0x4]; + u8 reserved_at_50[0x4]; u8 stat_rate[0x4]; u8 hop_limit[0x8]; - u8 reserved_4[0x4]; + u8 reserved_at_60[0x4]; u8 tclass[0x8]; u8 flow_label[0x14]; u8 rgid_rip[16][0x8]; - u8 reserved_5[0x4]; + u8 reserved_at_100[0x4]; u8 f_dscp[0x1]; u8 f_ecn[0x1]; - u8 reserved_6[0x1]; + u8 reserved_at_106[0x1]; u8 f_eth_prio[0x1]; u8 ecn[0x2]; u8 dscp[0x6]; @@ -458,25 +458,25 @@ struct mlx5_ifc_ads_bits { }; struct mlx5_ifc_flow_table_nic_cap_bits { - u8 reserved_0[0x200]; + u8 reserved_at_0[0x200]; struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_nic_receive; - u8 reserved_1[0x200]; + u8 reserved_at_400[0x200]; struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_nic_receive_sniffer; struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_nic_transmit; - u8 reserved_2[0x200]; + u8 reserved_at_a00[0x200]; struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_nic_transmit_sniffer; - u8 reserved_3[0x7200]; + u8 reserved_at_e00[0x7200]; }; struct mlx5_ifc_flow_table_eswitch_cap_bits { - u8 reserved_0[0x200]; + u8 reserved_at_0[0x200]; struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_nic_esw_fdb; @@ -484,7 +484,7 @@ struct mlx5_ifc_flow_table_eswitch_cap_bits { struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_esw_acl_egress; - u8 reserved_1[0x7800]; + u8 reserved_at_800[0x7800]; }; struct mlx5_ifc_e_switch_cap_bits { @@ -493,9 +493,9 @@ struct mlx5_ifc_e_switch_cap_bits { u8 vport_svlan_insert[0x1]; u8 vport_cvlan_insert_if_not_exist[0x1]; u8 vport_cvlan_insert_overwrite[0x1]; - u8 reserved_0[0x1b]; + u8 reserved_at_5[0x1b]; - u8 reserved_1[0x7e0]; + u8 reserved_at_20[0x7e0]; }; struct mlx5_ifc_per_protocol_networking_offload_caps_bits { @@ -504,51 +504,51 @@ struct mlx5_ifc_per_protocol_networking_offload_caps_bits { u8 lro_cap[0x1]; u8 lro_psh_flag[0x1]; u8 lro_time_stamp[0x1]; - u8 reserved_0[0x3]; + u8 reserved_at_5[0x3]; u8 self_lb_en_modifiable[0x1]; - u8 reserved_1[0x2]; + u8 reserved_at_9[0x2]; u8 max_lso_cap[0x5]; - u8 reserved_2[0x4]; + u8 reserved_at_10[0x4]; u8 rss_ind_tbl_cap[0x4]; - u8 reserved_3[0x3]; + u8 reserved_at_18[0x3]; u8 tunnel_lso_const_out_ip_id[0x1]; - u8 reserved_4[0x2]; + u8 reserved_at_1c[0x2]; u8 tunnel_statless_gre[0x1]; u8 tunnel_stateless_vxlan[0x1]; - u8 reserved_5[0x20]; + u8 reserved_at_20[0x20]; - u8 reserved_6[0x10]; + u8 reserved_at_40[0x10]; u8 lro_min_mss_size[0x10]; - u8 reserved_7[0x120]; + u8 reserved_at_60[0x120]; u8 lro_timer_supported_periods[4][0x20]; - u8 reserved_8[0x600]; + u8 reserved_at_200[0x600]; }; struct mlx5_ifc_roce_cap_bits { u8 roce_apm[0x1]; - u8 reserved_0[0x1f]; + u8 reserved_at_1[0x1f]; - u8 reserved_1[0x60]; + u8 reserved_at_20[0x60]; - u8 reserved_2[0xc]; + u8 reserved_at_80[0xc]; u8 l3_type[0x4]; - u8 reserved_3[0x8]; + u8 reserved_at_90[0x8]; u8 roce_version[0x8]; - u8 reserved_4[0x10]; + u8 reserved_at_a0[0x10]; u8 r_roce_dest_udp_port[0x10]; u8 r_roce_max_src_udp_port[0x10]; u8 r_roce_min_src_udp_port[0x10]; - u8 reserved_5[0x10]; + u8 reserved_at_e0[0x10]; u8 roce_address_table_size[0x10]; - u8 reserved_6[0x700]; + u8 reserved_at_100[0x700]; }; enum { @@ -576,35 +576,35 @@ enum { }; struct mlx5_ifc_atomic_caps_bits { - u8 reserved_0[0x40]; + u8 reserved_at_0[0x40]; u8 atomic_req_8B_endianess_mode[0x2]; - u8 reserved_1[0x4]; + u8 reserved_at_42[0x4]; u8 supported_atomic_req_8B_endianess_mode_1[0x1]; - u8 reserved_2[0x19]; + u8 reserved_at_47[0x19]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; - u8 reserved_4[0x10]; + u8 reserved_at_80[0x10]; u8 atomic_operations[0x10]; - u8 reserved_5[0x10]; + u8 reserved_at_a0[0x10]; u8 atomic_size_qp[0x10]; - u8 reserved_6[0x10]; + u8 reserved_at_c0[0x10]; u8 atomic_size_dc[0x10]; - u8 reserved_7[0x720]; + u8 reserved_at_e0[0x720]; }; struct mlx5_ifc_odp_cap_bits { - u8 reserved_0[0x40]; + u8 reserved_at_0[0x40]; u8 sig[0x1]; - u8 reserved_1[0x1f]; + u8 reserved_at_41[0x1f]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; struct mlx5_ifc_odp_per_transport_service_cap_bits rc_odp_caps; @@ -612,7 +612,7 @@ struct mlx5_ifc_odp_cap_bits { struct mlx5_ifc_odp_per_transport_service_cap_bits ud_odp_caps; - u8 reserved_3[0x720]; + u8 reserved_at_e0[0x720]; }; enum { @@ -660,55 +660,55 @@ enum { }; struct mlx5_ifc_cmd_hca_cap_bits { - u8 reserved_0[0x80]; + u8 reserved_at_0[0x80]; u8 log_max_srq_sz[0x8]; u8 log_max_qp_sz[0x8]; - u8 reserved_1[0xb]; + u8 reserved_at_90[0xb]; u8 log_max_qp[0x5]; - u8 reserved_2[0xb]; + u8 reserved_at_a0[0xb]; u8 log_max_srq[0x5]; - u8 reserved_3[0x10]; + u8 reserved_at_b0[0x10]; - u8 reserved_4[0x8]; + u8 reserved_at_c0[0x8]; u8 log_max_cq_sz[0x8]; - u8 reserved_5[0xb]; + u8 reserved_at_d0[0xb]; u8 log_max_cq[0x5]; u8 log_max_eq_sz[0x8]; - u8 reserved_6[0x2]; + u8 reserved_at_e8[0x2]; u8 log_max_mkey[0x6]; - u8 reserved_7[0xc]; + u8 reserved_at_f0[0xc]; u8 log_max_eq[0x4]; u8 max_indirection[0x8]; - u8 reserved_8[0x1]; + u8 reserved_at_108[0x1]; u8 log_max_mrw_sz[0x7]; - u8 reserved_9[0x2]; + u8 reserved_at_110[0x2]; u8 log_max_bsf_list_size[0x6]; - u8 reserved_10[0x2]; + u8 reserved_at_118[0x2]; u8 log_max_klm_list_size[0x6]; - u8 reserved_11[0xa]; + u8 reserved_at_120[0xa]; u8 log_max_ra_req_dc[0x6]; - u8 reserved_12[0xa]; + u8 reserved_at_130[0xa]; u8 log_max_ra_res_dc[0x6]; - u8 reserved_13[0xa]; + u8 reserved_at_140[0xa]; u8 log_max_ra_req_qp[0x6]; - u8 reserved_14[0xa]; + u8 reserved_at_150[0xa]; u8 log_max_ra_res_qp[0x6]; u8 pad_cap[0x1]; u8 cc_query_allowed[0x1]; u8 cc_modify_allowed[0x1]; - u8 reserved_15[0xd]; + u8 reserved_at_163[0xd]; u8 gid_table_size[0x10]; u8 out_of_seq_cnt[0x1]; u8 vport_counters[0x1]; - u8 reserved_16[0x4]; + u8 reserved_at_182[0x4]; u8 max_qp_cnt[0xa]; u8 pkey_table_size[0x10]; @@ -716,158 +716,158 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 vhca_group_manager[0x1]; u8 ib_virt[0x1]; u8 eth_virt[0x1]; - u8 reserved_17[0x1]; + u8 reserved_at_1a4[0x1]; u8 ets[0x1]; u8 nic_flow_table[0x1]; u8 eswitch_flow_table[0x1]; u8 early_vf_enable; - u8 reserved_18[0x2]; + u8 reserved_at_1a8[0x2]; u8 local_ca_ack_delay[0x5]; - u8 reserved_19[0x6]; + u8 reserved_at_1af[0x6]; u8 port_type[0x2]; u8 num_ports[0x8]; - u8 reserved_20[0x3]; + u8 reserved_at_1bf[0x3]; u8 log_max_msg[0x5]; - u8 reserved_21[0x18]; + u8 reserved_at_1c7[0x18]; u8 stat_rate_support[0x10]; - u8 reserved_22[0xc]; + u8 reserved_at_1ef[0xc]; u8 cqe_version[0x4]; u8 compact_address_vector[0x1]; - u8 reserved_23[0xe]; + u8 reserved_at_200[0xe]; u8 drain_sigerr[0x1]; u8 cmdif_checksum[0x2]; u8 sigerr_cqe[0x1]; - u8 reserved_24[0x1]; + u8 reserved_at_212[0x1]; u8 wq_signature[0x1]; u8 sctr_data_cqe[0x1]; - u8 reserved_25[0x1]; + u8 reserved_at_215[0x1]; u8 sho[0x1]; u8 tph[0x1]; u8 rf[0x1]; u8 dct[0x1]; - u8 reserved_26[0x1]; + u8 reserved_at_21a[0x1]; u8 eth_net_offloads[0x1]; u8 roce[0x1]; u8 atomic[0x1]; - u8 reserved_27[0x1]; + u8 reserved_at_21e[0x1]; u8 cq_oi[0x1]; u8 cq_resize[0x1]; u8 cq_moderation[0x1]; - u8 reserved_28[0x3]; + u8 reserved_at_222[0x3]; u8 cq_eq_remap[0x1]; u8 pg[0x1]; u8 block_lb_mc[0x1]; - u8 reserved_29[0x1]; + u8 reserved_at_228[0x1]; u8 scqe_break_moderation[0x1]; - u8 reserved_30[0x1]; + u8 reserved_at_22a[0x1]; u8 cd[0x1]; - u8 reserved_31[0x1]; + u8 reserved_at_22c[0x1]; u8 apm[0x1]; - u8 reserved_32[0x7]; + u8 reserved_at_22e[0x7]; u8 qkv[0x1]; u8 pkv[0x1]; - u8 reserved_33[0x4]; + u8 reserved_at_237[0x4]; u8 xrc[0x1]; u8 ud[0x1]; u8 uc[0x1]; u8 rc[0x1]; - u8 reserved_34[0xa]; + u8 reserved_at_23f[0xa]; u8 uar_sz[0x6]; - u8 reserved_35[0x8]; + u8 reserved_at_24f[0x8]; u8 log_pg_sz[0x8]; u8 bf[0x1]; - u8 reserved_36[0x1]; + u8 reserved_at_260[0x1]; u8 pad_tx_eth_packet[0x1]; - u8 reserved_37[0x8]; + u8 reserved_at_262[0x8]; u8 log_bf_reg_size[0x5]; - u8 reserved_38[0x10]; + u8 reserved_at_26f[0x10]; - u8 reserved_39[0x10]; + u8 reserved_at_27f[0x10]; u8 max_wqe_sz_sq[0x10]; - u8 reserved_40[0x10]; + u8 reserved_at_29f[0x10]; u8 max_wqe_sz_rq[0x10]; - u8 reserved_41[0x10]; + u8 reserved_at_2bf[0x10]; u8 max_wqe_sz_sq_dc[0x10]; - u8 reserved_42[0x7]; + u8 reserved_at_2df[0x7]; u8 max_qp_mcg[0x19]; - u8 reserved_43[0x18]; + u8 reserved_at_2ff[0x18]; u8 log_max_mcg[0x8]; - u8 reserved_44[0x3]; + u8 reserved_at_31f[0x3]; u8 log_max_transport_domain[0x5]; - u8 reserved_45[0x3]; + u8 reserved_at_327[0x3]; u8 log_max_pd[0x5]; - u8 reserved_46[0xb]; + u8 reserved_at_32f[0xb]; u8 log_max_xrcd[0x5]; - u8 reserved_47[0x20]; + u8 reserved_at_33f[0x20]; - u8 reserved_48[0x3]; + u8 reserved_at_35f[0x3]; u8 log_max_rq[0x5]; - u8 reserved_49[0x3]; + u8 reserved_at_367[0x3]; u8 log_max_sq[0x5]; - u8 reserved_50[0x3]; + u8 reserved_at_36f[0x3]; u8 log_max_tir[0x5]; - u8 reserved_51[0x3]; + u8 reserved_at_377[0x3]; u8 log_max_tis[0x5]; u8 basic_cyclic_rcv_wqe[0x1]; - u8 reserved_52[0x2]; + u8 reserved_at_380[0x2]; u8 log_max_rmp[0x5]; - u8 reserved_53[0x3]; + u8 reserved_at_387[0x3]; u8 log_max_rqt[0x5]; - u8 reserved_54[0x3]; + u8 reserved_at_38f[0x3]; u8 log_max_rqt_size[0x5]; - u8 reserved_55[0x3]; + u8 reserved_at_397[0x3]; u8 log_max_tis_per_sq[0x5]; - u8 reserved_56[0x3]; + u8 reserved_at_39f[0x3]; u8 log_max_stride_sz_rq[0x5]; - u8 reserved_57[0x3]; + u8 reserved_at_3a7[0x3]; u8 log_min_stride_sz_rq[0x5]; - u8 reserved_58[0x3]; + u8 reserved_at_3af[0x3]; u8 log_max_stride_sz_sq[0x5]; - u8 reserved_59[0x3]; + u8 reserved_at_3b7[0x3]; u8 log_min_stride_sz_sq[0x5]; - u8 reserved_60[0x1b]; + u8 reserved_at_3bf[0x1b]; u8 log_max_wq_sz[0x5]; u8 nic_vport_change_event[0x1]; - u8 reserved_61[0xa]; + u8 reserved_at_3e0[0xa]; u8 log_max_vlan_list[0x5]; - u8 reserved_62[0x3]; + u8 reserved_at_3ef[0x3]; u8 log_max_current_mc_list[0x5]; - u8 reserved_63[0x3]; + u8 reserved_at_3f7[0x3]; u8 log_max_current_uc_list[0x5]; - u8 reserved_64[0x80]; + u8 reserved_at_3ff[0x80]; - u8 reserved_65[0x3]; + u8 reserved_at_47f[0x3]; u8 log_max_l2_table[0x5]; - u8 reserved_66[0x8]; + u8 reserved_at_487[0x8]; u8 log_uar_page_sz[0x10]; - u8 reserved_67[0x20]; + u8 reserved_at_49f[0x20]; u8 device_frequency_mhz[0x20]; u8 device_frequency_khz[0x20]; - u8 reserved_68[0x5f]; + u8 reserved_at_4ff[0x5f]; u8 cqe_zip[0x1]; u8 cqe_zip_timeout[0x10]; u8 cqe_zip_max_num[0x10]; - u8 reserved_69[0x220]; + u8 reserved_at_57f[0x220]; }; enum mlx5_flow_destination_type { @@ -880,7 +880,7 @@ struct mlx5_ifc_dest_format_struct_bits { u8 destination_type[0x8]; u8 destination_id[0x18]; - u8 reserved_0[0x20]; + u8 reserved_at_20[0x20]; }; struct mlx5_ifc_fte_match_param_bits { @@ -890,7 +890,7 @@ struct mlx5_ifc_fte_match_param_bits { struct mlx5_ifc_fte_match_set_lyr_2_4_bits inner_headers; - u8 reserved_0[0xa00]; + u8 reserved_at_600[0xa00]; }; enum { @@ -922,18 +922,18 @@ struct mlx5_ifc_wq_bits { u8 wq_signature[0x1]; u8 end_padding_mode[0x2]; u8 cd_slave[0x1]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 hds_skip_first_sge[0x1]; u8 log2_hds_buf_size[0x3]; - u8 reserved_1[0x7]; + u8 reserved_at_24[0x7]; u8 page_offset[0x5]; u8 lwm[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 pd[0x18]; - u8 reserved_3[0x8]; + u8 reserved_at_60[0x8]; u8 uar_page[0x18]; u8 dbr_addr[0x40]; @@ -942,60 +942,60 @@ struct mlx5_ifc_wq_bits { u8 sw_counter[0x20]; - u8 reserved_4[0xc]; + u8 reserved_at_100[0xc]; u8 log_wq_stride[0x4]; - u8 reserved_5[0x3]; + u8 reserved_at_110[0x3]; u8 log_wq_pg_sz[0x5]; - u8 reserved_6[0x3]; + u8 reserved_at_118[0x3]; u8 log_wq_sz[0x5]; - u8 reserved_7[0x4e0]; + u8 reserved_at_120[0x4e0]; struct mlx5_ifc_cmd_pas_bits pas[0]; }; struct mlx5_ifc_rq_num_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 rq_num[0x18]; }; struct mlx5_ifc_mac_address_layout_bits { - u8 reserved_0[0x10]; + u8 reserved_at_0[0x10]; u8 mac_addr_47_32[0x10]; u8 mac_addr_31_0[0x20]; }; struct mlx5_ifc_vlan_layout_bits { - u8 reserved_0[0x14]; + u8 reserved_at_0[0x14]; u8 vlan[0x0c]; - u8 reserved_1[0x20]; + u8 reserved_at_20[0x20]; }; struct mlx5_ifc_cong_control_r_roce_ecn_np_bits { - u8 reserved_0[0xa0]; + u8 reserved_at_0[0xa0]; u8 min_time_between_cnps[0x20]; - u8 reserved_1[0x12]; + u8 reserved_at_c0[0x12]; u8 cnp_dscp[0x6]; - u8 reserved_2[0x5]; + u8 reserved_at_d8[0x5]; u8 cnp_802p_prio[0x3]; - u8 reserved_3[0x720]; + u8 reserved_at_e0[0x720]; }; struct mlx5_ifc_cong_control_r_roce_ecn_rp_bits { - u8 reserved_0[0x60]; + u8 reserved_at_0[0x60]; - u8 reserved_1[0x4]; + u8 reserved_at_60[0x4]; u8 clamp_tgt_rate[0x1]; - u8 reserved_2[0x3]; + u8 reserved_at_65[0x3]; u8 clamp_tgt_rate_after_time_inc[0x1]; - u8 reserved_3[0x17]; + u8 reserved_at_69[0x17]; - u8 reserved_4[0x20]; + u8 reserved_at_80[0x20]; u8 rpg_time_reset[0x20]; @@ -1015,7 +1015,7 @@ struct mlx5_ifc_cong_control_r_roce_ecn_rp_bits { u8 rpg_min_rate[0x20]; - u8 reserved_5[0xe0]; + u8 reserved_at_1c0[0xe0]; u8 rate_to_set_on_first_cnp[0x20]; @@ -1025,15 +1025,15 @@ struct mlx5_ifc_cong_control_r_roce_ecn_rp_bits { u8 rate_reduce_monitor_period[0x20]; - u8 reserved_6[0x20]; + u8 reserved_at_320[0x20]; u8 initial_alpha_value[0x20]; - u8 reserved_7[0x4a0]; + u8 reserved_at_360[0x4a0]; }; struct mlx5_ifc_cong_control_802_1qau_rp_bits { - u8 reserved_0[0x80]; + u8 reserved_at_0[0x80]; u8 rppp_max_rps[0x20]; @@ -1055,7 +1055,7 @@ struct mlx5_ifc_cong_control_802_1qau_rp_bits { u8 rpg_min_rate[0x20]; - u8 reserved_1[0x640]; + u8 reserved_at_1c0[0x640]; }; enum { @@ -1205,7 +1205,7 @@ struct mlx5_ifc_phys_layer_cntrs_bits { u8 successful_recovery_events[0x20]; - u8 reserved_0[0x180]; + u8 reserved_at_640[0x180]; }; struct mlx5_ifc_eth_per_traffic_grp_data_layout_bits { @@ -1213,7 +1213,7 @@ struct mlx5_ifc_eth_per_traffic_grp_data_layout_bits { u8 transmit_queue_low[0x20]; - u8 reserved_0[0x780]; + u8 reserved_at_40[0x780]; }; struct mlx5_ifc_eth_per_prio_grp_data_layout_bits { @@ -1221,7 +1221,7 @@ struct mlx5_ifc_eth_per_prio_grp_data_layout_bits { u8 rx_octets_low[0x20]; - u8 reserved_0[0xc0]; + u8 reserved_at_40[0xc0]; u8 rx_frames_high[0x20]; @@ -1231,7 +1231,7 @@ struct mlx5_ifc_eth_per_prio_grp_data_layout_bits { u8 tx_octets_low[0x20]; - u8 reserved_1[0xc0]; + u8 reserved_at_180[0xc0]; u8 tx_frames_high[0x20]; @@ -1257,7 +1257,7 @@ struct mlx5_ifc_eth_per_prio_grp_data_layout_bits { u8 rx_pause_transition_low[0x20]; - u8 reserved_2[0x400]; + u8 reserved_at_3c0[0x400]; }; struct mlx5_ifc_eth_extended_cntrs_grp_data_layout_bits { @@ -1265,7 +1265,7 @@ struct mlx5_ifc_eth_extended_cntrs_grp_data_layout_bits { u8 port_transmit_wait_low[0x20]; - u8 reserved_0[0x780]; + u8 reserved_at_40[0x780]; }; struct mlx5_ifc_eth_3635_cntrs_grp_data_layout_bits { @@ -1333,7 +1333,7 @@ struct mlx5_ifc_eth_3635_cntrs_grp_data_layout_bits { u8 dot3out_pause_frames_low[0x20]; - u8 reserved_0[0x3c0]; + u8 reserved_at_400[0x3c0]; }; struct mlx5_ifc_eth_2819_cntrs_grp_data_layout_bits { @@ -1421,7 +1421,7 @@ struct mlx5_ifc_eth_2819_cntrs_grp_data_layout_bits { u8 ether_stats_pkts8192to10239octets_low[0x20]; - u8 reserved_0[0x280]; + u8 reserved_at_540[0x280]; }; struct mlx5_ifc_eth_2863_cntrs_grp_data_layout_bits { @@ -1477,7 +1477,7 @@ struct mlx5_ifc_eth_2863_cntrs_grp_data_layout_bits { u8 if_out_broadcast_pkts_low[0x20]; - u8 reserved_0[0x480]; + u8 reserved_at_340[0x480]; }; struct mlx5_ifc_eth_802_3_cntrs_grp_data_layout_bits { @@ -1557,54 +1557,54 @@ struct mlx5_ifc_eth_802_3_cntrs_grp_data_layout_bits { u8 a_pause_mac_ctrl_frames_transmitted_low[0x20]; - u8 reserved_0[0x300]; + u8 reserved_at_4c0[0x300]; }; struct mlx5_ifc_cmd_inter_comp_event_bits { u8 command_completion_vector[0x20]; - u8 reserved_0[0xc0]; + u8 reserved_at_20[0xc0]; }; struct mlx5_ifc_stall_vl_event_bits { - u8 reserved_0[0x18]; + u8 reserved_at_0[0x18]; u8 port_num[0x1]; - u8 reserved_1[0x3]; + u8 reserved_at_19[0x3]; u8 vl[0x4]; - u8 reserved_2[0xa0]; + u8 reserved_at_20[0xa0]; }; struct mlx5_ifc_db_bf_congestion_event_bits { u8 event_subtype[0x8]; - u8 reserved_0[0x8]; + u8 reserved_at_8[0x8]; u8 congestion_level[0x8]; - u8 reserved_1[0x8]; + u8 reserved_at_18[0x8]; - u8 reserved_2[0xa0]; + u8 reserved_at_20[0xa0]; }; struct mlx5_ifc_gpio_event_bits { - u8 reserved_0[0x60]; + u8 reserved_at_0[0x60]; u8 gpio_event_hi[0x20]; u8 gpio_event_lo[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_a0[0x40]; }; struct mlx5_ifc_port_state_change_event_bits { - u8 reserved_0[0x40]; + u8 reserved_at_0[0x40]; u8 port_num[0x4]; - u8 reserved_1[0x1c]; + u8 reserved_at_44[0x1c]; - u8 reserved_2[0x80]; + u8 reserved_at_60[0x80]; }; struct mlx5_ifc_dropped_packet_logged_bits { - u8 reserved_0[0xe0]; + u8 reserved_at_0[0xe0]; }; enum { @@ -1613,15 +1613,15 @@ enum { }; struct mlx5_ifc_cq_error_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 cqn[0x18]; - u8 reserved_1[0x20]; + u8 reserved_at_20[0x20]; - u8 reserved_2[0x18]; + u8 reserved_at_40[0x18]; u8 syndrome[0x8]; - u8 reserved_3[0x80]; + u8 reserved_at_60[0x80]; }; struct mlx5_ifc_rdma_page_fault_event_bits { @@ -1629,14 +1629,14 @@ struct mlx5_ifc_rdma_page_fault_event_bits { u8 r_key[0x20]; - u8 reserved_0[0x10]; + u8 reserved_at_40[0x10]; u8 packet_len[0x10]; u8 rdma_op_len[0x20]; u8 rdma_va[0x40]; - u8 reserved_1[0x5]; + u8 reserved_at_c0[0x5]; u8 rdma[0x1]; u8 write[0x1]; u8 requestor[0x1]; @@ -1646,15 +1646,15 @@ struct mlx5_ifc_rdma_page_fault_event_bits { struct mlx5_ifc_wqe_associated_page_fault_event_bits { u8 bytes_committed[0x20]; - u8 reserved_0[0x10]; + u8 reserved_at_20[0x10]; u8 wqe_index[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_40[0x10]; u8 len[0x10]; - u8 reserved_2[0x60]; + u8 reserved_at_60[0x60]; - u8 reserved_3[0x5]; + u8 reserved_at_c0[0x5]; u8 rdma[0x1]; u8 write_read[0x1]; u8 requestor[0x1]; @@ -1662,26 +1662,26 @@ struct mlx5_ifc_wqe_associated_page_fault_event_bits { }; struct mlx5_ifc_qp_events_bits { - u8 reserved_0[0xa0]; + u8 reserved_at_0[0xa0]; u8 type[0x8]; - u8 reserved_1[0x18]; + u8 reserved_at_a8[0x18]; - u8 reserved_2[0x8]; + u8 reserved_at_c0[0x8]; u8 qpn_rqn_sqn[0x18]; }; struct mlx5_ifc_dct_events_bits { - u8 reserved_0[0xc0]; + u8 reserved_at_0[0xc0]; - u8 reserved_1[0x8]; + u8 reserved_at_c0[0x8]; u8 dct_number[0x18]; }; struct mlx5_ifc_comp_event_bits { - u8 reserved_0[0xc0]; + u8 reserved_at_0[0xc0]; - u8 reserved_1[0x8]; + u8 reserved_at_c0[0x8]; u8 cq_number[0x18]; }; @@ -1754,41 +1754,41 @@ enum { struct mlx5_ifc_qpc_bits { u8 state[0x4]; - u8 reserved_0[0x4]; + u8 reserved_at_4[0x4]; u8 st[0x8]; - u8 reserved_1[0x3]; + u8 reserved_at_10[0x3]; u8 pm_state[0x2]; - u8 reserved_2[0x7]; + u8 reserved_at_15[0x7]; u8 end_padding_mode[0x2]; - u8 reserved_3[0x2]; + u8 reserved_at_1e[0x2]; u8 wq_signature[0x1]; u8 block_lb_mc[0x1]; u8 atomic_like_write_en[0x1]; u8 latency_sensitive[0x1]; - u8 reserved_4[0x1]; + u8 reserved_at_24[0x1]; u8 drain_sigerr[0x1]; - u8 reserved_5[0x2]; + u8 reserved_at_26[0x2]; u8 pd[0x18]; u8 mtu[0x3]; u8 log_msg_max[0x5]; - u8 reserved_6[0x1]; + u8 reserved_at_48[0x1]; u8 log_rq_size[0x4]; u8 log_rq_stride[0x3]; u8 no_sq[0x1]; u8 log_sq_size[0x4]; - u8 reserved_7[0x6]; + u8 reserved_at_55[0x6]; u8 rlky[0x1]; - u8 reserved_8[0x4]; + u8 reserved_at_5c[0x4]; u8 counter_set_id[0x8]; u8 uar_page[0x18]; - u8 reserved_9[0x8]; + u8 reserved_at_80[0x8]; u8 user_index[0x18]; - u8 reserved_10[0x3]; + u8 reserved_at_a0[0x3]; u8 log_page_size[0x5]; u8 remote_qpn[0x18]; @@ -1797,66 +1797,66 @@ struct mlx5_ifc_qpc_bits { struct mlx5_ifc_ads_bits secondary_address_path; u8 log_ack_req_freq[0x4]; - u8 reserved_11[0x4]; + u8 reserved_at_384[0x4]; u8 log_sra_max[0x3]; - u8 reserved_12[0x2]; + u8 reserved_at_38b[0x2]; u8 retry_count[0x3]; u8 rnr_retry[0x3]; - u8 reserved_13[0x1]; + u8 reserved_at_393[0x1]; u8 fre[0x1]; u8 cur_rnr_retry[0x3]; u8 cur_retry_count[0x3]; - u8 reserved_14[0x5]; + u8 reserved_at_39b[0x5]; - u8 reserved_15[0x20]; + u8 reserved_at_3a0[0x20]; - u8 reserved_16[0x8]; + u8 reserved_at_3c0[0x8]; u8 next_send_psn[0x18]; - u8 reserved_17[0x8]; + u8 reserved_at_3e0[0x8]; u8 cqn_snd[0x18]; - u8 reserved_18[0x40]; + u8 reserved_at_400[0x40]; - u8 reserved_19[0x8]; + u8 reserved_at_440[0x8]; u8 last_acked_psn[0x18]; - u8 reserved_20[0x8]; + u8 reserved_at_460[0x8]; u8 ssn[0x18]; - u8 reserved_21[0x8]; + u8 reserved_at_480[0x8]; u8 log_rra_max[0x3]; - u8 reserved_22[0x1]; + u8 reserved_at_48b[0x1]; u8 atomic_mode[0x4]; u8 rre[0x1]; u8 rwe[0x1]; u8 rae[0x1]; - u8 reserved_23[0x1]; + u8 reserved_at_493[0x1]; u8 page_offset[0x6]; - u8 reserved_24[0x3]; + u8 reserved_at_49a[0x3]; u8 cd_slave_receive[0x1]; u8 cd_slave_send[0x1]; u8 cd_master[0x1]; - u8 reserved_25[0x3]; + u8 reserved_at_4a0[0x3]; u8 min_rnr_nak[0x5]; u8 next_rcv_psn[0x18]; - u8 reserved_26[0x8]; + u8 reserved_at_4c0[0x8]; u8 xrcd[0x18]; - u8 reserved_27[0x8]; + u8 reserved_at_4e0[0x8]; u8 cqn_rcv[0x18]; u8 dbr_addr[0x40]; u8 q_key[0x20]; - u8 reserved_28[0x5]; + u8 reserved_at_560[0x5]; u8 rq_type[0x3]; u8 srqn_rmpn[0x18]; - u8 reserved_29[0x8]; + u8 reserved_at_580[0x8]; u8 rmsn[0x18]; u8 hw_sq_wqebb_counter[0x10]; @@ -1866,33 +1866,33 @@ struct mlx5_ifc_qpc_bits { u8 sw_rq_counter[0x20]; - u8 reserved_30[0x20]; + u8 reserved_at_600[0x20]; - u8 reserved_31[0xf]; + u8 reserved_at_620[0xf]; u8 cgs[0x1]; u8 cs_req[0x8]; u8 cs_res[0x8]; u8 dc_access_key[0x40]; - u8 reserved_32[0xc0]; + u8 reserved_at_680[0xc0]; }; struct mlx5_ifc_roce_addr_layout_bits { u8 source_l3_address[16][0x8]; - u8 reserved_0[0x3]; + u8 reserved_at_80[0x3]; u8 vlan_valid[0x1]; u8 vlan_id[0xc]; u8 source_mac_47_32[0x10]; u8 source_mac_31_0[0x20]; - u8 reserved_1[0x14]; + u8 reserved_at_c0[0x14]; u8 roce_l3_type[0x4]; u8 roce_version[0x8]; - u8 reserved_2[0x20]; + u8 reserved_at_e0[0x20]; }; union mlx5_ifc_hca_cap_union_bits { @@ -1904,7 +1904,7 @@ union mlx5_ifc_hca_cap_union_bits { struct mlx5_ifc_flow_table_nic_cap_bits flow_table_nic_cap; struct mlx5_ifc_flow_table_eswitch_cap_bits flow_table_eswitch_cap; struct mlx5_ifc_e_switch_cap_bits e_switch_cap; - u8 reserved_0[0x8000]; + u8 reserved_at_0[0x8000]; }; enum { @@ -1914,24 +1914,24 @@ enum { }; struct mlx5_ifc_flow_context_bits { - u8 reserved_0[0x20]; + u8 reserved_at_0[0x20]; u8 group_id[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 flow_tag[0x18]; - u8 reserved_2[0x10]; + u8 reserved_at_60[0x10]; u8 action[0x10]; - u8 reserved_3[0x8]; + u8 reserved_at_80[0x8]; u8 destination_list_size[0x18]; - u8 reserved_4[0x160]; + u8 reserved_at_a0[0x160]; struct mlx5_ifc_fte_match_param_bits match_value; - u8 reserved_5[0x600]; + u8 reserved_at_1200[0x600]; struct mlx5_ifc_dest_format_struct_bits destination[0]; }; @@ -1944,43 +1944,43 @@ enum { struct mlx5_ifc_xrc_srqc_bits { u8 state[0x4]; u8 log_xrc_srq_size[0x4]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 wq_signature[0x1]; u8 cont_srq[0x1]; - u8 reserved_1[0x1]; + u8 reserved_at_22[0x1]; u8 rlky[0x1]; u8 basic_cyclic_rcv_wqe[0x1]; u8 log_rq_stride[0x3]; u8 xrcd[0x18]; u8 page_offset[0x6]; - u8 reserved_2[0x2]; + u8 reserved_at_46[0x2]; u8 cqn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; u8 user_index_equal_xrc_srqn[0x1]; - u8 reserved_4[0x1]; + u8 reserved_at_81[0x1]; u8 log_page_size[0x6]; u8 user_index[0x18]; - u8 reserved_5[0x20]; + u8 reserved_at_a0[0x20]; - u8 reserved_6[0x8]; + u8 reserved_at_c0[0x8]; u8 pd[0x18]; u8 lwm[0x10]; u8 wqe_cnt[0x10]; - u8 reserved_7[0x40]; + u8 reserved_at_100[0x40]; u8 db_record_addr_h[0x20]; u8 db_record_addr_l[0x1e]; - u8 reserved_8[0x2]; + u8 reserved_at_17e[0x2]; - u8 reserved_9[0x80]; + u8 reserved_at_180[0x80]; }; struct mlx5_ifc_traffic_counter_bits { @@ -1990,16 +1990,16 @@ struct mlx5_ifc_traffic_counter_bits { }; struct mlx5_ifc_tisc_bits { - u8 reserved_0[0xc]; + u8 reserved_at_0[0xc]; u8 prio[0x4]; - u8 reserved_1[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_2[0x100]; + u8 reserved_at_20[0x100]; - u8 reserved_3[0x8]; + u8 reserved_at_120[0x8]; u8 transport_domain[0x18]; - u8 reserved_4[0x3c0]; + u8 reserved_at_140[0x3c0]; }; enum { @@ -2024,31 +2024,31 @@ enum { }; struct mlx5_ifc_tirc_bits { - u8 reserved_0[0x20]; + u8 reserved_at_0[0x20]; u8 disp_type[0x4]; - u8 reserved_1[0x1c]; + u8 reserved_at_24[0x1c]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; - u8 reserved_3[0x4]; + u8 reserved_at_80[0x4]; u8 lro_timeout_period_usecs[0x10]; u8 lro_enable_mask[0x4]; u8 lro_max_ip_payload_size[0x8]; - u8 reserved_4[0x40]; + u8 reserved_at_a0[0x40]; - u8 reserved_5[0x8]; + u8 reserved_at_e0[0x8]; u8 inline_rqn[0x18]; u8 rx_hash_symmetric[0x1]; - u8 reserved_6[0x1]; + u8 reserved_at_101[0x1]; u8 tunneled_offload_en[0x1]; - u8 reserved_7[0x5]; + u8 reserved_at_103[0x5]; u8 indirect_table[0x18]; u8 rx_hash_fn[0x4]; - u8 reserved_8[0x2]; + u8 reserved_at_124[0x2]; u8 self_lb_block[0x2]; u8 transport_domain[0x18]; @@ -2058,7 +2058,7 @@ struct mlx5_ifc_tirc_bits { struct mlx5_ifc_rx_hash_field_select_bits rx_hash_field_selector_inner; - u8 reserved_9[0x4c0]; + u8 reserved_at_2c0[0x4c0]; }; enum { @@ -2069,39 +2069,39 @@ enum { struct mlx5_ifc_srqc_bits { u8 state[0x4]; u8 log_srq_size[0x4]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 wq_signature[0x1]; u8 cont_srq[0x1]; - u8 reserved_1[0x1]; + u8 reserved_at_22[0x1]; u8 rlky[0x1]; - u8 reserved_2[0x1]; + u8 reserved_at_24[0x1]; u8 log_rq_stride[0x3]; u8 xrcd[0x18]; u8 page_offset[0x6]; - u8 reserved_3[0x2]; + u8 reserved_at_46[0x2]; u8 cqn[0x18]; - u8 reserved_4[0x20]; + u8 reserved_at_60[0x20]; - u8 reserved_5[0x2]; + u8 reserved_at_80[0x2]; u8 log_page_size[0x6]; - u8 reserved_6[0x18]; + u8 reserved_at_88[0x18]; - u8 reserved_7[0x20]; + u8 reserved_at_a0[0x20]; - u8 reserved_8[0x8]; + u8 reserved_at_c0[0x8]; u8 pd[0x18]; u8 lwm[0x10]; u8 wqe_cnt[0x10]; - u8 reserved_9[0x40]; + u8 reserved_at_100[0x40]; u8 dbr_addr[0x40]; - u8 reserved_10[0x80]; + u8 reserved_at_180[0x80]; }; enum { @@ -2115,39 +2115,39 @@ struct mlx5_ifc_sqc_bits { u8 cd_master[0x1]; u8 fre[0x1]; u8 flush_in_error_en[0x1]; - u8 reserved_0[0x4]; + u8 reserved_at_4[0x4]; u8 state[0x4]; - u8 reserved_1[0x14]; + u8 reserved_at_c[0x14]; - u8 reserved_2[0x8]; + u8 reserved_at_20[0x8]; u8 user_index[0x18]; - u8 reserved_3[0x8]; + u8 reserved_at_40[0x8]; u8 cqn[0x18]; - u8 reserved_4[0xa0]; + u8 reserved_at_60[0xa0]; u8 tis_lst_sz[0x10]; - u8 reserved_5[0x10]; + u8 reserved_at_110[0x10]; - u8 reserved_6[0x40]; + u8 reserved_at_120[0x40]; - u8 reserved_7[0x8]; + u8 reserved_at_160[0x8]; u8 tis_num_0[0x18]; struct mlx5_ifc_wq_bits wq; }; struct mlx5_ifc_rqtc_bits { - u8 reserved_0[0xa0]; + u8 reserved_at_0[0xa0]; - u8 reserved_1[0x10]; + u8 reserved_at_a0[0x10]; u8 rqt_max_size[0x10]; - u8 reserved_2[0x10]; + u8 reserved_at_c0[0x10]; u8 rqt_actual_size[0x10]; - u8 reserved_3[0x6a0]; + u8 reserved_at_e0[0x6a0]; struct mlx5_ifc_rq_num_bits rq_num[0]; }; @@ -2165,27 +2165,27 @@ enum { struct mlx5_ifc_rqc_bits { u8 rlky[0x1]; - u8 reserved_0[0x2]; + u8 reserved_at_1[0x2]; u8 vsd[0x1]; u8 mem_rq_type[0x4]; u8 state[0x4]; - u8 reserved_1[0x1]; + u8 reserved_at_c[0x1]; u8 flush_in_error_en[0x1]; - u8 reserved_2[0x12]; + u8 reserved_at_e[0x12]; - u8 reserved_3[0x8]; + u8 reserved_at_20[0x8]; u8 user_index[0x18]; - u8 reserved_4[0x8]; + u8 reserved_at_40[0x8]; u8 cqn[0x18]; u8 counter_set_id[0x8]; - u8 reserved_5[0x18]; + u8 reserved_at_68[0x18]; - u8 reserved_6[0x8]; + u8 reserved_at_80[0x8]; u8 rmpn[0x18]; - u8 reserved_7[0xe0]; + u8 reserved_at_a0[0xe0]; struct mlx5_ifc_wq_bits wq; }; @@ -2196,31 +2196,31 @@ enum { }; struct mlx5_ifc_rmpc_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 state[0x4]; - u8 reserved_1[0x14]; + u8 reserved_at_c[0x14]; u8 basic_cyclic_rcv_wqe[0x1]; - u8 reserved_2[0x1f]; + u8 reserved_at_21[0x1f]; - u8 reserved_3[0x140]; + u8 reserved_at_40[0x140]; struct mlx5_ifc_wq_bits wq; }; struct mlx5_ifc_nic_vport_context_bits { - u8 reserved_0[0x1f]; + u8 reserved_at_0[0x1f]; u8 roce_en[0x1]; u8 arm_change_event[0x1]; - u8 reserved_1[0x1a]; + u8 reserved_at_21[0x1a]; u8 event_on_mtu[0x1]; u8 event_on_promisc_change[0x1]; u8 event_on_vlan_change[0x1]; u8 event_on_mc_address_change[0x1]; u8 event_on_uc_address_change[0x1]; - u8 reserved_2[0xf0]; + u8 reserved_at_40[0xf0]; u8 mtu[0x10]; @@ -2228,21 +2228,21 @@ struct mlx5_ifc_nic_vport_context_bits { u8 port_guid[0x40]; u8 node_guid[0x40]; - u8 reserved_3[0x140]; + u8 reserved_at_200[0x140]; u8 qkey_violation_counter[0x10]; - u8 reserved_4[0x430]; + u8 reserved_at_350[0x430]; u8 promisc_uc[0x1]; u8 promisc_mc[0x1]; u8 promisc_all[0x1]; - u8 reserved_5[0x2]; + u8 reserved_at_783[0x2]; u8 allowed_list_type[0x3]; - u8 reserved_6[0xc]; + u8 reserved_at_788[0xc]; u8 allowed_list_size[0xc]; struct mlx5_ifc_mac_address_layout_bits permanent_address; - u8 reserved_7[0x20]; + u8 reserved_at_7e0[0x20]; u8 current_uc_mac_address[0][0x40]; }; @@ -2254,9 +2254,9 @@ enum { }; struct mlx5_ifc_mkc_bits { - u8 reserved_0[0x1]; + u8 reserved_at_0[0x1]; u8 free[0x1]; - u8 reserved_1[0xd]; + u8 reserved_at_2[0xd]; u8 small_fence_on_rdma_read_response[0x1]; u8 umr_en[0x1]; u8 a[0x1]; @@ -2265,19 +2265,19 @@ struct mlx5_ifc_mkc_bits { u8 lw[0x1]; u8 lr[0x1]; u8 access_mode[0x2]; - u8 reserved_2[0x8]; + u8 reserved_at_18[0x8]; u8 qpn[0x18]; u8 mkey_7_0[0x8]; - u8 reserved_3[0x20]; + u8 reserved_at_40[0x20]; u8 length64[0x1]; u8 bsf_en[0x1]; u8 sync_umr[0x1]; - u8 reserved_4[0x2]; + u8 reserved_at_63[0x2]; u8 expected_sigerr_count[0x1]; - u8 reserved_5[0x1]; + u8 reserved_at_66[0x1]; u8 en_rinval[0x1]; u8 pd[0x18]; @@ -2287,18 +2287,18 @@ struct mlx5_ifc_mkc_bits { u8 bsf_octword_size[0x20]; - u8 reserved_6[0x80]; + u8 reserved_at_120[0x80]; u8 translations_octword_size[0x20]; - u8 reserved_7[0x1b]; + u8 reserved_at_1c0[0x1b]; u8 log_page_size[0x5]; - u8 reserved_8[0x20]; + u8 reserved_at_1e0[0x20]; }; struct mlx5_ifc_pkey_bits { - u8 reserved_0[0x10]; + u8 reserved_at_0[0x10]; u8 pkey[0x10]; }; @@ -2309,19 +2309,19 @@ struct mlx5_ifc_array128_auto_bits { struct mlx5_ifc_hca_vport_context_bits { u8 field_select[0x20]; - u8 reserved_0[0xe0]; + u8 reserved_at_20[0xe0]; u8 sm_virt_aware[0x1]; u8 has_smi[0x1]; u8 has_raw[0x1]; u8 grh_required[0x1]; - u8 reserved_1[0xc]; + u8 reserved_at_104[0xc]; u8 port_physical_state[0x4]; u8 vport_state_policy[0x4]; u8 port_state[0x4]; u8 vport_state[0x4]; - u8 reserved_2[0x20]; + u8 reserved_at_120[0x20]; u8 system_image_guid[0x40]; @@ -2337,33 +2337,33 @@ struct mlx5_ifc_hca_vport_context_bits { u8 cap_mask2_field_select[0x20]; - u8 reserved_3[0x80]; + u8 reserved_at_280[0x80]; u8 lid[0x10]; - u8 reserved_4[0x4]; + u8 reserved_at_310[0x4]; u8 init_type_reply[0x4]; u8 lmc[0x3]; u8 subnet_timeout[0x5]; u8 sm_lid[0x10]; u8 sm_sl[0x4]; - u8 reserved_5[0xc]; + u8 reserved_at_334[0xc]; u8 qkey_violation_counter[0x10]; u8 pkey_violation_counter[0x10]; - u8 reserved_6[0xca0]; + u8 reserved_at_360[0xca0]; }; struct mlx5_ifc_esw_vport_context_bits { - u8 reserved_0[0x3]; + u8 reserved_at_0[0x3]; u8 vport_svlan_strip[0x1]; u8 vport_cvlan_strip[0x1]; u8 vport_svlan_insert[0x1]; u8 vport_cvlan_insert[0x2]; - u8 reserved_1[0x18]; + u8 reserved_at_8[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_20[0x20]; u8 svlan_cfi[0x1]; u8 svlan_pcp[0x3]; @@ -2372,7 +2372,7 @@ struct mlx5_ifc_esw_vport_context_bits { u8 cvlan_pcp[0x3]; u8 cvlan_id[0xc]; - u8 reserved_3[0x7a0]; + u8 reserved_at_60[0x7a0]; }; enum { @@ -2387,41 +2387,41 @@ enum { struct mlx5_ifc_eqc_bits { u8 status[0x4]; - u8 reserved_0[0x9]; + u8 reserved_at_4[0x9]; u8 ec[0x1]; u8 oi[0x1]; - u8 reserved_1[0x5]; + u8 reserved_at_f[0x5]; u8 st[0x4]; - u8 reserved_2[0x8]; + u8 reserved_at_18[0x8]; - u8 reserved_3[0x20]; + u8 reserved_at_20[0x20]; - u8 reserved_4[0x14]; + u8 reserved_at_40[0x14]; u8 page_offset[0x6]; - u8 reserved_5[0x6]; + u8 reserved_at_5a[0x6]; - u8 reserved_6[0x3]; + u8 reserved_at_60[0x3]; u8 log_eq_size[0x5]; u8 uar_page[0x18]; - u8 reserved_7[0x20]; + u8 reserved_at_80[0x20]; - u8 reserved_8[0x18]; + u8 reserved_at_a0[0x18]; u8 intr[0x8]; - u8 reserved_9[0x3]; + u8 reserved_at_c0[0x3]; u8 log_page_size[0x5]; - u8 reserved_10[0x18]; + u8 reserved_at_c8[0x18]; - u8 reserved_11[0x60]; + u8 reserved_at_e0[0x60]; - u8 reserved_12[0x8]; + u8 reserved_at_140[0x8]; u8 consumer_counter[0x18]; - u8 reserved_13[0x8]; + u8 reserved_at_160[0x8]; u8 producer_counter[0x18]; - u8 reserved_14[0x80]; + u8 reserved_at_180[0x80]; }; enum { @@ -2445,14 +2445,14 @@ enum { }; struct mlx5_ifc_dctc_bits { - u8 reserved_0[0x4]; + u8 reserved_at_0[0x4]; u8 state[0x4]; - u8 reserved_1[0x18]; + u8 reserved_at_8[0x18]; - u8 reserved_2[0x8]; + u8 reserved_at_20[0x8]; u8 user_index[0x18]; - u8 reserved_3[0x8]; + u8 reserved_at_40[0x8]; u8 cqn[0x18]; u8 counter_set_id[0x8]; @@ -2464,45 +2464,45 @@ struct mlx5_ifc_dctc_bits { u8 latency_sensitive[0x1]; u8 rlky[0x1]; u8 free_ar[0x1]; - u8 reserved_4[0xd]; + u8 reserved_at_73[0xd]; - u8 reserved_5[0x8]; + u8 reserved_at_80[0x8]; u8 cs_res[0x8]; - u8 reserved_6[0x3]; + u8 reserved_at_90[0x3]; u8 min_rnr_nak[0x5]; - u8 reserved_7[0x8]; + u8 reserved_at_98[0x8]; - u8 reserved_8[0x8]; + u8 reserved_at_a0[0x8]; u8 srqn[0x18]; - u8 reserved_9[0x8]; + u8 reserved_at_c0[0x8]; u8 pd[0x18]; u8 tclass[0x8]; - u8 reserved_10[0x4]; + u8 reserved_at_e8[0x4]; u8 flow_label[0x14]; u8 dc_access_key[0x40]; - u8 reserved_11[0x5]; + u8 reserved_at_140[0x5]; u8 mtu[0x3]; u8 port[0x8]; u8 pkey_index[0x10]; - u8 reserved_12[0x8]; + u8 reserved_at_160[0x8]; u8 my_addr_index[0x8]; - u8 reserved_13[0x8]; + u8 reserved_at_170[0x8]; u8 hop_limit[0x8]; u8 dc_access_key_violation_count[0x20]; - u8 reserved_14[0x14]; + u8 reserved_at_1a0[0x14]; u8 dei_cfi[0x1]; u8 eth_prio[0x3]; u8 ecn[0x2]; u8 dscp[0x6]; - u8 reserved_15[0x40]; + u8 reserved_at_1c0[0x40]; }; enum { @@ -2524,54 +2524,54 @@ enum { struct mlx5_ifc_cqc_bits { u8 status[0x4]; - u8 reserved_0[0x4]; + u8 reserved_at_4[0x4]; u8 cqe_sz[0x3]; u8 cc[0x1]; - u8 reserved_1[0x1]; + u8 reserved_at_c[0x1]; u8 scqe_break_moderation_en[0x1]; u8 oi[0x1]; - u8 reserved_2[0x2]; + u8 reserved_at_f[0x2]; u8 cqe_zip_en[0x1]; u8 mini_cqe_res_format[0x2]; u8 st[0x4]; - u8 reserved_3[0x8]; + u8 reserved_at_18[0x8]; - u8 reserved_4[0x20]; + u8 reserved_at_20[0x20]; - u8 reserved_5[0x14]; + u8 reserved_at_40[0x14]; u8 page_offset[0x6]; - u8 reserved_6[0x6]; + u8 reserved_at_5a[0x6]; - u8 reserved_7[0x3]; + u8 reserved_at_60[0x3]; u8 log_cq_size[0x5]; u8 uar_page[0x18]; - u8 reserved_8[0x4]; + u8 reserved_at_80[0x4]; u8 cq_period[0xc]; u8 cq_max_count[0x10]; - u8 reserved_9[0x18]; + u8 reserved_at_a0[0x18]; u8 c_eqn[0x8]; - u8 reserved_10[0x3]; + u8 reserved_at_c0[0x3]; u8 log_page_size[0x5]; - u8 reserved_11[0x18]; + u8 reserved_at_c8[0x18]; - u8 reserved_12[0x20]; + u8 reserved_at_e0[0x20]; - u8 reserved_13[0x8]; + u8 reserved_at_100[0x8]; u8 last_notified_index[0x18]; - u8 reserved_14[0x8]; + u8 reserved_at_120[0x8]; u8 last_solicit_index[0x18]; - u8 reserved_15[0x8]; + u8 reserved_at_140[0x8]; u8 consumer_counter[0x18]; - u8 reserved_16[0x8]; + u8 reserved_at_160[0x8]; u8 producer_counter[0x18]; - u8 reserved_17[0x40]; + u8 reserved_at_180[0x40]; u8 dbr_addr[0x40]; }; @@ -2580,16 +2580,16 @@ union mlx5_ifc_cong_control_roce_ecn_auto_bits { struct mlx5_ifc_cong_control_802_1qau_rp_bits cong_control_802_1qau_rp; struct mlx5_ifc_cong_control_r_roce_ecn_rp_bits cong_control_r_roce_ecn_rp; struct mlx5_ifc_cong_control_r_roce_ecn_np_bits cong_control_r_roce_ecn_np; - u8 reserved_0[0x800]; + u8 reserved_at_0[0x800]; }; struct mlx5_ifc_query_adapter_param_block_bits { - u8 reserved_0[0xc0]; + u8 reserved_at_0[0xc0]; - u8 reserved_1[0x8]; + u8 reserved_at_c0[0x8]; u8 ieee_vendor_id[0x18]; - u8 reserved_2[0x10]; + u8 reserved_at_e0[0x10]; u8 vsd_vendor_id[0x10]; u8 vsd[208][0x8]; @@ -2600,14 +2600,14 @@ struct mlx5_ifc_query_adapter_param_block_bits { union mlx5_ifc_modify_field_select_resize_field_select_auto_bits { struct mlx5_ifc_modify_field_select_bits modify_field_select; struct mlx5_ifc_resize_field_select_bits resize_field_select; - u8 reserved_0[0x20]; + u8 reserved_at_0[0x20]; }; union mlx5_ifc_field_select_802_1_r_roce_auto_bits { struct mlx5_ifc_field_select_802_1qau_rp_bits field_select_802_1qau_rp; struct mlx5_ifc_field_select_r_roce_rp_bits field_select_r_roce_rp; struct mlx5_ifc_field_select_r_roce_np_bits field_select_r_roce_np; - u8 reserved_0[0x20]; + u8 reserved_at_0[0x20]; }; union mlx5_ifc_eth_cntrs_grp_data_layout_auto_bits { @@ -2619,7 +2619,7 @@ union mlx5_ifc_eth_cntrs_grp_data_layout_auto_bits { struct mlx5_ifc_eth_per_prio_grp_data_layout_bits eth_per_prio_grp_data_layout; struct mlx5_ifc_eth_per_traffic_grp_data_layout_bits eth_per_traffic_grp_data_layout; struct mlx5_ifc_phys_layer_cntrs_bits phys_layer_cntrs; - u8 reserved_0[0x7c0]; + u8 reserved_at_0[0x7c0]; }; union mlx5_ifc_event_auto_bits { @@ -2635,23 +2635,23 @@ union mlx5_ifc_event_auto_bits { struct mlx5_ifc_db_bf_congestion_event_bits db_bf_congestion_event; struct mlx5_ifc_stall_vl_event_bits stall_vl_event; struct mlx5_ifc_cmd_inter_comp_event_bits cmd_inter_comp_event; - u8 reserved_0[0xe0]; + u8 reserved_at_0[0xe0]; }; struct mlx5_ifc_health_buffer_bits { - u8 reserved_0[0x100]; + u8 reserved_at_0[0x100]; u8 assert_existptr[0x20]; u8 assert_callra[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_140[0x40]; u8 fw_version[0x20]; u8 hw_id[0x20]; - u8 reserved_2[0x20]; + u8 reserved_at_1c0[0x20]; u8 irisc_index[0x8]; u8 synd[0x8]; @@ -2660,20 +2660,20 @@ struct mlx5_ifc_health_buffer_bits { struct mlx5_ifc_register_loopback_control_bits { u8 no_lb[0x1]; - u8 reserved_0[0x7]; + u8 reserved_at_1[0x7]; u8 port[0x8]; - u8 reserved_1[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_2[0x60]; + u8 reserved_at_20[0x60]; }; struct mlx5_ifc_teardown_hca_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; enum { @@ -2683,108 +2683,108 @@ enum { struct mlx5_ifc_teardown_hca_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x10]; + u8 reserved_at_40[0x10]; u8 profile[0x10]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_sqerr2rts_qp_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_sqerr2rts_qp_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 qpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; u8 opt_param_mask[0x20]; - u8 reserved_4[0x20]; + u8 reserved_at_a0[0x20]; struct mlx5_ifc_qpc_bits qpc; - u8 reserved_5[0x80]; + u8 reserved_at_800[0x80]; }; struct mlx5_ifc_sqd2rts_qp_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_sqd2rts_qp_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 qpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; u8 opt_param_mask[0x20]; - u8 reserved_4[0x20]; + u8 reserved_at_a0[0x20]; struct mlx5_ifc_qpc_bits qpc; - u8 reserved_5[0x80]; + u8 reserved_at_800[0x80]; }; struct mlx5_ifc_set_roce_address_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_set_roce_address_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 roce_address_index[0x10]; - u8 reserved_2[0x10]; + u8 reserved_at_50[0x10]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; struct mlx5_ifc_roce_addr_layout_bits roce_address; }; struct mlx5_ifc_set_mad_demux_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; enum { @@ -2794,89 +2794,89 @@ enum { struct mlx5_ifc_set_mad_demux_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x20]; + u8 reserved_at_40[0x20]; - u8 reserved_3[0x6]; + u8 reserved_at_60[0x6]; u8 demux_mode[0x2]; - u8 reserved_4[0x18]; + u8 reserved_at_68[0x18]; }; struct mlx5_ifc_set_l2_table_entry_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_set_l2_table_entry_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x60]; + u8 reserved_at_40[0x60]; - u8 reserved_3[0x8]; + u8 reserved_at_a0[0x8]; u8 table_index[0x18]; - u8 reserved_4[0x20]; + u8 reserved_at_c0[0x20]; - u8 reserved_5[0x13]; + u8 reserved_at_e0[0x13]; u8 vlan_valid[0x1]; u8 vlan[0xc]; struct mlx5_ifc_mac_address_layout_bits mac_address; - u8 reserved_6[0xc0]; + u8 reserved_at_140[0xc0]; }; struct mlx5_ifc_set_issi_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_set_issi_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x10]; + u8 reserved_at_40[0x10]; u8 current_issi[0x10]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_set_hca_cap_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_set_hca_cap_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; union mlx5_ifc_hca_cap_union_bits capability; }; @@ -2890,156 +2890,156 @@ enum { struct mlx5_ifc_set_fte_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_set_fte_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; u8 table_type[0x8]; - u8 reserved_3[0x18]; + u8 reserved_at_88[0x18]; - u8 reserved_4[0x8]; + u8 reserved_at_a0[0x8]; u8 table_id[0x18]; - u8 reserved_5[0x18]; + u8 reserved_at_c0[0x18]; u8 modify_enable_mask[0x8]; - u8 reserved_6[0x20]; + u8 reserved_at_e0[0x20]; u8 flow_index[0x20]; - u8 reserved_7[0xe0]; + u8 reserved_at_120[0xe0]; struct mlx5_ifc_flow_context_bits flow_context; }; struct mlx5_ifc_rts2rts_qp_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_rts2rts_qp_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 qpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; u8 opt_param_mask[0x20]; - u8 reserved_4[0x20]; + u8 reserved_at_a0[0x20]; struct mlx5_ifc_qpc_bits qpc; - u8 reserved_5[0x80]; + u8 reserved_at_800[0x80]; }; struct mlx5_ifc_rtr2rts_qp_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_rtr2rts_qp_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 qpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; u8 opt_param_mask[0x20]; - u8 reserved_4[0x20]; + u8 reserved_at_a0[0x20]; struct mlx5_ifc_qpc_bits qpc; - u8 reserved_5[0x80]; + u8 reserved_at_800[0x80]; }; struct mlx5_ifc_rst2init_qp_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_rst2init_qp_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 qpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; u8 opt_param_mask[0x20]; - u8 reserved_4[0x20]; + u8 reserved_at_a0[0x20]; struct mlx5_ifc_qpc_bits qpc; - u8 reserved_5[0x80]; + u8 reserved_at_800[0x80]; }; struct mlx5_ifc_query_xrc_srq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_xrc_srqc_bits xrc_srq_context_entry; - u8 reserved_2[0x600]; + u8 reserved_at_280[0x600]; u8 pas[0][0x40]; }; struct mlx5_ifc_query_xrc_srq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 xrc_srqn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; enum { @@ -3049,13 +3049,13 @@ enum { struct mlx5_ifc_query_vport_state_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x20]; + u8 reserved_at_40[0x20]; - u8 reserved_2[0x18]; + u8 reserved_at_60[0x18]; u8 admin_state[0x4]; u8 state[0x4]; }; @@ -3067,25 +3067,25 @@ enum { struct mlx5_ifc_query_vport_state_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 other_vport[0x1]; - u8 reserved_2[0xf]; + u8 reserved_at_41[0xf]; u8 vport_number[0x10]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_vport_counter_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_traffic_counter_bits received_errors; @@ -3111,7 +3111,7 @@ struct mlx5_ifc_query_vport_counter_out_bits { struct mlx5_ifc_traffic_counter_bits transmitted_eth_multicast; - u8 reserved_2[0xa00]; + u8 reserved_at_680[0xa00]; }; enum { @@ -3120,328 +3120,328 @@ enum { struct mlx5_ifc_query_vport_counter_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 other_vport[0x1]; - u8 reserved_2[0xf]; + u8 reserved_at_41[0xf]; u8 vport_number[0x10]; - u8 reserved_3[0x60]; + u8 reserved_at_60[0x60]; u8 clear[0x1]; - u8 reserved_4[0x1f]; + u8 reserved_at_c1[0x1f]; - u8 reserved_5[0x20]; + u8 reserved_at_e0[0x20]; }; struct mlx5_ifc_query_tis_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_tisc_bits tis_context; }; struct mlx5_ifc_query_tis_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 tisn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_tir_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0xc0]; + u8 reserved_at_40[0xc0]; struct mlx5_ifc_tirc_bits tir_context; }; struct mlx5_ifc_query_tir_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 tirn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_srq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_srqc_bits srq_context_entry; - u8 reserved_2[0x600]; + u8 reserved_at_280[0x600]; u8 pas[0][0x40]; }; struct mlx5_ifc_query_srq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 srqn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_sq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0xc0]; + u8 reserved_at_40[0xc0]; struct mlx5_ifc_sqc_bits sq_context; }; struct mlx5_ifc_query_sq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 sqn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_special_contexts_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x20]; + u8 reserved_at_40[0x20]; u8 resd_lkey[0x20]; }; struct mlx5_ifc_query_special_contexts_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_query_rqt_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0xc0]; + u8 reserved_at_40[0xc0]; struct mlx5_ifc_rqtc_bits rqt_context; }; struct mlx5_ifc_query_rqt_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 rqtn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_rq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0xc0]; + u8 reserved_at_40[0xc0]; struct mlx5_ifc_rqc_bits rq_context; }; struct mlx5_ifc_query_rq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 rqn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_roce_address_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_roce_addr_layout_bits roce_address; }; struct mlx5_ifc_query_roce_address_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 roce_address_index[0x10]; - u8 reserved_2[0x10]; + u8 reserved_at_50[0x10]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_rmp_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0xc0]; + u8 reserved_at_40[0xc0]; struct mlx5_ifc_rmpc_bits rmp_context; }; struct mlx5_ifc_query_rmp_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 rmpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_qp_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; u8 opt_param_mask[0x20]; - u8 reserved_2[0x20]; + u8 reserved_at_a0[0x20]; struct mlx5_ifc_qpc_bits qpc; - u8 reserved_3[0x80]; + u8 reserved_at_800[0x80]; u8 pas[0][0x40]; }; struct mlx5_ifc_query_qp_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 qpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_q_counter_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; u8 rx_write_requests[0x20]; - u8 reserved_2[0x20]; + u8 reserved_at_a0[0x20]; u8 rx_read_requests[0x20]; - u8 reserved_3[0x20]; + u8 reserved_at_e0[0x20]; u8 rx_atomic_requests[0x20]; - u8 reserved_4[0x20]; + u8 reserved_at_120[0x20]; u8 rx_dct_connect[0x20]; - u8 reserved_5[0x20]; + u8 reserved_at_160[0x20]; u8 out_of_buffer[0x20]; - u8 reserved_6[0x20]; + u8 reserved_at_1a0[0x20]; u8 out_of_sequence[0x20]; - u8 reserved_7[0x620]; + u8 reserved_at_1e0[0x620]; }; struct mlx5_ifc_query_q_counter_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x80]; + u8 reserved_at_40[0x80]; u8 clear[0x1]; - u8 reserved_3[0x1f]; + u8 reserved_at_c1[0x1f]; - u8 reserved_4[0x18]; + u8 reserved_at_e0[0x18]; u8 counter_set_id[0x8]; }; struct mlx5_ifc_query_pages_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x10]; + u8 reserved_at_40[0x10]; u8 function_id[0x10]; u8 num_pages[0x20]; @@ -3455,55 +3455,55 @@ enum { struct mlx5_ifc_query_pages_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x10]; + u8 reserved_at_40[0x10]; u8 function_id[0x10]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_nic_vport_context_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_nic_vport_context_bits nic_vport_context; }; struct mlx5_ifc_query_nic_vport_context_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 other_vport[0x1]; - u8 reserved_2[0xf]; + u8 reserved_at_41[0xf]; u8 vport_number[0x10]; - u8 reserved_3[0x5]; + u8 reserved_at_60[0x5]; u8 allowed_list_type[0x3]; - u8 reserved_4[0x18]; + u8 reserved_at_68[0x18]; }; struct mlx5_ifc_query_mkey_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_mkc_bits memory_key_mkey_entry; - u8 reserved_2[0x600]; + u8 reserved_at_280[0x600]; u8 bsf0_klm0_pas_mtt0_1[16][0x8]; @@ -3512,265 +3512,265 @@ struct mlx5_ifc_query_mkey_out_bits { struct mlx5_ifc_query_mkey_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 mkey_index[0x18]; u8 pg_access[0x1]; - u8 reserved_3[0x1f]; + u8 reserved_at_61[0x1f]; }; struct mlx5_ifc_query_mad_demux_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; u8 mad_dumux_parameters_block[0x20]; }; struct mlx5_ifc_query_mad_demux_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_query_l2_table_entry_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0xa0]; + u8 reserved_at_40[0xa0]; - u8 reserved_2[0x13]; + u8 reserved_at_e0[0x13]; u8 vlan_valid[0x1]; u8 vlan[0xc]; struct mlx5_ifc_mac_address_layout_bits mac_address; - u8 reserved_3[0xc0]; + u8 reserved_at_140[0xc0]; }; struct mlx5_ifc_query_l2_table_entry_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x60]; + u8 reserved_at_40[0x60]; - u8 reserved_3[0x8]; + u8 reserved_at_a0[0x8]; u8 table_index[0x18]; - u8 reserved_4[0x140]; + u8 reserved_at_c0[0x140]; }; struct mlx5_ifc_query_issi_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x10]; + u8 reserved_at_40[0x10]; u8 current_issi[0x10]; - u8 reserved_2[0xa0]; + u8 reserved_at_60[0xa0]; - u8 supported_issi_reserved[76][0x8]; + u8 reserved_at_100[76][0x8]; u8 supported_issi_dw0[0x20]; }; struct mlx5_ifc_query_issi_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_query_hca_vport_pkey_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_pkey_bits pkey[0]; }; struct mlx5_ifc_query_hca_vport_pkey_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 other_vport[0x1]; - u8 reserved_2[0xb]; + u8 reserved_at_41[0xb]; u8 port_num[0x4]; u8 vport_number[0x10]; - u8 reserved_3[0x10]; + u8 reserved_at_60[0x10]; u8 pkey_index[0x10]; }; struct mlx5_ifc_query_hca_vport_gid_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x20]; + u8 reserved_at_40[0x20]; u8 gids_num[0x10]; - u8 reserved_2[0x10]; + u8 reserved_at_70[0x10]; struct mlx5_ifc_array128_auto_bits gid[0]; }; struct mlx5_ifc_query_hca_vport_gid_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 other_vport[0x1]; - u8 reserved_2[0xb]; + u8 reserved_at_41[0xb]; u8 port_num[0x4]; u8 vport_number[0x10]; - u8 reserved_3[0x10]; + u8 reserved_at_60[0x10]; u8 gid_index[0x10]; }; struct mlx5_ifc_query_hca_vport_context_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_hca_vport_context_bits hca_vport_context; }; struct mlx5_ifc_query_hca_vport_context_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 other_vport[0x1]; - u8 reserved_2[0xb]; + u8 reserved_at_41[0xb]; u8 port_num[0x4]; u8 vport_number[0x10]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_hca_cap_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; union mlx5_ifc_hca_cap_union_bits capability; }; struct mlx5_ifc_query_hca_cap_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_query_flow_table_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x80]; + u8 reserved_at_40[0x80]; - u8 reserved_2[0x8]; + u8 reserved_at_c0[0x8]; u8 level[0x8]; - u8 reserved_3[0x8]; + u8 reserved_at_d0[0x8]; u8 log_size[0x8]; - u8 reserved_4[0x120]; + u8 reserved_at_e0[0x120]; }; struct mlx5_ifc_query_flow_table_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; u8 table_type[0x8]; - u8 reserved_3[0x18]; + u8 reserved_at_88[0x18]; - u8 reserved_4[0x8]; + u8 reserved_at_a0[0x8]; u8 table_id[0x18]; - u8 reserved_5[0x140]; + u8 reserved_at_c0[0x140]; }; struct mlx5_ifc_query_fte_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x1c0]; + u8 reserved_at_40[0x1c0]; struct mlx5_ifc_flow_context_bits flow_context; }; struct mlx5_ifc_query_fte_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; u8 table_type[0x8]; - u8 reserved_3[0x18]; + u8 reserved_at_88[0x18]; - u8 reserved_4[0x8]; + u8 reserved_at_a0[0x8]; u8 table_id[0x18]; - u8 reserved_5[0x40]; + u8 reserved_at_c0[0x40]; u8 flow_index[0x20]; - u8 reserved_6[0xe0]; + u8 reserved_at_120[0xe0]; }; enum { @@ -3781,84 +3781,84 @@ enum { struct mlx5_ifc_query_flow_group_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0xa0]; + u8 reserved_at_40[0xa0]; u8 start_flow_index[0x20]; - u8 reserved_2[0x20]; + u8 reserved_at_100[0x20]; u8 end_flow_index[0x20]; - u8 reserved_3[0xa0]; + u8 reserved_at_140[0xa0]; - u8 reserved_4[0x18]; + u8 reserved_at_1e0[0x18]; u8 match_criteria_enable[0x8]; struct mlx5_ifc_fte_match_param_bits match_criteria; - u8 reserved_5[0xe00]; + u8 reserved_at_1200[0xe00]; }; struct mlx5_ifc_query_flow_group_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; u8 table_type[0x8]; - u8 reserved_3[0x18]; + u8 reserved_at_88[0x18]; - u8 reserved_4[0x8]; + u8 reserved_at_a0[0x8]; u8 table_id[0x18]; u8 group_id[0x20]; - u8 reserved_5[0x120]; + u8 reserved_at_e0[0x120]; }; struct mlx5_ifc_query_esw_vport_context_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_esw_vport_context_bits esw_vport_context; }; struct mlx5_ifc_query_esw_vport_context_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 other_vport[0x1]; - u8 reserved_2[0xf]; + u8 reserved_at_41[0xf]; u8 vport_number[0x10]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_modify_esw_vport_context_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_esw_vport_context_fields_select_bits { - u8 reserved[0x1c]; + u8 reserved_at_0[0x1c]; u8 vport_cvlan_insert[0x1]; u8 vport_svlan_insert[0x1]; u8 vport_cvlan_strip[0x1]; @@ -3867,13 +3867,13 @@ struct mlx5_ifc_esw_vport_context_fields_select_bits { struct mlx5_ifc_modify_esw_vport_context_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 other_vport[0x1]; - u8 reserved_2[0xf]; + u8 reserved_at_41[0xf]; u8 vport_number[0x10]; struct mlx5_ifc_esw_vport_context_fields_select_bits field_select; @@ -3883,124 +3883,124 @@ struct mlx5_ifc_modify_esw_vport_context_in_bits { struct mlx5_ifc_query_eq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_eqc_bits eq_context_entry; - u8 reserved_2[0x40]; + u8 reserved_at_280[0x40]; u8 event_bitmask[0x40]; - u8 reserved_3[0x580]; + u8 reserved_at_300[0x580]; u8 pas[0][0x40]; }; struct mlx5_ifc_query_eq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x18]; + u8 reserved_at_40[0x18]; u8 eq_number[0x8]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_dct_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_dctc_bits dct_context_entry; - u8 reserved_2[0x180]; + u8 reserved_at_280[0x180]; }; struct mlx5_ifc_query_dct_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 dctn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_cq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_cqc_bits cq_context; - u8 reserved_2[0x600]; + u8 reserved_at_280[0x600]; u8 pas[0][0x40]; }; struct mlx5_ifc_query_cq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 cqn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_cong_status_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x20]; + u8 reserved_at_40[0x20]; u8 enable[0x1]; u8 tag_enable[0x1]; - u8 reserved_2[0x1e]; + u8 reserved_at_62[0x1e]; }; struct mlx5_ifc_query_cong_status_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x18]; + u8 reserved_at_40[0x18]; u8 priority[0x4]; u8 cong_protocol[0x4]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_cong_statistics_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; u8 cur_flows[0x20]; @@ -4014,7 +4014,7 @@ struct mlx5_ifc_query_cong_statistics_out_bits { u8 cnp_handled_low[0x20]; - u8 reserved_2[0x100]; + u8 reserved_at_140[0x100]; u8 time_stamp_high[0x20]; @@ -4030,453 +4030,453 @@ struct mlx5_ifc_query_cong_statistics_out_bits { u8 cnps_sent_low[0x20]; - u8 reserved_3[0x560]; + u8 reserved_at_320[0x560]; }; struct mlx5_ifc_query_cong_statistics_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 clear[0x1]; - u8 reserved_2[0x1f]; + u8 reserved_at_41[0x1f]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_cong_params_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; union mlx5_ifc_cong_control_roce_ecn_auto_bits congestion_parameters; }; struct mlx5_ifc_query_cong_params_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x1c]; + u8 reserved_at_40[0x1c]; u8 cong_protocol[0x4]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_query_adapter_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_query_adapter_param_block_bits query_adapter_struct; }; struct mlx5_ifc_query_adapter_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_qp_2rst_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_qp_2rst_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 qpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_qp_2err_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_qp_2err_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 qpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_page_fault_resume_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_page_fault_resume_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 error[0x1]; - u8 reserved_2[0x4]; + u8 reserved_at_41[0x4]; u8 rdma[0x1]; u8 read_write[0x1]; u8 req_res[0x1]; u8 qpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_nop_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_nop_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_modify_vport_state_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_modify_vport_state_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 other_vport[0x1]; - u8 reserved_2[0xf]; + u8 reserved_at_41[0xf]; u8 vport_number[0x10]; - u8 reserved_3[0x18]; + u8 reserved_at_60[0x18]; u8 admin_state[0x4]; - u8 reserved_4[0x4]; + u8 reserved_at_7c[0x4]; }; struct mlx5_ifc_modify_tis_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_modify_tis_bitmask_bits { - u8 reserved_0[0x20]; + u8 reserved_at_0[0x20]; - u8 reserved_1[0x1f]; + u8 reserved_at_20[0x1f]; u8 prio[0x1]; }; struct mlx5_ifc_modify_tis_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 tisn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; struct mlx5_ifc_modify_tis_bitmask_bits bitmask; - u8 reserved_4[0x40]; + u8 reserved_at_c0[0x40]; struct mlx5_ifc_tisc_bits ctx; }; struct mlx5_ifc_modify_tir_bitmask_bits { - u8 reserved_0[0x20]; + u8 reserved_at_0[0x20]; - u8 reserved_1[0x1b]; + u8 reserved_at_20[0x1b]; u8 self_lb_en[0x1]; - u8 reserved_2[0x3]; + u8 reserved_at_3c[0x3]; u8 lro[0x1]; }; struct mlx5_ifc_modify_tir_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_modify_tir_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 tirn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; struct mlx5_ifc_modify_tir_bitmask_bits bitmask; - u8 reserved_4[0x40]; + u8 reserved_at_c0[0x40]; struct mlx5_ifc_tirc_bits ctx; }; struct mlx5_ifc_modify_sq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_modify_sq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 sq_state[0x4]; - u8 reserved_2[0x4]; + u8 reserved_at_44[0x4]; u8 sqn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; u8 modify_bitmask[0x40]; - u8 reserved_4[0x40]; + u8 reserved_at_c0[0x40]; struct mlx5_ifc_sqc_bits ctx; }; struct mlx5_ifc_modify_rqt_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_rqt_bitmask_bits { - u8 reserved[0x20]; + u8 reserved_at_0[0x20]; - u8 reserved1[0x1f]; + u8 reserved_at_20[0x1f]; u8 rqn_list[0x1]; }; struct mlx5_ifc_modify_rqt_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 rqtn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; struct mlx5_ifc_rqt_bitmask_bits bitmask; - u8 reserved_4[0x40]; + u8 reserved_at_c0[0x40]; struct mlx5_ifc_rqtc_bits ctx; }; struct mlx5_ifc_modify_rq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_modify_rq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 rq_state[0x4]; - u8 reserved_2[0x4]; + u8 reserved_at_44[0x4]; u8 rqn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; u8 modify_bitmask[0x40]; - u8 reserved_4[0x40]; + u8 reserved_at_c0[0x40]; struct mlx5_ifc_rqc_bits ctx; }; struct mlx5_ifc_modify_rmp_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_rmp_bitmask_bits { - u8 reserved[0x20]; + u8 reserved_at_0[0x20]; - u8 reserved1[0x1f]; + u8 reserved_at_20[0x1f]; u8 lwm[0x1]; }; struct mlx5_ifc_modify_rmp_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 rmp_state[0x4]; - u8 reserved_2[0x4]; + u8 reserved_at_44[0x4]; u8 rmpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; struct mlx5_ifc_rmp_bitmask_bits bitmask; - u8 reserved_4[0x40]; + u8 reserved_at_c0[0x40]; struct mlx5_ifc_rmpc_bits ctx; }; struct mlx5_ifc_modify_nic_vport_context_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_modify_nic_vport_field_select_bits { - u8 reserved_0[0x19]; + u8 reserved_at_0[0x19]; u8 mtu[0x1]; u8 change_event[0x1]; u8 promisc[0x1]; u8 permanent_address[0x1]; u8 addresses_list[0x1]; u8 roce_en[0x1]; - u8 reserved_1[0x1]; + u8 reserved_at_1f[0x1]; }; struct mlx5_ifc_modify_nic_vport_context_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 other_vport[0x1]; - u8 reserved_2[0xf]; + u8 reserved_at_41[0xf]; u8 vport_number[0x10]; struct mlx5_ifc_modify_nic_vport_field_select_bits field_select; - u8 reserved_3[0x780]; + u8 reserved_at_80[0x780]; struct mlx5_ifc_nic_vport_context_bits nic_vport_context; }; struct mlx5_ifc_modify_hca_vport_context_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_modify_hca_vport_context_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 other_vport[0x1]; - u8 reserved_2[0xb]; + u8 reserved_at_41[0xb]; u8 port_num[0x4]; u8 vport_number[0x10]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; struct mlx5_ifc_hca_vport_context_bits hca_vport_context; }; struct mlx5_ifc_modify_cq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; enum { @@ -4486,83 +4486,83 @@ enum { struct mlx5_ifc_modify_cq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 cqn[0x18]; union mlx5_ifc_modify_field_select_resize_field_select_auto_bits modify_field_select_resize_field_select; struct mlx5_ifc_cqc_bits cq_context; - u8 reserved_3[0x600]; + u8 reserved_at_280[0x600]; u8 pas[0][0x40]; }; struct mlx5_ifc_modify_cong_status_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_modify_cong_status_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x18]; + u8 reserved_at_40[0x18]; u8 priority[0x4]; u8 cong_protocol[0x4]; u8 enable[0x1]; u8 tag_enable[0x1]; - u8 reserved_3[0x1e]; + u8 reserved_at_62[0x1e]; }; struct mlx5_ifc_modify_cong_params_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_modify_cong_params_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x1c]; + u8 reserved_at_40[0x1c]; u8 cong_protocol[0x4]; union mlx5_ifc_field_select_802_1_r_roce_auto_bits field_select; - u8 reserved_3[0x80]; + u8 reserved_at_80[0x80]; union mlx5_ifc_cong_control_roce_ecn_auto_bits congestion_parameters; }; struct mlx5_ifc_manage_pages_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; u8 output_num_entries[0x20]; - u8 reserved_1[0x20]; + u8 reserved_at_60[0x20]; u8 pas[0][0x40]; }; @@ -4575,12 +4575,12 @@ enum { struct mlx5_ifc_manage_pages_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x10]; + u8 reserved_at_40[0x10]; u8 function_id[0x10]; u8 input_num_entries[0x20]; @@ -4590,117 +4590,117 @@ struct mlx5_ifc_manage_pages_in_bits { struct mlx5_ifc_mad_ifc_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; u8 response_mad_packet[256][0x8]; }; struct mlx5_ifc_mad_ifc_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 remote_lid[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_50[0x8]; u8 port[0x8]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; u8 mad[256][0x8]; }; struct mlx5_ifc_init_hca_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_init_hca_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_init2rtr_qp_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_init2rtr_qp_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 qpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; u8 opt_param_mask[0x20]; - u8 reserved_4[0x20]; + u8 reserved_at_a0[0x20]; struct mlx5_ifc_qpc_bits qpc; - u8 reserved_5[0x80]; + u8 reserved_at_800[0x80]; }; struct mlx5_ifc_init2init_qp_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_init2init_qp_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 qpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; u8 opt_param_mask[0x20]; - u8 reserved_4[0x20]; + u8 reserved_at_a0[0x20]; struct mlx5_ifc_qpc_bits qpc; - u8 reserved_5[0x80]; + u8 reserved_at_800[0x80]; }; struct mlx5_ifc_get_dropped_packet_log_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; u8 packet_headers_log[128][0x8]; @@ -4709,1029 +4709,1029 @@ struct mlx5_ifc_get_dropped_packet_log_out_bits { struct mlx5_ifc_get_dropped_packet_log_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_gen_eqe_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x18]; + u8 reserved_at_40[0x18]; u8 eq_number[0x8]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; u8 eqe[64][0x8]; }; struct mlx5_ifc_gen_eq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_enable_hca_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x20]; + u8 reserved_at_40[0x20]; }; struct mlx5_ifc_enable_hca_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x10]; + u8 reserved_at_40[0x10]; u8 function_id[0x10]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_drain_dct_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_drain_dct_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 dctn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_disable_hca_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x20]; + u8 reserved_at_40[0x20]; }; struct mlx5_ifc_disable_hca_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x10]; + u8 reserved_at_40[0x10]; u8 function_id[0x10]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_detach_from_mcg_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_detach_from_mcg_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 qpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; u8 multicast_gid[16][0x8]; }; struct mlx5_ifc_destroy_xrc_srq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_xrc_srq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 xrc_srqn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_destroy_tis_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_tis_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 tisn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_destroy_tir_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_tir_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 tirn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_destroy_srq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_srq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 srqn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_destroy_sq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_sq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 sqn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_destroy_rqt_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_rqt_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 rqtn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_destroy_rq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_rq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 rqn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_destroy_rmp_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_rmp_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 rmpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_destroy_qp_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_qp_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 qpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_destroy_psv_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_psv_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 psvn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_destroy_mkey_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_mkey_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 mkey_index[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_destroy_flow_table_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_flow_table_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; u8 table_type[0x8]; - u8 reserved_3[0x18]; + u8 reserved_at_88[0x18]; - u8 reserved_4[0x8]; + u8 reserved_at_a0[0x8]; u8 table_id[0x18]; - u8 reserved_5[0x140]; + u8 reserved_at_c0[0x140]; }; struct mlx5_ifc_destroy_flow_group_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_flow_group_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; u8 table_type[0x8]; - u8 reserved_3[0x18]; + u8 reserved_at_88[0x18]; - u8 reserved_4[0x8]; + u8 reserved_at_a0[0x8]; u8 table_id[0x18]; u8 group_id[0x20]; - u8 reserved_5[0x120]; + u8 reserved_at_e0[0x120]; }; struct mlx5_ifc_destroy_eq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_eq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x18]; + u8 reserved_at_40[0x18]; u8 eq_number[0x8]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_destroy_dct_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_dct_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 dctn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_destroy_cq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_destroy_cq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 cqn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_delete_vxlan_udp_dport_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_delete_vxlan_udp_dport_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x20]; + u8 reserved_at_40[0x20]; - u8 reserved_3[0x10]; + u8 reserved_at_60[0x10]; u8 vxlan_udp_port[0x10]; }; struct mlx5_ifc_delete_l2_table_entry_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_delete_l2_table_entry_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x60]; + u8 reserved_at_40[0x60]; - u8 reserved_3[0x8]; + u8 reserved_at_a0[0x8]; u8 table_index[0x18]; - u8 reserved_4[0x140]; + u8 reserved_at_c0[0x140]; }; struct mlx5_ifc_delete_fte_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_delete_fte_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; u8 table_type[0x8]; - u8 reserved_3[0x18]; + u8 reserved_at_88[0x18]; - u8 reserved_4[0x8]; + u8 reserved_at_a0[0x8]; u8 table_id[0x18]; - u8 reserved_5[0x40]; + u8 reserved_at_c0[0x40]; u8 flow_index[0x20]; - u8 reserved_6[0xe0]; + u8 reserved_at_120[0xe0]; }; struct mlx5_ifc_dealloc_xrcd_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_dealloc_xrcd_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 xrcd[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_dealloc_uar_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_dealloc_uar_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 uar[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_dealloc_transport_domain_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_dealloc_transport_domain_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 transport_domain[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_dealloc_q_counter_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_dealloc_q_counter_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x18]; + u8 reserved_at_40[0x18]; u8 counter_set_id[0x8]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_dealloc_pd_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_dealloc_pd_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 pd[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_xrc_srq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 xrc_srqn[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_xrc_srq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_xrc_srqc_bits xrc_srq_context_entry; - u8 reserved_3[0x600]; + u8 reserved_at_280[0x600]; u8 pas[0][0x40]; }; struct mlx5_ifc_create_tis_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 tisn[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_tis_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0xc0]; + u8 reserved_at_40[0xc0]; struct mlx5_ifc_tisc_bits ctx; }; struct mlx5_ifc_create_tir_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 tirn[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_tir_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0xc0]; + u8 reserved_at_40[0xc0]; struct mlx5_ifc_tirc_bits ctx; }; struct mlx5_ifc_create_srq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 srqn[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_srq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_srqc_bits srq_context_entry; - u8 reserved_3[0x600]; + u8 reserved_at_280[0x600]; u8 pas[0][0x40]; }; struct mlx5_ifc_create_sq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 sqn[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_sq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0xc0]; + u8 reserved_at_40[0xc0]; struct mlx5_ifc_sqc_bits ctx; }; struct mlx5_ifc_create_rqt_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 rqtn[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_rqt_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0xc0]; + u8 reserved_at_40[0xc0]; struct mlx5_ifc_rqtc_bits rqt_context; }; struct mlx5_ifc_create_rq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 rqn[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_rq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0xc0]; + u8 reserved_at_40[0xc0]; struct mlx5_ifc_rqc_bits ctx; }; struct mlx5_ifc_create_rmp_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 rmpn[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_rmp_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0xc0]; + u8 reserved_at_40[0xc0]; struct mlx5_ifc_rmpc_bits ctx; }; struct mlx5_ifc_create_qp_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 qpn[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_qp_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; u8 opt_param_mask[0x20]; - u8 reserved_3[0x20]; + u8 reserved_at_a0[0x20]; struct mlx5_ifc_qpc_bits qpc; - u8 reserved_4[0x80]; + u8 reserved_at_800[0x80]; u8 pas[0][0x40]; }; struct mlx5_ifc_create_psv_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; - u8 reserved_2[0x8]; + u8 reserved_at_80[0x8]; u8 psv0_index[0x18]; - u8 reserved_3[0x8]; + u8 reserved_at_a0[0x8]; u8 psv1_index[0x18]; - u8 reserved_4[0x8]; + u8 reserved_at_c0[0x8]; u8 psv2_index[0x18]; - u8 reserved_5[0x8]; + u8 reserved_at_e0[0x8]; u8 psv3_index[0x18]; }; struct mlx5_ifc_create_psv_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 num_psv[0x4]; - u8 reserved_2[0x4]; + u8 reserved_at_44[0x4]; u8 pd[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_mkey_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 mkey_index[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_mkey_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x20]; + u8 reserved_at_40[0x20]; u8 pg_access[0x1]; - u8 reserved_3[0x1f]; + u8 reserved_at_61[0x1f]; struct mlx5_ifc_mkc_bits memory_key_mkey_entry; - u8 reserved_4[0x80]; + u8 reserved_at_280[0x80]; u8 translations_octword_actual_size[0x20]; - u8 reserved_5[0x560]; + u8 reserved_at_320[0x560]; u8 klm_pas_mtt[0][0x20]; }; struct mlx5_ifc_create_flow_table_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 table_id[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_flow_table_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; u8 table_type[0x8]; - u8 reserved_3[0x18]; + u8 reserved_at_88[0x18]; - u8 reserved_4[0x20]; + u8 reserved_at_a0[0x20]; - u8 reserved_5[0x4]; + u8 reserved_at_c0[0x4]; u8 table_miss_mode[0x4]; u8 level[0x8]; - u8 reserved_6[0x8]; + u8 reserved_at_d0[0x8]; u8 log_size[0x8]; - u8 reserved_7[0x8]; + u8 reserved_at_e0[0x8]; u8 table_miss_id[0x18]; - u8 reserved_8[0x100]; + u8 reserved_at_100[0x100]; }; struct mlx5_ifc_create_flow_group_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 group_id[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; enum { @@ -5742,134 +5742,134 @@ enum { struct mlx5_ifc_create_flow_group_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; u8 table_type[0x8]; - u8 reserved_3[0x18]; + u8 reserved_at_88[0x18]; - u8 reserved_4[0x8]; + u8 reserved_at_a0[0x8]; u8 table_id[0x18]; - u8 reserved_5[0x20]; + u8 reserved_at_c0[0x20]; u8 start_flow_index[0x20]; - u8 reserved_6[0x20]; + u8 reserved_at_100[0x20]; u8 end_flow_index[0x20]; - u8 reserved_7[0xa0]; + u8 reserved_at_140[0xa0]; - u8 reserved_8[0x18]; + u8 reserved_at_1e0[0x18]; u8 match_criteria_enable[0x8]; struct mlx5_ifc_fte_match_param_bits match_criteria; - u8 reserved_9[0xe00]; + u8 reserved_at_1200[0xe00]; }; struct mlx5_ifc_create_eq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x18]; + u8 reserved_at_40[0x18]; u8 eq_number[0x8]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_eq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_eqc_bits eq_context_entry; - u8 reserved_3[0x40]; + u8 reserved_at_280[0x40]; u8 event_bitmask[0x40]; - u8 reserved_4[0x580]; + u8 reserved_at_300[0x580]; u8 pas[0][0x40]; }; struct mlx5_ifc_create_dct_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 dctn[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_dct_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_dctc_bits dct_context_entry; - u8 reserved_3[0x180]; + u8 reserved_at_280[0x180]; }; struct mlx5_ifc_create_cq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 cqn[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_create_cq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; struct mlx5_ifc_cqc_bits cq_context; - u8 reserved_3[0x600]; + u8 reserved_at_280[0x600]; u8 pas[0][0x40]; }; struct mlx5_ifc_config_int_moderation_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x4]; + u8 reserved_at_40[0x4]; u8 min_delay[0xc]; u8 int_vector[0x10]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; enum { @@ -5879,49 +5879,49 @@ enum { struct mlx5_ifc_config_int_moderation_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x4]; + u8 reserved_at_40[0x4]; u8 min_delay[0xc]; u8 int_vector[0x10]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_attach_to_mcg_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_attach_to_mcg_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 qpn[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; u8 multicast_gid[16][0x8]; }; struct mlx5_ifc_arm_xrc_srq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; enum { @@ -5930,25 +5930,25 @@ enum { struct mlx5_ifc_arm_xrc_srq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 xrc_srqn[0x18]; - u8 reserved_3[0x10]; + u8 reserved_at_60[0x10]; u8 lwm[0x10]; }; struct mlx5_ifc_arm_rq_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; enum { @@ -5957,179 +5957,179 @@ enum { struct mlx5_ifc_arm_rq_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 srq_number[0x18]; - u8 reserved_3[0x10]; + u8 reserved_at_60[0x10]; u8 lwm[0x10]; }; struct mlx5_ifc_arm_dct_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_arm_dct_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_40[0x8]; u8 dct_number[0x18]; - u8 reserved_3[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_alloc_xrcd_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 xrcd[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_alloc_xrcd_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_alloc_uar_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 uar[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_alloc_uar_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_alloc_transport_domain_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 transport_domain[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_alloc_transport_domain_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_alloc_q_counter_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x18]; + u8 reserved_at_40[0x18]; u8 counter_set_id[0x8]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_alloc_q_counter_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_alloc_pd_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x8]; + u8 reserved_at_40[0x8]; u8 pd[0x18]; - u8 reserved_2[0x20]; + u8 reserved_at_60[0x20]; }; struct mlx5_ifc_alloc_pd_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_add_vxlan_udp_dport_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_add_vxlan_udp_dport_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x20]; + u8 reserved_at_40[0x20]; - u8 reserved_3[0x10]; + u8 reserved_at_60[0x10]; u8 vxlan_udp_port[0x10]; }; struct mlx5_ifc_access_register_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; u8 register_data[0][0x20]; }; @@ -6141,12 +6141,12 @@ enum { struct mlx5_ifc_access_register_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x10]; + u8 reserved_at_40[0x10]; u8 register_id[0x10]; u8 argument[0x20]; @@ -6159,24 +6159,24 @@ struct mlx5_ifc_sltp_reg_bits { u8 version[0x4]; u8 local_port[0x8]; u8 pnat[0x2]; - u8 reserved_0[0x2]; + u8 reserved_at_12[0x2]; u8 lane[0x4]; - u8 reserved_1[0x8]; + u8 reserved_at_18[0x8]; - u8 reserved_2[0x20]; + u8 reserved_at_20[0x20]; - u8 reserved_3[0x7]; + u8 reserved_at_40[0x7]; u8 polarity[0x1]; u8 ob_tap0[0x8]; u8 ob_tap1[0x8]; u8 ob_tap2[0x8]; - u8 reserved_4[0xc]; + u8 reserved_at_60[0xc]; u8 ob_preemp_mode[0x4]; u8 ob_reg[0x8]; u8 ob_bias[0x8]; - u8 reserved_5[0x20]; + u8 reserved_at_80[0x20]; }; struct mlx5_ifc_slrg_reg_bits { @@ -6184,36 +6184,36 @@ struct mlx5_ifc_slrg_reg_bits { u8 version[0x4]; u8 local_port[0x8]; u8 pnat[0x2]; - u8 reserved_0[0x2]; + u8 reserved_at_12[0x2]; u8 lane[0x4]; - u8 reserved_1[0x8]; + u8 reserved_at_18[0x8]; u8 time_to_link_up[0x10]; - u8 reserved_2[0xc]; + u8 reserved_at_30[0xc]; u8 grade_lane_speed[0x4]; u8 grade_version[0x8]; u8 grade[0x18]; - u8 reserved_3[0x4]; + u8 reserved_at_60[0x4]; u8 height_grade_type[0x4]; u8 height_grade[0x18]; u8 height_dz[0x10]; u8 height_dv[0x10]; - u8 reserved_4[0x10]; + u8 reserved_at_a0[0x10]; u8 height_sigma[0x10]; - u8 reserved_5[0x20]; + u8 reserved_at_c0[0x20]; - u8 reserved_6[0x4]; + u8 reserved_at_e0[0x4]; u8 phase_grade_type[0x4]; u8 phase_grade[0x18]; - u8 reserved_7[0x8]; + u8 reserved_at_100[0x8]; u8 phase_eo_pos[0x8]; - u8 reserved_8[0x8]; + u8 reserved_at_110[0x8]; u8 phase_eo_neg[0x8]; u8 ffe_set_tested[0x10]; @@ -6221,70 +6221,70 @@ struct mlx5_ifc_slrg_reg_bits { }; struct mlx5_ifc_pvlc_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 local_port[0x8]; - u8 reserved_1[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_2[0x1c]; + u8 reserved_at_20[0x1c]; u8 vl_hw_cap[0x4]; - u8 reserved_3[0x1c]; + u8 reserved_at_40[0x1c]; u8 vl_admin[0x4]; - u8 reserved_4[0x1c]; + u8 reserved_at_60[0x1c]; u8 vl_operational[0x4]; }; struct mlx5_ifc_pude_reg_bits { u8 swid[0x8]; u8 local_port[0x8]; - u8 reserved_0[0x4]; + u8 reserved_at_10[0x4]; u8 admin_status[0x4]; - u8 reserved_1[0x4]; + u8 reserved_at_18[0x4]; u8 oper_status[0x4]; - u8 reserved_2[0x60]; + u8 reserved_at_20[0x60]; }; struct mlx5_ifc_ptys_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 local_port[0x8]; - u8 reserved_1[0xd]; + u8 reserved_at_10[0xd]; u8 proto_mask[0x3]; - u8 reserved_2[0x40]; + u8 reserved_at_20[0x40]; u8 eth_proto_capability[0x20]; u8 ib_link_width_capability[0x10]; u8 ib_proto_capability[0x10]; - u8 reserved_3[0x20]; + u8 reserved_at_a0[0x20]; u8 eth_proto_admin[0x20]; u8 ib_link_width_admin[0x10]; u8 ib_proto_admin[0x10]; - u8 reserved_4[0x20]; + u8 reserved_at_100[0x20]; u8 eth_proto_oper[0x20]; u8 ib_link_width_oper[0x10]; u8 ib_proto_oper[0x10]; - u8 reserved_5[0x20]; + u8 reserved_at_160[0x20]; u8 eth_proto_lp_advertise[0x20]; - u8 reserved_6[0x60]; + u8 reserved_at_1a0[0x60]; }; struct mlx5_ifc_ptas_reg_bits { - u8 reserved_0[0x20]; + u8 reserved_at_0[0x20]; u8 algorithm_options[0x10]; - u8 reserved_1[0x4]; + u8 reserved_at_30[0x4]; u8 repetitions_mode[0x4]; u8 num_of_repetitions[0x8]; @@ -6310,13 +6310,13 @@ struct mlx5_ifc_ptas_reg_bits { u8 ndeo_error_threshold[0x10]; u8 mixer_offset_step_size[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_110[0x8]; u8 mix90_phase_for_voltage_bath[0x8]; u8 mixer_offset_start[0x10]; u8 mixer_offset_end[0x10]; - u8 reserved_3[0x15]; + u8 reserved_at_140[0x15]; u8 ber_test_time[0xb]; }; @@ -6324,154 +6324,154 @@ struct mlx5_ifc_pspa_reg_bits { u8 swid[0x8]; u8 local_port[0x8]; u8 sub_port[0x8]; - u8 reserved_0[0x8]; + u8 reserved_at_18[0x8]; - u8 reserved_1[0x20]; + u8 reserved_at_20[0x20]; }; struct mlx5_ifc_pqdr_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 local_port[0x8]; - u8 reserved_1[0x5]; + u8 reserved_at_10[0x5]; u8 prio[0x3]; - u8 reserved_2[0x6]; + u8 reserved_at_18[0x6]; u8 mode[0x2]; - u8 reserved_3[0x20]; + u8 reserved_at_20[0x20]; - u8 reserved_4[0x10]; + u8 reserved_at_40[0x10]; u8 min_threshold[0x10]; - u8 reserved_5[0x10]; + u8 reserved_at_60[0x10]; u8 max_threshold[0x10]; - u8 reserved_6[0x10]; + u8 reserved_at_80[0x10]; u8 mark_probability_denominator[0x10]; - u8 reserved_7[0x60]; + u8 reserved_at_a0[0x60]; }; struct mlx5_ifc_ppsc_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 local_port[0x8]; - u8 reserved_1[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_2[0x60]; + u8 reserved_at_20[0x60]; - u8 reserved_3[0x1c]; + u8 reserved_at_80[0x1c]; u8 wrps_admin[0x4]; - u8 reserved_4[0x1c]; + u8 reserved_at_a0[0x1c]; u8 wrps_status[0x4]; - u8 reserved_5[0x8]; + u8 reserved_at_c0[0x8]; u8 up_threshold[0x8]; - u8 reserved_6[0x8]; + u8 reserved_at_d0[0x8]; u8 down_threshold[0x8]; - u8 reserved_7[0x20]; + u8 reserved_at_e0[0x20]; - u8 reserved_8[0x1c]; + u8 reserved_at_100[0x1c]; u8 srps_admin[0x4]; - u8 reserved_9[0x1c]; + u8 reserved_at_120[0x1c]; u8 srps_status[0x4]; - u8 reserved_10[0x40]; + u8 reserved_at_140[0x40]; }; struct mlx5_ifc_pplr_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 local_port[0x8]; - u8 reserved_1[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_2[0x8]; + u8 reserved_at_20[0x8]; u8 lb_cap[0x8]; - u8 reserved_3[0x8]; + u8 reserved_at_30[0x8]; u8 lb_en[0x8]; }; struct mlx5_ifc_pplm_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 local_port[0x8]; - u8 reserved_1[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_2[0x20]; + u8 reserved_at_20[0x20]; u8 port_profile_mode[0x8]; u8 static_port_profile[0x8]; u8 active_port_profile[0x8]; - u8 reserved_3[0x8]; + u8 reserved_at_58[0x8]; u8 retransmission_active[0x8]; u8 fec_mode_active[0x18]; - u8 reserved_4[0x20]; + u8 reserved_at_80[0x20]; }; struct mlx5_ifc_ppcnt_reg_bits { u8 swid[0x8]; u8 local_port[0x8]; u8 pnat[0x2]; - u8 reserved_0[0x8]; + u8 reserved_at_12[0x8]; u8 grp[0x6]; u8 clr[0x1]; - u8 reserved_1[0x1c]; + u8 reserved_at_21[0x1c]; u8 prio_tc[0x3]; union mlx5_ifc_eth_cntrs_grp_data_layout_auto_bits counter_set; }; struct mlx5_ifc_ppad_reg_bits { - u8 reserved_0[0x3]; + u8 reserved_at_0[0x3]; u8 single_mac[0x1]; - u8 reserved_1[0x4]; + u8 reserved_at_4[0x4]; u8 local_port[0x8]; u8 mac_47_32[0x10]; u8 mac_31_0[0x20]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_pmtu_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 local_port[0x8]; - u8 reserved_1[0x10]; + u8 reserved_at_10[0x10]; u8 max_mtu[0x10]; - u8 reserved_2[0x10]; + u8 reserved_at_30[0x10]; u8 admin_mtu[0x10]; - u8 reserved_3[0x10]; + u8 reserved_at_50[0x10]; u8 oper_mtu[0x10]; - u8 reserved_4[0x10]; + u8 reserved_at_70[0x10]; }; struct mlx5_ifc_pmpr_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 module[0x8]; - u8 reserved_1[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_2[0x18]; + u8 reserved_at_20[0x18]; u8 attenuation_5g[0x8]; - u8 reserved_3[0x18]; + u8 reserved_at_40[0x18]; u8 attenuation_7g[0x8]; - u8 reserved_4[0x18]; + u8 reserved_at_60[0x18]; u8 attenuation_12g[0x8]; }; struct mlx5_ifc_pmpe_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 module[0x8]; - u8 reserved_1[0xc]; + u8 reserved_at_10[0xc]; u8 module_status[0x4]; - u8 reserved_2[0x60]; + u8 reserved_at_20[0x60]; }; struct mlx5_ifc_pmpc_reg_bits { @@ -6479,20 +6479,20 @@ struct mlx5_ifc_pmpc_reg_bits { }; struct mlx5_ifc_pmlpn_reg_bits { - u8 reserved_0[0x4]; + u8 reserved_at_0[0x4]; u8 mlpn_status[0x4]; u8 local_port[0x8]; - u8 reserved_1[0x10]; + u8 reserved_at_10[0x10]; u8 e[0x1]; - u8 reserved_2[0x1f]; + u8 reserved_at_21[0x1f]; }; struct mlx5_ifc_pmlp_reg_bits { u8 rxtx[0x1]; - u8 reserved_0[0x7]; + u8 reserved_at_1[0x7]; u8 local_port[0x8]; - u8 reserved_1[0x8]; + u8 reserved_at_10[0x8]; u8 width[0x8]; u8 lane0_module_mapping[0x20]; @@ -6503,36 +6503,36 @@ struct mlx5_ifc_pmlp_reg_bits { u8 lane3_module_mapping[0x20]; - u8 reserved_2[0x160]; + u8 reserved_at_a0[0x160]; }; struct mlx5_ifc_pmaos_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 module[0x8]; - u8 reserved_1[0x4]; + u8 reserved_at_10[0x4]; u8 admin_status[0x4]; - u8 reserved_2[0x4]; + u8 reserved_at_18[0x4]; u8 oper_status[0x4]; u8 ase[0x1]; u8 ee[0x1]; - u8 reserved_3[0x1c]; + u8 reserved_at_22[0x1c]; u8 e[0x2]; - u8 reserved_4[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_plpc_reg_bits { - u8 reserved_0[0x4]; + u8 reserved_at_0[0x4]; u8 profile_id[0xc]; - u8 reserved_1[0x4]; + u8 reserved_at_10[0x4]; u8 proto_mask[0x4]; - u8 reserved_2[0x8]; + u8 reserved_at_18[0x8]; - u8 reserved_3[0x10]; + u8 reserved_at_20[0x10]; u8 lane_speed[0x10]; - u8 reserved_4[0x17]; + u8 reserved_at_40[0x17]; u8 lpbf[0x1]; u8 fec_mode_policy[0x8]; @@ -6545,44 +6545,44 @@ struct mlx5_ifc_plpc_reg_bits { u8 retransmission_request_admin[0x8]; u8 fec_mode_request_admin[0x18]; - u8 reserved_5[0x80]; + u8 reserved_at_c0[0x80]; }; struct mlx5_ifc_plib_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 local_port[0x8]; - u8 reserved_1[0x8]; + u8 reserved_at_10[0x8]; u8 ib_port[0x8]; - u8 reserved_2[0x60]; + u8 reserved_at_20[0x60]; }; struct mlx5_ifc_plbf_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 local_port[0x8]; - u8 reserved_1[0xd]; + u8 reserved_at_10[0xd]; u8 lbf_mode[0x3]; - u8 reserved_2[0x20]; + u8 reserved_at_20[0x20]; }; struct mlx5_ifc_pipg_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 local_port[0x8]; - u8 reserved_1[0x10]; + u8 reserved_at_10[0x10]; u8 dic[0x1]; - u8 reserved_2[0x19]; + u8 reserved_at_21[0x19]; u8 ipg[0x4]; - u8 reserved_3[0x2]; + u8 reserved_at_3e[0x2]; }; struct mlx5_ifc_pifr_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 local_port[0x8]; - u8 reserved_1[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_2[0xe0]; + u8 reserved_at_20[0xe0]; u8 port_filter[8][0x20]; @@ -6590,36 +6590,36 @@ struct mlx5_ifc_pifr_reg_bits { }; struct mlx5_ifc_pfcc_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 local_port[0x8]; - u8 reserved_1[0x10]; + u8 reserved_at_10[0x10]; u8 ppan[0x4]; - u8 reserved_2[0x4]; + u8 reserved_at_24[0x4]; u8 prio_mask_tx[0x8]; - u8 reserved_3[0x8]; + u8 reserved_at_30[0x8]; u8 prio_mask_rx[0x8]; u8 pptx[0x1]; u8 aptx[0x1]; - u8 reserved_4[0x6]; + u8 reserved_at_42[0x6]; u8 pfctx[0x8]; - u8 reserved_5[0x10]; + u8 reserved_at_50[0x10]; u8 pprx[0x1]; u8 aprx[0x1]; - u8 reserved_6[0x6]; + u8 reserved_at_62[0x6]; u8 pfcrx[0x8]; - u8 reserved_7[0x10]; + u8 reserved_at_70[0x10]; - u8 reserved_8[0x80]; + u8 reserved_at_80[0x80]; }; struct mlx5_ifc_pelc_reg_bits { u8 op[0x4]; - u8 reserved_0[0x4]; + u8 reserved_at_4[0x4]; u8 local_port[0x8]; - u8 reserved_1[0x10]; + u8 reserved_at_10[0x10]; u8 op_admin[0x8]; u8 op_capability[0x8]; @@ -6634,28 +6634,28 @@ struct mlx5_ifc_pelc_reg_bits { u8 active[0x40]; - u8 reserved_2[0x80]; + u8 reserved_at_140[0x80]; }; struct mlx5_ifc_peir_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 local_port[0x8]; - u8 reserved_1[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_2[0xc]; + u8 reserved_at_20[0xc]; u8 error_count[0x4]; - u8 reserved_3[0x10]; + u8 reserved_at_30[0x10]; - u8 reserved_4[0xc]; + u8 reserved_at_40[0xc]; u8 lane[0x4]; - u8 reserved_5[0x8]; + u8 reserved_at_50[0x8]; u8 error_type[0x8]; }; struct mlx5_ifc_pcap_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 local_port[0x8]; - u8 reserved_1[0x10]; + u8 reserved_at_10[0x10]; u8 port_capability_mask[4][0x20]; }; @@ -6663,46 +6663,46 @@ struct mlx5_ifc_pcap_reg_bits { struct mlx5_ifc_paos_reg_bits { u8 swid[0x8]; u8 local_port[0x8]; - u8 reserved_0[0x4]; + u8 reserved_at_10[0x4]; u8 admin_status[0x4]; - u8 reserved_1[0x4]; + u8 reserved_at_18[0x4]; u8 oper_status[0x4]; u8 ase[0x1]; u8 ee[0x1]; - u8 reserved_2[0x1c]; + u8 reserved_at_22[0x1c]; u8 e[0x2]; - u8 reserved_3[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_pamp_reg_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 opamp_group[0x8]; - u8 reserved_1[0xc]; + u8 reserved_at_10[0xc]; u8 opamp_group_type[0x4]; u8 start_index[0x10]; - u8 reserved_2[0x4]; + u8 reserved_at_30[0x4]; u8 num_of_indices[0xc]; u8 index_data[18][0x10]; }; struct mlx5_ifc_lane_2_module_mapping_bits { - u8 reserved_0[0x6]; + u8 reserved_at_0[0x6]; u8 rx_lane[0x2]; - u8 reserved_1[0x6]; + u8 reserved_at_8[0x6]; u8 tx_lane[0x2]; - u8 reserved_2[0x8]; + u8 reserved_at_10[0x8]; u8 module[0x8]; }; struct mlx5_ifc_bufferx_reg_bits { - u8 reserved_0[0x6]; + u8 reserved_at_0[0x6]; u8 lossy[0x1]; u8 epsb[0x1]; - u8 reserved_1[0xc]; + u8 reserved_at_8[0xc]; u8 size[0xc]; u8 xoff_threshold[0x10]; @@ -6714,21 +6714,21 @@ struct mlx5_ifc_set_node_in_bits { }; struct mlx5_ifc_register_power_settings_bits { - u8 reserved_0[0x18]; + u8 reserved_at_0[0x18]; u8 power_settings_level[0x8]; - u8 reserved_1[0x60]; + u8 reserved_at_20[0x60]; }; struct mlx5_ifc_register_host_endianness_bits { u8 he[0x1]; - u8 reserved_0[0x1f]; + u8 reserved_at_1[0x1f]; - u8 reserved_1[0x60]; + u8 reserved_at_20[0x60]; }; struct mlx5_ifc_umr_pointer_desc_argument_bits { - u8 reserved_0[0x20]; + u8 reserved_at_0[0x20]; u8 mkey[0x20]; @@ -6741,7 +6741,7 @@ struct mlx5_ifc_ud_adrs_vector_bits { u8 dc_key[0x40]; u8 ext[0x1]; - u8 reserved_0[0x7]; + u8 reserved_at_41[0x7]; u8 destination_qp_dct[0x18]; u8 static_rate[0x4]; @@ -6750,7 +6750,7 @@ struct mlx5_ifc_ud_adrs_vector_bits { u8 mlid[0x7]; u8 rlid_udp_sport[0x10]; - u8 reserved_1[0x20]; + u8 reserved_at_80[0x20]; u8 rmac_47_16[0x20]; @@ -6758,9 +6758,9 @@ struct mlx5_ifc_ud_adrs_vector_bits { u8 tclass[0x8]; u8 hop_limit[0x8]; - u8 reserved_2[0x1]; + u8 reserved_at_e0[0x1]; u8 grh[0x1]; - u8 reserved_3[0x2]; + u8 reserved_at_e2[0x2]; u8 src_addr_index[0x8]; u8 flow_label[0x14]; @@ -6768,27 +6768,27 @@ struct mlx5_ifc_ud_adrs_vector_bits { }; struct mlx5_ifc_pages_req_event_bits { - u8 reserved_0[0x10]; + u8 reserved_at_0[0x10]; u8 function_id[0x10]; u8 num_pages[0x20]; - u8 reserved_1[0xa0]; + u8 reserved_at_40[0xa0]; }; struct mlx5_ifc_eqe_bits { - u8 reserved_0[0x8]; + u8 reserved_at_0[0x8]; u8 event_type[0x8]; - u8 reserved_1[0x8]; + u8 reserved_at_10[0x8]; u8 event_sub_type[0x8]; - u8 reserved_2[0xe0]; + u8 reserved_at_20[0xe0]; union mlx5_ifc_event_auto_bits event_data; - u8 reserved_3[0x10]; + u8 reserved_at_1e0[0x10]; u8 signature[0x8]; - u8 reserved_4[0x7]; + u8 reserved_at_1f8[0x7]; u8 owner[0x1]; }; @@ -6798,14 +6798,14 @@ enum { struct mlx5_ifc_cmd_queue_entry_bits { u8 type[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 input_length[0x20]; u8 input_mailbox_pointer_63_32[0x20]; u8 input_mailbox_pointer_31_9[0x17]; - u8 reserved_1[0x9]; + u8 reserved_at_77[0x9]; u8 command_input_inline_data[16][0x8]; @@ -6814,20 +6814,20 @@ struct mlx5_ifc_cmd_queue_entry_bits { u8 output_mailbox_pointer_63_32[0x20]; u8 output_mailbox_pointer_31_9[0x17]; - u8 reserved_2[0x9]; + u8 reserved_at_1b7[0x9]; u8 output_length[0x20]; u8 token[0x8]; u8 signature[0x8]; - u8 reserved_3[0x8]; + u8 reserved_at_1f0[0x8]; u8 status[0x7]; u8 ownership[0x1]; }; struct mlx5_ifc_cmd_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; @@ -6836,9 +6836,9 @@ struct mlx5_ifc_cmd_out_bits { struct mlx5_ifc_cmd_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; u8 command[0][0x20]; @@ -6847,16 +6847,16 @@ struct mlx5_ifc_cmd_in_bits { struct mlx5_ifc_cmd_if_box_bits { u8 mailbox_data[512][0x8]; - u8 reserved_0[0x180]; + u8 reserved_at_1000[0x180]; u8 next_pointer_63_32[0x20]; u8 next_pointer_31_10[0x16]; - u8 reserved_1[0xa]; + u8 reserved_at_11b6[0xa]; u8 block_number[0x20]; - u8 reserved_2[0x8]; + u8 reserved_at_11e0[0x8]; u8 token[0x8]; u8 ctrl_signature[0x8]; u8 signature[0x8]; @@ -6866,7 +6866,7 @@ struct mlx5_ifc_mtt_bits { u8 ptag_63_32[0x20]; u8 ptag_31_8[0x18]; - u8 reserved_0[0x6]; + u8 reserved_at_38[0x6]; u8 wr_en[0x1]; u8 rd_en[0x1]; }; @@ -6904,38 +6904,38 @@ struct mlx5_ifc_initial_seg_bits { u8 cmd_interface_rev[0x10]; u8 fw_rev_subminor[0x10]; - u8 reserved_0[0x40]; + u8 reserved_at_40[0x40]; u8 cmdq_phy_addr_63_32[0x20]; u8 cmdq_phy_addr_31_12[0x14]; - u8 reserved_1[0x2]; + u8 reserved_at_b4[0x2]; u8 nic_interface[0x2]; u8 log_cmdq_size[0x4]; u8 log_cmdq_stride[0x4]; u8 command_doorbell_vector[0x20]; - u8 reserved_2[0xf00]; + u8 reserved_at_e0[0xf00]; u8 initializing[0x1]; - u8 reserved_3[0x4]; + u8 reserved_at_fe1[0x4]; u8 nic_interface_supported[0x3]; - u8 reserved_4[0x18]; + u8 reserved_at_fe8[0x18]; struct mlx5_ifc_health_buffer_bits health_buffer; u8 no_dram_nic_offset[0x20]; - u8 reserved_5[0x6e40]; + u8 reserved_at_1220[0x6e40]; - u8 reserved_6[0x1f]; + u8 reserved_at_8060[0x1f]; u8 clear_int[0x1]; u8 health_syndrome[0x8]; u8 health_counter[0x18]; - u8 reserved_7[0x17fc0]; + u8 reserved_at_80a0[0x17fc0]; }; union mlx5_ifc_ports_control_registers_document_bits { @@ -6980,44 +6980,44 @@ union mlx5_ifc_ports_control_registers_document_bits { struct mlx5_ifc_pvlc_reg_bits pvlc_reg; struct mlx5_ifc_slrg_reg_bits slrg_reg; struct mlx5_ifc_sltp_reg_bits sltp_reg; - u8 reserved_0[0x60e0]; + u8 reserved_at_0[0x60e0]; }; union mlx5_ifc_debug_enhancements_document_bits { struct mlx5_ifc_health_buffer_bits health_buffer; - u8 reserved_0[0x200]; + u8 reserved_at_0[0x200]; }; union mlx5_ifc_uplink_pci_interface_document_bits { struct mlx5_ifc_initial_seg_bits initial_seg; - u8 reserved_0[0x20060]; + u8 reserved_at_0[0x20060]; }; struct mlx5_ifc_set_flow_table_root_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_set_flow_table_root_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x40]; + u8 reserved_at_40[0x40]; u8 table_type[0x8]; - u8 reserved_3[0x18]; + u8 reserved_at_88[0x18]; - u8 reserved_4[0x8]; + u8 reserved_at_a0[0x8]; u8 table_id[0x18]; - u8 reserved_5[0x140]; + u8 reserved_at_c0[0x140]; }; enum { @@ -7026,39 +7026,39 @@ enum { struct mlx5_ifc_modify_flow_table_out_bits { u8 status[0x8]; - u8 reserved_0[0x18]; + u8 reserved_at_8[0x18]; u8 syndrome[0x20]; - u8 reserved_1[0x40]; + u8 reserved_at_40[0x40]; }; struct mlx5_ifc_modify_flow_table_in_bits { u8 opcode[0x10]; - u8 reserved_0[0x10]; + u8 reserved_at_10[0x10]; - u8 reserved_1[0x10]; + u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_2[0x20]; + u8 reserved_at_40[0x20]; - u8 reserved_3[0x10]; + u8 reserved_at_60[0x10]; u8 modify_field_select[0x10]; u8 table_type[0x8]; - u8 reserved_4[0x18]; + u8 reserved_at_88[0x18]; - u8 reserved_5[0x8]; + u8 reserved_at_a0[0x8]; u8 table_id[0x18]; - u8 reserved_6[0x4]; + u8 reserved_at_c0[0x4]; u8 table_miss_mode[0x4]; - u8 reserved_7[0x18]; + u8 reserved_at_c8[0x18]; - u8 reserved_8[0x8]; + u8 reserved_at_e0[0x8]; u8 table_miss_id[0x18]; - u8 reserved_9[0x100]; + u8 reserved_at_100[0x100]; }; #endif /* MLX5_IFC_H */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 289c2314d766..5440b7b705eb 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3718,7 +3718,7 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev, void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter); #define netdev_for_each_lower_dev(dev, ldev, iter) \ - for (iter = &(dev)->adj_list.lower, \ + for (iter = (dev)->adj_list.lower.next, \ ldev = netdev_lower_get_next(dev, &(iter)); \ ldev; \ ldev = netdev_lower_get_next(dev, &(iter))) diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 48e0320cd643..67300f8e5f2f 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -550,9 +550,7 @@ extern int nfs_readpage_async(struct nfs_open_context *, struct inode *, static inline loff_t nfs_size_to_loff_t(__u64 size) { - if (size > (__u64) OFFSET_MAX - 1) - return OFFSET_MAX - 1; - return (loff_t) size; + return min_t(u64, size, OFFSET_MAX); } static inline ino_t diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 791098a08a87..d320906cf13e 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -275,6 +275,7 @@ struct nfs4_layoutcommit_args { size_t layoutupdate_len; struct page *layoutupdate_page; struct page **layoutupdate_pages; + __be32 *start_p; }; struct nfs4_layoutcommit_res { diff --git a/include/linux/pci.h b/include/linux/pci.h index 27df4a6585da..27716254dcc5 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -988,23 +988,6 @@ static inline int pci_is_managed(struct pci_dev *pdev) return pdev->is_managed; } -static inline void pci_set_managed_irq(struct pci_dev *pdev, unsigned int irq) -{ - pdev->irq = irq; - pdev->irq_managed = 1; -} - -static inline void pci_reset_managed_irq(struct pci_dev *pdev) -{ - pdev->irq = 0; - pdev->irq_managed = 0; -} - -static inline bool pci_has_managed_irq(struct pci_dev *pdev) -{ - return pdev->irq_managed && pdev->irq > 0; -} - void pci_disable_device(struct pci_dev *dev); extern unsigned int pcibios_max_latency; diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index b35a61a481fa..f5c5a3fa2c81 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -397,6 +397,7 @@ struct pmu { * enum perf_event_active_state - the states of a event */ enum perf_event_active_state { + PERF_EVENT_STATE_DEAD = -4, PERF_EVENT_STATE_EXIT = -3, PERF_EVENT_STATE_ERROR = -2, PERF_EVENT_STATE_OFF = -1, @@ -905,7 +906,7 @@ perf_sw_event_sched(u32 event_id, u64 nr, u64 addr) } } -extern struct static_key_deferred perf_sched_events; +extern struct static_key_false perf_sched_events; static __always_inline bool perf_sw_migrate_enabled(void) @@ -924,7 +925,7 @@ static inline void perf_event_task_migrate(struct task_struct *task) static inline void perf_event_task_sched_in(struct task_struct *prev, struct task_struct *task) { - if (static_key_false(&perf_sched_events.key)) + if (static_branch_unlikely(&perf_sched_events)) __perf_event_task_sched_in(prev, task); if (perf_sw_migrate_enabled() && task->sched_migrated) { @@ -941,7 +942,7 @@ static inline void perf_event_task_sched_out(struct task_struct *prev, { perf_sw_event_sched(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 0); - if (static_key_false(&perf_sched_events.key)) + if (static_branch_unlikely(&perf_sched_events)) __perf_event_task_sched_out(prev, next); } diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h index 998d8f1c3c91..b50c0492629d 100644 --- a/include/linux/power/bq27xxx_battery.h +++ b/include/linux/power/bq27xxx_battery.h @@ -49,6 +49,7 @@ struct bq27xxx_reg_cache { struct bq27xxx_device_info { struct device *dev; + int id; enum bq27xxx_chip chip; const char *name; struct bq27xxx_access_methods bus; diff --git a/include/linux/random.h b/include/linux/random.h index a75840c1aa71..9c29122037f9 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -34,6 +34,7 @@ extern const struct file_operations random_fops, urandom_fops; #endif unsigned int get_random_int(void); +unsigned long get_random_long(void); unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len); u32 prandom_u32(void); diff --git a/include/linux/soc/ti/knav_dma.h b/include/linux/soc/ti/knav_dma.h index 343c13ac4f71..35cb9264e0d5 100644 --- a/include/linux/soc/ti/knav_dma.h +++ b/include/linux/soc/ti/knav_dma.h @@ -44,6 +44,7 @@ #define KNAV_DMA_NUM_EPIB_WORDS 4 #define KNAV_DMA_NUM_PS_WORDS 16 +#define KNAV_DMA_NUM_SW_DATA_WORDS 4 #define KNAV_DMA_FDQ_PER_CHAN 4 /* Tx channel scheduling priority */ @@ -142,6 +143,7 @@ struct knav_dma_cfg { * @orig_buff: buff pointer since 'buff' can be overwritten * @epib: Extended packet info block * @psdata: Protocol specific + * @sw_data: Software private data not touched by h/w */ struct knav_dma_desc { __le32 desc_info; @@ -154,7 +156,7 @@ struct knav_dma_desc { __le32 orig_buff; __le32 epib[KNAV_DMA_NUM_EPIB_WORDS]; __le32 psdata[KNAV_DMA_NUM_PS_WORDS]; - __le32 pad[4]; + u32 sw_data[KNAV_DMA_NUM_SW_DATA_WORDS]; } ____cacheline_aligned; #if IS_ENABLED(CONFIG_KEYSTONE_NAVIGATOR_DMA) diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 429fdfc3baf5..925730bc9fc1 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -568,6 +568,8 @@ enum { FILTER_DYN_STRING, FILTER_PTR_STRING, FILTER_TRACE_FN, + FILTER_COMM, + FILTER_CPU, }; extern int trace_event_raw_init(struct trace_event_call *call); diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index acd522a91539..acfdbf353a0b 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h @@ -14,8 +14,10 @@ * See the file COPYING for more details. */ +#include <linux/smp.h> #include <linux/errno.h> #include <linux/types.h> +#include <linux/cpumask.h> #include <linux/rcupdate.h> #include <linux/tracepoint-defs.h> @@ -132,6 +134,9 @@ extern void syscall_unregfunc(void); void *it_func; \ void *__data; \ \ + if (!cpu_online(raw_smp_processor_id())) \ + return; \ + \ if (!(cond)) \ return; \ prercu; \ diff --git a/include/linux/writeback.h b/include/linux/writeback.h index b333c945e571..d0b5ca5d4e08 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -198,6 +198,7 @@ void wbc_attach_and_unlock_inode(struct writeback_control *wbc, void wbc_detach_inode(struct writeback_control *wbc); void wbc_account_io(struct writeback_control *wbc, struct page *page, size_t bytes); +void cgroup_writeback_umount(void); /** * inode_attach_wb - associate an inode with its wb @@ -301,6 +302,10 @@ static inline void wbc_account_io(struct writeback_control *wbc, { } +static inline void cgroup_writeback_umount(void) +{ +} + #endif /* CONFIG_CGROUP_WRITEBACK */ /* diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 481fe1c9044c..49dcad4fe99e 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -270,8 +270,9 @@ struct dst_entry *inet_csk_route_child_sock(const struct sock *sk, struct sock *newsk, const struct request_sock *req); -void inet_csk_reqsk_queue_add(struct sock *sk, struct request_sock *req, - struct sock *child); +struct sock *inet_csk_reqsk_queue_add(struct sock *sk, + struct request_sock *req, + struct sock *child); void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req, unsigned long timeout); struct sock *inet_csk_complete_hashdance(struct sock *sk, struct sock *child, diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 7029527725dd..4079fc18ffe4 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -61,6 +61,7 @@ struct fib_nh_exception { struct rtable __rcu *fnhe_rth_input; struct rtable __rcu *fnhe_rth_output; unsigned long fnhe_stamp; + struct rcu_head rcu; }; struct fnhe_hash_bucket { diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index e2b712c90d3f..c21c38ce7450 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -343,7 +343,7 @@ void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus); void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus); void snd_hdac_bus_update_rirb(struct hdac_bus *bus); -void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, +int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, void (*ack)(struct hdac_bus *, struct hdac_stream *)); diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 1e3c8cb43bd7..625b38f65764 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -66,27 +66,33 @@ struct media_device_info { /* * DVB entities */ -#define MEDIA_ENT_F_DTV_DEMOD (MEDIA_ENT_F_BASE + 1) -#define MEDIA_ENT_F_TS_DEMUX (MEDIA_ENT_F_BASE + 2) -#define MEDIA_ENT_F_DTV_CA (MEDIA_ENT_F_BASE + 3) -#define MEDIA_ENT_F_DTV_NET_DECAP (MEDIA_ENT_F_BASE + 4) +#define MEDIA_ENT_F_DTV_DEMOD (MEDIA_ENT_F_BASE + 0x00001) +#define MEDIA_ENT_F_TS_DEMUX (MEDIA_ENT_F_BASE + 0x00002) +#define MEDIA_ENT_F_DTV_CA (MEDIA_ENT_F_BASE + 0x00003) +#define MEDIA_ENT_F_DTV_NET_DECAP (MEDIA_ENT_F_BASE + 0x00004) /* - * Connectors + * I/O entities */ -/* It is a responsibility of the entity drivers to add connectors and links */ -#define MEDIA_ENT_F_CONN_RF (MEDIA_ENT_F_BASE + 21) -#define MEDIA_ENT_F_CONN_SVIDEO (MEDIA_ENT_F_BASE + 22) -#define MEDIA_ENT_F_CONN_COMPOSITE (MEDIA_ENT_F_BASE + 23) -/* For internal test signal generators and other debug connectors */ -#define MEDIA_ENT_F_CONN_TEST (MEDIA_ENT_F_BASE + 24) +#define MEDIA_ENT_F_IO_DTV (MEDIA_ENT_F_BASE + 0x01001) +#define MEDIA_ENT_F_IO_VBI (MEDIA_ENT_F_BASE + 0x01002) +#define MEDIA_ENT_F_IO_SWRADIO (MEDIA_ENT_F_BASE + 0x01003) /* - * I/O entities + * Connectors */ -#define MEDIA_ENT_F_IO_DTV (MEDIA_ENT_F_BASE + 31) -#define MEDIA_ENT_F_IO_VBI (MEDIA_ENT_F_BASE + 32) -#define MEDIA_ENT_F_IO_SWRADIO (MEDIA_ENT_F_BASE + 33) +/* It is a responsibility of the entity drivers to add connectors and links */ +#ifdef __KERNEL__ + /* + * For now, it should not be used in userspace, as some + * definitions may change + */ + +#define MEDIA_ENT_F_CONN_RF (MEDIA_ENT_F_BASE + 0x30001) +#define MEDIA_ENT_F_CONN_SVIDEO (MEDIA_ENT_F_BASE + 0x30002) +#define MEDIA_ENT_F_CONN_COMPOSITE (MEDIA_ENT_F_BASE + 0x30003) + +#endif /* * Don't touch on those. The ranges MEDIA_ENT_F_OLD_BASE and @@ -291,14 +297,14 @@ struct media_v2_entity { __u32 id; char name[64]; /* FIXME: move to a property? (RFC says so) */ __u32 function; /* Main function of the entity */ - __u16 reserved[12]; -}; + __u32 reserved[6]; +} __attribute__ ((packed)); /* Should match the specific fields at media_intf_devnode */ struct media_v2_intf_devnode { __u32 major; __u32 minor; -}; +} __attribute__ ((packed)); struct media_v2_interface { __u32 id; @@ -310,22 +316,22 @@ struct media_v2_interface { struct media_v2_intf_devnode devnode; __u32 raw[16]; }; -}; +} __attribute__ ((packed)); struct media_v2_pad { __u32 id; __u32 entity_id; __u32 flags; - __u16 reserved[9]; -}; + __u32 reserved[5]; +} __attribute__ ((packed)); struct media_v2_link { __u32 id; __u32 source_id; __u32 sink_id; __u32 flags; - __u32 reserved[5]; -}; + __u32 reserved[6]; +} __attribute__ ((packed)); struct media_v2_topology { __u64 topology_version; @@ -345,7 +351,7 @@ struct media_v2_topology { __u32 num_links; __u32 reserved4; __u64 ptr_links; -}; +} __attribute__ ((packed)); static inline void __user *media_get_uptr(__u64 arg) { diff --git a/include/uapi/linux/ndctl.h b/include/uapi/linux/ndctl.h index 5b4a4be06e2b..cc68b92124d4 100644 --- a/include/uapi/linux/ndctl.h +++ b/include/uapi/linux/ndctl.h @@ -66,14 +66,18 @@ struct nd_cmd_ars_cap { __u64 length; __u32 status; __u32 max_ars_out; + __u32 clear_err_unit; + __u32 reserved; } __packed; struct nd_cmd_ars_start { __u64 address; __u64 length; __u16 type; - __u8 reserved[6]; + __u8 flags; + __u8 reserved[5]; __u32 status; + __u32 scrub_time; } __packed; struct nd_cmd_ars_status { @@ -81,11 +85,14 @@ struct nd_cmd_ars_status { __u32 out_length; __u64 address; __u64 length; + __u64 restart_address; + __u64 restart_length; __u16 type; + __u16 flags; __u32 num_records; struct nd_ars_record { __u32 handle; - __u32 flags; + __u32 reserved; __u64 err_address; __u64 length; } __packed records[0]; diff --git a/ipc/shm.c b/ipc/shm.c index ed3027d0f277..331fc1b0b3c7 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -156,11 +156,12 @@ static inline struct shmid_kernel *shm_lock(struct ipc_namespace *ns, int id) struct kern_ipc_perm *ipcp = ipc_lock(&shm_ids(ns), id); /* - * We raced in the idr lookup or with shm_destroy(). Either way, the - * ID is busted. + * Callers of shm_lock() must validate the status of the returned ipc + * object pointer (as returned by ipc_lock()), and error out as + * appropriate. */ - WARN_ON(IS_ERR(ipcp)); - + if (IS_ERR(ipcp)) + return (void *)ipcp; return container_of(ipcp, struct shmid_kernel, shm_perm); } @@ -186,18 +187,33 @@ static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s) } -/* This is called by fork, once for every shm attach. */ -static void shm_open(struct vm_area_struct *vma) +static int __shm_open(struct vm_area_struct *vma) { struct file *file = vma->vm_file; struct shm_file_data *sfd = shm_file_data(file); struct shmid_kernel *shp; shp = shm_lock(sfd->ns, sfd->id); + + if (IS_ERR(shp)) + return PTR_ERR(shp); + shp->shm_atim = get_seconds(); shp->shm_lprid = task_tgid_vnr(current); shp->shm_nattch++; shm_unlock(shp); + return 0; +} + +/* This is called by fork, once for every shm attach. */ +static void shm_open(struct vm_area_struct *vma) +{ + int err = __shm_open(vma); + /* + * We raced in the idr lookup or with shm_destroy(). + * Either way, the ID is busted. + */ + WARN_ON_ONCE(err); } /* @@ -260,6 +276,14 @@ static void shm_close(struct vm_area_struct *vma) down_write(&shm_ids(ns).rwsem); /* remove from the list of attaches of the shm segment */ shp = shm_lock(ns, sfd->id); + + /* + * We raced in the idr lookup or with shm_destroy(). + * Either way, the ID is busted. + */ + if (WARN_ON_ONCE(IS_ERR(shp))) + goto done; /* no-op */ + shp->shm_lprid = task_tgid_vnr(current); shp->shm_dtim = get_seconds(); shp->shm_nattch--; @@ -267,6 +291,7 @@ static void shm_close(struct vm_area_struct *vma) shm_destroy(ns, shp); else shm_unlock(shp); +done: up_write(&shm_ids(ns).rwsem); } @@ -388,17 +413,25 @@ static int shm_mmap(struct file *file, struct vm_area_struct *vma) struct shm_file_data *sfd = shm_file_data(file); int ret; + /* + * In case of remap_file_pages() emulation, the file can represent + * removed IPC ID: propogate shm_lock() error to caller. + */ + ret =__shm_open(vma); + if (ret) + return ret; + ret = sfd->file->f_op->mmap(sfd->file, vma); - if (ret != 0) + if (ret) { + shm_close(vma); return ret; + } sfd->vm_ops = vma->vm_ops; #ifdef CONFIG_MMU WARN_ON(!sfd->vm_ops->fault); #endif vma->vm_ops = &shm_vm_ops; - shm_open(vma); - - return ret; + return 0; } static int shm_release(struct inode *ino, struct file *file) diff --git a/kernel/events/core.c b/kernel/events/core.c index 5946460b2425..614614821f00 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -64,8 +64,17 @@ static void remote_function(void *data) struct task_struct *p = tfc->p; if (p) { - tfc->ret = -EAGAIN; - if (task_cpu(p) != smp_processor_id() || !task_curr(p)) + /* -EAGAIN */ + if (task_cpu(p) != smp_processor_id()) + return; + + /* + * Now that we're on right CPU with IRQs disabled, we can test + * if we hit the right task without races. + */ + + tfc->ret = -ESRCH; /* No such (running) process */ + if (p != current) return; } @@ -92,13 +101,17 @@ task_function_call(struct task_struct *p, remote_function_f func, void *info) .p = p, .func = func, .info = info, - .ret = -ESRCH, /* No such (running) process */ + .ret = -EAGAIN, }; + int ret; - if (task_curr(p)) - smp_call_function_single(task_cpu(p), remote_function, &data, 1); + do { + ret = smp_call_function_single(task_cpu(p), remote_function, &data, 1); + if (!ret) + ret = data.ret; + } while (ret == -EAGAIN); - return data.ret; + return ret; } /** @@ -169,19 +182,6 @@ static bool is_kernel_event(struct perf_event *event) * rely on ctx->is_active and therefore cannot use event_function_call(). * See perf_install_in_context(). * - * This is because we need a ctx->lock serialized variable (ctx->is_active) - * to reliably determine if a particular task/context is scheduled in. The - * task_curr() use in task_function_call() is racy in that a remote context - * switch is not a single atomic operation. - * - * As is, the situation is 'safe' because we set rq->curr before we do the - * actual context switch. This means that task_curr() will fail early, but - * we'll continue spinning on ctx->is_active until we've passed - * perf_event_task_sched_out(). - * - * Without this ctx->lock serialized variable we could have race where we find - * the task (and hence the context) would not be active while in fact they are. - * * If ctx->nr_events, then ctx->is_active and cpuctx->task_ctx are set. */ @@ -212,7 +212,7 @@ static int event_function(void *info) */ if (ctx->task) { if (ctx->task != current) { - ret = -EAGAIN; + ret = -ESRCH; goto unlock; } @@ -276,10 +276,10 @@ static void event_function_call(struct perf_event *event, event_f func, void *da return; } -again: if (task == TASK_TOMBSTONE) return; +again: if (!task_function_call(task, event_function, &efs)) return; @@ -289,13 +289,15 @@ again: * a concurrent perf_event_context_sched_out(). */ task = ctx->task; - if (task != TASK_TOMBSTONE) { - if (ctx->is_active) { - raw_spin_unlock_irq(&ctx->lock); - goto again; - } - func(event, NULL, ctx, data); + if (task == TASK_TOMBSTONE) { + raw_spin_unlock_irq(&ctx->lock); + return; } + if (ctx->is_active) { + raw_spin_unlock_irq(&ctx->lock); + goto again; + } + func(event, NULL, ctx, data); raw_spin_unlock_irq(&ctx->lock); } @@ -314,6 +316,7 @@ again: enum event_type_t { EVENT_FLEXIBLE = 0x1, EVENT_PINNED = 0x2, + EVENT_TIME = 0x4, EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED, }; @@ -321,7 +324,13 @@ enum event_type_t { * perf_sched_events : >0 events exist * perf_cgroup_events: >0 per-cpu cgroup events exist on this cpu */ -struct static_key_deferred perf_sched_events __read_mostly; + +static void perf_sched_delayed(struct work_struct *work); +DEFINE_STATIC_KEY_FALSE(perf_sched_events); +static DECLARE_DELAYED_WORK(perf_sched_work, perf_sched_delayed); +static DEFINE_MUTEX(perf_sched_mutex); +static atomic_t perf_sched_count; + static DEFINE_PER_CPU(atomic_t, perf_cgroup_events); static DEFINE_PER_CPU(int, perf_sched_cb_usages); @@ -1288,16 +1297,18 @@ static u64 perf_event_time(struct perf_event *event) /* * Update the total_time_enabled and total_time_running fields for a event. - * The caller of this function needs to hold the ctx->lock. */ static void update_event_times(struct perf_event *event) { struct perf_event_context *ctx = event->ctx; u64 run_end; + lockdep_assert_held(&ctx->lock); + if (event->state < PERF_EVENT_STATE_INACTIVE || event->group_leader->state < PERF_EVENT_STATE_INACTIVE) return; + /* * in cgroup mode, time_enabled represents * the time the event was enabled AND active @@ -1645,7 +1656,7 @@ out: static bool is_orphaned_event(struct perf_event *event) { - return event->state == PERF_EVENT_STATE_EXIT; + return event->state == PERF_EVENT_STATE_DEAD; } static inline int pmu_filter_match(struct perf_event *event) @@ -1690,14 +1701,14 @@ event_sched_out(struct perf_event *event, perf_pmu_disable(event->pmu); + event->tstamp_stopped = tstamp; + event->pmu->del(event, 0); + event->oncpu = -1; event->state = PERF_EVENT_STATE_INACTIVE; if (event->pending_disable) { event->pending_disable = 0; event->state = PERF_EVENT_STATE_OFF; } - event->tstamp_stopped = tstamp; - event->pmu->del(event, 0); - event->oncpu = -1; if (!is_software_event(event)) cpuctx->active_oncpu--; @@ -1732,7 +1743,6 @@ group_sched_out(struct perf_event *group_event, } #define DETACH_GROUP 0x01UL -#define DETACH_STATE 0x02UL /* * Cross CPU call to remove a performance event @@ -1752,8 +1762,6 @@ __perf_remove_from_context(struct perf_event *event, if (flags & DETACH_GROUP) perf_group_detach(event); list_del_event(event, ctx); - if (flags & DETACH_STATE) - event->state = PERF_EVENT_STATE_EXIT; if (!ctx->nr_events && ctx->is_active) { ctx->is_active = 0; @@ -2063,14 +2071,27 @@ static void add_event_to_ctx(struct perf_event *event, event->tstamp_stopped = tstamp; } -static void task_ctx_sched_out(struct perf_cpu_context *cpuctx, - struct perf_event_context *ctx); +static void ctx_sched_out(struct perf_event_context *ctx, + struct perf_cpu_context *cpuctx, + enum event_type_t event_type); static void ctx_sched_in(struct perf_event_context *ctx, struct perf_cpu_context *cpuctx, enum event_type_t event_type, struct task_struct *task); +static void task_ctx_sched_out(struct perf_cpu_context *cpuctx, + struct perf_event_context *ctx) +{ + if (!cpuctx->task_ctx) + return; + + if (WARN_ON_ONCE(ctx != cpuctx->task_ctx)) + return; + + ctx_sched_out(ctx, cpuctx, EVENT_ALL); +} + static void perf_event_sched_in(struct perf_cpu_context *cpuctx, struct perf_event_context *ctx, struct task_struct *task) @@ -2097,49 +2118,68 @@ static void ctx_resched(struct perf_cpu_context *cpuctx, /* * Cross CPU call to install and enable a performance event * - * Must be called with ctx->mutex held + * Very similar to remote_function() + event_function() but cannot assume that + * things like ctx->is_active and cpuctx->task_ctx are set. */ static int __perf_install_in_context(void *info) { - struct perf_event_context *ctx = info; + struct perf_event *event = info; + struct perf_event_context *ctx = event->ctx; struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); struct perf_event_context *task_ctx = cpuctx->task_ctx; + bool activate = true; + int ret = 0; raw_spin_lock(&cpuctx->ctx.lock); if (ctx->task) { raw_spin_lock(&ctx->lock); - /* - * If we hit the 'wrong' task, we've since scheduled and - * everything should be sorted, nothing to do! - */ task_ctx = ctx; - if (ctx->task != current) + + /* If we're on the wrong CPU, try again */ + if (task_cpu(ctx->task) != smp_processor_id()) { + ret = -ESRCH; goto unlock; + } /* - * If task_ctx is set, it had better be to us. + * If we're on the right CPU, see if the task we target is + * current, if not we don't have to activate the ctx, a future + * context switch will do that for us. */ - WARN_ON_ONCE(cpuctx->task_ctx != ctx && cpuctx->task_ctx); + if (ctx->task != current) + activate = false; + else + WARN_ON_ONCE(cpuctx->task_ctx && cpuctx->task_ctx != ctx); + } else if (task_ctx) { raw_spin_lock(&task_ctx->lock); } - ctx_resched(cpuctx, task_ctx); + if (activate) { + ctx_sched_out(ctx, cpuctx, EVENT_TIME); + add_event_to_ctx(event, ctx); + ctx_resched(cpuctx, task_ctx); + } else { + add_event_to_ctx(event, ctx); + } + unlock: perf_ctx_unlock(cpuctx, task_ctx); - return 0; + return ret; } /* - * Attach a performance event to a context + * Attach a performance event to a context. + * + * Very similar to event_function_call, see comment there. */ static void perf_install_in_context(struct perf_event_context *ctx, struct perf_event *event, int cpu) { - struct task_struct *task = NULL; + struct task_struct *task = READ_ONCE(ctx->task); lockdep_assert_held(&ctx->mutex); @@ -2147,40 +2187,46 @@ perf_install_in_context(struct perf_event_context *ctx, if (event->cpu != -1) event->cpu = cpu; + if (!task) { + cpu_function_call(cpu, __perf_install_in_context, event); + return; + } + + /* + * Should not happen, we validate the ctx is still alive before calling. + */ + if (WARN_ON_ONCE(task == TASK_TOMBSTONE)) + return; + /* * Installing events is tricky because we cannot rely on ctx->is_active * to be set in case this is the nr_events 0 -> 1 transition. - * - * So what we do is we add the event to the list here, which will allow - * a future context switch to DTRT and then send a racy IPI. If the IPI - * fails to hit the right task, this means a context switch must have - * happened and that will have taken care of business. */ - raw_spin_lock_irq(&ctx->lock); - task = ctx->task; +again: /* - * Worse, we cannot even rely on the ctx actually existing anymore. If - * between find_get_context() and perf_install_in_context() the task - * went through perf_event_exit_task() its dead and we should not be - * adding new events. + * Cannot use task_function_call() because we need to run on the task's + * CPU regardless of whether its current or not. */ - if (task == TASK_TOMBSTONE) { + if (!cpu_function_call(task_cpu(task), __perf_install_in_context, event)) + return; + + raw_spin_lock_irq(&ctx->lock); + task = ctx->task; + if (WARN_ON_ONCE(task == TASK_TOMBSTONE)) { + /* + * Cannot happen because we already checked above (which also + * cannot happen), and we hold ctx->mutex, which serializes us + * against perf_event_exit_task_context(). + */ raw_spin_unlock_irq(&ctx->lock); return; } - update_context_time(ctx); + raw_spin_unlock_irq(&ctx->lock); /* - * Update cgrp time only if current cgrp matches event->cgrp. - * Must be done before calling add_event_to_ctx(). + * Since !ctx->is_active doesn't mean anything, we must IPI + * unconditionally. */ - update_cgrp_time_from_event(event); - add_event_to_ctx(event, ctx); - raw_spin_unlock_irq(&ctx->lock); - - if (task) - task_function_call(task, __perf_install_in_context, ctx); - else - cpu_function_call(cpu, __perf_install_in_context, ctx); + goto again; } /* @@ -2219,17 +2265,18 @@ static void __perf_event_enable(struct perf_event *event, event->state <= PERF_EVENT_STATE_ERROR) return; - update_context_time(ctx); + if (ctx->is_active) + ctx_sched_out(ctx, cpuctx, EVENT_TIME); + __perf_event_mark_enabled(event); if (!ctx->is_active) return; if (!event_filter_match(event)) { - if (is_cgroup_event(event)) { - perf_cgroup_set_timestamp(current, ctx); // XXX ? + if (is_cgroup_event(event)) perf_cgroup_defer_enabled(event); - } + ctx_sched_in(ctx, cpuctx, EVENT_TIME, current); return; } @@ -2237,8 +2284,10 @@ static void __perf_event_enable(struct perf_event *event, * If the event is in a group and isn't the group leader, * then don't put it on unless the group is on. */ - if (leader != event && leader->state != PERF_EVENT_STATE_ACTIVE) + if (leader != event && leader->state != PERF_EVENT_STATE_ACTIVE) { + ctx_sched_in(ctx, cpuctx, EVENT_TIME, current); return; + } task_ctx = cpuctx->task_ctx; if (ctx->task) @@ -2344,24 +2393,33 @@ static void ctx_sched_out(struct perf_event_context *ctx, } ctx->is_active &= ~event_type; + if (!(ctx->is_active & EVENT_ALL)) + ctx->is_active = 0; + if (ctx->task) { WARN_ON_ONCE(cpuctx->task_ctx != ctx); if (!ctx->is_active) cpuctx->task_ctx = NULL; } - update_context_time(ctx); - update_cgrp_time_from_cpuctx(cpuctx); - if (!ctx->nr_active) + is_active ^= ctx->is_active; /* changed bits */ + + if (is_active & EVENT_TIME) { + /* update (and stop) ctx time */ + update_context_time(ctx); + update_cgrp_time_from_cpuctx(cpuctx); + } + + if (!ctx->nr_active || !(is_active & EVENT_ALL)) return; perf_pmu_disable(ctx->pmu); - if ((is_active & EVENT_PINNED) && (event_type & EVENT_PINNED)) { + if (is_active & EVENT_PINNED) { list_for_each_entry(event, &ctx->pinned_groups, group_entry) group_sched_out(event, cpuctx, ctx); } - if ((is_active & EVENT_FLEXIBLE) && (event_type & EVENT_FLEXIBLE)) { + if (is_active & EVENT_FLEXIBLE) { list_for_each_entry(event, &ctx->flexible_groups, group_entry) group_sched_out(event, cpuctx, ctx); } @@ -2641,18 +2699,6 @@ void __perf_event_task_sched_out(struct task_struct *task, perf_cgroup_sched_out(task, next); } -static void task_ctx_sched_out(struct perf_cpu_context *cpuctx, - struct perf_event_context *ctx) -{ - if (!cpuctx->task_ctx) - return; - - if (WARN_ON_ONCE(ctx != cpuctx->task_ctx)) - return; - - ctx_sched_out(ctx, cpuctx, EVENT_ALL); -} - /* * Called with IRQs disabled */ @@ -2735,7 +2781,7 @@ ctx_sched_in(struct perf_event_context *ctx, if (likely(!ctx->nr_events)) return; - ctx->is_active |= event_type; + ctx->is_active |= (event_type | EVENT_TIME); if (ctx->task) { if (!is_active) cpuctx->task_ctx = ctx; @@ -2743,18 +2789,24 @@ ctx_sched_in(struct perf_event_context *ctx, WARN_ON_ONCE(cpuctx->task_ctx != ctx); } - now = perf_clock(); - ctx->timestamp = now; - perf_cgroup_set_timestamp(task, ctx); + is_active ^= ctx->is_active; /* changed bits */ + + if (is_active & EVENT_TIME) { + /* start ctx time */ + now = perf_clock(); + ctx->timestamp = now; + perf_cgroup_set_timestamp(task, ctx); + } + /* * First go through the list and put on any pinned groups * in order to give them the best chance of going on. */ - if (!(is_active & EVENT_PINNED) && (event_type & EVENT_PINNED)) + if (is_active & EVENT_PINNED) ctx_pinned_sched_in(ctx, cpuctx); /* Then walk through the lower prio flexible groups */ - if (!(is_active & EVENT_FLEXIBLE) && (event_type & EVENT_FLEXIBLE)) + if (is_active & EVENT_FLEXIBLE) ctx_flexible_sched_in(ctx, cpuctx); } @@ -3120,6 +3172,7 @@ static void perf_event_enable_on_exec(int ctxn) cpuctx = __get_cpu_context(ctx); perf_ctx_lock(cpuctx, ctx); + ctx_sched_out(ctx, cpuctx, EVENT_TIME); list_for_each_entry(event, &ctx->event_list, event_entry) enabled |= event_enable_on_exec(event, ctx); @@ -3537,12 +3590,22 @@ static void unaccount_event(struct perf_event *event) if (has_branch_stack(event)) dec = true; - if (dec) - static_key_slow_dec_deferred(&perf_sched_events); + if (dec) { + if (!atomic_add_unless(&perf_sched_count, -1, 1)) + schedule_delayed_work(&perf_sched_work, HZ); + } unaccount_event_cpu(event, event->cpu); } +static void perf_sched_delayed(struct work_struct *work) +{ + mutex_lock(&perf_sched_mutex); + if (atomic_dec_and_test(&perf_sched_count)) + static_branch_disable(&perf_sched_events); + mutex_unlock(&perf_sched_mutex); +} + /* * The following implement mutual exclusion of events on "exclusive" pmus * (PERF_PMU_CAP_EXCLUSIVE). Such pmus can only have one event scheduled @@ -3752,30 +3815,42 @@ static void put_event(struct perf_event *event) */ int perf_event_release_kernel(struct perf_event *event) { - struct perf_event_context *ctx; + struct perf_event_context *ctx = event->ctx; struct perf_event *child, *tmp; + /* + * If we got here through err_file: fput(event_file); we will not have + * attached to a context yet. + */ + if (!ctx) { + WARN_ON_ONCE(event->attach_state & + (PERF_ATTACH_CONTEXT|PERF_ATTACH_GROUP)); + goto no_ctx; + } + if (!is_kernel_event(event)) perf_remove_from_owner(event); ctx = perf_event_ctx_lock(event); WARN_ON_ONCE(ctx->parent_ctx); - perf_remove_from_context(event, DETACH_GROUP | DETACH_STATE); - perf_event_ctx_unlock(event, ctx); + perf_remove_from_context(event, DETACH_GROUP); + raw_spin_lock_irq(&ctx->lock); /* - * At this point we must have event->state == PERF_EVENT_STATE_EXIT, - * either from the above perf_remove_from_context() or through - * perf_event_exit_event(). + * Mark this even as STATE_DEAD, there is no external reference to it + * anymore. * - * Therefore, anybody acquiring event->child_mutex after the below - * loop _must_ also see this, most importantly inherit_event() which - * will avoid placing more children on the list. + * Anybody acquiring event->child_mutex after the below loop _must_ + * also see this, most importantly inherit_event() which will avoid + * placing more children on the list. * * Thus this guarantees that we will in fact observe and kill _ALL_ * child events. */ - WARN_ON_ONCE(event->state != PERF_EVENT_STATE_EXIT); + event->state = PERF_EVENT_STATE_DEAD; + raw_spin_unlock_irq(&ctx->lock); + + perf_event_ctx_unlock(event, ctx); again: mutex_lock(&event->child_mutex); @@ -3830,8 +3905,8 @@ again: } mutex_unlock(&event->child_mutex); - /* Must be the last reference */ - put_event(event); +no_ctx: + put_event(event); /* Must be the 'last' reference */ return 0; } EXPORT_SYMBOL_GPL(perf_event_release_kernel); @@ -3988,7 +4063,7 @@ static bool is_event_hup(struct perf_event *event) { bool no_children; - if (event->state != PERF_EVENT_STATE_EXIT) + if (event->state > PERF_EVENT_STATE_EXIT) return false; mutex_lock(&event->child_mutex); @@ -7769,8 +7844,28 @@ static void account_event(struct perf_event *event) if (is_cgroup_event(event)) inc = true; - if (inc) - static_key_slow_inc(&perf_sched_events.key); + if (inc) { + if (atomic_inc_not_zero(&perf_sched_count)) + goto enabled; + + mutex_lock(&perf_sched_mutex); + if (!atomic_read(&perf_sched_count)) { + static_branch_enable(&perf_sched_events); + /* + * Guarantee that all CPUs observe they key change and + * call the perf scheduling hooks before proceeding to + * install events that need them. + */ + synchronize_sched(); + } + /* + * Now that we have waited for the sync_sched(), allow further + * increments to by-pass the mutex. + */ + atomic_inc(&perf_sched_count); + mutex_unlock(&perf_sched_mutex); + } +enabled: account_event_cpu(event, event->cpu); } @@ -8389,10 +8484,19 @@ SYSCALL_DEFINE5(perf_event_open, if (move_group) { gctx = group_leader->ctx; mutex_lock_double(&gctx->mutex, &ctx->mutex); + if (gctx->task == TASK_TOMBSTONE) { + err = -ESRCH; + goto err_locked; + } } else { mutex_lock(&ctx->mutex); } + if (ctx->task == TASK_TOMBSTONE) { + err = -ESRCH; + goto err_locked; + } + if (!perf_event_validate_size(event)) { err = -E2BIG; goto err_locked; @@ -8509,7 +8613,12 @@ err_context: perf_unpin_context(ctx); put_ctx(ctx); err_alloc: - free_event(event); + /* + * If event_file is set, the fput() above will have called ->release() + * and that will take care of freeing the event. + */ + if (!event_file) + free_event(event); err_cpus: put_online_cpus(); err_task: @@ -8563,12 +8672,14 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, WARN_ON_ONCE(ctx->parent_ctx); mutex_lock(&ctx->mutex); + if (ctx->task == TASK_TOMBSTONE) { + err = -ESRCH; + goto err_unlock; + } + if (!exclusive_event_installable(event, ctx)) { - mutex_unlock(&ctx->mutex); - perf_unpin_context(ctx); - put_ctx(ctx); err = -EBUSY; - goto err_free; + goto err_unlock; } perf_install_in_context(ctx, event, cpu); @@ -8577,6 +8688,10 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, return event; +err_unlock: + mutex_unlock(&ctx->mutex); + perf_unpin_context(ctx); + put_ctx(ctx); err_free: free_event(event); err: @@ -8695,7 +8810,7 @@ perf_event_exit_event(struct perf_event *child_event, if (parent_event) perf_group_detach(child_event); list_del_event(child_event, child_ctx); - child_event->state = PERF_EVENT_STATE_EXIT; /* see perf_event_release_kernel() */ + child_event->state = PERF_EVENT_STATE_EXIT; /* is_event_hup() */ raw_spin_unlock_irq(&child_ctx->lock); /* @@ -9206,7 +9321,7 @@ static void perf_event_init_cpu(int cpu) struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); mutex_lock(&swhash->hlist_mutex); - if (swhash->hlist_refcount > 0) { + if (swhash->hlist_refcount > 0 && !swevent_hlist_deref(swhash)) { struct swevent_hlist *hlist; hlist = kzalloc_node(sizeof(*hlist), GFP_KERNEL, cpu_to_node(cpu)); @@ -9282,11 +9397,9 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) switch (action & ~CPU_TASKS_FROZEN) { case CPU_UP_PREPARE: - case CPU_DOWN_FAILED: perf_event_init_cpu(cpu); break; - case CPU_UP_CANCELED: case CPU_DOWN_PREPARE: perf_event_exit_cpu(cpu); break; @@ -9315,9 +9428,6 @@ void __init perf_event_init(void) ret = init_hw_breakpoint(); WARN(ret, "hw_breakpoint initialization failed with: %d", ret); - /* do not patch jump label more than once per second */ - jump_label_rate_limit(&perf_sched_events, HZ); - /* * Build time assertion that we keep the data_head at the intended * location. IOW, validation we got the __reserved[] size right. diff --git a/kernel/memremap.c b/kernel/memremap.c index 2c468dea60bc..b981a7b023f0 100644 --- a/kernel/memremap.c +++ b/kernel/memremap.c @@ -114,7 +114,7 @@ EXPORT_SYMBOL(memunmap); static void devm_memremap_release(struct device *dev, void *res) { - memunmap(res); + memunmap(*(void **)res); } static int devm_memremap_match(struct device *dev, void *res, void *match_data) @@ -136,8 +136,10 @@ void *devm_memremap(struct device *dev, resource_size_t offset, if (addr) { *ptr = addr; devres_add(dev, ptr); - } else + } else { devres_free(ptr); + return ERR_PTR(-ENXIO); + } return addr; } diff --git a/kernel/module.c b/kernel/module.c index 9537da37ce87..794ebe8e878d 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -984,6 +984,8 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, mod->exit(); blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GOING, mod); + ftrace_release_mod(mod); + async_synchronize_full(); /* Store the name of the last unloaded module for diagnostic purposes */ @@ -3313,6 +3315,7 @@ fail: module_put(mod); blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GOING, mod); + ftrace_release_mod(mod); free_module(mod); wake_up_all(&module_wq); return ret; @@ -3389,6 +3392,7 @@ static int complete_formation(struct module *mod, struct load_info *info) mod->state = MODULE_STATE_COMING; mutex_unlock(&module_mutex); + ftrace_module_enable(mod); blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_COMING, mod); return 0; diff --git a/kernel/resource.c b/kernel/resource.c index 09c0597840b0..3669d1bfc425 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -1083,9 +1083,10 @@ struct resource * __request_region(struct resource *parent, if (!conflict) break; if (conflict != parent) { - parent = conflict; - if (!(conflict->flags & IORESOURCE_BUSY)) + if (!(conflict->flags & IORESOURCE_BUSY)) { + parent = conflict; continue; + } } if (conflict->flags & flags & IORESOURCE_MUXED) { add_wait_queue(&muxed_resource_wait, &wait); diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index cd64c979d0e1..57b939c81bce 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -420,7 +420,7 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se, * entity. */ if (dl_time_before(dl_se->deadline, rq_clock(rq))) { - printk_deferred_once("sched: DL replenish lagged to much\n"); + printk_deferred_once("sched: DL replenish lagged too much\n"); dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline; dl_se->runtime = pi_se->dl_runtime; } diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index eca592f977b2..57a6eea84694 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -4961,7 +4961,7 @@ void ftrace_release_mod(struct module *mod) mutex_unlock(&ftrace_lock); } -static void ftrace_module_enable(struct module *mod) +void ftrace_module_enable(struct module *mod) { struct dyn_ftrace *rec; struct ftrace_page *pg; @@ -5038,38 +5038,8 @@ void ftrace_module_init(struct module *mod) ftrace_process_locs(mod, mod->ftrace_callsites, mod->ftrace_callsites + mod->num_ftrace_callsites); } - -static int ftrace_module_notify(struct notifier_block *self, - unsigned long val, void *data) -{ - struct module *mod = data; - - switch (val) { - case MODULE_STATE_COMING: - ftrace_module_enable(mod); - break; - case MODULE_STATE_GOING: - ftrace_release_mod(mod); - break; - default: - break; - } - - return 0; -} -#else -static int ftrace_module_notify(struct notifier_block *self, - unsigned long val, void *data) -{ - return 0; -} #endif /* CONFIG_MODULES */ -struct notifier_block ftrace_module_nb = { - .notifier_call = ftrace_module_notify, - .priority = INT_MIN, /* Run after anything that can remove kprobes */ -}; - void __init ftrace_init(void) { extern unsigned long __start_mcount_loc[]; @@ -5098,10 +5068,6 @@ void __init ftrace_init(void) __start_mcount_loc, __stop_mcount_loc); - ret = register_module_notifier(&ftrace_module_nb); - if (ret) - pr_warning("Failed to register trace ftrace module exit notifier\n"); - set_ftrace_early_filters(); return; diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index f333e57c4614..05ddc0820771 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -97,16 +97,16 @@ trace_find_event_field(struct trace_event_call *call, char *name) struct ftrace_event_field *field; struct list_head *head; - field = __find_event_field(&ftrace_generic_fields, name); + head = trace_get_fields(call); + field = __find_event_field(head, name); if (field) return field; - field = __find_event_field(&ftrace_common_fields, name); + field = __find_event_field(&ftrace_generic_fields, name); if (field) return field; - head = trace_get_fields(call); - return __find_event_field(head, name); + return __find_event_field(&ftrace_common_fields, name); } static int __trace_define_field(struct list_head *head, const char *type, @@ -171,8 +171,10 @@ static int trace_define_generic_fields(void) { int ret; - __generic_field(int, cpu, FILTER_OTHER); - __generic_field(char *, comm, FILTER_PTR_STRING); + __generic_field(int, CPU, FILTER_CPU); + __generic_field(int, cpu, FILTER_CPU); + __generic_field(char *, COMM, FILTER_COMM); + __generic_field(char *, comm, FILTER_COMM); return ret; } @@ -869,7 +871,8 @@ t_next(struct seq_file *m, void *v, loff_t *pos) * The ftrace subsystem is for showing formats only. * They can not be enabled or disabled via the event files. */ - if (call->class && call->class->reg) + if (call->class && call->class->reg && + !(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)) return file; } diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index f93a219b18da..6816302542b2 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -1043,13 +1043,14 @@ static int init_pred(struct filter_parse_state *ps, return -EINVAL; } - if (is_string_field(field)) { + if (field->filter_type == FILTER_COMM) { + filter_build_regex(pred); + fn = filter_pred_comm; + pred->regex.field_len = TASK_COMM_LEN; + } else if (is_string_field(field)) { filter_build_regex(pred); - if (!strcmp(field->name, "comm")) { - fn = filter_pred_comm; - pred->regex.field_len = TASK_COMM_LEN; - } else if (field->filter_type == FILTER_STATIC_STRING) { + if (field->filter_type == FILTER_STATIC_STRING) { fn = filter_pred_string; pred->regex.field_len = field->size; } else if (field->filter_type == FILTER_DYN_STRING) @@ -1072,7 +1073,7 @@ static int init_pred(struct filter_parse_state *ps, } pred->val = val; - if (!strcmp(field->name, "cpu")) + if (field->filter_type == FILTER_CPU) fn = filter_pred_cpu; else fn = select_comparison_fn(pred->op, field->size, diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c index 202df6cffcca..2a1abbaca10e 100644 --- a/kernel/trace/trace_stack.c +++ b/kernel/trace/trace_stack.c @@ -156,7 +156,11 @@ check_stack(unsigned long ip, unsigned long *stack) for (; p < top && i < stack_trace_max.nr_entries; p++) { if (stack_dump_trace[i] == ULONG_MAX) break; - if (*p == stack_dump_trace[i]) { + /* + * The READ_ONCE_NOCHECK is used to let KASAN know that + * this is not a stack-out-of-bounds error. + */ + if ((READ_ONCE_NOCHECK(*p)) == stack_dump_trace[i]) { stack_dump_trace[x] = stack_dump_trace[i++]; this_size = stack_trace_index[x++] = (top - p) * sizeof(unsigned long); diff --git a/mm/filemap.c b/mm/filemap.c index 23edccecadb0..3461d97ecb30 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -446,7 +446,8 @@ int filemap_write_and_wait(struct address_space *mapping) { int err = 0; - if (mapping->nrpages) { + if ((!dax_mapping(mapping) && mapping->nrpages) || + (dax_mapping(mapping) && mapping->nrexceptional)) { err = filemap_fdatawrite(mapping); /* * Even if the above returned error, the pages may be @@ -482,13 +483,8 @@ int filemap_write_and_wait_range(struct address_space *mapping, { int err = 0; - if (dax_mapping(mapping) && mapping->nrexceptional) { - err = dax_writeback_mapping_range(mapping, lstart, lend); - if (err) - return err; - } - - if (mapping->nrpages) { + if ((!dax_mapping(mapping) && mapping->nrpages) || + (dax_mapping(mapping) && mapping->nrexceptional)) { err = __filemap_fdatawrite_range(mapping, lstart, lend, WB_SYNC_ALL); /* See comment of filemap_write_and_wait() */ diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 08fc0ba2207e..e10a4fee88d2 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1700,7 +1700,8 @@ bool move_huge_pmd(struct vm_area_struct *vma, struct vm_area_struct *new_vma, pmd = pmdp_huge_get_and_clear(mm, old_addr, old_pmd); VM_BUG_ON(!pmd_none(*new_pmd)); - if (pmd_move_must_withdraw(new_ptl, old_ptl)) { + if (pmd_move_must_withdraw(new_ptl, old_ptl) && + vma_is_anonymous(vma)) { pgtable_t pgtable; pgtable = pgtable_trans_huge_withdraw(mm, old_pmd); pgtable_trans_huge_deposit(mm, new_pmd, pgtable); @@ -2835,6 +2836,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd, pgtable_t pgtable; pmd_t _pmd; bool young, write, dirty; + unsigned long addr; int i; VM_BUG_ON(haddr & ~HPAGE_PMD_MASK); @@ -2860,10 +2862,11 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd, young = pmd_young(*pmd); dirty = pmd_dirty(*pmd); + pmdp_huge_split_prepare(vma, haddr, pmd); pgtable = pgtable_trans_huge_withdraw(mm, pmd); pmd_populate(mm, &_pmd, pgtable); - for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) { + for (i = 0, addr = haddr; i < HPAGE_PMD_NR; i++, addr += PAGE_SIZE) { pte_t entry, *pte; /* * Note that NUMA hinting access restrictions are not @@ -2884,9 +2887,9 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd, } if (dirty) SetPageDirty(page + i); - pte = pte_offset_map(&_pmd, haddr); + pte = pte_offset_map(&_pmd, addr); BUG_ON(!pte_none(*pte)); - set_pte_at(mm, haddr, pte, entry); + set_pte_at(mm, addr, pte, entry); atomic_inc(&page[i]._mapcount); pte_unmap(pte); } @@ -2936,7 +2939,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd, pmd_populate(mm, pmd, pgtable); if (freeze) { - for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) { + for (i = 0; i < HPAGE_PMD_NR; i++) { page_remove_rmap(page + i, false); put_page(page + i); } diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 06ae13e869d0..01f2b48c8618 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2630,8 +2630,10 @@ static int __init hugetlb_init(void) hugetlb_add_hstate(HUGETLB_PAGE_ORDER); } default_hstate_idx = hstate_index(size_to_hstate(default_hstate_size)); - if (default_hstate_max_huge_pages) - default_hstate.max_huge_pages = default_hstate_max_huge_pages; + if (default_hstate_max_huge_pages) { + if (!default_hstate.max_huge_pages) + default_hstate.max_huge_pages = default_hstate_max_huge_pages; + } hugetlb_init_hstates(); gather_bootmem_prealloc(); diff --git a/mm/memory.c b/mm/memory.c index 38090ca37a08..906d8e3b42c0 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3425,8 +3425,18 @@ static int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, if (unlikely(pmd_none(*pmd)) && unlikely(__pte_alloc(mm, vma, pmd, address))) return VM_FAULT_OOM; - /* if an huge pmd materialized from under us just retry later */ - if (unlikely(pmd_trans_huge(*pmd) || pmd_devmap(*pmd))) + /* + * If a huge pmd materialized under us just retry later. Use + * pmd_trans_unstable() instead of pmd_trans_huge() to ensure the pmd + * didn't become pmd_trans_huge under us and then back to pmd_none, as + * a result of MADV_DONTNEED running immediately after a huge pmd fault + * in a different thread of this mm, in turn leading to a misleading + * pmd_trans_huge() retval. All we have to ensure is that it is a + * regular pmd that we can walk with pte_offset_map() and we can do that + * through an atomic read in C, which is what pmd_trans_unstable() + * provides. + */ + if (unlikely(pmd_trans_unstable(pmd) || pmd_devmap(*pmd))) return 0; /* * A regular pmd is established and it can't morph into a huge pmd diff --git a/mm/migrate.c b/mm/migrate.c index b1034f9c77e7..3ad0fea5c438 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -1582,7 +1582,7 @@ static struct page *alloc_misplaced_dst_page(struct page *page, (GFP_HIGHUSER_MOVABLE | __GFP_THISNODE | __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN) & - ~(__GFP_IO | __GFP_FS), 0); + ~__GFP_RECLAIM, 0); return newpage; } diff --git a/mm/mmap.c b/mm/mmap.c index e2e9f48b06c2..90e3b869a8b9 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2664,12 +2664,29 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, if (!vma || !(vma->vm_flags & VM_SHARED)) goto out; - if (start < vma->vm_start || start + size > vma->vm_end) + if (start < vma->vm_start) goto out; - if (pgoff == linear_page_index(vma, start)) { - ret = 0; - goto out; + if (start + size > vma->vm_end) { + struct vm_area_struct *next; + + for (next = vma->vm_next; next; next = next->vm_next) { + /* hole between vmas ? */ + if (next->vm_start != next->vm_prev->vm_end) + goto out; + + if (next->vm_file != vma->vm_file) + goto out; + + if (next->vm_flags != vma->vm_flags) + goto out; + + if (start + size <= next->vm_end) + break; + } + + if (!next) + goto out; } prot |= vma->vm_flags & VM_READ ? PROT_READ : 0; @@ -2679,9 +2696,16 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, flags &= MAP_NONBLOCK; flags |= MAP_SHARED | MAP_FIXED | MAP_POPULATE; if (vma->vm_flags & VM_LOCKED) { + struct vm_area_struct *tmp; flags |= MAP_LOCKED; + /* drop PG_Mlocked flag for over-mapped range */ - munlock_vma_pages_range(vma, start, start + size); + for (tmp = vma; tmp->vm_start >= start + size; + tmp = tmp->vm_next) { + munlock_vma_pages_range(tmp, + max(tmp->vm_start, start), + min(tmp->vm_end, start + size)); + } } file = get_file(vma->vm_file); diff --git a/mm/slab.c b/mm/slab.c index 6ecc697a8bc4..621fbcb35a36 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2275,7 +2275,7 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) err = setup_cpu_cache(cachep, gfp); if (err) { - __kmem_cache_shutdown(cachep); + __kmem_cache_release(cachep); return err; } @@ -2414,12 +2414,13 @@ int __kmem_cache_shrink(struct kmem_cache *cachep, bool deactivate) int __kmem_cache_shutdown(struct kmem_cache *cachep) { + return __kmem_cache_shrink(cachep, false); +} + +void __kmem_cache_release(struct kmem_cache *cachep) +{ int i; struct kmem_cache_node *n; - int rc = __kmem_cache_shrink(cachep, false); - - if (rc) - return rc; free_percpu(cachep->cpu_cache); @@ -2430,7 +2431,6 @@ int __kmem_cache_shutdown(struct kmem_cache *cachep) kfree(n); cachep->node[i] = NULL; } - return 0; } /* diff --git a/mm/slab.h b/mm/slab.h index 834ad240c0bb..2eedacea439d 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -140,6 +140,7 @@ static inline unsigned long kmem_cache_flags(unsigned long object_size, #define CACHE_CREATE_MASK (SLAB_CORE_FLAGS | SLAB_DEBUG_FLAGS | SLAB_CACHE_FLAGS) int __kmem_cache_shutdown(struct kmem_cache *); +void __kmem_cache_release(struct kmem_cache *); int __kmem_cache_shrink(struct kmem_cache *, bool); void slab_kmem_cache_release(struct kmem_cache *); diff --git a/mm/slab_common.c b/mm/slab_common.c index b50aef01ccf7..065b7bdabdc3 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -693,6 +693,7 @@ static inline int shutdown_memcg_caches(struct kmem_cache *s, void slab_kmem_cache_release(struct kmem_cache *s) { + __kmem_cache_release(s); destroy_memcg_params(s); kfree_const(s->name); kmem_cache_free(kmem_cache, s); diff --git a/mm/slob.c b/mm/slob.c index 17e8f8cc7c53..5ec158054ffe 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -630,6 +630,10 @@ int __kmem_cache_shutdown(struct kmem_cache *c) return 0; } +void __kmem_cache_release(struct kmem_cache *c) +{ +} + int __kmem_cache_shrink(struct kmem_cache *d, bool deactivate) { return 0; diff --git a/mm/slub.c b/mm/slub.c index 2e1355ac056b..d8fbd4a6ed59 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1592,18 +1592,12 @@ static inline void add_partial(struct kmem_cache_node *n, __add_partial(n, page, tail); } -static inline void -__remove_partial(struct kmem_cache_node *n, struct page *page) -{ - list_del(&page->lru); - n->nr_partial--; -} - static inline void remove_partial(struct kmem_cache_node *n, struct page *page) { lockdep_assert_held(&n->list_lock); - __remove_partial(n, page); + list_del(&page->lru); + n->nr_partial--; } /* @@ -3184,6 +3178,12 @@ static void free_kmem_cache_nodes(struct kmem_cache *s) } } +void __kmem_cache_release(struct kmem_cache *s) +{ + free_percpu(s->cpu_slab); + free_kmem_cache_nodes(s); +} + static int init_kmem_cache_nodes(struct kmem_cache *s) { int node; @@ -3443,28 +3443,31 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page, /* * Attempt to free all partial slabs on a node. - * This is called from kmem_cache_close(). We must be the last thread - * using the cache and therefore we do not need to lock anymore. + * This is called from __kmem_cache_shutdown(). We must take list_lock + * because sysfs file might still access partial list after the shutdowning. */ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n) { struct page *page, *h; + BUG_ON(irqs_disabled()); + spin_lock_irq(&n->list_lock); list_for_each_entry_safe(page, h, &n->partial, lru) { if (!page->inuse) { - __remove_partial(n, page); + remove_partial(n, page); discard_slab(s, page); } else { list_slab_objects(s, page, - "Objects remaining in %s on kmem_cache_close()"); + "Objects remaining in %s on __kmem_cache_shutdown()"); } } + spin_unlock_irq(&n->list_lock); } /* * Release all resources used by a slab cache. */ -static inline int kmem_cache_close(struct kmem_cache *s) +int __kmem_cache_shutdown(struct kmem_cache *s) { int node; struct kmem_cache_node *n; @@ -3476,16 +3479,9 @@ static inline int kmem_cache_close(struct kmem_cache *s) if (n->nr_partial || slabs_node(s, node)) return 1; } - free_percpu(s->cpu_slab); - free_kmem_cache_nodes(s); return 0; } -int __kmem_cache_shutdown(struct kmem_cache *s) -{ - return kmem_cache_close(s); -} - /******************************************************************** * Kmalloc subsystem *******************************************************************/ @@ -3980,7 +3976,7 @@ int __kmem_cache_create(struct kmem_cache *s, unsigned long flags) memcg_propagate_slab_attrs(s); err = sysfs_slab_add(s); if (err) - kmem_cache_close(s); + __kmem_cache_release(s); return err; } diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index d5871ac493eb..f066781be3c8 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1625,7 +1625,7 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) rt = atrtr_find(&at_hint); } - err = ENETUNREACH; + err = -ENETUNREACH; if (!rt) goto out; diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index e6c8382c79ba..ccf70bed0d0c 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -527,11 +527,12 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv, * gets dereferenced. */ spin_lock_bh(&bat_priv->gw.list_lock); - hlist_del_init_rcu(&gw_node->list); + if (!hlist_unhashed(&gw_node->list)) { + hlist_del_init_rcu(&gw_node->list); + batadv_gw_node_free_ref(gw_node); + } spin_unlock_bh(&bat_priv->gw.list_lock); - batadv_gw_node_free_ref(gw_node); - curr_gw = batadv_gw_get_selected_gw_node(bat_priv); if (gw_node == curr_gw) batadv_gw_reselect(bat_priv); diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 01acccc4d218..57f7107169f5 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -76,6 +76,28 @@ out: } /** + * batadv_mutual_parents - check if two devices are each others parent + * @dev1: 1st net_device + * @dev2: 2nd net_device + * + * veth devices come in pairs and each is the parent of the other! + * + * Return: true if the devices are each others parent, otherwise false + */ +static bool batadv_mutual_parents(const struct net_device *dev1, + const struct net_device *dev2) +{ + int dev1_parent_iflink = dev_get_iflink(dev1); + int dev2_parent_iflink = dev_get_iflink(dev2); + + if (!dev1_parent_iflink || !dev2_parent_iflink) + return false; + + return (dev1_parent_iflink == dev2->ifindex) && + (dev2_parent_iflink == dev1->ifindex); +} + +/** * batadv_is_on_batman_iface - check if a device is a batman iface descendant * @net_dev: the device to check * @@ -108,6 +130,9 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev) if (WARN(!parent_dev, "Cannot find parent device")) return false; + if (batadv_mutual_parents(net_dev, parent_dev)) + return false; + ret = batadv_is_on_batman_iface(parent_dev); return ret; diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index cdfc85fa2743..0e80fd1461ab 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -303,9 +303,11 @@ static void batadv_tt_global_size_mod(struct batadv_orig_node *orig_node, if (atomic_add_return(v, &vlan->tt.num_entries) == 0) { spin_lock_bh(&orig_node->vlan_list_lock); - hlist_del_init_rcu(&vlan->list); + if (!hlist_unhashed(&vlan->list)) { + hlist_del_init_rcu(&vlan->list); + batadv_orig_node_vlan_free_ref(vlan); + } spin_unlock_bh(&orig_node->vlan_list_lock); - batadv_orig_node_vlan_free_ref(vlan); } batadv_orig_node_vlan_free_ref(vlan); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 47bcef754796..883c821a9e78 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -4112,8 +4112,10 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status, break; } - *req_complete = bt_cb(skb)->hci.req_complete; - *req_complete_skb = bt_cb(skb)->hci.req_complete_skb; + if (bt_cb(skb)->hci.req_flags & HCI_REQ_SKB) + *req_complete_skb = bt_cb(skb)->hci.req_complete_skb; + else + *req_complete = bt_cb(skb)->hci.req_complete; kfree_skb(skb); } spin_unlock_irqrestore(&hdev->cmd_q.lock, flags); diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 30e105f57f0d..74c278e00225 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -425,8 +425,8 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, mp = br_mdb_ip_get(mdb, group); if (!mp) { mp = br_multicast_new_group(br, port, group); - err = PTR_ERR(mp); - if (IS_ERR(mp)) + err = PTR_ERR_OR_ZERO(mp); + if (err) return err; } diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c index 61d7617d9249..b82440e1fcb4 100644 --- a/net/caif/cfrfml.c +++ b/net/caif/cfrfml.c @@ -159,7 +159,7 @@ static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt) tmppkt = NULL; /* Verify that length is correct */ - err = EPROTO; + err = -EPROTO; if (rfml->pdu_size != cfpkt_getlen(pkt) - RFM_HEAD_SIZE + 1) goto out; } diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 9cfedf565f5b..9382619a405b 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1197,6 +1197,13 @@ static bool ceph_msg_data_advance(struct ceph_msg_data_cursor *cursor, return new_piece; } +static size_t sizeof_footer(struct ceph_connection *con) +{ + return (con->peer_features & CEPH_FEATURE_MSG_AUTH) ? + sizeof(struct ceph_msg_footer) : + sizeof(struct ceph_msg_footer_old); +} + static void prepare_message_data(struct ceph_msg *msg, u32 data_len) { BUG_ON(!msg); @@ -2335,9 +2342,9 @@ static int read_partial_message(struct ceph_connection *con) ceph_pr_addr(&con->peer_addr.in_addr), seq, con->in_seq + 1); con->in_base_pos = -front_len - middle_len - data_len - - sizeof(m->footer); + sizeof_footer(con); con->in_tag = CEPH_MSGR_TAG_READY; - return 0; + return 1; } else if ((s64)seq - (s64)con->in_seq > 1) { pr_err("read_partial_message bad seq %lld expected %lld\n", seq, con->in_seq + 1); @@ -2360,10 +2367,10 @@ static int read_partial_message(struct ceph_connection *con) /* skip this message */ dout("alloc_msg said skip message\n"); con->in_base_pos = -front_len - middle_len - data_len - - sizeof(m->footer); + sizeof_footer(con); con->in_tag = CEPH_MSGR_TAG_READY; con->in_seq++; - return 0; + return 1; } BUG_ON(!con->in_msg); diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 3534e12683d3..5bc053778fed 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -2853,8 +2853,8 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, mutex_lock(&osdc->request_mutex); req = __lookup_request(osdc, tid); if (!req) { - pr_warn("%s osd%d tid %llu unknown, skipping\n", - __func__, osd->o_osd, tid); + dout("%s osd%d tid %llu unknown, skipping\n", __func__, + osd->o_osd, tid); m = NULL; *skip = 1; goto out; diff --git a/net/core/dev.c b/net/core/dev.c index 8cba3d852f25..0ef061b2badc 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5379,12 +5379,12 @@ void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter) { struct netdev_adjacent *lower; - lower = list_entry((*iter)->next, struct netdev_adjacent, list); + lower = list_entry(*iter, struct netdev_adjacent, list); if (&lower->list == &dev->adj_list.lower) return NULL; - *iter = &lower->list; + *iter = lower->list.next; return lower->dev; } @@ -7422,8 +7422,10 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, dev->priv_flags = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM; setup(dev); - if (!dev->tx_queue_len) + if (!dev->tx_queue_len) { dev->priv_flags |= IFF_NO_QUEUE; + dev->tx_queue_len = 1; + } dev->num_tx_queues = txqs; dev->real_num_tx_queues = txqs; diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index eab81bc80e5c..12e700332010 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -399,6 +399,13 @@ ip_proto_again: goto out_bad; proto = eth->h_proto; nhoff += sizeof(*eth); + + /* Cap headers that we access via pointers at the + * end of the Ethernet header as our maximum alignment + * at that point is only 2 bytes. + */ + if (NET_IP_ALIGN) + hlen = nhoff; } key_control->flags |= FLOW_DIS_ENCAPSULATION; diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 5684e14932bd..902d606324a0 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -824,26 +824,26 @@ lookup: if (sk->sk_state == DCCP_NEW_SYN_RECV) { struct request_sock *req = inet_reqsk(sk); - struct sock *nsk = NULL; + struct sock *nsk; sk = req->rsk_listener; - if (likely(sk->sk_state == DCCP_LISTEN)) { - nsk = dccp_check_req(sk, skb, req); - } else { + if (unlikely(sk->sk_state != DCCP_LISTEN)) { inet_csk_reqsk_queue_drop_and_put(sk, req); goto lookup; } + sock_hold(sk); + nsk = dccp_check_req(sk, skb, req); if (!nsk) { reqsk_put(req); - goto discard_it; + goto discard_and_relse; } if (nsk == sk) { - sock_hold(sk); reqsk_put(req); } else if (dccp_child_process(sk, nsk, skb)) { dccp_v4_ctl_send_reset(sk, skb); - goto discard_it; + goto discard_and_relse; } else { + sock_put(sk); return 0; } } diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 9c6d0508e63a..b8608b71a66d 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -691,26 +691,26 @@ lookup: if (sk->sk_state == DCCP_NEW_SYN_RECV) { struct request_sock *req = inet_reqsk(sk); - struct sock *nsk = NULL; + struct sock *nsk; sk = req->rsk_listener; - if (likely(sk->sk_state == DCCP_LISTEN)) { - nsk = dccp_check_req(sk, skb, req); - } else { + if (unlikely(sk->sk_state != DCCP_LISTEN)) { inet_csk_reqsk_queue_drop_and_put(sk, req); goto lookup; } + sock_hold(sk); + nsk = dccp_check_req(sk, skb, req); if (!nsk) { reqsk_put(req); - goto discard_it; + goto discard_and_relse; } if (nsk == sk) { - sock_hold(sk); reqsk_put(req); } else if (dccp_child_process(sk, nsk, skb)) { dccp_v6_ctl_send_reset(sk, skb); - goto discard_it; + goto discard_and_relse; } else { + sock_put(sk); return 0; } } diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 40b9ca72aae3..ab24521beb4d 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1194,7 +1194,6 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent, if (ret) { netdev_err(master, "error %d registering interface %s\n", ret, slave_dev->name); - phy_disconnect(p->phy); ds->ports[port] = NULL; free_netdev(slave_dev); return ret; @@ -1205,6 +1204,7 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent, ret = dsa_slave_phy_setup(p, slave_dev); if (ret) { netdev_err(master, "error %d setting up slave phy\n", ret); + unregister_netdev(slave_dev); free_netdev(slave_dev); return ret; } diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index cebd9d31e65a..f6303b17546b 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1847,7 +1847,7 @@ static int inet_netconf_get_devconf(struct sk_buff *in_skb, if (err < 0) goto errout; - err = EINVAL; + err = -EINVAL; if (!tb[NETCONFA_IFINDEX]) goto errout; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 46b9c887bede..64148914803a 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -789,14 +789,16 @@ static void inet_child_forget(struct sock *sk, struct request_sock *req, reqsk_put(req); } -void inet_csk_reqsk_queue_add(struct sock *sk, struct request_sock *req, - struct sock *child) +struct sock *inet_csk_reqsk_queue_add(struct sock *sk, + struct request_sock *req, + struct sock *child) { struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; spin_lock(&queue->rskq_lock); if (unlikely(sk->sk_state != TCP_LISTEN)) { inet_child_forget(sk, req, child); + child = NULL; } else { req->sk = child; req->dl_next = NULL; @@ -808,6 +810,7 @@ void inet_csk_reqsk_queue_add(struct sock *sk, struct request_sock *req, sk_acceptq_added(sk); } spin_unlock(&queue->rskq_lock); + return child; } EXPORT_SYMBOL(inet_csk_reqsk_queue_add); @@ -817,11 +820,8 @@ struct sock *inet_csk_complete_hashdance(struct sock *sk, struct sock *child, if (own_req) { inet_csk_reqsk_queue_drop(sk, req); reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req); - inet_csk_reqsk_queue_add(sk, req, child); - /* Warning: caller must not call reqsk_put(req); - * child stole last reference on it. - */ - return child; + if (inet_csk_reqsk_queue_add(sk, req, child)) + return child; } /* Too bad, another child took ownership of the request, undo. */ bh_unlock_sock(child); diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 56fdf4e0dce4..41ba68de46d8 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1054,8 +1054,9 @@ static const struct net_device_ops gre_tap_netdev_ops = { static void ipgre_tap_setup(struct net_device *dev) { ether_setup(dev); - dev->netdev_ops = &gre_tap_netdev_ops; - dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + dev->netdev_ops = &gre_tap_netdev_ops; + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; ip_tunnel_setup(dev, gre_tap_net_id); } diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 5f73a7c03e27..a50124260f5a 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -249,6 +249,8 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc, switch (cmsg->cmsg_type) { case IP_RETOPTS: err = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)); + + /* Our caller is responsible for freeing ipc->opt */ err = ip_options_get(net, &ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40); if (err) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index c117b21b937d..d3a27165f9cc 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -746,8 +746,10 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) if (msg->msg_controllen) { err = ip_cmsg_send(sock_net(sk), msg, &ipc, false); - if (err) + if (unlikely(err)) { + kfree(ipc.opt); return err; + } if (ipc.opt) free = 1; } diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index bc35f1842512..7113bae4e6a0 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -547,8 +547,10 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) if (msg->msg_controllen) { err = ip_cmsg_send(net, msg, &ipc, false); - if (err) + if (unlikely(err)) { + kfree(ipc.opt); goto out; + } if (ipc.opt) free = 1; } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 85f184e429c6..02c62299d717 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -129,6 +129,7 @@ static int ip_rt_mtu_expires __read_mostly = 10 * 60 * HZ; static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; static int ip_rt_min_advmss __read_mostly = 256; +static int ip_rt_gc_timeout __read_mostly = RT_GC_TIMEOUT; /* * Interface to generic destination cache. */ @@ -755,7 +756,7 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow struct fib_nh *nh = &FIB_RES_NH(res); update_or_create_fnhe(nh, fl4->daddr, new_gw, - 0, 0); + 0, jiffies + ip_rt_gc_timeout); } if (kill_route) rt->dst.obsolete = DST_OBSOLETE_KILL; @@ -1556,6 +1557,36 @@ static void ip_handle_martian_source(struct net_device *dev, #endif } +static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr) +{ + struct fnhe_hash_bucket *hash; + struct fib_nh_exception *fnhe, __rcu **fnhe_p; + u32 hval = fnhe_hashfun(daddr); + + spin_lock_bh(&fnhe_lock); + + hash = rcu_dereference_protected(nh->nh_exceptions, + lockdep_is_held(&fnhe_lock)); + hash += hval; + + fnhe_p = &hash->chain; + fnhe = rcu_dereference_protected(*fnhe_p, lockdep_is_held(&fnhe_lock)); + while (fnhe) { + if (fnhe->fnhe_daddr == daddr) { + rcu_assign_pointer(*fnhe_p, rcu_dereference_protected( + fnhe->fnhe_next, lockdep_is_held(&fnhe_lock))); + fnhe_flush_routes(fnhe); + kfree_rcu(fnhe, rcu); + break; + } + fnhe_p = &fnhe->fnhe_next; + fnhe = rcu_dereference_protected(fnhe->fnhe_next, + lockdep_is_held(&fnhe_lock)); + } + + spin_unlock_bh(&fnhe_lock); +} + /* called in rcu_read_lock() section */ static int __mkroute_input(struct sk_buff *skb, const struct fib_result *res, @@ -1609,11 +1640,20 @@ static int __mkroute_input(struct sk_buff *skb, fnhe = find_exception(&FIB_RES_NH(*res), daddr); if (do_cache) { - if (fnhe) + if (fnhe) { rth = rcu_dereference(fnhe->fnhe_rth_input); - else - rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); + if (rth && rth->dst.expires && + time_after(jiffies, rth->dst.expires)) { + ip_del_fnhe(&FIB_RES_NH(*res), daddr); + fnhe = NULL; + } else { + goto rt_cache; + } + } + + rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); +rt_cache: if (rt_cache_valid(rth)) { skb_dst_set_noref(skb, &rth->dst); goto out; @@ -2014,19 +2054,29 @@ static struct rtable *__mkroute_output(const struct fib_result *res, struct fib_nh *nh = &FIB_RES_NH(*res); fnhe = find_exception(nh, fl4->daddr); - if (fnhe) + if (fnhe) { prth = &fnhe->fnhe_rth_output; - else { - if (unlikely(fl4->flowi4_flags & - FLOWI_FLAG_KNOWN_NH && - !(nh->nh_gw && - nh->nh_scope == RT_SCOPE_LINK))) { - do_cache = false; - goto add; + rth = rcu_dereference(*prth); + if (rth && rth->dst.expires && + time_after(jiffies, rth->dst.expires)) { + ip_del_fnhe(nh, fl4->daddr); + fnhe = NULL; + } else { + goto rt_cache; } - prth = raw_cpu_ptr(nh->nh_pcpu_rth_output); } + + if (unlikely(fl4->flowi4_flags & + FLOWI_FLAG_KNOWN_NH && + !(nh->nh_gw && + nh->nh_scope == RT_SCOPE_LINK))) { + do_cache = false; + goto add; + } + prth = raw_cpu_ptr(nh->nh_pcpu_rth_output); rth = rcu_dereference(*prth); + +rt_cache: if (rt_cache_valid(rth)) { dst_hold(&rth->dst); return rth; @@ -2569,7 +2619,6 @@ void ip_rt_multicast_event(struct in_device *in_dev) } #ifdef CONFIG_SYSCTL -static int ip_rt_gc_timeout __read_mostly = RT_GC_TIMEOUT; static int ip_rt_gc_interval __read_mostly = 60 * HZ; static int ip_rt_gc_min_interval __read_mostly = HZ / 2; static int ip_rt_gc_elasticity __read_mostly = 8; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 0c36ef4a3f86..483ffdf5aa4d 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2950,7 +2950,7 @@ static void __tcp_alloc_md5sig_pool(void) struct crypto_hash *hash; hash = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR_OR_NULL(hash)) + if (IS_ERR(hash)) return; per_cpu(tcp_md5sig_pool, cpu).md5_desc.tfm = hash; } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 1c2a73406261..3b2c8e90a475 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2896,7 +2896,10 @@ static void tcp_update_rtt_min(struct sock *sk, u32 rtt_us) { const u32 now = tcp_time_stamp, wlen = sysctl_tcp_min_rtt_wlen * HZ; struct rtt_meas *m = tcp_sk(sk)->rtt_min; - struct rtt_meas rttm = { .rtt = (rtt_us ? : 1), .ts = now }; + struct rtt_meas rttm = { + .rtt = likely(rtt_us) ? rtt_us : jiffies_to_usecs(1), + .ts = now, + }; u32 elapsed; /* Check if the new measurement updates the 1st, 2nd, or 3rd choices */ diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 7f6ff037adaf..487ac67059e2 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1597,28 +1597,30 @@ process: if (sk->sk_state == TCP_NEW_SYN_RECV) { struct request_sock *req = inet_reqsk(sk); - struct sock *nsk = NULL; + struct sock *nsk; sk = req->rsk_listener; - if (tcp_v4_inbound_md5_hash(sk, skb)) - goto discard_and_relse; - if (likely(sk->sk_state == TCP_LISTEN)) { - nsk = tcp_check_req(sk, skb, req, false); - } else { + if (unlikely(tcp_v4_inbound_md5_hash(sk, skb))) { + reqsk_put(req); + goto discard_it; + } + if (unlikely(sk->sk_state != TCP_LISTEN)) { inet_csk_reqsk_queue_drop_and_put(sk, req); goto lookup; } + sock_hold(sk); + nsk = tcp_check_req(sk, skb, req, false); if (!nsk) { reqsk_put(req); - goto discard_it; + goto discard_and_relse; } if (nsk == sk) { - sock_hold(sk); reqsk_put(req); } else if (tcp_child_process(sk, nsk, skb)) { tcp_v4_send_reset(nsk, skb); - goto discard_it; + goto discard_and_relse; } else { + sock_put(sk); return 0; } } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index be0b21852b13..95d2f198017e 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1048,8 +1048,10 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) if (msg->msg_controllen) { err = ip_cmsg_send(sock_net(sk), msg, &ipc, sk->sk_family == AF_INET6); - if (err) + if (unlikely(err)) { + kfree(ipc.opt); return err; + } if (ipc.opt) free = 1; connected = 0; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 9efd9ffdc34c..bdd7eac4307a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -583,7 +583,7 @@ static int inet6_netconf_get_devconf(struct sk_buff *in_skb, if (err < 0) goto errout; - err = EINVAL; + err = -EINVAL; if (!tb[NETCONFA_IFINDEX]) goto errout; diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index f37f18b6b40c..a69aad1e29d1 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -1512,6 +1512,7 @@ static void ip6gre_tap_setup(struct net_device *dev) dev->destructor = ip6gre_dev_free; dev->features |= NETIF_F_NETNS_LOCAL; + dev->priv_flags &= ~IFF_TX_SKB_SHARING; } static int ip6gre_newlink(struct net *src_net, struct net_device *dev, diff --git a/net/ipv6/netfilter/nf_nat_masquerade_ipv6.c b/net/ipv6/netfilter/nf_nat_masquerade_ipv6.c index 31ba7ca19757..051b6a6bfff6 100644 --- a/net/ipv6/netfilter/nf_nat_masquerade_ipv6.c +++ b/net/ipv6/netfilter/nf_nat_masquerade_ipv6.c @@ -21,6 +21,10 @@ #include <net/ipv6.h> #include <net/netfilter/ipv6/nf_nat_masquerade.h> +#define MAX_WORK_COUNT 16 + +static atomic_t v6_worker_count; + unsigned int nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range *range, const struct net_device *out) @@ -78,14 +82,78 @@ static struct notifier_block masq_dev_notifier = { .notifier_call = masq_device_event, }; +struct masq_dev_work { + struct work_struct work; + struct net *net; + int ifindex; +}; + +static void iterate_cleanup_work(struct work_struct *work) +{ + struct masq_dev_work *w; + long index; + + w = container_of(work, struct masq_dev_work, work); + + index = w->ifindex; + nf_ct_iterate_cleanup(w->net, device_cmp, (void *)index, 0, 0); + + put_net(w->net); + kfree(w); + atomic_dec(&v6_worker_count); + module_put(THIS_MODULE); +} + +/* ipv6 inet notifier is an atomic notifier, i.e. we cannot + * schedule. + * + * Unfortunately, nf_ct_iterate_cleanup can run for a long + * time if there are lots of conntracks and the system + * handles high softirq load, so it frequently calls cond_resched + * while iterating the conntrack table. + * + * So we defer nf_ct_iterate_cleanup walk to the system workqueue. + * + * As we can have 'a lot' of inet_events (depending on amount + * of ipv6 addresses being deleted), we also need to add an upper + * limit to the number of queued work items. + */ static int masq_inet_event(struct notifier_block *this, unsigned long event, void *ptr) { struct inet6_ifaddr *ifa = ptr; - struct netdev_notifier_info info; + const struct net_device *dev; + struct masq_dev_work *w; + struct net *net; + + if (event != NETDEV_DOWN || + atomic_read(&v6_worker_count) >= MAX_WORK_COUNT) + return NOTIFY_DONE; + + dev = ifa->idev->dev; + net = maybe_get_net(dev_net(dev)); + if (!net) + return NOTIFY_DONE; - netdev_notifier_info_init(&info, ifa->idev->dev); - return masq_device_event(this, event, &info); + if (!try_module_get(THIS_MODULE)) + goto err_module; + + w = kmalloc(sizeof(*w), GFP_ATOMIC); + if (w) { + atomic_inc(&v6_worker_count); + + INIT_WORK(&w->work, iterate_cleanup_work); + w->ifindex = dev->ifindex; + w->net = net; + schedule_work(&w->work); + + return NOTIFY_DONE; + } + + module_put(THIS_MODULE); + err_module: + put_net(net); + return NOTIFY_DONE; } static struct notifier_block masq_inet_notifier = { diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 1a5a70fb8551..5c8c84273028 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1387,7 +1387,7 @@ process: if (sk->sk_state == TCP_NEW_SYN_RECV) { struct request_sock *req = inet_reqsk(sk); - struct sock *nsk = NULL; + struct sock *nsk; sk = req->rsk_listener; tcp_v6_fill_cb(skb, hdr, th); @@ -1395,24 +1395,24 @@ process: reqsk_put(req); goto discard_it; } - if (likely(sk->sk_state == TCP_LISTEN)) { - nsk = tcp_check_req(sk, skb, req, false); - } else { + if (unlikely(sk->sk_state != TCP_LISTEN)) { inet_csk_reqsk_queue_drop_and_put(sk, req); goto lookup; } + sock_hold(sk); + nsk = tcp_check_req(sk, skb, req, false); if (!nsk) { reqsk_put(req); - goto discard_it; + goto discard_and_relse; } if (nsk == sk) { - sock_hold(sk); reqsk_put(req); tcp_v6_restore_cb(skb); } else if (tcp_child_process(sk, nsk, skb)) { tcp_v6_send_reset(nsk, skb); - goto discard_it; + goto discard_and_relse; } else { + sock_put(sk); return 0; } } diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index f93c5be612a7..2caaa84ce92d 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c @@ -124,8 +124,13 @@ static int l2tp_tunnel_notify(struct genl_family *family, ret = l2tp_nl_tunnel_send(msg, info->snd_portid, info->snd_seq, NLM_F_ACK, tunnel, cmd); - if (ret >= 0) - return genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC); + if (ret >= 0) { + ret = genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC); + /* We don't care if no one is listening */ + if (ret == -ESRCH) + ret = 0; + return ret; + } nlmsg_free(msg); @@ -147,8 +152,13 @@ static int l2tp_session_notify(struct genl_family *family, ret = l2tp_nl_session_send(msg, info->snd_portid, info->snd_seq, NLM_F_ACK, session, cmd); - if (ret >= 0) - return genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC); + if (ret >= 0) { + ret = genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC); + /* We don't care if no one is listening */ + if (ret == -ESRCH) + ret = 0; + return ret; + } nlmsg_free(msg); diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 8c067e6663a1..95e757c377f9 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -891,7 +891,7 @@ config NETFILTER_XT_TARGET_TEE depends on IPV6 || IPV6=n depends on !NF_CONNTRACK || NF_CONNTRACK select NF_DUP_IPV4 - select NF_DUP_IPV6 if IP6_NF_IPTABLES != n + select NF_DUP_IPV6 if IPV6 ---help--- This option adds a "TEE" target with which a packet can be cloned and this clone be rerouted to another nexthop. diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 58882de06bd7..f60b4fdeeb8c 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1412,6 +1412,7 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data), } spin_unlock(lockp); local_bh_enable(); + cond_resched(); } for_each_possible_cpu(cpu) { @@ -1424,6 +1425,7 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data), set_bit(IPS_DYING_BIT, &ct->status); } spin_unlock_bh(&pcpu->lock); + cond_resched(); } return NULL; found: @@ -1440,6 +1442,8 @@ void nf_ct_iterate_cleanup(struct net *net, struct nf_conn *ct; unsigned int bucket = 0; + might_sleep(); + while ((ct = get_next_corpse(net, iter, data, &bucket)) != NULL) { /* Time to push up daises... */ if (del_timer(&ct->timeout)) @@ -1448,6 +1452,7 @@ void nf_ct_iterate_cleanup(struct net *net, /* ... else the timer will get him soon. */ nf_ct_put(ct); + cond_resched(); } } EXPORT_SYMBOL_GPL(nf_ct_iterate_cleanup); diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index a7ba23353dab..857ae89633af 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -311,14 +311,14 @@ replay: #endif { nfnl_unlock(subsys_id); - netlink_ack(skb, nlh, -EOPNOTSUPP); + netlink_ack(oskb, nlh, -EOPNOTSUPP); return kfree_skb(skb); } } if (!ss->commit || !ss->abort) { nfnl_unlock(subsys_id); - netlink_ack(skb, nlh, -EOPNOTSUPP); + netlink_ack(oskb, nlh, -EOPNOTSUPP); return kfree_skb(skb); } @@ -328,10 +328,12 @@ replay: nlh = nlmsg_hdr(skb); err = 0; - if (nlmsg_len(nlh) < sizeof(struct nfgenmsg) || - skb->len < nlh->nlmsg_len) { - err = -EINVAL; - goto ack; + if (nlh->nlmsg_len < NLMSG_HDRLEN || + skb->len < nlh->nlmsg_len || + nlmsg_len(nlh) < sizeof(struct nfgenmsg)) { + nfnl_err_reset(&err_list); + status |= NFNL_BATCH_FAILURE; + goto done; } /* Only requests are handled by the kernel */ @@ -406,7 +408,7 @@ ack: * pointing to the batch header. */ nfnl_err_reset(&err_list); - netlink_ack(skb, nlmsg_hdr(oskb), -ENOMEM); + netlink_ack(oskb, nlmsg_hdr(oskb), -ENOMEM); status |= NFNL_BATCH_FAILURE; goto done; } diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index 94837d236ab0..2671b9deb103 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c @@ -312,7 +312,7 @@ static void ctnl_untimeout(struct net *net, struct ctnl_timeout *timeout) hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode) untimeout(h, timeout); } - nf_conntrack_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); + spin_unlock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); } local_bh_enable(); } diff --git a/net/netfilter/nft_counter.c b/net/netfilter/nft_counter.c index c7808fc19719..c9743f78f219 100644 --- a/net/netfilter/nft_counter.c +++ b/net/netfilter/nft_counter.c @@ -100,7 +100,7 @@ static int nft_counter_init(const struct nft_ctx *ctx, cpu_stats = netdev_alloc_pcpu_stats(struct nft_counter_percpu); if (cpu_stats == NULL) - return ENOMEM; + return -ENOMEM; preempt_disable(); this_cpu = this_cpu_ptr(cpu_stats); @@ -138,7 +138,7 @@ static int nft_counter_clone(struct nft_expr *dst, const struct nft_expr *src) cpu_stats = __netdev_alloc_pcpu_stats(struct nft_counter_percpu, GFP_ATOMIC); if (cpu_stats == NULL) - return ENOMEM; + return -ENOMEM; preempt_disable(); this_cpu = this_cpu_ptr(cpu_stats); diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c index 3eff7b67cdf2..6e57a3966dc5 100644 --- a/net/netfilter/xt_TEE.c +++ b/net/netfilter/xt_TEE.c @@ -38,7 +38,7 @@ tee_tg4(struct sk_buff *skb, const struct xt_action_param *par) return XT_CONTINUE; } -#if IS_ENABLED(CONFIG_NF_DUP_IPV6) +#if IS_ENABLED(CONFIG_IPV6) static unsigned int tee_tg6(struct sk_buff *skb, const struct xt_action_param *par) { @@ -131,7 +131,7 @@ static struct xt_target tee_tg_reg[] __read_mostly = { .destroy = tee_tg_destroy, .me = THIS_MODULE, }, -#if IS_ENABLED(CONFIG_NF_DUP_IPV6) +#if IS_ENABLED(CONFIG_IPV6) { .name = "TEE", .revision = 1, diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c index de9cb19efb6a..5eb7694348b5 100644 --- a/net/openvswitch/vport-vxlan.c +++ b/net/openvswitch/vport-vxlan.c @@ -90,7 +90,7 @@ static struct vport *vxlan_tnl_create(const struct vport_parms *parms) int err; struct vxlan_config conf = { .no_share = true, - .flags = VXLAN_F_COLLECT_METADATA, + .flags = VXLAN_F_COLLECT_METADATA | VXLAN_F_UDP_ZERO_CSUM6_RX, /* Don't restrict the packets that can be sent by MTU */ .mtu = IP_MAX_MTU, }; diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index b5c2cf2aa6d4..af1acf009866 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1852,6 +1852,7 @@ reset: } tp = old_tp; + protocol = tc_skb_protocol(skb); goto reclassify; #endif } diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index ab0d538a74ed..1099e99a53c4 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -60,6 +60,8 @@ #include <net/inet_common.h> #include <net/inet_ecn.h> +#define MAX_SCTP_PORT_HASH_ENTRIES (64 * 1024) + /* Global data structures. */ struct sctp_globals sctp_globals __read_mostly; @@ -1355,6 +1357,8 @@ static __init int sctp_init(void) unsigned long limit; int max_share; int order; + int num_entries; + int max_entry_order; sock_skb_cb_check_size(sizeof(struct sctp_ulpevent)); @@ -1407,14 +1411,24 @@ static __init int sctp_init(void) /* Size and allocate the association hash table. * The methodology is similar to that of the tcp hash tables. + * Though not identical. Start by getting a goal size */ if (totalram_pages >= (128 * 1024)) goal = totalram_pages >> (22 - PAGE_SHIFT); else goal = totalram_pages >> (24 - PAGE_SHIFT); - for (order = 0; (1UL << order) < goal; order++) - ; + /* Then compute the page order for said goal */ + order = get_order(goal); + + /* Now compute the required page order for the maximum sized table we + * want to create + */ + max_entry_order = get_order(MAX_SCTP_PORT_HASH_ENTRIES * + sizeof(struct sctp_bind_hashbucket)); + + /* Limit the page order by that maximum hash table size */ + order = min(order, max_entry_order); /* Allocate and initialize the endpoint hash table. */ sctp_ep_hashsize = 64; @@ -1430,20 +1444,35 @@ static __init int sctp_init(void) INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain); } - /* Allocate and initialize the SCTP port hash table. */ + /* Allocate and initialize the SCTP port hash table. + * Note that order is initalized to start at the max sized + * table we want to support. If we can't get that many pages + * reduce the order and try again + */ do { - sctp_port_hashsize = (1UL << order) * PAGE_SIZE / - sizeof(struct sctp_bind_hashbucket); - if ((sctp_port_hashsize > (64 * 1024)) && order > 0) - continue; sctp_port_hashtable = (struct sctp_bind_hashbucket *) __get_free_pages(GFP_KERNEL | __GFP_NOWARN, order); } while (!sctp_port_hashtable && --order > 0); + if (!sctp_port_hashtable) { pr_err("Failed bind hash alloc\n"); status = -ENOMEM; goto err_bhash_alloc; } + + /* Now compute the number of entries that will fit in the + * port hash space we allocated + */ + num_entries = (1UL << order) * PAGE_SIZE / + sizeof(struct sctp_bind_hashbucket); + + /* And finish by rounding it down to the nearest power of two + * this wastes some memory of course, but its needed because + * the hash function operates based on the assumption that + * that the number of entries is a power of two + */ + sctp_port_hashsize = rounddown_pow_of_two(num_entries); + for (i = 0; i < sctp_port_hashsize; i++) { spin_lock_init(&sctp_port_hashtable[i].lock); INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain); @@ -1452,7 +1481,8 @@ static __init int sctp_init(void) if (sctp_transport_hashtable_init()) goto err_thash_alloc; - pr_info("Hash tables configured (bind %d)\n", sctp_port_hashsize); + pr_info("Hash tables configured (bind %d/%d)\n", sctp_port_hashsize, + num_entries); sctp_sysctl_register(); diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 799e65b944b9..cabf586f47d7 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -740,7 +740,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) default: printk(KERN_CRIT "%s: bad return from " "gss_fill_context: %zd\n", __func__, err); - BUG(); + gss_msg->msg.errno = -EIO; } goto err_release_msg; } diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 2b32fd602669..273bc3a35425 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1225,7 +1225,7 @@ int qword_get(char **bpp, char *dest, int bufsize) if (bp[0] == '\\' && bp[1] == 'x') { /* HEX STRING */ bp += 2; - while (len < bufsize) { + while (len < bufsize - 1) { int h, l; h = hex_to_bin(bp[0]); diff --git a/net/sunrpc/xprtrdma/backchannel.c b/net/sunrpc/xprtrdma/backchannel.c index cc1251d07297..2dcd7640eeb5 100644 --- a/net/sunrpc/xprtrdma/backchannel.c +++ b/net/sunrpc/xprtrdma/backchannel.c @@ -341,6 +341,8 @@ void rpcrdma_bc_receive_call(struct rpcrdma_xprt *r_xprt, rqst->rq_reply_bytes_recvd = 0; rqst->rq_bytes_sent = 0; rqst->rq_xid = headerp->rm_xid; + + rqst->rq_private_buf.len = size; set_bit(RPC_BC_PA_IN_USE, &rqst->rq_bc_pa_state); buf = &rqst->rq_rcv_buf; diff --git a/net/tipc/link.c b/net/tipc/link.c index 0c2944fb9ae0..347cdc99ed09 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1973,8 +1973,10 @@ int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg) hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, NLM_F_MULTI, TIPC_NL_LINK_GET); - if (!hdr) + if (!hdr) { + tipc_bcast_unlock(net); return -EMSGSIZE; + } attrs = nla_nest_start(msg->skb, TIPC_NLA_LINK); if (!attrs) diff --git a/net/tipc/node.c b/net/tipc/node.c index fa97d9649a28..9d7a16fc5ca4 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -346,12 +346,6 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities) skb_queue_head_init(&n->bc_entry.inputq2); for (i = 0; i < MAX_BEARERS; i++) spin_lock_init(&n->links[i].lock); - hlist_add_head_rcu(&n->hash, &tn->node_htable[tipc_hashfn(addr)]); - list_for_each_entry_rcu(temp_node, &tn->node_list, list) { - if (n->addr < temp_node->addr) - break; - } - list_add_tail_rcu(&n->list, &temp_node->list); n->state = SELF_DOWN_PEER_LEAVING; n->signature = INVALID_NODE_SIG; n->active_links[0] = INVALID_BEARER_ID; @@ -372,6 +366,12 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities) tipc_node_get(n); setup_timer(&n->timer, tipc_node_timeout, (unsigned long)n); n->keepalive_intv = U32_MAX; + hlist_add_head_rcu(&n->hash, &tn->node_htable[tipc_hashfn(addr)]); + list_for_each_entry_rcu(temp_node, &tn->node_list, list) { + if (n->addr < temp_node->addr) + break; + } + list_add_tail_rcu(&n->list, &temp_node->list); exit: spin_unlock_bh(&tn->node_list_lock); return n; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 29be035f9c65..f75f847e688d 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1781,7 +1781,12 @@ restart_locked: goto out_unlock; } - if (unlikely(unix_peer(other) != sk && unix_recvq_full(other))) { + /* other == sk && unix_peer(other) != sk if + * - unix_peer(sk) == NULL, destination address bound to sk + * - unix_peer(sk) == sk by time of get but disconnected before lock + */ + if (other != sk && + unlikely(unix_peer(other) != sk && unix_recvq_full(other))) { if (timeo) { timeo = unix_wait_for_peer(other, timeo); @@ -2277,13 +2282,15 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state) size_t size = state->size; unsigned int last_len; - err = -EINVAL; - if (sk->sk_state != TCP_ESTABLISHED) + if (unlikely(sk->sk_state != TCP_ESTABLISHED)) { + err = -EINVAL; goto out; + } - err = -EOPNOTSUPP; - if (flags & MSG_OOB) + if (unlikely(flags & MSG_OOB)) { + err = -EOPNOTSUPP; goto out; + } target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); timeo = sock_rcvtimeo(sk, noblock); @@ -2305,6 +2312,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state) bool drop_skb; struct sk_buff *skb, *last; +redo: unix_state_lock(sk); if (sock_flag(sk, SOCK_DEAD)) { err = -ECONNRESET; @@ -2329,9 +2337,11 @@ again: goto unlock; unix_state_unlock(sk); - err = -EAGAIN; - if (!timeo) + if (!timeo) { + err = -EAGAIN; break; + } + mutex_unlock(&u->readlock); timeo = unix_stream_data_wait(sk, timeo, last, @@ -2344,7 +2354,7 @@ again: } mutex_lock(&u->readlock); - continue; + goto redo; unlock: unix_state_unlock(sk); break; diff --git a/net/unix/diag.c b/net/unix/diag.c index c512f64d5287..4d9679701a6d 100644 --- a/net/unix/diag.c +++ b/net/unix/diag.c @@ -220,7 +220,7 @@ done: return skb->len; } -static struct sock *unix_lookup_by_ino(int ino) +static struct sock *unix_lookup_by_ino(unsigned int ino) { int i; struct sock *sk; diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 7fd1220fbfa0..bbe65dcb9738 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -1557,8 +1557,6 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, if (err < 0) goto out; - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); - while (total_written < len) { ssize_t written; @@ -1578,7 +1576,9 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, goto out_wait; release_sock(sk); + prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); timeout = schedule_timeout(timeout); + finish_wait(sk_sleep(sk), &wait); lock_sock(sk); if (signal_pending(current)) { err = sock_intr_errno(timeout); @@ -1588,8 +1588,6 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, goto out_wait; } - prepare_to_wait(sk_sleep(sk), &wait, - TASK_INTERRUPTIBLE); } /* These checks occur both as part of and after the loop @@ -1635,7 +1633,6 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, out_wait: if (total_written > 0) err = total_written; - finish_wait(sk_sleep(sk), &wait); out: release_sock(sk); return err; @@ -1716,7 +1713,6 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, if (err < 0) goto out; - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); while (1) { s64 ready = vsock_stream_has_data(vsk); @@ -1727,7 +1723,7 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, */ err = -ENOMEM; - goto out_wait; + goto out; } else if (ready > 0) { ssize_t read; @@ -1750,7 +1746,7 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, vsk, target, read, !(flags & MSG_PEEK), &recv_data); if (err < 0) - goto out_wait; + goto out; if (read >= target || flags & MSG_PEEK) break; @@ -1773,7 +1769,9 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, break; release_sock(sk); + prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); timeout = schedule_timeout(timeout); + finish_wait(sk_sleep(sk), &wait); lock_sock(sk); if (signal_pending(current)) { @@ -1783,9 +1781,6 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, err = -EAGAIN; break; } - - prepare_to_wait(sk_sleep(sk), &wait, - TASK_INTERRUPTIBLE); } } @@ -1816,8 +1811,6 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, err = copied; } -out_wait: - finish_wait(sk_sleep(sk), &wait); out: release_sock(sk); return err; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f8110cfd80ff..f1ab71504e1d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3249,7 +3249,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t static void selinux_inode_getsecid(struct inode *inode, u32 *secid) { - struct inode_security_struct *isec = inode_security(inode); + struct inode_security_struct *isec = inode_security_novalidate(inode); *secid = isec->sid; } diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index b9c0910fb8c4..0608f216f359 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -170,6 +170,19 @@ struct snd_ctl_elem_value32 { unsigned char reserved[128]; }; +#ifdef CONFIG_X86_X32 +/* x32 has a different alignment for 64bit values from ia32 */ +struct snd_ctl_elem_value_x32 { + struct snd_ctl_elem_id id; + unsigned int indirect; /* bit-field causes misalignment */ + union { + s32 integer[128]; + unsigned char data[512]; + s64 integer64[64]; + } value; + unsigned char reserved[128]; +}; +#endif /* CONFIG_X86_X32 */ /* get the value type and count of the control */ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, @@ -219,9 +232,11 @@ static int get_elem_size(int type, int count) static int copy_ctl_value_from_user(struct snd_card *card, struct snd_ctl_elem_value *data, - struct snd_ctl_elem_value32 __user *data32, + void __user *userdata, + void __user *valuep, int *typep, int *countp) { + struct snd_ctl_elem_value32 __user *data32 = userdata; int i, type, size; int uninitialized_var(count); unsigned int indirect; @@ -239,8 +254,9 @@ static int copy_ctl_value_from_user(struct snd_card *card, if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || type == SNDRV_CTL_ELEM_TYPE_INTEGER) { for (i = 0; i < count; i++) { + s32 __user *intp = valuep; int val; - if (get_user(val, &data32->value.integer[i])) + if (get_user(val, &intp[i])) return -EFAULT; data->value.integer.value[i] = val; } @@ -250,8 +266,7 @@ static int copy_ctl_value_from_user(struct snd_card *card, dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); return -EINVAL; } - if (copy_from_user(data->value.bytes.data, - data32->value.data, size)) + if (copy_from_user(data->value.bytes.data, valuep, size)) return -EFAULT; } @@ -261,7 +276,8 @@ static int copy_ctl_value_from_user(struct snd_card *card, } /* restore the value to 32bit */ -static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32, +static int copy_ctl_value_to_user(void __user *userdata, + void __user *valuep, struct snd_ctl_elem_value *data, int type, int count) { @@ -270,22 +286,22 @@ static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32, if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || type == SNDRV_CTL_ELEM_TYPE_INTEGER) { for (i = 0; i < count; i++) { + s32 __user *intp = valuep; int val; val = data->value.integer.value[i]; - if (put_user(val, &data32->value.integer[i])) + if (put_user(val, &intp[i])) return -EFAULT; } } else { size = get_elem_size(type, count); - if (copy_to_user(data32->value.data, - data->value.bytes.data, size)) + if (copy_to_user(valuep, data->value.bytes.data, size)) return -EFAULT; } return 0; } -static int snd_ctl_elem_read_user_compat(struct snd_card *card, - struct snd_ctl_elem_value32 __user *data32) +static int ctl_elem_read_user(struct snd_card *card, + void __user *userdata, void __user *valuep) { struct snd_ctl_elem_value *data; int err, type, count; @@ -294,7 +310,9 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card, if (data == NULL) return -ENOMEM; - if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0) + err = copy_ctl_value_from_user(card, data, userdata, valuep, + &type, &count); + if (err < 0) goto error; snd_power_lock(card); @@ -303,14 +321,15 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card, err = snd_ctl_elem_read(card, data); snd_power_unlock(card); if (err >= 0) - err = copy_ctl_value_to_user(data32, data, type, count); + err = copy_ctl_value_to_user(userdata, valuep, data, + type, count); error: kfree(data); return err; } -static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, - struct snd_ctl_elem_value32 __user *data32) +static int ctl_elem_write_user(struct snd_ctl_file *file, + void __user *userdata, void __user *valuep) { struct snd_ctl_elem_value *data; struct snd_card *card = file->card; @@ -320,7 +339,9 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, if (data == NULL) return -ENOMEM; - if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0) + err = copy_ctl_value_from_user(card, data, userdata, valuep, + &type, &count); + if (err < 0) goto error; snd_power_lock(card); @@ -329,12 +350,39 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, err = snd_ctl_elem_write(card, file, data); snd_power_unlock(card); if (err >= 0) - err = copy_ctl_value_to_user(data32, data, type, count); + err = copy_ctl_value_to_user(userdata, valuep, data, + type, count); error: kfree(data); return err; } +static int snd_ctl_elem_read_user_compat(struct snd_card *card, + struct snd_ctl_elem_value32 __user *data32) +{ + return ctl_elem_read_user(card, data32, &data32->value); +} + +static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, + struct snd_ctl_elem_value32 __user *data32) +{ + return ctl_elem_write_user(file, data32, &data32->value); +} + +#ifdef CONFIG_X86_X32 +static int snd_ctl_elem_read_user_x32(struct snd_card *card, + struct snd_ctl_elem_value_x32 __user *data32) +{ + return ctl_elem_read_user(card, data32, &data32->value); +} + +static int snd_ctl_elem_write_user_x32(struct snd_ctl_file *file, + struct snd_ctl_elem_value_x32 __user *data32) +{ + return ctl_elem_write_user(file, data32, &data32->value); +} +#endif /* CONFIG_X86_X32 */ + /* add or replace a user control */ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, struct snd_ctl_elem_info32 __user *data32, @@ -393,6 +441,10 @@ enum { SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32), SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32), SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32), +#ifdef CONFIG_X86_X32 + SNDRV_CTL_IOCTL_ELEM_READ_X32 = _IOWR('U', 0x12, struct snd_ctl_elem_value_x32), + SNDRV_CTL_IOCTL_ELEM_WRITE_X32 = _IOWR('U', 0x13, struct snd_ctl_elem_value_x32), +#endif /* CONFIG_X86_X32 */ }; static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) @@ -431,6 +483,12 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns return snd_ctl_elem_add_compat(ctl, argp, 0); case SNDRV_CTL_IOCTL_ELEM_REPLACE32: return snd_ctl_elem_add_compat(ctl, argp, 1); +#ifdef CONFIG_X86_X32 + case SNDRV_CTL_IOCTL_ELEM_READ_X32: + return snd_ctl_elem_read_user_x32(ctl->card, argp); + case SNDRV_CTL_IOCTL_ELEM_WRITE_X32: + return snd_ctl_elem_write_user_x32(ctl, argp); +#endif /* CONFIG_X86_X32 */ } down_read(&snd_ioctl_rwsem); diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 9630e9f72b7b..1f64ab0c2a95 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -183,6 +183,14 @@ static int snd_pcm_ioctl_channel_info_compat(struct snd_pcm_substream *substream return err; } +#ifdef CONFIG_X86_X32 +/* X32 ABI has the same struct as x86-64 for snd_pcm_channel_info */ +static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream, + struct snd_pcm_channel_info __user *src); +#define snd_pcm_ioctl_channel_info_x32(s, p) \ + snd_pcm_channel_info_user(s, p) +#endif /* CONFIG_X86_X32 */ + struct snd_pcm_status32 { s32 state; struct compat_timespec trigger_tstamp; @@ -243,6 +251,71 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, return err; } +#ifdef CONFIG_X86_X32 +/* X32 ABI has 64bit timespec and 64bit alignment */ +struct snd_pcm_status_x32 { + s32 state; + u32 rsvd; /* alignment */ + struct timespec trigger_tstamp; + struct timespec tstamp; + u32 appl_ptr; + u32 hw_ptr; + s32 delay; + u32 avail; + u32 avail_max; + u32 overrange; + s32 suspended_state; + u32 audio_tstamp_data; + struct timespec audio_tstamp; + struct timespec driver_tstamp; + u32 audio_tstamp_accuracy; + unsigned char reserved[52-2*sizeof(struct timespec)]; +} __packed; + +#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst)) + +static int snd_pcm_status_user_x32(struct snd_pcm_substream *substream, + struct snd_pcm_status_x32 __user *src, + bool ext) +{ + struct snd_pcm_status status; + int err; + + memset(&status, 0, sizeof(status)); + /* + * with extension, parameters are read/write, + * get audio_tstamp_data from user, + * ignore rest of status structure + */ + if (ext && get_user(status.audio_tstamp_data, + (u32 __user *)(&src->audio_tstamp_data))) + return -EFAULT; + err = snd_pcm_status(substream, &status); + if (err < 0) + return err; + + if (clear_user(src, sizeof(*src))) + return -EFAULT; + if (put_user(status.state, &src->state) || + put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) || + put_timespec(&status.tstamp, &src->tstamp) || + put_user(status.appl_ptr, &src->appl_ptr) || + put_user(status.hw_ptr, &src->hw_ptr) || + put_user(status.delay, &src->delay) || + put_user(status.avail, &src->avail) || + put_user(status.avail_max, &src->avail_max) || + put_user(status.overrange, &src->overrange) || + put_user(status.suspended_state, &src->suspended_state) || + put_user(status.audio_tstamp_data, &src->audio_tstamp_data) || + put_timespec(&status.audio_tstamp, &src->audio_tstamp) || + put_timespec(&status.driver_tstamp, &src->driver_tstamp) || + put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy)) + return -EFAULT; + + return err; +} +#endif /* CONFIG_X86_X32 */ + /* both for HW_PARAMS and HW_REFINE */ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, int refine, @@ -469,6 +542,93 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream, return 0; } +#ifdef CONFIG_X86_X32 +/* X32 ABI has 64bit timespec and 64bit alignment */ +struct snd_pcm_mmap_status_x32 { + s32 state; + s32 pad1; + u32 hw_ptr; + u32 pad2; /* alignment */ + struct timespec tstamp; + s32 suspended_state; + struct timespec audio_tstamp; +} __packed; + +struct snd_pcm_mmap_control_x32 { + u32 appl_ptr; + u32 avail_min; +}; + +struct snd_pcm_sync_ptr_x32 { + u32 flags; + u32 rsvd; /* alignment */ + union { + struct snd_pcm_mmap_status_x32 status; + unsigned char reserved[64]; + } s; + union { + struct snd_pcm_mmap_control_x32 control; + unsigned char reserved[64]; + } c; +} __packed; + +static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream, + struct snd_pcm_sync_ptr_x32 __user *src) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + volatile struct snd_pcm_mmap_status *status; + volatile struct snd_pcm_mmap_control *control; + u32 sflags; + struct snd_pcm_mmap_control scontrol; + struct snd_pcm_mmap_status sstatus; + snd_pcm_uframes_t boundary; + int err; + + if (snd_BUG_ON(!runtime)) + return -EINVAL; + + if (get_user(sflags, &src->flags) || + get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || + get_user(scontrol.avail_min, &src->c.control.avail_min)) + return -EFAULT; + if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) { + err = snd_pcm_hwsync(substream); + if (err < 0) + return err; + } + status = runtime->status; + control = runtime->control; + boundary = recalculate_boundary(runtime); + if (!boundary) + boundary = 0x7fffffff; + snd_pcm_stream_lock_irq(substream); + /* FIXME: we should consider the boundary for the sync from app */ + if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) + control->appl_ptr = scontrol.appl_ptr; + else + scontrol.appl_ptr = control->appl_ptr % boundary; + if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) + control->avail_min = scontrol.avail_min; + else + scontrol.avail_min = control->avail_min; + sstatus.state = status->state; + sstatus.hw_ptr = status->hw_ptr % boundary; + sstatus.tstamp = status->tstamp; + sstatus.suspended_state = status->suspended_state; + sstatus.audio_tstamp = status->audio_tstamp; + snd_pcm_stream_unlock_irq(substream); + if (put_user(sstatus.state, &src->s.status.state) || + put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) || + put_timespec(&sstatus.tstamp, &src->s.status.tstamp) || + put_user(sstatus.suspended_state, &src->s.status.suspended_state) || + put_timespec(&sstatus.audio_tstamp, &src->s.status.audio_tstamp) || + put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || + put_user(scontrol.avail_min, &src->c.control.avail_min)) + return -EFAULT; + + return 0; +} +#endif /* CONFIG_X86_X32 */ /* */ @@ -487,7 +647,12 @@ enum { SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32), SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32), SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32), - +#ifdef CONFIG_X86_X32 + SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info), + SNDRV_PCM_IOCTL_STATUS_X32 = _IOR('A', 0x20, struct snd_pcm_status_x32), + SNDRV_PCM_IOCTL_STATUS_EXT_X32 = _IOWR('A', 0x24, struct snd_pcm_status_x32), + SNDRV_PCM_IOCTL_SYNC_PTR_X32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr_x32), +#endif /* CONFIG_X86_X32 */ }; static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) @@ -559,6 +724,16 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l return snd_pcm_ioctl_rewind_compat(substream, argp); case SNDRV_PCM_IOCTL_FORWARD32: return snd_pcm_ioctl_forward_compat(substream, argp); +#ifdef CONFIG_X86_X32 + case SNDRV_PCM_IOCTL_STATUS_X32: + return snd_pcm_status_user_x32(substream, argp, false); + case SNDRV_PCM_IOCTL_STATUS_EXT_X32: + return snd_pcm_status_user_x32(substream, argp, true); + case SNDRV_PCM_IOCTL_SYNC_PTR_X32: + return snd_pcm_ioctl_sync_ptr_x32(substream, argp); + case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32: + return snd_pcm_ioctl_channel_info_x32(substream, argp); +#endif /* CONFIG_X86_X32 */ } return -ENOIOCTLCMD; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index fadd3eb8e8bb..9106d8e2300e 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -74,6 +74,18 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream); static DEFINE_RWLOCK(snd_pcm_link_rwlock); static DECLARE_RWSEM(snd_pcm_link_rwsem); +/* Writer in rwsem may block readers even during its waiting in queue, + * and this may lead to a deadlock when the code path takes read sem + * twice (e.g. one in snd_pcm_action_nonatomic() and another in + * snd_pcm_stream_lock()). As a (suboptimal) workaround, let writer to + * spin until it gets the lock. + */ +static inline void down_write_nonblock(struct rw_semaphore *lock) +{ + while (!down_write_trylock(lock)) + cond_resched(); +} + /** * snd_pcm_stream_lock - Lock the PCM stream * @substream: PCM substream @@ -1813,7 +1825,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) res = -ENOMEM; goto _nolock; } - down_write(&snd_pcm_link_rwsem); + down_write_nonblock(&snd_pcm_link_rwsem); write_lock_irq(&snd_pcm_link_rwlock); if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN || substream->runtime->status->state != substream1->runtime->status->state || @@ -1860,7 +1872,7 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream) struct snd_pcm_substream *s; int res = 0; - down_write(&snd_pcm_link_rwsem); + down_write_nonblock(&snd_pcm_link_rwsem); write_lock_irq(&snd_pcm_link_rwlock); if (!snd_pcm_stream_linked(substream)) { res = -EALREADY; diff --git a/sound/core/rawmidi_compat.c b/sound/core/rawmidi_compat.c index 5268c1f58c25..f69764d7cdd7 100644 --- a/sound/core/rawmidi_compat.c +++ b/sound/core/rawmidi_compat.c @@ -85,8 +85,7 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, if (err < 0) return err; - if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || - put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || + if (compat_put_timespec(&status.tstamp, &src->tstamp) || put_user(status.avail, &src->avail) || put_user(status.xruns, &src->xruns)) return -EFAULT; @@ -94,9 +93,58 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, return 0; } +#ifdef CONFIG_X86_X32 +/* X32 ABI has 64bit timespec and 64bit alignment */ +struct snd_rawmidi_status_x32 { + s32 stream; + u32 rsvd; /* alignment */ + struct timespec tstamp; + u32 avail; + u32 xruns; + unsigned char reserved[16]; +} __attribute__((packed)); + +#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst)) + +static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile, + struct snd_rawmidi_status_x32 __user *src) +{ + int err; + struct snd_rawmidi_status status; + + if (rfile->output == NULL) + return -EINVAL; + if (get_user(status.stream, &src->stream)) + return -EFAULT; + + switch (status.stream) { + case SNDRV_RAWMIDI_STREAM_OUTPUT: + err = snd_rawmidi_output_status(rfile->output, &status); + break; + case SNDRV_RAWMIDI_STREAM_INPUT: + err = snd_rawmidi_input_status(rfile->input, &status); + break; + default: + return -EINVAL; + } + if (err < 0) + return err; + + if (put_timespec(&status.tstamp, &src->tstamp) || + put_user(status.avail, &src->avail) || + put_user(status.xruns, &src->xruns)) + return -EFAULT; + + return 0; +} +#endif /* CONFIG_X86_X32 */ + enum { SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32), SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32), +#ifdef CONFIG_X86_X32 + SNDRV_RAWMIDI_IOCTL_STATUS_X32 = _IOWR('W', 0x20, struct snd_rawmidi_status_x32), +#endif /* CONFIG_X86_X32 */ }; static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) @@ -115,6 +163,10 @@ static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsign return snd_rawmidi_ioctl_params_compat(rfile, argp); case SNDRV_RAWMIDI_IOCTL_STATUS32: return snd_rawmidi_ioctl_status_compat(rfile, argp); +#ifdef CONFIG_X86_X32 + case SNDRV_RAWMIDI_IOCTL_STATUS_X32: + return snd_rawmidi_ioctl_status_x32(rfile, argp); +#endif /* CONFIG_X86_X32 */ } return -ENOIOCTLCMD; } diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c index 8db156b207f1..8cdf489df80e 100644 --- a/sound/core/seq/oss/seq_oss.c +++ b/sound/core/seq/oss/seq_oss.c @@ -149,8 +149,6 @@ odev_release(struct inode *inode, struct file *file) if ((dp = file->private_data) == NULL) return 0; - snd_seq_oss_drain_write(dp); - mutex_lock(®ister_mutex); snd_seq_oss_release(dp); mutex_unlock(®ister_mutex); diff --git a/sound/core/seq/oss/seq_oss_device.h b/sound/core/seq/oss/seq_oss_device.h index b43924325249..d7b4d016b547 100644 --- a/sound/core/seq/oss/seq_oss_device.h +++ b/sound/core/seq/oss/seq_oss_device.h @@ -127,7 +127,6 @@ int snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int co unsigned int snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_table * wait); void snd_seq_oss_reset(struct seq_oss_devinfo *dp); -void snd_seq_oss_drain_write(struct seq_oss_devinfo *dp); /* */ void snd_seq_oss_process_queue(struct seq_oss_devinfo *dp, abstime_t time); diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c index 6779e82b46dd..92c96a95a903 100644 --- a/sound/core/seq/oss/seq_oss_init.c +++ b/sound/core/seq/oss/seq_oss_init.c @@ -436,22 +436,6 @@ snd_seq_oss_release(struct seq_oss_devinfo *dp) /* - * Wait until the queue is empty (if we don't have nonblock) - */ -void -snd_seq_oss_drain_write(struct seq_oss_devinfo *dp) -{ - if (! dp->timer->running) - return; - if (is_write_mode(dp->file_mode) && !is_nonblock_mode(dp->file_mode) && - dp->writeq) { - while (snd_seq_oss_writeq_sync(dp->writeq)) - ; - } -} - - -/* * reset sequencer devices */ void diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index 801076687bb1..c850345c43b5 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c @@ -383,15 +383,20 @@ int snd_seq_pool_init(struct snd_seq_pool *pool) if (snd_BUG_ON(!pool)) return -EINVAL; - if (pool->ptr) /* should be atomic? */ - return 0; - pool->ptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size); - if (!pool->ptr) + cellptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size); + if (!cellptr) return -ENOMEM; /* add new cells to the free cell list */ spin_lock_irqsave(&pool->lock, flags); + if (pool->ptr) { + spin_unlock_irqrestore(&pool->lock, flags); + vfree(cellptr); + return 0; + } + + pool->ptr = cellptr; pool->free = NULL; for (cell = 0; cell < pool->size; cell++) { diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 921fb2bd8fad..fe686ee41c6d 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -535,19 +535,22 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client, bool is_src, bool ack) { struct snd_seq_port_subs_info *grp; + struct list_head *list; + bool empty; grp = is_src ? &port->c_src : &port->c_dest; + list = is_src ? &subs->src_list : &subs->dest_list; down_write(&grp->list_mutex); write_lock_irq(&grp->list_lock); - if (is_src) - list_del(&subs->src_list); - else - list_del(&subs->dest_list); + empty = list_empty(list); + if (!empty) + list_del_init(list); grp->exclusive = 0; write_unlock_irq(&grp->list_lock); up_write(&grp->list_mutex); - unsubscribe_port(client, port, grp, &subs->info, ack); + if (!empty) + unsubscribe_port(client, port, grp, &subs->info, ack); } /* connect two ports */ diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c index e05802ae6e1b..2e908225d754 100644 --- a/sound/core/timer_compat.c +++ b/sound/core/timer_compat.c @@ -70,13 +70,14 @@ static int snd_timer_user_status_compat(struct file *file, struct snd_timer_status32 __user *_status) { struct snd_timer_user *tu; - struct snd_timer_status status; + struct snd_timer_status32 status; tu = file->private_data; if (snd_BUG_ON(!tu->timeri)) return -ENXIO; memset(&status, 0, sizeof(status)); - status.tstamp = tu->tstamp; + status.tstamp.tv_sec = tu->tstamp.tv_sec; + status.tstamp.tv_nsec = tu->tstamp.tv_nsec; status.resolution = snd_timer_resolution(tu->timeri); status.lost = tu->timeri->lost; status.overrun = tu->overrun; @@ -88,12 +89,21 @@ static int snd_timer_user_status_compat(struct file *file, return 0; } +#ifdef CONFIG_X86_X32 +/* X32 ABI has the same struct as x86-64 */ +#define snd_timer_user_status_x32(file, s) \ + snd_timer_user_status(file, s) +#endif /* CONFIG_X86_X32 */ + /* */ enum { SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32), SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32), +#ifdef CONFIG_X86_X32 + SNDRV_TIMER_IOCTL_STATUS_X32 = _IOW('T', 0x14, struct snd_timer_status), +#endif /* CONFIG_X86_X32 */ }; static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) @@ -122,6 +132,10 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns return snd_timer_user_info_compat(file, argp); case SNDRV_TIMER_IOCTL_STATUS32: return snd_timer_user_status_compat(file, argp); +#ifdef CONFIG_X86_X32 + case SNDRV_TIMER_IOCTL_STATUS_X32: + return snd_timer_user_status_x32(file, argp); +#endif /* CONFIG_X86_X32 */ } return -ENOIOCTLCMD; } diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index b5a17cb510a0..8c486235c905 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -426,18 +426,22 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_chip); * @bus: HD-audio core bus * @status: INTSTS register value * @ask: callback to be called for woken streams + * + * Returns the bits of handled streams, or zero if no stream is handled. */ -void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, +int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, void (*ack)(struct hdac_bus *, struct hdac_stream *)) { struct hdac_stream *azx_dev; u8 sd_status; + int handled = 0; list_for_each_entry(azx_dev, &bus->stream_list, list) { if (status & azx_dev->sd_int_sta_mask) { sd_status = snd_hdac_stream_readb(azx_dev, SD_STS); snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); + handled |= 1 << azx_dev->index; if (!azx_dev->substream || !azx_dev->running || !(sd_status & SD_INT_COMPLETE)) continue; @@ -445,6 +449,7 @@ void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, ack(bus, azx_dev); } } + return handled; } EXPORT_SYMBOL_GPL(snd_hdac_bus_handle_stream_irq); diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 37cf9cee9835..27de8015717d 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -930,6 +930,8 @@ irqreturn_t azx_interrupt(int irq, void *dev_id) struct azx *chip = dev_id; struct hdac_bus *bus = azx_bus(chip); u32 status; + bool active, handled = false; + int repeat = 0; /* count for avoiding endless loop */ #ifdef CONFIG_PM if (azx_has_pm_runtime(chip)) @@ -939,33 +941,36 @@ irqreturn_t azx_interrupt(int irq, void *dev_id) spin_lock(&bus->reg_lock); - if (chip->disabled) { - spin_unlock(&bus->reg_lock); - return IRQ_NONE; - } - - status = azx_readl(chip, INTSTS); - if (status == 0 || status == 0xffffffff) { - spin_unlock(&bus->reg_lock); - return IRQ_NONE; - } + if (chip->disabled) + goto unlock; - snd_hdac_bus_handle_stream_irq(bus, status, stream_update); + do { + status = azx_readl(chip, INTSTS); + if (status == 0 || status == 0xffffffff) + break; - /* clear rirb int */ - status = azx_readb(chip, RIRBSTS); - if (status & RIRB_INT_MASK) { - if (status & RIRB_INT_RESPONSE) { - if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) - udelay(80); - snd_hdac_bus_update_rirb(bus); + handled = true; + active = false; + if (snd_hdac_bus_handle_stream_irq(bus, status, stream_update)) + active = true; + + /* clear rirb int */ + status = azx_readb(chip, RIRBSTS); + if (status & RIRB_INT_MASK) { + active = true; + if (status & RIRB_INT_RESPONSE) { + if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) + udelay(80); + snd_hdac_bus_update_rirb(bus); + } + azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); } - azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); - } + } while (active && ++repeat < 10); + unlock: spin_unlock(&bus->reg_lock); - return IRQ_HANDLED; + return IRQ_RETVAL(handled); } EXPORT_SYMBOL_GPL(azx_interrupt); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 4045dca3d699..e5240cb3749f 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -363,7 +363,10 @@ enum { ((pci)->device == 0x0d0c) || \ ((pci)->device == 0x160c)) -#define IS_BROXTON(pci) ((pci)->device == 0x5a98) +#define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170) +#define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70) +#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) +#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci)) static char *driver_short_names[] = { [AZX_DRIVER_ICH] = "HDA Intel", @@ -540,13 +543,13 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset) if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) snd_hdac_set_codec_wakeup(bus, true); - if (IS_BROXTON(pci)) { + if (IS_SKL_PLUS(pci)) { pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val); val = val & ~INTEL_HDA_CGCTL_MISCBDCGE; pci_write_config_dword(pci, INTEL_HDA_CGCTL, val); } azx_init_chip(chip, full_reset); - if (IS_BROXTON(pci)) { + if (IS_SKL_PLUS(pci)) { pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val); val = val | INTEL_HDA_CGCTL_MISCBDCGE; pci_write_config_dword(pci, INTEL_HDA_CGCTL, val); @@ -555,7 +558,7 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset) snd_hdac_set_codec_wakeup(bus, false); /* reduce dma latency to avoid noise */ - if (IS_BROXTON(pci)) + if (IS_BXT(pci)) bxt_reduce_dma_latency(chip); } @@ -977,11 +980,6 @@ static int azx_resume(struct device *dev) /* put codec down to D3 at hibernation for Intel SKL+; * otherwise BIOS may still access the codec and screw up the driver */ -#define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170) -#define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70) -#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) -#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci)) - static int azx_freeze_noirq(struct device *dev) { struct pci_dev *pci = to_pci_dev(dev); @@ -2168,10 +2166,10 @@ static void azx_remove(struct pci_dev *pci) struct hda_intel *hda; if (card) { - /* flush the pending probing work */ + /* cancel the pending probing work */ chip = card->private_data; hda = container_of(chip, struct hda_intel, chip); - flush_work(&hda->probe_work); + cancel_work_sync(&hda->probe_work); snd_card_free(card); } diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 8ee78dbd4c60..bcbc4ee10130 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2477,13 +2477,6 @@ static int patch_generic_hdmi(struct hda_codec *codec) is_broxton(codec)) codec->core.link_power_control = 1; - if (codec_has_acomp(codec)) { - codec->depop_delay = 0; - spec->i915_audio_ops.audio_ptr = codec; - spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify; - snd_hdac_i915_register_notifier(&spec->i915_audio_ops); - } - if (hdmi_parse_codec(codec) < 0) { if (spec->i915_bound) snd_hdac_i915_exit(&codec->bus->core); @@ -2505,6 +2498,18 @@ static int patch_generic_hdmi(struct hda_codec *codec) init_channel_allocations(); + if (codec_has_acomp(codec)) { + codec->depop_delay = 0; + spec->i915_audio_ops.audio_ptr = codec; + /* intel_audio_codec_enable() or intel_audio_codec_disable() + * will call pin_eld_notify with using audio_ptr pointer + * We need make sure audio_ptr is really setup + */ + wmb(); + spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify; + snd_hdac_i915_register_notifier(&spec->i915_audio_ops); + } + return 0; } diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index efd4980cffb8..93d2156b6241 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3801,6 +3801,10 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, static void alc_headset_mode_default(struct hda_codec *codec) { + static struct coef_fw coef0225[] = { + UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10), + {} + }; static struct coef_fw coef0255[] = { WRITE_COEF(0x45, 0xc089), WRITE_COEF(0x45, 0xc489), @@ -3842,6 +3846,9 @@ static void alc_headset_mode_default(struct hda_codec *codec) }; switch (codec->core.vendor_id) { + case 0x10ec0225: + alc_process_coef_fw(codec, coef0225); + break; case 0x10ec0255: case 0x10ec0256: alc_process_coef_fw(codec, coef0255); @@ -4749,6 +4756,9 @@ enum { ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE, ALC293_FIXUP_LENOVO_SPK_NOISE, ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, + ALC255_FIXUP_DELL_SPK_NOISE, + ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, + ALC280_FIXUP_HP_HEADSET_MIC, }; static const struct hda_fixup alc269_fixups[] = { @@ -5368,6 +5378,29 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc233_fixup_lenovo_line2_mic_hotkey, }, + [ALC255_FIXUP_DELL_SPK_NOISE] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_disable_aamix, + .chained = true, + .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE + }, + [ALC225_FIXUP_DELL1_MIC_NO_PRESENCE] = { + .type = HDA_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { + /* Disable pass-through path for FRONT 14h */ + { 0x20, AC_VERB_SET_COEF_INDEX, 0x36 }, + { 0x20, AC_VERB_SET_PROC_COEF, 0x57d7 }, + {} + }, + .chained = true, + .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE + }, + [ALC280_FIXUP_HP_HEADSET_MIC] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_disable_aamix, + .chained = true, + .chain_id = ALC269_FIXUP_HEADSET_MIC, + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -5379,6 +5412,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK), SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK), + SND_PCI_QUIRK(0x1025, 0x0762, "Acer Aspire E1-472", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS), SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK), @@ -5410,6 +5444,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), + SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE), SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), @@ -5470,6 +5505,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), + SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), @@ -5638,10 +5674,10 @@ static const struct hda_model_fixup alc269_fixup_models[] = { {0x21, 0x03211020} static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { - SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, + SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, ALC225_STANDARD_PINS, {0x14, 0x901701a0}), - SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, + SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, ALC225_STANDARD_PINS, {0x14, 0x901701b0}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 2875b4f6d8c9..7c8941b8b2de 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -2879,7 +2879,7 @@ static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp); + ucontrol->value.integer.value[0] = hdsp_dds_offset(hdsp); return 0; } @@ -2891,7 +2891,7 @@ static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; - val = ucontrol->value.enumerated.item[0]; + val = ucontrol->value.integer.value[0]; spin_lock_irq(&hdsp->lock); if (val != hdsp_dds_offset(hdsp)) change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0; diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 8bc8016c173d..a4a999a0317e 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1601,6 +1601,9 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) { u64 n; + if (snd_BUG_ON(rate <= 0)) + return; + if (rate >= 112000) rate /= 4; else if (rate >= 56000) @@ -2215,6 +2218,8 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm) } else { /* slave mode, return external sample rate */ rate = hdspm_external_sample_rate(hdspm); + if (!rate) + rate = hdspm->system_sample_rate; } } @@ -2260,8 +2265,11 @@ static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol, ucontrol) { struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); + int rate = ucontrol->value.integer.value[0]; - hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]); + if (rate < 27000 || rate > 207000) + return -EINVAL; + hdspm_set_dds_value(hdspm, ucontrol->value.integer.value[0]); return 0; } @@ -4449,7 +4457,7 @@ static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol, { struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = hdspm->tco->term; + ucontrol->value.integer.value[0] = hdspm->tco->term; return 0; } @@ -4460,8 +4468,8 @@ static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol, { struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) { - hdspm->tco->term = ucontrol->value.enumerated.item[0]; + if (hdspm->tco->term != ucontrol->value.integer.value[0]) { + hdspm->tco->term = ucontrol->value.integer.value[0]; hdspm_tco_write(hdspm); diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 4f6ce1cac8e2..c458d60d5030 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1124,6 +1124,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) case USB_ID(0x045E, 0x076F): /* MS Lifecam HD-6000 */ case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */ case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */ + case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */ case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */ case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */ case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */ diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index 90bd2ea41032..b3281dcd4a5d 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c @@ -217,13 +217,16 @@ static int nfit_test_cmd_set_config_data(struct nd_cmd_set_config_hdr *nd_cmd, return rc; } +#define NFIT_TEST_ARS_RECORDS 4 + static int nfit_test_cmd_ars_cap(struct nd_cmd_ars_cap *nd_cmd, unsigned int buf_len) { if (buf_len < sizeof(*nd_cmd)) return -EINVAL; - nd_cmd->max_ars_out = 256; + nd_cmd->max_ars_out = sizeof(struct nd_cmd_ars_status) + + NFIT_TEST_ARS_RECORDS * sizeof(struct nd_ars_record); nd_cmd->status = (ND_ARS_PERSISTENT | ND_ARS_VOLATILE) << 16; return 0; @@ -246,7 +249,8 @@ static int nfit_test_cmd_ars_status(struct nd_cmd_ars_status *nd_cmd, if (buf_len < sizeof(*nd_cmd)) return -EINVAL; - nd_cmd->out_length = 256; + nd_cmd->out_length = sizeof(struct nd_cmd_ars_status); + /* TODO: emit error records */ nd_cmd->num_records = 0; nd_cmd->address = 0; nd_cmd->length = -1ULL; diff --git a/tools/testing/selftests/ftrace/test.d/instances/instance.tc b/tools/testing/selftests/ftrace/test.d/instances/instance.tc index 773e276ff90b..1e1abe0ad354 100644 --- a/tools/testing/selftests/ftrace/test.d/instances/instance.tc +++ b/tools/testing/selftests/ftrace/test.d/instances/instance.tc @@ -39,28 +39,23 @@ instance_slam() { } instance_slam & -x=`jobs -l` -p1=`echo $x | cut -d' ' -f2` +p1=$! echo $p1 instance_slam & -x=`jobs -l | tail -1` -p2=`echo $x | cut -d' ' -f2` +p2=$! echo $p2 instance_slam & -x=`jobs -l | tail -1` -p3=`echo $x | cut -d' ' -f2` +p3=$! echo $p3 instance_slam & -x=`jobs -l | tail -1` -p4=`echo $x | cut -d' ' -f2` +p4=$! echo $p4 instance_slam & -x=`jobs -l | tail -1` -p5=`echo $x | cut -d' ' -f2` +p5=$! echo $p5 ls -lR >/dev/null diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 69bca185c471..ea6064696fe4 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c @@ -143,7 +143,7 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level) * Check if there was a change in the timer state (should we raise or lower * the line level to the GIC). */ -static void kvm_timer_update_state(struct kvm_vcpu *vcpu) +static int kvm_timer_update_state(struct kvm_vcpu *vcpu) { struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; @@ -154,10 +154,12 @@ static void kvm_timer_update_state(struct kvm_vcpu *vcpu) * until we call this function from kvm_timer_flush_hwstate. */ if (!vgic_initialized(vcpu->kvm)) - return; + return -ENODEV; if (kvm_timer_should_fire(vcpu) != timer->irq.level) kvm_timer_update_irq(vcpu, !timer->irq.level); + + return 0; } /* @@ -218,7 +220,8 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) bool phys_active; int ret; - kvm_timer_update_state(vcpu); + if (kvm_timer_update_state(vcpu)) + return; /* * If we enter the guest with the virtual input level to the VGIC diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 043032c6a5a4..00429b392c61 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c @@ -1875,8 +1875,8 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu) static int vgic_vcpu_init_maps(struct kvm_vcpu *vcpu, int nr_irqs) { struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; - - int sz = (nr_irqs - VGIC_NR_PRIVATE_IRQS) / 8; + int nr_longs = BITS_TO_LONGS(nr_irqs - VGIC_NR_PRIVATE_IRQS); + int sz = nr_longs * sizeof(unsigned long); vgic_cpu->pending_shared = kzalloc(sz, GFP_KERNEL); vgic_cpu->active_shared = kzalloc(sz, GFP_KERNEL); vgic_cpu->pend_act_shared = kzalloc(sz, GFP_KERNEL); diff --git a/virt/kvm/async_pf.c b/virt/kvm/async_pf.c index 353159922456..db2dd3335c6a 100644 --- a/virt/kvm/async_pf.c +++ b/virt/kvm/async_pf.c @@ -172,7 +172,7 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, unsigned long hva, * do alloc nowait since if we are going to sleep anyway we * may as well sleep faulting in page */ - work = kmem_cache_zalloc(async_pf_cache, GFP_NOWAIT); + work = kmem_cache_zalloc(async_pf_cache, GFP_NOWAIT | __GFP_NOWARN); if (!work) return 0; |