diff options
953 files changed, 13542 insertions, 8459 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt index 3a268127b05..bc50899e0c8 100644 --- a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt @@ -81,7 +81,8 @@ PA31 TXD4 Required properties for pin configuration node: - atmel,pins: 4 integers array, represents a group of pins mux and config setting. The format is atmel,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>. - The PERIPH 0 means gpio. + The PERIPH 0 means gpio, PERIPH 1 is periph A, PERIPH 2 is periph B... + PIN_BANK 0 is pioA, PIN_BANK 1 is pioB... Bits used for CONFIG: PULL_UP (1 << 0): indicate this pin need a pull up. @@ -126,7 +127,7 @@ pinctrl@fffff400 { pinctrl_dbgu: dbgu-0 { atmel,pins = <1 14 0x1 0x0 /* PB14 periph A */ - 1 15 0x1 0x1>; /* PB15 periph with pullup */ + 1 15 0x1 0x1>; /* PB15 periph A with pullup */ }; }; }; diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt index 8fbd8b46ee3..dcf338e62b7 100644 --- a/Documentation/filesystems/f2fs.txt +++ b/Documentation/filesystems/f2fs.txt @@ -175,9 +175,9 @@ consists of multiple segments as described below. align with the zone size <-| |-> align with the segment size _________________________________________________________________________ - | | | Node | Segment | Segment | | - | Superblock | Checkpoint | Address | Info. | Summary | Main | - | (SB) | (CP) | Table (NAT) | Table (SIT) | Area (SSA) | | + | | | Segment | Node | Segment | | + | Superblock | Checkpoint | Info. | Address | Summary | Main | + | (SB) | (CP) | Table (SIT) | Table (NAT) | Area (SSA) | | |____________|_____2______|______N______|______N______|______N_____|__N___| . . . . @@ -200,14 +200,14 @@ consists of multiple segments as described below. : It contains file system information, bitmaps for valid NAT/SIT sets, orphan inode lists, and summary entries of current active segments. -- Node Address Table (NAT) - : It is composed of a block address table for all the node blocks stored in - Main area. - - Segment Information Table (SIT) : It contains segment information such as valid block count and bitmap for the validity of all the blocks. +- Node Address Table (NAT) + : It is composed of a block address table for all the node blocks stored in + Main area. + - Segment Summary Area (SSA) : It contains summary entries which contains the owner information of all the data and node blocks stored in Main area. @@ -236,13 +236,13 @@ For file system consistency, each CP points to which NAT and SIT copies are valid, as shown as below. +--------+----------+---------+ - | CP | NAT | SIT | + | CP | SIT | NAT | +--------+----------+---------+ . . . . . . . . . . . . +-------+-------+--------+--------+--------+--------+ - | CP #0 | CP #1 | NAT #0 | NAT #1 | SIT #0 | SIT #1 | + | CP #0 | CP #1 | SIT #0 | SIT #1 | NAT #0 | NAT #1 | +-------+-------+--------+--------+--------+--------+ | ^ ^ | | | diff --git a/MAINTAINERS b/MAINTAINERS index 915564eda14..fd9959c174e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -228,7 +228,7 @@ S: Maintained F: drivers/platform/x86/acerhdf.c ACER WMI LAPTOP EXTRAS -M: Joey Lee <jlee@novell.com> +M: "Lee, Chun-Yi" <jlee@suse.com> L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/acer-wmi.c @@ -648,7 +648,7 @@ F: arch/arm/ ARM SUB-ARCHITECTURES L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: MAINTAINED +S: Maintained F: arch/arm/mach-*/ F: arch/arm/plat-*/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git @@ -1351,6 +1351,14 @@ W: http://wireless.kernel.org/en/users/Drivers/ath9k S: Supported F: drivers/net/wireless/ath/ath9k/ +WILOCITY WIL6210 WIRELESS DRIVER +M: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> +L: linux-wireless@vger.kernel.org +L: wil6210@qca.qualcomm.com +S: Supported +W: http://wireless.kernel.org/en/users/Drivers/wil6210 +F: drivers/net/wireless/ath/wil6210/ + CARL9170 LINUX COMMUNITY WIRELESS DRIVER M: Christian Lamparter <chunkeey@googlemail.com> L: linux-wireless@vger.kernel.org @@ -1964,9 +1972,9 @@ S: Maintained F: drivers/usb/host/ohci-ep93xx.c CIRRUS LOGIC CS4270 SOUND DRIVER -M: Timur Tabi <timur@freescale.com> +M: Timur Tabi <timur@tabi.org> L: alsa-devel@alsa-project.org (moderated for non-subscribers) -S: Supported +S: Odd Fixes F: sound/soc/codecs/cs4270* CLEANCACHE API @@ -3183,9 +3191,9 @@ F: include/uapi/video/ F: include/uapi/linux/fb.h FREESCALE DIU FRAMEBUFFER DRIVER -M: Timur Tabi <timur@freescale.com> +M: Timur Tabi <timur@tabi.org> L: linux-fbdev@vger.kernel.org -S: Supported +S: Maintained F: drivers/video/fsl-diu-fb.* FREESCALE DMA DRIVER @@ -3220,9 +3228,8 @@ F: drivers/net/ethernet/freescale/fs_enet/ F: include/linux/fs_enet_pd.h FREESCALE QUICC ENGINE LIBRARY -M: Timur Tabi <timur@freescale.com> L: linuxppc-dev@lists.ozlabs.org -S: Supported +S: Orphan F: arch/powerpc/sysdev/qe_lib/ F: arch/powerpc/include/asm/*qe.h @@ -3241,16 +3248,16 @@ S: Maintained F: drivers/net/ethernet/freescale/ucc_geth* FREESCALE QUICC ENGINE UCC UART DRIVER -M: Timur Tabi <timur@freescale.com> +M: Timur Tabi <timur@tabi.org> L: linuxppc-dev@lists.ozlabs.org -S: Supported +S: Maintained F: drivers/tty/serial/ucc_uart.c FREESCALE SOC SOUND DRIVERS -M: Timur Tabi <timur@freescale.com> +M: Timur Tabi <timur@tabi.org> L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: linuxppc-dev@lists.ozlabs.org -S: Supported +S: Maintained F: sound/soc/fsl/fsl* F: sound/soc/fsl/mpc8610_hpcd.c @@ -4209,6 +4216,7 @@ M: Thomas Gleixner <tglx@linutronix.de> S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core F: kernel/irq/ +F: drivers/irqchip/ IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY) M: Benjamin Herrenschmidt <benh@kernel.crashing.org> @@ -5077,7 +5085,7 @@ S: Maintained F: drivers/media/radio/radio-mr800.c MSI LAPTOP SUPPORT -M: "Lee, Chun-Yi" <jlee@novell.com> +M: "Lee, Chun-Yi" <jlee@suse.com> L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/msi-laptop.c @@ -5507,8 +5515,7 @@ M: Benoît Cousson <b-cousson@ti.com> M: Paul Walmsley <paul@pwsan.com> L: linux-omap@vger.kernel.org S: Maintained -F: arch/arm/mach-omap2/omap_hwmod.c -F: arch/arm/plat-omap/include/plat/omap_hwmod.h +F: arch/arm/mach-omap2/omap_hwmod.* OMAP HWMOD DATA FOR OMAP4-BASED DEVICES M: Benoît Cousson <b-cousson@ti.com> @@ -6579,7 +6586,7 @@ F: drivers/media/platform/s3c-camif/ F: include/media/s3c_camif.h SERIAL DRIVERS -M: Alan Cox <alan@linux.intel.com> +M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> L: linux-serial@vger.kernel.org S: Maintained F: drivers/tty/serial @@ -7334,7 +7341,7 @@ S: Odd Fixes F: drivers/staging/speakup/ STAGING - TI DSP BRIDGE DRIVERS -M: Omar Ramirez Luna <omar.ramirez@ti.com> +M: Omar Ramirez Luna <omar.ramirez@copitl.com> S: Odd Fixes F: drivers/staging/tidspbridge/ @@ -8526,7 +8533,7 @@ F: Documentation/x86/ F: arch/x86/ X86 PLATFORM DRIVERS -M: Matthew Garrett <mjg@redhat.com> +M: Matthew Garrett <matthew.garrett@nebula.com> L: platform-driver-x86@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.git S: Maintained @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 8 SUBLEVEL = 0 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc5 NAME = Terrified Chipmunk # *DOCUMENTATION* @@ -169,7 +169,7 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ -e s/arm.*/arm/ -e s/sa110/arm/ \ -e s/s390x/s390/ -e s/parisc64/parisc/ \ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ - -e s/sh[234].*/sh/ ) + -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ ) # Cross compiling and selecting different set of gcc/bin-utils # --------------------------------------------------------------------------- diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index eb9fc2f8acf..c2950f3e678 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -344,10 +344,10 @@ config ARCH_BCM2835 select ARM_ERRATA_411920 select ARM_TIMER_SP804 select CLKDEV_LOOKUP + select CLKSRC_OF select COMMON_CLK select CPU_V6 select GENERIC_CLOCKEVENTS - select GENERIC_GPIO select MULTI_IRQ_HANDLER select PINCTRL select PINCTRL_BCM2835 @@ -645,7 +645,6 @@ config ARCH_TEGRA select CLKSRC_OF select COMMON_CLK select GENERIC_CLOCKEVENTS - select GENERIC_GPIO select HAVE_CLK select HAVE_SMP select MIGHT_HAVE_CACHE_L2X0 @@ -745,7 +744,6 @@ config ARCH_S3C24XX select ARCH_HAS_CPUFREQ select ARCH_USES_GETTIMEOFFSET select CLKDEV_LOOKUP - select GENERIC_GPIO select HAVE_CLK select HAVE_S3C2410_I2C if I2C select HAVE_S3C2410_WATCHDOG if WATCHDOG @@ -788,7 +786,6 @@ config ARCH_S5P64X0 select CLKSRC_MMIO select CPU_V6 select GENERIC_CLOCKEVENTS - select GENERIC_GPIO select HAVE_CLK select HAVE_S3C2410_I2C if I2C select HAVE_S3C2410_WATCHDOG if WATCHDOG @@ -803,7 +800,6 @@ config ARCH_S5PC100 select ARCH_USES_GETTIMEOFFSET select CLKDEV_LOOKUP select CPU_V7 - select GENERIC_GPIO select HAVE_CLK select HAVE_S3C2410_I2C if I2C select HAVE_S3C2410_WATCHDOG if WATCHDOG @@ -821,7 +817,6 @@ config ARCH_S5PV210 select CLKSRC_MMIO select CPU_V7 select GENERIC_CLOCKEVENTS - select GENERIC_GPIO select HAVE_CLK select HAVE_S3C2410_I2C if I2C select HAVE_S3C2410_WATCHDOG if WATCHDOG @@ -839,7 +834,6 @@ config ARCH_EXYNOS select CLKDEV_LOOKUP select CPU_V7 select GENERIC_CLOCKEVENTS - select GENERIC_GPIO select HAVE_CLK select HAVE_S3C2410_I2C if I2C select HAVE_S3C2410_WATCHDOG if WATCHDOG @@ -874,7 +868,6 @@ config ARCH_U300 select COMMON_CLK select CPU_ARM926T select GENERIC_CLOCKEVENTS - select GENERIC_GPIO select HAVE_TCM select SPARSE_IRQ help @@ -958,7 +951,6 @@ config ARCH_VT8500_SINGLE select COMMON_CLK select CPU_ARM926T select GENERIC_CLOCKEVENTS - select GENERIC_GPIO select HAVE_CLK select MULTI_IRQ_HANDLER select SPARSE_IRQ diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 661030d6bc6..1dceb8e3161 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -219,12 +219,12 @@ choice Say Y here if you want kernel low-level debugging support on i.MX51. - config DEBUG_IMX50_IMX53_UART - bool "i.MX50 and i.MX53 Debug UART" - depends on SOC_IMX50 || SOC_IMX53 + config DEBUG_IMX53_UART + bool "i.MX53 Debug UART" + depends on SOC_IMX53 help Say Y here if you want kernel low-level debugging support - on i.MX50 or i.MX53. + on i.MX53. config DEBUG_IMX6Q_UART bool "i.MX6Q Debug UART" @@ -497,7 +497,7 @@ config DEBUG_LL_INCLUDE DEBUG_IMX21_IMX27_UART || \ DEBUG_IMX31_IMX35_UART || \ DEBUG_IMX51_UART || \ - DEBUG_IMX50_IMX53_UART ||\ + DEBUG_IMX53_UART ||\ DEBUG_IMX6Q_UART default "debug/highbank.S" if DEBUG_HIGHBANK_UART default "debug/mvebu.S" if DEBUG_MVEBU_UART diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c index 9deb56a702c..24b0475cb8b 100644 --- a/arch/arm/boot/compressed/decompress.c +++ b/arch/arm/boot/compressed/decompress.c @@ -13,8 +13,6 @@ extern void error(char *); #define STATIC static #define STATIC_RW_DATA /* non-static please */ -#define ARCH_HAS_DECOMP_WDOG - /* Diagnostic functions */ #ifdef DEBUG # define Assert(cond,msg) {if(!(cond)) error(msg);} diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index e44da40d984..5ebb44fe826 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -155,6 +155,7 @@ dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \ dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb targets += dtbs +targets += $(dtb-y) endif # *.dtb used to be generated in the directory above. Clean out the diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts index 00044026ef1..9b82facb256 100644 --- a/arch/arm/boot/dts/armada-370-db.dts +++ b/arch/arm/boot/dts/armada-370-db.dts @@ -26,7 +26,7 @@ memory { device_type = "memory"; - reg = <0x00000000 0x20000000>; /* 512 MB */ + reg = <0x00000000 0x40000000>; /* 1 GB */ }; soc { diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi index 271855a6e22..e041f42ed71 100644 --- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi @@ -50,27 +50,25 @@ }; gpio0: gpio@d0018100 { - compatible = "marvell,armadaxp-gpio"; - reg = <0xd0018100 0x40>, - <0xd0018800 0x30>; + compatible = "marvell,orion-gpio"; + reg = <0xd0018100 0x40>; ngpios = <32>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupts-cells = <2>; - interrupts = <16>, <17>, <18>, <19>; + interrupts = <82>, <83>, <84>, <85>; }; gpio1: gpio@d0018140 { - compatible = "marvell,armadaxp-gpio"; - reg = <0xd0018140 0x40>, - <0xd0018840 0x30>; + compatible = "marvell,orion-gpio"; + reg = <0xd0018140 0x40>; ngpios = <17>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupts-cells = <2>; - interrupts = <20>, <21>, <22>; + interrupts = <87>, <88>, <89>; }; }; }; diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi index 1c1937dbce7..9e23bd8c953 100644 --- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi @@ -51,39 +51,36 @@ }; gpio0: gpio@d0018100 { - compatible = "marvell,armadaxp-gpio"; - reg = <0xd0018100 0x40>, - <0xd0018800 0x30>; + compatible = "marvell,orion-gpio"; + reg = <0xd0018100 0x40>; ngpios = <32>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupts-cells = <2>; - interrupts = <16>, <17>, <18>, <19>; + interrupts = <82>, <83>, <84>, <85>; }; gpio1: gpio@d0018140 { - compatible = "marvell,armadaxp-gpio"; - reg = <0xd0018140 0x40>, - <0xd0018840 0x30>; + compatible = "marvell,orion-gpio"; + reg = <0xd0018140 0x40>; ngpios = <32>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupts-cells = <2>; - interrupts = <20>, <21>, <22>, <23>; + interrupts = <87>, <88>, <89>, <90>; }; gpio2: gpio@d0018180 { - compatible = "marvell,armadaxp-gpio"; - reg = <0xd0018180 0x40>, - <0xd0018870 0x30>; + compatible = "marvell,orion-gpio"; + reg = <0xd0018180 0x40>; ngpios = <3>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupts-cells = <2>; - interrupts = <24>; + interrupts = <91>; }; ethernet@d0034000 { diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi index 4905cf3a5ef..965966110e3 100644 --- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi @@ -66,39 +66,36 @@ }; gpio0: gpio@d0018100 { - compatible = "marvell,armadaxp-gpio"; - reg = <0xd0018100 0x40>, - <0xd0018800 0x30>; + compatible = "marvell,orion-gpio"; + reg = <0xd0018100 0x40>; ngpios = <32>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupts-cells = <2>; - interrupts = <16>, <17>, <18>, <19>; + interrupts = <82>, <83>, <84>, <85>; }; gpio1: gpio@d0018140 { - compatible = "marvell,armadaxp-gpio"; - reg = <0xd0018140 0x40>, - <0xd0018840 0x30>; + compatible = "marvell,orion-gpio"; + reg = <0xd0018140 0x40>; ngpios = <32>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupts-cells = <2>; - interrupts = <20>, <21>, <22>, <23>; + interrupts = <87>, <88>, <89>, <90>; }; gpio2: gpio@d0018180 { - compatible = "marvell,armadaxp-gpio"; - reg = <0xd0018180 0x40>, - <0xd0018870 0x30>; + compatible = "marvell,orion-gpio"; + reg = <0xd0018180 0x40>; ngpios = <3>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupts-cells = <2>; - interrupts = <24>; + interrupts = <91>; }; ethernet@d0034000 { diff --git a/arch/arm/boot/dts/at91rm9200.dtsi b/arch/arm/boot/dts/at91rm9200.dtsi index e154f242c68..222047f1ece 100644 --- a/arch/arm/boot/dts/at91rm9200.dtsi +++ b/arch/arm/boot/dts/at91rm9200.dtsi @@ -336,8 +336,8 @@ i2c@0 { compatible = "i2c-gpio"; - gpios = <&pioA 23 0 /* sda */ - &pioA 24 0 /* scl */ + gpios = <&pioA 25 0 /* sda */ + &pioA 26 0 /* scl */ >; i2c-gpio,sda-open-drain; i2c-gpio,scl-open-drain; diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi index 68bccf41a2c..cb7bcc51608 100644 --- a/arch/arm/boot/dts/at91sam9260.dtsi +++ b/arch/arm/boot/dts/at91sam9260.dtsi @@ -306,6 +306,22 @@ }; }; + ssc0 { + pinctrl_ssc0_tx: ssc0_tx-0 { + atmel,pins = + <1 16 0x1 0x0 /* PB16 periph A */ + 1 17 0x1 0x0 /* PB17 periph A */ + 1 18 0x1 0x0>; /* PB18 periph A */ + }; + + pinctrl_ssc0_rx: ssc0_rx-0 { + atmel,pins = + <1 19 0x1 0x0 /* PB19 periph A */ + 1 20 0x1 0x0 /* PB20 periph A */ + 1 21 0x1 0x0>; /* PB21 periph A */ + }; + }; + pioA: gpio@fffff400 { compatible = "atmel,at91rm9200-gpio"; reg = <0xfffff400 0x200>; @@ -450,6 +466,8 @@ compatible = "atmel,at91rm9200-ssc"; reg = <0xfffbc000 0x4000>; interrupts = <14 4 5>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi index 32ec62cf538..271d4de026e 100644 --- a/arch/arm/boot/dts/at91sam9263.dtsi +++ b/arch/arm/boot/dts/at91sam9263.dtsi @@ -271,6 +271,38 @@ }; }; + ssc0 { + pinctrl_ssc0_tx: ssc0_tx-0 { + atmel,pins = + <1 0 0x2 0x0 /* PB0 periph B */ + 1 1 0x2 0x0 /* PB1 periph B */ + 1 2 0x2 0x0>; /* PB2 periph B */ + }; + + pinctrl_ssc0_rx: ssc0_rx-0 { + atmel,pins = + <1 3 0x2 0x0 /* PB3 periph B */ + 1 4 0x2 0x0 /* PB4 periph B */ + 1 5 0x2 0x0>; /* PB5 periph B */ + }; + }; + + ssc1 { + pinctrl_ssc1_tx: ssc1_tx-0 { + atmel,pins = + <1 6 0x1 0x0 /* PB6 periph A */ + 1 7 0x1 0x0 /* PB7 periph A */ + 1 8 0x1 0x0>; /* PB8 periph A */ + }; + + pinctrl_ssc1_rx: ssc1_rx-0 { + atmel,pins = + <1 9 0x1 0x0 /* PB9 periph A */ + 1 10 0x1 0x0 /* PB10 periph A */ + 1 11 0x1 0x0>; /* PB11 periph A */ + }; + }; + pioA: gpio@fffff200 { compatible = "atmel,at91rm9200-gpio"; reg = <0xfffff200 0x200>; @@ -368,6 +400,8 @@ compatible = "atmel,at91rm9200-ssc"; reg = <0xfff98000 0x4000>; interrupts = <16 4 5>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>; status = "disabled"; }; @@ -375,6 +409,8 @@ compatible = "atmel,at91rm9200-ssc"; reg = <0xfff9c000 0x4000>; interrupts = <17 4 5>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index 231858ffd85..6b1d4cab24c 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -290,6 +290,38 @@ }; }; + ssc0 { + pinctrl_ssc0_tx: ssc0_tx-0 { + atmel,pins = + <3 0 0x1 0x0 /* PD0 periph A */ + 3 1 0x1 0x0 /* PD1 periph A */ + 3 2 0x1 0x0>; /* PD2 periph A */ + }; + + pinctrl_ssc0_rx: ssc0_rx-0 { + atmel,pins = + <3 3 0x1 0x0 /* PD3 periph A */ + 3 4 0x1 0x0 /* PD4 periph A */ + 3 5 0x1 0x0>; /* PD5 periph A */ + }; + }; + + ssc1 { + pinctrl_ssc1_tx: ssc1_tx-0 { + atmel,pins = + <3 10 0x1 0x0 /* PD10 periph A */ + 3 11 0x1 0x0 /* PD11 periph A */ + 3 12 0x1 0x0>; /* PD12 periph A */ + }; + + pinctrl_ssc1_rx: ssc1_rx-0 { + atmel,pins = + <3 13 0x1 0x0 /* PD13 periph A */ + 3 14 0x1 0x0 /* PD14 periph A */ + 3 15 0x1 0x0>; /* PD15 periph A */ + }; + }; + pioA: gpio@fffff200 { compatible = "atmel,at91rm9200-gpio"; reg = <0xfffff200 0x200>; @@ -425,6 +457,8 @@ compatible = "atmel,at91sam9g45-ssc"; reg = <0xfff9c000 0x4000>; interrupts = <16 4 5>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>; status = "disabled"; }; @@ -432,6 +466,8 @@ compatible = "atmel,at91sam9g45-ssc"; reg = <0xfffa0000 0x4000>; interrupts = <17 4 5>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi index e9efb34f437..80e29c605d4 100644 --- a/arch/arm/boot/dts/at91sam9n12.dtsi +++ b/arch/arm/boot/dts/at91sam9n12.dtsi @@ -28,6 +28,7 @@ tcb1 = &tcb1; i2c0 = &i2c0; i2c1 = &i2c1; + ssc0 = &ssc0; }; cpus { cpu@0 { @@ -244,6 +245,22 @@ }; }; + ssc0 { + pinctrl_ssc0_tx: ssc0_tx-0 { + atmel,pins = + <0 24 0x2 0x0 /* PA24 periph B */ + 0 25 0x2 0x0 /* PA25 periph B */ + 0 26 0x2 0x0>; /* PA26 periph B */ + }; + + pinctrl_ssc0_rx: ssc0_rx-0 { + atmel,pins = + <0 27 0x2 0x0 /* PA27 periph B */ + 0 28 0x2 0x0 /* PA28 periph B */ + 0 29 0x2 0x0>; /* PA29 periph B */ + }; + }; + pioA: gpio@fffff400 { compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; reg = <0xfffff400 0x200>; @@ -294,6 +311,15 @@ status = "disabled"; }; + ssc0: ssc@f0010000 { + compatible = "atmel,at91sam9g45-ssc"; + reg = <0xf0010000 0x4000>; + interrupts = <28 4 5>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>; + status = "disabled"; + }; + usart0: serial@f801c000 { compatible = "atmel,at91sam9260-usart"; reg = <0xf801c000 0x4000>; diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index 40ac3a4eb1a..8ecca6948d8 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -88,13 +88,6 @@ interrupts = <1 4 7>; }; - ssc0: ssc@f0010000 { - compatible = "atmel,at91sam9g45-ssc"; - reg = <0xf0010000 0x4000>; - interrupts = <28 4 5>; - status = "disabled"; - }; - tcb0: timer@f8008000 { compatible = "atmel,at91sam9x5-tcb"; reg = <0xf8008000 0x100>; @@ -150,6 +143,11 @@ atmel,pins = <0 3 0x1 0x0>; /* PA3 periph A */ }; + + pinctrl_usart0_sck: usart0_sck-0 { + atmel,pins = + <0 4 0x1 0x0>; /* PA4 periph A */ + }; }; usart1 { @@ -161,12 +159,17 @@ pinctrl_usart1_rts: usart1_rts-0 { atmel,pins = - <3 27 0x3 0x0>; /* PC27 periph C */ + <2 27 0x3 0x0>; /* PC27 periph C */ }; pinctrl_usart1_cts: usart1_cts-0 { atmel,pins = - <3 28 0x3 0x0>; /* PC28 periph C */ + <2 28 0x3 0x0>; /* PC28 periph C */ + }; + + pinctrl_usart1_sck: usart1_sck-0 { + atmel,pins = + <2 28 0x3 0x0>; /* PC29 periph C */ }; }; @@ -179,46 +182,56 @@ pinctrl_uart2_rts: uart2_rts-0 { atmel,pins = - <0 0 0x2 0x0>; /* PB0 periph B */ + <1 0 0x2 0x0>; /* PB0 periph B */ }; pinctrl_uart2_cts: uart2_cts-0 { atmel,pins = - <0 1 0x2 0x0>; /* PB1 periph B */ + <1 1 0x2 0x0>; /* PB1 periph B */ + }; + + pinctrl_usart2_sck: usart2_sck-0 { + atmel,pins = + <1 2 0x2 0x0>; /* PB2 periph B */ }; }; usart3 { pinctrl_uart3: usart3-0 { atmel,pins = - <3 23 0x2 0x1 /* PC22 periph B with pullup */ - 3 23 0x2 0x0>; /* PC23 periph B */ + <2 23 0x2 0x1 /* PC22 periph B with pullup */ + 2 23 0x2 0x0>; /* PC23 periph B */ }; pinctrl_usart3_rts: usart3_rts-0 { atmel,pins = - <3 24 0x2 0x0>; /* PC24 periph B */ + <2 24 0x2 0x0>; /* PC24 periph B */ }; pinctrl_usart3_cts: usart3_cts-0 { atmel,pins = - <3 25 0x2 0x0>; /* PC25 periph B */ + <2 25 0x2 0x0>; /* PC25 periph B */ + }; + + pinctrl_usart3_sck: usart3_sck-0 { + atmel,pins = + <2 26 0x2 0x0>; /* PC26 periph B */ }; }; uart0 { pinctrl_uart0: uart0-0 { atmel,pins = - <3 8 0x3 0x0 /* PC8 periph C */ - 3 9 0x3 0x1>; /* PC9 periph C with pullup */ + <2 8 0x3 0x0 /* PC8 periph C */ + 2 9 0x3 0x1>; /* PC9 periph C with pullup */ }; }; uart1 { pinctrl_uart1: uart1-0 { atmel,pins = - <3 16 0x3 0x0 /* PC16 periph C */ - 3 17 0x3 0x1>; /* PC17 periph C with pullup */ + <2 16 0x3 0x0 /* PC16 periph C */ + 2 17 0x3 0x1>; /* PC17 periph C with pullup */ }; }; @@ -247,14 +260,14 @@ pinctrl_macb0_rmii_mii: macb0_rmii_mii-0 { atmel,pins = - <1 8 0x1 0x0 /* PA8 periph A */ - 1 11 0x1 0x0 /* PA11 periph A */ - 1 12 0x1 0x0 /* PA12 periph A */ - 1 13 0x1 0x0 /* PA13 periph A */ - 1 14 0x1 0x0 /* PA14 periph A */ - 1 15 0x1 0x0 /* PA15 periph A */ - 1 16 0x1 0x0 /* PA16 periph A */ - 1 17 0x1 0x0>; /* PA17 periph A */ + <1 8 0x1 0x0 /* PB8 periph A */ + 1 11 0x1 0x0 /* PB11 periph A */ + 1 12 0x1 0x0 /* PB12 periph A */ + 1 13 0x1 0x0 /* PB13 periph A */ + 1 14 0x1 0x0 /* PB14 periph A */ + 1 15 0x1 0x0 /* PB15 periph A */ + 1 16 0x1 0x0 /* PB16 periph A */ + 1 17 0x1 0x0>; /* PB17 periph A */ }; }; @@ -290,6 +303,22 @@ }; }; + ssc0 { + pinctrl_ssc0_tx: ssc0_tx-0 { + atmel,pins = + <0 24 0x2 0x0 /* PA24 periph B */ + 0 25 0x2 0x0 /* PA25 periph B */ + 0 26 0x2 0x0>; /* PA26 periph B */ + }; + + pinctrl_ssc0_rx: ssc0_rx-0 { + atmel,pins = + <0 27 0x2 0x0 /* PA27 periph B */ + 0 28 0x2 0x0 /* PA28 periph B */ + 0 29 0x2 0x0>; /* PA29 periph B */ + }; + }; + pioA: gpio@fffff400 { compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; reg = <0xfffff400 0x200>; @@ -333,6 +362,15 @@ }; }; + ssc0: ssc@f0010000 { + compatible = "atmel,at91sam9g45-ssc"; + reg = <0xf0010000 0x4000>; + interrupts = <28 4 5>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>; + status = "disabled"; + }; + mmc0: mmc@f0008000 { compatible = "atmel,hsmci"; reg = <0xf0008000 0x600>; diff --git a/arch/arm/boot/dts/cros5250-common.dtsi b/arch/arm/boot/dts/cros5250-common.dtsi index fddd1741743..46c09801703 100644 --- a/arch/arm/boot/dts/cros5250-common.dtsi +++ b/arch/arm/boot/dts/cros5250-common.dtsi @@ -96,8 +96,8 @@ fifo-depth = <0x80>; card-detect-delay = <200>; samsung,dw-mshc-ciu-div = <3>; - samsung,dw-mshc-sdr-timing = <2 3 3>; - samsung,dw-mshc-ddr-timing = <1 2 3>; + samsung,dw-mshc-sdr-timing = <2 3>; + samsung,dw-mshc-ddr-timing = <1 2>; slot@0 { reg = <0>; @@ -120,8 +120,8 @@ fifo-depth = <0x80>; card-detect-delay = <200>; samsung,dw-mshc-ciu-div = <3>; - samsung,dw-mshc-sdr-timing = <2 3 3>; - samsung,dw-mshc-ddr-timing = <1 2 3>; + samsung,dw-mshc-sdr-timing = <2 3>; + samsung,dw-mshc-ddr-timing = <1 2>; slot@0 { reg = <0>; @@ -141,8 +141,8 @@ fifo-depth = <0x80>; card-detect-delay = <200>; samsung,dw-mshc-ciu-div = <3>; - samsung,dw-mshc-sdr-timing = <2 3 3>; - samsung,dw-mshc-ddr-timing = <1 2 3>; + samsung,dw-mshc-sdr-timing = <2 3>; + samsung,dw-mshc-ddr-timing = <1 2>; slot@0 { reg = <0>; diff --git a/arch/arm/boot/dts/dove-cubox.dts b/arch/arm/boot/dts/dove-cubox.dts index fed7d3f9f43..cdee96fca6e 100644 --- a/arch/arm/boot/dts/dove-cubox.dts +++ b/arch/arm/boot/dts/dove-cubox.dts @@ -26,10 +26,15 @@ }; &uart0 { status = "okay"; }; -&sdio0 { status = "okay"; }; &sata0 { status = "okay"; }; &i2c0 { status = "okay"; }; +&sdio0 { + status = "okay"; + /* sdio0 card detect is connected to wrong pin on CuBox */ + cd-gpios = <&gpio0 12 1>; +}; + &spi0 { status = "okay"; @@ -42,9 +47,14 @@ }; &pinctrl { - pinctrl-0 = <&pmx_gpio_18>; + pinctrl-0 = <&pmx_gpio_12 &pmx_gpio_18>; pinctrl-names = "default"; + pmx_gpio_12: pmx-gpio-12 { + marvell,pins = "mpp12"; + marvell,function = "gpio"; + }; + pmx_gpio_18: pmx-gpio-18 { marvell,pins = "mpp18"; marvell,function = "gpio"; diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 942d5761ca9..e05b18f3c33 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -115,8 +115,8 @@ fifo-depth = <0x80>; card-detect-delay = <200>; samsung,dw-mshc-ciu-div = <3>; - samsung,dw-mshc-sdr-timing = <2 3 3>; - samsung,dw-mshc-ddr-timing = <1 2 3>; + samsung,dw-mshc-sdr-timing = <2 3>; + samsung,dw-mshc-ddr-timing = <1 2>; slot@0 { reg = <0>; @@ -139,8 +139,8 @@ fifo-depth = <0x80>; card-detect-delay = <200>; samsung,dw-mshc-ciu-div = <3>; - samsung,dw-mshc-sdr-timing = <2 3 3>; - samsung,dw-mshc-ddr-timing = <1 2 3>; + samsung,dw-mshc-sdr-timing = <2 3>; + samsung,dw-mshc-ddr-timing = <1 2>; slot@0 { reg = <0>; diff --git a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi index 9bc6785ad22..77d21abfcdf 100644 --- a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi +++ b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi @@ -1,4 +1,5 @@ /include/ "kirkwood.dtsi" +/include/ "kirkwood-6281.dtsi" / { chosen { @@ -6,6 +7,21 @@ }; ocp@f1000000 { + pinctrl: pinctrl@10000 { + pinctrl-0 = < &pmx_spi &pmx_twsi0 &pmx_uart0 + &pmx_ns2_sata0 &pmx_ns2_sata1>; + pinctrl-names = "default"; + + pmx_ns2_sata0: pmx-ns2-sata0 { + marvell,pins = "mpp21"; + marvell,function = "sata0"; + }; + pmx_ns2_sata1: pmx-ns2-sata1 { + marvell,pins = "mpp20"; + marvell,function = "sata1"; + }; + }; + serial@12000 { clock-frequency = <166666667>; status = "okay"; diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi index 110d6cbb795..d6ab442b701 100644 --- a/arch/arm/boot/dts/kirkwood.dtsi +++ b/arch/arm/boot/dts/kirkwood.dtsi @@ -36,6 +36,7 @@ reg = <0x10100 0x40>; ngpios = <32>; interrupt-controller; + #interrupt-cells = <2>; interrupts = <35>, <36>, <37>, <38>; }; @@ -46,6 +47,7 @@ reg = <0x10140 0x40>; ngpios = <18>; interrupt-controller; + #interrupt-cells = <2>; interrupts = <39>, <40>, <41>; }; diff --git a/arch/arm/boot/dts/kizbox.dts b/arch/arm/boot/dts/kizbox.dts index e8814fe0e27..b4dc3ed9a3e 100644 --- a/arch/arm/boot/dts/kizbox.dts +++ b/arch/arm/boot/dts/kizbox.dts @@ -48,6 +48,8 @@ macb0: ethernet@fffc4000 { phy-mode = "mii"; + pinctrl-0 = <&pinctrl_macb_rmii + &pinctrl_macb_rmii_mii_alt>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sunxi.dtsi b/arch/arm/boot/dts/sunxi.dtsi index 8bbc2bfef22..8b36abea9f2 100644 --- a/arch/arm/boot/dts/sunxi.dtsi +++ b/arch/arm/boot/dts/sunxi.dtsi @@ -60,19 +60,21 @@ }; uart0: uart@01c28000 { - compatible = "ns8250"; + compatible = "snps,dw-apb-uart"; reg = <0x01c28000 0x400>; interrupts = <1>; reg-shift = <2>; + reg-io-width = <4>; clock-frequency = <24000000>; status = "disabled"; }; uart1: uart@01c28400 { - compatible = "ns8250"; + compatible = "snps,dw-apb-uart"; reg = <0x01c28400 0x400>; interrupts = <2>; reg-shift = <2>; + reg-io-width = <4>; clock-frequency = <24000000>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts index 1fc405a9ecf..cf8071ad22d 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts @@ -45,7 +45,6 @@ reg = <1>; }; -/* A7s disabled till big.LITTLE patches are available... cpu2: cpu@2 { device_type = "cpu"; compatible = "arm,cortex-a7"; @@ -63,7 +62,6 @@ compatible = "arm,cortex-a7"; reg = <0x102>; }; -*/ }; memory@80000000 { diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig index 45ceeb0e93e..9353184d730 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig @@ -1,26 +1,3 @@ -config ARM_GIC - bool - select IRQ_DOMAIN - select MULTI_IRQ_HANDLER - -config GIC_NON_BANKED - bool - -config ARM_VIC - bool - select IRQ_DOMAIN - select MULTI_IRQ_HANDLER - -config ARM_VIC_NR - int - default 4 if ARCH_S5PV210 - default 3 if ARCH_S5PC100 - default 2 - depends on ARM_VIC - help - The maximum number of VICs available in the system, for - power management. - config ICST bool diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index e8a4e58f1b8..dc8dd0de5c0 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -2,8 +2,6 @@ # Makefile for the linux kernel. # -obj-$(CONFIG_ARM_GIC) += gic.o -obj-$(CONFIG_ARM_VIC) += vic.o obj-$(CONFIG_ICST) += icst.o obj-$(CONFIG_SA1111) += sa1111.o obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig index b175577d7ab..1ea959019fc 100644 --- a/arch/arm/configs/at91_dt_defconfig +++ b/arch/arm/configs/at91_dt_defconfig @@ -19,6 +19,7 @@ CONFIG_SOC_AT91SAM9260=y CONFIG_SOC_AT91SAM9263=y CONFIG_SOC_AT91SAM9G45=y CONFIG_SOC_AT91SAM9X5=y +CONFIG_SOC_AT91SAM9N12=y CONFIG_MACH_AT91SAM_DT=y CONFIG_AT91_PROGRAMMABLE_CLOCKS=y CONFIG_AT91_TIMER_HZ=128 @@ -31,7 +32,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_ARM_APPENDED_DTB=y CONFIG_ARM_ATAG_DTB_COMPAT=y -CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw" +CONFIG_CMDLINE="console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw" CONFIG_KEXEC=y CONFIG_AUTO_ZRELADDR=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 69667133321..6dddbf877b0 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -32,7 +32,6 @@ CONFIG_MACH_PCM043=y CONFIG_MACH_MX35_3DS=y CONFIG_MACH_VPR200=y CONFIG_MACH_IMX51_DT=y -CONFIG_MACH_MX51_3DS=y CONFIG_MACH_EUKREA_CPUIMX51SD=y CONFIG_SOC_IMX53=y CONFIG_SOC_IMX6Q=y diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h index 15cb035309f..18c88302333 100644 --- a/arch/arm/include/asm/mach/irq.h +++ b/arch/arm/include/asm/mach/irq.h @@ -22,6 +22,7 @@ extern int show_fiq_list(struct seq_file *, int); #ifdef CONFIG_MULTI_IRQ_HANDLER extern void (*handle_arch_irq)(struct pt_regs *); +extern void set_handle_irq(void (*handle_irq)(struct pt_regs *)); #endif /* diff --git a/arch/arm/include/debug/imx.S b/arch/arm/include/debug/imx.S index 0c4e17d4d35..c6f294cf18f 100644 --- a/arch/arm/include/debug/imx.S +++ b/arch/arm/include/debug/imx.S @@ -34,7 +34,7 @@ #define UART_PADDR 0x43f90000 #elif defined (CONFIG_DEBUG_IMX51_UART) #define UART_PADDR 0x73fbc000 -#elif defined (CONFIG_DEBUG_IMX50_IMX53_UART) +#elif defined (CONFIG_DEBUG_IMX53_UART) #define UART_PADDR 0x53fbc000 #elif defined (CONFIG_DEBUG_IMX6Q_UART) #define UART_PADDR IMX6Q_DEBUG_UART_BASE diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S index 6809200c31f..14f7c3b1463 100644 --- a/arch/arm/kernel/debug.S +++ b/arch/arm/kernel/debug.S @@ -100,12 +100,14 @@ ENTRY(printch) b 1b ENDPROC(printch) +#ifdef CONFIG_MMU ENTRY(debug_ll_addr) addruart r2, r3, ip str r2, [r0] str r3, [r1] mov pc, lr ENDPROC(debug_ll_addr) +#endif #else diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 4eee351f466..486a15ae901 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -246,6 +246,7 @@ __create_page_tables: /* * Then map boot params address in r2 if specified. + * We map 2 sections in case the ATAGs/DTB crosses a section boundary. */ mov r0, r2, lsr #SECTION_SHIFT movs r0, r0, lsl #SECTION_SHIFT @@ -253,6 +254,8 @@ __create_page_tables: addne r3, r3, #PAGE_OFFSET addne r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER) orrne r6, r7, r0 + strne r6, [r3], #1 << PMD_ORDER + addne r6, r6, #1 << SECTION_SHIFT strne r6, [r3] #ifdef CONFIG_DEBUG_LL @@ -331,7 +334,7 @@ ENTRY(secondary_startup) * as it has already been validated by the primary processor. */ #ifdef CONFIG_ARM_VIRT_EXT - bl __hyp_stub_install + bl __hyp_stub_install_secondary #endif safe_svcmode_maskall r9 diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S index 65b2417aebc..1315c4ccfa5 100644 --- a/arch/arm/kernel/hyp-stub.S +++ b/arch/arm/kernel/hyp-stub.S @@ -99,7 +99,7 @@ ENTRY(__hyp_stub_install_secondary) * immediately. */ compare_cpu_mode_with_primary r4, r5, r6, r7 - bxne lr + movne pc, lr /* * Once we have given up on one CPU, we do not try to install the @@ -111,7 +111,7 @@ ENTRY(__hyp_stub_install_secondary) */ cmp r4, #HYP_MODE - bxne lr @ give up if the CPU is not in HYP mode + movne pc, lr @ give up if the CPU is not in HYP mode /* * Configure HSCTLR to set correct exception endianness/instruction set @@ -120,7 +120,8 @@ ENTRY(__hyp_stub_install_secondary) * Eventually, CPU-specific code might be needed -- assume not for now * * This code relies on the "eret" instruction to synchronize the - * various coprocessor accesses. + * various coprocessor accesses. This is done when we switch to SVC + * (see safe_svcmode_maskall). */ @ Now install the hypervisor stub: adr r7, __hyp_stub_vectors @@ -155,14 +156,7 @@ THUMB( orr r7, #(1 << 30) ) @ HSCTLR.TE 1: #endif - bic r7, r4, #MODE_MASK - orr r7, r7, #SVC_MODE -THUMB( orr r7, r7, #PSR_T_BIT ) - msr spsr_cxsf, r7 @ This is SPSR_hyp. - - __MSR_ELR_HYP(14) @ msr elr_hyp, lr - __ERET @ return, switching to SVC mode - @ The boot CPU mode is left in r4. + bx lr @ The boot CPU mode is left in r4. ENDPROC(__hyp_stub_install_secondary) __hyp_stub_do_trap: @@ -200,7 +194,7 @@ ENDPROC(__hyp_get_vectors) @ fall through ENTRY(__hyp_set_vectors) __HVC(0) - bx lr + mov pc, lr ENDPROC(__hyp_set_vectors) #ifndef ZIMAGE diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 896165096d6..8e4ef4c83a7 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -117,6 +117,16 @@ void __init init_IRQ(void) machine_desc->init_irq(); } +#ifdef CONFIG_MULTI_IRQ_HANDLER +void __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) +{ + if (handle_arch_irq) + return; + + handle_arch_irq = handle_irq; +} +#endif + #ifdef CONFIG_SPARSE_IRQ int __init arch_probe_nr_irqs(void) { diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 84f4cbf652e..3fc96db2a4b 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -416,7 +416,8 @@ static void (*smp_cross_call)(const struct cpumask *, unsigned int); void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int)) { - smp_cross_call = fn; + if (!smp_cross_call) + smp_cross_call = fn; } void arch_send_call_function_ipi_mask(const struct cpumask *mask) diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 49f335d301b..dc9bb014666 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -24,7 +24,6 @@ #include <asm/smp_twd.h> #include <asm/localtimer.h> -#include <asm/hardware/gic.h> /* set up by the platform code */ static void __iomem *twd_base; diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c index 180b3024bec..2acdff4c1df 100644 --- a/arch/arm/mach-at91/at91rm9200_time.c +++ b/arch/arm/mach-at91/at91rm9200_time.c @@ -174,7 +174,6 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev) static struct clock_event_device clkevt = { .name = "at91_tick", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .rating = 150, .set_next_event = clkevt32k_next_event, .set_mode = clkevt32k_mode, @@ -265,11 +264,9 @@ void __init at91rm9200_timer_init(void) at91_st_write(AT91_ST_RTMR, 1); /* Setup timer clockevent, with minimum of two ticks (important!!) */ - clkevt.mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, clkevt.shift); - clkevt.max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, &clkevt); - clkevt.min_delta_ns = clockevent_delta2ns(2, &clkevt) + 1; clkevt.cpumask = cpumask_of(0); - clockevents_register_device(&clkevt); + clockevents_config_and_register(&clkevt, AT91_SLOW_CLOCK, + 2, AT91_ST_ALMV); /* register clocksource */ clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK); diff --git a/arch/arm/mach-at91/include/mach/uncompress.h b/arch/arm/mach-at91/include/mach/uncompress.h index 97ad68a826f..5659f7c7212 100644 --- a/arch/arm/mach-at91/include/mach/uncompress.h +++ b/arch/arm/mach-at91/include/mach/uncompress.h @@ -196,6 +196,4 @@ static inline void flush(void) barrier(); } -#define arch_decomp_wdog() - #endif diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 9ee866ce047..4b678478cf9 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -105,6 +105,8 @@ static void __init soc_detect(u32 dbgu_base) switch (socid) { case ARCH_ID_AT91RM9200: at91_soc_initdata.type = AT91_SOC_RM9200; + if (at91_soc_initdata.subtype == AT91_SOC_SUBTYPE_NONE) + at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA; at91_boot_soc = at91rm9200_soc; break; diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 48705c10a0f..bf02471d7e7 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -7,7 +7,6 @@ config ARCH_BCM select ARM_GIC select CPU_V7 select GENERIC_CLOCKEVENTS - select GENERIC_GPIO select GENERIC_TIME select GPIO_BCM select SPARSE_IRQ diff --git a/arch/arm/mach-bcm/board_bcm.c b/arch/arm/mach-bcm/board_bcm.c index 3df68030cf6..f0f9abafad2 100644 --- a/arch/arm/mach-bcm/board_bcm.c +++ b/arch/arm/mach-bcm/board_bcm.c @@ -11,30 +11,19 @@ * GNU General Public License for more details. */ -#include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/init.h> #include <linux/device.h> #include <linux/platform_device.h> +#include <linux/irqchip.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> - #include <asm/mach/time.h> -static const struct of_device_id irq_match[] = { - {.compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - {} -}; - static void timer_init(void) { } -static void __init init_irq(void) -{ - of_irq_init(irq_match); -} static void __init board_init(void) { @@ -45,9 +34,8 @@ static void __init board_init(void) static const char * const bcm11351_dt_compat[] = { "bcm,bcm11351", NULL, }; DT_MACHINE_START(BCM11351_DT, "Broadcom Application Processor") - .init_irq = init_irq, + .init_irq = irqchip_init, .init_time = timer_init, .init_machine = board_init, .dt_compat = bcm11351_dt_compat, - .handle_irq = gic_handle_irq, MACHINE_END diff --git a/arch/arm/mach-bcm2835/bcm2835.c b/arch/arm/mach-bcm2835/bcm2835.c index 176d2d24782..d615a61e902 100644 --- a/arch/arm/mach-bcm2835/bcm2835.c +++ b/arch/arm/mach-bcm2835/bcm2835.c @@ -17,8 +17,8 @@ #include <linux/irqchip/bcm2835.h> #include <linux/of_address.h> #include <linux/of_platform.h> -#include <linux/bcm2835_timer.h> #include <linux/clk/bcm2835.h> +#include <linux/clocksource.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -104,7 +104,7 @@ DT_MACHINE_START(BCM2835, "BCM2835") .init_irq = bcm2835_init_irq, .handle_irq = bcm2835_handle_irq, .init_machine = bcm2835_init, - .init_time = bcm2835_timer_init, + .init_time = clocksource_of_init, .restart = bcm2835_restart, .dt_compat = bcm2835_compat MACHINE_END diff --git a/arch/arm/mach-bcm2835/include/mach/uncompress.h b/arch/arm/mach-bcm2835/include/mach/uncompress.h index cc46dcc7237..bf86dca3bf7 100644 --- a/arch/arm/mach-bcm2835/include/mach/uncompress.h +++ b/arch/arm/mach-bcm2835/include/mach/uncompress.h @@ -42,4 +42,3 @@ static inline void flush(void) } #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-clps711x/include/mach/uncompress.h b/arch/arm/mach-clps711x/include/mach/uncompress.h index 7b28d6a4769..5f02d06dc65 100644 --- a/arch/arm/mach-clps711x/include/mach/uncompress.h +++ b/arch/arm/mach-clps711x/include/mach/uncompress.h @@ -53,5 +53,3 @@ static inline void flush(void) * nothing to do */ #define arch_decomp_setup() - -#define arch_decomp_wdog() diff --git a/arch/arm/mach-cns3xxx/cns3420vb.c b/arch/arm/mach-cns3xxx/cns3420vb.c index 3c86f910b64..a71867e1d8d 100644 --- a/arch/arm/mach-cns3xxx/cns3420vb.c +++ b/arch/arm/mach-cns3xxx/cns3420vb.c @@ -28,7 +28,6 @@ #include <linux/usb/ohci_pdriver.h> #include <asm/setup.h> #include <asm/mach-types.h> -#include <asm/hardware/gic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/time.h> @@ -251,7 +250,6 @@ MACHINE_START(CNS3420VB, "Cavium Networks CNS3420 Validation Board") .map_io = cns3420_map_io, .init_irq = cns3xxx_init_irq, .init_time = cns3xxx_timer_init, - .handle_irq = gic_handle_irq, .init_machine = cns3420_init, .restart = cns3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c index 1754f8f4f34..e698f26cc0c 100644 --- a/arch/arm/mach-cns3xxx/core.c +++ b/arch/arm/mach-cns3xxx/core.c @@ -12,10 +12,10 @@ #include <linux/interrupt.h> #include <linux/clockchips.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <asm/mach/map.h> #include <asm/mach/time.h> #include <asm/mach/irq.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <mach/cns3xxx.h> #include "core.h" @@ -134,7 +134,6 @@ static int cns3xxx_timer_set_next_event(unsigned long evt, static struct clock_event_device cns3xxx_tmr1_clockevent = { .name = "cns3xxx timer1", - .shift = 8, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_mode = cns3xxx_timer_set_mode, .set_next_event = cns3xxx_timer_set_next_event, @@ -145,15 +144,9 @@ static struct clock_event_device cns3xxx_tmr1_clockevent = { static void __init cns3xxx_clockevents_init(unsigned int timer_irq) { cns3xxx_tmr1_clockevent.irq = timer_irq; - cns3xxx_tmr1_clockevent.mult = - div_sc((cns3xxx_cpu_clock() >> 3) * 1000000, NSEC_PER_SEC, - cns3xxx_tmr1_clockevent.shift); - cns3xxx_tmr1_clockevent.max_delta_ns = - clockevent_delta2ns(0xffffffff, &cns3xxx_tmr1_clockevent); - cns3xxx_tmr1_clockevent.min_delta_ns = - clockevent_delta2ns(0xf, &cns3xxx_tmr1_clockevent); - - clockevents_register_device(&cns3xxx_tmr1_clockevent); + clockevents_config_and_register(&cns3xxx_tmr1_clockevent, + (cns3xxx_cpu_clock() >> 3) * 1000000, + 0xf, 0xffffffff); } /* diff --git a/arch/arm/mach-cns3xxx/include/mach/uncompress.h b/arch/arm/mach-cns3xxx/include/mach/uncompress.h index a91b6058ab4..7a030b99df8 100644 --- a/arch/arm/mach-cns3xxx/include/mach/uncompress.h +++ b/arch/arm/mach-cns3xxx/include/mach/uncompress.h @@ -51,4 +51,3 @@ static inline void flush(void) * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h index 3a0ff905a69..f49c2916aa3 100644 --- a/arch/arm/mach-davinci/include/mach/uncompress.h +++ b/arch/arm/mach-davinci/include/mach/uncompress.h @@ -101,4 +101,3 @@ static inline void __arch_decomp_setup(unsigned long arch_id) } #define arch_decomp_setup() __arch_decomp_setup(arch_id) -#define arch_decomp_wdog() diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c index 0c7911b3e15..ea84c535a11 100644 --- a/arch/arm/mach-dove/common.c +++ b/arch/arm/mach-dove/common.c @@ -8,35 +8,24 @@ * warranty of any kind, whether express or implied. */ -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/pci.h> #include <linux/clk-provider.h> #include <linux/clk/mvebu.h> -#include <linux/ata_platform.h> -#include <linux/gpio.h> +#include <linux/dma-mapping.h> +#include <linux/init.h> #include <linux/of.h> #include <linux/of_platform.h> -#include <asm/page.h> -#include <asm/setup.h> -#include <asm/timex.h> +#include <linux/platform_data/dma-mv_xor.h> +#include <linux/platform_data/usb-ehci-orion.h> +#include <linux/platform_device.h> #include <asm/hardware/cache-tauros2.h> +#include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/time.h> -#include <asm/mach/pci.h> -#include <mach/dove.h> -#include <mach/pm.h> #include <mach/bridge-regs.h> -#include <asm/mach/arch.h> -#include <linux/irq.h> -#include <plat/time.h> -#include <linux/platform_data/usb-ehci-orion.h> -#include <linux/platform_data/dma-mv_xor.h> -#include <plat/irq.h> +#include <mach/pm.h> #include <plat/common.h> -#include <plat/addr-map.h> +#include <plat/irq.h> +#include <plat/time.h> #include "common.h" /***************************************************************************** diff --git a/arch/arm/mach-dove/include/mach/uncompress.h b/arch/arm/mach-dove/include/mach/uncompress.h index 2c5cdd7a3ee..5c8ae9b9d39 100644 --- a/arch/arm/mach-dove/include/mach/uncompress.h +++ b/arch/arm/mach-dove/include/mach/uncompress.h @@ -34,4 +34,3 @@ static void flush(void) * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-ebsa110/include/mach/uncompress.h b/arch/arm/mach-ebsa110/include/mach/uncompress.h index 32041509fbf..ab64bea69c7 100644 --- a/arch/arm/mach-ebsa110/include/mach/uncompress.h +++ b/arch/arm/mach-ebsa110/include/mach/uncompress.h @@ -42,4 +42,3 @@ static inline void flush(void) * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c index 82d9c788535..bda6c3a5c92 100644 --- a/arch/arm/mach-ep93xx/adssphere.c +++ b/arch/arm/mach-ep93xx/adssphere.c @@ -17,7 +17,6 @@ #include <mach/hardware.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -39,7 +38,6 @@ MACHINE_START(ADSSPHERE, "ADS Sphere board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = adssphere_init_machine, .init_late = ep93xx_init_late, diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index ee27b4b0ab0..c49ed3dc1ae 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -34,6 +34,7 @@ #include <linux/i2c-gpio.h> #include <linux/spi/spi.h> #include <linux/export.h> +#include <linux/irqchip/arm-vic.h> #include <mach/hardware.h> #include <linux/platform_data/video-ep93xx.h> @@ -44,8 +45,6 @@ #include <asm/mach/map.h> #include <asm/mach/time.h> -#include <asm/hardware/vic.h> - #include "soc.h" /************************************************************************* diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c index ac260519c9e..27b14ae92c7 100644 --- a/arch/arm/mach-ep93xx/edb93xx.c +++ b/arch/arm/mach-ep93xx/edb93xx.c @@ -39,7 +39,6 @@ #include <linux/platform_data/spi-ep93xx.h> #include <mach/gpio-ep93xx.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -276,7 +275,6 @@ MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, @@ -290,7 +288,6 @@ MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, @@ -304,7 +301,6 @@ MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, @@ -318,7 +314,6 @@ MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, @@ -332,7 +327,6 @@ MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, @@ -346,7 +340,6 @@ MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, @@ -360,7 +353,6 @@ MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, @@ -374,7 +366,6 @@ MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c index 76c50f42bd7..0cca5b18330 100644 --- a/arch/arm/mach-ep93xx/gesbc9312.c +++ b/arch/arm/mach-ep93xx/gesbc9312.c @@ -17,7 +17,6 @@ #include <mach/hardware.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -39,7 +38,6 @@ MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = gesbc9312_init_machine, .init_late = ep93xx_init_late, diff --git a/arch/arm/mach-ep93xx/include/mach/uncompress.h b/arch/arm/mach-ep93xx/include/mach/uncompress.h index d64274fc576..d2afb4dd82a 100644 --- a/arch/arm/mach-ep93xx/include/mach/uncompress.h +++ b/arch/arm/mach-ep93xx/include/mach/uncompress.h @@ -86,5 +86,3 @@ static void arch_decomp_setup(void) { ethernet_reset(); } - -#define arch_decomp_wdog() diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c index 777cd2170f8..373583c2982 100644 --- a/arch/arm/mach-ep93xx/micro9.c +++ b/arch/arm/mach-ep93xx/micro9.c @@ -18,7 +18,6 @@ #include <mach/hardware.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -82,7 +81,6 @@ MACHINE_START(MICRO9, "Contec Micro9-High") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = micro9_init_machine, .init_late = ep93xx_init_late, @@ -96,7 +94,6 @@ MACHINE_START(MICRO9M, "Contec Micro9-Mid") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = micro9_init_machine, .init_late = ep93xx_init_late, @@ -110,7 +107,6 @@ MACHINE_START(MICRO9L, "Contec Micro9-Lite") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = micro9_init_machine, .init_late = ep93xx_init_late, @@ -124,7 +120,6 @@ MACHINE_START(MICRO9S, "Contec Micro9-Slim") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = micro9_init_machine, .init_late = ep93xx_init_late, diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c index 6ff39ee2ad5..36f22c1a31f 100644 --- a/arch/arm/mach-ep93xx/simone.c +++ b/arch/arm/mach-ep93xx/simone.c @@ -25,7 +25,6 @@ #include <linux/platform_data/video-ep93xx.h> #include <mach/gpio-ep93xx.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -83,7 +82,6 @@ MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = simone_init_machine, .init_late = ep93xx_init_late, diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c index 6434c07dbf9..aa86f86638d 100644 --- a/arch/arm/mach-ep93xx/snappercl15.c +++ b/arch/arm/mach-ep93xx/snappercl15.c @@ -31,7 +31,6 @@ #include <linux/platform_data/video-ep93xx.h> #include <mach/gpio-ep93xx.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -176,7 +175,6 @@ MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = snappercl15_init_machine, .init_late = ep93xx_init_late, diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index e4fa0d3760a..61f4b5dc4d7 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c @@ -22,7 +22,6 @@ #include <mach/hardware.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/map.h> #include <asm/mach/arch.h> @@ -246,7 +245,6 @@ MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC") .atag_offset = 0x100, .map_io = ts72xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = ts72xx_init_machine, .init_late = ep93xx_init_late, diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c index 8610ba29399..605956fd07a 100644 --- a/arch/arm/mach-ep93xx/vision_ep9307.c +++ b/arch/arm/mach-ep93xx/vision_ep9307.c @@ -34,7 +34,6 @@ #include <linux/platform_data/spi-ep93xx.h> #include <mach/gpio-ep93xx.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/map.h> #include <asm/mach/arch.h> @@ -364,7 +363,6 @@ MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307") .atag_offset = 0x100, .map_io = vision_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, .init_time = ep93xx_timer_init, .init_machine = vision_init_machine, .init_late = ep93xx_init_late, diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 1a89824a5f7..9ce3e54a77c 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -22,12 +22,13 @@ #include <linux/of_irq.h> #include <linux/export.h> #include <linux/irqdomain.h> +#include <linux/irqchip.h> #include <linux/of_address.h> +#include <linux/irqchip/arm-gic.h> #include <asm/proc-fns.h> #include <asm/exception.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> #include <asm/cacheflush.h> @@ -35,7 +36,6 @@ #include <mach/regs-irq.h> #include <mach/regs-pmu.h> #include <mach/regs-gpio.h> -#include <mach/pmu.h> #include <plat/cpu.h> #include <plat/clock.h> @@ -644,8 +644,6 @@ static int __init combiner_of_init(struct device_node *np, } static const struct of_device_id exynos_dt_irq_match[] = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - { .compatible = "arm,cortex-a15-gic", .data = gic_of_init, }, { .compatible = "samsung,exynos4210-combiner", .data = combiner_of_init, }, {}, @@ -661,8 +659,10 @@ void __init exynos4_init_irq(void) if (!of_have_populated_dt()) gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset, NULL); #ifdef CONFIG_OF - else + else { + irqchip_init(); of_irq_init(exynos_dt_irq_match); + } #endif if (!of_have_populated_dt()) @@ -679,6 +679,7 @@ void __init exynos4_init_irq(void) void __init exynos5_init_irq(void) { #ifdef CONFIG_OF + irqchip_init(); of_irq_init(exynos_dt_irq_match); #endif /* diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 12f2f1117e9..feefc86293c 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -64,4 +64,24 @@ extern struct smp_operations exynos_smp_ops; extern void exynos_cpu_die(unsigned int cpu); +/* PMU(Power Management Unit) support */ + +#define PMU_TABLE_END NULL + +enum sys_powerdown { + SYS_AFTR, + SYS_LPA, + SYS_SLEEP, + NUM_SYS_POWERDOWN, +}; + +extern unsigned long l2x0_regs_phys; +struct exynos_pmu_conf { + void __iomem *reg; + unsigned int val[NUM_SYS_POWERDOWN]; +}; + +extern void exynos_sys_powerdown_conf(enum sys_powerdown mode); +extern void s3c_cpu_resume(void); + #endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */ diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 05092415277..fcfe0251aa3 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -23,10 +23,11 @@ #include <asm/cpuidle.h> #include <mach/regs-clock.h> #include <mach/regs-pmu.h> -#include <mach/pmu.h> #include <plat/cpu.h> +#include "common.h" + #define REG_DIRECTGO_ADDR (samsung_rev() == EXYNOS4210_REV_1_1 ? \ S5P_INFORM7 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \ (S5P_VA_SYSRAM + 0x24) : S5P_INFORM0)) diff --git a/arch/arm/mach-exynos/dev-audio.c b/arch/arm/mach-exynos/dev-audio.c index 9d1a60951d7..c662c89794b 100644 --- a/arch/arm/mach-exynos/dev-audio.c +++ b/arch/arm/mach-exynos/dev-audio.c @@ -21,7 +21,8 @@ #include <mach/map.h> #include <mach/dma.h> #include <mach/irqs.h> -#include <mach/regs-audss.h> + +#define EXYNOS4_AUDSS_INT_MEM (0x03000000) static int exynos4_cfg_i2s(struct platform_device *pdev) { diff --git a/arch/arm/mach-exynos/include/mach/pmu.h b/arch/arm/mach-exynos/include/mach/pmu.h deleted file mode 100644 index 7c27c2d4bf4..00000000000 --- a/arch/arm/mach-exynos/include/mach/pmu.h +++ /dev/null @@ -1,34 +0,0 @@ -/* linux/arch/arm/mach-exynos4/include/mach/pmu.h - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * EXYNOS4210 - PMU(Power Management Unit) support - * - * 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. -*/ - -#ifndef __ASM_ARCH_PMU_H -#define __ASM_ARCH_PMU_H __FILE__ - -#define PMU_TABLE_END NULL - -enum sys_powerdown { - SYS_AFTR, - SYS_LPA, - SYS_SLEEP, - NUM_SYS_POWERDOWN, -}; - -extern unsigned long l2x0_regs_phys; -struct exynos_pmu_conf { - void __iomem *reg; - unsigned int val[NUM_SYS_POWERDOWN]; -}; - -extern void exynos_sys_powerdown_conf(enum sys_powerdown mode); -extern void s3c_cpu_resume(void); - -#endif /* __ASM_ARCH_PMU_H */ diff --git a/arch/arm/mach-exynos/include/mach/regs-audss.h b/arch/arm/mach-exynos/include/mach/regs-audss.h deleted file mode 100644 index ca5a8b64218..00000000000 --- a/arch/arm/mach-exynos/include/mach/regs-audss.h +++ /dev/null @@ -1,18 +0,0 @@ -/* arch/arm/mach-exynos4/include/mach/regs-audss.h - * - * Copyright (c) 2011 Samsung Electronics - * http://www.samsung.com - * - * Exynos4 Audio SubSystem clock register definitions - * - * 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. -*/ - -#ifndef __PLAT_REGS_AUDSS_H -#define __PLAT_REGS_AUDSS_H __FILE__ - -#define EXYNOS4_AUDSS_INT_MEM (0x03000000) - -#endif /* _PLAT_REGS_AUDSS_H */ diff --git a/arch/arm/mach-exynos/include/mach/regs-irq.h b/arch/arm/mach-exynos/include/mach/regs-irq.h index 9c7b4bfd546..f2b50506b9f 100644 --- a/arch/arm/mach-exynos/include/mach/regs-irq.h +++ b/arch/arm/mach-exynos/include/mach/regs-irq.h @@ -13,7 +13,7 @@ #ifndef __ASM_ARCH_REGS_IRQ_H #define __ASM_ARCH_REGS_IRQ_H __FILE__ -#include <asm/hardware/gic.h> +#include <linux/irqchip/arm-gic.h> #include <mach/map.h> #endif /* __ASM_ARCH_REGS_IRQ_H */ diff --git a/arch/arm/mach-exynos/mach-armlex4210.c b/arch/arm/mach-exynos/mach-armlex4210.c index 2f18130d0d1..685f29173af 100644 --- a/arch/arm/mach-exynos/mach-armlex4210.c +++ b/arch/arm/mach-exynos/mach-armlex4210.c @@ -16,7 +16,6 @@ #include <linux/smsc911x.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <plat/cpu.h> @@ -201,7 +200,6 @@ MACHINE_START(ARMLEX4210, "ARMLEX4210") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = armlex4210_map_io, - .handle_irq = gic_handle_irq, .init_machine = armlex4210_machine_init, .init_late = exynos_init_late, .init_time = exynos4_timer_init, diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c index 160030168b1..112d10e53d2 100644 --- a/arch/arm/mach-exynos/mach-exynos4-dt.c +++ b/arch/arm/mach-exynos/mach-exynos4-dt.c @@ -15,7 +15,6 @@ #include <linux/serial_core.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <mach/map.h> #include <plat/cpu.h> @@ -107,7 +106,6 @@ DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = exynos4_dt_map_io, - .handle_irq = gic_handle_irq, .init_machine = exynos4_dt_machine_init, .init_late = exynos_init_late, .init_time = exynos4_timer_init, diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c index 4e074c67cc8..0deeecffa3a 100644 --- a/arch/arm/mach-exynos/mach-exynos5-dt.c +++ b/arch/arm/mach-exynos/mach-exynos5-dt.c @@ -16,7 +16,6 @@ #include <linux/io.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <mach/map.h> #include <mach/regs-pmu.h> @@ -179,7 +178,6 @@ DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)") .init_irq = exynos5_init_irq, .smp = smp_ops(exynos_smp_ops), .map_io = exynos5_dt_map_io, - .handle_irq = gic_handle_irq, .init_machine = exynos5_dt_machine_init, .init_late = exynos_init_late, .init_time = exynos4_timer_init, diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c index dccd1d16b83..b8b3fbf0bae 100644 --- a/arch/arm/mach-exynos/mach-nuri.c +++ b/arch/arm/mach-exynos/mach-nuri.c @@ -39,7 +39,6 @@ #include <media/v4l2-mediabus.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <plat/adc.h> @@ -1379,7 +1378,6 @@ MACHINE_START(NURI, "NURI") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = nuri_map_io, - .handle_irq = gic_handle_irq, .init_machine = nuri_machine_init, .init_late = exynos_init_late, .init_time = exynos4_timer_init, diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index 4e115632456..579d2d171da 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -29,7 +29,6 @@ #include <linux/platform_data/usb-exynos.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <video/platform_lcd.h> @@ -814,7 +813,6 @@ MACHINE_START(ORIGEN, "ORIGEN") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = origen_map_io, - .handle_irq = gic_handle_irq, .init_machine = origen_machine_init, .init_late = exynos_init_late, .init_time = exynos4_timer_init, diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c index e9c9c2995f0..fe6149624b8 100644 --- a/arch/arm/mach-exynos/mach-smdk4x12.c +++ b/arch/arm/mach-exynos/mach-smdk4x12.c @@ -25,7 +25,6 @@ #include <linux/platform_data/s3c-hsotg.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <video/samsung_fimd.h> @@ -376,7 +375,6 @@ MACHINE_START(SMDK4212, "SMDK4212") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = smdk4x12_map_io, - .handle_irq = gic_handle_irq, .init_machine = smdk4x12_machine_init, .init_time = exynos4_timer_init, .restart = exynos4_restart, @@ -390,7 +388,6 @@ MACHINE_START(SMDK4412, "SMDK4412") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = smdk4x12_map_io, - .handle_irq = gic_handle_irq, .init_machine = smdk4x12_machine_init, .init_late = exynos_init_late, .init_time = exynos4_timer_init, diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c index b228ab9bda0..d71672922b1 100644 --- a/arch/arm/mach-exynos/mach-smdkv310.c +++ b/arch/arm/mach-exynos/mach-smdkv310.c @@ -26,7 +26,6 @@ #include <linux/platform_data/usb-exynos.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <video/platform_lcd.h> @@ -423,7 +422,6 @@ MACHINE_START(SMDKV310, "SMDKV310") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = smdkv310_map_io, - .handle_irq = gic_handle_irq, .init_machine = smdkv310_machine_init, .init_time = exynos4_timer_init, .reserve = &smdkv310_reserve, @@ -436,7 +434,6 @@ MACHINE_START(SMDKC210, "SMDKC210") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = smdkv310_map_io, - .handle_irq = gic_handle_irq, .init_machine = smdkv310_machine_init, .init_late = exynos_init_late, .init_time = exynos4_timer_init, diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c index 866f29a9bee..c9d33a43103 100644 --- a/arch/arm/mach-exynos/mach-universal_c210.c +++ b/arch/arm/mach-exynos/mach-universal_c210.c @@ -29,7 +29,6 @@ #include <drm/exynos_drm.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <video/samsung_fimd.h> @@ -1151,7 +1150,6 @@ MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = universal_map_io, - .handle_irq = gic_handle_irq, .init_machine = universal_machine_init, .init_late = exynos_init_late, .init_time = s5p_timer_init, diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c index 4a89b54fcad..c9d6650f9b5 100644 --- a/arch/arm/mach-exynos/mct.c +++ b/arch/arm/mach-exynos/mct.c @@ -22,7 +22,6 @@ #include <linux/of.h> #include <asm/arch_timer.h> -#include <asm/hardware/gic.h> #include <asm/localtimer.h> #include <plat/cpu.h> @@ -255,13 +254,9 @@ static struct irqaction mct_comp_event_irq = { static void exynos4_clockevent_init(void) { - clockevents_calc_mult_shift(&mct_comp_device, clk_rate, 5); - mct_comp_device.max_delta_ns = - clockevent_delta2ns(0xffffffff, &mct_comp_device); - mct_comp_device.min_delta_ns = - clockevent_delta2ns(0xf, &mct_comp_device); mct_comp_device.cpumask = cpumask_of(0); - clockevents_register_device(&mct_comp_device); + clockevents_config_and_register(&mct_comp_device, clk_rate, + 0xf, 0xffffffff); if (soc_is_exynos5250()) setup_irq(EXYNOS5_IRQ_MCT_G0, &mct_comp_event_irq); @@ -404,14 +399,8 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt) evt->set_mode = exynos4_tick_set_mode; evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; evt->rating = 450; - - clockevents_calc_mult_shift(evt, clk_rate / (TICK_BASE_CNT + 1), 5); - evt->max_delta_ns = - clockevent_delta2ns(0x7fffffff, evt); - evt->min_delta_ns = - clockevent_delta2ns(0xf, evt); - - clockevents_register_device(evt); + clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1), + 0xf, 0x7fffffff); exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET); diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index c5c840e947b..60f7c5be057 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -20,9 +20,9 @@ #include <linux/jiffies.h> #include <linux/smp.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <asm/cacheflush.h> -#include <asm/hardware/gic.h> #include <asm/smp_plat.h> #include <asm/smp_scu.h> @@ -149,7 +149,7 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct __raw_writel(virt_to_phys(exynos4_secondary_startup), cpu_boot_reg(phys_cpu)); - gic_raise_softirq(cpumask_of(cpu), 0); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); if (pen_release == -1) break; @@ -190,8 +190,6 @@ static void __init exynos_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index b9b539cac81..f459afda822 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -34,7 +34,8 @@ #include <mach/regs-clock.h> #include <mach/regs-pmu.h> #include <mach/pm-core.h> -#include <mach/pmu.h> + +#include "common.h" static struct sleep_save exynos4_set_clksrc[] = { { .reg = EXYNOS4_CLKSRC_MASK_TOP , .val = 0x00000001, }, diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c index 3a48c852be6..daebc1abc96 100644 --- a/arch/arm/mach-exynos/pmu.c +++ b/arch/arm/mach-exynos/pmu.c @@ -14,7 +14,8 @@ #include <linux/bug.h> #include <mach/regs-clock.h> -#include <mach/pmu.h> + +#include "common.h" static struct exynos_pmu_conf *exynos_pmu_config; diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index 9f14b1d9a0e..9ee78f7b499 100644 --- a/arch/arm/mach-footbridge/dc21285-timer.c +++ b/arch/arm/mach-footbridge/dc21285-timer.c @@ -101,10 +101,6 @@ void __init footbridge_timer_init(void) setup_irq(ce->irq, &footbridge_timer_irq); - clockevents_calc_mult_shift(ce, mem_fclk_21285, 5); - ce->max_delta_ns = clockevent_delta2ns(0xffffff, ce); - ce->min_delta_ns = clockevent_delta2ns(0x000004, ce); ce->cpumask = cpumask_of(smp_processor_id()); - - clockevents_register_device(ce); + clockevents_config_and_register(ce, mem_fclk_21285, 0x4, 0xffffff); } diff --git a/arch/arm/mach-footbridge/include/mach/uncompress.h b/arch/arm/mach-footbridge/include/mach/uncompress.h index 5dfa4428734..a69398c05a5 100644 --- a/arch/arm/mach-footbridge/include/mach/uncompress.h +++ b/arch/arm/mach-footbridge/include/mach/uncompress.h @@ -35,4 +35,3 @@ static inline void flush(void) * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-gemini/include/mach/uncompress.h b/arch/arm/mach-gemini/include/mach/uncompress.h index 0efa2624723..02e225673ac 100644 --- a/arch/arm/mach-gemini/include/mach/uncompress.h +++ b/arch/arm/mach-gemini/include/mach/uncompress.h @@ -39,6 +39,4 @@ static inline void flush(void) */ #define arch_decomp_setup() -#define arch_decomp_wdog() - #endif /* __MACH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-h720x/include/mach/uncompress.h b/arch/arm/mach-h720x/include/mach/uncompress.h index d6623234f61..43e343c4b50 100644 --- a/arch/arm/mach-h720x/include/mach/uncompress.h +++ b/arch/arm/mach-h720x/include/mach/uncompress.h @@ -32,6 +32,5 @@ static inline void flush(void) * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() #endif diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index 41e254cac1a..fd630bccbd3 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c @@ -18,6 +18,7 @@ #include <linux/dma-mapping.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/irqchip.h> #include <linux/irqdomain.h> #include <linux/of.h> #include <linux/of_irq.h> @@ -32,7 +33,6 @@ #include <asm/smp_twd.h> #include <asm/hardware/arm_timer.h> #include <asm/hardware/timer-sp.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -66,12 +66,6 @@ void highbank_set_cpu_jump(int cpu, void *jump_addr) HB_JUMP_TABLE_PHYS(cpu) + 15); } -const static struct of_device_id irq_match[] = { - { .compatible = "arm,cortex-a15-gic", .data = gic_of_init, }, - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - {} -}; - #ifdef CONFIG_CACHE_L2X0 static void highbank_l2x0_disable(void) { @@ -82,7 +76,7 @@ static void highbank_l2x0_disable(void) static void __init highbank_init_irq(void) { - of_irq_init(irq_match); + irqchip_init(); if (of_find_compatible_node(NULL, NULL, "arm,cortex-a9")) highbank_scu_map_io(); @@ -206,7 +200,6 @@ DT_MACHINE_START(HIGHBANK, "Highbank") .map_io = debug_ll_io_init, .init_irq = highbank_init_irq, .init_time = highbank_timer_init, - .handle_irq = gic_handle_irq, .init_machine = highbank_init, .dt_compat = highbank_match, .restart = highbank_restart, diff --git a/arch/arm/mach-highbank/platsmp.c b/arch/arm/mach-highbank/platsmp.c index 4ecc864ac8b..8797a700172 100644 --- a/arch/arm/mach-highbank/platsmp.c +++ b/arch/arm/mach-highbank/platsmp.c @@ -17,9 +17,9 @@ #include <linux/init.h> #include <linux/smp.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <asm/smp_scu.h> -#include <asm/hardware/gic.h> #include "core.h" @@ -33,7 +33,7 @@ static void __cpuinit highbank_secondary_init(unsigned int cpu) static int __cpuinit highbank_boot_secondary(unsigned int cpu, struct task_struct *idle) { highbank_set_cpu_jump(cpu, secondary_startup); - gic_raise_softirq(cpumask_of(cpu), 0); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); return 0; } @@ -56,8 +56,6 @@ static void __init highbank_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init highbank_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 3e628fd7a67..7b11d3329e8 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -95,9 +95,6 @@ config MACH_MX27 config ARCH_MX5 bool -config ARCH_MX50 - bool - config ARCH_MX51 bool @@ -164,11 +161,6 @@ config SOC_IMX5 select CPU_V7 select MXC_TZIC -config SOC_IMX50 - bool - select ARCH_MX50 - select SOC_IMX5 - config SOC_IMX51 bool select ARCH_MX5 @@ -738,25 +730,10 @@ endif if ARCH_MULTI_V7 -comment "i.MX5 platforms:" - -config MACH_MX50_RDP - bool "Support MX50 reference design platform" - depends on BROKEN - select IMX_HAVE_PLATFORM_IMX_I2C - select IMX_HAVE_PLATFORM_IMX_UART - select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select IMX_HAVE_PLATFORM_SPI_IMX - select SOC_IMX50 - help - Include support for MX50 reference design platform (RDP) board. This - includes specific configurations for the board and its peripherals. - comment "i.MX51 machines:" config MACH_IMX51_DT bool "Support i.MX51 platforms from device tree" - select MACH_MX51_BABBAGE select SOC_IMX51 help Include support for Freescale i.MX51 based platforms @@ -777,19 +754,6 @@ config MACH_MX51_BABBAGE u-boot. This includes specific configurations for the board and its peripherals. -config MACH_MX51_3DS - bool "Support MX51PDK (3DS)" - select IMX_HAVE_PLATFORM_IMX2_WDT - select IMX_HAVE_PLATFORM_IMX_KEYPAD - select IMX_HAVE_PLATFORM_IMX_UART - select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select IMX_HAVE_PLATFORM_SPI_IMX - select MXC_DEBUG_BOARD - select SOC_IMX51 - help - Include support for MX51PDK (3DS) platform. This includes specific - configurations for the board and its peripherals. - config MACH_EUKREA_CPUIMX51SD bool "Support Eukrea CPUIMX51SD module" select IMX_HAVE_PLATFORM_FSL_USB2_UDC @@ -851,6 +815,7 @@ config SOC_IMX6Q select HAVE_CAN_FLEXCAN if CAN select HAVE_IMX_GPC select HAVE_IMX_MMDC + select HAVE_IMX_SRC select HAVE_SMP select MFD_SYSCON select PINCTRL diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 0634b3152c2..240e0294c37 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -88,7 +88,6 @@ obj-$(CONFIG_MACH_EUKREA_CPUIMX35SD) += mach-cpuimx35.o obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o -obj-$(CONFIG_DEBUG_LL) += lluart.o obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o obj-$(CONFIG_HAVE_IMX_SRC) += src.o @@ -103,10 +102,8 @@ endif # i.MX5 based machines obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o -obj-$(CONFIG_MACH_MX51_3DS) += mach-mx51_3ds.o obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += mach-cpuimx51sd.o obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd51-baseboard.o -obj-$(CONFIG_MACH_MX50_RDP) += mach-mx50_rdp.o obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o obj-$(CONFIG_SOC_IMX53) += mach-imx53.o diff --git a/arch/arm/mach-imx/Makefile.boot b/arch/arm/mach-imx/Makefile.boot index b27815de847..41ba1bb0437 100644 --- a/arch/arm/mach-imx/Makefile.boot +++ b/arch/arm/mach-imx/Makefile.boot @@ -22,10 +22,6 @@ zreladdr-$(CONFIG_SOC_IMX35) += 0x80008000 params_phys-$(CONFIG_SOC_IMX35) := 0x80000100 initrd_phys-$(CONFIG_SOC_IMX35) := 0x80800000 -zreladdr-$(CONFIG_SOC_IMX50) += 0x70008000 -params_phys-$(CONFIG_SOC_IMX50) := 0x70000100 -initrd_phys-$(CONFIG_SOC_IMX50) := 0x70800000 - zreladdr-$(CONFIG_SOC_IMX51) += 0x90008000 params_phys-$(CONFIG_SOC_IMX51) := 0x90000100 initrd_phys-$(CONFIG_SOC_IMX51) := 0x90800000 diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c index b197aa73dc4..2c570cdaae7 100644 --- a/arch/arm/mach-imx/clk-imx25.c +++ b/arch/arm/mach-imx/clk-imx25.c @@ -254,9 +254,9 @@ int __init mx25_clocks_init(void) clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2"); clk_register_clkdev(clk[usbotg_ahb], "ahb", "mxc-ehci.2"); clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2"); - clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc"); - clk_register_clkdev(clk[usbotg_ahb], "ahb", "fsl-usb2-udc"); - clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc"); + clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27"); + clk_register_clkdev(clk[usbotg_ahb], "ahb", "imx-udc-mx27"); + clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27"); clk_register_clkdev(clk[nfc_ipg_per], NULL, "imx25-nand.0"); /* i.mx25 has the i.mx35 type cspi */ clk_register_clkdev(clk[cspi1_ipg], NULL, "imx35-cspi.0"); diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c index 4c1d1e4efc7..1ffe3b534e5 100644 --- a/arch/arm/mach-imx/clk-imx27.c +++ b/arch/arm/mach-imx/clk-imx27.c @@ -236,9 +236,9 @@ int __init mx27_clocks_init(unsigned long fref) clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx21-fb.0"); clk_register_clkdev(clk[csi_ahb_gate], "ahb", "imx27-camera.0"); clk_register_clkdev(clk[per4_gate], "per", "imx27-camera.0"); - clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc"); - clk_register_clkdev(clk[usb_ipg_gate], "ipg", "fsl-usb2-udc"); - clk_register_clkdev(clk[usb_ahb_gate], "ahb", "fsl-usb2-udc"); + clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27"); + clk_register_clkdev(clk[usb_ipg_gate], "ipg", "imx-udc-mx27"); + clk_register_clkdev(clk[usb_ahb_gate], "ahb", "imx-udc-mx27"); clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0"); clk_register_clkdev(clk[usb_ipg_gate], "ipg", "mxc-ehci.0"); clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.0"); diff --git a/arch/arm/mach-imx/clk-imx31.c b/arch/arm/mach-imx/clk-imx31.c index 8be64e0a4ac..16ccbd41dea 100644 --- a/arch/arm/mach-imx/clk-imx31.c +++ b/arch/arm/mach-imx/clk-imx31.c @@ -139,9 +139,9 @@ int __init mx31_clocks_init(unsigned long fref) clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.2"); clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.2"); clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2"); - clk_register_clkdev(clk[usb_div_post], "per", "fsl-usb2-udc"); - clk_register_clkdev(clk[usb_gate], "ahb", "fsl-usb2-udc"); - clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc"); + clk_register_clkdev(clk[usb_div_post], "per", "imx-udc-mx27"); + clk_register_clkdev(clk[usb_gate], "ahb", "imx-udc-mx27"); + clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27"); clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0"); /* i.mx31 has the i.mx21 type uart */ clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0"); diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c index 66f3d65ea27..f0727e80815 100644 --- a/arch/arm/mach-imx/clk-imx35.c +++ b/arch/arm/mach-imx/clk-imx35.c @@ -251,9 +251,9 @@ int __init mx35_clocks_init() clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2"); clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2"); clk_register_clkdev(clk[usbotg_gate], "ahb", "mxc-ehci.2"); - clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc"); - clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc"); - clk_register_clkdev(clk[usbotg_gate], "ahb", "fsl-usb2-udc"); + clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27"); + clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27"); + clk_register_clkdev(clk[usbotg_gate], "ahb", "imx-udc-mx27"); clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0"); clk_register_clkdev(clk[nfc_div], NULL, "imx25-nand.0"); clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0"); diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c index 579023f59dc..fb7cb841b64 100644 --- a/arch/arm/mach-imx/clk-imx51-imx53.c +++ b/arch/arm/mach-imx/clk-imx51-imx53.c @@ -269,9 +269,9 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, clk_register_clkdev(clk[usboh3_per_gate], "per", "mxc-ehci.2"); clk_register_clkdev(clk[usboh3_gate], "ipg", "mxc-ehci.2"); clk_register_clkdev(clk[usboh3_gate], "ahb", "mxc-ehci.2"); - clk_register_clkdev(clk[usboh3_per_gate], "per", "fsl-usb2-udc"); - clk_register_clkdev(clk[usboh3_gate], "ipg", "fsl-usb2-udc"); - clk_register_clkdev(clk[usboh3_gate], "ahb", "fsl-usb2-udc"); + clk_register_clkdev(clk[usboh3_per_gate], "per", "imx-udc-mx51"); + clk_register_clkdev(clk[usboh3_gate], "ipg", "imx-udc-mx51"); + clk_register_clkdev(clk[usboh3_gate], "ahb", "imx-udc-mx51"); clk_register_clkdev(clk[nfc_gate], NULL, "imx51-nand"); clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0"); clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1"); diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 7f2c10c7413..19644f6524d 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -56,8 +56,6 @@ static void __iomem *ccm_base; -void __init imx6q_clock_map_io(void) { } - int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) { u32 val = readl_relaxed(ccm_base + CLPCR); @@ -436,6 +434,9 @@ int __init mx6q_clocks_init(void) for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) clk_prepare_enable(clk[clks_init_on[i]]); + /* Set initial power mode */ + imx6q_set_lpm(WAIT_CLOCKED); + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"); base = of_iomap(np, 0); WARN_ON(!base); diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 7191ab4434e..76c42004328 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -21,7 +21,6 @@ extern void mx25_map_io(void); extern void mx27_map_io(void); extern void mx31_map_io(void); extern void mx35_map_io(void); -extern void mx50_map_io(void); extern void mx51_map_io(void); extern void mx53_map_io(void); extern void imx1_init_early(void); @@ -30,7 +29,6 @@ extern void imx25_init_early(void); extern void imx27_init_early(void); extern void imx31_init_early(void); extern void imx35_init_early(void); -extern void imx50_init_early(void); extern void imx51_init_early(void); extern void imx53_init_early(void); extern void mxc_init_irq(void __iomem *); @@ -41,7 +39,6 @@ extern void mx25_init_irq(void); extern void mx27_init_irq(void); extern void mx31_init_irq(void); extern void mx35_init_irq(void); -extern void mx50_init_irq(void); extern void mx51_init_irq(void); extern void mx53_init_irq(void); extern void imx1_soc_init(void); @@ -50,7 +47,6 @@ extern void imx25_soc_init(void); extern void imx27_soc_init(void); extern void imx31_soc_init(void); extern void imx35_soc_init(void); -extern void imx50_soc_init(void); extern void imx51_soc_init(void); extern void imx51_init_late(void); extern void imx53_init_late(void); @@ -109,18 +105,11 @@ void tzic_handle_irq(struct pt_regs *); #define imx27_handle_irq avic_handle_irq #define imx31_handle_irq avic_handle_irq #define imx35_handle_irq avic_handle_irq -#define imx50_handle_irq tzic_handle_irq #define imx51_handle_irq tzic_handle_irq #define imx53_handle_irq tzic_handle_irq -#define imx6q_handle_irq gic_handle_irq extern void imx_enable_cpu(int cpu, bool enable); extern void imx_set_cpu_jump(int cpu, void *jump_addr); -#ifdef CONFIG_DEBUG_LL -extern void imx_lluart_map_io(void); -#else -static inline void imx_lluart_map_io(void) {} -#endif extern void v7_cpu_resume(void); extern u32 *pl310_get_save_ptr(void); #ifdef CONFIG_SMP @@ -139,9 +128,9 @@ extern void imx_gpc_init(void); extern void imx_gpc_pre_suspend(void); extern void imx_gpc_post_resume(void); extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); -extern void imx6q_clock_map_io(void); extern void imx_cpu_die(unsigned int cpu); +extern int imx_cpu_kill(unsigned int cpu); #ifdef CONFIG_PM extern void imx6q_pm_init(void); diff --git a/arch/arm/mach-imx/cpu-imx5.c b/arch/arm/mach-imx/cpu-imx5.c index d88760014ff..d7ce72252a4 100644 --- a/arch/arm/mach-imx/cpu-imx5.c +++ b/arch/arm/mach-imx/cpu-imx5.c @@ -22,7 +22,6 @@ static int mx5_cpu_rev = -1; #define IIM_SREV 0x24 -#define MX50_HW_ADADIG_DIGPROG 0xB0 static int get_mx51_srev(void) { @@ -108,41 +107,3 @@ int mx53_revision(void) return mx5_cpu_rev; } EXPORT_SYMBOL(mx53_revision); - -static int get_mx50_srev(void) -{ - void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K); - u32 rev; - - if (!anatop) { - mx5_cpu_rev = -EINVAL; - return 0; - } - - rev = readl(anatop + MX50_HW_ADADIG_DIGPROG); - rev &= 0xff; - - iounmap(anatop); - if (rev == 0x0) - return IMX_CHIP_REVISION_1_0; - else if (rev == 0x1) - return IMX_CHIP_REVISION_1_1; - return 0; -} - -/* - * Returns: - * the silicon revision of the cpu - * -EINVAL - not a mx50 - */ -int mx50_revision(void) -{ - if (!cpu_is_mx50()) - return -EINVAL; - - if (mx5_cpu_rev == -1) - mx5_cpu_rev = get_mx50_srev(); - - return mx5_cpu_rev; -} -EXPORT_SYMBOL(mx50_revision); diff --git a/arch/arm/mach-imx/devices-imx50.h b/arch/arm/mach-imx/devices-imx50.h deleted file mode 100644 index 2c290391f29..00000000000 --- a/arch/arm/mach-imx/devices-imx50.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -/* - * 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. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "devices/devices-common.h" - -extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[]; -#define imx50_add_imx_uart(id, pdata) \ - imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata) - -extern const struct imx_fec_data imx50_fec_data; -#define imx50_add_fec(pdata) \ - imx_add_fec(&imx50_fec_data, pdata) - -extern const struct imx_imx_i2c_data imx50_imx_i2c_data[]; -#define imx50_add_imx_i2c(id, pdata) \ - imx_add_imx_i2c(&imx50_imx_i2c_data[id], pdata) diff --git a/arch/arm/mach-imx/devices/Kconfig b/arch/arm/mach-imx/devices/Kconfig index 9a8f1ca7bcb..9b9ba1f4ffe 100644 --- a/arch/arm/mach-imx/devices/Kconfig +++ b/arch/arm/mach-imx/devices/Kconfig @@ -1,6 +1,6 @@ config IMX_HAVE_PLATFORM_FEC bool - default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX50 || SOC_IMX51 || SOC_IMX53 + default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53 config IMX_HAVE_PLATFORM_FLEXCAN bool diff --git a/arch/arm/mach-imx/devices/devices-common.h b/arch/arm/mach-imx/devices/devices-common.h index 6277baf1b7b..9bd5777ff0e 100644 --- a/arch/arm/mach-imx/devices/devices-common.h +++ b/arch/arm/mach-imx/devices/devices-common.h @@ -63,6 +63,7 @@ struct platform_device *__init imx_add_flexcan( #include <linux/fsl_devices.h> struct imx_fsl_usb2_udc_data { + const char *devid; resource_size_t iobase; resource_size_t irq; }; diff --git a/arch/arm/mach-imx/devices/platform-fec.c b/arch/arm/mach-imx/devices/platform-fec.c index 2cb188ad9a0..63eba08f87b 100644 --- a/arch/arm/mach-imx/devices/platform-fec.c +++ b/arch/arm/mach-imx/devices/platform-fec.c @@ -35,12 +35,6 @@ const struct imx_fec_data imx35_fec_data __initconst = imx_fec_data_entry_single(MX35, "imx27-fec"); #endif -#ifdef CONFIG_SOC_IMX50 -/* i.mx50 has the i.mx25 type fec */ -const struct imx_fec_data imx50_fec_data __initconst = - imx_fec_data_entry_single(MX50, "imx25-fec"); -#endif - #ifdef CONFIG_SOC_IMX51 /* i.mx51 has the i.mx27 type fec */ const struct imx_fec_data imx51_fec_data __initconst = diff --git a/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c b/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c index 37e44398197..3c06bd96e9c 100644 --- a/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c +++ b/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c @@ -11,35 +11,36 @@ #include "../hardware.h" #include "devices-common.h" -#define imx_fsl_usb2_udc_data_entry_single(soc) \ +#define imx_fsl_usb2_udc_data_entry_single(soc, _devid) \ { \ + .devid = _devid, \ .iobase = soc ## _USB_OTG_BASE_ADDR, \ .irq = soc ## _INT_USB_OTG, \ } #ifdef CONFIG_SOC_IMX25 const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data __initconst = - imx_fsl_usb2_udc_data_entry_single(MX25); + imx_fsl_usb2_udc_data_entry_single(MX25, "imx-udc-mx27"); #endif /* ifdef CONFIG_SOC_IMX25 */ #ifdef CONFIG_SOC_IMX27 const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data __initconst = - imx_fsl_usb2_udc_data_entry_single(MX27); + imx_fsl_usb2_udc_data_entry_single(MX27, "imx-udc-mx27"); #endif /* ifdef CONFIG_SOC_IMX27 */ #ifdef CONFIG_SOC_IMX31 const struct imx_fsl_usb2_udc_data imx31_fsl_usb2_udc_data __initconst = - imx_fsl_usb2_udc_data_entry_single(MX31); + imx_fsl_usb2_udc_data_entry_single(MX31, "imx-udc-mx27"); #endif /* ifdef CONFIG_SOC_IMX31 */ #ifdef CONFIG_SOC_IMX35 const struct imx_fsl_usb2_udc_data imx35_fsl_usb2_udc_data __initconst = - imx_fsl_usb2_udc_data_entry_single(MX35); + imx_fsl_usb2_udc_data_entry_single(MX35, "imx-udc-mx27"); #endif /* ifdef CONFIG_SOC_IMX35 */ #ifdef CONFIG_SOC_IMX51 const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data __initconst = - imx_fsl_usb2_udc_data_entry_single(MX51); + imx_fsl_usb2_udc_data_entry_single(MX51, "imx-udc-mx51"); #endif struct platform_device *__init imx_add_fsl_usb2_udc( @@ -57,7 +58,7 @@ struct platform_device *__init imx_add_fsl_usb2_udc( .flags = IORESOURCE_IRQ, }, }; - return imx_add_platform_device_dmamask("fsl-usb2-udc", -1, + return imx_add_platform_device_dmamask(data->devid, -1, res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32)); } diff --git a/arch/arm/mach-imx/devices/platform-imx-fb.c b/arch/arm/mach-imx/devices/platform-imx-fb.c index 10b0ed39f07..25a47c616b2 100644 --- a/arch/arm/mach-imx/devices/platform-imx-fb.c +++ b/arch/arm/mach-imx/devices/platform-imx-fb.c @@ -54,7 +54,7 @@ struct platform_device *__init imx_add_imx_fb( .flags = IORESOURCE_IRQ, }, }; - return imx_add_platform_device_dmamask("imx-fb", 0, + return imx_add_platform_device_dmamask(data->devid, 0, res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32)); } diff --git a/arch/arm/mach-imx/devices/platform-imx-i2c.c b/arch/arm/mach-imx/devices/platform-imx-i2c.c index 8e30e5703cd..57d342e85c2 100644 --- a/arch/arm/mach-imx/devices/platform-imx-i2c.c +++ b/arch/arm/mach-imx/devices/platform-imx-i2c.c @@ -70,16 +70,6 @@ const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst = { }; #endif /* ifdef CONFIG_SOC_IMX35 */ -#ifdef CONFIG_SOC_IMX50 -const struct imx_imx_i2c_data imx50_imx_i2c_data[] __initconst = { -#define imx50_imx_i2c_data_entry(_id, _hwid) \ - imx_imx_i2c_data_entry(MX50, "imx21-i2c", _id, _hwid, SZ_4K) - imx50_imx_i2c_data_entry(0, 1), - imx50_imx_i2c_data_entry(1, 2), - imx50_imx_i2c_data_entry(2, 3), -}; -#endif /* ifdef CONFIG_SOC_IMX51 */ - #ifdef CONFIG_SOC_IMX51 const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = { #define imx51_imx_i2c_data_entry(_id, _hwid) \ diff --git a/arch/arm/mach-imx/devices/platform-imx-uart.c b/arch/arm/mach-imx/devices/platform-imx-uart.c index 67bf866a2cb..faac4aa6ca6 100644 --- a/arch/arm/mach-imx/devices/platform-imx-uart.c +++ b/arch/arm/mach-imx/devices/platform-imx-uart.c @@ -94,18 +94,6 @@ const struct imx_imx_uart_1irq_data imx35_imx_uart_data[] __initconst = { }; #endif /* ifdef CONFIG_SOC_IMX35 */ -#ifdef CONFIG_SOC_IMX50 -const struct imx_imx_uart_1irq_data imx50_imx_uart_data[] __initconst = { -#define imx50_imx_uart_data_entry(_id, _hwid) \ - imx_imx_uart_1irq_data_entry(MX50, _id, _hwid, SZ_4K) - imx50_imx_uart_data_entry(0, 1), - imx50_imx_uart_data_entry(1, 2), - imx50_imx_uart_data_entry(2, 3), - imx50_imx_uart_data_entry(3, 4), - imx50_imx_uart_data_entry(4, 5), -}; -#endif /* ifdef CONFIG_SOC_IMX50 */ - #ifdef CONFIG_SOC_IMX51 const struct imx_imx_uart_1irq_data imx51_imx_uart_data[] __initconst = { #define imx51_imx_uart_data_entry(_id, _hwid) \ diff --git a/arch/arm/mach-imx/epit.c b/arch/arm/mach-imx/epit.c index 04a5961beea..e02de188ae8 100644 --- a/arch/arm/mach-imx/epit.c +++ b/arch/arm/mach-imx/epit.c @@ -178,7 +178,6 @@ static struct irqaction epit_timer_irq = { static struct clock_event_device clockevent_epit = { .name = "epit", .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .set_mode = epit_set_mode, .set_next_event = epit_set_next_event, .rating = 200, @@ -186,18 +185,10 @@ static struct clock_event_device clockevent_epit = { static int __init epit_clockevent_init(struct clk *timer_clk) { - unsigned int c = clk_get_rate(timer_clk); - - clockevent_epit.mult = div_sc(c, NSEC_PER_SEC, - clockevent_epit.shift); - clockevent_epit.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &clockevent_epit); - clockevent_epit.min_delta_ns = - clockevent_delta2ns(0x800, &clockevent_epit); - clockevent_epit.cpumask = cpumask_of(0); - - clockevents_register_device(&clockevent_epit); + clockevents_config_and_register(&clockevent_epit, + clk_get_rate(timer_clk), + 0x800, 0xfffffffe); return 0; } diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index e1537f9e45b..ff24920699e 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -15,7 +15,7 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> -#include <asm/hardware/gic.h> +#include <linux/irqchip/arm-gic.h> #define GPC_IMR1 0x008 #define GPC_PGC_CPU_PDN 0x2a0 diff --git a/arch/arm/mach-imx/hardware.h b/arch/arm/mach-imx/hardware.h index 3ce7fa3bd43..911e9b31b03 100644 --- a/arch/arm/mach-imx/hardware.h +++ b/arch/arm/mach-imx/hardware.h @@ -72,11 +72,6 @@ * AVIC 0x68000000+0x100000 -> 0xf5800000+0x100000 * X_MEMC 0xb8000000+0x010000 -> 0xf5c00000+0x010000 * SPBA0 0x50000000+0x100000 -> 0xf5400000+0x100000 - * mx50: - * TZIC 0x0fffc000+0x004000 -> 0xf4bfc000+0x004000 - * AIPS1 0x53f00000+0x100000 -> 0xf5700000+0x100000 - * SPBA0 0x50000000+0x100000 -> 0xf5400000+0x100000 - * AIPS2 0x63f00000+0x100000 -> 0xf5300000+0x100000 * mx51: * TZIC 0x0fffc000+0x004000 -> 0xf4bfc000+0x004000 * IRAM 0x1ffe0000+0x020000 -> 0xf4fe0000+0x020000 @@ -108,7 +103,6 @@ #include "mxc.h" #include "mx6q.h" -#include "mx50.h" #include "mx51.h" #include "mx53.h" #include "mx3x.h" diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c index 3dec962b077..7bc5fe15dda 100644 --- a/arch/arm/mach-imx/hotplug.c +++ b/arch/arm/mach-imx/hotplug.c @@ -46,9 +46,11 @@ static inline void cpu_enter_lowpower(void) void imx_cpu_die(unsigned int cpu) { cpu_enter_lowpower(); - imx_enable_cpu(cpu, false); + cpu_do_idle(); +} - /* spin here until hardware takes it down */ - while (1) - ; +int imx_cpu_kill(unsigned int cpu) +{ + imx_enable_cpu(cpu, false); + return 1; } diff --git a/arch/arm/mach-imx/imx31-dt.c b/arch/arm/mach-imx/imx31-dt.c index f9a69096009..b5c04eece78 100644 --- a/arch/arm/mach-imx/imx31-dt.c +++ b/arch/arm/mach-imx/imx31-dt.c @@ -43,12 +43,17 @@ static const char *imx31_dt_board_compat[] __initdata = { NULL }; +static void __init imx31_dt_timer_init(void) +{ + mx31_clocks_init_dt(); +} + DT_MACHINE_START(IMX31_DT, "Freescale i.MX31 (Device Tree Support)") .map_io = mx31_map_io, .init_early = imx31_init_early, .init_irq = mx31_init_irq, .handle_irq = imx31_handle_irq, - .init_time = mx31_clocks_init_dt, + .init_time = imx31_dt_timer_init, .init_machine = imx31_dt_init, .dt_compat = imx31_dt_board_compat, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/iomux-mx50.h b/arch/arm/mach-imx/iomux-mx50.h deleted file mode 100644 index 00f56e0e800..00000000000 --- a/arch/arm/mach-imx/iomux-mx50.h +++ /dev/null @@ -1,977 +0,0 @@ -/* - * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. - * - * 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. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef __MACH_IOMUX_MX50_H__ -#define __MACH_IOMUX_MX50_H__ - -#include "iomux-v3.h" - -#define MX50_ELCDIF_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_DSE_HIGH) - -#define MX50_SD_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \ - PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_HIGH) - -#define MX50_UART_PAD_CTRL (PAD_CTL_DSE_HIGH | PAD_CTL_PKE) - -#define MX50_I2C_PAD_CTRL (PAD_CTL_ODE | PAD_CTL_DSE_HIGH | \ - PAD_CTL_PUS_100K_UP | PAD_CTL_HYS) - -#define MX50_USB_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ - PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP) - -#define MX50_FEC_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \ - PAD_CTL_PUS_22K_UP | PAD_CTL_ODE | \ - PAD_CTL_DSE_HIGH) - -#define MX50_OWIRE_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \ - PAD_CTL_PUS_100K_UP | PAD_CTL_ODE | \ - PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST) - -#define MX50_KEYPAD_CTRL (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \ - PAD_CTL_PUS_100K_UP | PAD_CTL_DSE_HIGH) - -#define MX50_CSPI_SS_PAD (PAD_CTL_PKE | PAD_CTL_PUE | \ - PAD_CTL_PUS_22K_UP | PAD_CTL_DSE_HIGH) - -#define MX50_PAD_KEY_COL0__KEY_COL0 IOMUX_PAD(0x2CC, 0x20, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_KEY_COL0__GPIO_4_0 IOMUX_PAD(0x2CC, 0x20, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_KEY_COL0__NANDF_CLE IOMUX_PAD(0x2CC, 0x20, 2, 0x0, 0, PAD_CTL_DSE_HIGH) - -#define MX50_PAD_KEY_ROW0__KEY_ROW0 IOMUX_PAD(0x2D0, 0x24, 0, 0x0, 0, MX50_KEYPAD_CTRL) -#define MX50_PAD_KEY_ROW0__GPIO_4_1 IOMUX_PAD(0x2D0, 0x24, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_KEY_ROW0__NANDF_ALE IOMUX_PAD(0x2D0, 0x24, 2, 0x0, 0, PAD_CTL_DSE_HIGH) - -#define MX50_PAD_KEY_COL1__KEY_COL1 IOMUX_PAD(0x2D4, 0x28, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_KEY_COL1__GPIO_4_2 IOMUX_PAD(0x2D4, 0x28, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_KEY_COL1__NANDF_CE0 IOMUX_PAD(0x2D4, 0x28, 2, 0x0, 0, PAD_CTL_DSE_HIGH) - -#define MX50_PAD_KEY_ROW1__KEY_ROW1 IOMUX_PAD(0x2D8, 0x2C, 0, 0x0, 0, MX50_KEYPAD_CTRL) -#define MX50_PAD_KEY_ROW1__GPIO_4_3 IOMUX_PAD(0x2D8, 0x2C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_KEY_ROW1__NANDF_CE1 IOMUX_PAD(0x2D8, 0x2C, 2, 0x0, 0, PAD_CTL_DSE_HIGH) - -#define MX50_PAD_KEY_COL2__KEY_COL2 IOMUX_PAD(0x2DC, 0x30, 0, 0x0, 0, MX50_KEYPAD_CTRL) -#define MX50_PAD_KEY_COL2__GPIO_4_4 IOMUX_PAD(0x2DC, 0x30, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_KEY_COL2__NANDF_CE2 IOMUX_PAD(0x2DC, 0x30, 2, 0x0, 0, PAD_CTL_DSE_HIGH) - -#define MX50_PAD_KEY_ROW2__KEY_ROW2 IOMUX_PAD(0x2E0, 0x34, 0, 0x0, 0, MX50_KEYPAD_CTRL) -#define MX50_PAD_KEY_ROW2__GPIO_4_5 IOMUX_PAD(0x2E0, 0x34, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_KEY_ROW2__NANDF_CE3 IOMUX_PAD(0x2E0, 0x34, 2, 0x0, 0, PAD_CTL_DSE_HIGH) - -#define MX50_PAD_KEY_COL3__KEY_COL3 IOMUX_PAD(0x2E4, 0x38, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_KEY_COL3__GPIO_4_6 IOMUX_PAD(0x2E4, 0x38, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_KEY_COL3__NANDF_READY IOMUX_PAD(0x2E4, 0x38, 2, 0x7b4, 0, PAD_CTL_PKE | \ - PAD_CTL_PUE | PAD_CTL_PUS_100K_UP) -#define MX50_PAD_KEY_COL3__SDMA_EXT0 IOMUX_PAD(0x2E4, 0x38, 6, 0x7b8, 0, NO_PAD_CTRL) - -#define MX50_PAD_KEY_ROW3__KEY_ROW3 IOMUX_PAD(0x2E8, 0x3C, 0, 0x0, 0, MX50_KEYPAD_CTRL) -#define MX50_PAD_KEY_ROW3__GPIO_4_7 IOMUX_PAD(0x2E8, 0x3C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_KEY_ROW3__NANDF_DQS IOMUX_PAD(0x2E8, 0x3C, 2, 0x7b0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_KEY_ROW3__SDMA_EXT1 IOMUX_PAD(0x2E8, 0x3C, 6, 0x7bc, 0, NO_PAD_CTRL) - -#define MX50_PAD_I2C1_SCL__I2C1_SCL IOMUX_PAD(0x2EC, 0x40, IOMUX_CONFIG_SION, 0x0, 0, \ - MX50_I2C_PAD_CTRL) -#define MX50_PAD_I2C1_SCL__GPIO_6_18 IOMUX_PAD(0x2EC, 0x40, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_I2C1_SCL__UART2_TXD IOMUX_PAD(0x2EC, 0x40, 2, 0x0, 0, MX50_UART_PAD_CTRL) - -#define MX50_PAD_I2C1_SDA__I2C1_SDA IOMUX_PAD(0x2F0, 0x44, IOMUX_CONFIG_SION, 0x0, 0, \ - MX50_I2C_PAD_CTRL) -#define MX50_PAD_I2C1_SDA__GPIO_6_19 IOMUX_PAD(0x2F0, 0x44, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_I2C1_SDA__UART2_RXD IOMUX_PAD(0x2F0, 0x44, 2, 0x7cc, 1, MX50_UART_PAD_CTRL) - -#define MX50_PAD_I2C2_SCL__I2C2_SCL IOMUX_PAD(0x2F4, 0x48, IOMUX_CONFIG_SION, 0x0, 0, \ - MX50_I2C_PAD_CTRL) -#define MX50_PAD_I2C2_SCL__GPIO_6_20 IOMUX_PAD(0x2F4, 0x48, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_I2C2_SCL__UART2_CTS IOMUX_PAD(0x2F4, 0x48, 2, 0x0, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_I2C2_SCL__DCDC_OK IOMUX_PAD(0x2F4, 0x48, 7, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_I2C2_SDA__I2C2_SDA IOMUX_PAD(0x2F8, 0x4C, IOMUX_CONFIG_SION, 0x0, 0, \ - MX50_I2C_PAD_CTRL) -#define MX50_PAD_I2C2_SDA__GPIO_6_21 IOMUX_PAD(0x2F8, 0x4C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_I2C2_SDA__UART2_RTS IOMUX_PAD(0x2F8, 0x4C, 2, 0x7c8, 1, MX50_UART_PAD_CTRL) -#define MX50_PAD_I2C2_SDA__PWRSTABLE IOMUX_PAD(0x2F8, 0x4C, 7, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_I2C3_SCL__I2C3_SCL IOMUX_PAD(0x2FC, 0x50, IOMUX_CONFIG_SION, 0x0, 0, \ - MX50_I2C_PAD_CTRL) -#define MX50_PAD_I2C3_SCL__GPIO_6_22 IOMUX_PAD(0x2FC, 0x50, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_I2C3_SCL__FEC_MDC IOMUX_PAD(0x2FC, 0x50, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_I2C3_SCL__PMIC_RDY IOMUX_PAD(0x2FC, 0x50, 3, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_I2C3_SCL__GPT_CAPIN1 IOMUX_PAD(0x2FC, 0x50, 5, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_I2C3_SCL__USBOTG_OC IOMUX_PAD(0x2FC, 0x50, 7, 0x7E8, 0, MX50_USB_PAD_CTRL) - -#define MX50_PAD_I2C3_SDA__I2C3_SDA IOMUX_PAD(0x300, 0x54, IOMUX_CONFIG_SION, 0x0, 0, \ - MX50_I2C_PAD_CTRL) -#define MX50_PAD_I2C3_SDA__GPIO_6_23 IOMUX_PAD(0x300, 0x54, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_I2C3_SDA__FEC_MDIO IOMUX_PAD(0x300, 0x54, 2, 0x774, 0, MX50_FEC_PAD_CTRL) -#define MX50_PAD_I2C3_SDA__PWRFAIL_INT IOMUX_PAD(0x300, 0x54, 3, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_I2C3_SDA__ALARM_DEB IOMUX_PAD(0x300, 0x54, 4, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_I2C3_SDA__GPT_CAPIN1 IOMUX_PAD(0x300, 0x54, 5, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_I2C3_SDA__USBOTG_PWR IOMUX_PAD(0x300, 0x54, 7, 0x0, 0, \ - PAD_CTL_PKE | PAD_CTL_DSE_HIGH) - -#define MX50_PAD_PWM1__PWM1_PWMO IOMUX_PAD(0x304, 0x58, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_PWM1__GPIO_6_24 IOMUX_PAD(0x304, 0x58, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_PWM1__USBOTG_OC IOMUX_PAD(0x304, 0x58, 2, 0x7E8, 1, MX50_USB_PAD_CTRL) -#define MX50_PAD_PWM1__GPT_CMPOUT1 IOMUX_PAD(0x304, 0x58, 5, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_PWM2__PWM2_PWMO IOMUX_PAD(0x308, 0x5C, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_PWM2__GPIO_6_25 IOMUX_PAD(0x308, 0x5C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_PWM2__USBOTG_PWR IOMUX_PAD(0x308, 0x5C, 2, 0x0, 0, \ - PAD_CTL_PKE | PAD_CTL_DSE_HIGH) -#define MX50_PAD_PWM2__DCDC_PWM IOMUX_PAD(0x308, 0x5C, 4, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_PWM2__GPT_CMPOUT2 IOMUX_PAD(0x308, 0x5C, 5, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_PWM2__ANY_PU_RST IOMUX_PAD(0x308, 0x5C, 7, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_OWIRE__OWIRE IOMUX_PAD(0x30C, 0x60, 0, 0x0, 0, MX50_OWIRE_PAD_CTRL) -#define MX50_PAD_OWIRE__GPIO_6_26 IOMUX_PAD(0x30C, 0x60, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_OWIRE__USBH1_OC IOMUX_PAD(0x30C, 0x60, 2, 0x0, 0, MX50_USB_PAD_CTRL) -#define MX50_PAD_OWIRE__SSI_EXT1_CLK IOMUX_PAD(0x30C, 0x60, 3, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_OWIRE__EPDC_PWRIRQ IOMUX_PAD(0x30C, 0x60, 4, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_OWIRE__GPT_CMPOUT3 IOMUX_PAD(0x30C, 0x60, 5, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPITO__EPITO IOMUX_PAD(0x310, 0x64, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPITO__GPIO_6_27 IOMUX_PAD(0x310, 0x64, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPITO__USBH1_PWR IOMUX_PAD(0x310, 0x64, 2, 0x0, 0, \ - PAD_CTL_PKE | PAD_CTL_DSE_HIGH) -#define MX50_PAD_EPITO__SSI_EXT2_CLK IOMUX_PAD(0x310, 0x64, 3, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPITO__TOG_EN IOMUX_PAD(0x310, 0x64, 4, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPITO__GPT_CLKIN IOMUX_PAD(0x310, 0x64, 5, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_WDOG__WDOG IOMUX_PAD(0x314, 0x68, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_WDOG__GPIO_6_28 IOMUX_PAD(0x314, 0x68, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_WDOG__WDOG_RST IOMUX_PAD(0x314, 0x68, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_WDOG__XTAL32K IOMUX_PAD(0x314, 0x68, 6, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SSI_TXFS__SSI_TXFS IOMUX_PAD(0x318, 0x6C, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SSI_TXFS__GPIO_6_0 IOMUX_PAD(0x318, 0x6C, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SSI_TXC__SSI_TXC IOMUX_PAD(0x31C, 0x70, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SSI_TXC__GPIO_6_1 IOMUX_PAD(0x31C, 0x70, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SSI_TXD__SSI_TXD IOMUX_PAD(0x320, 0x74, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SSI_TXD__GPIO_6_2 IOMUX_PAD(0x320, 0x74, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SSI_TXD__CSPI_RDY IOMUX_PAD(0x320, 0x74, 4, 0x6e8, 0, NO_PAD_CTRL) - -#define MX50_PAD_SSI_RXD__SSI_RXD IOMUX_PAD(0x324, 0x78, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SSI_RXD__GPIO_6_3 IOMUX_PAD(0x324, 0x78, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SSI_RXD__CSPI_SS3 IOMUX_PAD(0x324, 0x78, 4, 0x6f4, 0, MX50_CSPI_SS_PAD) - -#define MX50_PAD_SSI_RXFS__AUD3_RXFS IOMUX_PAD(0x328, 0x7C, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SSI_RXFS__GPIO_6_4 IOMUX_PAD(0x328, 0x7C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SSI_RXFS__UART5_TXD IOMUX_PAD(0x328, 0x7C, 2, 0x0, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_SSI_RXFS__WEIM_D6 IOMUX_PAD(0x328, 0x7C, 3, 0x804, 0, NO_PAD_CTRL) -#define MX50_PAD_SSI_RXFS__CSPI_SS2 IOMUX_PAD(0x328, 0x7C, 4, 0x6f0, 0, MX50_CSPI_SS_PAD) -#define MX50_PAD_SSI_RXFS__FEC_COL IOMUX_PAD(0x328, 0x7C, 5, 0x770, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_SSI_RXFS__FEC_MDC IOMUX_PAD(0x328, 0x7C, 6, 0x0, 0, PAD_CTL_DSE_HIGH) - -#define MX50_PAD_SSI_RXC__AUD3_RXC IOMUX_PAD(0x32C, 0x80, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SSI_RXC__GPIO_6_5 IOMUX_PAD(0x32C, 0x80, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SSI_RXC__UART5_RXD IOMUX_PAD(0x32C, 0x80, 2, 0x7e4, 1, MX50_UART_PAD_CTRL) -#define MX50_PAD_SSI_RXC__WEIM_D7 IOMUX_PAD(0x32C, 0x80, 3, 0x808, 0, NO_PAD_CTRL) -#define MX50_PAD_SSI_RXC__CSPI_SS1 IOMUX_PAD(0x32C, 0x80, 4, 0x6ec, 0, MX50_CSPI_SS_PAD) -#define MX50_PAD_SSI_RXC__FEC_RX_CLK IOMUX_PAD(0x32C, 0x80, 5, 0x780, 0, NO_PAD_CTRL) -#define MX50_PAD_SSI_RXC__FEC_MDIO IOMUX_PAD(0x32C, 0x80, 6, 0x774, 1, MX50_FEC_PAD_CTRL) - -#define MX50_PAD_UART1_TXD__UART1_TXD IOMUX_PAD(0x330, 0x84, 0, 0x0, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART1_TXD__GPIO_6_6 IOMUX_PAD(0x330, 0x84, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_UART1_RXD__UART1_RXD IOMUX_PAD(0x334, 0x88, 0, 0x7c4, 1, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART1_RXD__GPIO_6_7 IOMUX_PAD(0x334, 0x88, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_UART1_CTS__UART1_CTS IOMUX_PAD(0x338, 0x8C, 0, 0x0, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART1_CTS__GPIO_6_8 IOMUX_PAD(0x338, 0x8C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_UART1_CTS__UART5_TXD IOMUX_PAD(0x338, 0x8C, 2, 0x0, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART1_CTS__SD4_D4 IOMUX_PAD(0x338, 0x8C, 4, 0x760, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART1_CTS__SD4_CMD IOMUX_PAD(0x338, 0x8C, 5, 0x74c, 0, MX50_SD_PAD_CTRL) - -#define MX50_PAD_UART1_RTS__UART1_RTS IOMUX_PAD(0x33C, 0x90, 0, 0x7c0, 1, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART1_RTS__GPIO_6_9 IOMUX_PAD(0x33C, 0x90, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_UART1_RTS__UART5_RXD IOMUX_PAD(0x33C, 0x90, 2, 0x7e4, 3, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART1_RTS__SD4_D5 IOMUX_PAD(0x33C, 0x90, 4, 0x764, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART1_RTS__SD4_CLK IOMUX_PAD(0x33C, 0x90, 5, 0x748, 0, MX50_SD_PAD_CTRL) - -#define MX50_PAD_UART2_TXD__UART2_TXD IOMUX_PAD(0x340, 0x94, 0, 0x0, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART2_TXD__GPIO_6_10 IOMUX_PAD(0x340, 0x94, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_UART2_TXD__SD4_D6 IOMUX_PAD(0x340, 0x94, 4, 0x768, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART2_TXD__SD4_D4 IOMUX_PAD(0x340, 0x94, 5, 0x760, 1, MX50_SD_PAD_CTRL) - -#define MX50_PAD_UART2_RXD__UART2_RXD IOMUX_PAD(0x344, 0x98, 0, 0x7cc, 3, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART2_RXD__GPIO_6_11 IOMUX_PAD(0x344, 0x98, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_UART2_RXD__SD4_D7 IOMUX_PAD(0x344, 0x98, 4, 0x76c, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART2_RXD__SD4_D5 IOMUX_PAD(0x344, 0x98, 5, 0x764, 1, MX50_SD_PAD_CTRL) - -#define MX50_PAD_UART2_CTS__UART2_CTS IOMUX_PAD(0x348, 0x9C, 0, 0x0, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART2_CTS__GPIO_6_12 IOMUX_PAD(0x348, 0x9C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_UART2_CTS__SD4_CMD IOMUX_PAD(0x348, 0x9C, 4, 0x74c, 1, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART2_CTS__SD4_D6 IOMUX_PAD(0x348, 0x9C, 5, 0x768, 1, MX50_SD_PAD_CTRL) - -#define MX50_PAD_UART2_RTS__UART2_RTS IOMUX_PAD(0x34C, 0xA0, 0, 0x7c8, 3, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART2_RTS__GPIO_6_13 IOMUX_PAD(0x34C, 0xA0, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_UART2_RTS__SD4_CLK IOMUX_PAD(0x34C, 0xA0, 4, 0x748, 1, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART2_RTS__SD4_D7 IOMUX_PAD(0x34C, 0xA0, 5, 0x76c, 1, MX50_SD_PAD_CTRL) - -#define MX50_PAD_UART3_TXD__UART3_TXD IOMUX_PAD(0x350, 0xA4, 0, 0x0, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART3_TXD__GPIO_6_14 IOMUX_PAD(0x350, 0xA4, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_UART3_TXD__SD1_D4 IOMUX_PAD(0x350, 0xA4, 3, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART3_TXD__SD4_D0 IOMUX_PAD(0x350, 0xA4, 4, 0x750, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART3_TXD__SD2_WP IOMUX_PAD(0x350, 0xA4, 5, 0x744, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART3_TXD__WEIM_D12 IOMUX_PAD(0x350, 0xA4, 6, 0x81c, 0, NO_PAD_CTRL) - -#define MX50_PAD_UART3_RXD__UART3_RXD IOMUX_PAD(0x354, 0xA8, 0, 0x7d4, 1, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART3_RXD__GPIO_6_15 IOMUX_PAD(0x354, 0xA8, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_UART3_RXD__SD1_D5 IOMUX_PAD(0x354, 0xA8, 3, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART3_RXD__SD4_D1 IOMUX_PAD(0x354, 0xA8, 4, 0x754, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART3_RXD__SD2_CD IOMUX_PAD(0x354, 0xA8, 5, 0x740, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART3_RXD__WEIM_D13 IOMUX_PAD(0x354, 0xA8, 6, 0x820, 0, NO_PAD_CTRL) - -#define MX50_PAD_UART4_TXD__UART4_TXD IOMUX_PAD(0x358, 0xAC, 0, 0x0, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART4_TXD__GPIO_6_16 IOMUX_PAD(0x358, 0xAC, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_UART4_TXD__UART3_CTS IOMUX_PAD(0x358, 0xAC, 2, 0x0, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART4_TXD__SD1_D6 IOMUX_PAD(0x358, 0xAC, 3, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART4_TXD__SD4_D2 IOMUX_PAD(0x358, 0xAC, 4, 0x758, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART4_TXD__SD2_LCTL IOMUX_PAD(0x358, 0xAC, 5, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART4_TXD__WEIM_D14 IOMUX_PAD(0x358, 0xAC, 6, 0x824, 0, NO_PAD_CTRL) - -#define MX50_PAD_UART4_RXD__UART4_RXD IOMUX_PAD(0x35C, 0xB0, 0, 0x7dc, 1, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART4_RXD__GPIO_6_17 IOMUX_PAD(0x35C, 0xB0, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_UART4_RXD__UART3_RTS IOMUX_PAD(0x35C, 0xB0, 2, 0x7d0, 1, MX50_UART_PAD_CTRL) -#define MX50_PAD_UART4_RXD__SD1_D7 IOMUX_PAD(0x35C, 0xB0, 3, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART4_RXD__SD4_D3 IOMUX_PAD(0x35C, 0xB0, 4, 0x75c, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART4_RXD__SD1_LCTL IOMUX_PAD(0x35C, 0xB0, 5, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_UART4_RXD__WEIM_D15 IOMUX_PAD(0x35C, 0xB0, 6, 0x828, 0, NO_PAD_CTRL) - -#define MX50_PAD_CSPI_SCLK__CSPI_SCLK IOMUX_PAD(0x360, 0xB4, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_CSPI_SCLK__GPIO_4_8 IOMUX_PAD(0x360, 0xB4, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_CSPI_MOSI__CSPI_MOSI IOMUX_PAD(0x364, 0xB8, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_CSPI_MOSI__GPIO_4_9 IOMUX_PAD(0x364, 0xB8, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_CSPI_MISO__CSPI_MISO IOMUX_PAD(0x368, 0xBC, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_CSPI_MISO__GPIO_4_10 IOMUX_PAD(0x368, 0xBC, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_CSPI_SS0__CSPI_SS0 IOMUX_PAD(0x36C, 0xC0, 0, 0x0, 0, MX50_CSPI_SS_PAD) -#define MX50_PAD_CSPI_SS0__GPIO_4_11 IOMUX_PAD(0x36C, 0xC0, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_ECSPI1_SCLK__ECSPI1_SCLK IOMUX_PAD(0x370, 0xC4, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI1_SCLK__GPIO_4_12 IOMUX_PAD(0x370, 0xC4, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI1_SCLK__CSPI_RDY IOMUX_PAD(0x370, 0xC4, 2, 0x6e8, 1, NO_PAD_CTRL) -#define MX50_PAD_ECSPI1_SCLK__ECSPI2_RDY IOMUX_PAD(0x370, 0xC4, 3, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI1_SCLK__UART3_RTS IOMUX_PAD(0x370, 0xC4, 4, 0x7d0, 2, MX50_UART_PAD_CTRL) -#define MX50_PAD_ECSPI1_SCLK__EPDC_SDCE6 IOMUX_PAD(0x370, 0xC4, 5, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI1_SCLK__WEIM_D8 IOMUX_PAD(0x370, 0xC4, 7, 0x80c, 0, NO_PAD_CTRL) - -#define MX50_PAD_ECSPI1_MOSI__ECSPI1_MOSI IOMUX_PAD(0x374, 0xC8, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI1_MOSI__GPIO_4_13 IOMUX_PAD(0x374, 0xC8, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI1_MOSI__CSPI_SS1 IOMUX_PAD(0x374, 0xC8, 2, 0x6ec, 1, MX50_CSPI_SS_PAD) -#define MX50_PAD_ECSPI1_MOSI__ECSPI2_SS1 IOMUX_PAD(0x374, 0xC8, 3, 0x0, 0, MX50_CSPI_SS_PAD) -#define MX50_PAD_ECSPI1_MOSI__UART3_CTS IOMUX_PAD(0x374, 0xC8, 4, 0x0, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_ECSPI1_MOSI__EPDC_SDCE7 IOMUX_PAD(0x374, 0xC8, 5, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI1_MOSI__WEIM_D9 IOMUX_PAD(0x374, 0xC8, 7, 0x810, 0, NO_PAD_CTRL) - -#define MX50_PAD_ECSPI1_MISO__ECSPI1_MISO IOMUX_PAD(0x378, 0xCC, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI1_MISO__GPIO_4_14 IOMUX_PAD(0x378, 0xCC, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI1_MISO__CSPI_SS2 IOMUX_PAD(0x378, 0xCC, 2, 0x6f0, 1, MX50_CSPI_SS_PAD) -#define MX50_PAD_ECSPI1_MISO__ECSPI2_SS2 IOMUX_PAD(0x378, 0xCC, 3, 0x0, 0, MX50_CSPI_SS_PAD) -#define MX50_PAD_ECSPI1_MISO__UART4_RTS IOMUX_PAD(0x378, 0xCC, 4, 0x7d8, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_ECSPI1_MISO__EPDC_SDCE8 IOMUX_PAD(0x378, 0xCC, 5, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI1_MISO__WEIM_D10 IOMUX_PAD(0x378, 0xCC, 7, 0x814, 0, NO_PAD_CTRL) - -#define MX50_PAD_ECSPI1_SS0__ECSPI1_SS0 IOMUX_PAD(0x37C, 0xD0, 0, 0x0, 0, MX50_CSPI_SS_PAD) -#define MX50_PAD_ECSPI1_SS0__GPIO_4_15 IOMUX_PAD(0x37C, 0xD0, 1, 0x0, 0, PAD_CTL_PUS_100K_UP) -#define MX50_PAD_ECSPI1_SS0__CSPI_SS3 IOMUX_PAD(0x37C, 0xD0, 2, 0x6f4, 1, MX50_CSPI_SS_PAD) -#define MX50_PAD_ECSPI1_SS0__ECSPI2_SS3 IOMUX_PAD(0x37C, 0xD0, 3, 0x0, 0, MX50_CSPI_SS_PAD) -#define MX50_PAD_ECSPI1_SS0__UART4_CTS IOMUX_PAD(0x37C, 0xD0, 4, 0x0, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_ECSPI1_SS0__EPDC_SDCE9 IOMUX_PAD(0x37C, 0xD0, 5, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI1_SS0__WEIM_D11 IOMUX_PAD(0x37C, 0xD0, 7, 0x818, 0, NO_PAD_CTRL) - -#define MX50_PAD_ECSPI2_SCLK__ECSPI2_SCLK IOMUX_PAD(0x380, 0xD4, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_SCLK__GPIO_4_16 IOMUX_PAD(0x380, 0xD4, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_SCLK__ELCDIF_WR IOMUX_PAD(0x380, 0xD4, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_SCLK__ECSPI1_RDY IOMUX_PAD(0x380, 0xD4, 3, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_SCLK__UART5_RTS IOMUX_PAD(0x380, 0xD4, 4, 0x7e0, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_ECSPI2_SCLK__ELCDIF_DOTCLK IOMUX_PAD(0x380, 0xD4, 5, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_SCLK__NANDF_CEN4 IOMUX_PAD(0x380, 0xD4, 6, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_SCLK__WEIM_D8 IOMUX_PAD(0x380, 0xD4, 7, 0x80c, 1, NO_PAD_CTRL) - -#define MX50_PAD_ECSPI2_MOSI__ECSPI2_MOSI IOMUX_PAD(0x384, 0xD8, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_MOSI__GPIO_4_17 IOMUX_PAD(0x384, 0xD8, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_MOSI__ELCDIF_RD IOMUX_PAD(0x384, 0xD8, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_MOSI__ECSPI1_SS1 IOMUX_PAD(0x384, 0xD8, 3, 0x0, 0, MX50_CSPI_SS_PAD) -#define MX50_PAD_ECSPI2_MOSI__UART5_CTS IOMUX_PAD(0x384, 0xD8, 4, 0x0, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_ECSPI2_MOSI__ELCDIF_EN IOMUX_PAD(0x384, 0xD8, 5, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_MOSI__NANDF_CEN5 IOMUX_PAD(0x384, 0xD8, 6, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_MOSI__WEIM_D9 IOMUX_PAD(0x384, 0xD8, 7, 0x810, 1, NO_PAD_CTRL) - -#define MX50_PAD_ECSPI2_MISO__ECSPI2_MISO IOMUX_PAD(0x388, 0xDC, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_MISO__GPIO_4_18 IOMUX_PAD(0x388, 0xDC, 1, 0x0, 0, PAD_CTL_PUS_100K_UP) -#define MX50_PAD_ECSPI2_MISO__ELCDIF_RS IOMUX_PAD(0x388, 0xDC, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_MISO__ECSPI1_SS2 IOMUX_PAD(0x388, 0xDC, 3, 0x0, 0, MX50_CSPI_SS_PAD) -#define MX50_PAD_ECSPI2_MISO__UART5_TXD IOMUX_PAD(0x388, 0xDC, 4, 0x0, 0, MX50_UART_PAD_CTRL) -#define MX50_PAD_ECSPI2_MISO__ELCDIF_VSYNC IOMUX_PAD(0x388, 0xDC, 5, 0x73c, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_MISO__NANDF_CEN6 IOMUX_PAD(0x388, 0xDC, 6, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_MISO__WEIM_D10 IOMUX_PAD(0x388, 0xDC, 7, 0x814, 1, NO_PAD_CTRL) - -#define MX50_PAD_ECSPI2_SS0__ECSPI2_SS0 IOMUX_PAD(0x38C, 0xE0, 0, 0x0, 0, MX50_CSPI_SS_PAD) -#define MX50_PAD_ECSPI2_SS0__GPIO_4_19 IOMUX_PAD(0x38C, 0xE0, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_SS0__ELCDIF_CS IOMUX_PAD(0x38C, 0xE0, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_SS0__ECSPI1_SS3 IOMUX_PAD(0x38C, 0xE0, 3, 0x0, 0, MX50_CSPI_SS_PAD) -#define MX50_PAD_ECSPI2_SS0__UART5_RXD IOMUX_PAD(0x38C, 0xE0, 4, 0x7e4, 5, MX50_UART_PAD_CTRL) -#define MX50_PAD_ECSPI2_SS0__ELCDIF_HSYNC IOMUX_PAD(0x38C, 0xE0, 5, 0x6f8, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_SS0__NANDF_CEN7 IOMUX_PAD(0x38C, 0xE0, 6, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_ECSPI2_SS0__WEIM_D11 IOMUX_PAD(0x38C, 0xE0, 7, 0x818, 1, NO_PAD_CTRL) - -#define MX50_PAD_SD1_CLK__SD1_CLK IOMUX_PAD(0x390, 0xE4, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD1_CLK__GPIO_5_0 IOMUX_PAD(0x390, 0xE4, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD1_CLK__CLKO IOMUX_PAD(0x390, 0xE4, 7, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD1_CMD__SD1_CMD IOMUX_PAD(0x394, 0xE8, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD1_CMD__GPIO_5_1 IOMUX_PAD(0x394, 0xE8, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD1_CMD__CLKO2 IOMUX_PAD(0x394, 0xE8, 7, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD1_D0__SD1_D0 IOMUX_PAD(0x398, 0xEC, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD1_D0__GPIO_5_2 IOMUX_PAD(0x398, 0xEC, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD1_D0__PLL1_BYP IOMUX_PAD(0x398, 0xEC, 7, 0x6dc, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD1_D1__SD1_D1 IOMUX_PAD(0x39C, 0xF0, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD1_D1__GPIO_5_3 IOMUX_PAD(0x39C, 0xF0, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD1_D1__PLL2_BYP IOMUX_PAD(0x39C, 0xF0, 7, 0x6e0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD1_D2__SD1_D2 IOMUX_PAD(0x3A0, 0xF4, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD1_D2__GPIO_5_4 IOMUX_PAD(0x3A0, 0xF4, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD1_D2__PLL3_BYP IOMUX_PAD(0x3A0, 0xF4, 7, 0x6e4, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD1_D3__SD1_D3 IOMUX_PAD(0x3A4, 0xF8, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD1_D3__GPIO_5_5 IOMUX_PAD(0x3A4, 0xF8, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD2_CLK__SD2_CLK IOMUX_PAD(0x3A8, 0xFC, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_CLK__GPIO_5_6 IOMUX_PAD(0x3A8, 0xFC, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_CLK__MSHC_SCLK IOMUX_PAD(0x3A8, 0xFC, 2, 0x0, 0, MX50_SD_PAD_CTRL) - -#define MX50_PAD_SD2_CMD__SD2_CMD IOMUX_PAD(0x3AC, 0x100, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_CMD__GPIO_5_7 IOMUX_PAD(0x3AC, 0x100, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_CMD__MSHC_BS IOMUX_PAD(0x3AC, 0x100, 2, 0x0, 0, MX50_SD_PAD_CTRL) - -#define MX50_PAD_SD2_D0__SD2_D0 IOMUX_PAD(0x3B0, 0x104, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_D0__GPIO_5_8 IOMUX_PAD(0x3B0, 0x104, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D0__MSHC_D0 IOMUX_PAD(0x3B0, 0x104, 2, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_D0__KEY_COL4 IOMUX_PAD(0x3B0, 0x104, 3, 0x790, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD2_D1__SD2_D1 IOMUX_PAD(0x3B4, 0x108, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_D1__GPIO_5_9 IOMUX_PAD(0x3B4, 0x108, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D1__MSHC_D1 IOMUX_PAD(0x3B4, 0x108, 2, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_D1__KEY_ROW4 IOMUX_PAD(0x3B4, 0x108, 3, 0x7a0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD2_D2__SD2_D2 IOMUX_PAD(0x3B8, 0x10C, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_D2__GPIO_5_10 IOMUX_PAD(0x3B8, 0x10C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D2__MSHC_D2 IOMUX_PAD(0x3B8, 0x10C, 2, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_D2__KEY_COL5 IOMUX_PAD(0x3B8, 0x10C, 3, 0x794, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD2_D3__SD2_D3 IOMUX_PAD(0x3BC, 0x110, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_D3__GPIO_5_11 IOMUX_PAD(0x3BC, 0x110, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D3__MSHC_D3 IOMUX_PAD(0x3BC, 0x110, 2, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_D3__KEY_ROW5 IOMUX_PAD(0x3BC, 0x110, 3, 0x7a4, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD2_D4__SD2_D4 IOMUX_PAD(0x3C0, 0x114, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_D4__GPIO_5_12 IOMUX_PAD(0x3C0, 0x114, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D4__AUD4_RXFS IOMUX_PAD(0x3C0, 0x114, 2, 0x6d0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D4__KEY_COL6 IOMUX_PAD(0x3C0, 0x114, 3, 0x798, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D4__WEIM_D0 IOMUX_PAD(0x3C0, 0x114, 4, 0x7ec, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D4__CCM_OUT0 IOMUX_PAD(0x3C0, 0x114, 7, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD2_D5__SD2_D5 IOMUX_PAD(0x3C4, 0x118, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_D5__GPIO_5_13 IOMUX_PAD(0x3C4, 0x118, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D5__AUD4_RXC IOMUX_PAD(0x3C4, 0x118, 2, 0x6cc, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D5__KEY_ROW6 IOMUX_PAD(0x3C4, 0x118, 3, 0x7a8, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D5__WEIM_D1 IOMUX_PAD(0x3C4, 0x118, 4, 0x7f0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D5__CCM_OUT1 IOMUX_PAD(0x3C4, 0x118, 7, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD2_D6__SD2_D6 IOMUX_PAD(0x3C8, 0x11C, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_D6__GPIO_5_14 IOMUX_PAD(0x3C8, 0x11C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D6__AUD4_RXD IOMUX_PAD(0x3C8, 0x11C, 2, 0x6c4, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D6__KEY_COL7 IOMUX_PAD(0x3C8, 0x11C, 3, 0x79c, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D6__WEIM_D2 IOMUX_PAD(0x3C8, 0x11C, 4, 0x7f4, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D6__CCM_OUT2 IOMUX_PAD(0x3C8, 0x11C, 7, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD2_D7__SD2_D7 IOMUX_PAD(0x3CC, 0x120, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_D7__GPIO_5_15 IOMUX_PAD(0x3CC, 0x120, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D7__AUD4_TXFS IOMUX_PAD(0x3CC, 0x120, 2, 0x6d8, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D7__KEY_ROW7 IOMUX_PAD(0x3CC, 0x120, 3, 0x7ac, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D7__WEIM_D3 IOMUX_PAD(0x3CC, 0x120, 4, 0x7f8, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_D7__CCM_STOP IOMUX_PAD(0x3CC, 0x120, 7, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD2_WP__SD2_WP IOMUX_PAD(0x3D0, 0x124, 0, 0x744, 1, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_WP__GPIO_5_16 IOMUX_PAD(0x3D0, 0x124, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_WP__AUD4_TXD IOMUX_PAD(0x3D0, 0x124, 2, 0x6c8, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_WP__WEIM_D4 IOMUX_PAD(0x3D0, 0x124, 4, 0x7fc, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_WP__CCM_WAIT IOMUX_PAD(0x3D0, 0x124, 7, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD2_CD__SD2_CD IOMUX_PAD(0x3D4, 0x128, 0, 0x740, 1, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD2_CD__GPIO_5_17 IOMUX_PAD(0x3D4, 0x128, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_CD__AUD4_TXC IOMUX_PAD(0x3D4, 0x128, 2, 0x6d4, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_CD__WEIM_D5 IOMUX_PAD(0x3D4, 0x128, 4, 0x800, 0, NO_PAD_CTRL) -#define MX50_PAD_SD2_CD__CCM_REF_EN IOMUX_PAD(0x3D4, 0x128, 7, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_PMIC_ON_REQ__PMIC_ON_REQ IOMUX_PAD(0x3D8, 0, 0, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_PMIC_STBY_REQ__PMIC_STBY_REQ IOMUX_PAD(0x3DC, 0, 0, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_PMIC_PORT_B__PMIC_PORT_B IOMUX_PAD(0x3E0, 0, 0, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_PMIC_BOOT_MODE1__PMIC_BOOT_MODE1 IOMUX_PAD(0x3E4, 0, 0, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_PMIC_RESET_IN_B__PMIC_RESET_IN_B IOMUX_PAD(0x3E8, 0, 0, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_PMIC_BOOT_MODE0__PMIC_BOOT_MODE0 IOMUX_PAD(0x3EC, 0, 0, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_PMIC_TEST_MODE__PMIC_TEST_MODE IOMUX_PAD(0x3F0, 0, 0, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_PMIC_JTAG_TMS__PMIC_JTAG_TMS IOMUX_PAD(0x3F4, 0, 0, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_PMIC_JTAG_MOD__PMIC_JTAG_MOD IOMUX_PAD(0x3F8, 0, 0, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_PMIC_JTAG_TRSTB__PMIC_JTAG_TRSTB IOMUX_PAD(0x3FC, 0, 0, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_PMIC_JTAG_TDI__PMIC_JTAG_TDI IOMUX_PAD(0x400, 0, 0, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_PMIC_JTAG_TCK__PMIC_JTAG_TCK IOMUX_PAD(0x404, 0, 0, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_PMIC_JTAG_TDO__PMIC_JTAG_TDO IOMUX_PAD(0x408, 0, 0, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_DISP_D0__DISP_D0 IOMUX_PAD(0x40C, 0x12C, 0, 0x6fc, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D0__GPIO_2_0 IOMUX_PAD(0x40C, 0x12C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D0__FEC_TXCLK IOMUX_PAD(0x40C, 0x12C, 2, 0x78c, 0, PAD_CTL_HYS | PAD_CTL_PKE) - -#define MX50_PAD_DISP_D1__DISP_D1 IOMUX_PAD(0x410, 0x130, 0, 0x700, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D1__GPIO_2_1 IOMUX_PAD(0x410, 0x130, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D1__FEC_RX_ER IOMUX_PAD(0x410, 0x130, 2, 0x788, 0, PAD_CTL_HYS | PAD_CTL_PKE) -#define MX50_PAD_DISP_D1__WEIM_A17 IOMUX_PAD(0x410, 0x130, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_DISP_D2__DISP_D2 IOMUX_PAD(0x414, 0x134, 0, 0x704, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D2__GPIO_2_2 IOMUX_PAD(0x414, 0x134, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D2__FEC_RX_DV IOMUX_PAD(0x414, 0x134, 2, 0x784, 0, PAD_CTL_HYS | PAD_CTL_PKE) -#define MX50_PAD_DISP_D2__WEIM_A18 IOMUX_PAD(0x414, 0x134, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_DISP_D3__DISP_D3 IOMUX_PAD(0x418, 0x138, 0, 0x708, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D3__GPIO_2_3 IOMUX_PAD(0x418, 0x138, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D3__FEC_RXD1 IOMUX_PAD(0x418, 0x138, 2, 0x77C, 0, PAD_CTL_HYS | PAD_CTL_PKE) -#define MX50_PAD_DISP_D3__WEIM_A19 IOMUX_PAD(0x418, 0x138, 3, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D3__FEC_COL IOMUX_PAD(0x418, 0x138, 4, 0x770, 1, NO_PAD_CTRL) - -#define MX50_PAD_DISP_D4__DISP_D4 IOMUX_PAD(0x41C, 0x13C, 0, 0x70c, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D4__GPIO_2_4 IOMUX_PAD(0x41C, 0x13C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D4__FEC_RXD0 IOMUX_PAD(0x41C, 0x13C, 2, 0x778, 0, PAD_CTL_HYS | PAD_CTL_PKE) -#define MX50_PAD_DISP_D4__WEIM_A20 IOMUX_PAD(0x41C, 0x13C, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_DISP_D5__DISP_D5 IOMUX_PAD(0x420, 0x140, 0, 0x710, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D5__GPIO_2_5 IOMUX_PAD(0x420, 0x140, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D5__FEC_TX_EN IOMUX_PAD(0x420, 0x140, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_DISP_D5__WEIM_A21 IOMUX_PAD(0x420, 0x140, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_DISP_D6__DISP_D6 IOMUX_PAD(0x424, 0x144, 0, 0x714, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D6__GPIO_2_6 IOMUX_PAD(0x424, 0x144, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D6__FEC_TXD1 IOMUX_PAD(0x424, 0x144, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_DISP_D6__WEIM_A22 IOMUX_PAD(0x424, 0x144, 3, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D6__FEC_RX_CLK IOMUX_PAD(0x424, 0x144, 4, 0x780, 1, NO_PAD_CTRL) - -#define MX50_PAD_DISP_D7__DISP_D7 IOMUX_PAD(0x428, 0x148, 0, 0x718, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D7__GPIO_2_7 IOMUX_PAD(0x428, 0x148, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D7__FEC_TXD0 IOMUX_PAD(0x428, 0x148, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_DISP_D7__WEIM_A23 IOMUX_PAD(0x428, 0x148, 3, 0x0, 0, NO_PAD_CTRL) - - -#define MX50_PAD_DISP_WR__ELCDIF_WR IOMUX_PAD(0x42C, 0x14C, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_WR__GPIO_2_16 IOMUX_PAD(0x42C, 0x14C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_WR__ELCDIF_PIXCLK IOMUX_PAD(0x42C, 0x14C, 2, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_WR__WEIM_A24 IOMUX_PAD(0x42C, 0x14C, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_DISP_RD__ELCDIF_RD IOMUX_PAD(0x430, 0x150, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_RD__GPIO_2_19 IOMUX_PAD(0x430, 0x150, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_RD__ELCDIF_EN IOMUX_PAD(0x430, 0x150, 2, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_RD__WEIM_A25 IOMUX_PAD(0x430, 0x150, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_DISP_RS__ELCDIF_RS IOMUX_PAD(0x434, 0x154, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_RS__GPIO_2_17 IOMUX_PAD(0x434, 0x154, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_RS__ELCDIF_VSYNC IOMUX_PAD(0x434, 0x154, 2, 0x73c, 1, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_RS__WEIM_A26 IOMUX_PAD(0x434, 0x154, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_DISP_CS__ELCDIF_CS IOMUX_PAD(0x438, 0x158, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_CS__GPIO_2_21 IOMUX_PAD(0x438, 0x158, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_CS__ELCDIF_HSYNC IOMUX_PAD(0x438, 0x158, 2, 0x6f8, 1, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_CS__WEIM_A27 IOMUX_PAD(0x438, 0x158, 3, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_CS__WEIM_CS3 IOMUX_PAD(0x438, 0x158, 4, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_DISP_BUSY__ELCDIF_HSYNC IOMUX_PAD(0x43C, 0x15C, 0, 0x6f8, 2, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_BUSY__GPIO_2_18 IOMUX_PAD(0x43C, 0x15C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_BUSY__WEIM_CS3 IOMUX_PAD(0x43C, 0x15C, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_DISP_RESET__ELCDIF_RST IOMUX_PAD(0x440, 0x160, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_RESET__GPIO_2_20 IOMUX_PAD(0x440, 0x160, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_RESET__WEIM_CS3 IOMUX_PAD(0x440, 0x160, 4, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD3_CMD__SD3_CMD IOMUX_PAD(0x444, 0x164, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD3_CMD__GPIO_5_18 IOMUX_PAD(0x444, 0x164, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_SD3_CMD__NANDF_WRN IOMUX_PAD(0x444, 0x164, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_SD3_CMD__SSP_CMD IOMUX_PAD(0x444, 0x164, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD3_CLK__SD3_CLK IOMUX_PAD(0x448, 0x168, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD3_CLK__GPIO_5_19 IOMUX_PAD(0x448, 0x168, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_SD3_CLK__NANDF_RDN IOMUX_PAD(0x448, 0x168, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_SD3_CLK__SSP_CLK IOMUX_PAD(0x448, 0x168, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD3_D0__SD3_D0 IOMUX_PAD(0x44C, 0x16C, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD3_D0__GPIO_5_20 IOMUX_PAD(0x44C, 0x16C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_SD3_D0__NANDF_D4 IOMUX_PAD(0x44C, 0x16C, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_SD3_D0__SSP_D0 IOMUX_PAD(0x44C, 0x16C, 3, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD3_D0__PLL1_BYP IOMUX_PAD(0x44C, 0x16C, 7, 0x6dc, 1, NO_PAD_CTRL) - -#define MX50_PAD_SD3_D1__SD3_D1 IOMUX_PAD(0x450, 0x170, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD3_D1__GPIO_5_21 IOMUX_PAD(0x450, 0x170, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_SD3_D1__NANDF_D5 IOMUX_PAD(0x450, 0x170, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_SD3_D1__PLL2_BYP IOMUX_PAD(0x450, 0x170, 7, 0x6e0, 1, NO_PAD_CTRL) - -#define MX50_PAD_SD3_D2__SD3_D2 IOMUX_PAD(0x454, 0x174, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD3_D2__GPIO_5_22 IOMUX_PAD(0x454, 0x174, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_SD3_D2__NANDF_D6 IOMUX_PAD(0x454, 0x174, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_SD3_D2__SSP_D2 IOMUX_PAD(0x454, 0x174, 3, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD3_D2__PLL3_BYP IOMUX_PAD(0x454, 0x174, 7, 0x6e4, 1, NO_PAD_CTRL) - -#define MX50_PAD_SD3_D3__SD3_D3 IOMUX_PAD(0x458, 0x178, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD3_D3__GPIO_5_23 IOMUX_PAD(0x458, 0x178, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_SD3_D3__NANDF_D7 IOMUX_PAD(0x458, 0x178, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_SD3_D3__SSP_D3 IOMUX_PAD(0x458, 0x178, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD3_D4__SD3_D4 IOMUX_PAD(0x45C, 0x17C, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD3_D4__GPIO_5_24 IOMUX_PAD(0x45C, 0x17C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_SD3_D4__NANDF_D0 IOMUX_PAD(0x45C, 0x17C, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_SD3_D4__SSP_D4 IOMUX_PAD(0x45C, 0x17C, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD3_D5__SD3_D5 IOMUX_PAD(0x460, 0x180, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD3_D5__GPIO_5_25 IOMUX_PAD(0x460, 0x180, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_SD3_D5__NANDF_D1 IOMUX_PAD(0x460, 0x180, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_SD3_D5__SSP_D5 IOMUX_PAD(0x460, 0x180, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD3_D6__SD3_D6 IOMUX_PAD(0x464, 0x184, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD3_D6__GPIO_5_26 IOMUX_PAD(0x464, 0x184, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_SD3_D6__NANDF_D2 IOMUX_PAD(0x464, 0x184, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_SD3_D6__SSP_D6 IOMUX_PAD(0x464, 0x184, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD3_D7__SD3_D7 IOMUX_PAD(0x468, 0x188, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD3_D7__GPIO_5_27 IOMUX_PAD(0x468, 0x188, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_SD3_D7__NANDF_D3 IOMUX_PAD(0x468, 0x188, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_SD3_D7__SSP_D7 IOMUX_PAD(0x468, 0x188, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_SD3_WP__SD3_WP IOMUX_PAD(0x46C, 0x18C, 0, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD3_WP__GPIO_5_28 IOMUX_PAD(0x46C, 0x18C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_SD3_WP__NANDF_RESETN IOMUX_PAD(0x46C, 0x18C, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_SD3_WP__SSP_CD IOMUX_PAD(0x46C, 0x18C, 3, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_SD3_WP__SD4_LCTL IOMUX_PAD(0x46C, 0x18C, 4, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_SD3_WP__WEIM_CS3 IOMUX_PAD(0x46C, 0x18C, 5, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_DISP_D8__DISP_D8 IOMUX_PAD(0x470, 0x190, 0, 0x71c, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D8__GPIO_2_8 IOMUX_PAD(0x470, 0x190, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D8__NANDF_CLE IOMUX_PAD(0x470, 0x190, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D8__SD1_LCTL IOMUX_PAD(0x470, 0x190, 3, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_DISP_D8__SD4_CMD IOMUX_PAD(0x470, 0x190, 4, 0x74c, 2, MX50_SD_PAD_CTRL) -#define MX50_PAD_DISP_D8__KEY_COL4 IOMUX_PAD(0x470, 0x190, 5, 0x790, 1, NO_PAD_CTRL) -#define MX50_PAD_DISP_D8__FEC_TX_CLK IOMUX_PAD(0x470, 0x190, 6, 0x78c, 1, NO_PAD_CTRL) - -#define MX50_PAD_DISP_D9__DISP_D9 IOMUX_PAD(0x474, 0x194, 0, 0x720, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D9__GPIO_2_9 IOMUX_PAD(0x474, 0x194, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D9__NANDF_ALE IOMUX_PAD(0x474, 0x194, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D9__SD2_LCTL IOMUX_PAD(0x474, 0x194, 3, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_DISP_D9__SD4_CLK IOMUX_PAD(0x474, 0x194, 4, 0x748, 2, MX50_SD_PAD_CTRL) -#define MX50_PAD_DISP_D9__KEY_ROW4 IOMUX_PAD(0x474, 0x194, 5, 0x7a0, 1, NO_PAD_CTRL) -#define MX50_PAD_DISP_D9__FEC_RX_ER IOMUX_PAD(0x474, 0x194, 6, 0x788, 1, NO_PAD_CTRL) - -#define MX50_PAD_DISP_D10__DISP_D10 IOMUX_PAD(0x478, 0x198, 0, 0x724, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D10__GPIO_2_10 IOMUX_PAD(0x478, 0x198, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D10__NANDF_CEN0 IOMUX_PAD(0x478, 0x198, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D10__SD3_LCTL IOMUX_PAD(0x478, 0x198, 3, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_DISP_D10__SD4_D0 IOMUX_PAD(0x478, 0x198, 4, 0x750, 1, MX50_SD_PAD_CTRL) -#define MX50_PAD_DISP_D10__KEY_COL5 IOMUX_PAD(0x478, 0x198, 5, 0x794, 1, NO_PAD_CTRL) -#define MX50_PAD_DISP_D10__FEC_RX_DV IOMUX_PAD(0x478, 0x198, 6, 0x784, 1, NO_PAD_CTRL) - -#define MX50_PAD_DISP_D11__DISP_D11 IOMUX_PAD(0x47C, 0x19C, 0, 0x728, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D11__GPIO_2_11 IOMUX_PAD(0x47C, 0x19C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D11__NANDF_CEN1 IOMUX_PAD(0x47C, 0x19C, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D11__SD4_D1 IOMUX_PAD(0x47C, 0x19C, 4, 0x754, 1, MX50_SD_PAD_CTRL) -#define MX50_PAD_DISP_D11__KEY_ROW5 IOMUX_PAD(0x47C, 0x19C, 5, 0x7a4, 1, NO_PAD_CTRL) -#define MX50_PAD_DISP_D11__FEC_RDAT1 IOMUX_PAD(0x47C, 0x19C, 6, 0x77c, 1, NO_PAD_CTRL) - -#define MX50_PAD_DISP_D12__DISP_D12 IOMUX_PAD(0x480, 0x1A0, 0, 0x72c, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D12__GPIO_2_12 IOMUX_PAD(0x480, 0x1A0, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D12__NANDF_CEN2 IOMUX_PAD(0x480, 0x1A0, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D12__SD1_CD IOMUX_PAD(0x480, 0x1A0, 3, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_DISP_D12__SD4_D2 IOMUX_PAD(0x480, 0x1A0, 4, 0x758, 1, MX50_SD_PAD_CTRL) -#define MX50_PAD_DISP_D12__KEY_COL6 IOMUX_PAD(0x480, 0x1A0, 5, 0x798, 1, NO_PAD_CTRL) -#define MX50_PAD_DISP_D12__FEC_RDAT0 IOMUX_PAD(0x480, 0x1A0, 6, 0x778, 1, NO_PAD_CTRL) - -#define MX50_PAD_DISP_D13__DISP_D13 IOMUX_PAD(0x484, 0x1A4, 0, 0x730, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D13__GPIO_2_13 IOMUX_PAD(0x484, 0x1A4, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D13__NANDF_CEN3 IOMUX_PAD(0x484, 0x1A4, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D13__SD3_CD IOMUX_PAD(0x484, 0x1A4, 3, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_DISP_D13__SD4_D3 IOMUX_PAD(0x484, 0x1A4, 4, 0x75c, 1, MX50_SD_PAD_CTRL) -#define MX50_PAD_DISP_D13__KEY_ROW6 IOMUX_PAD(0x484, 0x1A4, 5, 0x7a8, 1, NO_PAD_CTRL) -#define MX50_PAD_DISP_D13__FEC_TX_EN IOMUX_PAD(0x484, 0x1A4, 6, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_DISP_D14__DISP_D14 IOMUX_PAD(0x488, 0x1A8, 0, 0x734, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D14__GPIO_2_14 IOMUX_PAD(0x488, 0x1A8, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D14__NANDF_RDY0 IOMUX_PAD(0x488, 0x1A8, 2, 0x7b4, 1, NO_PAD_CTRL) -#define MX50_PAD_DISP_D14__SD1_WP IOMUX_PAD(0x488, 0x1A8, 3, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_DISP_D14__SD4_WP IOMUX_PAD(0x488, 0x1A8, 4, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_DISP_D14__KEY_COL7 IOMUX_PAD(0x488, 0x1A8, 5, 0x79c, 1, NO_PAD_CTRL) -#define MX50_PAD_DISP_D14__FEC_TDAT1 IOMUX_PAD(0x488, 0x1A8, 6, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_DISP_D15__DISP_D15 IOMUX_PAD(0x48C, 0x1AC, 0, 0x738, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_DISP_D15__GPIO_2_15 IOMUX_PAD(0x48C, 0x1AC, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_DISP_D15__NANDF_DQS IOMUX_PAD(0x48C, 0x1AC, 2, 0x7b0, 1, NO_PAD_CTRL) -#define MX50_PAD_DISP_D15__SD3_RST IOMUX_PAD(0x48C, 0x1AC, 3, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_DISP_D15__SD4_CD IOMUX_PAD(0x48C, 0x1AC, 4, 0x0, 0, MX50_SD_PAD_CTRL) -#define MX50_PAD_DISP_D15__KEY_ROW7 IOMUX_PAD(0x48C, 0x1AC, 5, 0x7ac, 1, NO_PAD_CTRL) -#define MX50_PAD_DISP_D15__FEC_TDAT0 IOMUX_PAD(0x48C, 0x1AC, 6, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_D0__EPDC_D0 IOMUX_PAD(0x54C, 0x1B0, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D0__GPIO_3_0 IOMUX_PAD(0x54C, 0x1B0, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D0__WEIM_D0 IOMUX_PAD(0x54C, 0x1B0, 2, 0x7ec, 1, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D0__ELCDIF_RS IOMUX_PAD(0x54C, 0x1B0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_D0__ELCDIF_PIXCLK IOMUX_PAD(0x54C, 0x1B0, 4, 0x0, 0, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_D1__EPDC_D1 IOMUX_PAD(0x550, 0x1B4, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D1__GPIO_3_1 IOMUX_PAD(0x550, 0x1B4, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D1__WEIM_D1 IOMUX_PAD(0x550, 0x1B4, 2, 0x7f0, 1, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D1__ELCDIF_CS IOMUX_PAD(0x550, 0x1B4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_D1__ELCDIF_EN IOMUX_PAD(0x550, 0x1B4, 4, 0x0, 0, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_D2__EPDC_D2 IOMUX_PAD(0x554, 0x1B8, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D2__GPIO_3_2 IOMUX_PAD(0x554, 0x1B8, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D2__WEIM_D2 IOMUX_PAD(0x554, 0x1B8, 2, 0x7f4, 1, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D2__ELCDIF_WR IOMUX_PAD(0x554, 0x1B8, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_D2__ELCDIF_VSYNC IOMUX_PAD(0x554, 0x1B8, 4, 0x73c, 2, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_D3__EPDC_D3 IOMUX_PAD(0x558, 0x1BC, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D3__GPIO_3_3 IOMUX_PAD(0x558, 0x1BC, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D3__WEIM_D3 IOMUX_PAD(0x558, 0x1BC, 2, 0x7f8, 1, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D3__ELCDIF_RD IOMUX_PAD(0x558, 0x1BC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_D3__ELCDIF_HSYNC IOMUX_PAD(0x558, 0x1BC, 4, 0x6f8, 3, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_D4__EPDC_D4 IOMUX_PAD(0x55C, 0x1C0, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D4__GPIO_3_4 IOMUX_PAD(0x55C, 0x1C0, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D4__WEIM_D4 IOMUX_PAD(0x55C, 0x1C0, 2, 0x7fc, 1, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_D5__EPDC_D5 IOMUX_PAD(0x560, 0x1C4, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D5__GPIO_3_5 IOMUX_PAD(0x560, 0x1C4, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D5__WEIM_D5 IOMUX_PAD(0x560, 0x1C4, 2, 0x800, 1, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_D6__EPDC_D6 IOMUX_PAD(0x564, 0x1C8, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D6__GPIO_3_6 IOMUX_PAD(0x564, 0x1C8, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D6__WEIM_D6 IOMUX_PAD(0x564, 0x1C8, 2, 0x804, 1, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_D7__EPDC_D7 IOMUX_PAD(0x568, 0x1CC, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D7__GPIO_3_7 IOMUX_PAD(0x568, 0x1CC, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D7__WEIM_D7 IOMUX_PAD(0x568, 0x1CC, 2, 0x808, 1, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_D8__EPDC_D8 IOMUX_PAD(0x56C, 0x1D0, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D8__GPIO_3_8 IOMUX_PAD(0x56C, 0x1D0, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D8__WEIM_D8 IOMUX_PAD(0x56C, 0x1D0, 2, 0x80c, 2, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D8__ELCDIF_D24 IOMUX_PAD(0x56C, 0x1D0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_D9__EPDC_D9 IOMUX_PAD(0x570, 0x1D4, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D9__GPIO_3_9 IOMUX_PAD(0x570, 0x1D4, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D9__WEIM_D9 IOMUX_PAD(0x570, 0x1D4, 2, 0x810, 2, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D9__ELCDIF_D25 IOMUX_PAD(0x570, 0x1D4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_D10__EPDC_D10 IOMUX_PAD(0x574, 0x1D8, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D10__GPIO_3_10 IOMUX_PAD(0x574, 0x1D8, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D10__WEIM_D10 IOMUX_PAD(0x574, 0x1D8, 2, 0x814, 2, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D10__ELCDIF_D26 IOMUX_PAD(0x574, 0x1D8, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_D11__EPDC_D11 IOMUX_PAD(0x578, 0x1DC, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D11__GPIO_3_11 IOMUX_PAD(0x578, 0x1DC, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D11__WEIM_D11 IOMUX_PAD(0x578, 0x1DC, 2, 0x818, 2, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D11__ELCDIF_D27 IOMUX_PAD(0x578, 0x1DC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_D12__EPDC_D12 IOMUX_PAD(0x57C, 0x1E0, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D12__GPIO_3_12 IOMUX_PAD(0x57C, 0x1E0, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D12__WEIM_D12 IOMUX_PAD(0x57C, 0x1E0, 2, 0x81c, 1, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D12__ELCDIF_D28 IOMUX_PAD(0x57C, 0x1E0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_D13__EPDC_D13 IOMUX_PAD(0x580, 0x1E4, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D13__GPIO_3_13 IOMUX_PAD(0x580, 0x1E4, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D13__WEIM_D13 IOMUX_PAD(0x580, 0x1E4, 2, 0x820, 1, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D13__ELCDIF_D29 IOMUX_PAD(0x580, 0x1E4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_D14__EPDC_D14 IOMUX_PAD(0x584, 0x1E8, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D14__GPIO_3_14 IOMUX_PAD(0x584, 0x1E8, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D14__WEIM_D14 IOMUX_PAD(0x584, 0x1E8, 2, 0x824, 1, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D14__ELCDIF_D30 IOMUX_PAD(0x584, 0x1E8, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_D14__AUD6_TXD IOMUX_PAD(0x584, 0x1E8, 4, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_D15__EPDC_D15 IOMUX_PAD(0x588, 0x1EC, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D15__GPIO_3_15 IOMUX_PAD(0x588, 0x1EC, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D15__WEIM_D15 IOMUX_PAD(0x588, 0x1EC, 2, 0x828, 1, NO_PAD_CTRL) -#define MX50_PAD_EPDC_D15__ELCDIF_D31 IOMUX_PAD(0x588, 0x1EC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_D15__AUD6_TXC IOMUX_PAD(0x588, 0x1EC, 4, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_GDCLK__EPDC_GDCLK IOMUX_PAD(0x58C, 0x1F0, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_GDCLK__GPIO_3_16 IOMUX_PAD(0x58C, 0x1F0, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_GDCLK__WEIM_D16 IOMUX_PAD(0x58C, 0x1F0, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_GDCLK__ELCDIF_D16 IOMUX_PAD(0x58C, 0x1F0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_GDCLK__AUD6_TXFS IOMUX_PAD(0x58C, 0x1F0, 4, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_GDSP__EPDC_GDSP IOMUX_PAD(0x590, 0x1F4, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_GDSP__GPIO_3_17 IOMUX_PAD(0x590, 0x1F4, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_GDSP__WEIM_D17 IOMUX_PAD(0x590, 0x1F4, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_GDSP__ELCDIF_D17 IOMUX_PAD(0x590, 0x1F4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_GDSP__AUD6_RXD IOMUX_PAD(0x590, 0x1F4, 4, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_GDOE__EPDC_GDOE IOMUX_PAD(0x594, 0x1F8, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_GDOE__GPIO_3_18 IOMUX_PAD(0x594, 0x1F8, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_GDOE__WEIM_D18 IOMUX_PAD(0x594, 0x1F8, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_GDOE__ELCDIF_D18 IOMUX_PAD(0x594, 0x1F8, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_GDOE__AUD6_RXC IOMUX_PAD(0x594, 0x1F8, 4, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_GDRL__EPDC_GDRL IOMUX_PAD(0x598, 0x1FC, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_GDRL__GPIO_3_19 IOMUX_PAD(0x598, 0x1FC, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_GDRL__WEIM_D19 IOMUX_PAD(0x598, 0x1FC, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_GDRL__ELCDIF_D19 IOMUX_PAD(0x598, 0x1FC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_GDRL__AUD6_RXFS IOMUX_PAD(0x598, 0x1FC, 4, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_SDCLK__EPDC_SDCLK IOMUX_PAD(0x59C, 0x200, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCLK__GPIO_3_20 IOMUX_PAD(0x59C, 0x200, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCLK__WEIM_D20 IOMUX_PAD(0x59C, 0x200, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCLK__ELCDIF_D20 IOMUX_PAD(0x59C, 0x200, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_SDCLK__AUD5_TXD IOMUX_PAD(0x59C, 0x200, 4, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_SDOEZ__EPDC_SDOEZ IOMUX_PAD(0x5A0, 0x204, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDOEZ__GPIO_3_21 IOMUX_PAD(0x5A0, 0x204, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDOEZ__WEIM_D21 IOMUX_PAD(0x5A0, 0x204, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDOEZ__ELCDIF_D21 IOMUX_PAD(0x5A0, 0x204, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_SDOEZ__AUD5_TXC IOMUX_PAD(0x5A0, 0x204, 4, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_SDOED__EPDC_SDOED IOMUX_PAD(0x5A4, 0x208, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDOED__GPIO_3_22 IOMUX_PAD(0x5A4, 0x208, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDOED__WEIM_D22 IOMUX_PAD(0x5A4, 0x208, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDOED__ELCDIF_D22 IOMUX_PAD(0x5A4, 0x208, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_SDOED__AUD5_TXFS IOMUX_PAD(0x5A4, 0x208, 4, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_SDOE__EPDC_SDOE IOMUX_PAD(0x5A8, 0x20C, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDOE__GPIO_3_23 IOMUX_PAD(0x5A8, 0x20C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDOE__WEIM_D23 IOMUX_PAD(0x5A8, 0x20C, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDOE__ELCDIF_D23 IOMUX_PAD(0x5A8, 0x20C, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_SDOE__AUD5_RXD IOMUX_PAD(0x5A8, 0x20C, 4, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_SDLE__EPDC_SDLE IOMUX_PAD(0x5AC, 0x210, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDLE__GPIO_3_24 IOMUX_PAD(0x5AC, 0x210, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDLE__WEIM_D24 IOMUX_PAD(0x5AC, 0x210, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDLE__ELCDIF_D8 IOMUX_PAD(0x5AC, 0x210, 3, 0x71c, 1, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_SDLE__AUD5_RXC IOMUX_PAD(0x5AC, 0x210, 4, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_SDCLKN__EPDC_SDCLKN IOMUX_PAD(0x5B0, 0x214, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCLKN__GPIO_3_25 IOMUX_PAD(0x5B0, 0x214, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCLKN__WEIM_D25 IOMUX_PAD(0x5B0, 0x214, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCLKN__ELCDIF_D9 IOMUX_PAD(0x5B0, 0x214, 3, 0x720, 1, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_SDCLKN__AUD5_RXFS IOMUX_PAD(0x5B0, 0x214, 4, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_SDSHR__EPDC_SDSHR IOMUX_PAD(0x5B4, 0x218, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDSHR__GPIO_3_26 IOMUX_PAD(0x5B4, 0x218, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDSHR__WEIM_D26 IOMUX_PAD(0x5B4, 0x218, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDSHR__ELCDIF_D10 IOMUX_PAD(0x5B4, 0x218, 3, 0x724, 1, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_SDSHR__AUD4_TXD IOMUX_PAD(0x5B4, 0x218, 4, 0x6c8, 1, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_PWRCOM__EPDC_PWRCOM IOMUX_PAD(0x5B8, 0x21C, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCOM__GPIO_3_27 IOMUX_PAD(0x5B8, 0x21C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCOM__WEIM_D27 IOMUX_PAD(0x5B8, 0x21C, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCOM__ELCDIF_D11 IOMUX_PAD(0x5B8, 0x21C, 3, 0x728, 1, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCOM__AUD4_TXC IOMUX_PAD(0x5B8, 0x21C, 4, 0x6d4, 1, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_PWRSTAT__EPDC_PWRSTAT IOMUX_PAD(0x5BC, 0x220, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRSTAT__GPIO_3_28 IOMUX_PAD(0x5BC, 0x220, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRSTAT__WEIM_D28 IOMUX_PAD(0x5BC, 0x220, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRSTAT__ELCDIF_D12 IOMUX_PAD(0x5BC, 0x220, 3, 0x72c, 1, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_PWRSTAT__AUD4_TXFS IOMUX_PAD(0x5BC, 0x220, 4, 0x6d8, 1, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_PWRCTRL0__EPDC_PWRCTRL0 IOMUX_PAD(0x5C0, 0x224, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL0__GPIO_3_29 IOMUX_PAD(0x5C0, 0x224, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL0__WEIM_D29 IOMUX_PAD(0x5C0, 0x224, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL0__ELCDIF_D13 IOMUX_PAD(0x5C0, 0x224, 3, 0x730, 1, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL0__AUD4_RXD IOMUX_PAD(0x5C0, 0x224, 4, 0x6c4, 1, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_PWRCTRL1__EPDC_PWRCTRL1 IOMUX_PAD(0x5C4, 0x228, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL1__GPIO_3_30 IOMUX_PAD(0x5C4, 0x228, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL1__WEIM_D30 IOMUX_PAD(0x5C4, 0x228, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL1__ELCDIF_D14 IOMUX_PAD(0x5C4, 0x228, 3, 0x734, 1, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL1__AUD4_RXC IOMUX_PAD(0x5C4, 0x228, 4, 0x6cc, 1, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_PWRCTRL2__EPDC_PWRCTRL2 IOMUX_PAD(0x5C8, 0x22C, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL2__GPIO_3_31 IOMUX_PAD(0x5C8, 0x22C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL2__WEIM_D31 IOMUX_PAD(0x5C8, 0x22C, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL2__ELCDIF_D15 IOMUX_PAD(0x5C8, 0x22C, 3, 0x738, 1, MX50_ELCDIF_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL2__AUD4_RXFS IOMUX_PAD(0x5C8, 0x22C, 4, 0x6d0, 1, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL2__SDMA_EXT0 IOMUX_PAD(0x5C8, 0x22C, 6, 0x7b8, 1, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_PWRCTRL3__PWRCTRL3 IOMUX_PAD(0x5CC, 0x230, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL3__GPIO_4_20 IOMUX_PAD(0x5CC, 0x230, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL3__WEIM_EB2 IOMUX_PAD(0x5CC, 0x230, 2, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_PWRCTRL3__SDMA_EXT1 IOMUX_PAD(0x5CC, 0x230, 6, 0x7bc, 1, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_VCOM0__EPDC_VCOM0 IOMUX_PAD(0x5D0, 0x234, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_VCOM0__GPIO_4_21 IOMUX_PAD(0x5D0, 0x234, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_VCOM0__WEIM_EB3 IOMUX_PAD(0x5D0, 0x234, 2, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_VCOM1__EPDC_VCOM1 IOMUX_PAD(0x5D4, 0x238, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_VCOM1__GPIO_4_22 IOMUX_PAD(0x5D4, 0x238, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_VCOM1__WEIM_CS3 IOMUX_PAD(0x5D4, 0x238, 2, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EPDC_BDR0__EPDC_BDR0 IOMUX_PAD(0x5D8, 0x23C, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_BDR0__GPIO_4_23 IOMUX_PAD(0x5D8, 0x23C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_BDR0__ELCDIF_D7 IOMUX_PAD(0x5D8, 0x23C, 3, 0x718, 1, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_BDR1__EPDC_BDR1 IOMUX_PAD(0x5DC, 0x240, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_BDR1__GPIO_4_24 IOMUX_PAD(0x5DC, 0x240, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_BDR1__ELCDIF_D6 IOMUX_PAD(0x5DC, 0x240, 3, 0x714, 1, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_SDCE0__EPDC_SDCE0 IOMUX_PAD(0x5E0, 0x244, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCE0__GPIO_4_25 IOMUX_PAD(0x5E0, 0x244, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCE0__ELCDIF_D5 IOMUX_PAD(0x5E0, 0x244, 3, 0x710, 1, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_SDCE1__EPDC_SDCE1 IOMUX_PAD(0x5E4, 0x248, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCE1__GPIO_4_26 IOMUX_PAD(0x5E4, 0x248, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCE1__ELCDIF_D4 IOMUX_PAD(0x5E4, 0x248, 2, 0x70c, 1, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_SDCE2__EPDC_SDCE2 IOMUX_PAD(0x5E8, 0x24C, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCE2__GPIO_4_27 IOMUX_PAD(0x5E8, 0x24C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCE2__ELCDIF_DAT3 IOMUX_PAD(0x5E8, 0x24C, 3, 0x708, 1, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_SDCE3__EPDC_SDCE3 IOMUX_PAD(0x5EC, 0x250, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCE3__GPIO_4_28 IOMUX_PAD(0x5EC, 0x250, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCE3__ELCDIF_D2 IOMUX_PAD(0x5EC, 0x250, 3, 0x704, 1, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_SDCE4__EPDC_SDCE4 IOMUX_PAD(0x5F0, 0x254, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCE4__GPIO_4_29 IOMUX_PAD(0x5F0, 0x254, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCE4__ELCDIF_D1 IOMUX_PAD(0x5F0, 0x254, 3, 0x700, 1, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EPDC_SDCE5__EPDC_SDCE5 IOMUX_PAD(0x5F4, 0x258, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCE5__GPIO_4_30 IOMUX_PAD(0x5F4, 0x258, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EPDC_SDCE5__ELCDIF_D0 IOMUX_PAD(0x5F4, 0x258, 3, 0x6fc, 1, MX50_ELCDIF_PAD_CTRL) - -#define MX50_PAD_EIM_DA0__WEIM_A0 IOMUX_PAD(0x5F8, 0x25C, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA0__GPIO_1_0 IOMUX_PAD(0x5F8, 0x25C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA0__KEY_COL4 IOMUX_PAD(0x5f8, 0x25C, 3, 0x790, 2, NO_PAD_CTRL) - -#define MX50_PAD_EIM_DA1__WEIM_A1 IOMUX_PAD(0x5FC, 0x260, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA1__GPIO_1_1 IOMUX_PAD(0x5FC, 0x260, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA1__KEY_ROW4 IOMUX_PAD(0x5fc, 0x260, 3, 0x7a0, 2, MX50_KEYPAD_CTRL) - -#define MX50_PAD_EIM_DA2__WEIM_A2 IOMUX_PAD(0x600, 0x264, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA2__GPIO_1_2 IOMUX_PAD(0x600, 0x264, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA2__KEY_COL5 IOMUX_PAD(0x600, 0x264, 3, 0x794, 2, NO_PAD_CTRL) - -#define MX50_PAD_EIM_DA3__WEIM_A3 IOMUX_PAD(0x604, 0x268, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA3__GPIO_1_3 IOMUX_PAD(0x604, 0x268, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA3__KEY_ROW5 IOMUX_PAD(0x604, 0x268, 3, 0x7a4, 2, MX50_KEYPAD_CTRL) - -#define MX50_PAD_EIM_DA4__WEIM_A4 IOMUX_PAD(0x608, 0x26C, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA4__GPIO_1_4 IOMUX_PAD(0x608, 0x26C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA4__KEY_COL6 IOMUX_PAD(0x608, 0x26C, 3, 0x798, 2, NO_PAD_CTRL) - -#define MX50_PAD_EIM_DA5__WEIM_A5 IOMUX_PAD(0x60C, 0x270, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA5__GPIO_1_5 IOMUX_PAD(0x60C, 0x270, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA5__KEY_ROW6 IOMUX_PAD(0x60C, 0x270, 3, 0x7a8, 2, MX50_KEYPAD_CTRL) - -#define MX50_PAD_EIM_DA6__WEIM_A6 IOMUX_PAD(0x610, 0x274, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA6__GPIO_1_6 IOMUX_PAD(0x610, 0x274, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA6__KEY_COL7 IOMUX_PAD(0x610, 0x274, 3, 0x79c, 2, NO_PAD_CTRL) - -#define MX50_PAD_EIM_DA7__WEIM_A7 IOMUX_PAD(0x614, 0x278, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA7__GPIO_1_7 IOMUX_PAD(0x614, 0x278, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA7__KEY_ROW7 IOMUX_PAD(0x614, 0x278, 3, 0x7ac, 2, MX50_KEYPAD_CTRL) - -#define MX50_PAD_EIM_DA8__WEIM_A8 IOMUX_PAD(0x618, 0x27C, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA8__GPIO_1_8 IOMUX_PAD(0x618, 0x27C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_EIM_DA8__NANDF_CLE IOMUX_PAD(0x618, 0x27C, 2, 0x0, 0, PAD_CTL_DSE_HIGH) - -#define MX50_PAD_EIM_DA9__WEIM_A9 IOMUX_PAD(0x61C, 0x280, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA9__GPIO_1_9 IOMUX_PAD(0x61C, 0x280, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_EIM_DA9__NANDF_ALE IOMUX_PAD(0x61C, 0x280, 2, 0x0, 0, PAD_CTL_DSE_HIGH) - -#define MX50_PAD_EIM_DA10__WEIM_A10 IOMUX_PAD(0x620, 0x284, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA10__GPIO_1_10 IOMUX_PAD(0x620, 0x284, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_EIM_DA10__NANDF_CE0 IOMUX_PAD(0x620, 0x284, 2, 0x0, 0, PAD_CTL_DSE_HIGH) - -#define MX50_PAD_EIM_DA11__WEIM_A11 IOMUX_PAD(0x624, 0x288, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA11__GPIO_1_11 IOMUX_PAD(0x624, 0x288, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_EIM_DA11__NANDF_CE1 IOMUX_PAD(0x624, 0x288, 2, 0x0, 0, PAD_CTL_DSE_HIGH) - -#define MX50_PAD_EIM_DA12__WEIM_A12 IOMUX_PAD(0x628, 0x28C, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA12__GPIO_1_12 IOMUX_PAD(0x628, 0x28C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_EIM_DA12__NANDF_CE2 IOMUX_PAD(0x628, 0x28C, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PAD_EIM_DA12__EPDC_SDCE6 IOMUX_PAD(0x628, 0x28C, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EIM_DA13__WEIM_A13 IOMUX_PAD(0x62C, 0x290, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA13__GPIO_1_13 IOMUX_PAD(0x62C, 0x290, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_EIM_DA13__NANDF_CE3 IOMUX_PAD(0x62C, 0x290, 2, 0x0, 0, PAD_CTL_DSE_HIGH) -#define MX50_PIN_EIM_DA13__EPDC_SDCE7 IOMUX_PAD(0x62C, 0x290, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EIM_DA14__WEIM_A14 IOMUX_PAD(0x630, 0x294, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA14__GPIO_1_14 IOMUX_PAD(0x630, 0x294, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA14__NANDF_READY IOMUX_PAD(0x630, 0x294, 2, 0x7B4, 2, PAD_CTL_PKE | \ - PAD_CTL_PUE | PAD_CTL_PUS_100K_UP) -#define MX50_PAD_EIM_DA14__EPDC_SDCE8 IOMUX_PAD(0x630, 0x294, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EIM_DA15__WEIM_A15 IOMUX_PAD(0x634, 0x298, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_DA15__GPIO_1_15 IOMUX_PAD(0x634, 0x298, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PIN_EIM_DA15__NANDF_DQS IOMUX_PAD(0x634, 0x298, 2, 0x7B0, 2, PAD_CTL_DSE_HIGH) -#define MX50_PAD_EIM_DA15__EPDC_SDCE9 IOMUX_PAD(0x634, 0x298, 3, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EIM_CS2__WEIM_CS2 IOMUX_PAD(0x638, 0x29C, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_CS2__GPIO_1_16 IOMUX_PAD(0x638, 0x29C, 1, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_CS2__WEIM_A27 IOMUX_PAD(0x638, 0x29C, 2, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EIM_CS1__WEIM_CS1 IOMUX_PAD(0x63C, 0x2A0, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_CS1__GPIO_1_17 IOMUX_PAD(0x63C, 0x2A0, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EIM_CS0__WEIM_CS0 IOMUX_PAD(0x640, 0x2A4, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_CS0__GPIO_1_18 IOMUX_PAD(0x640, 0x2A4, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EIM_EB0__WEIM_EB0 IOMUX_PAD(0x644, 0x2A8, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_EB0__GPIO_1_19 IOMUX_PAD(0x644, 0x2A8, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EIM_EB1__WEIM_EB1 IOMUX_PAD(0x648, 0x2AC, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_EB1__GPIO_1_20 IOMUX_PAD(0x648, 0x2AC, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EIM_WAIT__WEIM_WAIT IOMUX_PAD(0x64C, 0x2B0, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_WAIT__GPIO_1_21 IOMUX_PAD(0x64C, 0x2B0, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EIM_BCLK__WEIM_BCLK IOMUX_PAD(0x650, 0x2B4, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_BCLK__GPIO_1_22 IOMUX_PAD(0x650, 0x2B4, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EIM_RDY__WEIM_RDY IOMUX_PAD(0x654, 0x2B8, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_RDY__GPIO_1_23 IOMUX_PAD(0x654, 0x2B8, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EIM_OE__WEIM_OE IOMUX_PAD(0x658, 0x2BC, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_OE__GPIO_1_24 IOMUX_PAD(0x658, 0x2BC, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EIM_RW__WEIM_RW IOMUX_PAD(0x65C, 0x2C0, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_RW__GPIO_1_25 IOMUX_PAD(0x65C, 0x2C0, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EIM_LBA__WEIM_LBA IOMUX_PAD(0x660, 0x2C4, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_LBA__GPIO_1_26 IOMUX_PAD(0x660, 0x2C4, 1, 0x0, 0, NO_PAD_CTRL) - -#define MX50_PAD_EIM_CRE__WEIM_CRE IOMUX_PAD(0x664, 0x2C8, 0, 0x0, 0, NO_PAD_CTRL) -#define MX50_PAD_EIM_CRE__GPIO_1_27 IOMUX_PAD(0x664, 0x2C8, 1, 0x0, 0, NO_PAD_CTRL) - -#endif /* __MACH_IOMUX_MX50_H__ */ diff --git a/arch/arm/mach-imx/iram_alloc.c b/arch/arm/mach-imx/iram_alloc.c index 6c80424f678..e05cf407db6 100644 --- a/arch/arm/mach-imx/iram_alloc.c +++ b/arch/arm/mach-imx/iram_alloc.c @@ -22,8 +22,7 @@ #include <linux/module.h> #include <linux/spinlock.h> #include <linux/genalloc.h> - -#include "iram.h" +#include "linux/platform_data/imx-iram.h" static unsigned long iram_phys_base; static void __iomem *iram_virt_base; diff --git a/arch/arm/mach-imx/lluart.c b/arch/arm/mach-imx/lluart.c deleted file mode 100644 index 2fdc9bf2fb5..00000000000 --- a/arch/arm/mach-imx/lluart.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2011 Freescale Semiconductor, Inc. - * Copyright 2011 Linaro Ltd. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include <linux/init.h> -#include <asm/page.h> -#include <asm/sizes.h> -#include <asm/mach/map.h> - -#include "hardware.h" - -#define IMX6Q_UART1_BASE_ADDR 0x02020000 -#define IMX6Q_UART2_BASE_ADDR 0x021e8000 -#define IMX6Q_UART3_BASE_ADDR 0x021ec000 -#define IMX6Q_UART4_BASE_ADDR 0x021f0000 -#define IMX6Q_UART5_BASE_ADDR 0x021f4000 - -/* - * IMX6Q_UART_BASE_ADDR is put in the middle to force the expansion - * of IMX6Q_UART##n##_BASE_ADDR. - */ -#define IMX6Q_UART_BASE_ADDR(n) IMX6Q_UART##n##_BASE_ADDR -#define IMX6Q_UART_BASE(n) IMX6Q_UART_BASE_ADDR(n) -#define IMX6Q_DEBUG_UART_BASE IMX6Q_UART_BASE(CONFIG_DEBUG_IMX6Q_UART_PORT) - -static struct map_desc imx_lluart_desc = { -#ifdef CONFIG_DEBUG_IMX6Q_UART - .virtual = IMX_IO_P2V(IMX6Q_DEBUG_UART_BASE), - .pfn = __phys_to_pfn(IMX6Q_DEBUG_UART_BASE), - .length = 0x4000, - .type = MT_DEVICE, -#endif -}; - -void __init imx_lluart_map_io(void) -{ - if (imx_lluart_desc.virtual) - iotable_init(&imx_lluart_desc, 1); -} diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index cd277a0f5b1..5a18e7e5c56 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -18,6 +18,7 @@ #include <linux/init.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/irqchip.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> @@ -29,8 +30,8 @@ #include <asm/cpuidle.h> #include <asm/smp_twd.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <asm/mach/arch.h> +#include <asm/mach/map.h> #include <asm/mach/time.h> #include <asm/system_misc.h> @@ -216,22 +217,16 @@ static void __init imx6q_init_late(void) static void __init imx6q_map_io(void) { - imx_lluart_map_io(); + debug_ll_io_init(); imx_scu_map_io(); - imx6q_clock_map_io(); } -static const struct of_device_id imx6q_irq_match[] __initconst = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - { /* sentinel */ } -}; - static void __init imx6q_init_irq(void) { l2x0_of_init(0, ~0UL); imx_src_init(); imx_gpc_init(); - of_irq_init(imx6q_irq_match); + irqchip_init(); } static void __init imx6q_timer_init(void) @@ -250,7 +245,6 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)") .smp = smp_ops(imx_smp_ops), .map_io = imx6q_map_io, .init_irq = imx6q_init_irq, - .handle_irq = imx6q_handle_irq, .init_time = imx6q_timer_init, .init_machine = imx6q_init_machine, .init_late = imx6q_init_late, diff --git a/arch/arm/mach-imx/mach-mx50_rdp.c b/arch/arm/mach-imx/mach-mx50_rdp.c deleted file mode 100644 index 8937902bda5..00000000000 --- a/arch/arm/mach-imx/mach-mx50_rdp.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -/* - * 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. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#include <linux/io.h> - -#include <asm/irq.h> -#include <asm/setup.h> -#include <asm/mach-types.h> -#include <asm/mach/arch.h> -#include <asm/mach/time.h> - -#include "common.h" -#include "devices-imx50.h" -#include "hardware.h" -#include "iomux-mx50.h" - -#define FEC_EN IMX_GPIO_NR(6, 23) -#define FEC_RESET_B IMX_GPIO_NR(4, 12) - -static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = { - /* SD1 */ - MX50_PAD_ECSPI2_SS0__GPIO_4_19, - MX50_PAD_EIM_CRE__GPIO_1_27, - MX50_PAD_SD1_CMD__SD1_CMD, - - MX50_PAD_SD1_CLK__SD1_CLK, - MX50_PAD_SD1_D0__SD1_D0, - MX50_PAD_SD1_D1__SD1_D1, - MX50_PAD_SD1_D2__SD1_D2, - MX50_PAD_SD1_D3__SD1_D3, - - /* SD2 */ - MX50_PAD_SD2_CD__GPIO_5_17, - MX50_PAD_SD2_WP__GPIO_5_16, - MX50_PAD_SD2_CMD__SD2_CMD, - MX50_PAD_SD2_CLK__SD2_CLK, - MX50_PAD_SD2_D0__SD2_D0, - MX50_PAD_SD2_D1__SD2_D1, - MX50_PAD_SD2_D2__SD2_D2, - MX50_PAD_SD2_D3__SD2_D3, - MX50_PAD_SD2_D4__SD2_D4, - MX50_PAD_SD2_D5__SD2_D5, - MX50_PAD_SD2_D6__SD2_D6, - MX50_PAD_SD2_D7__SD2_D7, - - /* SD3 */ - MX50_PAD_SD3_CMD__SD3_CMD, - MX50_PAD_SD3_CLK__SD3_CLK, - MX50_PAD_SD3_D0__SD3_D0, - MX50_PAD_SD3_D1__SD3_D1, - MX50_PAD_SD3_D2__SD3_D2, - MX50_PAD_SD3_D3__SD3_D3, - MX50_PAD_SD3_D4__SD3_D4, - MX50_PAD_SD3_D5__SD3_D5, - MX50_PAD_SD3_D6__SD3_D6, - MX50_PAD_SD3_D7__SD3_D7, - - /* PWR_INT */ - MX50_PAD_ECSPI2_MISO__GPIO_4_18, - - /* UART pad setting */ - MX50_PAD_UART1_TXD__UART1_TXD, - MX50_PAD_UART1_RXD__UART1_RXD, - MX50_PAD_UART1_RTS__UART1_RTS, - MX50_PAD_UART2_TXD__UART2_TXD, - MX50_PAD_UART2_RXD__UART2_RXD, - MX50_PAD_UART2_CTS__UART2_CTS, - MX50_PAD_UART2_RTS__UART2_RTS, - - MX50_PAD_I2C1_SCL__I2C1_SCL, - MX50_PAD_I2C1_SDA__I2C1_SDA, - MX50_PAD_I2C2_SCL__I2C2_SCL, - MX50_PAD_I2C2_SDA__I2C2_SDA, - - MX50_PAD_EPITO__USBH1_PWR, - /* Need to comment below line if - * one needs to debug owire. - */ - MX50_PAD_OWIRE__USBH1_OC, - /* using gpio to control otg pwr */ - MX50_PAD_PWM2__GPIO_6_25, - MX50_PAD_I2C3_SCL__USBOTG_OC, - - MX50_PAD_SSI_RXC__FEC_MDIO, - MX50_PAD_SSI_RXFS__FEC_MDC, - MX50_PAD_DISP_D0__FEC_TXCLK, - MX50_PAD_DISP_D1__FEC_RX_ER, - MX50_PAD_DISP_D2__FEC_RX_DV, - MX50_PAD_DISP_D3__FEC_RXD1, - MX50_PAD_DISP_D4__FEC_RXD0, - MX50_PAD_DISP_D5__FEC_TX_EN, - MX50_PAD_DISP_D6__FEC_TXD1, - MX50_PAD_DISP_D7__FEC_TXD0, - MX50_PAD_I2C3_SDA__GPIO_6_23, - MX50_PAD_ECSPI1_SCLK__GPIO_4_12, - - MX50_PAD_CSPI_SS0__CSPI_SS0, - MX50_PAD_ECSPI1_MOSI__CSPI_SS1, - MX50_PAD_CSPI_MOSI__CSPI_MOSI, - MX50_PAD_CSPI_MISO__CSPI_MISO, - - /* SGTL500_OSC_EN */ - MX50_PAD_UART1_CTS__GPIO_6_8, - - /* SGTL_AMP_SHDN */ - MX50_PAD_UART3_RXD__GPIO_6_15, - - /* Keypad */ - MX50_PAD_KEY_COL0__KEY_COL0, - MX50_PAD_KEY_ROW0__KEY_ROW0, - MX50_PAD_KEY_COL1__KEY_COL1, - MX50_PAD_KEY_ROW1__KEY_ROW1, - MX50_PAD_KEY_COL2__KEY_COL2, - MX50_PAD_KEY_ROW2__KEY_ROW2, - MX50_PAD_KEY_COL3__KEY_COL3, - MX50_PAD_KEY_ROW3__KEY_ROW3, - MX50_PAD_EIM_DA0__KEY_COL4, - MX50_PAD_EIM_DA1__KEY_ROW4, - MX50_PAD_EIM_DA2__KEY_COL5, - MX50_PAD_EIM_DA3__KEY_ROW5, - MX50_PAD_EIM_DA4__KEY_COL6, - MX50_PAD_EIM_DA5__KEY_ROW6, - MX50_PAD_EIM_DA6__KEY_COL7, - MX50_PAD_EIM_DA7__KEY_ROW7, - /*EIM pads */ - MX50_PAD_EIM_DA8__GPIO_1_8, - MX50_PAD_EIM_DA9__GPIO_1_9, - MX50_PAD_EIM_DA10__GPIO_1_10, - MX50_PAD_EIM_DA11__GPIO_1_11, - MX50_PAD_EIM_DA12__GPIO_1_12, - MX50_PAD_EIM_DA13__GPIO_1_13, - MX50_PAD_EIM_DA14__GPIO_1_14, - MX50_PAD_EIM_DA15__GPIO_1_15, - MX50_PAD_EIM_CS2__GPIO_1_16, - MX50_PAD_EIM_CS1__GPIO_1_17, - MX50_PAD_EIM_CS0__GPIO_1_18, - MX50_PAD_EIM_EB0__GPIO_1_19, - MX50_PAD_EIM_EB1__GPIO_1_20, - MX50_PAD_EIM_WAIT__GPIO_1_21, - MX50_PAD_EIM_BCLK__GPIO_1_22, - MX50_PAD_EIM_RDY__GPIO_1_23, - MX50_PAD_EIM_OE__GPIO_1_24, -}; - -/* Serial ports */ -static const struct imxuart_platform_data uart_pdata __initconst = { - .flags = IMXUART_HAVE_RTSCTS, -}; - -static const struct fec_platform_data fec_data __initconst = { - .phy = PHY_INTERFACE_MODE_RMII, -}; - -static inline void mx50_rdp_fec_reset(void) -{ - gpio_request(FEC_EN, "fec-en"); - gpio_direction_output(FEC_EN, 0); - gpio_request(FEC_RESET_B, "fec-reset_b"); - gpio_direction_output(FEC_RESET_B, 0); - msleep(1); - gpio_set_value(FEC_RESET_B, 1); -} - -static const struct imxi2c_platform_data i2c_data __initconst = { - .bitrate = 100000, -}; - -/* - * Board specific initialization. - */ -static void __init mx50_rdp_board_init(void) -{ - imx50_soc_init(); - - mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads, - ARRAY_SIZE(mx50_rdp_pads)); - - imx50_add_imx_uart(0, &uart_pdata); - imx50_add_imx_uart(1, &uart_pdata); - mx50_rdp_fec_reset(); - imx50_add_fec(&fec_data); - imx50_add_imx_i2c(0, &i2c_data); - imx50_add_imx_i2c(1, &i2c_data); - imx50_add_imx_i2c(2, &i2c_data); -} - -static void __init mx50_rdp_timer_init(void) -{ - mx50_clocks_init(32768, 24000000, 22579200); -} - -MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform") - .map_io = mx50_map_io, - .init_early = imx50_init_early, - .init_irq = mx50_init_irq, - .handle_irq = imx50_handle_irq, - .init_time = mx50_rdp_timer_init, - .init_machine = mx50_rdp_board_init, - .restart = mxc_restart, -MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx51_3ds.c b/arch/arm/mach-imx/mach-mx51_3ds.c deleted file mode 100644 index 2d236511153..00000000000 --- a/arch/arm/mach-imx/mach-mx51_3ds.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright (C) 2010 Jason Wang <jason77.wang@gmail.com> - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include <linux/irq.h> -#include <linux/platform_device.h> -#include <linux/spi/spi.h> -#include <linux/gpio.h> - -#include <asm/mach-types.h> -#include <asm/mach/arch.h> -#include <asm/mach/time.h> - -#include "3ds_debugboard.h" -#include "common.h" -#include "devices-imx51.h" -#include "hardware.h" -#include "iomux-mx51.h" - -#define MX51_3DS_ECSPI2_CS (GPIO_PORTC + 28) - -static iomux_v3_cfg_t mx51_3ds_pads[] = { - /* UART1 */ - MX51_PAD_UART1_RXD__UART1_RXD, - MX51_PAD_UART1_TXD__UART1_TXD, - MX51_PAD_UART1_RTS__UART1_RTS, - MX51_PAD_UART1_CTS__UART1_CTS, - - /* UART2 */ - MX51_PAD_UART2_RXD__UART2_RXD, - MX51_PAD_UART2_TXD__UART2_TXD, - MX51_PAD_EIM_D25__UART2_CTS, - MX51_PAD_EIM_D26__UART2_RTS, - - /* UART3 */ - MX51_PAD_UART3_RXD__UART3_RXD, - MX51_PAD_UART3_TXD__UART3_TXD, - MX51_PAD_EIM_D24__UART3_CTS, - MX51_PAD_EIM_D27__UART3_RTS, - - /* CPLD PARENT IRQ PIN */ - MX51_PAD_GPIO1_6__GPIO1_6, - - /* KPP */ - MX51_PAD_KEY_ROW0__KEY_ROW0, - MX51_PAD_KEY_ROW1__KEY_ROW1, - MX51_PAD_KEY_ROW2__KEY_ROW2, - MX51_PAD_KEY_ROW3__KEY_ROW3, - MX51_PAD_KEY_COL0__KEY_COL0, - MX51_PAD_KEY_COL1__KEY_COL1, - MX51_PAD_KEY_COL2__KEY_COL2, - MX51_PAD_KEY_COL3__KEY_COL3, - MX51_PAD_KEY_COL4__KEY_COL4, - MX51_PAD_KEY_COL5__KEY_COL5, - - /* eCSPI2 */ - MX51_PAD_NANDF_RB2__ECSPI2_SCLK, - MX51_PAD_NANDF_RB3__ECSPI2_MISO, - MX51_PAD_NANDF_D15__ECSPI2_MOSI, - MX51_PAD_NANDF_D12__GPIO3_28, -}; - -/* Serial ports */ -static const struct imxuart_platform_data uart_pdata __initconst = { - .flags = IMXUART_HAVE_RTSCTS, -}; - -static int mx51_3ds_board_keymap[] = { - KEY(0, 0, KEY_1), - KEY(0, 1, KEY_2), - KEY(0, 2, KEY_3), - KEY(0, 3, KEY_F1), - KEY(0, 4, KEY_UP), - KEY(0, 5, KEY_F2), - - KEY(1, 0, KEY_4), - KEY(1, 1, KEY_5), - KEY(1, 2, KEY_6), - KEY(1, 3, KEY_LEFT), - KEY(1, 4, KEY_SELECT), - KEY(1, 5, KEY_RIGHT), - - KEY(2, 0, KEY_7), - KEY(2, 1, KEY_8), - KEY(2, 2, KEY_9), - KEY(2, 3, KEY_F3), - KEY(2, 4, KEY_DOWN), - KEY(2, 5, KEY_F4), - - KEY(3, 0, KEY_0), - KEY(3, 1, KEY_OK), - KEY(3, 2, KEY_ESC), - KEY(3, 3, KEY_ENTER), - KEY(3, 4, KEY_MENU), - KEY(3, 5, KEY_BACK) -}; - -static const struct matrix_keymap_data mx51_3ds_map_data __initconst = { - .keymap = mx51_3ds_board_keymap, - .keymap_size = ARRAY_SIZE(mx51_3ds_board_keymap), -}; - -static int mx51_3ds_spi2_cs[] = { - MXC_SPI_CS(0), - MX51_3DS_ECSPI2_CS, -}; - -static const struct spi_imx_master mx51_3ds_ecspi2_pdata __initconst = { - .chipselect = mx51_3ds_spi2_cs, - .num_chipselect = ARRAY_SIZE(mx51_3ds_spi2_cs), -}; - -static struct spi_board_info mx51_3ds_spi_nor_device[] = { - { - .modalias = "m25p80", - .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ - .bus_num = 1, - .chip_select = 1, - .mode = SPI_MODE_0, - .platform_data = NULL,}, -}; - -/* - * Board specific initialization. - */ -static void __init mx51_3ds_init(void) -{ - imx51_soc_init(); - - mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads, - ARRAY_SIZE(mx51_3ds_pads)); - - imx51_add_imx_uart(0, &uart_pdata); - imx51_add_imx_uart(1, &uart_pdata); - imx51_add_imx_uart(2, &uart_pdata); - - imx51_add_ecspi(1, &mx51_3ds_ecspi2_pdata); - spi_register_board_info(mx51_3ds_spi_nor_device, - ARRAY_SIZE(mx51_3ds_spi_nor_device)); - - if (mxc_expio_init(MX51_CS5_BASE_ADDR, IMX_GPIO_NR(1, 6))) - printk(KERN_WARNING "Init of the debugboard failed, all " - "devices on the board are unusable.\n"); - - imx51_add_sdhci_esdhc_imx(0, NULL); - imx51_add_imx_keypad(&mx51_3ds_map_data); - imx51_add_imx2_wdt(0); -} - -static void __init mx51_3ds_timer_init(void) -{ - mx51_clocks_init(32768, 24000000, 22579200, 0); -} - -MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board") - /* Maintainer: Freescale Semiconductor, Inc. */ - .atag_offset = 0x100, - .map_io = mx51_map_io, - .init_early = imx51_init_early, - .init_irq = mx51_init_irq, - .handle_irq = imx51_handle_irq, - .init_time = mx51_3ds_timer_init, - .init_machine = mx51_3ds_init, - .init_late = imx51_init_late, - .restart = mxc_restart, -MACHINE_END diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c index 79d71cf23a1..cf34994cfe2 100644 --- a/arch/arm/mach-imx/mm-imx5.c +++ b/arch/arm/mach-imx/mm-imx5.c @@ -24,16 +24,6 @@ #include "iomux-v3.h" /* - * Define the MX50 memory map. - */ -static struct map_desc mx50_io_desc[] __initdata = { - imx_map_entry(MX50, TZIC, MT_DEVICE), - imx_map_entry(MX50, SPBA0, MT_DEVICE), - imx_map_entry(MX50, AIPS1, MT_DEVICE), - imx_map_entry(MX50, AIPS2, MT_DEVICE), -}; - -/* * Define the MX51 memory map. */ static struct map_desc mx51_io_desc[] __initdata = { @@ -59,11 +49,6 @@ static struct map_desc mx53_io_desc[] __initdata = { * system startup to create static physical to virtual memory mappings * for the IO modules. */ -void __init mx50_map_io(void) -{ - iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc)); -} - void __init mx51_map_io(void) { iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc)); @@ -74,13 +59,6 @@ void __init mx53_map_io(void) iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc)); } -void __init imx50_init_early(void) -{ - mxc_set_cpu_type(MXC_CPU_MX50); - mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR)); - mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR)); -} - /* * The MIPI HSC unit has been removed from the i.MX51 Reference Manual by * the Freescale marketing division. However this did not remove the @@ -115,11 +93,6 @@ void __init imx53_init_early(void) mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR)); } -void __init mx50_init_irq(void) -{ - tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR)); -} - void __init mx51_init_irq(void) { tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR)); @@ -148,31 +121,10 @@ static struct sdma_platform_data imx51_sdma_pdata __initdata = { .script_addrs = &imx51_sdma_script, }; -static const struct resource imx50_audmux_res[] __initconst = { - DEFINE_RES_MEM(MX50_AUDMUX_BASE_ADDR, SZ_16K), -}; - static const struct resource imx51_audmux_res[] __initconst = { DEFINE_RES_MEM(MX51_AUDMUX_BASE_ADDR, SZ_16K), }; -void __init imx50_soc_init(void) -{ - mxc_device_init(); - - /* i.mx50 has the i.mx35 type gpio */ - mxc_register_gpio("imx35-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH); - mxc_register_gpio("imx35-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH); - mxc_register_gpio("imx35-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH); - mxc_register_gpio("imx35-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH); - mxc_register_gpio("imx35-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH); - mxc_register_gpio("imx35-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH); - - /* i.mx50 has the i.mx31 type audmux */ - platform_device_register_simple("imx31-audmux", 0, imx50_audmux_res, - ARRAY_SIZE(imx50_audmux_res)); -} - void __init imx51_soc_init(void) { mxc_device_init(); diff --git a/arch/arm/mach-imx/mx50.h b/arch/arm/mach-imx/mx50.h deleted file mode 100644 index 09ac19c1570..00000000000 --- a/arch/arm/mach-imx/mx50.h +++ /dev/null @@ -1,290 +0,0 @@ -#ifndef __MACH_MX50_H__ -#define __MACH_MX50_H__ - -/* - * IROM - */ -#define MX50_IROM_BASE_ADDR 0x0 -#define MX50_IROM_SIZE SZ_64K - -/* TZIC */ -#define MX50_TZIC_BASE_ADDR 0x0fffc000 -#define MX50_TZIC_SIZE SZ_16K - -/* - * IRAM - */ -#define MX50_IRAM_BASE_ADDR 0xf8000000 /* internal ram */ -#define MX50_IRAM_PARTITIONS 16 -#define MX50_IRAM_SIZE (MX50_IRAM_PARTITIONS * SZ_8K) /* 128KB */ - -/* - * Databahn - */ -#define MX50_DATABAHN_BASE_ADDR 0x14000000 - -/* - * Graphics Memory of GPU - */ -#define MX50_GPU2D_BASE_ADDR 0x20000000 - -#define MX50_DEBUG_BASE_ADDR 0x40000000 -#define MX50_DEBUG_SIZE SZ_1M -#define MX50_ETB_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x00001000) -#define MX50_ETM_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x00002000) -#define MX50_TPIU_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x00003000) -#define MX50_CTI0_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x00004000) -#define MX50_CTI1_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x00005000) -#define MX50_CTI2_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x00006000) -#define MX50_CTI3_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x00007000) -#define MX50_CORTEX_DBG_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x00008000) - -#define MX50_APBHDMA_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x01000000) -#define MX50_OCOTP_CTRL_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x01002000) -#define MX50_DIGCTL_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x01004000) -#define MX50_GPMI_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x01006000) -#define MX50_BCH_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x01008000) -#define MX50_ELCDIF_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x0100a000) -#define MX50_EPXP_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x0100c000) -#define MX50_DCP_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x0100e000) -#define MX50_EPDC_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x01010000) -#define MX50_QOSC_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x01012000) -#define MX50_PERFMON_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x01014000) -#define MX50_SSP_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x01016000) -#define MX50_ANATOP_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x01018000) -#define MX50_NIC_BASE_ADDR (MX50_DEBUG_BASE_ADDR + 0x08000000) - -/* - * SPBA global module enabled #0 - */ -#define MX50_SPBA0_BASE_ADDR 0x50000000 -#define MX50_SPBA0_SIZE SZ_1M - -#define MX50_MMC_SDHC1_BASE_ADDR (MX50_SPBA0_BASE_ADDR + 0x00004000) -#define MX50_MMC_SDHC2_BASE_ADDR (MX50_SPBA0_BASE_ADDR + 0x00008000) -#define MX50_UART3_BASE_ADDR (MX50_SPBA0_BASE_ADDR + 0x0000c000) -#define MX50_CSPI1_BASE_ADDR (MX50_SPBA0_BASE_ADDR + 0x00010000) -#define MX50_SSI2_BASE_ADDR (MX50_SPBA0_BASE_ADDR + 0x00014000) -#define MX50_MMC_SDHC3_BASE_ADDR (MX50_SPBA0_BASE_ADDR + 0x00020000) -#define MX50_MMC_SDHC4_BASE_ADDR (MX50_SPBA0_BASE_ADDR + 0x00024000) - -/* - * AIPS 1 - */ -#define MX50_AIPS1_BASE_ADDR 0x53f00000 -#define MX50_AIPS1_SIZE SZ_1M - -#define MX50_OTG_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x00080000) -#define MX50_GPIO1_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x00084000) -#define MX50_GPIO2_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x00088000) -#define MX50_GPIO3_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x0008c000) -#define MX50_GPIO4_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x00090000) -#define MX50_KPP_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x00094000) -#define MX50_WDOG_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x00098000) -#define MX50_GPT1_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000a0000) -#define MX50_SRTC_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000a4000) -#define MX50_IOMUXC_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000a8000) -#define MX50_EPIT1_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000ac000) -#define MX50_PWM1_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000b4000) -#define MX50_PWM2_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000b8000) -#define MX50_UART1_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000bc000) -#define MX50_UART2_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000c0000) -#define MX50_SRC_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000d0000) -#define MX50_CCM_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000d4000) -#define MX50_GPC_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000d8000) -#define MX50_GPIO5_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000dc000) -#define MX50_GPIO6_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000e0000) -#define MX50_I2C3_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000ec000) -#define MX50_UART4_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000f0000) - -#define MX50_MSHC_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000f4000) -#define MX50_RNGB_BASE_ADDR (MX50_AIPS1_BASE_ADDR + 0x000f8000) - -/* - * AIPS 2 - */ -#define MX50_AIPS2_BASE_ADDR 0x63f00000 -#define MX50_AIPS2_SIZE SZ_1M - -#define MX50_PLL1_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x00080000) -#define MX50_PLL2_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x00084000) -#define MX50_PLL3_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x00088000) -#define MX50_UART5_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x00090000) -#define MX50_AHBMAX_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x00094000) -#define MX50_ARM_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x000a0000) -#define MX50_OWIRE_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x000a4000) -#define MX50_CSPI2_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x000ac000) -#define MX50_SDMA_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x000b0000) -#define MX50_ROMCP_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x000b8000) -#define MX50_CSPI3_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x000c0000) -#define MX50_I2C2_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x000c4000) -#define MX50_I2C1_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x000c8000) -#define MX50_SSI1_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x000cc000) -#define MX50_AUDMUX_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x000d0000) -#define MX50_WEIM_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x000d8000) -#define MX50_FEC_BASE_ADDR (MX50_AIPS2_BASE_ADDR + 0x000ec000) - -/* - * Memory regions and CS - */ -#define MX50_CSD0_BASE_ADDR 0x70000000 -#define MX50_CSD1_BASE_ADDR 0xb0000000 -#define MX50_CS0_BASE_ADDR 0xf0000000 - -#define MX50_IO_P2V(x) IMX_IO_P2V(x) -#define MX50_IO_ADDRESS(x) IOMEM(MX50_IO_P2V(x)) - -/* - * defines for SPBA modules - */ -#define MX50_SPBA_SDHC1 0x04 -#define MX50_SPBA_SDHC2 0x08 -#define MX50_SPBA_UART3 0x0c -#define MX50_SPBA_CSPI1 0x10 -#define MX50_SPBA_SSI2 0x14 -#define MX50_SPBA_SDHC3 0x20 -#define MX50_SPBA_SDHC4 0x24 -#define MX50_SPBA_SPDIF 0x28 -#define MX50_SPBA_ATA 0x30 -#define MX50_SPBA_SLIM 0x34 -#define MX50_SPBA_HSI2C 0x38 -#define MX50_SPBA_CTRL 0x3c - -/* - * DMA request assignments - */ -#define MX50_DMA_REQ_GPC 1 -#define MX50_DMA_REQ_ATA_UART4_RX 2 -#define MX50_DMA_REQ_ATA_UART4_TX 3 -#define MX50_DMA_REQ_CSPI1_RX 6 -#define MX50_DMA_REQ_CSPI1_TX 7 -#define MX50_DMA_REQ_CSPI2_RX 8 -#define MX50_DMA_REQ_CSPI2_TX 9 -#define MX50_DMA_REQ_I2C3_SDHC3 10 -#define MX50_DMA_REQ_SDHC4 11 -#define MX50_DMA_REQ_UART2_FIRI_RX 12 -#define MX50_DMA_REQ_UART2_FIRI_TX 13 -#define MX50_DMA_REQ_EXT0 14 -#define MX50_DMA_REQ_EXT1 15 -#define MX50_DMA_REQ_UART5_RX 16 -#define MX50_DMA_REQ_UART5_TX 17 -#define MX50_DMA_REQ_UART1_RX 18 -#define MX50_DMA_REQ_UART1_TX 19 -#define MX50_DMA_REQ_I2C1_SDHC1 20 -#define MX50_DMA_REQ_I2C2_SDHC2 21 -#define MX50_DMA_REQ_SSI2_RX2 22 -#define MX50_DMA_REQ_SSI2_TX2 23 -#define MX50_DMA_REQ_SSI2_RX1 24 -#define MX50_DMA_REQ_SSI2_TX1 25 -#define MX50_DMA_REQ_SSI1_RX2 26 -#define MX50_DMA_REQ_SSI1_TX2 27 -#define MX50_DMA_REQ_SSI1_RX1 28 -#define MX50_DMA_REQ_SSI1_TX1 29 -#define MX50_DMA_REQ_CSPI_RX 38 -#define MX50_DMA_REQ_CSPI_TX 39 -#define MX50_DMA_REQ_UART3_RX 42 -#define MX50_DMA_REQ_UART3_TX 43 - -/* - * Interrupt numbers - */ -#include <asm/irq.h> -#define MX50_INT_MMC_SDHC1 (NR_IRQS_LEGACY + 1) -#define MX50_INT_MMC_SDHC2 (NR_IRQS_LEGACY + 2) -#define MX50_INT_MMC_SDHC3 (NR_IRQS_LEGACY + 3) -#define MX50_INT_MMC_SDHC4 (NR_IRQS_LEGACY + 4) -#define MX50_INT_DAP (NR_IRQS_LEGACY + 5) -#define MX50_INT_SDMA (NR_IRQS_LEGACY + 6) -#define MX50_INT_IOMUX (NR_IRQS_LEGACY + 7) -#define MX50_INT_UART4 (NR_IRQS_LEGACY + 13) -#define MX50_INT_USB_H1 (NR_IRQS_LEGACY + 14) -#define MX50_INT_USB_OTG (NR_IRQS_LEGACY + 18) -#define MX50_INT_DATABAHN (NR_IRQS_LEGACY + 19) -#define MX50_INT_ELCDIF (NR_IRQS_LEGACY + 20) -#define MX50_INT_EPXP (NR_IRQS_LEGACY + 21) -#define MX50_INT_SRTC_NTZ (NR_IRQS_LEGACY + 24) -#define MX50_INT_SRTC_TZ (NR_IRQS_LEGACY + 25) -#define MX50_INT_EPDC (NR_IRQS_LEGACY + 27) -#define MX50_INT_NIC (NR_IRQS_LEGACY + 28) -#define MX50_INT_SSI1 (NR_IRQS_LEGACY + 29) -#define MX50_INT_SSI2 (NR_IRQS_LEGACY + 30) -#define MX50_INT_UART1 (NR_IRQS_LEGACY + 31) -#define MX50_INT_UART2 (NR_IRQS_LEGACY + 32) -#define MX50_INT_UART3 (NR_IRQS_LEGACY + 33) -#define MX50_INT_RESV34 (NR_IRQS_LEGACY + 34) -#define MX50_INT_RESV35 (NR_IRQS_LEGACY + 35) -#define MX50_INT_CSPI1 (NR_IRQS_LEGACY + 36) -#define MX50_INT_CSPI2 (NR_IRQS_LEGACY + 37) -#define MX50_INT_CSPI (NR_IRQS_LEGACY + 38) -#define MX50_INT_GPT (NR_IRQS_LEGACY + 39) -#define MX50_INT_EPIT1 (NR_IRQS_LEGACY + 40) -#define MX50_INT_GPIO1_INT7 (NR_IRQS_LEGACY + 42) -#define MX50_INT_GPIO1_INT6 (NR_IRQS_LEGACY + 43) -#define MX50_INT_GPIO1_INT5 (NR_IRQS_LEGACY + 44) -#define MX50_INT_GPIO1_INT4 (NR_IRQS_LEGACY + 45) -#define MX50_INT_GPIO1_INT3 (NR_IRQS_LEGACY + 46) -#define MX50_INT_GPIO1_INT2 (NR_IRQS_LEGACY + 47) -#define MX50_INT_GPIO1_INT1 (NR_IRQS_LEGACY + 48) -#define MX50_INT_GPIO1_INT0 (NR_IRQS_LEGACY + 49) -#define MX50_INT_GPIO1_LOW (NR_IRQS_LEGACY + 50) -#define MX50_INT_GPIO1_HIGH (NR_IRQS_LEGACY + 51) -#define MX50_INT_GPIO2_LOW (NR_IRQS_LEGACY + 52) -#define MX50_INT_GPIO2_HIGH (NR_IRQS_LEGACY + 53) -#define MX50_INT_GPIO3_LOW (NR_IRQS_LEGACY + 54) -#define MX50_INT_GPIO3_HIGH (NR_IRQS_LEGACY + 55) -#define MX50_INT_GPIO4_LOW (NR_IRQS_LEGACY + 56) -#define MX50_INT_GPIO4_HIGH (NR_IRQS_LEGACY + 57) -#define MX50_INT_WDOG1 (NR_IRQS_LEGACY + 58) -#define MX50_INT_KPP (NR_IRQS_LEGACY + 60) -#define MX50_INT_PWM1 (NR_IRQS_LEGACY + 61) -#define MX50_INT_I2C1 (NR_IRQS_LEGACY + 62) -#define MX50_INT_I2C2 (NR_IRQS_LEGACY + 63) -#define MX50_INT_I2C3 (NR_IRQS_LEGACY + 64) -#define MX50_INT_RESV65 (NR_IRQS_LEGACY + 65) -#define MX50_INT_DCDC (NR_IRQS_LEGACY + 66) -#define MX50_INT_THERMAL_ALARM (NR_IRQS_LEGACY + 67) -#define MX50_INT_ANA3 (NR_IRQS_LEGACY + 68) -#define MX50_INT_ANA4 (NR_IRQS_LEGACY + 69) -#define MX50_INT_CCM1 (NR_IRQS_LEGACY + 71) -#define MX50_INT_CCM2 (NR_IRQS_LEGACY + 72) -#define MX50_INT_GPC1 (NR_IRQS_LEGACY + 73) -#define MX50_INT_GPC2 (NR_IRQS_LEGACY + 74) -#define MX50_INT_SRC (NR_IRQS_LEGACY + 75) -#define MX50_INT_NM (NR_IRQS_LEGACY + 76) -#define MX50_INT_PMU (NR_IRQS_LEGACY + 77) -#define MX50_INT_CTI_IRQ (NR_IRQS_LEGACY + 78) -#define MX50_INT_CTI1_TG0 (NR_IRQS_LEGACY + 79) -#define MX50_INT_CTI1_TG1 (NR_IRQS_LEGACY + 80) -#define MX50_INT_GPU2_IRQ (NR_IRQS_LEGACY + 84) -#define MX50_INT_GPU2_BUSY (NR_IRQS_LEGACY + 85) -#define MX50_INT_UART5 (NR_IRQS_LEGACY + 86) -#define MX50_INT_FEC (NR_IRQS_LEGACY + 87) -#define MX50_INT_OWIRE (NR_IRQS_LEGACY + 88) -#define MX50_INT_CTI1_TG2 (NR_IRQS_LEGACY + 89) -#define MX50_INT_SJC (NR_IRQS_LEGACY + 90) -#define MX50_INT_DCP_CHAN1_3 (NR_IRQS_LEGACY + 91) -#define MX50_INT_DCP_CHAN0 (NR_IRQS_LEGACY + 92) -#define MX50_INT_PWM2 (NR_IRQS_LEGACY + 94) -#define MX50_INT_RNGB (NR_IRQS_LEGACY + 97) -#define MX50_INT_CTI1_TG3 (NR_IRQS_LEGACY + 98) -#define MX50_INT_RAWNAND_BCH (NR_IRQS_LEGACY + 100) -#define MX50_INT_RAWNAND_GPMI (NR_IRQS_LEGACY + 102) -#define MX50_INT_GPIO5_LOW (NR_IRQS_LEGACY + 103) -#define MX50_INT_GPIO5_HIGH (NR_IRQS_LEGACY + 104) -#define MX50_INT_GPIO6_LOW (NR_IRQS_LEGACY + 105) -#define MX50_INT_GPIO6_HIGH (NR_IRQS_LEGACY + 106) -#define MX50_INT_MSHC (NR_IRQS_LEGACY + 109) -#define MX50_INT_APBHDMA_CHAN0 (NR_IRQS_LEGACY + 110) -#define MX50_INT_APBHDMA_CHAN1 (NR_IRQS_LEGACY + 111) -#define MX50_INT_APBHDMA_CHAN2 (NR_IRQS_LEGACY + 112) -#define MX50_INT_APBHDMA_CHAN3 (NR_IRQS_LEGACY + 113) -#define MX50_INT_APBHDMA_CHAN4 (NR_IRQS_LEGACY + 114) -#define MX50_INT_APBHDMA_CHAN5 (NR_IRQS_LEGACY + 115) -#define MX50_INT_APBHDMA_CHAN6 (NR_IRQS_LEGACY + 116) -#define MX50_INT_APBHDMA_CHAN7 (NR_IRQS_LEGACY + 117) - -#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS) -extern int mx50_revision(void); -#endif - -#endif /* ifndef __MACH_MX50_H__ */ diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h index d78298366a9..7dce17a9fe6 100644 --- a/arch/arm/mach-imx/mxc.h +++ b/arch/arm/mach-imx/mxc.h @@ -32,7 +32,6 @@ #define MXC_CPU_MX27 27 #define MXC_CPU_MX31 31 #define MXC_CPU_MX35 35 -#define MXC_CPU_MX50 50 #define MXC_CPU_MX51 51 #define MXC_CPU_MX53 53 @@ -126,18 +125,6 @@ extern unsigned int __mxc_cpu_type; # define cpu_is_mx35() (0) #endif -#ifdef CONFIG_SOC_IMX50 -# ifdef mxc_cpu_type -# undef mxc_cpu_type -# define mxc_cpu_type __mxc_cpu_type -# else -# define mxc_cpu_type MXC_CPU_MX50 -# endif -# define cpu_is_mx50() (mxc_cpu_type == MXC_CPU_MX50) -#else -# define cpu_is_mx50() (0) -#endif - #ifdef CONFIG_SOC_IMX51 # ifdef mxc_cpu_type # undef mxc_cpu_type diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c index 3777b805b76..b2872ec614a 100644 --- a/arch/arm/mach-imx/platsmp.c +++ b/arch/arm/mach-imx/platsmp.c @@ -12,9 +12,9 @@ #include <linux/init.h> #include <linux/smp.h> +#include <linux/irqchip/arm-gic.h> #include <asm/page.h> #include <asm/smp_scu.h> -#include <asm/hardware/gic.h> #include <asm/mach/map.h> #include "common.h" @@ -71,8 +71,6 @@ static void __init imx_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } void imx_smp_prepare(void) @@ -92,5 +90,6 @@ struct smp_operations imx_smp_ops __initdata = { .smp_boot_secondary = imx_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = imx_cpu_die, + .cpu_kill = imx_cpu_kill, #endif }; diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c index 2e063c2deb9..f67fd7ee812 100644 --- a/arch/arm/mach-imx/pm-imx5.c +++ b/arch/arm/mach-imx/pm-imx5.c @@ -34,7 +34,7 @@ /* * set cpu low power mode before WFI instruction. This function is called - * mx5 because it can be used for mx50, mx51, and mx53. + * mx5 because it can be used for mx51, and mx53. */ static void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode) { @@ -85,10 +85,7 @@ static void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode) __raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC); __raw_writel(ccm_clpcr, MXC_CCM_CLPCR); __raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR); - - /* Enable NEON SRPG for all but MX50TO1.0. */ - if (mx50_revision() != IMX_CHIP_REVISION_1_0) - __raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR); + __raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR); if (stop_mode) { empgc0 |= MXC_SRPGCR_PCR; diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c index a17543da602..ee42d20cba1 100644 --- a/arch/arm/mach-imx/pm-imx6q.c +++ b/arch/arm/mach-imx/pm-imx6q.c @@ -41,6 +41,7 @@ static int imx6q_pm_enter(suspend_state_t state) cpu_suspend(0, imx6q_suspend_finish); imx_smp_prepare(); imx_gpc_post_resume(); + imx6q_set_lpm(WAIT_CLOCKED); break; default: return -EINVAL; diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c index f017302f6d0..62769df36db 100644 --- a/arch/arm/mach-imx/time.c +++ b/arch/arm/mach-imx/time.c @@ -256,7 +256,6 @@ static struct irqaction mxc_timer_irq = { static struct clock_event_device clockevent_mxc = { .name = "mxc_timer1", .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .set_mode = mxc_set_mode, .set_next_event = mx1_2_set_next_event, .rating = 200, @@ -264,21 +263,13 @@ static struct clock_event_device clockevent_mxc = { static int __init mxc_clockevent_init(struct clk *timer_clk) { - unsigned int c = clk_get_rate(timer_clk); - if (timer_is_v2()) clockevent_mxc.set_next_event = v2_set_next_event; - clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC, - clockevent_mxc.shift); - clockevent_mxc.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &clockevent_mxc); - clockevent_mxc.min_delta_ns = - clockevent_delta2ns(0xff, &clockevent_mxc); - clockevent_mxc.cpumask = cpumask_of(0); - - clockevents_register_device(&clockevent_mxc); + clockevents_config_and_register(&clockevent_mxc, + clk_get_rate(timer_clk), + 0xff, 0xfffffffe); return 0; } diff --git a/arch/arm/mach-integrator/include/mach/uncompress.h b/arch/arm/mach-integrator/include/mach/uncompress.h index 30452f00a16..8f3cc9954c1 100644 --- a/arch/arm/mach-integrator/include/mach/uncompress.h +++ b/arch/arm/mach-integrator/include/mach/uncompress.h @@ -46,5 +46,3 @@ static inline void flush(void) * nothing to do */ #define arch_decomp_setup() - -#define arch_decomp_wdog() diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c index be50e795536..e7fcea7f330 100644 --- a/arch/arm/mach-integrator/pci_v3.c +++ b/arch/arm/mach-integrator/pci_v3.c @@ -475,13 +475,12 @@ int __init pci_v3_setup(int nr, struct pci_sys_data *sys) { int ret = 0; + if (!ap_syscon_base) + return -EINVAL; + if (nr == 0) { sys->mem_offset = PHYS_PCI_MEM_BASE; ret = pci_v3_setup_resources(sys); - /* Remap the Integrator system controller */ - ap_syscon_base = ioremap(INTEGRATOR_SC_BASE, 0x100); - if (!ap_syscon_base) - return -EINVAL; } return ret; @@ -497,6 +496,13 @@ void __init pci_v3_preinit(void) unsigned int temp; int ret; + /* Remap the Integrator system controller */ + ap_syscon_base = ioremap(INTEGRATOR_SC_BASE, 0x100); + if (!ap_syscon_base) { + pr_err("unable to remap the AP syscon for PCIv3\n"); + return; + } + pcibios_min_mem = 0x00100000; /* diff --git a/arch/arm/mach-iop13xx/include/mach/uncompress.h b/arch/arm/mach-iop13xx/include/mach/uncompress.h index fa4f80522fa..d3791ece277 100644 --- a/arch/arm/mach-iop13xx/include/mach/uncompress.h +++ b/arch/arm/mach-iop13xx/include/mach/uncompress.h @@ -20,4 +20,3 @@ static inline void flush(void) * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-iop32x/include/mach/uncompress.h b/arch/arm/mach-iop32x/include/mach/uncompress.h index 4fd715496f4..b3d45fd365e 100644 --- a/arch/arm/mach-iop32x/include/mach/uncompress.h +++ b/arch/arm/mach-iop32x/include/mach/uncompress.h @@ -36,4 +36,3 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id) * nothing to do */ #define arch_decomp_setup() __arch_decomp_setup(arch_id) -#define arch_decomp_wdog() diff --git a/arch/arm/mach-iop33x/include/mach/uncompress.h b/arch/arm/mach-iop33x/include/mach/uncompress.h index f99bb848c5a..ed282e14176 100644 --- a/arch/arm/mach-iop33x/include/mach/uncompress.h +++ b/arch/arm/mach-iop33x/include/mach/uncompress.h @@ -34,4 +34,3 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id) * nothing to do */ #define arch_decomp_setup() __arch_decomp_setup(arch_id) -#define arch_decomp_wdog() diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index f6ac695ceb6..1dbeb7c99d5 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -519,22 +519,15 @@ static struct clock_event_device clockevent_ixp4xx = { .name = "ixp4xx timer1", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .rating = 200, - .shift = 24, .set_mode = ixp4xx_set_mode, .set_next_event = ixp4xx_set_next_event, }; static void __init ixp4xx_clockevent_init(void) { - clockevent_ixp4xx.mult = div_sc(IXP4XX_TIMER_FREQ, NSEC_PER_SEC, - clockevent_ixp4xx.shift); - clockevent_ixp4xx.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &clockevent_ixp4xx); - clockevent_ixp4xx.min_delta_ns = - clockevent_delta2ns(0xf, &clockevent_ixp4xx); clockevent_ixp4xx.cpumask = cpumask_of(0); - - clockevents_register_device(&clockevent_ixp4xx); + clockevents_config_and_register(&clockevent_ixp4xx, IXP4XX_TIMER_FREQ, + 0xf, 0xfffffffe); } void ixp4xx_restart(char mode, const char *cmd) diff --git a/arch/arm/mach-ixp4xx/include/mach/uncompress.h b/arch/arm/mach-ixp4xx/include/mach/uncompress.h index eb945a926d0..7b25c0225e4 100644 --- a/arch/arm/mach-ixp4xx/include/mach/uncompress.h +++ b/arch/arm/mach-ixp4xx/include/mach/uncompress.h @@ -53,6 +53,4 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id) */ #define arch_decomp_setup() __arch_decomp_setup(arch_id) -#define arch_decomp_wdog() - #endif diff --git a/arch/arm/mach-kirkwood/board-ib62x0.c b/arch/arm/mach-kirkwood/board-ib62x0.c index 9f6f496380d..9a857ae8398 100644 --- a/arch/arm/mach-kirkwood/board-ib62x0.c +++ b/arch/arm/mach-kirkwood/board-ib62x0.c @@ -14,7 +14,6 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/mv643xx_eth.h> -#include <linux/input.h> #include "common.h" static struct mv643xx_eth_platform_data ib62x0_ge00_data = { diff --git a/arch/arm/mach-kirkwood/board-mplcec4.c b/arch/arm/mach-kirkwood/board-mplcec4.c index 56bfe5a1605..3264925b831 100644 --- a/arch/arm/mach-kirkwood/board-mplcec4.c +++ b/arch/arm/mach-kirkwood/board-mplcec4.c @@ -14,7 +14,6 @@ #include <linux/mv643xx_eth.h> #include <linux/platform_data/mmc-mvsdio.h> #include "common.h" -#include "mpp.h" static struct mv643xx_eth_platform_data mplcec4_ge00_data = { .phy_addr = MV643XX_ETH_PHY_ADDR(1), diff --git a/arch/arm/mach-kirkwood/board-ns2.c b/arch/arm/mach-kirkwood/board-ns2.c index 8821720ab5a..f4632a809f6 100644 --- a/arch/arm/mach-kirkwood/board-ns2.c +++ b/arch/arm/mach-kirkwood/board-ns2.c @@ -18,47 +18,11 @@ #include <linux/gpio.h> #include <linux/of.h> #include "common.h" -#include "mpp.h" static struct mv643xx_eth_platform_data ns2_ge00_data = { .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; -static unsigned int ns2_mpp_config[] __initdata = { - MPP0_SPI_SCn, - MPP1_SPI_MOSI, - MPP2_SPI_SCK, - MPP3_SPI_MISO, - MPP4_NF_IO6, - MPP5_NF_IO7, - MPP6_SYSRST_OUTn, - MPP7_GPO, /* Fan speed (bit 1) */ - MPP8_TW0_SDA, - MPP9_TW0_SCK, - MPP10_UART0_TXD, - MPP11_UART0_RXD, - MPP12_GPO, /* Red led */ - MPP14_GPIO, /* USB fuse */ - MPP16_GPIO, /* SATA 0 power */ - MPP17_GPIO, /* SATA 1 power */ - MPP18_NF_IO0, - MPP19_NF_IO1, - MPP20_SATA1_ACTn, - MPP21_SATA0_ACTn, - MPP22_GPIO, /* Fan speed (bit 0) */ - MPP23_GPIO, /* Fan power */ - MPP24_GPIO, /* USB mode select */ - MPP25_GPIO, /* Fan rotation fail */ - MPP26_GPIO, /* USB device vbus */ - MPP28_GPIO, /* USB enable host vbus */ - MPP29_GPIO, /* Blue led (slow register) */ - MPP30_GPIO, /* Blue led (command register) */ - MPP31_GPIO, /* Board power off */ - MPP32_GPIO, /* Power button (0 = Released, 1 = Pushed) */ - MPP33_GPO, /* Fan speed (bit 2) */ - 0 -}; - #define NS2_GPIO_POWER_OFF 31 static void ns2_power_off(void) @@ -71,8 +35,6 @@ void __init ns2_init(void) /* * Basic setup. Needs to be called early. */ - kirkwood_mpp_conf(ns2_mpp_config); - if (of_machine_is_compatible("lacie,netspace_lite_v2") || of_machine_is_compatible("lacie,netspace_mini_v2")) ns2_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0); diff --git a/arch/arm/mach-kirkwood/board-nsa310.c b/arch/arm/mach-kirkwood/board-nsa310.c index f58d2e1a404..61c4b189d06 100644 --- a/arch/arm/mach-kirkwood/board-nsa310.c +++ b/arch/arm/mach-kirkwood/board-nsa310.c @@ -10,12 +10,9 @@ #include <linux/kernel.h> #include <linux/init.h> -#include <linux/i2c.h> #include <linux/gpio.h> - -#include <asm/mach-types.h> -#include <asm/mach/arch.h> #include <mach/kirkwood.h> +#include <linux/of.h> #include "common.h" #include "mpp.h" @@ -79,14 +76,10 @@ static void __init nsa310_gpio_init(void) void __init nsa310_init(void) { - u32 dev, rev; - kirkwood_mpp_conf(nsa310_mpp_config); nsa310_gpio_init(); - kirkwood_pcie_id(&dev, &rev); - i2c_register_board_info(0, ARRAY_AND_SIZE(nsa310_i2c_info)); } diff --git a/arch/arm/mach-kirkwood/dockstar-setup.c b/arch/arm/mach-kirkwood/dockstar-setup.c index 77f98f2b041..060ccf9cb63 100644 --- a/arch/arm/mach-kirkwood/dockstar-setup.c +++ b/arch/arm/mach-kirkwood/dockstar-setup.c @@ -19,7 +19,6 @@ #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <mach/kirkwood.h> -#include <linux/platform_data/mmc-mvsdio.h> #include "common.h" #include "mpp.h" diff --git a/arch/arm/mach-kirkwood/include/mach/uncompress.h b/arch/arm/mach-kirkwood/include/mach/uncompress.h index 75d5497df3a..5bca5534021 100644 --- a/arch/arm/mach-kirkwood/include/mach/uncompress.h +++ b/arch/arm/mach-kirkwood/include/mach/uncompress.h @@ -44,4 +44,3 @@ static void flush(void) * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-ks8695/include/mach/uncompress.h b/arch/arm/mach-ks8695/include/mach/uncompress.h index 8879d610308..c089a1aea67 100644 --- a/arch/arm/mach-ks8695/include/mach/uncompress.h +++ b/arch/arm/mach-ks8695/include/mach/uncompress.h @@ -32,6 +32,5 @@ static inline void flush(void) } #define arch_decomp_setup() -#define arch_decomp_wdog() #endif diff --git a/arch/arm/mach-lpc32xx/include/mach/uncompress.h b/arch/arm/mach-lpc32xx/include/mach/uncompress.h index c142487d299..1198a89183c 100644 --- a/arch/arm/mach-lpc32xx/include/mach/uncompress.h +++ b/arch/arm/mach-lpc32xx/include/mach/uncompress.h @@ -55,6 +55,5 @@ static inline void flush(void) /* NULL functions; we don't presently need them */ #define arch_decomp_setup() -#define arch_decomp_wdog() #endif diff --git a/arch/arm/mach-lpc32xx/timer.c b/arch/arm/mach-lpc32xx/timer.c index 88bd4ce3b94..20eab63d10b 100644 --- a/arch/arm/mach-lpc32xx/timer.c +++ b/arch/arm/mach-lpc32xx/timer.c @@ -70,7 +70,6 @@ static void lpc32xx_clkevt_mode(enum clock_event_mode mode, static struct clock_event_device lpc32xx_clkevt = { .name = "lpc32xx_clkevt", .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .rating = 300, .set_next_event = lpc32xx_clkevt_next_event, .set_mode = lpc32xx_clkevt_mode, @@ -141,14 +140,8 @@ void __init lpc32xx_timer_init(void) setup_irq(IRQ_LPC32XX_TIMER0, &lpc32xx_timer_irq); /* Setup the clockevent structure. */ - lpc32xx_clkevt.mult = div_sc(clkrate, NSEC_PER_SEC, - lpc32xx_clkevt.shift); - lpc32xx_clkevt.max_delta_ns = clockevent_delta2ns(-1, - &lpc32xx_clkevt); - lpc32xx_clkevt.min_delta_ns = clockevent_delta2ns(1, - &lpc32xx_clkevt) + 1; lpc32xx_clkevt.cpumask = cpumask_of(0); - clockevents_register_device(&lpc32xx_clkevt); + clockevents_config_and_register(&lpc32xx_clkevt, clkrate, 1, -1); /* Use timer1 as clock source. */ __raw_writel(LPC32XX_TIMER_CNTR_TCR_RESET, diff --git a/arch/arm/mach-mmp/include/mach/uncompress.h b/arch/arm/mach-mmp/include/mach/uncompress.h index d6daeb7e4ef..8890fa8fa77 100644 --- a/arch/arm/mach-mmp/include/mach/uncompress.h +++ b/arch/arm/mach-mmp/include/mach/uncompress.h @@ -43,9 +43,3 @@ static inline void arch_decomp_setup(void) if (machine_is_avengers_lite()) UART = (unsigned long *)UART3_BASE; } - -/* - * nothing to do - */ - -#define arch_decomp_wdog() diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c index 936447c7097..86a18b3d252 100644 --- a/arch/arm/mach-mmp/time.c +++ b/arch/arm/mach-mmp/time.c @@ -141,7 +141,6 @@ static void timer_set_mode(enum clock_event_mode mode, static struct clock_event_device ckevt = { .name = "clockevent", .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .rating = 200, .set_next_event = timer_set_next_event, .set_mode = timer_set_mode, @@ -198,15 +197,13 @@ void __init timer_init(int irq) setup_sched_clock(mmp_read_sched_clock, 32, CLOCK_TICK_RATE); - ckevt.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt.shift); - ckevt.max_delta_ns = clockevent_delta2ns(MAX_DELTA, &ckevt); - ckevt.min_delta_ns = clockevent_delta2ns(MIN_DELTA, &ckevt); ckevt.cpumask = cpumask_of(0); setup_irq(irq, &timer_irq); clocksource_register_hz(&cksrc, CLOCK_TICK_RATE); - clockevents_register_device(&ckevt); + clockevents_config_and_register(&ckevt, CLOCK_TICK_RATE, + MIN_DELTA, MAX_DELTA); } #ifdef CONFIG_OF diff --git a/arch/arm/mach-msm/board-dt-8660.c b/arch/arm/mach-msm/board-dt-8660.c index 27c41eabfd1..7dcfc5300bb 100644 --- a/arch/arm/mach-msm/board-dt-8660.c +++ b/arch/arm/mach-msm/board-dt-8660.c @@ -11,26 +11,15 @@ */ #include <linux/init.h> +#include <linux/irqchip.h> #include <linux/of.h> -#include <linux/of_irq.h> #include <linux/of_platform.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <mach/board.h> #include "common.h" -static const struct of_device_id msm_dt_gic_match[] __initconst = { - { .compatible = "qcom,msm-8660-qgic", .data = gic_of_init }, - {} -}; - -static void __init msm8x60_init_irq(void) -{ - of_irq_init(msm_dt_gic_match); -} - static void __init msm8x60_init_late(void) { smd_debugfs_init(); @@ -55,8 +44,7 @@ static const char *msm8x60_fluid_match[] __initdata = { DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)") .smp = smp_ops(msm_smp_ops), .map_io = msm_map_msm8x60_io, - .init_irq = msm8x60_init_irq, - .handle_irq = gic_handle_irq, + .init_irq = irqchip_init, .init_machine = msm8x60_dt_init, .init_late = msm8x60_init_late, .init_time = msm_dt_timer_init, diff --git a/arch/arm/mach-msm/board-dt-8960.c b/arch/arm/mach-msm/board-dt-8960.c index 3226d527696..73019363ffa 100644 --- a/arch/arm/mach-msm/board-dt-8960.c +++ b/arch/arm/mach-msm/board-dt-8960.c @@ -11,24 +11,13 @@ */ #include <linux/init.h> -#include <linux/of_irq.h> +#include <linux/irqchip.h> #include <linux/of_platform.h> -#include <asm/hardware/gic.h> #include <asm/mach/arch.h> #include "common.h" -static const struct of_device_id msm_dt_gic_match[] __initconst = { - { .compatible = "qcom,msm-qgic2", .data = gic_of_init }, - { } -}; - -static void __init msm_dt_init_irq(void) -{ - of_irq_init(msm_dt_gic_match); -} - static void __init msm_dt_init(void) { of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); @@ -42,9 +31,8 @@ static const char * const msm8960_dt_match[] __initconst = { DT_MACHINE_START(MSM8960_DT, "Qualcomm MSM (Flattened Device Tree)") .smp = smp_ops(msm_smp_ops), .map_io = msm_map_msm8960_io, - .init_irq = msm_dt_init_irq, + .init_irq = irqchip_init, .init_time = msm_dt_timer_init, .init_machine = msm_dt_init, .dt_compat = msm8960_dt_match, - .handle_irq = gic_handle_irq, MACHINE_END diff --git a/arch/arm/mach-msm/include/mach/uncompress.h b/arch/arm/mach-msm/include/mach/uncompress.h index c14011fe832..fa97a10d869 100644 --- a/arch/arm/mach-msm/include/mach/uncompress.h +++ b/arch/arm/mach-msm/include/mach/uncompress.h @@ -60,8 +60,4 @@ static inline void arch_decomp_setup(void) { } -static inline void arch_decomp_wdog(void) -{ -} - #endif diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c index 7ed69b69c87..42932865416 100644 --- a/arch/arm/mach-msm/platsmp.c +++ b/arch/arm/mach-msm/platsmp.c @@ -15,8 +15,8 @@ #include <linux/jiffies.h> #include <linux/smp.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> -#include <asm/hardware/gic.h> #include <asm/cacheflush.h> #include <asm/cputype.h> #include <asm/mach-types.h> @@ -115,7 +115,7 @@ static int __cpuinit msm_boot_secondary(unsigned int cpu, struct task_struct *id * the boot monitor to read the system wide flags register, * and branch to the address found there. */ - gic_raise_softirq(cpumask_of(cpu), 0); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { @@ -153,8 +153,6 @@ static void __init msm_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init msm_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 2fb5f3eec50..2969027f02f 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -25,7 +25,6 @@ #include <linux/of_irq.h> #include <asm/mach/time.h> -#include <asm/hardware/gic.h> #include <asm/localtimer.h> #include <asm/sched_clock.h> @@ -144,13 +143,9 @@ static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt) evt->rating = msm_clockevent.rating; evt->set_mode = msm_timer_set_mode; evt->set_next_event = msm_timer_set_next_event; - evt->shift = msm_clockevent.shift; - evt->mult = div_sc(GPT_HZ, NSEC_PER_SEC, evt->shift); - evt->max_delta_ns = clockevent_delta2ns(0xf0000000, evt); - evt->min_delta_ns = clockevent_delta2ns(4, evt); *__this_cpu_ptr(msm_evt.percpu_evt) = evt; - clockevents_register_device(evt); + clockevents_config_and_register(evt, GPT_HZ, 4, 0xf0000000); enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING); return 0; } diff --git a/arch/arm/mach-mv78xx0/include/mach/uncompress.h b/arch/arm/mach-mv78xx0/include/mach/uncompress.h index 365264298e7..6a761c44a29 100644 --- a/arch/arm/mach-mv78xx0/include/mach/uncompress.h +++ b/arch/arm/mach-mv78xx0/include/mach/uncompress.h @@ -44,4 +44,3 @@ static void flush(void) * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index 5dcb369b58a..99df4df680f 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -1,6 +1,8 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \ -I$(srctree)/arch/arm/plat-orion/include +AFLAGS_coherency_ll.o := -Wa,-march=armv7-a + obj-y += system-controller.o obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o pmsu.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o diff --git a/arch/arm/mach-mxs/include/mach/uncompress.h b/arch/arm/mach-mxs/include/mach/uncompress.h index ef281149544..533f5186e20 100644 --- a/arch/arm/mach-mxs/include/mach/uncompress.h +++ b/arch/arm/mach-mxs/include/mach/uncompress.h @@ -72,6 +72,5 @@ static inline void __arch_decomp_setup(unsigned long arch_id) } #define arch_decomp_setup() __arch_decomp_setup(arch_id) -#define arch_decomp_wdog() #endif /* __MACH_MXS_UNCOMPRESS_H__ */ diff --git a/arch/arm/mach-mxs/timer.c b/arch/arm/mach-mxs/timer.c index 856f4c79606..27451b1ba3f 100644 --- a/arch/arm/mach-mxs/timer.c +++ b/arch/arm/mach-mxs/timer.c @@ -195,7 +195,6 @@ static void mxs_set_mode(enum clock_event_mode mode, static struct clock_event_device mxs_clockevent_device = { .name = "mxs_timrot", .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .set_mode = mxs_set_mode, .set_next_event = timrotv2_set_next_event, .rating = 200, @@ -203,25 +202,12 @@ static struct clock_event_device mxs_clockevent_device = { static int __init mxs_clockevent_init(struct clk *timer_clk) { - unsigned int c = clk_get_rate(timer_clk); - - mxs_clockevent_device.mult = - div_sc(c, NSEC_PER_SEC, mxs_clockevent_device.shift); - mxs_clockevent_device.cpumask = cpumask_of(0); - if (timrot_is_v1()) { + if (timrot_is_v1()) mxs_clockevent_device.set_next_event = timrotv1_set_next_event; - mxs_clockevent_device.max_delta_ns = - clockevent_delta2ns(0xfffe, &mxs_clockevent_device); - mxs_clockevent_device.min_delta_ns = - clockevent_delta2ns(0xf, &mxs_clockevent_device); - } else { - mxs_clockevent_device.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &mxs_clockevent_device); - mxs_clockevent_device.min_delta_ns = - clockevent_delta2ns(0xf, &mxs_clockevent_device); - } - - clockevents_register_device(&mxs_clockevent_device); + mxs_clockevent_device.cpumask = cpumask_of(0); + clockevents_config_and_register(&mxs_clockevent_device, + clk_get_rate(timer_clk), 0xf, + timrot_is_v1() ? 0xfffe : 0xfffffffe); return 0; } diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c index aa627465d91..27c2cb7ab81 100644 --- a/arch/arm/mach-netx/generic.c +++ b/arch/arm/mach-netx/generic.c @@ -23,9 +23,9 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/irqchip/arm-vic.h> #include <mach/hardware.h> #include <asm/mach/map.h> -#include <asm/hardware/vic.h> #include <mach/netx-regs.h> #include <asm/mach/irq.h> diff --git a/arch/arm/mach-netx/include/mach/uncompress.h b/arch/arm/mach-netx/include/mach/uncompress.h index 84f91284f61..5cb1051b583 100644 --- a/arch/arm/mach-netx/include/mach/uncompress.h +++ b/arch/arm/mach-netx/include/mach/uncompress.h @@ -73,4 +73,3 @@ static inline void flush(void) * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-netx/nxdb500.c b/arch/arm/mach-netx/nxdb500.c index 241e1b9c58c..9b558eb3070 100644 --- a/arch/arm/mach-netx/nxdb500.c +++ b/arch/arm/mach-netx/nxdb500.c @@ -28,7 +28,6 @@ #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/hardware/vic.h> #include <mach/netx-regs.h> #include <linux/platform_data/eth-netx.h> @@ -204,7 +203,6 @@ MACHINE_START(NXDB500, "Hilscher nxdb500") .atag_offset = 0x100, .map_io = netx_map_io, .init_irq = netx_init_irq, - .handle_irq = vic_handle_irq, .init_time = netx_timer_init, .init_machine = nxdb500_init, .restart = netx_restart, diff --git a/arch/arm/mach-netx/nxdkn.c b/arch/arm/mach-netx/nxdkn.c index 055aeecedde..a5e86cd365e 100644 --- a/arch/arm/mach-netx/nxdkn.c +++ b/arch/arm/mach-netx/nxdkn.c @@ -28,7 +28,6 @@ #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/hardware/vic.h> #include <mach/netx-regs.h> #include <linux/platform_data/eth-netx.h> @@ -97,7 +96,6 @@ MACHINE_START(NXDKN, "Hilscher nxdkn") .atag_offset = 0x100, .map_io = netx_map_io, .init_irq = netx_init_irq, - .handle_irq = vic_handle_irq, .init_time = netx_timer_init, .init_machine = nxdkn_init, .restart = netx_restart, diff --git a/arch/arm/mach-netx/nxeb500hmi.c b/arch/arm/mach-netx/nxeb500hmi.c index 018e91c55b0..ad17885d015 100644 --- a/arch/arm/mach-netx/nxeb500hmi.c +++ b/arch/arm/mach-netx/nxeb500hmi.c @@ -28,7 +28,6 @@ #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/hardware/vic.h> #include <mach/netx-regs.h> #include <linux/platform_data/eth-netx.h> @@ -181,7 +180,6 @@ MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi") .atag_offset = 0x100, .map_io = netx_map_io, .init_irq = netx_init_irq, - .handle_irq = vic_handle_irq, .init_time = netx_timer_init, .init_machine = nxeb500hmi_init, .restart = netx_restart, diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c index 0dee4524494..6df42e64303 100644 --- a/arch/arm/mach-netx/time.c +++ b/arch/arm/mach-netx/time.c @@ -76,7 +76,6 @@ static int netx_set_next_event(unsigned long evt, static struct clock_event_device netx_clockevent = { .name = "netx-timer" __stringify(TIMER_CLOCKEVENT), - .shift = 32, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_next_event = netx_set_next_event, .set_mode = netx_set_mode, @@ -140,14 +139,9 @@ void __init netx_timer_init(void) clocksource_mmio_init(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE), "netx_timer", CLOCK_TICK_RATE, 200, 32, clocksource_mmio_readl_up); - netx_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, - netx_clockevent.shift); - netx_clockevent.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &netx_clockevent); /* with max_delta_ns >= delta2ns(0x800) the system currently runs fine. * Adding some safety ... */ - netx_clockevent.min_delta_ns = - clockevent_delta2ns(0xa00, &netx_clockevent); netx_clockevent.cpumask = cpumask_of(0); - clockevents_register_device(&netx_clockevent); + clockevents_config_and_register(&netx_clockevent, CLOCK_TICK_RATE, + 0xa00, 0xfffffffe); } diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c index c9015ba647a..aaed48d9437 100644 --- a/arch/arm/mach-nomadik/board-nhk8815.c +++ b/arch/arm/mach-nomadik/board-nhk8815.c @@ -27,7 +27,6 @@ #include <linux/pinctrl/machine.h> #include <linux/platform_data/pinctrl-nomadik.h> #include <linux/platform_data/clocksource-nomadik-mtu.h> -#include <asm/hardware/vic.h> #include <asm/sizes.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -348,7 +347,6 @@ MACHINE_START(NOMADIK, "NHK8815") .atag_offset = 0x100, .map_io = cpu8815_map_io, .init_irq = cpu8815_init_irq, - .handle_irq = vic_handle_irq, .init_time = nomadik_timer_init, .init_machine = nhk8815_platform_init, .restart = cpu8815_restart, diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index 1273931303f..351404673f6 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -25,13 +25,13 @@ #include <linux/slab.h> #include <linux/irq.h> #include <linux/dma-mapping.h> +#include <linux/irqchip/arm-vic.h> #include <linux/platform_data/clk-nomadik.h> #include <linux/platform_data/pinctrl-nomadik.h> #include <mach/hardware.h> #include <mach/irqs.h> #include <asm/mach/map.h> -#include <asm/hardware/vic.h> #include <asm/cacheflush.h> #include <asm/hardware/cache-l2x0.h> diff --git a/arch/arm/mach-nomadik/include/mach/uncompress.h b/arch/arm/mach-nomadik/include/mach/uncompress.h index 7d4687e9cbd..f527af6527c 100644 --- a/arch/arm/mach-nomadik/include/mach/uncompress.h +++ b/arch/arm/mach-nomadik/include/mach/uncompress.h @@ -58,6 +58,4 @@ static inline void arch_decomp_setup(void) { } -#define arch_decomp_wdog() /* nothing to do here */ - #endif /* __ASM_ARCH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-omap1/include/mach/uncompress.h b/arch/arm/mach-omap1/include/mach/uncompress.h index ad6fbe7d83f..4869633de8c 100644 --- a/arch/arm/mach-omap1/include/mach/uncompress.h +++ b/arch/arm/mach-omap1/include/mach/uncompress.h @@ -115,8 +115,3 @@ static inline void arch_decomp_setup(void) DEBUG_LL_OMAP1(3, sx1); } while (0); } - -/* - * nothing to do - */ -#define arch_decomp_wdog() diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index 1d4512fdc9b..726ec23d29c 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c @@ -145,7 +145,6 @@ static void omap_mpu_set_mode(enum clock_event_mode mode, static struct clock_event_device clockevent_mpu_timer1 = { .name = "mpu_timer1", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .set_next_event = omap_mpu_set_next_event, .set_mode = omap_mpu_set_mode, }; @@ -170,15 +169,9 @@ static __init void omap_init_mpu_timer(unsigned long rate) setup_irq(INT_TIMER1, &omap_mpu_timer1_irq); omap_mpu_timer_start(0, (rate / HZ) - 1, 1); - clockevent_mpu_timer1.mult = div_sc(rate, NSEC_PER_SEC, - clockevent_mpu_timer1.shift); - clockevent_mpu_timer1.max_delta_ns = - clockevent_delta2ns(-1, &clockevent_mpu_timer1); - clockevent_mpu_timer1.min_delta_ns = - clockevent_delta2ns(1, &clockevent_mpu_timer1); - clockevent_mpu_timer1.cpumask = cpumask_of(0); - clockevents_register_device(&clockevent_mpu_timer1); + clockevents_config_and_register(&clockevent_mpu_timer1, rate, + 1, -1); } diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c index 41152fadd4c..0b74246ba62 100644 --- a/arch/arm/mach-omap1/timer32k.c +++ b/arch/arm/mach-omap1/timer32k.c @@ -140,7 +140,6 @@ static void omap_32k_timer_set_mode(enum clock_event_mode mode, static struct clock_event_device clockevent_32k_timer = { .name = "32k-timer", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .set_next_event = omap_32k_timer_set_next_event, .set_mode = omap_32k_timer_set_mode, }; @@ -165,16 +164,9 @@ static __init void omap_init_32k_timer(void) { setup_irq(INT_OS_TIMER, &omap_32k_timer_irq); - clockevent_32k_timer.mult = div_sc(OMAP_32K_TICKS_PER_SEC, - NSEC_PER_SEC, - clockevent_32k_timer.shift); - clockevent_32k_timer.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &clockevent_32k_timer); - clockevent_32k_timer.min_delta_ns = - clockevent_delta2ns(1, &clockevent_32k_timer); - clockevent_32k_timer.cpumask = cpumask_of(0); - clockevents_register_device(&clockevent_32k_timer); + clockevents_config_and_register(&clockevent_32k_timer, + OMAP_32K_TICKS_PER_SEC, 1, 0xfffffffe); } /* diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index f5d5f5941d7..f8eeef40efe 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -26,10 +26,10 @@ #include <linux/regulator/fixed.h> #include <linux/leds.h> #include <linux/leds_pwm.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/omap4-keypad.h> #include <linux/usb/musb.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -722,7 +722,6 @@ MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board") .map_io = omap4_map_io, .init_early = omap4430_init_early, .init_irq = gic_init_irq, - .handle_irq = gic_handle_irq, .init_machine = omap_4430sdp_init, .init_late = omap4430_init_late, .init_time = omap4_local_timer_init, diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 8a5f814613c..2590463e4b5 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -16,7 +16,6 @@ #include <linux/of_platform.h> #include <linux/irqdomain.h> -#include <asm/hardware/gic.h> #include <asm/mach/arch.h> #include "common.h" @@ -156,7 +155,6 @@ DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)") .map_io = omap4_map_io, .init_early = omap4430_init_early, .init_irq = omap_gic_of_init, - .handle_irq = gic_handle_irq, .init_machine = omap_generic_init, .init_late = omap4430_init_late, .init_time = omap4_local_timer_init, @@ -177,7 +175,6 @@ DT_MACHINE_START(OMAP5_DT, "Generic OMAP5 (Flattened Device Tree)") .map_io = omap5_map_io, .init_early = omap5_init_early, .init_irq = omap_gic_of_init, - .handle_irq = gic_handle_irq, .init_machine = omap_generic_init, .init_time = omap5_realtime_timer_init, .dt_compat = omap5_boards_compat, diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index ed8240c1a9b..b62317906b3 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -31,9 +31,9 @@ #include <linux/ti_wilink_st.h> #include <linux/usb/musb.h> #include <linux/wl12xx.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/omap-abe-twl6040.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -397,6 +397,12 @@ static struct omap_board_mux board_mux[] __initdata = { OMAP_PULL_ENA), OMAP4_MUX(ABE_MCBSP1_FSX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + /* UART2 - BT/FM/GPS shared transport */ + OMAP4_MUX(UART2_CTS, OMAP_PIN_INPUT | OMAP_MUX_MODE0), + OMAP4_MUX(UART2_RTS, OMAP_PIN_OUTPUT | OMAP_MUX_MODE0), + OMAP4_MUX(UART2_RX, OMAP_PIN_INPUT | OMAP_MUX_MODE0), + OMAP4_MUX(UART2_TX, OMAP_PIN_OUTPUT | OMAP_MUX_MODE0), + { .reg_offset = OMAP_MUX_TERMINATOR }, }; @@ -453,7 +459,6 @@ MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board") .map_io = omap4_map_io, .init_early = omap4430_init_early, .init_irq = gic_init_irq, - .handle_irq = gic_handle_irq, .init_machine = omap4_panda_init, .init_late = omap4430_init_late, .init_time = omap4_local_timer_init, diff --git a/arch/arm/mach-omap2/cclock2420_data.c b/arch/arm/mach-omap2/cclock2420_data.c index 7e5febe456d..ab7e952d207 100644 --- a/arch/arm/mach-omap2/cclock2420_data.c +++ b/arch/arm/mach-omap2/cclock2420_data.c @@ -1935,6 +1935,8 @@ int __init omap2420_clk_init(void) omap2_init_clk_hw_omap_clocks(c->lk.clk); } + omap2xxx_clkt_vps_late_init(); + omap2_clk_disable_autoidle_all(); omap2_clk_enable_init_clocks(enable_init_clks, diff --git a/arch/arm/mach-omap2/cclock2430_data.c b/arch/arm/mach-omap2/cclock2430_data.c index eda079b96c6..eb3dab68d53 100644 --- a/arch/arm/mach-omap2/cclock2430_data.c +++ b/arch/arm/mach-omap2/cclock2430_data.c @@ -2050,6 +2050,8 @@ int __init omap2430_clk_init(void) omap2_init_clk_hw_omap_clocks(c->lk.clk); } + omap2xxx_clkt_vps_late_init(); + omap2_clk_disable_autoidle_all(); omap2_clk_enable_init_clocks(enable_init_clks, diff --git a/arch/arm/mach-omap2/cclock44xx_data.c b/arch/arm/mach-omap2/cclock44xx_data.c index 5789a5e2556..a2cc046b47f 100644 --- a/arch/arm/mach-omap2/cclock44xx_data.c +++ b/arch/arm/mach-omap2/cclock44xx_data.c @@ -2026,14 +2026,13 @@ int __init omap4xxx_clk_init(void) * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power * state when turning the ABE clock domain. Workaround this by * locking the ABE DPLL on boot. + * Lock the ABE DPLL in any case to avoid issues with audio. */ - if (cpu_is_omap446x()) { - rc = clk_set_parent(&abe_dpll_refclk_mux_ck, &sys_32k_ck); - if (!rc) - rc = clk_set_rate(&dpll_abe_ck, OMAP4_DPLL_ABE_DEFFREQ); - if (rc) - pr_err("%s: failed to configure ABE DPLL!\n", __func__); - } + rc = clk_set_parent(&abe_dpll_refclk_mux_ck, &sys_32k_ck); + if (!rc) + rc = clk_set_rate(&dpll_abe_ck, OMAP4_DPLL_ABE_DEFFREQ); + if (rc) + pr_err("%s: failed to configure ABE DPLL!\n", __func__); return 0; } diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 5e304d0719a..626f3ea3142 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -639,7 +639,7 @@ static int count_ocp2scp_devices(struct omap_ocp2scp_dev *ocp2scp_dev) return cnt; } -static void omap_init_ocp2scp(void) +static void __init omap_init_ocp2scp(void) { struct omap_hwmod *oh; struct platform_device *pdev; diff --git a/arch/arm/mach-omap2/drm.c b/arch/arm/mach-omap2/drm.c index 4c7566c7e24..2a2cfa88ddb 100644 --- a/arch/arm/mach-omap2/drm.c +++ b/arch/arm/mach-omap2/drm.c @@ -25,6 +25,7 @@ #include <linux/dma-mapping.h> #include <linux/platform_data/omap_drm.h> +#include "soc.h" #include "omap_device.h" #include "omap_hwmod.h" @@ -56,7 +57,7 @@ static int __init omap_init_drm(void) oh->name); } - platform_data.omaprev = GET_OMAP_REVISION(); + platform_data.omaprev = GET_OMAP_TYPE; return platform_device_register(&omap_drm_device); diff --git a/arch/arm/mach-omap2/include/mach/uncompress.h b/arch/arm/mach-omap2/include/mach/uncompress.h index 8e3546d3e04..7b360acd19c 100644 --- a/arch/arm/mach-omap2/include/mach/uncompress.h +++ b/arch/arm/mach-omap2/include/mach/uncompress.h @@ -169,8 +169,3 @@ static inline void arch_decomp_setup(void) DEBUG_LL_AM33XX(1, am335xevm); } while (0); } - -/* - * nothing to do - */ -#define arch_decomp_wdog() diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index cd42d921940..361677983af 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -19,9 +19,9 @@ #include <linux/device.h> #include <linux/smp.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <asm/cacheflush.h> -#include <asm/hardware/gic.h> #include <asm/smp_scu.h> #include "omap-secure.h" @@ -157,7 +157,7 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct * booted = true; } - gic_raise_softirq(cpumask_of(cpu), 0); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); /* * Now the secondary core is starting up let it run its @@ -231,8 +231,6 @@ static void __init omap4_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init omap4_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index 5d3b4f4f81a..8c5b5e3e354 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c @@ -24,8 +24,7 @@ #include <linux/cpu.h> #include <linux/notifier.h> #include <linux/cpu_pm.h> - -#include <asm/hardware/gic.h> +#include <linux/irqchip/arm-gic.h> #include "omap-wakeupgen.h" #include "omap-secure.h" diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 6897ae21bb8..54709488360 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -15,13 +15,14 @@ #include <linux/init.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/irqchip.h> #include <linux/platform_device.h> #include <linux/memblock.h> #include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/export.h> +#include <linux/irqchip/arm-gic.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/mach/map.h> #include <asm/memblock.h> @@ -255,16 +256,10 @@ static int __init omap4_sar_ram_init(void) } early_initcall(omap4_sar_ram_init); -static struct of_device_id irq_match[] __initdata = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - { .compatible = "arm,cortex-a15-gic", .data = gic_of_init, }, - { } -}; - void __init omap_gic_of_init(void) { omap_wakeupgen_init(); - of_irq_init(irq_match); + irqchip_init(); } #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 129d5081ed1..793f54ac7d1 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -2132,8 +2132,12 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = { * currently reset very early during boot, before I2C is * available, so it doesn't seem that we have any choice in * the kernel other than to avoid resetting it. + * + * Also, McPDM needs to be configured to NO_IDLE mode when it + * is in used otherwise vital clocks will be gated which + * results 'slow motion' audio playback. */ - .flags = HWMOD_EXT_OPT_MAIN_CLK, + .flags = HWMOD_EXT_OPT_MAIN_CLK | HWMOD_SWSUP_SIDLE, .mpu_irqs = omap44xx_mcpdm_irqs, .sdma_reqs = omap44xx_mcpdm_sdma_reqs, .main_clk = "mcpdm_fck", diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 5975a42e16d..d86074745c5 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -131,7 +131,6 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode, static struct clock_event_device clockevent_gpt = { .name = "gp_timer", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .rating = 300, .set_next_event = omap2_gp_timer_set_next_event, .set_mode = omap2_gp_timer_set_mode, @@ -165,15 +164,11 @@ static struct device_node * __init omap_get_timer_dt(struct of_device_id *match, struct device_node *np; for_each_matching_node(np, match) { - if (!of_device_is_available(np)) { - of_node_put(np); + if (!of_device_is_available(np)) continue; - } - if (property && !of_get_property(np, property, NULL)) { - of_node_put(np); + if (property && !of_get_property(np, property, NULL)) continue; - } of_add_property(np, &device_disabled); return np; @@ -340,17 +335,11 @@ static void __init omap2_gp_clockevent_init(int gptimer_id, __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW); - clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC, - clockevent_gpt.shift); - clockevent_gpt.max_delta_ns = - clockevent_delta2ns(0xffffffff, &clockevent_gpt); - clockevent_gpt.min_delta_ns = - clockevent_delta2ns(3, &clockevent_gpt); - /* Timer internal resynch latency. */ - clockevent_gpt.cpumask = cpu_possible_mask; clockevent_gpt.irq = omap_dm_timer_get_irq(&clkev); - clockevents_register_device(&clockevent_gpt); + clockevents_config_and_register(&clockevent_gpt, clkev.rate, + 3, /* Timer internal resynch latency */ + 0xffffffff); pr_info("OMAP clockevent source: GPTIMER%d at %lu Hz\n", gptimer_id, clkev.rate); diff --git a/arch/arm/mach-orion5x/include/mach/uncompress.h b/arch/arm/mach-orion5x/include/mach/uncompress.h index 4322dba468a..abd26b542c3 100644 --- a/arch/arm/mach-orion5x/include/mach/uncompress.h +++ b/arch/arm/mach-orion5x/include/mach/uncompress.h @@ -46,4 +46,3 @@ static void flush(void) * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-picoxcell/Kconfig b/arch/arm/mach-picoxcell/Kconfig index 868796f8085..13bae78b215 100644 --- a/arch/arm/mach-picoxcell/Kconfig +++ b/arch/arm/mach-picoxcell/Kconfig @@ -7,7 +7,6 @@ config ARCH_PICOXCELL select DW_APB_TIMER select DW_APB_TIMER_OF select GENERIC_CLOCKEVENTS - select GENERIC_GPIO select HAVE_TCM select NO_IOPORT select SPARSE_IRQ diff --git a/arch/arm/mach-picoxcell/common.c b/arch/arm/mach-picoxcell/common.c index 518c59bdbcd..70b441ad1d1 100644 --- a/arch/arm/mach-picoxcell/common.c +++ b/arch/arm/mach-picoxcell/common.c @@ -9,6 +9,7 @@ */ #include <linux/delay.h> #include <linux/irq.h> +#include <linux/irqchip.h> #include <linux/irqdomain.h> #include <linux/of.h> #include <linux/of_address.h> @@ -17,7 +18,6 @@ #include <linux/dw_apb_timer.h> #include <asm/mach/arch.h> -#include <asm/hardware/vic.h> #include <asm/mach/map.h> #include "common.h" @@ -70,16 +70,6 @@ static const char *picoxcell_dt_match[] = { NULL }; -static const struct of_device_id vic_of_match[] __initconst = { - { .compatible = "arm,pl192-vic", .data = vic_of_init, }, - { /* Sentinel */ } -}; - -static void __init picoxcell_init_irq(void) -{ - of_irq_init(vic_of_match); -} - static void picoxcell_wdt_restart(char mode, const char *cmd) { /* @@ -97,8 +87,7 @@ static void picoxcell_wdt_restart(char mode, const char *cmd) DT_MACHINE_START(PICOXCELL, "Picochip picoXcell") .map_io = picoxcell_map_io, .nr_irqs = NR_IRQS_LEGACY, - .init_irq = picoxcell_init_irq, - .handle_irq = vic_handle_irq, + .init_irq = irqchip_init, .init_time = dw_apb_timer_init, .init_machine = picoxcell_init_machine, .dt_compat = picoxcell_dt_match, diff --git a/arch/arm/mach-prima2/include/mach/uncompress.h b/arch/arm/mach-prima2/include/mach/uncompress.h index 0c898fcf909..f72ca26ab4f 100644 --- a/arch/arm/mach-prima2/include/mach/uncompress.h +++ b/arch/arm/mach-prima2/include/mach/uncompress.h @@ -17,8 +17,6 @@ void arch_decomp_setup(void) { } -#define arch_decomp_wdog() - static __inline__ void putc(char c) { /* diff --git a/arch/arm/mach-prima2/timer.c b/arch/arm/mach-prima2/timer.c index 8c732a5beb7..a7a2c199c3e 100644 --- a/arch/arm/mach-prima2/timer.c +++ b/arch/arm/mach-prima2/timer.c @@ -175,15 +175,9 @@ static u32 notrace sirfsoc_read_sched_clock(void) static void __init sirfsoc_clockevent_init(void) { - clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60); - - sirfsoc_clockevent.max_delta_ns = - clockevent_delta2ns(-2, &sirfsoc_clockevent); - sirfsoc_clockevent.min_delta_ns = - clockevent_delta2ns(2, &sirfsoc_clockevent); - sirfsoc_clockevent.cpumask = cpumask_of(0); - clockevents_register_device(&sirfsoc_clockevent); + clockevents_config_and_register(&sirfsoc_clockevent, CLOCK_TICK_RATE, + 2, -2); } /* initialize the kernel jiffy timer source */ diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h index a611ad3153c..b6132aa95dc 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h @@ -463,6 +463,9 @@ GPIO76_LCD_PCLK, \ GPIO77_LCD_BIAS +/* these enable a work-around for a hw bug in pxa27x during ac97 warm reset */ +#define GPIO113_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO113, AF0, DEFAULT) +#define GPIO95_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO95, AF0, DEFAULT) extern int keypad_set_wake(unsigned int on); #endif /* __ASM_ARCH_MFP_PXA27X_H */ diff --git a/arch/arm/mach-pxa/include/mach/palmtreo.h b/arch/arm/mach-pxa/include/mach/palmtreo.h index 2d3f14e3be2..714b6574393 100644 --- a/arch/arm/mach-pxa/include/mach/palmtreo.h +++ b/arch/arm/mach-pxa/include/mach/palmtreo.h @@ -38,13 +38,14 @@ #define GPIO_NR_TREO_LCD_POWER 25 /* Treo680 specific GPIOs */ -#ifdef CONFIG_MACH_TREO680 #define GPIO_NR_TREO680_SD_READONLY 33 #define GPIO_NR_TREO680_SD_POWER 42 #define GPIO_NR_TREO680_VIBRATE_EN 44 #define GPIO_NR_TREO680_KEYB_BL 24 #define GPIO_NR_TREO680_BT_EN 43 -#endif /* CONFIG_MACH_TREO680 */ +#define GPIO_NR_TREO680_LCD_POWER 77 +#define GPIO_NR_TREO680_LCD_EN 86 +#define GPIO_NR_TREO680_LCD_EN_N 25 /* Centro685 specific GPIOs */ #define GPIO_NR_CENTRO_SD_POWER 21 diff --git a/arch/arm/mach-pxa/include/mach/smemc.h b/arch/arm/mach-pxa/include/mach/smemc.h index b7de471b273..b802f285fe0 100644 --- a/arch/arm/mach-pxa/include/mach/smemc.h +++ b/arch/arm/mach-pxa/include/mach/smemc.h @@ -37,6 +37,7 @@ #define CSADRCFG1 (SMEMC_VIRT + 0x84) /* Address Configuration Register for CS1 */ #define CSADRCFG2 (SMEMC_VIRT + 0x88) /* Address Configuration Register for CS2 */ #define CSADRCFG3 (SMEMC_VIRT + 0x8C) /* Address Configuration Register for CS3 */ +#define CSMSADRCFG (SMEMC_VIRT + 0xA0) /* Chip Select Configuration Register */ /* * More handy macros for PCMCIA diff --git a/arch/arm/mach-pxa/include/mach/uncompress.h b/arch/arm/mach-pxa/include/mach/uncompress.h index 5519a34b667..8c27757e68f 100644 --- a/arch/arm/mach-pxa/include/mach/uncompress.h +++ b/arch/arm/mach-pxa/include/mach/uncompress.h @@ -72,8 +72,3 @@ static inline void arch_decomp_setup(void) uart_is_pxa = 0; } } - -/* - * nothing to do - */ -#define arch_decomp_wdog() diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c index d17bda27878..a29849d181c 100644 --- a/arch/arm/mach-pxa/palmtreo.c +++ b/arch/arm/mach-pxa/palmtreo.c @@ -98,9 +98,6 @@ static unsigned long treo_pin_config[] __initdata = { GPIO96_KP_MKOUT_6, GPIO93_KP_DKIN_0 | WAKEUP_ON_LEVEL_HIGH, /* Hotsync button */ - /* LCD */ - GPIOxx_LCD_TFT_16BPP, - /* Quick Capture Interface */ GPIO84_CIF_FV, GPIO85_CIF_LV, @@ -140,6 +137,12 @@ static unsigned long treo680_pin_config[] __initdata = { /* MATRIX KEYPAD - different wake up source */ GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH, GPIO99_KP_MKIN_5, + + /* LCD... L_BIAS alt fn not configured on Treo680; is GPIO instead */ + GPIOxx_LCD_16BPP, + GPIO74_LCD_FCLK, + GPIO75_LCD_LCLK, + GPIO76_LCD_PCLK, }; #endif /* CONFIG_MACH_TREO680 */ @@ -155,6 +158,9 @@ static unsigned long centro685_pin_config[] __initdata = { /* MATRIX KEYPAD - different wake up source */ GPIO100_KP_MKIN_0, GPIO99_KP_MKIN_5 | WAKEUP_ON_LEVEL_HIGH, + + /* LCD */ + GPIOxx_LCD_TFT_16BPP, }; #endif /* CONFIG_MACH_CENTRO */ @@ -328,7 +334,6 @@ static inline void palmtreo_uhc_init(void) {} /****************************************************************************** * Vibra and LEDs ******************************************************************************/ -#ifdef CONFIG_MACH_TREO680 static struct gpio_led treo680_gpio_leds[] = { { .name = "treo680:vibra:vibra", @@ -379,21 +384,17 @@ static struct gpio_led_platform_data centro_gpio_led_info = { static struct platform_device palmtreo_leds = { .name = "leds-gpio", .id = -1, - .dev = { - .platform_data = &treo680_gpio_led_info, - } }; static void __init palmtreo_leds_init(void) { if (machine_is_centro()) palmtreo_leds.dev.platform_data = ¢ro_gpio_led_info; + else if (machine_is_treo680()) + palmtreo_leds.dev.platform_data = &treo680_gpio_led_info; platform_device_register(&palmtreo_leds); } -#else -static inline void palmtreo_leds_init(void) {} -#endif /****************************************************************************** * Machine init @@ -424,10 +425,59 @@ static void __init palmphone_common_init(void) } #ifdef CONFIG_MACH_TREO680 +void __init treo680_gpio_init(void) +{ + unsigned int gpio; + + /* drive all three lcd gpios high initially */ + const unsigned long lcd_flags = GPIOF_INIT_HIGH | GPIOF_DIR_OUT; + + /* + * LCD GPIO initialization... + */ + + /* + * This is likely the power to the lcd. Toggling it low/high appears to + * turn the lcd off/on. Can be toggled after lcd is initialized without + * any apparent adverse effects to the lcd operation. Note that this + * gpio line is used by the lcd controller as the L_BIAS signal, but + * treo680 configures it as gpio. + */ + gpio = GPIO_NR_TREO680_LCD_POWER; + if (gpio_request_one(gpio, lcd_flags, "LCD power") < 0) + goto fail; + + /* + * These two are called "enables", for lack of a better understanding. + * If either of these are toggled after the lcd is initialized, the + * image becomes degraded. N.B. The IPL shipped with the treo + * configures GPIO_NR_TREO680_LCD_EN_N as output and drives it high. If + * the IPL is ever reprogrammed, this initialization may be need to be + * revisited. + */ + gpio = GPIO_NR_TREO680_LCD_EN; + if (gpio_request_one(gpio, lcd_flags, "LCD enable") < 0) + goto fail; + gpio = GPIO_NR_TREO680_LCD_EN_N; + if (gpio_request_one(gpio, lcd_flags, "LCD enable_n") < 0) + goto fail; + + /* driving this low turns LCD on */ + gpio_set_value(GPIO_NR_TREO680_LCD_EN_N, 0); + + return; + fail: + pr_err("gpio %d initialization failed\n", gpio); + gpio_free(GPIO_NR_TREO680_LCD_POWER); + gpio_free(GPIO_NR_TREO680_LCD_EN); + gpio_free(GPIO_NR_TREO680_LCD_EN_N); +} + static void __init treo680_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(treo680_pin_config)); palmphone_common_init(); + treo680_gpio_init(); palm27x_mmc_init(GPIO_NR_TREO_SD_DETECT_N, GPIO_NR_TREO680_SD_READONLY, GPIO_NR_TREO680_SD_POWER, 0); } diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 8047ee0effc..616cb87b617 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -47,9 +47,9 @@ void pxa27x_clear_otgph(void) EXPORT_SYMBOL(pxa27x_clear_otgph); static unsigned long ac97_reset_config[] = { - GPIO113_GPIO, + GPIO113_AC97_nRESET_GPIO_HIGH, GPIO113_AC97_nRESET, - GPIO95_GPIO, + GPIO95_AC97_nRESET_GPIO_HIGH, GPIO95_AC97_nRESET, }; diff --git a/arch/arm/mach-pxa/smemc.c b/arch/arm/mach-pxa/smemc.c index 79923058d10..f38aa890b2c 100644 --- a/arch/arm/mach-pxa/smemc.c +++ b/arch/arm/mach-pxa/smemc.c @@ -40,6 +40,8 @@ static void pxa3xx_smemc_resume(void) __raw_writel(csadrcfg[1], CSADRCFG1); __raw_writel(csadrcfg[2], CSADRCFG2); __raw_writel(csadrcfg[3], CSADRCFG3); + /* CSMSADRCFG wakes up in its default state (0), so we need to set it */ + __raw_writel(0x2, CSMSADRCFG); } static struct syscore_ops smemc_syscore_ops = { @@ -49,8 +51,19 @@ static struct syscore_ops smemc_syscore_ops = { static int __init smemc_init(void) { - if (cpu_is_pxa3xx()) + if (cpu_is_pxa3xx()) { + /* + * The only documentation we have on the + * Chip Select Configuration Register (CSMSADRCFG) is that + * it must be programmed to 0x2. + * Moreover, in the bit definitions, the second bit + * (CSMSADRCFG[1]) is called "SETALWAYS". + * Other bits are reserved in this register. + */ + __raw_writel(0x2, CSMSADRCFG); + register_syscore_ops(&smemc_syscore_ops); + } return 0; } diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index f90aa27ad59..362726c49c7 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -732,7 +732,7 @@ static inline void spitz_lcd_init(void) {} #endif /****************************************************************************** - * Framebuffer + * NAND Flash ******************************************************************************/ #if defined(CONFIG_MTD_NAND_SHARPSL) || defined(CONFIG_MTD_NAND_SHARPSL_MODULE) static struct mtd_partition spitz_nand_partitions[] = { @@ -858,7 +858,7 @@ static inline void spitz_nor_init(void) {} #endif /****************************************************************************** - * GPIO expander + * I2C devices ******************************************************************************/ #if defined(CONFIG_I2C_PXA) || defined(CONFIG_I2C_PXA_MODULE) static struct pca953x_platform_data akita_pca953x_pdata = { diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index bea19a06b2b..8f1ee92aea3 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -151,16 +151,12 @@ void __init pxa_timer_init(void) setup_sched_clock(pxa_read_sched_clock, 32, clock_tick_rate); - clockevents_calc_mult_shift(&ckevt_pxa_osmr0, clock_tick_rate, 4); - ckevt_pxa_osmr0.max_delta_ns = - clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0); - ckevt_pxa_osmr0.min_delta_ns = - clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_pxa_osmr0) + 1; ckevt_pxa_osmr0.cpumask = cpumask_of(0); setup_irq(IRQ_OST0, &pxa_ost0_irq); clocksource_mmio_init(OSCR, "oscr0", clock_tick_rate, 200, 32, clocksource_mmio_readl_up); - clockevents_register_device(&ckevt_pxa_osmr0); + clockevents_config_and_register(&ckevt_pxa_osmr0, clock_tick_rate, + MIN_OSCR_DELTA * 2, 0x7fffffff); } diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 68246748058..1d5ee5c9a1d 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -42,7 +42,6 @@ #include <asm/mach/irq.h> #include <asm/mach/map.h> -#include <asm/hardware/gic.h> #include <mach/platform.h> #include <mach/irqs.h> diff --git a/arch/arm/mach-realview/include/mach/uncompress.h b/arch/arm/mach-realview/include/mach/uncompress.h index 83050378ffd..cfa30d21783 100644 --- a/arch/arm/mach-realview/include/mach/uncompress.h +++ b/arch/arm/mach-realview/include/mach/uncompress.h @@ -75,4 +75,3 @@ static inline void flush(void) * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index 300f7064465..98e3052b793 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -14,7 +14,6 @@ #include <linux/io.h> #include <mach/hardware.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/smp_scu.h> @@ -59,8 +58,6 @@ static void __init realview_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init realview_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index f892862fd6a..5b1c8bfe6fa 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -27,13 +27,13 @@ #include <linux/amba/mmci.h> #include <linux/amba/pl022.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/clk-realview.h> #include <mach/hardware.h> #include <asm/irq.h> #include <asm/mach-types.h> #include <asm/pgtable.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/smp_twd.h> @@ -469,7 +469,6 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB") .init_early = realview_init_early, .init_irq = gic_init_irq, .init_time = realview_eb_timer_init, - .handle_irq = gic_handle_irq, .init_machine = realview_eb_init, #ifdef CONFIG_ZONE_DMA .dma_zone_size = SZ_256M, diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index 6a4524b93fc..d5e83a1f698 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -29,13 +29,13 @@ #include <linux/mtd/physmap.h> #include <linux/mtd/partitions.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/clk-realview.h> #include <mach/hardware.h> #include <asm/irq.h> #include <asm/mach-types.h> #include <asm/pgtable.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/mach/arch.h> @@ -381,7 +381,6 @@ MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176") .init_early = realview_init_early, .init_irq = gic_init_irq, .init_time = realview_pb1176_timer_init, - .handle_irq = gic_handle_irq, .init_machine = realview_pb1176_init, #ifdef CONFIG_ZONE_DMA .dma_zone_size = SZ_256M, diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index 502f6e6c691..c3cfe213b5e 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -27,13 +27,13 @@ #include <linux/amba/mmci.h> #include <linux/amba/pl022.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/clk-realview.h> #include <mach/hardware.h> #include <asm/irq.h> #include <asm/mach-types.h> #include <asm/pgtable.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/smp_twd.h> @@ -364,7 +364,6 @@ MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore") .init_early = realview_init_early, .init_irq = gic_init_irq, .init_time = realview_pb11mp_timer_init, - .handle_irq = gic_handle_irq, .init_machine = realview_pb11mp_init, #ifdef CONFIG_ZONE_DMA .dma_zone_size = SZ_256M, diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index 85c81aaa05e..dde652a5962 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -27,12 +27,12 @@ #include <linux/amba/mmci.h> #include <linux/amba/pl022.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/clk-realview.h> #include <asm/irq.h> #include <asm/mach-types.h> #include <asm/pgtable.h> -#include <asm/hardware/gic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -305,7 +305,6 @@ MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8") .init_early = realview_init_early, .init_irq = gic_init_irq, .init_time = realview_pba8_timer_init, - .handle_irq = gic_handle_irq, .init_machine = realview_pba8_init, #ifdef CONFIG_ZONE_DMA .dma_zone_size = SZ_256M, diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index a15a7b0be29..54f0185b01e 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -26,13 +26,13 @@ #include <linux/amba/mmci.h> #include <linux/amba/pl022.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/clk-realview.h> #include <asm/irq.h> #include <asm/mach-types.h> #include <asm/smp_twd.h> #include <asm/pgtable.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/mach/arch.h> @@ -401,7 +401,6 @@ MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX") .init_early = realview_init_early, .init_irq = gic_init_irq, .init_time = realview_pbx_timer_init, - .handle_irq = gic_handle_irq, .init_machine = realview_pbx_init, #ifdef CONFIG_ZONE_DMA .dma_zone_size = SZ_256M, diff --git a/arch/arm/mach-rpc/include/mach/uncompress.h b/arch/arm/mach-rpc/include/mach/uncompress.h index 9cd9bcdad6c..0fd4b0b8ef2 100644 --- a/arch/arm/mach-rpc/include/mach/uncompress.h +++ b/arch/arm/mach-rpc/include/mach/uncompress.h @@ -189,8 +189,3 @@ static void arch_decomp_setup(void) if (nr_pages * page_size < 4096*1024) error("<4M of mem\n"); } #endif - -/* - * nothing to do - */ -#define arch_decomp_wdog() diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile index c4609243981..0ddd17fa067 100644 --- a/arch/arm/mach-s3c2440/Makefile +++ b/arch/arm/mach-s3c2440/Makefile @@ -9,8 +9,6 @@ obj-m := obj-n := obj- := -obj-$(CONFIG_CPU_S3C2440) += dsc.o - obj-$(CONFIG_S3C2440_CPUFREQ) += s3c2440-cpufreq.o obj-$(CONFIG_S3C2440_PLL_12000000) += s3c2440-pll-12000000.o diff --git a/arch/arm/mach-s3c2440/dsc.c b/arch/arm/mach-s3c2440/dsc.c deleted file mode 100644 index 9ea66e31f62..00000000000 --- a/arch/arm/mach-s3c2440/dsc.c +++ /dev/null @@ -1,54 +0,0 @@ -/* linux/arch/arm/mach-s3c2440/dsc.c - * - * Copyright (c) 2004-2005 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * Samsung S3C2440 Drive Strength Control support - * - * 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. -*/ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/io.h> - -#include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/irq.h> - -#include <mach/hardware.h> -#include <asm/irq.h> - -#include <mach/regs-gpio.h> -#include <mach/regs-dsc.h> - -#include <plat/cpu.h> -#include <plat/s3c244x.h> - -int s3c2440_set_dsc(unsigned int pin, unsigned int value) -{ - void __iomem *base; - unsigned long val; - unsigned long flags; - unsigned long mask; - - base = (pin & S3C2440_SELECT_DSC1) ? S3C2440_DSC1 : S3C2440_DSC0; - mask = 3 << S3C2440_DSC_GETSHIFT(pin); - - local_irq_save(flags); - - val = __raw_readl(base); - val &= ~mask; - val |= value & mask; - __raw_writel(val, base); - - local_irq_restore(flags); - return 0; -} - -EXPORT_SYMBOL(s3c2440_set_dsc); diff --git a/arch/arm/mach-s3c24xx/anubis.h b/arch/arm/mach-s3c24xx/anubis.h new file mode 100644 index 00000000000..2691665f27d --- /dev/null +++ b/arch/arm/mach-s3c24xx/anubis.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2005 Simtec Electronics + * http://www.simtec.co.uk/products/ + * Ben Dooks <ben@simtec.co.uk> + * + * ANUBIS - CPLD control constants + * ANUBIS - IRQ Number definitions + * ANUBIS - Memory map definitions + * + * 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. +*/ + +#ifndef __MACH_S3C24XX_ANUBIS_H +#define __MACH_S3C24XX_ANUBIS_H __FILE__ + +/* CTRL2 - NAND WP control, IDE Reset assert/check */ + +#define ANUBIS_CTRL1_NANDSEL (0x3) + +/* IDREG - revision */ + +#define ANUBIS_IDREG_REVMASK (0x7) + +/* irq */ + +#define ANUBIS_IRQ_IDE0 IRQ_EINT2 +#define ANUBIS_IRQ_IDE1 IRQ_EINT3 +#define ANUBIS_IRQ_ASIX IRQ_EINT1 + +/* map */ + +/* start peripherals off after the S3C2410 */ + +#define ANUBIS_IOADDR(x) (S3C2410_ADDR((x) + 0x01800000)) + +#define ANUBIS_PA_CPLD (S3C2410_CS1 | (1<<26)) + +/* we put the CPLD registers next, to get them out of the way */ + +#define ANUBIS_VA_CTRL1 ANUBIS_IOADDR(0x00000000) +#define ANUBIS_PA_CTRL1 ANUBIS_PA_CPLD + +#define ANUBIS_VA_IDREG ANUBIS_IOADDR(0x00300000) +#define ANUBIS_PA_IDREG (ANUBIS_PA_CPLD + (3 << 23)) + +#define ANUBIS_IDEPRI ANUBIS_IOADDR(0x01000000) +#define ANUBIS_IDEPRIAUX ANUBIS_IOADDR(0x01100000) +#define ANUBIS_IDESEC ANUBIS_IOADDR(0x01200000) +#define ANUBIS_IDESECAUX ANUBIS_IOADDR(0x01300000) + +#endif /* __MACH_S3C24XX_ANUBIS_H */ diff --git a/arch/arm/mach-s3c24xx/bast-ide.c b/arch/arm/mach-s3c24xx/bast-ide.c index ba02cf8d80a..3f0288f2f54 100644 --- a/arch/arm/mach-s3c24xx/bast-ide.c +++ b/arch/arm/mach-s3c24xx/bast-ide.c @@ -25,8 +25,8 @@ #include <asm/mach/irq.h> #include <mach/map.h> -#include <mach/bast-map.h> -#include <mach/bast-irq.h> + +#include "bast.h" /* IDE ports */ @@ -34,12 +34,10 @@ static struct pata_platform_info bast_ide_platdata = { .ioport_shift = 5, }; -#define IDE_CS S3C2410_CS5 - static struct resource bast_ide0_resource[] = { - [0] = DEFINE_RES_MEM(IDE_CS + BAST_PA_IDEPRI, 8 * 0x20), - [1] = DEFINE_RES_MEM(IDE_CS + BAST_PA_IDEPRIAUX + (6 * 0x20), 0x20), - [2] = DEFINE_RES_IRQ(IRQ_IDE0), + [0] = DEFINE_RES_MEM(BAST_IDE_CS + BAST_PA_IDEPRI, 8 * 0x20), + [1] = DEFINE_RES_MEM(BAST_IDE_CS + BAST_PA_IDEPRIAUX + (6 * 0x20), 0x20), + [2] = DEFINE_RES_IRQ(BAST_IRQ_IDE0), }; static struct platform_device bast_device_ide0 = { @@ -55,9 +53,9 @@ static struct platform_device bast_device_ide0 = { }; static struct resource bast_ide1_resource[] = { - [0] = DEFINE_RES_MEM(IDE_CS + BAST_PA_IDESEC, 8 * 0x20), - [1] = DEFINE_RES_MEM(IDE_CS + BAST_PA_IDESECAUX + (6 * 0x20), 0x20), - [2] = DEFINE_RES_IRQ(IRQ_IDE1), + [0] = DEFINE_RES_MEM(BAST_IDE_CS + BAST_PA_IDESEC, 8 * 0x20), + [1] = DEFINE_RES_MEM(BAST_IDE_CS + BAST_PA_IDESECAUX + (6 * 0x20), 0x20), + [2] = DEFINE_RES_IRQ(BAST_IRQ_IDE1), }; static struct platform_device bast_device_ide1 = { diff --git a/arch/arm/mach-s3c24xx/bast-irq.c b/arch/arm/mach-s3c24xx/bast-irq.c index ac7b2ad5c40..c0daa9590b4 100644 --- a/arch/arm/mach-s3c24xx/bast-irq.c +++ b/arch/arm/mach-s3c24xx/bast-irq.c @@ -27,27 +27,20 @@ #include <linux/device.h> #include <linux/io.h> -#include <asm/mach-types.h> - -#include <mach/hardware.h> #include <asm/irq.h> - +#include <asm/mach-types.h> #include <asm/mach/irq.h> +#include <mach/hardware.h> #include <mach/regs-irq.h> -#include <mach/bast-map.h> -#include <mach/bast-irq.h> #include <plat/irq.h> -#if 0 -#include <asm/debug-ll.h> -#endif +#include "bast.h" #define irqdbf(x...) #define irqdbf2(x...) - /* handle PC104 ISA interrupts from the system CPLD */ /* table of ISA irq nos to the relevant mask... zero means @@ -87,7 +80,7 @@ bast_pc104_mask(struct irq_data *data) static void bast_pc104_maskack(struct irq_data *data) { - struct irq_desc *desc = irq_desc + IRQ_ISA; + struct irq_desc *desc = irq_desc + BAST_IRQ_ISA; bast_pc104_mask(data); desc->irq_data.chip->irq_ack(&desc->irq_data); @@ -122,7 +115,7 @@ bast_irq_pc104_demux(unsigned int irq, if (unlikely(stat == 0)) { /* ack if we get an irq with nothing (ie, startup) */ - desc = irq_desc + IRQ_ISA; + desc = irq_desc + BAST_IRQ_ISA; desc->irq_data.chip->irq_ack(&desc->irq_data); } else { /* handle the IRQ */ @@ -147,7 +140,7 @@ static __init int bast_irq_init(void) __raw_writeb(0x0, BAST_VA_PC104_IRQMASK); - irq_set_chained_handler(IRQ_ISA, bast_irq_pc104_demux); + irq_set_chained_handler(BAST_IRQ_ISA, bast_irq_pc104_demux); /* register our IRQs */ diff --git a/arch/arm/mach-s3c24xx/bast.h b/arch/arm/mach-s3c24xx/bast.h new file mode 100644 index 00000000000..5c7534bae92 --- /dev/null +++ b/arch/arm/mach-s3c24xx/bast.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2003-2004 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * BAST - CPLD control constants + * BAST - IRQ Number definitions + * BAST - Memory map definitions + * + * 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. +*/ + +#ifndef __MACH_S3C24XX_BAST_H +#define __MACH_S3C24XX_BAST_H __FILE__ + +/* CTRL1 - Audio LR routing */ + +#define BAST_CPLD_CTRL1_LRCOFF (0x00) +#define BAST_CPLD_CTRL1_LRCADC (0x01) +#define BAST_CPLD_CTRL1_LRCDAC (0x02) +#define BAST_CPLD_CTRL1_LRCARM (0x03) +#define BAST_CPLD_CTRL1_LRMASK (0x03) + +/* CTRL2 - NAND WP control, IDE Reset assert/check */ + +#define BAST_CPLD_CTRL2_WNAND (0x04) +#define BAST_CPLD_CTLR2_IDERST (0x08) + +/* CTRL3 - rom write control, CPLD identity */ + +#define BAST_CPLD_CTRL3_IDMASK (0x0e) +#define BAST_CPLD_CTRL3_ROMWEN (0x01) + +/* CTRL4 - 8bit LCD interface control/status */ + +#define BAST_CPLD_CTRL4_LLAT (0x01) +#define BAST_CPLD_CTRL4_LCDRW (0x02) +#define BAST_CPLD_CTRL4_LCDCMD (0x04) +#define BAST_CPLD_CTRL4_LCDE2 (0x01) + +/* CTRL5 - DMA routing */ + +#define BAST_CPLD_DMA0_PRIIDE (0) +#define BAST_CPLD_DMA0_SECIDE (1) +#define BAST_CPLD_DMA0_ISA15 (2) +#define BAST_CPLD_DMA0_ISA36 (3) + +#define BAST_CPLD_DMA1_PRIIDE (0 << 2) +#define BAST_CPLD_DMA1_SECIDE (1 << 2) +#define BAST_CPLD_DMA1_ISA15 (2 << 2) +#define BAST_CPLD_DMA1_ISA36 (3 << 2) + +/* irq numbers to onboard peripherals */ + +#define BAST_IRQ_USBOC IRQ_EINT18 +#define BAST_IRQ_IDE0 IRQ_EINT16 +#define BAST_IRQ_IDE1 IRQ_EINT17 +#define BAST_IRQ_PCSERIAL1 IRQ_EINT15 +#define BAST_IRQ_PCSERIAL2 IRQ_EINT14 +#define BAST_IRQ_PCPARALLEL IRQ_EINT13 +#define BAST_IRQ_ASIX IRQ_EINT11 +#define BAST_IRQ_DM9000 IRQ_EINT10 +#define BAST_IRQ_ISA IRQ_EINT9 +#define BAST_IRQ_SMALERT IRQ_EINT8 + +/* map */ + +/* + * ok, we've used up to 0x13000000, now we need to find space for the + * peripherals that live in the nGCS[x] areas, which are quite numerous + * in their space. We also have the board's CPLD to find register space + * for. + */ + +#define BAST_IOADDR(x) (S3C2410_ADDR((x) + 0x01300000)) + +/* we put the CPLD registers next, to get them out of the way */ + +#define BAST_VA_CTRL1 BAST_IOADDR(0x00000000) +#define BAST_PA_CTRL1 (S3C2410_CS5 | 0x7800000) + +#define BAST_VA_CTRL2 BAST_IOADDR(0x00100000) +#define BAST_PA_CTRL2 (S3C2410_CS1 | 0x6000000) + +#define BAST_VA_CTRL3 BAST_IOADDR(0x00200000) +#define BAST_PA_CTRL3 (S3C2410_CS1 | 0x6800000) + +#define BAST_VA_CTRL4 BAST_IOADDR(0x00300000) +#define BAST_PA_CTRL4 (S3C2410_CS1 | 0x7000000) + +/* next, we have the PC104 ISA interrupt registers */ + +#define BAST_PA_PC104_IRQREQ (S3C2410_CS5 | 0x6000000) +#define BAST_VA_PC104_IRQREQ BAST_IOADDR(0x00400000) + +#define BAST_PA_PC104_IRQRAW (S3C2410_CS5 | 0x6800000) +#define BAST_VA_PC104_IRQRAW BAST_IOADDR(0x00500000) + +#define BAST_PA_PC104_IRQMASK (S3C2410_CS5 | 0x7000000) +#define BAST_VA_PC104_IRQMASK BAST_IOADDR(0x00600000) + +#define BAST_PA_LCD_RCMD1 (0x8800000) +#define BAST_VA_LCD_RCMD1 BAST_IOADDR(0x00700000) + +#define BAST_PA_LCD_WCMD1 (0x8000000) +#define BAST_VA_LCD_WCMD1 BAST_IOADDR(0x00800000) + +#define BAST_PA_LCD_RDATA1 (0x9800000) +#define BAST_VA_LCD_RDATA1 BAST_IOADDR(0x00900000) + +#define BAST_PA_LCD_WDATA1 (0x9000000) +#define BAST_VA_LCD_WDATA1 BAST_IOADDR(0x00A00000) + +#define BAST_PA_LCD_RCMD2 (0xA800000) +#define BAST_VA_LCD_RCMD2 BAST_IOADDR(0x00B00000) + +#define BAST_PA_LCD_WCMD2 (0xA000000) +#define BAST_VA_LCD_WCMD2 BAST_IOADDR(0x00C00000) + +#define BAST_PA_LCD_RDATA2 (0xB800000) +#define BAST_VA_LCD_RDATA2 BAST_IOADDR(0x00D00000) + +#define BAST_PA_LCD_WDATA2 (0xB000000) +#define BAST_VA_LCD_WDATA2 BAST_IOADDR(0x00E00000) + + +/* + * 0xE0000000 contains the IO space that is split by speed and + * whether the access is for 8 or 16bit IO... this ensures that + * the correct access is made + * + * 0x10000000 of space, partitioned as so: + * + * 0x00000000 to 0x04000000 8bit, slow + * 0x04000000 to 0x08000000 16bit, slow + * 0x08000000 to 0x0C000000 16bit, net + * 0x0C000000 to 0x10000000 16bit, fast + * + * each of these spaces has the following in: + * + * 0x00000000 to 0x01000000 16MB ISA IO space + * 0x01000000 to 0x02000000 16MB ISA memory space + * 0x02000000 to 0x02100000 1MB IDE primary channel + * 0x02100000 to 0x02200000 1MB IDE primary channel aux + * 0x02200000 to 0x02400000 1MB IDE secondary channel + * 0x02300000 to 0x02400000 1MB IDE secondary channel aux + * 0x02400000 to 0x02500000 1MB ASIX ethernet controller + * 0x02500000 to 0x02600000 1MB Davicom DM9000 ethernet controller + * 0x02600000 to 0x02700000 1MB PC SuperIO controller + * + * the phyiscal layout of the zones are: + * nGCS2 - 8bit, slow + * nGCS3 - 16bit, slow + * nGCS4 - 16bit, net + * nGCS5 - 16bit, fast + */ + +#define BAST_VA_MULTISPACE (0xE0000000) + +#define BAST_VA_ISAIO (BAST_VA_MULTISPACE + 0x00000000) +#define BAST_VA_ISAMEM (BAST_VA_MULTISPACE + 0x01000000) +#define BAST_VA_IDEPRI (BAST_VA_MULTISPACE + 0x02000000) +#define BAST_VA_IDEPRIAUX (BAST_VA_MULTISPACE + 0x02100000) +#define BAST_VA_IDESEC (BAST_VA_MULTISPACE + 0x02200000) +#define BAST_VA_IDESECAUX (BAST_VA_MULTISPACE + 0x02300000) +#define BAST_VA_ASIXNET (BAST_VA_MULTISPACE + 0x02400000) +#define BAST_VA_DM9000 (BAST_VA_MULTISPACE + 0x02500000) +#define BAST_VA_SUPERIO (BAST_VA_MULTISPACE + 0x02600000) + +#define BAST_VAM_CS2 (0x00000000) +#define BAST_VAM_CS3 (0x04000000) +#define BAST_VAM_CS4 (0x08000000) +#define BAST_VAM_CS5 (0x0C000000) + +/* physical offset addresses for the peripherals */ + +#define BAST_PA_ISAIO (0x00000000) +#define BAST_PA_ASIXNET (0x01000000) +#define BAST_PA_SUPERIO (0x01800000) +#define BAST_PA_IDEPRI (0x02000000) +#define BAST_PA_IDEPRIAUX (0x02800000) +#define BAST_PA_IDESEC (0x03000000) +#define BAST_PA_IDESECAUX (0x03800000) +#define BAST_PA_ISAMEM (0x04000000) +#define BAST_PA_DM9000 (0x05000000) + +/* some configurations for the peripherals */ + +#define BAST_PCSIO (BAST_VA_SUPERIO + BAST_VAM_CS2) + +#define BAST_ASIXNET_CS BAST_VAM_CS5 +#define BAST_DM9000_CS BAST_VAM_CS4 + +#define BAST_IDE_CS S3C2410_CS5 + +#endif /* __MACH_S3C24XX_BAST_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/gta02.h b/arch/arm/mach-s3c24xx/gta02.h index 21739348215..9430a71e918 100644 --- a/arch/arm/mach-s3c24xx/include/mach/gta02.h +++ b/arch/arm/mach-s3c24xx/gta02.h @@ -1,5 +1,13 @@ -#ifndef _GTA02_H -#define _GTA02_H +/* + * GTA02 header + * + * 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. +*/ + +#ifndef __MACH_S3C24XX_GTA02_H +#define __MACH_S3C24XX_GTA02_H __FILE__ #include <mach/regs-gpio.h> @@ -12,4 +20,4 @@ #define GTA02_IRQ_PCF50633 IRQ_EINT9 -#endif /* _GTA02_H */ +#endif /* __MACH_S3C24XX_GTA02_H */ diff --git a/arch/arm/mach-s3c24xx/h1940-bluetooth.c b/arch/arm/mach-s3c24xx/h1940-bluetooth.c index 3f40c61b6e0..5b98bfd1df4 100644 --- a/arch/arm/mach-s3c24xx/h1940-bluetooth.c +++ b/arch/arm/mach-s3c24xx/h1940-bluetooth.c @@ -19,10 +19,10 @@ #include <linux/gpio.h> #include <linux/rfkill.h> -#include <mach/regs-gpio.h> #include <mach/hardware.h> -#include <mach/h1940-latch.h> -#include <mach/h1940.h> +#include <mach/regs-gpio.h> + +#include "h1940.h" #define DRV_NAME "h1940-bt" diff --git a/arch/arm/mach-s3c24xx/include/mach/h1940-latch.h b/arch/arm/mach-s3c24xx/h1940.h index fc897d3a056..2950cc46684 100644 --- a/arch/arm/mach-s3c24xx/include/mach/h1940-latch.h +++ b/arch/arm/mach-s3c24xx/h1940.h @@ -1,20 +1,30 @@ -/* arch/arm/mach-s3c2410/include/mach/h1940-latch.h +/* + * Copyright 2006 Ben Dooks <ben-linux@fluff.org> * * Copyright (c) 2005 Simtec Electronics * http://armlinux.simtec.co.uk/ * Ben Dooks <ben@simtec.co.uk> * - * iPAQ H1940 series - latch definitions + * iPAQ H1940 series definitions * * 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. */ -#ifndef __ASM_ARCH_H1940_LATCH_H -#define __ASM_ARCH_H1940_LATCH_H +#ifndef __MACH_S3C24XX_H1940_H +#define __MACH_S3C24XX_H1940_H __FILE__ -#include <asm/gpio.h> +#define H1940_SUSPEND_CHECKSUM (0x30003ff8) +#define H1940_SUSPEND_RESUMEAT (0x30081000) +#define H1940_SUSPEND_CHECK (0x30080000) + +extern void h1940_pm_return(void); +extern int h1940_led_blink_set(unsigned gpio, int state, + unsigned long *delay_on, + unsigned long *delay_off); + +#include <linux/gpio.h> #define H1940_LATCH_GPIO(x) (S3C_GPIO_END + (x)) @@ -40,4 +50,4 @@ #define H1940_LATCH_LED_GREEN H1940_LATCH_GPIO(14) #define H1940_LATCH_LED_FLASH H1940_LATCH_GPIO(15) -#endif /* __ASM_ARCH_H1940_LATCH_H */ +#endif /* __MACH_S3C24XX_H1940_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/anubis-cpld.h b/arch/arm/mach-s3c24xx/include/mach/anubis-cpld.h deleted file mode 100644 index 1b614d5a81f..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/anubis-cpld.h +++ /dev/null @@ -1,25 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/anubis-cpld.h - * - * Copyright (c) 2005 Simtec Electronics - * http://www.simtec.co.uk/products/ - * Ben Dooks <ben@simtec.co.uk> - * - * ANUBIS - CPLD control constants - * - * 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. -*/ - -#ifndef __ASM_ARCH_ANUBISCPLD_H -#define __ASM_ARCH_ANUBISCPLD_H - -/* CTRL2 - NAND WP control, IDE Reset assert/check */ - -#define ANUBIS_CTRL1_NANDSEL (0x3) - -/* IDREG - revision */ - -#define ANUBIS_IDREG_REVMASK (0x7) - -#endif /* __ASM_ARCH_ANUBISCPLD_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/anubis-irq.h b/arch/arm/mach-s3c24xx/include/mach/anubis-irq.h deleted file mode 100644 index a2a328134e3..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/anubis-irq.h +++ /dev/null @@ -1,21 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/anubis-irq.h - * - * Copyright (c) 2005 Simtec Electronics - * http://www.simtec.co.uk/products/ - * Ben Dooks <ben@simtec.co.uk> - * - * ANUBIS - IRQ Number definitions - * - * 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. -*/ - -#ifndef __ASM_ARCH_ANUBISIRQ_H -#define __ASM_ARCH_ANUBISIRQ_H - -#define IRQ_IDE0 IRQ_EINT2 -#define IRQ_IDE1 IRQ_EINT3 -#define IRQ_ASIX IRQ_EINT1 - -#endif /* __ASM_ARCH_ANUBISIRQ_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/anubis-map.h b/arch/arm/mach-s3c24xx/include/mach/anubis-map.h deleted file mode 100644 index c9deb3a5b2c..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/anubis-map.h +++ /dev/null @@ -1,38 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/anubis-map.h - * - * Copyright (c) 2005 Simtec Electronics - * http://www.simtec.co.uk/products/ - * Ben Dooks <ben@simtec.co.uk> - * - * ANUBIS - Memory map definitions - * - * 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. -*/ - -/* needs arch/map.h including with this */ - -#ifndef __ASM_ARCH_ANUBISMAP_H -#define __ASM_ARCH_ANUBISMAP_H - -/* start peripherals off after the S3C2410 */ - -#define ANUBIS_IOADDR(x) (S3C2410_ADDR((x) + 0x01800000)) - -#define ANUBIS_PA_CPLD (S3C2410_CS1 | (1<<26)) - -/* we put the CPLD registers next, to get them out of the way */ - -#define ANUBIS_VA_CTRL1 ANUBIS_IOADDR(0x00000000) /* 0x01800000 */ -#define ANUBIS_PA_CTRL1 (ANUBIS_PA_CPLD) - -#define ANUBIS_VA_IDREG ANUBIS_IOADDR(0x00300000) /* 0x01B00000 */ -#define ANUBIS_PA_IDREG (ANUBIS_PA_CPLD + (3<<23)) - -#define ANUBIS_IDEPRI ANUBIS_IOADDR(0x01000000) -#define ANUBIS_IDEPRIAUX ANUBIS_IOADDR(0x01100000) -#define ANUBIS_IDESEC ANUBIS_IOADDR(0x01200000) -#define ANUBIS_IDESECAUX ANUBIS_IOADDR(0x01300000) - -#endif /* __ASM_ARCH_ANUBISMAP_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/bast-cpld.h b/arch/arm/mach-s3c24xx/include/mach/bast-cpld.h deleted file mode 100644 index bee2a7a932a..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/bast-cpld.h +++ /dev/null @@ -1,53 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/bast-cpld.h - * - * Copyright (c) 2003-2004 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * BAST - CPLD control constants - * - * 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. -*/ - -#ifndef __ASM_ARCH_BASTCPLD_H -#define __ASM_ARCH_BASTCPLD_H - -/* CTRL1 - Audio LR routing */ - -#define BAST_CPLD_CTRL1_LRCOFF (0x00) -#define BAST_CPLD_CTRL1_LRCADC (0x01) -#define BAST_CPLD_CTRL1_LRCDAC (0x02) -#define BAST_CPLD_CTRL1_LRCARM (0x03) -#define BAST_CPLD_CTRL1_LRMASK (0x03) - -/* CTRL2 - NAND WP control, IDE Reset assert/check */ - -#define BAST_CPLD_CTRL2_WNAND (0x04) -#define BAST_CPLD_CTLR2_IDERST (0x08) - -/* CTRL3 - rom write control, CPLD identity */ - -#define BAST_CPLD_CTRL3_IDMASK (0x0e) -#define BAST_CPLD_CTRL3_ROMWEN (0x01) - -/* CTRL4 - 8bit LCD interface control/status */ - -#define BAST_CPLD_CTRL4_LLAT (0x01) -#define BAST_CPLD_CTRL4_LCDRW (0x02) -#define BAST_CPLD_CTRL4_LCDCMD (0x04) -#define BAST_CPLD_CTRL4_LCDE2 (0x01) - -/* CTRL5 - DMA routing */ - -#define BAST_CPLD_DMA0_PRIIDE (0<<0) -#define BAST_CPLD_DMA0_SECIDE (1<<0) -#define BAST_CPLD_DMA0_ISA15 (2<<0) -#define BAST_CPLD_DMA0_ISA36 (3<<0) - -#define BAST_CPLD_DMA1_PRIIDE (0<<2) -#define BAST_CPLD_DMA1_SECIDE (1<<2) -#define BAST_CPLD_DMA1_ISA15 (2<<2) -#define BAST_CPLD_DMA1_ISA36 (3<<2) - -#endif /* __ASM_ARCH_BASTCPLD_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/bast-irq.h b/arch/arm/mach-s3c24xx/include/mach/bast-irq.h deleted file mode 100644 index cac428c42e7..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/bast-irq.h +++ /dev/null @@ -1,29 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/bast-irq.h - * - * Copyright (c) 2003-2004 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * Machine BAST - IRQ Number definitions - * - * 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. -*/ - -#ifndef __ASM_ARCH_BASTIRQ_H -#define __ASM_ARCH_BASTIRQ_H - -/* irq numbers to onboard peripherals */ - -#define IRQ_USBOC IRQ_EINT18 -#define IRQ_IDE0 IRQ_EINT16 -#define IRQ_IDE1 IRQ_EINT17 -#define IRQ_PCSERIAL1 IRQ_EINT15 -#define IRQ_PCSERIAL2 IRQ_EINT14 -#define IRQ_PCPARALLEL IRQ_EINT13 -#define IRQ_ASIX IRQ_EINT11 -#define IRQ_DM9000 IRQ_EINT10 -#define IRQ_ISA IRQ_EINT9 -#define IRQ_SMALERT IRQ_EINT8 - -#endif /* __ASM_ARCH_BASTIRQ_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/bast-map.h b/arch/arm/mach-s3c24xx/include/mach/bast-map.h deleted file mode 100644 index eecea2a50f8..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/bast-map.h +++ /dev/null @@ -1,146 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/bast-map.h - * - * Copyright (c) 2003-2004 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * Machine BAST - Memory map definitions - * - * 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. -*/ - -/* needs arch/map.h including with this */ - -/* ok, we've used up to 0x13000000, now we need to find space for the - * peripherals that live in the nGCS[x] areas, which are quite numerous - * in their space. We also have the board's CPLD to find register space - * for. - */ - -#ifndef __ASM_ARCH_BASTMAP_H -#define __ASM_ARCH_BASTMAP_H - -#define BAST_IOADDR(x) (S3C2410_ADDR((x) + 0x01300000)) - -/* we put the CPLD registers next, to get them out of the way */ - -#define BAST_VA_CTRL1 BAST_IOADDR(0x00000000) /* 0x01300000 */ -#define BAST_PA_CTRL1 (S3C2410_CS5 | 0x7800000) - -#define BAST_VA_CTRL2 BAST_IOADDR(0x00100000) /* 0x01400000 */ -#define BAST_PA_CTRL2 (S3C2410_CS1 | 0x6000000) - -#define BAST_VA_CTRL3 BAST_IOADDR(0x00200000) /* 0x01500000 */ -#define BAST_PA_CTRL3 (S3C2410_CS1 | 0x6800000) - -#define BAST_VA_CTRL4 BAST_IOADDR(0x00300000) /* 0x01600000 */ -#define BAST_PA_CTRL4 (S3C2410_CS1 | 0x7000000) - -/* next, we have the PC104 ISA interrupt registers */ - -#define BAST_PA_PC104_IRQREQ (S3C2410_CS5 | 0x6000000) /* 0x01700000 */ -#define BAST_VA_PC104_IRQREQ BAST_IOADDR(0x00400000) - -#define BAST_PA_PC104_IRQRAW (S3C2410_CS5 | 0x6800000) /* 0x01800000 */ -#define BAST_VA_PC104_IRQRAW BAST_IOADDR(0x00500000) - -#define BAST_PA_PC104_IRQMASK (S3C2410_CS5 | 0x7000000) /* 0x01900000 */ -#define BAST_VA_PC104_IRQMASK BAST_IOADDR(0x00600000) - -#define BAST_PA_LCD_RCMD1 (0x8800000) -#define BAST_VA_LCD_RCMD1 BAST_IOADDR(0x00700000) - -#define BAST_PA_LCD_WCMD1 (0x8000000) -#define BAST_VA_LCD_WCMD1 BAST_IOADDR(0x00800000) - -#define BAST_PA_LCD_RDATA1 (0x9800000) -#define BAST_VA_LCD_RDATA1 BAST_IOADDR(0x00900000) - -#define BAST_PA_LCD_WDATA1 (0x9000000) -#define BAST_VA_LCD_WDATA1 BAST_IOADDR(0x00A00000) - -#define BAST_PA_LCD_RCMD2 (0xA800000) -#define BAST_VA_LCD_RCMD2 BAST_IOADDR(0x00B00000) - -#define BAST_PA_LCD_WCMD2 (0xA000000) -#define BAST_VA_LCD_WCMD2 BAST_IOADDR(0x00C00000) - -#define BAST_PA_LCD_RDATA2 (0xB800000) -#define BAST_VA_LCD_RDATA2 BAST_IOADDR(0x00D00000) - -#define BAST_PA_LCD_WDATA2 (0xB000000) -#define BAST_VA_LCD_WDATA2 BAST_IOADDR(0x00E00000) - - -/* 0xE0000000 contains the IO space that is split by speed and - * whether the access is for 8 or 16bit IO... this ensures that - * the correct access is made - * - * 0x10000000 of space, partitioned as so: - * - * 0x00000000 to 0x04000000 8bit, slow - * 0x04000000 to 0x08000000 16bit, slow - * 0x08000000 to 0x0C000000 16bit, net - * 0x0C000000 to 0x10000000 16bit, fast - * - * each of these spaces has the following in: - * - * 0x00000000 to 0x01000000 16MB ISA IO space - * 0x01000000 to 0x02000000 16MB ISA memory space - * 0x02000000 to 0x02100000 1MB IDE primary channel - * 0x02100000 to 0x02200000 1MB IDE primary channel aux - * 0x02200000 to 0x02400000 1MB IDE secondary channel - * 0x02300000 to 0x02400000 1MB IDE secondary channel aux - * 0x02400000 to 0x02500000 1MB ASIX ethernet controller - * 0x02500000 to 0x02600000 1MB Davicom DM9000 ethernet controller - * 0x02600000 to 0x02700000 1MB PC SuperIO controller - * - * the phyiscal layout of the zones are: - * nGCS2 - 8bit, slow - * nGCS3 - 16bit, slow - * nGCS4 - 16bit, net - * nGCS5 - 16bit, fast - */ - -#define BAST_VA_MULTISPACE (0xE0000000) - -#define BAST_VA_ISAIO (BAST_VA_MULTISPACE + 0x00000000) -#define BAST_VA_ISAMEM (BAST_VA_MULTISPACE + 0x01000000) -#define BAST_VA_IDEPRI (BAST_VA_MULTISPACE + 0x02000000) -#define BAST_VA_IDEPRIAUX (BAST_VA_MULTISPACE + 0x02100000) -#define BAST_VA_IDESEC (BAST_VA_MULTISPACE + 0x02200000) -#define BAST_VA_IDESECAUX (BAST_VA_MULTISPACE + 0x02300000) -#define BAST_VA_ASIXNET (BAST_VA_MULTISPACE + 0x02400000) -#define BAST_VA_DM9000 (BAST_VA_MULTISPACE + 0x02500000) -#define BAST_VA_SUPERIO (BAST_VA_MULTISPACE + 0x02600000) - -#define BAST_VA_MULTISPACE (0xE0000000) - -#define BAST_VAM_CS2 (0x00000000) -#define BAST_VAM_CS3 (0x04000000) -#define BAST_VAM_CS4 (0x08000000) -#define BAST_VAM_CS5 (0x0C000000) - -/* physical offset addresses for the peripherals */ - -#define BAST_PA_ISAIO (0x00000000) -#define BAST_PA_ASIXNET (0x01000000) -#define BAST_PA_SUPERIO (0x01800000) -#define BAST_PA_IDEPRI (0x02000000) -#define BAST_PA_IDEPRIAUX (0x02800000) -#define BAST_PA_IDESEC (0x03000000) -#define BAST_PA_IDESECAUX (0x03800000) -#define BAST_PA_ISAMEM (0x04000000) -#define BAST_PA_DM9000 (0x05000000) - -/* some configurations for the peripherals */ - -#define BAST_PCSIO (BAST_VA_SUPERIO + BAST_VAM_CS2) -/* */ - -#define BAST_ASIXNET_CS BAST_VAM_CS5 -#define BAST_IDE_CS BAST_VAM_CS5 -#define BAST_DM9000_CS BAST_VAM_CS4 - -#endif /* __ASM_ARCH_BASTMAP_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/gpio-fns.h b/arch/arm/mach-s3c24xx/include/mach/gpio-fns.h deleted file mode 100644 index c53ad34c657..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/gpio-fns.h +++ /dev/null @@ -1 +0,0 @@ -#include <plat/gpio-fns.h> diff --git a/arch/arm/mach-s3c24xx/include/mach/gpio-nrs.h b/arch/arm/mach-s3c24xx/include/mach/gpio-nrs.h deleted file mode 100644 index 3890a05948f..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/gpio-nrs.h +++ /dev/null @@ -1,97 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/gpio-nrs.h - * - * Copyright (c) 2008 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks <ben@simtec.co.uk> - * - * S3C2410 - GPIO bank numbering - * - * 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. -*/ - -#ifndef __MACH_GPIONRS_H -#define __MACH_GPIONRS_H - -#define S3C2410_GPIONO(bank,offset) ((bank) + (offset)) - -#define S3C2410_GPIO_BANKG (32*6) -#define S3C2410_GPIO_BANKH (32*7) - -/* GPIO sizes for various SoCs: - * - * 2442 - * 2410 2412 2440 2443 2416 - * ---- ---- ---- ---- ---- - * A 23 22 25 16 25 - * B 11 11 11 11 9 - * C 16 15 16 16 16 - * D 16 16 16 16 16 - * E 16 16 16 16 16 - * F 8 8 8 8 8 - * G 16 16 16 16 8 - * H 11 11 9 15 15 - * J -- -- 13 16 -- - * K -- -- -- -- 16 - * L -- -- -- 15 7 - * M -- -- -- 2 2 - */ - -/* GPIO bank sizes */ -#define S3C2410_GPIO_A_NR (32) -#define S3C2410_GPIO_B_NR (32) -#define S3C2410_GPIO_C_NR (32) -#define S3C2410_GPIO_D_NR (32) -#define S3C2410_GPIO_E_NR (32) -#define S3C2410_GPIO_F_NR (32) -#define S3C2410_GPIO_G_NR (32) -#define S3C2410_GPIO_H_NR (32) -#define S3C2410_GPIO_J_NR (32) /* technically 16. */ -#define S3C2410_GPIO_K_NR (32) /* technically 16. */ -#define S3C2410_GPIO_L_NR (32) /* technically 15. */ -#define S3C2410_GPIO_M_NR (32) /* technically 2. */ - -#if CONFIG_S3C_GPIO_SPACE != 0 -#error CONFIG_S3C_GPIO_SPACE cannot be nonzero at the moment -#endif - -#define S3C2410_GPIO_NEXT(__gpio) \ - ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 0) - -#ifndef __ASSEMBLY__ - -enum s3c_gpio_number { - S3C2410_GPIO_A_START = 0, - S3C2410_GPIO_B_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_A), - S3C2410_GPIO_C_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_B), - S3C2410_GPIO_D_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_C), - S3C2410_GPIO_E_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_D), - S3C2410_GPIO_F_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_E), - S3C2410_GPIO_G_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_F), - S3C2410_GPIO_H_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_G), - S3C2410_GPIO_J_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_H), - S3C2410_GPIO_K_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_J), - S3C2410_GPIO_L_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_K), - S3C2410_GPIO_M_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_L), -}; - -#endif /* __ASSEMBLY__ */ - -/* S3C2410 GPIO number definitions. */ - -#define S3C2410_GPA(_nr) (S3C2410_GPIO_A_START + (_nr)) -#define S3C2410_GPB(_nr) (S3C2410_GPIO_B_START + (_nr)) -#define S3C2410_GPC(_nr) (S3C2410_GPIO_C_START + (_nr)) -#define S3C2410_GPD(_nr) (S3C2410_GPIO_D_START + (_nr)) -#define S3C2410_GPE(_nr) (S3C2410_GPIO_E_START + (_nr)) -#define S3C2410_GPF(_nr) (S3C2410_GPIO_F_START + (_nr)) -#define S3C2410_GPG(_nr) (S3C2410_GPIO_G_START + (_nr)) -#define S3C2410_GPH(_nr) (S3C2410_GPIO_H_START + (_nr)) -#define S3C2410_GPJ(_nr) (S3C2410_GPIO_J_START + (_nr)) -#define S3C2410_GPK(_nr) (S3C2410_GPIO_K_START + (_nr)) -#define S3C2410_GPL(_nr) (S3C2410_GPIO_L_START + (_nr)) -#define S3C2410_GPM(_nr) (S3C2410_GPIO_M_START + (_nr)) - -#endif /* __MACH_GPIONRS_H */ - diff --git a/arch/arm/mach-s3c24xx/include/mach/gpio-track.h b/arch/arm/mach-s3c24xx/include/mach/gpio-track.h deleted file mode 100644 index c410a078622..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/gpio-track.h +++ /dev/null @@ -1,33 +0,0 @@ -/* arch/arm/mach-s3c24100/include/mach/gpio-core.h - * - * Copyright 2008 Openmoko, Inc. - * Copyright 2008 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * http://armlinux.simtec.co.uk/ - * - * S3C2410 - GPIO core support - * - * 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. -*/ - -#ifndef __ASM_ARCH_GPIO_CORE_H -#define __ASM_ARCH_GPIO_CORE_H __FILE__ - -#include <mach/regs-gpio.h> - -extern struct samsung_gpio_chip s3c24xx_gpios[]; - -static inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int pin) -{ - struct samsung_gpio_chip *chip; - - if (pin > S3C_GPIO_END) - return NULL; - - chip = &s3c24xx_gpios[pin/32]; - return ((pin - chip->chip.base) < chip->chip.ngpio) ? chip : NULL; -} - -#endif /* __ASM_ARCH_GPIO_CORE_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/gpio.h b/arch/arm/mach-s3c24xx/include/mach/gpio.h index 6fac70f3484..14591563ca7 100644 --- a/arch/arm/mach-s3c24xx/include/mach/gpio.h +++ b/arch/arm/mach-s3c24xx/include/mach/gpio.h @@ -1,5 +1,4 @@ -/* arch/arm/mach-s3c2410/include/mach/gpio.h - * +/* * Copyright (c) 2008 Simtec Electronics * http://armlinux.simtec.co.uk/ * Ben Dooks <ben@simtec.co.uk> @@ -15,6 +14,9 @@ * devices that need GPIO. */ +#ifndef __MACH_GPIO_H +#define __MACH_GPIO_H __FILE__ + #ifdef CONFIG_CPU_S3C244X #define ARCH_NR_GPIOS (32 * 9 + CONFIG_S3C24XX_GPIO_EXTRA) #elif defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2416) @@ -23,8 +25,83 @@ #define ARCH_NR_GPIOS (256 + CONFIG_S3C24XX_GPIO_EXTRA) #endif -#include <mach/gpio-nrs.h> -#include <mach/gpio-fns.h> +/* + * GPIO sizes for various SoCs: + * + * 2410 2412 2440 2443 2416 + * 2442 + * ---- ---- ---- ---- ---- + * A 23 22 25 16 25 + * B 11 11 11 11 9 + * C 16 15 16 16 16 + * D 16 16 16 16 16 + * E 16 16 16 16 16 + * F 8 8 8 8 8 + * G 16 16 16 16 8 + * H 11 11 9 15 15 + * J -- -- 13 16 -- + * K -- -- -- -- 16 + * L -- -- -- 15 7 + * M -- -- -- 2 2 + */ + +/* GPIO bank sizes */ + +#define S3C2410_GPIO_A_NR (32) +#define S3C2410_GPIO_B_NR (32) +#define S3C2410_GPIO_C_NR (32) +#define S3C2410_GPIO_D_NR (32) +#define S3C2410_GPIO_E_NR (32) +#define S3C2410_GPIO_F_NR (32) +#define S3C2410_GPIO_G_NR (32) +#define S3C2410_GPIO_H_NR (32) +#define S3C2410_GPIO_J_NR (32) /* technically 16. */ +#define S3C2410_GPIO_K_NR (32) /* technically 16. */ +#define S3C2410_GPIO_L_NR (32) /* technically 15. */ +#define S3C2410_GPIO_M_NR (32) /* technically 2. */ + +#if CONFIG_S3C_GPIO_SPACE != 0 +#error CONFIG_S3C_GPIO_SPACE cannot be nonzero at the moment +#endif + +#define S3C2410_GPIO_NEXT(__gpio) \ + ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 0) + +#ifndef __ASSEMBLY__ + +enum s3c_gpio_number { + S3C2410_GPIO_A_START = 0, + S3C2410_GPIO_B_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_A), + S3C2410_GPIO_C_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_B), + S3C2410_GPIO_D_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_C), + S3C2410_GPIO_E_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_D), + S3C2410_GPIO_F_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_E), + S3C2410_GPIO_G_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_F), + S3C2410_GPIO_H_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_G), + S3C2410_GPIO_J_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_H), + S3C2410_GPIO_K_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_J), + S3C2410_GPIO_L_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_K), + S3C2410_GPIO_M_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_L), +}; + +#endif /* __ASSEMBLY__ */ + +/* S3C2410 GPIO number definitions. */ + +#define S3C2410_GPA(_nr) (S3C2410_GPIO_A_START + (_nr)) +#define S3C2410_GPB(_nr) (S3C2410_GPIO_B_START + (_nr)) +#define S3C2410_GPC(_nr) (S3C2410_GPIO_C_START + (_nr)) +#define S3C2410_GPD(_nr) (S3C2410_GPIO_D_START + (_nr)) +#define S3C2410_GPE(_nr) (S3C2410_GPIO_E_START + (_nr)) +#define S3C2410_GPF(_nr) (S3C2410_GPIO_F_START + (_nr)) +#define S3C2410_GPG(_nr) (S3C2410_GPIO_G_START + (_nr)) +#define S3C2410_GPH(_nr) (S3C2410_GPIO_H_START + (_nr)) +#define S3C2410_GPJ(_nr) (S3C2410_GPIO_J_START + (_nr)) +#define S3C2410_GPK(_nr) (S3C2410_GPIO_K_START + (_nr)) +#define S3C2410_GPL(_nr) (S3C2410_GPIO_L_START + (_nr)) +#define S3C2410_GPM(_nr) (S3C2410_GPIO_M_START + (_nr)) + +#include <plat/gpio-cfg.h> #ifdef CONFIG_CPU_S3C244X #define S3C_GPIO_END (S3C2410_GPJ(0) + 32) @@ -33,3 +110,5 @@ #else #define S3C_GPIO_END (S3C2410_GPH(0) + 32) #endif + +#endif /* __MACH_GPIO_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/h1940.h b/arch/arm/mach-s3c24xx/include/mach/h1940.h deleted file mode 100644 index 2aa683c8d3d..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/h1940.h +++ /dev/null @@ -1,24 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/h1940.h - * - * Copyright 2006 Ben Dooks <ben-linux@fluff.org> - * - * H1940 definitions - * - * 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. -*/ - -#ifndef __ASM_ARCH_H1940_H -#define __ASM_ARCH_H1940_H - -#define H1940_SUSPEND_CHECKSUM (0x30003ff8) -#define H1940_SUSPEND_RESUMEAT (0x30081000) -#define H1940_SUSPEND_CHECK (0x30080000) - -extern void h1940_pm_return(void); -extern int h1940_led_blink_set(unsigned gpio, int state, - unsigned long *delay_on, unsigned long *delay_off); - - -#endif /* __ASM_ARCH_H1940_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/idle.h b/arch/arm/mach-s3c24xx/include/mach/idle.h deleted file mode 100644 index e9ddd706b16..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/idle.h +++ /dev/null @@ -1,24 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/idle.h - * - * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk> - * http://www.simtec.co.uk/products/SWLINUX/ - * - * 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. - * - * S3C2410 CPU Idle controls -*/ - -#ifndef __ASM_ARCH_IDLE_H -#define __ASM_ARCH_IDLE_H __FILE__ - -/* This allows the over-ride of the default idle code, in case there - * is any other things to be done over idle (like DVS) -*/ - -extern void (*s3c24xx_idle)(void); - -extern void s3c24xx_default_idle(void); - -#endif /* __ASM_ARCH_IDLE_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/osiris-cpld.h b/arch/arm/mach-s3c24xx/include/mach/osiris-cpld.h deleted file mode 100644 index e9e36b0abba..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/osiris-cpld.h +++ /dev/null @@ -1,30 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/osiris-cpld.h - * - * Copyright 2005 Simtec Electronics - * http://www.simtec.co.uk/products/ - * Ben Dooks <ben@simtec.co.uk> - * - * OSIRIS - CPLD control constants - * - * 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. -*/ - -#ifndef __ASM_ARCH_OSIRISCPLD_H -#define __ASM_ARCH_OSIRISCPLD_H - -/* CTRL0 - NAND WP control */ - -#define OSIRIS_CTRL0_NANDSEL (0x3) -#define OSIRIS_CTRL0_BOOT_INT (1<<3) -#define OSIRIS_CTRL0_PCMCIA (1<<4) -#define OSIRIS_CTRL0_FIX8 (1<<5) -#define OSIRIS_CTRL0_PCMCIA_nWAIT (1<<6) -#define OSIRIS_CTRL0_PCMCIA_nIOIS16 (1<<7) - -#define OSIRIS_CTRL1_FIX8 (1<<0) - -#define OSIRIS_ID_REVMASK (0x7) - -#endif /* __ASM_ARCH_OSIRISCPLD_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h b/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h index a11a638bd59..c2ef016032a 100644 --- a/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h +++ b/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h @@ -14,8 +14,6 @@ #ifndef __ASM_ARCH_REGS_GPIO_H #define __ASM_ARCH_REGS_GPIO_H -#include <mach/gpio-nrs.h> - #define S3C24XX_MISCCR S3C24XX_GPIOREG2(0x80) /* general configuration options */ diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-s3c2412.h b/arch/arm/mach-s3c24xx/include/mach/regs-s3c2412.h deleted file mode 100644 index aa69dc79bc3..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/regs-s3c2412.h +++ /dev/null @@ -1,23 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/regs-s3c2412.h - * - * Copyright 2007 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks <ben@simtec.co.uk> - * - * 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. - * - * S3C2412 specific register definitions -*/ - -#ifndef __ASM_ARCH_REGS_S3C2412_H -#define __ASM_ARCH_REGS_S3C2412_H "s3c2412" - -#define S3C2412_SWRST (S3C24XX_VA_CLKPWR + 0x30) -#define S3C2412_SWRST_RESET (0x533C2412) - -/* see regs-power.h for the other registers in the power block. */ - -#endif /* __ASM_ARCH_REGS_S3C2412_H */ - diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-s3c2416-mem.h b/arch/arm/mach-s3c24xx/include/mach/regs-s3c2416-mem.h deleted file mode 100644 index 2f31b74974a..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/regs-s3c2416-mem.h +++ /dev/null @@ -1,30 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/regs-s3c2416-mem.h - * - * Copyright (c) 2009 Yauhen Kharuzhy <jekhor@gmail.com>, - * as part of OpenInkpot project - * Copyright (c) 2009 Promwad Innovation Company - * Yauhen Kharuzhy <yauhen.kharuzhy@promwad.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. - * - * S3C2416 memory register definitions -*/ - -#ifndef __ASM_ARM_REGS_S3C2416_MEM -#define __ASM_ARM_REGS_S3C2416_MEM - -#ifndef S3C2416_MEMREG -#define S3C2416_MEMREG(x) (S3C24XX_VA_MEMCTRL + (x)) -#endif - -#define S3C2416_BANKCFG S3C2416_MEMREG(0x00) -#define S3C2416_BANKCON1 S3C2416_MEMREG(0x04) -#define S3C2416_BANKCON2 S3C2416_MEMREG(0x08) -#define S3C2416_BANKCON3 S3C2416_MEMREG(0x0C) - -#define S3C2416_REFRESH S3C2416_MEMREG(0x10) -#define S3C2416_TIMEOUT S3C2416_MEMREG(0x14) - -#endif /* __ASM_ARM_REGS_S3C2416_MEM */ diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-s3c2416.h b/arch/arm/mach-s3c24xx/include/mach/regs-s3c2416.h deleted file mode 100644 index e443167efb8..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/regs-s3c2416.h +++ /dev/null @@ -1,24 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/regs-s3c2416.h - * - * Copyright (c) 2009 Yauhen Kharuzhy <jekhor@gmail.com>, - * as part of OpenInkpot project - * Copyright (c) 2009 Promwad Innovation Company - * Yauhen Kharuzhy <yauhen.kharuzhy@promwad.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. - * - * S3C2416 specific register definitions -*/ - -#ifndef __ASM_ARCH_REGS_S3C2416_H -#define __ASM_ARCH_REGS_S3C2416_H "s3c2416" - -#define S3C2416_SWRST (S3C24XX_VA_CLKPWR + 0x44) -#define S3C2416_SWRST_RESET (0x533C2416) - -/* see regs-power.h for the other registers in the power block. */ - -#endif /* __ASM_ARCH_REGS_S3C2416_H */ - diff --git a/arch/arm/mach-s3c24xx/include/mach/vr1000-cpld.h b/arch/arm/mach-s3c24xx/include/mach/vr1000-cpld.h deleted file mode 100644 index e4119913d7c..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/vr1000-cpld.h +++ /dev/null @@ -1,18 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/vr1000-cpld.h - * - * Copyright (c) 2003 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * VR1000 - CPLD control constants - * - * 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. -*/ - -#ifndef __ASM_ARCH_VR1000CPLD_H -#define __ASM_ARCH_VR1000CPLD_H - -#define VR1000_CPLD_CTRL2_RAMWEN (0x04) /* SRAM Write Enable */ - -#endif /* __ASM_ARCH_VR1000CPLD_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/vr1000-irq.h b/arch/arm/mach-s3c24xx/include/mach/vr1000-irq.h deleted file mode 100644 index 47add133b8e..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/vr1000-irq.h +++ /dev/null @@ -1,26 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/vr1000-irq.h - * - * Copyright (c) 2003-2004 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * Machine VR1000 - IRQ Number definitions - * - * 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. -*/ - -#ifndef __ASM_ARCH_VR1000IRQ_H -#define __ASM_ARCH_VR1000IRQ_H - -/* irq numbers to onboard peripherals */ - -#define IRQ_USBOC IRQ_EINT19 -#define IRQ_IDE0 IRQ_EINT16 -#define IRQ_IDE1 IRQ_EINT17 -#define IRQ_VR1000_SERIAL IRQ_EINT12 -#define IRQ_VR1000_DM9000A IRQ_EINT10 -#define IRQ_VR1000_DM9000N IRQ_EINT9 -#define IRQ_SMALERT IRQ_EINT8 - -#endif /* __ASM_ARCH_VR1000IRQ_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/vr1000-map.h b/arch/arm/mach-s3c24xx/include/mach/vr1000-map.h deleted file mode 100644 index 28376e56dd3..00000000000 --- a/arch/arm/mach-s3c24xx/include/mach/vr1000-map.h +++ /dev/null @@ -1,110 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/vr1000-map.h - * - * Copyright (c) 2003-2005 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * Machine VR1000 - Memory map definitions - * - * 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. -*/ - -/* needs arch/map.h including with this */ - -/* ok, we've used up to 0x13000000, now we need to find space for the - * peripherals that live in the nGCS[x] areas, which are quite numerous - * in their space. We also have the board's CPLD to find register space - * for. - */ - -#ifndef __ASM_ARCH_VR1000MAP_H -#define __ASM_ARCH_VR1000MAP_H - -#include <mach/bast-map.h> - -#define VR1000_IOADDR(x) BAST_IOADDR(x) - -/* we put the CPLD registers next, to get them out of the way */ - -#define VR1000_VA_CTRL1 VR1000_IOADDR(0x00000000) /* 0x01300000 */ -#define VR1000_PA_CTRL1 (S3C2410_CS5 | 0x7800000) - -#define VR1000_VA_CTRL2 VR1000_IOADDR(0x00100000) /* 0x01400000 */ -#define VR1000_PA_CTRL2 (S3C2410_CS1 | 0x6000000) - -#define VR1000_VA_CTRL3 VR1000_IOADDR(0x00200000) /* 0x01500000 */ -#define VR1000_PA_CTRL3 (S3C2410_CS1 | 0x6800000) - -#define VR1000_VA_CTRL4 VR1000_IOADDR(0x00300000) /* 0x01600000 */ -#define VR1000_PA_CTRL4 (S3C2410_CS1 | 0x7000000) - -/* next, we have the PC104 ISA interrupt registers */ - -#define VR1000_PA_PC104_IRQREQ (S3C2410_CS5 | 0x6000000) /* 0x01700000 */ -#define VR1000_VA_PC104_IRQREQ VR1000_IOADDR(0x00400000) - -#define VR1000_PA_PC104_IRQRAW (S3C2410_CS5 | 0x6800000) /* 0x01800000 */ -#define VR1000_VA_PC104_IRQRAW VR1000_IOADDR(0x00500000) - -#define VR1000_PA_PC104_IRQMASK (S3C2410_CS5 | 0x7000000) /* 0x01900000 */ -#define VR1000_VA_PC104_IRQMASK VR1000_IOADDR(0x00600000) - -/* 0xE0000000 contains the IO space that is split by speed and - * whether the access is for 8 or 16bit IO... this ensures that - * the correct access is made - * - * 0x10000000 of space, partitioned as so: - * - * 0x00000000 to 0x04000000 8bit, slow - * 0x04000000 to 0x08000000 16bit, slow - * 0x08000000 to 0x0C000000 16bit, net - * 0x0C000000 to 0x10000000 16bit, fast - * - * each of these spaces has the following in: - * - * 0x02000000 to 0x02100000 1MB IDE primary channel - * 0x02100000 to 0x02200000 1MB IDE primary channel aux - * 0x02200000 to 0x02400000 1MB IDE secondary channel - * 0x02300000 to 0x02400000 1MB IDE secondary channel aux - * 0x02500000 to 0x02600000 1MB Davicom DM9000 ethernet controllers - * 0x02600000 to 0x02700000 1MB - * - * the phyiscal layout of the zones are: - * nGCS2 - 8bit, slow - * nGCS3 - 16bit, slow - * nGCS4 - 16bit, net - * nGCS5 - 16bit, fast - */ - -#define VR1000_VA_MULTISPACE (0xE0000000) - -#define VR1000_VA_ISAIO (VR1000_VA_MULTISPACE + 0x00000000) -#define VR1000_VA_ISAMEM (VR1000_VA_MULTISPACE + 0x01000000) -#define VR1000_VA_IDEPRI (VR1000_VA_MULTISPACE + 0x02000000) -#define VR1000_VA_IDEPRIAUX (VR1000_VA_MULTISPACE + 0x02100000) -#define VR1000_VA_IDESEC (VR1000_VA_MULTISPACE + 0x02200000) -#define VR1000_VA_IDESECAUX (VR1000_VA_MULTISPACE + 0x02300000) -#define VR1000_VA_ASIXNET (VR1000_VA_MULTISPACE + 0x02400000) -#define VR1000_VA_DM9000 (VR1000_VA_MULTISPACE + 0x02500000) -#define VR1000_VA_SUPERIO (VR1000_VA_MULTISPACE + 0x02600000) - -/* physical offset addresses for the peripherals */ - -#define VR1000_PA_IDEPRI (0x02000000) -#define VR1000_PA_IDEPRIAUX (0x02800000) -#define VR1000_PA_IDESEC (0x03000000) -#define VR1000_PA_IDESECAUX (0x03800000) -#define VR1000_PA_DM9000 (0x05000000) - -#define VR1000_PA_SERIAL (0x11800000) -#define VR1000_VA_SERIAL (VR1000_IOADDR(0x00700000)) - -/* VR1000 ram is in CS1, with A26..A24 = 2_101 */ -#define VR1000_PA_SRAM (S3C2410_CS1 | 0x05000000) - -/* some configurations for the peripherals */ - -#define VR1000_DM9000_CS VR1000_VAM_CS4 - -#endif /* __ASM_ARCH_VR1000MAP_H */ diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c index 85eefab881a..3c4b6e30c74 100644 --- a/arch/arm/mach-s3c24xx/mach-anubis.c +++ b/arch/arm/mach-s3c24xx/mach-anubis.c @@ -28,10 +28,6 @@ #include <asm/mach/map.h> #include <asm/mach/irq.h> -#include <mach/anubis-map.h> -#include <mach/anubis-irq.h> -#include <mach/anubis-cpld.h> - #include <mach/hardware.h> #include <asm/irq.h> #include <asm/mach-types.h> @@ -55,8 +51,9 @@ #include <plat/cpu.h> #include <linux/platform_data/asoc-s3c24xx_simtec.h> -#include "simtec.h" +#include "anubis.h" #include "common.h" +#include "simtec.h" #define COPYRIGHT ", Copyright 2005-2009 Simtec Electronics" @@ -237,7 +234,7 @@ static struct pata_platform_info anubis_ide_platdata = { static struct resource anubis_ide0_resource[] = { [0] = DEFINE_RES_MEM(S3C2410_CS3, 8 * 32), [2] = DEFINE_RES_MEM(S3C2410_CS3 + (1 << 26) + (6 * 32), 32), - [3] = DEFINE_RES_IRQ(IRQ_IDE0), + [3] = DEFINE_RES_IRQ(ANUBIS_IRQ_IDE0), }; static struct platform_device anubis_device_ide0 = { @@ -254,7 +251,7 @@ static struct platform_device anubis_device_ide0 = { static struct resource anubis_ide1_resource[] = { [0] = DEFINE_RES_MEM(S3C2410_CS4, 8 * 32), [1] = DEFINE_RES_MEM(S3C2410_CS4 + (1 << 26) + (6 * 32), 32), - [2] = DEFINE_RES_IRQ(IRQ_IDE0), + [2] = DEFINE_RES_IRQ(ANUBIS_IRQ_IDE0), }; static struct platform_device anubis_device_ide1 = { @@ -279,7 +276,7 @@ static struct ax_plat_data anubis_asix_platdata = { static struct resource anubis_asix_resource[] = { [0] = DEFINE_RES_MEM(S3C2410_CS5, 0x20 * 0x20), - [1] = DEFINE_RES_IRQ(IRQ_ASIX), + [1] = DEFINE_RES_IRQ(ANUBIS_IRQ_ASIX), }; static struct platform_device anubis_device_asix = { diff --git a/arch/arm/mach-s3c24xx/mach-at2440evb.c b/arch/arm/mach-s3c24xx/mach-at2440evb.c index b31c4aa724f..cdcd784e30c 100644 --- a/arch/arm/mach-s3c24xx/mach-at2440evb.c +++ b/arch/arm/mach-s3c24xx/mach-at2440evb.c @@ -14,6 +14,7 @@ #include <linux/kernel.h> #include <linux/types.h> +#include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/list.h> #include <linux/timer.h> diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c index 526964c19dd..5c1e3dfb9ab 100644 --- a/arch/arm/mach-s3c24xx/mach-bast.c +++ b/arch/arm/mach-s3c24xx/mach-bast.c @@ -24,48 +24,42 @@ #include <linux/ata_platform.h> #include <linux/i2c.h> #include <linux/io.h> +#include <linux/serial_8250.h> + +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/nand_ecc.h> +#include <linux/mtd/partitions.h> + +#include <linux/platform_data/asoc-s3c24xx_simtec.h> +#include <linux/platform_data/hwmon-s3c.h> +#include <linux/platform_data/i2c-s3c2410.h> +#include <linux/platform_data/mtd-nand-s3c2410.h> #include <net/ax88796.h> +#include <asm/irq.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> - -#include <mach/bast-map.h> -#include <mach/bast-irq.h> -#include <mach/bast-cpld.h> - -#include <mach/hardware.h> -#include <asm/irq.h> #include <asm/mach-types.h> -//#include <asm/debug-ll.h> -#include <plat/regs-serial.h> +#include <mach/fb.h> +#include <mach/hardware.h> #include <mach/regs-gpio.h> -#include <mach/regs-mem.h> #include <mach/regs-lcd.h> - -#include <linux/platform_data/hwmon-s3c.h> -#include <linux/platform_data/mtd-nand-s3c2410.h> -#include <linux/platform_data/i2c-s3c2410.h> -#include <mach/fb.h> - -#include <linux/mtd/mtd.h> -#include <linux/mtd/nand.h> -#include <linux/mtd/nand_ecc.h> -#include <linux/mtd/partitions.h> - -#include <linux/serial_8250.h> +#include <mach/regs-mem.h> #include <plat/clock.h> -#include <plat/devs.h> #include <plat/cpu.h> #include <plat/cpu-freq.h> +#include <plat/devs.h> #include <plat/gpio-cfg.h> -#include <linux/platform_data/asoc-s3c24xx_simtec.h> +#include <plat/regs-serial.h> -#include "simtec.h" +#include "bast.h" #include "common.h" +#include "simtec.h" #define COPYRIGHT ", Copyright 2004-2008 Simtec Electronics" @@ -312,7 +306,7 @@ static struct s3c2410_platform_nand __initdata bast_nand_info = { static struct resource bast_dm9k_resource[] = { [0] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_DM9000, 4), [1] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_DM9000 + 0x40, 0x40), - [2] = DEFINE_RES_NAMED(IRQ_DM9000 , 1, NULL, IORESOURCE_IRQ \ + [2] = DEFINE_RES_NAMED(BAST_IRQ_DM9000 , 1, NULL, IORESOURCE_IRQ \ | IORESOURCE_IRQ_HIGHLEVEL), }; @@ -343,7 +337,7 @@ static struct platform_device bast_device_dm9k = { static struct plat_serial8250_port bast_sio_data[] = { [0] = { .mapbase = SERIAL_BASE + 0x2f8, - .irq = IRQ_PCSERIAL1, + .irq = BAST_IRQ_PCSERIAL1, .flags = SERIAL_FLAGS, .iotype = UPIO_MEM, .regshift = 0, @@ -351,7 +345,7 @@ static struct plat_serial8250_port bast_sio_data[] = { }, [1] = { .mapbase = SERIAL_BASE + 0x3f8, - .irq = IRQ_PCSERIAL2, + .irq = BAST_IRQ_PCSERIAL2, .flags = SERIAL_FLAGS, .iotype = UPIO_MEM, .regshift = 0, @@ -390,7 +384,7 @@ static struct ax_plat_data bast_asix_platdata = { static struct resource bast_asix_resource[] = { [0] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_ASIXNET, 0x18 * 0x20), [1] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20), 1), - [2] = DEFINE_RES_IRQ(IRQ_ASIX), + [2] = DEFINE_RES_IRQ(BAST_IRQ_ASIX), }; static struct platform_device bast_device_asix = { diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c index fb5d3b3b53d..b9782ac2237 100644 --- a/arch/arm/mach-s3c24xx/mach-gta02.c +++ b/arch/arm/mach-s3c24xx/mach-gta02.c @@ -1,6 +1,4 @@ /* - * linux/arch/arm/mach-s3c2442/mach-gta02.c - * * S3C2442 Machine Support for Openmoko GTA02 / FreeRunner. * * Copyright (C) 2006-2009 by Openmoko, Inc. @@ -23,7 +21,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA - * */ #include <linux/kernel.h> @@ -34,62 +31,60 @@ #include <linux/timer.h> #include <linux/init.h> #include <linux/gpio.h> +#include <linux/gpio_keys.h> #include <linux/workqueue.h> #include <linux/platform_device.h> #include <linux/serial_core.h> -#include <linux/spi/spi.h> -#include <linux/spi/s3c24xx.h> +#include <linux/input.h> +#include <linux/io.h> +#include <linux/i2c.h> #include <linux/mmc/host.h> +#include <linux/mfd/pcf50633/adc.h> +#include <linux/mfd/pcf50633/backlight.h> +#include <linux/mfd/pcf50633/core.h> +#include <linux/mfd/pcf50633/gpio.h> +#include <linux/mfd/pcf50633/mbc.h> +#include <linux/mfd/pcf50633/pmic.h> + #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/nand_ecc.h> #include <linux/mtd/partitions.h> #include <linux/mtd/physmap.h> -#include <linux/io.h> -#include <linux/i2c.h> #include <linux/regulator/machine.h> -#include <linux/mfd/pcf50633/core.h> -#include <linux/mfd/pcf50633/mbc.h> -#include <linux/mfd/pcf50633/adc.h> -#include <linux/mfd/pcf50633/gpio.h> -#include <linux/mfd/pcf50633/pmic.h> -#include <linux/mfd/pcf50633/backlight.h> - -#include <linux/input.h> -#include <linux/gpio_keys.h> +#include <linux/spi/spi.h> +#include <linux/spi/s3c24xx.h> +#include <asm/irq.h> +#include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> -#include <asm/irq.h> -#include <asm/mach-types.h> +#include <linux/platform_data/i2c-s3c2410.h> +#include <linux/platform_data/mtd-nand-s3c2410.h> +#include <linux/platform_data/touchscreen-s3c2410.h> +#include <linux/platform_data/usb-ohci-s3c2410.h> +#include <linux/platform_data/usb-s3c2410_udc.h> -#include <mach/regs-irq.h> -#include <mach/regs-gpio.h> #include <mach/fb.h> - -#include <linux/platform_data/usb-ohci-s3c2410.h> -#include <mach/regs-mem.h> #include <mach/hardware.h> +#include <mach/regs-gpio.h> +#include <mach/regs-irq.h> +#include <mach/regs-mem.h> -#include <mach/gta02.h> - -#include <plat/regs-serial.h> -#include <linux/platform_data/mtd-nand-s3c2410.h> -#include <plat/devs.h> #include <plat/cpu.h> -#include <plat/pm.h> -#include <linux/platform_data/usb-s3c2410_udc.h> +#include <plat/devs.h> #include <plat/gpio-cfg.h> -#include <linux/platform_data/i2c-s3c2410.h> -#include <linux/platform_data/touchscreen-s3c2410.h> +#include <plat/pm.h> +#include <plat/regs-serial.h> #include "common.h" +#include "gta02.h" static struct pcf50633 *gta02_pcf; diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c index 2eb09e27c13..79bc0830d74 100644 --- a/arch/arm/mach-s3c24xx/mach-h1940.c +++ b/arch/arm/mach-s3c24xx/mach-h1940.c @@ -1,5 +1,4 @@ -/* linux/arch/arm/mach-s3c2410/mach-h1940.c - * +/* * Copyright (c) 2003-2005 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> * @@ -37,40 +36,36 @@ #include <linux/mmc/host.h> #include <linux/export.h> +#include <asm/irq.h> +#include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> -#include <mach/hardware.h> -#include <asm/irq.h> -#include <asm/mach-types.h> - -#include <plat/regs-serial.h> -#include <mach/regs-lcd.h> -#include <mach/regs-clock.h> +#include <linux/platform_data/i2c-s3c2410.h> +#include <linux/platform_data/mmc-s3cmci.h> +#include <linux/platform_data/touchscreen-s3c2410.h> +#include <linux/platform_data/usb-s3c2410_udc.h> -#include <mach/regs-gpio.h> -#include <mach/gpio-fns.h> -#include <mach/gpio-nrs.h> +#include <sound/uda1380.h> -#include <mach/h1940.h> -#include <mach/h1940-latch.h> #include <mach/fb.h> -#include <linux/platform_data/usb-s3c2410_udc.h> -#include <linux/platform_data/i2c-s3c2410.h> +#include <mach/hardware.h> +#include <mach/regs-clock.h> +#include <mach/regs-gpio.h> +#include <mach/regs-lcd.h> -#include <plat/gpio-cfg.h> #include <plat/clock.h> -#include <plat/devs.h> #include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/gpio-cfg.h> #include <plat/pll.h> #include <plat/pm.h> -#include <linux/platform_data/mmc-s3cmci.h> -#include <linux/platform_data/touchscreen-s3c2410.h> +#include <plat/regs-serial.h> -#include <sound/uda1380.h> #include "common.h" +#include "h1940.h" #define H1940_LATCH ((void __force __iomem *)0xF8000000) diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c index ba0f5b5ec19..4b57f9aa0a8 100644 --- a/arch/arm/mach-s3c24xx/mach-osiris.c +++ b/arch/arm/mach-s3c24xx/mach-osiris.c @@ -1,5 +1,4 @@ -/* linux/arch/arm/mach-s3c2440/mach-osiris.c - * +/* * Copyright (c) 2005-2008 Simtec Electronics * http://armlinux.simtec.co.uk/ * Ben Dooks <ben@simtec.co.uk> @@ -25,22 +24,12 @@ #include <linux/i2c/tps65010.h> +#include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> - -#include <mach/osiris-map.h> -#include <mach/osiris-cpld.h> - -#include <mach/hardware.h> #include <asm/irq.h> -#include <asm/mach-types.h> -#include <plat/cpu-freq.h> -#include <plat/regs-serial.h> -#include <mach/regs-gpio.h> -#include <mach/regs-mem.h> -#include <mach/regs-lcd.h> #include <linux/platform_data/mtd-nand-s3c2410.h> #include <linux/platform_data/i2c-s3c2410.h> @@ -49,12 +38,20 @@ #include <linux/mtd/nand_ecc.h> #include <linux/mtd/partitions.h> -#include <plat/gpio-cfg.h> #include <plat/clock.h> -#include <plat/devs.h> #include <plat/cpu.h> +#include <plat/cpu-freq.h> +#include <plat/devs.h> +#include <plat/gpio-cfg.h> +#include <plat/regs-serial.h> + +#include <mach/hardware.h> +#include <mach/regs-gpio.h> +#include <mach/regs-mem.h> +#include <mach/regs-lcd.h> #include "common.h" +#include "osiris.h" /* onboard perihperal map */ diff --git a/arch/arm/mach-s3c24xx/mach-otom.c b/arch/arm/mach-s3c24xx/mach-otom.c index e0fdae93aa7..40a47d6c6a8 100644 --- a/arch/arm/mach-s3c24xx/mach-otom.c +++ b/arch/arm/mach-s3c24xx/mach-otom.c @@ -1,4 +1,4 @@ -/* linux/arch/arm/mach-s3c2410/mach-otom.c +/* * * Copyright (c) 2004 Nex Vision * Guillaume GOURAT <guillaume.gourat@nexvision.fr> @@ -6,7 +6,6 @@ * 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. - * */ #include <linux/kernel.h> @@ -19,26 +18,25 @@ #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/platform_data/i2c-s3c2410.h> + +#include <asm/irq.h> +#include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> -#include <mach/otom-map.h> - #include <mach/hardware.h> -#include <asm/irq.h> -#include <asm/mach-types.h> - -#include <plat/regs-serial.h> #include <mach/regs-gpio.h> -#include <plat/s3c2410.h> #include <plat/clock.h> -#include <plat/devs.h> -#include <linux/platform_data/i2c-s3c2410.h> #include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/regs-serial.h> +#include <plat/s3c2410.h> #include "common.h" +#include "otom.h" static struct map_desc otom11_iodesc[] __initdata = { /* Device area */ diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c index e14ec7105a6..1f9ba2ae528 100644 --- a/arch/arm/mach-s3c24xx/mach-rx1950.c +++ b/arch/arm/mach-s3c24xx/mach-rx1950.c @@ -1,5 +1,4 @@ -/* linux/arch/arm/mach-s3c2440/mach-rx1950.c - * +/* * Copyright (c) 2006-2009 Victor Chukhantsev, Denis Grigoriev, * Copyright (c) 2007-2010 Vasily Khoruzhick * @@ -37,31 +36,31 @@ #include <linux/mmc/host.h> +#include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> -#include <asm/mach-types.h> +#include <linux/platform_data/i2c-s3c2410.h> +#include <linux/platform_data/mmc-s3cmci.h> +#include <linux/platform_data/mtd-nand-s3c2410.h> +#include <linux/platform_data/touchscreen-s3c2410.h> +#include <linux/platform_data/usb-s3c2410_udc.h> + +#include <sound/uda1380.h> + +#include <mach/fb.h> #include <mach/regs-gpio.h> #include <mach/regs-lcd.h> -#include <mach/h1940.h> -#include <mach/fb.h> #include <plat/clock.h> -#include <plat/regs-serial.h> -#include <plat/regs-iic.h> -#include <linux/platform_data/mmc-s3cmci.h> -#include <linux/platform_data/usb-s3c2410_udc.h> -#include <linux/platform_data/mtd-nand-s3c2410.h> -#include <linux/platform_data/i2c-s3c2410.h> -#include <plat/devs.h> #include <plat/cpu.h> +#include <plat/devs.h> #include <plat/pm.h> -#include <plat/irq.h> -#include <linux/platform_data/touchscreen-s3c2410.h> - -#include <sound/uda1380.h> +#include <plat/regs-iic.h> +#include <plat/regs-serial.h> #include "common.h" +#include "h1940.h" #define LCD_PWM_PERIOD 192960 #define LCD_PWM_DUTY 127353 diff --git a/arch/arm/mach-s3c24xx/mach-rx3715.c b/arch/arm/mach-s3c24xx/mach-rx3715.c index d00caa8de92..f20418a2fb1 100644 --- a/arch/arm/mach-s3c24xx/mach-rx3715.c +++ b/arch/arm/mach-s3c24xx/mach-rx3715.c @@ -31,27 +31,27 @@ #include <linux/mtd/partitions.h> #include <asm/mach/arch.h> -#include <asm/mach/map.h> #include <asm/mach/irq.h> +#include <asm/mach/map.h> + +#include <linux/platform_data/mtd-nand-s3c2410.h> -#include <mach/hardware.h> #include <asm/irq.h> #include <asm/mach-types.h> -#include <plat/regs-serial.h> +#include <mach/fb.h> +#include <mach/hardware.h> #include <mach/regs-gpio.h> #include <mach/regs-lcd.h> -#include <mach/h1940.h> -#include <linux/platform_data/mtd-nand-s3c2410.h> -#include <mach/fb.h> - #include <plat/clock.h> -#include <plat/devs.h> #include <plat/cpu.h> +#include <plat/devs.h> #include <plat/pm.h> +#include <plat/regs-serial.h> #include "common.h" +#include "h1940.h" static struct map_desc rx3715_iodesc[] __initdata = { /* dump ISA space somewhere unused */ diff --git a/arch/arm/mach-s3c24xx/mach-smdk2413.c b/arch/arm/mach-s3c24xx/mach-smdk2413.c index 69f356e8379..86d7847c9d4 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2413.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2413.c @@ -37,7 +37,6 @@ #include <mach/regs-gpio.h> #include <mach/regs-lcd.h> -#include <mach/idle.h> #include <linux/platform_data/usb-s3c2410_udc.h> #include <linux/platform_data/i2c-s3c2410.h> #include <mach/fb.h> diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c index fe160c7f4b0..72dfec68932 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2416.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c @@ -39,7 +39,6 @@ #include <mach/regs-lcd.h> #include <mach/regs-s3c2443-clock.h> -#include <mach/idle.h> #include <linux/platform_data/leds-s3c24xx.h> #include <linux/platform_data/i2c-s3c2410.h> diff --git a/arch/arm/mach-s3c24xx/mach-smdk2440.c b/arch/arm/mach-s3c24xx/mach-smdk2440.c index a8fdafedc4c..08cc38c8a4a 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2440.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2440.c @@ -35,7 +35,6 @@ #include <mach/regs-gpio.h> #include <mach/regs-lcd.h> -#include <mach/idle.h> #include <mach/fb.h> #include <linux/platform_data/i2c-s3c2410.h> diff --git a/arch/arm/mach-s3c24xx/mach-smdk2443.c b/arch/arm/mach-s3c24xx/mach-smdk2443.c index 7830d700430..406c8137620 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2443.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2443.c @@ -35,7 +35,6 @@ #include <mach/regs-gpio.h> #include <mach/regs-lcd.h> -#include <mach/idle.h> #include <mach/fb.h> #include <linux/platform_data/i2c-s3c2410.h> diff --git a/arch/arm/mach-s3c24xx/mach-vr1000.c b/arch/arm/mach-s3c24xx/mach-vr1000.c index dda21a01e3c..ec42d1e4e46 100644 --- a/arch/arm/mach-s3c24xx/mach-vr1000.c +++ b/arch/arm/mach-s3c24xx/mach-vr1000.c @@ -1,5 +1,4 @@ -/* linux/arch/arm/mach-s3c2410/mach-vr1000.c - * +/* * Copyright (c) 2003-2008 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> * @@ -32,27 +31,25 @@ #include <asm/mach/map.h> #include <asm/mach/irq.h> -#include <mach/bast-map.h> -#include <mach/vr1000-map.h> -#include <mach/vr1000-irq.h> -#include <mach/vr1000-cpld.h> - -#include <mach/hardware.h> #include <asm/irq.h> #include <asm/mach-types.h> -#include <plat/regs-serial.h> -#include <mach/regs-gpio.h> #include <linux/platform_data/leds-s3c24xx.h> +#include <linux/platform_data/i2c-s3c2410.h> +#include <linux/platform_data/asoc-s3c24xx_simtec.h> + +#include <mach/hardware.h> +#include <mach/regs-gpio.h> #include <plat/clock.h> -#include <plat/devs.h> #include <plat/cpu.h> -#include <linux/platform_data/i2c-s3c2410.h> -#include <linux/platform_data/asoc-s3c24xx_simtec.h> +#include <plat/devs.h> +#include <plat/regs-serial.h> -#include "simtec.h" +#include "bast.h" #include "common.h" +#include "simtec.h" +#include "vr1000.h" /* macros for virtual address mods for the io space entries */ #define VA_C5(item) ((unsigned long)(item) + BAST_VAM_CS5) @@ -143,7 +140,7 @@ static struct s3c2410_uartcfg vr1000_uartcfgs[] __initdata = { static struct plat_serial8250_port serial_platform_data[] = { [0] = { .mapbase = VR1000_SERIAL_MAPBASE(0), - .irq = IRQ_VR1000_SERIAL + 0, + .irq = VR1000_IRQ_SERIAL + 0, .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, .iotype = UPIO_MEM, .regshift = 0, @@ -151,7 +148,7 @@ static struct plat_serial8250_port serial_platform_data[] = { }, [1] = { .mapbase = VR1000_SERIAL_MAPBASE(1), - .irq = IRQ_VR1000_SERIAL + 1, + .irq = VR1000_IRQ_SERIAL + 1, .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, .iotype = UPIO_MEM, .regshift = 0, @@ -159,7 +156,7 @@ static struct plat_serial8250_port serial_platform_data[] = { }, [2] = { .mapbase = VR1000_SERIAL_MAPBASE(2), - .irq = IRQ_VR1000_SERIAL + 2, + .irq = VR1000_IRQ_SERIAL + 2, .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, .iotype = UPIO_MEM, .regshift = 0, @@ -167,7 +164,7 @@ static struct plat_serial8250_port serial_platform_data[] = { }, [3] = { .mapbase = VR1000_SERIAL_MAPBASE(3), - .irq = IRQ_VR1000_SERIAL + 3, + .irq = VR1000_IRQ_SERIAL + 3, .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, .iotype = UPIO_MEM, .regshift = 0, @@ -189,14 +186,14 @@ static struct platform_device serial_device = { static struct resource vr1000_dm9k0_resource[] = { [0] = DEFINE_RES_MEM(S3C2410_CS5 + VR1000_PA_DM9000, 4), [1] = DEFINE_RES_MEM(S3C2410_CS5 + VR1000_PA_DM9000 + 0x40, 0x40), - [2] = DEFINE_RES_NAMED(IRQ_VR1000_DM9000A, 1, NULL, IORESOURCE_IRQ \ + [2] = DEFINE_RES_NAMED(VR1000_IRQ_DM9000A, 1, NULL, IORESOURCE_IRQ \ | IORESOURCE_IRQ_HIGHLEVEL), }; static struct resource vr1000_dm9k1_resource[] = { [0] = DEFINE_RES_MEM(S3C2410_CS5 + VR1000_PA_DM9000 + 0x80, 4), [1] = DEFINE_RES_MEM(S3C2410_CS5 + VR1000_PA_DM9000 + 0xC0, 0x40), - [2] = DEFINE_RES_NAMED(IRQ_VR1000_DM9000N, 1, NULL, IORESOURCE_IRQ \ + [2] = DEFINE_RES_NAMED(VR1000_IRQ_DM9000N, 1, NULL, IORESOURCE_IRQ \ | IORESOURCE_IRQ_HIGHLEVEL), }; diff --git a/arch/arm/mach-s3c24xx/mach-vstms.c b/arch/arm/mach-s3c24xx/mach-vstms.c index 7fe7d4f6041..3e2bfddc9df 100644 --- a/arch/arm/mach-s3c24xx/mach-vstms.c +++ b/arch/arm/mach-s3c24xx/mach-vstms.c @@ -36,7 +36,6 @@ #include <mach/regs-gpio.h> #include <mach/regs-lcd.h> -#include <mach/idle.h> #include <mach/fb.h> #include <linux/platform_data/i2c-s3c2410.h> diff --git a/arch/arm/mach-s3c24xx/include/mach/osiris-map.h b/arch/arm/mach-s3c24xx/osiris.h index 17380f84842..b8d56074aba 100644 --- a/arch/arm/mach-s3c24xx/include/mach/osiris-map.h +++ b/arch/arm/mach-s3c24xx/osiris.h @@ -1,9 +1,9 @@ -/* arch/arm/mach-s3c2410/include/mach/osiris-map.h - * +/* * Copyright 2005 Simtec Electronics * http://www.simtec.co.uk/products/ * Ben Dooks <ben@simtec.co.uk> * + * OSIRIS - CPLD control constants * OSIRIS - Memory map definitions * * This program is free software; you can redistribute it and/or modify @@ -11,10 +11,21 @@ * published by the Free Software Foundation. */ -/* needs arch/map.h including with this */ +#ifndef __MACH_S3C24XX_OSIRIS_H +#define __MACH_S3C24XX_OSIRIS_H __FILE__ + +/* CTRL0 - NAND WP control */ + +#define OSIRIS_CTRL0_NANDSEL (0x3) +#define OSIRIS_CTRL0_BOOT_INT (1<<3) +#define OSIRIS_CTRL0_PCMCIA (1<<4) +#define OSIRIS_CTRL0_FIX8 (1<<5) +#define OSIRIS_CTRL0_PCMCIA_nWAIT (1<<6) +#define OSIRIS_CTRL0_PCMCIA_nIOIS16 (1<<7) + +#define OSIRIS_CTRL1_FIX8 (1<<0) -#ifndef __ASM_ARCH_OSIRISMAP_H -#define __ASM_ARCH_OSIRISMAP_H +#define OSIRIS_ID_REVMASK (0x7) /* start peripherals off after the S3C2410 */ @@ -39,4 +50,4 @@ #define OSIRIS_VA_IDREG OSIRIS_IOADDR(0x00700000) #define OSIRIS_PA_IDREG (OSIRIS_PA_CPLD + (7<<23)) -#endif /* __ASM_ARCH_OSIRISMAP_H */ +#endif /* __MACH_S3C24XX_OSIRIS_H */ diff --git a/arch/arm/mach-s3c24xx/include/mach/otom-map.h b/arch/arm/mach-s3c24xx/otom.h index f9277a52c14..321b7be1c0f 100644 --- a/arch/arm/mach-s3c24xx/include/mach/otom-map.h +++ b/arch/arm/mach-s3c24xx/otom.h @@ -1,5 +1,4 @@ -/* arch/arm/mach-s3c2410/include/mach/otom-map.h - * +/* * (c) 2005 Guillaume GOURAT / NexVision * guillaume.gourat@nexvision.fr * @@ -10,21 +9,20 @@ * published by the Free Software Foundation. */ -/* needs arch/map.h including with this */ - -/* ok, we've used up to 0x01300000, now we need to find space for the +/* + * ok, we've used up to 0x01300000, now we need to find space for the * peripherals that live in the nGCS[x] areas, which are quite numerous * in their space. */ -#ifndef __ASM_ARCH_OTOMMAP_H -#define __ASM_ARCH_OTOMMAP_H +#ifndef __MACH_S3C24XX_OTOM_H +#define __MACH_S3C24XX_OTOM_H __FILE__ -#define OTOM_PA_CS8900A_BASE (S3C2410_CS3 + 0x01000000) /* nGCS3 +0x01000000 */ -#define OTOM_VA_CS8900A_BASE S3C2410_ADDR(0x04000000) /* 0xF4000000 */ +#define OTOM_PA_CS8900A_BASE (S3C2410_CS3 + 0x01000000) /* nGCS3 +0x01000000 */ +#define OTOM_VA_CS8900A_BASE S3C2410_ADDR(0x04000000) /* 0xF4000000 */ /* physical offset addresses for the peripherals */ -#define OTOM_PA_FLASH0_BASE (S3C2410_CS0) /* Bank 0 */ +#define OTOM_PA_FLASH0_BASE (S3C2410_CS0) -#endif /* __ASM_ARCH_OTOMMAP_H */ +#endif /* __MACH_S3C24XX_OTOM_H */ diff --git a/arch/arm/mach-s3c24xx/pm-s3c2410.c b/arch/arm/mach-s3c24xx/pm-s3c2410.c index 949ae05e07c..2d82c4f116c 100644 --- a/arch/arm/mach-s3c24xx/pm-s3c2410.c +++ b/arch/arm/mach-s3c24xx/pm-s3c2410.c @@ -29,16 +29,16 @@ #include <linux/gpio.h> #include <linux/io.h> -#include <mach/hardware.h> - #include <asm/mach-types.h> +#include <mach/hardware.h> #include <mach/regs-gpio.h> -#include <mach/h1940.h> #include <plat/cpu.h> #include <plat/pm.h> +#include "h1940.h" + static void s3c2410_pm_prepare(void) { /* ensure at least GSTATUS3 has the resume address */ diff --git a/arch/arm/mach-s3c24xx/pm-s3c2412.c b/arch/arm/mach-s3c24xx/pm-s3c2412.c index c60f67a75af..206765cc409 100644 --- a/arch/arm/mach-s3c24xx/pm-s3c2412.c +++ b/arch/arm/mach-s3c24xx/pm-s3c2412.c @@ -21,19 +21,19 @@ #include <linux/platform_device.h> #include <linux/io.h> -#include <mach/hardware.h> #include <asm/cacheflush.h> #include <asm/irq.h> -#include <mach/regs-power.h> +#include <mach/hardware.h> #include <mach/regs-gpio.h> -#include <mach/regs-dsc.h> +#include <mach/regs-power.h> #include <plat/cpu.h> #include <plat/pm.h> - #include <plat/s3c2412.h> +#include "regs-dsc.h" + extern void s3c2412_sleep_enter(void); static int s3c2412_cpu_suspend(unsigned long arg) diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-dsc.h b/arch/arm/mach-s3c24xx/regs-dsc.h index 98fd4a05587..98fd4a05587 100644 --- a/arch/arm/mach-s3c24xx/include/mach/regs-dsc.h +++ b/arch/arm/mach-s3c24xx/regs-dsc.h diff --git a/arch/arm/mach-s3c24xx/s3c2412.c b/arch/arm/mach-s3c24xx/s3c2412.c index 6c5f4031ff0..c511a225f07 100644 --- a/arch/arm/mach-s3c24xx/s3c2412.c +++ b/arch/arm/mach-s3c24xx/s3c2412.c @@ -1,5 +1,4 @@ -/* linux/arch/arm/mach-s3c2412/s3c2412.c - * +/* * Copyright (c) 2006 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> * @@ -28,28 +27,30 @@ #include <asm/mach/map.h> #include <asm/mach/irq.h> -#include <mach/hardware.h> #include <asm/proc-fns.h> #include <asm/irq.h> #include <asm/system_misc.h> -#include <plat/cpu-freq.h> - +#include <mach/hardware.h> #include <mach/regs-clock.h> -#include <plat/regs-serial.h> -#include <mach/regs-power.h> #include <mach/regs-gpio.h> -#include <mach/regs-dsc.h> -#include <plat/regs-spi.h> -#include <mach/regs-s3c2412.h> +#include <mach/regs-power.h> -#include <plat/s3c2412.h> +#include <plat/clock.h> #include <plat/cpu.h> +#include <plat/cpu-freq.h> #include <plat/devs.h> -#include <plat/clock.h> -#include <plat/pm.h> -#include <plat/pll.h> #include <plat/nand-core.h> +#include <plat/pll.h> +#include <plat/pm.h> +#include <plat/regs-serial.h> +#include <plat/regs-spi.h> +#include <plat/s3c2412.h> + +#include "regs-dsc.h" + +#define S3C2412_SWRST (S3C24XX_VA_CLKPWR + 0x30) +#define S3C2412_SWRST_RESET (0x533C2412) #ifndef CONFIG_CPU_S3C2412_ONLY void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO; diff --git a/arch/arm/mach-s3c24xx/s3c244x.c b/arch/arm/mach-s3c24xx/s3c244x.c index b0b60a1154d..ad2671baa91 100644 --- a/arch/arm/mach-s3c24xx/s3c244x.c +++ b/arch/arm/mach-s3c24xx/s3c244x.c @@ -36,7 +36,6 @@ #include <mach/regs-clock.h> #include <plat/regs-serial.h> #include <mach/regs-gpio.h> -#include <mach/regs-dsc.h> #include <plat/s3c2410.h> #include <plat/s3c244x.h> @@ -48,6 +47,8 @@ #include <plat/nand-core.h> #include <plat/watchdog-reset.h> +#include "regs-dsc.h" + static struct map_desc s3c244x_iodesc[] __initdata = { IODESC_ENT(CLKPWR), IODESC_ENT(TIMER), diff --git a/arch/arm/mach-s3c24xx/simtec-audio.c b/arch/arm/mach-s3c24xx/simtec-audio.c index fd0ef05763a..67cb5120dfe 100644 --- a/arch/arm/mach-s3c24xx/simtec-audio.c +++ b/arch/arm/mach-s3c24xx/simtec-audio.c @@ -17,16 +17,13 @@ #include <linux/device.h> #include <linux/io.h> -#include <mach/bast-map.h> -#include <mach/bast-irq.h> -#include <mach/bast-cpld.h> - #include <mach/hardware.h> #include <mach/regs-gpio.h> #include <linux/platform_data/asoc-s3c24xx_simtec.h> #include <plat/devs.h> +#include "bast.h" #include "simtec.h" /* platform ops for audio */ diff --git a/arch/arm/mach-s3c24xx/simtec-nor.c b/arch/arm/mach-s3c24xx/simtec-nor.c index 029744fcaac..8884bffa619 100644 --- a/arch/arm/mach-s3c24xx/simtec-nor.c +++ b/arch/arm/mach-s3c24xx/simtec-nor.c @@ -27,9 +27,8 @@ #include <asm/mach/irq.h> #include <mach/map.h> -#include <mach/bast-map.h> -#include <mach/bast-cpld.h> +#include "bast.h" #include "simtec.h" static void simtec_nor_vpp(struct platform_device *pdev, int vpp) diff --git a/arch/arm/mach-s3c24xx/simtec-usb.c b/arch/arm/mach-s3c24xx/simtec-usb.c index ddf7a3c743a..2ed2e32430d 100644 --- a/arch/arm/mach-s3c24xx/simtec-usb.c +++ b/arch/arm/mach-s3c24xx/simtec-usb.c @@ -28,15 +28,13 @@ #include <asm/mach/map.h> #include <asm/mach/irq.h> -#include <mach/bast-map.h> -#include <mach/bast-irq.h> - #include <mach/hardware.h> #include <asm/irq.h> #include <linux/platform_data/usb-ohci-s3c2410.h> #include <plat/devs.h> +#include "bast.h" #include "simtec.h" /* control power and monitor over-current events on various Simtec @@ -79,7 +77,7 @@ static void usb_simtec_enableoc(struct s3c2410_hcd_info *info, int on) int ret; if (on) { - ret = request_irq(IRQ_USBOC, usb_simtec_ocirq, + ret = request_irq(BAST_IRQ_USBOC, usb_simtec_ocirq, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "USB Over-current", info); @@ -87,7 +85,7 @@ static void usb_simtec_enableoc(struct s3c2410_hcd_info *info, int on) printk(KERN_ERR "failed to request usb oc irq\n"); } } else { - free_irq(IRQ_USBOC, info); + free_irq(BAST_IRQ_USBOC, info); } } diff --git a/arch/arm/mach-s3c24xx/vr1000.h b/arch/arm/mach-s3c24xx/vr1000.h new file mode 100644 index 00000000000..7fcd2c2f183 --- /dev/null +++ b/arch/arm/mach-s3c24xx/vr1000.h @@ -0,0 +1,118 @@ + +/* arch/arm/mach-s3c2410/include/mach/vr1000-cpld.h + * + * Copyright (c) 2003 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * VR1000 - CPLD control constants + * Machine VR1000 - IRQ Number definitions + * Machine VR1000 - Memory map definitions + * + * 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. +*/ + +#ifndef __MACH_S3C24XX_VR1000_H +#define __MACH_S3C24XX_VR1000_H __FILE__ + +#define VR1000_CPLD_CTRL2_RAMWEN (0x04) /* SRAM Write Enable */ + +/* irq numbers to onboard peripherals */ + +#define VR1000_IRQ_USBOC IRQ_EINT19 +#define VR1000_IRQ_IDE0 IRQ_EINT16 +#define VR1000_IRQ_IDE1 IRQ_EINT17 +#define VR1000_IRQ_SERIAL IRQ_EINT12 +#define VR1000_IRQ_DM9000A IRQ_EINT10 +#define VR1000_IRQ_DM9000N IRQ_EINT9 +#define VR1000_IRQ_SMALERT IRQ_EINT8 + +/* map */ + +#define VR1000_IOADDR(x) (S3C2410_ADDR((x) + 0x01300000)) + +/* we put the CPLD registers next, to get them out of the way */ + +#define VR1000_VA_CTRL1 VR1000_IOADDR(0x00000000) /* 0x01300000 */ +#define VR1000_PA_CTRL1 (S3C2410_CS5 | 0x7800000) + +#define VR1000_VA_CTRL2 VR1000_IOADDR(0x00100000) /* 0x01400000 */ +#define VR1000_PA_CTRL2 (S3C2410_CS1 | 0x6000000) + +#define VR1000_VA_CTRL3 VR1000_IOADDR(0x00200000) /* 0x01500000 */ +#define VR1000_PA_CTRL3 (S3C2410_CS1 | 0x6800000) + +#define VR1000_VA_CTRL4 VR1000_IOADDR(0x00300000) /* 0x01600000 */ +#define VR1000_PA_CTRL4 (S3C2410_CS1 | 0x7000000) + +/* next, we have the PC104 ISA interrupt registers */ + +#define VR1000_PA_PC104_IRQREQ (S3C2410_CS5 | 0x6000000) /* 0x01700000 */ +#define VR1000_VA_PC104_IRQREQ VR1000_IOADDR(0x00400000) + +#define VR1000_PA_PC104_IRQRAW (S3C2410_CS5 | 0x6800000) /* 0x01800000 */ +#define VR1000_VA_PC104_IRQRAW VR1000_IOADDR(0x00500000) + +#define VR1000_PA_PC104_IRQMASK (S3C2410_CS5 | 0x7000000) /* 0x01900000 */ +#define VR1000_VA_PC104_IRQMASK VR1000_IOADDR(0x00600000) + +/* + * 0xE0000000 contains the IO space that is split by speed and + * whether the access is for 8 or 16bit IO... this ensures that + * the correct access is made + * + * 0x10000000 of space, partitioned as so: + * + * 0x00000000 to 0x04000000 8bit, slow + * 0x04000000 to 0x08000000 16bit, slow + * 0x08000000 to 0x0C000000 16bit, net + * 0x0C000000 to 0x10000000 16bit, fast + * + * each of these spaces has the following in: + * + * 0x02000000 to 0x02100000 1MB IDE primary channel + * 0x02100000 to 0x02200000 1MB IDE primary channel aux + * 0x02200000 to 0x02400000 1MB IDE secondary channel + * 0x02300000 to 0x02400000 1MB IDE secondary channel aux + * 0x02500000 to 0x02600000 1MB Davicom DM9000 ethernet controllers + * 0x02600000 to 0x02700000 1MB + * + * the phyiscal layout of the zones are: + * nGCS2 - 8bit, slow + * nGCS3 - 16bit, slow + * nGCS4 - 16bit, net + * nGCS5 - 16bit, fast + */ + +#define VR1000_VA_MULTISPACE (0xE0000000) + +#define VR1000_VA_ISAIO (VR1000_VA_MULTISPACE + 0x00000000) +#define VR1000_VA_ISAMEM (VR1000_VA_MULTISPACE + 0x01000000) +#define VR1000_VA_IDEPRI (VR1000_VA_MULTISPACE + 0x02000000) +#define VR1000_VA_IDEPRIAUX (VR1000_VA_MULTISPACE + 0x02100000) +#define VR1000_VA_IDESEC (VR1000_VA_MULTISPACE + 0x02200000) +#define VR1000_VA_IDESECAUX (VR1000_VA_MULTISPACE + 0x02300000) +#define VR1000_VA_ASIXNET (VR1000_VA_MULTISPACE + 0x02400000) +#define VR1000_VA_DM9000 (VR1000_VA_MULTISPACE + 0x02500000) +#define VR1000_VA_SUPERIO (VR1000_VA_MULTISPACE + 0x02600000) + +/* physical offset addresses for the peripherals */ + +#define VR1000_PA_IDEPRI (0x02000000) +#define VR1000_PA_IDEPRIAUX (0x02800000) +#define VR1000_PA_IDESEC (0x03000000) +#define VR1000_PA_IDESECAUX (0x03800000) +#define VR1000_PA_DM9000 (0x05000000) + +#define VR1000_PA_SERIAL (0x11800000) +#define VR1000_VA_SERIAL (VR1000_IOADDR(0x00700000)) + +/* VR1000 ram is in CS1, with A26..A24 = 2_101 */ +#define VR1000_PA_SRAM (S3C2410_CS1 | 0x05000000) + +/* some configurations for the peripherals */ + +#define VR1000_DM9000_CS VR1000_VAM_CS4 + +#endif /* __MACH_S3C24XX_VR1000_H */ diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c index 803711e283b..8499415be9c 100644 --- a/arch/arm/mach-s3c64xx/clock.c +++ b/arch/arm/mach-s3c64xx/clock.c @@ -23,7 +23,6 @@ #include <mach/hardware.h> #include <mach/map.h> -#include <mach/regs-sys.h> #include <mach/regs-clock.h> #include <plat/cpu.h> @@ -33,6 +32,8 @@ #include <plat/clock-clksrc.h> #include <plat/pll.h> +#include "regs-sys.h" + /* fin_apll, fin_mpll and fin_epll are all the same clock, which we call * ext_xtal_mux for want of an actual name from the manual. */ diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c index aef303b8997..0b9c0ba4483 100644 --- a/arch/arm/mach-s3c64xx/common.c +++ b/arch/arm/mach-s3c64xx/common.c @@ -25,10 +25,10 @@ #include <linux/dma-mapping.h> #include <linux/irq.h> #include <linux/gpio.h> +#include <linux/irqchip/arm-vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> -#include <asm/hardware/vic.h> #include <asm/system_misc.h> #include <mach/map.h> diff --git a/arch/arm/mach-s3c64xx/cpuidle.c b/arch/arm/mach-s3c64xx/cpuidle.c index acb197ccf3f..ead5fab0dbb 100644 --- a/arch/arm/mach-s3c64xx/cpuidle.c +++ b/arch/arm/mach-s3c64xx/cpuidle.c @@ -20,8 +20,8 @@ #include <mach/map.h> -#include <mach/regs-sys.h> -#include <mach/regs-syscon-power.h> +#include "regs-sys.h" +#include "regs-syscon-power.h" static int s3c64xx_enter_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, diff --git a/arch/arm/mach-s3c64xx/include/mach/crag6410.h b/arch/arm/mach-s3c64xx/crag6410.h index 4c3c9994fc2..4c3c9994fc2 100644 --- a/arch/arm/mach-s3c64xx/include/mach/crag6410.h +++ b/arch/arm/mach-s3c64xx/crag6410.h diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c index f2a7a172559..ec29b35f25c 100644 --- a/arch/arm/mach-s3c64xx/dma.c +++ b/arch/arm/mach-s3c64xx/dma.c @@ -28,10 +28,10 @@ #include <mach/map.h> #include <mach/irqs.h> -#include <mach/regs-sys.h> - #include <asm/hardware/pl080.h> +#include "regs-sys.h" + /* dma channel state information */ struct s3c64xx_dmac { diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-irq.h b/arch/arm/mach-s3c64xx/include/mach/regs-irq.h index bcce68a0bb7..6a1127891c8 100644 --- a/arch/arm/mach-s3c64xx/include/mach/regs-irq.h +++ b/arch/arm/mach-s3c64xx/include/mach/regs-irq.h @@ -15,6 +15,5 @@ #ifndef __ASM_ARCH_REGS_IRQ_H #define __ASM_ARCH_REGS_IRQ_H __FILE__ -#include <asm/hardware/vic.h> #endif /* __ASM_ARCH_6400_REGS_IRQ_H */ diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-sys.h b/arch/arm/mach-s3c64xx/include/mach/regs-sys.h deleted file mode 100644 index b91e0209328..00000000000 --- a/arch/arm/mach-s3c64xx/include/mach/regs-sys.h +++ /dev/null @@ -1,31 +0,0 @@ -/* arch/arm/plat-s3c64xx/include/plat/regs-sys.h - * - * Copyright 2008 Openmoko, Inc. - * Copyright 2008 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * http://armlinux.simtec.co.uk/ - * - * S3C64XX system register definitions - * - * 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. -*/ - -#ifndef __PLAT_REGS_SYS_H -#define __PLAT_REGS_SYS_H __FILE__ - -#define S3C_SYSREG(x) (S3C_VA_SYS + (x)) - -#define S3C64XX_AHB_CON0 S3C_SYSREG(0x100) -#define S3C64XX_AHB_CON1 S3C_SYSREG(0x104) -#define S3C64XX_AHB_CON2 S3C_SYSREG(0x108) - -#define S3C64XX_SDMA_SEL S3C_SYSREG(0x110) - -#define S3C64XX_OTHERS S3C_SYSREG(0x900) - -#define S3C64XX_OTHERS_USBMASK (1 << 16) -#define S3C64XX_OTHERS_SYNCMUXSEL (1 << 6) - -#endif /* _PLAT_REGS_SYS_H */ diff --git a/arch/arm/mach-s3c64xx/include/mach/tick.h b/arch/arm/mach-s3c64xx/include/mach/tick.h index ebe18a9469b..db9c1b1d56a 100644 --- a/arch/arm/mach-s3c64xx/include/mach/tick.h +++ b/arch/arm/mach-s3c64xx/include/mach/tick.h @@ -15,6 +15,8 @@ #ifndef __ASM_ARCH_TICK_H #define __ASM_ARCH_TICK_H __FILE__ +#include <linux/irqchip/arm-vic.h> + /* note, the timer interrutps turn up in 2 places, the vic and then * the timer block. We take the VIC as the base at the moment. */ diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c index 75cbc67f628..728eef3296b 100644 --- a/arch/arm/mach-s3c64xx/mach-anw6410.c +++ b/arch/arm/mach-s3c64xx/mach-anw6410.c @@ -31,7 +31,6 @@ #include <video/platform_lcd.h> #include <video/samsung_fimd.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> @@ -50,9 +49,9 @@ #include <plat/devs.h> #include <plat/cpu.h> #include <mach/regs-gpio.h> -#include <mach/regs-modem.h> #include "common.h" +#include "regs-modem.h" /* DM9000 */ #define ANW6410_PA_DM9000 (0x18000000) @@ -230,7 +229,6 @@ MACHINE_START(ANW6410, "A&W6410") .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = anw6410_map_io, .init_machine = anw6410_machine_init, .init_late = s3c64xx_init_late, diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c index 553059f5184..bf3d1c09b08 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c @@ -29,7 +29,7 @@ #include <linux/platform_data/spi-s3c64xx.h> -#include <mach/crag6410.h> +#include "crag6410.h" static struct s3c64xx_spi_csinfo wm0010_spi_csinfo = { .line = S3C64XX_GPC(3), @@ -47,7 +47,7 @@ static struct spi_board_info wm1253_devs[] = { .bus_num = 0, .chip_select = 0, .mode = SPI_MODE_0, - .irq = S3C_EINT(5), + .irq = S3C_EINT(4), .controller_data = &wm0010_spi_csinfo, .platform_data = &wm0010_pdata, }, diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c index 053dbcbeaa7..1acf02bace5 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410.c @@ -42,7 +42,6 @@ #include <sound/wm1250-ev1.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> @@ -50,12 +49,7 @@ #include <mach/hardware.h> #include <mach/map.h> -#include <mach/regs-sys.h> #include <mach/regs-gpio.h> -#include <mach/regs-modem.h> -#include <mach/crag6410.h> - -#include <mach/regs-gpio-memport.h> #include <plat/regs-serial.h> #include <plat/fb.h> @@ -72,6 +66,10 @@ #include <plat/pm.h> #include "common.h" +#include "crag6410.h" +#include "regs-gpio-memport.h" +#include "regs-modem.h" +#include "regs-sys.h" /* serial port setup */ @@ -867,7 +865,6 @@ MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410") /* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */ .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = crag6410_map_io, .init_machine = crag6410_machine_init, .init_late = s3c64xx_init_late, diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c index 7e8605d9814..7212eb9cfeb 100644 --- a/arch/arm/mach-s3c64xx/mach-hmt.c +++ b/arch/arm/mach-s3c64xx/mach-hmt.c @@ -30,7 +30,6 @@ #include <mach/hardware.h> #include <mach/map.h> -#include <asm/hardware/vic.h> #include <asm/irq.h> #include <asm/mach-types.h> @@ -273,7 +272,6 @@ MACHINE_START(HMT, "Airgoo-HMT") /* Maintainer: Peter Korsgaard <jacmet@sunsite.dk> */ .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = hmt_map_io, .init_machine = hmt_machine_init, .init_late = s3c64xx_init_late, diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c index 4f8dc7dff92..4b41fcdaa7b 100644 --- a/arch/arm/mach-s3c64xx/mach-mini6410.c +++ b/arch/arm/mach-s3c64xx/mach-mini6410.c @@ -24,15 +24,12 @@ #include <linux/serial_core.h> #include <linux/types.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <mach/map.h> #include <mach/regs-gpio.h> -#include <mach/regs-modem.h> -#include <mach/regs-srom.h> #include <plat/adc.h> #include <plat/cpu.h> @@ -46,6 +43,8 @@ #include <video/samsung_fimd.h> #include "common.h" +#include "regs-modem.h" +#include "regs-srom.h" #define UCON S3C2410_UCON_DEFAULT #define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB) @@ -352,7 +351,6 @@ MACHINE_START(MINI6410, "MINI6410") /* Maintainer: Darius Augulis <augulis.darius@gmail.com> */ .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = mini6410_map_io, .init_machine = mini6410_machine_init, .init_late = s3c64xx_init_late, diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c index cdd7f947376..8d3cedd995f 100644 --- a/arch/arm/mach-s3c64xx/mach-ncp.c +++ b/arch/arm/mach-s3c64xx/mach-ncp.c @@ -26,7 +26,6 @@ #include <video/platform_lcd.h> #include <video/samsung_fimd.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> @@ -101,7 +100,6 @@ MACHINE_START(NCP, "NCP") /* Maintainer: Samsung Electronics */ .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = ncp_map_io, .init_machine = ncp_machine_init, .init_late = s3c64xx_init_late, diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c index b0f61982ef5..fa12bd21ad8 100644 --- a/arch/arm/mach-s3c64xx/mach-real6410.c +++ b/arch/arm/mach-s3c64xx/mach-real6410.c @@ -25,15 +25,12 @@ #include <linux/serial_core.h> #include <linux/types.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <mach/map.h> #include <mach/regs-gpio.h> -#include <mach/regs-modem.h> -#include <mach/regs-srom.h> #include <plat/adc.h> #include <plat/cpu.h> @@ -47,6 +44,8 @@ #include <video/samsung_fimd.h> #include "common.h" +#include "regs-modem.h" +#include "regs-srom.h" #define UCON S3C2410_UCON_DEFAULT #define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB) @@ -331,7 +330,6 @@ MACHINE_START(REAL6410, "REAL6410") .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = real6410_map_io, .init_machine = real6410_machine_init, .init_late = s3c64xx_init_late, diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c index c6d7390939a..fc3e9b32e26 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq.c +++ b/arch/arm/mach-s3c64xx/mach-smartq.c @@ -25,7 +25,6 @@ #include <mach/map.h> #include <mach/regs-gpio.h> -#include <mach/regs-modem.h> #include <plat/clock.h> #include <plat/cpu.h> @@ -41,6 +40,7 @@ #include <video/platform_lcd.h> #include "common.h" +#include "regs-modem.h" #define UCON S3C2410_UCON_DEFAULT #define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE) diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c index 7a737614717..ca2afcfce57 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq5.c +++ b/arch/arm/mach-s3c64xx/mach-smartq5.c @@ -17,7 +17,6 @@ #include <linux/leds.h> #include <linux/platform_device.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -153,7 +152,6 @@ MACHINE_START(SMARTQ5, "SmartQ 5") /* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */ .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = smartq_map_io, .init_machine = smartq5_machine_init, .init_late = s3c64xx_init_late, diff --git a/arch/arm/mach-s3c64xx/mach-smartq7.c b/arch/arm/mach-s3c64xx/mach-smartq7.c index 889d525325c..37bb0c632a5 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq7.c +++ b/arch/arm/mach-s3c64xx/mach-smartq7.c @@ -17,7 +17,6 @@ #include <linux/leds.h> #include <linux/platform_device.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -169,7 +168,6 @@ MACHINE_START(SMARTQ7, "SmartQ 7") /* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */ .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = smartq_map_io, .init_machine = smartq7_machine_init, .init_late = s3c64xx_init_late, diff --git a/arch/arm/mach-s3c64xx/mach-smdk6400.c b/arch/arm/mach-s3c64xx/mach-smdk6400.c index e31fe5bb37b..a392869c834 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6400.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6400.c @@ -22,7 +22,6 @@ #include <asm/mach-types.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> @@ -90,7 +89,6 @@ MACHINE_START(SMDK6400, "SMDK6400") .atag_offset = 0x100, .init_irq = s3c6400_init_irq, - .handle_irq = vic_handle_irq, .map_io = smdk6400_map_io, .init_machine = smdk6400_machine_init, .init_late = s3c64xx_init_late, diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c index f1b87cd9cb0..ba7544e2d04 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c @@ -45,7 +45,6 @@ #include <video/platform_lcd.h> #include <video/samsung_fimd.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> @@ -57,10 +56,7 @@ #include <asm/mach-types.h> #include <plat/regs-serial.h> -#include <mach/regs-modem.h> #include <mach/regs-gpio.h> -#include <mach/regs-sys.h> -#include <mach/regs-srom.h> #include <linux/platform_data/ata-samsung_cf.h> #include <linux/platform_data/i2c-s3c2410.h> #include <plat/fb.h> @@ -75,6 +71,9 @@ #include <plat/backlight.h> #include "common.h" +#include "regs-modem.h" +#include "regs-srom.h" +#include "regs-sys.h" #define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB @@ -700,7 +699,6 @@ MACHINE_START(SMDK6410, "SMDK6410") .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = smdk6410_map_io, .init_machine = smdk6410_machine_init, .init_late = s3c64xx_init_late, diff --git a/arch/arm/mach-s3c64xx/pm.c b/arch/arm/mach-s3c64xx/pm.c index 7feb426fc20..a6d7c6cf45e 100644 --- a/arch/arm/mach-s3c64xx/pm.c +++ b/arch/arm/mach-s3c64xx/pm.c @@ -26,12 +26,13 @@ #include <plat/pm.h> #include <plat/wakeup-mask.h> -#include <mach/regs-sys.h> #include <mach/regs-gpio.h> #include <mach/regs-clock.h> -#include <mach/regs-syscon-power.h> -#include <mach/regs-gpio-memport.h> -#include <mach/regs-modem.h> + +#include "regs-gpio-memport.h" +#include "regs-modem.h" +#include "regs-sys.h" +#include "regs-syscon-power.h" struct s3c64xx_pm_domain { char *const name; @@ -338,8 +339,10 @@ int __init s3c64xx_pm_init(void) for (i = 0; i < ARRAY_SIZE(s3c64xx_pm_domains); i++) pm_genpd_init(&s3c64xx_pm_domains[i]->pd, NULL, false); +#ifdef CONFIG_S3C_DEV_FB if (dev_get_platdata(&s3c_device_fb.dev)) pm_genpd_add_device(&s3c64xx_pm_f.pd, &s3c_device_fb.dev); +#endif return 0; } diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-gpio-memport.h b/arch/arm/mach-s3c64xx/regs-gpio-memport.h index 82342f6fd27..b927593019f 100644 --- a/arch/arm/mach-s3c64xx/include/mach/regs-gpio-memport.h +++ b/arch/arm/mach-s3c64xx/regs-gpio-memport.h @@ -1,5 +1,4 @@ -/* linux/arch/arm/plat-s3c64xx/include/mach/regs-gpio-memport.h - * +/* * Copyright 2008 Openmoko, Inc. * Copyright 2008 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> @@ -8,8 +7,8 @@ * S3C64XX - GPIO memory port register definitions */ -#ifndef __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H -#define __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H __FILE__ +#ifndef __MACH_S3C64XX_REGS_GPIO_MEMPORT_H +#define __MACH_S3C64XX_REGS_GPIO_MEMPORT_H __FILE__ #define S3C64XX_MEM0CONSTOP S3C64XX_GPIOREG(0x1B0) #define S3C64XX_MEM1CONSTOP S3C64XX_GPIOREG(0x1B4) @@ -21,5 +20,5 @@ #define S3C64XX_MEM0DRVCON S3C64XX_GPIOREG(0x1D0) #define S3C64XX_MEM1DRVCON S3C64XX_GPIOREG(0x1D4) -#endif /* __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H */ +#endif /* __MACH_S3C64XX_REGS_GPIO_MEMPORT_H */ diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-modem.h b/arch/arm/mach-s3c64xx/regs-modem.h index 49f7759dedf..073cdd3a03b 100644 --- a/arch/arm/mach-s3c64xx/include/mach/regs-modem.h +++ b/arch/arm/mach-s3c64xx/regs-modem.h @@ -1,5 +1,4 @@ -/* arch/arm/plat-s3c64xx/include/plat/regs-modem.h - * +/* * Copyright 2008 Openmoko, Inc. * Copyright 2008 Simtec Electronics * http://armlinux.simtec.co.uk/ @@ -12,10 +11,10 @@ * published by the Free Software Foundation. */ -#ifndef __PLAT_S3C64XX_REGS_MODEM_H -#define __PLAT_S3C64XX_REGS_MODEM_H __FILE__ +#ifndef __MACH_S3C64XX_REGS_MODEM_H +#define __MACH_S3C64XX_REGS_MODEM_H __FILE__ -#define S3C64XX_MODEMREG(x) (S3C64XX_VA_MODEM + (x)) +#define S3C64XX_MODEMREG(x) (S3C64XX_VA_MODEM + (x)) #define S3C64XX_MODEM_INT2AP S3C64XX_MODEMREG(0x0) #define S3C64XX_MODEM_INT2MODEM S3C64XX_MODEMREG(0x4) @@ -28,4 +27,4 @@ #define MIFPCON_INT2M_LEVEL (1 << 4) #define MIFPCON_LCD_BYPASS (1 << 3) -#endif /* __PLAT_S3C64XX_REGS_MODEM_H */ +#endif /* __MACH_S3C64XX_REGS_MODEM_H */ diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-srom.h b/arch/arm/mach-s3c64xx/regs-srom.h index 756731b3629..d56f3386eb0 100644 --- a/arch/arm/mach-s3c64xx/include/mach/regs-srom.h +++ b/arch/arm/mach-s3c64xx/regs-srom.h @@ -1,5 +1,4 @@ -/* arch/arm/plat-s3c64xx/include/plat/regs-srom.h - * +/* * Copyright 2009 Andy Green <andy@warmcat.com> * * S3C64XX SROM definitions @@ -9,8 +8,8 @@ * published by the Free Software Foundation. */ -#ifndef __PLAT_REGS_SROM_H -#define __PLAT_REGS_SROM_H __FILE__ +#ifndef __MACH_S3C64XX_REGS_SROM_H +#define __MACH_S3C64XX_REGS_SROM_H __FILE__ #define S3C64XX_SROMREG(x) (S3C_VA_MEM + (x)) @@ -29,7 +28,7 @@ #define S3C64XX_SROM_BW__DATAWIDTH__SHIFT 0 #define S3C64XX_SROM_BW__WAITENABLE__SHIFT 2 #define S3C64XX_SROM_BW__BYTEENABLE__SHIFT 3 -#define S3C64XX_SROM_BW__CS_MASK 0xf +#define S3C64XX_SROM_BW__CS_MASK 0xf #define S3C64XX_SROM_BW__NCS0__SHIFT 0 #define S3C64XX_SROM_BW__NCS1__SHIFT 4 @@ -56,4 +55,4 @@ #define S3C64XX_SROM_BCX__TACS__SHIFT 28 #define S3C64XX_SROM_BCX__TACS__MASK 0xf -#endif /* _PLAT_REGS_SROM_H */ +#endif /* __MACH_S3C64XX_REGS_SROM_H */ diff --git a/arch/arm/mach-s3c64xx/regs-sys.h b/arch/arm/mach-s3c64xx/regs-sys.h new file mode 100644 index 00000000000..8c411fbb0cd --- /dev/null +++ b/arch/arm/mach-s3c64xx/regs-sys.h @@ -0,0 +1,30 @@ +/* + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX system register definitions + * + * 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. +*/ + +#ifndef __MACH_S3C64XX_REGS_SYS_H +#define __MACH_S3C64XX_REGS_SYS_H __FILE__ + +#define S3C_SYSREG(x) (S3C_VA_SYS + (x)) + +#define S3C64XX_AHB_CON0 S3C_SYSREG(0x100) +#define S3C64XX_AHB_CON1 S3C_SYSREG(0x104) +#define S3C64XX_AHB_CON2 S3C_SYSREG(0x108) + +#define S3C64XX_SDMA_SEL S3C_SYSREG(0x110) + +#define S3C64XX_OTHERS S3C_SYSREG(0x900) + +#define S3C64XX_OTHERS_USBMASK (1 << 16) +#define S3C64XX_OTHERS_SYNCMUXSEL (1 << 6) + +#endif /* __MACH_S3C64XX_REGS_SYS_H */ diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-syscon-power.h b/arch/arm/mach-s3c64xx/regs-syscon-power.h index 270d96ac970..6e16b3404da 100644 --- a/arch/arm/mach-s3c64xx/include/mach/regs-syscon-power.h +++ b/arch/arm/mach-s3c64xx/regs-syscon-power.h @@ -1,5 +1,4 @@ -/* arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h - * +/* * Copyright 2008 Openmoko, Inc. * Copyright 2008 Simtec Electronics * http://armlinux.simtec.co.uk/ @@ -12,8 +11,8 @@ * published by the Free Software Foundation. */ -#ifndef __PLAT_S3C64XX_REGS_SYSCON_POWER_H -#define __PLAT_S3C64XX_REGS_SYSCON_POWER_H __FILE__ +#ifndef __MACH_S3C64XX_REGS_SYSCON_POWER_H +#define __MACH_S3C64XX_REGS_SYSCON_POWER_H __FILE__ #define S3C64XX_PWR_CFG S3C_SYSREG(0x804) @@ -113,4 +112,4 @@ #define S3C64XX_INFORM2 S3C_SYSREG(0xA08) #define S3C64XX_INFORM3 S3C_SYSREG(0xA0C) -#endif /* __PLAT_S3C64XX_REGS_SYSCON_POWER_H */ +#endif /* __MACH_S3C64XX_REGS_SYSCON_POWER_H */ diff --git a/arch/arm/mach-s3c64xx/setup-usb-phy.c b/arch/arm/mach-s3c64xx/setup-usb-phy.c index f6757e02d7d..c8174d95339 100644 --- a/arch/arm/mach-s3c64xx/setup-usb-phy.c +++ b/arch/arm/mach-s3c64xx/setup-usb-phy.c @@ -15,11 +15,12 @@ #include <linux/io.h> #include <linux/platform_device.h> #include <mach/map.h> -#include <mach/regs-sys.h> #include <plat/cpu.h> #include <plat/regs-usb-hsotg-phy.h> #include <plat/usb-phy.h> +#include "regs-sys.h" + static int s3c_usb_otgphy_init(struct platform_device *pdev) { struct clk *xusbxti; diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c index 5112371079d..3537815247f 100644 --- a/arch/arm/mach-s5p64x0/clock-s5p6440.c +++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c @@ -23,7 +23,6 @@ #include <mach/hardware.h> #include <mach/map.h> #include <mach/regs-clock.h> -#include <mach/s5p64x0-clock.h> #include <plat/cpu-freq.h> #include <plat/clock.h> @@ -32,6 +31,7 @@ #include <plat/s5p-clock.h> #include <plat/clock-clksrc.h> +#include "clock.h" #include "common.h" static u32 epll_div[][5] = { diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c index 154dea702d7..af384ddd2dc 100644 --- a/arch/arm/mach-s5p64x0/clock-s5p6450.c +++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c @@ -23,7 +23,6 @@ #include <mach/hardware.h> #include <mach/map.h> #include <mach/regs-clock.h> -#include <mach/s5p64x0-clock.h> #include <plat/cpu-freq.h> #include <plat/clock.h> @@ -32,6 +31,7 @@ #include <plat/s5p-clock.h> #include <plat/clock-clksrc.h> +#include "clock.h" #include "common.h" static struct clksrc_clk clk_mout_dpll = { diff --git a/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h b/arch/arm/mach-s5p64x0/clock.h index 0ef47d1b767..28b8e3c6bd2 100644 --- a/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h +++ b/arch/arm/mach-s5p64x0/clock.h @@ -1,5 +1,4 @@ -/* linux/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h - * +/* * Copyright (c) 2010 Samsung Electronics Co., Ltd. * http://www.samsung.com * @@ -10,8 +9,8 @@ * published by the Free Software Foundation. */ -#ifndef __ASM_ARCH_CLOCK_H -#define __ASM_ARCH_CLOCK_H __FILE__ +#ifndef __MACH_S5P64X0_CLOCK_H +#define __MACH_S5P64X0_CLOCK_H __FILE__ #include <linux/clk.h> @@ -36,4 +35,4 @@ extern int s5p64x0_mem_ctrl(struct clk *clk, int enable); extern int s5p64x0_clk48m_ctrl(struct clk *clk, int enable); -#endif /* __ASM_ARCH_CLOCK_H */ +#endif /* __MACH_S5P64X0_CLOCK_H */ diff --git a/arch/arm/mach-s5p64x0/gpiolib.c b/arch/arm/mach-s5p64x0/gpiolib.c deleted file mode 100644 index 700dac6c43f..00000000000 --- a/arch/arm/mach-s5p64x0/gpiolib.c +++ /dev/null @@ -1,508 +0,0 @@ -/* linux/arch/arm/mach-s5p64x0/gpiolib.c - * - * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * S5P64X0 - GPIOlib support - * - * 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. -*/ - -#include <linux/kernel.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/gpio.h> - -#include <mach/map.h> -#include <mach/regs-gpio.h> -#include <mach/regs-clock.h> - -#include <plat/cpu.h> -#include <plat/gpio-core.h> -#include <plat/gpio-cfg.h> -#include <plat/gpio-cfg-helpers.h> - -/* - * S5P6440 GPIO bank summary: - * - * Bank GPIOs Style SlpCon ExtInt Group - * A 6 4Bit Yes 1 - * B 7 4Bit Yes 1 - * C 8 4Bit Yes 2 - * F 2 2Bit Yes 4 [1] - * G 7 4Bit Yes 5 - * H 10 4Bit[2] Yes 6 - * I 16 2Bit Yes None - * J 12 2Bit Yes None - * N 16 2Bit No IRQ_EINT - * P 8 2Bit Yes 8 - * R 15 4Bit[2] Yes 8 - * - * S5P6450 GPIO bank summary: - * - * Bank GPIOs Style SlpCon ExtInt Group - * A 6 4Bit Yes 1 - * B 7 4Bit Yes 1 - * C 8 4Bit Yes 2 - * D 8 4Bit Yes None - * F 2 2Bit Yes None - * G 14 4Bit[2] Yes 5 - * H 10 4Bit[2] Yes 6 - * I 16 2Bit Yes None - * J 12 2Bit Yes None - * K 5 4Bit Yes None - * N 16 2Bit No IRQ_EINT - * P 11 2Bit Yes 8 - * Q 14 2Bit Yes None - * R 15 4Bit[2] Yes None - * S 8 2Bit Yes None - * - * [1] BANKF pins 14,15 do not form part of the external interrupt sources - * [2] BANK has two control registers, GPxCON0 and GPxCON1 - */ - -static int s5p64x0_gpiolib_rbank_4bit2_input(struct gpio_chip *chip, - unsigned int offset) -{ - struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); - void __iomem *base = ourchip->base; - void __iomem *regcon = base; - unsigned long con; - unsigned long flags; - - switch (offset) { - case 6: - offset += 1; - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - regcon -= 4; - break; - default: - offset -= 7; - break; - } - - s3c_gpio_lock(ourchip, flags); - - con = __raw_readl(regcon); - con &= ~(0xf << con_4bit_shift(offset)); - __raw_writel(con, regcon); - - s3c_gpio_unlock(ourchip, flags); - - return 0; -} - -static int s5p64x0_gpiolib_rbank_4bit2_output(struct gpio_chip *chip, - unsigned int offset, int value) -{ - struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); - void __iomem *base = ourchip->base; - void __iomem *regcon = base; - unsigned long con; - unsigned long dat; - unsigned long flags; - unsigned con_offset = offset; - - switch (con_offset) { - case 6: - con_offset += 1; - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - regcon -= 4; - break; - default: - con_offset -= 7; - break; - } - - s3c_gpio_lock(ourchip, flags); - - con = __raw_readl(regcon); - con &= ~(0xf << con_4bit_shift(con_offset)); - con |= 0x1 << con_4bit_shift(con_offset); - - dat = __raw_readl(base + GPIODAT_OFF); - if (value) - dat |= 1 << offset; - else - dat &= ~(1 << offset); - - __raw_writel(con, regcon); - __raw_writel(dat, base + GPIODAT_OFF); - - s3c_gpio_unlock(ourchip, flags); - - return 0; -} - -int s5p64x0_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip, - unsigned int off, unsigned int cfg) -{ - void __iomem *reg = chip->base; - unsigned int shift; - u32 con; - - switch (off) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - shift = (off & 7) * 4; - reg -= 4; - break; - case 6: - shift = ((off + 1) & 7) * 4; - reg -= 4; - default: - shift = ((off + 1) & 7) * 4; - break; - } - - if (s3c_gpio_is_cfg_special(cfg)) { - cfg &= 0xf; - cfg <<= shift; - } - - con = __raw_readl(reg); - con &= ~(0xf << shift); - con |= cfg; - __raw_writel(con, reg); - - return 0; -} - -static struct s3c_gpio_cfg s5p64x0_gpio_cfgs[] = { - { - .cfg_eint = 0, - }, { - .cfg_eint = 7, - }, { - .cfg_eint = 3, - .set_config = s5p64x0_gpio_setcfg_4bit_rbank, - }, { - .cfg_eint = 0, - .set_config = s3c_gpio_setcfg_s3c24xx, - .get_config = s3c_gpio_getcfg_s3c24xx, - }, { - .cfg_eint = 2, - .set_config = s3c_gpio_setcfg_s3c24xx, - .get_config = s3c_gpio_getcfg_s3c24xx, - }, { - .cfg_eint = 3, - .set_config = s3c_gpio_setcfg_s3c24xx, - .get_config = s3c_gpio_getcfg_s3c24xx, - }, -}; - -static struct s3c_gpio_chip s5p6440_gpio_4bit[] = { - { - .base = S5P64X0_GPA_BASE, - .config = &s5p64x0_gpio_cfgs[1], - .chip = { - .base = S5P6440_GPA(0), - .ngpio = S5P6440_GPIO_A_NR, - .label = "GPA", - }, - }, { - .base = S5P64X0_GPB_BASE, - .config = &s5p64x0_gpio_cfgs[1], - .chip = { - .base = S5P6440_GPB(0), - .ngpio = S5P6440_GPIO_B_NR, - .label = "GPB", - }, - }, { - .base = S5P64X0_GPC_BASE, - .config = &s5p64x0_gpio_cfgs[1], - .chip = { - .base = S5P6440_GPC(0), - .ngpio = S5P6440_GPIO_C_NR, - .label = "GPC", - }, - }, { - .base = S5P64X0_GPG_BASE, - .config = &s5p64x0_gpio_cfgs[1], - .chip = { - .base = S5P6440_GPG(0), - .ngpio = S5P6440_GPIO_G_NR, - .label = "GPG", - }, - }, -}; - -static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = { - { - .base = S5P64X0_GPH_BASE + 0x4, - .config = &s5p64x0_gpio_cfgs[1], - .chip = { - .base = S5P6440_GPH(0), - .ngpio = S5P6440_GPIO_H_NR, - .label = "GPH", - }, - }, -}; - -static struct s3c_gpio_chip s5p6440_gpio_rbank_4bit2[] = { - { - .base = S5P64X0_GPR_BASE + 0x4, - .config = &s5p64x0_gpio_cfgs[2], - .chip = { - .base = S5P6440_GPR(0), - .ngpio = S5P6440_GPIO_R_NR, - .label = "GPR", - }, - }, -}; - -static struct s3c_gpio_chip s5p6440_gpio_2bit[] = { - { - .base = S5P64X0_GPF_BASE, - .config = &s5p64x0_gpio_cfgs[5], - .chip = { - .base = S5P6440_GPF(0), - .ngpio = S5P6440_GPIO_F_NR, - .label = "GPF", - }, - }, { - .base = S5P64X0_GPI_BASE, - .config = &s5p64x0_gpio_cfgs[3], - .chip = { - .base = S5P6440_GPI(0), - .ngpio = S5P6440_GPIO_I_NR, - .label = "GPI", - }, - }, { - .base = S5P64X0_GPJ_BASE, - .config = &s5p64x0_gpio_cfgs[3], - .chip = { - .base = S5P6440_GPJ(0), - .ngpio = S5P6440_GPIO_J_NR, - .label = "GPJ", - }, - }, { - .base = S5P64X0_GPN_BASE, - .config = &s5p64x0_gpio_cfgs[4], - .chip = { - .base = S5P6440_GPN(0), - .ngpio = S5P6440_GPIO_N_NR, - .label = "GPN", - }, - }, { - .base = S5P64X0_GPP_BASE, - .config = &s5p64x0_gpio_cfgs[5], - .chip = { - .base = S5P6440_GPP(0), - .ngpio = S5P6440_GPIO_P_NR, - .label = "GPP", - }, - }, -}; - -static struct s3c_gpio_chip s5p6450_gpio_4bit[] = { - { - .base = S5P64X0_GPA_BASE, - .config = &s5p64x0_gpio_cfgs[1], - .chip = { - .base = S5P6450_GPA(0), - .ngpio = S5P6450_GPIO_A_NR, - .label = "GPA", - }, - }, { - .base = S5P64X0_GPB_BASE, - .config = &s5p64x0_gpio_cfgs[1], - .chip = { - .base = S5P6450_GPB(0), - .ngpio = S5P6450_GPIO_B_NR, - .label = "GPB", - }, - }, { - .base = S5P64X0_GPC_BASE, - .config = &s5p64x0_gpio_cfgs[1], - .chip = { - .base = S5P6450_GPC(0), - .ngpio = S5P6450_GPIO_C_NR, - .label = "GPC", - }, - }, { - .base = S5P6450_GPD_BASE, - .config = &s5p64x0_gpio_cfgs[1], - .chip = { - .base = S5P6450_GPD(0), - .ngpio = S5P6450_GPIO_D_NR, - .label = "GPD", - }, - }, { - .base = S5P6450_GPK_BASE, - .config = &s5p64x0_gpio_cfgs[1], - .chip = { - .base = S5P6450_GPK(0), - .ngpio = S5P6450_GPIO_K_NR, - .label = "GPK", - }, - }, -}; - -static struct s3c_gpio_chip s5p6450_gpio_4bit2[] = { - { - .base = S5P64X0_GPG_BASE + 0x4, - .config = &s5p64x0_gpio_cfgs[1], - .chip = { - .base = S5P6450_GPG(0), - .ngpio = S5P6450_GPIO_G_NR, - .label = "GPG", - }, - }, { - .base = S5P64X0_GPH_BASE + 0x4, - .config = &s5p64x0_gpio_cfgs[1], - .chip = { - .base = S5P6450_GPH(0), - .ngpio = S5P6450_GPIO_H_NR, - .label = "GPH", - }, - }, -}; - -static struct s3c_gpio_chip s5p6450_gpio_rbank_4bit2[] = { - { - .base = S5P64X0_GPR_BASE + 0x4, - .config = &s5p64x0_gpio_cfgs[2], - .chip = { - .base = S5P6450_GPR(0), - .ngpio = S5P6450_GPIO_R_NR, - .label = "GPR", - }, - }, -}; - -static struct s3c_gpio_chip s5p6450_gpio_2bit[] = { - { - .base = S5P64X0_GPF_BASE, - .config = &s5p64x0_gpio_cfgs[5], - .chip = { - .base = S5P6450_GPF(0), - .ngpio = S5P6450_GPIO_F_NR, - .label = "GPF", - }, - }, { - .base = S5P64X0_GPI_BASE, - .config = &s5p64x0_gpio_cfgs[3], - .chip = { - .base = S5P6450_GPI(0), - .ngpio = S5P6450_GPIO_I_NR, - .label = "GPI", - }, - }, { - .base = S5P64X0_GPJ_BASE, - .config = &s5p64x0_gpio_cfgs[3], - .chip = { - .base = S5P6450_GPJ(0), - .ngpio = S5P6450_GPIO_J_NR, - .label = "GPJ", - }, - }, { - .base = S5P64X0_GPN_BASE, - .config = &s5p64x0_gpio_cfgs[4], - .chip = { - .base = S5P6450_GPN(0), - .ngpio = S5P6450_GPIO_N_NR, - .label = "GPN", - }, - }, { - .base = S5P64X0_GPP_BASE, - .config = &s5p64x0_gpio_cfgs[5], - .chip = { - .base = S5P6450_GPP(0), - .ngpio = S5P6450_GPIO_P_NR, - .label = "GPP", - }, - }, { - .base = S5P6450_GPQ_BASE, - .config = &s5p64x0_gpio_cfgs[4], - .chip = { - .base = S5P6450_GPQ(0), - .ngpio = S5P6450_GPIO_Q_NR, - .label = "GPQ", - }, - }, { - .base = S5P6450_GPS_BASE, - .config = &s5p64x0_gpio_cfgs[5], - .chip = { - .base = S5P6450_GPS(0), - .ngpio = S5P6450_GPIO_S_NR, - .label = "GPS", - }, - }, -}; - -void __init s5p64x0_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips) -{ - for (; nr_chips > 0; nr_chips--, chipcfg++) { - if (!chipcfg->set_config) - chipcfg->set_config = s3c_gpio_setcfg_s3c64xx_4bit; - if (!chipcfg->get_config) - chipcfg->get_config = s3c_gpio_getcfg_s3c64xx_4bit; - if (!chipcfg->set_pull) - chipcfg->set_pull = s3c_gpio_setpull_updown; - if (!chipcfg->get_pull) - chipcfg->get_pull = s3c_gpio_getpull_updown; - } -} - -static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip, - int nr_chips) -{ - for (; nr_chips > 0; nr_chips--, chip++) { - chip->chip.direction_input = s5p64x0_gpiolib_rbank_4bit2_input; - chip->chip.direction_output = - s5p64x0_gpiolib_rbank_4bit2_output; - s3c_gpiolib_add(chip); - } -} - -static int __init s5p64x0_gpiolib_init(void) -{ - s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs, - ARRAY_SIZE(s5p64x0_gpio_cfgs)); - - if (soc_is_s5p6450()) { - samsung_gpiolib_add_2bit_chips(s5p6450_gpio_2bit, - ARRAY_SIZE(s5p6450_gpio_2bit)); - - samsung_gpiolib_add_4bit_chips(s5p6450_gpio_4bit, - ARRAY_SIZE(s5p6450_gpio_4bit)); - - samsung_gpiolib_add_4bit2_chips(s5p6450_gpio_4bit2, - ARRAY_SIZE(s5p6450_gpio_4bit2)); - - s5p64x0_gpio_add_rbank_4bit2(s5p6450_gpio_rbank_4bit2, - ARRAY_SIZE(s5p6450_gpio_rbank_4bit2)); - } else { - samsung_gpiolib_add_2bit_chips(s5p6440_gpio_2bit, - ARRAY_SIZE(s5p6440_gpio_2bit)); - - samsung_gpiolib_add_4bit_chips(s5p6440_gpio_4bit, - ARRAY_SIZE(s5p6440_gpio_4bit)); - - samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2, - ARRAY_SIZE(s5p6440_gpio_4bit2)); - - s5p64x0_gpio_add_rbank_4bit2(s5p6440_gpio_rbank_4bit2, - ARRAY_SIZE(s5p6440_gpio_rbank_4bit2)); - } - - return 0; -} -core_initcall(s5p64x0_gpiolib_init); diff --git a/arch/arm/mach-s5p64x0/include/mach/i2c.h b/arch/arm/mach-s5p64x0/i2c.h index 887d25209e8..1e5bb4ea200 100644 --- a/arch/arm/mach-s5p64x0/include/mach/i2c.h +++ b/arch/arm/mach-s5p64x0/i2c.h @@ -1,5 +1,4 @@ -/* linux/arch/arm/mach-s5p64x0/include/mach/i2c.h - * +/* * Copyright (c) 2010 Samsung Electronics Co., Ltd. * http://www.samsung.com * diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-irq.h b/arch/arm/mach-s5p64x0/include/mach/regs-irq.h index 4aaebdace55..d60397d1ff4 100644 --- a/arch/arm/mach-s5p64x0/include/mach/regs-irq.h +++ b/arch/arm/mach-s5p64x0/include/mach/regs-irq.h @@ -13,7 +13,6 @@ #ifndef __ASM_ARCH_REGS_IRQ_H #define __ASM_ARCH_REGS_IRQ_H __FILE__ -#include <asm/hardware/vic.h> #include <mach/map.h> #endif /* __ASM_ARCH_REGS_IRQ_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/tick.h b/arch/arm/mach-s5p64x0/include/mach/tick.h deleted file mode 100644 index 00aa7f1d8e5..00000000000 --- a/arch/arm/mach-s5p64x0/include/mach/tick.h +++ /dev/null @@ -1,29 +0,0 @@ -/* linux/arch/arm/mach-s5p64x0/include/mach/tick.h - * - * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Copyright 2008 Openmoko, Inc. - * Copyright 2008 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks <ben@simtec.co.uk> - * - * S5P64X0 - Timer tick support definitions - * - * 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. -*/ - -#ifndef __ASM_ARCH_TICK_H -#define __ASM_ARCH_TICK_H __FILE__ - -static inline u32 s3c24xx_ostimer_pending(void) -{ - u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS); - return pend & (1 << (IRQ_TIMER4_VIC - S5P_IRQ_VIC0(0))); -} - -#define TICK_MAX (0xffffffff) - -#endif /* __ASM_ARCH_TICK_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/uncompress.h b/arch/arm/mach-s5p64x0/include/mach/uncompress.h index 1608faf870f..19e0d64d78c 100644 --- a/arch/arm/mach-s5p64x0/include/mach/uncompress.h +++ b/arch/arm/mach-s5p64x0/include/mach/uncompress.h @@ -116,33 +116,6 @@ static inline void flush(void) *((volatile unsigned int __force *)(ad)) = (d); \ } while (0) -/* - * CONFIG_S3C_BOOT_WATCHDOG - * - * Simple boot-time watchdog setup, to reboot the system if there is - * any problem with the boot process - */ - -#ifdef CONFIG_S3C_BOOT_WATCHDOG - -#define WDOG_COUNT (0xff00) - -static inline void arch_decomp_wdog(void) -{ - __raw_writel(WDOG_COUNT, S3C2410_WTCNT); -} - -static void arch_decomp_wdog_start(void) -{ - __raw_writel(WDOG_COUNT, S3C2410_WTDAT); - __raw_writel(WDOG_COUNT, S3C2410_WTCNT); - __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x80), S3C2410_WTCON); -} - -#else -#define arch_decomp_wdog_start() -#define arch_decomp_wdog() -#endif #ifdef CONFIG_S3C_BOOT_ERROR_RESET @@ -192,7 +165,6 @@ static void arch_decomp_setup(void) */ arch_detect_cpu(); - arch_decomp_wdog_start(); /* * Enable the UART FIFOs if they where not enabled and our diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c index 0a3146dc081..e23723a5a21 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6440.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c @@ -29,7 +29,6 @@ #include <video/platform_lcd.h> #include <video/samsung_fimd.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/irq.h> @@ -38,7 +37,6 @@ #include <mach/hardware.h> #include <mach/map.h> #include <mach/regs-clock.h> -#include <mach/i2c.h> #include <mach/regs-gpio.h> #include <plat/regs-serial.h> @@ -56,6 +54,7 @@ #include <plat/sdhci.h> #include "common.h" +#include "i2c.h" #define SMDK6440_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ @@ -272,7 +271,6 @@ MACHINE_START(SMDK6440, "SMDK6440") .atag_offset = 0x100, .init_irq = s5p6440_init_irq, - .handle_irq = vic_handle_irq, .map_io = smdk6440_map_io, .init_machine = smdk6440_machine_init, .init_time = s5p_timer_init, diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c index 36917f2ea25..ca10963a959 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6450.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c @@ -29,7 +29,6 @@ #include <video/platform_lcd.h> #include <video/samsung_fimd.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/irq.h> @@ -38,7 +37,6 @@ #include <mach/hardware.h> #include <mach/map.h> #include <mach/regs-clock.h> -#include <mach/i2c.h> #include <mach/regs-gpio.h> #include <plat/regs-serial.h> @@ -56,6 +54,7 @@ #include <plat/sdhci.h> #include "common.h" +#include "i2c.h" #define SMDK6450_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ @@ -291,7 +290,6 @@ MACHINE_START(SMDK6450, "SMDK6450") .atag_offset = 0x100, .init_irq = s5p6450_init_irq, - .handle_irq = vic_handle_irq, .map_io = smdk6450_map_io, .init_machine = smdk6450_machine_init, .init_time = s5p_timer_init, diff --git a/arch/arm/mach-s5p64x0/setup-i2c0.c b/arch/arm/mach-s5p64x0/setup-i2c0.c index a32edc545e6..569b76ac98c 100644 --- a/arch/arm/mach-s5p64x0/setup-i2c0.c +++ b/arch/arm/mach-s5p64x0/setup-i2c0.c @@ -21,7 +21,7 @@ struct platform_device; /* don't need the contents */ #include <plat/gpio-cfg.h> #include <linux/platform_data/i2c-s3c2410.h> -#include <mach/i2c.h> +#include "i2c.h" void s5p6440_i2c0_cfg_gpio(struct platform_device *dev) { diff --git a/arch/arm/mach-s5p64x0/setup-i2c1.c b/arch/arm/mach-s5p64x0/setup-i2c1.c index ca2c5c7f8aa..867374e6d0b 100644 --- a/arch/arm/mach-s5p64x0/setup-i2c1.c +++ b/arch/arm/mach-s5p64x0/setup-i2c1.c @@ -21,7 +21,7 @@ struct platform_device; /* don't need the contents */ #include <plat/gpio-cfg.h> #include <linux/platform_data/i2c-s3c2410.h> -#include <mach/i2c.h> +#include "i2c.h" void s5p6440_i2c1_cfg_gpio(struct platform_device *dev) { diff --git a/arch/arm/mach-s5pc100/include/mach/regs-irq.h b/arch/arm/mach-s5pc100/include/mach/regs-irq.h index 4d9036d0f28..761627897f3 100644 --- a/arch/arm/mach-s5pc100/include/mach/regs-irq.h +++ b/arch/arm/mach-s5pc100/include/mach/regs-irq.h @@ -14,6 +14,5 @@ #define __ASM_ARCH_REGS_IRQ_H __FILE__ #include <mach/map.h> -#include <asm/hardware/vic.h> #endif /* __ASM_ARCH_REGS_IRQ_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/tick.h b/arch/arm/mach-s5pc100/include/mach/tick.h index 20f68730ed1..0af8e41230e 100644 --- a/arch/arm/mach-s5pc100/include/mach/tick.h +++ b/arch/arm/mach-s5pc100/include/mach/tick.h @@ -15,6 +15,8 @@ #ifndef __ASM_ARCH_TICK_H #define __ASM_ARCH_TICK_H __FILE__ +#include <linux/irqchip/arm-vic.h> + /* note, the timer interrutps turn up in 2 places, the vic and then * the timer block. We take the VIC as the base at the moment. */ diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c index 39a9197d174..185a1958389 100644 --- a/arch/arm/mach-s5pc100/mach-smdkc100.c +++ b/arch/arm/mach-s5pc100/mach-smdkc100.c @@ -25,7 +25,6 @@ #include <linux/input.h> #include <linux/pwm_backlight.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -254,7 +253,6 @@ MACHINE_START(SMDKC100, "SMDKC100") /* Maintainer: Byungho Min <bhmin@samsung.com> */ .atag_offset = 0x100, .init_irq = s5pc100_init_irq, - .handle_irq = vic_handle_irq, .map_io = smdkc100_map_io, .init_machine = smdkc100_machine_init, .init_time = s3c24xx_timer_init, diff --git a/arch/arm/mach-s5pv210/dev-audio.c b/arch/arm/mach-s5pv210/dev-audio.c index addfb165c13..2d67361ef43 100644 --- a/arch/arm/mach-s5pv210/dev-audio.c +++ b/arch/arm/mach-s5pv210/dev-audio.c @@ -18,7 +18,8 @@ #include <mach/map.h> #include <mach/dma.h> #include <mach/irqs.h> -#include <mach/regs-audss.h> + +#define S5PV210_AUDSS_INT_MEM (0xC0000000) static int s5pv210_cfg_i2s(struct platform_device *pdev) { diff --git a/arch/arm/mach-s5pv210/include/mach/regs-audss.h b/arch/arm/mach-s5pv210/include/mach/regs-audss.h deleted file mode 100644 index eacc1f79080..00000000000 --- a/arch/arm/mach-s5pv210/include/mach/regs-audss.h +++ /dev/null @@ -1,18 +0,0 @@ -/* arch/arm/mach-s5pv210/include/mach/regs-audss.h - * - * Copyright (c) 2011 Samsung Electronics - * http://www.samsung.com - * - * S5PV210 Audio SubSystem clock register definitions - * - * 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. -*/ - -#ifndef __PLAT_REGS_AUDSS_H -#define __PLAT_REGS_AUDSS_H __FILE__ - -#define S5PV210_AUDSS_INT_MEM (0xC0000000) - -#endif /* _PLAT_REGS_AUDSS_H */ diff --git a/arch/arm/mach-s5pv210/include/mach/regs-irq.h b/arch/arm/mach-s5pv210/include/mach/regs-irq.h index 5c3b104a7c8..d8bc1e6c7aa 100644 --- a/arch/arm/mach-s5pv210/include/mach/regs-irq.h +++ b/arch/arm/mach-s5pv210/include/mach/regs-irq.h @@ -13,7 +13,6 @@ #ifndef __ASM_ARCH_REGS_IRQ_H #define __ASM_ARCH_REGS_IRQ_H __FILE__ -#include <asm/hardware/vic.h> #include <mach/map.h> #endif /* __ASM_ARCH_REGS_IRQ_H */ diff --git a/arch/arm/mach-s5pv210/include/mach/regs-sys.h b/arch/arm/mach-s5pv210/include/mach/regs-sys.h deleted file mode 100644 index cccb1eddaa3..00000000000 --- a/arch/arm/mach-s5pv210/include/mach/regs-sys.h +++ /dev/null @@ -1,15 +0,0 @@ -/* arch/arm/mach-s5pv210/include/mach/regs-sys.h - * - * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5PV210 - System registers definitions - * - * 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. -*/ - -#define S5PV210_USB_PHY_CON (S3C_VA_SYS + 0xE80C) -#define S5PV210_USB_PHY0_EN (1 << 0) -#define S5PV210_USB_PHY1_EN (1 << 1) diff --git a/arch/arm/mach-s5pv210/include/mach/tick.h b/arch/arm/mach-s5pv210/include/mach/tick.h deleted file mode 100644 index 7993b3603cc..00000000000 --- a/arch/arm/mach-s5pv210/include/mach/tick.h +++ /dev/null @@ -1,26 +0,0 @@ -/* linux/arch/arm/mach-s5pv210/include/mach/tick.h - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * Based on arch/arm/mach-s3c6400/include/mach/tick.h - * - * S5PV210 - Timer tick support definitions - * - * 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. -*/ - -#ifndef __ASM_ARCH_TICK_H -#define __ASM_ARCH_TICK_H __FILE__ - -static inline u32 s3c24xx_ostimer_pending(void) -{ - u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS); - return pend & (1 << (IRQ_TIMER4_VIC - S5P_IRQ_VIC0(0))); -} - -#define TICK_MAX (0xffffffff) - -#endif /* __ASM_ARCH_TICK_H */ diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index 1fb44a5ebb8..11900a8e88a 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c @@ -22,7 +22,6 @@ #include <linux/input.h> #include <linux/gpio.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/setup.h> @@ -685,7 +684,6 @@ MACHINE_START(AQUILA, "Aquila") Kyungmin Park <kyungmin.park@samsung.com> */ .atag_offset = 0x100, .init_irq = s5pv210_init_irq, - .handle_irq = vic_handle_irq, .map_io = aquila_map_io, .init_machine = aquila_machine_init, .init_time = s5p_timer_init, diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index ababdca2b3e..57048159174 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -29,7 +29,6 @@ #include <linux/interrupt.h> #include <linux/platform_data/s3c-hsotg.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/setup.h> @@ -972,7 +971,6 @@ MACHINE_START(GONI, "GONI") /* Maintainers: Kyungmin Park <kyungmin.park@samsung.com> */ .atag_offset = 0x100, .init_irq = s5pv210_init_irq, - .handle_irq = vic_handle_irq, .map_io = goni_map_io, .init_machine = goni_machine_init, .init_time = s5p_timer_init, diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c index acfb0ebce13..28bd0248a3e 100644 --- a/arch/arm/mach-s5pv210/mach-smdkc110.c +++ b/arch/arm/mach-s5pv210/mach-smdkc110.c @@ -15,7 +15,6 @@ #include <linux/i2c.h> #include <linux/device.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/setup.h> @@ -152,7 +151,6 @@ MACHINE_START(SMDKC110, "SMDKC110") /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ .atag_offset = 0x100, .init_irq = s5pv210_init_irq, - .handle_irq = vic_handle_irq, .map_io = smdkc110_map_io, .init_machine = smdkc110_machine_init, .init_time = s5p_timer_init, diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c index e1d820f3b42..3c73f36869b 100644 --- a/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/arch/arm/mach-s5pv210/mach-smdkv210.c @@ -21,7 +21,6 @@ #include <linux/pwm_backlight.h> #include <linux/platform_data/s3c-hsotg.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/setup.h> @@ -328,7 +327,6 @@ MACHINE_START(SMDKV210, "SMDKV210") /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ .atag_offset = 0x100, .init_irq = s5pv210_init_irq, - .handle_irq = vic_handle_irq, .map_io = smdkv210_map_io, .init_machine = smdkv210_machine_init, .init_time = s5p_timer_init, diff --git a/arch/arm/mach-s5pv210/mach-torbreck.c b/arch/arm/mach-s5pv210/mach-torbreck.c index 1e6fc6eccdf..2d4c5531819 100644 --- a/arch/arm/mach-s5pv210/mach-torbreck.c +++ b/arch/arm/mach-s5pv210/mach-torbreck.c @@ -14,7 +14,6 @@ #include <linux/init.h> #include <linux/serial_core.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/setup.h> @@ -129,7 +128,6 @@ MACHINE_START(TORBRECK, "TORBRECK") /* Maintainer: Hyunchul Ko <ghcstop@gmail.com> */ .atag_offset = 0x100, .init_irq = s5pv210_init_irq, - .handle_irq = vic_handle_irq, .map_io = torbreck_map_io, .init_machine = torbreck_machine_init, .init_time = s5p_timer_init, diff --git a/arch/arm/mach-s5pv210/setup-usb-phy.c b/arch/arm/mach-s5pv210/setup-usb-phy.c index be39cf4aa91..356a0900af0 100644 --- a/arch/arm/mach-s5pv210/setup-usb-phy.c +++ b/arch/arm/mach-s5pv210/setup-usb-phy.c @@ -12,12 +12,17 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/platform_device.h> + #include <mach/map.h> -#include <mach/regs-sys.h> + #include <plat/cpu.h> #include <plat/regs-usb-hsotg-phy.h> #include <plat/usb-phy.h> +#define S5PV210_USB_PHY_CON (S3C_VA_SYS + 0xE80C) +#define S5PV210_USB_PHY0_EN (1 << 0) +#define S5PV210_USB_PHY1_EN (1 << 1) + static int s5pv210_usb_otgphy_init(struct platform_device *pdev) { struct clk *xusbxti; diff --git a/arch/arm/mach-sa1100/include/mach/uncompress.h b/arch/arm/mach-sa1100/include/mach/uncompress.h index 5cf71da60e4..73093dc8982 100644 --- a/arch/arm/mach-sa1100/include/mach/uncompress.h +++ b/arch/arm/mach-sa1100/include/mach/uncompress.h @@ -49,4 +49,3 @@ static inline void flush(void) * Nothing to do for these */ #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index 934db6385cd..a59a13a665a 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c @@ -124,16 +124,12 @@ void __init sa1100_timer_init(void) setup_sched_clock(sa1100_read_sched_clock, 32, 3686400); - clockevents_calc_mult_shift(&ckevt_sa1100_osmr0, 3686400, 4); - ckevt_sa1100_osmr0.max_delta_ns = - clockevent_delta2ns(0x7fffffff, &ckevt_sa1100_osmr0); - ckevt_sa1100_osmr0.min_delta_ns = - clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_sa1100_osmr0) + 1; ckevt_sa1100_osmr0.cpumask = cpumask_of(0); setup_irq(IRQ_OST0, &sa1100_timer_irq); clocksource_mmio_init(OSCR, "oscr", CLOCK_TICK_RATE, 200, 32, clocksource_mmio_readl_up); - clockevents_register_device(&ckevt_sa1100_osmr0); + clockevents_config_and_register(&ckevt_sa1100_osmr0, 3686400, + MIN_OSCR_DELTA * 2, 0x7fffffff); } diff --git a/arch/arm/mach-shark/include/mach/uncompress.h b/arch/arm/mach-shark/include/mach/uncompress.h index 22ccab4c3c5..a168435aecc 100644 --- a/arch/arm/mach-shark/include/mach/uncompress.h +++ b/arch/arm/mach-shark/include/mach/uncompress.h @@ -48,4 +48,3 @@ static void putr() * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index d81a66362b7..705bc63c798 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -40,6 +40,7 @@ #include <linux/mmc/sh_mobile_sdhi.h> #include <linux/mfd/tmio.h> #include <linux/sh_clk.h> +#include <linux/irqchip/arm-gic.h> #include <video/sh_mobile_lcdc.h> #include <video/sh_mipi_dsi.h> #include <sound/sh_fsi.h> @@ -49,7 +50,6 @@ #include <mach/common.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/traps.h> @@ -668,7 +668,6 @@ MACHINE_START(AG5EVM, "ag5evm") .init_early = sh73a0_add_early_devices, .nr_irqs = NR_IRQS_LEGACY, .init_irq = sh73a0_init_irq, - .handle_irq = gic_handle_irq, .init_machine = ag5evm_init, .init_late = shmobile_init_late, .init_time = sh73a0_earlytimer_init, diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c index 2f24994f2ef..d759a9c2b9e 100644 --- a/arch/arm/mach-shmobile/board-kota2.c +++ b/arch/arm/mach-shmobile/board-kota2.c @@ -35,6 +35,7 @@ #include <linux/input/sh_keysc.h> #include <linux/gpio_keys.h> #include <linux/leds.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/leds-renesas-tpu.h> #include <linux/mmc/host.h> #include <linux/mmc/sh_mmcif.h> @@ -47,7 +48,6 @@ #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/time.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/traps.h> @@ -550,7 +550,6 @@ MACHINE_START(KOTA2, "kota2") .init_early = sh73a0_add_early_devices, .nr_irqs = NR_IRQS_LEGACY, .init_irq = sh73a0_init_irq, - .handle_irq = gic_handle_irq, .init_machine = kota2_init, .init_late = shmobile_init_late, .init_time = sh73a0_earlytimer_init, diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c index 59be864f599..c254782aa72 100644 --- a/arch/arm/mach-shmobile/board-kzm9d.c +++ b/arch/arm/mach-shmobile/board-kzm9d.c @@ -28,7 +28,6 @@ #include <mach/emev2.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> /* Dummy supplies, where voltage doesn't matter */ static struct regulator_consumer_supply dummy_supplies[] = { @@ -89,7 +88,6 @@ DT_MACHINE_START(KZM9D_DT, "kzm9d") .init_early = emev2_add_early_devices, .nr_irqs = NR_IRQS_LEGACY, .init_irq = emev2_init_irq, - .handle_irq = gic_handle_irq, .init_machine = kzm9d_add_standard_devices, .init_late = shmobile_init_late, .init_time = shmobile_timer_init, diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c index adb23ef5112..ac9428530d7 100644 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ b/arch/arm/mach-shmobile/board-kzm9g.c @@ -25,6 +25,7 @@ #include <linux/i2c.h> #include <linux/i2c/pcf857x.h> #include <linux/input.h> +#include <linux/irqchip/arm-gic.h> #include <linux/mmc/host.h> #include <linux/mmc/sh_mmcif.h> #include <linux/mmc/sh_mobile_sdhi.h> @@ -42,7 +43,6 @@ #include <mach/sh73a0.h> #include <mach/common.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <video/sh_mobile_lcdc.h> @@ -792,7 +792,6 @@ DT_MACHINE_START(KZM9G_DT, "kzm9g") .init_early = sh73a0_add_early_devices, .nr_irqs = NR_IRQS_LEGACY, .init_irq = sh73a0_init_irq, - .handle_irq = gic_handle_irq, .init_machine = kzm_init, .init_late = shmobile_init_late, .init_time = sh73a0_earlytimer_init, diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c index ca45a0c50af..cdcb799e802 100644 --- a/arch/arm/mach-shmobile/board-marzen.c +++ b/arch/arm/mach-shmobile/board-marzen.c @@ -44,7 +44,6 @@ #include <mach/irqs.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/traps.h> /* Fixed 3.3V regulator to be used by SDHI0 */ @@ -382,7 +381,6 @@ MACHINE_START(MARZEN, "marzen") .init_early = r8a7779_add_early_devices, .nr_irqs = NR_IRQS_LEGACY, .init_irq = r8a7779_init_irq, - .handle_irq = gic_handle_irq, .init_machine = marzen_init, .init_late = marzen_init_late, .init_time = r8a7779_earlytimer_init, diff --git a/arch/arm/mach-shmobile/include/mach/uncompress.h b/arch/arm/mach-shmobile/include/mach/uncompress.h index 0bd7556b138..f1aee56781e 100644 --- a/arch/arm/mach-shmobile/include/mach/uncompress.h +++ b/arch/arm/mach-shmobile/include/mach/uncompress.h @@ -16,6 +16,4 @@ static void arch_decomp_setup(void) { } -#define arch_decomp_wdog() - #endif /* __ASM_MACH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-shmobile/intc-r8a7779.c b/arch/arm/mach-shmobile/intc-r8a7779.c index ef66f1a8aa2..8807c27f71f 100644 --- a/arch/arm/mach-shmobile/intc-r8a7779.c +++ b/arch/arm/mach-shmobile/intc-r8a7779.c @@ -22,10 +22,10 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <mach/common.h> #include <mach/intc.h> #include <mach/r8a7779.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c index f0c5e519060..978369973be 100644 --- a/arch/arm/mach-shmobile/intc-sh73a0.c +++ b/arch/arm/mach-shmobile/intc-sh73a0.c @@ -23,10 +23,10 @@ #include <linux/irq.h> #include <linux/io.h> #include <linux/sh_intc.h> +#include <linux/irqchip/arm-gic.h> #include <mach/intc.h> #include <mach/irqs.h> #include <mach/sh73a0.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index ed8d2351915..1f958d7b0ba 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c @@ -12,7 +12,6 @@ */ #include <linux/init.h> #include <linux/smp.h> -#include <asm/hardware/gic.h> void __init shmobile_smp_init_cpus(unsigned int ncores) { @@ -26,6 +25,4 @@ void __init shmobile_smp_init_cpus(unsigned int ncores) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c index ea61cb657ac..47662a581c0 100644 --- a/arch/arm/mach-shmobile/setup-emev2.c +++ b/arch/arm/mach-shmobile/setup-emev2.c @@ -20,13 +20,14 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/irqchip.h> #include <linux/platform_device.h> #include <linux/platform_data/gpio-em.h> #include <linux/of_platform.h> #include <linux/delay.h> #include <linux/input.h> #include <linux/io.h> -#include <linux/of_irq.h> +#include <linux/irqchip/arm-gic.h> #include <mach/hardware.h> #include <mach/common.h> #include <mach/emev2.h> @@ -35,7 +36,6 @@ #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/time.h> -#include <asm/hardware/gic.h> static struct map_desc emev2_io_desc[] __initdata = { #ifdef CONFIG_SMP @@ -445,27 +445,16 @@ void __init emev2_add_standard_devices_dt(void) emev2_auxdata_lookup, NULL); } -static const struct of_device_id emev2_dt_irq_match[] = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - {}, -}; - static const char *emev2_boards_compat_dt[] __initdata = { "renesas,emev2", NULL, }; -void __init emev2_init_irq_dt(void) -{ - of_irq_init(emev2_dt_irq_match); -} - DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)") .smp = smp_ops(emev2_smp_ops), .init_early = emev2_init_delay, .nr_irqs = NR_IRQS_LEGACY, - .init_irq = emev2_init_irq_dt, - .handle_irq = gic_handle_irq, + .init_irq = irqchip_init, .init_machine = emev2_add_standard_devices_dt, .init_time = shmobile_timer_init, .dt_compat = emev2_boards_compat_dt, diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c index f6745628628..953eb1f9388 100644 --- a/arch/arm/mach-shmobile/smp-emev2.c +++ b/arch/arm/mach-shmobile/smp-emev2.c @@ -23,11 +23,11 @@ #include <linux/spinlock.h> #include <linux/io.h> #include <linux/delay.h> +#include <linux/irqchip/arm-gic.h> #include <mach/common.h> #include <mach/emev2.h> #include <asm/smp_plat.h> #include <asm/smp_scu.h> -#include <asm/hardware/gic.h> #include <asm/cacheflush.h> #define EMEV2_SCU_BASE 0x1e000000 @@ -100,7 +100,7 @@ static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct * /* Tell ROM loader about our vector (in headsmp.S) */ emev2_set_boot_vector(__pa(shmobile_secondary_vector)); - gic_raise_softirq(cpumask_of(cpu), 0); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); return 0; } diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c index 2ce6af9a6a3..3a4acf23edc 100644 --- a/arch/arm/mach-shmobile/smp-r8a7779.c +++ b/arch/arm/mach-shmobile/smp-r8a7779.c @@ -23,12 +23,12 @@ #include <linux/spinlock.h> #include <linux/io.h> #include <linux/delay.h> +#include <linux/irqchip/arm-gic.h> #include <mach/common.h> #include <mach/r8a7779.h> #include <asm/smp_plat.h> #include <asm/smp_scu.h> #include <asm/smp_twd.h> -#include <asm/hardware/gic.h> #define AVECR IOMEM(0xfe700040) diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index 624f00f70ab..5c5bcb59535 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c @@ -23,12 +23,12 @@ #include <linux/spinlock.h> #include <linux/io.h> #include <linux/delay.h> +#include <linux/irqchip/arm-gic.h> #include <mach/common.h> #include <asm/smp_plat.h> #include <mach/sh73a0.h> #include <asm/smp_scu.h> #include <asm/smp_twd.h> -#include <asm/hardware/gic.h> #define WUPCR IOMEM(0xe6151010) #define SRESCR IOMEM(0xe6151018) diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c index 68dd1b69512..4e9e69d9e7d 100644 --- a/arch/arm/mach-socfpga/platsmp.c +++ b/arch/arm/mach-socfpga/platsmp.c @@ -22,9 +22,9 @@ #include <linux/io.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/irqchip/arm-gic.h> #include <asm/cacheflush.h> -#include <asm/hardware/gic.h> #include <asm/smp_scu.h> #include <asm/smp_plat.h> @@ -83,8 +83,6 @@ static void __init socfpga_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c index b54baea5f80..27d68468a02 100644 --- a/arch/arm/mach-socfpga/socfpga.c +++ b/arch/arm/mach-socfpga/socfpga.c @@ -15,12 +15,12 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <linux/dw_apb_timer.h> +#include <linux/irqchip.h> #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/of_platform.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -62,11 +62,6 @@ static void __init socfpga_map_io(void) early_printk("Early printk initialized\n"); } -const static struct of_device_id irq_match[] = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - {} -}; - void __init socfpga_sysmgr_init(void) { struct device_node *np; @@ -78,9 +73,9 @@ void __init socfpga_sysmgr_init(void) rst_manager_base_addr = of_iomap(np, 0); } -static void __init gic_init_irq(void) +static void __init socfpga_init_irq(void) { - of_irq_init(irq_match); + irqchip_init(); socfpga_sysmgr_init(); } @@ -105,8 +100,7 @@ static const char *altera_dt_match[] = { DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA") .smp = smp_ops(socfpga_smp_ops), .map_io = socfpga_map_io, - .init_irq = gic_init_irq, - .handle_irq = gic_handle_irq, + .init_irq = socfpga_init_irq, .init_time = dw_apb_timer_init, .init_machine = socfpga_cyclone5_init, .restart = socfpga_cyclone5_restart, diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h index 35e8a007463..633e678e01a 100644 --- a/arch/arm/mach-spear13xx/include/mach/generic.h +++ b/arch/arm/mach-spear13xx/include/mach/generic.h @@ -28,7 +28,6 @@ extern struct dw_dma_slave nand_write_dma_priv; /* Add spear13xx family function declarations here */ void __init spear_setup_of_timer(void); void __init spear13xx_map_io(void); -void __init spear13xx_dt_init_irq(void); void __init spear13xx_l2x0_init(void); bool dw_dma_filter(struct dma_chan *chan, void *slave); void spear_restart(char, const char *); diff --git a/arch/arm/mach-spear13xx/platsmp.c b/arch/arm/mach-spear13xx/platsmp.c index 2eaa3fa7b43..af4ade61cd9 100644 --- a/arch/arm/mach-spear13xx/platsmp.c +++ b/arch/arm/mach-spear13xx/platsmp.c @@ -15,8 +15,8 @@ #include <linux/jiffies.h> #include <linux/io.h> #include <linux/smp.h> +#include <linux/irqchip/arm-gic.h> #include <asm/cacheflush.h> -#include <asm/hardware/gic.h> #include <asm/smp_scu.h> #include <mach/spear.h> #include <mach/generic.h> @@ -104,8 +104,6 @@ static void __init spear13xx_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init spear13xx_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c index e77d05d4808..56214d1076e 100644 --- a/arch/arm/mach-spear13xx/spear1310.c +++ b/arch/arm/mach-spear13xx/spear1310.c @@ -14,9 +14,9 @@ #define pr_fmt(fmt) "SPEAr1310: " fmt #include <linux/amba/pl022.h> +#include <linux/irqchip.h> #include <linux/of_platform.h> #include <linux/pata_arasan_cf_data.h> -#include <asm/hardware/gic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <mach/generic.h> @@ -90,8 +90,7 @@ static void __init spear1310_map_io(void) DT_MACHINE_START(SPEAR1310_DT, "ST SPEAr1310 SoC with Flattened Device Tree") .smp = smp_ops(spear13xx_smp_ops), .map_io = spear1310_map_io, - .init_irq = spear13xx_dt_init_irq, - .handle_irq = gic_handle_irq, + .init_irq = irqchip_init, .init_time = spear13xx_timer_init, .init_machine = spear1310_dt_init, .restart = spear_restart, diff --git a/arch/arm/mach-spear13xx/spear1340.c b/arch/arm/mach-spear13xx/spear1340.c index ebc25477906..9a28beb2a11 100644 --- a/arch/arm/mach-spear13xx/spear1340.c +++ b/arch/arm/mach-spear13xx/spear1340.c @@ -18,7 +18,7 @@ #include <linux/delay.h> #include <linux/dw_dmac.h> #include <linux/of_platform.h> -#include <asm/hardware/gic.h> +#include <linux/irqchip.h> #include <asm/mach/arch.h> #include <mach/dma.h> #include <mach/generic.h> @@ -184,8 +184,7 @@ static const char * const spear1340_dt_board_compat[] = { DT_MACHINE_START(SPEAR1340_DT, "ST SPEAr1340 SoC with Flattened Device Tree") .smp = smp_ops(spear13xx_smp_ops), .map_io = spear13xx_map_io, - .init_irq = spear13xx_dt_init_irq, - .handle_irq = gic_handle_irq, + .init_irq = irqchip_init, .init_time = spear13xx_timer_init, .init_machine = spear1340_dt_init, .restart = spear_restart, diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c index 7f7acf775f0..c7d2b4a8d8c 100644 --- a/arch/arm/mach-spear13xx/spear13xx.c +++ b/arch/arm/mach-spear13xx/spear13xx.c @@ -17,9 +17,8 @@ #include <linux/clk.h> #include <linux/dw_dmac.h> #include <linux/err.h> -#include <linux/of_irq.h> +#include <linux/of.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <asm/mach/map.h> #include <asm/smp_twd.h> #include <mach/dma.h> @@ -182,13 +181,3 @@ void __init spear13xx_timer_init(void) spear_setup_of_timer(); twd_local_timer_of_register(); } - -static const struct of_device_id gic_of_match[] __initconst = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init }, - { /* Sentinel */ } -}; - -void __init spear13xx_dt_init_irq(void) -{ - of_irq_init(gic_of_match); -} diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h index 46b8f7e4d38..df310799e41 100644 --- a/arch/arm/mach-spear3xx/include/mach/generic.h +++ b/arch/arm/mach-spear3xx/include/mach/generic.h @@ -30,7 +30,6 @@ extern struct pl08x_platform_data pl080_plat_data; void __init spear_setup_of_timer(void); void __init spear3xx_clk_init(void); void __init spear3xx_map_io(void); -void __init spear3xx_dt_init_irq(void); void spear_restart(char, const char *); diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c index 2630efa93f5..bbc9b7e9c62 100644 --- a/arch/arm/mach-spear3xx/spear300.c +++ b/arch/arm/mach-spear3xx/spear300.c @@ -14,8 +14,8 @@ #define pr_fmt(fmt) "SPEAr300: " fmt #include <linux/amba/pl08x.h> +#include <linux/irqchip.h> #include <linux/of_platform.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <mach/generic.h> #include <mach/spear.h> @@ -212,8 +212,7 @@ static void __init spear300_map_io(void) DT_MACHINE_START(SPEAR300_DT, "ST SPEAr300 SoC with Flattened Device Tree") .map_io = spear300_map_io, - .init_irq = spear3xx_dt_init_irq, - .handle_irq = vic_handle_irq, + .init_irq = irqchip_init, .init_time = spear3xx_timer_init, .init_machine = spear300_dt_init, .restart = spear_restart, diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c index b6147eaebcd..c13a434a819 100644 --- a/arch/arm/mach-spear3xx/spear310.c +++ b/arch/arm/mach-spear3xx/spear310.c @@ -15,8 +15,8 @@ #include <linux/amba/pl08x.h> #include <linux/amba/serial.h> +#include <linux/irqchip.h> #include <linux/of_platform.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <mach/generic.h> #include <mach/spear.h> @@ -254,8 +254,7 @@ static void __init spear310_map_io(void) DT_MACHINE_START(SPEAR310_DT, "ST SPEAr310 SoC with Flattened Device Tree") .map_io = spear310_map_io, - .init_irq = spear3xx_dt_init_irq, - .handle_irq = vic_handle_irq, + .init_irq = irqchip_init, .init_time = spear3xx_timer_init, .init_machine = spear310_dt_init, .restart = spear_restart, diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c index 53160f713af..e1c77079a3e 100644 --- a/arch/arm/mach-spear3xx/spear320.c +++ b/arch/arm/mach-spear3xx/spear320.c @@ -16,8 +16,8 @@ #include <linux/amba/pl022.h> #include <linux/amba/pl08x.h> #include <linux/amba/serial.h> +#include <linux/irqchip.h> #include <linux/of_platform.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <mach/generic.h> #include <mach/spear.h> @@ -268,8 +268,7 @@ static void __init spear320_map_io(void) DT_MACHINE_START(SPEAR320_DT, "ST SPEAr320 SoC with Flattened Device Tree") .map_io = spear320_map_io, - .init_irq = spear3xx_dt_init_irq, - .handle_irq = vic_handle_irq, + .init_irq = irqchip_init, .init_time = spear3xx_timer_init, .init_machine = spear320_dt_init, .restart = spear_restart, diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c index 89f4c58908e..b2ba516ca2d 100644 --- a/arch/arm/mach-spear3xx/spear3xx.c +++ b/arch/arm/mach-spear3xx/spear3xx.c @@ -15,11 +15,8 @@ #include <linux/amba/pl022.h> #include <linux/amba/pl08x.h> -#include <linux/irqchip/spear-shirq.h> -#include <linux/of_irq.h> #include <linux/io.h> #include <asm/hardware/pl080.h> -#include <asm/hardware/vic.h> #include <plat/pl080.h> #include <mach/generic.h> #include <mach/spear.h> @@ -115,16 +112,3 @@ void __init spear3xx_timer_init(void) spear_setup_of_timer(); } - -static const struct of_device_id vic_of_match[] __initconst = { - { .compatible = "arm,pl190-vic", .data = vic_of_init, }, - { .compatible = "st,spear300-shirq", .data = spear300_shirq_of_init, }, - { .compatible = "st,spear310-shirq", .data = spear310_shirq_of_init, }, - { .compatible = "st,spear320-shirq", .data = spear320_shirq_of_init, }, - { /* Sentinel */ } -}; - -void __init spear3xx_dt_init_irq(void) -{ - of_irq_init(vic_of_match); -} diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c index 1f85bc07c6c..b8bd33ca88b 100644 --- a/arch/arm/mach-spear6xx/spear6xx.c +++ b/arch/arm/mach-spear6xx/spear6xx.c @@ -16,12 +16,11 @@ #include <linux/amba/pl08x.h> #include <linux/clk.h> #include <linux/err.h> +#include <linux/irqchip.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_irq.h> #include <linux/of_platform.h> #include <asm/hardware/pl080.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/time.h> #include <asm/mach/map.h> @@ -421,20 +420,9 @@ static const char *spear600_dt_board_compat[] = { NULL }; -static const struct of_device_id vic_of_match[] __initconst = { - { .compatible = "arm,pl190-vic", .data = vic_of_init, }, - { /* Sentinel */ } -}; - -static void __init spear6xx_dt_init_irq(void) -{ - of_irq_init(vic_of_match); -} - DT_MACHINE_START(SPEAR600_DT, "ST SPEAr600 (Flattened Device Tree)") .map_io = spear6xx_map_io, - .init_irq = spear6xx_dt_init_irq, - .handle_irq = vic_handle_irq, + .init_irq = irqchip_init, .init_time = spear6xx_timer_init, .init_machine = spear600_dt_init, .restart = spear_restart, diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index 6980cfa646f..23afb732cb4 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -21,15 +21,16 @@ #include <linux/irqchip/sunxi.h> -#include <asm/hardware/vic.h> - #include <asm/mach/arch.h> #include <asm/mach/map.h> #include "sunxi.h" #define WATCHDOG_CTRL_REG 0x00 +#define WATCHDOG_CTRL_RESTART (1 << 0) #define WATCHDOG_MODE_REG 0x04 +#define WATCHDOG_MODE_ENABLE (1 << 0) +#define WATCHDOG_MODE_RESET_ENABLE (1 << 1) static void __iomem *wdt_base; @@ -50,11 +51,19 @@ static void sunxi_restart(char mode, const char *cmd) return; /* Enable timer and set reset bit in the watchdog */ - writel(3, wdt_base + WATCHDOG_MODE_REG); - writel(0xa57 << 1 | 1, wdt_base + WATCHDOG_CTRL_REG); - while(1) { + writel(WATCHDOG_MODE_ENABLE | WATCHDOG_MODE_RESET_ENABLE, + wdt_base + WATCHDOG_MODE_REG); + + /* + * Restart the watchdog. The default (and lowest) interval + * value for the watchdog is 0.5s. + */ + writel(WATCHDOG_CTRL_RESTART, wdt_base + WATCHDOG_CTRL_REG); + + while (1) { mdelay(5); - writel(3, wdt_base + WATCHDOG_MODE_REG); + writel(WATCHDOG_MODE_ENABLE | WATCHDOG_MODE_RESET_ENABLE, + wdt_base + WATCHDOG_MODE_REG); } } diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c index e1f87dd314e..d320f7ad735 100644 --- a/arch/arm/mach-tegra/board-dt-tegra20.c +++ b/arch/arm/mach-tegra/board-dt-tegra20.c @@ -26,7 +26,6 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_fdt.h> -#include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/pda_power.h> #include <linux/platform_data/tegra_usb.h> @@ -35,7 +34,6 @@ #include <linux/i2c-tegra.h> #include <linux/usb/tegra_usb_phy.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/time.h> @@ -203,7 +201,6 @@ DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)") .smp = smp_ops(tegra_smp_ops), .init_early = tegra20_init_early, .init_irq = tegra_dt_init_irq, - .handle_irq = gic_handle_irq, .init_time = clocksource_of_init, .init_machine = tegra_dt_init, .init_late = tegra_dt_init_late, diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c index cfe5fc02be7..97e1f67fc31 100644 --- a/arch/arm/mach-tegra/board-dt-tegra30.c +++ b/arch/arm/mach-tegra/board-dt-tegra30.c @@ -32,7 +32,6 @@ #include <linux/of_platform.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include "board.h" #include "clock.h" @@ -113,7 +112,6 @@ DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)") .map_io = tegra_map_common_io, .init_early = tegra30_init_early, .init_irq = tegra_dt_init_irq, - .handle_irq = gic_handle_irq, .init_time = clocksource_of_init, .init_machine = tegra30_dt_init, .init_late = tegra_init_late, diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 3efe80b2af2..8f0ffe97ffe 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -21,10 +21,9 @@ #include <linux/io.h> #include <linux/clk.h> #include <linux/delay.h> -#include <linux/of_irq.h> +#include <linux/irqchip.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <mach/powergate.h> @@ -58,15 +57,10 @@ u32 tegra_uart_config[4] = { }; #ifdef CONFIG_OF -static const struct of_device_id tegra_dt_irq_match[] __initconst = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init }, - { } -}; - void __init tegra_dt_init_irq(void) { tegra_init_irq(); - of_irq_init(tegra_dt_irq_match); + irqchip_init(); } #endif diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h index 485003f9b63..08386418196 100644 --- a/arch/arm/mach-tegra/include/mach/uncompress.h +++ b/arch/arm/mach-tegra/include/mach/uncompress.h @@ -172,8 +172,4 @@ static inline void arch_decomp_setup(void) uart[UART_LCR << DEBUG_UART_SHIFT] = 3; } -static inline void arch_decomp_wdog(void) -{ -} - #endif diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c index b7886f18351..2ff2128cb9d 100644 --- a/arch/arm/mach-tegra/irq.c +++ b/arch/arm/mach-tegra/irq.c @@ -22,8 +22,7 @@ #include <linux/irq.h> #include <linux/io.h> #include <linux/of.h> - -#include <asm/hardware/gic.h> +#include <linux/irqchip/arm-gic.h> #include "board.h" #include "iomap.h" diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index 68670304d9b..3c4a43c892a 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c @@ -18,9 +18,9 @@ #include <linux/jiffies.h> #include <linux/smp.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <asm/cacheflush.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/smp_scu.h> #include <asm/smp_plat.h> @@ -193,8 +193,6 @@ static void __init tegra_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init tegra_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 100a8b764da..12060ae4e8f 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -31,11 +31,11 @@ #include <linux/dma-mapping.h> #include <linux/platform_data/clk-u300.h> #include <linux/platform_data/pinctrl-coh901.h> +#include <linux/irqchip/arm-vic.h> #include <asm/types.h> #include <asm/setup.h> #include <asm/memory.h> -#include <asm/hardware/vic.h> #include <asm/mach/map.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -1779,7 +1779,6 @@ MACHINE_START(U300, "Ericsson AB U335 S335/B335 Prototype Board") .map_io = u300_map_io, .nr_irqs = 0, .init_irq = u300_init_irq, - .handle_irq = vic_handle_irq, .init_time = u300_timer_init, .init_machine = u300_init_machine, .restart = u300_restart, diff --git a/arch/arm/mach-u300/include/mach/uncompress.h b/arch/arm/mach-u300/include/mach/uncompress.h index 29acb718acf..783e7e60101 100644 --- a/arch/arm/mach-u300/include/mach/uncompress.h +++ b/arch/arm/mach-u300/include/mach/uncompress.h @@ -43,4 +43,3 @@ static inline void flush(void) * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c index 1f47d962e3a..7037d3687e9 100644 --- a/arch/arm/mach-ux500/board-mop500-uib.c +++ b/arch/arm/mach-ux500/board-mop500-uib.c @@ -13,6 +13,7 @@ #include <mach/hardware.h> #include "board-mop500.h" +#include "id.h" enum mop500_uib { STUIB, diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index e1dfa24b4fb..0e928d28175 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -40,7 +40,6 @@ #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <mach/hardware.h> #include <mach/setup.h> @@ -752,7 +751,6 @@ MACHINE_START(U8500, "ST-Ericsson MOP500 platform") .init_irq = ux500_init_irq, /* we re-use nomadik timer here */ .init_time = ux500_timer_init, - .handle_irq = gic_handle_irq, .init_machine = mop500_init_machine, .init_late = ux500_init_late, MACHINE_END @@ -762,7 +760,6 @@ MACHINE_START(U8520, "ST-Ericsson U8520 Platform HREFP520") .map_io = u8500_map_io, .init_irq = ux500_init_irq, .init_time = ux500_timer_init, - .handle_irq = gic_handle_irq, .init_machine = mop500_init_machine, .init_late = ux500_init_late, MACHINE_END @@ -773,7 +770,6 @@ MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+") .map_io = u8500_map_io, .init_irq = ux500_init_irq, .init_time = ux500_timer_init, - .handle_irq = gic_handle_irq, .init_machine = hrefv60_init_machine, .init_late = ux500_init_late, MACHINE_END @@ -785,7 +781,6 @@ MACHINE_START(SNOWBALL, "Calao Systems Snowball platform") .init_irq = ux500_init_irq, /* we re-use nomadik timer here */ .init_time = ux500_timer_init, - .handle_irq = gic_handle_irq, .init_machine = snowball_init_machine, .init_late = NULL, MACHINE_END diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c index 75d5b512a3d..1c1609da76c 100644 --- a/arch/arm/mach-ux500/cache-l2x0.c +++ b/arch/arm/mach-ux500/cache-l2x0.c @@ -10,7 +10,8 @@ #include <asm/cacheflush.h> #include <asm/hardware/cache-l2x0.h> #include <mach/hardware.h> -#include <mach/id.h> + +#include "id.h" static void __iomem *l2x0_base; diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index c1fb38b5ed9..d614d7150dc 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -27,7 +27,6 @@ #include <asm/pmu.h> #include <asm/mach/map.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <mach/hardware.h> #include <mach/setup.h> @@ -37,7 +36,9 @@ #include "devices-db8500.h" #include "ste-dma40-db8500.h" + #include "board-mop500.h" +#include "id.h" /* minimum static i/o mapping required to boot U8500 platforms */ static struct map_desc u8500_uart_io_desc[] __initdata = { @@ -342,7 +343,6 @@ DT_MACHINE_START(U8500_DT, "ST-Ericsson Ux5x0 platform (Device Tree Support)") .init_irq = ux500_init_irq, /* we re-use nomadik timer here */ .init_time = ux500_timer_init, - .handle_irq = gic_handle_irq, .init_machine = u8500_init_machine, .init_late = NULL, .dt_compat = stericsson_dt_platform_compat, diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index 721e7b4275f..506c5b2d0fa 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -17,9 +17,10 @@ #include <linux/of.h> #include <linux/of_irq.h> #include <linux/irq.h> +#include <linux/irqchip.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/clk-ux500.h> -#include <asm/hardware/gic.h> #include <asm/mach/map.h> #include <mach/hardware.h> @@ -27,6 +28,7 @@ #include <mach/devices.h> #include "board-mop500.h" +#include "id.h" void __iomem *_PRCMU_BASE; @@ -42,11 +44,6 @@ void __iomem *_PRCMU_BASE; * This feels fragile because it depends on the gpio device getting probed * _before_ any device uses the gpio interrupts. */ -static const struct of_device_id ux500_dt_irq_match[] = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - {}, -}; - void __init ux500_init_irq(void) { void __iomem *dist_base; @@ -62,7 +59,7 @@ void __init ux500_init_irq(void) #ifdef CONFIG_OF if (of_have_populated_dt()) - of_irq_init(ux500_dt_irq_match); + irqchip_init(); else #endif gic_init(0, 29, dist_base, cpu_base); diff --git a/arch/arm/mach-ux500/id.c b/arch/arm/mach-ux500/id.c index d1579920139..9f951842e1e 100644 --- a/arch/arm/mach-ux500/id.c +++ b/arch/arm/mach-ux500/id.c @@ -17,6 +17,8 @@ #include <mach/hardware.h> #include <mach/setup.h> +#include "id.h" + struct dbx500_asic_id dbx500_id; static unsigned int ux500_read_asicid(phys_addr_t addr) diff --git a/arch/arm/mach-ux500/include/mach/id.h b/arch/arm/mach-ux500/id.h index 9c42642ab16..bcc58a8cccb 100644 --- a/arch/arm/mach-ux500/include/mach/id.h +++ b/arch/arm/mach-ux500/id.h @@ -61,9 +61,14 @@ static inline bool __attribute_const__ cpu_is_u8540(void) return dbx500_partnumber() == 0x8540; } +static inline bool __attribute_const__ cpu_is_u8580(void) +{ + return dbx500_partnumber() == 0x8580; +} + static inline bool cpu_is_ux540_family(void) { - return cpu_is_u9540() || cpu_is_u8540(); + return cpu_is_u9540() || cpu_is_u8540() || cpu_is_u8580(); } /* @@ -115,6 +120,20 @@ static inline bool cpu_is_u8500v20_or_later(void) return (cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11()); } +/* + * 8540 revisions + */ + +static inline bool __attribute_const__ cpu_is_u8540v10(void) +{ + return cpu_is_u8540() && dbx500_revision() == 0xA0; +} + +static inline bool __attribute_const__ cpu_is_u8580v10(void) +{ + return cpu_is_u8580() && dbx500_revision() == 0xA0; +} + static inline bool ux500_is_svp(void) { return false; diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h index 28d16e744bf..5201ddace50 100644 --- a/arch/arm/mach-ux500/include/mach/hardware.h +++ b/arch/arm/mach-ux500/include/mach/hardware.h @@ -39,7 +39,6 @@ #ifndef __ASSEMBLY__ -#include <mach/id.h> extern void __iomem *_PRCMU_BASE; #define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) diff --git a/arch/arm/mach-ux500/include/mach/uncompress.h b/arch/arm/mach-ux500/include/mach/uncompress.h index d60ecd1753f..36969d52e53 100644 --- a/arch/arm/mach-ux500/include/mach/uncompress.h +++ b/arch/arm/mach-ux500/include/mach/uncompress.h @@ -54,6 +54,4 @@ static inline void arch_decomp_setup(void) ux500_uart_base = (void __iomem *)U8500_UART2_BASE; } -#define arch_decomp_wdog() /* nothing to do here */ - #endif /* __ASM_ARCH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index 3db7782f3af..18f7af339dc 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -16,14 +16,17 @@ #include <linux/device.h> #include <linux/smp.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <asm/cacheflush.h> -#include <asm/hardware/gic.h> #include <asm/smp_plat.h> #include <asm/smp_scu.h> + #include <mach/hardware.h> #include <mach/setup.h> +#include "id.h" + /* This is called from headsmp.S to wakeup the secondary core */ extern void u8500_secondary_startup(void); @@ -91,7 +94,7 @@ static int __cpuinit ux500_boot_secondary(unsigned int cpu, struct task_struct * */ write_pen_release(cpu_logical_map(cpu)); - smp_send_reschedule(cpu); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { @@ -155,8 +158,6 @@ static void __init ux500_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init ux500_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c index aa2a78acb59..a6af0b8732b 100644 --- a/arch/arm/mach-ux500/timer.c +++ b/arch/arm/mach-ux500/timer.c @@ -17,6 +17,8 @@ #include <mach/hardware.h> #include <mach/irqs.h> +#include "id.h" + #ifdef CONFIG_HAVE_ARM_TWD static DEFINE_TWD_LOCAL_TIMER(u8500_twd_local_timer, U8500_TWD_BASE, IRQ_LOCALTIMER); diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index d5ddc0c77f5..a42b89083eb 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -32,6 +32,7 @@ #include <linux/amba/mmci.h> #include <linux/amba/pl022.h> #include <linux/io.h> +#include <linux/irqchip/arm-vic.h> #include <linux/irqchip/versatile-fpga.h> #include <linux/gfp.h> #include <linux/clkdev.h> @@ -40,7 +41,6 @@ #include <asm/irq.h> #include <asm/hardware/arm_timer.h> #include <asm/hardware/icst.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> diff --git a/arch/arm/mach-versatile/include/mach/uncompress.h b/arch/arm/mach-versatile/include/mach/uncompress.h index 3dd0048afb3..986e3d303f3 100644 --- a/arch/arm/mach-versatile/include/mach/uncompress.h +++ b/arch/arm/mach-versatile/include/mach/uncompress.h @@ -43,4 +43,3 @@ static inline void flush(void) * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-versatile/versatile_ab.c b/arch/arm/mach-versatile/versatile_ab.c index 187c1da2c4b..1caef109379 100644 --- a/arch/arm/mach-versatile/versatile_ab.c +++ b/arch/arm/mach-versatile/versatile_ab.c @@ -26,7 +26,6 @@ #include <mach/hardware.h> #include <asm/irq.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -39,7 +38,6 @@ MACHINE_START(VERSATILE_AB, "ARM-Versatile AB") .map_io = versatile_map_io, .init_early = versatile_init_early, .init_irq = versatile_init_irq, - .handle_irq = vic_handle_irq, .init_time = versatile_timer_init, .init_machine = versatile_init, .restart = versatile_restart, diff --git a/arch/arm/mach-versatile/versatile_dt.c b/arch/arm/mach-versatile/versatile_dt.c index ccf9f8a9206..2558f2e957c 100644 --- a/arch/arm/mach-versatile/versatile_dt.c +++ b/arch/arm/mach-versatile/versatile_dt.c @@ -24,7 +24,6 @@ #include <linux/init.h> #include <linux/of_irq.h> #include <linux/of_platform.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -46,7 +45,6 @@ DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)") .map_io = versatile_map_io, .init_early = versatile_init_early, .init_irq = versatile_init_irq, - .handle_irq = vic_handle_irq, .init_time = versatile_timer_init, .init_machine = versatile_dt_init, .dt_compat = versatile_dt_match, diff --git a/arch/arm/mach-versatile/versatile_pb.c b/arch/arm/mach-versatile/versatile_pb.c index 1cabc0aa569..611d140c869 100644 --- a/arch/arm/mach-versatile/versatile_pb.c +++ b/arch/arm/mach-versatile/versatile_pb.c @@ -27,7 +27,6 @@ #include <linux/io.h> #include <mach/hardware.h> -#include <asm/hardware/vic.h> #include <asm/irq.h> #include <asm/mach-types.h> @@ -107,7 +106,6 @@ MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") .map_io = versatile_map_io, .init_early = versatile_init_early, .init_irq = versatile_init_irq, - .handle_irq = vic_handle_irq, .init_time = versatile_timer_init, .init_machine = versatile_pb_init, .restart = versatile_restart, diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 60838ddb856..6f34497a424 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -10,10 +10,10 @@ #include <linux/amba/clcd.h> #include <linux/clkdev.h> #include <linux/vexpress.h> +#include <linux/irqchip/arm-gic.h> #include <asm/hardware/arm_timer.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <asm/smp_scu.h> #include <asm/smp_twd.h> @@ -182,8 +182,6 @@ static void __init ct_ca9x4_init_cpu_map(void) for (i = 0; i < ncores; ++i) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init ct_ca9x4_smp_enable(unsigned int max_cpus) diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c index c5d70de9bb4..dc1ace55d55 100644 --- a/arch/arm/mach-vexpress/platsmp.c +++ b/arch/arm/mach-vexpress/platsmp.c @@ -16,7 +16,6 @@ #include <linux/vexpress.h> #include <asm/smp_scu.h> -#include <asm/hardware/gic.h> #include <asm/mach/map.h> #include <mach/motherboard.h> @@ -128,8 +127,6 @@ static void __init vexpress_dt_smp_init_cpus(void) for (i = 0; i < ncores; ++i) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init vexpress_dt_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 08bd548ef14..915683cb67d 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -7,6 +7,7 @@ #include <linux/io.h> #include <linux/smp.h> #include <linux/init.h> +#include <linux/irqchip.h> #include <linux/of_address.h> #include <linux/of_fdt.h> #include <linux/of_irq.h> @@ -30,7 +31,6 @@ #include <asm/mach/time.h> #include <asm/hardware/arm_timer.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <asm/hardware/timer-sp.h> #include <mach/ct-ca9x4.h> @@ -373,7 +373,6 @@ MACHINE_START(VEXPRESS, "ARM-Versatile Express") .init_early = v2m_init_early, .init_irq = v2m_init_irq, .init_time = v2m_timer_init, - .handle_irq = gic_handle_irq, .init_machine = v2m_init, .restart = vexpress_restart, MACHINE_END @@ -430,16 +429,6 @@ void __init v2m_dt_init_early(void) } } -static struct of_device_id vexpress_irq_match[] __initdata = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - {} -}; - -static void __init v2m_dt_init_irq(void) -{ - of_irq_init(vexpress_irq_match); -} - static void __init v2m_dt_timer_init(void) { struct device_node *node = NULL; @@ -489,9 +478,8 @@ DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express") .smp = smp_ops(vexpress_smp_ops), .map_io = v2m_dt_map_io, .init_early = v2m_dt_init_early, - .init_irq = v2m_dt_init_irq, + .init_irq = irqchip_init, .init_time = v2m_dt_timer_init, .init_machine = v2m_dt_init, - .handle_irq = gic_handle_irq, .restart = vexpress_restart, MACHINE_END diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig index 2ed0b7d95db..9adcb9e76f5 100644 --- a/arch/arm/mach-vt8500/Kconfig +++ b/arch/arm/mach-vt8500/Kconfig @@ -4,9 +4,10 @@ config ARCH_VT8500 select ARCH_HAS_CPUFREQ select ARCH_REQUIRE_GPIOLIB select CLKDEV_LOOKUP + select CLKSRC_OF select CPU_ARM926T select GENERIC_CLOCKEVENTS - select GENERIC_GPIO select HAVE_CLK + select VT8500_TIMER help Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip. diff --git a/arch/arm/mach-vt8500/Makefile b/arch/arm/mach-vt8500/Makefile index e035251cda4..92ceb2436b6 100644 --- a/arch/arm/mach-vt8500/Makefile +++ b/arch/arm/mach-vt8500/Makefile @@ -1 +1 @@ -obj-$(CONFIG_ARCH_VT8500) += irq.o timer.o vt8500.o +obj-$(CONFIG_ARCH_VT8500) += irq.o vt8500.o diff --git a/arch/arm/mach-vt8500/common.h b/arch/arm/mach-vt8500/common.h index 6f2b843115d..77611a6968d 100644 --- a/arch/arm/mach-vt8500/common.h +++ b/arch/arm/mach-vt8500/common.h @@ -18,7 +18,6 @@ #include <linux/of.h> -void __init vt8500_timer_init(void); int __init vt8500_irq_init(struct device_node *node, struct device_node *parent); diff --git a/arch/arm/mach-vt8500/include/mach/uncompress.h b/arch/arm/mach-vt8500/include/mach/uncompress.h index e6e81fdaf10..5b4f19ecb4c 100644 --- a/arch/arm/mach-vt8500/include/mach/uncompress.h +++ b/arch/arm/mach-vt8500/include/mach/uncompress.h @@ -34,4 +34,3 @@ static void flush(void) * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c index d5b9c6689c9..fe99b709f11 100644 --- a/arch/arm/mach-vt8500/vt8500.c +++ b/arch/arm/mach-vt8500/vt8500.c @@ -18,6 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/clocksource.h> #include <linux/io.h> #include <linux/pm.h> @@ -185,8 +186,8 @@ DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)") .dt_compat = vt8500_dt_compat, .map_io = vt8500_map_io, .init_irq = vt8500_init_irq, - .init_time = vt8500_timer_init, .init_machine = vt8500_init, + .init_time = clocksource_of_init, .restart = vt8500_restart, .handle_irq = vt8500_handle_irq, MACHINE_END diff --git a/arch/arm/mach-w90x900/include/mach/uncompress.h b/arch/arm/mach-w90x900/include/mach/uncompress.h index 03130212ace..4b7c324ff66 100644 --- a/arch/arm/mach-w90x900/include/mach/uncompress.h +++ b/arch/arm/mach-w90x900/include/mach/uncompress.h @@ -24,8 +24,6 @@ #include <mach/map.h> #include <linux/serial_reg.h> -#define arch_decomp_wdog() - #define TX_DONE (UART_LSR_TEMT | UART_LSR_THRE) static volatile u32 * const uart_base = (u32 *)UART0_PA; diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c index d9c3d6b801c..30fbca84457 100644 --- a/arch/arm/mach-w90x900/time.c +++ b/arch/arm/mach-w90x900/time.c @@ -91,7 +91,6 @@ static int nuc900_clockevent_setnextevent(unsigned long evt, static struct clock_event_device nuc900_clockevent_device = { .name = "nuc900-timer0", - .shift = 32, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_mode = nuc900_clockevent_setmode, .set_next_event = nuc900_clockevent_setnextevent, @@ -133,15 +132,10 @@ static void __init nuc900_clockevents_init(void) __raw_writel(RESETINT, REG_TISR); setup_irq(IRQ_TIMER0, &nuc900_timer0_irq); - nuc900_clockevent_device.mult = div_sc(rate, NSEC_PER_SEC, - nuc900_clockevent_device.shift); - nuc900_clockevent_device.max_delta_ns = clockevent_delta2ns(0xffffffff, - &nuc900_clockevent_device); - nuc900_clockevent_device.min_delta_ns = clockevent_delta2ns(0xf, - &nuc900_clockevent_device); nuc900_clockevent_device.cpumask = cpumask_of(0); - clockevents_register_device(&nuc900_clockevent_device); + clockevents_config_and_register(&nuc900_clockevent_device, rate, + 0xf, 0xffffffff); } static void __init nuc900_clocksource_init(void) diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 2ae4bce652b..5c898321818 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -24,6 +24,7 @@ #include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/of.h> +#include <linux/irqchip.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -31,7 +32,6 @@ #include <asm/mach-types.h> #include <asm/page.h> #include <asm/pgtable.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include "common.h" @@ -55,19 +55,6 @@ static void __init xilinx_init_machine(void) of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL); } -static struct of_device_id irq_match[] __initdata = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - { } -}; - -/** - * xilinx_irq_init() - Interrupt controller initialization for the GIC. - */ -static void __init xilinx_irq_init(void) -{ - of_irq_init(irq_match); -} - #define SCU_PERIPH_PHYS 0xF8F00000 #define SCU_PERIPH_SIZE SZ_8K #define SCU_PERIPH_VIRT (VMALLOC_END - SCU_PERIPH_SIZE) @@ -90,7 +77,7 @@ static void __init xilinx_zynq_timer_init(void) xilinx_zynq_clocks_init(slcr); - xttcpss_timer_init(); + xttcps_timer_init(); } /** @@ -110,8 +97,7 @@ static const char *xilinx_dt_match[] = { MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform") .map_io = xilinx_map_io, - .init_irq = xilinx_irq_init, - .handle_irq = gic_handle_irq, + .init_irq = irqchip_init, .init_machine = xilinx_init_machine, .init_time = xilinx_zynq_timer_init, .dt_compat = xilinx_dt_match, diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h index 954b91c13c9..8b4dbbaa01c 100644 --- a/arch/arm/mach-zynq/common.h +++ b/arch/arm/mach-zynq/common.h @@ -17,6 +17,6 @@ #ifndef __MACH_ZYNQ_COMMON_H__ #define __MACH_ZYNQ_COMMON_H__ -void __init xttcpss_timer_init(void); +void __init xttcps_timer_init(void); #endif diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c index de3df283da7..f9fbc9c1e7a 100644 --- a/arch/arm/mach-zynq/timer.c +++ b/arch/arm/mach-zynq/timer.c @@ -15,39 +15,29 @@ * GNU General Public License for more details. */ -#include <linux/kernel.h> -#include <linux/init.h> #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/types.h> -#include <linux/clocksource.h> #include <linux/clockchips.h> -#include <linux/io.h> -#include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/slab.h> #include <linux/clk-provider.h> - #include "common.h" /* * Timer Register Offset Definitions of Timer 1, Increment base address by 4 * and use same offsets for Timer 2 */ -#define XTTCPSS_CLK_CNTRL_OFFSET 0x00 /* Clock Control Reg, RW */ -#define XTTCPSS_CNT_CNTRL_OFFSET 0x0C /* Counter Control Reg, RW */ -#define XTTCPSS_COUNT_VAL_OFFSET 0x18 /* Counter Value Reg, RO */ -#define XTTCPSS_INTR_VAL_OFFSET 0x24 /* Interval Count Reg, RW */ -#define XTTCPSS_MATCH_1_OFFSET 0x30 /* Match 1 Value Reg, RW */ -#define XTTCPSS_MATCH_2_OFFSET 0x3C /* Match 2 Value Reg, RW */ -#define XTTCPSS_MATCH_3_OFFSET 0x48 /* Match 3 Value Reg, RW */ -#define XTTCPSS_ISR_OFFSET 0x54 /* Interrupt Status Reg, RO */ -#define XTTCPSS_IER_OFFSET 0x60 /* Interrupt Enable Reg, RW */ - -#define XTTCPSS_CNT_CNTRL_DISABLE_MASK 0x1 - -/* Setup the timers to use pre-scaling, using a fixed value for now that will +#define XTTCPS_CLK_CNTRL_OFFSET 0x00 /* Clock Control Reg, RW */ +#define XTTCPS_CNT_CNTRL_OFFSET 0x0C /* Counter Control Reg, RW */ +#define XTTCPS_COUNT_VAL_OFFSET 0x18 /* Counter Value Reg, RO */ +#define XTTCPS_INTR_VAL_OFFSET 0x24 /* Interval Count Reg, RW */ +#define XTTCPS_ISR_OFFSET 0x54 /* Interrupt Status Reg, RO */ +#define XTTCPS_IER_OFFSET 0x60 /* Interrupt Enable Reg, RW */ + +#define XTTCPS_CNT_CNTRL_DISABLE_MASK 0x1 + +/* + * Setup the timers to use pre-scaling, using a fixed value for now that will * work across most input frequency, but it may need to be more dynamic */ #define PRESCALE_EXPONENT 11 /* 2 ^ PRESCALE_EXPONENT = PRESCALE */ @@ -57,72 +47,73 @@ #define CNT_CNTRL_RESET (1<<4) /** - * struct xttcpss_timer - This definition defines local timer structure + * struct xttcps_timer - This definition defines local timer structure * * @base_addr: Base address of timer **/ -struct xttcpss_timer { +struct xttcps_timer { void __iomem *base_addr; }; -struct xttcpss_timer_clocksource { - struct xttcpss_timer xttc; +struct xttcps_timer_clocksource { + struct xttcps_timer xttc; struct clocksource cs; }; -#define to_xttcpss_timer_clksrc(x) \ - container_of(x, struct xttcpss_timer_clocksource, cs) +#define to_xttcps_timer_clksrc(x) \ + container_of(x, struct xttcps_timer_clocksource, cs) -struct xttcpss_timer_clockevent { - struct xttcpss_timer xttc; +struct xttcps_timer_clockevent { + struct xttcps_timer xttc; struct clock_event_device ce; struct clk *clk; }; -#define to_xttcpss_timer_clkevent(x) \ - container_of(x, struct xttcpss_timer_clockevent, ce) +#define to_xttcps_timer_clkevent(x) \ + container_of(x, struct xttcps_timer_clockevent, ce) /** - * xttcpss_set_interval - Set the timer interval value + * xttcps_set_interval - Set the timer interval value * * @timer: Pointer to the timer instance * @cycles: Timer interval ticks **/ -static void xttcpss_set_interval(struct xttcpss_timer *timer, +static void xttcps_set_interval(struct xttcps_timer *timer, unsigned long cycles) { u32 ctrl_reg; /* Disable the counter, set the counter value and re-enable counter */ - ctrl_reg = __raw_readl(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET); - ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK; - __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET); + ctrl_reg = __raw_readl(timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET); + ctrl_reg |= XTTCPS_CNT_CNTRL_DISABLE_MASK; + __raw_writel(ctrl_reg, timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET); - __raw_writel(cycles, timer->base_addr + XTTCPSS_INTR_VAL_OFFSET); + __raw_writel(cycles, timer->base_addr + XTTCPS_INTR_VAL_OFFSET); - /* Reset the counter (0x10) so that it starts from 0, one-shot - mode makes this needed for timing to be right. */ + /* + * Reset the counter (0x10) so that it starts from 0, one-shot + * mode makes this needed for timing to be right. + */ ctrl_reg |= CNT_CNTRL_RESET; - ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK; - __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET); + ctrl_reg &= ~XTTCPS_CNT_CNTRL_DISABLE_MASK; + __raw_writel(ctrl_reg, timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET); } /** - * xttcpss_clock_event_interrupt - Clock event timer interrupt handler + * xttcps_clock_event_interrupt - Clock event timer interrupt handler * * @irq: IRQ number of the Timer - * @dev_id: void pointer to the xttcpss_timer instance + * @dev_id: void pointer to the xttcps_timer instance * * returns: Always IRQ_HANDLED - success **/ -static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id) +static irqreturn_t xttcps_clock_event_interrupt(int irq, void *dev_id) { - struct xttcpss_timer_clockevent *xttce = dev_id; - struct xttcpss_timer *timer = &xttce->xttc; + struct xttcps_timer_clockevent *xttce = dev_id; + struct xttcps_timer *timer = &xttce->xttc; /* Acknowledge the interrupt and call event handler */ - __raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET), - timer->base_addr + XTTCPSS_ISR_OFFSET); + __raw_readl(timer->base_addr + XTTCPS_ISR_OFFSET); xttce->ce.event_handler(&xttce->ce); @@ -136,46 +127,46 @@ static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id) **/ static cycle_t __xttc_clocksource_read(struct clocksource *cs) { - struct xttcpss_timer *timer = &to_xttcpss_timer_clksrc(cs)->xttc; + struct xttcps_timer *timer = &to_xttcps_timer_clksrc(cs)->xttc; return (cycle_t)__raw_readl(timer->base_addr + - XTTCPSS_COUNT_VAL_OFFSET); + XTTCPS_COUNT_VAL_OFFSET); } /** - * xttcpss_set_next_event - Sets the time interval for next event + * xttcps_set_next_event - Sets the time interval for next event * * @cycles: Timer interval ticks * @evt: Address of clock event instance * * returns: Always 0 - success **/ -static int xttcpss_set_next_event(unsigned long cycles, +static int xttcps_set_next_event(unsigned long cycles, struct clock_event_device *evt) { - struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt); - struct xttcpss_timer *timer = &xttce->xttc; + struct xttcps_timer_clockevent *xttce = to_xttcps_timer_clkevent(evt); + struct xttcps_timer *timer = &xttce->xttc; - xttcpss_set_interval(timer, cycles); + xttcps_set_interval(timer, cycles); return 0; } /** - * xttcpss_set_mode - Sets the mode of timer + * xttcps_set_mode - Sets the mode of timer * * @mode: Mode to be set * @evt: Address of clock event instance **/ -static void xttcpss_set_mode(enum clock_event_mode mode, +static void xttcps_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { - struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt); - struct xttcpss_timer *timer = &xttce->xttc; + struct xttcps_timer_clockevent *xttce = to_xttcps_timer_clkevent(evt); + struct xttcps_timer *timer = &xttce->xttc; u32 ctrl_reg; switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - xttcpss_set_interval(timer, + xttcps_set_interval(timer, DIV_ROUND_CLOSEST(clk_get_rate(xttce->clk), PRESCALE * HZ)); break; @@ -183,17 +174,17 @@ static void xttcpss_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: ctrl_reg = __raw_readl(timer->base_addr + - XTTCPSS_CNT_CNTRL_OFFSET); - ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK; + XTTCPS_CNT_CNTRL_OFFSET); + ctrl_reg |= XTTCPS_CNT_CNTRL_DISABLE_MASK; __raw_writel(ctrl_reg, - timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET); + timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET); break; case CLOCK_EVT_MODE_RESUME: ctrl_reg = __raw_readl(timer->base_addr + - XTTCPSS_CNT_CNTRL_OFFSET); - ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK; + XTTCPS_CNT_CNTRL_OFFSET); + ctrl_reg &= ~XTTCPS_CNT_CNTRL_DISABLE_MASK; __raw_writel(ctrl_reg, - timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET); + timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET); break; } } @@ -201,7 +192,7 @@ static void xttcpss_set_mode(enum clock_event_mode mode, static void __init zynq_ttc_setup_clocksource(struct device_node *np, void __iomem *base) { - struct xttcpss_timer_clocksource *ttccs; + struct xttcps_timer_clocksource *ttccs; struct clk *clk; int err; u32 reg; @@ -230,11 +221,11 @@ static void __init zynq_ttc_setup_clocksource(struct device_node *np, ttccs->cs.mask = CLOCKSOURCE_MASK(16); ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; - __raw_writel(0x0, ttccs->xttc.base_addr + XTTCPSS_IER_OFFSET); + __raw_writel(0x0, ttccs->xttc.base_addr + XTTCPS_IER_OFFSET); __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, - ttccs->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET); + ttccs->xttc.base_addr + XTTCPS_CLK_CNTRL_OFFSET); __raw_writel(CNT_CNTRL_RESET, - ttccs->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET); + ttccs->xttc.base_addr + XTTCPS_CNT_CNTRL_OFFSET); err = clocksource_register_hz(&ttccs->cs, clk_get_rate(clk) / PRESCALE); if (WARN_ON(err)) @@ -244,7 +235,7 @@ static void __init zynq_ttc_setup_clocksource(struct device_node *np, static void __init zynq_ttc_setup_clockevent(struct device_node *np, void __iomem *base) { - struct xttcpss_timer_clockevent *ttcce; + struct xttcps_timer_clockevent *ttcce; int err, irq; u32 reg; @@ -272,17 +263,18 @@ static void __init zynq_ttc_setup_clockevent(struct device_node *np, ttcce->ce.name = np->name; ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; - ttcce->ce.set_next_event = xttcpss_set_next_event; - ttcce->ce.set_mode = xttcpss_set_mode; + ttcce->ce.set_next_event = xttcps_set_next_event; + ttcce->ce.set_mode = xttcps_set_mode; ttcce->ce.rating = 200; ttcce->ce.irq = irq; + ttcce->ce.cpumask = cpu_possible_mask; - __raw_writel(0x23, ttcce->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET); + __raw_writel(0x23, ttcce->xttc.base_addr + XTTCPS_CNT_CNTRL_OFFSET); __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, - ttcce->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET); - __raw_writel(0x1, ttcce->xttc.base_addr + XTTCPSS_IER_OFFSET); + ttcce->xttc.base_addr + XTTCPS_CLK_CNTRL_OFFSET); + __raw_writel(0x1, ttcce->xttc.base_addr + XTTCPS_IER_OFFSET); - err = request_irq(irq, xttcpss_clock_event_interrupt, IRQF_TIMER, + err = request_irq(irq, xttcps_clock_event_interrupt, IRQF_TIMER, np->name, ttcce); if (WARN_ON(err)) return; @@ -301,12 +293,12 @@ static const __initconst struct of_device_id zynq_ttc_match[] = { }; /** - * xttcpss_timer_init - Initialize the timer + * xttcps_timer_init - Initialize the timer * * Initializes the timer hardware and register the clock source and clock event * timers with Linux kernal timer framework **/ -void __init xttcpss_timer_init(void) +void __init xttcps_timer_init(void) { struct device_node *np; diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 6b2fb87c869..076c26d4386 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -774,25 +774,27 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset, size_t size, enum dma_data_direction dir, void (*op)(const void *, size_t, int)) { + unsigned long pfn; + size_t left = size; + + pfn = page_to_pfn(page) + offset / PAGE_SIZE; + offset %= PAGE_SIZE; + /* * A single sg entry may refer to multiple physically contiguous * pages. But we still need to process highmem pages individually. * If highmem is not configured then the bulk of this loop gets * optimized out. */ - size_t left = size; do { size_t len = left; void *vaddr; + page = pfn_to_page(pfn); + if (PageHighMem(page)) { - if (len + offset > PAGE_SIZE) { - if (offset >= PAGE_SIZE) { - page += offset / PAGE_SIZE; - offset %= PAGE_SIZE; - } + if (len + offset > PAGE_SIZE) len = PAGE_SIZE - offset; - } vaddr = kmap_high_get(page); if (vaddr) { vaddr += offset; @@ -809,7 +811,7 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset, op(vaddr, len, dir); } offset = 0; - page++; + pfn++; left -= len; } while (left); } diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 9f0610243bd..ce328c7f5c9 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -283,7 +283,7 @@ static struct mem_type mem_types[] = { }, [MT_MEMORY_SO] = { .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | - L_PTE_MT_UNCACHED, + L_PTE_MT_UNCACHED | L_PTE_XN, .prot_l1 = PMD_TYPE_TABLE, .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_S | PMD_SECT_UNCACHED | PMD_SECT_XN, diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c index cbfbbe46178..837a2d52e9d 100644 --- a/arch/arm/plat-iop/time.c +++ b/arch/arm/plat-iop/time.c @@ -156,14 +156,9 @@ void __init iop_init_time(unsigned long tick_rate) write_tmr0(timer_ctl & ~IOP_TMR_EN); write_tisr(1); setup_irq(IRQ_IOP_TIMER0, &iop_timer_irq); - clockevents_calc_mult_shift(&iop_clockevent, - tick_rate, IOP_MIN_RANGE); - iop_clockevent.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &iop_clockevent); - iop_clockevent.min_delta_ns = - clockevent_delta2ns(0xf, &iop_clockevent); iop_clockevent.cpumask = cpumask_of(0); - clockevents_register_device(&iop_clockevent); + clockevents_config_and_register(&iop_clockevent, tick_rate, + 0xf, 0xfffffffe); /* * Set up free-running clocksource timer 1. diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c index 0f4fa863dd5..5d5ac0f0542 100644 --- a/arch/arm/plat-orion/time.c +++ b/arch/arm/plat-orion/time.c @@ -156,7 +156,6 @@ orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) static struct clock_event_device orion_clkevt = { .name = "orion_tick", .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, - .shift = 32, .rating = 300, .set_next_event = orion_clkevt_next_event, .set_mode = orion_clkevt_mode, @@ -221,9 +220,6 @@ orion_time_init(void __iomem *_bridge_base, u32 _bridge_timer1_clr_mask, * Setup clockevent timer (interrupt-driven). */ setup_irq(irq, &orion_timer_irq); - orion_clkevt.mult = div_sc(tclk, NSEC_PER_SEC, orion_clkevt.shift); - orion_clkevt.max_delta_ns = clockevent_delta2ns(0xfffffffe, &orion_clkevt); - orion_clkevt.min_delta_ns = clockevent_delta2ns(1, &orion_clkevt); orion_clkevt.cpumask = cpumask_of(0); - clockevents_register_device(&orion_clkevt); + clockevents_config_and_register(&orion_clkevt, tclk, 1, 0xfffffffe); } diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h index f7a3ea2c498..cf5aae5b097 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-core.h +++ b/arch/arm/plat-samsung/include/plat/gpio-core.h @@ -106,7 +106,18 @@ static inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int chi #else /* machine specific code should provide samsung_gpiolib_getchip */ -#include <mach/gpio-track.h> +extern struct samsung_gpio_chip s3c24xx_gpios[]; + +static inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int pin) +{ + struct samsung_gpio_chip *chip; + + if (pin > S3C_GPIO_END) + return NULL; + + chip = &s3c24xx_gpios[pin/32]; + return ((pin - chip->chip.base) < chip->chip.ngpio) ? chip : NULL; +} static inline void s3c_gpiolib_track(struct samsung_gpio_chip *chip) { } #endif diff --git a/arch/arm/plat-samsung/include/plat/gpio-fns.h b/arch/arm/plat-samsung/include/plat/gpio-fns.h deleted file mode 100644 index d1ecef0e38e..00000000000 --- a/arch/arm/plat-samsung/include/plat/gpio-fns.h +++ /dev/null @@ -1 +0,0 @@ -#include <plat/gpio-cfg.h> diff --git a/arch/arm/plat-samsung/include/plat/uncompress.h b/arch/arm/plat-samsung/include/plat/uncompress.h index 7e068d182c3..438b24846e7 100644 --- a/arch/arm/plat-samsung/include/plat/uncompress.h +++ b/arch/arm/plat-samsung/include/plat/uncompress.h @@ -97,33 +97,6 @@ static inline void flush(void) *((volatile unsigned int __force *)(ad)) = (d); \ } while (0) -/* CONFIG_S3C_BOOT_WATCHDOG - * - * Simple boot-time watchdog setup, to reboot the system if there is - * any problem with the boot process -*/ - -#ifdef CONFIG_S3C_BOOT_WATCHDOG - -#define WDOG_COUNT (0xff00) - -static inline void arch_decomp_wdog(void) -{ - __raw_writel(WDOG_COUNT, S3C2410_WTCNT); -} - -static void arch_decomp_wdog_start(void) -{ - __raw_writel(WDOG_COUNT, S3C2410_WTDAT); - __raw_writel(WDOG_COUNT, S3C2410_WTCNT); - __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x80), S3C2410_WTCON); -} - -#else -#define arch_decomp_wdog_start() -#define arch_decomp_wdog() -#endif - #ifdef CONFIG_S3C_BOOT_ERROR_RESET static void arch_decomp_error(const char *x) @@ -173,7 +146,6 @@ arch_decomp_setup(void) */ arch_detect_cpu(); - arch_decomp_wdog_start(); /* Enable the UART FIFOs if they where not enabled and our * configuration says we should turn them on. diff --git a/arch/arm/plat-samsung/s5p-irq-eint.c b/arch/arm/plat-samsung/s5p-irq-eint.c index 33bd3f3d20f..faa65160278 100644 --- a/arch/arm/plat-samsung/s5p-irq-eint.c +++ b/arch/arm/plat-samsung/s5p-irq-eint.c @@ -15,8 +15,7 @@ #include <linux/io.h> #include <linux/device.h> #include <linux/gpio.h> - -#include <asm/hardware/vic.h> +#include <linux/irqchip/arm-vic.h> #include <plat/regs-irqtype.h> diff --git a/arch/arm/plat-samsung/s5p-irq.c b/arch/arm/plat-samsung/s5p-irq.c index dfb47d638f0..103e371f5e3 100644 --- a/arch/arm/plat-samsung/s5p-irq.c +++ b/arch/arm/plat-samsung/s5p-irq.c @@ -13,8 +13,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/io.h> - -#include <asm/hardware/vic.h> +#include <linux/irqchip/arm-vic.h> #include <mach/map.h> #include <plat/regs-timer.h> diff --git a/arch/arm/plat-samsung/s5p-time.c b/arch/arm/plat-samsung/s5p-time.c index dabede46c0e..e92510cf82e 100644 --- a/arch/arm/plat-samsung/s5p-time.c +++ b/arch/arm/plat-samsung/s5p-time.c @@ -274,15 +274,8 @@ static void __init s5p_clockevent_init(void) clock_rate = clk_get_rate(tin_event); clock_count_per_tick = clock_rate / HZ; - clockevents_calc_mult_shift(&time_event_device, - clock_rate, S5PTIMER_MIN_RANGE); - time_event_device.max_delta_ns = - clockevent_delta2ns(-1, &time_event_device); - time_event_device.min_delta_ns = - clockevent_delta2ns(1, &time_event_device); - time_event_device.cpumask = cpumask_of(0); - clockevents_register_device(&time_event_device); + clockevents_config_and_register(&time_event_device, clock_rate, 1, -1); irq_number = timer_source.event_id + IRQ_TIMER0; setup_irq(irq_number, &s5p_clock_event_irq); diff --git a/arch/arm/plat-spear/include/plat/uncompress.h b/arch/arm/plat-spear/include/plat/uncompress.h index 2ce6cb17a98..51b2dc93e4d 100644 --- a/arch/arm/plat-spear/include/plat/uncompress.h +++ b/arch/arm/plat-spear/include/plat/uncompress.h @@ -38,6 +38,5 @@ static inline void flush(void) * nothing to do */ #define arch_decomp_setup() -#define arch_decomp_wdog() #endif /* __PLAT_UNCOMPRESS_H */ diff --git a/arch/arm/plat-spear/time.c b/arch/arm/plat-spear/time.c index 03321af5de9..bd5c53cd696 100644 --- a/arch/arm/plat-spear/time.c +++ b/arch/arm/plat-spear/time.c @@ -186,15 +186,9 @@ static void __init spear_clockevent_init(int irq) tick_rate = clk_get_rate(gpt_clk); tick_rate >>= CTRL_PRESCALER16; - clockevents_calc_mult_shift(&clkevt, tick_rate, SPEAR_MIN_RANGE); - - clkevt.max_delta_ns = clockevent_delta2ns(0xfff0, - &clkevt); - clkevt.min_delta_ns = clockevent_delta2ns(3, &clkevt); - clkevt.cpumask = cpumask_of(0); - clockevents_register_device(&clkevt); + clockevents_config_and_register(&clkevt, tick_rate, 3, 0xfff0); setup_irq(irq, &spear_timer_irq); } diff --git a/arch/arm/plat-versatile/headsmp.S b/arch/arm/plat-versatile/headsmp.S index dd703ef09b8..b178d44e9ea 100644 --- a/arch/arm/plat-versatile/headsmp.S +++ b/arch/arm/plat-versatile/headsmp.S @@ -20,7 +20,7 @@ */ ENTRY(versatile_secondary_startup) mrc p15, 0, r0, c0, c0, 5 - and r0, r0, #15 + bic r0, #0xff000000 adr r4, 1f ldmia r4, {r5, r6} sub r4, r4, r5 diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c index 04ca4937d8c..f2ac1556177 100644 --- a/arch/arm/plat-versatile/platsmp.c +++ b/arch/arm/plat-versatile/platsmp.c @@ -14,10 +14,10 @@ #include <linux/device.h> #include <linux/jiffies.h> #include <linux/smp.h> +#include <linux/irqchip/arm-gic.h> #include <asm/cacheflush.h> #include <asm/smp_plat.h> -#include <asm/hardware/gic.h> /* * Write pen_release in a way that is guaranteed to be visible to all @@ -79,7 +79,7 @@ int __cpuinit versatile_boot_secondary(unsigned int cpu, struct task_struct *idl * the boot monitor to read the system wide flags register, * and branch to the address found there. */ - gic_raise_softirq(cpumask_of(cpu), 0); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S index cc926c98598..323ce1a62bb 100644 --- a/arch/arm/vfp/entry.S +++ b/arch/arm/vfp/entry.S @@ -22,7 +22,7 @@ @ IRQs disabled. @ ENTRY(do_vfp) -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPT_COUNT ldr r4, [r10, #TI_PREEMPT] @ get preempt count add r11, r4, #1 @ increment it str r11, [r10, #TI_PREEMPT] @@ -35,7 +35,7 @@ ENTRY(do_vfp) ENDPROC(do_vfp) ENTRY(vfp_null_entry) -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPT_COUNT get_thread_info r10 ldr r4, [r10, #TI_PREEMPT] @ get preempt count sub r11, r4, #1 @ decrement it @@ -53,7 +53,7 @@ ENDPROC(vfp_null_entry) __INIT ENTRY(vfp_testing_entry) -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPT_COUNT get_thread_info r10 ldr r4, [r10, #TI_PREEMPT] @ get preempt count sub r11, r4, #1 @ decrement it diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index ea0349f6358..dd5e56f95f3 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -168,7 +168,7 @@ vfp_hw_state_valid: @ else it's one 32-bit instruction, so @ always subtract 4 from the following @ instruction address. -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPT_COUNT get_thread_info r10 ldr r4, [r10, #TI_PREEMPT] @ get preempt count sub r11, r4, #1 @ decrement it @@ -192,7 +192,7 @@ look_for_VFP_exceptions: @ not recognised by VFP DBGSTR "not VFP" -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPT_COUNT get_thread_info r10 ldr r4, [r10, #TI_PREEMPT] @ get preempt count sub r11, r4, #1 @ decrement it diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile index 801e2d7fcbc..32ac0aef006 100644 --- a/arch/arm64/boot/dts/Makefile +++ b/arch/arm64/boot/dts/Makefile @@ -1,4 +1,5 @@ targets += dtbs +targets += $(dtb-y) dtbs: $(addprefix $(obj)/, $(dtb-y)) diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index 07fea290d7c..fe32c0e4ac0 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -26,7 +26,10 @@ typedef unsigned long elf_greg_t; -#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) +#define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t)) +#define ELF_CORE_COPY_REGS(dest, regs) \ + *(struct user_pt_regs *)&(dest) = (regs)->user_regs; + typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef struct user_fpsimd_state elf_fpregset_t; diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 64b13394950..e333a243bfc 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -24,7 +24,8 @@ /* * Software defined PTE bits definition. */ -#define PTE_VALID (_AT(pteval_t, 1) << 0) /* pte_present() check */ +#define PTE_VALID (_AT(pteval_t, 1) << 0) +#define PTE_PROT_NONE (_AT(pteval_t, 1) << 1) /* only when !PTE_VALID */ #define PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !pte_present() */ #define PTE_DIRTY (_AT(pteval_t, 1) << 55) #define PTE_SPECIAL (_AT(pteval_t, 1) << 56) @@ -60,9 +61,12 @@ extern void __pgd_error(const char *file, int line, unsigned long val); extern pgprot_t pgprot_default; -#define _MOD_PROT(p, b) __pgprot(pgprot_val(p) | (b)) +#define __pgprot_modify(prot,mask,bits) \ + __pgprot((pgprot_val(prot) & ~(mask)) | (bits)) + +#define _MOD_PROT(p, b) __pgprot_modify(p, 0, b) -#define PAGE_NONE _MOD_PROT(pgprot_default, PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) +#define PAGE_NONE __pgprot_modify(pgprot_default, PTE_TYPE_MASK, PTE_PROT_NONE) #define PAGE_SHARED _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) #define PAGE_SHARED_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN) #define PAGE_COPY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) @@ -72,7 +76,7 @@ extern pgprot_t pgprot_default; #define PAGE_KERNEL _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY) #define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY) -#define __PAGE_NONE __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) +#define __PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE) #define __PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) #define __PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) #define __PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) @@ -125,16 +129,15 @@ extern struct page *empty_zero_page; /* * The following only work if pte_present(). Undefined behaviour otherwise. */ -#define pte_present(pte) (pte_val(pte) & PTE_VALID) +#define pte_present(pte) (pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)) #define pte_dirty(pte) (pte_val(pte) & PTE_DIRTY) #define pte_young(pte) (pte_val(pte) & PTE_AF) #define pte_special(pte) (pte_val(pte) & PTE_SPECIAL) #define pte_write(pte) (!(pte_val(pte) & PTE_RDONLY)) #define pte_exec(pte) (!(pte_val(pte) & PTE_UXN)) -#define pte_present_exec_user(pte) \ - ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == \ - (PTE_VALID | PTE_USER)) +#define pte_valid_user(pte) \ + ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER)) #define PTE_BIT_FUNC(fn,op) \ static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } @@ -157,10 +160,13 @@ extern void __sync_icache_dcache(pte_t pteval, unsigned long addr); static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte) { - if (pte_present_exec_user(pte)) - __sync_icache_dcache(pte, addr); - if (!pte_dirty(pte)) - pte = pte_wrprotect(pte); + if (pte_valid_user(pte)) { + if (pte_exec(pte)) + __sync_icache_dcache(pte, addr); + if (!pte_dirty(pte)) + pte = pte_wrprotect(pte); + } + set_pte(ptep, pte); } @@ -170,9 +176,6 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, #define pte_huge(pte) ((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE) #define pte_mkhuge(pte) (__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE)) -#define __pgprot_modify(prot,mask,bits) \ - __pgprot((pgprot_val(prot) & ~(mask)) | (bits)) - #define __HAVE_ARCH_PTE_SPECIAL /* @@ -264,7 +267,8 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { - const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY; + const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY | + PTE_PROT_NONE | PTE_VALID; pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); return pte; } diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 58432625fdb..5ef47ba3ed4 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -395,8 +395,13 @@ __SYSCALL(370, sys_name_to_handle_at) __SYSCALL(371, compat_sys_open_by_handle_at) __SYSCALL(372, compat_sys_clock_adjtime) __SYSCALL(373, sys_syncfs) +__SYSCALL(374, compat_sys_sendmmsg) +__SYSCALL(375, sys_setns) +__SYSCALL(376, compat_sys_process_vm_readv) +__SYSCALL(377, compat_sys_process_vm_writev) +__SYSCALL(378, sys_ni_syscall) /* 378 for kcmp */ -#define __NR_compat_syscalls 374 +#define __NR_compat_syscalls 379 /* * Compat syscall numbers used by the AArch64 kernel. diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index c958cb84d75..6a389dc1bd4 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -252,10 +252,6 @@ void update_vsyscall(struct timekeeper *tk) void update_vsyscall_tz(void) { - ++vdso_data->tb_seq_count; - smp_wmb(); vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; vdso_data->tz_dsttime = sys_tz.tz_dsttime; - smp_wmb(); - ++vdso_data->tb_seq_count; } diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S index 8bf658d974f..f0a6d10b521 100644 --- a/arch/arm64/kernel/vdso/gettimeofday.S +++ b/arch/arm64/kernel/vdso/gettimeofday.S @@ -73,8 +73,6 @@ ENTRY(__kernel_gettimeofday) /* If tz is NULL, return 0. */ cbz x1, 3f ldp w4, w5, [vdso_data, #VDSO_TZ_MINWEST] - seqcnt_read w9 - seqcnt_check w9, 1b stp w4, w5, [x1, #TZ_MINWEST] 3: mov x0, xzr diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 4265ff64219..b7a5fffe092 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -672,33 +672,6 @@ ptrace_attach_sync_user_rbs (struct task_struct *child) read_unlock(&tasklist_lock); } -static inline int -thread_matches (struct task_struct *thread, unsigned long addr) -{ - unsigned long thread_rbs_end; - struct pt_regs *thread_regs; - - if (ptrace_check_attach(thread, 0) < 0) - /* - * If the thread is not in an attachable state, we'll - * ignore it. The net effect is that if ADDR happens - * to overlap with the portion of the thread's - * register backing store that is currently residing - * on the thread's kernel stack, then ptrace() may end - * up accessing a stale value. But if the thread - * isn't stopped, that's a problem anyhow, so we're - * doing as well as we can... - */ - return 0; - - thread_regs = task_pt_regs(thread); - thread_rbs_end = ia64_get_user_rbs_end(thread, thread_regs, NULL); - if (!on_kernel_rbs(addr, thread_regs->ar_bspstore, thread_rbs_end)) - return 0; - - return 1; /* looks like we've got a winner */ -} - /* * Write f32-f127 back to task->thread.fph if it has been modified. */ diff --git a/arch/m68k/include/asm/dma-mapping.h b/arch/m68k/include/asm/dma-mapping.h index 17f7a45948e..3e6b8445af6 100644 --- a/arch/m68k/include/asm/dma-mapping.h +++ b/arch/m68k/include/asm/dma-mapping.h @@ -21,6 +21,22 @@ extern void *dma_alloc_coherent(struct device *, size_t, extern void dma_free_coherent(struct device *, size_t, void *, dma_addr_t); +static inline void *dma_alloc_attrs(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag, + struct dma_attrs *attrs) +{ + /* attrs is not supported and ignored */ + return dma_alloc_coherent(dev, size, dma_handle, flag); +} + +static inline void dma_free_attrs(struct device *dev, size_t size, + void *cpu_addr, dma_addr_t dma_handle, + struct dma_attrs *attrs) +{ + /* attrs is not supported and ignored */ + dma_free_coherent(dev, size, cpu_addr, dma_handle); +} + static inline void *dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t flag) { diff --git a/arch/m68k/include/asm/pgtable_no.h b/arch/m68k/include/asm/pgtable_no.h index bf86b29fe64..037028f4ab7 100644 --- a/arch/m68k/include/asm/pgtable_no.h +++ b/arch/m68k/include/asm/pgtable_no.h @@ -64,6 +64,8 @@ extern unsigned int kobjsize(const void *objp); */ #define VMALLOC_START 0 #define VMALLOC_END 0xffffffff +#define KMAP_START 0 +#define KMAP_END 0xffffffff #include <asm-generic/pgtable.h> diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index 847994ce680..f9337f61466 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 348 +#define NR_syscalls 349 #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 b94bfbf9070..625f321001d 100644 --- a/arch/m68k/include/uapi/asm/unistd.h +++ b/arch/m68k/include/uapi/asm/unistd.h @@ -353,5 +353,6 @@ #define __NR_process_vm_readv 345 #define __NR_process_vm_writev 346 #define __NR_kcmp 347 +#define __NR_finit_module 348 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */ diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S index c30da5b3f2d..3f04ea0ab80 100644 --- a/arch/m68k/kernel/syscalltable.S +++ b/arch/m68k/kernel/syscalltable.S @@ -368,4 +368,5 @@ ENTRY(sys_call_table) .long sys_process_vm_readv /* 345 */ .long sys_process_vm_writev .long sys_kcmp + .long sys_finit_module diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c index f0e05bce92f..afd8106fd83 100644 --- a/arch/m68k/mm/init.c +++ b/arch/m68k/mm/init.c @@ -39,6 +39,11 @@ void *empty_zero_page; EXPORT_SYMBOL(empty_zero_page); +#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE) +extern void init_pointer_table(unsigned long ptable); +extern pmd_t *zero_pgtable; +#endif + #ifdef CONFIG_MMU pg_data_t pg_data_map[MAX_NUMNODES]; @@ -69,9 +74,6 @@ void __init m68k_setup_node(int node) node_set_online(node); } -extern void init_pointer_table(unsigned long ptable); -extern pmd_t *zero_pgtable; - #else /* CONFIG_MMU */ /* diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index aa03f2e1338..e70001cfa05 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig @@ -6,6 +6,7 @@ config MN10300 select ARCH_WANT_IPC_PARSE_VERSION select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_KGDB + select GENERIC_ATOMIC64 select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER select GENERIC_CLOCKEVENTS select MODULES_USE_ELF_RELA diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index bfb44247d7a..eb7850b46c2 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -1865,7 +1865,7 @@ syscall_restore: /* Are we being ptraced? */ ldw TASK_FLAGS(%r1),%r19 - ldi (_TIF_SINGLESTEP|_TIF_BLOCKSTEP),%r2 + ldi _TIF_SYSCALL_TRACE_MASK,%r2 and,COND(=) %r19,%r2,%r0 b,n syscall_restore_rfi @@ -1978,15 +1978,23 @@ syscall_restore_rfi: /* sr2 should be set to zero for userspace syscalls */ STREG %r0,TASK_PT_SR2(%r1) -pt_regs_ok: LDREG TASK_PT_GR31(%r1),%r2 - depi 3,31,2,%r2 /* ensure return to user mode. */ - STREG %r2,TASK_PT_IAOQ0(%r1) + depi 3,31,2,%r2 /* ensure return to user mode. */ + STREG %r2,TASK_PT_IAOQ0(%r1) ldo 4(%r2),%r2 STREG %r2,TASK_PT_IAOQ1(%r1) + b intr_restore copy %r25,%r16 + +pt_regs_ok: + LDREG TASK_PT_IAOQ0(%r1),%r2 + depi 3,31,2,%r2 /* ensure return to user mode. */ + STREG %r2,TASK_PT_IAOQ0(%r1) + LDREG TASK_PT_IAOQ1(%r1),%r2 + depi 3,31,2,%r2 + STREG %r2,TASK_PT_IAOQ1(%r1) b intr_restore - nop + copy %r25,%r16 .import schedule,code syscall_do_resched: diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index c0b1affc06a..0299d63cd11 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -410,11 +410,13 @@ void __init init_IRQ(void) { local_irq_disable(); /* PARANOID - should already be disabled */ mtctl(~0UL, 23); /* EIRR : clear all pending external intr */ - claim_cpu_irqs(); #ifdef CONFIG_SMP - if (!cpu_eiem) + if (!cpu_eiem) { + claim_cpu_irqs(); cpu_eiem = EIEM_MASK(IPI_IRQ) | EIEM_MASK(TIMER_IRQ); + } #else + claim_cpu_irqs(); cpu_eiem = EIEM_MASK(TIMER_IRQ); #endif set_eiem(cpu_eiem); /* EIEM : enable all external intr */ diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 857c2f54547..534abd4936e 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -26,7 +26,7 @@ #include <asm/asm-offsets.h> /* PSW bits we allow the debugger to modify */ -#define USER_PSW_BITS (PSW_N | PSW_V | PSW_CB) +#define USER_PSW_BITS (PSW_N | PSW_B | PSW_V | PSW_CB) /* * Called by kernel/ptrace.c when detaching.. diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index 53799695599..fd051705a40 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c @@ -190,8 +190,10 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n", (unsigned long)ka, sp, frame_size); + /* Align alternate stack and reserve 64 bytes for the signal + handler's frame marker. */ if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) - sp = current->sas_ss_sp; /* Stacks grow up! */ + sp = (current->sas_ss_sp + 0x7f) & ~0x3f; /* Stacks grow up! */ DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp); return (void __user *) sp; /* Stacks grow up. Fun. */ diff --git a/arch/parisc/math-emu/cnv_float.h b/arch/parisc/math-emu/cnv_float.h index 9071e093164..933423fa514 100644 --- a/arch/parisc/math-emu/cnv_float.h +++ b/arch/parisc/math-emu/cnv_float.h @@ -347,16 +347,15 @@ Sgl_isinexact_to_fix(sgl_value,exponent) #define Duint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \ - {Sall(sgl_value) <<= SGL_EXP_LENGTH; /* left-justify */ \ + {unsigned int val = Sall(sgl_value) << SGL_EXP_LENGTH; \ if (exponent <= 31) { \ - Dintp1(dresultA) = 0; \ - Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \ + Dintp1(dresultA) = 0; \ + Dintp2(dresultB) = val >> (31 - exponent); \ } \ else { \ - Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent); \ - Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31); \ + Dintp1(dresultA) = val >> (63 - exponent); \ + Dintp2(dresultB) = exponent <= 62 ? val << (exponent - 31) : 0; \ } \ - Sall(sgl_value) >>= SGL_EXP_LENGTH; /* return to original */ \ } #define Duint_setzero(dresultA,dresultB) \ diff --git a/arch/powerpc/include/uapi/asm/kvm_para.h b/arch/powerpc/include/uapi/asm/kvm_para.h index ed0e0254b47..e3af3286a06 100644 --- a/arch/powerpc/include/uapi/asm/kvm_para.h +++ b/arch/powerpc/include/uapi/asm/kvm_para.h @@ -78,7 +78,7 @@ struct kvm_vcpu_arch_shared { #define KVM_HCALL_TOKEN(num) _EV_HCALL_TOKEN(EV_KVM_VENDOR_ID, num) -#include <uapi/asm/epapr_hcalls.h> +#include <asm/epapr_hcalls.h> #define KVM_FEATURE_MAGIC_PAGE 1 diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c index 35f3cf0269b..a353c485808 100644 --- a/arch/powerpc/kvm/book3s_hv_ras.c +++ b/arch/powerpc/kvm/book3s_hv_ras.c @@ -79,7 +79,9 @@ static void flush_tlb_power7(struct kvm_vcpu *vcpu) static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu) { unsigned long srr1 = vcpu->arch.shregs.msr; +#ifdef CONFIG_PPC_POWERNV struct opal_machine_check_event *opal_evt; +#endif long handled = 1; if (srr1 & SRR1_MC_LDSTERR) { @@ -117,6 +119,7 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu) handled = 0; } +#ifdef CONFIG_PPC_POWERNV /* * See if OPAL has already handled the condition. * We assume that if the condition is recovered then OPAL @@ -131,6 +134,7 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu) if (handled) opal_evt->in_use = 0; +#endif return handled; } diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index b0855e5d890..9d9cddc5b34 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c @@ -39,6 +39,7 @@ #define OP_31_XOP_TRAP 4 #define OP_31_XOP_LWZX 23 #define OP_31_XOP_TRAP_64 68 +#define OP_31_XOP_DCBF 86 #define OP_31_XOP_LBZX 87 #define OP_31_XOP_STWX 151 #define OP_31_XOP_STBX 215 @@ -374,6 +375,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs); break; + case OP_31_XOP_DCBF: case OP_31_XOP_DCBI: /* Do nothing. The guest is performing dcbi because * hardware DMA is not snooped by the dcache, but diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 4b8e08b56f4..7e3ce78d429 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -24,8 +24,8 @@ CHECKFLAGS += -D__s390__ -msize-long else LD_BFD := elf64-s390 LDFLAGS := -m elf64_s390 -KBUILD_AFLAGS_MODULE += -fpic -D__PIC__ -KBUILD_CFLAGS_MODULE += -fpic -D__PIC__ +KBUILD_AFLAGS_MODULE += -fPIC +KBUILD_CFLAGS_MODULE += -fPIC KBUILD_CFLAGS += -m64 KBUILD_AFLAGS += -m64 UTS_MACHINE := s390x diff --git a/arch/s390/include/asm/dma.h b/arch/s390/include/asm/dma.h index de015d85e3e..bb9bdcd2086 100644 --- a/arch/s390/include/asm/dma.h +++ b/arch/s390/include/asm/dma.h @@ -10,4 +10,10 @@ */ #define MAX_DMA_ADDRESS 0x80000000 +#ifdef CONFIG_PCI +extern int isa_dma_bridge_buggy; +#else +#define isa_dma_bridge_buggy (0) +#endif + #endif /* _ASM_S390_DMA_H */ diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h index 16c3eb164f4..27cb32185ce 100644 --- a/arch/s390/include/asm/io.h +++ b/arch/s390/include/asm/io.h @@ -85,6 +85,11 @@ static inline void iounmap(volatile void __iomem *addr) #define __raw_writel zpci_write_u32 #define __raw_writeq zpci_write_u64 +#define readb_relaxed readb +#define readw_relaxed readw +#define readl_relaxed readl +#define readq_relaxed readq + #endif /* CONFIG_PCI */ #include <asm-generic/io.h> diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h index e6972f85d2b..7def77302d6 100644 --- a/arch/s390/include/asm/irq.h +++ b/arch/s390/include/asm/irq.h @@ -2,43 +2,61 @@ #define _ASM_IRQ_H #include <linux/hardirq.h> +#include <linux/percpu.h> +#include <linux/cache.h> #include <linux/types.h> -enum interruption_class { +enum interruption_main_class { EXTERNAL_INTERRUPT, IO_INTERRUPT, - EXTINT_CLK, - EXTINT_EXC, - EXTINT_EMS, - EXTINT_TMR, - EXTINT_TLA, - EXTINT_PFL, - EXTINT_DSD, - EXTINT_VRT, - EXTINT_SCP, - EXTINT_IUC, - EXTINT_CMS, - EXTINT_CMC, - EXTINT_CMR, - IOINT_CIO, - IOINT_QAI, - IOINT_DAS, - IOINT_C15, - IOINT_C70, - IOINT_TAP, - IOINT_VMR, - IOINT_LCS, - IOINT_CLW, - IOINT_CTC, - IOINT_APB, - IOINT_ADM, - IOINT_CSC, - IOINT_PCI, - IOINT_MSI, + NR_IRQS +}; + +enum interruption_class { + IRQEXT_CLK, + IRQEXT_EXC, + IRQEXT_EMS, + IRQEXT_TMR, + IRQEXT_TLA, + IRQEXT_PFL, + IRQEXT_DSD, + IRQEXT_VRT, + IRQEXT_SCP, + IRQEXT_IUC, + IRQEXT_CMS, + IRQEXT_CMC, + IRQEXT_CMR, + IRQIO_CIO, + IRQIO_QAI, + IRQIO_DAS, + IRQIO_C15, + IRQIO_C70, + IRQIO_TAP, + IRQIO_VMR, + IRQIO_LCS, + IRQIO_CLW, + IRQIO_CTC, + IRQIO_APB, + IRQIO_ADM, + IRQIO_CSC, + IRQIO_PCI, + IRQIO_MSI, NMI_NMI, - NR_IRQS, + CPU_RST, + NR_ARCH_IRQS }; +struct irq_stat { + unsigned int irqs[NR_ARCH_IRQS]; +}; + +DECLARE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat); + +static __always_inline void inc_irq_stat(enum interruption_class irq) +{ + __get_cpu_var(irq_stat).irqs[irq]++; +} + struct ext_code { unsigned short subcode; unsigned short code; diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index c928dc1938f..c1d7930a82f 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -1387,10 +1387,7 @@ static inline int has_transparent_hugepage(void) static inline unsigned long pmd_pfn(pmd_t pmd) { - if (pmd_trans_huge(pmd)) - return pmd_val(pmd) >> HPAGE_SHIFT; - else - return pmd_val(pmd) >> PAGE_SHIFT; + return pmd_val(pmd) >> PAGE_SHIFT; } #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index fba4d66788a..4c060bb5b8e 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h @@ -128,4 +128,32 @@ static inline unsigned long long get_clock_monotonic(void) return get_clock_xt() - sched_clock_base_cc; } +/** + * tod_to_ns - convert a TOD format value to nanoseconds + * @todval: to be converted TOD format value + * Returns: number of nanoseconds that correspond to the TOD format value + * + * Converting a 64 Bit TOD format value to nanoseconds means that the value + * must be divided by 4.096. In order to achieve that we multiply with 125 + * and divide by 512: + * + * ns = (todval * 125) >> 9; + * + * In order to avoid an overflow with the multiplication we can rewrite this. + * With a split todval == 2^32 * th + tl (th upper 32 bits, tl lower 32 bits) + * we end up with + * + * ns = ((2^32 * th + tl) * 125 ) >> 9; + * -> ns = (2^23 * th * 125) + ((tl * 125) >> 9); + * + */ +static inline unsigned long long tod_to_ns(unsigned long long todval) +{ + unsigned long long ns; + + ns = ((todval >> 32) << 23) * 125; + ns += ((todval & 0xffffffff) * 125) >> 9; + return ns; +} + #endif diff --git a/arch/s390/include/uapi/asm/unistd.h b/arch/s390/include/uapi/asm/unistd.h index 63e6078699f..864f693c237 100644 --- a/arch/s390/include/uapi/asm/unistd.h +++ b/arch/s390/include/uapi/asm/unistd.h @@ -279,7 +279,8 @@ #define __NR_process_vm_writev 341 #define __NR_s390_runtime_instr 342 #define __NR_kcmp 343 -#define NR_syscalls 344 +#define __NR_finit_module 344 +#define NR_syscalls 345 /* * There are some system calls that are not present on 64 bit, some diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 827e094a2f4..9b9a805656b 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1659,3 +1659,9 @@ ENTRY(sys_kcmp_wrapper) llgfr %r5,%r5 # unsigned long llgfr %r6,%r6 # unsigned long jg sys_kcmp + +ENTRY(sys_finit_module_wrapper) + lgfr %r2,%r2 # int + llgtr %r3,%r3 # const char __user * + lgfr %r4,%r4 # int + jg sys_finit_module diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index ba500d8dc39..4e8215e0d4b 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -1127,13 +1127,14 @@ debug_register_view(debug_info_t * id, struct debug_view *view) if (i == DEBUG_MAX_VIEWS) { pr_err("Registering view %s/%s would exceed the maximum " "number of views %i\n", id->name, view->name, i); - debugfs_remove(pde); rc = -1; } else { id->views[i] = view; id->debugfs_entries[i] = pde; } spin_unlock_irqrestore(&id->lock, flags); + if (rc) + debugfs_remove(pde); out: return rc; } @@ -1146,9 +1147,9 @@ EXPORT_SYMBOL(debug_register_view); int debug_unregister_view(debug_info_t * id, struct debug_view *view) { - int rc = 0; - int i; + struct dentry *dentry = NULL; unsigned long flags; + int i, rc = 0; if (!id) goto out; @@ -1160,10 +1161,12 @@ debug_unregister_view(debug_info_t * id, struct debug_view *view) if (i == DEBUG_MAX_VIEWS) rc = -1; else { - debugfs_remove(id->debugfs_entries[i]); + dentry = id->debugfs_entries[i]; id->views[i] = NULL; + id->debugfs_entries[i] = NULL; } spin_unlock_irqrestore(&id->lock, flags); + debugfs_remove(dentry); out: return rc; } diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index bf24293970c..9df824ea166 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -24,43 +24,65 @@ #include <asm/irq.h> #include "entry.h" +DEFINE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat); +EXPORT_PER_CPU_SYMBOL_GPL(irq_stat); + struct irq_class { char *name; char *desc; }; -static const struct irq_class intrclass_names[] = { +/* + * The list of "main" irq classes on s390. This is the list of interrrupts + * that appear both in /proc/stat ("intr" line) and /proc/interrupts. + * Historically only external and I/O interrupts have been part of /proc/stat. + * We can't add the split external and I/O sub classes since the first field + * in the "intr" line in /proc/stat is supposed to be the sum of all other + * fields. + * Since the external and I/O interrupt fields are already sums we would end + * up with having a sum which accounts each interrupt twice. + */ +static const struct irq_class irqclass_main_desc[NR_IRQS] = { [EXTERNAL_INTERRUPT] = {.name = "EXT"}, - [IO_INTERRUPT] = {.name = "I/O"}, - [EXTINT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"}, - [EXTINT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"}, - [EXTINT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"}, - [EXTINT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"}, - [EXTINT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"}, - [EXTINT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"}, - [EXTINT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"}, - [EXTINT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"}, - [EXTINT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"}, - [EXTINT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"}, - [EXTINT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"}, - [EXTINT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"}, - [EXTINT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"}, - [IOINT_CIO] = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"}, - [IOINT_QAI] = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"}, - [IOINT_DAS] = {.name = "DAS", .desc = "[I/O] DASD"}, - [IOINT_C15] = {.name = "C15", .desc = "[I/O] 3215"}, - [IOINT_C70] = {.name = "C70", .desc = "[I/O] 3270"}, - [IOINT_TAP] = {.name = "TAP", .desc = "[I/O] Tape"}, - [IOINT_VMR] = {.name = "VMR", .desc = "[I/O] Unit Record Devices"}, - [IOINT_LCS] = {.name = "LCS", .desc = "[I/O] LCS"}, - [IOINT_CLW] = {.name = "CLW", .desc = "[I/O] CLAW"}, - [IOINT_CTC] = {.name = "CTC", .desc = "[I/O] CTC"}, - [IOINT_APB] = {.name = "APB", .desc = "[I/O] AP Bus"}, - [IOINT_ADM] = {.name = "ADM", .desc = "[I/O] EADM Subchannel"}, - [IOINT_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"}, - [IOINT_PCI] = {.name = "PCI", .desc = "[I/O] PCI Interrupt" }, - [IOINT_MSI] = {.name = "MSI", .desc = "[I/O] MSI Interrupt" }, + [IO_INTERRUPT] = {.name = "I/O"} +}; + +/* + * The list of split external and I/O interrupts that appear only in + * /proc/interrupts. + * In addition this list contains non external / I/O events like NMIs. + */ +static const struct irq_class irqclass_sub_desc[NR_ARCH_IRQS] = { + [IRQEXT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"}, + [IRQEXT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"}, + [IRQEXT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"}, + [IRQEXT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"}, + [IRQEXT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"}, + [IRQEXT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"}, + [IRQEXT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"}, + [IRQEXT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"}, + [IRQEXT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"}, + [IRQEXT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"}, + [IRQEXT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"}, + [IRQEXT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"}, + [IRQEXT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"}, + [IRQIO_CIO] = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"}, + [IRQIO_QAI] = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"}, + [IRQIO_DAS] = {.name = "DAS", .desc = "[I/O] DASD"}, + [IRQIO_C15] = {.name = "C15", .desc = "[I/O] 3215"}, + [IRQIO_C70] = {.name = "C70", .desc = "[I/O] 3270"}, + [IRQIO_TAP] = {.name = "TAP", .desc = "[I/O] Tape"}, + [IRQIO_VMR] = {.name = "VMR", .desc = "[I/O] Unit Record Devices"}, + [IRQIO_LCS] = {.name = "LCS", .desc = "[I/O] LCS"}, + [IRQIO_CLW] = {.name = "CLW", .desc = "[I/O] CLAW"}, + [IRQIO_CTC] = {.name = "CTC", .desc = "[I/O] CTC"}, + [IRQIO_APB] = {.name = "APB", .desc = "[I/O] AP Bus"}, + [IRQIO_ADM] = {.name = "ADM", .desc = "[I/O] EADM Subchannel"}, + [IRQIO_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"}, + [IRQIO_PCI] = {.name = "PCI", .desc = "[I/O] PCI Interrupt" }, + [IRQIO_MSI] = {.name = "MSI", .desc = "[I/O] MSI Interrupt" }, [NMI_NMI] = {.name = "NMI", .desc = "[NMI] Machine Check"}, + [CPU_RST] = {.name = "RST", .desc = "[CPU] CPU Restart"}, }; /* @@ -68,30 +90,34 @@ static const struct irq_class intrclass_names[] = { */ int show_interrupts(struct seq_file *p, void *v) { - int i = *(loff_t *) v, j; + int irq = *(loff_t *) v; + int cpu; get_online_cpus(); - if (i == 0) { + if (irq == 0) { seq_puts(p, " "); - for_each_online_cpu(j) - seq_printf(p, "CPU%d ",j); + for_each_online_cpu(cpu) + seq_printf(p, "CPU%d ", cpu); seq_putc(p, '\n'); } - - if (i < NR_IRQS) { - seq_printf(p, "%s: ", intrclass_names[i].name); -#ifndef CONFIG_SMP - seq_printf(p, "%10u ", kstat_irqs(i)); -#else - for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); -#endif - if (intrclass_names[i].desc) - seq_printf(p, " %s", intrclass_names[i].desc); - seq_putc(p, '\n'); - } + if (irq < NR_IRQS) { + seq_printf(p, "%s: ", irqclass_main_desc[irq].name); + for_each_online_cpu(cpu) + seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[irq]); + seq_putc(p, '\n'); + goto skip_arch_irqs; + } + for (irq = 0; irq < NR_ARCH_IRQS; irq++) { + seq_printf(p, "%s: ", irqclass_sub_desc[irq].name); + for_each_online_cpu(cpu) + seq_printf(p, "%10u ", per_cpu(irq_stat, cpu).irqs[irq]); + if (irqclass_sub_desc[irq].desc) + seq_printf(p, " %s", irqclass_sub_desc[irq].desc); + seq_putc(p, '\n'); + } +skip_arch_irqs: put_online_cpus(); - return 0; + return 0; } /* @@ -222,7 +248,7 @@ void __irq_entry do_extint(struct pt_regs *regs, struct ext_code ext_code, /* Serve timer interrupts first. */ clock_comparator_work(); } - kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; + kstat_incr_irqs_this_cpu(EXTERNAL_INTERRUPT, NULL); if (ext_code.code != 0x1004) __get_cpu_var(s390_idle).nohz_delay = 1; diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index a6daa5c5cdb..7918fbea36b 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c @@ -254,7 +254,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs) int umode; nmi_enter(); - kstat_cpu(smp_processor_id()).irqs[NMI_NMI]++; + inc_irq_stat(NMI_NMI); mci = (struct mci *) &S390_lowcore.mcck_interruption_code; mcck = &__get_cpu_var(cpu_mcck); umode = user_mode(regs); diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index c4e7269d4a0..86ec7447e1f 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c @@ -229,7 +229,7 @@ static void cpumf_measurement_alert(struct ext_code ext_code, if (!(alert & CPU_MF_INT_CF_MASK)) return; - kstat_cpu(smp_processor_id()).irqs[EXTINT_CMC]++; + inc_irq_stat(IRQEXT_CMC); cpuhw = &__get_cpu_var(cpu_hw_events); /* Measurement alerts are shared and might happen when the PMU diff --git a/arch/s390/kernel/runtime_instr.c b/arch/s390/kernel/runtime_instr.c index 61066f6f71a..077a99389b0 100644 --- a/arch/s390/kernel/runtime_instr.c +++ b/arch/s390/kernel/runtime_instr.c @@ -71,7 +71,7 @@ static void runtime_instr_int_handler(struct ext_code ext_code, if (!(param32 & CPU_MF_INT_RI_MASK)) return; - kstat_cpu(smp_processor_id()).irqs[EXTINT_CMR]++; + inc_irq_stat(IRQEXT_CMR); if (!current->thread.ri_cb) return; diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 2568590973a..a5360de85ec 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -16,7 +16,7 @@ #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include <linux/errno.h> -#include <linux/module.h> +#include <linux/export.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/memblock.h> @@ -289,6 +289,7 @@ void machine_power_off(void) * Dummy power off function. */ void (*pm_power_off)(void) = machine_power_off; +EXPORT_SYMBOL_GPL(pm_power_off); static int __init early_parse_mem(char *p) { diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 0b45baa5543..7433a2f9e5c 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -433,9 +433,9 @@ static void do_ext_call_interrupt(struct ext_code ext_code, cpu = smp_processor_id(); if (ext_code.code == 0x1202) - kstat_cpu(cpu).irqs[EXTINT_EXC]++; + inc_irq_stat(IRQEXT_EXC); else - kstat_cpu(cpu).irqs[EXTINT_EMS]++; + inc_irq_stat(IRQEXT_EMS); /* * handle bit signal external calls */ @@ -623,9 +623,10 @@ static struct sclp_cpu_info *smp_get_cpu_info(void) return info; } -static int smp_add_present_cpu(int cpu); +static int __cpuinit smp_add_present_cpu(int cpu); -static int __smp_rescan_cpus(struct sclp_cpu_info *info, int sysfs_add) +static int __cpuinit __smp_rescan_cpus(struct sclp_cpu_info *info, + int sysfs_add) { struct pcpu *pcpu; cpumask_t avail; @@ -708,6 +709,7 @@ static void __cpuinit smp_start_secondary(void *cpuvoid) pfault_init(); notify_cpu_starting(smp_processor_id()); set_cpu_online(smp_processor_id(), true); + inc_irq_stat(CPU_RST); local_irq_enable(); /* cpu_idle will call schedule for us */ cpu_idle(); @@ -985,7 +987,7 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, return notifier_from_errno(err); } -static int smp_add_present_cpu(int cpu) +static int __cpuinit smp_add_present_cpu(int cpu) { struct cpu *c = &pcpu_devices[cpu].cpu; struct device *s = &c->dev; diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 48174850f3b..6a6c61f94dd 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -352,3 +352,4 @@ SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wr SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper) SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper) SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper) +SYSCALL(sys_finit_module,sys_finit_module,sys_finit_module_wrapper) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 7fcd690d42c..a5f4f5a1d24 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -63,7 +63,7 @@ static DEFINE_PER_CPU(struct clock_event_device, comparators); */ unsigned long long notrace __kprobes sched_clock(void) { - return (get_clock_monotonic() * 125) >> 9; + return tod_to_ns(get_clock_monotonic()); } /* @@ -168,7 +168,7 @@ static void clock_comparator_interrupt(struct ext_code ext_code, unsigned int param32, unsigned long param64) { - kstat_cpu(smp_processor_id()).irqs[EXTINT_CLK]++; + inc_irq_stat(IRQEXT_CLK); if (S390_lowcore.clock_comparator == -1ULL) set_clock_comparator(S390_lowcore.clock_comparator); } @@ -179,7 +179,7 @@ static void stp_timing_alert(struct stp_irq_parm *); static void timing_alert_interrupt(struct ext_code ext_code, unsigned int param32, unsigned long param64) { - kstat_cpu(smp_processor_id()).irqs[EXTINT_TLA]++; + inc_irq_stat(IRQEXT_TLA); if (param32 & 0x00c40000) etr_timing_alert((struct etr_irq_parm *) ¶m32); if (param32 & 0x00038000) diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index f1aba87cceb..4b2e3e31700 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -10,6 +10,7 @@ #include <linux/bootmem.h> #include <linux/cpuset.h> #include <linux/device.h> +#include <linux/export.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/init.h> @@ -42,6 +43,7 @@ static struct mask_info socket_info; static struct mask_info book_info; struct cpu_topology_s390 cpu_topology[NR_CPUS]; +EXPORT_SYMBOL_GPL(cpu_topology); static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) { diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index c30615e605a..82c481ddef7 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -408,7 +408,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) return 0; } - sltime = ((vcpu->arch.sie_block->ckc - now)*125)>>9; + sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now); hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL); VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime); diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index c9011bfaabb..f090e819bf7 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -613,7 +613,9 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) kvm_s390_deliver_pending_interrupts(vcpu); vcpu->arch.sie_block->icptcode = 0; + preempt_disable(); kvm_guest_enter(); + preempt_enable(); VCPU_EVENT(vcpu, 6, "entering sie flags %x", atomic_read(&vcpu->arch.sie_block->cpuflags)); trace_kvm_s390_sie_enter(vcpu, diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 42601d6e166..2fb9e63b8fc 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -569,7 +569,7 @@ static void pfault_interrupt(struct ext_code ext_code, subcode = ext_code.subcode; if ((subcode & 0xff00) != __SUBCODE_MASK) return; - kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++; + inc_irq_stat(IRQEXT_PFL); /* Get the token (= pid of the affected task). */ pid = sizeof(void *) == 4 ? param32 : param64; rcu_read_lock(); diff --git a/arch/s390/oprofile/hwsampler.c b/arch/s390/oprofile/hwsampler.c index 0cb385da202..b5b2916895e 100644 --- a/arch/s390/oprofile/hwsampler.c +++ b/arch/s390/oprofile/hwsampler.c @@ -233,7 +233,7 @@ static void hws_ext_handler(struct ext_code ext_code, if (!(param32 & CPU_MF_INT_SF_MASK)) return; - kstat_cpu(smp_processor_id()).irqs[EXTINT_CMS]++; + inc_irq_stat(IRQEXT_CMS); atomic_xchg(&cb->ext_params, atomic_read(&cb->ext_params) | param32); if (hws_wq) diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index ff49427e994..60e0372545d 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -160,35 +160,6 @@ int pci_proc_domain(struct pci_bus *bus) } EXPORT_SYMBOL_GPL(pci_proc_domain); -/* Store PCI function information block */ -static int zpci_store_fib(struct zpci_dev *zdev, u8 *fc) -{ - struct zpci_fib *fib; - u8 status, cc; - - fib = (void *) get_zeroed_page(GFP_KERNEL); - if (!fib) - return -ENOMEM; - - do { - cc = __stpcifc(zdev->fh, 0, fib, &status); - if (cc == 2) { - msleep(ZPCI_INSN_BUSY_DELAY); - memset(fib, 0, PAGE_SIZE); - } - } while (cc == 2); - - if (cc) - pr_err_once("%s: cc: %u status: %u\n", - __func__, cc, status); - - /* Return PCI function controls */ - *fc = fib->fc; - - free_page((unsigned long) fib); - return (cc) ? -EIO : 0; -} - /* Modify PCI: Register adapter interruptions */ static int zpci_register_airq(struct zpci_dev *zdev, unsigned int aisb, u64 aibv) @@ -469,7 +440,7 @@ static void zpci_irq_handler(void *dont, void *need) int rescan = 0, max = aisb_max; struct zdev_irq_map *imap; - kstat_cpu(smp_processor_id()).irqs[IOINT_PCI]++; + inc_irq_stat(IRQIO_PCI); sbit = start; scan: @@ -481,7 +452,7 @@ scan: /* find vector bit */ imap = bucket->imap[sbit]; for_each_set_bit_left(mbit, &imap->aibv, imap->msi_vecs) { - kstat_cpu(smp_processor_id()).irqs[IOINT_MSI]++; + inc_irq_stat(IRQIO_MSI); clear_bit(63 - mbit, &imap->aibv); spin_lock(&imap->lock); diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c index 6138468b420..a547419907c 100644 --- a/arch/s390/pci/pci_dma.c +++ b/arch/s390/pci/pci_dma.c @@ -13,8 +13,6 @@ #include <linux/pci.h> #include <asm/pci_dma.h> -static enum zpci_ioat_dtype zpci_ioat_dt = ZPCI_IOTA_RTTO; - static struct kmem_cache *dma_region_table_cache; static struct kmem_cache *dma_page_table_cache; diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 3fede4556c9..a0fa5791cd4 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -70,6 +70,16 @@ * OFF-ON : MMC */ +/* + * FSI - DA7210 + * + * it needs amixer settings for playing + * + * amixer set 'HeadPhone' 80 + * amixer set 'Out Mixer Left DAC Left' on + * amixer set 'Out Mixer Right DAC Right' on + */ + /* Heartbeat */ static unsigned char led_pos[] = { 0, 1, 2, 3 }; diff --git a/arch/sh/include/asm/elf.h b/arch/sh/include/asm/elf.h index 37924afa8d8..bf9f44f17c2 100644 --- a/arch/sh/include/asm/elf.h +++ b/arch/sh/include/asm/elf.h @@ -203,9 +203,9 @@ extern void __kernel_vsyscall; if (vdso_enabled) \ NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE); \ else \ - NEW_AUX_ENT(AT_IGNORE, 0); + NEW_AUX_ENT(AT_IGNORE, 0) #else -#define VSYSCALL_AUX_ENT +#define VSYSCALL_AUX_ENT NEW_AUX_ENT(AT_IGNORE, 0) #endif /* CONFIG_VSYSCALL */ #ifdef CONFIG_SH_FPU diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h index b1320d55ca3..e699a12cdcc 100644 --- a/arch/sh/include/asm/processor_32.h +++ b/arch/sh/include/asm/processor_32.h @@ -39,7 +39,7 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE / 3) /* * Bit of SR register diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h index 1ee8946f095..1cc7d319714 100644 --- a/arch/sh/include/asm/processor_64.h +++ b/arch/sh/include/asm/processor_64.h @@ -47,7 +47,7 @@ pc; }) /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE / 3) /* * Bit of SR register diff --git a/arch/sh/include/uapi/asm/unistd_32.h b/arch/sh/include/uapi/asm/unistd_32.h index 9e465f246dc..d13a1d62373 100644 --- a/arch/sh/include/uapi/asm/unistd_32.h +++ b/arch/sh/include/uapi/asm/unistd_32.h @@ -379,7 +379,8 @@ #define __NR_process_vm_readv 365 #define __NR_process_vm_writev 366 #define __NR_kcmp 367 +#define __NR_finit_module 368 -#define NR_syscalls 368 +#define NR_syscalls 369 #endif /* __ASM_SH_UNISTD_32_H */ diff --git a/arch/sh/include/uapi/asm/unistd_64.h b/arch/sh/include/uapi/asm/unistd_64.h index 8e3a2edd284..e6820c86e8c 100644 --- a/arch/sh/include/uapi/asm/unistd_64.h +++ b/arch/sh/include/uapi/asm/unistd_64.h @@ -399,7 +399,8 @@ #define __NR_process_vm_readv 376 #define __NR_process_vm_writev 377 #define __NR_kcmp 378 +#define __NR_finit_module 379 -#define NR_syscalls 379 +#define NR_syscalls 380 #endif /* __ASM_SH_UNISTD_64_H */ diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S index fe97ae5e56f..734234be2f0 100644 --- a/arch/sh/kernel/syscalls_32.S +++ b/arch/sh/kernel/syscalls_32.S @@ -385,3 +385,4 @@ ENTRY(sys_call_table) .long sys_process_vm_readv /* 365 */ .long sys_process_vm_writev .long sys_kcmp + .long sys_finit_module diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S index 5c7b1c67bdc..579fcb9a896 100644 --- a/arch/sh/kernel/syscalls_64.S +++ b/arch/sh/kernel/syscalls_64.S @@ -405,3 +405,4 @@ sys_call_table: .long sys_process_vm_readv .long sys_process_vm_writev .long sys_kcmp + .long sys_finit_module diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S index 60164e65d66..52aa2011d75 100644 --- a/arch/sh/lib/mcount.S +++ b/arch/sh/lib/mcount.S @@ -294,6 +294,8 @@ stack_panic: .align 2 .L_init_thread_union: .long init_thread_union +.L_ebss: + .long __bss_stop .Lpanic: .long panic .Lpanic_s: diff --git a/arch/sparc/include/uapi/asm/unistd.h b/arch/sparc/include/uapi/asm/unistd.h index cac719d1bc5..62ced589bcf 100644 --- a/arch/sparc/include/uapi/asm/unistd.h +++ b/arch/sparc/include/uapi/asm/unistd.h @@ -407,8 +407,9 @@ #define __NR_process_vm_writev 339 #define __NR_kern_features 340 #define __NR_kcmp 341 +#define __NR_finit_module 342 -#define NR_syscalls 342 +#define NR_syscalls 343 /* Bitmask values returned from kern_features system call. */ #define KERN_FEATURE_MIXED_MODE_STACK 0x00000001 diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index 04bacce76fe..baf4366e2d6 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -378,7 +378,8 @@ static void apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p) /* Cook up fake bus resources for SUNW,simba PCI bridges which lack * a proper 'ranges' property. */ -static void apb_fake_ranges(struct pci_dev *dev, struct pci_bus *bus, +static void apb_fake_ranges(struct pci_dev *dev, + struct pci_bus *bus, struct pci_pbm_info *pbm) { struct pci_bus_region region; @@ -403,13 +404,15 @@ static void apb_fake_ranges(struct pci_dev *dev, struct pci_bus *bus, pcibios_bus_to_resource(dev, res, ®ion); } -static void pci_of_scan_bus(struct pci_pbm_info *pbm, struct device_node *node, +static void pci_of_scan_bus(struct pci_pbm_info *pbm, + struct device_node *node, struct pci_bus *bus); #define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1]) static void of_scan_pci_bridge(struct pci_pbm_info *pbm, - struct device_node *node, struct pci_dev *dev) + struct device_node *node, + struct pci_dev *dev) { struct pci_bus *bus; const u32 *busrange, *ranges; @@ -500,7 +503,8 @@ after_ranges: pci_of_scan_bus(pbm, node, bus); } -static void pci_of_scan_bus(struct pci_pbm_info *pbm, struct device_node *node, +static void pci_of_scan_bus(struct pci_pbm_info *pbm, + struct device_node *node, struct pci_bus *bus) { struct device_node *child; diff --git a/arch/sparc/kernel/pci_psycho.c b/arch/sparc/kernel/pci_psycho.c index b8523828971..c647634ead2 100644 --- a/arch/sparc/kernel/pci_psycho.c +++ b/arch/sparc/kernel/pci_psycho.c @@ -366,7 +366,8 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) pci_config_write8(addr, 64); } -static void psycho_scan_bus(struct pci_pbm_info *pbm, struct device *parent) +static void psycho_scan_bus(struct pci_pbm_info *pbm, + struct device *parent) { pbm_config_busmastering(pbm); pbm->is_66mhz_capable = 0; diff --git a/arch/sparc/kernel/pci_sabre.c b/arch/sparc/kernel/pci_sabre.c index 531186d7c9a..6f00d27e8da 100644 --- a/arch/sparc/kernel/pci_sabre.c +++ b/arch/sparc/kernel/pci_sabre.c @@ -442,7 +442,8 @@ static void sabre_scan_bus(struct pci_pbm_info *pbm, struct device *parent) sabre_register_error_handlers(pbm); } -static void sabre_pbm_init(struct pci_pbm_info *pbm, struct platform_device *op) +static void sabre_pbm_init(struct pci_pbm_info *pbm, + struct platform_device *op) { psycho_pbm_init_common(pbm, op, "SABRE", PBM_CHIP_TYPE_SABRE); pbm->pci_afsr = pbm->controller_regs + SABRE_PIOAFSR; diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c index 29e888158ae..8f76f23dac3 100644 --- a/arch/sparc/kernel/pci_schizo.c +++ b/arch/sparc/kernel/pci_schizo.c @@ -1306,8 +1306,9 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) } } -static int schizo_pbm_init(struct pci_pbm_info *pbm, struct platform_device *op, - u32 portid, int chip_type) +static int schizo_pbm_init(struct pci_pbm_info *pbm, + struct platform_device *op, u32 portid, + int chip_type) { const struct linux_prom64_registers *regs; struct device_node *dp = op->dev.of_node; diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index 5147f574f12..6ac43c36bbb 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S @@ -85,4 +85,4 @@ sys_call_table: /*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init /*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime /*335*/ .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev -/*340*/ .long sys_ni_syscall, sys_kcmp +/*340*/ .long sys_ni_syscall, sys_kcmp, sys_finit_module diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index cdbd9b81775..1009ecb9267 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -86,7 +86,7 @@ sys_call_table32: .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init /*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev -/*340*/ .word sys_kern_features, sys_kcmp +/*340*/ .word sys_kern_features, sys_kcmp, sys_finit_module #endif /* CONFIG_COMPAT */ @@ -164,4 +164,4 @@ sys_call_table: .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init /*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev -/*340*/ .word sys_kern_features, sys_kcmp +/*340*/ .word sys_kern_features, sys_kcmp, sys_finit_module diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index b1942e22276..18e329ca108 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -302,7 +302,7 @@ static efi_status_t setup_efi_pci(struct boot_params *params) if (status != EFI_SUCCESS) continue; - if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) + if (!(attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)) continue; if (!pci->romimage || !pci->romsize) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 4428fd178bc..6774c17a557 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -340,9 +340,6 @@ int x86_setup_perfctr(struct perf_event *event) /* BTS is currently only allowed for user-mode. */ if (!attr->exclude_kernel) return -EOPNOTSUPP; - - if (!attr->exclude_guest) - return -EOPNOTSUPP; } hwc->config |= config; @@ -385,9 +382,6 @@ int x86_pmu_hw_config(struct perf_event *event) if (event->attr.precise_ip) { int precise = 0; - if (!event->attr.exclude_guest) - return -EOPNOTSUPP; - /* Support for constant skid */ if (x86_pmu.pebs_active && !x86_pmu.pebs_broken) { precise++; diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index ff84d5469d7..6ed91d9980e 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -1065,7 +1065,6 @@ ENTRY(xen_failsafe_callback) lea 16(%esp),%esp CFI_ADJUST_CFA_OFFSET -16 jz 5f - addl $16,%esp jmp iret_exc 5: pushl_cfi $-1 /* orig_ax = -1 => not a system call */ SAVE_ALL diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 08b973f6403..9c2bd8bd4b4 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -43,6 +43,7 @@ #include <asm/apicdef.h> #include <asm/hypervisor.h> #include <asm/kvm_guest.h> +#include <asm/context_tracking.h> static int kvmapf = 1; @@ -121,6 +122,8 @@ void kvm_async_pf_task_wait(u32 token) struct kvm_task_sleep_node n, *e; DEFINE_WAIT(wait); + rcu_irq_enter(); + spin_lock(&b->lock); e = _find_apf_task(b, token); if (e) { @@ -128,6 +131,8 @@ void kvm_async_pf_task_wait(u32 token) hlist_del(&e->link); kfree(e); spin_unlock(&b->lock); + + rcu_irq_exit(); return; } @@ -152,13 +157,16 @@ void kvm_async_pf_task_wait(u32 token) /* * We cannot reschedule. So halt. */ + rcu_irq_exit(); native_safe_halt(); + rcu_irq_enter(); local_irq_disable(); } } if (!n.halted) finish_wait(&n.wq, &wait); + rcu_irq_exit(); return; } EXPORT_SYMBOL_GPL(kvm_async_pf_task_wait); @@ -252,10 +260,10 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code) break; case KVM_PV_REASON_PAGE_NOT_PRESENT: /* page is swapped out by the host. */ - rcu_irq_enter(); + exception_enter(regs); exit_idle(); kvm_async_pf_task_wait((u32)read_cr2()); - rcu_irq_exit(); + exception_exit(regs); break; case KVM_PV_REASON_PAGE_READY: rcu_irq_enter(); diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 23ddd558fbd..00f6c1472b8 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -610,6 +610,83 @@ static __init void reserve_ibft_region(void) static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10; +static bool __init snb_gfx_workaround_needed(void) +{ +#ifdef CONFIG_PCI + int i; + u16 vendor, devid; + static const __initconst u16 snb_ids[] = { + 0x0102, + 0x0112, + 0x0122, + 0x0106, + 0x0116, + 0x0126, + 0x010a, + }; + + /* Assume no if something weird is going on with PCI */ + if (!early_pci_allowed()) + return false; + + vendor = read_pci_config_16(0, 2, 0, PCI_VENDOR_ID); + if (vendor != 0x8086) + return false; + + devid = read_pci_config_16(0, 2, 0, PCI_DEVICE_ID); + for (i = 0; i < ARRAY_SIZE(snb_ids); i++) + if (devid == snb_ids[i]) + return true; +#endif + + return false; +} + +/* + * Sandy Bridge graphics has trouble with certain ranges, exclude + * them from allocation. + */ +static void __init trim_snb_memory(void) +{ + static const __initconst unsigned long bad_pages[] = { + 0x20050000, + 0x20110000, + 0x20130000, + 0x20138000, + 0x40004000, + }; + int i; + + if (!snb_gfx_workaround_needed()) + return; + + printk(KERN_DEBUG "reserving inaccessible SNB gfx pages\n"); + + /* + * Reserve all memory below the 1 MB mark that has not + * already been reserved. + */ + memblock_reserve(0, 1<<20); + + for (i = 0; i < ARRAY_SIZE(bad_pages); i++) { + if (memblock_reserve(bad_pages[i], PAGE_SIZE)) + printk(KERN_WARNING "failed to reserve 0x%08lx\n", + bad_pages[i]); + } +} + +/* + * Here we put platform-specific memory range workarounds, i.e. + * memory known to be corrupt or otherwise in need to be reserved on + * specific platforms. + * + * If this gets used more widely it could use a real dispatch mechanism. + */ +static void __init trim_platform_memory_ranges(void) +{ + trim_snb_memory(); +} + static void __init trim_bios_range(void) { /* @@ -630,6 +707,7 @@ static void __init trim_bios_range(void) * take them out. */ e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1); + sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); } @@ -908,6 +986,8 @@ void __init setup_arch(char **cmdline_p) setup_real_mode(); + trim_platform_memory_ranges(); + init_gbpages(); /* max_pfn_mapped is updated here */ diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c index cd3b2438a98..9b4d51d0c0d 100644 --- a/arch/x86/kernel/step.c +++ b/arch/x86/kernel/step.c @@ -165,10 +165,11 @@ void set_task_blockstep(struct task_struct *task, bool on) * Ensure irq/preemption can't change debugctl in between. * Note also that both TIF_BLOCKSTEP and debugctl should * be changed atomically wrt preemption. - * FIXME: this means that set/clear TIF_BLOCKSTEP is simply - * wrong if task != current, SIGKILL can wakeup the stopped - * tracee and set/clear can play with the running task, this - * can confuse the next __switch_to_xtra(). + * + * NOTE: this means that set/clear TIF_BLOCKSTEP is only safe if + * task is current or it can't be running, otherwise we can race + * with __switch_to_xtra(). We rely on ptrace_freeze_traced() but + * PTRACE_KILL is not safe. */ local_irq_disable(); debugctl = get_debugctlmsr(); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 76f54461f7c..c243b81e3c7 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -120,7 +120,7 @@ struct kvm_shared_msrs { }; static struct kvm_shared_msrs_global __read_mostly shared_msrs_global; -static DEFINE_PER_CPU(struct kvm_shared_msrs, shared_msrs); +static struct kvm_shared_msrs __percpu *shared_msrs; struct kvm_stats_debugfs_item debugfs_entries[] = { { "pf_fixed", VCPU_STAT(pf_fixed) }, @@ -191,10 +191,10 @@ static void kvm_on_user_return(struct user_return_notifier *urn) static void shared_msr_update(unsigned slot, u32 msr) { - struct kvm_shared_msrs *smsr; u64 value; + unsigned int cpu = smp_processor_id(); + struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu); - smsr = &__get_cpu_var(shared_msrs); /* only read, and nobody should modify it at this time, * so don't need lock */ if (slot >= shared_msrs_global.nr) { @@ -226,7 +226,8 @@ static void kvm_shared_msr_cpu_online(void) void kvm_set_shared_msr(unsigned slot, u64 value, u64 mask) { - struct kvm_shared_msrs *smsr = &__get_cpu_var(shared_msrs); + unsigned int cpu = smp_processor_id(); + struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu); if (((value ^ smsr->values[slot].curr) & mask) == 0) return; @@ -242,7 +243,8 @@ EXPORT_SYMBOL_GPL(kvm_set_shared_msr); static void drop_user_return_notifiers(void *ignore) { - struct kvm_shared_msrs *smsr = &__get_cpu_var(shared_msrs); + unsigned int cpu = smp_processor_id(); + struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu); if (smsr->registered) kvm_on_user_return(&smsr->urn); @@ -5233,9 +5235,16 @@ int kvm_arch_init(void *opaque) goto out; } + r = -ENOMEM; + shared_msrs = alloc_percpu(struct kvm_shared_msrs); + if (!shared_msrs) { + printk(KERN_ERR "kvm: failed to allocate percpu kvm_shared_msrs\n"); + goto out; + } + r = kvm_mmu_module_init(); if (r) - goto out; + goto out_free_percpu; kvm_set_mmio_spte_mask(); kvm_init_msr_list(); @@ -5258,6 +5267,8 @@ int kvm_arch_init(void *opaque) return 0; +out_free_percpu: + free_percpu(shared_msrs); out: return r; } @@ -5275,6 +5286,7 @@ void kvm_arch_exit(void) #endif kvm_x86_ops = NULL; kvm_mmu_module_exit(); + free_percpu(shared_msrs); } int kvm_emulate_halt(struct kvm_vcpu *vcpu) diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 4f7d2599b48..34bc4cee888 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -432,13 +432,6 @@ static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */ play_dead_common(); HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); cpu_bringup(); - /* - * Balance out the preempt calls - as we are running in cpu_idle - * loop which has been called at bootup from cpu_bringup_and_idle. - * The cpucpu_bringup_and_idle called cpu_bringup which made a - * preempt_disable() So this preempt_enable will balance it out. - */ - preempt_enable(); } #else /* !CONFIG_HOTPLUG_CPU */ diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 00a783661d0..46f80e2c92f 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -590,6 +590,9 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr, if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 && *access_bit_width < 32) *access_bit_width = 32; + else if (bit_width == 64 && bit_offset == 0 && (*paddr & 0x07) == 0 && + *access_bit_width < 64) + *access_bit_width = 64; if ((bit_width + bit_offset) > *access_bit_width) { pr_warning(FW_BUG APEI_PFX diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 95af6f674a6..35da1811321 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -297,7 +297,7 @@ static int acpi_platform_notify(struct device *dev) if (!ret) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - acpi_get_name(dev->acpi_handle, ACPI_FULL_PATHNAME, &buffer); + acpi_get_name(ACPI_HANDLE(dev), ACPI_FULL_PATHNAME, &buffer); DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer); kfree(buffer.pointer); } else diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f1a5da44591..ed9a1cc690b 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -958,6 +958,9 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) return -EINVAL; } + if (!dev) + return -EINVAL; + dev->cpu = pr->id; if (max_cstate == 0) @@ -1149,6 +1152,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) } /* Populate Updated C-state information */ + acpi_processor_get_power_info(pr); acpi_processor_setup_cpuidle_states(pr); /* Enable all cpuidle devices */ diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 836bfe06904..53e7ac9403a 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -340,6 +340,13 @@ static void amd_fixup_frequency(struct acpi_processor_px *px, int i) if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) || boot_cpu_data.x86 == 0x11) { rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi); + /* + * MSR C001_0064+: + * Bit 63: PstateEn. Read-write. If set, the P-state is valid. + */ + if (!(hi & BIT(31))) + return; + fid = lo & 0x3f; did = (lo >> 6) & 7; if (boot_cpu_data.x86 == 0x10) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 7862d17976b..49791273256 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -53,6 +53,7 @@ enum { AHCI_PCI_BAR_STA2X11 = 0, + AHCI_PCI_BAR_ENMOTUS = 2, AHCI_PCI_BAR_STANDARD = 5, }; @@ -410,6 +411,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ + /* Enmotus */ + { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, + /* Generic, PCI class code for AHCI */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, @@ -1098,9 +1102,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev_info(&pdev->dev, "PDC42819 can only drive SATA devices with this driver\n"); - /* The Connext uses non-standard BAR */ + /* Both Connext and Enmotus devices use non-standard BARs */ if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) ahci_pci_bar = AHCI_PCI_BAR_STA2X11; + else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) + ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; /* acquire resources */ rc = pcim_enable_device(pdev); diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 320712a7b9e..6cd7805e47c 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1951,13 +1951,13 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) /* Use the nominal value 10 ms if the read MDAT is zero, * the nominal value of DETO is 20 ms. */ - if (dev->sata_settings[ATA_LOG_DEVSLP_VALID] & + if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] & ATA_LOG_DEVSLP_VALID_MASK) { - mdat = dev->sata_settings[ATA_LOG_DEVSLP_MDAT] & + mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] & ATA_LOG_DEVSLP_MDAT_MASK; if (!mdat) mdat = 10; - deto = dev->sata_settings[ATA_LOG_DEVSLP_DETO]; + deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO]; if (!deto) deto = 20; } else { diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 9e8b99af400..46cd3f4c6aa 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2325,24 +2325,28 @@ int ata_dev_configure(struct ata_device *dev) } } - /* check and mark DevSlp capability */ - if (ata_id_has_devslp(dev->id)) - dev->flags |= ATA_DFLAG_DEVSLP; - - /* Obtain SATA Settings page from Identify Device Data Log, - * which contains DevSlp timing variables etc. - * Exclude old devices with ata_id_has_ncq() + /* Check and mark DevSlp capability. Get DevSlp timing variables + * from SATA Settings page of Identify Device Data Log. */ - if (ata_id_has_ncq(dev->id)) { + if (ata_id_has_devslp(dev->id)) { + u8 sata_setting[ATA_SECT_SIZE]; + int i, j; + + dev->flags |= ATA_DFLAG_DEVSLP; err_mask = ata_read_log_page(dev, ATA_LOG_SATA_ID_DEV_DATA, ATA_LOG_SATA_SETTINGS, - dev->sata_settings, + sata_setting, 1); if (err_mask) ata_dev_dbg(dev, "failed to get Identify Device Data, Emask 0x%x\n", err_mask); + else + for (i = 0; i < ATA_LOG_DEVSLP_SIZE; i++) { + j = ATA_LOG_DEVSLP_OFFSET + i; + dev->devslp_timing[i] = sata_setting[j]; + } } dev->cdb_len = 16; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index bf039b0e97b..bcf4437214f 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2094,7 +2094,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, */ static inline int ata_eh_worth_retry(struct ata_queued_cmd *qc) { - if (qc->flags & AC_ERR_MEDIA) + if (qc->err_mask & AC_ERR_MEDIA) return 0; /* don't retry media errors */ if (qc->flags & ATA_QCFLAG_IO) return 1; /* otherwise retry anything from fs stack */ diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 63452943abd..fb10728f637 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -224,7 +224,7 @@ static void cpu_device_release(struct device *dev) * by the cpu device. * * Never copy this way of doing things, or you too will be made fun of - * on the linux-kerenl list, you have been warned. + * on the linux-kernel list, you have been warned. */ } diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index d8146030918..b392b353be3 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -305,7 +305,7 @@ static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf char *buf; size = fw_file_size(file); - if (size < 0) + if (size <= 0) return false; buf = vmalloc(size); if (!buf) diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 07aad786f81..d9a6c94ce42 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -56,6 +56,19 @@ static const struct file_operations regmap_name_fops = { .llseek = default_llseek, }; +static void regmap_debugfs_free_dump_cache(struct regmap *map) +{ + struct regmap_debugfs_off_cache *c; + + while (!list_empty(&map->debugfs_off_cache)) { + c = list_first_entry(&map->debugfs_off_cache, + struct regmap_debugfs_off_cache, + list); + list_del(&c->list); + kfree(c); + } +} + /* * Work out where the start offset maps into register numbers, bearing * in mind that we suppress hidden registers. @@ -91,8 +104,10 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, /* No cache entry? Start a new one */ if (!c) { c = kzalloc(sizeof(*c), GFP_KERNEL); - if (!c) - break; + if (!c) { + regmap_debugfs_free_dump_cache(map); + return base; + } c->min = p; c->base_reg = i; } @@ -101,14 +116,32 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, } } + /* Close the last entry off if we didn't scan beyond it */ + if (c) { + c->max = p - 1; + list_add_tail(&c->list, + &map->debugfs_off_cache); + } + + /* + * This should never happen; we return above if we fail to + * allocate and we should never be in this code if there are + * no registers at all. + */ + if (list_empty(&map->debugfs_off_cache)) { + WARN_ON(list_empty(&map->debugfs_off_cache)); + return base; + } + /* Find the relevant block */ list_for_each_entry(c, &map->debugfs_off_cache, list) { - if (*pos >= c->min && *pos <= c->max) { + if (from >= c->min && from <= c->max) { *pos = c->min; return c->base_reg; } - ret = c->max; + *pos = c->min; + ret = c->base_reg; } return ret; @@ -387,16 +420,8 @@ void regmap_debugfs_init(struct regmap *map, const char *name) void regmap_debugfs_exit(struct regmap *map) { - struct regmap_debugfs_off_cache *c; - debugfs_remove_recursive(map->debugfs); - while (!list_empty(&map->debugfs_off_cache)) { - c = list_first_entry(&map->debugfs_off_cache, - struct regmap_debugfs_off_cache, - list); - list_del(&c->list); - kfree(c); - } + regmap_debugfs_free_dump_cache(map); kfree(map->debugfs_name); } diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 42d5cb0f503..f00b059c057 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1106,7 +1106,7 @@ EXPORT_SYMBOL_GPL(regmap_raw_write); * @val_count: Number of registers to write * * This function is intended to be used for writing a large block of - * data to be device either in single transfer or multiple transfer. + * data to the device either in single transfer or multiple transfer. * * A value of zero will be returned on success, a negative errno will * be returned in error cases. diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 9d8409c0208..8ad21a25bc0 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -889,6 +889,7 @@ static void virtblk_remove(struct virtio_device *vdev) { struct virtio_blk *vblk = vdev->priv; int index = vblk->index; + int refc; /* Prevent config work handler from accessing the device. */ mutex_lock(&vblk->config_lock); @@ -903,11 +904,15 @@ static void virtblk_remove(struct virtio_device *vdev) flush_work(&vblk->config_work); + refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount); put_disk(vblk->disk); mempool_destroy(vblk->pool); vdev->config->del_vqs(vdev); kfree(vblk); - ida_simple_remove(&vd_index_ida, index); + + /* Only free device id if we don't have any users */ + if (refc == 1) + ida_simple_remove(&vd_index_ida, index); } #ifdef CONFIG_PM diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c index ff004578a11..9dd2551a0a4 100644 --- a/drivers/clk/mvebu/clk-cpu.c +++ b/drivers/clk/mvebu/clk-cpu.c @@ -124,7 +124,7 @@ void __init of_cpu_clk_setup(struct device_node *node) clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL); if (WARN_ON(!clks)) - return; + goto clks_out; for_each_node_by_type(dn, "cpu") { struct clk_init_data init; @@ -134,11 +134,11 @@ void __init of_cpu_clk_setup(struct device_node *node) int cpu, err; if (WARN_ON(!clk_name)) - return; + goto bail_out; err = of_property_read_u32(dn, "reg", &cpu); if (WARN_ON(err)) - return; + goto bail_out; sprintf(clk_name, "cpu%d", cpu); parent_clk = of_clk_get(node, 0); @@ -167,6 +167,9 @@ void __init of_cpu_clk_setup(struct device_node *node) return; bail_out: kfree(clks); + while(ncpus--) + kfree(cpuclk[ncpus].clk_name); +clks_out: kfree(cpuclk); } diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a32b7a9c65d..7d978c1bd52 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -28,6 +28,9 @@ config ARMADA_370_XP_TIMER config SUNXI_TIMER bool +config VT8500_TIMER + bool + config CLKSRC_NOMADIK_MTU bool depends on (ARCH_NOMADIK || ARCH_U8500) diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index b5cc50796a8..596c45c2f19 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -18,5 +18,6 @@ obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o obj-$(CONFIG_SUNXI_TIMER) += sunxi_timer.o obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o +obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o obj-$(CONFIG_CLKSRC_ARM_GENERIC) += arm_generic.o diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c index 7f796d8f750..50c68fef944 100644 --- a/drivers/clocksource/bcm2835_timer.c +++ b/drivers/clocksource/bcm2835_timer.c @@ -16,7 +16,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/bcm2835_timer.h> #include <linux/bitops.h> #include <linux/clockchips.h> #include <linux/clocksource.h> @@ -101,7 +100,7 @@ static struct of_device_id bcm2835_time_match[] __initconst = { {} }; -void __init bcm2835_timer_init(void) +static void __init bcm2835_timer_init(void) { struct device_node *node; void __iomem *base; @@ -155,3 +154,5 @@ void __init bcm2835_timer_init(void) pr_info("bcm2835: system timer (irq = %d)\n", irq); } +CLOCKSOURCE_OF_DECLARE(bcm2835, "brcm,bcm2835-system-timer", + bcm2835_timer_init); diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/cs5535-clockevt.c index d9279385304..ea210482dd2 100644 --- a/drivers/clocksource/cs5535-clockevt.c +++ b/drivers/clocksource/cs5535-clockevt.c @@ -100,7 +100,6 @@ static struct clock_event_device cs5535_clockevent = { .set_mode = mfgpt_set_mode, .set_next_event = mfgpt_next_event, .rating = 250, - .shift = 32 }; static irqreturn_t mfgpt_tick(int irq, void *dev_id) @@ -169,17 +168,11 @@ static int __init cs5535_mfgpt_init(void) cs5535_mfgpt_write(cs5535_event_clock, MFGPT_REG_SETUP, val); /* Set up the clock event */ - cs5535_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC, - cs5535_clockevent.shift); - cs5535_clockevent.min_delta_ns = clockevent_delta2ns(0xF, - &cs5535_clockevent); - cs5535_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFE, - &cs5535_clockevent); - printk(KERN_INFO DRV_NAME ": Registering MFGPT timer as a clock event, using IRQ %d\n", timer_irq); - clockevents_register_device(&cs5535_clockevent); + clockevents_config_and_register(&cs5535_clockevent, MFGPT_HZ, + 0xF, 0xFFFE); return 0; diff --git a/drivers/clocksource/sunxi_timer.c b/drivers/clocksource/sunxi_timer.c index 6c2ed56e8b1..0ce85e29769 100644 --- a/drivers/clocksource/sunxi_timer.c +++ b/drivers/clocksource/sunxi_timer.c @@ -74,7 +74,6 @@ static int sunxi_clkevt_next_event(unsigned long evt, static struct clock_event_device sunxi_clockevent = { .name = "sunxi_tick", - .shift = 32, .rating = 300, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_mode = sunxi_clkevt_mode, @@ -154,14 +153,8 @@ void __init sunxi_timer_init(void) val = readl(timer_base + TIMER_CTL_REG); writel(val | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG); - sunxi_clockevent.mult = div_sc(rate / TIMER_SCAL, - NSEC_PER_SEC, - sunxi_clockevent.shift); - sunxi_clockevent.max_delta_ns = clockevent_delta2ns(0xff, - &sunxi_clockevent); - sunxi_clockevent.min_delta_ns = clockevent_delta2ns(0x1, - &sunxi_clockevent); sunxi_clockevent.cpumask = cpumask_of(0); - clockevents_register_device(&sunxi_clockevent); + clockevents_config_and_register(&sunxi_clockevent, rate / TIMER_SCAL, + 0x1, 0xff); } diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c index 32cb929b8eb..8a6187225dd 100644 --- a/drivers/clocksource/tcb_clksrc.c +++ b/drivers/clocksource/tcb_clksrc.c @@ -157,7 +157,6 @@ static struct tc_clkevt_device clkevt = { .name = "tc_clkevt", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, /* Should be lower than at91rm9200's system timer */ .rating = 125, .set_next_event = tc_next_event, @@ -196,13 +195,9 @@ static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx) timer_clock = clk32k_divisor_idx; - clkevt.clkevt.mult = div_sc(32768, NSEC_PER_SEC, clkevt.clkevt.shift); - clkevt.clkevt.max_delta_ns - = clockevent_delta2ns(0xffff, &clkevt.clkevt); - clkevt.clkevt.min_delta_ns = clockevent_delta2ns(1, &clkevt.clkevt) + 1; clkevt.clkevt.cpumask = cpumask_of(0); - clockevents_register_device(&clkevt.clkevt); + clockevents_config_and_register(&clkevt.clkevt, 32768, 1, 0xffff); setup_irq(irq, &tc_irqaction); } diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c index 5bc14299de3..0bde03feb09 100644 --- a/drivers/clocksource/tegra20_timer.c +++ b/drivers/clocksource/tegra20_timer.c @@ -255,14 +255,10 @@ static void __init tegra20_init_timer(void) BUG(); } - clockevents_calc_mult_shift(&tegra_clockevent, 1000000, 5); - tegra_clockevent.max_delta_ns = - clockevent_delta2ns(0x1fffffff, &tegra_clockevent); - tegra_clockevent.min_delta_ns = - clockevent_delta2ns(0x1, &tegra_clockevent); tegra_clockevent.cpumask = cpu_all_mask; tegra_clockevent.irq = tegra_timer_irq.irq; - clockevents_register_device(&tegra_clockevent); + clockevents_config_and_register(&tegra_clockevent, 1000000, + 0x1, 0x1fffffff); #ifdef CONFIG_HAVE_ARM_TWD twd_local_timer_of_register(); #endif diff --git a/arch/arm/mach-vt8500/timer.c b/drivers/clocksource/vt8500_timer.c index 3dd21a47881..8efc86b5b5d 100644 --- a/arch/arm/mach-vt8500/timer.c +++ b/drivers/clocksource/vt8500_timer.c @@ -134,7 +134,7 @@ static struct of_device_id vt8500_timer_ids[] = { { } }; -void __init vt8500_timer_init(void) +static void __init vt8500_timer_init(void) { struct device_node *np; int timer_irq; @@ -168,17 +168,13 @@ void __init vt8500_timer_init(void) pr_err("%s: vt8500_timer_init: clocksource_register failed for %s\n", __func__, clocksource.name); - clockevents_calc_mult_shift(&clockevent, VT8500_TIMER_HZ, 4); - - /* copy-pasted from mach-msm; no idea */ - clockevent.max_delta_ns = - clockevent_delta2ns(0xf0000000, &clockevent); - clockevent.min_delta_ns = clockevent_delta2ns(4, &clockevent); clockevent.cpumask = cpumask_of(0); if (setup_irq(timer_irq, &irq)) pr_err("%s: setup_irq failed for %s\n", __func__, clockevent.name); - clockevents_register_device(&clockevent); + clockevents_config_and_register(&clockevent, VT8500_TIMER_HZ, + 4, 0xf0000000); } +CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init) diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86 index 934854ae5eb..7227cd73404 100644 --- a/drivers/cpufreq/Kconfig.x86 +++ b/drivers/cpufreq/Kconfig.x86 @@ -106,7 +106,7 @@ config X86_POWERNOW_K7_ACPI config X86_POWERNOW_K8 tristate "AMD Opteron/Athlon64 PowerNow!" select CPU_FREQ_TABLE - depends on ACPI && ACPI_PROCESSOR + depends on ACPI && ACPI_PROCESSOR && X86_ACPI_CPUFREQ help This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors. Support for K10 and newer processors is now in acpi-cpufreq. diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 0d048f6a2b2..7b0d49d78c6 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -1030,4 +1030,11 @@ MODULE_PARM_DESC(acpi_pstate_strict, late_initcall(acpi_cpufreq_init); module_exit(acpi_cpufreq_exit); +static const struct x86_cpu_id acpi_cpufreq_ids[] = { + X86_FEATURE_MATCH(X86_FEATURE_ACPI), + X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE), + {} +}; +MODULE_DEVICE_TABLE(x86cpu, acpi_cpufreq_ids); + MODULE_ALIAS("acpi"); diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index 52bf36d599f..debc5a7c8db 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -71,12 +71,15 @@ static int cpu0_set_target(struct cpufreq_policy *policy, } if (cpu_reg) { + rcu_read_lock(); opp = opp_find_freq_ceil(cpu_dev, &freq_Hz); if (IS_ERR(opp)) { + rcu_read_unlock(); pr_err("failed to find OPP for %ld\n", freq_Hz); return PTR_ERR(opp); } volt = opp_get_voltage(opp); + rcu_read_unlock(); tol = volt * voltage_tolerance / 100; volt_old = regulator_get_voltage(cpu_reg); } @@ -236,12 +239,14 @@ static int cpu0_cpufreq_driver_init(void) */ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) ; + rcu_read_lock(); opp = opp_find_freq_exact(cpu_dev, freq_table[0].frequency * 1000, true); min_uV = opp_get_voltage(opp); opp = opp_find_freq_exact(cpu_dev, freq_table[i-1].frequency * 1000, true); max_uV = opp_get_voltage(opp); + rcu_read_unlock(); ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV); if (ret > 0) transition_latency += ret * 1000; diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c index 4f154bc0ebe..523c9403bfc 100644 --- a/drivers/cpufreq/db8500-cpufreq.c +++ b/drivers/cpufreq/db8500-cpufreq.c @@ -167,9 +167,6 @@ static struct platform_driver db8500_cpufreq_plat_driver = { static int __init db8500_cpufreq_register(void) { - if (!cpu_is_u8500_family()) - return -ENODEV; - pr_info("cpufreq for DB8500 started\n"); return platform_driver_register(&db8500_cpufreq_plat_driver); } diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c index 7012ea8bf1e..caf638b585b 100644 --- a/drivers/cpufreq/exynos-cpufreq.c +++ b/drivers/cpufreq/exynos-cpufreq.c @@ -18,10 +18,10 @@ #include <linux/cpufreq.h> #include <linux/suspend.h> -#include <mach/cpufreq.h> - #include <plat/cpu.h> +#include "exynos-cpufreq.h" + static struct exynos_dvfs_info *exynos_info; static struct regulator *arm_regulator; diff --git a/arch/arm/mach-exynos/include/mach/cpufreq.h b/drivers/cpufreq/exynos-cpufreq.h index 7517c3f417a..25c748b9b91 100644 --- a/arch/arm/mach-exynos/include/mach/cpufreq.h +++ b/drivers/cpufreq/exynos-cpufreq.h @@ -1,5 +1,4 @@ -/* linux/arch/arm/mach-exynos/include/mach/cpufreq.h - * +/* * Copyright (c) 2010 Samsung Electronics Co., Ltd. * http://www.samsung.com * diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c index fb148fa2767..a5d0a818422 100644 --- a/drivers/cpufreq/exynos4210-cpufreq.c +++ b/drivers/cpufreq/exynos4210-cpufreq.c @@ -18,7 +18,8 @@ #include <linux/cpufreq.h> #include <mach/regs-clock.h> -#include <mach/cpufreq.h> + +#include "exynos-cpufreq.h" #define CPUFREQ_LEVEL_END L5 diff --git a/drivers/cpufreq/exynos4x12-cpufreq.c b/drivers/cpufreq/exynos4x12-cpufreq.c index 8c5a7afa5b0..63ff74eec52 100644 --- a/drivers/cpufreq/exynos4x12-cpufreq.c +++ b/drivers/cpufreq/exynos4x12-cpufreq.c @@ -18,7 +18,8 @@ #include <linux/cpufreq.h> #include <mach/regs-clock.h> -#include <mach/cpufreq.h> + +#include "exynos-cpufreq.h" #define CPUFREQ_LEVEL_END (L13 + 1) diff --git a/drivers/cpufreq/exynos5250-cpufreq.c b/drivers/cpufreq/exynos5250-cpufreq.c index e64c253cb16..407126c2d7c 100644 --- a/drivers/cpufreq/exynos5250-cpufreq.c +++ b/drivers/cpufreq/exynos5250-cpufreq.c @@ -19,7 +19,8 @@ #include <mach/map.h> #include <mach/regs-clock.h> -#include <mach/cpufreq.h> + +#include "exynos-cpufreq.h" #define CPUFREQ_LEVEL_END (L15 + 1) diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 1f3417a8322..97102b05843 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -110,13 +110,16 @@ static int omap_target(struct cpufreq_policy *policy, freq = ret; if (mpu_reg) { + rcu_read_lock(); opp = opp_find_freq_ceil(mpu_dev, &freq); if (IS_ERR(opp)) { + rcu_read_unlock(); dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n", __func__, freqs.new); return -EINVAL; } volt = opp_get_voltage(opp); + rcu_read_unlock(); tol = volt * OPP_TOLERANCE / 100; volt_old = regulator_get_voltage(mpu_reg); } diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index fb4a7dd57f9..e1f6860e069 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -69,24 +69,15 @@ int cpuidle_play_dead(void) { struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); - int i, dead_state = -1; - int power_usage = INT_MAX; + int i; if (!drv) return -ENODEV; /* Find lowest-power state that supports long-term idle */ - for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { - struct cpuidle_state *s = &drv->states[i]; - - if (s->power_usage < power_usage && s->enter_dead) { - power_usage = s->power_usage; - dead_state = i; - } - } - - if (dead_state != -1) - return drv->states[dead_state].enter_dead(dev, dead_state); + for (i = drv->state_count - 1; i >= CPUIDLE_DRIVER_STATE_START; i--) + if (drv->states[i].enter_dead) + return drv->states[i].enter_dead(dev, i); return -ENODEV; } diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index c2b281afe0e..422c7b69ba7 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -19,34 +19,9 @@ DEFINE_SPINLOCK(cpuidle_driver_lock); static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu); static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu); -static void set_power_states(struct cpuidle_driver *drv) -{ - int i; - - /* - * cpuidle driver should set the drv->power_specified bit - * before registering if the driver provides - * power_usage numbers. - * - * If power_specified is not set, - * we fill in power_usage with decreasing values as the - * cpuidle code has an implicit assumption that state Cn - * uses less power than C(n-1). - * - * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned - * an power value of -1. So we use -2, -3, etc, for other - * c-states. - */ - for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) - drv->states[i].power_usage = -1 - i; -} - static void __cpuidle_driver_init(struct cpuidle_driver *drv) { drv->refcnt = 0; - - if (!drv->power_specified) - set_power_states(drv); } static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu) diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 20ea33afdda..fe343a06b7d 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -312,7 +312,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) { struct menu_device *data = &__get_cpu_var(menu_devices); int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); - int power_usage = INT_MAX; int i; int multiplier; struct timespec t; @@ -383,11 +382,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) if (s->exit_latency * multiplier > data->predicted_us) continue; - if (s->power_usage < power_usage) { - power_usage = s->power_usage; - data->last_state_idx = i; - data->exit_us = s->exit_latency; - } + data->last_state_idx = i; + data->exit_us = s->exit_latency; } /* not deepest C-state chosen for low predicted residency */ diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 34094294610..428754af623 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -374,7 +374,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); /* state statistics */ - for (i = 0; i < drv->state_count; i++) { + for (i = 0; i < device->state_count; i++) { kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL); if (!kobj) goto error_state; diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 53766f39aad..3b367973a80 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -994,6 +994,11 @@ module_exit(devfreq_exit); * @freq: The frequency given to target function * @flags: Flags handed from devfreq framework. * + * Locking: This function must be called under rcu_read_lock(). opp is a rcu + * protected pointer. The reason for the same is that the opp pointer which is + * returned will remain valid for use with opp_get_{voltage, freq} only while + * under the locked area. The pointer returned must be used prior to unlocking + * with rcu_read_unlock() to maintain the integrity of the pointer. */ struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, u32 flags) diff --git a/drivers/devfreq/exynos4_bus.c b/drivers/devfreq/exynos4_bus.c index 80c745e8308..46d94e9e95b 100644 --- a/drivers/devfreq/exynos4_bus.c +++ b/drivers/devfreq/exynos4_bus.c @@ -73,6 +73,16 @@ enum busclk_level_idx { #define EX4210_LV_NUM (LV_2 + 1) #define EX4x12_LV_NUM (LV_4 + 1) +/** + * struct busfreq_opp_info - opp information for bus + * @rate: Frequency in hertz + * @volt: Voltage in microvolts corresponding to this OPP + */ +struct busfreq_opp_info { + unsigned long rate; + unsigned long volt; +}; + struct busfreq_data { enum exynos4_busf_type type; struct device *dev; @@ -80,7 +90,7 @@ struct busfreq_data { bool disabled; struct regulator *vdd_int; struct regulator *vdd_mif; /* Exynos4412/4212 only */ - struct opp *curr_opp; + struct busfreq_opp_info curr_oppinfo; struct exynos4_ppmu dmc[2]; struct notifier_block pm_notifier; @@ -296,13 +306,14 @@ static unsigned int exynos4x12_clkdiv_sclkip[][3] = { }; -static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp) +static int exynos4210_set_busclk(struct busfreq_data *data, + struct busfreq_opp_info *oppi) { unsigned int index; unsigned int tmp; for (index = LV_0; index < EX4210_LV_NUM; index++) - if (opp_get_freq(opp) == exynos4210_busclk_table[index].clk) + if (oppi->rate == exynos4210_busclk_table[index].clk) break; if (index == EX4210_LV_NUM) @@ -361,13 +372,14 @@ static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp) return 0; } -static int exynos4x12_set_busclk(struct busfreq_data *data, struct opp *opp) +static int exynos4x12_set_busclk(struct busfreq_data *data, + struct busfreq_opp_info *oppi) { unsigned int index; unsigned int tmp; for (index = LV_0; index < EX4x12_LV_NUM; index++) - if (opp_get_freq(opp) == exynos4x12_mifclk_table[index].clk) + if (oppi->rate == exynos4x12_mifclk_table[index].clk) break; if (index == EX4x12_LV_NUM) @@ -576,11 +588,12 @@ static int exynos4x12_get_intspec(unsigned long mifclk) return -EINVAL; } -static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, - struct opp *oldopp) +static int exynos4_bus_setvolt(struct busfreq_data *data, + struct busfreq_opp_info *oppi, + struct busfreq_opp_info *oldoppi) { int err = 0, tmp; - unsigned long volt = opp_get_voltage(opp); + unsigned long volt = oppi->volt; switch (data->type) { case TYPE_BUSF_EXYNOS4210: @@ -595,11 +608,11 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, if (err) break; - tmp = exynos4x12_get_intspec(opp_get_freq(opp)); + tmp = exynos4x12_get_intspec(oppi->rate); if (tmp < 0) { err = tmp; regulator_set_voltage(data->vdd_mif, - opp_get_voltage(oldopp), + oldoppi->volt, MAX_SAFEVOLT); break; } @@ -609,7 +622,7 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, /* Try to recover */ if (err) regulator_set_voltage(data->vdd_mif, - opp_get_voltage(oldopp), + oldoppi->volt, MAX_SAFEVOLT); break; default: @@ -626,17 +639,26 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, struct platform_device *pdev = container_of(dev, struct platform_device, dev); struct busfreq_data *data = platform_get_drvdata(pdev); - struct opp *opp = devfreq_recommended_opp(dev, _freq, flags); - unsigned long freq = opp_get_freq(opp); - unsigned long old_freq = opp_get_freq(data->curr_opp); + struct opp *opp; + unsigned long freq; + unsigned long old_freq = data->curr_oppinfo.rate; + struct busfreq_opp_info new_oppinfo; - if (IS_ERR(opp)) + rcu_read_lock(); + opp = devfreq_recommended_opp(dev, _freq, flags); + if (IS_ERR(opp)) { + rcu_read_unlock(); return PTR_ERR(opp); + } + new_oppinfo.rate = opp_get_freq(opp); + new_oppinfo.volt = opp_get_voltage(opp); + rcu_read_unlock(); + freq = new_oppinfo.rate; if (old_freq == freq) return 0; - dev_dbg(dev, "targetting %lukHz %luuV\n", freq, opp_get_voltage(opp)); + dev_dbg(dev, "targetting %lukHz %luuV\n", freq, new_oppinfo.volt); mutex_lock(&data->lock); @@ -644,17 +666,18 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, goto out; if (old_freq < freq) - err = exynos4_bus_setvolt(data, opp, data->curr_opp); + err = exynos4_bus_setvolt(data, &new_oppinfo, + &data->curr_oppinfo); if (err) goto out; if (old_freq != freq) { switch (data->type) { case TYPE_BUSF_EXYNOS4210: - err = exynos4210_set_busclk(data, opp); + err = exynos4210_set_busclk(data, &new_oppinfo); break; case TYPE_BUSF_EXYNOS4x12: - err = exynos4x12_set_busclk(data, opp); + err = exynos4x12_set_busclk(data, &new_oppinfo); break; default: err = -EINVAL; @@ -664,11 +687,12 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, goto out; if (old_freq > freq) - err = exynos4_bus_setvolt(data, opp, data->curr_opp); + err = exynos4_bus_setvolt(data, &new_oppinfo, + &data->curr_oppinfo); if (err) goto out; - data->curr_opp = opp; + data->curr_oppinfo = new_oppinfo; out: mutex_unlock(&data->lock); return err; @@ -702,7 +726,7 @@ static int exynos4_bus_get_dev_status(struct device *dev, exynos4_read_ppmu(data); busier_dmc = exynos4_get_busier_dmc(data); - stat->current_frequency = opp_get_freq(data->curr_opp); + stat->current_frequency = data->curr_oppinfo.rate; if (busier_dmc) addr = S5P_VA_DMC1; @@ -933,6 +957,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, struct busfreq_data *data = container_of(this, struct busfreq_data, pm_notifier); struct opp *opp; + struct busfreq_opp_info new_oppinfo; unsigned long maxfreq = ULONG_MAX; int err = 0; @@ -943,18 +968,29 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, data->disabled = true; + rcu_read_lock(); opp = opp_find_freq_floor(data->dev, &maxfreq); + if (IS_ERR(opp)) { + rcu_read_unlock(); + dev_err(data->dev, "%s: unable to find a min freq\n", + __func__); + return PTR_ERR(opp); + } + new_oppinfo.rate = opp_get_freq(opp); + new_oppinfo.volt = opp_get_voltage(opp); + rcu_read_unlock(); - err = exynos4_bus_setvolt(data, opp, data->curr_opp); + err = exynos4_bus_setvolt(data, &new_oppinfo, + &data->curr_oppinfo); if (err) goto unlock; switch (data->type) { case TYPE_BUSF_EXYNOS4210: - err = exynos4210_set_busclk(data, opp); + err = exynos4210_set_busclk(data, &new_oppinfo); break; case TYPE_BUSF_EXYNOS4x12: - err = exynos4x12_set_busclk(data, opp); + err = exynos4x12_set_busclk(data, &new_oppinfo); break; default: err = -EINVAL; @@ -962,7 +998,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, if (err) goto unlock; - data->curr_opp = opp; + data->curr_oppinfo = new_oppinfo; unlock: mutex_unlock(&data->lock); if (err) @@ -1027,13 +1063,17 @@ static int exynos4_busfreq_probe(struct platform_device *pdev) } } + rcu_read_lock(); opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq); if (IS_ERR(opp)) { + rcu_read_unlock(); dev_err(dev, "Invalid initial frequency %lu kHz.\n", exynos4_devfreq_profile.initial_freq); return PTR_ERR(opp); } - data->curr_opp = opp; + data->curr_oppinfo.rate = opp_get_freq(opp); + data->curr_oppinfo.volt = opp_get_voltage(opp); + rcu_read_unlock(); platform_set_drvdata(pdev, data); diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index dbf0e6f8de8..a7dcf78b1ff 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -684,9 +684,8 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, break; } - imxdmac->hw_chaining = 1; - if (!imxdma_hw_chain(imxdmac)) - return -EINVAL; + imxdmac->hw_chaining = 0; + imxdmac->ccr_from_device = (mode | IMX_DMA_TYPE_FIFO) | ((IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR) << 2) | CCR_REN; diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index e5fc944de1f..3e9d66920eb 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -951,7 +951,7 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device) goto free_resources; } } - dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_TO_DEVICE); + dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); /* skip validate if the capability is not present */ if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask)) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index c39e61bc817..3cad856fe67 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -266,6 +266,7 @@ static struct tegra_dma_desc *tegra_dma_desc_get( if (async_tx_test_ack(&dma_desc->txd)) { list_del(&dma_desc->node); spin_unlock_irqrestore(&tdc->lock, flags); + dma_desc->txd.flags = 0; return dma_desc; } } @@ -1050,7 +1051,9 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( TEGRA_APBDMA_AHBSEQ_WRAP_SHIFT; ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32; - csr |= TEGRA_APBDMA_CSR_FLOW | TEGRA_APBDMA_CSR_IE_EOC; + csr |= TEGRA_APBDMA_CSR_FLOW; + if (flags & DMA_PREP_INTERRUPT) + csr |= TEGRA_APBDMA_CSR_IE_EOC; csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1; @@ -1095,7 +1098,8 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( mem += len; } sg_req->last_sg = true; - dma_desc->txd.flags = 0; + if (flags & DMA_CTRL_ACK) + dma_desc->txd.flags = DMA_CTRL_ACK; /* * Make sure that mode should not be conflicting with currently diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 7d9bd94be8d..6819d63cb16 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -547,7 +547,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) mvchip->membase = devm_request_and_ioremap(&pdev->dev, res); if (! mvchip->membase) { dev_err(&pdev->dev, "Cannot ioremap\n"); - kfree(mvchip->chip.label); return -ENOMEM; } @@ -557,14 +556,12 @@ static int mvebu_gpio_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (! res) { dev_err(&pdev->dev, "Cannot get memory resource\n"); - kfree(mvchip->chip.label); return -ENODEV; } mvchip->percpu_membase = devm_request_and_ioremap(&pdev->dev, res); if (! mvchip->percpu_membase) { dev_err(&pdev->dev, "Cannot ioremap\n"); - kfree(mvchip->chip.label); return -ENOMEM; } } @@ -625,7 +622,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); if (mvchip->irqbase < 0) { dev_err(&pdev->dev, "no irqs\n"); - kfree(mvchip->chip.label); return -ENOMEM; } @@ -633,7 +629,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) mvchip->membase, handle_level_irq); if (! gc) { dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n"); - kfree(mvchip->chip.label); return -ENOMEM; } @@ -668,7 +663,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); kfree(gc); - kfree(mvchip->chip.label); return -ENODEV; } diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 01f7fe95559..edf1eb5cb12 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -32,14 +32,12 @@ #include <mach/hardware.h> #include <mach/map.h> -#include <mach/regs-clock.h> #include <mach/regs-gpio.h> #include <plat/cpu.h> #include <plat/gpio-core.h> #include <plat/gpio-cfg.h> #include <plat/gpio-cfg-helpers.h> -#include <plat/gpio-fns.h> #include <plat/pm.h> int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip, @@ -446,7 +444,7 @@ static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = { }; #endif -#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5) +#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_SOC_EXYNOS5250) static struct samsung_gpio_cfg exynos_gpio_cfg = { .set_pull = exynos_gpio_setpull, .get_pull = exynos_gpio_getpull, @@ -2446,7 +2444,7 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = { }; #endif -#ifdef CONFIG_ARCH_EXYNOS5 +#ifdef CONFIG_SOC_EXYNOS5250 static struct samsung_gpio_chip exynos5_gpios_1[] = { { .chip = { @@ -2614,7 +2612,7 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = { }; #endif -#ifdef CONFIG_ARCH_EXYNOS5 +#ifdef CONFIG_SOC_EXYNOS5250 static struct samsung_gpio_chip exynos5_gpios_2[] = { { .chip = { @@ -2675,7 +2673,7 @@ static struct samsung_gpio_chip exynos5_gpios_2[] = { }; #endif -#ifdef CONFIG_ARCH_EXYNOS5 +#ifdef CONFIG_SOC_EXYNOS5250 static struct samsung_gpio_chip exynos5_gpios_3[] = { { .chip = { @@ -2711,7 +2709,7 @@ static struct samsung_gpio_chip exynos5_gpios_3[] = { }; #endif -#ifdef CONFIG_ARCH_EXYNOS5 +#ifdef CONFIG_SOC_EXYNOS5250 static struct samsung_gpio_chip exynos5_gpios_4[] = { { .chip = { @@ -3010,7 +3008,7 @@ static __init int samsung_gpiolib_init(void) int i, nr_chips; int group = 0; -#ifdef CONFIG_PINCTRL_SAMSUNG +#if defined(CONFIG_PINCTRL_EXYNOS) || defined(CONFIG_PINCTRL_EXYNOS5440) /* * This gpio driver includes support for device tree support and there * are platforms using it. In order to maintain compatibility with those @@ -3026,6 +3024,7 @@ static __init int samsung_gpiolib_init(void) static const struct of_device_id exynos_pinctrl_ids[] = { { .compatible = "samsung,pinctrl-exynos4210", }, { .compatible = "samsung,pinctrl-exynos4x12", }, + { .compatible = "samsung,pinctrl-exynos5440", }, }; for_each_matching_node(pctrl_np, exynos_pinctrl_ids) if (pctrl_np && of_device_is_available(pctrl_np)) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 2bf9670ba29..2aa331499f8 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -221,11 +221,13 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, BUG_ON(!hole_node->hole_follows || node->allocated); - if (mm->color_adjust) - mm->color_adjust(hole_node, color, &adj_start, &adj_end); - if (adj_start < start) adj_start = start; + if (adj_end > end) + adj_end = end; + + if (mm->color_adjust) + mm->color_adjust(hole_node, color, &adj_start, &adj_end); if (alignment) { unsigned tmp = adj_start % alignment; @@ -506,7 +508,7 @@ void drm_mm_init_scan(struct drm_mm *mm, mm->scan_size = size; mm->scanned_blocks = 0; mm->scan_hit_start = 0; - mm->scan_hit_size = 0; + mm->scan_hit_end = 0; mm->scan_check_range = 0; mm->prev_scanned_node = NULL; } @@ -533,7 +535,7 @@ void drm_mm_init_scan_with_range(struct drm_mm *mm, mm->scan_size = size; mm->scanned_blocks = 0; mm->scan_hit_start = 0; - mm->scan_hit_size = 0; + mm->scan_hit_end = 0; mm->scan_start = start; mm->scan_end = end; mm->scan_check_range = 1; @@ -552,8 +554,7 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) struct drm_mm *mm = node->mm; struct drm_mm_node *prev_node; unsigned long hole_start, hole_end; - unsigned long adj_start; - unsigned long adj_end; + unsigned long adj_start, adj_end; mm->scanned_blocks++; @@ -570,14 +571,8 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) node->node_list.next = &mm->prev_scanned_node->node_list; mm->prev_scanned_node = node; - hole_start = drm_mm_hole_node_start(prev_node); - hole_end = drm_mm_hole_node_end(prev_node); - - adj_start = hole_start; - adj_end = hole_end; - - if (mm->color_adjust) - mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end); + adj_start = hole_start = drm_mm_hole_node_start(prev_node); + adj_end = hole_end = drm_mm_hole_node_end(prev_node); if (mm->scan_check_range) { if (adj_start < mm->scan_start) @@ -586,11 +581,14 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) adj_end = mm->scan_end; } + if (mm->color_adjust) + mm->color_adjust(prev_node, mm->scan_color, + &adj_start, &adj_end); + if (check_free_hole(adj_start, adj_end, mm->scan_size, mm->scan_alignment)) { mm->scan_hit_start = hole_start; - mm->scan_hit_size = hole_end; - + mm->scan_hit_end = hole_end; return 1; } @@ -626,19 +624,10 @@ int drm_mm_scan_remove_block(struct drm_mm_node *node) node_list); prev_node->hole_follows = node->scanned_preceeds_hole; - INIT_LIST_HEAD(&node->node_list); list_add(&node->node_list, &prev_node->node_list); - /* Only need to check for containement because start&size for the - * complete resulting free block (not just the desired part) is - * stored. */ - if (node->start >= mm->scan_hit_start && - node->start + node->size - <= mm->scan_hit_start + mm->scan_hit_size) { - return 1; - } - - return 0; + return (drm_mm_hole_node_end(node) > mm->scan_hit_start && + node->start < mm->scan_hit_end); } EXPORT_SYMBOL(drm_mm_scan_remove_block); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e6a11ca85ea..7944d301518 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -641,6 +641,7 @@ static void i915_ring_error_state(struct seq_file *m, seq_printf(m, "%s command stream:\n", ring_str(ring)); seq_printf(m, " HEAD: 0x%08x\n", error->head[ring]); seq_printf(m, " TAIL: 0x%08x\n", error->tail[ring]); + seq_printf(m, " CTL: 0x%08x\n", error->ctl[ring]); seq_printf(m, " ACTHD: 0x%08x\n", error->acthd[ring]); seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]); seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]); @@ -693,6 +694,8 @@ static int i915_error_state(struct seq_file *m, void *unused) seq_printf(m, "EIR: 0x%08x\n", error->eir); seq_printf(m, "IER: 0x%08x\n", error->ier); seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); + seq_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake); + seq_printf(m, "DERRMR: 0x%08x\n", error->derrmr); seq_printf(m, "CCID: 0x%08x\n", error->ccid); for (i = 0; i < dev_priv->num_fence_regs; i++) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ed305957557..12ab3bdea54 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -188,10 +188,13 @@ struct drm_i915_error_state { u32 pgtbl_er; u32 ier; u32 ccid; + u32 derrmr; + u32 forcewake; bool waiting[I915_NUM_RINGS]; u32 pipestat[I915_MAX_PIPES]; u32 tail[I915_NUM_RINGS]; u32 head[I915_NUM_RINGS]; + u32 ctl[I915_NUM_RINGS]; u32 ipeir[I915_NUM_RINGS]; u32 ipehr[I915_NUM_RINGS]; u32 instdone[I915_NUM_RINGS]; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index da3c82e301b..8febea6daa0 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1717,7 +1717,8 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj) } static long -i915_gem_purge(struct drm_i915_private *dev_priv, long target) +__i915_gem_shrink(struct drm_i915_private *dev_priv, long target, + bool purgeable_only) { struct drm_i915_gem_object *obj, *next; long count = 0; @@ -1725,7 +1726,7 @@ i915_gem_purge(struct drm_i915_private *dev_priv, long target) list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list, gtt_list) { - if (i915_gem_object_is_purgeable(obj) && + if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) && i915_gem_object_put_pages(obj) == 0) { count += obj->base.size >> PAGE_SHIFT; if (count >= target) @@ -1736,7 +1737,7 @@ i915_gem_purge(struct drm_i915_private *dev_priv, long target) list_for_each_entry_safe(obj, next, &dev_priv->mm.inactive_list, mm_list) { - if (i915_gem_object_is_purgeable(obj) && + if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) && i915_gem_object_unbind(obj) == 0 && i915_gem_object_put_pages(obj) == 0) { count += obj->base.size >> PAGE_SHIFT; @@ -1748,6 +1749,12 @@ i915_gem_purge(struct drm_i915_private *dev_priv, long target) return count; } +static long +i915_gem_purge(struct drm_i915_private *dev_priv, long target) +{ + return __i915_gem_shrink(dev_priv, target, true); +} + static void i915_gem_shrink_all(struct drm_i915_private *dev_priv) { @@ -3522,14 +3529,15 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, goto out; } - obj->user_pin_count++; - obj->pin_filp = file; - if (obj->user_pin_count == 1) { + if (obj->user_pin_count == 0) { ret = i915_gem_object_pin(obj, args->alignment, true, false); if (ret) goto out; } + obj->user_pin_count++; + obj->pin_filp = file; + /* XXX - flush the CPU caches for pinned objects * as the X server doesn't manage domains yet */ @@ -4395,6 +4403,9 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc) if (nr_to_scan) { nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan); if (nr_to_scan > 0) + nr_to_scan -= __i915_gem_shrink(dev_priv, nr_to_scan, + false); + if (nr_to_scan > 0) i915_gem_shrink_all(dev_priv); } @@ -4402,7 +4413,7 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc) list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list) if (obj->pages_pin_count == 0) cnt += obj->base.size >> PAGE_SHIFT; - list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) + list_for_each_entry(obj, &dev_priv->mm.inactive_list, gtt_list) if (obj->pin_count == 0 && obj->pages_pin_count == 0) cnt += obj->base.size >> PAGE_SHIFT; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index d6a994a0739..26d08bb5821 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -539,6 +539,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, total = 0; for (i = 0; i < count; i++) { struct drm_i915_gem_relocation_entry __user *user_relocs; + u64 invalid_offset = (u64)-1; + int j; user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr; @@ -549,6 +551,25 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, goto err; } + /* As we do not update the known relocation offsets after + * relocating (due to the complexities in lock handling), + * we need to mark them as invalid now so that we force the + * relocation processing next time. Just in case the target + * object is evicted and then rebound into its old + * presumed_offset before the next execbuffer - if that + * happened we would make the mistake of assuming that the + * relocations were valid. + */ + for (j = 0; j < exec[i].relocation_count; j++) { + if (copy_to_user(&user_relocs[j].presumed_offset, + &invalid_offset, + sizeof(invalid_offset))) { + ret = -EFAULT; + mutex_lock(&dev->struct_mutex); + goto err; + } + } + reloc_offset[i] = total; total += exec[i].relocation_count; } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2220dec3e5d..fe843389c7b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1157,6 +1157,7 @@ static void i915_record_ring_state(struct drm_device *dev, error->acthd[ring->id] = intel_ring_get_active_head(ring); error->head[ring->id] = I915_READ_HEAD(ring); error->tail[ring->id] = I915_READ_TAIL(ring); + error->ctl[ring->id] = I915_READ_CTL(ring); error->cpu_ring_head[ring->id] = ring->head; error->cpu_ring_tail[ring->id] = ring->tail; @@ -1251,6 +1252,16 @@ static void i915_capture_error_state(struct drm_device *dev) else error->ier = I915_READ(IER); + if (INTEL_INFO(dev)->gen >= 6) + error->derrmr = I915_READ(DERRMR); + + if (IS_VALLEYVIEW(dev)) + error->forcewake = I915_READ(FORCEWAKE_VLV); + else if (INTEL_INFO(dev)->gen >= 7) + error->forcewake = I915_READ(FORCEWAKE_MT); + else if (INTEL_INFO(dev)->gen == 6) + error->forcewake = I915_READ(FORCEWAKE); + for_each_pipe(pipe) error->pipestat[pipe] = I915_READ(PIPESTAT(pipe)); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 186ee5c85b5..b401788e179 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -512,6 +512,8 @@ #define GEN7_ERR_INT 0x44040 #define ERR_INT_MMIO_UNCLAIMED (1<<13) +#define DERRMR 0x44050 + /* GM45+ chicken bits -- debug workaround bits that may be required * for various sorts of correct behavior. The top 16 bits of each are * the enables for writing to the corresponding low bit. diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a9fb046b94a..da1ad9c80bb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8598,19 +8598,30 @@ int intel_framebuffer_init(struct drm_device *dev, { int ret; - if (obj->tiling_mode == I915_TILING_Y) + if (obj->tiling_mode == I915_TILING_Y) { + DRM_DEBUG("hardware does not support tiling Y\n"); return -EINVAL; + } - if (mode_cmd->pitches[0] & 63) + if (mode_cmd->pitches[0] & 63) { + DRM_DEBUG("pitch (%d) must be at least 64 byte aligned\n", + mode_cmd->pitches[0]); return -EINVAL; + } /* FIXME <= Gen4 stride limits are bit unclear */ - if (mode_cmd->pitches[0] > 32768) + if (mode_cmd->pitches[0] > 32768) { + DRM_DEBUG("pitch (%d) must be at less than 32768\n", + mode_cmd->pitches[0]); return -EINVAL; + } if (obj->tiling_mode != I915_TILING_NONE && - mode_cmd->pitches[0] != obj->stride) + mode_cmd->pitches[0] != obj->stride) { + DRM_DEBUG("pitch (%d) must match tiling stride (%d)\n", + mode_cmd->pitches[0], obj->stride); return -EINVAL; + } /* Reject formats not supported by any plane early. */ switch (mode_cmd->pixel_format) { @@ -8621,8 +8632,10 @@ int intel_framebuffer_init(struct drm_device *dev, break; case DRM_FORMAT_XRGB1555: case DRM_FORMAT_ARGB1555: - if (INTEL_INFO(dev)->gen > 3) + if (INTEL_INFO(dev)->gen > 3) { + DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format); return -EINVAL; + } break; case DRM_FORMAT_XBGR8888: case DRM_FORMAT_ABGR8888: @@ -8630,18 +8643,22 @@ int intel_framebuffer_init(struct drm_device *dev, case DRM_FORMAT_ARGB2101010: case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_ABGR2101010: - if (INTEL_INFO(dev)->gen < 4) + if (INTEL_INFO(dev)->gen < 4) { + DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format); return -EINVAL; + } break; case DRM_FORMAT_YUYV: case DRM_FORMAT_UYVY: case DRM_FORMAT_YVYU: case DRM_FORMAT_VYUY: - if (INTEL_INFO(dev)->gen < 6) + if (INTEL_INFO(dev)->gen < 5) { + DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format); return -EINVAL; + } break; default: - DRM_DEBUG_KMS("unsupported pixel format 0x%08x\n", mode_cmd->pixel_format); + DRM_DEBUG("unsupported pixel format 0x%08x\n", mode_cmd->pixel_format); return -EINVAL; } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1b63d55318a..fb3715b4b09 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2579,7 +2579,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect static void intel_dp_init_panel_power_sequencer(struct drm_device *dev, - struct intel_dp *intel_dp) + struct intel_dp *intel_dp, + struct edp_power_seq *out) { struct drm_i915_private *dev_priv = dev->dev_private; struct edp_power_seq cur, vbt, spec, final; @@ -2650,16 +2651,35 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, intel_dp->panel_power_cycle_delay = get_delay(t11_t12); #undef get_delay + DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", + intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay, + intel_dp->panel_power_cycle_delay); + + DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", + intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); + + if (out) + *out = final; +} + +static void +intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, + struct intel_dp *intel_dp, + struct edp_power_seq *seq) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 pp_on, pp_off, pp_div; + /* And finally store the new values in the power sequencer. */ - pp_on = (final.t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) | - (final.t8 << PANEL_LIGHT_ON_DELAY_SHIFT); - pp_off = (final.t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) | - (final.t10 << PANEL_POWER_DOWN_DELAY_SHIFT); + pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) | + (seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT); + pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) | + (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT); /* Compute the divisor for the pp clock, simply match the Bspec * formula. */ pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1) << PP_REFERENCE_DIVIDER_SHIFT; - pp_div |= (DIV_ROUND_UP(final.t11_t12, 1000) + pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000) << PANEL_POWER_CYCLE_DELAY_SHIFT); /* Haswell doesn't have any port selection bits for the panel @@ -2675,14 +2695,6 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, I915_WRITE(PCH_PP_OFF_DELAYS, pp_off); I915_WRITE(PCH_PP_DIVISOR, pp_div); - - DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", - intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay, - intel_dp->panel_power_cycle_delay); - - DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", - intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); - DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n", I915_READ(PCH_PP_ON_DELAYS), I915_READ(PCH_PP_OFF_DELAYS), @@ -2699,6 +2711,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, struct drm_device *dev = intel_encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_display_mode *fixed_mode = NULL; + struct edp_power_seq power_seq = { 0 }; enum port port = intel_dig_port->port; const char *name = NULL; int type; @@ -2771,7 +2784,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, } if (is_edp(intel_dp)) - intel_dp_init_panel_power_sequencer(dev, intel_dp); + intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); intel_dp_i2c_init(intel_dp, intel_connector, name); @@ -2798,6 +2811,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, return; } + /* We now know it's not a ghost, init power sequence regs. */ + intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, + &power_seq); + ironlake_edp_panel_vdd_on(intel_dp); edid = drm_get_edid(connector, &intel_dp->adapter); if (edid) { diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index b9a660a5367..17aee74258a 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -776,14 +776,6 @@ static const struct dmi_system_id intel_no_lvds[] = { }, { .callback = intel_no_lvds_dmi_callback, - .ident = "ZOTAC ZBOXSD-ID12/ID13", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"), - DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"), - }, - }, - { - .callback = intel_no_lvds_dmi_callback, .ident = "Gigabyte GA-D525TUD", .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e6f54ffab3b..3280cffe50f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -44,6 +44,14 @@ * i915.i915_enable_fbc parameter */ +static bool intel_crtc_active(struct drm_crtc *crtc) +{ + /* Be paranoid as we can arrive here with only partial + * state retrieved from the hardware during setup. + */ + return to_intel_crtc(crtc)->active && crtc->fb && crtc->mode.clock; +} + static void i8xx_disable_fbc(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -405,9 +413,8 @@ void intel_update_fbc(struct drm_device *dev) * - going to an unsupported config (interlace, pixel multiply, etc.) */ list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { - if (to_intel_crtc(tmp_crtc)->active && - !to_intel_crtc(tmp_crtc)->primary_disabled && - tmp_crtc->fb) { + if (intel_crtc_active(tmp_crtc) && + !to_intel_crtc(tmp_crtc)->primary_disabled) { if (crtc) { DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; @@ -992,7 +999,7 @@ static struct drm_crtc *single_enabled_crtc(struct drm_device *dev) struct drm_crtc *crtc, *enabled = NULL; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (to_intel_crtc(crtc)->active && crtc->fb) { + if (intel_crtc_active(crtc)) { if (enabled) return NULL; enabled = crtc; @@ -1086,7 +1093,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, int entries, tlb_miss; crtc = intel_get_crtc_for_plane(dev, plane); - if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) { + if (!intel_crtc_active(crtc)) { *cursor_wm = cursor->guard_size; *plane_wm = display->guard_size; return false; @@ -1215,7 +1222,7 @@ static bool vlv_compute_drain_latency(struct drm_device *dev, int entries; crtc = intel_get_crtc_for_plane(dev, plane); - if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) + if (!intel_crtc_active(crtc)) return false; clock = crtc->mode.clock; /* VESA DOT Clock */ @@ -1476,7 +1483,7 @@ static void i9xx_update_wm(struct drm_device *dev) fifo_size = dev_priv->display.get_fifo_size(dev, 0); crtc = intel_get_crtc_for_plane(dev, 0); - if (to_intel_crtc(crtc)->active && crtc->fb) { + if (intel_crtc_active(crtc)) { int cpp = crtc->fb->bits_per_pixel / 8; if (IS_GEN2(dev)) cpp = 4; @@ -1490,7 +1497,7 @@ static void i9xx_update_wm(struct drm_device *dev) fifo_size = dev_priv->display.get_fifo_size(dev, 1); crtc = intel_get_crtc_for_plane(dev, 1); - if (to_intel_crtc(crtc)->active && crtc->fb) { + if (intel_crtc_active(crtc)) { int cpp = crtc->fb->bits_per_pixel / 8; if (IS_GEN2(dev)) cpp = 4; @@ -2044,7 +2051,7 @@ sandybridge_compute_sprite_wm(struct drm_device *dev, int plane, int entries, tlb_miss; crtc = intel_get_crtc_for_plane(dev, plane); - if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) { + if (!intel_crtc_active(crtc)) { *sprite_wm = display->guard_size; return false; } @@ -4243,7 +4250,8 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff)); - POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ + /* something from same cacheline, but !FORCEWAKE_MT */ + POSTING_READ(ECOBUS); } static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) @@ -4260,7 +4268,8 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); - POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ + /* something from same cacheline, but !FORCEWAKE_MT */ + POSTING_READ(ECOBUS); if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1), FORCEWAKE_ACK_TIMEOUT_MS)) @@ -4297,14 +4306,16 @@ void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE, 0); - /* gen6_gt_check_fifodbg doubles as the POSTING_READ */ + /* something from same cacheline, but !FORCEWAKE */ + POSTING_READ(ECOBUS); gen6_gt_check_fifodbg(dev_priv); } static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); - /* gen6_gt_check_fifodbg doubles as the POSTING_READ */ + /* something from same cacheline, but !FORCEWAKE_MT */ + POSTING_READ(ECOBUS); gen6_gt_check_fifodbg(dev_priv); } @@ -4344,6 +4355,8 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) static void vlv_force_wake_reset(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff)); + /* something from same cacheline, but !FORCEWAKE_VLV */ + POSTING_READ(FORCEWAKE_ACK_VLV); } static void vlv_force_wake_get(struct drm_i915_private *dev_priv) @@ -4364,7 +4377,8 @@ static void vlv_force_wake_get(struct drm_i915_private *dev_priv) static void vlv_force_wake_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); - /* The below doubles as a POSTING_READ */ + /* something from same cacheline, but !FORCEWAKE_VLV */ + POSTING_READ(FORCEWAKE_ACK_VLV); gen6_gt_check_fifodbg(dev_priv); } diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 827dcd4edf1..d7b060e0a23 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -120,11 +120,10 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); - linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); + linear_offset = y * fb->pitches[0] + x * pixel_size; sprsurf_offset = intel_gen4_compute_offset_xtiled(&x, &y, - fb->bits_per_pixel / 8, - fb->pitches[0]); + pixel_size, fb->pitches[0]); linear_offset -= sprsurf_offset; /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET @@ -286,11 +285,10 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x); - linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); + linear_offset = y * fb->pitches[0] + x * pixel_size; dvssurf_offset = intel_gen4_compute_offset_xtiled(&x, &y, - fb->bits_per_pixel / 8, - fb->pitches[0]); + pixel_size, fb->pitches[0]); linear_offset -= dvssurf_offset; if (obj->tiling_mode != I915_TILING_NONE) diff --git a/drivers/gpu/drm/nouveau/core/core/client.c b/drivers/gpu/drm/nouveau/core/core/client.c index c617f048007..8bbb58f94a1 100644 --- a/drivers/gpu/drm/nouveau/core/core/client.c +++ b/drivers/gpu/drm/nouveau/core/core/client.c @@ -66,10 +66,8 @@ nouveau_client_create_(const char *name, u64 devname, const char *cfg, ret = nouveau_handle_create(nv_object(client), ~0, ~0, nv_object(client), &client->root); - if (ret) { - nouveau_namedb_destroy(&client->base); + if (ret) return ret; - } /* prevent init/fini being called, os in in charge of this */ atomic_set(&nv_object(client)->usecount, 2); diff --git a/drivers/gpu/drm/nouveau/core/core/handle.c b/drivers/gpu/drm/nouveau/core/core/handle.c index b8d2cbf8a7a..264c2b338ac 100644 --- a/drivers/gpu/drm/nouveau/core/core/handle.c +++ b/drivers/gpu/drm/nouveau/core/core/handle.c @@ -109,7 +109,7 @@ nouveau_handle_create(struct nouveau_object *parent, u32 _parent, u32 _handle, while (!nv_iclass(namedb, NV_NAMEDB_CLASS)) namedb = namedb->parent; - handle = *phandle = kzalloc(sizeof(*handle), GFP_KERNEL); + handle = kzalloc(sizeof(*handle), GFP_KERNEL); if (!handle) return -ENOMEM; @@ -146,6 +146,9 @@ nouveau_handle_create(struct nouveau_object *parent, u32 _parent, u32 _handle, } hprintk(handle, TRACE, "created\n"); + + *phandle = handle; + return 0; } diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 0f09af13541..ca1a7d76a95 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -851,20 +851,23 @@ exec_script(struct nv50_disp_priv *priv, int head, int id) for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) ctrl = nv_rd32(priv, 0x610b5c + (i * 8)); - if (nv_device(priv)->chipset < 0x90 || - nv_device(priv)->chipset == 0x92 || - nv_device(priv)->chipset == 0xa0) { - for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) - ctrl = nv_rd32(priv, 0x610b74 + (i * 8)); - i += 3; - } else { - for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) - ctrl = nv_rd32(priv, 0x610798 + (i * 8)); - i += 3; + if (!(ctrl & (1 << head))) { + if (nv_device(priv)->chipset < 0x90 || + nv_device(priv)->chipset == 0x92 || + nv_device(priv)->chipset == 0xa0) { + for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) + ctrl = nv_rd32(priv, 0x610b74 + (i * 8)); + i += 4; + } else { + for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) + ctrl = nv_rd32(priv, 0x610798 + (i * 8)); + i += 4; + } } if (!(ctrl & (1 << head))) return false; + i--; data = exec_lookup(priv, head, i, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info); if (data) { @@ -898,20 +901,23 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) ctrl = nv_rd32(priv, 0x610b58 + (i * 8)); - if (nv_device(priv)->chipset < 0x90 || - nv_device(priv)->chipset == 0x92 || - nv_device(priv)->chipset == 0xa0) { - for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) - ctrl = nv_rd32(priv, 0x610b70 + (i * 8)); - i += 3; - } else { - for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) - ctrl = nv_rd32(priv, 0x610794 + (i * 8)); - i += 3; + if (!(ctrl & (1 << head))) { + if (nv_device(priv)->chipset < 0x90 || + nv_device(priv)->chipset == 0x92 || + nv_device(priv)->chipset == 0xa0) { + for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) + ctrl = nv_rd32(priv, 0x610b70 + (i * 8)); + i += 4; + } else { + for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) + ctrl = nv_rd32(priv, 0x610794 + (i * 8)); + i += 4; + } } if (!(ctrl & (1 << head))) return 0x0000; + i--; data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1); if (!data) diff --git a/drivers/gpu/drm/nouveau/core/include/core/client.h b/drivers/gpu/drm/nouveau/core/include/core/client.h index 0193532ceac..63acc0346ff 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/client.h +++ b/drivers/gpu/drm/nouveau/core/include/core/client.h @@ -36,6 +36,9 @@ nouveau_client(void *obj) int nouveau_client_create_(const char *name, u64 device, const char *cfg, const char *dbg, int, void **); +#define nouveau_client_destroy(p) \ + nouveau_namedb_destroy(&(p)->base) + int nouveau_client_init(struct nouveau_client *); int nouveau_client_fini(struct nouveau_client *, bool suspend); diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h index c345097592f..b2f3d4d0aa4 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h @@ -38,6 +38,8 @@ enum nvbios_pll_type { PLL_UNK42 = 0x42, PLL_VPLL0 = 0x80, PLL_VPLL1 = 0x81, + PLL_VPLL2 = 0x82, + PLL_VPLL3 = 0x83, PLL_MAX = 0xff }; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c index 2917d552689..690ed438b2a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c @@ -1534,7 +1534,6 @@ init_io(struct nvbios_init *init) mdelay(10); init_wr32(init, 0x614100, 0x10000018); init_wr32(init, 0x614900, 0x10000018); - return; } value = init_rdport(init, port) & mask; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c index f6962c9b6c3..7c9626258a4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c @@ -52,6 +52,8 @@ nvc0_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) switch (info.type) { case PLL_VPLL0: case PLL_VPLL1: + case PLL_VPLL2: + case PLL_VPLL3: nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100); nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M); nv_wr32(priv, info.reg + 0x10, fN << 16); diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c index 306bdf12145..7606ed15b6f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c @@ -145,14 +145,14 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, mem->memtype = type; mem->size = size; - mutex_lock(&mm->mutex); + mutex_lock(&pfb->base.mutex); do { if (back) ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); else ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); if (ret) { - mutex_unlock(&mm->mutex); + mutex_unlock(&pfb->base.mutex); pfb->ram.put(pfb, &mem); return ret; } @@ -160,7 +160,7 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, list_add_tail(&r->rl_entry, &mem->regions); size -= r->length; } while (size); - mutex_unlock(&mm->mutex); + mutex_unlock(&pfb->base.mutex); r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); mem->offset = (u64)r->offset << 12; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c index 1188227ca6a..6565f3dbbe0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c @@ -40,15 +40,21 @@ nouveau_instobj_create_(struct nouveau_object *parent, if (ret) return ret; + mutex_lock(&imem->base.mutex); list_add(&iobj->head, &imem->list); + mutex_unlock(&imem->base.mutex); return 0; } void nouveau_instobj_destroy(struct nouveau_instobj *iobj) { - if (iobj->head.prev) - list_del(&iobj->head); + struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine); + + mutex_lock(&subdev->mutex); + list_del(&iobj->head); + mutex_unlock(&subdev->mutex); + return nouveau_object_destroy(&iobj->base); } @@ -88,6 +94,8 @@ nouveau_instmem_init(struct nouveau_instmem *imem) if (ret) return ret; + mutex_lock(&imem->base.mutex); + list_for_each_entry(iobj, &imem->list, head) { if (iobj->suspend) { for (i = 0; i < iobj->size; i += 4) @@ -97,6 +105,8 @@ nouveau_instmem_init(struct nouveau_instmem *imem) } } + mutex_unlock(&imem->base.mutex); + return 0; } @@ -104,17 +114,26 @@ int nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend) { struct nouveau_instobj *iobj; - int i; + int i, ret = 0; if (suspend) { + mutex_lock(&imem->base.mutex); + list_for_each_entry(iobj, &imem->list, head) { iobj->suspend = vmalloc(iobj->size); - if (iobj->suspend) { - for (i = 0; i < iobj->size; i += 4) - iobj->suspend[i / 4] = nv_ro32(iobj, i); - } else - return -ENOMEM; + if (!iobj->suspend) { + ret = -ENOMEM; + break; + } + + for (i = 0; i < iobj->size; i += 4) + iobj->suspend[i / 4] = nv_ro32(iobj, i); } + + mutex_unlock(&imem->base.mutex); + + if (ret) + return ret; } return nouveau_subdev_fini(&imem->base, suspend); diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c index 082c11b75ac..77c67fc970e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c @@ -352,7 +352,7 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, u64 mm_length = (offset + length) - mm_offset; int ret; - vm = *pvm = kzalloc(sizeof(*vm), GFP_KERNEL); + vm = kzalloc(sizeof(*vm), GFP_KERNEL); if (!vm) return -ENOMEM; @@ -376,6 +376,8 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, return ret; } + *pvm = vm; + return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index ac340ba3201..e620ba8271b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -127,12 +127,26 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, struct nouveau_encoder **pnv_encoder) { struct drm_device *dev = connector->dev; + struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_gpio *gpio = nouveau_gpio(drm->device); struct nouveau_i2c *i2c = nouveau_i2c(drm->device); - int i; + struct nouveau_i2c_port *port = NULL; + int i, panel = -ENODEV; + + /* eDP panels need powering on by us (if the VBIOS doesn't default it + * to on) before doing any AUX channel transactions. LVDS panel power + * is handled by the SOR itself, and not required for LVDS DDC. + */ + if (nv_connector->type == DCB_CONNECTOR_eDP) { + panel = gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff); + if (panel == 0) { + gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); + msleep(300); + } + } for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { - struct nouveau_i2c_port *port = NULL; struct nouveau_encoder *nv_encoder; struct drm_mode_object *obj; int id; @@ -150,11 +164,19 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, port = i2c->find(i2c, nv_encoder->dcb->i2c_index); if (port && nv_probe_i2c(port, 0x50)) { *pnv_encoder = nv_encoder; - return port; + break; } + + port = NULL; } - return NULL; + /* eDP panel not detected, restore panel power GPIO to previous + * state to avoid confusing the SOR for other output types. + */ + if (!port && panel == 0) + gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, panel); + + return port; } static struct nouveau_encoder * diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index e4188f24fc7..508b00a2ce0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -225,15 +225,6 @@ nouveau_display_init(struct drm_device *dev) if (ret) return ret; - /* power on internal panel if it's not already. the init tables of - * some vbios default this to off for some reason, causing the - * panel to not work after resume - */ - if (gpio && gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff) == 0) { - gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); - msleep(300); - } - /* enable polling for external displays */ drm_kms_helper_poll_enable(dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 180a45e3b52..8b090f1eb51 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -84,11 +84,16 @@ nouveau_cli_create(struct pci_dev *pdev, const char *name, struct nouveau_cli *cli; int ret; + *pcli = NULL; ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config, nouveau_debug, size, pcli); cli = *pcli; - if (ret) + if (ret) { + if (cli) + nouveau_client_destroy(&cli->base); + *pcli = NULL; return ret; + } mutex_init(&cli->mutex); return 0; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index bedafd1c953..cdb83acdffe 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -60,6 +60,7 @@ u32 nv10_fence_read(struct nouveau_channel *); void nv10_fence_context_del(struct nouveau_channel *); void nv10_fence_destroy(struct nouveau_drm *); int nv10_fence_create(struct nouveau_drm *); +void nv17_fence_resume(struct nouveau_drm *drm); int nv50_fence_create(struct nouveau_drm *); int nv84_fence_create(struct nouveau_drm *); diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index 184cdf80676..39ffc07f906 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -505,7 +505,7 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) static inline bool is_powersaving_dpms(int mode) { - return (mode != DRM_MODE_DPMS_ON); + return mode != DRM_MODE_DPMS_ON && mode != NV_DPMS_CLEARED; } static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c index 7ae7f97a6d4..03017f24d59 100644 --- a/drivers/gpu/drm/nouveau/nv10_fence.c +++ b/drivers/gpu/drm/nouveau/nv10_fence.c @@ -162,6 +162,13 @@ nv10_fence_destroy(struct nouveau_drm *drm) kfree(priv); } +void nv17_fence_resume(struct nouveau_drm *drm) +{ + struct nv10_fence_priv *priv = drm->fence; + + nouveau_bo_wr32(priv->bo, 0, priv->sequence); +} + int nv10_fence_create(struct nouveau_drm *drm) { @@ -197,6 +204,7 @@ nv10_fence_create(struct nouveau_drm *drm) if (ret == 0) { nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); priv->base.sync = nv17_fence_sync; + priv->base.resume = nv17_fence_resume; } } diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c index c20f2727ea0..d889f3ac0d4 100644 --- a/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/drivers/gpu/drm/nouveau/nv50_fence.c @@ -122,6 +122,7 @@ nv50_fence_create(struct nouveau_drm *drm) if (ret == 0) { nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); priv->base.sync = nv17_fence_sync; + priv->base.resume = nv17_fence_resume; } if (ret) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 061fa0a2890..4d0e60adbc6 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2401,6 +2401,12 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) { struct evergreen_mc_save save; + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + if (reset_mask == 0) return 0; diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 896f1cbc58a..59acabb45c9 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1409,6 +1409,12 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) { struct evergreen_mc_save save; + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + if (reset_mask == 0) return 0; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 537e259b383..3cb9d608937 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1378,6 +1378,12 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) { struct rv515_mc_save save; + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + if (reset_mask == 0) return 0; diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 03191a56eb4..69ec24ab8d6 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -2476,8 +2476,10 @@ static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error) kfree(parser->relocs); for (i = 0; i < parser->nchunks; i++) { kfree(parser->chunks[i].kdata); - kfree(parser->chunks[i].kpage[0]); - kfree(parser->chunks[i].kpage[1]); + if (parser->rdev && (parser->rdev->flags & RADEON_IS_AGP)) { + kfree(parser->chunks[i].kpage[0]); + kfree(parser->chunks[i].kpage[1]); + } } kfree(parser->chunks); kfree(parser->chunks_array); @@ -2561,16 +2563,16 @@ int r600_dma_cs_next_reloc(struct radeon_cs_parser *p, struct radeon_cs_chunk *relocs_chunk; unsigned idx; + *cs_reloc = NULL; if (p->chunk_relocs_idx == -1) { DRM_ERROR("No relocation chunk !\n"); return -EINVAL; } - *cs_reloc = NULL; relocs_chunk = &p->chunks[p->chunk_relocs_idx]; idx = p->dma_reloc_idx; - if (idx >= relocs_chunk->length_dw) { + if (idx >= p->nrelocs) { DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", - idx, relocs_chunk->length_dw); + idx, p->nrelocs); return -EINVAL; } *cs_reloc = p->relocs_ptr[idx]; diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 34e52304a52..a08f657329a 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -324,7 +324,6 @@ struct radeon_bo { struct list_head list; /* Protected by tbo.reserved */ u32 placements[3]; - u32 busy_placements[3]; struct ttm_placement placement; struct ttm_buffer_object tbo; struct ttm_bo_kmap_obj kmap; @@ -654,6 +653,8 @@ struct radeon_ring { u32 ptr_reg_mask; u32 nop; u32 idx; + u64 last_semaphore_signal_addr; + u64 last_semaphore_wait_addr; }; /* diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 396baba0141..469661fd190 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -279,13 +279,13 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) p->chunks[p->chunk_ib_idx].length_dw); return -EINVAL; } - if ((p->rdev->flags & RADEON_IS_AGP)) { + if (p->rdev && (p->rdev->flags & RADEON_IS_AGP)) { p->chunks[p->chunk_ib_idx].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL); p->chunks[p->chunk_ib_idx].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL); if (p->chunks[p->chunk_ib_idx].kpage[0] == NULL || p->chunks[p->chunk_ib_idx].kpage[1] == NULL) { - kfree(p->chunks[i].kpage[0]); - kfree(p->chunks[i].kpage[1]); + kfree(p->chunks[p->chunk_ib_idx].kpage[0]); + kfree(p->chunks[p->chunk_ib_idx].kpage[1]); return -ENOMEM; } } @@ -583,7 +583,8 @@ static int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx) struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx]; int i; int size = PAGE_SIZE; - bool copy1 = (p->rdev->flags & RADEON_IS_AGP) ? false : true; + bool copy1 = (p->rdev && (p->rdev->flags & RADEON_IS_AGP)) ? + false : true; for (i = ibc->last_copied_page + 1; i < pg_idx; i++) { if (DRM_COPY_FROM_USER(p->ib.ptr + (i * (PAGE_SIZE/4)), diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index dff6cf77f95..d9bf96ee299 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -69,9 +69,10 @@ * 2.26.0 - r600-eg: fix htile size computation * 2.27.0 - r600-SI: Add CS ioctl support for async DMA * 2.28.0 - r600-eg: Add MEM_WRITE packet support + * 2.29.0 - R500 FP16 color clear registers */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 28 +#define KMS_DRIVER_MINOR 29 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index f5ba2241dac..62cd512f5c8 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -640,6 +640,14 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc enum drm_connector_status found = connector_status_disconnected; bool color = true; + /* just don't bother on RN50 those chip are often connected to remoting + * console hw and often we get failure to load detect those. So to make + * everyone happy report the encoder as always connected. + */ + if (ASIC_IS_RN50(rdev)) { + return connector_status_connected; + } + /* save the regs we need */ vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL); crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 883c95d8d90..d3aface2d12 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -84,6 +84,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) rbo->placement.fpfn = 0; rbo->placement.lpfn = 0; rbo->placement.placement = rbo->placements; + rbo->placement.busy_placement = rbo->placements; if (domain & RADEON_GEM_DOMAIN_VRAM) rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM; @@ -104,14 +105,6 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) if (!c) rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; rbo->placement.num_placement = c; - - c = 0; - rbo->placement.busy_placement = rbo->busy_placements; - if (rbo->rdev->flags & RADEON_IS_AGP) { - rbo->busy_placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT; - } else { - rbo->busy_placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT; - } rbo->placement.num_busy_placement = c; } @@ -357,6 +350,7 @@ int radeon_bo_list_validate(struct list_head *head) { struct radeon_bo_list *lobj; struct radeon_bo *bo; + u32 domain; int r; r = ttm_eu_reserve_buffers(head); @@ -366,9 +360,17 @@ int radeon_bo_list_validate(struct list_head *head) list_for_each_entry(lobj, head, tv.head) { bo = lobj->bo; if (!bo->pin_count) { + domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain; + + retry: + radeon_ttm_placement_from_domain(bo, domain); r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); if (unlikely(r)) { + if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) { + domain |= RADEON_GEM_DOMAIN_GTT; + goto retry; + } return r; } } diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 141f2b6a9cf..2430d80b187 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -784,6 +784,8 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data) } seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr); seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr); + seq_printf(m, "last semaphore signal addr : 0x%016llx\n", ring->last_semaphore_signal_addr); + seq_printf(m, "last semaphore wait addr : 0x%016llx\n", ring->last_semaphore_wait_addr); seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); seq_printf(m, "%u dwords in ring\n", count); /* print 8 dw before current rptr as often it's the last executed diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c index 97f3ece81cd..8dcc20f53d7 100644 --- a/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c @@ -95,6 +95,10 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev, /* we assume caller has already allocated space on waiters ring */ radeon_semaphore_emit_wait(rdev, waiter, semaphore); + /* for debugging lockup only, used by sysfs debug files */ + rdev->ring[signaler].last_semaphore_signal_addr = semaphore->gpu_addr; + rdev->ring[waiter].last_semaphore_wait_addr = semaphore->gpu_addr; + return 0; } diff --git a/drivers/gpu/drm/radeon/reg_srcs/rv515 b/drivers/gpu/drm/radeon/reg_srcs/rv515 index 911a8fbd32b..78d5e99d759 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/rv515 +++ b/drivers/gpu/drm/radeon/reg_srcs/rv515 @@ -324,6 +324,8 @@ rv515 0x6d40 0x46AC US_OUT_FMT_2 0x46B0 US_OUT_FMT_3 0x46B4 US_W_FMT +0x46C0 RB3D_COLOR_CLEAR_VALUE_AR +0x46C4 RB3D_COLOR_CLEAR_VALUE_GB 0x4BC0 FG_FOG_BLEND 0x4BC4 FG_FOG_FACTOR 0x4BC8 FG_FOG_COLOR_R diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 3240a3d64f3..ae8b48205a6 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2215,6 +2215,12 @@ static int si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) { struct evergreen_mc_save save; + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + if (reset_mask == 0) return 0; diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 33d20be87db..52b20b12c83 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -434,6 +434,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, bo->mem = tmp_mem; bdev->driver->move_notify(bo, mem); bo->mem = *mem; + *mem = tmp_mem; } goto out_err; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index d73d6e3e17b..44420fca7df 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -344,8 +344,12 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, if (ttm->state == tt_unpopulated) { ret = ttm->bdev->driver->ttm_tt_populate(ttm); - if (ret) + if (ret) { + /* if we fail here don't nuke the mm node + * as the bo still owns it */ + old_copy.mm_node = NULL; goto out1; + } } add = 0; @@ -371,8 +375,11 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, prot); } else ret = ttm_copy_io_page(new_iomap, old_iomap, page); - if (ret) + if (ret) { + /* failing here, means keep old copy as-is */ + old_copy.mm_node = NULL; goto out1; + } } mb(); out2: diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index 512f44add89..fe5cdbcf263 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c @@ -22,13 +22,17 @@ static u8 *udl_get_edid(struct udl_device *udl) { u8 *block; - char rbuf[3]; + char *rbuf; int ret, i; block = kmalloc(EDID_LENGTH, GFP_KERNEL); if (block == NULL) return NULL; + rbuf = kmalloc(2, GFP_KERNEL); + if (rbuf == NULL) + goto error; + for (i = 0; i < EDID_LENGTH; i++) { ret = usb_control_msg(udl->ddev->usbdev, usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02), @@ -36,16 +40,17 @@ static u8 *udl_get_edid(struct udl_device *udl) HZ); if (ret < 1) { DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); - i--; goto error; } block[i] = rbuf[1]; } + kfree(rbuf); return block; error: kfree(block); + kfree(rbuf); return NULL; } @@ -57,6 +62,14 @@ static int udl_get_modes(struct drm_connector *connector) edid = (struct edid *)udl_get_edid(udl); + /* + * We only read the main block, but if the monitor reports extension + * blocks then the drm edid code expects them to be present, so patch + * the extension count to 0. + */ + edid->checksum += edid->extensions; + edid->extensions = 0; + drm_mode_connector_update_edid_property(connector, edid); ret = drm_add_edid_modes(connector, edid); kfree(edid); diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index f6c0011a033..dd289fd179c 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -403,7 +403,7 @@ struct dm_info_header { */ struct dm_info_msg { - struct dm_info_header header; + struct dm_header hdr; __u32 reserved; __u32 info_size; __u8 info[]; @@ -503,13 +503,17 @@ static void hot_add_req(struct hv_dynmem_device *dm, struct dm_hot_add *msg) static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg) { - switch (msg->header.type) { + struct dm_info_header *info_hdr; + + info_hdr = (struct dm_info_header *)msg->info; + + switch (info_hdr->type) { case INFO_TYPE_MAX_PAGE_CNT: pr_info("Received INFO_TYPE_MAX_PAGE_CNT\n"); - pr_info("Data Size is %d\n", msg->header.data_size); + pr_info("Data Size is %d\n", info_hdr->data_size); break; default: - pr_info("Received Unknown type: %d\n", msg->header.type); + pr_info("Received Unknown type: %d\n", info_hdr->type); } } @@ -879,7 +883,7 @@ static int balloon_probe(struct hv_device *dev, balloon_onchannelcallback, dev); if (ret) - return ret; + goto probe_error0; dm_device.dev = dev; dm_device.state = DM_INITIALIZING; @@ -891,7 +895,7 @@ static int balloon_probe(struct hv_device *dev, kthread_run(dm_thread_func, &dm_device, "hv_balloon"); if (IS_ERR(dm_device.thread)) { ret = PTR_ERR(dm_device.thread); - goto probe_error0; + goto probe_error1; } hv_set_drvdata(dev, &dm_device); @@ -914,12 +918,12 @@ static int balloon_probe(struct hv_device *dev, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret) - goto probe_error1; + goto probe_error2; t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ); if (t == 0) { ret = -ETIMEDOUT; - goto probe_error1; + goto probe_error2; } /* @@ -928,7 +932,7 @@ static int balloon_probe(struct hv_device *dev, */ if (dm_device.state == DM_INIT_ERROR) { ret = -ETIMEDOUT; - goto probe_error1; + goto probe_error2; } /* * Now submit our capabilities to the host. @@ -961,12 +965,12 @@ static int balloon_probe(struct hv_device *dev, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret) - goto probe_error1; + goto probe_error2; t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ); if (t == 0) { ret = -ETIMEDOUT; - goto probe_error1; + goto probe_error2; } /* @@ -975,18 +979,20 @@ static int balloon_probe(struct hv_device *dev, */ if (dm_device.state == DM_INIT_ERROR) { ret = -ETIMEDOUT; - goto probe_error1; + goto probe_error2; } dm_device.state = DM_INITIALIZED; return 0; -probe_error1: +probe_error2: kthread_stop(dm_device.thread); -probe_error0: +probe_error1: vmbus_close(dev->channel); +probe_error0: + kfree(send_buffer); return ret; } @@ -999,6 +1005,7 @@ static int balloon_remove(struct hv_device *dev) vmbus_close(dev->channel); kthread_stop(dm->thread); + kfree(send_buffer); return 0; } diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c index 86d7f6d858b..d867e6bb2be 100644 --- a/drivers/hwmon/vexpress.c +++ b/drivers/hwmon/vexpress.c @@ -19,6 +19,7 @@ #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/vexpress.h> diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index cbba7db9ad5..f5258c205de 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -34,6 +34,7 @@ #include <linux/io.h> #include <linux/pm_runtime.h> #include <linux/delay.h> +#include <linux/module.h> #include "i2c-designware-core.h" /* @@ -725,3 +726,6 @@ u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev) return dw_readl(dev, DW_IC_COMP_PARAM_1); } EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param); + +MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core"); +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 1b1a936eccc..d6abaf2cf2e 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -127,7 +127,7 @@ struct mxs_i2c_dev { struct device *dev; void __iomem *regs; struct completion cmd_complete; - u32 cmd_err; + int cmd_err; struct i2c_adapter adapter; const struct mxs_i2c_speed_config *speed; @@ -316,7 +316,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, if (msg->len == 0) return -EINVAL; - init_completion(&i2c->cmd_complete); + INIT_COMPLETION(i2c->cmd_complete); i2c->cmd_err = 0; ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); @@ -473,6 +473,8 @@ static int mxs_i2c_probe(struct platform_device *pdev) i2c->dev = dev; i2c->speed = &mxs_i2c_95kHz_config; + init_completion(&i2c->cmd_complete); + if (dev->of_node) { err = mxs_i2c_get_ofdata(i2c); if (err) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 20d41bfa7c1..4cc2f0528c8 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -803,7 +803,7 @@ static int errata_omap3_i462(struct omap_i2c_dev *dev) if (stat & OMAP_I2C_STAT_AL) { dev_err(dev->dev, "Arbitration lost\n"); dev->cmd_err |= OMAP_I2C_STAT_AL; - omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK); + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL); } return -EIO; @@ -963,7 +963,7 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) i2c_omap_errata_i207(dev, stat); omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); - break; + continue; } if (stat & OMAP_I2C_STAT_RRDY) { @@ -989,7 +989,7 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) break; omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XDR); - break; + continue; } if (stat & OMAP_I2C_STAT_XRDY) { diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index 3f1818b8797..e03381aee34 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -12,6 +12,7 @@ #include <linux/slab.h> #include <linux/platform_device.h> #include <linux/i2c.h> +#include <linux/of_i2c.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/io.h> @@ -328,6 +329,7 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) adap->algo = &i2c_sirfsoc_algo; adap->algo_data = siic; + adap->dev.of_node = pdev->dev.of_node; adap->dev.parent = &pdev->dev; adap->nr = pdev->id; @@ -371,6 +373,8 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) clk_disable(clk); + of_i2c_register_devices(adap); + dev_info(&pdev->dev, " I2C adapter ready to operate\n"); return 0; diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index 1e44d04d1b2..a43c0ce5e3d 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -167,7 +167,7 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) } mux->busses = devm_kzalloc(&pdev->dev, - sizeof(mux->busses) * mux->pdata->bus_count, + sizeof(*mux->busses) * mux->pdata->bus_count, GFP_KERNEL); if (!mux->busses) { dev_err(&pdev->dev, "Cannot allocate busses\n"); diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 4ba384f1ab5..2df9414a72f 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -448,8 +448,6 @@ static int intel_idle_probe(void) else on_each_cpu(__setup_broadcast_timer, (void *)true, 1); - register_cpu_notifier(&cpu_hotplug_notifier); - pr_debug(PREFIX "v" INTEL_IDLE_VERSION " model 0x%X\n", boot_cpu_data.x86_model); @@ -612,6 +610,7 @@ static int __init intel_idle_init(void) return retval; } } + register_cpu_notifier(&cpu_hotplug_notifier); return 0; } diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index fe4bcd7c5b1..05e996fafc9 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -8,6 +8,7 @@ config HID_SENSOR_ACCEL_3D select IIO_BUFFER select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON + select HID_SENSOR_IIO_TRIGGER tristate "HID Accelerometers 3D" help Say yes here to build support for the HID SENSOR diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index 4a5f639bc68..bbad9b94cd7 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -411,7 +411,11 @@ static int ad7266_probe(struct spi_device *spi) if (ret) goto error_put_reg; - st->vref_uv = regulator_get_voltage(st->reg); + ret = regulator_get_voltage(st->reg); + if (ret < 0) + goto error_disable_reg; + + st->vref_uv = ret; } else { /* Use internal reference */ st->vref_uv = 2500000; diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 04b013561f0..a526c0e3aaa 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -80,7 +80,7 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) *timestamp = pf->timestamp; } - iio_push_to_buffers(indio_dev, (u8 *)st->buffer); + iio_push_to_buffers(idev, (u8 *)st->buffer); iio_trigger_notify_done(idev->trig); diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index b5669be6f39..03b25b3dc71 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c @@ -1605,19 +1605,20 @@ static int max1363_probe(struct i2c_client *client, return 0; error_free_irq: - free_irq(st->client->irq, indio_dev); + if (client->irq) + free_irq(st->client->irq, indio_dev); error_uninit_buffer: iio_buffer_unregister(indio_dev); error_cleanup_buffer: max1363_buffer_cleanup(indio_dev); error_free_available_scan_masks: kfree(indio_dev->available_scan_masks); -error_unregister_map: - iio_map_array_unregister(indio_dev, client->dev.platform_data); error_disable_reg: regulator_disable(st->reg); error_put_reg: regulator_put(st->reg); +error_unregister_map: + iio_map_array_unregister(indio_dev, client->dev.platform_data); error_free_device: iio_device_free(indio_dev); error_out: @@ -1635,10 +1636,8 @@ static int max1363_remove(struct i2c_client *client) iio_buffer_unregister(indio_dev); max1363_buffer_cleanup(indio_dev); kfree(indio_dev->available_scan_masks); - if (!IS_ERR(st->reg)) { - regulator_disable(st->reg); - regulator_put(st->reg); - } + regulator_disable(st->reg); + regulator_put(st->reg); iio_map_array_unregister(indio_dev, client->dev.platform_data); iio_device_free(indio_dev); diff --git a/drivers/iio/common/hid-sensors/Kconfig b/drivers/iio/common/hid-sensors/Kconfig index ae10778da7a..1178121b55b 100644 --- a/drivers/iio/common/hid-sensors/Kconfig +++ b/drivers/iio/common/hid-sensors/Kconfig @@ -6,7 +6,7 @@ menu "Hid Sensor IIO Common" config HID_SENSOR_IIO_COMMON tristate "Common modules for all HID Sensor IIO drivers" depends on HID_SENSOR_HUB - select IIO_TRIGGER if IIO_BUFFER + select HID_SENSOR_IIO_TRIGGER if IIO_BUFFER help Say yes here to build support for HID sensor to use HID sensor common processing for attributes and IIO triggers. @@ -14,6 +14,17 @@ config HID_SENSOR_IIO_COMMON HID sensor drivers, this module contains processing for those attributes. +config HID_SENSOR_IIO_TRIGGER + tristate "Common module (trigger) for all HID Sensor IIO drivers" + depends on HID_SENSOR_HUB && HID_SENSOR_IIO_COMMON + select IIO_TRIGGER + help + Say yes here to build trigger support for HID sensors. + Triggers will be send if all requested attributes were read. + + If this driver is compiled as a module, it will be named + hid-sensor-trigger. + config HID_SENSOR_ENUM_BASE_QUIRKS bool "ENUM base quirks for HID Sensor IIO drivers" depends on HID_SENSOR_IIO_COMMON diff --git a/drivers/iio/common/hid-sensors/Makefile b/drivers/iio/common/hid-sensors/Makefile index 1f463e00c24..22e7c5a8232 100644 --- a/drivers/iio/common/hid-sensors/Makefile +++ b/drivers/iio/common/hid-sensors/Makefile @@ -3,4 +3,5 @@ # obj-$(CONFIG_HID_SENSOR_IIO_COMMON) += hid-sensor-iio-common.o -hid-sensor-iio-common-y := hid-sensor-attributes.o hid-sensor-trigger.o +obj-$(CONFIG_HID_SENSOR_IIO_TRIGGER) += hid-sensor-trigger.o +hid-sensor-iio-common-y := hid-sensor-attributes.o diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index 6c7898c765d..483fc379a2d 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c @@ -406,7 +406,11 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap, goto error_free_reg; } - st->vref = regulator_get_voltage(st->vref_reg); + ret = regulator_get_voltage(st->vref_reg); + if (ret < 0) + goto error_disable_reg; + + st->vref = ret; } else { st->vref = st->chip_info->int_vref; ctrl |= AD5380_CTRL_INT_VREF_EN; diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c index 29f653dab2f..f5583aedfb5 100644 --- a/drivers/iio/dac/ad5446.c +++ b/drivers/iio/dac/ad5446.c @@ -226,7 +226,11 @@ static int ad5446_probe(struct device *dev, const char *name, if (ret) goto error_put_reg; - voltage_uv = regulator_get_voltage(reg); + ret = regulator_get_voltage(reg); + if (ret < 0) + goto error_disable_reg; + + voltage_uv = ret; } indio_dev = iio_device_alloc(sizeof(*st)); diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index b2a31a0468e..0661829f277 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -296,7 +296,11 @@ static int ad5504_probe(struct spi_device *spi) if (ret) goto error_put_reg; - voltage_uv = regulator_get_voltage(reg); + ret = regulator_get_voltage(reg); + if (ret < 0) + goto error_disable_reg; + + voltage_uv = ret; } spi_set_drvdata(spi, indio_dev); diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c index e9947969f9f..f6e116627b7 100644 --- a/drivers/iio/dac/ad5624r_spi.c +++ b/drivers/iio/dac/ad5624r_spi.c @@ -238,7 +238,11 @@ static int ad5624r_probe(struct spi_device *spi) if (ret) goto error_put_reg; - voltage_uv = regulator_get_voltage(st->reg); + ret = regulator_get_voltage(st->reg); + if (ret < 0) + goto error_disable_reg; + + voltage_uv = ret; } spi_set_drvdata(spi, indio_dev); diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index 36e51382ae5..ca9609d7a15 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -332,7 +332,11 @@ static int ad5686_probe(struct spi_device *spi) if (ret) goto error_put_reg; - voltage_uv = regulator_get_voltage(st->reg); + ret = regulator_get_voltage(st->reg); + if (ret < 0) + goto error_disable_reg; + + voltage_uv = ret; } st->chip_info = diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c index c84180f2313..6407b5407dd 100644 --- a/drivers/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c @@ -365,7 +365,11 @@ static int ad5791_probe(struct spi_device *spi) if (ret) goto error_put_reg_pos; - pos_voltage_uv = regulator_get_voltage(st->reg_vdd); + ret = regulator_get_voltage(st->reg_vdd); + if (ret < 0) + goto error_disable_reg_pos; + + pos_voltage_uv = ret; } st->reg_vss = regulator_get(&spi->dev, "vss"); @@ -374,7 +378,11 @@ static int ad5791_probe(struct spi_device *spi) if (ret) goto error_put_reg_neg; - neg_voltage_uv = regulator_get_voltage(st->reg_vss); + ret = regulator_get_voltage(st->reg_vss); + if (ret < 0) + goto error_disable_reg_neg; + + neg_voltage_uv = ret; } st->pwr_down = true; @@ -428,6 +436,7 @@ error_put_reg_neg: if (!IS_ERR(st->reg_vss)) regulator_put(st->reg_vss); +error_disable_reg_pos: if (!IS_ERR(st->reg_vdd)) regulator_disable(st->reg_vdd); error_put_reg_pos: diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index e5033b4cfba..a884252ac66 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -173,7 +173,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) } while ((st->r1_mod > ADF4350_MAX_MODULUS) && r_cnt); } while (r_cnt == 0); - tmp = freq * (u64)st->r1_mod + (st->fpfd > 1); + tmp = freq * (u64)st->r1_mod + (st->fpfd >> 1); do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */ st->r0_fract = do_div(tmp, st->r1_mod); st->r0_int = tmp; diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index 48ed1483ff2..96b68f63a90 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig @@ -17,6 +17,7 @@ config HID_SENSOR_GYRO_3D select IIO_BUFFER select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON + select HID_SENSOR_IIO_TRIGGER tristate "HID Gyroscope 3D" help Say yes here to build support for the HID SENSOR diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 1763c9bcb98..dbf80abc834 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -47,6 +47,7 @@ config HID_SENSOR_ALS select IIO_BUFFER select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON + select HID_SENSOR_IIO_TRIGGER tristate "HID ALS" help Say yes here to build support for the HID SENSOR diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index c1f0cdd5703..ff11d68225c 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -8,6 +8,7 @@ config HID_SENSOR_MAGNETOMETER_3D select IIO_BUFFER select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON + select HID_SENSOR_IIO_TRIGGER tristate "HID Magenetometer 3D" help Say yes here to build support for the HID SENSOR diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 62ca575701d..a350969e5ef 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -1,3 +1,30 @@ +config IRQCHIP + def_bool y + depends on OF_IRQ + +config ARM_GIC + bool + select IRQ_DOMAIN + select MULTI_IRQ_HANDLER + +config GIC_NON_BANKED + bool + +config ARM_VIC + bool + select IRQ_DOMAIN + select MULTI_IRQ_HANDLER + +config ARM_VIC_NR + int + default 4 if ARCH_S5PV210 + default 3 if ARCH_S5PC100 + default 2 + depends on ARM_VIC + help + The maximum number of VICs available in the system, for + power management. + config VERSATILE_FPGA_IRQ bool select IRQ_DOMAIN diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index bf4609a5bd9..0fb86557439 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -1,4 +1,8 @@ +obj-$(CONFIG_IRQCHIP) += irqchip.o + obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi.o -obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o +obj-$(CONFIG_ARM_GIC) += irq-gic.o +obj-$(CONFIG_ARM_VIC) += irq-vic.o +obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o diff --git a/arch/arm/common/gic.c b/drivers/irqchip/irq-gic.c index 36ae03a3f5d..69d9a395d54 100644 --- a/arch/arm/common/gic.c +++ b/drivers/irqchip/irq-gic.c @@ -38,12 +38,14 @@ #include <linux/interrupt.h> #include <linux/percpu.h> #include <linux/slab.h> +#include <linux/irqchip/arm-gic.h> #include <asm/irq.h> #include <asm/exception.h> #include <asm/smp_plat.h> #include <asm/mach/irq.h> -#include <asm/hardware/gic.h> + +#include "irqchip.h" union gic_base { void __iomem *common_base; @@ -276,7 +278,7 @@ static int gic_set_wake(struct irq_data *d, unsigned int on) #define gic_set_wake NULL #endif -asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) +static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) { u32 irqstat, irqnr; struct gic_chip_data *gic = &gic_data[0]; @@ -617,6 +619,27 @@ static void __init gic_pm_init(struct gic_chip_data *gic) } #endif +#ifdef CONFIG_SMP +void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) +{ + int cpu; + unsigned long map = 0; + + /* Convert our logical CPU mask into a physical one. */ + for_each_cpu(cpu, mask) + map |= 1 << cpu_logical_map(cpu); + + /* + * Ensure that stores to Normal memory are visible to the + * other CPUs before issuing the IPI. + */ + dsb(); + + /* this always happens on GIC0 */ + writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); +} +#endif + static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) { @@ -743,6 +766,12 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, if (WARN_ON(!gic->domain)) return; +#ifdef CONFIG_SMP + set_smp_cross_call(gic_raise_softirq); +#endif + + set_handle_irq(gic_handle_irq); + gic_chip.flags |= gic_arch_extn.flags; gic_dist_init(gic); gic_cpu_init(gic); @@ -756,27 +785,6 @@ void __cpuinit gic_secondary_init(unsigned int gic_nr) gic_cpu_init(&gic_data[gic_nr]); } -#ifdef CONFIG_SMP -void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) -{ - int cpu; - unsigned long map = 0; - - /* Convert our logical CPU mask into a physical one. */ - for_each_cpu(cpu, mask) - map |= gic_cpu_map[cpu]; - - /* - * Ensure that stores to Normal memory are visible to the - * other CPUs before issuing the IPI. - */ - dsb(); - - /* this always happens on GIC0 */ - writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); -} -#endif - #ifdef CONFIG_OF static int gic_cnt __initdata = 0; @@ -808,4 +816,9 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) gic_cnt++; return 0; } +IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init); +IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init); +IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init); +IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init); + #endif diff --git a/arch/arm/common/vic.c b/drivers/irqchip/irq-vic.c index 8f324b99416..3cf97aaebe4 100644 --- a/arch/arm/common/vic.c +++ b/drivers/irqchip/irq-vic.c @@ -30,10 +30,29 @@ #include <linux/syscore_ops.h> #include <linux/device.h> #include <linux/amba/bus.h> +#include <linux/irqchip/arm-vic.h> #include <asm/exception.h> #include <asm/mach/irq.h> -#include <asm/hardware/vic.h> + +#include "irqchip.h" + +#define VIC_IRQ_STATUS 0x00 +#define VIC_FIQ_STATUS 0x04 +#define VIC_INT_SELECT 0x0c /* 1 = FIQ, 0 = IRQ */ +#define VIC_INT_SOFT 0x18 +#define VIC_INT_SOFT_CLEAR 0x1c +#define VIC_PROTECT 0x20 +#define VIC_PL190_VECT_ADDR 0x30 /* PL190 only */ +#define VIC_PL190_DEF_VECT_ADDR 0x34 /* PL190 only */ + +#define VIC_VECT_ADDR0 0x100 /* 0 to 15 (0..31 PL192) */ +#define VIC_VECT_CNTL0 0x200 /* 0 to 15 (0..31 PL192) */ +#define VIC_ITCR 0x300 /* VIC test control register */ + +#define VIC_VECT_CNTL_ENABLE (1 << 5) + +#define VIC_PL192_VECT_ADDR 0xF00 /** * struct vic_device - VIC PM device @@ -66,6 +85,8 @@ static struct vic_device vic_devices[CONFIG_ARM_VIC_NR]; static int vic_id; +static void vic_handle_irq(struct pt_regs *regs); + /** * vic_init2 - common initialisation code * @base: Base of the VIC. @@ -182,6 +203,40 @@ static int vic_irqdomain_map(struct irq_domain *d, unsigned int irq, return 0; } +/* + * Handle each interrupt in a single VIC. Returns non-zero if we've + * handled at least one interrupt. This reads the status register + * before handling each interrupt, which is necessary given that + * handle_IRQ may briefly re-enable interrupts for soft IRQ handling. + */ +static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs) +{ + u32 stat, irq; + int handled = 0; + + while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) { + irq = ffs(stat) - 1; + handle_IRQ(irq_find_mapping(vic->domain, irq), regs); + handled = 1; + } + + return handled; +} + +/* + * Keep iterating over all registered VIC's until there are no pending + * interrupts. + */ +static asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) +{ + int i, handled; + + do { + for (i = 0, handled = 0; i < vic_id; ++i) + handled |= handle_one_vic(&vic_devices[i], regs); + } while (handled); +} + static struct irq_domain_ops vic_irqdomain_ops = { .map = vic_irqdomain_map, .xlate = irq_domain_xlate_onetwocell, @@ -218,6 +273,7 @@ static void __init vic_register(void __iomem *base, unsigned int irq, v->valid_sources = valid_sources; v->resume_sources = resume_sources; v->irq = irq; + set_handle_irq(vic_handle_irq); vic_id++; v->domain = irq_domain_add_simple(node, fls(valid_sources), irq, &vic_irqdomain_ops, v); @@ -427,38 +483,7 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent) return 0; } +IRQCHIP_DECLARE(arm_pl190_vic, "arm,pl190-vic", vic_of_init); +IRQCHIP_DECLARE(arm_pl192_vic, "arm,pl192-vic", vic_of_init); +IRQCHIP_DECLARE(arm_versatile_vic, "arm,versatile-vic", vic_of_init); #endif /* CONFIG OF */ - -/* - * Handle each interrupt in a single VIC. Returns non-zero if we've - * handled at least one interrupt. This reads the status register - * before handling each interrupt, which is necessary given that - * handle_IRQ may briefly re-enable interrupts for soft IRQ handling. - */ -static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs) -{ - u32 stat, irq; - int handled = 0; - - while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) { - irq = ffs(stat) - 1; - handle_IRQ(irq_find_mapping(vic->domain, irq), regs); - handled = 1; - } - - return handled; -} - -/* - * Keep iterating over all registered VIC's until there are no pending - * interrupts. - */ -asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) -{ - int i, handled; - - do { - for (i = 0, handled = 0; i < vic_id; ++i) - handled |= handle_one_vic(&vic_devices[i], regs); - } while (handled); -} diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c new file mode 100644 index 00000000000..f496afce29d --- /dev/null +++ b/drivers/irqchip/irqchip.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2012 Thomas Petazzoni + * + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/init.h> +#include <linux/of_irq.h> + +#include "irqchip.h" + +/* + * This special of_device_id is the sentinel at the end of the + * of_device_id[] array of all irqchips. It is automatically placed at + * the end of the array by the linker, thanks to being part of a + * special section. + */ +static const struct of_device_id +irqchip_of_match_end __used __section(__irqchip_of_end); + +extern struct of_device_id __irqchip_begin[]; + +void __init irqchip_init(void) +{ + of_irq_init(__irqchip_begin); +} diff --git a/drivers/irqchip/irqchip.h b/drivers/irqchip/irqchip.h new file mode 100644 index 00000000000..e445ba2d6ad --- /dev/null +++ b/drivers/irqchip/irqchip.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2012 Thomas Petazzoni + * + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef _IRQCHIP_H +#define _IRQCHIP_H + +/* + * This macro must be used by the different irqchip drivers to declare + * the association between their DT compatible string and their + * initialization function. + * + * @name: name that must be unique accross all IRQCHIP_DECLARE of the + * same file. + * @compstr: compatible string of the irqchip driver + * @fn: initialization function + */ +#define IRQCHIP_DECLARE(name,compstr,fn) \ + static const struct of_device_id irqchip_of_match_##name \ + __used __section(__irqchip_of_table) \ + = { .compatible = compstr, .data = fn } + +#endif diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c index 80e1d2fd9d4..8527743b5ce 100644 --- a/drivers/irqchip/spear-shirq.c +++ b/drivers/irqchip/spear-shirq.c @@ -25,6 +25,8 @@ #include <linux/of_irq.h> #include <linux/spinlock.h> +#include "irqchip.h" + static DEFINE_SPINLOCK(lock); /* spear300 shared irq registers offsets and masks */ @@ -300,6 +302,7 @@ int __init spear300_shirq_of_init(struct device_node *np, return shirq_init(spear300_shirq_blocks, ARRAY_SIZE(spear300_shirq_blocks), np); } +IRQCHIP_DECLARE(spear300_shirq, "st,spear300-shirq", spear300_shirq_of_init); int __init spear310_shirq_of_init(struct device_node *np, struct device_node *parent) @@ -307,6 +310,7 @@ int __init spear310_shirq_of_init(struct device_node *np, return shirq_init(spear310_shirq_blocks, ARRAY_SIZE(spear310_shirq_blocks), np); } +IRQCHIP_DECLARE(spear310_shirq, "st,spear310-shirq", spear310_shirq_of_init); int __init spear320_shirq_of_init(struct device_node *np, struct device_node *parent) @@ -314,3 +318,4 @@ int __init spear320_shirq_of_init(struct device_node *np, return shirq_init(spear320_shirq_blocks, ARRAY_SIZE(spear320_shirq_blocks), np); } +IRQCHIP_DECLARE(spear320_shirq, "st,spear320-shirq", spear320_shirq_of_init); diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index 8a8d42fe263..d4e7567b367 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c @@ -556,7 +556,7 @@ static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, mutex_lock(&info->lock); format = __find_format(info, fh, fmt->which, info->res_type); - if (!format) + if (format) fmt->format = *format; else ret = -EINVAL; diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 1cf8293c0fb..4a980e029ca 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -23,8 +23,8 @@ #include <linux/slab.h> #include <linux/videodev2.h> #include <linux/of.h> +#include <linux/platform_data/imx-iram.h> -#include <mach/iram.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index e0d73a64218..8dac17511e6 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -35,9 +35,6 @@ #include <linux/vmalloc.h> #include <media/v4l2-dev.h> #include <media/v4l2-ioctl.h> -#include <plat/iommu.h> -#include <plat/iovmm.h> -#include <plat/omap-pm.h> #include "ispvideo.h" #include "isp.h" diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c index 4ab99f3a7b0..b4a68ecf0ca 100644 --- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c @@ -593,7 +593,7 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd) { struct media_entity *source, *sink; unsigned int flags = MEDIA_LNK_FL_ENABLED; - int i, ret; + int i, ret = 0; for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { struct fimc_lite *fimc = fmd->fimc_lite[i]; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 379f5743371..681bc6ba149 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -412,62 +412,48 @@ leave_handle_frame: } /* Error handling for interrupt */ -static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx, - unsigned int reason, unsigned int err) +static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev, + struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err) { - struct s5p_mfc_dev *dev; unsigned long flags; - /* If no context is available then all necessary - * processing has been done. */ - if (ctx == NULL) - return; - - dev = ctx->dev; mfc_err("Interrupt Error: %08x\n", err); - s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); - wake_up_dev(dev, reason, err); - /* Error recovery is dependent on the state of context */ - switch (ctx->state) { - case MFCINST_INIT: - /* This error had to happen while acquireing instance */ - case MFCINST_GOT_INST: - /* This error had to happen while parsing the header */ - case MFCINST_HEAD_PARSED: - /* This error had to happen while setting dst buffers */ - case MFCINST_RETURN_INST: - /* This error had to happen while releasing instance */ - clear_work_bit(ctx); - wake_up_ctx(ctx, reason, err); - if (test_and_clear_bit(0, &dev->hw_lock) == 0) - BUG(); - s5p_mfc_clock_off(); - ctx->state = MFCINST_ERROR; - break; - case MFCINST_FINISHING: - case MFCINST_FINISHED: - case MFCINST_RUNNING: - /* It is higly probable that an error occured - * while decoding a frame */ - clear_work_bit(ctx); - ctx->state = MFCINST_ERROR; - /* Mark all dst buffers as having an error */ - spin_lock_irqsave(&dev->irqlock, flags); - s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue, - &ctx->vq_dst); - /* Mark all src buffers as having an error */ - s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue, - &ctx->vq_src); - spin_unlock_irqrestore(&dev->irqlock, flags); - if (test_and_clear_bit(0, &dev->hw_lock) == 0) - BUG(); - s5p_mfc_clock_off(); - break; - default: - mfc_err("Encountered an error interrupt which had not been handled\n"); - break; + if (ctx != NULL) { + /* Error recovery is dependent on the state of context */ + switch (ctx->state) { + case MFCINST_RES_CHANGE_INIT: + case MFCINST_RES_CHANGE_FLUSH: + case MFCINST_RES_CHANGE_END: + case MFCINST_FINISHING: + case MFCINST_FINISHED: + case MFCINST_RUNNING: + /* It is higly probable that an error occured + * while decoding a frame */ + clear_work_bit(ctx); + ctx->state = MFCINST_ERROR; + /* Mark all dst buffers as having an error */ + spin_lock_irqsave(&dev->irqlock, flags); + s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, + &ctx->dst_queue, &ctx->vq_dst); + /* Mark all src buffers as having an error */ + s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, + &ctx->src_queue, &ctx->vq_src); + spin_unlock_irqrestore(&dev->irqlock, flags); + wake_up_ctx(ctx, reason, err); + break; + default: + clear_work_bit(ctx); + ctx->state = MFCINST_ERROR; + wake_up_ctx(ctx, reason, err); + break; + } } + if (test_and_clear_bit(0, &dev->hw_lock) == 0) + BUG(); + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); + s5p_mfc_clock_off(); + wake_up_dev(dev, reason, err); return; } @@ -632,7 +618,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) dev->warn_start) s5p_mfc_handle_frame(ctx, reason, err); else - s5p_mfc_handle_error(ctx, reason, err); + s5p_mfc_handle_error(dev, ctx, reason, err); clear_bit(0, &dev->enter_suspend); break; diff --git a/drivers/media/usb/gspca/kinect.c b/drivers/media/usb/gspca/kinect.c index 40ad6687ee5..3773a8a745d 100644 --- a/drivers/media/usb/gspca/kinect.c +++ b/drivers/media/usb/gspca/kinect.c @@ -381,6 +381,7 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const struct usb_device_id device_table[] = { {USB_DEVICE(0x045e, 0x02ae)}, + {USB_DEVICE(0x045e, 0x02bf)}, {} }; diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c index 70511d5f953..1220340e760 100644 --- a/drivers/media/usb/gspca/sonixb.c +++ b/drivers/media/usb/gspca/sonixb.c @@ -496,7 +496,7 @@ static void reg_w(struct gspca_dev *gspca_dev, } } -static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer) +static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buf) { int retry = 60; @@ -504,16 +504,19 @@ static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer) return; /* is i2c ready */ - reg_w(gspca_dev, 0x08, buffer, 8); + reg_w(gspca_dev, 0x08, buf, 8); while (retry--) { if (gspca_dev->usb_err < 0) return; - msleep(10); + msleep(1); reg_r(gspca_dev, 0x08); if (gspca_dev->usb_buf[0] & 0x04) { if (gspca_dev->usb_buf[0] & 0x08) { dev_err(gspca_dev->v4l2_dev.dev, - "i2c write error\n"); + "i2c error writing %02x %02x %02x %02x" + " %02x %02x %02x %02x\n", + buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7]); gspca_dev->usb_err = -EIO; } return; @@ -530,7 +533,7 @@ static void i2c_w_vector(struct gspca_dev *gspca_dev, for (;;) { if (gspca_dev->usb_err < 0) return; - reg_w(gspca_dev, 0x08, *buffer, 8); + i2c_w(gspca_dev, *buffer); len -= 8; if (len <= 0) break; diff --git a/drivers/media/usb/gspca/sonixj.c b/drivers/media/usb/gspca/sonixj.c index 5a86047b846..36307a9028a 100644 --- a/drivers/media/usb/gspca/sonixj.c +++ b/drivers/media/usb/gspca/sonixj.c @@ -1550,6 +1550,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) 0, gspca_dev->usb_buf, 8, 500); + msleep(2); if (ret < 0) { pr_err("i2c_w1 err %d\n", ret); gspca_dev->usb_err = ret; diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 2bb7613ddeb..d5baab17a5e 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1431,8 +1431,10 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, int ret; ctrl = uvc_find_control(chain, xctrl->id, &mapping); - if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) == 0) + if (ctrl == NULL) return -EINVAL; + if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) + return -EACCES; /* Clamp out of range values. */ switch (mapping->v4l2_type) { diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index f2ee8c6b0d8..68d59b52749 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -657,8 +657,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) ret = uvc_ctrl_get(chain, ctrl); if (ret < 0) { uvc_ctrl_rollback(handle); - ctrls->error_idx = ret == -ENOENT - ? ctrls->count : i; + ctrls->error_idx = i; return ret; } } @@ -686,8 +685,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) ret = uvc_ctrl_set(chain, ctrl); if (ret < 0) { uvc_ctrl_rollback(handle); - ctrls->error_idx = (ret == -ENOENT && - cmd == VIDIOC_S_EXT_CTRLS) + ctrls->error_idx = cmd == VIDIOC_S_EXT_CTRLS ? ctrls->count : i; return ret; } diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 9f81be23a81..e02c4797b1c 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -921,8 +921,10 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b * In videobuf we use our internal V4l2_planes struct for * single-planar buffers as well, for simplicity. */ - if (V4L2_TYPE_IS_OUTPUT(b->type)) + if (V4L2_TYPE_IS_OUTPUT(b->type)) { v4l2_planes[0].bytesused = b->bytesused; + v4l2_planes[0].data_offset = 0; + } if (b->memory == V4L2_MEMORY_USERPTR) { v4l2_planes[0].m.userptr = b->m.userptr; diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 1c0abd4dfc4..47ad4e27087 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -292,6 +292,7 @@ config TWL4030_CORE bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support" depends on I2C=y && GENERIC_HARDIRQS select IRQ_DOMAIN + select REGMAP_I2C help Say yes here if you have TWL4030 / TWL6030 family chip on your board. This core driver provides register access and IRQ handling diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index dc8826d8d69..d9fedd4d919 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -26,17 +26,16 @@ #include <linux/fs.h> #include <linux/platform_device.h> #include <linux/uaccess.h> +#include <linux/irqchip/arm-gic.h> #include <linux/mfd/core.h> #include <linux/mfd/dbx500-prcmu.h> #include <linux/mfd/abx500/ab8500.h> #include <linux/regulator/db8500-prcmu.h> #include <linux/regulator/machine.h> #include <linux/cpufreq.h> -#include <asm/hardware/gic.h> #include <mach/hardware.h> #include <mach/irqs.h> #include <mach/db8500-regs.h> -#include <mach/id.h> #include "dbx500-prcmu-regs.h" /* Offset for the firmware version within the TCPM */ @@ -216,10 +215,8 @@ #define PRCM_REQ_MB5_I2C_HW_BITS (PRCM_REQ_MB5 + 0x1) #define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 0x2) #define PRCM_REQ_MB5_I2C_VAL (PRCM_REQ_MB5 + 0x3) -#define PRCMU_I2C_WRITE(slave) \ - (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0)) -#define PRCMU_I2C_READ(slave) \ - (((slave) << 1) | BIT(0) | (cpu_is_u8500v2() ? BIT(6) : 0)) +#define PRCMU_I2C_WRITE(slave) (((slave) << 1) | BIT(6)) +#define PRCMU_I2C_READ(slave) (((slave) << 1) | BIT(0) | BIT(6)) #define PRCMU_I2C_STOP_EN BIT(3) /* Mailbox 5 ACKs */ @@ -1049,12 +1046,13 @@ int db8500_prcmu_get_ddr_opp(void) * * This function sets the operating point of the DDR. */ +static bool enable_set_ddr_opp; int db8500_prcmu_set_ddr_opp(u8 opp) { if (opp < DDR_100_OPP || opp > DDR_25_OPP) return -EINVAL; /* Changing the DDR OPP can hang the hardware pre-v21 */ - if (cpu_is_u8500v20_or_later() && !cpu_is_u8500v20()) + if (enable_set_ddr_opp) writeb(opp, PRCM_DDR_SUBSYS_APE_MINBW); return 0; @@ -2790,6 +2788,7 @@ void __init db8500_prcmu_early_init(void) pr_err("prcmu: Unsupported chip version\n"); BUG(); } + tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); spin_lock_init(&mb0_transfer.lock); spin_lock_init(&mb0_transfer.dbb_irqs_lock); @@ -3104,9 +3103,6 @@ static int db8500_prcmu_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; int irq = 0, err = 0, i; - if (ux500_is_svp()) - return -ENODEV; - init_prcm_registers(); /* Clean up the mailbox interrupts after pre-kernel code. */ @@ -3135,8 +3131,7 @@ static int db8500_prcmu_probe(struct platform_device *pdev) } } - if (cpu_is_u8500v20_or_later()) - prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); + prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); db8500_prcmu_update_cpufreq(); diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index e5d8f63b252..77048b18439 100644 --- a/drivers/mfd/vexpress-sysreg.c +++ b/drivers/mfd/vexpress-sysreg.c @@ -313,19 +313,11 @@ static void vexpress_sysreg_config_complete(unsigned long data) } -void __init vexpress_sysreg_early_init(void __iomem *base) +void __init vexpress_sysreg_setup(struct device_node *node) { - struct device_node *node = of_find_compatible_node(NULL, NULL, - "arm,vexpress-sysreg"); - - if (node) - base = of_iomap(node, 0); - - if (WARN_ON(!base)) + if (WARN_ON(!vexpress_sysreg_base)) return; - vexpress_sysreg_base = base; - if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE) vexpress_master_site = VEXPRESS_SITE_DB2; else @@ -336,9 +328,23 @@ void __init vexpress_sysreg_early_init(void __iomem *base) WARN_ON(!vexpress_sysreg_config_bridge); } +void __init vexpress_sysreg_early_init(void __iomem *base) +{ + vexpress_sysreg_base = base; + vexpress_sysreg_setup(NULL); +} + void __init vexpress_sysreg_of_early_init(void) { - vexpress_sysreg_early_init(NULL); + struct device_node *node = of_find_compatible_node(NULL, NULL, + "arm,vexpress-sysreg"); + + if (node) { + vexpress_sysreg_base = of_iomap(node, 0); + vexpress_sysreg_setup(node); + } else { + pr_info("vexpress-sysreg: No Device Tree node found."); + } } @@ -426,9 +432,11 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) return -EBUSY; } - if (!vexpress_sysreg_base) + if (!vexpress_sysreg_base) { vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + vexpress_sysreg_setup(pdev->dev.of_node); + } if (!vexpress_sysreg_base) { dev_err(&pdev->dev, "Failed to obtain base address!\n"); diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index 158da5a81a6..3c09cbb70b1 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c @@ -19,6 +19,7 @@ #include <linux/module.h> #include <linux/of.h> +#include <linux/pinctrl/consumer.h> /* Serialize access to ssc_list and user count */ static DEFINE_SPINLOCK(user_lock); @@ -131,6 +132,13 @@ static int ssc_probe(struct platform_device *pdev) struct resource *regs; struct ssc_device *ssc; const struct atmel_ssc_platform_data *plat_dat; + struct pinctrl *pinctrl; + + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) { + dev_err(&pdev->dev, "Failed to request pinctrl\n"); + return PTR_ERR(pinctrl); + } ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL); if (!ssc) { diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 18794aea606..e40ffd9502d 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -187,13 +187,13 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, wait_ret = wait_event_interruptible(dev->iamthif_cl.wait, (cb = mei_amthif_find_read_list_entry(dev, file))); + /* Locking again the Mutex */ + mutex_lock(&dev->device_lock); + if (wait_ret) return -ERESTARTSYS; dev_dbg(&dev->pdev->dev, "woke up from sleep\n"); - - /* Locking again the Mutex */ - mutex_lock(&dev->device_lock); } diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 9ff942a346e..83269f1d16e 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -468,6 +468,11 @@ long st_kim_start(void *kim_data) if (pdata->chip_enable) pdata->chip_enable(kim_gdata); + /* Configure BT nShutdown to HIGH state */ + gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); + mdelay(5); /* FIXME: a proper toggle */ + gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); + mdelay(100); /* re-initialize the completion */ INIT_COMPLETION(kim_gdata->ldisc_installed); /* send notification to UIM */ @@ -509,7 +514,8 @@ long st_kim_start(void *kim_data) * (b) upon failure to either install ldisc or download firmware. * The function is responsible to (a) notify UIM about un-installation, * (b) flush UART if the ldisc was installed. - * (c) invoke platform's chip disabling routine. + * (c) reset BT_EN - pull down nshutdown at the end. + * (d) invoke platform's chip disabling routine. */ long st_kim_stop(void *kim_data) { @@ -541,6 +547,13 @@ long st_kim_stop(void *kim_data) err = -ETIMEDOUT; } + /* By default configure BT nShutdown to LOW state */ + gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); + mdelay(1); + gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); + mdelay(1); + gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); + /* platform specific disable */ if (pdata->chip_disable) pdata->chip_disable(kim_gdata); @@ -733,6 +746,20 @@ static int kim_probe(struct platform_device *pdev) /* refer to itself */ kim_gdata->core_data->kim_data = kim_gdata; + /* Claim the chip enable nShutdown gpio from the system */ + kim_gdata->nshutdown = pdata->nshutdown_gpio; + err = gpio_request(kim_gdata->nshutdown, "kim"); + if (unlikely(err)) { + pr_err(" gpio %ld request failed ", kim_gdata->nshutdown); + return err; + } + + /* Configure nShutdown GPIO as output=0 */ + err = gpio_direction_output(kim_gdata->nshutdown, 0); + if (unlikely(err)) { + pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown); + return err; + } /* get reference of pdev for request_firmware */ kim_gdata->kim_pdev = pdev; @@ -779,10 +806,18 @@ err_core_init: static int kim_remove(struct platform_device *pdev) { + /* free the GPIOs requested */ + struct ti_st_plat_data *pdata = pdev->dev.platform_data; struct kim_data_s *kim_gdata; kim_gdata = dev_get_drvdata(&pdev->dev); + /* Free the Bluetooth/FM/GPIO + * nShutdown gpio from the system + */ + gpio_free(pdata->nshutdown_gpio); + pr_info("nshutdown GPIO Freed"); + debugfs_remove_recursive(kim_debugfs_dir); sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); pr_info("sysfs entries removed"); diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index de4c20b3936..f8dd3610294 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -50,8 +50,6 @@ struct mvsd_host { struct timer_list timer; struct mmc_host *mmc; struct device *dev; - struct resource *res; - int irq; struct clk *clk; int gpio_card_detect; int gpio_write_protect; @@ -718,10 +716,6 @@ static int __init mvsd_probe(struct platform_device *pdev) if (!r || irq < 0 || !mvsd_data) return -ENXIO; - r = request_mem_region(r->start, SZ_1K, DRIVER_NAME); - if (!r) - return -EBUSY; - mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev); if (!mmc) { ret = -ENOMEM; @@ -731,8 +725,8 @@ static int __init mvsd_probe(struct platform_device *pdev) host = mmc_priv(mmc); host->mmc = mmc; host->dev = &pdev->dev; - host->res = r; host->base_clock = mvsd_data->clock / 2; + host->clk = ERR_PTR(-EINVAL); mmc->ops = &mvsd_ops; @@ -752,7 +746,7 @@ static int __init mvsd_probe(struct platform_device *pdev) spin_lock_init(&host->lock); - host->base = ioremap(r->start, SZ_4K); + host->base = devm_request_and_ioremap(&pdev->dev, r); if (!host->base) { ret = -ENOMEM; goto out; @@ -765,44 +759,45 @@ static int __init mvsd_probe(struct platform_device *pdev) mvsd_power_down(host); - ret = request_irq(irq, mvsd_irq, 0, DRIVER_NAME, host); + ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host); if (ret) { pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq); goto out; - } else - host->irq = irq; + } /* Not all platforms can gate the clock, so it is not an error if the clock does not exists. */ - host->clk = clk_get(&pdev->dev, NULL); - if (!IS_ERR(host->clk)) { + host->clk = devm_clk_get(&pdev->dev, NULL); + if (!IS_ERR(host->clk)) clk_prepare_enable(host->clk); - } if (mvsd_data->gpio_card_detect) { - ret = gpio_request(mvsd_data->gpio_card_detect, - DRIVER_NAME " cd"); + ret = devm_gpio_request_one(&pdev->dev, + mvsd_data->gpio_card_detect, + GPIOF_IN, DRIVER_NAME " cd"); if (ret == 0) { - gpio_direction_input(mvsd_data->gpio_card_detect); irq = gpio_to_irq(mvsd_data->gpio_card_detect); - ret = request_irq(irq, mvsd_card_detect_irq, - IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING, - DRIVER_NAME " cd", host); + ret = devm_request_irq(&pdev->dev, irq, + mvsd_card_detect_irq, + IRQ_TYPE_EDGE_RISING | + IRQ_TYPE_EDGE_FALLING, + DRIVER_NAME " cd", host); if (ret == 0) host->gpio_card_detect = mvsd_data->gpio_card_detect; else - gpio_free(mvsd_data->gpio_card_detect); + devm_gpio_free(&pdev->dev, + mvsd_data->gpio_card_detect); } } if (!host->gpio_card_detect) mmc->caps |= MMC_CAP_NEEDS_POLL; if (mvsd_data->gpio_write_protect) { - ret = gpio_request(mvsd_data->gpio_write_protect, - DRIVER_NAME " wp"); + ret = devm_gpio_request_one(&pdev->dev, + mvsd_data->gpio_write_protect, + GPIOF_IN, DRIVER_NAME " wp"); if (ret == 0) { - gpio_direction_input(mvsd_data->gpio_write_protect); host->gpio_write_protect = mvsd_data->gpio_write_protect; } @@ -824,26 +819,11 @@ static int __init mvsd_probe(struct platform_device *pdev) return 0; out: - if (host) { - if (host->irq) - free_irq(host->irq, host); - if (host->gpio_card_detect) { - free_irq(gpio_to_irq(host->gpio_card_detect), host); - gpio_free(host->gpio_card_detect); - } - if (host->gpio_write_protect) - gpio_free(host->gpio_write_protect); - if (host->base) - iounmap(host->base); - } - if (r) - release_resource(r); - if (mmc) - if (!IS_ERR_OR_NULL(host->clk)) { + if (mmc) { + if (!IS_ERR(host->clk)) clk_disable_unprepare(host->clk); - clk_put(host->clk); - } mmc_free_host(mmc); + } return ret; } @@ -852,28 +832,16 @@ static int __exit mvsd_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); - if (mmc) { - struct mvsd_host *host = mmc_priv(mmc); + struct mvsd_host *host = mmc_priv(mmc); - if (host->gpio_card_detect) { - free_irq(gpio_to_irq(host->gpio_card_detect), host); - gpio_free(host->gpio_card_detect); - } - mmc_remove_host(mmc); - free_irq(host->irq, host); - if (host->gpio_write_protect) - gpio_free(host->gpio_write_protect); - del_timer_sync(&host->timer); - mvsd_power_down(host); - iounmap(host->base); - release_resource(host->res); + mmc_remove_host(mmc); + del_timer_sync(&host->timer); + mvsd_power_down(host); + + if (!IS_ERR(host->clk)) + clk_disable_unprepare(host->clk); + mmc_free_host(mmc); - if (!IS_ERR(host->clk)) { - clk_disable_unprepare(host->clk); - clk_put(host->clk); - } - mmc_free_host(mmc); - } platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig index e49c0eff040..a9481606bbc 100644 --- a/drivers/net/ethernet/adi/Kconfig +++ b/drivers/net/ethernet/adi/Kconfig @@ -61,6 +61,7 @@ config BFIN_RX_DESC_NUM config BFIN_MAC_USE_HWSTAMP bool "Use IEEE 1588 hwstamp" + depends on BFIN_MAC && BF518 select PTP_1588_CLOCK default y ---help--- diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 01588b66a38..f771ddfba64 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -80,12 +80,37 @@ static inline void bnx2x_move_fp(struct bnx2x *bp, int from, int to) new_txdata_index = new_max_eth_txqs + FCOE_TXQ_IDX_OFFSET; } - memcpy(&bp->bnx2x_txq[old_txdata_index], - &bp->bnx2x_txq[new_txdata_index], + memcpy(&bp->bnx2x_txq[new_txdata_index], + &bp->bnx2x_txq[old_txdata_index], sizeof(struct bnx2x_fp_txdata)); to_fp->txdata_ptr[0] = &bp->bnx2x_txq[new_txdata_index]; } +/** + * bnx2x_shrink_eth_fp - guarantees fastpath structures stay intact + * + * @bp: driver handle + * @delta: number of eth queues which were not allocated + */ +static void bnx2x_shrink_eth_fp(struct bnx2x *bp, int delta) +{ + int i, cos, old_eth_num = BNX2X_NUM_ETH_QUEUES(bp); + + /* Queue pointer cannot be re-set on an fp-basis, as moving pointer + * backward along the array could cause memory to be overriden + */ + for (cos = 1; cos < bp->max_cos; cos++) { + for (i = 0; i < old_eth_num - delta; i++) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + int new_idx = cos * (old_eth_num - delta) + i; + + memcpy(&bp->bnx2x_txq[new_idx], fp->txdata_ptr[cos], + sizeof(struct bnx2x_fp_txdata)); + fp->txdata_ptr[cos] = &bp->bnx2x_txq[new_idx]; + } + } +} + int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */ /* free skb in the packet ring at pos idx @@ -3863,6 +3888,7 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp) int delta = BNX2X_NUM_ETH_QUEUES(bp) - i; WARN_ON(delta < 0); + bnx2x_shrink_eth_fp(bp, delta); if (CNIC_SUPPORT(bp)) /* move non eth FPs next to last eth FP * must be done in that order diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 277f17e3c8f..a427b49a886 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -2777,10 +2777,10 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info) } else if ((info->flow_type == UDP_V6_FLOW) && (bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) { bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested; - return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0); DP(BNX2X_MSG_ETHTOOL, "rss re-configured, UDP 4-tupple %s\n", udp_rss_requested ? "enabled" : "disabled"); + return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0); } else { return 0; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 940ef859dc6..5523da3afcd 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -127,6 +127,17 @@ MODULE_PARM_DESC(debug, " Default debug msglevel"); struct workqueue_struct *bnx2x_wq; +struct bnx2x_mac_vals { + u32 xmac_addr; + u32 xmac_val; + u32 emac_addr; + u32 emac_val; + u32 umac_addr; + u32 umac_val; + u32 bmac_addr; + u32 bmac_val[2]; +}; + enum bnx2x_board_type { BCM57710 = 0, BCM57711, @@ -9420,12 +9431,19 @@ static inline void bnx2x_undi_int_disable(struct bnx2x *bp) bnx2x_undi_int_disable_e1h(bp); } -static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) +static void bnx2x_prev_unload_close_mac(struct bnx2x *bp, + struct bnx2x_mac_vals *vals) { u32 val, base_addr, offset, mask, reset_reg; bool mac_stopped = false; u8 port = BP_PORT(bp); + /* reset addresses as they also mark which values were changed */ + vals->bmac_addr = 0; + vals->umac_addr = 0; + vals->xmac_addr = 0; + vals->emac_addr = 0; + reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2); if (!CHIP_IS_E3(bp)) { @@ -9447,14 +9465,18 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) */ wb_data[0] = REG_RD(bp, base_addr + offset); wb_data[1] = REG_RD(bp, base_addr + offset + 0x4); + vals->bmac_addr = base_addr + offset; + vals->bmac_val[0] = wb_data[0]; + vals->bmac_val[1] = wb_data[1]; wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE; - REG_WR(bp, base_addr + offset, wb_data[0]); - REG_WR(bp, base_addr + offset + 0x4, wb_data[1]); + REG_WR(bp, vals->bmac_addr, wb_data[0]); + REG_WR(bp, vals->bmac_addr + 0x4, wb_data[1]); } BNX2X_DEV_INFO("Disable emac Rx\n"); - REG_WR(bp, NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4, 0); - + vals->emac_addr = NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4; + vals->emac_val = REG_RD(bp, vals->emac_addr); + REG_WR(bp, vals->emac_addr, 0); mac_stopped = true; } else { if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) { @@ -9465,14 +9487,18 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) val & ~(1 << 1)); REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI, val | (1 << 1)); - REG_WR(bp, base_addr + XMAC_REG_CTRL, 0); + vals->xmac_addr = base_addr + XMAC_REG_CTRL; + vals->xmac_val = REG_RD(bp, vals->xmac_addr); + REG_WR(bp, vals->xmac_addr, 0); mac_stopped = true; } mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port; if (mask & reset_reg) { BNX2X_DEV_INFO("Disable umac Rx\n"); base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0; - REG_WR(bp, base_addr + UMAC_REG_COMMAND_CONFIG, 0); + vals->umac_addr = base_addr + UMAC_REG_COMMAND_CONFIG; + vals->umac_val = REG_RD(bp, vals->umac_addr); + REG_WR(bp, vals->umac_addr, 0); mac_stopped = true; } } @@ -9664,12 +9690,16 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) { u32 reset_reg, tmp_reg = 0, rc; bool prev_undi = false; + struct bnx2x_mac_vals mac_vals; + /* It is possible a previous function received 'common' answer, * but hasn't loaded yet, therefore creating a scenario of * multiple functions receiving 'common' on the same path. */ BNX2X_DEV_INFO("Common unload Flow\n"); + memset(&mac_vals, 0, sizeof(mac_vals)); + if (bnx2x_prev_is_path_marked(bp)) return bnx2x_prev_mcp_done(bp); @@ -9680,7 +9710,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) u32 timer_count = 1000; /* Close the MAC Rx to prevent BRB from filling up */ - bnx2x_prev_unload_close_mac(bp); + bnx2x_prev_unload_close_mac(bp, &mac_vals); + + /* close LLH filters towards the BRB */ + bnx2x_set_rx_filter(&bp->link_params, 0); /* Check if the UNDI driver was previously loaded * UNDI driver initializes CID offset for normal bell to 0x7 @@ -9727,6 +9760,17 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) /* No packets are in the pipeline, path is ready for reset */ bnx2x_reset_common(bp); + if (mac_vals.xmac_addr) + REG_WR(bp, mac_vals.xmac_addr, mac_vals.xmac_val); + if (mac_vals.umac_addr) + REG_WR(bp, mac_vals.umac_addr, mac_vals.umac_val); + if (mac_vals.emac_addr) + REG_WR(bp, mac_vals.emac_addr, mac_vals.emac_val); + if (mac_vals.bmac_addr) { + REG_WR(bp, mac_vals.bmac_addr, mac_vals.bmac_val[0]); + REG_WR(bp, mac_vals.bmac_addr + 4, mac_vals.bmac_val[1]); + } + rc = bnx2x_prev_mark_path(bp, prev_undi); if (rc) { bnx2x_prev_mcp_done(bp); diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 3bc1912afba..4eba17b83ba 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -190,6 +190,7 @@ struct be_eq_obj { u8 idx; /* array index */ u16 tx_budget; + u16 spurious_intr; struct napi_struct napi; struct be_adapter *adapter; } ____cacheline_aligned_in_smp; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 9dca22be812..5c995700e53 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -2026,19 +2026,30 @@ static irqreturn_t be_intx(int irq, void *dev) struct be_adapter *adapter = eqo->adapter; int num_evts = 0; - /* On Lancer, clear-intr bit of the EQ DB does not work. - * INTx is de-asserted only on notifying num evts. + /* IRQ is not expected when NAPI is scheduled as the EQ + * will not be armed. + * But, this can happen on Lancer INTx where it takes + * a while to de-assert INTx or in BE2 where occasionaly + * an interrupt may be raised even when EQ is unarmed. + * If NAPI is already scheduled, then counting & notifying + * events will orphan them. */ - if (lancer_chip(adapter)) + if (napi_schedule_prep(&eqo->napi)) { num_evts = events_get(eqo); + __napi_schedule(&eqo->napi); + if (num_evts) + eqo->spurious_intr = 0; + } + be_eq_notify(adapter, eqo->q.id, false, true, num_evts); - /* The EQ-notify may not de-assert INTx rightaway, causing - * the ISR to be invoked again. So, return HANDLED even when - * num_evts is zero. + /* Return IRQ_HANDLED only for the the first spurious intr + * after a valid intr to stop the kernel from branding + * this irq as a bad one! */ - be_eq_notify(adapter, eqo->q.id, false, true, num_evts); - napi_schedule(&eqo->napi); - return IRQ_HANDLED; + if (num_evts || eqo->spurious_intr++ == 0) + return IRQ_HANDLED; + else + return IRQ_NONE; } static irqreturn_t be_msix(int irq, void *dev) diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index f80cd975dae..3e73742024b 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -4678,7 +4678,7 @@ static int qlge_probe(struct pci_dev *pdev, qdev = netdev_priv(ndev); SET_NETDEV_DEV(ndev, &pdev->dev); ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | - NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN | + NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_HW_VLAN_TX | NETIF_F_RXCSUM; ndev->features = ndev->hw_features | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; diff --git a/drivers/net/ethernet/xilinx/Kconfig b/drivers/net/ethernet/xilinx/Kconfig index 5778a4ae116..122d60c0481 100644 --- a/drivers/net/ethernet/xilinx/Kconfig +++ b/drivers/net/ethernet/xilinx/Kconfig @@ -27,7 +27,7 @@ config XILINX_EMACLITE config XILINX_AXI_EMAC tristate "Xilinx 10/100/1000 AXI Ethernet support" - depends on (PPC32 || MICROBLAZE) + depends on MICROBLAZE select PHYLIB ---help--- This driver supports the 10/100/1000 Ethernet from Xilinx for the diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index d9f69b82cc4..6f47100e58d 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1590,7 +1590,7 @@ static int axienet_of_probe(struct platform_device *op) lp->rx_irq = irq_of_parse_and_map(np, 1); lp->tx_irq = irq_of_parse_and_map(np, 0); of_node_put(np); - if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) { + if ((lp->rx_irq <= 0) || (lp->tx_irq <= 0)) { dev_err(&op->dev, "could not determine irqs\n"); ret = -ENOMEM; goto err_iounmap_2; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index fbd106edbe5..af372d0957f 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -404,8 +404,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean) struct tun_struct *tun; struct net_device *dev; - tun = rcu_dereference_protected(tfile->tun, - lockdep_rtnl_is_held()); + tun = rtnl_dereference(tfile->tun); + if (tun) { u16 index = tfile->queue_index; BUG_ON(index >= tun->numqueues); @@ -414,8 +414,7 @@ static void __tun_detach(struct tun_file *tfile, bool clean) rcu_assign_pointer(tun->tfiles[index], tun->tfiles[tun->numqueues - 1]); rcu_assign_pointer(tfile->tun, NULL); - ntfile = rcu_dereference_protected(tun->tfiles[index], - lockdep_rtnl_is_held()); + ntfile = rtnl_dereference(tun->tfiles[index]); ntfile->queue_index = index; --tun->numqueues; @@ -429,8 +428,10 @@ static void __tun_detach(struct tun_file *tfile, bool clean) /* Drop read queue */ skb_queue_purge(&tfile->sk.sk_receive_queue); tun_set_real_num_queues(tun); - } else if (tfile->detached && clean) + } else if (tfile->detached && clean) { tun = tun_enable_queue(tfile); + sock_put(&tfile->sk); + } if (clean) { if (tun && tun->numqueues == 0 && tun->numdisabled == 0 && @@ -458,8 +459,7 @@ static void tun_detach_all(struct net_device *dev) int i, n = tun->numqueues; for (i = 0; i < n; i++) { - tfile = rcu_dereference_protected(tun->tfiles[i], - lockdep_rtnl_is_held()); + tfile = rtnl_dereference(tun->tfiles[i]); BUG_ON(!tfile); wake_up_all(&tfile->wq.wait); rcu_assign_pointer(tfile->tun, NULL); @@ -469,8 +469,7 @@ static void tun_detach_all(struct net_device *dev) synchronize_net(); for (i = 0; i < n; i++) { - tfile = rcu_dereference_protected(tun->tfiles[i], - lockdep_rtnl_is_held()); + tfile = rtnl_dereference(tun->tfiles[i]); /* Drop read queue */ skb_queue_purge(&tfile->sk.sk_receive_queue); sock_put(&tfile->sk); @@ -481,6 +480,9 @@ static void tun_detach_all(struct net_device *dev) sock_put(&tfile->sk); } BUG_ON(tun->numdisabled != 0); + + if (tun->flags & TUN_PERSIST) + module_put(THIS_MODULE); } static int tun_attach(struct tun_struct *tun, struct file *file) @@ -489,7 +491,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file) int err; err = -EINVAL; - if (rcu_dereference_protected(tfile->tun, lockdep_rtnl_is_held())) + if (rtnl_dereference(tfile->tun)) goto out; err = -EBUSY; @@ -1544,6 +1546,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) struct net_device *dev; int err; + if (tfile->detached) + return -EINVAL; + dev = __dev_get_by_name(net, ifr->ifr_name); if (dev) { if (ifr->ifr_flags & IFF_TUN_EXCL) @@ -1738,8 +1743,7 @@ static void tun_detach_filter(struct tun_struct *tun, int n) struct tun_file *tfile; for (i = 0; i < n; i++) { - tfile = rcu_dereference_protected(tun->tfiles[i], - lockdep_rtnl_is_held()); + tfile = rtnl_dereference(tun->tfiles[i]); sk_detach_filter(tfile->socket.sk); } @@ -1752,8 +1756,7 @@ static int tun_attach_filter(struct tun_struct *tun) struct tun_file *tfile; for (i = 0; i < tun->numqueues; i++) { - tfile = rcu_dereference_protected(tun->tfiles[i], - lockdep_rtnl_is_held()); + tfile = rtnl_dereference(tun->tfiles[i]); ret = sk_attach_filter(&tun->fprog, tfile->socket.sk); if (ret) { tun_detach_filter(tun, i); @@ -1771,8 +1774,7 @@ static void tun_set_sndbuf(struct tun_struct *tun) int i; for (i = 0; i < tun->numqueues; i++) { - tfile = rcu_dereference_protected(tun->tfiles[i], - lockdep_rtnl_is_held()); + tfile = rtnl_dereference(tun->tfiles[i]); tfile->socket.sk->sk_sndbuf = tun->sndbuf; } } @@ -1789,13 +1791,10 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr) tun = tfile->detached; if (!tun) ret = -EINVAL; - else if (tun_not_capable(tun)) - ret = -EPERM; else ret = tun_attach(tun, file); } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) { - tun = rcu_dereference_protected(tfile->tun, - lockdep_rtnl_is_held()); + tun = rtnl_dereference(tfile->tun); if (!tun || !(tun->flags & TUN_TAP_MQ)) ret = -EINVAL; else @@ -1880,10 +1879,11 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, /* Disable/Enable persist mode. Keep an extra reference to the * module to prevent the module being unprobed. */ - if (arg) { + if (arg && !(tun->flags & TUN_PERSIST)) { tun->flags |= TUN_PERSIST; __module_get(THIS_MODULE); - } else { + } + if (!arg && (tun->flags & TUN_PERSIST)) { tun->flags &= ~TUN_PERSIST; module_put(THIS_MODULE); } diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 1a67a4f829f..2c02b4e8409 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig @@ -30,5 +30,6 @@ source "drivers/net/wireless/ath/ath9k/Kconfig" source "drivers/net/wireless/ath/carl9170/Kconfig" source "drivers/net/wireless/ath/ath6kl/Kconfig" source "drivers/net/wireless/ath/ar5523/Kconfig" +source "drivers/net/wireless/ath/wil6210/Kconfig" endif diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index 1e18621326d..97b964ded2b 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_ATH9K_HW) += ath9k/ obj-$(CONFIG_CARL9170) += carl9170/ obj-$(CONFIG_ATH6KL) += ath6kl/ obj-$(CONFIG_AR5523) += ar5523/ +obj-$(CONFIG_WIL6210) += wil6210/ obj-$(CONFIG_ATH_COMMON) += ath.o diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig new file mode 100644 index 00000000000..bac3d98a0cf --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/Kconfig @@ -0,0 +1,29 @@ +config WIL6210 + tristate "Wilocity 60g WiFi card wil6210 support" + depends on CFG80211 + depends on PCI + default n + ---help--- + This module adds support for wireless adapter based on + wil6210 chip by Wilocity. It supports operation on the + 60 GHz band, covered by the IEEE802.11ad standard. + + http://wireless.kernel.org/en/users/Drivers/wil6210 + + If you choose to build it as a module, it will be called + wil6210 + +config WIL6210_ISR_COR + bool "Use Clear-On-Read mode for ISR registers for wil6210" + depends on WIL6210 + default y + ---help--- + ISR registers on wil6210 chip may operate in either + COR (Clear-On-Read) or W1C (Write-1-to-Clear) mode. + For production code, use COR (say y); is default since + it saves extra target transaction; + For ISR debug, use W1C (say n); is allows to monitor ISR + registers with debugfs. If COR were used, ISR would + self-clear when accessed for debug purposes, it makes + such monitoring impossible. + Say y unless you debug interrupts diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile new file mode 100644 index 00000000000..9396dc9fe3c --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/Makefile @@ -0,0 +1,13 @@ +obj-$(CONFIG_WIL6210) += wil6210.o + +wil6210-objs := main.o +wil6210-objs += netdev.o +wil6210-objs += cfg80211.o +wil6210-objs += pcie_bus.o +wil6210-objs += debugfs.o +wil6210-objs += wmi.o +wil6210-objs += interrupt.o +wil6210-objs += txrx.o + +subdir-ccflags-y += -Werror +subdir-ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c new file mode 100644 index 00000000000..116f4e807ae --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -0,0 +1,573 @@ +/* + * Copyright (c) 2012 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <linux/kernel.h> +#include <linux/netdevice.h> +#include <linux/sched.h> +#include <linux/etherdevice.h> +#include <linux/wireless.h> +#include <linux/ieee80211.h> +#include <linux/slab.h> +#include <linux/version.h> +#include <net/cfg80211.h> + +#include "wil6210.h" +#include "wmi.h" + +#define CHAN60G(_channel, _flags) { \ + .band = IEEE80211_BAND_60GHZ, \ + .center_freq = 56160 + (2160 * (_channel)), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 40, \ +} + +static struct ieee80211_channel wil_60ghz_channels[] = { + CHAN60G(1, 0), + CHAN60G(2, 0), + CHAN60G(3, 0), +/* channel 4 not supported yet */ +}; + +static struct ieee80211_supported_band wil_band_60ghz = { + .channels = wil_60ghz_channels, + .n_channels = ARRAY_SIZE(wil_60ghz_channels), + .ht_cap = { + .ht_supported = true, + .cap = 0, /* TODO */ + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, /* TODO */ + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, /* TODO */ + .mcs = { + /* MCS 1..12 - SC PHY */ + .rx_mask = {0xfe, 0x1f}, /* 1..12 */ + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, /* TODO */ + }, + }, +}; + +static const struct ieee80211_txrx_stypes +wil_mgmt_stypes[NUM_NL80211_IFTYPES] = { + [NL80211_IFTYPE_STATION] = { + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_AP] = { + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_P2P_CLIENT] = { + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_P2P_GO] = { + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, +}; + +static const u32 wil_cipher_suites[] = { + WLAN_CIPHER_SUITE_GCMP, +}; + +int wil_iftype_nl2wmi(enum nl80211_iftype type) +{ + static const struct { + enum nl80211_iftype nl; + enum wmi_network_type wmi; + } __nl2wmi[] = { + {NL80211_IFTYPE_ADHOC, WMI_NETTYPE_ADHOC}, + {NL80211_IFTYPE_STATION, WMI_NETTYPE_INFRA}, + {NL80211_IFTYPE_AP, WMI_NETTYPE_AP}, + {NL80211_IFTYPE_P2P_CLIENT, WMI_NETTYPE_P2P}, + {NL80211_IFTYPE_P2P_GO, WMI_NETTYPE_P2P}, + {NL80211_IFTYPE_MONITOR, WMI_NETTYPE_ADHOC}, /* FIXME */ + }; + uint i; + + for (i = 0; i < ARRAY_SIZE(__nl2wmi); i++) { + if (__nl2wmi[i].nl == type) + return __nl2wmi[i].wmi; + } + + return -EOPNOTSUPP; +} + +static int wil_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_info *sinfo) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + int rc; + struct wmi_notify_req_cmd cmd = { + .cid = 0, + .interval_usec = 0, + }; + + if (memcmp(mac, wil->dst_addr[0], ETH_ALEN)) + return -ENOENT; + + /* WMI_NOTIFY_REQ_DONE_EVENTID handler fills wil->stats.bf_mcs */ + rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd), + WMI_NOTIFY_REQ_DONE_EVENTID, NULL, 0, 20); + if (rc) + return rc; + + sinfo->generation = wil->sinfo_gen; + + sinfo->filled |= STATION_INFO_TX_BITRATE; + sinfo->txrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; + sinfo->txrate.mcs = wil->stats.bf_mcs; + sinfo->filled |= STATION_INFO_RX_BITRATE; + sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; + sinfo->rxrate.mcs = wil->stats.last_mcs_rx; + + if (test_bit(wil_status_fwconnected, &wil->status)) { + sinfo->filled |= STATION_INFO_SIGNAL; + sinfo->signal = 12; /* TODO: provide real value */ + } + + return 0; +} + +static int wil_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wireless_dev *wdev = wil->wdev; + + switch (type) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_P2P_GO: + break; + case NL80211_IFTYPE_MONITOR: + if (flags) + wil->monitor_flags = *flags; + else + wil->monitor_flags = 0; + + break; + default: + return -EOPNOTSUPP; + } + + wdev->iftype = type; + + return 0; +} + +static int wil_cfg80211_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wireless_dev *wdev = wil->wdev; + struct { + struct wmi_start_scan_cmd cmd; + u16 chnl[4]; + } __packed cmd; + uint i, n; + + if (wil->scan_request) { + wil_err(wil, "Already scanning\n"); + return -EAGAIN; + } + + /* check we are client side */ + switch (wdev->iftype) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_P2P_CLIENT: + break; + default: + return -EOPNOTSUPP; + + } + + /* FW don't support scan after connection attempt */ + if (test_bit(wil_status_dontscan, &wil->status)) { + wil_err(wil, "Scan after connect attempt not supported\n"); + return -EBUSY; + } + + wil->scan_request = request; + + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd.num_channels = 0; + n = min(request->n_channels, 4U); + for (i = 0; i < n; i++) { + int ch = request->channels[i]->hw_value; + if (ch == 0) { + wil_err(wil, + "Scan requested for unknown frequency %dMhz\n", + request->channels[i]->center_freq); + continue; + } + /* 0-based channel indexes */ + cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1; + wil_dbg(wil, "Scan for ch %d : %d MHz\n", ch, + request->channels[i]->center_freq); + } + + return wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + + cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); +} + +static int wil_cfg80211_connect(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_connect_params *sme) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct cfg80211_bss *bss; + struct wmi_connect_cmd conn; + const u8 *ssid_eid; + const u8 *rsn_eid; + int ch; + int rc = 0; + + bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, + sme->ssid, sme->ssid_len, + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); + if (!bss) { + wil_err(wil, "Unable to find BSS\n"); + return -ENOENT; + } + + ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); + if (!ssid_eid) { + wil_err(wil, "No SSID\n"); + rc = -ENOENT; + goto out; + } + + rsn_eid = sme->ie ? + cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) : + NULL; + if (rsn_eid) { + if (sme->ie_len > WMI_MAX_IE_LEN) { + rc = -ERANGE; + wil_err(wil, "IE too large (%td bytes)\n", + sme->ie_len); + goto out; + } + /* + * For secure assoc, send: + * (1) WMI_DELETE_CIPHER_KEY_CMD + * (2) WMI_SET_APPIE_CMD + */ + rc = wmi_del_cipher_key(wil, 0, bss->bssid); + if (rc) { + wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD failed\n"); + goto out; + } + /* WMI_SET_APPIE_CMD */ + rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie); + if (rc) { + wil_err(wil, "WMI_SET_APPIE_CMD failed\n"); + goto out; + } + } + + /* WMI_CONNECT_CMD */ + memset(&conn, 0, sizeof(conn)); + switch (bss->capability & 0x03) { + case WLAN_CAPABILITY_DMG_TYPE_AP: + conn.network_type = WMI_NETTYPE_INFRA; + break; + case WLAN_CAPABILITY_DMG_TYPE_PBSS: + conn.network_type = WMI_NETTYPE_P2P; + break; + default: + wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n", + bss->capability); + goto out; + } + if (rsn_eid) { + conn.dot11_auth_mode = WMI_AUTH11_SHARED; + conn.auth_mode = WMI_AUTH_WPA2_PSK; + conn.pairwise_crypto_type = WMI_CRYPT_AES_GCMP; + conn.pairwise_crypto_len = 16; + } else { + conn.dot11_auth_mode = WMI_AUTH11_OPEN; + conn.auth_mode = WMI_AUTH_NONE; + } + + conn.ssid_len = min_t(u8, ssid_eid[1], 32); + memcpy(conn.ssid, ssid_eid+2, conn.ssid_len); + + ch = bss->channel->hw_value; + if (ch == 0) { + wil_err(wil, "BSS at unknown frequency %dMhz\n", + bss->channel->center_freq); + rc = -EOPNOTSUPP; + goto out; + } + conn.channel = ch - 1; + + memcpy(conn.bssid, bss->bssid, 6); + memcpy(conn.dst_mac, bss->bssid, 6); + /* + * FW don't support scan after connection attempt + */ + set_bit(wil_status_dontscan, &wil->status); + + rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); + if (rc == 0) { + /* Connect can take lots of time */ + mod_timer(&wil->connect_timer, + jiffies + msecs_to_jiffies(2000)); + } + + out: + cfg80211_put_bss(bss); + + return rc; +} + +static int wil_cfg80211_disconnect(struct wiphy *wiphy, + struct net_device *ndev, + u16 reason_code) +{ + int rc; + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + + rc = wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); + + return rc; +} + +static int wil_cfg80211_set_channel(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wireless_dev *wdev = wil->wdev; + + wdev->preset_chandef = *chandef; + + return 0; +} + +static int wil_cfg80211_add_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, + const u8 *mac_addr, + struct key_params *params) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + + /* group key is not used */ + if (!pairwise) + return 0; + + return wmi_add_cipher_key(wil, key_index, mac_addr, + params->key_len, params->key); +} + +static int wil_cfg80211_del_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, + const u8 *mac_addr) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + + /* group key is not used */ + if (!pairwise) + return 0; + + return wmi_del_cipher_key(wil, key_index, mac_addr); +} + +/* Need to be present or wiphy_new() will WARN */ +static int wil_cfg80211_set_default_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool unicast, + bool multicast) +{ + return 0; +} + +static int wil_cfg80211_start_ap(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_ap_settings *info) +{ + int rc = 0; + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wireless_dev *wdev = ndev->ieee80211_ptr; + struct ieee80211_channel *channel = info->chandef.chan; + struct cfg80211_beacon_data *bcon = &info->beacon; + u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); + + if (!channel) { + wil_err(wil, "AP: No channel???\n"); + return -EINVAL; + } + + wil_dbg(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value, + channel->center_freq, info->privacy ? "secure" : "open"); + print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET, + info->ssid, info->ssid_len); + + rc = wil_reset(wil); + if (rc) + return rc; + + rc = wmi_set_ssid(wil, info->ssid_len, info->ssid); + if (rc) + return rc; + + rc = wmi_set_channel(wil, channel->hw_value); + if (rc) + return rc; + + /* MAC address - pre-requisite for other commands */ + wmi_set_mac_address(wil, ndev->dev_addr); + + /* IE's */ + /* bcon 'head IE's are not relevant for 60g band */ + wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len, + bcon->beacon_ies); + wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len, + bcon->proberesp_ies); + wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, + bcon->assocresp_ies); + + wil->secure_pcp = info->privacy; + + rc = wmi_set_bcon(wil, info->beacon_interval, wmi_nettype); + if (rc) + return rc; + + /* Rx VRING. After MAC and beacon */ + rc = wil_rx_init(wil); + + netif_carrier_on(ndev); + + return rc; +} + +static int wil_cfg80211_stop_ap(struct wiphy *wiphy, + struct net_device *ndev) +{ + int rc = 0; + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wireless_dev *wdev = ndev->ieee80211_ptr; + u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); + + /* To stop beaconing, set BI to 0 */ + rc = wmi_set_bcon(wil, 0, wmi_nettype); + + return rc; +} + +static struct cfg80211_ops wil_cfg80211_ops = { + .scan = wil_cfg80211_scan, + .connect = wil_cfg80211_connect, + .disconnect = wil_cfg80211_disconnect, + .change_virtual_intf = wil_cfg80211_change_iface, + .get_station = wil_cfg80211_get_station, + .set_monitor_channel = wil_cfg80211_set_channel, + .add_key = wil_cfg80211_add_key, + .del_key = wil_cfg80211_del_key, + .set_default_key = wil_cfg80211_set_default_key, + /* AP mode */ + .start_ap = wil_cfg80211_start_ap, + .stop_ap = wil_cfg80211_stop_ap, +}; + +static void wil_wiphy_init(struct wiphy *wiphy) +{ + /* TODO: set real value */ + wiphy->max_scan_ssids = 10; + wiphy->max_num_pmkids = 0 /* TODO: */; + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_MONITOR); + /* TODO: enable P2P when integrated with supplicant: + * BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) + */ + wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | + WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; + dev_warn(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", + __func__, wiphy->flags); + wiphy->probe_resp_offload = + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; + + wiphy->bands[IEEE80211_BAND_60GHZ] = &wil_band_60ghz; + + /* TODO: figure this out */ + wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + + wiphy->cipher_suites = wil_cipher_suites; + wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites); + wiphy->mgmt_stypes = wil_mgmt_stypes; +} + +struct wireless_dev *wil_cfg80211_init(struct device *dev) +{ + int rc = 0; + struct wireless_dev *wdev; + + wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!wdev) + return ERR_PTR(-ENOMEM); + + wdev->wiphy = wiphy_new(&wil_cfg80211_ops, + sizeof(struct wil6210_priv)); + if (!wdev->wiphy) { + rc = -ENOMEM; + goto out; + } + + set_wiphy_dev(wdev->wiphy, dev); + wil_wiphy_init(wdev->wiphy); + + rc = wiphy_register(wdev->wiphy); + if (rc < 0) + goto out_failed_reg; + + return wdev; + +out_failed_reg: + wiphy_free(wdev->wiphy); +out: + kfree(wdev); + + return ERR_PTR(rc); +} + +void wil_wdev_free(struct wil6210_priv *wil) +{ + struct wireless_dev *wdev = wil_to_wdev(wil); + + if (!wdev) + return; + + wiphy_unregister(wdev->wiphy); + wiphy_free(wdev->wiphy); + kfree(wdev); +} diff --git a/drivers/net/wireless/ath/wil6210/dbg_hexdump.h b/drivers/net/wireless/ath/wil6210/dbg_hexdump.h new file mode 100644 index 00000000000..6a315ba5aa7 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/dbg_hexdump.h @@ -0,0 +1,30 @@ +#ifndef WIL_DBG_HEXDUMP_H_ +#define WIL_DBG_HEXDUMP_H_ + +#if defined(CONFIG_DYNAMIC_DEBUG) +#define wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ + groupsize, buf, len, ascii) \ +do { \ + DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, \ + __builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\ + if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \ + print_hex_dump(KERN_DEBUG, prefix_str, \ + prefix_type, rowsize, groupsize, \ + buf, len, ascii); \ +} while (0) + +#define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ + groupsize, buf, len, ascii) \ + wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ + groupsize, buf, len, ascii) + +#define print_hex_dump_bytes(prefix_str, prefix_type, buf, len) \ + wil_dynamic_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true) +#else /* defined(CONFIG_DYNAMIC_DEBUG) */ +#define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ + groupsize, buf, len, ascii) \ + print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, rowsize, \ + groupsize, buf, len, ascii) +#endif /* defined(CONFIG_DYNAMIC_DEBUG) */ + +#endif /* WIL_DBG_HEXDUMP_H_ */ diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c new file mode 100644 index 00000000000..65fc9683bfd --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -0,0 +1,603 @@ +/* + * Copyright (c) 2012 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <linux/module.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/pci.h> +#include <linux/rtnetlink.h> + +#include "wil6210.h" +#include "txrx.h" + +/* Nasty hack. Better have per device instances */ +static u32 mem_addr; +static u32 dbg_txdesc_index; + +static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, + const char *name, struct vring *vring) +{ + void __iomem *x = wmi_addr(wil, vring->hwtail); + + seq_printf(s, "VRING %s = {\n", name); + seq_printf(s, " pa = 0x%016llx\n", (unsigned long long)vring->pa); + seq_printf(s, " va = 0x%p\n", vring->va); + seq_printf(s, " size = %d\n", vring->size); + seq_printf(s, " swtail = %d\n", vring->swtail); + seq_printf(s, " swhead = %d\n", vring->swhead); + seq_printf(s, " hwtail = [0x%08x] -> ", vring->hwtail); + if (x) + seq_printf(s, "0x%08x\n", ioread32(x)); + else + seq_printf(s, "???\n"); + + if (vring->va && (vring->size < 1025)) { + uint i; + for (i = 0; i < vring->size; i++) { + volatile struct vring_tx_desc *d = &vring->va[i].tx; + if ((i % 64) == 0 && (i != 0)) + seq_printf(s, "\n"); + seq_printf(s, "%s", (d->dma.status & BIT(0)) ? + "S" : (vring->ctx[i] ? "H" : "h")); + } + seq_printf(s, "\n"); + } + seq_printf(s, "}\n"); +} + +static int wil_vring_debugfs_show(struct seq_file *s, void *data) +{ + uint i; + struct wil6210_priv *wil = s->private; + + wil_print_vring(s, wil, "rx", &wil->vring_rx); + + for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { + struct vring *vring = &(wil->vring_tx[i]); + if (vring->va) { + char name[10]; + snprintf(name, sizeof(name), "tx_%2d", i); + wil_print_vring(s, wil, name, vring); + } + } + + return 0; +} + +static int wil_vring_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, wil_vring_debugfs_show, inode->i_private); +} + +static const struct file_operations fops_vring = { + .open = wil_vring_seq_open, + .release = single_release, + .read = seq_read, + .llseek = seq_lseek, +}; + +static void wil_print_ring(struct seq_file *s, const char *prefix, + void __iomem *off) +{ + struct wil6210_priv *wil = s->private; + struct wil6210_mbox_ring r; + int rsize; + uint i; + + wil_memcpy_fromio_32(&r, off, sizeof(r)); + wil_mbox_ring_le2cpus(&r); + /* + * we just read memory block from NIC. This memory may be + * garbage. Check validity before using it. + */ + rsize = r.size / sizeof(struct wil6210_mbox_ring_desc); + + seq_printf(s, "ring %s = {\n", prefix); + seq_printf(s, " base = 0x%08x\n", r.base); + seq_printf(s, " size = 0x%04x bytes -> %d entries\n", r.size, rsize); + seq_printf(s, " tail = 0x%08x\n", r.tail); + seq_printf(s, " head = 0x%08x\n", r.head); + seq_printf(s, " entry size = %d\n", r.entry_size); + + if (r.size % sizeof(struct wil6210_mbox_ring_desc)) { + seq_printf(s, " ??? size is not multiple of %zd, garbage?\n", + sizeof(struct wil6210_mbox_ring_desc)); + goto out; + } + + if (!wmi_addr(wil, r.base) || + !wmi_addr(wil, r.tail) || + !wmi_addr(wil, r.head)) { + seq_printf(s, " ??? pointers are garbage?\n"); + goto out; + } + + for (i = 0; i < rsize; i++) { + struct wil6210_mbox_ring_desc d; + struct wil6210_mbox_hdr hdr; + size_t delta = i * sizeof(d); + void __iomem *x = wil->csr + HOSTADDR(r.base) + delta; + + wil_memcpy_fromio_32(&d, x, sizeof(d)); + + seq_printf(s, " [%2x] %s %s%s 0x%08x", i, + d.sync ? "F" : "E", + (r.tail - r.base == delta) ? "t" : " ", + (r.head - r.base == delta) ? "h" : " ", + le32_to_cpu(d.addr)); + if (0 == wmi_read_hdr(wil, d.addr, &hdr)) { + u16 len = le16_to_cpu(hdr.len); + seq_printf(s, " -> %04x %04x %04x %02x\n", + le16_to_cpu(hdr.seq), len, + le16_to_cpu(hdr.type), hdr.flags); + if (len <= MAX_MBOXITEM_SIZE) { + int n = 0; + unsigned char printbuf[16 * 3 + 2]; + unsigned char databuf[MAX_MBOXITEM_SIZE]; + void __iomem *src = wmi_buffer(wil, d.addr) + + sizeof(struct wil6210_mbox_hdr); + /* + * No need to check @src for validity - + * we already validated @d.addr while + * reading header + */ + wil_memcpy_fromio_32(databuf, src, len); + while (n < len) { + int l = min(len - n, 16); + hex_dump_to_buffer(databuf + n, l, + 16, 1, printbuf, + sizeof(printbuf), + false); + seq_printf(s, " : %s\n", printbuf); + n += l; + } + } + } else { + seq_printf(s, "\n"); + } + } + out: + seq_printf(s, "}\n"); +} + +static int wil_mbox_debugfs_show(struct seq_file *s, void *data) +{ + struct wil6210_priv *wil = s->private; + + wil_print_ring(s, "tx", wil->csr + HOST_MBOX + + offsetof(struct wil6210_mbox_ctl, tx)); + wil_print_ring(s, "rx", wil->csr + HOST_MBOX + + offsetof(struct wil6210_mbox_ctl, rx)); + + return 0; +} + +static int wil_mbox_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, wil_mbox_debugfs_show, inode->i_private); +} + +static const struct file_operations fops_mbox = { + .open = wil_mbox_seq_open, + .release = single_release, + .read = seq_read, + .llseek = seq_lseek, +}; + +static int wil_debugfs_iomem_x32_set(void *data, u64 val) +{ + iowrite32(val, (void __iomem *)data); + wmb(); /* make sure write propagated to HW */ + + return 0; +} + +static int wil_debugfs_iomem_x32_get(void *data, u64 *val) +{ + *val = ioread32((void __iomem *)data); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get, + wil_debugfs_iomem_x32_set, "0x%08llx\n"); + +static struct dentry *wil_debugfs_create_iomem_x32(const char *name, + mode_t mode, + struct dentry *parent, + void __iomem *value) +{ + return debugfs_create_file(name, mode, parent, (void * __force)value, + &fops_iomem_x32); +} + +static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil, + const char *name, + struct dentry *parent, u32 off) +{ + struct dentry *d = debugfs_create_dir(name, parent); + + if (IS_ERR_OR_NULL(d)) + return -ENODEV; + + wil_debugfs_create_iomem_x32("ICC", S_IRUGO | S_IWUSR, d, + wil->csr + off); + wil_debugfs_create_iomem_x32("ICR", S_IRUGO | S_IWUSR, d, + wil->csr + off + 4); + wil_debugfs_create_iomem_x32("ICM", S_IRUGO | S_IWUSR, d, + wil->csr + off + 8); + wil_debugfs_create_iomem_x32("ICS", S_IWUSR, d, + wil->csr + off + 12); + wil_debugfs_create_iomem_x32("IMV", S_IRUGO | S_IWUSR, d, + wil->csr + off + 16); + wil_debugfs_create_iomem_x32("IMS", S_IWUSR, d, + wil->csr + off + 20); + wil_debugfs_create_iomem_x32("IMC", S_IWUSR, d, + wil->csr + off + 24); + + return 0; +} + +static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil, + struct dentry *parent) +{ + struct dentry *d = debugfs_create_dir("PSEUDO_ISR", parent); + + if (IS_ERR_OR_NULL(d)) + return -ENODEV; + + wil_debugfs_create_iomem_x32("CAUSE", S_IRUGO, d, wil->csr + + HOSTADDR(RGF_DMA_PSEUDO_CAUSE)); + wil_debugfs_create_iomem_x32("MASK_SW", S_IRUGO, d, wil->csr + + HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); + wil_debugfs_create_iomem_x32("MASK_FW", S_IRUGO, d, wil->csr + + HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW)); + + return 0; +} + +static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil, + struct dentry *parent) +{ + struct dentry *d = debugfs_create_dir("ITR_CNT", parent); + + if (IS_ERR_OR_NULL(d)) + return -ENODEV; + + wil_debugfs_create_iomem_x32("TRSH", S_IRUGO, d, wil->csr + + HOSTADDR(RGF_DMA_ITR_CNT_TRSH)); + wil_debugfs_create_iomem_x32("DATA", S_IRUGO, d, wil->csr + + HOSTADDR(RGF_DMA_ITR_CNT_DATA)); + wil_debugfs_create_iomem_x32("CTL", S_IRUGO, d, wil->csr + + HOSTADDR(RGF_DMA_ITR_CNT_CRL)); + + return 0; +} + +static int wil_memread_debugfs_show(struct seq_file *s, void *data) +{ + struct wil6210_priv *wil = s->private; + void __iomem *a = wmi_buffer(wil, cpu_to_le32(mem_addr)); + + if (a) + seq_printf(s, "[0x%08x] = 0x%08x\n", mem_addr, ioread32(a)); + else + seq_printf(s, "[0x%08x] = INVALID\n", mem_addr); + + return 0; +} + +static int wil_memread_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, wil_memread_debugfs_show, inode->i_private); +} + +static const struct file_operations fops_memread = { + .open = wil_memread_seq_open, + .release = single_release, + .read = seq_read, + .llseek = seq_lseek, +}; + +static int wil_default_open(struct inode *inode, struct file *file) +{ + if (inode->i_private) + file->private_data = inode->i_private; + + return 0; +} + +static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + enum { max_count = 4096 }; + struct debugfs_blob_wrapper *blob = file->private_data; + loff_t pos = *ppos; + size_t available = blob->size; + void *buf; + size_t ret; + + if (pos < 0) + return -EINVAL; + + if (pos >= available || !count) + return 0; + + if (count > available - pos) + count = available - pos; + if (count > max_count) + count = max_count; + + buf = kmalloc(count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + wil_memcpy_fromio_32(buf, (const volatile void __iomem *)blob->data + + pos, count); + + ret = copy_to_user(user_buf, buf, count); + kfree(buf); + if (ret == count) + return -EFAULT; + + count -= ret; + *ppos = pos + count; + + return count; +} + +static const struct file_operations fops_ioblob = { + .read = wil_read_file_ioblob, + .open = wil_default_open, + .llseek = default_llseek, +}; + +static +struct dentry *wil_debugfs_create_ioblob(const char *name, + mode_t mode, + struct dentry *parent, + struct debugfs_blob_wrapper *blob) +{ + return debugfs_create_file(name, mode, parent, blob, &fops_ioblob); +} +/*---reset---*/ +static ssize_t wil_write_file_reset(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) +{ + struct wil6210_priv *wil = file->private_data; + struct net_device *ndev = wil_to_ndev(wil); + + /** + * BUG: + * this code does NOT sync device state with the rest of system + * use with care, debug only!!! + */ + rtnl_lock(); + dev_close(ndev); + ndev->flags &= ~IFF_UP; + rtnl_unlock(); + wil_reset(wil); + + return len; +} + +static const struct file_operations fops_reset = { + .write = wil_write_file_reset, + .open = wil_default_open, +}; +/*---------Tx descriptor------------*/ + +static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) +{ + struct wil6210_priv *wil = s->private; + struct vring *vring = &(wil->vring_tx[0]); + + if (!vring->va) { + seq_printf(s, "No Tx VRING\n"); + return 0; + } + + if (dbg_txdesc_index < vring->size) { + volatile struct vring_tx_desc *d = + &(vring->va[dbg_txdesc_index].tx); + volatile u32 *u = (volatile u32 *)d; + struct sk_buff *skb = vring->ctx[dbg_txdesc_index]; + + seq_printf(s, "Tx[%3d] = {\n", dbg_txdesc_index); + seq_printf(s, " MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n", + u[0], u[1], u[2], u[3]); + seq_printf(s, " DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n", + u[4], u[5], u[6], u[7]); + seq_printf(s, " SKB = %p\n", skb); + + if (skb) { + unsigned char printbuf[16 * 3 + 2]; + int i = 0; + int len = skb_headlen(skb); + void *p = skb->data; + + seq_printf(s, " len = %d\n", len); + + while (i < len) { + int l = min(len - i, 16); + hex_dump_to_buffer(p + i, l, 16, 1, printbuf, + sizeof(printbuf), false); + seq_printf(s, " : %s\n", printbuf); + i += l; + } + } + seq_printf(s, "}\n"); + } else { + seq_printf(s, "TxDesc index (%d) >= size (%d)\n", + dbg_txdesc_index, vring->size); + } + + return 0; +} + +static int wil_txdesc_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, wil_txdesc_debugfs_show, inode->i_private); +} + +static const struct file_operations fops_txdesc = { + .open = wil_txdesc_seq_open, + .release = single_release, + .read = seq_read, + .llseek = seq_lseek, +}; + +/*---------beamforming------------*/ +static int wil_bf_debugfs_show(struct seq_file *s, void *data) +{ + struct wil6210_priv *wil = s->private; + seq_printf(s, + "TSF : 0x%016llx\n" + "TxMCS : %d\n" + "Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n", + wil->stats.tsf, wil->stats.bf_mcs, + wil->stats.my_rx_sector, wil->stats.my_tx_sector, + wil->stats.peer_rx_sector, wil->stats.peer_tx_sector); + return 0; +} + +static int wil_bf_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, wil_bf_debugfs_show, inode->i_private); +} + +static const struct file_operations fops_bf = { + .open = wil_bf_seq_open, + .release = single_release, + .read = seq_read, + .llseek = seq_lseek, +}; +/*---------SSID------------*/ +static ssize_t wil_read_file_ssid(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wil6210_priv *wil = file->private_data; + struct wireless_dev *wdev = wil_to_wdev(wil); + + return simple_read_from_buffer(user_buf, count, ppos, + wdev->ssid, wdev->ssid_len); +} + +static ssize_t wil_write_file_ssid(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct wil6210_priv *wil = file->private_data; + struct wireless_dev *wdev = wil_to_wdev(wil); + struct net_device *ndev = wil_to_ndev(wil); + + if (*ppos != 0) { + wil_err(wil, "Unable to set SSID substring from [%d]\n", + (int)*ppos); + return -EINVAL; + } + + if (count > sizeof(wdev->ssid)) { + wil_err(wil, "SSID too long, len = %d\n", (int)count); + return -EINVAL; + } + if (netif_running(ndev)) { + wil_err(wil, "Unable to change SSID on running interface\n"); + return -EINVAL; + } + + wdev->ssid_len = count; + return simple_write_to_buffer(wdev->ssid, wdev->ssid_len, ppos, + buf, count); +} + +static const struct file_operations fops_ssid = { + .read = wil_read_file_ssid, + .write = wil_write_file_ssid, + .open = wil_default_open, +}; + +/*----------------*/ +int wil6210_debugfs_init(struct wil6210_priv *wil) +{ + struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME, + wil_to_wiphy(wil)->debugfsdir); + + if (IS_ERR_OR_NULL(dbg)) + return -ENODEV; + + debugfs_create_file("mbox", S_IRUGO, dbg, wil, &fops_mbox); + debugfs_create_file("vrings", S_IRUGO, dbg, wil, &fops_vring); + debugfs_create_file("txdesc", S_IRUGO, dbg, wil, &fops_txdesc); + debugfs_create_u32("txdesc_index", S_IRUGO | S_IWUSR, dbg, + &dbg_txdesc_index); + debugfs_create_file("bf", S_IRUGO, dbg, wil, &fops_bf); + debugfs_create_file("ssid", S_IRUGO | S_IWUSR, dbg, wil, &fops_ssid); + debugfs_create_u32("secure_pcp", S_IRUGO | S_IWUSR, dbg, + &wil->secure_pcp); + + wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg, + HOSTADDR(RGF_USER_USER_ICR)); + wil6210_debugfs_create_ISR(wil, "DMA_EP_TX_ICR", dbg, + HOSTADDR(RGF_DMA_EP_TX_ICR)); + wil6210_debugfs_create_ISR(wil, "DMA_EP_RX_ICR", dbg, + HOSTADDR(RGF_DMA_EP_RX_ICR)); + wil6210_debugfs_create_ISR(wil, "DMA_EP_MISC_ICR", dbg, + HOSTADDR(RGF_DMA_EP_MISC_ICR)); + wil6210_debugfs_create_pseudo_ISR(wil, dbg); + wil6210_debugfs_create_ITR_CNT(wil, dbg); + + debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr); + debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread); + + debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset); + + wil->rgf_blob.data = (void * __force)wil->csr + 0; + wil->rgf_blob.size = 0xa000; + wil_debugfs_create_ioblob("blob_rgf", S_IRUGO, dbg, &wil->rgf_blob); + + wil->fw_code_blob.data = (void * __force)wil->csr + 0x40000; + wil->fw_code_blob.size = 0x40000; + wil_debugfs_create_ioblob("blob_fw_code", S_IRUGO, dbg, + &wil->fw_code_blob); + + wil->fw_data_blob.data = (void * __force)wil->csr + 0x80000; + wil->fw_data_blob.size = 0x8000; + wil_debugfs_create_ioblob("blob_fw_data", S_IRUGO, dbg, + &wil->fw_data_blob); + + wil->fw_peri_blob.data = (void * __force)wil->csr + 0x88000; + wil->fw_peri_blob.size = 0x18000; + wil_debugfs_create_ioblob("blob_fw_peri", S_IRUGO, dbg, + &wil->fw_peri_blob); + + wil->uc_code_blob.data = (void * __force)wil->csr + 0xa0000; + wil->uc_code_blob.size = 0x10000; + wil_debugfs_create_ioblob("blob_uc_code", S_IRUGO, dbg, + &wil->uc_code_blob); + + wil->uc_data_blob.data = (void * __force)wil->csr + 0xb0000; + wil->uc_data_blob.size = 0x4000; + wil_debugfs_create_ioblob("blob_uc_data", S_IRUGO, dbg, + &wil->uc_data_blob); + + return 0; +} + +void wil6210_debugfs_remove(struct wil6210_priv *wil) +{ + debugfs_remove_recursive(wil->debug); + wil->debug = NULL; +} diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c new file mode 100644 index 00000000000..38049da7104 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -0,0 +1,471 @@ +/* + * Copyright (c) 2012 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <linux/interrupt.h> + +#include "wil6210.h" + +/** + * Theory of operation: + * + * There is ISR pseudo-cause register, + * dma_rgf->DMA_RGF.PSEUDO_CAUSE.PSEUDO_CAUSE + * Its bits represents OR'ed bits from 3 real ISR registers: + * TX, RX, and MISC. + * + * Registers may be configured to either "write 1 to clear" or + * "clear on read" mode + * + * When handling interrupt, one have to mask/unmask interrupts for the + * real ISR registers, or hardware may malfunction. + * + */ + +#define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL) +#define WIL6210_IMC_RX BIT_DMA_EP_RX_ICR_RX_DONE +#define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \ + BIT_DMA_EP_TX_ICR_TX_DONE_N(0)) +#define WIL6210_IMC_MISC (ISR_MISC_FW_READY | ISR_MISC_MBOX_EVT) + +#define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \ + BIT_DMA_PSEUDO_CAUSE_TX | \ + BIT_DMA_PSEUDO_CAUSE_MISC)) + +#if defined(CONFIG_WIL6210_ISR_COR) +/* configure to Clear-On-Read mode */ +#define WIL_ICR_ICC_VALUE (0xFFFFFFFFUL) + +static inline void wil_icr_clear(u32 x, void __iomem *addr) +{ + +} +#else /* defined(CONFIG_WIL6210_ISR_COR) */ +/* configure to Write-1-to-Clear mode */ +#define WIL_ICR_ICC_VALUE (0UL) + +static inline void wil_icr_clear(u32 x, void __iomem *addr) +{ + iowrite32(x, addr); +} +#endif /* defined(CONFIG_WIL6210_ISR_COR) */ + +static inline u32 wil_ioread32_and_clear(void __iomem *addr) +{ + u32 x = ioread32(addr); + + wil_icr_clear(x, addr); + + return x; +} + +static void wil6210_mask_irq_tx(struct wil6210_priv *wil) +{ + iowrite32(WIL6210_IRQ_DISABLE, wil->csr + + HOSTADDR(RGF_DMA_EP_TX_ICR) + + offsetof(struct RGF_ICR, IMS)); +} + +static void wil6210_mask_irq_rx(struct wil6210_priv *wil) +{ + iowrite32(WIL6210_IRQ_DISABLE, wil->csr + + HOSTADDR(RGF_DMA_EP_RX_ICR) + + offsetof(struct RGF_ICR, IMS)); +} + +static void wil6210_mask_irq_misc(struct wil6210_priv *wil) +{ + iowrite32(WIL6210_IRQ_DISABLE, wil->csr + + HOSTADDR(RGF_DMA_EP_MISC_ICR) + + offsetof(struct RGF_ICR, IMS)); +} + +static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil) +{ + wil_dbg_IRQ(wil, "%s()\n", __func__); + + iowrite32(WIL6210_IRQ_DISABLE, wil->csr + + HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); + + clear_bit(wil_status_irqen, &wil->status); +} + +static void wil6210_unmask_irq_tx(struct wil6210_priv *wil) +{ + iowrite32(WIL6210_IMC_TX, wil->csr + + HOSTADDR(RGF_DMA_EP_TX_ICR) + + offsetof(struct RGF_ICR, IMC)); +} + +static void wil6210_unmask_irq_rx(struct wil6210_priv *wil) +{ + iowrite32(WIL6210_IMC_RX, wil->csr + + HOSTADDR(RGF_DMA_EP_RX_ICR) + + offsetof(struct RGF_ICR, IMC)); +} + +static void wil6210_unmask_irq_misc(struct wil6210_priv *wil) +{ + iowrite32(WIL6210_IMC_MISC, wil->csr + + HOSTADDR(RGF_DMA_EP_MISC_ICR) + + offsetof(struct RGF_ICR, IMC)); +} + +static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) +{ + wil_dbg_IRQ(wil, "%s()\n", __func__); + + set_bit(wil_status_irqen, &wil->status); + + iowrite32(WIL6210_IRQ_PSEUDO_MASK, wil->csr + + HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); +} + +void wil6210_disable_irq(struct wil6210_priv *wil) +{ + wil_dbg_IRQ(wil, "%s()\n", __func__); + + wil6210_mask_irq_tx(wil); + wil6210_mask_irq_rx(wil); + wil6210_mask_irq_misc(wil); + wil6210_mask_irq_pseudo(wil); +} + +void wil6210_enable_irq(struct wil6210_priv *wil) +{ + wil_dbg_IRQ(wil, "%s()\n", __func__); + + iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) + + offsetof(struct RGF_ICR, ICC)); + iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) + + offsetof(struct RGF_ICR, ICC)); + iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) + + offsetof(struct RGF_ICR, ICC)); + + wil6210_unmask_irq_pseudo(wil); + wil6210_unmask_irq_tx(wil); + wil6210_unmask_irq_rx(wil); + wil6210_unmask_irq_misc(wil); +} + +static irqreturn_t wil6210_irq_rx(int irq, void *cookie) +{ + struct wil6210_priv *wil = cookie; + u32 isr = wil_ioread32_and_clear(wil->csr + + HOSTADDR(RGF_DMA_EP_RX_ICR) + + offsetof(struct RGF_ICR, ICR)); + + wil_dbg_IRQ(wil, "ISR RX 0x%08x\n", isr); + + if (!isr) { + wil_err(wil, "spurious IRQ: RX\n"); + return IRQ_NONE; + } + + wil6210_mask_irq_rx(wil); + + if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) { + wil_dbg_IRQ(wil, "RX done\n"); + isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE; + wil_rx_handle(wil); + } + + if (isr) + wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr); + + wil6210_unmask_irq_rx(wil); + + return IRQ_HANDLED; +} + +static irqreturn_t wil6210_irq_tx(int irq, void *cookie) +{ + struct wil6210_priv *wil = cookie; + u32 isr = wil_ioread32_and_clear(wil->csr + + HOSTADDR(RGF_DMA_EP_TX_ICR) + + offsetof(struct RGF_ICR, ICR)); + + wil_dbg_IRQ(wil, "ISR TX 0x%08x\n", isr); + + if (!isr) { + wil_err(wil, "spurious IRQ: TX\n"); + return IRQ_NONE; + } + + wil6210_mask_irq_tx(wil); + + if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) { + uint i; + wil_dbg_IRQ(wil, "TX done\n"); + isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; + for (i = 0; i < 24; i++) { + u32 mask = BIT_DMA_EP_TX_ICR_TX_DONE_N(i); + if (isr & mask) { + isr &= ~mask; + wil_dbg_IRQ(wil, "TX done(%i)\n", i); + wil_tx_complete(wil, i); + } + } + } + + if (isr) + wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr); + + wil6210_unmask_irq_tx(wil); + + return IRQ_HANDLED; +} + +static irqreturn_t wil6210_irq_misc(int irq, void *cookie) +{ + struct wil6210_priv *wil = cookie; + u32 isr = wil_ioread32_and_clear(wil->csr + + HOSTADDR(RGF_DMA_EP_MISC_ICR) + + offsetof(struct RGF_ICR, ICR)); + + wil_dbg_IRQ(wil, "ISR MISC 0x%08x\n", isr); + + if (!isr) { + wil_err(wil, "spurious IRQ: MISC\n"); + return IRQ_NONE; + } + + wil6210_mask_irq_misc(wil); + + if (isr & ISR_MISC_FW_READY) { + wil_dbg_IRQ(wil, "IRQ: FW ready\n"); + /** + * Actual FW ready indicated by the + * WMI_FW_READY_EVENTID + */ + isr &= ~ISR_MISC_FW_READY; + } + + wil->isr_misc = isr; + + if (isr) { + return IRQ_WAKE_THREAD; + } else { + wil6210_unmask_irq_misc(wil); + return IRQ_HANDLED; + } +} + +static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) +{ + struct wil6210_priv *wil = cookie; + u32 isr = wil->isr_misc; + + wil_dbg_IRQ(wil, "Thread ISR MISC 0x%08x\n", isr); + + if (isr & ISR_MISC_MBOX_EVT) { + wil_dbg_IRQ(wil, "MBOX event\n"); + wmi_recv_cmd(wil); + isr &= ~ISR_MISC_MBOX_EVT; + } + + if (isr) + wil_err(wil, "un-handled MISC ISR bits 0x%08x\n", isr); + + wil->isr_misc = 0; + + wil6210_unmask_irq_misc(wil); + + return IRQ_HANDLED; +} + +/** + * thread IRQ handler + */ +static irqreturn_t wil6210_thread_irq(int irq, void *cookie) +{ + struct wil6210_priv *wil = cookie; + + wil_dbg_IRQ(wil, "Thread IRQ\n"); + /* Discover real IRQ cause */ + if (wil->isr_misc) + wil6210_irq_misc_thread(irq, cookie); + + wil6210_unmask_irq_pseudo(wil); + + return IRQ_HANDLED; +} + +/* DEBUG + * There is subtle bug in hardware that causes IRQ to raise when it should be + * masked. It is quite rare and hard to debug. + * + * Catch irq issue if it happens and print all I can. + */ +static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause) +{ + if (!test_bit(wil_status_irqen, &wil->status)) { + u32 icm_rx = wil_ioread32_and_clear(wil->csr + + HOSTADDR(RGF_DMA_EP_RX_ICR) + + offsetof(struct RGF_ICR, ICM)); + u32 icr_rx = wil_ioread32_and_clear(wil->csr + + HOSTADDR(RGF_DMA_EP_RX_ICR) + + offsetof(struct RGF_ICR, ICR)); + u32 imv_rx = ioread32(wil->csr + + HOSTADDR(RGF_DMA_EP_RX_ICR) + + offsetof(struct RGF_ICR, IMV)); + u32 icm_tx = wil_ioread32_and_clear(wil->csr + + HOSTADDR(RGF_DMA_EP_TX_ICR) + + offsetof(struct RGF_ICR, ICM)); + u32 icr_tx = wil_ioread32_and_clear(wil->csr + + HOSTADDR(RGF_DMA_EP_TX_ICR) + + offsetof(struct RGF_ICR, ICR)); + u32 imv_tx = ioread32(wil->csr + + HOSTADDR(RGF_DMA_EP_TX_ICR) + + offsetof(struct RGF_ICR, IMV)); + u32 icm_misc = wil_ioread32_and_clear(wil->csr + + HOSTADDR(RGF_DMA_EP_MISC_ICR) + + offsetof(struct RGF_ICR, ICM)); + u32 icr_misc = wil_ioread32_and_clear(wil->csr + + HOSTADDR(RGF_DMA_EP_MISC_ICR) + + offsetof(struct RGF_ICR, ICR)); + u32 imv_misc = ioread32(wil->csr + + HOSTADDR(RGF_DMA_EP_MISC_ICR) + + offsetof(struct RGF_ICR, IMV)); + wil_err(wil, "IRQ when it should be masked: pseudo 0x%08x\n" + "Rx icm:icr:imv 0x%08x 0x%08x 0x%08x\n" + "Tx icm:icr:imv 0x%08x 0x%08x 0x%08x\n" + "Misc icm:icr:imv 0x%08x 0x%08x 0x%08x\n", + pseudo_cause, + icm_rx, icr_rx, imv_rx, + icm_tx, icr_tx, imv_tx, + icm_misc, icr_misc, imv_misc); + + return -EINVAL; + } + + return 0; +} + +static irqreturn_t wil6210_hardirq(int irq, void *cookie) +{ + irqreturn_t rc = IRQ_HANDLED; + struct wil6210_priv *wil = cookie; + u32 pseudo_cause = ioread32(wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE)); + + /** + * pseudo_cause is Clear-On-Read, no need to ACK + */ + if ((pseudo_cause == 0) || ((pseudo_cause & 0xff) == 0xff)) + return IRQ_NONE; + + /* FIXME: IRQ mask debug */ + if (wil6210_debug_irq_mask(wil, pseudo_cause)) + return IRQ_NONE; + + wil6210_mask_irq_pseudo(wil); + + /* Discover real IRQ cause + * There are 2 possible phases for every IRQ: + * - hard IRQ handler called right here + * - threaded handler called later + * + * Hard IRQ handler reads and clears ISR. + * + * If threaded handler requested, hard IRQ handler + * returns IRQ_WAKE_THREAD and saves ISR register value + * for the threaded handler use. + * + * voting for wake thread - need at least 1 vote + */ + if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_RX) && + (wil6210_irq_rx(irq, cookie) == IRQ_WAKE_THREAD)) + rc = IRQ_WAKE_THREAD; + + if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_TX) && + (wil6210_irq_tx(irq, cookie) == IRQ_WAKE_THREAD)) + rc = IRQ_WAKE_THREAD; + + if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_MISC) && + (wil6210_irq_misc(irq, cookie) == IRQ_WAKE_THREAD)) + rc = IRQ_WAKE_THREAD; + + /* if thread is requested, it will unmask IRQ */ + if (rc != IRQ_WAKE_THREAD) + wil6210_unmask_irq_pseudo(wil); + + wil_dbg_IRQ(wil, "Hard IRQ 0x%08x\n", pseudo_cause); + + return rc; +} + +static int wil6210_request_3msi(struct wil6210_priv *wil, int irq) +{ + int rc; + /* + * IRQ's are in the following order: + * - Tx + * - Rx + * - Misc + */ + + rc = request_irq(irq, wil6210_irq_tx, IRQF_SHARED, + WIL_NAME"_tx", wil); + if (rc) + return rc; + + rc = request_irq(irq + 1, wil6210_irq_rx, IRQF_SHARED, + WIL_NAME"_rx", wil); + if (rc) + goto free0; + + rc = request_threaded_irq(irq + 2, wil6210_irq_misc, + wil6210_irq_misc_thread, + IRQF_SHARED, WIL_NAME"_misc", wil); + if (rc) + goto free1; + + return 0; + /* error branch */ +free1: + free_irq(irq + 1, wil); +free0: + free_irq(irq, wil); + + return rc; +} + +int wil6210_init_irq(struct wil6210_priv *wil, int irq) +{ + int rc; + if (wil->n_msi == 3) + rc = wil6210_request_3msi(wil, irq); + else + rc = request_threaded_irq(irq, wil6210_hardirq, + wil6210_thread_irq, + wil->n_msi ? 0 : IRQF_SHARED, + WIL_NAME, wil); + if (rc) + return rc; + + wil6210_enable_irq(wil); + + return 0; +} + +void wil6210_fini_irq(struct wil6210_priv *wil, int irq) +{ + wil6210_disable_irq(wil); + free_irq(irq, wil); + if (wil->n_msi == 3) { + free_irq(irq + 1, wil); + free_irq(irq + 2, wil); + } +} diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c new file mode 100644 index 00000000000..95fcd361322 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -0,0 +1,407 @@ +/* + * Copyright (c) 2012 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <linux/kernel.h> +#include <linux/netdevice.h> +#include <linux/sched.h> +#include <linux/ieee80211.h> +#include <linux/wireless.h> +#include <linux/slab.h> +#include <linux/moduleparam.h> +#include <linux/if_arp.h> + +#include "wil6210.h" + +/* + * Due to a hardware issue, + * one has to read/write to/from NIC in 32-bit chunks; + * regular memcpy_fromio and siblings will + * not work on 64-bit platform - it uses 64-bit transactions + * + * Force 32-bit transactions to enable NIC on 64-bit platforms + * + * To avoid byte swap on big endian host, __raw_{read|write}l + * should be used - {read|write}l would swap bytes to provide + * little endian on PCI value in host endianness. + */ +void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, + size_t count) +{ + u32 *d = dst; + const volatile u32 __iomem *s = src; + + /* size_t is unsigned, if (count%4 != 0) it will wrap */ + for (count += 4; count > 4; count -= 4) + *d++ = __raw_readl(s++); +} + +void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, + size_t count) +{ + volatile u32 __iomem *d = dst; + const u32 *s = src; + + for (count += 4; count > 4; count -= 4) + __raw_writel(*s++, d++); +} + +static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid) +{ + uint i; + struct net_device *ndev = wil_to_ndev(wil); + struct wireless_dev *wdev = wil->wdev; + + wil_dbg(wil, "%s()\n", __func__); + + wil_link_off(wil); + clear_bit(wil_status_fwconnected, &wil->status); + + switch (wdev->sme_state) { + case CFG80211_SME_CONNECTED: + cfg80211_disconnected(ndev, WLAN_STATUS_UNSPECIFIED_FAILURE, + NULL, 0, GFP_KERNEL); + break; + case CFG80211_SME_CONNECTING: + cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + break; + default: + ; + } + + for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) + wil_vring_fini_tx(wil, i); +} + +static void wil_disconnect_worker(struct work_struct *work) +{ + struct wil6210_priv *wil = container_of(work, + struct wil6210_priv, disconnect_worker); + + _wil6210_disconnect(wil, NULL); +} + +static void wil_connect_timer_fn(ulong x) +{ + struct wil6210_priv *wil = (void *)x; + + wil_dbg(wil, "Connect timeout\n"); + + /* reschedule to thread context - disconnect won't + * run from atomic context + */ + schedule_work(&wil->disconnect_worker); +} + +int wil_priv_init(struct wil6210_priv *wil) +{ + wil_dbg(wil, "%s()\n", __func__); + + mutex_init(&wil->mutex); + mutex_init(&wil->wmi_mutex); + + init_completion(&wil->wmi_ready); + + wil->pending_connect_cid = -1; + setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); + + INIT_WORK(&wil->wmi_connect_worker, wmi_connect_worker); + INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); + INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); + + INIT_LIST_HEAD(&wil->pending_wmi_ev); + spin_lock_init(&wil->wmi_ev_lock); + + wil->wmi_wq = create_singlethread_workqueue(WIL_NAME"_wmi"); + if (!wil->wmi_wq) + return -EAGAIN; + + wil->wmi_wq_conn = create_singlethread_workqueue(WIL_NAME"_connect"); + if (!wil->wmi_wq_conn) { + destroy_workqueue(wil->wmi_wq); + return -EAGAIN; + } + + /* make shadow copy of registers that should not change on run time */ + wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, + sizeof(struct wil6210_mbox_ctl)); + wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); + wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); + + return 0; +} + +void wil6210_disconnect(struct wil6210_priv *wil, void *bssid) +{ + del_timer_sync(&wil->connect_timer); + _wil6210_disconnect(wil, bssid); +} + +void wil_priv_deinit(struct wil6210_priv *wil) +{ + cancel_work_sync(&wil->disconnect_worker); + wil6210_disconnect(wil, NULL); + wmi_event_flush(wil); + destroy_workqueue(wil->wmi_wq_conn); + destroy_workqueue(wil->wmi_wq); +} + +static void wil_target_reset(struct wil6210_priv *wil) +{ + wil_dbg(wil, "Resetting...\n"); + + /* register write */ +#define W(a, v) iowrite32(v, wil->csr + HOSTADDR(a)) + /* register set = read, OR, write */ +#define S(a, v) iowrite32(ioread32(wil->csr + HOSTADDR(a)) | v, \ + wil->csr + HOSTADDR(a)) + + /* hpal_perst_from_pad_src_n_mask */ + S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6)); + /* car_perst_rst_src_n_mask */ + S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7)); + + W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */ + W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ + + msleep(100); + + W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); + W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); + W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170); + W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00); + + msleep(100); + + W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); + W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); + W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); + W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); + + W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001); + W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); + W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); + + msleep(2000); + + W(RGF_USER_USER_CPU_0, BIT(0)); /* user_cpu_man_de_rst */ + + msleep(2000); + + wil_dbg(wil, "Reset completed\n"); + +#undef W +#undef S +} + +void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r) +{ + le32_to_cpus(&r->base); + le16_to_cpus(&r->entry_size); + le16_to_cpus(&r->size); + le32_to_cpus(&r->tail); + le32_to_cpus(&r->head); +} + +static int wil_wait_for_fw_ready(struct wil6210_priv *wil) +{ + ulong to = msecs_to_jiffies(1000); + ulong left = wait_for_completion_timeout(&wil->wmi_ready, to); + if (0 == left) { + wil_err(wil, "Firmware not ready\n"); + return -ETIME; + } else { + wil_dbg(wil, "FW ready after %d ms\n", + jiffies_to_msecs(to-left)); + } + return 0; +} + +/* + * We reset all the structures, and we reset the UMAC. + * After calling this routine, you're expected to reload + * the firmware. + */ +int wil_reset(struct wil6210_priv *wil) +{ + int rc; + + cancel_work_sync(&wil->disconnect_worker); + wil6210_disconnect(wil, NULL); + + wmi_event_flush(wil); + + flush_workqueue(wil->wmi_wq); + flush_workqueue(wil->wmi_wq_conn); + + wil6210_disable_irq(wil); + wil->status = 0; + + /* TODO: put MAC in reset */ + wil_target_reset(wil); + + /* init after reset */ + wil->pending_connect_cid = -1; + INIT_COMPLETION(wil->wmi_ready); + + /* make shadow copy of registers that should not change on run time */ + wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, + sizeof(struct wil6210_mbox_ctl)); + wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); + wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); + + /* TODO: release MAC reset */ + wil6210_enable_irq(wil); + + /* we just started MAC, wait for FW ready */ + rc = wil_wait_for_fw_ready(wil); + + return rc; +} + + +void wil_link_on(struct wil6210_priv *wil) +{ + struct net_device *ndev = wil_to_ndev(wil); + + wil_dbg(wil, "%s()\n", __func__); + + netif_carrier_on(ndev); + netif_tx_wake_all_queues(ndev); +} + +void wil_link_off(struct wil6210_priv *wil) +{ + struct net_device *ndev = wil_to_ndev(wil); + + wil_dbg(wil, "%s()\n", __func__); + + netif_tx_stop_all_queues(ndev); + netif_carrier_off(ndev); +} + +static int __wil_up(struct wil6210_priv *wil) +{ + struct net_device *ndev = wil_to_ndev(wil); + struct wireless_dev *wdev = wil->wdev; + struct ieee80211_channel *channel = wdev->preset_chandef.chan; + int rc; + int bi; + u16 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); + + rc = wil_reset(wil); + if (rc) + return rc; + + /* FIXME Firmware works now in PBSS mode(ToDS=0, FromDS=0) */ + wmi_nettype = wil_iftype_nl2wmi(NL80211_IFTYPE_ADHOC); + switch (wdev->iftype) { + case NL80211_IFTYPE_STATION: + wil_dbg(wil, "type: STATION\n"); + bi = 0; + ndev->type = ARPHRD_ETHER; + break; + case NL80211_IFTYPE_AP: + wil_dbg(wil, "type: AP\n"); + bi = 100; + ndev->type = ARPHRD_ETHER; + break; + case NL80211_IFTYPE_P2P_CLIENT: + wil_dbg(wil, "type: P2P_CLIENT\n"); + bi = 0; + ndev->type = ARPHRD_ETHER; + break; + case NL80211_IFTYPE_P2P_GO: + wil_dbg(wil, "type: P2P_GO\n"); + bi = 100; + ndev->type = ARPHRD_ETHER; + break; + case NL80211_IFTYPE_MONITOR: + wil_dbg(wil, "type: Monitor\n"); + bi = 0; + ndev->type = ARPHRD_IEEE80211_RADIOTAP; + /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */ + break; + default: + return -EOPNOTSUPP; + } + + /* Apply profile in the following order: */ + /* SSID and channel for the AP */ + switch (wdev->iftype) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: + if (wdev->ssid_len == 0) { + wil_err(wil, "SSID not set\n"); + return -EINVAL; + } + wmi_set_ssid(wil, wdev->ssid_len, wdev->ssid); + if (channel) + wmi_set_channel(wil, channel->hw_value); + break; + default: + ; + } + + /* MAC address - pre-requisite for other commands */ + wmi_set_mac_address(wil, ndev->dev_addr); + + /* Set up beaconing if required. */ + rc = wmi_set_bcon(wil, bi, wmi_nettype); + if (rc) + return rc; + + /* Rx VRING. After MAC and beacon */ + wil_rx_init(wil); + + return 0; +} + +int wil_up(struct wil6210_priv *wil) +{ + int rc; + + mutex_lock(&wil->mutex); + rc = __wil_up(wil); + mutex_unlock(&wil->mutex); + + return rc; +} + +static int __wil_down(struct wil6210_priv *wil) +{ + if (wil->scan_request) { + cfg80211_scan_done(wil->scan_request, true); + wil->scan_request = NULL; + } + + wil6210_disconnect(wil, NULL); + wil_rx_fini(wil); + + return 0; +} + +int wil_down(struct wil6210_priv *wil) +{ + int rc; + + mutex_lock(&wil->mutex); + rc = __wil_down(wil); + mutex_unlock(&wil->mutex); + + return rc; +} diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c new file mode 100644 index 00000000000..3068b5cb53a --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2012 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/slab.h> + +#include "wil6210.h" + +static int wil_open(struct net_device *ndev) +{ + struct wil6210_priv *wil = ndev_to_wil(ndev); + + return wil_up(wil); +} + +static int wil_stop(struct net_device *ndev) +{ + struct wil6210_priv *wil = ndev_to_wil(ndev); + + return wil_down(wil); +} + +/* + * AC to queue mapping + * + * AC_VO -> queue 3 + * AC_VI -> queue 2 + * AC_BE -> queue 1 + * AC_BK -> queue 0 + */ +static u16 wil_select_queue(struct net_device *ndev, struct sk_buff *skb) +{ + static const u16 wil_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; + struct wil6210_priv *wil = ndev_to_wil(ndev); + u16 rc; + + skb->priority = cfg80211_classify8021d(skb); + + rc = wil_1d_to_queue[skb->priority]; + + wil_dbg_TXRX(wil, "%s() %d -> %d\n", __func__, (int)skb->priority, + (int)rc); + + return rc; +} + +static const struct net_device_ops wil_netdev_ops = { + .ndo_open = wil_open, + .ndo_stop = wil_stop, + .ndo_start_xmit = wil_start_xmit, + .ndo_select_queue = wil_select_queue, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + +void *wil_if_alloc(struct device *dev, void __iomem *csr) +{ + struct net_device *ndev; + struct wireless_dev *wdev; + struct wil6210_priv *wil; + struct ieee80211_channel *ch; + int rc = 0; + + wdev = wil_cfg80211_init(dev); + if (IS_ERR(wdev)) { + dev_err(dev, "wil_cfg80211_init failed\n"); + return wdev; + } + + wil = wdev_to_wil(wdev); + wil->csr = csr; + wil->wdev = wdev; + + rc = wil_priv_init(wil); + if (rc) { + dev_err(dev, "wil_priv_init failed\n"); + goto out_wdev; + } + + wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */ + /* default monitor channel */ + ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels; + cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); + + ndev = alloc_netdev_mqs(0, "wlan%d", ether_setup, WIL6210_TX_QUEUES, 1); + if (!ndev) { + dev_err(dev, "alloc_netdev_mqs failed\n"); + rc = -ENOMEM; + goto out_priv; + } + + ndev->netdev_ops = &wil_netdev_ops; + ndev->ieee80211_ptr = wdev; + SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); + wdev->netdev = ndev; + + wil_link_off(wil); + + return wil; + + out_priv: + wil_priv_deinit(wil); + + out_wdev: + wil_wdev_free(wil); + + return ERR_PTR(rc); +} + +void wil_if_free(struct wil6210_priv *wil) +{ + struct net_device *ndev = wil_to_ndev(wil); + if (!ndev) + return; + + free_netdev(ndev); + wil_priv_deinit(wil); + wil_wdev_free(wil); +} + +int wil_if_add(struct wil6210_priv *wil) +{ + struct net_device *ndev = wil_to_ndev(wil); + int rc; + + rc = register_netdev(ndev); + if (rc < 0) { + dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc); + return rc; + } + + wil_link_off(wil); + + return 0; +} + +void wil_if_remove(struct wil6210_priv *wil) +{ + struct net_device *ndev = wil_to_ndev(wil); + + unregister_netdev(ndev); +} diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c new file mode 100644 index 00000000000..0fc83edd6ba --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2012 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/netdevice.h> +#include <linux/debugfs.h> +#include <linux/pci.h> +#include <linux/moduleparam.h> + +#include "wil6210.h" + +static int use_msi = 1; +module_param(use_msi, int, S_IRUGO); +MODULE_PARM_DESC(use_msi, + " Use MSI interrupt: " + "0 - don't, 1 - (default) - single, or 3"); + +/* Bus ops */ +static int wil_if_pcie_enable(struct wil6210_priv *wil) +{ + struct pci_dev *pdev = wil->pdev; + int rc; + + pci_set_master(pdev); + + /* + * how many MSI interrupts to request? + */ + switch (use_msi) { + case 3: + case 1: + case 0: + break; + default: + wil_err(wil, "Invalid use_msi=%d, default to 1\n", + use_msi); + use_msi = 1; + } + wil->n_msi = use_msi; + if (wil->n_msi) { + wil_dbg(wil, "Setup %d MSI interrupts\n", use_msi); + rc = pci_enable_msi_block(pdev, wil->n_msi); + if (rc && (wil->n_msi == 3)) { + wil_err(wil, "3 MSI mode failed, try 1 MSI\n"); + wil->n_msi = 1; + rc = pci_enable_msi_block(pdev, wil->n_msi); + } + if (rc) { + wil_err(wil, "pci_enable_msi failed, use INTx\n"); + wil->n_msi = 0; + } + } else { + wil_dbg(wil, "MSI interrupts disabled, use INTx\n"); + } + + rc = wil6210_init_irq(wil, pdev->irq); + if (rc) + goto stop_master; + + /* need reset here to obtain MAC */ + rc = wil_reset(wil); + if (rc) + goto release_irq; + + return 0; + + release_irq: + wil6210_fini_irq(wil, pdev->irq); + /* safe to call if no MSI */ + pci_disable_msi(pdev); + stop_master: + pci_clear_master(pdev); + return rc; +} + +static int wil_if_pcie_disable(struct wil6210_priv *wil) +{ + struct pci_dev *pdev = wil->pdev; + + pci_clear_master(pdev); + /* disable and release IRQ */ + wil6210_fini_irq(wil, pdev->irq); + /* safe to call if no MSI */ + pci_disable_msi(pdev); + /* TODO: disable HW */ + + return 0; +} + +static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct wil6210_priv *wil; + struct device *dev = &pdev->dev; + void __iomem *csr; + int rc; + + /* check HW */ + dev_info(&pdev->dev, WIL_NAME " device found [%04x:%04x] (rev %x)\n", + (int)pdev->vendor, (int)pdev->device, (int)pdev->revision); + + if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) { + dev_err(&pdev->dev, "Not " WIL_NAME "? " + "BAR0 size is %lu while expecting %lu\n", + (ulong)pci_resource_len(pdev, 0), WIL6210_MEM_SIZE); + return -ENODEV; + } + + rc = pci_enable_device(pdev); + if (rc) { + dev_err(&pdev->dev, "pci_enable_device failed\n"); + return -ENODEV; + } + /* rollback to err_disable_pdev */ + + rc = pci_request_region(pdev, 0, WIL_NAME); + if (rc) { + dev_err(&pdev->dev, "pci_request_region failed\n"); + goto err_disable_pdev; + } + /* rollback to err_release_reg */ + + csr = pci_ioremap_bar(pdev, 0); + if (!csr) { + dev_err(&pdev->dev, "pci_ioremap_bar failed\n"); + rc = -ENODEV; + goto err_release_reg; + } + /* rollback to err_iounmap */ + dev_info(&pdev->dev, "CSR at %pR -> %p\n", &pdev->resource[0], csr); + + wil = wil_if_alloc(dev, csr); + if (IS_ERR(wil)) { + rc = (int)PTR_ERR(wil); + dev_err(dev, "wil_if_alloc failed: %d\n", rc); + goto err_iounmap; + } + /* rollback to if_free */ + + pci_set_drvdata(pdev, wil); + wil->pdev = pdev; + + /* FW should raise IRQ when ready */ + rc = wil_if_pcie_enable(wil); + if (rc) { + wil_err(wil, "Enable device failed\n"); + goto if_free; + } + /* rollback to bus_disable */ + + rc = wil_if_add(wil); + if (rc) { + wil_err(wil, "wil_if_add failed: %d\n", rc); + goto bus_disable; + } + + wil6210_debugfs_init(wil); + + /* check FW is alive */ + wmi_echo(wil); + + return 0; + + bus_disable: + wil_if_pcie_disable(wil); + if_free: + wil_if_free(wil); + err_iounmap: + pci_iounmap(pdev, csr); + err_release_reg: + pci_release_region(pdev, 0); + err_disable_pdev: + pci_disable_device(pdev); + + return rc; +} + +static void wil_pcie_remove(struct pci_dev *pdev) +{ + struct wil6210_priv *wil = pci_get_drvdata(pdev); + + wil6210_debugfs_remove(wil); + wil_if_pcie_disable(wil); + wil_if_remove(wil); + wil_if_free(wil); + pci_iounmap(pdev, wil->csr); + pci_release_region(pdev, 0); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); +} + +static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = { + { PCI_DEVICE(0x1ae9, 0x0301) }, + { /* end: all zeroes */ }, +}; +MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); + +static struct pci_driver wil6210_driver = { + .probe = wil_pcie_probe, + .remove = wil_pcie_remove, + .id_table = wil6210_pcie_ids, + .name = WIL_NAME, +}; + +module_pci_driver(wil6210_driver); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Qualcomm Atheros <wil6210@qca.qualcomm.com>"); +MODULE_DESCRIPTION("Driver for 60g WiFi WIL6210 card"); diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c new file mode 100644 index 00000000000..f29c294413c --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -0,0 +1,871 @@ +/* + * Copyright (c) 2012 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <linux/kernel.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/hardirq.h> +#include <net/ieee80211_radiotap.h> +#include <linux/if_arp.h> +#include <linux/moduleparam.h> + +#include "wil6210.h" +#include "wmi.h" +#include "txrx.h" + +static bool rtap_include_phy_info; +module_param(rtap_include_phy_info, bool, S_IRUGO); +MODULE_PARM_DESC(rtap_include_phy_info, + " Include PHY info in the radiotap header, default - no"); + +static inline int wil_vring_is_empty(struct vring *vring) +{ + return vring->swhead == vring->swtail; +} + +static inline u32 wil_vring_next_tail(struct vring *vring) +{ + return (vring->swtail + 1) % vring->size; +} + +static inline void wil_vring_advance_head(struct vring *vring, int n) +{ + vring->swhead = (vring->swhead + n) % vring->size; +} + +static inline int wil_vring_is_full(struct vring *vring) +{ + return wil_vring_next_tail(vring) == vring->swhead; +} +/* + * Available space in Tx Vring + */ +static inline int wil_vring_avail_tx(struct vring *vring) +{ + u32 swhead = vring->swhead; + u32 swtail = vring->swtail; + int used = (vring->size + swhead - swtail) % vring->size; + + return vring->size - used - 1; +} + +static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring) +{ + struct device *dev = wil_to_dev(wil); + size_t sz = vring->size * sizeof(vring->va[0]); + uint i; + + BUILD_BUG_ON(sizeof(vring->va[0]) != 32); + + vring->swhead = 0; + vring->swtail = 0; + vring->ctx = kzalloc(vring->size * sizeof(vring->ctx[0]), GFP_KERNEL); + if (!vring->ctx) { + wil_err(wil, "vring_alloc [%d] failed to alloc ctx mem\n", + vring->size); + vring->va = NULL; + return -ENOMEM; + } + /* + * vring->va should be aligned on its size rounded up to power of 2 + * This is granted by the dma_alloc_coherent + */ + vring->va = dma_alloc_coherent(dev, sz, &vring->pa, GFP_KERNEL); + if (!vring->va) { + wil_err(wil, "vring_alloc [%d] failed to alloc DMA mem\n", + vring->size); + kfree(vring->ctx); + vring->ctx = NULL; + return -ENOMEM; + } + /* initially, all descriptors are SW owned + * For Tx and Rx, ownership bit is at the same location, thus + * we can use any + */ + for (i = 0; i < vring->size; i++) { + volatile struct vring_tx_desc *d = &(vring->va[i].tx); + d->dma.status = TX_DMA_STATUS_DU; + } + + wil_dbg(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size, + vring->va, (unsigned long long)vring->pa, vring->ctx); + + return 0; +} + +static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, + int tx) +{ + struct device *dev = wil_to_dev(wil); + size_t sz = vring->size * sizeof(vring->va[0]); + + while (!wil_vring_is_empty(vring)) { + if (tx) { + volatile struct vring_tx_desc *d = + &vring->va[vring->swtail].tx; + dma_addr_t pa = d->dma.addr_low | + ((u64)d->dma.addr_high << 32); + struct sk_buff *skb = vring->ctx[vring->swtail]; + if (skb) { + dma_unmap_single(dev, pa, d->dma.length, + DMA_TO_DEVICE); + dev_kfree_skb_any(skb); + vring->ctx[vring->swtail] = NULL; + } else { + dma_unmap_page(dev, pa, d->dma.length, + DMA_TO_DEVICE); + } + vring->swtail = wil_vring_next_tail(vring); + } else { /* rx */ + volatile struct vring_rx_desc *d = + &vring->va[vring->swtail].rx; + dma_addr_t pa = d->dma.addr_low | + ((u64)d->dma.addr_high << 32); + struct sk_buff *skb = vring->ctx[vring->swhead]; + dma_unmap_single(dev, pa, d->dma.length, + DMA_FROM_DEVICE); + kfree_skb(skb); + wil_vring_advance_head(vring, 1); + } + } + dma_free_coherent(dev, sz, (void *)vring->va, vring->pa); + kfree(vring->ctx); + vring->pa = 0; + vring->va = NULL; + vring->ctx = NULL; +} + +/** + * Allocate one skb for Rx VRING + * + * Safe to call from IRQ + */ +static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring, + u32 i, int headroom) +{ + struct device *dev = wil_to_dev(wil); + unsigned int sz = RX_BUF_LEN; + volatile struct vring_rx_desc *d = &(vring->va[i].rx); + dma_addr_t pa; + + /* TODO align */ + struct sk_buff *skb = dev_alloc_skb(sz + headroom); + if (unlikely(!skb)) + return -ENOMEM; + + skb_reserve(skb, headroom); + skb_put(skb, sz); + + pa = dma_map_single(dev, skb->data, skb->len, DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(dev, pa))) { + kfree_skb(skb); + return -ENOMEM; + } + + d->dma.d0 = BIT(9) | RX_DMA_D0_CMD_DMA_IT; + d->dma.addr_low = lower_32_bits(pa); + d->dma.addr_high = (u16)upper_32_bits(pa); + /* ip_length don't care */ + /* b11 don't care */ + /* error don't care */ + d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ + d->dma.length = sz; + vring->ctx[i] = skb; + + return 0; +} + +/** + * Adds radiotap header + * + * Any error indicated as "Bad FCS" + * + * Vendor data for 04:ce:14-1 (Wilocity-1) consists of: + * - Rx descriptor: 32 bytes + * - Phy info + */ +static void wil_rx_add_radiotap_header(struct wil6210_priv *wil, + struct sk_buff *skb, + volatile struct vring_rx_desc *d) +{ + struct wireless_dev *wdev = wil->wdev; + struct wil6210_rtap { + struct ieee80211_radiotap_header rthdr; + /* fields should be in the order of bits in rthdr.it_present */ + /* flags */ + u8 flags; + /* channel */ + __le16 chnl_freq __aligned(2); + __le16 chnl_flags; + /* MCS */ + u8 mcs_present; + u8 mcs_flags; + u8 mcs_index; + } __packed; + struct wil6210_rtap_vendor { + struct wil6210_rtap rtap; + /* vendor */ + u8 vendor_oui[3] __aligned(2); + u8 vendor_ns; + __le16 vendor_skip; + u8 vendor_data[0]; + } __packed; + struct wil6210_rtap_vendor *rtap_vendor; + int rtap_len = sizeof(struct wil6210_rtap); + int phy_length = 0; /* phy info header size, bytes */ + static char phy_data[128]; + struct ieee80211_channel *ch = wdev->preset_chandef.chan; + + if (rtap_include_phy_info) { + rtap_len = sizeof(*rtap_vendor) + sizeof(*d); + /* calculate additional length */ + if (d->dma.status & RX_DMA_STATUS_PHY_INFO) { + /** + * PHY info starts from 8-byte boundary + * there are 8-byte lines, last line may be partially + * written (HW bug), thus FW configures for last line + * to be excessive. Driver skips this last line. + */ + int len = min_t(int, 8 + sizeof(phy_data), + wil_rxdesc_phy_length(d)); + if (len > 8) { + void *p = skb_tail_pointer(skb); + void *pa = PTR_ALIGN(p, 8); + if (skb_tailroom(skb) >= len + (pa - p)) { + phy_length = len - 8; + memcpy(phy_data, pa, phy_length); + } + } + } + rtap_len += phy_length; + } + + if (skb_headroom(skb) < rtap_len && + pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)) { + wil_err(wil, "Unable to expand headrom to %d\n", rtap_len); + return; + } + + rtap_vendor = (void *)skb_push(skb, rtap_len); + memset(rtap_vendor, 0, rtap_len); + + rtap_vendor->rtap.rthdr.it_version = PKTHDR_RADIOTAP_VERSION; + rtap_vendor->rtap.rthdr.it_len = cpu_to_le16(rtap_len); + rtap_vendor->rtap.rthdr.it_present = cpu_to_le32( + (1 << IEEE80211_RADIOTAP_FLAGS) | + (1 << IEEE80211_RADIOTAP_CHANNEL) | + (1 << IEEE80211_RADIOTAP_MCS)); + if (d->dma.status & RX_DMA_STATUS_ERROR) + rtap_vendor->rtap.flags |= IEEE80211_RADIOTAP_F_BADFCS; + + rtap_vendor->rtap.chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320); + rtap_vendor->rtap.chnl_flags = cpu_to_le16(0); + + rtap_vendor->rtap.mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS; + rtap_vendor->rtap.mcs_flags = 0; + rtap_vendor->rtap.mcs_index = wil_rxdesc_mcs(d); + + if (rtap_include_phy_info) { + rtap_vendor->rtap.rthdr.it_present |= cpu_to_le32(1 << + IEEE80211_RADIOTAP_VENDOR_NAMESPACE); + /* OUI for Wilocity 04:ce:14 */ + rtap_vendor->vendor_oui[0] = 0x04; + rtap_vendor->vendor_oui[1] = 0xce; + rtap_vendor->vendor_oui[2] = 0x14; + rtap_vendor->vendor_ns = 1; + /* Rx descriptor + PHY data */ + rtap_vendor->vendor_skip = cpu_to_le16(sizeof(*d) + + phy_length); + memcpy(rtap_vendor->vendor_data, (void *)d, sizeof(*d)); + memcpy(rtap_vendor->vendor_data + sizeof(*d), phy_data, + phy_length); + } +} + +/* + * Fast swap in place between 2 registers + */ +static void wil_swap_u16(u16 *a, u16 *b) +{ + *a ^= *b; + *b ^= *a; + *a ^= *b; +} + +static void wil_swap_ethaddr(void *data) +{ + struct ethhdr *eth = data; + u16 *s = (u16 *)eth->h_source; + u16 *d = (u16 *)eth->h_dest; + + wil_swap_u16(s++, d++); + wil_swap_u16(s++, d++); + wil_swap_u16(s, d); +} + +/** + * reap 1 frame from @swhead + * + * Safe to call from IRQ + */ +static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, + struct vring *vring) +{ + struct device *dev = wil_to_dev(wil); + struct net_device *ndev = wil_to_ndev(wil); + volatile struct vring_rx_desc *d; + struct sk_buff *skb; + dma_addr_t pa; + unsigned int sz = RX_BUF_LEN; + u8 ftype; + u8 ds_bits; + + if (wil_vring_is_empty(vring)) + return NULL; + + d = &(vring->va[vring->swhead].rx); + if (!(d->dma.status & RX_DMA_STATUS_DU)) { + /* it is not error, we just reached end of Rx done area */ + return NULL; + } + + pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); + skb = vring->ctx[vring->swhead]; + dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE); + skb_trim(skb, d->dma.length); + + wil->stats.last_mcs_rx = wil_rxdesc_mcs(d); + + /* use radiotap header only if required */ + if (ndev->type == ARPHRD_IEEE80211_RADIOTAP) + wil_rx_add_radiotap_header(wil, skb, d); + + wil_dbg_TXRX(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length); + wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_NONE, 32, 4, + (const void *)d, sizeof(*d), false); + + wil_vring_advance_head(vring, 1); + + /* no extra checks if in sniffer mode */ + if (ndev->type != ARPHRD_ETHER) + return skb; + /* + * Non-data frames may be delivered through Rx DMA channel (ex: BAR) + * Driver should recognize it by frame type, that is found + * in Rx descriptor. If type is not data, it is 802.11 frame as is + */ + ftype = wil_rxdesc_ftype(d) << 2; + if (ftype != IEEE80211_FTYPE_DATA) { + wil_dbg_TXRX(wil, "Non-data frame ftype 0x%08x\n", ftype); + /* TODO: process it */ + kfree_skb(skb); + return NULL; + } + + if (skb->len < ETH_HLEN) { + wil_err(wil, "Short frame, len = %d\n", skb->len); + /* TODO: process it (i.e. BAR) */ + kfree_skb(skb); + return NULL; + } + + ds_bits = wil_rxdesc_ds_bits(d); + if (ds_bits == 1) { + /* + * HW bug - in ToDS mode, i.e. Rx on AP side, + * addresses get swapped + */ + wil_swap_ethaddr(skb->data); + } + + return skb; +} + +/** + * allocate and fill up to @count buffers in rx ring + * buffers posted at @swtail + */ +static int wil_rx_refill(struct wil6210_priv *wil, int count) +{ + struct net_device *ndev = wil_to_ndev(wil); + struct vring *v = &wil->vring_rx; + u32 next_tail; + int rc = 0; + int headroom = ndev->type == ARPHRD_IEEE80211_RADIOTAP ? + WIL6210_RTAP_SIZE : 0; + + for (; next_tail = wil_vring_next_tail(v), + (next_tail != v->swhead) && (count-- > 0); + v->swtail = next_tail) { + rc = wil_vring_alloc_skb(wil, v, v->swtail, headroom); + if (rc) { + wil_err(wil, "Error %d in wil_rx_refill[%d]\n", + rc, v->swtail); + break; + } + } + iowrite32(v->swtail, wil->csr + HOSTADDR(v->hwtail)); + + return rc; +} + +/* + * Pass Rx packet to the netif. Update statistics. + */ +static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) +{ + int rc; + unsigned int len = skb->len; + + if (in_interrupt()) + rc = netif_rx(skb); + else + rc = netif_rx_ni(skb); + + if (likely(rc == NET_RX_SUCCESS)) { + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += len; + + } else { + ndev->stats.rx_dropped++; + } +} + +/** + * Proceed all completed skb's from Rx VRING + * + * Safe to call from IRQ + */ +void wil_rx_handle(struct wil6210_priv *wil) +{ + struct net_device *ndev = wil_to_ndev(wil); + struct vring *v = &wil->vring_rx; + struct sk_buff *skb; + + if (!v->va) { + wil_err(wil, "Rx IRQ while Rx not yet initialized\n"); + return; + } + wil_dbg_TXRX(wil, "%s()\n", __func__); + while (NULL != (skb = wil_vring_reap_rx(wil, v))) { + wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_OFFSET, 16, 1, + skb->data, skb_headlen(skb), false); + + skb_orphan(skb); + + if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { + skb->dev = ndev; + skb_reset_mac_header(skb); + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_802_2); + + } else { + skb->protocol = eth_type_trans(skb, ndev); + } + + wil_netif_rx_any(skb, ndev); + } + wil_rx_refill(wil, v->size); +} + +int wil_rx_init(struct wil6210_priv *wil) +{ + struct net_device *ndev = wil_to_ndev(wil); + struct wireless_dev *wdev = wil->wdev; + struct vring *vring = &wil->vring_rx; + int rc; + struct wmi_cfg_rx_chain_cmd cmd = { + .action = WMI_RX_CHAIN_ADD, + .rx_sw_ring = { + .max_mpdu_size = cpu_to_le16(RX_BUF_LEN), + }, + .mid = 0, /* TODO - what is it? */ + .decap_trans_type = WMI_DECAP_TYPE_802_3, + }; + struct { + struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cfg_rx_chain_done_event evt; + } __packed evt; + + vring->size = WIL6210_RX_RING_SIZE; + rc = wil_vring_alloc(wil, vring); + if (rc) + return rc; + + cmd.rx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); + cmd.rx_sw_ring.ring_size = cpu_to_le16(vring->size); + if (wdev->iftype == NL80211_IFTYPE_MONITOR) { + struct ieee80211_channel *ch = wdev->preset_chandef.chan; + + cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON); + if (ch) + cmd.sniffer_cfg.channel = ch->hw_value - 1; + cmd.sniffer_cfg.phy_info_mode = + cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP); + cmd.sniffer_cfg.phy_support = + cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL) + ? WMI_SNIFFER_CP : WMI_SNIFFER_DP); + } + /* typical time for secure PCP is 840ms */ + rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), + WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000); + if (rc) + goto err_free; + + vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr); + + wil_dbg(wil, "Rx init: status %d tail 0x%08x\n", + le32_to_cpu(evt.evt.status), vring->hwtail); + + rc = wil_rx_refill(wil, vring->size); + if (rc) + goto err_free; + + return 0; + err_free: + wil_vring_free(wil, vring, 0); + + return rc; +} + +void wil_rx_fini(struct wil6210_priv *wil) +{ + struct vring *vring = &wil->vring_rx; + + if (vring->va) { + int rc; + struct wmi_cfg_rx_chain_cmd cmd = { + .action = cpu_to_le32(WMI_RX_CHAIN_DEL), + .rx_sw_ring = { + .max_mpdu_size = cpu_to_le16(RX_BUF_LEN), + }, + }; + struct { + struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cfg_rx_chain_done_event cfg; + } __packed wmi_rx_cfg_reply; + + rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), + WMI_CFG_RX_CHAIN_DONE_EVENTID, + &wmi_rx_cfg_reply, sizeof(wmi_rx_cfg_reply), + 100); + wil_vring_free(wil, vring, 0); + } +} + +int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, + int cid, int tid) +{ + int rc; + struct wmi_vring_cfg_cmd cmd = { + .action = cpu_to_le32(WMI_VRING_CMD_ADD), + .vring_cfg = { + .tx_sw_ring = { + .max_mpdu_size = cpu_to_le16(TX_BUF_LEN), + }, + .ringid = id, + .cidxtid = (cid & 0xf) | ((tid & 0xf) << 4), + .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, + .mac_ctrl = 0, + .to_resolution = 0, + .agg_max_wsize = 16, + .schd_params = { + .priority = cpu_to_le16(0), + .timeslot_us = cpu_to_le16(0xfff), + }, + }, + }; + struct { + struct wil6210_mbox_hdr_wmi wmi; + struct wmi_vring_cfg_done_event cmd; + } __packed reply; + struct vring *vring = &wil->vring_tx[id]; + + if (vring->va) { + wil_err(wil, "Tx ring [%d] already allocated\n", id); + rc = -EINVAL; + goto out; + } + + vring->size = size; + rc = wil_vring_alloc(wil, vring); + if (rc) + goto out; + + cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); + cmd.vring_cfg.tx_sw_ring.ring_size = cpu_to_le16(vring->size); + + rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd), + WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); + if (rc) + goto out_free; + + if (reply.cmd.status != WMI_VRING_CFG_SUCCESS) { + wil_err(wil, "Tx config failed, status 0x%02x\n", + reply.cmd.status); + goto out_free; + } + vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); + + return 0; + out_free: + wil_vring_free(wil, vring, 1); + out: + + return rc; +} + +void wil_vring_fini_tx(struct wil6210_priv *wil, int id) +{ + struct vring *vring = &wil->vring_tx[id]; + + if (!vring->va) + return; + + wil_vring_free(wil, vring, 1); +} + +static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, + struct sk_buff *skb) +{ + struct vring *v = &wil->vring_tx[0]; + + if (v->va) + return v; + + return NULL; +} + +static int wil_tx_desc_map(volatile struct vring_tx_desc *d, + dma_addr_t pa, u32 len) +{ + d->dma.addr_low = lower_32_bits(pa); + d->dma.addr_high = (u16)upper_32_bits(pa); + d->dma.ip_length = 0; + /* 0..6: mac_length; 7:ip_version 0-IP6 1-IP4*/ + d->dma.b11 = 0/*14 | BIT(7)*/; + d->dma.error = 0; + d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ + d->dma.length = len; + d->dma.d0 = 0; + d->mac.d[0] = 0; + d->mac.d[1] = 0; + d->mac.d[2] = 0; + d->mac.ucode_cmd = 0; + /* use dst index 0 */ + d->mac.d[1] |= BIT(MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS) | + (0 << MAC_CFG_DESC_TX_1_DST_INDEX_POS); + /* translation type: 0 - bypass; 1 - 802.3; 2 - native wifi */ + d->mac.d[2] = BIT(MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS) | + (1 << MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS); + + return 0; +} + +static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, + struct sk_buff *skb) +{ + struct device *dev = wil_to_dev(wil); + volatile struct vring_tx_desc *d; + u32 swhead = vring->swhead; + int avail = wil_vring_avail_tx(vring); + int nr_frags = skb_shinfo(skb)->nr_frags; + uint f; + int vring_index = vring - wil->vring_tx; + uint i = swhead; + dma_addr_t pa; + + wil_dbg_TXRX(wil, "%s()\n", __func__); + + if (avail < vring->size/8) + netif_tx_stop_all_queues(wil_to_ndev(wil)); + if (avail < 1 + nr_frags) { + wil_err(wil, "Tx ring full. No space for %d fragments\n", + 1 + nr_frags); + return -ENOMEM; + } + d = &(vring->va[i].tx); + + /* FIXME FW can accept only unicast frames for the peer */ + memcpy(skb->data, wil->dst_addr[vring_index], ETH_ALEN); + + pa = dma_map_single(dev, skb->data, + skb_headlen(skb), DMA_TO_DEVICE); + + wil_dbg_TXRX(wil, "Tx skb %d bytes %p -> %#08llx\n", skb_headlen(skb), + skb->data, (unsigned long long)pa); + wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_OFFSET, 16, 1, + skb->data, skb_headlen(skb), false); + + if (unlikely(dma_mapping_error(dev, pa))) + return -EINVAL; + /* 1-st segment */ + wil_tx_desc_map(d, pa, skb_headlen(skb)); + d->mac.d[2] |= ((nr_frags + 1) << + MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS); + /* middle segments */ + for (f = 0; f < nr_frags; f++) { + const struct skb_frag_struct *frag = + &skb_shinfo(skb)->frags[f]; + int len = skb_frag_size(frag); + i = (swhead + f + 1) % vring->size; + d = &(vring->va[i].tx); + pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), + DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(dev, pa))) + goto dma_error; + wil_tx_desc_map(d, pa, len); + vring->ctx[i] = NULL; + } + /* for the last seg only */ + d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS); + d->dma.d0 |= BIT(9); /* BUG: undocumented bit */ + d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS); + d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_POS); + + wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_NONE, 32, 4, + (const void *)d, sizeof(*d), false); + + /* advance swhead */ + wil_vring_advance_head(vring, nr_frags + 1); + wil_dbg_TXRX(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead); + iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail)); + /* hold reference to skb + * to prevent skb release before accounting + * in case of immediate "tx done" + */ + vring->ctx[i] = skb_get(skb); + + return 0; + dma_error: + /* unmap what we have mapped */ + /* Note: increment @f to operate with positive index */ + for (f++; f > 0; f--) { + i = (swhead + f) % vring->size; + d = &(vring->va[i].tx); + d->dma.status = TX_DMA_STATUS_DU; + pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); + if (vring->ctx[i]) + dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE); + else + dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE); + } + + return -EINVAL; +} + + +netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + struct wil6210_priv *wil = ndev_to_wil(ndev); + struct vring *vring; + int rc; + + wil_dbg_TXRX(wil, "%s()\n", __func__); + if (!test_bit(wil_status_fwready, &wil->status)) { + wil_err(wil, "FW not ready\n"); + goto drop; + } + if (!test_bit(wil_status_fwconnected, &wil->status)) { + wil_err(wil, "FW not connected\n"); + goto drop; + } + if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { + wil_err(wil, "Xmit in monitor mode not supported\n"); + goto drop; + } + if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { + rc = wmi_tx_eapol(wil, skb); + } else { + /* find vring */ + vring = wil_find_tx_vring(wil, skb); + if (!vring) { + wil_err(wil, "No Tx VRING available\n"); + goto drop; + } + /* set up vring entry */ + rc = wil_tx_vring(wil, vring, skb); + } + switch (rc) { + case 0: + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += skb->len; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + case -ENOMEM: + return NETDEV_TX_BUSY; + default: + ; /* goto drop; */ + break; + } + drop: + netif_tx_stop_all_queues(ndev); + ndev->stats.tx_dropped++; + dev_kfree_skb_any(skb); + + return NET_XMIT_DROP; +} + +/** + * Clean up transmitted skb's from the Tx VRING + * + * Safe to call from IRQ + */ +void wil_tx_complete(struct wil6210_priv *wil, int ringid) +{ + struct device *dev = wil_to_dev(wil); + struct vring *vring = &wil->vring_tx[ringid]; + + if (!vring->va) { + wil_err(wil, "Tx irq[%d]: vring not initialized\n", ringid); + return; + } + + wil_dbg_TXRX(wil, "%s(%d)\n", __func__, ringid); + + while (!wil_vring_is_empty(vring)) { + volatile struct vring_tx_desc *d = &vring->va[vring->swtail].tx; + dma_addr_t pa; + struct sk_buff *skb; + if (!(d->dma.status & TX_DMA_STATUS_DU)) + break; + + wil_dbg_TXRX(wil, + "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n", + vring->swtail, d->dma.length, d->dma.status, + d->dma.error); + wil_hex_dump_TXRX("TxC ", DUMP_PREFIX_NONE, 32, 4, + (const void *)d, sizeof(*d), false); + + pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); + skb = vring->ctx[vring->swtail]; + if (skb) { + dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE); + dev_kfree_skb_any(skb); + vring->ctx[vring->swtail] = NULL; + } else { + dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE); + } + d->dma.addr_low = 0; + d->dma.addr_high = 0; + d->dma.length = 0; + d->dma.status = TX_DMA_STATUS_DU; + vring->swtail = wil_vring_next_tail(vring); + } + if (wil_vring_avail_tx(vring) > vring->size/4) + netif_tx_wake_all_queues(wil_to_ndev(wil)); +} diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h new file mode 100644 index 00000000000..45a61f597c5 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/txrx.h @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2012 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef WIL6210_TXRX_H +#define WIL6210_TXRX_H + +#define BUF_SW_OWNED (1) +#define BUF_HW_OWNED (0) + +/* size of max. Rx packet */ +#define RX_BUF_LEN (2048) +#define TX_BUF_LEN (2048) +/* how many bytes to reserve for rtap header? */ +#define WIL6210_RTAP_SIZE (128) + +/* Tx/Rx path */ +/* + * Tx descriptor - MAC part + * [dword 0] + * bit 0.. 9 : lifetime_expiry_value:10 + * bit 10 : interrup_en:1 + * bit 11 : status_en:1 + * bit 12..13 : txss_override:2 + * bit 14 : timestamp_insertion:1 + * bit 15 : duration_preserve:1 + * bit 16..21 : reserved0:6 + * bit 22..26 : mcs_index:5 + * bit 27 : mcs_en:1 + * bit 28..29 : reserved1:2 + * bit 30 : reserved2:1 + * bit 31 : sn_preserved:1 + * [dword 1] + * bit 0.. 3 : pkt_mode:4 + * bit 4 : pkt_mode_en:1 + * bit 5.. 7 : reserved0:3 + * bit 8..13 : reserved1:6 + * bit 14 : reserved2:1 + * bit 15 : ack_policy_en:1 + * bit 16..19 : dst_index:4 + * bit 20 : dst_index_en:1 + * bit 21..22 : ack_policy:2 + * bit 23 : lifetime_en:1 + * bit 24..30 : max_retry:7 + * bit 31 : max_retry_en:1 + * [dword 2] + * bit 0.. 7 : num_of_descriptors:8 + * bit 8..17 : reserved:10 + * bit 18..19 : l2_translation_type:2 + * bit 20 : snap_hdr_insertion_en:1 + * bit 21 : vlan_removal_en:1 + * bit 22..31 : reserved0:10 + * [dword 3] + * bit 0.. 31: ucode_cmd:32 + */ +struct vring_tx_mac { + u32 d[3]; + u32 ucode_cmd; +} __packed; + +/* TX MAC Dword 0 */ +#define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_POS 0 +#define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_LEN 10 +#define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_MSK 0x3FF + +#define MAC_CFG_DESC_TX_0_INTERRUP_EN_POS 10 +#define MAC_CFG_DESC_TX_0_INTERRUP_EN_LEN 1 +#define MAC_CFG_DESC_TX_0_INTERRUP_EN_MSK 0x400 + +#define MAC_CFG_DESC_TX_0_STATUS_EN_POS 11 +#define MAC_CFG_DESC_TX_0_STATUS_EN_LEN 1 +#define MAC_CFG_DESC_TX_0_STATUS_EN_MSK 0x800 + +#define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_POS 12 +#define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_LEN 2 +#define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_MSK 0x3000 + +#define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_POS 14 +#define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_LEN 1 +#define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_MSK 0x4000 + +#define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_POS 15 +#define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_LEN 1 +#define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_MSK 0x8000 + +#define MAC_CFG_DESC_TX_0_MCS_INDEX_POS 22 +#define MAC_CFG_DESC_TX_0_MCS_INDEX_LEN 5 +#define MAC_CFG_DESC_TX_0_MCS_INDEX_MSK 0x7C00000 + +#define MAC_CFG_DESC_TX_0_MCS_EN_POS 27 +#define MAC_CFG_DESC_TX_0_MCS_EN_LEN 1 +#define MAC_CFG_DESC_TX_0_MCS_EN_MSK 0x8000000 + +#define MAC_CFG_DESC_TX_0_SN_PRESERVED_POS 31 +#define MAC_CFG_DESC_TX_0_SN_PRESERVED_LEN 1 +#define MAC_CFG_DESC_TX_0_SN_PRESERVED_MSK 0x80000000 + +/* TX MAC Dword 1 */ +#define MAC_CFG_DESC_TX_1_PKT_MODE_POS 0 +#define MAC_CFG_DESC_TX_1_PKT_MODE_LEN 4 +#define MAC_CFG_DESC_TX_1_PKT_MODE_MSK 0xF + +#define MAC_CFG_DESC_TX_1_PKT_MODE_EN_POS 4 +#define MAC_CFG_DESC_TX_1_PKT_MODE_EN_LEN 1 +#define MAC_CFG_DESC_TX_1_PKT_MODE_EN_MSK 0x10 + +#define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_POS 15 +#define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_LEN 1 +#define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_MSK 0x8000 + +#define MAC_CFG_DESC_TX_1_DST_INDEX_POS 16 +#define MAC_CFG_DESC_TX_1_DST_INDEX_LEN 4 +#define MAC_CFG_DESC_TX_1_DST_INDEX_MSK 0xF0000 + +#define MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS 20 +#define MAC_CFG_DESC_TX_1_DST_INDEX_EN_LEN 1 +#define MAC_CFG_DESC_TX_1_DST_INDEX_EN_MSK 0x100000 + +#define MAC_CFG_DESC_TX_1_ACK_POLICY_POS 21 +#define MAC_CFG_DESC_TX_1_ACK_POLICY_LEN 2 +#define MAC_CFG_DESC_TX_1_ACK_POLICY_MSK 0x600000 + +#define MAC_CFG_DESC_TX_1_LIFETIME_EN_POS 23 +#define MAC_CFG_DESC_TX_1_LIFETIME_EN_LEN 1 +#define MAC_CFG_DESC_TX_1_LIFETIME_EN_MSK 0x800000 + +#define MAC_CFG_DESC_TX_1_MAX_RETRY_POS 24 +#define MAC_CFG_DESC_TX_1_MAX_RETRY_LEN 7 +#define MAC_CFG_DESC_TX_1_MAX_RETRY_MSK 0x7F000000 + +#define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_POS 31 +#define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_LEN 1 +#define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_MSK 0x80000000 + +/* TX MAC Dword 2 */ +#define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS 0 +#define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_LEN 8 +#define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_MSK 0xFF + +#define MAC_CFG_DESC_TX_2_RESERVED_POS 8 +#define MAC_CFG_DESC_TX_2_RESERVED_LEN 10 +#define MAC_CFG_DESC_TX_2_RESERVED_MSK 0x3FF00 + +#define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS 18 +#define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_LEN 2 +#define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_MSK 0xC0000 + +#define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS 20 +#define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_LEN 1 +#define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_MSK 0x100000 + +#define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_POS 21 +#define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_LEN 1 +#define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_MSK 0x200000 + +/* TX MAC Dword 3 */ +#define MAC_CFG_DESC_TX_3_UCODE_CMD_POS 0 +#define MAC_CFG_DESC_TX_3_UCODE_CMD_LEN 32 +#define MAC_CFG_DESC_TX_3_UCODE_CMD_MSK 0xFFFFFFFF + +/* TX DMA Dword 0 */ +#define DMA_CFG_DESC_TX_0_L4_LENGTH_POS 0 +#define DMA_CFG_DESC_TX_0_L4_LENGTH_LEN 8 +#define DMA_CFG_DESC_TX_0_L4_LENGTH_MSK 0xFF + +#define DMA_CFG_DESC_TX_0_CMD_EOP_POS 8 +#define DMA_CFG_DESC_TX_0_CMD_EOP_LEN 1 +#define DMA_CFG_DESC_TX_0_CMD_EOP_MSK 0x100 + +#define DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS 10 +#define DMA_CFG_DESC_TX_0_CMD_DMA_IT_LEN 1 +#define DMA_CFG_DESC_TX_0_CMD_DMA_IT_MSK 0x400 + +#define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_POS 11 +#define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_LEN 2 +#define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_MSK 0x1800 + +#define DMA_CFG_DESC_TX_0_TCP_SEG_EN_POS 13 +#define DMA_CFG_DESC_TX_0_TCP_SEG_EN_LEN 1 +#define DMA_CFG_DESC_TX_0_TCP_SEG_EN_MSK 0x2000 + +#define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_POS 14 +#define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_LEN 1 +#define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_MSK 0x4000 + +#define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS 15 +#define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_LEN 1 +#define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_MSK 0x8000 + +#define DMA_CFG_DESC_TX_0_QID_POS 16 +#define DMA_CFG_DESC_TX_0_QID_LEN 5 +#define DMA_CFG_DESC_TX_0_QID_MSK 0x1F0000 + +#define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS 21 +#define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_LEN 1 +#define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_MSK 0x200000 + +#define DMA_CFG_DESC_TX_0_L4_TYPE_POS 30 +#define DMA_CFG_DESC_TX_0_L4_TYPE_LEN 2 +#define DMA_CFG_DESC_TX_0_L4_TYPE_MSK 0xC0000000 + + +#define TX_DMA_STATUS_DU BIT(0) + +struct vring_tx_dma { + u32 d0; + u32 addr_low; + u16 addr_high; + u8 ip_length; + u8 b11; /* 0..6: mac_length; 7:ip_version */ + u8 error; /* 0..2: err; 3..7: reserved; */ + u8 status; /* 0: used; 1..7; reserved */ + u16 length; +} __packed; + +/* + * Rx descriptor - MAC part + * [dword 0] + * bit 0.. 3 : tid:4 The QoS (b3-0) TID Field + * bit 4.. 6 : connection_id:3 :The Source index that was found during + * Parsing the TA. This field is used to define the source of the packet + * bit 7 : reserved:1 + * bit 8.. 9 : mac_id:2 : The MAC virtual Ring number (always zero) + * bit 10..11 : frame_type:2 : The FC Control (b3-2) - MPDU Type + * (management, data, control and extension) + * bit 12..15 : frame_subtype:4 : The FC Control (b7-4) - Frame Subtype + * bit 16..27 : seq_number:12 The received Sequence number field + * bit 28..31 : extended:4 extended subtype + * [dword 1] + * bit 0.. 3 : reserved + * bit 4.. 5 : key_id:2 + * bit 6 : decrypt_bypass:1 + * bit 7 : security:1 + * bit 8.. 9 : ds_bits:2 + * bit 10 : a_msdu_present:1 from qos header + * bit 11 : a_msdu_type:1 from qos header + * bit 12 : a_mpdu:1 part of AMPDU aggregation + * bit 13 : broadcast:1 + * bit 14 : mutlicast:1 + * bit 15 : reserved:1 + * bit 16..20 : rx_mac_qid:5 The Queue Identifier that the packet + * is received from + * bit 21..24 : mcs:4 + * bit 25..28 : mic_icr:4 + * bit 29..31 : reserved:3 + * [dword 2] + * bit 0.. 2 : time_slot:3 The timeslot that the MPDU is received + * bit 3 : fc_protocol_ver:1 The FC Control (b0) - Protocol Version + * bit 4 : fc_order:1 The FC Control (b15) -Order + * bit 5.. 7 : qos_ack_policy:3 The QoS (b6-5) ack policy Field + * bit 8 : esop:1 The QoS (b4) ESOP field + * bit 9 : qos_rdg_more_ppdu:1 The QoS (b9) RDG field + * bit 10..14 : qos_reserved:5 The QoS (b14-10) Reserved field + * bit 15 : qos_ac_constraint:1 + * bit 16..31 : pn_15_0:16 low 2 bytes of PN + * [dword 3] + * bit 0..31 : pn_47_16:32 high 4 bytes of PN + */ +struct vring_rx_mac { + u32 d0; + u32 d1; + u16 w4; + u16 pn_15_0; + u32 pn_47_16; +} __packed; + +/* + * Rx descriptor - DMA part + * [dword 0] + * bit 0.. 7 : l4_length:8 layer 4 length + * bit 8.. 9 : reserved:2 + * bit 10 : cmd_dma_it:1 + * bit 11..15 : reserved:5 + * bit 16..29 : phy_info_length:14 + * bit 30..31 : l4_type:2 valid if the L4I bit is set in the status field + * [dword 1] + * bit 0..31 : addr_low:32 The payload buffer low address + * [dword 2] + * bit 0..15 : addr_high:16 The payload buffer high address + * bit 16..23 : ip_length:8 + * bit 24..30 : mac_length:7 + * bit 31 : ip_version:1 + * [dword 3] + * [byte 12] error + * [byte 13] status + * bit 0 : du:1 + * bit 1 : eop:1 + * bit 2 : error:1 + * bit 3 : mi:1 + * bit 4 : l3_identified:1 + * bit 5 : l4_identified:1 + * bit 6 : phy_info_included:1 + * bit 7 : reserved:1 + * [word 7] length + * + */ + +#define RX_DMA_D0_CMD_DMA_IT BIT(10) + +#define RX_DMA_STATUS_DU BIT(0) +#define RX_DMA_STATUS_ERROR BIT(2) +#define RX_DMA_STATUS_PHY_INFO BIT(6) + +struct vring_rx_dma { + u32 d0; + u32 addr_low; + u16 addr_high; + u8 ip_length; + u8 b11; + u8 error; + u8 status; + u16 length; +} __packed; + +struct vring_tx_desc { + struct vring_tx_mac mac; + struct vring_tx_dma dma; +} __packed; + +struct vring_rx_desc { + struct vring_rx_mac mac; + struct vring_rx_dma dma; +} __packed; + +union vring_desc { + struct vring_tx_desc tx; + struct vring_rx_desc rx; +} __packed; + +static inline int wil_rxdesc_phy_length(volatile struct vring_rx_desc *d) +{ + return WIL_GET_BITS(d->dma.d0, 16, 29); +} + +static inline int wil_rxdesc_mcs(volatile struct vring_rx_desc *d) +{ + return WIL_GET_BITS(d->mac.d1, 21, 24); +} + +static inline int wil_rxdesc_ds_bits(volatile struct vring_rx_desc *d) +{ + return WIL_GET_BITS(d->mac.d1, 8, 9); +} + +static inline int wil_rxdesc_ftype(volatile struct vring_rx_desc *d) +{ + return WIL_GET_BITS(d->mac.d0, 10, 11); +} + +#endif /* WIL6210_TXRX_H */ diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h new file mode 100644 index 00000000000..9bcfffa4006 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2012 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __WIL6210_H__ +#define __WIL6210_H__ + +#include <linux/netdevice.h> +#include <linux/wireless.h> +#include <net/cfg80211.h> + +#include "dbg_hexdump.h" + +#define WIL_NAME "wil6210" + +/** + * extract bits [@b0:@b1] (inclusive) from the value @x + * it should be @b0 <= @b1, or result is incorrect + */ +static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) +{ + return (x >> b0) & ((1 << (b1 - b0 + 1)) - 1); +} + +#define WIL6210_MEM_SIZE (2*1024*1024UL) + +#define WIL6210_TX_QUEUES (4) + +#define WIL6210_RX_RING_SIZE (128) +#define WIL6210_TX_RING_SIZE (128) +#define WIL6210_MAX_TX_RINGS (24) + +/* Hardware definitions begin */ + +/* + * Mapping + * RGF File | Host addr | FW addr + * | | + * user_rgf | 0x000000 | 0x880000 + * dma_rgf | 0x001000 | 0x881000 + * pcie_rgf | 0x002000 | 0x882000 + * | | + */ + +/* Where various structures placed in host address space */ +#define WIL6210_FW_HOST_OFF (0x880000UL) + +#define HOSTADDR(fwaddr) (fwaddr - WIL6210_FW_HOST_OFF) + +/* + * Interrupt control registers block + * + * each interrupt controlled by the same bit in all registers + */ +struct RGF_ICR { + u32 ICC; /* Cause Control, RW: 0 - W1C, 1 - COR */ + u32 ICR; /* Cause, W1C/COR depending on ICC */ + u32 ICM; /* Cause masked (ICR & ~IMV), W1C/COR depending on ICC */ + u32 ICS; /* Cause Set, WO */ + u32 IMV; /* Mask, RW+S/C */ + u32 IMS; /* Mask Set, write 1 to set */ + u32 IMC; /* Mask Clear, write 1 to clear */ +} __packed; + +/* registers - FW addresses */ +#define RGF_USER_USER_SCRATCH_PAD (0x8802bc) +#define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */ + #define BIT_USER_USER_ICR_SW_INT_2 BIT(18) +#define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14) +#define RGF_USER_MAC_CPU_0 (0x8801fc) +#define RGF_USER_USER_CPU_0 (0x8801e0) +#define RGF_USER_CLKS_CTL_SW_RST_VEC_0 (0x880b04) +#define RGF_USER_CLKS_CTL_SW_RST_VEC_1 (0x880b08) +#define RGF_USER_CLKS_CTL_SW_RST_VEC_2 (0x880b0c) +#define RGF_USER_CLKS_CTL_SW_RST_VEC_3 (0x880b10) + +#define RGF_DMA_PSEUDO_CAUSE (0x881c68) +#define RGF_DMA_PSEUDO_CAUSE_MASK_SW (0x881c6c) +#define RGF_DMA_PSEUDO_CAUSE_MASK_FW (0x881c70) + #define BIT_DMA_PSEUDO_CAUSE_RX BIT(0) + #define BIT_DMA_PSEUDO_CAUSE_TX BIT(1) + #define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2) + +#define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ + #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) + #define BIT_DMA_EP_TX_ICR_TX_DONE_N(n) BIT(n+1) /* n = [0..23] */ +#define RGF_DMA_EP_RX_ICR (0x881bd0) /* struct RGF_ICR */ + #define BIT_DMA_EP_RX_ICR_RX_DONE BIT(0) +#define RGF_DMA_EP_MISC_ICR (0x881bec) /* struct RGF_ICR */ + #define BIT_DMA_EP_MISC_ICR_RX_HTRSH BIT(0) + #define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1) + #define BIT_DMA_EP_MISC_ICR_FW_INT0 BIT(28) + #define BIT_DMA_EP_MISC_ICR_FW_INT1 BIT(29) + +/* Interrupt moderation control */ +#define RGF_DMA_ITR_CNT_TRSH (0x881c5c) +#define RGF_DMA_ITR_CNT_DATA (0x881c60) +#define RGF_DMA_ITR_CNT_CRL (0x881C64) + #define BIT_DMA_ITR_CNT_CRL_EN BIT(0) + #define BIT_DMA_ITR_CNT_CRL_EXT_TICK BIT(1) + #define BIT_DMA_ITR_CNT_CRL_FOREVER BIT(2) + #define BIT_DMA_ITR_CNT_CRL_CLR BIT(3) + #define BIT_DMA_ITR_CNT_CRL_REACH_TRSH BIT(4) + +/* popular locations */ +#define HOST_MBOX HOSTADDR(RGF_USER_USER_SCRATCH_PAD) +#define HOST_SW_INT (HOSTADDR(RGF_USER_USER_ICR) + \ + offsetof(struct RGF_ICR, ICS)) +#define SW_INT_MBOX BIT_USER_USER_ICR_SW_INT_2 + +/* ISR register bits */ +#define ISR_MISC_FW_READY BIT_DMA_EP_MISC_ICR_FW_INT0 +#define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT1 + +/* Hardware definitions end */ + +struct wil6210_mbox_ring { + u32 base; + u16 entry_size; /* max. size of mbox entry, incl. all headers */ + u16 size; + u32 tail; + u32 head; +} __packed; + +struct wil6210_mbox_ring_desc { + __le32 sync; + __le32 addr; +} __packed; + +/* at HOST_OFF_WIL6210_MBOX_CTL */ +struct wil6210_mbox_ctl { + struct wil6210_mbox_ring tx; + struct wil6210_mbox_ring rx; +} __packed; + +struct wil6210_mbox_hdr { + __le16 seq; + __le16 len; /* payload, bytes after this header */ + __le16 type; + u8 flags; + u8 reserved; +} __packed; + +#define WIL_MBOX_HDR_TYPE_WMI (0) + +/* max. value for wil6210_mbox_hdr.len */ +#define MAX_MBOXITEM_SIZE (240) + +struct wil6210_mbox_hdr_wmi { + u8 reserved0[2]; + __le16 id; + __le16 info1; /* bits [0..3] - device_id, rest - unused */ + u8 reserved1[2]; +} __packed; + +struct pending_wmi_event { + struct list_head list; + struct { + struct wil6210_mbox_hdr hdr; + struct wil6210_mbox_hdr_wmi wmi; + u8 data[0]; + } __packed event; +}; + +union vring_desc; + +struct vring { + dma_addr_t pa; + volatile union vring_desc *va; /* vring_desc[size], WriteBack by DMA */ + u16 size; /* number of vring_desc elements */ + u32 swtail; + u32 swhead; + u32 hwtail; /* write here to inform hw */ + void **ctx; /* void *ctx[size] - software context */ +}; + +enum { /* for wil6210_priv.status */ + wil_status_fwready = 0, + wil_status_fwconnected, + wil_status_dontscan, + wil_status_irqen, /* FIXME: interrupts enabled - for debug */ +}; + +struct pci_dev; + +struct wil6210_stats { + u64 tsf; + u32 snr; + u16 last_mcs_rx; + u16 bf_mcs; /* last BF, used for Tx */ + u16 my_rx_sector; + u16 my_tx_sector; + u16 peer_rx_sector; + u16 peer_tx_sector; +}; + +struct wil6210_priv { + struct pci_dev *pdev; + int n_msi; + struct wireless_dev *wdev; + void __iomem *csr; + ulong status; + /* profile */ + u32 monitor_flags; + u32 secure_pcp; /* create secure PCP? */ + int sinfo_gen; + /* cached ISR registers */ + u32 isr_misc; + /* mailbox related */ + struct mutex wmi_mutex; + struct wil6210_mbox_ctl mbox_ctl; + struct completion wmi_ready; + u16 wmi_seq; + u16 reply_id; /**< wait for this WMI event */ + void *reply_buf; + u16 reply_size; + struct workqueue_struct *wmi_wq; /* for deferred calls */ + struct work_struct wmi_event_worker; + struct workqueue_struct *wmi_wq_conn; /* for connect worker */ + struct work_struct wmi_connect_worker; + struct work_struct disconnect_worker; + struct timer_list connect_timer; + int pending_connect_cid; + struct list_head pending_wmi_ev; + /* + * protect pending_wmi_ev + * - fill in IRQ from wil6210_irq_misc, + * - consumed in thread by wmi_event_worker + */ + spinlock_t wmi_ev_lock; + /* DMA related */ + struct vring vring_rx; + struct vring vring_tx[WIL6210_MAX_TX_RINGS]; + u8 dst_addr[WIL6210_MAX_TX_RINGS][ETH_ALEN]; + /* scan */ + struct cfg80211_scan_request *scan_request; + + struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */ + /* statistics */ + struct wil6210_stats stats; + /* debugfs */ + struct dentry *debug; + struct debugfs_blob_wrapper fw_code_blob; + struct debugfs_blob_wrapper fw_data_blob; + struct debugfs_blob_wrapper fw_peri_blob; + struct debugfs_blob_wrapper uc_code_blob; + struct debugfs_blob_wrapper uc_data_blob; + struct debugfs_blob_wrapper rgf_blob; +}; + +#define wil_to_wiphy(i) (i->wdev->wiphy) +#define wil_to_dev(i) (wiphy_dev(wil_to_wiphy(i))) +#define wiphy_to_wil(w) (struct wil6210_priv *)(wiphy_priv(w)) +#define wil_to_wdev(i) (i->wdev) +#define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w)) +#define wil_to_ndev(i) (wil_to_wdev(i)->netdev) +#define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr)) + +#define wil_dbg(wil, fmt, arg...) netdev_dbg(wil_to_ndev(wil), fmt, ##arg) +#define wil_info(wil, fmt, arg...) netdev_info(wil_to_ndev(wil), fmt, ##arg) +#define wil_err(wil, fmt, arg...) netdev_err(wil_to_ndev(wil), fmt, ##arg) + +#define wil_dbg_IRQ(wil, fmt, arg...) wil_dbg(wil, "DBG[ IRQ]" fmt, ##arg) +#define wil_dbg_TXRX(wil, fmt, arg...) wil_dbg(wil, "DBG[TXRX]" fmt, ##arg) +#define wil_dbg_WMI(wil, fmt, arg...) wil_dbg(wil, "DBG[ WMI]" fmt, ##arg) + +#define wil_hex_dump_TXRX(prefix_str, prefix_type, rowsize, \ + groupsize, buf, len, ascii) \ + wil_print_hex_dump_debug("DBG[TXRX]" prefix_str,\ + prefix_type, rowsize, \ + groupsize, buf, len, ascii) + +#define wil_hex_dump_WMI(prefix_str, prefix_type, rowsize, \ + groupsize, buf, len, ascii) \ + wil_print_hex_dump_debug("DBG[ WMI]" prefix_str,\ + prefix_type, rowsize, \ + groupsize, buf, len, ascii) + +void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, + size_t count); +void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, + size_t count); + +void *wil_if_alloc(struct device *dev, void __iomem *csr); +void wil_if_free(struct wil6210_priv *wil); +int wil_if_add(struct wil6210_priv *wil); +void wil_if_remove(struct wil6210_priv *wil); +int wil_priv_init(struct wil6210_priv *wil); +void wil_priv_deinit(struct wil6210_priv *wil); +int wil_reset(struct wil6210_priv *wil); +void wil_link_on(struct wil6210_priv *wil); +void wil_link_off(struct wil6210_priv *wil); +int wil_up(struct wil6210_priv *wil); +int wil_down(struct wil6210_priv *wil); +void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r); + +void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr); +void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); +int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, + struct wil6210_mbox_hdr *hdr); +int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len); +void wmi_recv_cmd(struct wil6210_priv *wil); +int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, + u16 reply_id, void *reply, u8 reply_size, int to_msec); +void wmi_connect_worker(struct work_struct *work); +void wmi_event_worker(struct work_struct *work); +void wmi_event_flush(struct wil6210_priv *wil); +int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid); +int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid); +int wmi_set_channel(struct wil6210_priv *wil, int channel); +int wmi_get_channel(struct wil6210_priv *wil, int *channel); +int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb); +int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, + const void *mac_addr); +int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, + const void *mac_addr, int key_len, const void *key); +int wmi_echo(struct wil6210_priv *wil); +int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); + +int wil6210_init_irq(struct wil6210_priv *wil, int irq); +void wil6210_fini_irq(struct wil6210_priv *wil, int irq); +void wil6210_disable_irq(struct wil6210_priv *wil); +void wil6210_enable_irq(struct wil6210_priv *wil); + +int wil6210_debugfs_init(struct wil6210_priv *wil); +void wil6210_debugfs_remove(struct wil6210_priv *wil); + +struct wireless_dev *wil_cfg80211_init(struct device *dev); +void wil_wdev_free(struct wil6210_priv *wil); + +int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); +int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype); +void wil6210_disconnect(struct wil6210_priv *wil, void *bssid); + +int wil_rx_init(struct wil6210_priv *wil); +void wil_rx_fini(struct wil6210_priv *wil); + +/* TX API */ +int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, + int cid, int tid); +void wil_vring_fini_tx(struct wil6210_priv *wil, int id); + +netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); +void wil_tx_complete(struct wil6210_priv *wil, int ringid); + +/* RX API */ +void wil_rx_handle(struct wil6210_priv *wil); + +int wil_iftype_nl2wmi(enum nl80211_iftype type); + +#endif /* __WIL6210_H__ */ diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c new file mode 100644 index 00000000000..12915f6e761 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -0,0 +1,975 @@ +/* + * Copyright (c) 2012 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <linux/pci.h> +#include <linux/io.h> +#include <linux/list.h> +#include <linux/etherdevice.h> + +#include "wil6210.h" +#include "wmi.h" + +/** + * WMI event receiving - theory of operations + * + * When firmware about to report WMI event, it fills memory area + * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for + * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler. + * + * @wmi_recv_cmd reads event, allocates memory chunk and attaches it to the + * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up + * and handles events within the @wmi_event_worker. Every event get detached + * from list, processed and deleted. + * + * Purpose for this mechanism is to release IRQ thread; otherwise, + * if WMI event handling involves another WMI command flow, this 2-nd flow + * won't be completed because of blocked IRQ thread. + */ + +/** + * Addressing - theory of operations + * + * There are several buses present on the WIL6210 card. + * Same memory areas are visible at different address on + * the different busses. There are 3 main bus masters: + * - MAC CPU (ucode) + * - User CPU (firmware) + * - AHB (host) + * + * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing + * AHB addresses starting from 0x880000 + * + * Internally, firmware uses addresses that allows faster access but + * are invisible from the host. To read from these addresses, alternative + * AHB address must be used. + * + * Memory mapping + * Linker address PCI/Host address + * 0x880000 .. 0xa80000 2Mb BAR0 + * 0x800000 .. 0x807000 0x900000 .. 0x907000 28k DCCM + * 0x840000 .. 0x857000 0x908000 .. 0x91f000 92k PERIPH + */ + +/** + * @fw_mapping provides memory remapping table + */ +static const struct { + u32 from; /* linker address - from, inclusive */ + u32 to; /* linker address - to, exclusive */ + u32 host; /* PCI/Host address - BAR0 + 0x880000 */ +} fw_mapping[] = { + {0x000000, 0x040000, 0x8c0000}, /* FW code RAM 256k */ + {0x800000, 0x808000, 0x900000}, /* FW data RAM 32k */ + {0x840000, 0x860000, 0x908000}, /* peripheral data RAM 128k/96k used */ + {0x880000, 0x88a000, 0x880000}, /* various RGF */ + {0x8c0000, 0x932000, 0x8c0000}, /* trivial mapping for upper area */ + /* + * 920000..930000 ucode code RAM + * 930000..932000 ucode data RAM + */ +}; + +/** + * return AHB address for given firmware/ucode internal (linker) address + * @x - internal address + * If address have no valid AHB mapping, return 0 + */ +static u32 wmi_addr_remap(u32 x) +{ + uint i; + + for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { + if ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to)) + return x + fw_mapping[i].host - fw_mapping[i].from; + } + + return 0; +} + +/** + * Check address validity for WMI buffer; remap if needed + * @ptr - internal (linker) fw/ucode address + * + * Valid buffer should be DWORD aligned + * + * return address for accessing buffer from the host; + * if buffer is not valid, return NULL. + */ +void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) +{ + u32 off; + u32 ptr = le32_to_cpu(ptr_); + + if (ptr % 4) + return NULL; + + ptr = wmi_addr_remap(ptr); + if (ptr < WIL6210_FW_HOST_OFF) + return NULL; + + off = HOSTADDR(ptr); + if (off > WIL6210_MEM_SIZE - 4) + return NULL; + + return wil->csr + off; +} + +/** + * Check address validity + */ +void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr) +{ + u32 off; + + if (ptr % 4) + return NULL; + + if (ptr < WIL6210_FW_HOST_OFF) + return NULL; + + off = HOSTADDR(ptr); + if (off > WIL6210_MEM_SIZE - 4) + return NULL; + + return wil->csr + off; +} + +int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, + struct wil6210_mbox_hdr *hdr) +{ + void __iomem *src = wmi_buffer(wil, ptr); + if (!src) + return -EINVAL; + + wil_memcpy_fromio_32(hdr, src, sizeof(*hdr)); + + return 0; +} + +static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) +{ + struct { + struct wil6210_mbox_hdr hdr; + struct wil6210_mbox_hdr_wmi wmi; + } __packed cmd = { + .hdr = { + .type = WIL_MBOX_HDR_TYPE_WMI, + .flags = 0, + .len = cpu_to_le16(sizeof(cmd.wmi) + len), + }, + .wmi = { + .id = cpu_to_le16(cmdid), + .info1 = 0, + }, + }; + struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx; + struct wil6210_mbox_ring_desc d_head; + u32 next_head; + void __iomem *dst; + void __iomem *head = wmi_addr(wil, r->head); + uint retry; + + if (sizeof(cmd) + len > r->entry_size) { + wil_err(wil, "WMI size too large: %d bytes, max is %d\n", + (int)(sizeof(cmd) + len), r->entry_size); + return -ERANGE; + + } + + might_sleep(); + + if (!test_bit(wil_status_fwready, &wil->status)) { + wil_err(wil, "FW not ready\n"); + return -EAGAIN; + } + + if (!head) { + wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head); + return -EINVAL; + } + /* read Tx head till it is not busy */ + for (retry = 5; retry > 0; retry--) { + wil_memcpy_fromio_32(&d_head, head, sizeof(d_head)); + if (d_head.sync == 0) + break; + msleep(20); + } + if (d_head.sync != 0) { + wil_err(wil, "WMI head busy\n"); + return -EBUSY; + } + /* next head */ + next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size); + wil_dbg_WMI(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head); + /* wait till FW finish with previous command */ + for (retry = 5; retry > 0; retry--) { + r->tail = ioread32(wil->csr + HOST_MBOX + + offsetof(struct wil6210_mbox_ctl, tx.tail)); + if (next_head != r->tail) + break; + msleep(20); + } + if (next_head == r->tail) { + wil_err(wil, "WMI ring full\n"); + return -EBUSY; + } + dst = wmi_buffer(wil, d_head.addr); + if (!dst) { + wil_err(wil, "invalid WMI buffer: 0x%08x\n", + le32_to_cpu(d_head.addr)); + return -EINVAL; + } + cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq); + /* set command */ + wil_dbg_WMI(wil, "WMI command 0x%04x [%d]\n", cmdid, len); + wil_hex_dump_WMI("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd, + sizeof(cmd), true); + wil_hex_dump_WMI("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf, + len, true); + wil_memcpy_toio_32(dst, &cmd, sizeof(cmd)); + wil_memcpy_toio_32(dst + sizeof(cmd), buf, len); + /* mark entry as full */ + iowrite32(1, wil->csr + HOSTADDR(r->head) + + offsetof(struct wil6210_mbox_ring_desc, sync)); + /* advance next ptr */ + iowrite32(r->head = next_head, wil->csr + HOST_MBOX + + offsetof(struct wil6210_mbox_ctl, tx.head)); + + /* interrupt to FW */ + iowrite32(SW_INT_MBOX, wil->csr + HOST_SW_INT); + + return 0; +} + +int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) +{ + int rc; + + mutex_lock(&wil->wmi_mutex); + rc = __wmi_send(wil, cmdid, buf, len); + mutex_unlock(&wil->wmi_mutex); + + return rc; +} + +/*=== Event handlers ===*/ +static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) +{ + struct net_device *ndev = wil_to_ndev(wil); + struct wireless_dev *wdev = wil->wdev; + struct wmi_ready_event *evt = d; + u32 ver = le32_to_cpu(evt->sw_version); + + wil_dbg_WMI(wil, "FW ver. %d; MAC %pM\n", ver, evt->mac); + + if (!is_valid_ether_addr(ndev->dev_addr)) { + memcpy(ndev->dev_addr, evt->mac, ETH_ALEN); + memcpy(ndev->perm_addr, evt->mac, ETH_ALEN); + } + snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version), + "%d", ver); +} + +static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d, + int len) +{ + wil_dbg_WMI(wil, "WMI: FW ready\n"); + + set_bit(wil_status_fwready, &wil->status); + /* reuse wmi_ready for the firmware ready indication */ + complete(&wil->wmi_ready); +} + +static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) +{ + struct wmi_rx_mgmt_packet_event *data = d; + struct wiphy *wiphy = wil_to_wiphy(wil); + struct ieee80211_mgmt *rx_mgmt_frame = + (struct ieee80211_mgmt *)data->payload; + int ch_no = data->info.channel+1; + u32 freq = ieee80211_channel_to_frequency(ch_no, + IEEE80211_BAND_60GHZ); + struct ieee80211_channel *channel = ieee80211_get_channel(wiphy, freq); + /* TODO convert LE to CPU */ + s32 signal = 0; /* TODO */ + __le16 fc = rx_mgmt_frame->frame_control; + u32 d_len = le32_to_cpu(data->info.len); + u16 d_status = le16_to_cpu(data->info.status); + + wil_dbg_WMI(wil, "MGMT: channel %d MCS %d SNR %d\n", + data->info.channel, data->info.mcs, data->info.snr); + wil_dbg_WMI(wil, "status 0x%04x len %d stype %04x\n", d_status, d_len, + le16_to_cpu(data->info.stype)); + wil_dbg_WMI(wil, "qid %d mid %d cid %d\n", + data->info.qid, data->info.mid, data->info.cid); + + if (!channel) { + wil_err(wil, "Frame on unsupported channel\n"); + return; + } + + if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) { + struct cfg80211_bss *bss; + u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp); + u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info); + u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int); + const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable; + size_t ie_len = d_len - offsetof(struct ieee80211_mgmt, + u.beacon.variable); + wil_dbg_WMI(wil, "Capability info : 0x%04x\n", cap); + + bss = cfg80211_inform_bss(wiphy, channel, rx_mgmt_frame->bssid, + tsf, cap, bi, ie_buf, ie_len, + signal, GFP_KERNEL); + if (bss) { + wil_dbg_WMI(wil, "Added BSS %pM\n", + rx_mgmt_frame->bssid); + cfg80211_put_bss(bss); + } else { + wil_err(wil, "cfg80211_inform_bss() failed\n"); + } + } +} + +static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, + void *d, int len) +{ + if (wil->scan_request) { + struct wmi_scan_complete_event *data = d; + bool aborted = (data->status != 0); + + wil_dbg_WMI(wil, "SCAN_COMPLETE(0x%08x)\n", data->status); + cfg80211_scan_done(wil->scan_request, aborted); + wil->scan_request = NULL; + } else { + wil_err(wil, "SCAN_COMPLETE while not scanning\n"); + } +} + +static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) +{ + struct net_device *ndev = wil_to_ndev(wil); + struct wireless_dev *wdev = wil->wdev; + struct wmi_connect_event *evt = d; + int ch; /* channel number */ + struct station_info sinfo; + u8 *assoc_req_ie, *assoc_resp_ie; + size_t assoc_req_ielen, assoc_resp_ielen; + /* capinfo(u16) + listen_interval(u16) + IEs */ + const size_t assoc_req_ie_offset = sizeof(u16) * 2; + /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */ + const size_t assoc_resp_ie_offset = sizeof(u16) * 3; + + if (len < sizeof(*evt)) { + wil_err(wil, "Connect event too short : %d bytes\n", len); + return; + } + if (len != sizeof(*evt) + evt->beacon_ie_len + evt->assoc_req_len + + evt->assoc_resp_len) { + wil_err(wil, + "Connect event corrupted : %d != %d + %d + %d + %d\n", + len, (int)sizeof(*evt), evt->beacon_ie_len, + evt->assoc_req_len, evt->assoc_resp_len); + return; + } + ch = evt->channel + 1; + wil_dbg_WMI(wil, "Connect %pM channel [%d] cid %d\n", + evt->bssid, ch, evt->cid); + wil_hex_dump_WMI("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1, + evt->assoc_info, len - sizeof(*evt), true); + + /* figure out IE's */ + assoc_req_ie = &evt->assoc_info[evt->beacon_ie_len + + assoc_req_ie_offset]; + assoc_req_ielen = evt->assoc_req_len - assoc_req_ie_offset; + if (evt->assoc_req_len <= assoc_req_ie_offset) { + assoc_req_ie = NULL; + assoc_req_ielen = 0; + } + + assoc_resp_ie = &evt->assoc_info[evt->beacon_ie_len + + evt->assoc_req_len + + assoc_resp_ie_offset]; + assoc_resp_ielen = evt->assoc_resp_len - assoc_resp_ie_offset; + if (evt->assoc_resp_len <= assoc_resp_ie_offset) { + assoc_resp_ie = NULL; + assoc_resp_ielen = 0; + } + + if ((wdev->iftype == NL80211_IFTYPE_STATION) || + (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { + if (wdev->sme_state != CFG80211_SME_CONNECTING) { + wil_err(wil, "Not in connecting state\n"); + return; + } + del_timer_sync(&wil->connect_timer); + cfg80211_connect_result(ndev, evt->bssid, + assoc_req_ie, assoc_req_ielen, + assoc_resp_ie, assoc_resp_ielen, + WLAN_STATUS_SUCCESS, GFP_KERNEL); + + } else if ((wdev->iftype == NL80211_IFTYPE_AP) || + (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { + memset(&sinfo, 0, sizeof(sinfo)); + + sinfo.generation = wil->sinfo_gen++; + + if (assoc_req_ie) { + sinfo.assoc_req_ies = assoc_req_ie; + sinfo.assoc_req_ies_len = assoc_req_ielen; + sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; + } + + cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); + } + set_bit(wil_status_fwconnected, &wil->status); + + /* FIXME FW can transmit only ucast frames to peer */ + /* FIXME real ring_id instead of hard coded 0 */ + memcpy(wil->dst_addr[0], evt->bssid, ETH_ALEN); + + wil->pending_connect_cid = evt->cid; + queue_work(wil->wmi_wq_conn, &wil->wmi_connect_worker); +} + +static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, + void *d, int len) +{ + struct wmi_disconnect_event *evt = d; + + wil_dbg_WMI(wil, "Disconnect %pM reason %d proto %d wmi\n", + evt->bssid, + evt->protocol_reason_status, evt->disconnect_reason); + + wil->sinfo_gen++; + + wil6210_disconnect(wil, evt->bssid); + clear_bit(wil_status_dontscan, &wil->status); +} + +static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len) +{ + struct wmi_notify_req_done_event *evt = d; + + if (len < sizeof(*evt)) { + wil_err(wil, "Short NOTIFY event\n"); + return; + } + + wil->stats.tsf = le64_to_cpu(evt->tsf); + wil->stats.snr = le32_to_cpu(evt->snr_val); + wil->stats.bf_mcs = le16_to_cpu(evt->bf_mcs); + wil->stats.my_rx_sector = le16_to_cpu(evt->my_rx_sector); + wil->stats.my_tx_sector = le16_to_cpu(evt->my_tx_sector); + wil->stats.peer_rx_sector = le16_to_cpu(evt->other_rx_sector); + wil->stats.peer_tx_sector = le16_to_cpu(evt->other_tx_sector); + wil_dbg_WMI(wil, "Link status, MCS %d TSF 0x%016llx\n" + "BF status 0x%08x SNR 0x%08x\n" + "Tx Tpt %d goodput %d Rx goodput %d\n" + "Sectors(rx:tx) my %d:%d peer %d:%d\n", + wil->stats.bf_mcs, wil->stats.tsf, evt->status, + wil->stats.snr, le32_to_cpu(evt->tx_tpt), + le32_to_cpu(evt->tx_goodput), le32_to_cpu(evt->rx_goodput), + wil->stats.my_rx_sector, wil->stats.my_tx_sector, + wil->stats.peer_rx_sector, wil->stats.peer_tx_sector); +} + +/* + * Firmware reports EAPOL frame using WME event. + * Reconstruct Ethernet frame and deliver it via normal Rx + */ +static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, + void *d, int len) +{ + struct net_device *ndev = wil_to_ndev(wil); + struct wmi_eapol_rx_event *evt = d; + u16 eapol_len = le16_to_cpu(evt->eapol_len); + int sz = eapol_len + ETH_HLEN; + struct sk_buff *skb; + struct ethhdr *eth; + + wil_dbg_WMI(wil, "EAPOL len %d from %pM\n", eapol_len, + evt->src_mac); + + if (eapol_len > 196) { /* TODO: revisit size limit */ + wil_err(wil, "EAPOL too large\n"); + return; + } + + skb = alloc_skb(sz, GFP_KERNEL); + if (!skb) { + wil_err(wil, "Failed to allocate skb\n"); + return; + } + eth = (struct ethhdr *)skb_put(skb, ETH_HLEN); + memcpy(eth->h_dest, ndev->dev_addr, ETH_ALEN); + memcpy(eth->h_source, evt->src_mac, ETH_ALEN); + eth->h_proto = cpu_to_be16(ETH_P_PAE); + memcpy(skb_put(skb, eapol_len), evt->eapol, eapol_len); + skb->protocol = eth_type_trans(skb, ndev); + if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) { + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += skb->len; + } else { + ndev->stats.rx_dropped++; + } +} + +static const struct { + int eventid; + void (*handler)(struct wil6210_priv *wil, int eventid, + void *data, int data_len); +} wmi_evt_handlers[] = { + {WMI_READY_EVENTID, wmi_evt_ready}, + {WMI_FW_READY_EVENTID, wmi_evt_fw_ready}, + {WMI_RX_MGMT_PACKET_EVENTID, wmi_evt_rx_mgmt}, + {WMI_SCAN_COMPLETE_EVENTID, wmi_evt_scan_complete}, + {WMI_CONNECT_EVENTID, wmi_evt_connect}, + {WMI_DISCONNECT_EVENTID, wmi_evt_disconnect}, + {WMI_NOTIFY_REQ_DONE_EVENTID, wmi_evt_notify}, + {WMI_EAPOL_RX_EVENTID, wmi_evt_eapol_rx}, +}; + +/* + * Run in IRQ context + * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev + * that will be eventually handled by the @wmi_event_worker in the thread + * context of thread "wil6210_wmi" + */ +void wmi_recv_cmd(struct wil6210_priv *wil) +{ + struct wil6210_mbox_ring_desc d_tail; + struct wil6210_mbox_hdr hdr; + struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx; + struct pending_wmi_event *evt; + u8 *cmd; + void __iomem *src; + ulong flags; + + for (;;) { + u16 len; + + r->head = ioread32(wil->csr + HOST_MBOX + + offsetof(struct wil6210_mbox_ctl, rx.head)); + if (r->tail == r->head) + return; + + /* read cmd from tail */ + wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail), + sizeof(struct wil6210_mbox_ring_desc)); + if (d_tail.sync == 0) { + wil_err(wil, "Mbox evt not owned by FW?\n"); + return; + } + + if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) { + wil_err(wil, "Mbox evt at 0x%08x?\n", + le32_to_cpu(d_tail.addr)); + return; + } + + len = le16_to_cpu(hdr.len); + src = wmi_buffer(wil, d_tail.addr) + + sizeof(struct wil6210_mbox_hdr); + evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event, + event.wmi) + len, 4), + GFP_KERNEL); + if (!evt) { + wil_err(wil, "kmalloc for WMI event (%d) failed\n", + len); + return; + } + evt->event.hdr = hdr; + cmd = (void *)&evt->event.wmi; + wil_memcpy_fromio_32(cmd, src, len); + /* mark entry as empty */ + iowrite32(0, wil->csr + HOSTADDR(r->tail) + + offsetof(struct wil6210_mbox_ring_desc, sync)); + /* indicate */ + wil_dbg_WMI(wil, "Mbox evt %04x %04x %04x %02x\n", + le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type), + hdr.flags); + if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) && + (len >= sizeof(struct wil6210_mbox_hdr_wmi))) { + wil_dbg_WMI(wil, "WMI event 0x%04x\n", + evt->event.wmi.id); + } + wil_hex_dump_WMI("evt ", DUMP_PREFIX_OFFSET, 16, 1, + &evt->event.hdr, sizeof(hdr) + len, true); + + /* advance tail */ + r->tail = r->base + ((r->tail - r->base + + sizeof(struct wil6210_mbox_ring_desc)) % r->size); + iowrite32(r->tail, wil->csr + HOST_MBOX + + offsetof(struct wil6210_mbox_ctl, rx.tail)); + + /* add to the pending list */ + spin_lock_irqsave(&wil->wmi_ev_lock, flags); + list_add_tail(&evt->list, &wil->pending_wmi_ev); + spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); + { + int q = queue_work(wil->wmi_wq, + &wil->wmi_event_worker); + wil_dbg_WMI(wil, "queue_work -> %d\n", q); + } + } +} + +int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, + u16 reply_id, void *reply, u8 reply_size, int to_msec) +{ + int rc; + int remain; + + mutex_lock(&wil->wmi_mutex); + + rc = __wmi_send(wil, cmdid, buf, len); + if (rc) + goto out; + + wil->reply_id = reply_id; + wil->reply_buf = reply; + wil->reply_size = reply_size; + remain = wait_for_completion_timeout(&wil->wmi_ready, + msecs_to_jiffies(to_msec)); + if (0 == remain) { + wil_err(wil, "wmi_call(0x%04x->0x%04x) timeout %d msec\n", + cmdid, reply_id, to_msec); + rc = -ETIME; + } else { + wil_dbg_WMI(wil, + "wmi_call(0x%04x->0x%04x) completed in %d msec\n", + cmdid, reply_id, + to_msec - jiffies_to_msecs(remain)); + } + wil->reply_id = 0; + wil->reply_buf = NULL; + wil->reply_size = 0; + out: + mutex_unlock(&wil->wmi_mutex); + + return rc; +} + +int wmi_echo(struct wil6210_priv *wil) +{ + struct wmi_echo_cmd cmd = { + .value = cpu_to_le32(0x12345678), + }; + + return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd), + WMI_ECHO_RSP_EVENTID, NULL, 0, 20); +} + +int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) +{ + struct wmi_set_mac_address_cmd cmd; + + memcpy(cmd.mac, addr, ETH_ALEN); + + wil_dbg_WMI(wil, "Set MAC %pM\n", addr); + + return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd)); +} + +int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype) +{ + struct wmi_bcon_ctrl_cmd cmd = { + .bcon_interval = cpu_to_le16(bi), + .network_type = wmi_nettype, + .disable_sec_offload = 1, + }; + + if (!wil->secure_pcp) + cmd.disable_sec = 1; + + return wmi_send(wil, WMI_BCON_CTRL_CMDID, &cmd, sizeof(cmd)); +} + +int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid) +{ + struct wmi_set_ssid_cmd cmd = { + .ssid_len = cpu_to_le32(ssid_len), + }; + + if (ssid_len > sizeof(cmd.ssid)) + return -EINVAL; + + memcpy(cmd.ssid, ssid, ssid_len); + + return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd)); +} + +int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid) +{ + int rc; + struct { + struct wil6210_mbox_hdr_wmi wmi; + struct wmi_set_ssid_cmd cmd; + } __packed reply; + int len; /* reply.cmd.ssid_len in CPU order */ + + rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID, + &reply, sizeof(reply), 20); + if (rc) + return rc; + + len = le32_to_cpu(reply.cmd.ssid_len); + if (len > sizeof(reply.cmd.ssid)) + return -EINVAL; + + *ssid_len = len; + memcpy(ssid, reply.cmd.ssid, len); + + return 0; +} + +int wmi_set_channel(struct wil6210_priv *wil, int channel) +{ + struct wmi_set_pcp_channel_cmd cmd = { + .channel = channel - 1, + }; + + return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd)); +} + +int wmi_get_channel(struct wil6210_priv *wil, int *channel) +{ + int rc; + struct { + struct wil6210_mbox_hdr_wmi wmi; + struct wmi_set_pcp_channel_cmd cmd; + } __packed reply; + + rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0, + WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20); + if (rc) + return rc; + + if (reply.cmd.channel > 3) + return -EINVAL; + + *channel = reply.cmd.channel + 1; + + return 0; +} + +int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb) +{ + struct wmi_eapol_tx_cmd *cmd; + struct ethhdr *eth; + u16 eapol_len = skb->len - ETH_HLEN; + void *eapol = skb->data + ETH_HLEN; + uint i; + int rc; + + skb_set_mac_header(skb, 0); + eth = eth_hdr(skb); + wil_dbg_WMI(wil, "EAPOL %d bytes to %pM\n", eapol_len, eth->h_dest); + for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { + if (memcmp(wil->dst_addr[i], eth->h_dest, ETH_ALEN) == 0) + goto found_dest; + } + + return -EINVAL; + + found_dest: + /* find out eapol data & len */ + cmd = kzalloc(sizeof(*cmd) + eapol_len, GFP_KERNEL); + if (!cmd) + return -EINVAL; + + memcpy(cmd->dst_mac, eth->h_dest, ETH_ALEN); + cmd->eapol_len = cpu_to_le16(eapol_len); + memcpy(cmd->eapol, eapol, eapol_len); + rc = wmi_send(wil, WMI_EAPOL_TX_CMDID, cmd, sizeof(*cmd) + eapol_len); + kfree(cmd); + + return rc; +} + +int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, + const void *mac_addr) +{ + struct wmi_delete_cipher_key_cmd cmd = { + .key_index = key_index, + }; + + if (mac_addr) + memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); + + return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); +} + +int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, + const void *mac_addr, int key_len, const void *key) +{ + struct wmi_add_cipher_key_cmd cmd = { + .key_index = key_index, + .key_usage = WMI_KEY_USE_PAIRWISE, + .key_len = key_len, + }; + + if (!key || (key_len > sizeof(cmd.key))) + return -EINVAL; + + memcpy(cmd.key, key, key_len); + if (mac_addr) + memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); + + return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); +} + +int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) +{ + int rc; + u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len; + struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL); + if (!cmd) { + wil_err(wil, "kmalloc(%d) failed\n", len); + return -ENOMEM; + } + + cmd->mgmt_frm_type = type; + /* BUG: FW API define ieLen as u8. Will fix FW */ + cmd->ie_len = cpu_to_le16(ie_len); + memcpy(cmd->ie_info, ie, ie_len); + rc = wmi_send(wil, WMI_SET_APPIE_CMDID, &cmd, len); + kfree(cmd); + + return rc; +} + +void wmi_event_flush(struct wil6210_priv *wil) +{ + struct pending_wmi_event *evt, *t; + + wil_dbg_WMI(wil, "%s()\n", __func__); + + list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) { + list_del(&evt->list); + kfree(evt); + } +} + +static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id, + void *d, int len) +{ + uint i; + + for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) { + if (wmi_evt_handlers[i].eventid == id) { + wmi_evt_handlers[i].handler(wil, id, d, len); + return true; + } + } + + return false; +} + +static void wmi_event_handle(struct wil6210_priv *wil, + struct wil6210_mbox_hdr *hdr) +{ + u16 len = le16_to_cpu(hdr->len); + + if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) && + (len >= sizeof(struct wil6210_mbox_hdr_wmi))) { + struct wil6210_mbox_hdr_wmi *wmi = (void *)(&hdr[1]); + void *evt_data = (void *)(&wmi[1]); + u16 id = le16_to_cpu(wmi->id); + /* check if someone waits for this event */ + if (wil->reply_id && wil->reply_id == id) { + if (wil->reply_buf) { + memcpy(wil->reply_buf, wmi, + min(len, wil->reply_size)); + } else { + wmi_evt_call_handler(wil, id, evt_data, + len - sizeof(*wmi)); + } + wil_dbg_WMI(wil, "Complete WMI 0x%04x\n", id); + complete(&wil->wmi_ready); + return; + } + /* unsolicited event */ + /* search for handler */ + if (!wmi_evt_call_handler(wil, id, evt_data, + len - sizeof(*wmi))) { + wil_err(wil, "Unhandled event 0x%04x\n", id); + } + } else { + wil_err(wil, "Unknown event type\n"); + print_hex_dump(KERN_ERR, "evt?? ", DUMP_PREFIX_OFFSET, 16, 1, + hdr, sizeof(*hdr) + len, true); + } +} + +/* + * Retrieve next WMI event from the pending list + */ +static struct list_head *next_wmi_ev(struct wil6210_priv *wil) +{ + ulong flags; + struct list_head *ret = NULL; + + spin_lock_irqsave(&wil->wmi_ev_lock, flags); + + if (!list_empty(&wil->pending_wmi_ev)) { + ret = wil->pending_wmi_ev.next; + list_del(ret); + } + + spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); + + return ret; +} + +/* + * Handler for the WMI events + */ +void wmi_event_worker(struct work_struct *work) +{ + struct wil6210_priv *wil = container_of(work, struct wil6210_priv, + wmi_event_worker); + struct pending_wmi_event *evt; + struct list_head *lh; + + while ((lh = next_wmi_ev(wil)) != NULL) { + evt = list_entry(lh, struct pending_wmi_event, list); + wmi_event_handle(wil, &evt->event.hdr); + kfree(evt); + } +} + +void wmi_connect_worker(struct work_struct *work) +{ + int rc; + struct wil6210_priv *wil = container_of(work, struct wil6210_priv, + wmi_connect_worker); + + if (wil->pending_connect_cid < 0) { + wil_err(wil, "No connection pending\n"); + return; + } + + wil_dbg_WMI(wil, "Configure for connection CID %d\n", + wil->pending_connect_cid); + + rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE, + wil->pending_connect_cid, 0); + wil->pending_connect_cid = -1; + if (rc == 0) + wil_link_on(wil); +} diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h new file mode 100644 index 00000000000..3bbf87572b0 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -0,0 +1,1116 @@ +/* + * Copyright (c) 2012 Qualcomm Atheros, Inc. + * Copyright (c) 2006-2012 Wilocity . + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file contains the definitions of the WMI protocol specified in the + * Wireless Module Interface (WMI) for the Wilocity + * MARLON 60 Gigabit wireless solution. + * It includes definitions of all the commands and events. + * Commands are messages from the host to the WM. + * Events are messages from the WM to the host. + */ + +#ifndef __WILOCITY_WMI_H__ +#define __WILOCITY_WMI_H__ + +/* General */ + +#define WMI_MAC_LEN (6) +#define WMI_PROX_RANGE_NUM (3) + +/* List of Commands */ +enum wmi_command_id { + WMI_CONNECT_CMDID = 0x0001, + WMI_DISCONNECT_CMDID = 0x0003, + WMI_START_SCAN_CMDID = 0x0007, + WMI_SET_BSS_FILTER_CMDID = 0x0009, + WMI_SET_PROBED_SSID_CMDID = 0x000a, + WMI_SET_LISTEN_INT_CMDID = 0x000b, + WMI_BCON_CTRL_CMDID = 0x000f, + WMI_ADD_CIPHER_KEY_CMDID = 0x0016, + WMI_DELETE_CIPHER_KEY_CMDID = 0x0017, + WMI_SET_APPIE_CMDID = 0x003f, + WMI_GET_APPIE_CMDID = 0x0040, + WMI_SET_WSC_STATUS_CMDID = 0x0041, + WMI_PXMT_RANGE_CFG_CMDID = 0x0042, + WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043, + WMI_FAST_MEM_ACC_MODE_CMDID = 0x0300, + WMI_MEM_READ_CMDID = 0x0800, + WMI_MEM_WR_CMDID = 0x0801, + WMI_ECHO_CMDID = 0x0803, + WMI_DEEP_ECHO_CMDID = 0x0804, + WMI_CONFIG_MAC_CMDID = 0x0805, + WMI_CONFIG_PHY_DEBUG_CMDID = 0x0806, + WMI_ADD_STATION_CMDID = 0x0807, + WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x0808, + WMI_PHY_GET_STATISTICS_CMDID = 0x0809, + WMI_FS_TUNE_CMDID = 0x080a, + WMI_CORR_MEASURE_CMDID = 0x080b, + WMI_TEMP_SENSE_CMDID = 0x080e, + WMI_DC_CALIB_CMDID = 0x080f, + WMI_SEND_TONE_CMDID = 0x0810, + WMI_IQ_TX_CALIB_CMDID = 0x0811, + WMI_IQ_RX_CALIB_CMDID = 0x0812, + WMI_SET_UCODE_IDLE_CMDID = 0x0813, + WMI_SET_WORK_MODE_CMDID = 0x0815, + WMI_LO_LEAKAGE_CALIB_CMDID = 0x0816, + WMI_MARLON_R_ACTIVATE_CMDID = 0x0817, + WMI_MARLON_R_READ_CMDID = 0x0818, + WMI_MARLON_R_WRITE_CMDID = 0x0819, + WMI_MARLON_R_TXRX_SEL_CMDID = 0x081a, + MAC_IO_STATIC_PARAMS_CMDID = 0x081b, + MAC_IO_DYNAMIC_PARAMS_CMDID = 0x081c, + WMI_SILENT_RSSI_CALIB_CMDID = 0x081d, + WMI_CFG_RX_CHAIN_CMDID = 0x0820, + WMI_VRING_CFG_CMDID = 0x0821, + WMI_RX_ON_CMDID = 0x0822, + WMI_VRING_BA_EN_CMDID = 0x0823, + WMI_VRING_BA_DIS_CMDID = 0x0824, + WMI_RCP_ADDBA_RESP_CMDID = 0x0825, + WMI_RCP_DELBA_CMDID = 0x0826, + WMI_SET_SSID_CMDID = 0x0827, + WMI_GET_SSID_CMDID = 0x0828, + WMI_SET_PCP_CHANNEL_CMDID = 0x0829, + WMI_GET_PCP_CHANNEL_CMDID = 0x082a, + WMI_SW_TX_REQ_CMDID = 0x082b, + WMI_RX_OFF_CMDID = 0x082c, + WMI_READ_MAC_RXQ_CMDID = 0x0830, + WMI_READ_MAC_TXQ_CMDID = 0x0831, + WMI_WRITE_MAC_RXQ_CMDID = 0x0832, + WMI_WRITE_MAC_TXQ_CMDID = 0x0833, + WMI_WRITE_MAC_XQ_FIELD_CMDID = 0x0834, + WMI_MLME_PUSH_CMDID = 0x0835, + WMI_BEAMFORMING_MGMT_CMDID = 0x0836, + WMI_BF_TXSS_MGMT_CMDID = 0x0837, + WMI_BF_SM_MGMT_CMDID = 0x0838, + WMI_BF_RXSS_MGMT_CMDID = 0x0839, + WMI_SET_SECTORS_CMDID = 0x0849, + WMI_MAINTAIN_PAUSE_CMDID = 0x0850, + WMI_MAINTAIN_RESUME_CMDID = 0x0851, + WMI_RS_MGMT_CMDID = 0x0852, + WMI_RF_MGMT_CMDID = 0x0853, + /* Performance monitoring commands */ + WMI_BF_CTRL_CMDID = 0x0862, + WMI_NOTIFY_REQ_CMDID = 0x0863, + WMI_GET_STATUS_CMDID = 0x0864, + WMI_UNIT_TEST_CMDID = 0x0900, + WMI_HICCUP_CMDID = 0x0901, + WMI_FLASH_READ_CMDID = 0x0902, + WMI_FLASH_WRITE_CMDID = 0x0903, + WMI_SECURITY_UNIT_TEST_CMDID = 0x0904, + + WMI_SET_MAC_ADDRESS_CMDID = 0xf003, + WMI_ABORT_SCAN_CMDID = 0xf007, + WMI_SET_PMK_CMDID = 0xf028, + + WMI_SET_PROMISCUOUS_MODE_CMDID = 0xf041, + WMI_GET_PMK_CMDID = 0xf048, + WMI_SET_PASSPHRASE_CMDID = 0xf049, + WMI_SEND_ASSOC_RES_CMDID = 0xf04a, + WMI_SET_ASSOC_REQ_RELAY_CMDID = 0xf04b, + WMI_EAPOL_TX_CMDID = 0xf04c, + WMI_MAC_ADDR_REQ_CMDID = 0xf04d, + WMI_FW_VER_CMDID = 0xf04e, +}; + +/* + * Commands data structures + */ + +/* + * Frame Types + */ +enum wmi_mgmt_frame_type { + WMI_FRAME_BEACON = 0, + WMI_FRAME_PROBE_REQ = 1, + WMI_FRAME_PROBE_RESP = 2, + WMI_FRAME_ASSOC_REQ = 3, + WMI_FRAME_ASSOC_RESP = 4, + WMI_NUM_MGMT_FRAME, +}; + +/* + * WMI_CONNECT_CMDID + */ +enum wmi_network_type { + WMI_NETTYPE_INFRA = 0x01, + WMI_NETTYPE_ADHOC = 0x02, + WMI_NETTYPE_ADHOC_CREATOR = 0x04, + WMI_NETTYPE_AP = 0x10, + WMI_NETTYPE_P2P = 0x20, + WMI_NETTYPE_WBE = 0x40, /* PCIE over 60g */ +}; + +enum wmi_dot11_auth_mode { + WMI_AUTH11_OPEN = 0x01, + WMI_AUTH11_SHARED = 0x02, + WMI_AUTH11_LEAP = 0x04, + WMI_AUTH11_WSC = 0x08, +}; + +enum wmi_auth_mode { + WMI_AUTH_NONE = 0x01, + WMI_AUTH_WPA = 0x02, + WMI_AUTH_WPA2 = 0x04, + WMI_AUTH_WPA_PSK = 0x08, + WMI_AUTH_WPA2_PSK = 0x10, + WMI_AUTH_WPA_CCKM = 0x20, + WMI_AUTH_WPA2_CCKM = 0x40, +}; + +enum wmi_crypto_type { + WMI_CRYPT_NONE = 0x01, + WMI_CRYPT_WEP = 0x02, + WMI_CRYPT_TKIP = 0x04, + WMI_CRYPT_AES = 0x08, + WMI_CRYPT_AES_GCMP = 0x20, +}; + + +enum wmi_connect_ctrl_flag_bits { + WMI_CONNECT_ASSOC_POLICY_USER = 0x0001, + WMI_CONNECT_SEND_REASSOC = 0x0002, + WMI_CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004, + WMI_CONNECT_PROFILE_MATCH_DONE = 0x0008, + WMI_CONNECT_IGNORE_AAC_BEACON = 0x0010, + WMI_CONNECT_CSA_FOLLOW_BSS = 0x0020, + WMI_CONNECT_DO_WPA_OFFLOAD = 0x0040, + WMI_CONNECT_DO_NOT_DEAUTH = 0x0080, +}; + +#define WMI_MAX_SSID_LEN (32) + +struct wmi_connect_cmd { + u8 network_type; + u8 dot11_auth_mode; + u8 auth_mode; + u8 pairwise_crypto_type; + u8 pairwise_crypto_len; + u8 group_crypto_type; + u8 group_crypto_len; + u8 ssid_len; + u8 ssid[WMI_MAX_SSID_LEN]; + u8 channel; + u8 reserved0; + u8 bssid[WMI_MAC_LEN]; + __le32 ctrl_flags; + u8 dst_mac[WMI_MAC_LEN]; + u8 reserved1[2]; +} __packed; + + +/* + * WMI_RECONNECT_CMDID + */ +struct wmi_reconnect_cmd { + u8 channel; /* hint */ + u8 reserved; + u8 bssid[WMI_MAC_LEN]; /* mandatory if set */ +} __packed; + + +/* + * WMI_SET_PMK_CMDID + */ + +#define WMI_MIN_KEY_INDEX (0) +#define WMI_MAX_KEY_INDEX (3) +#define WMI_MAX_KEY_LEN (32) +#define WMI_PASSPHRASE_LEN (64) +#define WMI_PMK_LEN (32) + +struct wmi_set_pmk_cmd { + u8 pmk[WMI_PMK_LEN]; +} __packed; + + +/* + * WMI_SET_PASSPHRASE_CMDID + */ +struct wmi_set_passphrase_cmd { + u8 ssid[WMI_MAX_SSID_LEN]; + u8 passphrase[WMI_PASSPHRASE_LEN]; + u8 ssid_len; + u8 passphrase_len; +} __packed; + +/* + * WMI_ADD_CIPHER_KEY_CMDID + */ +enum wmi_key_usage { + WMI_KEY_USE_PAIRWISE = 0, + WMI_KEY_USE_GROUP = 1, + WMI_KEY_USE_TX = 2, /* default Tx Key - Static WEP only */ +}; + +struct wmi_add_cipher_key_cmd { + u8 key_index; + u8 key_type; + u8 key_usage; /* enum wmi_key_usage */ + u8 key_len; + u8 key_rsc[8]; /* key replay sequence counter */ + u8 key[WMI_MAX_KEY_LEN]; + u8 key_op_ctrl; /* Additional Key Control information */ + u8 mac[WMI_MAC_LEN]; +} __packed; + +/* + * WMI_DELETE_CIPHER_KEY_CMDID + */ +struct wmi_delete_cipher_key_cmd { + u8 key_index; + u8 mac[WMI_MAC_LEN]; +} __packed; + + +/* + * WMI_START_SCAN_CMDID + * + * Start L1 scan operation + * + * Returned events: + * - WMI_RX_MGMT_PACKET_EVENTID - for every probe resp. + * - WMI_SCAN_COMPLETE_EVENTID + */ +enum wmi_scan_type { + WMI_LONG_SCAN = 0, + WMI_SHORT_SCAN = 1, +}; + +struct wmi_start_scan_cmd { + u8 reserved[8]; + __le32 home_dwell_time; /* Max duration in the home channel(ms) */ + __le32 force_scan_interval; /* Time interval between scans (ms)*/ + u8 scan_type; /* wmi_scan_type */ + u8 num_channels; /* how many channels follow */ + struct { + u8 channel; + u8 reserved; + } channel_list[0]; /* channels ID's */ + /* 0 - 58320 MHz */ + /* 1 - 60480 MHz */ + /* 2 - 62640 MHz */ +} __packed; + +/* + * WMI_SET_PROBED_SSID_CMDID + */ +#define MAX_PROBED_SSID_INDEX (15) + +enum wmi_ssid_flag { + WMI_SSID_FLAG_DISABLE = 0, /* disables entry */ + WMI_SSID_FLAG_SPECIFIC = 1, /* probes specified ssid */ + WMI_SSID_FLAG_ANY = 2, /* probes for any ssid */ +}; + +struct wmi_probed_ssid_cmd { + u8 entry_index; /* 0 to MAX_PROBED_SSID_INDEX */ + u8 flag; /* enum wmi_ssid_flag */ + u8 ssid_len; + u8 ssid[WMI_MAX_SSID_LEN]; +} __packed; + +/* + * WMI_SET_APPIE_CMDID + * Add Application specified IE to a management frame + */ +struct wmi_set_appie_cmd { + u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */ + u8 reserved; + __le16 ie_len; /* Length of the IE to be added to MGMT frame */ + u8 ie_info[0]; +} __packed; + +#define WMI_MAX_IE_LEN (1024) + +struct wmi_pxmt_range_cfg_cmd { + u8 dst_mac[WMI_MAC_LEN]; + __le16 range; +} __packed; + +struct wmi_pxmt_snr2_range_cfg_cmd { + s8 snr2range_arr[WMI_PROX_RANGE_NUM-1]; +} __packed; + +/* + * WMI_RF_MGMT_CMDID + */ +enum wmi_rf_mgmt_type { + WMI_RF_MGMT_W_DISABLE = 0, + WMI_RF_MGMT_W_ENABLE = 1, + WMI_RF_MGMT_GET_STATUS = 2, +}; + +struct wmi_rf_mgmt_cmd { + __le32 rf_mgmt_type; +} __packed; + +/* + * WMI_SET_SSID_CMDID + */ +struct wmi_set_ssid_cmd { + __le32 ssid_len; + u8 ssid[WMI_MAX_SSID_LEN]; +} __packed; + +/* + * WMI_SET_PCP_CHANNEL_CMDID + */ +struct wmi_set_pcp_channel_cmd { + u8 channel; + u8 reserved[3]; +} __packed; + +/* + * WMI_BCON_CTRL_CMDID + */ +struct wmi_bcon_ctrl_cmd { + __le16 bcon_interval; + __le16 frag_num; + __le64 ss_mask; + u8 network_type; + u8 reserved; + u8 disable_sec_offload; + u8 disable_sec; +} __packed; + +/* + * WMI_SW_TX_REQ_CMDID + */ +struct wmi_sw_tx_req_cmd { + u8 dst_mac[WMI_MAC_LEN]; + __le16 len; + u8 payload[0]; +} __packed; + +/* + * WMI_VRING_CFG_CMDID + */ + +struct wmi_sw_ring_cfg { + __le64 ring_mem_base; + __le16 ring_size; + __le16 max_mpdu_size; +} __packed; + +struct wmi_vring_cfg_schd { + __le16 priority; + __le16 timeslot_us; +} __packed; + +enum wmi_vring_cfg_encap_trans_type { + WMI_VRING_ENC_TYPE_802_3 = 0, + WMI_VRING_ENC_TYPE_NATIVE_WIFI = 1, +}; + +enum wmi_vring_cfg_ds_cfg { + WMI_VRING_DS_PBSS = 0, + WMI_VRING_DS_STATION = 1, + WMI_VRING_DS_AP = 2, + WMI_VRING_DS_ADDR4 = 3, +}; + +enum wmi_vring_cfg_nwifi_ds_trans_type { + WMI_NWIFI_TX_TRANS_MODE_NO = 0, + WMI_NWIFI_TX_TRANS_MODE_AP2PBSS = 1, + WMI_NWIFI_TX_TRANS_MODE_STA2PBSS = 2, +}; + +enum wmi_vring_cfg_schd_params_priority { + WMI_SCH_PRIO_REGULAR = 0, + WMI_SCH_PRIO_HIGH = 1, +}; + +struct wmi_vring_cfg { + struct wmi_sw_ring_cfg tx_sw_ring; + u8 ringid; /* 0-23 vrings */ + + #define CIDXTID_CID_POS (0) + #define CIDXTID_CID_LEN (4) + #define CIDXTID_CID_MSK (0xF) + #define CIDXTID_TID_POS (4) + #define CIDXTID_TID_LEN (4) + #define CIDXTID_TID_MSK (0xF0) + u8 cidxtid; + + u8 encap_trans_type; + u8 ds_cfg; /* 802.3 DS cfg */ + u8 nwifi_ds_trans_type; + + #define VRING_CFG_MAC_CTRL_LIFETIME_EN_POS (0) + #define VRING_CFG_MAC_CTRL_LIFETIME_EN_LEN (1) + #define VRING_CFG_MAC_CTRL_LIFETIME_EN_MSK (0x1) + #define VRING_CFG_MAC_CTRL_AGGR_EN_POS (1) + #define VRING_CFG_MAC_CTRL_AGGR_EN_LEN (1) + #define VRING_CFG_MAC_CTRL_AGGR_EN_MSK (0x2) + u8 mac_ctrl; + + #define VRING_CFG_TO_RESOLUTION_VALUE_POS (0) + #define VRING_CFG_TO_RESOLUTION_VALUE_LEN (6) + #define VRING_CFG_TO_RESOLUTION_VALUE_MSK (0x3F) + u8 to_resolution; + u8 agg_max_wsize; + struct wmi_vring_cfg_schd schd_params; +} __packed; + +enum wmi_vring_cfg_cmd_action { + WMI_VRING_CMD_ADD = 0, + WMI_VRING_CMD_MODIFY = 1, + WMI_VRING_CMD_DELETE = 2, +}; + +struct wmi_vring_cfg_cmd { + __le32 action; + struct wmi_vring_cfg vring_cfg; +} __packed; + +/* + * WMI_VRING_BA_EN_CMDID + */ +struct wmi_vring_ba_en_cmd { + u8 ringid; + u8 agg_max_wsize; + __le16 ba_timeout; +} __packed; + +/* + * WMI_VRING_BA_DIS_CMDID + */ +struct wmi_vring_ba_dis_cmd { + u8 ringid; + u8 reserved; + __le16 reason; +} __packed; + +/* + * WMI_NOTIFY_REQ_CMDID + */ +struct wmi_notify_req_cmd { + u8 cid; + u8 reserved[3]; + __le32 interval_usec; +} __packed; + +/* + * WMI_CFG_RX_CHAIN_CMDID + */ +enum wmi_sniffer_cfg_mode { + WMI_SNIFFER_OFF = 0, + WMI_SNIFFER_ON = 1, +}; + +enum wmi_sniffer_cfg_phy_info_mode { + WMI_SNIFFER_PHY_INFO_DISABLED = 0, + WMI_SNIFFER_PHY_INFO_ENABLED = 1, +}; + +enum wmi_sniffer_cfg_phy_support { + WMI_SNIFFER_CP = 0, + WMI_SNIFFER_DP = 1, + WMI_SNIFFER_BOTH_PHYS = 2, +}; + +struct wmi_sniffer_cfg { + __le32 mode; /* enum wmi_sniffer_cfg_mode */ + __le32 phy_info_mode; /* enum wmi_sniffer_cfg_phy_info_mode */ + __le32 phy_support; /* enum wmi_sniffer_cfg_phy_support */ + u8 channel; + u8 reserved[3]; +} __packed; + +enum wmi_cfg_rx_chain_cmd_action { + WMI_RX_CHAIN_ADD = 0, + WMI_RX_CHAIN_DEL = 1, +}; + +enum wmi_cfg_rx_chain_cmd_decap_trans_type { + WMI_DECAP_TYPE_802_3 = 0, + WMI_DECAP_TYPE_NATIVE_WIFI = 1, +}; + +enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type { + WMI_NWIFI_RX_TRANS_MODE_NO = 0, + WMI_NWIFI_RX_TRANS_MODE_PBSS2AP = 1, + WMI_NWIFI_RX_TRANS_MODE_PBSS2STA = 2, +}; + +struct wmi_cfg_rx_chain_cmd { + __le32 action; + struct wmi_sw_ring_cfg rx_sw_ring; + u8 mid; + u8 decap_trans_type; + + #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0) + #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1) + #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1) + u8 l2_802_3_offload_ctrl; + + #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0) + #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_LEN (1) + #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_MSK (0x1) + #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_POS (1) + #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_LEN (1) + #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_MSK (0x2) + u8 l2_nwifi_offload_ctrl; + + u8 vlan_id; + u8 nwifi_ds_trans_type; + + #define L3_L4_CTRL_IPV4_CHECKSUM_EN_POS (0) + #define L3_L4_CTRL_IPV4_CHECKSUM_EN_LEN (1) + #define L3_L4_CTRL_IPV4_CHECKSUM_EN_MSK (0x1) + #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS (1) + #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_LEN (1) + #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_MSK (0x2) + u8 l3_l4_ctrl; + + #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_POS (0) + #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_LEN (1) + #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_MSK (0x1) + #define RING_CTRL_OVERRIDE_WB_THRSH_POS (1) + #define RING_CTRL_OVERRIDE_WB_THRSH_LEN (1) + #define RING_CTRL_OVERRIDE_WB_THRSH_MSK (0x2) + #define RING_CTRL_OVERRIDE_ITR_THRSH_POS (2) + #define RING_CTRL_OVERRIDE_ITR_THRSH_LEN (1) + #define RING_CTRL_OVERRIDE_ITR_THRSH_MSK (0x4) + #define RING_CTRL_OVERRIDE_HOST_THRSH_POS (3) + #define RING_CTRL_OVERRIDE_HOST_THRSH_LEN (1) + #define RING_CTRL_OVERRIDE_HOST_THRSH_MSK (0x8) + u8 ring_ctrl; + + __le16 prefetch_thrsh; + __le16 wb_thrsh; + __le32 itr_value; + __le16 host_thrsh; + u8 reserved[2]; + struct wmi_sniffer_cfg sniffer_cfg; +} __packed; + +/* + * WMI_RCP_ADDBA_RESP_CMDID + */ +struct wmi_rcp_addba_resp_cmd { + + #define CIDXTID_CID_POS (0) + #define CIDXTID_CID_LEN (4) + #define CIDXTID_CID_MSK (0xF) + #define CIDXTID_TID_POS (4) + #define CIDXTID_TID_LEN (4) + #define CIDXTID_TID_MSK (0xF0) + u8 cidxtid; + + u8 dialog_token; + __le16 status_code; + __le16 ba_param_set; /* ieee80211_ba_parameterset field to send */ + __le16 ba_timeout; +} __packed; + +/* + * WMI_RCP_DELBA_CMDID + */ +struct wmi_rcp_delba_cmd { + + #define CIDXTID_CID_POS (0) + #define CIDXTID_CID_LEN (4) + #define CIDXTID_CID_MSK (0xF) + #define CIDXTID_TID_POS (4) + #define CIDXTID_TID_LEN (4) + #define CIDXTID_TID_MSK (0xF0) + u8 cidxtid; + + u8 reserved; + __le16 reason; +} __packed; + +/* + * WMI_RCP_ADDBA_REQ_CMDID + */ +struct wmi_rcp_addba_req_cmd { + + #define CIDXTID_CID_POS (0) + #define CIDXTID_CID_LEN (4) + #define CIDXTID_CID_MSK (0xF) + #define CIDXTID_TID_POS (4) + #define CIDXTID_TID_LEN (4) + #define CIDXTID_TID_MSK (0xF0) + u8 cidxtid; + + u8 dialog_token; + /* ieee80211_ba_parameterset field as it received */ + __le16 ba_param_set; + __le16 ba_timeout; + /* ieee80211_ba_seqstrl field as it received */ + __le16 ba_seq_ctrl; +} __packed; + +/* + * WMI_SET_MAC_ADDRESS_CMDID + */ +struct wmi_set_mac_address_cmd { + u8 mac[WMI_MAC_LEN]; + u8 reserved[2]; +} __packed; + + +/* +* WMI_EAPOL_TX_CMDID +*/ +struct wmi_eapol_tx_cmd { + u8 dst_mac[WMI_MAC_LEN]; + __le16 eapol_len; + u8 eapol[0]; +} __packed; + +/* + * WMI_ECHO_CMDID + * + * Check FW is alive + * + * WMI_DEEP_ECHO_CMDID + * + * Check FW and ucode are alive + * + * Returned event: WMI_ECHO_RSP_EVENTID + * same event for both commands + */ +struct wmi_echo_cmd { + __le32 value; +} __packed; + +/* + * WMI Events + */ + +/* + * List of Events (target to host) + */ +enum wmi_event_id { + WMI_IMM_RSP_EVENTID = 0x0000, + WMI_READY_EVENTID = 0x1001, + WMI_CONNECT_EVENTID = 0x1002, + WMI_DISCONNECT_EVENTID = 0x1003, + WMI_SCAN_COMPLETE_EVENTID = 0x100a, + WMI_REPORT_STATISTICS_EVENTID = 0x100b, + WMI_RD_MEM_RSP_EVENTID = 0x1800, + WMI_FW_READY_EVENTID = 0x1801, + WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x0200, + WMI_ECHO_RSP_EVENTID = 0x1803, + WMI_CONFIG_MAC_DONE_EVENTID = 0x1805, + WMI_CONFIG_PHY_DEBUG_DONE_EVENTID = 0x1806, + WMI_ADD_STATION_DONE_EVENTID = 0x1807, + WMI_ADD_DEBUG_TX_PCKT_DONE_EVENTID = 0x1808, + WMI_PHY_GET_STATISTICS_EVENTID = 0x1809, + WMI_FS_TUNE_DONE_EVENTID = 0x180a, + WMI_CORR_MEASURE_DONE_EVENTID = 0x180b, + WMI_TEMP_SENSE_DONE_EVENTID = 0x180e, + WMI_DC_CALIB_DONE_EVENTID = 0x180f, + WMI_IQ_TX_CALIB_DONE_EVENTID = 0x1811, + WMI_IQ_RX_CALIB_DONE_EVENTID = 0x1812, + WMI_SET_WORK_MODE_DONE_EVENTID = 0x1815, + WMI_LO_LEAKAGE_CALIB_DONE_EVENTID = 0x1816, + WMI_MARLON_R_ACTIVATE_DONE_EVENTID = 0x1817, + WMI_MARLON_R_READ_DONE_EVENTID = 0x1818, + WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819, + WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181a, + WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181d, + + WMI_CFG_RX_CHAIN_DONE_EVENTID = 0x1820, + WMI_VRING_CFG_DONE_EVENTID = 0x1821, + WMI_RX_ON_DONE_EVENTID = 0x1822, + WMI_BA_STATUS_EVENTID = 0x1823, + WMI_RCP_ADDBA_REQ_EVENTID = 0x1824, + WMI_ADDBA_RESP_SENT_EVENTID = 0x1825, + WMI_DELBA_EVENTID = 0x1826, + WMI_GET_SSID_EVENTID = 0x1828, + WMI_GET_PCP_CHANNEL_EVENTID = 0x182a, + WMI_SW_TX_COMPLETE_EVENTID = 0x182b, + WMI_RX_OFF_DONE_EVENTID = 0x182c, + + WMI_READ_MAC_RXQ_EVENTID = 0x1830, + WMI_READ_MAC_TXQ_EVENTID = 0x1831, + WMI_WRITE_MAC_RXQ_EVENTID = 0x1832, + WMI_WRITE_MAC_TXQ_EVENTID = 0x1833, + WMI_WRITE_MAC_XQ_FIELD_EVENTID = 0x1834, + + WMI_BEAFORMING_MGMT_DONE_EVENTID = 0x1836, + WMI_BF_TXSS_MGMT_DONE_EVENTID = 0x1837, + WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839, + WMI_RS_MGMT_DONE_EVENTID = 0x1852, + WMI_RF_MGMT_STATUS_EVENTID = 0x1853, + WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838, + WMI_RX_MGMT_PACKET_EVENTID = 0x1840, + + /* Performance monitoring events */ + WMI_DATA_PORT_OPEN_EVENTID = 0x1860, + WMI_WBE_LINKDOWN_EVENTID = 0x1861, + + WMI_BF_CTRL_DONE_EVENTID = 0x1862, + WMI_NOTIFY_REQ_DONE_EVENTID = 0x1863, + WMI_GET_STATUS_DONE_EVENTID = 0x1864, + + WMI_UNIT_TEST_EVENTID = 0x1900, + WMI_FLASH_READ_DONE_EVENTID = 0x1902, + WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, + + WMI_SET_CHANNEL_EVENTID = 0x9000, + WMI_ASSOC_REQ_EVENTID = 0x9001, + WMI_EAPOL_RX_EVENTID = 0x9002, + WMI_MAC_ADDR_RESP_EVENTID = 0x9003, + WMI_FW_VER_EVENTID = 0x9004, +}; + +/* + * Events data structures + */ + +/* + * WMI_RF_MGMT_STATUS_EVENTID + */ +enum wmi_rf_status { + WMI_RF_ENABLED = 0, + WMI_RF_DISABLED_HW = 1, + WMI_RF_DISABLED_SW = 2, + WMI_RF_DISABLED_HW_SW = 3, +}; + +struct wmi_rf_mgmt_status_event { + __le32 rf_status; +} __packed; + +/* + * WMI_GET_STATUS_DONE_EVENTID + */ +struct wmi_get_status_done_event { + __le32 is_associated; + u8 cid; + u8 reserved0[3]; + u8 bssid[WMI_MAC_LEN]; + u8 channel; + u8 reserved1; + u8 network_type; + u8 reserved2[3]; + __le32 ssid_len; + u8 ssid[WMI_MAX_SSID_LEN]; + __le32 rf_status; + __le32 is_secured; +} __packed; + +/* + * WMI_FW_VER_EVENTID + */ +struct wmi_fw_ver_event { + u8 major; + u8 minor; + __le16 subminor; + __le16 build; +} __packed; + +/* +* WMI_MAC_ADDR_RESP_EVENTID +*/ +struct wmi_mac_addr_resp_event { + u8 mac[WMI_MAC_LEN]; + u8 auth_mode; + u8 crypt_mode; + __le32 offload_mode; +} __packed; + +/* +* WMI_EAPOL_RX_EVENTID +*/ +struct wmi_eapol_rx_event { + u8 src_mac[WMI_MAC_LEN]; + __le16 eapol_len; + u8 eapol[0]; +} __packed; + +/* +* WMI_READY_EVENTID +*/ +enum wmi_phy_capability { + WMI_11A_CAPABILITY = 1, + WMI_11G_CAPABILITY = 2, + WMI_11AG_CAPABILITY = 3, + WMI_11NA_CAPABILITY = 4, + WMI_11NG_CAPABILITY = 5, + WMI_11NAG_CAPABILITY = 6, + WMI_11AD_CAPABILITY = 7, + WMI_11N_CAPABILITY_OFFSET = WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY, +}; + +struct wmi_ready_event { + __le32 sw_version; + __le32 abi_version; + u8 mac[WMI_MAC_LEN]; + u8 phy_capability; /* enum wmi_phy_capability */ + u8 reserved; +} __packed; + +/* + * WMI_NOTIFY_REQ_DONE_EVENTID + */ +struct wmi_notify_req_done_event { + __le32 status; + __le64 tsf; + __le32 snr_val; + __le32 tx_tpt; + __le32 tx_goodput; + __le32 rx_goodput; + __le16 bf_mcs; + __le16 my_rx_sector; + __le16 my_tx_sector; + __le16 other_rx_sector; + __le16 other_tx_sector; + __le16 range; +} __packed; + +/* + * WMI_CONNECT_EVENTID + */ +struct wmi_connect_event { + u8 channel; + u8 reserved0; + u8 bssid[WMI_MAC_LEN]; + __le16 listen_interval; + __le16 beacon_interval; + u8 network_type; + u8 reserved1[3]; + u8 beacon_ie_len; + u8 assoc_req_len; + u8 assoc_resp_len; + u8 cid; + u8 reserved2[3]; + u8 assoc_info[0]; +} __packed; + +/* + * WMI_DISCONNECT_EVENTID + */ +enum wmi_disconnect_reason { + WMI_DIS_REASON_NO_NETWORK_AVAIL = 1, + WMI_DIS_REASON_LOST_LINK = 2, /* bmiss */ + WMI_DIS_REASON_DISCONNECT_CMD = 3, + WMI_DIS_REASON_BSS_DISCONNECTED = 4, + WMI_DIS_REASON_AUTH_FAILED = 5, + WMI_DIS_REASON_ASSOC_FAILED = 6, + WMI_DIS_REASON_NO_RESOURCES_AVAIL = 7, + WMI_DIS_REASON_CSERV_DISCONNECT = 8, + WMI_DIS_REASON_INVALID_PROFILE = 10, + WMI_DIS_REASON_DOT11H_CHANNEL_SWITCH = 11, + WMI_DIS_REASON_PROFILE_MISMATCH = 12, + WMI_DIS_REASON_CONNECTION_EVICTED = 13, + WMI_DIS_REASON_IBSS_MERGE = 14, +}; + +struct wmi_disconnect_event { + __le16 protocol_reason_status; /* reason code, see 802.11 spec. */ + u8 bssid[WMI_MAC_LEN]; /* set if known */ + u8 disconnect_reason; /* see wmi_disconnect_reason_e */ + u8 assoc_resp_len; + u8 assoc_info[0]; +} __packed; + +/* + * WMI_SCAN_COMPLETE_EVENTID + */ +struct wmi_scan_complete_event { + __le32 status; +} __packed; + +/* + * WMI_BA_STATUS_EVENTID + */ +enum wmi_vring_ba_status { + WMI_BA_AGREED = 0, + WMI_BA_NON_AGREED = 1, +}; + +struct wmi_vring_ba_status_event { + __le16 status; + u8 reserved[2]; + u8 ringid; + u8 agg_wsize; + __le16 ba_timeout; +} __packed; + +/* + * WMI_DELBA_EVENTID + */ +struct wmi_delba_event { + + #define CIDXTID_CID_POS (0) + #define CIDXTID_CID_LEN (4) + #define CIDXTID_CID_MSK (0xF) + #define CIDXTID_TID_POS (4) + #define CIDXTID_TID_LEN (4) + #define CIDXTID_TID_MSK (0xF0) + u8 cidxtid; + + u8 from_initiator; + __le16 reason; +} __packed; + +/* + * WMI_VRING_CFG_DONE_EVENTID + */ +enum wmi_vring_cfg_done_event_status { + WMI_VRING_CFG_SUCCESS = 0, + WMI_VRING_CFG_FAILURE = 1, +}; + +struct wmi_vring_cfg_done_event { + u8 ringid; + u8 status; + u8 reserved[2]; + __le32 tx_vring_tail_ptr; +} __packed; + +/* + * WMI_ADDBA_RESP_SENT_EVENTID + */ +enum wmi_rcp_addba_resp_sent_event_status { + WMI_ADDBA_SUCCESS = 0, + WMI_ADDBA_FAIL = 1, +}; + +struct wmi_rcp_addba_resp_sent_event { + + #define CIDXTID_CID_POS (0) + #define CIDXTID_CID_LEN (4) + #define CIDXTID_CID_MSK (0xF) + #define CIDXTID_TID_POS (4) + #define CIDXTID_TID_LEN (4) + #define CIDXTID_TID_MSK (0xF0) + u8 cidxtid; + + u8 reserved; + __le16 status; +} __packed; + +/* + * WMI_RCP_ADDBA_REQ_EVENTID + */ +struct wmi_rcp_addba_req_event { + + #define CIDXTID_CID_POS (0) + #define CIDXTID_CID_LEN (4) + #define CIDXTID_CID_MSK (0xF) + #define CIDXTID_TID_POS (4) + #define CIDXTID_TID_LEN (4) + #define CIDXTID_TID_MSK (0xF0) + u8 cidxtid; + + u8 dialog_token; + __le16 ba_param_set; /* ieee80211_ba_parameterset as it received */ + __le16 ba_timeout; + __le16 ba_seq_ctrl; /* ieee80211_ba_seqstrl field as it received */ +} __packed; + +/* + * WMI_CFG_RX_CHAIN_DONE_EVENTID + */ +enum wmi_cfg_rx_chain_done_event_status { + WMI_CFG_RX_CHAIN_SUCCESS = 1, +}; + +struct wmi_cfg_rx_chain_done_event { + __le32 rx_ring_tail_ptr; /* Rx V-Ring Tail pointer */ + __le32 status; +} __packed; + +/* + * WMI_WBE_LINKDOWN_EVENTID + */ +enum wmi_wbe_link_down_event_reason { + WMI_WBE_REASON_USER_REQUEST = 0, + WMI_WBE_REASON_RX_DISASSOC = 1, + WMI_WBE_REASON_BAD_PHY_LINK = 2, +}; + +struct wmi_wbe_link_down_event { + u8 cid; + u8 reserved[3]; + __le32 reason; +} __packed; + +/* + * WMI_DATA_PORT_OPEN_EVENTID + */ +struct wmi_data_port_open_event { + u8 cid; + u8 reserved[3]; +} __packed; + +/* + * WMI_GET_PCP_CHANNEL_EVENTID + */ +struct wmi_get_pcp_channel_event { + u8 channel; + u8 reserved[3]; +} __packed; + +/* + * WMI_SW_TX_COMPLETE_EVENTID + */ +enum wmi_sw_tx_status { + WMI_TX_SW_STATUS_SUCCESS = 0, + WMI_TX_SW_STATUS_FAILED_NO_RESOURCES = 1, + WMI_TX_SW_STATUS_FAILED_TX = 2, +}; + +struct wmi_sw_tx_complete_event { + u8 status; /* enum wmi_sw_tx_status */ + u8 reserved[3]; +} __packed; + +/* + * WMI_GET_SSID_EVENTID + */ +struct wmi_get_ssid_event { + __le32 ssid_len; + u8 ssid[WMI_MAX_SSID_LEN]; +} __packed; + +/* + * WMI_RX_MGMT_PACKET_EVENTID + */ +struct wmi_rx_mgmt_info { + u8 mcs; + s8 snr; + __le16 range; + __le16 stype; + __le16 status; + __le32 len; + u8 qid; + u8 mid; + u8 cid; + u8 channel; /* From Radio MNGR */ +} __packed; + +struct wmi_rx_mgmt_packet_event { + struct wmi_rx_mgmt_info info; + u8 payload[0]; +} __packed; + +/* + * WMI_ECHO_RSP_EVENTID + */ +struct wmi_echo_event { + __le32 echoed_value; +} __packed; + +#endif /* __WILOCITY_WMI_H__ */ diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index b298e5d68be..10e288d470e 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -7,6 +7,7 @@ #include <linux/hw_random.h> #include <linux/bcma/bcma.h> #include <linux/ssb/ssb.h> +#include <linux/completion.h> #include <net/mac80211.h> #include "debugfs.h" @@ -722,6 +723,10 @@ enum b43_firmware_file_type { struct b43_request_fw_context { /* The device we are requesting the fw for. */ struct b43_wldev *dev; + /* a completion event structure needed if this call is asynchronous */ + struct completion fw_load_complete; + /* a pointer to the firmware object */ + const struct firmware *blob; /* The type of firmware to request. */ enum b43_firmware_file_type req_type; /* Error messages for each firmware type. */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 16ab280359b..806e34c1928 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2088,11 +2088,18 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error) b43warn(wl, text); } +static void b43_fw_cb(const struct firmware *firmware, void *context) +{ + struct b43_request_fw_context *ctx = context; + + ctx->blob = firmware; + complete(&ctx->fw_load_complete); +} + int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, - struct b43_firmware_file *fw) + struct b43_firmware_file *fw, bool async) { - const struct firmware *blob; struct b43_fw_header *hdr; u32 size; int err; @@ -2131,11 +2138,31 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, B43_WARN_ON(1); return -ENOSYS; } - err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); + if (async) { + /* do this part asynchronously */ + init_completion(&ctx->fw_load_complete); + err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, + ctx->dev->dev->dev, GFP_KERNEL, + ctx, b43_fw_cb); + if (err < 0) { + pr_err("Unable to load firmware\n"); + return err; + } + /* stall here until fw ready */ + wait_for_completion(&ctx->fw_load_complete); + if (ctx->blob) + goto fw_ready; + /* On some ARM systems, the async request will fail, but the next sync + * request works. For this reason, we dall through here + */ + } + err = request_firmware(&ctx->blob, ctx->fwname, + ctx->dev->dev->dev); if (err == -ENOENT) { snprintf(ctx->errors[ctx->req_type], sizeof(ctx->errors[ctx->req_type]), - "Firmware file \"%s\" not found\n", ctx->fwname); + "Firmware file \"%s\" not found\n", + ctx->fwname); return err; } else if (err) { snprintf(ctx->errors[ctx->req_type], @@ -2144,14 +2171,15 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, ctx->fwname, err); return err; } - if (blob->size < sizeof(struct b43_fw_header)) +fw_ready: + if (ctx->blob->size < sizeof(struct b43_fw_header)) goto err_format; - hdr = (struct b43_fw_header *)(blob->data); + hdr = (struct b43_fw_header *)(ctx->blob->data); switch (hdr->type) { case B43_FW_TYPE_UCODE: case B43_FW_TYPE_PCM: size = be32_to_cpu(hdr->size); - if (size != blob->size - sizeof(struct b43_fw_header)) + if (size != ctx->blob->size - sizeof(struct b43_fw_header)) goto err_format; /* fallthrough */ case B43_FW_TYPE_IV: @@ -2162,7 +2190,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, goto err_format; } - fw->data = blob; + fw->data = ctx->blob; fw->filename = name; fw->type = ctx->req_type; @@ -2172,7 +2200,7 @@ err_format: snprintf(ctx->errors[ctx->req_type], sizeof(ctx->errors[ctx->req_type]), "Firmware file \"%s\" format error.\n", ctx->fwname); - release_firmware(blob); + release_firmware(ctx->blob); return -EPROTO; } @@ -2223,7 +2251,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) goto err_no_ucode; } } - err = b43_do_request_fw(ctx, filename, &fw->ucode); + err = b43_do_request_fw(ctx, filename, &fw->ucode, true); if (err) goto err_load; @@ -2235,7 +2263,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) else goto err_no_pcm; fw->pcm_request_failed = false; - err = b43_do_request_fw(ctx, filename, &fw->pcm); + err = b43_do_request_fw(ctx, filename, &fw->pcm, false); if (err == -ENOENT) { /* We did not find a PCM file? Not fatal, but * core rev <= 10 must do without hwcrypto then. */ @@ -2296,7 +2324,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) default: goto err_no_initvals; } - err = b43_do_request_fw(ctx, filename, &fw->initvals); + err = b43_do_request_fw(ctx, filename, &fw->initvals, false); if (err) goto err_load; @@ -2355,7 +2383,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) default: goto err_no_initvals; } - err = b43_do_request_fw(ctx, filename, &fw->initvals_band); + err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false); if (err) goto err_load; diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 8c684cd3352..abac25ee958 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h @@ -137,9 +137,8 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on); struct b43_request_fw_context; -int b43_do_request_fw(struct b43_request_fw_context *ctx, - const char *name, - struct b43_firmware_file *fw); +int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, + struct b43_firmware_file *fw, bool async); void b43_do_release_fw(struct b43_firmware_file *fw); #endif /* B43_MAIN_H_ */ diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index d604b4036a7..3726cd6fcd7 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3273,7 +3273,7 @@ il3945_store_measurement(struct device *d, struct device_attribute *attr, if (count) { char *p = buffer; - strncpy(buffer, buf, min(sizeof(buffer), count)); + strlcpy(buffer, buf, sizeof(buffer)); channel = simple_strtoul(p, NULL, 0); if (channel) params.channel = channel; diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index da21328ca8e..a790599fe2c 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c @@ -1151,13 +1151,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, next_reclaimed = ssn; } - if (tid != IWL_TID_NON_QOS) { - priv->tid_data[sta_id][tid].next_reclaimed = - next_reclaimed; - IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", - next_reclaimed); - } - iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); iwlagn_check_ratid_empty(priv, sta_id, tid); @@ -1208,11 +1201,28 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, if (!is_agg) iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); + /* + * W/A for FW bug - the seq_ctl isn't updated when the + * queues are flushed. Fetch it from the packet itself + */ + if (!is_agg && status == TX_STATUS_FAIL_FIFO_FLUSHED) { + next_reclaimed = le16_to_cpu(hdr->seq_ctrl); + next_reclaimed = + SEQ_TO_SN(next_reclaimed + 0x10); + } + is_offchannel_skb = (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); freed++; } + if (tid != IWL_TID_NON_QOS) { + priv->tid_data[sta_id][tid].next_reclaimed = + next_reclaimed; + IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", + next_reclaimed); + } + WARN_ON(!is_agg && freed != 1); /* diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index dad4c4aad91..8389cd38338 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -1166,6 +1166,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data) else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && !trans_pcie->inta) iwl_enable_interrupts(trans); + return IRQ_HANDLED; none: /* re-enable interrupts here since we don't have anything to service. */ diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index a875499f894..efe525be27d 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1709,7 +1709,7 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv, NL80211_CHAN_NO_HT) config_bands |= BAND_GN; } else { - if (cfg80211_get_chandef_type(¶ms->chandef) != + if (cfg80211_get_chandef_type(¶ms->chandef) == NL80211_CHAN_NO_HT) config_bands = BAND_A; else diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index cb682561c43..60e88b58039 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -56,7 +56,6 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, */ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) { - bool cancel_flag = false; int status; struct cmd_ctrl_node *cmd_queued; @@ -70,14 +69,11 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) atomic_inc(&adapter->cmd_pending); /* Wait for completion */ - wait_event_interruptible(adapter->cmd_wait_q.wait, - *(cmd_queued->condition)); - if (!*(cmd_queued->condition)) - cancel_flag = true; - - if (cancel_flag) { - mwifiex_cancel_pending_ioctl(adapter); - dev_dbg(adapter->dev, "cmd cancel\n"); + status = wait_event_interruptible(adapter->cmd_wait_q.wait, + *(cmd_queued->condition)); + if (status) { + dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); + return status; } status = adapter->cmd_wait_q.status; @@ -496,8 +492,11 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) return false; } - wait_event_interruptible(adapter->hs_activate_wait_q, - adapter->hs_activate_wait_q_woken); + if (wait_event_interruptible(adapter->hs_activate_wait_q, + adapter->hs_activate_wait_q_woken)) { + dev_err(adapter->dev, "hs_activate_wait_q terminated\n"); + return false; + } return true; } diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index f221b95b90b..83564d36e80 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -4250,9 +4250,11 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, p->amsdu_enabled = 0; rc = mwl8k_post_cmd(hw, &cmd->header); + if (!rc) + rc = p->station_id; kfree(cmd); - return rc ? rc : p->station_id; + return rc; } static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index 1d5d3604e3e..246e5352f2e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c @@ -692,7 +692,7 @@ u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw) if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { rtl92c_phy_sw_chnl_callback(hw); RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false schdule workitem\n"); + "sw_chnl_inprogress false schedule workitem\n"); rtlphy->sw_chnl_inprogress = false; } else { RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c index 39cc7938eed..3d8536bb0d2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c @@ -1106,7 +1106,7 @@ u8 rtl8723ae_phy_sw_chnl(struct ieee80211_hw *hw) if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { rtl8723ae_phy_sw_chnl_callback(hw); RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false schdule workitem\n"); + "sw_chnl_inprogress false schedule workitem\n"); rtlphy->sw_chnl_inprogress = false; } else { RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 26ffd3e3fb7..2c113de9432 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -44,7 +44,6 @@ extern bool pciehp_poll_mode; extern int pciehp_poll_time; extern bool pciehp_debug; extern bool pciehp_force; -extern struct workqueue_struct *pciehp_wq; #define dbg(format, arg...) \ do { \ @@ -78,6 +77,7 @@ struct slot { struct hotplug_slot *hotplug_slot; struct delayed_work work; /* work for button event */ struct mutex lock; + struct workqueue_struct *wq; }; struct event_info { diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 916bf4f53ab..939bd1d4b5b 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -42,7 +42,6 @@ bool pciehp_debug; bool pciehp_poll_mode; int pciehp_poll_time; bool pciehp_force; -struct workqueue_struct *pciehp_wq; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" @@ -340,18 +339,13 @@ static int __init pcied_init(void) { int retval = 0; - pciehp_wq = alloc_workqueue("pciehp", 0, 0); - if (!pciehp_wq) - return -ENOMEM; - pciehp_firmware_init(); retval = pcie_port_service_register(&hpdriver_portdrv); dbg("pcie_port_service_register = %d\n", retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - if (retval) { - destroy_workqueue(pciehp_wq); + if (retval) dbg("Failure to register service\n"); - } + return retval; } @@ -359,7 +353,6 @@ static void __exit pcied_cleanup(void) { dbg("unload_pciehpd()\n"); pcie_port_service_unregister(&hpdriver_portdrv); - destroy_workqueue(pciehp_wq); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 27f44295a65..38f01867917 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -49,7 +49,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) info->p_slot = p_slot; INIT_WORK(&info->work, interrupt_event_handler); - queue_work(pciehp_wq, &info->work); + queue_work(p_slot->wq, &info->work); return 0; } @@ -344,7 +344,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work) kfree(info); goto out; } - queue_work(pciehp_wq, &info->work); + queue_work(p_slot->wq, &info->work); out: mutex_unlock(&p_slot->lock); } @@ -377,7 +377,7 @@ static void handle_button_press_event(struct slot *p_slot) if (ATTN_LED(ctrl)) pciehp_set_attention_status(p_slot, 0); - queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ); + queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); break; case BLINKINGOFF_STATE: case BLINKINGON_STATE: @@ -439,7 +439,7 @@ static void handle_surprise_event(struct slot *p_slot) else p_slot->state = POWERON_STATE; - queue_work(pciehp_wq, &info->work); + queue_work(p_slot->wq, &info->work); } static void interrupt_event_handler(struct work_struct *work) diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 13b2eaf7ba4..5127f3f4182 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -773,23 +773,32 @@ static void pcie_shutdown_notification(struct controller *ctrl) static int pcie_init_slot(struct controller *ctrl) { struct slot *slot; + char name[32]; slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) return -ENOMEM; + snprintf(name, sizeof(name), "pciehp-%u", PSN(ctrl)); + slot->wq = alloc_workqueue(name, 0, 0); + if (!slot->wq) + goto abort; + slot->ctrl = ctrl; mutex_init(&slot->lock); INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); ctrl->slot = slot; return 0; +abort: + kfree(slot); + return -ENOMEM; } static void pcie_cleanup_slot(struct controller *ctrl) { struct slot *slot = ctrl->slot; cancel_delayed_work(&slot->work); - flush_workqueue(pciehp_wq); + destroy_workqueue(slot->wq); kfree(slot); } diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index ca64932e658..b849f995075 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -46,8 +46,6 @@ extern bool shpchp_poll_mode; extern int shpchp_poll_time; extern bool shpchp_debug; -extern struct workqueue_struct *shpchp_wq; -extern struct workqueue_struct *shpchp_ordered_wq; #define dbg(format, arg...) \ do { \ @@ -91,6 +89,7 @@ struct slot { struct list_head slot_list; struct delayed_work work; /* work for button event */ struct mutex lock; + struct workqueue_struct *wq; u8 hp_slot; }; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index b6de307248e..3100c52c837 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -39,8 +39,6 @@ bool shpchp_debug; bool shpchp_poll_mode; int shpchp_poll_time; -struct workqueue_struct *shpchp_wq; -struct workqueue_struct *shpchp_ordered_wq; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" @@ -129,6 +127,14 @@ static int init_slots(struct controller *ctrl) slot->device = ctrl->slot_device_offset + i; slot->hpc_ops = ctrl->hpc_ops; slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i); + + snprintf(name, sizeof(name), "shpchp-%d", slot->number); + slot->wq = alloc_workqueue(name, 0, 0); + if (!slot->wq) { + retval = -ENOMEM; + goto error_info; + } + mutex_init(&slot->lock); INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work); @@ -148,7 +154,7 @@ static int init_slots(struct controller *ctrl) if (retval) { ctrl_err(ctrl, "pci_hp_register failed with error %d\n", retval); - goto error_info; + goto error_slotwq; } get_power_status(hotplug_slot, &info->power_status); @@ -160,6 +166,8 @@ static int init_slots(struct controller *ctrl) } return 0; +error_slotwq: + destroy_workqueue(slot->wq); error_info: kfree(info); error_hpslot: @@ -180,8 +188,7 @@ void cleanup_slots(struct controller *ctrl) slot = list_entry(tmp, struct slot, slot_list); list_del(&slot->slot_list); cancel_delayed_work(&slot->work); - flush_workqueue(shpchp_wq); - flush_workqueue(shpchp_ordered_wq); + destroy_workqueue(slot->wq); pci_hp_deregister(slot->hotplug_slot); } } @@ -364,25 +371,12 @@ static struct pci_driver shpc_driver = { static int __init shpcd_init(void) { - int retval = 0; - - shpchp_wq = alloc_ordered_workqueue("shpchp", 0); - if (!shpchp_wq) - return -ENOMEM; - - shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0); - if (!shpchp_ordered_wq) { - destroy_workqueue(shpchp_wq); - return -ENOMEM; - } + int retval; retval = pci_register_driver(&shpc_driver); dbg("%s: pci_register_driver = %d\n", __func__, retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - if (retval) { - destroy_workqueue(shpchp_ordered_wq); - destroy_workqueue(shpchp_wq); - } + return retval; } @@ -390,8 +384,6 @@ static void __exit shpcd_cleanup(void) { dbg("unload_shpchpd()\n"); pci_unregister_driver(&shpc_driver); - destroy_workqueue(shpchp_ordered_wq); - destroy_workqueue(shpchp_wq); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index f9b5a52e411..58499277903 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -51,7 +51,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) info->p_slot = p_slot; INIT_WORK(&info->work, interrupt_event_handler); - queue_work(shpchp_wq, &info->work); + queue_work(p_slot->wq, &info->work); return 0; } @@ -453,7 +453,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work) kfree(info); goto out; } - queue_work(shpchp_ordered_wq, &info->work); + queue_work(p_slot->wq, &info->work); out: mutex_unlock(&p_slot->lock); } @@ -501,7 +501,7 @@ static void handle_button_press_event(struct slot *p_slot) p_slot->hpc_ops->green_led_blink(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); - queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ); + queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); break; case BLINKINGOFF_STATE: case BLINKINGON_STATE: diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index bafd2bbcaf6..c18e5bf444f 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -739,7 +739,7 @@ EXPORT_SYMBOL_GPL(pci_num_vf); /** * pci_sriov_set_totalvfs -- reduce the TotalVFs available * @dev: the PCI PF device - * numvfs: number that should be used for TotalVFs supported + * @numvfs: number that should be used for TotalVFs supported * * Should be called from PF driver's probe routine with * device's mutex held. diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index 6c8bc580978..fde4a32a029 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig @@ -82,4 +82,4 @@ endchoice config PCIE_PME def_bool y - depends on PCIEPORTBUS && PM_RUNTIME && EXPERIMENTAL && ACPI + depends on PCIEPORTBUS && PM_RUNTIME && ACPI diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 421bbc5fee3..564d97f94b6 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -630,6 +630,7 @@ static void aer_recover_work_func(struct work_struct *work) continue; } do_recovery(pdev, entry.severity); + pci_dev_put(pdev); } } #endif diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index b52630b8ead..8474b6a4fc9 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -771,6 +771,9 @@ void pcie_clear_aspm(struct pci_bus *bus) { struct pci_dev *child; + if (aspm_force) + return; + /* * Clear any ASPM setup that the firmware has carried out on this bus */ diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 06f4eb7ab87..afed7018a2b 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -125,8 +125,11 @@ static const struct key_entry acer_wmi_keymap[] = { {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} }, {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */ {KE_IGNORE, 0x81, {KEY_SLEEP} }, - {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad On/Off */ + {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad Toggle */ + {KE_KEY, KEY_TOUCHPAD_ON, {KEY_TOUCHPAD_ON} }, + {KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} }, {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} }, + {KE_KEY, 0x85, {KEY_TOUCHPAD_TOGGLE} }, {KE_END, 0} }; @@ -147,6 +150,7 @@ struct event_return_value { #define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */ #define ACER_WMID3_GDS_WIMAX (1<<7) /* WiMAX */ #define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */ +#define ACER_WMID3_GDS_TOUCHPAD (1<<1) /* Touchpad */ struct lm_input_params { u8 function_num; /* Function Number */ @@ -875,7 +879,7 @@ WMI_execute_u32(u32 method_id, u32 in, u32 *out) struct acpi_buffer input = { (acpi_size) sizeof(u32), (void *)(&in) }; struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; - u32 tmp; + u32 tmp = 0; acpi_status status; status = wmi_evaluate_method(WMID_GUID1, 1, method_id, &input, &result); @@ -884,14 +888,14 @@ WMI_execute_u32(u32 method_id, u32 in, u32 *out) return status; obj = (union acpi_object *) result.pointer; - if (obj && obj->type == ACPI_TYPE_BUFFER && - (obj->buffer.length == sizeof(u32) || - obj->buffer.length == sizeof(u64))) { - tmp = *((u32 *) obj->buffer.pointer); - } else if (obj->type == ACPI_TYPE_INTEGER) { - tmp = (u32) obj->integer.value; - } else { - tmp = 0; + if (obj) { + if (obj->type == ACPI_TYPE_BUFFER && + (obj->buffer.length == sizeof(u32) || + obj->buffer.length == sizeof(u64))) { + tmp = *((u32 *) obj->buffer.pointer); + } else if (obj->type == ACPI_TYPE_INTEGER) { + tmp = (u32) obj->integer.value; + } } if (out) @@ -1193,12 +1197,14 @@ static acpi_status WMID_set_capabilities(void) return status; obj = (union acpi_object *) out.pointer; - if (obj && obj->type == ACPI_TYPE_BUFFER && - (obj->buffer.length == sizeof(u32) || - obj->buffer.length == sizeof(u64))) { - devices = *((u32 *) obj->buffer.pointer); - } else if (obj->type == ACPI_TYPE_INTEGER) { - devices = (u32) obj->integer.value; + if (obj) { + if (obj->type == ACPI_TYPE_BUFFER && + (obj->buffer.length == sizeof(u32) || + obj->buffer.length == sizeof(u64))) { + devices = *((u32 *) obj->buffer.pointer); + } else if (obj->type == ACPI_TYPE_INTEGER) { + devices = (u32) obj->integer.value; + } } else { kfree(out.pointer); return AE_ERROR; @@ -1676,6 +1682,7 @@ static void acer_wmi_notify(u32 value, void *context) acpi_status status; u16 device_state; const struct key_entry *key; + u32 scancode; status = wmi_get_event_data(value, &response); if (status != AE_OK) { @@ -1712,6 +1719,7 @@ static void acer_wmi_notify(u32 value, void *context) pr_warn("Unknown key number - 0x%x\n", return_value.key_num); } else { + scancode = return_value.key_num; switch (key->keycode) { case KEY_WLAN: case KEY_BLUETOOTH: @@ -1725,9 +1733,11 @@ static void acer_wmi_notify(u32 value, void *context) rfkill_set_sw_state(bluetooth_rfkill, !(device_state & ACER_WMID3_GDS_BLUETOOTH)); break; + case KEY_TOUCHPAD_TOGGLE: + scancode = (device_state & ACER_WMID3_GDS_TOUCHPAD) ? + KEY_TOUCHPAD_ON : KEY_TOUCHPAD_OFF; } - sparse_keymap_report_entry(acer_wmi_input_dev, key, - 1, true); + sparse_keymap_report_event(acer_wmi_input_dev, scancode, 1, true); } break; case WMID_ACCEL_EVENT: @@ -1946,12 +1956,14 @@ static u32 get_wmid_devices(void) return 0; obj = (union acpi_object *) out.pointer; - if (obj && obj->type == ACPI_TYPE_BUFFER && - (obj->buffer.length == sizeof(u32) || - obj->buffer.length == sizeof(u64))) { - devices = *((u32 *) obj->buffer.pointer); - } else if (obj->type == ACPI_TYPE_INTEGER) { - devices = (u32) obj->integer.value; + if (obj) { + if (obj->type == ACPI_TYPE_BUFFER && + (obj->buffer.length == sizeof(u32) || + obj->buffer.length == sizeof(u64))) { + devices = *((u32 *) obj->buffer.pointer); + } else if (obj->type == ACPI_TYPE_INTEGER) { + devices = (u32) obj->integer.value; + } } kfree(out.pointer); diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index ec1d3bc2dbe..fcde4e52881 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -860,8 +860,10 @@ static ssize_t show_infos(struct device *dev, /* * The HWRS method return informations about the hardware. * 0x80 bit is for WLAN, 0x100 for Bluetooth. + * 0x40 for WWAN, 0x10 for WIMAX. * The significance of others is yet to be found. - * If we don't find the method, we assume the device are present. + * We don't currently use this for device detection, and it + * takes several seconds to run on some systems. */ rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp); if (!ACPI_FAILURE(rv)) @@ -1682,7 +1684,7 @@ static int asus_laptop_get_info(struct asus_laptop *asus) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *model = NULL; - unsigned long long bsts_result, hwrs_result; + unsigned long long bsts_result; char *string = NULL; acpi_status status; @@ -1741,20 +1743,9 @@ static int asus_laptop_get_info(struct asus_laptop *asus) return -ENOMEM; } - if (*string) + if (string) pr_notice(" %s model detected\n", string); - /* - * The HWRS method return informations about the hardware. - * 0x80 bit is for WLAN, 0x100 for Bluetooth, - * 0x40 for WWAN, 0x10 for WIMAX. - * The significance of others is yet to be found. - */ - status = - acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result); - if (!ACPI_FAILURE(status)) - pr_notice(" HWRS returned %x", (int)hwrs_result); - if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) asus->have_rsts = true; diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index dd90d15f521..71623a2ff3e 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c @@ -1523,6 +1523,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { }, .driver_data = &samsung_broken_acpi_video, }, + { + .callback = samsung_dmi_matched, + .ident = "N250P", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "N250P"), + DMI_MATCH(DMI_BOARD_NAME, "N250P"), + }, + .driver_data = &samsung_broken_acpi_video, + }, { }, }; MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index daaddec68de..b8ad71f7863 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -786,28 +786,29 @@ static int sony_nc_int_call(acpi_handle handle, char *name, int *value, static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, void *buffer, size_t buflen) { + int ret = 0; size_t len = len; union acpi_object *object = __call_snc_method(handle, name, value); if (!object) return -EINVAL; - if (object->type == ACPI_TYPE_BUFFER) + if (object->type == ACPI_TYPE_BUFFER) { len = MIN(buflen, object->buffer.length); + memcpy(buffer, object->buffer.pointer, len); - else if (object->type == ACPI_TYPE_INTEGER) + } else if (object->type == ACPI_TYPE_INTEGER) { len = MIN(buflen, sizeof(object->integer.value)); + memcpy(buffer, &object->integer.value, len); - else { + } else { pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", ACPI_TYPE_BUFFER, object->type); - kfree(object); - return -EINVAL; + ret = -EINVAL; } - memcpy(buffer, object->buffer.pointer, len); kfree(object); - return 0; + return ret; } struct sony_nc_handles { diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 0f65b246cc0..278584302f2 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1885,9 +1885,15 @@ int regulator_can_change_voltage(struct regulator *regulator) struct regulator_dev *rdev = regulator->rdev; if (rdev->constraints && - rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE && - (rdev->desc->n_voltages - rdev->desc->linear_min_sel) > 1) - return 1; + (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { + if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1) + return 1; + + if (rdev->desc->continuous_voltage_range && + rdev->constraints->min_uV && rdev->constraints->max_uV && + rdev->constraints->min_uV != rdev->constraints->max_uV) + return 1; + } return 0; } @@ -3315,7 +3321,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) * @config: runtime configuration for regulator * * Called by regulator drivers to register a regulator. - * Returns 0 on success. + * Returns a valid pointer to struct regulator_dev on success + * or an ERR_PTR() on error. */ struct regulator_dev * regulator_register(const struct regulator_desc *regulator_desc, diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index df0eafb0dc7..02be7fcae32 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -71,26 +71,26 @@ struct voltage_map_desc { int step; }; -/* Voltage maps in mV */ +/* Voltage maps in uV */ static const struct voltage_map_desc ldo_voltage_map_desc = { - .min = 800, .max = 3950, .step = 50, + .min = 800000, .max = 3950000, .step = 50000, }; /* LDO1 ~ 18, 21 all */ static const struct voltage_map_desc buck1245_voltage_map_desc = { - .min = 650, .max = 2225, .step = 25, + .min = 650000, .max = 2225000, .step = 25000, }; /* Buck1, 2, 4, 5 */ static const struct voltage_map_desc buck37_voltage_map_desc = { - .min = 750, .max = 3900, .step = 50, + .min = 750000, .max = 3900000, .step = 50000, }; /* Buck3, 7 */ -/* current map in mA */ +/* current map in uA */ static const struct voltage_map_desc charger_current_map_desc = { - .min = 200, .max = 950, .step = 50, + .min = 200000, .max = 950000, .step = 50000, }; static const struct voltage_map_desc topoff_current_map_desc = { - .min = 50, .max = 200, .step = 10, + .min = 50000, .max = 200000, .step = 10000, }; static const struct voltage_map_desc *reg_voltage_map[] = { @@ -194,7 +194,7 @@ static int max8997_list_voltage(struct regulator_dev *rdev, if (val > desc->max) return -EINVAL; - return val * 1000; + return val; } static int max8997_get_enable_register(struct regulator_dev *rdev, @@ -485,7 +485,6 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, { struct max8997_data *max8997 = rdev_get_drvdata(rdev); struct i2c_client *i2c = max8997->iodev->i2c; - int min_vol = min_uV / 1000, max_vol = max_uV / 1000; const struct voltage_map_desc *desc; int rid = rdev_get_id(rdev); int i, reg, shift, mask, ret; @@ -509,7 +508,7 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, desc = reg_voltage_map[rid]; - i = max8997_get_voltage_proper_val(desc, min_vol, max_vol); + i = max8997_get_voltage_proper_val(desc, min_uV, max_uV); if (i < 0) return i; @@ -557,7 +556,7 @@ static int max8997_set_voltage_ldobuck_time_sel(struct regulator_dev *rdev, case MAX8997_BUCK4: case MAX8997_BUCK5: return DIV_ROUND_UP(desc->step * (new_selector - old_selector), - max8997->ramp_delay); + max8997->ramp_delay * 1000); } return 0; @@ -656,7 +655,6 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev, const struct voltage_map_desc *desc; int new_val, new_idx, damage, tmp_val, tmp_idx, tmp_dmg; bool gpio_dvs_mode = false; - int min_vol = min_uV / 1000, max_vol = max_uV / 1000; if (rid < MAX8997_BUCK1 || rid > MAX8997_BUCK7) return -EINVAL; @@ -681,7 +679,7 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev, selector); desc = reg_voltage_map[rid]; - new_val = max8997_get_voltage_proper_val(desc, min_vol, max_vol); + new_val = max8997_get_voltage_proper_val(desc, min_uV, max_uV); if (new_val < 0) return new_val; @@ -1123,8 +1121,8 @@ static int max8997_pmic_probe(struct platform_device *pdev) max8997->buck1_vol[i] = ret = max8997_get_voltage_proper_val( &buck1245_voltage_map_desc, - pdata->buck1_voltage[i] / 1000, - pdata->buck1_voltage[i] / 1000 + + pdata->buck1_voltage[i], + pdata->buck1_voltage[i] + buck1245_voltage_map_desc.step); if (ret < 0) goto err_out; @@ -1132,8 +1130,8 @@ static int max8997_pmic_probe(struct platform_device *pdev) max8997->buck2_vol[i] = ret = max8997_get_voltage_proper_val( &buck1245_voltage_map_desc, - pdata->buck2_voltage[i] / 1000, - pdata->buck2_voltage[i] / 1000 + + pdata->buck2_voltage[i], + pdata->buck2_voltage[i] + buck1245_voltage_map_desc.step); if (ret < 0) goto err_out; @@ -1141,8 +1139,8 @@ static int max8997_pmic_probe(struct platform_device *pdev) max8997->buck5_vol[i] = ret = max8997_get_voltage_proper_val( &buck1245_voltage_map_desc, - pdata->buck5_voltage[i] / 1000, - pdata->buck5_voltage[i] / 1000 + + pdata->buck5_voltage[i], + pdata->buck5_voltage[i] + buck1245_voltage_map_desc.step); if (ret < 0) goto err_out; diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index b821d08eb64..1f0df4046b8 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -51,39 +51,39 @@ struct voltage_map_desc { int step; }; -/* Voltage maps */ +/* Voltage maps in uV*/ static const struct voltage_map_desc ldo23_voltage_map_desc = { - .min = 800, .step = 50, .max = 1300, + .min = 800000, .step = 50000, .max = 1300000, }; static const struct voltage_map_desc ldo456711_voltage_map_desc = { - .min = 1600, .step = 100, .max = 3600, + .min = 1600000, .step = 100000, .max = 3600000, }; static const struct voltage_map_desc ldo8_voltage_map_desc = { - .min = 3000, .step = 100, .max = 3600, + .min = 3000000, .step = 100000, .max = 3600000, }; static const struct voltage_map_desc ldo9_voltage_map_desc = { - .min = 2800, .step = 100, .max = 3100, + .min = 2800000, .step = 100000, .max = 3100000, }; static const struct voltage_map_desc ldo10_voltage_map_desc = { - .min = 950, .step = 50, .max = 1300, + .min = 95000, .step = 50000, .max = 1300000, }; static const struct voltage_map_desc ldo1213_voltage_map_desc = { - .min = 800, .step = 100, .max = 3300, + .min = 800000, .step = 100000, .max = 3300000, }; static const struct voltage_map_desc ldo1415_voltage_map_desc = { - .min = 1200, .step = 100, .max = 3300, + .min = 1200000, .step = 100000, .max = 3300000, }; static const struct voltage_map_desc ldo1617_voltage_map_desc = { - .min = 1600, .step = 100, .max = 3600, + .min = 1600000, .step = 100000, .max = 3600000, }; static const struct voltage_map_desc buck12_voltage_map_desc = { - .min = 750, .step = 25, .max = 1525, + .min = 750000, .step = 25000, .max = 1525000, }; static const struct voltage_map_desc buck3_voltage_map_desc = { - .min = 1600, .step = 100, .max = 3600, + .min = 1600000, .step = 100000, .max = 3600000, }; static const struct voltage_map_desc buck4_voltage_map_desc = { - .min = 800, .step = 100, .max = 2300, + .min = 800000, .step = 100000, .max = 2300000, }; static const struct voltage_map_desc *ldo_voltage_map[] = { @@ -445,9 +445,9 @@ static int max8998_set_voltage_buck_time_sel(struct regulator_dev *rdev, if (max8998->iodev->type == TYPE_MAX8998 && !(val & MAX8998_ENRAMP)) return 0; - difference = (new_selector - old_selector) * desc->step; + difference = (new_selector - old_selector) * desc->step / 1000; if (difference > 0) - return difference / ((val & 0x0f) + 1); + return DIV_ROUND_UP(difference, (val & 0x0f) + 1); return 0; } @@ -702,7 +702,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) i = 0; while (buck12_voltage_map_desc.min + buck12_voltage_map_desc.step*i - < (pdata->buck1_voltage1 / 1000)) + < pdata->buck1_voltage1) i++; max8998->buck1_vol[0] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); @@ -713,7 +713,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) i = 0; while (buck12_voltage_map_desc.min + buck12_voltage_map_desc.step*i - < (pdata->buck1_voltage2 / 1000)) + < pdata->buck1_voltage2) i++; max8998->buck1_vol[1] = i; @@ -725,7 +725,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) i = 0; while (buck12_voltage_map_desc.min + buck12_voltage_map_desc.step*i - < (pdata->buck1_voltage3 / 1000)) + < pdata->buck1_voltage3) i++; max8998->buck1_vol[2] = i; @@ -737,7 +737,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) i = 0; while (buck12_voltage_map_desc.min + buck12_voltage_map_desc.step*i - < (pdata->buck1_voltage4 / 1000)) + < pdata->buck1_voltage4) i++; max8998->buck1_vol[3] = i; @@ -763,7 +763,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) i = 0; while (buck12_voltage_map_desc.min + buck12_voltage_map_desc.step*i - < (pdata->buck2_voltage1 / 1000)) + < pdata->buck2_voltage1) i++; max8998->buck2_vol[0] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); @@ -774,7 +774,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) i = 0; while (buck12_voltage_map_desc.min + buck12_voltage_map_desc.step*i - < (pdata->buck2_voltage2 / 1000)) + < pdata->buck2_voltage2) i++; max8998->buck2_vol[1] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); @@ -792,8 +792,8 @@ static int max8998_pmic_probe(struct platform_device *pdev) int count = (desc->max - desc->min) / desc->step + 1; regulators[index].n_voltages = count; - regulators[index].min_uV = desc->min * 1000; - regulators[index].uV_step = desc->step * 1000; + regulators[index].min_uV = desc->min; + regulators[index].uV_step = desc->step; } config.dev = max8998->dev; diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 9f991f2c525..33b65c9ad5d 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -214,7 +214,7 @@ static int s5m8767_reg_is_enabled(struct regulator_dev *rdev) struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); int ret, reg; int mask = 0xc0, enable_ctrl; - u8 val; + unsigned int val; ret = s5m8767_get_register(rdev, ®, &enable_ctrl); if (ret == -EINVAL) @@ -306,7 +306,7 @@ static int s5m8767_get_voltage_sel(struct regulator_dev *rdev) struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); int reg, mask, ret; int reg_id = rdev_get_id(rdev); - u8 val; + unsigned int val; ret = s5m8767_get_voltage_register(rdev, ®); if (ret) diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c index 96bafc5c3bf..8f0dcfedb83 100644 --- a/drivers/rtc/rtc-da9055.c +++ b/drivers/rtc/rtc-da9055.c @@ -227,7 +227,7 @@ static const struct rtc_class_ops da9055_rtc_ops = { .alarm_irq_enable = da9055_rtc_alarm_irq_enable, }; -static int __init da9055_rtc_device_init(struct da9055 *da9055, +static int da9055_rtc_device_init(struct da9055 *da9055, struct da9055_pdata *pdata) { int ret; diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 9bd5da36f99..704488d0f81 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -248,7 +248,7 @@ static void dasd_ext_handler(struct ext_code ext_code, default: return; } - kstat_cpu(smp_processor_id()).irqs[EXTINT_DSD]++; + inc_irq_stat(IRQEXT_DSD); if (!ip) { /* no intparm: unsolicited interrupt */ DBF_EVENT(DBF_NOTICE, "%s", "caught unsolicited " "interrupt"); diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 806fe912d6e..e37bc1620d1 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -4274,7 +4274,7 @@ static struct ccw_driver dasd_eckd_driver = { .thaw = dasd_generic_restore_device, .restore = dasd_generic_restore_device, .uc_handler = dasd_generic_uc_handler, - .int_class = IOINT_DAS, + .int_class = IRQIO_DAS, }; /* diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index eb748507c7f..41469858434 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -78,7 +78,7 @@ static struct ccw_driver dasd_fba_driver = { .freeze = dasd_generic_pm_freeze, .thaw = dasd_generic_restore_device, .restore = dasd_generic_restore_device, - .int_class = IOINT_DAS, + .int_class = IRQIO_DAS, }; static void diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 40084501c31..33b7141a182 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -44,6 +44,7 @@ #define RAW3215_NR_CCWS 3 #define RAW3215_TIMEOUT HZ/10 /* time for delayed output */ +#define RAW3215_FIXED 1 /* 3215 console device is not be freed */ #define RAW3215_WORKING 4 /* set if a request is being worked on */ #define RAW3215_THROTTLED 8 /* set if reading is disabled */ #define RAW3215_STOPPED 16 /* set if writing is disabled */ @@ -630,7 +631,8 @@ static void raw3215_shutdown(struct raw3215_info *raw) DECLARE_WAITQUEUE(wait, current); unsigned long flags; - if (!(raw->port.flags & ASYNC_INITIALIZED)) + if (!(raw->port.flags & ASYNC_INITIALIZED) || + (raw->flags & RAW3215_FIXED)) return; /* Wait for outstanding requests, then free irq */ spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); @@ -805,7 +807,7 @@ static struct ccw_driver raw3215_ccw_driver = { .freeze = &raw3215_pm_stop, .thaw = &raw3215_pm_start, .restore = &raw3215_pm_start, - .int_class = IOINT_C15, + .int_class = IRQIO_C15, }; #ifdef CONFIG_TN3215_CONSOLE @@ -927,6 +929,8 @@ static int __init con3215_init(void) dev_set_drvdata(&cdev->dev, raw); cdev->handler = raw3215_irq; + raw->flags |= RAW3215_FIXED; + /* Request the console irq */ if (raw3215_startup(raw) != 0) { raw3215_free_info(raw); diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index f3b8bb84faf..9a6c140c5f0 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -1396,7 +1396,7 @@ static struct ccw_driver raw3270_ccw_driver = { .freeze = &raw3270_pm_stop, .thaw = &raw3270_pm_start, .restore = &raw3270_pm_start, - .int_class = IOINT_C70, + .int_class = IRQIO_C70, }; static int diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 4fa21f7e230..12c16a65dd2 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -400,7 +400,7 @@ static void sclp_interrupt_handler(struct ext_code ext_code, u32 finished_sccb; u32 evbuf_pending; - kstat_cpu(smp_processor_id()).irqs[EXTINT_SCP]++; + inc_irq_stat(IRQEXT_SCP); spin_lock(&sclp_lock); finished_sccb = param32 & 0xfffffff8; evbuf_pending = param32 & 0x3; @@ -813,7 +813,7 @@ static void sclp_check_handler(struct ext_code ext_code, { u32 finished_sccb; - kstat_cpu(smp_processor_id()).irqs[EXTINT_SCP]++; + inc_irq_stat(IRQEXT_SCP); finished_sccb = param32 & 0xfffffff8; /* Is this the interrupt we are waiting for? */ if (finished_sccb == 0) diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 6ae929c024a..9aa79702b37 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c @@ -1193,7 +1193,7 @@ static struct ccw_driver tape_34xx_driver = { .set_online = tape_34xx_online, .set_offline = tape_generic_offline, .freeze = tape_generic_pm_suspend, - .int_class = IOINT_TAP, + .int_class = IRQIO_TAP, }; static int diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 1b0eb49f739..327cb19ad0b 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c @@ -1656,7 +1656,7 @@ static struct ccw_driver tape_3590_driver = { .set_offline = tape_generic_offline, .set_online = tape_3590_online, .freeze = tape_generic_pm_suspend, - .int_class = IOINT_TAP, + .int_class = IRQIO_TAP, }; /* diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index 73bef0bd394..483f72ba030 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c @@ -74,7 +74,7 @@ static struct ccw_driver ur_driver = { .set_online = ur_set_online, .set_offline = ur_set_offline, .freeze = ur_pm_suspend, - .int_class = IOINT_VMR, + .int_class = IRQIO_VMR, }; static DEFINE_MUTEX(vmur_mutex); diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 68e80e2734a..10729bbcece 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -283,7 +283,7 @@ struct chsc_sei_nt2_area { u8 ccdf[PAGE_SIZE - 24 - 56]; /* content-code dependent field */ } __packed; -#define CHSC_SEI_NT0 0ULL +#define CHSC_SEI_NT0 (1ULL << 63) #define CHSC_SEI_NT2 (1ULL << 61) struct chsc_sei { @@ -291,7 +291,8 @@ struct chsc_sei { u32 reserved1; u64 ntsm; /* notification type mask */ struct chsc_header response; - u32 reserved2; + u32 :24; + u8 nt; union { struct chsc_sei_nt0_area nt0_area; struct chsc_sei_nt2_area nt2_area; @@ -496,17 +497,17 @@ static int __chsc_process_crw(struct chsc_sei *sei, u64 ntsm) css_schedule_eval_all(); } - switch (sei->ntsm) { - case CHSC_SEI_NT0: + switch (sei->nt) { + case 0: chsc_process_sei_nt0(&sei->u.nt0_area); - return 1; - case CHSC_SEI_NT2: + break; + case 2: chsc_process_sei_nt2(&sei->u.nt2_area); - return 1; + break; default: - CIO_CRW_EVENT(2, "chsc: unhandled nt (nt=%08Lx)\n", - sei->ntsm); - return 0; + CIO_CRW_EVENT(2, "chsc: unhandled nt=%d\n", + sei->nt); + break; } } else { CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n", @@ -537,15 +538,7 @@ static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow) sei = sei_page; CIO_TRACE_EVENT(2, "prcss"); - - /* - * The ntsm does not allow to select NT0 and NT2 together. We need to - * first check for NT2, than additionally for NT0... - */ -#ifdef CONFIG_PCI - if (!__chsc_process_crw(sei, CHSC_SEI_NT2)) -#endif - __chsc_process_crw(sei, CHSC_SEI_NT0); + __chsc_process_crw(sei, CHSC_SEI_NT0 | CHSC_SEI_NT2); } void chsc_chp_online(struct chp_id chpid) diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 8f9a1a38449..facdf809113 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c @@ -58,7 +58,7 @@ static void chsc_subchannel_irq(struct subchannel *sch) CHSC_LOG(4, "irb"); CHSC_LOG_HEX(4, irb, sizeof(*irb)); - kstat_cpu(smp_processor_id()).irqs[IOINT_CSC]++; + inc_irq_stat(IRQIO_CSC); /* Copy irb to provided request and set done. */ if (!request) { diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 8e927b9f285..c8faf6230b0 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -611,7 +611,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs) tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id; irb = (struct irb *)&S390_lowcore.irb; do { - kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++; + kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL); if (tpi_info->adapter_IO) { do_adapter_IO(tpi_info->isc); continue; @@ -619,7 +619,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs) sch = (struct subchannel *)(unsigned long)tpi_info->intparm; if (!sch) { /* Clear pending interrupt condition. */ - kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; + inc_irq_stat(IRQIO_CIO); tsch(tpi_info->schid, irb); continue; } @@ -633,9 +633,9 @@ void __irq_entry do_IRQ(struct pt_regs *regs) if (sch->driver && sch->driver->irq) sch->driver->irq(sch); else - kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; + inc_irq_stat(IRQIO_CIO); } else - kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; + inc_irq_stat(IRQIO_CIO); spin_unlock(sch->lock); /* * Are more interrupts pending? @@ -678,7 +678,7 @@ static void cio_tsch(struct subchannel *sch) if (sch->driver && sch->driver->irq) sch->driver->irq(sch); else - kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; + inc_irq_stat(IRQIO_CIO); if (!irq_context) { irq_exit(); _local_bh_enable(); diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 6995cff4463..7cd5c6812ac 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -758,7 +758,7 @@ static int io_subchannel_initialize_dev(struct subchannel *sch, struct ccw_device *cdev) { cdev->private->cdev = cdev; - cdev->private->int_class = IOINT_CIO; + cdev->private->int_class = IRQIO_CIO; atomic_set(&cdev->private->onoff, 0); cdev->dev.parent = &sch->dev; cdev->dev.release = ccw_device_release; @@ -1023,7 +1023,7 @@ static void io_subchannel_irq(struct subchannel *sch) if (cdev) dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); else - kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; + inc_irq_stat(IRQIO_CIO); } void io_subchannel_init_config(struct subchannel *sch) @@ -1634,7 +1634,7 @@ ccw_device_probe_console(void) memset(&console_private, 0, sizeof(struct ccw_device_private)); console_cdev.private = &console_private; console_private.cdev = &console_cdev; - console_private.int_class = IOINT_CIO; + console_private.int_class = IRQIO_CIO; ret = ccw_device_console_enable(&console_cdev, sch); if (ret) { cio_release_console(); @@ -1715,13 +1715,13 @@ ccw_device_probe (struct device *dev) if (cdrv->int_class != 0) cdev->private->int_class = cdrv->int_class; else - cdev->private->int_class = IOINT_CIO; + cdev->private->int_class = IRQIO_CIO; ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV; if (ret) { cdev->drv = NULL; - cdev->private->int_class = IOINT_CIO; + cdev->private->int_class = IRQIO_CIO; return ret; } @@ -1755,7 +1755,7 @@ ccw_device_remove (struct device *dev) } ccw_device_set_timeout(cdev, 0); cdev->drv = NULL; - cdev->private->int_class = IOINT_CIO; + cdev->private->int_class = IRQIO_CIO; return 0; } diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 2e575cff984..7d4ecb65db0 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h @@ -61,11 +61,10 @@ dev_fsm_event(struct ccw_device *cdev, enum dev_event dev_event) if (dev_event == DEV_EVENT_INTERRUPT) { if (state == DEV_STATE_ONLINE) - kstat_cpu(smp_processor_id()). - irqs[cdev->private->int_class]++; + inc_irq_stat(cdev->private->int_class); else if (state != DEV_STATE_CMFCHANGE && state != DEV_STATE_CMFUPDATE) - kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; + inc_irq_stat(IRQIO_CIO); } dev_jumptable[state][dev_event](cdev, dev_event); } diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c index 6c967340046..d9eddcba7e8 100644 --- a/drivers/s390/cio/eadm_sch.c +++ b/drivers/s390/cio/eadm_sch.c @@ -139,7 +139,7 @@ static void eadm_subchannel_irq(struct subchannel *sch) EADM_LOG(6, "irq"); EADM_LOG_HEX(6, irb, sizeof(*irb)); - kstat_cpu(smp_processor_id()).irqs[IOINT_ADM]++; + inc_irq_stat(IRQIO_ADM); if ((scsw->stctl & (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)) && scsw->eswf == 1 && irb->esw.eadm.erw.r) diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index bdb394b066f..bde5255200d 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -182,7 +182,7 @@ static void tiqdio_thinint_handler(void *alsi, void *data) struct qdio_q *q; last_ai_time = S390_lowcore.int_clock; - kstat_cpu(smp_processor_id()).irqs[IOINT_QAI]++; + inc_irq_stat(IRQIO_QAI); /* protect tiq_list entries, only changed in activate or shutdown */ rcu_read_lock(); diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 7b865a7300e..b8b340ac533 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -1272,7 +1272,7 @@ out: static void ap_interrupt_handler(void *unused1, void *unused2) { - kstat_cpu(smp_processor_id()).irqs[IOINT_APB]++; + inc_irq_stat(IRQIO_APB); tasklet_schedule(&ap_tasklet); } diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 7dabef624da..8491111aec1 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c @@ -392,7 +392,7 @@ static void kvm_extint_handler(struct ext_code ext_code, if ((ext_code.subcode & 0xff00) != VIRTIO_SUBCODE_64) return; - kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++; + inc_irq_stat(IRQEXT_VRT); /* The LSB might be overloaded, we have to mask it */ vq = (struct virtqueue *)(param64 & ~1UL); diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 5c70a659957..83bc9c5fa0c 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -282,7 +282,7 @@ static struct ccw_driver claw_ccw_driver = { .ids = claw_ids, .probe = ccwgroup_probe_ccwdev, .remove = ccwgroup_remove_ccwdev, - .int_class = IOINT_CLW, + .int_class = IRQIO_CLW, }; static ssize_t claw_driver_group_store(struct device_driver *ddrv, diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 817b68925dd..676f12049a3 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -1755,7 +1755,7 @@ static struct ccw_driver ctcm_ccw_driver = { .ids = ctcm_ids, .probe = ccwgroup_probe_ccwdev, .remove = ccwgroup_remove_ccwdev, - .int_class = IOINT_CTC, + .int_class = IRQIO_CTC, }; static struct ccwgroup_driver ctcm_group_driver = { diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 2ca0f1dd7a0..c645dc9e98a 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -2384,7 +2384,7 @@ static struct ccw_driver lcs_ccw_driver = { .ids = lcs_ids, .probe = ccwgroup_probe_ccwdev, .remove = ccwgroup_remove_ccwdev, - .int_class = IOINT_LCS, + .int_class = IRQIO_LCS, }; /** diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index 5aedcdf4ac5..1ebe67cd183 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c @@ -126,6 +126,12 @@ static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate) static int sh_clk_div_enable(struct clk *clk) { + if (clk->div_mask == SH_CLK_DIV6_MSK) { + int ret = sh_clk_div_set_rate(clk, clk->rate); + if (ret < 0) + return ret; + } + sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk); return 0; } diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 7de2a10213b..36eec320569 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -444,6 +444,7 @@ config COMEDI_ADQ12B config COMEDI_NI_AT_A2150 tristate "NI AT-A2150 ISA card support" + select COMEDI_FC depends on VIRT_TO_BUS ---help--- Enable support for National Instruments AT-A2150 cards diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index b7bba1790a2..9b038e4a7e7 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1549,6 +1549,9 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, if (cmd == COMEDI_DEVCONFIG) { rc = do_devconfig_ioctl(dev, (struct comedi_devconfig __user *)arg); + if (rc == 0) + /* Evade comedi_auto_unconfig(). */ + dev_file_info->hardware_device = NULL; goto done; } diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index fb3d09323ba..01de996239f 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -345,7 +345,7 @@ static int waveform_ai_cancel(struct comedi_device *dev, struct waveform_private *devpriv = dev->private; devpriv->timer_running = 0; - del_timer(&devpriv->timer); + del_timer_sync(&devpriv->timer); return 0; } diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index aaac0b2cc9e..fd1662b4175 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -963,7 +963,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_unipolar = 0, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 8, .caldac = {caldac_none}, .has_8255 = 0, @@ -982,7 +982,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_unipolar = 0, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 8, .caldac = {caldac_none}, .has_8255 = 0, @@ -1001,7 +1001,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_unipolar = 0, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 8, .caldac = {caldac_none}, .has_8255 = 0, @@ -1037,7 +1037,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_unipolar = 0, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 32, .caldac = {caldac_none}, .has_8255 = 0, @@ -1056,7 +1056,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_unipolar = 0, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 32, .caldac = {caldac_none}, .has_8255 = 0, @@ -1092,7 +1092,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_628x_ao, .reg_type = ni_reg_628x, .ao_unipolar = 1, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 8, .caldac = {caldac_none}, .has_8255 = 0, @@ -1111,7 +1111,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_628x_ao, .reg_type = ni_reg_628x, .ao_unipolar = 1, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 8, .caldac = {caldac_none}, .has_8255 = 0, @@ -1147,7 +1147,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_628x_ao, .reg_type = ni_reg_628x, .ao_unipolar = 1, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 32, .caldac = {caldac_none}, .has_8255 = 0, diff --git a/drivers/staging/fwserial/Kconfig b/drivers/staging/fwserial/Kconfig index 580406cb180..b2f8331e4ac 100644 --- a/drivers/staging/fwserial/Kconfig +++ b/drivers/staging/fwserial/Kconfig @@ -3,7 +3,9 @@ config FIREWIRE_SERIAL depends on FIREWIRE help This enables TTY over IEEE 1394, providing high-speed serial - connectivity to cabled peers. + connectivity to cabled peers. This driver implements a + ad-hoc transport protocol and is currently limited to + Linux-to-Linux communication. To compile this driver as a module, say M here: the module will be called firewire-serial. diff --git a/drivers/staging/fwserial/TODO b/drivers/staging/fwserial/TODO index 726900548ea..8dae8fb2522 100644 --- a/drivers/staging/fwserial/TODO +++ b/drivers/staging/fwserial/TODO @@ -1,5 +1,5 @@ -TODOs ------ +TODOs prior to this driver moving out of staging +------------------------------------------------ 1. Implement retries for RCODE_BUSY, RCODE_NO_ACK and RCODE_SEND_ERROR - I/O is handled asynchronously which presents some issues when error conditions occur. @@ -11,17 +11,9 @@ TODOs -- Issues with firewire stack -- 1. This driver uses the same unregistered vendor id that the firewire core does (0xd00d1e). Perhaps this could be exposed as a define in - firewire-constants.h? -2. MAX_ASYNC_PAYLOAD needs to be publicly exposed by core/ohci - - otherwise how will this driver know the max size of address window to - open for one packet write? + firewire.h? 3. Maybe device_max_receive() and link_speed_to_max_payload() should be taken up by the firewire core? -4. To avoid dropping rx data while still limiting the maximum buffering, - the size of the AR context must be known. How to expose this to drivers? -5. Explore if bigger AR context will reduce RCODE_BUSY responses - (or auto-grow to certain max size -- but this would require major surgery - as the current AR is contiguously mapped) -- Issues with TTY core -- 1. Hack for alternate device name scheme diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index 61ee29083b2..d03a7f57e8d 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -179,7 +179,7 @@ static void dump_profile(struct seq_file *m, struct stats *stats) /* Returns the max receive packet size for the given card */ static inline int device_max_receive(struct fw_device *fw_device) { - return 1 << (clamp_t(int, fw_device->max_rec, 8U, 13U) + 1); + return 1 << (clamp_t(int, fw_device->max_rec, 8U, 11U) + 1); } static void fwtty_log_tx_error(struct fwtty_port *port, int rcode) diff --git a/drivers/staging/fwserial/fwserial.h b/drivers/staging/fwserial/fwserial.h index 8b572edf956..caa1c1ea82d 100644 --- a/drivers/staging/fwserial/fwserial.h +++ b/drivers/staging/fwserial/fwserial.h @@ -374,10 +374,10 @@ static inline void fwtty_bind_console(struct fwtty_port *port, */ static inline int link_speed_to_max_payload(unsigned speed) { - static const int max_async[] = { 307, 614, 1229, 2458, 4916, 9832, }; - BUILD_BUG_ON(ARRAY_SIZE(max_async) - 1 != SCODE_3200); + static const int max_async[] = { 307, 614, 1229, 2458, }; + BUILD_BUG_ON(ARRAY_SIZE(max_async) - 1 != SCODE_800); - speed = clamp(speed, (unsigned) SCODE_100, (unsigned) SCODE_3200); + speed = clamp(speed, (unsigned) SCODE_100, (unsigned) SCODE_800); if (limit_bw) return max_async[speed]; else diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index fb31b457a56..c5ceb9d90ea 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -239,7 +239,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p) struct mxs_lradc *lradc = iio_priv(iio); const uint32_t chan_value = LRADC_CH_ACCUMULATE | ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); - int i, j = 0; + unsigned int i, j = 0; for_each_set_bit(i, iio->active_scan_mask, iio->masklength) { lradc->buffer[j] = readl(lradc->base + LRADC_CH(j)); diff --git a/drivers/staging/iio/gyro/Kconfig b/drivers/staging/iio/gyro/Kconfig index ea295b25308..87979a0d03a 100644 --- a/drivers/staging/iio/gyro/Kconfig +++ b/drivers/staging/iio/gyro/Kconfig @@ -27,8 +27,8 @@ config ADIS16130 config ADIS16260 tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver" depends on SPI - select IIO_TRIGGER if IIO_BUFFER - select IIO_SW_RING if IIO_BUFFER + select IIO_ADIS_LIB + select IIO_ADIS_LIB_BUFFER if IIO_BUFFER help Say yes here to build support for Analog Devices ADIS16260 ADIS16265 ADIS16250 ADIS16255 and ADIS16251 programmable digital gyroscope sensors. diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c index 3525a68d6a7..41d7350d030 100644 --- a/drivers/staging/iio/gyro/adis16080_core.c +++ b/drivers/staging/iio/gyro/adis16080_core.c @@ -69,7 +69,7 @@ static int adis16080_spi_read(struct iio_dev *indio_dev, ret = spi_read(st->us, st->buf, 2); if (ret == 0) - *val = ((st->buf[0] & 0xF) << 8) | st->buf[1]; + *val = sign_extend32(((st->buf[0] & 0xF) << 8) | st->buf[1], 11); mutex_unlock(&st->buf_lock); return ret; diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index ecf0f44bc70..cec19f1cf56 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -584,7 +584,6 @@ int imx_drm_add_encoder(struct drm_encoder *encoder, ret = imx_drm_encoder_register(imx_drm_encoder); if (ret) { - kfree(imx_drm_encoder); ret = -ENOMEM; goto err_register; } diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c index 677e665ca86..f7059cddd7f 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c @@ -1104,7 +1104,9 @@ static int ipu_probe(struct platform_device *pdev) if (ret) goto out_failed_irq; - ipu_reset(ipu); + ret = ipu_reset(ipu); + if (ret) + goto out_failed_reset; /* Set MCU_T to divide MCU access window into 2 */ ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18), @@ -1129,6 +1131,7 @@ failed_add_clients: ipu_submodules_exit(ipu); failed_submodules_init: ipu_irq_exit(ipu); +out_failed_reset: out_failed_irq: clk_disable_unprepare(ipu->clk); failed_clk_get: diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c index 1892006526b..4b3a019409b 100644 --- a/drivers/staging/imx-drm/ipuv3-crtc.c +++ b/drivers/staging/imx-drm/ipuv3-crtc.c @@ -452,7 +452,7 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc, int ret; ipu_crtc->ipu_ch = ipu_idmac_get(ipu, pdata->dma[0]); - if (IS_ERR_OR_NULL(ipu_crtc->ipu_ch)) { + if (IS_ERR(ipu_crtc->ipu_ch)) { ret = PTR_ERR(ipu_crtc->ipu_ch); goto err_out; } @@ -472,7 +472,7 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc, if (pdata->dp >= 0) { ipu_crtc->dp = ipu_dp_get(ipu, pdata->dp); if (IS_ERR(ipu_crtc->dp)) { - ret = PTR_ERR(ipu_crtc->ipu_ch); + ret = PTR_ERR(ipu_crtc->dp); goto err_out; } } @@ -548,6 +548,8 @@ static int ipu_drm_probe(struct platform_device *pdev) ipu_crtc->dev = &pdev->dev; ret = ipu_crtc_init(ipu_crtc, pdata); + if (ret) + return ret; platform_set_drvdata(pdev, ipu_crtc); diff --git a/drivers/staging/omapdrm/Makefile b/drivers/staging/omapdrm/Makefile index 1ca0e0016de..d85e058f284 100644 --- a/drivers/staging/omapdrm/Makefile +++ b/drivers/staging/omapdrm/Makefile @@ -5,6 +5,7 @@ ccflags-y := -Iinclude/drm -Werror omapdrm-y := omap_drv.o \ + omap_irq.o \ omap_debugfs.o \ omap_crtc.o \ omap_plane.o \ diff --git a/drivers/staging/omapdrm/TODO b/drivers/staging/omapdrm/TODO index 938c7888ca3..abeeb00aaa1 100644 --- a/drivers/staging/omapdrm/TODO +++ b/drivers/staging/omapdrm/TODO @@ -17,9 +17,6 @@ TODO . Revisit GEM sync object infrastructure.. TTM has some framework for this already. Possibly this could be refactored out and made more common? There should be some way to do this with less wheel-reinvention. -. Review DSS vs KMS mismatches. The omap_dss_device is sort of part encoder, - part connector. Which results in a bit of duct tape to fwd calls from - encoder to connector. Possibly this could be done a bit better. . Solve PM sequencing on resume. DMM/TILER must be reloaded before any access is made from any component in the system. Which means on suspend CRTC's should be disabled, and on resume the LUT should be reprogrammed diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c index 91edb3f9697..4cc9ee733c5 100644 --- a/drivers/staging/omapdrm/omap_connector.c +++ b/drivers/staging/omapdrm/omap_connector.c @@ -31,9 +31,10 @@ struct omap_connector { struct drm_connector base; struct omap_dss_device *dssdev; + struct drm_encoder *encoder; }; -static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode, +void copy_timings_omap_to_drm(struct drm_display_mode *mode, struct omap_video_timings *timings) { mode->clock = timings->pixel_clock; @@ -64,7 +65,7 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode, mode->flags |= DRM_MODE_FLAG_NVSYNC; } -static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, +void copy_timings_drm_to_omap(struct omap_video_timings *timings, struct drm_display_mode *mode) { timings->pixel_clock = mode->clock; @@ -96,48 +97,7 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; } -static void omap_connector_dpms(struct drm_connector *connector, int mode) -{ - struct omap_connector *omap_connector = to_omap_connector(connector); - struct omap_dss_device *dssdev = omap_connector->dssdev; - int old_dpms; - - DBG("%s: %d", dssdev->name, mode); - - old_dpms = connector->dpms; - - /* from off to on, do from crtc to connector */ - if (mode < old_dpms) - drm_helper_connector_dpms(connector, mode); - - if (mode == DRM_MODE_DPMS_ON) { - /* store resume info for suspended displays */ - switch (dssdev->state) { - case OMAP_DSS_DISPLAY_SUSPENDED: - dssdev->activate_after_resume = true; - break; - case OMAP_DSS_DISPLAY_DISABLED: { - int ret = dssdev->driver->enable(dssdev); - if (ret) { - DBG("%s: failed to enable: %d", - dssdev->name, ret); - dssdev->driver->disable(dssdev); - } - break; - } - default: - break; - } - } else { - /* TODO */ - } - - /* from on to off, do from connector to crtc */ - if (mode > old_dpms) - drm_helper_connector_dpms(connector, mode); -} - -enum drm_connector_status omap_connector_detect( +static enum drm_connector_status omap_connector_detect( struct drm_connector *connector, bool force) { struct omap_connector *omap_connector = to_omap_connector(connector); @@ -164,8 +124,6 @@ static void omap_connector_destroy(struct drm_connector *connector) struct omap_connector *omap_connector = to_omap_connector(connector); struct omap_dss_device *dssdev = omap_connector->dssdev; - dssdev->driver->disable(dssdev); - DBG("%s", omap_connector->dssdev->name); drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); @@ -261,36 +219,12 @@ static int omap_connector_mode_valid(struct drm_connector *connector, struct drm_encoder *omap_connector_attached_encoder( struct drm_connector *connector) { - int i; struct omap_connector *omap_connector = to_omap_connector(connector); - - for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { - struct drm_mode_object *obj; - - if (connector->encoder_ids[i] == 0) - break; - - obj = drm_mode_object_find(connector->dev, - connector->encoder_ids[i], - DRM_MODE_OBJECT_ENCODER); - - if (obj) { - struct drm_encoder *encoder = obj_to_encoder(obj); - struct omap_overlay_manager *mgr = - omap_encoder_get_manager(encoder); - DBG("%s: found %s", omap_connector->dssdev->name, - mgr->name); - return encoder; - } - } - - DBG("%s: no encoder", omap_connector->dssdev->name); - - return NULL; + return omap_connector->encoder; } static const struct drm_connector_funcs omap_connector_funcs = { - .dpms = omap_connector_dpms, + .dpms = drm_helper_connector_dpms, .detect = omap_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = omap_connector_destroy, @@ -302,34 +236,6 @@ static const struct drm_connector_helper_funcs omap_connector_helper_funcs = { .best_encoder = omap_connector_attached_encoder, }; -/* called from encoder when mode is set, to propagate settings to the dssdev */ -void omap_connector_mode_set(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct drm_device *dev = connector->dev; - struct omap_connector *omap_connector = to_omap_connector(connector); - struct omap_dss_device *dssdev = omap_connector->dssdev; - struct omap_dss_driver *dssdrv = dssdev->driver; - struct omap_video_timings timings = {0}; - - copy_timings_drm_to_omap(&timings, mode); - - DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", - omap_connector->dssdev->name, - mode->base.id, mode->name, mode->vrefresh, mode->clock, - mode->hdisplay, mode->hsync_start, - mode->hsync_end, mode->htotal, - mode->vdisplay, mode->vsync_start, - mode->vsync_end, mode->vtotal, mode->type, mode->flags); - - if (dssdrv->check_timings(dssdev, &timings)) { - dev_err(dev->dev, "could not set timings\n"); - return; - } - - dssdrv->set_timings(dssdev, &timings); -} - /* flush an area of the framebuffer (in case of manual update display that * is not automatically flushed) */ @@ -344,7 +250,8 @@ void omap_connector_flush(struct drm_connector *connector, /* initialize connector */ struct drm_connector *omap_connector_init(struct drm_device *dev, - int connector_type, struct omap_dss_device *dssdev) + int connector_type, struct omap_dss_device *dssdev, + struct drm_encoder *encoder) { struct drm_connector *connector = NULL; struct omap_connector *omap_connector; @@ -360,6 +267,8 @@ struct drm_connector *omap_connector_init(struct drm_device *dev, } omap_connector->dssdev = dssdev; + omap_connector->encoder = encoder; + connector = &omap_connector->base; drm_connector_init(dev, connector, &omap_connector_funcs, diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c index d87bd84257b..5c6ed6040ef 100644 --- a/drivers/staging/omapdrm/omap_crtc.c +++ b/drivers/staging/omapdrm/omap_crtc.c @@ -28,19 +28,131 @@ struct omap_crtc { struct drm_crtc base; struct drm_plane *plane; + const char *name; - int id; + int pipe; + enum omap_channel channel; + struct omap_overlay_manager_info info; + + /* + * Temporary: eventually this will go away, but it is needed + * for now to keep the output's happy. (They only need + * mgr->id.) Eventually this will be replaced w/ something + * more common-panel-framework-y + */ + struct omap_overlay_manager mgr; + + struct omap_video_timings timings; + bool enabled; + bool full_update; + + struct omap_drm_apply apply; + + struct omap_drm_irq apply_irq; + struct omap_drm_irq error_irq; + + /* list of in-progress apply's: */ + struct list_head pending_applies; + + /* list of queued apply's: */ + struct list_head queued_applies; + + /* for handling queued and in-progress applies: */ + struct work_struct apply_work; /* if there is a pending flip, these will be non-null: */ struct drm_pending_vblank_event *event; struct drm_framebuffer *old_fb; + + /* for handling page flips without caring about what + * the callback is called from. Possibly we should just + * make omap_gem always call the cb from the worker so + * we don't have to care about this.. + * + * XXX maybe fold into apply_work?? + */ + struct work_struct page_flip_work; +}; + +/* + * Manager-ops, callbacks from output when they need to configure + * the upstream part of the video pipe. + * + * Most of these we can ignore until we add support for command-mode + * panels.. for video-mode the crtc-helpers already do an adequate + * job of sequencing the setup of the video pipe in the proper order + */ + +/* we can probably ignore these until we support command-mode panels: */ +static void omap_crtc_start_update(struct omap_overlay_manager *mgr) +{ +} + +static int omap_crtc_enable(struct omap_overlay_manager *mgr) +{ + return 0; +} + +static void omap_crtc_disable(struct omap_overlay_manager *mgr) +{ +} + +static void omap_crtc_set_timings(struct omap_overlay_manager *mgr, + const struct omap_video_timings *timings) +{ + struct omap_crtc *omap_crtc = container_of(mgr, struct omap_crtc, mgr); + DBG("%s", omap_crtc->name); + omap_crtc->timings = *timings; + omap_crtc->full_update = true; +} + +static void omap_crtc_set_lcd_config(struct omap_overlay_manager *mgr, + const struct dss_lcd_mgr_config *config) +{ + struct omap_crtc *omap_crtc = container_of(mgr, struct omap_crtc, mgr); + DBG("%s", omap_crtc->name); + dispc_mgr_set_lcd_config(omap_crtc->channel, config); +} + +static int omap_crtc_register_framedone_handler( + struct omap_overlay_manager *mgr, + void (*handler)(void *), void *data) +{ + return 0; +} + +static void omap_crtc_unregister_framedone_handler( + struct omap_overlay_manager *mgr, + void (*handler)(void *), void *data) +{ +} + +static const struct dss_mgr_ops mgr_ops = { + .start_update = omap_crtc_start_update, + .enable = omap_crtc_enable, + .disable = omap_crtc_disable, + .set_timings = omap_crtc_set_timings, + .set_lcd_config = omap_crtc_set_lcd_config, + .register_framedone_handler = omap_crtc_register_framedone_handler, + .unregister_framedone_handler = omap_crtc_unregister_framedone_handler, }; +/* + * CRTC funcs: + */ + static void omap_crtc_destroy(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + + DBG("%s", omap_crtc->name); + + WARN_ON(omap_crtc->apply_irq.registered); + omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); + omap_crtc->plane->funcs->destroy(omap_crtc->plane); drm_crtc_cleanup(crtc); + kfree(omap_crtc); } @@ -48,14 +160,25 @@ static void omap_crtc_dpms(struct drm_crtc *crtc, int mode) { struct omap_drm_private *priv = crtc->dev->dev_private; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + bool enabled = (mode == DRM_MODE_DPMS_ON); int i; - WARN_ON(omap_plane_dpms(omap_crtc->plane, mode)); + DBG("%s: %d", omap_crtc->name, mode); + + if (enabled != omap_crtc->enabled) { + omap_crtc->enabled = enabled; + omap_crtc->full_update = true; + omap_crtc_apply(crtc, &omap_crtc->apply); - for (i = 0; i < priv->num_planes; i++) { - struct drm_plane *plane = priv->planes[i]; - if (plane->crtc == crtc) - WARN_ON(omap_plane_dpms(plane, mode)); + /* also enable our private plane: */ + WARN_ON(omap_plane_dpms(omap_crtc->plane, mode)); + + /* and any attached overlay planes: */ + for (i = 0; i < priv->num_planes; i++) { + struct drm_plane *plane = priv->planes[i]; + if (plane->crtc == crtc) + WARN_ON(omap_plane_dpms(plane, mode)); + } } } @@ -73,12 +196,26 @@ static int omap_crtc_mode_set(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); - struct drm_plane *plane = omap_crtc->plane; - return omap_plane_mode_set(plane, crtc, crtc->fb, + mode = adjusted_mode; + + DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", + omap_crtc->name, mode->base.id, mode->name, + mode->vrefresh, mode->clock, + mode->hdisplay, mode->hsync_start, + mode->hsync_end, mode->htotal, + mode->vdisplay, mode->vsync_start, + mode->vsync_end, mode->vtotal, + mode->type, mode->flags); + + copy_timings_drm_to_omap(&omap_crtc->timings, mode); + omap_crtc->full_update = true; + + return omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb, 0, 0, mode->hdisplay, mode->vdisplay, x << 16, y << 16, - mode->hdisplay << 16, mode->vdisplay << 16); + mode->hdisplay << 16, mode->vdisplay << 16, + NULL, NULL); } static void omap_crtc_prepare(struct drm_crtc *crtc) @@ -102,10 +239,11 @@ static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, struct drm_plane *plane = omap_crtc->plane; struct drm_display_mode *mode = &crtc->mode; - return plane->funcs->update_plane(plane, crtc, crtc->fb, + return omap_plane_mode_set(plane, crtc, crtc->fb, 0, 0, mode->hdisplay, mode->vdisplay, x << 16, y << 16, - mode->hdisplay << 16, mode->vdisplay << 16); + mode->hdisplay << 16, mode->vdisplay << 16, + NULL, NULL); } static void omap_crtc_load_lut(struct drm_crtc *crtc) @@ -114,63 +252,54 @@ static void omap_crtc_load_lut(struct drm_crtc *crtc) static void vblank_cb(void *arg) { - static uint32_t sequence; struct drm_crtc *crtc = arg; struct drm_device *dev = crtc->dev; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); - struct drm_pending_vblank_event *event = omap_crtc->event; unsigned long flags; - struct timeval now; - WARN_ON(!event); + spin_lock_irqsave(&dev->event_lock, flags); + + /* wakeup userspace */ + if (omap_crtc->event) + drm_send_vblank_event(dev, omap_crtc->pipe, omap_crtc->event); omap_crtc->event = NULL; + omap_crtc->old_fb = NULL; - /* wakeup userspace */ - if (event) { - do_gettimeofday(&now); - - spin_lock_irqsave(&dev->event_lock, flags); - /* TODO: we can't yet use the vblank time accounting, - * because omapdss lower layer is the one that knows - * the irq # and registers the handler, which more or - * less defeats how drm_irq works.. for now just fake - * the sequence number and use gettimeofday.. - * - event->event.sequence = drm_vblank_count_and_time( - dev, omap_crtc->id, &now); - */ - event->event.sequence = sequence++; - event->event.tv_sec = now.tv_sec; - event->event.tv_usec = now.tv_usec; - list_add_tail(&event->base.link, - &event->base.file_priv->event_list); - wake_up_interruptible(&event->base.file_priv->event_wait); - spin_unlock_irqrestore(&dev->event_lock, flags); - } + spin_unlock_irqrestore(&dev->event_lock, flags); } -static void page_flip_cb(void *arg) +static void page_flip_worker(struct work_struct *work) { - struct drm_crtc *crtc = arg; - struct omap_crtc *omap_crtc = to_omap_crtc(crtc); - struct drm_framebuffer *old_fb = omap_crtc->old_fb; + struct omap_crtc *omap_crtc = + container_of(work, struct omap_crtc, page_flip_work); + struct drm_crtc *crtc = &omap_crtc->base; + struct drm_device *dev = crtc->dev; + struct drm_display_mode *mode = &crtc->mode; struct drm_gem_object *bo; - omap_crtc->old_fb = NULL; - - omap_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb); - - /* really we'd like to setup the callback atomically w/ setting the - * new scanout buffer to avoid getting stuck waiting an extra vblank - * cycle.. for now go for correctness and later figure out speed.. - */ - omap_plane_on_endwin(omap_crtc->plane, vblank_cb, crtc); + mutex_lock(&dev->mode_config.mutex); + omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb, + 0, 0, mode->hdisplay, mode->vdisplay, + crtc->x << 16, crtc->y << 16, + mode->hdisplay << 16, mode->vdisplay << 16, + vblank_cb, crtc); + mutex_unlock(&dev->mode_config.mutex); bo = omap_framebuffer_bo(crtc->fb, 0); drm_gem_object_unreference_unlocked(bo); } +static void page_flip_cb(void *arg) +{ + struct drm_crtc *crtc = arg; + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + struct omap_drm_private *priv = crtc->dev->dev_private; + + /* avoid assumptions about what ctxt we are called from: */ + queue_work(priv->wq, &omap_crtc->page_flip_work); +} + static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event) @@ -179,14 +308,14 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, struct omap_crtc *omap_crtc = to_omap_crtc(crtc); struct drm_gem_object *bo; - DBG("%d -> %d", crtc->fb ? crtc->fb->base.id : -1, fb->base.id); + DBG("%d -> %d (event=%p)", crtc->fb ? crtc->fb->base.id : -1, + fb->base.id, event); - if (omap_crtc->event) { + if (omap_crtc->old_fb) { dev_err(dev->dev, "already a pending flip\n"); return -EINVAL; } - omap_crtc->old_fb = crtc->fb; omap_crtc->event = event; crtc->fb = fb; @@ -234,14 +363,244 @@ static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { .load_lut = omap_crtc_load_lut, }; +const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + return &omap_crtc->timings; +} + +enum omap_channel omap_crtc_channel(struct drm_crtc *crtc) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + return omap_crtc->channel; +} + +static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) +{ + struct omap_crtc *omap_crtc = + container_of(irq, struct omap_crtc, error_irq); + struct drm_crtc *crtc = &omap_crtc->base; + DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus); + /* avoid getting in a flood, unregister the irq until next vblank */ + omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); +} + +static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus) +{ + struct omap_crtc *omap_crtc = + container_of(irq, struct omap_crtc, apply_irq); + struct drm_crtc *crtc = &omap_crtc->base; + + if (!omap_crtc->error_irq.registered) + omap_irq_register(crtc->dev, &omap_crtc->error_irq); + + if (!dispc_mgr_go_busy(omap_crtc->channel)) { + struct omap_drm_private *priv = + crtc->dev->dev_private; + DBG("%s: apply done", omap_crtc->name); + omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq); + queue_work(priv->wq, &omap_crtc->apply_work); + } +} + +static void apply_worker(struct work_struct *work) +{ + struct omap_crtc *omap_crtc = + container_of(work, struct omap_crtc, apply_work); + struct drm_crtc *crtc = &omap_crtc->base; + struct drm_device *dev = crtc->dev; + struct omap_drm_apply *apply, *n; + bool need_apply; + + /* + * Synchronize everything on mode_config.mutex, to keep + * the callbacks and list modification all serialized + * with respect to modesetting ioctls from userspace. + */ + mutex_lock(&dev->mode_config.mutex); + dispc_runtime_get(); + + /* + * If we are still pending a previous update, wait.. when the + * pending update completes, we get kicked again. + */ + if (omap_crtc->apply_irq.registered) + goto out; + + /* finish up previous apply's: */ + list_for_each_entry_safe(apply, n, + &omap_crtc->pending_applies, pending_node) { + apply->post_apply(apply); + list_del(&apply->pending_node); + } + + need_apply = !list_empty(&omap_crtc->queued_applies); + + /* then handle the next round of of queued apply's: */ + list_for_each_entry_safe(apply, n, + &omap_crtc->queued_applies, queued_node) { + apply->pre_apply(apply); + list_del(&apply->queued_node); + apply->queued = false; + list_add_tail(&apply->pending_node, + &omap_crtc->pending_applies); + } + + if (need_apply) { + enum omap_channel channel = omap_crtc->channel; + + DBG("%s: GO", omap_crtc->name); + + if (dispc_mgr_is_enabled(channel)) { + omap_irq_register(dev, &omap_crtc->apply_irq); + dispc_mgr_go(channel); + } else { + struct omap_drm_private *priv = dev->dev_private; + queue_work(priv->wq, &omap_crtc->apply_work); + } + } + +out: + dispc_runtime_put(); + mutex_unlock(&dev->mode_config.mutex); +} + +int omap_crtc_apply(struct drm_crtc *crtc, + struct omap_drm_apply *apply) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + struct drm_device *dev = crtc->dev; + + WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); + + /* no need to queue it again if it is already queued: */ + if (apply->queued) + return 0; + + apply->queued = true; + list_add_tail(&apply->queued_node, &omap_crtc->queued_applies); + + /* + * If there are no currently pending updates, then go ahead and + * kick the worker immediately, otherwise it will run again when + * the current update finishes. + */ + if (list_empty(&omap_crtc->pending_applies)) { + struct omap_drm_private *priv = crtc->dev->dev_private; + queue_work(priv->wq, &omap_crtc->apply_work); + } + + return 0; +} + +/* called only from apply */ +static void set_enabled(struct drm_crtc *crtc, bool enable) +{ + struct drm_device *dev = crtc->dev; + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + enum omap_channel channel = omap_crtc->channel; + struct omap_irq_wait *wait = NULL; + + if (dispc_mgr_is_enabled(channel) == enable) + return; + + /* ignore sync-lost irqs during enable/disable */ + omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); + + if (dispc_mgr_get_framedone_irq(channel)) { + if (!enable) { + wait = omap_irq_wait_init(dev, + dispc_mgr_get_framedone_irq(channel), 1); + } + } else { + /* + * When we disable digit output, we need to wait until fields + * are done. Otherwise the DSS is still working, and turning + * off the clocks prevents DSS from going to OFF mode. And when + * enabling, we need to wait for the extra sync losts + */ + wait = omap_irq_wait_init(dev, + dispc_mgr_get_vsync_irq(channel), 2); + } + + dispc_mgr_enable(channel, enable); + + if (wait) { + int ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); + if (ret) { + dev_err(dev->dev, "%s: timeout waiting for %s\n", + omap_crtc->name, enable ? "enable" : "disable"); + } + } + + omap_irq_register(crtc->dev, &omap_crtc->error_irq); +} + +static void omap_crtc_pre_apply(struct omap_drm_apply *apply) +{ + struct omap_crtc *omap_crtc = + container_of(apply, struct omap_crtc, apply); + struct drm_crtc *crtc = &omap_crtc->base; + struct drm_encoder *encoder = NULL; + + DBG("%s: enabled=%d, full=%d", omap_crtc->name, + omap_crtc->enabled, omap_crtc->full_update); + + if (omap_crtc->full_update) { + struct omap_drm_private *priv = crtc->dev->dev_private; + int i; + for (i = 0; i < priv->num_encoders; i++) { + if (priv->encoders[i]->crtc == crtc) { + encoder = priv->encoders[i]; + break; + } + } + } + + if (!omap_crtc->enabled) { + set_enabled(&omap_crtc->base, false); + if (encoder) + omap_encoder_set_enabled(encoder, false); + } else { + if (encoder) { + omap_encoder_set_enabled(encoder, false); + omap_encoder_update(encoder, &omap_crtc->mgr, + &omap_crtc->timings); + omap_encoder_set_enabled(encoder, true); + omap_crtc->full_update = false; + } + + dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info); + dispc_mgr_set_timings(omap_crtc->channel, + &omap_crtc->timings); + set_enabled(&omap_crtc->base, true); + } + + omap_crtc->full_update = false; +} + +static void omap_crtc_post_apply(struct omap_drm_apply *apply) +{ + /* nothing needed for post-apply */ +} + +static const char *channel_names[] = { + [OMAP_DSS_CHANNEL_LCD] = "lcd", + [OMAP_DSS_CHANNEL_DIGIT] = "tv", + [OMAP_DSS_CHANNEL_LCD2] = "lcd2", +}; + /* initialize crtc */ struct drm_crtc *omap_crtc_init(struct drm_device *dev, - struct omap_overlay *ovl, int id) + struct drm_plane *plane, enum omap_channel channel, int id) { struct drm_crtc *crtc = NULL; - struct omap_crtc *omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL); + struct omap_crtc *omap_crtc; + struct omap_overlay_manager_info *info; + + DBG("%s", channel_names[channel]); - DBG("%s", ovl->name); + omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL); if (!omap_crtc) { dev_err(dev->dev, "could not allocate CRTC\n"); @@ -250,10 +609,40 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, crtc = &omap_crtc->base; - omap_crtc->plane = omap_plane_init(dev, ovl, (1 << id), true); + INIT_WORK(&omap_crtc->page_flip_work, page_flip_worker); + INIT_WORK(&omap_crtc->apply_work, apply_worker); + + INIT_LIST_HEAD(&omap_crtc->pending_applies); + INIT_LIST_HEAD(&omap_crtc->queued_applies); + + omap_crtc->apply.pre_apply = omap_crtc_pre_apply; + omap_crtc->apply.post_apply = omap_crtc_post_apply; + + omap_crtc->apply_irq.irqmask = pipe2vbl(id); + omap_crtc->apply_irq.irq = omap_crtc_apply_irq; + + omap_crtc->error_irq.irqmask = + dispc_mgr_get_sync_lost_irq(channel); + omap_crtc->error_irq.irq = omap_crtc_error_irq; + omap_irq_register(dev, &omap_crtc->error_irq); + + omap_crtc->channel = channel; + omap_crtc->plane = plane; omap_crtc->plane->crtc = crtc; - omap_crtc->name = ovl->name; - omap_crtc->id = id; + omap_crtc->name = channel_names[channel]; + omap_crtc->pipe = id; + + /* temporary: */ + omap_crtc->mgr.id = channel; + + dss_install_mgr_ops(&mgr_ops); + + /* TODO: fix hard-coded setup.. add properties! */ + info = &omap_crtc->info; + info->default_color = 0x00000000; + info->trans_key = 0x00000000; + info->trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST; + info->trans_enabled = false; drm_crtc_init(dev, crtc, &omap_crtc_funcs); drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs); diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c index 84943e5ba1d..ae5ecc2efbc 100644 --- a/drivers/staging/omapdrm/omap_drv.c +++ b/drivers/staging/omapdrm/omap_drv.c @@ -74,320 +74,99 @@ static int get_connector_type(struct omap_dss_device *dssdev) } } -#if 0 /* enable when dss2 supports hotplug */ -static int omap_drm_notifier(struct notifier_block *nb, - unsigned long evt, void *arg) -{ - switch (evt) { - case OMAP_DSS_SIZE_CHANGE: - case OMAP_DSS_HOTPLUG_CONNECT: - case OMAP_DSS_HOTPLUG_DISCONNECT: { - struct drm_device *dev = drm_device; - DBG("hotplug event: evt=%d, dev=%p", evt, dev); - if (dev) - drm_sysfs_hotplug_event(dev); - - return NOTIFY_OK; - } - default: /* don't care about other events for now */ - return NOTIFY_DONE; - } -} -#endif - -static void dump_video_chains(void) -{ - int i; - - DBG("dumping video chains: "); - for (i = 0; i < omap_dss_get_num_overlays(); i++) { - struct omap_overlay *ovl = omap_dss_get_overlay(i); - struct omap_overlay_manager *mgr = ovl->manager; - struct omap_dss_device *dssdev = mgr ? - mgr->get_device(mgr) : NULL; - if (dssdev) { - DBG("%d: %s -> %s -> %s", i, ovl->name, mgr->name, - dssdev->name); - } else if (mgr) { - DBG("%d: %s -> %s", i, ovl->name, mgr->name); - } else { - DBG("%d: %s", i, ovl->name); - } - } -} - -/* create encoders for each manager */ -static int create_encoder(struct drm_device *dev, - struct omap_overlay_manager *mgr) -{ - struct omap_drm_private *priv = dev->dev_private; - struct drm_encoder *encoder = omap_encoder_init(dev, mgr); - - if (!encoder) { - dev_err(dev->dev, "could not create encoder: %s\n", - mgr->name); - return -ENOMEM; - } - - BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders)); - - priv->encoders[priv->num_encoders++] = encoder; - - return 0; -} - -/* create connectors for each display device */ -static int create_connector(struct drm_device *dev, - struct omap_dss_device *dssdev) +static int omap_modeset_init(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; - static struct notifier_block *notifier; - struct drm_connector *connector; - int j; - - if (!dssdev->driver) { - dev_warn(dev->dev, "%s has no driver.. skipping it\n", - dssdev->name); - return 0; - } + struct omap_dss_device *dssdev = NULL; + int num_ovls = dss_feat_get_num_ovls(); + int id; - if (!(dssdev->driver->get_timings || - dssdev->driver->read_edid)) { - dev_warn(dev->dev, "%s driver does not support " - "get_timings or read_edid.. skipping it!\n", - dssdev->name); - return 0; - } + drm_mode_config_init(dev); - connector = omap_connector_init(dev, - get_connector_type(dssdev), dssdev); + omap_drm_irq_install(dev); - if (!connector) { - dev_err(dev->dev, "could not create connector: %s\n", - dssdev->name); - return -ENOMEM; - } - - BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors)); + /* + * Create private planes and CRTCs for the last NUM_CRTCs overlay + * plus manager: + */ + for (id = 0; id < min(num_crtc, num_ovls); id++) { + struct drm_plane *plane; + struct drm_crtc *crtc; - priv->connectors[priv->num_connectors++] = connector; + plane = omap_plane_init(dev, id, true); + crtc = omap_crtc_init(dev, plane, pipe2chan(id), id); -#if 0 /* enable when dss2 supports hotplug */ - notifier = kzalloc(sizeof(struct notifier_block), GFP_KERNEL); - notifier->notifier_call = omap_drm_notifier; - omap_dss_add_notify(dssdev, notifier); -#else - notifier = NULL; -#endif + BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs)); + priv->crtcs[id] = crtc; + priv->num_crtcs++; - for (j = 0; j < priv->num_encoders; j++) { - struct omap_overlay_manager *mgr = - omap_encoder_get_manager(priv->encoders[j]); - if (mgr->get_device(mgr) == dssdev) { - drm_mode_connector_attach_encoder(connector, - priv->encoders[j]); - } + priv->planes[id] = plane; + priv->num_planes++; } - return 0; -} - -/* create up to max_overlays CRTCs mapping to overlays.. by default, - * connect the overlays to different managers/encoders, giving priority - * to encoders connected to connectors with a detected connection - */ -static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl, - int *j, unsigned int connected_connectors) -{ - struct omap_drm_private *priv = dev->dev_private; - struct omap_overlay_manager *mgr = NULL; - struct drm_crtc *crtc; - - /* find next best connector, ones with detected connection first + /* + * Create normal planes for the remaining overlays: */ - while (*j < priv->num_connectors && !mgr) { - if (connected_connectors & (1 << *j)) { - struct drm_encoder *encoder = - omap_connector_attached_encoder( - priv->connectors[*j]); - if (encoder) - mgr = omap_encoder_get_manager(encoder); + for (; id < num_ovls; id++) { + struct drm_plane *plane = omap_plane_init(dev, id, false); - } - (*j)++; + BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes)); + priv->planes[priv->num_planes++] = plane; } - /* if we couldn't find another connected connector, lets start - * looking at the unconnected connectors: - * - * note: it might not be immediately apparent, but thanks to - * the !mgr check in both this loop and the one above, the only - * way to enter this loop is with *j == priv->num_connectors, - * so idx can never go negative. - */ - while (*j < 2 * priv->num_connectors && !mgr) { - int idx = *j - priv->num_connectors; - if (!(connected_connectors & (1 << idx))) { - struct drm_encoder *encoder = - omap_connector_attached_encoder( - priv->connectors[idx]); - if (encoder) - mgr = omap_encoder_get_manager(encoder); + for_each_dss_dev(dssdev) { + struct drm_connector *connector; + struct drm_encoder *encoder; + if (!dssdev->driver) { + dev_warn(dev->dev, "%s has no driver.. skipping it\n", + dssdev->name); + return 0; } - (*j)++; - } - - crtc = omap_crtc_init(dev, ovl, priv->num_crtcs); - - if (!crtc) { - dev_err(dev->dev, "could not create CRTC: %s\n", - ovl->name); - return -ENOMEM; - } - BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs)); - - priv->crtcs[priv->num_crtcs++] = crtc; - - return 0; -} - -static int create_plane(struct drm_device *dev, struct omap_overlay *ovl, - unsigned int possible_crtcs) -{ - struct omap_drm_private *priv = dev->dev_private; - struct drm_plane *plane = - omap_plane_init(dev, ovl, possible_crtcs, false); - - if (!plane) { - dev_err(dev->dev, "could not create plane: %s\n", - ovl->name); - return -ENOMEM; - } - - BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes)); - - priv->planes[priv->num_planes++] = plane; - - return 0; -} - -static int match_dev_name(struct omap_dss_device *dssdev, void *data) -{ - return !strcmp(dssdev->name, data); -} - -static unsigned int detect_connectors(struct drm_device *dev) -{ - struct omap_drm_private *priv = dev->dev_private; - unsigned int connected_connectors = 0; - int i; - - for (i = 0; i < priv->num_connectors; i++) { - struct drm_connector *connector = priv->connectors[i]; - if (omap_connector_detect(connector, true) == - connector_status_connected) { - connected_connectors |= (1 << i); + if (!(dssdev->driver->get_timings || + dssdev->driver->read_edid)) { + dev_warn(dev->dev, "%s driver does not support " + "get_timings or read_edid.. skipping it!\n", + dssdev->name); + return 0; } - } - - return connected_connectors; -} -static int omap_modeset_init(struct drm_device *dev) -{ - const struct omap_drm_platform_data *pdata = dev->dev->platform_data; - struct omap_kms_platform_data *kms_pdata = NULL; - struct omap_drm_private *priv = dev->dev_private; - struct omap_dss_device *dssdev = NULL; - int i, j; - unsigned int connected_connectors = 0; + encoder = omap_encoder_init(dev, dssdev); - drm_mode_config_init(dev); - - if (pdata && pdata->kms_pdata) { - kms_pdata = pdata->kms_pdata; - - /* if platform data is provided by the board file, use it to - * control which overlays, managers, and devices we own. - */ - for (i = 0; i < kms_pdata->mgr_cnt; i++) { - struct omap_overlay_manager *mgr = - omap_dss_get_overlay_manager( - kms_pdata->mgr_ids[i]); - create_encoder(dev, mgr); - } - - for (i = 0; i < kms_pdata->dev_cnt; i++) { - struct omap_dss_device *dssdev = - omap_dss_find_device( - (void *)kms_pdata->dev_names[i], - match_dev_name); - if (!dssdev) { - dev_warn(dev->dev, "no such dssdev: %s\n", - kms_pdata->dev_names[i]); - continue; - } - create_connector(dev, dssdev); + if (!encoder) { + dev_err(dev->dev, "could not create encoder: %s\n", + dssdev->name); + return -ENOMEM; } - connected_connectors = detect_connectors(dev); + connector = omap_connector_init(dev, + get_connector_type(dssdev), dssdev, encoder); - j = 0; - for (i = 0; i < kms_pdata->ovl_cnt; i++) { - struct omap_overlay *ovl = - omap_dss_get_overlay(kms_pdata->ovl_ids[i]); - create_crtc(dev, ovl, &j, connected_connectors); + if (!connector) { + dev_err(dev->dev, "could not create connector: %s\n", + dssdev->name); + return -ENOMEM; } - for (i = 0; i < kms_pdata->pln_cnt; i++) { - struct omap_overlay *ovl = - omap_dss_get_overlay(kms_pdata->pln_ids[i]); - create_plane(dev, ovl, (1 << priv->num_crtcs) - 1); - } - } else { - /* otherwise just grab up to CONFIG_DRM_OMAP_NUM_CRTCS and try - * to make educated guesses about everything else - */ - int max_overlays = min(omap_dss_get_num_overlays(), num_crtc); + BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders)); + BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors)); - for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) - create_encoder(dev, omap_dss_get_overlay_manager(i)); - - for_each_dss_dev(dssdev) { - create_connector(dev, dssdev); - } + priv->encoders[priv->num_encoders++] = encoder; + priv->connectors[priv->num_connectors++] = connector; - connected_connectors = detect_connectors(dev); + drm_mode_connector_attach_encoder(connector, encoder); - j = 0; - for (i = 0; i < max_overlays; i++) { - create_crtc(dev, omap_dss_get_overlay(i), - &j, connected_connectors); - } - - /* use any remaining overlays as drm planes */ - for (; i < omap_dss_get_num_overlays(); i++) { - struct omap_overlay *ovl = omap_dss_get_overlay(i); - create_plane(dev, ovl, (1 << priv->num_crtcs) - 1); + /* figure out which crtc's we can connect the encoder to: */ + encoder->possible_crtcs = 0; + for (id = 0; id < priv->num_crtcs; id++) { + enum omap_dss_output_id supported_outputs = + dss_feat_get_supported_outputs(pipe2chan(id)); + if (supported_outputs & dssdev->output->id) + encoder->possible_crtcs |= (1 << id); } } - /* for now keep the mapping of CRTCs and encoders static.. */ - for (i = 0; i < priv->num_encoders; i++) { - struct drm_encoder *encoder = priv->encoders[i]; - struct omap_overlay_manager *mgr = - omap_encoder_get_manager(encoder); - - encoder->possible_crtcs = (1 << priv->num_crtcs) - 1; - - DBG("%s: possible_crtcs=%08x", mgr->name, - encoder->possible_crtcs); - } - - dump_video_chains(); - dev->mode_config.min_width = 32; dev->mode_config.min_height = 32; @@ -450,7 +229,7 @@ static int ioctl_gem_new(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_omap_gem_new *args = data; - DBG("%p:%p: size=0x%08x, flags=%08x", dev, file_priv, + VERB("%p:%p: size=0x%08x, flags=%08x", dev, file_priv, args->size.bytes, args->flags); return omap_gem_new_handle(dev, file_priv, args->size, args->flags, &args->handle); @@ -510,7 +289,7 @@ static int ioctl_gem_info(struct drm_device *dev, void *data, struct drm_gem_object *obj; int ret = 0; - DBG("%p:%p: handle=%d", dev, file_priv, args->handle); + VERB("%p:%p: handle=%d", dev, file_priv, args->handle); obj = drm_gem_object_lookup(dev, file_priv, args->handle); if (!obj) @@ -565,14 +344,6 @@ static int dev_load(struct drm_device *dev, unsigned long flags) dev->dev_private = priv; - ret = omapdss_compat_init(); - if (ret) { - dev_err(dev->dev, "coult not init omapdss\n"); - dev->dev_private = NULL; - kfree(priv); - return ret; - } - priv->wq = alloc_ordered_workqueue("omapdrm", 0); INIT_LIST_HEAD(&priv->obj_list); @@ -584,10 +355,13 @@ static int dev_load(struct drm_device *dev, unsigned long flags) dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret); dev->dev_private = NULL; kfree(priv); - omapdss_compat_uninit(); return ret; } + ret = drm_vblank_init(dev, priv->num_crtcs); + if (ret) + dev_warn(dev->dev, "could not init vblank\n"); + priv->fbdev = omap_fbdev_init(dev); if (!priv->fbdev) { dev_warn(dev->dev, "omap_fbdev_init failed\n"); @@ -596,10 +370,6 @@ static int dev_load(struct drm_device *dev, unsigned long flags) drm_kms_helper_poll_init(dev); - ret = drm_vblank_init(dev, priv->num_crtcs); - if (ret) - dev_warn(dev->dev, "could not init vblank\n"); - return 0; } @@ -609,8 +379,9 @@ static int dev_unload(struct drm_device *dev) DBG("unload: dev=%p", dev); - drm_vblank_cleanup(dev); drm_kms_helper_poll_fini(dev); + drm_vblank_cleanup(dev); + omap_drm_irq_uninstall(dev); omap_fbdev_free(dev); omap_modeset_free(dev); @@ -619,8 +390,6 @@ static int dev_unload(struct drm_device *dev) flush_workqueue(priv->wq); destroy_workqueue(priv->wq); - omapdss_compat_uninit(); - kfree(dev->dev_private); dev->dev_private = NULL; @@ -680,7 +449,9 @@ static void dev_lastclose(struct drm_device *dev) } } + mutex_lock(&dev->mode_config.mutex); ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev); + mutex_unlock(&dev->mode_config.mutex); if (ret) DBG("failed to restore crtc mode"); } @@ -695,60 +466,6 @@ static void dev_postclose(struct drm_device *dev, struct drm_file *file) DBG("postclose: dev=%p, file=%p", dev, file); } -/** - * enable_vblank - enable vblank interrupt events - * @dev: DRM device - * @crtc: which irq to enable - * - * Enable vblank interrupts for @crtc. If the device doesn't have - * a hardware vblank counter, this routine should be a no-op, since - * interrupts will have to stay on to keep the count accurate. - * - * RETURNS - * Zero on success, appropriate errno if the given @crtc's vblank - * interrupt cannot be enabled. - */ -static int dev_enable_vblank(struct drm_device *dev, int crtc) -{ - DBG("enable_vblank: dev=%p, crtc=%d", dev, crtc); - return 0; -} - -/** - * disable_vblank - disable vblank interrupt events - * @dev: DRM device - * @crtc: which irq to enable - * - * Disable vblank interrupts for @crtc. If the device doesn't have - * a hardware vblank counter, this routine should be a no-op, since - * interrupts will have to stay on to keep the count accurate. - */ -static void dev_disable_vblank(struct drm_device *dev, int crtc) -{ - DBG("disable_vblank: dev=%p, crtc=%d", dev, crtc); -} - -static irqreturn_t dev_irq_handler(DRM_IRQ_ARGS) -{ - return IRQ_HANDLED; -} - -static void dev_irq_preinstall(struct drm_device *dev) -{ - DBG("irq_preinstall: dev=%p", dev); -} - -static int dev_irq_postinstall(struct drm_device *dev) -{ - DBG("irq_postinstall: dev=%p", dev); - return 0; -} - -static void dev_irq_uninstall(struct drm_device *dev) -{ - DBG("irq_uninstall: dev=%p", dev); -} - static const struct vm_operations_struct omap_gem_vm_ops = { .fault = omap_gem_fault, .open = drm_gem_vm_open, @@ -778,12 +495,12 @@ static struct drm_driver omap_drm_driver = { .preclose = dev_preclose, .postclose = dev_postclose, .get_vblank_counter = drm_vblank_count, - .enable_vblank = dev_enable_vblank, - .disable_vblank = dev_disable_vblank, - .irq_preinstall = dev_irq_preinstall, - .irq_postinstall = dev_irq_postinstall, - .irq_uninstall = dev_irq_uninstall, - .irq_handler = dev_irq_handler, + .enable_vblank = omap_irq_enable_vblank, + .disable_vblank = omap_irq_disable_vblank, + .irq_preinstall = omap_irq_preinstall, + .irq_postinstall = omap_irq_postinstall, + .irq_uninstall = omap_irq_uninstall, + .irq_handler = omap_irq_handler, #ifdef CONFIG_DEBUG_FS .debugfs_init = omap_debugfs_init, .debugfs_cleanup = omap_debugfs_cleanup, diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h index 1d4aea53b75..cd1f22b0b12 100644 --- a/drivers/staging/omapdrm/omap_drv.h +++ b/drivers/staging/omapdrm/omap_drv.h @@ -28,6 +28,7 @@ #include <linux/platform_data/omap_drm.h> #include "omap_drm.h" + #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) #define VERB(fmt, ...) if (0) DRM_DEBUG(fmt, ##__VA_ARGS__) /* verbose debug */ @@ -39,6 +40,51 @@ */ #define MAX_MAPPERS 2 +/* parameters which describe (unrotated) coordinates of scanout within a fb: */ +struct omap_drm_window { + uint32_t rotation; + int32_t crtc_x, crtc_y; /* signed because can be offscreen */ + uint32_t crtc_w, crtc_h; + uint32_t src_x, src_y; + uint32_t src_w, src_h; +}; + +/* Once GO bit is set, we can't make further updates to shadowed registers + * until the GO bit is cleared. So various parts in the kms code that need + * to update shadowed registers queue up a pair of callbacks, pre_apply + * which is called before setting GO bit, and post_apply that is called + * after GO bit is cleared. The crtc manages the queuing, and everyone + * else goes thru omap_crtc_apply() using these callbacks so that the + * code which has to deal w/ GO bit state is centralized. + */ +struct omap_drm_apply { + struct list_head pending_node, queued_node; + bool queued; + void (*pre_apply)(struct omap_drm_apply *apply); + void (*post_apply)(struct omap_drm_apply *apply); +}; + +/* For transiently registering for different DSS irqs that various parts + * of the KMS code need during setup/configuration. We these are not + * necessarily the same as what drm_vblank_get/put() are requesting, and + * the hysteresis in drm_vblank_put() is not necessarily desirable for + * internal housekeeping related irq usage. + */ +struct omap_drm_irq { + struct list_head node; + uint32_t irqmask; + bool registered; + void (*irq)(struct omap_drm_irq *irq, uint32_t irqstatus); +}; + +/* For KMS code that needs to wait for a certain # of IRQs: + */ +struct omap_irq_wait; +struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev, + uint32_t irqmask, int count); +int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait, + unsigned long timeout); + struct omap_drm_private { uint32_t omaprev; @@ -58,6 +104,7 @@ struct omap_drm_private { struct workqueue_struct *wq; + /* list of GEM objects: */ struct list_head obj_list; bool has_dmm; @@ -65,6 +112,11 @@ struct omap_drm_private { /* properties: */ struct drm_property *rotation_prop; struct drm_property *zorder_prop; + + /* irq handling: */ + struct list_head irq_list; /* list of omap_drm_irq */ + uint32_t vblank_mask; /* irq bits set for userspace vblank */ + struct omap_drm_irq error_handler; }; /* this should probably be in drm-core to standardize amongst drivers */ @@ -75,15 +127,6 @@ struct omap_drm_private { #define DRM_REFLECT_X 4 #define DRM_REFLECT_Y 5 -/* parameters which describe (unrotated) coordinates of scanout within a fb: */ -struct omap_drm_window { - uint32_t rotation; - int32_t crtc_x, crtc_y; /* signed because can be offscreen */ - uint32_t crtc_w, crtc_h; - uint32_t src_x, src_y; - uint32_t src_w, src_h; -}; - #ifdef CONFIG_DEBUG_FS int omap_debugfs_init(struct drm_minor *minor); void omap_debugfs_cleanup(struct drm_minor *minor); @@ -92,23 +135,36 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m); void omap_gem_describe_objects(struct list_head *list, struct seq_file *m); #endif +int omap_irq_enable_vblank(struct drm_device *dev, int crtc); +void omap_irq_disable_vblank(struct drm_device *dev, int crtc); +irqreturn_t omap_irq_handler(DRM_IRQ_ARGS); +void omap_irq_preinstall(struct drm_device *dev); +int omap_irq_postinstall(struct drm_device *dev); +void omap_irq_uninstall(struct drm_device *dev); +void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq); +void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq); +int omap_drm_irq_uninstall(struct drm_device *dev); +int omap_drm_irq_install(struct drm_device *dev); + struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev); void omap_fbdev_free(struct drm_device *dev); +const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc); +enum omap_channel omap_crtc_channel(struct drm_crtc *crtc); +int omap_crtc_apply(struct drm_crtc *crtc, + struct omap_drm_apply *apply); struct drm_crtc *omap_crtc_init(struct drm_device *dev, - struct omap_overlay *ovl, int id); + struct drm_plane *plane, enum omap_channel channel, int id); struct drm_plane *omap_plane_init(struct drm_device *dev, - struct omap_overlay *ovl, unsigned int possible_crtcs, - bool priv); + int plane_id, bool private_plane); int omap_plane_dpms(struct drm_plane *plane, int mode); int omap_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h); -void omap_plane_on_endwin(struct drm_plane *plane, + uint32_t src_w, uint32_t src_h, void (*fxn)(void *), void *arg); void omap_plane_install_properties(struct drm_plane *plane, struct drm_mode_object *obj); @@ -116,21 +172,25 @@ int omap_plane_set_property(struct drm_plane *plane, struct drm_property *property, uint64_t val); struct drm_encoder *omap_encoder_init(struct drm_device *dev, - struct omap_overlay_manager *mgr); -struct omap_overlay_manager *omap_encoder_get_manager( + struct omap_dss_device *dssdev); +int omap_encoder_set_enabled(struct drm_encoder *encoder, bool enabled); +int omap_encoder_update(struct drm_encoder *encoder, + struct omap_overlay_manager *mgr, + struct omap_video_timings *timings); + +struct drm_connector *omap_connector_init(struct drm_device *dev, + int connector_type, struct omap_dss_device *dssdev, struct drm_encoder *encoder); struct drm_encoder *omap_connector_attached_encoder( struct drm_connector *connector); -enum drm_connector_status omap_connector_detect( - struct drm_connector *connector, bool force); - -struct drm_connector *omap_connector_init(struct drm_device *dev, - int connector_type, struct omap_dss_device *dssdev); -void omap_connector_mode_set(struct drm_connector *connector, - struct drm_display_mode *mode); void omap_connector_flush(struct drm_connector *connector, int x, int y, int w, int h); +void copy_timings_omap_to_drm(struct drm_display_mode *mode, + struct omap_video_timings *timings); +void copy_timings_drm_to_omap(struct omap_video_timings *timings, + struct drm_display_mode *mode); + uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats, uint32_t max_formats, enum omap_color_mode supported_modes); struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev, @@ -207,6 +267,40 @@ static inline int align_pitch(int pitch, int width, int bpp) return ALIGN(pitch, 8 * bytespp); } +static inline enum omap_channel pipe2chan(int pipe) +{ + int num_mgrs = dss_feat_get_num_mgrs(); + + /* + * We usually don't want to create a CRTC for each manager, + * at least not until we have a way to expose private planes + * to userspace. Otherwise there would not be enough video + * pipes left for drm planes. The higher #'d managers tend + * to have more features so start in reverse order. + */ + return num_mgrs - pipe - 1; +} + +/* map crtc to vblank mask */ +static inline uint32_t pipe2vbl(int crtc) +{ + enum omap_channel channel = pipe2chan(crtc); + return dispc_mgr_get_vsync_irq(channel); +} + +static inline int crtc2pipe(struct drm_device *dev, struct drm_crtc *crtc) +{ + struct omap_drm_private *priv = dev->dev_private; + int i; + + for (i = 0; i < ARRAY_SIZE(priv->crtcs); i++) + if (priv->crtcs[i] == crtc) + return i; + + BUG(); /* bogus CRTC ptr */ + return -1; +} + /* should these be made into common util helpers? */ diff --git a/drivers/staging/omapdrm/omap_encoder.c b/drivers/staging/omapdrm/omap_encoder.c index 5341d5e3e31..e053160d2db 100644 --- a/drivers/staging/omapdrm/omap_encoder.c +++ b/drivers/staging/omapdrm/omap_encoder.c @@ -22,37 +22,56 @@ #include "drm_crtc.h" #include "drm_crtc_helper.h" +#include <linux/list.h> + + /* * encoder funcs */ #define to_omap_encoder(x) container_of(x, struct omap_encoder, base) +/* The encoder and connector both map to same dssdev.. the encoder + * handles the 'active' parts, ie. anything the modifies the state + * of the hw, and the connector handles the 'read-only' parts, like + * detecting connection and reading edid. + */ struct omap_encoder { struct drm_encoder base; - struct omap_overlay_manager *mgr; + struct omap_dss_device *dssdev; }; static void omap_encoder_destroy(struct drm_encoder *encoder) { struct omap_encoder *omap_encoder = to_omap_encoder(encoder); - DBG("%s", omap_encoder->mgr->name); drm_encoder_cleanup(encoder); kfree(omap_encoder); } +static const struct drm_encoder_funcs omap_encoder_funcs = { + .destroy = omap_encoder_destroy, +}; + +/* + * The CRTC drm_crtc_helper_set_mode() doesn't really give us the right + * order.. the easiest way to work around this for now is to make all + * the encoder-helper's no-op's and have the omap_crtc code take care + * of the sequencing and call us in the right points. + * + * Eventually to handle connecting CRTCs to different encoders properly, + * either the CRTC helpers need to change or we need to replace + * drm_crtc_helper_set_mode(), but lets wait until atomic-modeset for + * that. + */ + static void omap_encoder_dpms(struct drm_encoder *encoder, int mode) { - struct omap_encoder *omap_encoder = to_omap_encoder(encoder); - DBG("%s: %d", omap_encoder->mgr->name, mode); } static bool omap_encoder_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct omap_encoder *omap_encoder = to_omap_encoder(encoder); - DBG("%s", omap_encoder->mgr->name); return true; } @@ -60,47 +79,16 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct omap_encoder *omap_encoder = to_omap_encoder(encoder); - struct drm_device *dev = encoder->dev; - struct omap_drm_private *priv = dev->dev_private; - int i; - - mode = adjusted_mode; - - DBG("%s: set mode: %dx%d", omap_encoder->mgr->name, - mode->hdisplay, mode->vdisplay); - - for (i = 0; i < priv->num_connectors; i++) { - struct drm_connector *connector = priv->connectors[i]; - if (connector->encoder == encoder) - omap_connector_mode_set(connector, mode); - - } } static void omap_encoder_prepare(struct drm_encoder *encoder) { - struct omap_encoder *omap_encoder = to_omap_encoder(encoder); - struct drm_encoder_helper_funcs *encoder_funcs = - encoder->helper_private; - DBG("%s", omap_encoder->mgr->name); - encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); } static void omap_encoder_commit(struct drm_encoder *encoder) { - struct omap_encoder *omap_encoder = to_omap_encoder(encoder); - struct drm_encoder_helper_funcs *encoder_funcs = - encoder->helper_private; - DBG("%s", omap_encoder->mgr->name); - omap_encoder->mgr->apply(omap_encoder->mgr); - encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); } -static const struct drm_encoder_funcs omap_encoder_funcs = { - .destroy = omap_encoder_destroy, -}; - static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = { .dpms = omap_encoder_dpms, .mode_fixup = omap_encoder_mode_fixup, @@ -109,23 +97,54 @@ static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = { .commit = omap_encoder_commit, }; -struct omap_overlay_manager *omap_encoder_get_manager( - struct drm_encoder *encoder) +/* + * Instead of relying on the helpers for modeset, the omap_crtc code + * calls these functions in the proper sequence. + */ + +int omap_encoder_set_enabled(struct drm_encoder *encoder, bool enabled) { struct omap_encoder *omap_encoder = to_omap_encoder(encoder); - return omap_encoder->mgr; + struct omap_dss_device *dssdev = omap_encoder->dssdev; + struct omap_dss_driver *dssdrv = dssdev->driver; + + if (enabled) { + return dssdrv->enable(dssdev); + } else { + dssdrv->disable(dssdev); + return 0; + } +} + +int omap_encoder_update(struct drm_encoder *encoder, + struct omap_overlay_manager *mgr, + struct omap_video_timings *timings) +{ + struct drm_device *dev = encoder->dev; + struct omap_encoder *omap_encoder = to_omap_encoder(encoder); + struct omap_dss_device *dssdev = omap_encoder->dssdev; + struct omap_dss_driver *dssdrv = dssdev->driver; + int ret; + + dssdev->output->manager = mgr; + + ret = dssdrv->check_timings(dssdev, timings); + if (ret) { + dev_err(dev->dev, "could not set timings: %d\n", ret); + return ret; + } + + dssdrv->set_timings(dssdev, timings); + + return 0; } /* initialize encoder */ struct drm_encoder *omap_encoder_init(struct drm_device *dev, - struct omap_overlay_manager *mgr) + struct omap_dss_device *dssdev) { struct drm_encoder *encoder = NULL; struct omap_encoder *omap_encoder; - struct omap_overlay_manager_info info; - int ret; - - DBG("%s", mgr->name); omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL); if (!omap_encoder) { @@ -133,33 +152,14 @@ struct drm_encoder *omap_encoder_init(struct drm_device *dev, goto fail; } - omap_encoder->mgr = mgr; + omap_encoder->dssdev = dssdev; + encoder = &omap_encoder->base; drm_encoder_init(dev, encoder, &omap_encoder_funcs, DRM_MODE_ENCODER_TMDS); drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs); - mgr->get_manager_info(mgr, &info); - - /* TODO: fix hard-coded setup.. */ - info.default_color = 0x00000000; - info.trans_key = 0x00000000; - info.trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST; - info.trans_enabled = false; - - ret = mgr->set_manager_info(mgr, &info); - if (ret) { - dev_err(dev->dev, "could not set manager info\n"); - goto fail; - } - - ret = mgr->apply(mgr); - if (ret) { - dev_err(dev->dev, "could not apply\n"); - goto fail; - } - return encoder; fail: diff --git a/drivers/staging/omapdrm/omap_gem_dmabuf.c b/drivers/staging/omapdrm/omap_gem_dmabuf.c index ea384003825..b6c5b5c6c8c 100644 --- a/drivers/staging/omapdrm/omap_gem_dmabuf.c +++ b/drivers/staging/omapdrm/omap_gem_dmabuf.c @@ -194,7 +194,7 @@ struct dma_buf_ops omap_dmabuf_ops = { struct dma_buf *omap_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags) { - return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, 0600); + return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, flags); } struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev, diff --git a/drivers/staging/omapdrm/omap_irq.c b/drivers/staging/omapdrm/omap_irq.c new file mode 100644 index 00000000000..2629ba7be6c --- /dev/null +++ b/drivers/staging/omapdrm/omap_irq.c @@ -0,0 +1,322 @@ +/* + * drivers/staging/omapdrm/omap_irq.c + * + * Copyright (C) 2012 Texas Instruments + * Author: Rob Clark <rob.clark@linaro.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "omap_drv.h" + +static DEFINE_SPINLOCK(list_lock); + +static void omap_irq_error_handler(struct omap_drm_irq *irq, + uint32_t irqstatus) +{ + DRM_ERROR("errors: %08x\n", irqstatus); +} + +/* call with list_lock and dispc runtime held */ +static void omap_irq_update(struct drm_device *dev) +{ + struct omap_drm_private *priv = dev->dev_private; + struct omap_drm_irq *irq; + uint32_t irqmask = priv->vblank_mask; + + BUG_ON(!spin_is_locked(&list_lock)); + + list_for_each_entry(irq, &priv->irq_list, node) + irqmask |= irq->irqmask; + + DBG("irqmask=%08x", irqmask); + + dispc_write_irqenable(irqmask); + dispc_read_irqenable(); /* flush posted write */ +} + +void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) +{ + struct omap_drm_private *priv = dev->dev_private; + unsigned long flags; + + dispc_runtime_get(); + spin_lock_irqsave(&list_lock, flags); + + if (!WARN_ON(irq->registered)) { + irq->registered = true; + list_add(&irq->node, &priv->irq_list); + omap_irq_update(dev); + } + + spin_unlock_irqrestore(&list_lock, flags); + dispc_runtime_put(); +} + +void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq) +{ + unsigned long flags; + + dispc_runtime_get(); + spin_lock_irqsave(&list_lock, flags); + + if (!WARN_ON(!irq->registered)) { + irq->registered = false; + list_del(&irq->node); + omap_irq_update(dev); + } + + spin_unlock_irqrestore(&list_lock, flags); + dispc_runtime_put(); +} + +struct omap_irq_wait { + struct omap_drm_irq irq; + int count; +}; + +static DECLARE_WAIT_QUEUE_HEAD(wait_event); + +static void wait_irq(struct omap_drm_irq *irq, uint32_t irqstatus) +{ + struct omap_irq_wait *wait = + container_of(irq, struct omap_irq_wait, irq); + wait->count--; + wake_up_all(&wait_event); +} + +struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev, + uint32_t irqmask, int count) +{ + struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL); + wait->irq.irq = wait_irq; + wait->irq.irqmask = irqmask; + wait->count = count; + omap_irq_register(dev, &wait->irq); + return wait; +} + +int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait, + unsigned long timeout) +{ + int ret = wait_event_timeout(wait_event, (wait->count <= 0), timeout); + omap_irq_unregister(dev, &wait->irq); + kfree(wait); + if (ret == 0) + return -1; + return 0; +} + +/** + * enable_vblank - enable vblank interrupt events + * @dev: DRM device + * @crtc: which irq to enable + * + * Enable vblank interrupts for @crtc. If the device doesn't have + * a hardware vblank counter, this routine should be a no-op, since + * interrupts will have to stay on to keep the count accurate. + * + * RETURNS + * Zero on success, appropriate errno if the given @crtc's vblank + * interrupt cannot be enabled. + */ +int omap_irq_enable_vblank(struct drm_device *dev, int crtc) +{ + struct omap_drm_private *priv = dev->dev_private; + unsigned long flags; + + DBG("dev=%p, crtc=%d", dev, crtc); + + dispc_runtime_get(); + spin_lock_irqsave(&list_lock, flags); + priv->vblank_mask |= pipe2vbl(crtc); + omap_irq_update(dev); + spin_unlock_irqrestore(&list_lock, flags); + dispc_runtime_put(); + + return 0; +} + +/** + * disable_vblank - disable vblank interrupt events + * @dev: DRM device + * @crtc: which irq to enable + * + * Disable vblank interrupts for @crtc. If the device doesn't have + * a hardware vblank counter, this routine should be a no-op, since + * interrupts will have to stay on to keep the count accurate. + */ +void omap_irq_disable_vblank(struct drm_device *dev, int crtc) +{ + struct omap_drm_private *priv = dev->dev_private; + unsigned long flags; + + DBG("dev=%p, crtc=%d", dev, crtc); + + dispc_runtime_get(); + spin_lock_irqsave(&list_lock, flags); + priv->vblank_mask &= ~pipe2vbl(crtc); + omap_irq_update(dev); + spin_unlock_irqrestore(&list_lock, flags); + dispc_runtime_put(); +} + +irqreturn_t omap_irq_handler(DRM_IRQ_ARGS) +{ + struct drm_device *dev = (struct drm_device *) arg; + struct omap_drm_private *priv = dev->dev_private; + struct omap_drm_irq *handler, *n; + unsigned long flags; + unsigned int id; + u32 irqstatus; + + irqstatus = dispc_read_irqstatus(); + dispc_clear_irqstatus(irqstatus); + dispc_read_irqstatus(); /* flush posted write */ + + VERB("irqs: %08x", irqstatus); + + for (id = 0; id < priv->num_crtcs; id++) + if (irqstatus & pipe2vbl(id)) + drm_handle_vblank(dev, id); + + spin_lock_irqsave(&list_lock, flags); + list_for_each_entry_safe(handler, n, &priv->irq_list, node) { + if (handler->irqmask & irqstatus) { + spin_unlock_irqrestore(&list_lock, flags); + handler->irq(handler, handler->irqmask & irqstatus); + spin_lock_irqsave(&list_lock, flags); + } + } + spin_unlock_irqrestore(&list_lock, flags); + + return IRQ_HANDLED; +} + +void omap_irq_preinstall(struct drm_device *dev) +{ + DBG("dev=%p", dev); + dispc_runtime_get(); + dispc_clear_irqstatus(0xffffffff); + dispc_runtime_put(); +} + +int omap_irq_postinstall(struct drm_device *dev) +{ + struct omap_drm_private *priv = dev->dev_private; + struct omap_drm_irq *error_handler = &priv->error_handler; + + DBG("dev=%p", dev); + + INIT_LIST_HEAD(&priv->irq_list); + + error_handler->irq = omap_irq_error_handler; + error_handler->irqmask = DISPC_IRQ_OCP_ERR; + + /* for now ignore DISPC_IRQ_SYNC_LOST_DIGIT.. really I think + * we just need to ignore it while enabling tv-out + */ + error_handler->irqmask &= ~DISPC_IRQ_SYNC_LOST_DIGIT; + + omap_irq_register(dev, error_handler); + + return 0; +} + +void omap_irq_uninstall(struct drm_device *dev) +{ + DBG("dev=%p", dev); + // TODO prolly need to call drm_irq_uninstall() somewhere too +} + +/* + * We need a special version, instead of just using drm_irq_install(), + * because we need to register the irq via omapdss. Once omapdss and + * omapdrm are merged together we can assign the dispc hwmod data to + * ourselves and drop these and just use drm_irq_{install,uninstall}() + */ + +int omap_drm_irq_install(struct drm_device *dev) +{ + int ret; + + mutex_lock(&dev->struct_mutex); + + if (dev->irq_enabled) { + mutex_unlock(&dev->struct_mutex); + return -EBUSY; + } + dev->irq_enabled = 1; + mutex_unlock(&dev->struct_mutex); + + /* Before installing handler */ + if (dev->driver->irq_preinstall) + dev->driver->irq_preinstall(dev); + + ret = dispc_request_irq(dev->driver->irq_handler, dev); + + if (ret < 0) { + mutex_lock(&dev->struct_mutex); + dev->irq_enabled = 0; + mutex_unlock(&dev->struct_mutex); + return ret; + } + + /* After installing handler */ + if (dev->driver->irq_postinstall) + ret = dev->driver->irq_postinstall(dev); + + if (ret < 0) { + mutex_lock(&dev->struct_mutex); + dev->irq_enabled = 0; + mutex_unlock(&dev->struct_mutex); + dispc_free_irq(dev); + } + + return ret; +} + +int omap_drm_irq_uninstall(struct drm_device *dev) +{ + unsigned long irqflags; + int irq_enabled, i; + + mutex_lock(&dev->struct_mutex); + irq_enabled = dev->irq_enabled; + dev->irq_enabled = 0; + mutex_unlock(&dev->struct_mutex); + + /* + * Wake up any waiters so they don't hang. + */ + if (dev->num_crtcs) { + spin_lock_irqsave(&dev->vbl_lock, irqflags); + for (i = 0; i < dev->num_crtcs; i++) { + DRM_WAKEUP(&dev->vbl_queue[i]); + dev->vblank_enabled[i] = 0; + dev->last_vblank[i] = + dev->driver->get_vblank_counter(dev, i); + } + spin_unlock_irqrestore(&dev->vbl_lock, irqflags); + } + + if (!irq_enabled) + return -EINVAL; + + if (dev->driver->irq_uninstall) + dev->driver->irq_uninstall(dev); + + dispc_free_irq(dev); + + return 0; +} diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c index 2a8e5bab49c..bb989d7f026 100644 --- a/drivers/staging/omapdrm/omap_plane.c +++ b/drivers/staging/omapdrm/omap_plane.c @@ -41,12 +41,14 @@ struct callback { struct omap_plane { struct drm_plane base; - struct omap_overlay *ovl; + int id; /* TODO rename omap_plane -> omap_plane_id in omapdss so I can use the enum */ + const char *name; struct omap_overlay_info info; + struct omap_drm_apply apply; /* position/orientation of scanout within the fb: */ struct omap_drm_window win; - + bool enabled; /* last fb that we pinned: */ struct drm_framebuffer *pinned_fb; @@ -54,189 +56,15 @@ struct omap_plane { uint32_t nformats; uint32_t formats[32]; - /* for synchronizing access to unpins fifo */ - struct mutex unpin_mutex; + struct omap_drm_irq error_irq; - /* set of bo's pending unpin until next END_WIN irq */ + /* set of bo's pending unpin until next post_apply() */ DECLARE_KFIFO_PTR(unpin_fifo, struct drm_gem_object *); - int num_unpins, pending_num_unpins; - - /* for deferred unpin when we need to wait for scanout complete irq */ - struct work_struct work; - - /* callback on next endwin irq */ - struct callback endwin; -}; -/* map from ovl->id to the irq we are interested in for scanout-done */ -static const uint32_t id2irq[] = { - [OMAP_DSS_GFX] = DISPC_IRQ_GFX_END_WIN, - [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_END_WIN, - [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_END_WIN, - [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_END_WIN, + // XXX maybe get rid of this and handle vblank in crtc too? + struct callback apply_done_cb; }; -static void dispc_isr(void *arg, uint32_t mask) -{ - struct drm_plane *plane = arg; - struct omap_plane *omap_plane = to_omap_plane(plane); - struct omap_drm_private *priv = plane->dev->dev_private; - - omap_dispc_unregister_isr(dispc_isr, plane, - id2irq[omap_plane->ovl->id]); - - queue_work(priv->wq, &omap_plane->work); -} - -static void unpin_worker(struct work_struct *work) -{ - struct omap_plane *omap_plane = - container_of(work, struct omap_plane, work); - struct callback endwin; - - mutex_lock(&omap_plane->unpin_mutex); - DBG("unpinning %d of %d", omap_plane->num_unpins, - omap_plane->num_unpins + omap_plane->pending_num_unpins); - while (omap_plane->num_unpins > 0) { - struct drm_gem_object *bo = NULL; - int ret = kfifo_get(&omap_plane->unpin_fifo, &bo); - WARN_ON(!ret); - omap_gem_put_paddr(bo); - drm_gem_object_unreference_unlocked(bo); - omap_plane->num_unpins--; - } - endwin = omap_plane->endwin; - omap_plane->endwin.fxn = NULL; - mutex_unlock(&omap_plane->unpin_mutex); - - if (endwin.fxn) - endwin.fxn(endwin.arg); -} - -static void install_irq(struct drm_plane *plane) -{ - struct omap_plane *omap_plane = to_omap_plane(plane); - struct omap_overlay *ovl = omap_plane->ovl; - int ret; - - ret = omap_dispc_register_isr(dispc_isr, plane, id2irq[ovl->id]); - - /* - * omapdss has upper limit on # of registered irq handlers, - * which we shouldn't hit.. but if we do the limit should - * be raised or bad things happen: - */ - WARN_ON(ret == -EBUSY); -} - -/* push changes down to dss2 */ -static int commit(struct drm_plane *plane) -{ - struct drm_device *dev = plane->dev; - struct omap_plane *omap_plane = to_omap_plane(plane); - struct omap_overlay *ovl = omap_plane->ovl; - struct omap_overlay_info *info = &omap_plane->info; - int ret; - - DBG("%s", ovl->name); - DBG("%dx%d -> %dx%d (%d)", info->width, info->height, info->out_width, - info->out_height, info->screen_width); - DBG("%d,%d %08x %08x", info->pos_x, info->pos_y, - info->paddr, info->p_uv_addr); - - /* NOTE: do we want to do this at all here, or just wait - * for dpms(ON) since other CRTC's may not have their mode - * set yet, so fb dimensions may still change.. - */ - ret = ovl->set_overlay_info(ovl, info); - if (ret) { - dev_err(dev->dev, "could not set overlay info\n"); - return ret; - } - - mutex_lock(&omap_plane->unpin_mutex); - omap_plane->num_unpins += omap_plane->pending_num_unpins; - omap_plane->pending_num_unpins = 0; - mutex_unlock(&omap_plane->unpin_mutex); - - /* our encoder doesn't necessarily get a commit() after this, in - * particular in the dpms() and mode_set_base() cases, so force the - * manager to update: - * - * could this be in the encoder somehow? - */ - if (ovl->manager) { - ret = ovl->manager->apply(ovl->manager); - if (ret) { - dev_err(dev->dev, "could not apply settings\n"); - return ret; - } - - /* - * NOTE: really this should be atomic w/ mgr->apply() but - * omapdss does not expose such an API - */ - if (omap_plane->num_unpins > 0) - install_irq(plane); - - } else { - struct omap_drm_private *priv = dev->dev_private; - queue_work(priv->wq, &omap_plane->work); - } - - - if (ovl->is_enabled(ovl)) { - omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y, - info->out_width, info->out_height); - } - - return 0; -} - -/* when CRTC that we are attached to has potentially changed, this checks - * if we are attached to proper manager, and if necessary updates. - */ -static void update_manager(struct drm_plane *plane) -{ - struct omap_drm_private *priv = plane->dev->dev_private; - struct omap_plane *omap_plane = to_omap_plane(plane); - struct omap_overlay *ovl = omap_plane->ovl; - struct omap_overlay_manager *mgr = NULL; - int i; - - if (plane->crtc) { - for (i = 0; i < priv->num_encoders; i++) { - struct drm_encoder *encoder = priv->encoders[i]; - if (encoder->crtc == plane->crtc) { - mgr = omap_encoder_get_manager(encoder); - break; - } - } - } - - if (ovl->manager != mgr) { - bool enabled = ovl->is_enabled(ovl); - - /* don't switch things around with enabled overlays: */ - if (enabled) - omap_plane_dpms(plane, DRM_MODE_DPMS_OFF); - - if (ovl->manager) { - DBG("disconnecting %s from %s", ovl->name, - ovl->manager->name); - ovl->unset_manager(ovl); - } - - if (mgr) { - DBG("connecting %s to %s", ovl->name, mgr->name); - ovl->set_manager(ovl, mgr); - } - - if (enabled && mgr) - omap_plane_dpms(plane, DRM_MODE_DPMS_ON); - } -} - static void unpin(void *arg, struct drm_gem_object *bo) { struct drm_plane *plane = arg; @@ -244,7 +72,6 @@ static void unpin(void *arg, struct drm_gem_object *bo) if (kfifo_put(&omap_plane->unpin_fifo, (const struct drm_gem_object **)&bo)) { - omap_plane->pending_num_unpins++; /* also hold a ref so it isn't free'd while pinned */ drm_gem_object_reference(bo); } else { @@ -264,13 +91,19 @@ static int update_pin(struct drm_plane *plane, struct drm_framebuffer *fb) DBG("%p -> %p", pinned_fb, fb); - mutex_lock(&omap_plane->unpin_mutex); + if (fb) + drm_framebuffer_reference(fb); + ret = omap_framebuffer_replace(pinned_fb, fb, plane, unpin); - mutex_unlock(&omap_plane->unpin_mutex); + + if (pinned_fb) + drm_framebuffer_unreference(pinned_fb); if (ret) { dev_err(plane->dev->dev, "could not swap %p -> %p\n", omap_plane->pinned_fb, fb); + if (fb) + drm_framebuffer_unreference(fb); omap_plane->pinned_fb = NULL; return ret; } @@ -281,31 +114,90 @@ static int update_pin(struct drm_plane *plane, struct drm_framebuffer *fb) return 0; } -/* update parameters that are dependent on the framebuffer dimensions and - * position within the fb that this plane scans out from. This is called - * when framebuffer or x,y base may have changed. - */ -static void update_scanout(struct drm_plane *plane) +static void omap_plane_pre_apply(struct omap_drm_apply *apply) { - struct omap_plane *omap_plane = to_omap_plane(plane); - struct omap_overlay_info *info = &omap_plane->info; + struct omap_plane *omap_plane = + container_of(apply, struct omap_plane, apply); struct omap_drm_window *win = &omap_plane->win; + struct drm_plane *plane = &omap_plane->base; + struct drm_device *dev = plane->dev; + struct omap_overlay_info *info = &omap_plane->info; + struct drm_crtc *crtc = plane->crtc; + enum omap_channel channel; + bool enabled = omap_plane->enabled && crtc; + bool ilace, replication; int ret; - ret = update_pin(plane, plane->fb); - if (ret) { - dev_err(plane->dev->dev, - "could not pin fb: %d\n", ret); - omap_plane_dpms(plane, DRM_MODE_DPMS_OFF); + DBG("%s, enabled=%d", omap_plane->name, enabled); + + /* if fb has changed, pin new fb: */ + update_pin(plane, enabled ? plane->fb : NULL); + + if (!enabled) { + dispc_ovl_enable(omap_plane->id, false); return; } + channel = omap_crtc_channel(crtc); + + /* update scanout: */ omap_framebuffer_update_scanout(plane->fb, win, info); - DBG("%s: %d,%d: %08x %08x (%d)", omap_plane->ovl->name, - win->src_x, win->src_y, - (u32)info->paddr, (u32)info->p_uv_addr, + DBG("%dx%d -> %dx%d (%d)", info->width, info->height, + info->out_width, info->out_height, info->screen_width); + DBG("%d,%d %08x %08x", info->pos_x, info->pos_y, + info->paddr, info->p_uv_addr); + + /* TODO: */ + ilace = false; + replication = false; + + /* and finally, update omapdss: */ + ret = dispc_ovl_setup(omap_plane->id, info, + replication, omap_crtc_timings(crtc), false); + if (ret) { + dev_err(dev->dev, "dispc_ovl_setup failed: %d\n", ret); + return; + } + + dispc_ovl_enable(omap_plane->id, true); + dispc_ovl_set_channel_out(omap_plane->id, channel); +} + +static void omap_plane_post_apply(struct omap_drm_apply *apply) +{ + struct omap_plane *omap_plane = + container_of(apply, struct omap_plane, apply); + struct drm_plane *plane = &omap_plane->base; + struct omap_overlay_info *info = &omap_plane->info; + struct drm_gem_object *bo = NULL; + struct callback cb; + + cb = omap_plane->apply_done_cb; + omap_plane->apply_done_cb.fxn = NULL; + + while (kfifo_get(&omap_plane->unpin_fifo, &bo)) { + omap_gem_put_paddr(bo); + drm_gem_object_unreference_unlocked(bo); + } + + if (cb.fxn) + cb.fxn(cb.arg); + + if (omap_plane->enabled) { + omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y, + info->out_width, info->out_height); + } +} + +static int apply(struct drm_plane *plane) +{ + if (plane->crtc) { + struct omap_plane *omap_plane = to_omap_plane(plane); + return omap_crtc_apply(plane->crtc, &omap_plane->apply); + } + return 0; } int omap_plane_mode_set(struct drm_plane *plane, @@ -313,7 +205,8 @@ int omap_plane_mode_set(struct drm_plane *plane, int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h) + uint32_t src_w, uint32_t src_h, + void (*fxn)(void *), void *arg) { struct omap_plane *omap_plane = to_omap_plane(plane); struct omap_drm_window *win = &omap_plane->win; @@ -329,17 +222,20 @@ int omap_plane_mode_set(struct drm_plane *plane, win->src_w = src_w >> 16; win->src_h = src_h >> 16; - /* note: this is done after this fxn returns.. but if we need - * to do a commit/update_scanout, etc before this returns we - * need the current value. - */ + if (fxn) { + /* omap_crtc should ensure that a new page flip + * isn't permitted while there is one pending: + */ + BUG_ON(omap_plane->apply_done_cb.fxn); + + omap_plane->apply_done_cb.fxn = fxn; + omap_plane->apply_done_cb.arg = arg; + } + plane->fb = fb; plane->crtc = crtc; - update_scanout(plane); - update_manager(plane); - - return 0; + return apply(plane); } static int omap_plane_update(struct drm_plane *plane, @@ -349,9 +245,12 @@ static int omap_plane_update(struct drm_plane *plane, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { - omap_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, - src_x, src_y, src_w, src_h); - return omap_plane_dpms(plane, DRM_MODE_DPMS_ON); + struct omap_plane *omap_plane = to_omap_plane(plane); + omap_plane->enabled = true; + return omap_plane_mode_set(plane, crtc, fb, + crtc_x, crtc_y, crtc_w, crtc_h, + src_x, src_y, src_w, src_h, + NULL, NULL); } static int omap_plane_disable(struct drm_plane *plane) @@ -364,48 +263,32 @@ static int omap_plane_disable(struct drm_plane *plane) static void omap_plane_destroy(struct drm_plane *plane) { struct omap_plane *omap_plane = to_omap_plane(plane); - DBG("%s", omap_plane->ovl->name); + + DBG("%s", omap_plane->name); + + omap_irq_unregister(plane->dev, &omap_plane->error_irq); + omap_plane_disable(plane); drm_plane_cleanup(plane); - WARN_ON(omap_plane->pending_num_unpins + omap_plane->num_unpins > 0); + + WARN_ON(!kfifo_is_empty(&omap_plane->unpin_fifo)); kfifo_free(&omap_plane->unpin_fifo); + kfree(omap_plane); } int omap_plane_dpms(struct drm_plane *plane, int mode) { struct omap_plane *omap_plane = to_omap_plane(plane); - struct omap_overlay *ovl = omap_plane->ovl; - int r; + bool enabled = (mode == DRM_MODE_DPMS_ON); + int ret = 0; - DBG("%s: %d", omap_plane->ovl->name, mode); - - if (mode == DRM_MODE_DPMS_ON) { - update_scanout(plane); - r = commit(plane); - if (!r) - r = ovl->enable(ovl); - } else { - struct omap_drm_private *priv = plane->dev->dev_private; - r = ovl->disable(ovl); - update_pin(plane, NULL); - queue_work(priv->wq, &omap_plane->work); + if (enabled != omap_plane->enabled) { + omap_plane->enabled = enabled; + ret = apply(plane); } - return r; -} - -void omap_plane_on_endwin(struct drm_plane *plane, - void (*fxn)(void *), void *arg) -{ - struct omap_plane *omap_plane = to_omap_plane(plane); - - mutex_lock(&omap_plane->unpin_mutex); - omap_plane->endwin.fxn = fxn; - omap_plane->endwin.arg = arg; - mutex_unlock(&omap_plane->unpin_mutex); - - install_irq(plane); + return ret; } /* helper to install properties which are common to planes and crtcs */ @@ -454,25 +337,13 @@ int omap_plane_set_property(struct drm_plane *plane, int ret = -EINVAL; if (property == priv->rotation_prop) { - struct omap_overlay *ovl = omap_plane->ovl; - - DBG("%s: rotation: %02x", ovl->name, (uint32_t)val); + DBG("%s: rotation: %02x", omap_plane->name, (uint32_t)val); omap_plane->win.rotation = val; - - if (ovl->is_enabled(ovl)) - ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON); - else - ret = 0; + ret = apply(plane); } else if (property == priv->zorder_prop) { - struct omap_overlay *ovl = omap_plane->ovl; - - DBG("%s: zorder: %d", ovl->name, (uint32_t)val); + DBG("%s: zorder: %02x", omap_plane->name, (uint32_t)val); omap_plane->info.zorder = val; - - if (ovl->is_enabled(ovl)) - ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON); - else - ret = 0; + ret = apply(plane); } return ret; @@ -485,20 +356,38 @@ static const struct drm_plane_funcs omap_plane_funcs = { .set_property = omap_plane_set_property, }; +static void omap_plane_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) +{ + struct omap_plane *omap_plane = + container_of(irq, struct omap_plane, error_irq); + DRM_ERROR("%s: errors: %08x\n", omap_plane->name, irqstatus); +} + +static const char *plane_names[] = { + [OMAP_DSS_GFX] = "gfx", + [OMAP_DSS_VIDEO1] = "vid1", + [OMAP_DSS_VIDEO2] = "vid2", + [OMAP_DSS_VIDEO3] = "vid3", +}; + +static const uint32_t error_irqs[] = { + [OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW, + [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW, + [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW, + [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW, +}; + /* initialize plane */ struct drm_plane *omap_plane_init(struct drm_device *dev, - struct omap_overlay *ovl, unsigned int possible_crtcs, - bool priv) + int id, bool private_plane) { + struct omap_drm_private *priv = dev->dev_private; struct drm_plane *plane = NULL; struct omap_plane *omap_plane; + struct omap_overlay_info *info; int ret; - DBG("%s: possible_crtcs=%08x, priv=%d", ovl->name, - possible_crtcs, priv); - - /* friendly reminder to update table for future hw: */ - WARN_ON(ovl->id >= ARRAY_SIZE(id2irq)); + DBG("%s: priv=%d", plane_names[id], private_plane); omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL); if (!omap_plane) { @@ -506,47 +395,50 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, goto fail; } - mutex_init(&omap_plane->unpin_mutex); - ret = kfifo_alloc(&omap_plane->unpin_fifo, 16, GFP_KERNEL); if (ret) { dev_err(dev->dev, "could not allocate unpin FIFO\n"); goto fail; } - INIT_WORK(&omap_plane->work, unpin_worker); - omap_plane->nformats = omap_framebuffer_get_formats( omap_plane->formats, ARRAY_SIZE(omap_plane->formats), - ovl->supported_modes); - omap_plane->ovl = ovl; + dss_feat_get_supported_color_modes(id)); + omap_plane->id = id; + omap_plane->name = plane_names[id]; + plane = &omap_plane->base; - drm_plane_init(dev, plane, possible_crtcs, &omap_plane_funcs, - omap_plane->formats, omap_plane->nformats, priv); + omap_plane->apply.pre_apply = omap_plane_pre_apply; + omap_plane->apply.post_apply = omap_plane_post_apply; + + omap_plane->error_irq.irqmask = error_irqs[id]; + omap_plane->error_irq.irq = omap_plane_error_irq; + omap_irq_register(dev, &omap_plane->error_irq); + + drm_plane_init(dev, plane, (1 << priv->num_crtcs) - 1, &omap_plane_funcs, + omap_plane->formats, omap_plane->nformats, private_plane); omap_plane_install_properties(plane, &plane->base); /* get our starting configuration, set defaults for parameters * we don't currently use, etc: */ - ovl->get_overlay_info(ovl, &omap_plane->info); - omap_plane->info.rotation_type = OMAP_DSS_ROT_DMA; - omap_plane->info.rotation = OMAP_DSS_ROT_0; - omap_plane->info.global_alpha = 0xff; - omap_plane->info.mirror = 0; + info = &omap_plane->info; + info->rotation_type = OMAP_DSS_ROT_DMA; + info->rotation = OMAP_DSS_ROT_0; + info->global_alpha = 0xff; + info->mirror = 0; /* Set defaults depending on whether we are a CRTC or overlay * layer. * TODO add ioctl to give userspace an API to change this.. this * will come in a subsequent patch. */ - if (priv) + if (private_plane) omap_plane->info.zorder = 0; else - omap_plane->info.zorder = ovl->id; - - update_manager(plane); + omap_plane->info.zorder = id; return plane; diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index ae38475854b..d10d75e8a33 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c @@ -937,7 +937,8 @@ short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count) dma_tmp = pci_map_single(pdev, buf, bufsize * sizeof(u8), PCI_DMA_FROMDEVICE); - + if (pci_dma_mapping_error(pdev, dma_tmp)) + return -1; if (-1 == buffer_add(&(priv->rxbuffer), buf, dma_tmp, &(priv->rxbufferhead))) { DMESGE("Unable to allocate mem RX buf"); diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index 808aab6fa5e..a9d78e9651c 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c @@ -1183,6 +1183,8 @@ void rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc, pTxFwInfo->TxRate, cb_desc); + if (pci_dma_mapping_error(priv->pdev, mapping)) + RT_TRACE(COMP_ERR, "DMA Mapping error\n");; if (cb_desc->bAMPDUEnable) { pTxFwInfo->AllowAggregation = 1; pTxFwInfo->RxMF = cb_desc->ampdu_factor; @@ -1280,6 +1282,8 @@ void rtl8192_tx_fill_cmd_desc(struct net_device *dev, dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(priv->pdev, mapping)) + RT_TRACE(COMP_ERR, "DMA Mapping error\n");; memset(entry, 0, 12); entry->LINIP = cb_desc->bLastIniPkt; entry->FirstSeg = 1; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 1a70f324552..4ebf99b3097 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -2104,7 +2104,10 @@ static short rtl8192_alloc_rx_desc_ring(struct net_device *dev) skb_tail_pointer_rsl(skb), priv->rxbuffersize, PCI_DMA_FROMDEVICE); - + if (pci_dma_mapping_error(priv->pdev, *mapping)) { + dev_kfree_skb_any(skb); + return -1; + } entry->BufferAddress = cpu_to_le32(*mapping); entry->Length = priv->rxbuffersize; @@ -2397,7 +2400,11 @@ static void rtl8192_rx_normal(struct net_device *dev) skb_tail_pointer_rsl(skb), priv->rxbuffersize, PCI_DMA_FROMDEVICE); - + if (pci_dma_mapping_error(priv->pdev, + *((dma_addr_t *)skb->cb))) { + dev_kfree_skb_any(skb); + return; + } } done: pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb)); diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index 6b73843e580..a96cd06d69d 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -63,6 +63,8 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = { {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */ /* Belkin */ {USB_DEVICE(0x050D, 0x945A)}, + /* ISY IWL - Belkin clone */ + {USB_DEVICE(0x050D, 0x11F1)}, /* Corega */ {USB_DEVICE(0x07AA, 0x0047)}, /* D-Link */ diff --git a/drivers/staging/sb105x/Kconfig b/drivers/staging/sb105x/Kconfig index ac87c5e38de..1facad62555 100644 --- a/drivers/staging/sb105x/Kconfig +++ b/drivers/staging/sb105x/Kconfig @@ -2,6 +2,7 @@ config SB105X tristate "SystemBase PCI Multiport UART" select SERIAL_CORE depends on PCI + depends on X86 help A driver for the SystemBase Multi-2/PCI serial card diff --git a/drivers/staging/sb105x/sb_pci_mp.c b/drivers/staging/sb105x/sb_pci_mp.c index edb2a85b9d5..9464f387434 100644 --- a/drivers/staging/sb105x/sb_pci_mp.c +++ b/drivers/staging/sb105x/sb_pci_mp.c @@ -3054,6 +3054,7 @@ static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd) sbdev->nr_ports = ((portnum_hex/16)*10) + (portnum_hex % 16); } break; +#ifdef CONFIG_PARPORT_PC case PCI_DEVICE_ID_MP2S1P : sbdev->nr_ports = 2; @@ -3073,6 +3074,7 @@ static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd) /* add PC compatible parallel port */ parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0); break; +#endif } ret = request_region(sbdev->uart_access_addr, (8*sbdev->nr_ports), sbdev->name); diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c index df953379809..7616f058a00 100644 --- a/drivers/staging/speakup/synth.c +++ b/drivers/staging/speakup/synth.c @@ -342,7 +342,7 @@ int synth_init(char *synth_name) mutex_lock(&spk_mutex); /* First, check if we already have it loaded. */ - for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) + for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) if (strcmp(synths[i]->name, synth_name) == 0) synth = synths[i]; @@ -423,7 +423,7 @@ int synth_add(struct spk_synth *in_synth) int i; int status = 0; mutex_lock(&spk_mutex); - for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) + for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) /* synth_remove() is responsible for rotating the array down */ if (in_synth == synths[i]) { mutex_unlock(&spk_mutex); diff --git a/drivers/staging/tidspbridge/core/_tiomap.h b/drivers/staging/tidspbridge/core/_tiomap.h index 543a127c7d4..b783bfa59b1 100644 --- a/drivers/staging/tidspbridge/core/_tiomap.h +++ b/drivers/staging/tidspbridge/core/_tiomap.h @@ -31,7 +31,7 @@ * driver should read or write to PRM/CM registers directly; they * should rely on OMAP core code to do this. */ -#include <mach-omap2/cm2xxx_3xxx.h> +#include <mach-omap2/cm3xxx.h> #include <mach-omap2/prm-regbits-34xx.h> #include <mach-omap2/cm-regbits-34xx.h> #include <dspbridge/devdefs.h> diff --git a/drivers/staging/tidspbridge/core/dsp-clock.c b/drivers/staging/tidspbridge/core/dsp-clock.c index b647207928b..2f084e181d3 100644 --- a/drivers/staging/tidspbridge/core/dsp-clock.c +++ b/drivers/staging/tidspbridge/core/dsp-clock.c @@ -121,9 +121,13 @@ void dsp_clk_exit(void) for (i = 0; i < DM_TIMER_CLOCKS; i++) omap_dm_timer_free(timer[i]); + clk_unprepare(iva2_clk); clk_put(iva2_clk); + clk_unprepare(ssi.sst_fck); clk_put(ssi.sst_fck); + clk_unprepare(ssi.ssr_fck); clk_put(ssi.ssr_fck); + clk_unprepare(ssi.ick); clk_put(ssi.ick); } @@ -145,14 +149,21 @@ void dsp_clk_init(void) iva2_clk = clk_get(&dspbridge_device.dev, "iva2_ck"); if (IS_ERR(iva2_clk)) dev_err(bridge, "failed to get iva2 clock %p\n", iva2_clk); + else + clk_prepare(iva2_clk); ssi.sst_fck = clk_get(&dspbridge_device.dev, "ssi_sst_fck"); ssi.ssr_fck = clk_get(&dspbridge_device.dev, "ssi_ssr_fck"); ssi.ick = clk_get(&dspbridge_device.dev, "ssi_ick"); - if (IS_ERR(ssi.sst_fck) || IS_ERR(ssi.ssr_fck) || IS_ERR(ssi.ick)) + if (IS_ERR(ssi.sst_fck) || IS_ERR(ssi.ssr_fck) || IS_ERR(ssi.ick)) { dev_err(bridge, "failed to get ssi: sst %p, ssr %p, ick %p\n", ssi.sst_fck, ssi.ssr_fck, ssi.ick); + } else { + clk_prepare(ssi.sst_fck); + clk_prepare(ssi.ssr_fck); + clk_prepare(ssi.ick); + } } /** diff --git a/drivers/staging/tidspbridge/core/wdt.c b/drivers/staging/tidspbridge/core/wdt.c index 1dce36fb828..7ff0e6c9803 100644 --- a/drivers/staging/tidspbridge/core/wdt.c +++ b/drivers/staging/tidspbridge/core/wdt.c @@ -63,11 +63,15 @@ int dsp_wdt_init(void) dsp_wdt.fclk = clk_get(NULL, "wdt3_fck"); if (!IS_ERR(dsp_wdt.fclk)) { + clk_prepare(dsp_wdt.fclk); + dsp_wdt.iclk = clk_get(NULL, "wdt3_ick"); if (IS_ERR(dsp_wdt.iclk)) { clk_put(dsp_wdt.fclk); dsp_wdt.fclk = NULL; ret = -EFAULT; + } else { + clk_prepare(dsp_wdt.iclk); } } else ret = -EFAULT; @@ -95,10 +99,14 @@ void dsp_wdt_exit(void) free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt); tasklet_kill(&dsp_wdt.wdt3_tasklet); - if (dsp_wdt.fclk) + if (dsp_wdt.fclk) { + clk_unprepare(dsp_wdt.fclk); clk_put(dsp_wdt.fclk); - if (dsp_wdt.iclk) + } + if (dsp_wdt.iclk) { + clk_unprepare(dsp_wdt.iclk); clk_put(dsp_wdt.iclk); + } dsp_wdt.fclk = NULL; dsp_wdt.iclk = NULL; diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c index 0331178ca3b..bf73ba26e88 100644 --- a/drivers/staging/vme/devices/vme_pio2_core.c +++ b/drivers/staging/vme/devices/vme_pio2_core.c @@ -162,11 +162,9 @@ static struct vme_driver pio2_driver = { static int __init pio2_init(void) { - int retval = 0; - if (bus_num == 0) { pr_err("No cards, skipping registration\n"); - goto err_nocard; + return -ENODEV; } if (bus_num > PIO2_CARDS_MAX) { @@ -176,15 +174,7 @@ static int __init pio2_init(void) } /* Register the PIO2 driver */ - retval = vme_register_driver(&pio2_driver, bus_num); - if (retval != 0) - goto err_reg; - - return retval; - -err_reg: -err_nocard: - return retval; + return vme_register_driver(&pio2_driver, bus_num); } static int pio2_match(struct vme_dev *vdev) diff --git a/drivers/staging/vt6656/bssdb.h b/drivers/staging/vt6656/bssdb.h index 6b2ec390e77..806cbf72fb5 100644 --- a/drivers/staging/vt6656/bssdb.h +++ b/drivers/staging/vt6656/bssdb.h @@ -90,7 +90,6 @@ typedef struct tagSRSNCapObject { } SRSNCapObject, *PSRSNCapObject; // BSS info(AP) -#pragma pack(1) typedef struct tagKnownBSS { // BSS info BOOL bActive; diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h index 5d8faf9f96e..e0d2b07ba60 100644 --- a/drivers/staging/vt6656/int.h +++ b/drivers/staging/vt6656/int.h @@ -34,7 +34,6 @@ #include "device.h" /*--------------------- Export Definitions -------------------------*/ -#pragma pack(1) typedef struct tagSINTData { BYTE byTSR0; BYTE byPkt0; diff --git a/drivers/staging/vt6656/iocmd.h b/drivers/staging/vt6656/iocmd.h index 22710cef751..ae6e2d237b2 100644 --- a/drivers/staging/vt6656/iocmd.h +++ b/drivers/staging/vt6656/iocmd.h @@ -95,13 +95,12 @@ typedef enum tagWZONETYPE { // Ioctl interface structure // Command structure // -#pragma pack(1) typedef struct tagSCmdRequest { u8 name[16]; void *data; u16 wResult; u16 wCmdCode; -} SCmdRequest, *PSCmdRequest; +} __packed SCmdRequest, *PSCmdRequest; // // Scan @@ -111,7 +110,7 @@ typedef struct tagSCmdScan { u8 ssid[SSID_MAXLEN + 2]; -} SCmdScan, *PSCmdScan; +} __packed SCmdScan, *PSCmdScan; // // BSS Join @@ -126,7 +125,7 @@ typedef struct tagSCmdBSSJoin { BOOL bPSEnable; BOOL bShareKeyAuth; -} SCmdBSSJoin, *PSCmdBSSJoin; +} __packed SCmdBSSJoin, *PSCmdBSSJoin; // // Zonetype Setting @@ -137,7 +136,7 @@ typedef struct tagSCmdZoneTypeSet { BOOL bWrite; WZONETYPE ZoneType; -} SCmdZoneTypeSet, *PSCmdZoneTypeSet; +} __packed SCmdZoneTypeSet, *PSCmdZoneTypeSet; typedef struct tagSWPAResult { char ifname[100]; @@ -145,7 +144,7 @@ typedef struct tagSWPAResult { u8 key_mgmt; u8 eap_type; BOOL authenticated; -} SWPAResult, *PSWPAResult; +} __packed SWPAResult, *PSWPAResult; typedef struct tagSCmdStartAP { @@ -157,7 +156,7 @@ typedef struct tagSCmdStartAP { BOOL bShareKeyAuth; u8 byBasicRate; -} SCmdStartAP, *PSCmdStartAP; +} __packed SCmdStartAP, *PSCmdStartAP; typedef struct tagSCmdSetWEP { @@ -167,7 +166,7 @@ typedef struct tagSCmdSetWEP { BOOL bWepKeyAvailable[WEP_NKEYS]; u32 auWepKeyLength[WEP_NKEYS]; -} SCmdSetWEP, *PSCmdSetWEP; +} __packed SCmdSetWEP, *PSCmdSetWEP; typedef struct tagSBSSIDItem { @@ -180,14 +179,14 @@ typedef struct tagSBSSIDItem { BOOL bWEPOn; u32 uRSSI; -} SBSSIDItem; +} __packed SBSSIDItem; typedef struct tagSBSSIDList { u32 uItem; SBSSIDItem sBSSIDList[0]; -} SBSSIDList, *PSBSSIDList; +} __packed SBSSIDList, *PSBSSIDList; typedef struct tagSNodeItem { @@ -208,7 +207,7 @@ typedef struct tagSNodeItem { u32 uTxAttempts; u16 wFailureRatio; -} SNodeItem; +} __packed SNodeItem; typedef struct tagSNodeList { @@ -216,7 +215,7 @@ typedef struct tagSNodeList { u32 uItem; SNodeItem sNodeList[0]; -} SNodeList, *PSNodeList; +} __packed SNodeList, *PSNodeList; typedef struct tagSCmdLinkStatus { @@ -229,7 +228,7 @@ typedef struct tagSCmdLinkStatus { u32 uChannel; u32 uLinkRate; -} SCmdLinkStatus, *PSCmdLinkStatus; +} __packed SCmdLinkStatus, *PSCmdLinkStatus; // // 802.11 counter @@ -247,7 +246,7 @@ typedef struct tagSDot11MIBCount { u32 ReceivedFragmentCount; u32 MulticastReceivedFrameCount; u32 FCSErrorCount; -} SDot11MIBCount, *PSDot11MIBCount; +} __packed SDot11MIBCount, *PSDot11MIBCount; @@ -355,13 +354,13 @@ typedef struct tagSStatMIBCount { u32 ullTxBroadcastBytes[2]; u32 ullTxMulticastBytes[2]; u32 ullTxDirectedBytes[2]; -} SStatMIBCount, *PSStatMIBCount; +} __packed SStatMIBCount, *PSStatMIBCount; typedef struct tagSCmdValue { u32 dwValue; -} SCmdValue, *PSCmdValue; +} __packed SCmdValue, *PSCmdValue; // // hostapd & viawget ioctl related @@ -431,7 +430,7 @@ struct viawget_hostapd_param { u8 ssid[32]; } scan_req; } u; -}; +} __packed; /*--------------------- Export Classes ----------------------------*/ diff --git a/drivers/staging/vt6656/iowpa.h b/drivers/staging/vt6656/iowpa.h index 959c8868f6e..2522ddec718 100644 --- a/drivers/staging/vt6656/iowpa.h +++ b/drivers/staging/vt6656/iowpa.h @@ -67,12 +67,11 @@ enum { -#pragma pack(1) typedef struct viawget_wpa_header { u8 type; u16 req_ie_len; u16 resp_ie_len; -} viawget_wpa_header; +} __packed viawget_wpa_header; struct viawget_wpa_param { u32 cmd; @@ -113,9 +112,8 @@ struct viawget_wpa_param { u8 *buf; } scan_results; } u; -}; +} __packed; -#pragma pack(1) struct viawget_scan_result { u8 bssid[6]; u8 ssid[32]; @@ -130,7 +128,7 @@ struct viawget_scan_result { int noise; int level; int maxrate; -}; +} __packed; /*--------------------- Export Classes ----------------------------*/ diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 18c06a59c09..1d31eab19d1 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -638,8 +638,8 @@ int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev) } -int prism2_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type, - int mbm) +int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm) { struct prism2_wiphy_private *priv = wiphy_priv(wiphy); wlandevice_t *wlandev = priv->wlandev; @@ -665,7 +665,8 @@ exit: return err; } -int prism2_get_tx_power(struct wiphy *wiphy, int *dbm) +int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, + int *dbm) { struct prism2_wiphy_private *priv = wiphy_priv(wiphy); wlandevice_t *wlandev = priv->wlandev; diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 4efa9bc0fcf..89bfd858bb2 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -406,7 +406,7 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) /* SSID */ req->ssid.status = P80211ENUM_msgitem_status_data_ok; req->ssid.data.len = le16_to_cpu(item->ssid.len); - req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_BSSID_LEN); + req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_SSID_MAXLEN); memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len); /* supported rates */ diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index fb4a7c94aed..f2a73bd739f 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -265,7 +265,7 @@ out_cleanup: static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, int offset) { - int ret; + int ret = 0; size_t clen; unsigned long handle; struct page *page; @@ -286,10 +286,8 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, goto out; } ret = zram_decompress_page(zram, uncmem, index); - if (ret) { - kfree(uncmem); + if (ret) goto out; - } } /* @@ -302,16 +300,18 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, user_mem = kmap_atomic(page); - if (is_partial_io(bvec)) + if (is_partial_io(bvec)) { memcpy(uncmem + offset, user_mem + bvec->bv_offset, bvec->bv_len); - else + kunmap_atomic(user_mem); + user_mem = NULL; + } else { uncmem = user_mem; + } if (page_zero_filled(uncmem)) { - kunmap_atomic(user_mem); - if (is_partial_io(bvec)) - kfree(uncmem); + if (!is_partial_io(bvec)) + kunmap_atomic(user_mem); zram_stat_inc(&zram->stats.pages_zero); zram_set_flag(zram, index, ZRAM_ZERO); ret = 0; @@ -321,9 +321,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen, zram->compress_workmem); - kunmap_atomic(user_mem); - if (is_partial_io(bvec)) - kfree(uncmem); + if (!is_partial_io(bvec)) { + kunmap_atomic(user_mem); + user_mem = NULL; + uncmem = NULL; + } if (unlikely(ret != LZO_E_OK)) { pr_err("Compression failed! err=%d\n", ret); @@ -332,8 +334,10 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, if (unlikely(clen > max_zpage_size)) { zram_stat_inc(&zram->stats.bad_compress); - src = uncmem; clen = PAGE_SIZE; + src = NULL; + if (is_partial_io(bvec)) + src = uncmem; } handle = zs_malloc(zram->mem_pool, clen); @@ -345,7 +349,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, } cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_WO); + if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) + src = kmap_atomic(page); memcpy(cmem, src, clen); + if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) + kunmap_atomic(src); zs_unmap_object(zram->mem_pool, handle); @@ -358,9 +366,10 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, if (clen <= PAGE_SIZE / 2) zram_stat_inc(&zram->stats.good_compress); - return 0; - out: + if (is_partial_io(bvec)) + kfree(uncmem); + if (ret) zram_stat64_inc(zram, &zram->stats.failed_writes); return ret; diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c index 9ac4c151eae..ba6091bf93f 100644 --- a/drivers/target/iscsi/iscsi_target_erl2.c +++ b/drivers/target/iscsi/iscsi_target_erl2.c @@ -372,7 +372,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) * made generic here. */ if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd && - iscsi_sna_gte(cmd->stat_sn, conn->sess->exp_cmd_sn)) { + iscsi_sna_gte(cmd->cmd_sn, conn->sess->exp_cmd_sn)) { list_del(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock); iscsit_free_cmd(cmd); diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 85140f7dde1..7d4ec02e29a 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -212,7 +212,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem; unsigned char *buf; unsigned char *ptr; - sense_reason_t rc; + sense_reason_t rc = TCM_NO_SENSE; u32 len = 4; /* Skip over RESERVED area in header */ int alua_access_state, primary = 0; u16 tg_pt_id, rtpi; diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index e35dbf85841..8e0290b38e4 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -2053,7 +2053,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, /* Used for APTPL metadata w/ UNREGISTER */ unsigned char *pr_aptpl_buf = NULL; unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; - sense_reason_t ret; + sense_reason_t ret = TCM_NO_SENSE; int pr_holder = 0, type; if (!se_sess || !se_lun) { diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c23c76ccef6..bd587b70661 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -541,9 +541,6 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd) void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) { - if (!(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) - transport_lun_remove_cmd(cmd); - if (transport_cmd_check_stop_to_fabric(cmd)) return; if (remove) @@ -1396,6 +1393,8 @@ static void target_complete_tmr_failure(struct work_struct *work) se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; se_cmd->se_tfo->queue_tm_rsp(se_cmd); + + transport_cmd_check_stop_to_fabric(se_cmd); } /** @@ -1688,6 +1687,7 @@ void target_execute_cmd(struct se_cmd *cmd) } cmd->t_state = TRANSPORT_PROCESSING; + cmd->transport_state |= CMD_T_ACTIVE; spin_unlock_irq(&cmd->t_state_lock); if (!target_handle_task_attr(cmd)) @@ -2597,6 +2597,16 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd, * SENSE KEY values from include/scsi/scsi.h */ switch (reason) { + case TCM_NO_SENSE: + /* CURRENT ERROR */ + buffer[0] = 0x70; + buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; + /* Not Ready */ + buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY; + /* NO ADDITIONAL SENSE INFORMATION */ + buffer[SPC_ASC_KEY_OFFSET] = 0; + buffer[SPC_ASCQ_KEY_OFFSET] = 0; + break; case TCM_NON_EXISTENT_LUN: /* CURRENT ERROR */ buffer[0] = 0x70; @@ -2743,7 +2753,7 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd, /* ILLEGAL REQUEST */ buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; /* LOGICAL UNIT COMMUNICATION FAILURE */ - buffer[SPC_ASC_KEY_OFFSET] = 0x80; + buffer[SPC_ASC_KEY_OFFSET] = 0x08; break; } /* @@ -2804,6 +2814,8 @@ void transport_send_task_abort(struct se_cmd *cmd) } cmd->scsi_status = SAM_STAT_TASK_ABORTED; + transport_lun_remove_cmd(cmd); + pr_debug("Setting SAM_STAT_TASK_ABORTED status for CDB: 0x%02x," " ITT: 0x%08x\n", cmd->t_task_cdb[0], cmd->se_tfo->get_task_tag(cmd)); diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 12d6fa21e5e..6659dd36e80 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -355,11 +355,11 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, tport = ft_tport_create(rdata->local_port); if (!tport) - return 0; /* not a target for this local port */ + goto not_target; /* not a target for this local port */ acl = ft_acl_get(tport->tpg, rdata); if (!acl) - return 0; + goto not_target; /* no target for this remote */ if (!rspp) goto fill; @@ -396,12 +396,18 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, /* * OR in our service parameters with other provider (initiator), if any. - * TBD XXX - indicate RETRY capability? */ fill: fcp_parm = ntohl(spp->spp_params); + fcp_parm &= ~FCP_SPPF_RETRY; spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN); return FC_SPP_RESP_ACK; + +not_target: + fcp_parm = ntohl(spp->spp_params); + fcp_parm &= ~FCP_SPPF_TARG_FCN; + spp->spp_params = htonl(fcp_parm); + return 0; } /** diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index be6a373601b..79ff3a5e925 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -441,6 +441,8 @@ static int pty_bsd_ioctl(struct tty_struct *tty, return pty_get_pktmode(tty, (int __user *)arg); case TIOCSIG: /* Send signal to other side of pty */ return pty_signal(tty, (int) arg); + case TIOCGPTN: /* TTY returns ENOTTY, but glibc expects EINVAL here */ + return -EINVAL; } return -ENOIOCTLCMD; } diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index d085e3a8ec0..f9320437a64 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -300,6 +300,12 @@ static const struct serial8250_config uart_config[] = { UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, .flags = UART_CAP_FIFO, }, + [PORT_BRCM_TRUMANAGE] = { + .name = "TruManage", + .fifo_size = 1, + .tx_loadsz = 1024, + .flags = UART_CAP_HFIFO, + }, [PORT_8250_CIR] = { .name = "CIR port" } @@ -1490,6 +1496,11 @@ void serial8250_tx_chars(struct uart_8250_port *up) port->icount.tx++; if (uart_circ_empty(xmit)) break; + if (up->capabilities & UART_CAP_HFIFO) { + if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) != + BOTH_EMPTY) + break; + } } while (--count > 0); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 3b4ea84898c..12caa1292b7 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -40,6 +40,7 @@ struct serial8250_config { #define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */ #define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */ #define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */ +#define UART_CAP_HFIFO (1 << 14) /* UART has a "hidden" FIFO */ #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 1d0dba2d562..096d2ef48b3 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -79,7 +79,7 @@ static int dw8250_handle_irq(struct uart_port *p) } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { /* Clear the USR and write the LCR again. */ (void)p->serial_in(p, UART_USR); - p->serial_out(p, d->last_lcr, UART_LCR); + p->serial_out(p, UART_LCR, d->last_lcr); return 1; } diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 26b9dc012ed..a27a98e1b06 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1085,6 +1085,18 @@ pci_omegapci_setup(struct serial_private *priv, return setup_port(priv, port, 2, idx * 8, 0); } +static int +pci_brcm_trumanage_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + int ret = pci_default_setup(priv, board, port, idx); + + port->port.type = PORT_BRCM_TRUMANAGE; + port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); + return ret; +} + static int skip_tx_en_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_8250_port *port, int idx) @@ -1301,9 +1313,10 @@ pci_wch_ch353_setup(struct serial_private *priv, #define PCI_VENDOR_ID_AGESTAR 0x5372 #define PCI_DEVICE_ID_AGESTAR_9375 0x6872 #define PCI_VENDOR_ID_ASIX 0x9710 -#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0019 #define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020 #define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021 +#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022 +#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ @@ -1954,6 +1967,17 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .setup = pci_xr17v35x_setup, }, /* + * Broadcom TruManage (NetXtreme) + */ + { + .vendor = PCI_VENDOR_ID_BROADCOM, + .device = PCI_DEVICE_ID_BROADCOM_TRUMANAGE, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_brcm_trumanage_setup, + }, + + /* * Default "match everything" terminator entry */ { @@ -2148,6 +2172,7 @@ enum pci_board_num_t { pbn_ce4100_1_115200, pbn_omegapci, pbn_NETMOS9900_2s_115200, + pbn_brcm_trumanage, }; /* @@ -2246,7 +2271,7 @@ static struct pciserial_board pci_boards[] = { [pbn_b0_8_1152000_200] = { .flags = FL_BASE0, - .num_ports = 2, + .num_ports = 8, .base_baud = 1152000, .uart_offset = 0x200, }, @@ -2892,6 +2917,12 @@ static struct pciserial_board pci_boards[] = { .num_ports = 2, .base_baud = 115200, }, + [pbn_brcm_trumanage] = { + .flags = FL_BASE0, + .num_ports = 1, + .reg_shift = 2, + .base_baud = 115200, + }, }; static const struct pci_device_id blacklist[] = { @@ -4471,6 +4502,13 @@ static struct pci_device_id serial_pci_tbl[] = { pbn_omegapci }, /* + * Broadcom TruManage + */ + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BROADCOM_TRUMANAGE, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_brcm_trumanage }, + + /* * AgeStar as-prs2-009 */ { PCI_VENDOR_ID_AGESTAR, PCI_DEVICE_ID_AGESTAR_9375, diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 675d94ab0af..8cb6d8d66a1 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -637,6 +637,7 @@ static void ifx_port_shutdown(struct tty_port *port) clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags); mrdy_set_low(ifx_dev); + del_timer(&ifx_dev->spi_timer); clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); tasklet_kill(&ifx_dev->io_work_tasklet); } @@ -810,7 +811,8 @@ static void ifx_spi_io(unsigned long data) ifx_dev->spi_xfer.cs_change = 0; ifx_dev->spi_xfer.speed_hz = ifx_dev->spi_dev->max_speed_hz; /* ifx_dev->spi_xfer.speed_hz = 390625; */ - ifx_dev->spi_xfer.bits_per_word = spi_bpw; + ifx_dev->spi_xfer.bits_per_word = + ifx_dev->spi_dev->bits_per_word; ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer; ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer; diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 6db23b035ef..e55615eb34a 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -253,7 +253,7 @@ static void mxs_auart_tx_chars(struct mxs_auart_port *s) struct circ_buf *xmit = &s->port.state->xmit; if (auart_dma_enabled(s)) { - int i = 0; + u32 i = 0; int size; void *buffer = s->tx_dma_buf; @@ -412,10 +412,12 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl) u32 ctrl = readl(u->membase + AUART_CTRL2); - ctrl &= ~AUART_CTRL2_RTSEN; + ctrl &= ~(AUART_CTRL2_RTSEN | AUART_CTRL2_RTS); if (mctrl & TIOCM_RTS) { if (tty_port_cts_enabled(&u->state->port)) ctrl |= AUART_CTRL2_RTSEN; + else + ctrl |= AUART_CTRL2_RTS; } s->ctrl = mctrl; diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 12e5249d053..e514b3a4dc5 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1006,7 +1006,6 @@ static void s3c24xx_serial_resetport(struct uart_port *port, ucon &= ucon_mask; wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); - wr_regl(port, S3C2410_ULCON, cfg->ulcon); /* reset both fifos */ wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 8fd181436a6..d5ed9f61300 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c @@ -604,7 +604,7 @@ static int vt8500_serial_probe(struct platform_device *pdev) vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0); - if (vt8500_port->clk) { + if (!IS_ERR(vt8500_port->clk)) { vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk); } else { /* use the default of 24Mhz if not specified and warn */ diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 4c90b510d01..640ae6c6d2d 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -37,6 +37,7 @@ config USB_ARCH_HAS_EHCI default y if ARCH_W90X900 default y if ARCH_AT91 default y if ARCH_MXC + default y if ARCH_MXS default y if ARCH_OMAP3 default y if ARCH_CNS3XXX default y if ARCH_VT8500 diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index caecad9213f..8e9d31277c4 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -70,6 +70,9 @@ static int host_start(struct ci13xxx *ci) else ci->hcd = hcd; + if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING) + hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); + return ret; } diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 8d809a811e1..2d92cce260d 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1602,6 +1602,9 @@ static const struct usb_device_id acm_ids[] = { { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */ .driver_info = NO_UNION_NORMAL, }, + { USB_DEVICE(0x05f9, 0x4002), /* PSC Scanning, Magellan 800i */ + .driver_info = NO_UNION_NORMAL, + }, { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ }, diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a815fd2cc5e..957ed2c4148 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -877,6 +877,60 @@ static int hub_hub_status(struct usb_hub *hub, return ret; } +static int hub_set_port_link_state(struct usb_hub *hub, int port1, + unsigned int link_status) +{ + return set_port_feature(hub->hdev, + port1 | (link_status << 3), + USB_PORT_FEAT_LINK_STATE); +} + +/* + * If USB 3.0 ports are placed into the Disabled state, they will no longer + * detect any device connects or disconnects. This is generally not what the + * USB core wants, since it expects a disabled port to produce a port status + * change event when a new device connects. + * + * Instead, set the link state to Disabled, wait for the link to settle into + * that state, clear any change bits, and then put the port into the RxDetect + * state. + */ +static int hub_usb3_port_disable(struct usb_hub *hub, int port1) +{ + int ret; + int total_time; + u16 portchange, portstatus; + + if (!hub_is_superspeed(hub->hdev)) + return -EINVAL; + + ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED); + if (ret) { + dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", + port1, ret); + return ret; + } + + /* Wait for the link to enter the disabled state. */ + for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) { + ret = hub_port_status(hub, port1, &portstatus, &portchange); + if (ret < 0) + return ret; + + if ((portstatus & USB_PORT_STAT_LINK_STATE) == + USB_SS_PORT_LS_SS_DISABLED) + break; + if (total_time >= HUB_DEBOUNCE_TIMEOUT) + break; + msleep(HUB_DEBOUNCE_STEP); + } + if (total_time >= HUB_DEBOUNCE_TIMEOUT) + dev_warn(hub->intfdev, "Could not disable port %d after %d ms\n", + port1, total_time); + + return hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_RX_DETECT); +} + static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) { struct usb_device *hdev = hub->hdev; @@ -885,8 +939,13 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) if (hub->ports[port1 - 1]->child && set_state) usb_set_device_state(hub->ports[port1 - 1]->child, USB_STATE_NOTATTACHED); - if (!hub->error && !hub_is_superspeed(hub->hdev)) - ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); + if (!hub->error) { + if (hub_is_superspeed(hub->hdev)) + ret = hub_usb3_port_disable(hub, port1); + else + ret = clear_port_feature(hdev, port1, + USB_PORT_FEAT_ENABLE); + } if (ret) dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", port1, ret); @@ -2440,7 +2499,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub) #define HUB_SHORT_RESET_TIME 10 #define HUB_BH_RESET_TIME 50 #define HUB_LONG_RESET_TIME 200 -#define HUB_RESET_TIMEOUT 500 +#define HUB_RESET_TIMEOUT 800 static int hub_port_reset(struct usb_hub *hub, int port1, struct usb_device *udev, unsigned int delay, bool warm); @@ -2475,6 +2534,10 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, if (ret < 0) return ret; + /* The port state is unknown until the reset completes. */ + if ((portstatus & USB_PORT_STAT_RESET)) + goto delay; + /* * Some buggy devices require a warm reset to be issued even * when the port appears not to be connected. @@ -2520,11 +2583,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, if ((portchange & USB_PORT_STAT_C_CONNECTION)) return -ENOTCONN; - /* if we`ve finished resetting, then break out of - * the loop - */ - if (!(portstatus & USB_PORT_STAT_RESET) && - (portstatus & USB_PORT_STAT_ENABLE)) { + if ((portstatus & USB_PORT_STAT_ENABLE)) { if (hub_is_wusb(hub)) udev->speed = USB_SPEED_WIRELESS; else if (hub_is_superspeed(hub->hdev)) @@ -2538,10 +2597,15 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, return 0; } } else { - if (portchange & USB_PORT_STAT_C_BH_RESET) - return 0; + if (!(portstatus & USB_PORT_STAT_CONNECTION) || + hub_port_warm_reset_required(hub, + portstatus)) + return -ENOTCONN; + + return 0; } +delay: /* switch to the long delay after two short delay failures */ if (delay_time >= 2 * HUB_SHORT_RESET_TIME) delay = HUB_LONG_RESET_TIME; @@ -2565,14 +2629,11 @@ static void hub_port_finish_reset(struct usb_hub *hub, int port1, msleep(10 + 40); update_devnum(udev, 0); hcd = bus_to_hcd(udev->bus); - if (hcd->driver->reset_device) { - *status = hcd->driver->reset_device(hcd, udev); - if (*status < 0) { - dev_err(&udev->dev, "Cannot reset " - "HCD device state\n"); - break; - } - } + /* The xHC may think the device is already reset, + * so ignore the status. + */ + if (hcd->driver->reset_device) + hcd->driver->reset_device(hcd, udev); } /* FALL THROUGH */ case -ENOTCONN: @@ -2580,16 +2641,16 @@ static void hub_port_finish_reset(struct usb_hub *hub, int port1, clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_RESET); /* FIXME need disconnect() for NOTATTACHED device */ - if (warm) { + if (hub_is_superspeed(hub->hdev)) { clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_BH_PORT_RESET); clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_PORT_LINK_STATE); - } else { + } + if (!warm) usb_set_device_state(udev, *status ? USB_STATE_NOTATTACHED : USB_STATE_DEFAULT); - } break; } } @@ -2939,7 +3000,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) static int finish_port_resume(struct usb_device *udev) { int status = 0; - u16 devstatus; + u16 devstatus = 0; /* caller owns the udev device lock */ dev_dbg(&udev->dev, "%s\n", @@ -2984,7 +3045,13 @@ static int finish_port_resume(struct usb_device *udev) if (status) { dev_dbg(&udev->dev, "gone after usb resume? status %d\n", status); - } else if (udev->actconfig) { + /* + * There are a few quirky devices which violate the standard + * by claiming to have remote wakeup enabled after a reset, + * which crash if the feature is cleared, hence check for + * udev->reset_resume + */ + } else if (udev->actconfig && !udev->reset_resume) { le16_to_cpus(&devstatus); if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { status = usb_control_msg(udev, @@ -4638,9 +4705,14 @@ static void hub_events(void) * SS.Inactive state. */ if (hub_port_warm_reset_required(hub, portstatus)) { + int status; + dev_dbg(hub_dev, "warm reset port %d\n", i); - hub_port_reset(hub, i, NULL, + status = hub_port_reset(hub, i, NULL, HUB_BH_RESET_TIME, true); + if (status < 0) + hub_port_disable(hub, i, 1); + connect_change = 0; } if (connect_change) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index fdefd9c7f7a..3113c1d7144 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -43,6 +43,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Creative SB Audigy 2 NX */ { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Microsoft LifeCam-VX700 v2.0 */ + { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Logitech Quickcam Fusion */ { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 92604b4f971..5945aadaa1c 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -56,7 +56,7 @@ #define dump_register(nm) \ { \ .name = __stringify(nm), \ - .offset = DWC3_ ##nm, \ + .offset = DWC3_ ##nm - DWC3_GLOBALS_REGS_START, \ } static const struct debugfs_reg32 dwc3_regs[] = { diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 2e43b332aae..2fdd767f8fe 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1605,6 +1605,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc) if (epnum == 0 || epnum == 1) { dep->endpoint.maxpacket = 512; + dep->endpoint.maxburst = 1; dep->endpoint.ops = &dwc3_gadget_ep0_ops; if (!epnum) dwc->gadget.ep0 = &dep->endpoint; diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index fc0ec5e0d58..d9f6b937249 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -3231,7 +3231,7 @@ static int udc_pci_probe( } if (!pdev->irq) { - dev_err(&dev->pdev->dev, "irq not set\n"); + dev_err(&pdev->dev, "irq not set\n"); kfree(dev); dev = NULL; retval = -ENODEV; @@ -3250,7 +3250,7 @@ static int udc_pci_probe( dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR); if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) { - dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq); + dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq); kfree(dev); dev = NULL; retval = -EBUSY; diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 95d584dbed1..8cf0c0f6fa1 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -130,10 +130,7 @@ static const char ep0name[] = "ep0"; static const char *const ep_name[] = { ep0name, /* everyone has ep0 */ - /* act like a net2280: high speed, six configurable endpoints */ - "ep-a", "ep-b", "ep-c", "ep-d", "ep-e", "ep-f", - - /* or like pxa250: fifteen fixed function endpoints */ + /* act like a pxa250: fifteen fixed function endpoints */ "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int", "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int", "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso", @@ -141,6 +138,10 @@ static const char *const ep_name[] = { /* or like sa1100: two fixed function endpoints */ "ep1out-bulk", "ep2in-bulk", + + /* and now some generic EPs so we have enough in multi config */ + "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in", + "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out", }; #define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name) diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 4a6961c517f..8c2f2512114 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -1153,15 +1153,15 @@ static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts) pr_err("%s: unmapped value: %lu\n", opts, value); return -EINVAL; } - } - else if (!memcmp(opts, "gid", 3)) + } else if (!memcmp(opts, "gid", 3)) { data->perms.gid = make_kgid(current_user_ns(), value); if (!gid_valid(data->perms.gid)) { pr_err("%s: unmapped value: %lu\n", opts, value); return -EINVAL; } - else + } else { goto invalid; + } break; default: diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c index 1b0f086426b..d3bd7b095ba 100644 --- a/drivers/usb/gadget/fsl_mxc_udc.c +++ b/drivers/usb/gadget/fsl_mxc_udc.c @@ -18,14 +18,13 @@ #include <linux/platform_device.h> #include <linux/io.h> -#include <mach/hardware.h> - static struct clk *mxc_ahb_clk; static struct clk *mxc_per_clk; static struct clk *mxc_ipg_clk; /* workaround ENGcm09152 for i.MX35 */ -#define USBPHYCTRL_OTGBASE_OFFSET 0x608 +#define MX35_USBPHYCTRL_OFFSET 0x600 +#define USBPHYCTRL_OTGBASE_OFFSET 0x8 #define USBPHYCTRL_EVDO (1 << 23) int fsl_udc_clk_init(struct platform_device *pdev) @@ -59,7 +58,7 @@ int fsl_udc_clk_init(struct platform_device *pdev) clk_prepare_enable(mxc_per_clk); /* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */ - if (!cpu_is_mx51()) { + if (!strcmp(pdev->id_entry->name, "imx-udc-mx27")) { freq = clk_get_rate(mxc_per_clk); if (pdata->phy_mode != FSL_USB2_PHY_ULPI && (freq < 59999000 || freq > 60001000)) { @@ -79,27 +78,40 @@ eclkrate: return ret; } -void fsl_udc_clk_finalize(struct platform_device *pdev) +int fsl_udc_clk_finalize(struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; - if (cpu_is_mx35()) { - unsigned int v; + int ret = 0; - /* workaround ENGcm09152 for i.MX35 */ - if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) { - v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + - USBPHYCTRL_OTGBASE_OFFSET)); - writel(v | USBPHYCTRL_EVDO, - MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + - USBPHYCTRL_OTGBASE_OFFSET)); + /* workaround ENGcm09152 for i.MX35 */ + if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) { + unsigned int v; + struct resource *res = platform_get_resource + (pdev, IORESOURCE_MEM, 0); + void __iomem *phy_regs = ioremap(res->start + + MX35_USBPHYCTRL_OFFSET, 512); + if (!phy_regs) { + dev_err(&pdev->dev, "ioremap for phy address fails\n"); + ret = -EINVAL; + goto ioremap_err; } + + v = readl(phy_regs + USBPHYCTRL_OTGBASE_OFFSET); + writel(v | USBPHYCTRL_EVDO, + phy_regs + USBPHYCTRL_OTGBASE_OFFSET); + + iounmap(phy_regs); } + +ioremap_err: /* ULPI transceivers don't need usbpll */ if (pdata->phy_mode == FSL_USB2_PHY_ULPI) { clk_disable_unprepare(mxc_per_clk); mxc_per_clk = NULL; } + + return ret; } void fsl_udc_clk_release(void) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index c19f7f13790..667275cb7ba 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -41,6 +41,7 @@ #include <linux/fsl_devices.h> #include <linux/dmapool.h> #include <linux/delay.h> +#include <linux/of_device.h> #include <asm/byteorder.h> #include <asm/io.h> @@ -2438,11 +2439,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev) unsigned int i; u32 dccparams; - if (strcmp(pdev->name, driver_name)) { - VDBG("Wrong device"); - return -ENODEV; - } - udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL); if (udc_controller == NULL) { ERR("malloc udc failed\n"); @@ -2547,7 +2543,9 @@ static int __init fsl_udc_probe(struct platform_device *pdev) dr_controller_setup(udc_controller); } - fsl_udc_clk_finalize(pdev); + ret = fsl_udc_clk_finalize(pdev); + if (ret) + goto err_free_irq; /* Setup gadget structure */ udc_controller->gadget.ops = &fsl_gadget_ops; @@ -2756,22 +2754,32 @@ static int fsl_udc_otg_resume(struct device *dev) return fsl_udc_resume(NULL); } - /*------------------------------------------------------------------------- Register entry point for the peripheral controller driver --------------------------------------------------------------------------*/ - +static const struct platform_device_id fsl_udc_devtype[] = { + { + .name = "imx-udc-mx27", + }, { + .name = "imx-udc-mx51", + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(platform, fsl_udc_devtype); static struct platform_driver udc_driver = { - .remove = __exit_p(fsl_udc_remove), + .remove = __exit_p(fsl_udc_remove), + /* Just for FSL i.mx SoC currently */ + .id_table = fsl_udc_devtype, /* these suspend and resume are not usb suspend and resume */ - .suspend = fsl_udc_suspend, - .resume = fsl_udc_resume, - .driver = { - .name = (char *)driver_name, - .owner = THIS_MODULE, - /* udc suspend/resume called from OTG driver */ - .suspend = fsl_udc_otg_suspend, - .resume = fsl_udc_otg_resume, + .suspend = fsl_udc_suspend, + .resume = fsl_udc_resume, + .driver = { + .name = (char *)driver_name, + .owner = THIS_MODULE, + /* udc suspend/resume called from OTG driver */ + .suspend = fsl_udc_otg_suspend, + .resume = fsl_udc_otg_resume, }, }; diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index f61a967f708..c6703bb07b2 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -592,15 +592,16 @@ static inline struct ep_queue_head *get_qh_by_ep(struct fsl_ep *ep) struct platform_device; #ifdef CONFIG_ARCH_MXC int fsl_udc_clk_init(struct platform_device *pdev); -void fsl_udc_clk_finalize(struct platform_device *pdev); +int fsl_udc_clk_finalize(struct platform_device *pdev); void fsl_udc_clk_release(void); #else static inline int fsl_udc_clk_init(struct platform_device *pdev) { return 0; } -static inline void fsl_udc_clk_finalize(struct platform_device *pdev) +static inline int fsl_udc_clk_finalize(struct platform_device *pdev) { + return 0; } static inline void fsl_udc_clk_release(void) { diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 379aac7b82f..6e8b1272ebc 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -1012,7 +1012,7 @@ static void udc_clock_enable(struct mv_udc *udc) unsigned int i; for (i = 0; i < udc->clknum; i++) - clk_enable(udc->clk[i]); + clk_prepare_enable(udc->clk[i]); } static void udc_clock_disable(struct mv_udc *udc) @@ -1020,7 +1020,7 @@ static void udc_clock_disable(struct mv_udc *udc) unsigned int i; for (i = 0; i < udc->clknum; i++) - clk_disable(udc->clk[i]); + clk_disable_unprepare(udc->clk[i]); } static void udc_stop(struct mv_udc *udc) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 141971d9051..439c3f972f8 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -3477,12 +3477,11 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg) /** * s3c_hsotg_release - release callback for hsotg device * @dev: Device to for which release is called + * + * Nothing to do as the resource is allocated using devm_ API. */ static void s3c_hsotg_release(struct device *dev) { - struct s3c_hsotg *hsotg = dev_get_drvdata(dev); - - kfree(hsotg); } /** diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 4f7f76f00c7..7cacd6ae818 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -1794,9 +1794,10 @@ static int tcm_usbg_drop_nexus(struct usbg_tpg *tpg) tpg->tpg_nexus = NULL; kfree(tv_nexus); + ret = 0; out: mutex_unlock(&tpg->tpg_mutex); - return 0; + return ret; } static ssize_t tcm_usbg_tpg_store_nexus( diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index d0f95482f40..598dcc1212f 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -887,7 +887,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) pr_debug("gs_close: ttyGS%d (%p,%p) done!\n", port->port_num, tty, file); - wake_up_interruptible(&port->port.close_wait); + wake_up(&port->port.close_wait); exit: spin_unlock_irq(&port->port_lock); } diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index d6bb128ce21..3a21c5d683c 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -148,7 +148,7 @@ config USB_EHCI_FSL Variation of ARC USB block used in some Freescale chips. config USB_EHCI_MXC - bool "Support for Freescale i.MX on-chip EHCI USB controller" + tristate "Support for Freescale i.MX on-chip EHCI USB controller" depends on USB_EHCI_HCD && ARCH_MXC select USB_EHCI_ROOT_HUB_TT ---help--- diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 1eb4c3006e9..001fbff2fde 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_PCI) += pci-quirks.o obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o +obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index fd9b5424b86..d81d2fcbff1 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -230,7 +230,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, switch (phy_mode) { case FSL_USB2_PHY_ULPI: - if (pdata->controller_ver) { + if (pdata->have_sysif_regs && pdata->controller_ver) { /* controller version 1.6 or above */ setbits32(non_ehci + FSL_SOC_USB_CTRL, ULPI_PHY_CLK_SEL); @@ -251,7 +251,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, portsc |= PORT_PTS_PTW; /* fall through */ case FSL_USB2_PHY_UTMI: - if (pdata->controller_ver) { + if (pdata->have_sysif_regs && pdata->controller_ver) { /* controller version 1.6 or above */ setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN); mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to @@ -267,7 +267,8 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, break; } - if (pdata->controller_ver && (phy_mode == FSL_USB2_PHY_ULPI)) { + if (pdata->have_sysif_regs && pdata->controller_ver && + (phy_mode == FSL_USB2_PHY_ULPI)) { /* check PHY_CLK_VALID to get phy clk valid */ if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) & PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) { @@ -278,7 +279,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); - if (phy_mode != FSL_USB2_PHY_ULPI) + if (phy_mode != FSL_USB2_PHY_ULPI && pdata->have_sysif_regs) setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN); return 0; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c97503bb0b0..09537b2f100 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -74,10 +74,6 @@ static const char hcd_name [] = "ehci_hcd"; #undef VERBOSE_DEBUG #undef EHCI_URB_TRACE -#ifdef DEBUG -#define EHCI_STATS -#endif - /* magic numbers that can affect system performance */ #define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ #define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ @@ -1250,11 +1246,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_fsl_driver #endif -#ifdef CONFIG_USB_EHCI_MXC -#include "ehci-mxc.c" -#define PLATFORM_DRIVER ehci_mxc_driver -#endif - #ifdef CONFIG_USB_EHCI_SH #include "ehci-sh.c" #define PLATFORM_DRIVER ehci_hcd_sh_driver @@ -1352,7 +1343,8 @@ MODULE_LICENSE ("GPL"); #if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \ !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \ - !defined(CONFIG_USB_CHIPIDEA_HOST) && \ + !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \ + !IS_ENABLED(CONFIG_USB_EHCI_MXC) && \ !defined(PLATFORM_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && \ !defined(OF_PLATFORM_DRIVER) && \ diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index f7bfc0b898b..6c56297ea16 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -43,7 +43,7 @@ static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv) unsigned int i; for (i = 0; i < ehci_mv->clknum; i++) - clk_enable(ehci_mv->clk[i]); + clk_prepare_enable(ehci_mv->clk[i]); } static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv) @@ -51,7 +51,7 @@ static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv) unsigned int i; for (i = 0; i < ehci_mv->clknum; i++) - clk_disable(ehci_mv->clk[i]); + clk_disable_unprepare(ehci_mv->clk[i]); } static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv) diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index ec7f5d2c90d..dedb80bb8d4 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -17,75 +17,38 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/io.h> #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/usb/otg.h> #include <linux/usb/ulpi.h> #include <linux/slab.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> #include <linux/platform_data/usb-ehci-mxc.h> #include <asm/mach-types.h> +#include "ehci.h" + +#define DRIVER_DESC "Freescale On-Chip EHCI Host driver" + +static const char hcd_name[] = "ehci-mxc"; + #define ULPI_VIEWPORT_OFFSET 0x170 struct ehci_mxc_priv { struct clk *usbclk, *ahbclk, *phyclk; - struct usb_hcd *hcd; }; -/* called during probe() after chip reset completes */ -static int ehci_mxc_setup(struct usb_hcd *hcd) -{ - hcd->has_tt = 1; - - return ehci_setup(hcd); -} +static struct hc_driver __read_mostly ehci_mxc_hc_driver; -static const struct hc_driver ehci_mxc_hc_driver = { - .description = hcd_name, - .product_desc = "Freescale On-Chip EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_USB2 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .reset = ehci_mxc_setup, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, +static const struct ehci_driver_overrides ehci_mxc_overrides __initdata = { + .extra_priv_size = sizeof(struct ehci_mxc_priv), }; static int ehci_mxc_drv_probe(struct platform_device *pdev) @@ -112,12 +75,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) if (!hcd) return -ENOMEM; - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - ret = -ENOMEM; - goto err_alloc; - } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "Found HC with no register addr. Check setup!\n"); @@ -135,6 +92,10 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) goto err_alloc; } + hcd->has_tt = 1; + ehci = hcd_to_ehci(hcd); + priv = (struct ehci_mxc_priv *) ehci->priv; + /* enable clocks */ priv->usbclk = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(priv->usbclk)) { @@ -169,8 +130,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) mdelay(10); } - ehci = hcd_to_ehci(hcd); - /* EHCI registers start at offset 0x100 */ ehci->caps = hcd->regs + 0x100; ehci->regs = hcd->regs + 0x100 + @@ -198,8 +157,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) } } - priv->hcd = hcd; - platform_set_drvdata(pdev, priv); + platform_set_drvdata(pdev, hcd); ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) @@ -244,8 +202,11 @@ err_alloc: static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) { struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data; - struct ehci_mxc_priv *priv = platform_get_drvdata(pdev); - struct usb_hcd *hcd = priv->hcd; + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + struct ehci_mxc_priv *priv = (struct ehci_mxc_priv *) ehci->priv; + + usb_remove_hcd(hcd); if (pdata && pdata->exit) pdata->exit(pdev); @@ -253,23 +214,20 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) if (pdata->otg) usb_phy_shutdown(pdata->otg); - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - platform_set_drvdata(pdev, NULL); - clk_disable_unprepare(priv->usbclk); clk_disable_unprepare(priv->ahbclk); if (priv->phyclk) clk_disable_unprepare(priv->phyclk); + usb_put_hcd(hcd); + platform_set_drvdata(pdev, NULL); return 0; } static void ehci_mxc_drv_shutdown(struct platform_device *pdev) { - struct ehci_mxc_priv *priv = platform_get_drvdata(pdev); - struct usb_hcd *hcd = priv->hcd; + struct usb_hcd *hcd = platform_get_drvdata(pdev); if (hcd->driver->shutdown) hcd->driver->shutdown(hcd); @@ -279,9 +237,31 @@ MODULE_ALIAS("platform:mxc-ehci"); static struct platform_driver ehci_mxc_driver = { .probe = ehci_mxc_drv_probe, - .remove = __exit_p(ehci_mxc_drv_remove), + .remove = ehci_mxc_drv_remove, .shutdown = ehci_mxc_drv_shutdown, .driver = { .name = "mxc-ehci", }, }; + +static int __init ehci_mxc_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ehci_init_driver(&ehci_mxc_hc_driver, &ehci_mxc_overrides); + return platform_driver_register(&ehci_mxc_driver); +} +module_init(ehci_mxc_init); + +static void __exit ehci_mxc_cleanup(void) +{ + platform_driver_unregister(&ehci_mxc_driver); +} +module_exit(ehci_mxc_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Sascha Hauer"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index dabb2049482..170b9399e09 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -200,6 +200,26 @@ static int ehci_pci_setup(struct usb_hcd *hcd) break; } + /* optional debug port, normally in the first BAR */ + temp = pci_find_capability(pdev, PCI_CAP_ID_DBG); + if (temp) { + pci_read_config_dword(pdev, temp, &temp); + temp >>= 16; + if (((temp >> 13) & 7) == 1) { + u32 hcs_params = ehci_readl(ehci, + &ehci->caps->hcs_params); + + temp &= 0x1fff; + ehci->debug = hcd->regs + temp; + temp = ehci_readl(ehci, &ehci->debug->control); + ehci_info(ehci, "debug port %d%s\n", + HCS_DEBUG_PORT(hcs_params), + (temp & DBGP_ENABLED) ? " IN USE" : ""); + if (!(temp & DBGP_ENABLED)) + ehci->debug = NULL; + } + } + retval = ehci_setup(hcd); if (retval) return retval; @@ -228,25 +248,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) break; } - /* optional debug port, normally in the first BAR */ - temp = pci_find_capability(pdev, 0x0a); - if (temp) { - pci_read_config_dword(pdev, temp, &temp); - temp >>= 16; - if ((temp & (3 << 13)) == (1 << 13)) { - temp &= 0x1fff; - ehci->debug = hcd->regs + temp; - temp = ehci_readl(ehci, &ehci->debug->control); - ehci_info(ehci, "debug port %d%s\n", - HCS_DEBUG_PORT(ehci->hcs_params), - (temp & DBGP_ENABLED) - ? " IN USE" - : ""); - if (!(temp & DBGP_ENABLED)) - ehci->debug = NULL; - } - } - /* at least the Genesys GL880S needs fixup here */ temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); temp &= 0x0f; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 9dadc7118d6..36c3a821059 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -38,6 +38,10 @@ typedef __u16 __bitwise __hc16; #endif /* statistics can be kept for tuning/monitoring */ +#ifdef DEBUG +#define EHCI_STATS +#endif + struct ehci_stats { /* irq usage */ unsigned long normal; @@ -221,6 +225,9 @@ struct ehci_hcd { /* one per controller */ #ifdef DEBUG struct dentry *debug_dir; #endif + + /* platform-specific data -- must come last */ + unsigned long priv[0] __aligned(sizeof(s64)); }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 5105127c1d4..11e0b79ff9d 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -142,6 +142,9 @@ static int usb_get_ver_info(struct device_node *np) return ver; } + if (of_device_is_compatible(np, "fsl,mpc5121-usb2-dr")) + return FSL_USB_VER_OLD; + if (of_device_is_compatible(np, "fsl-usb2-mph")) { if (of_device_is_compatible(np, "fsl-usb2-mph-v1.6")) ver = FSL_USB_VER_1_6; diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index bd6a7447ccc..f0ebe8e7c58 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -58,6 +58,7 @@ #include <linux/usb.h> #include <linux/usb/hcd.h> #include <linux/dma-mapping.h> +#include <linux/module.h> #include "imx21-hcd.h" diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index d370245a4ee..5e3a6deb62b 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c @@ -128,7 +128,8 @@ static void tmio_start_hc(struct platform_device *dev) tmio_iowrite8(2, tmio->ccr + CCR_INTC); dev_info(&dev->dev, "revision %d @ 0x%08llx, irq %d\n", - tmio_ioread8(tmio->ccr + CCR_REVID), hcd->rsrc_start, hcd->irq); + tmio_ioread8(tmio->ccr + CCR_REVID), + (u64) hcd->rsrc_start, hcd->irq); } static int ohci_tmio_start(struct usb_hcd *hcd) diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 4b9e9aba266..4f64d24eebc 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -447,6 +447,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) return IRQ_NONE; uhci_writew(uhci, status, USBSTS); /* Clear it */ + spin_lock(&uhci->lock); + if (unlikely(!uhci->is_initialized)) /* not yet configured */ + goto done; + if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { if (status & USBSTS_HSE) dev_err(uhci_dev(uhci), "host system error, " @@ -455,7 +459,6 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) dev_err(uhci_dev(uhci), "host controller process " "error, something bad happened!\n"); if (status & USBSTS_HCH) { - spin_lock(&uhci->lock); if (uhci->rh_state >= UHCI_RH_RUNNING) { dev_err(uhci_dev(uhci), "host controller halted, " @@ -473,15 +476,15 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) * pending unlinks */ mod_timer(&hcd->rh_timer, jiffies); } - spin_unlock(&uhci->lock); } } - if (status & USBSTS_RD) + if (status & USBSTS_RD) { + spin_unlock(&uhci->lock); usb_hcd_poll_rh_status(hcd); - else { - spin_lock(&uhci->lock); + } else { uhci_scan_schedule(uhci); + done: spin_unlock(&uhci->lock); } @@ -662,9 +665,9 @@ static int uhci_start(struct usb_hcd *hcd) */ mb(); + spin_lock_irq(&uhci->lock); configure_hc(uhci); uhci->is_initialized = 1; - spin_lock_irq(&uhci->lock); start_rh(uhci); spin_unlock_irq(&uhci->lock); return 0; diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index a686cf4905b..68914429482 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -761,12 +761,39 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, break; case USB_PORT_FEAT_LINK_STATE: temp = xhci_readl(xhci, port_array[wIndex]); + + /* Disable port */ + if (link_state == USB_SS_PORT_LS_SS_DISABLED) { + xhci_dbg(xhci, "Disable port %d\n", wIndex); + temp = xhci_port_state_to_neutral(temp); + /* + * Clear all change bits, so that we get a new + * connection event. + */ + temp |= PORT_CSC | PORT_PEC | PORT_WRC | + PORT_OCC | PORT_RC | PORT_PLC | + PORT_CEC; + xhci_writel(xhci, temp | PORT_PE, + port_array[wIndex]); + temp = xhci_readl(xhci, port_array[wIndex]); + break; + } + + /* Put link in RxDetect (enable port) */ + if (link_state == USB_SS_PORT_LS_RX_DETECT) { + xhci_dbg(xhci, "Enable port %d\n", wIndex); + xhci_set_link_state(xhci, port_array, wIndex, + link_state); + temp = xhci_readl(xhci, port_array[wIndex]); + break; + } + /* Software should not attempt to set - * port link state above '5' (Rx.Detect) and the port + * port link state above '3' (U3) and the port * must be enabled. */ if ((temp & PORT_PE) == 0 || - (link_state > USB_SS_PORT_LS_RX_DETECT)) { + (link_state > USB_SS_PORT_LS_U3)) { xhci_warn(xhci, "Cannot set link state.\n"); goto error; } @@ -957,6 +984,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) int max_ports; __le32 __iomem **port_array; struct xhci_bus_state *bus_state; + bool reset_change = false; max_ports = xhci_get_ports(hcd, &port_array); bus_state = &xhci->bus_state[hcd_index(hcd)]; @@ -988,6 +1016,12 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) buf[(i + 1) / 8] |= 1 << (i + 1) % 8; status = 1; } + if ((temp & PORT_RC)) + reset_change = true; + } + if (!status && !reset_change) { + xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); } spin_unlock_irqrestore(&xhci->lock, flags); return status ? retval : 0; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index fb51c7085ad..35616ffbe3a 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1250,6 +1250,8 @@ static unsigned int xhci_microframes_to_exponent(struct usb_device *udev, static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, struct usb_host_endpoint *ep) { + if (ep->desc.bInterval == 0) + return 0; return xhci_microframes_to_exponent(udev, ep, ep->desc.bInterval, 0, 15); } diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index cbb44b7b9d6..59fb5c677db 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1725,6 +1725,15 @@ cleanup: if (bogus_port_status) return; + /* + * xHCI port-status-change events occur when the "or" of all the + * status-change bits in the portsc register changes from 0 to 1. + * New status changes won't cause an event if any other change + * bits are still set. When an event occurs, switch over to + * polling to avoid losing status changes. + */ + xhci_dbg(xhci, "%s: starting port polling.\n", __func__); + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); spin_unlock(&xhci->lock); /* Pass this up to the core */ usb_hcd_poll_rh_status(hcd); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 5c72c431bab..f1f01a834ba 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -884,6 +884,11 @@ int xhci_suspend(struct xhci_hcd *xhci) xhci->shared_hcd->state != HC_STATE_SUSPENDED) return -EINVAL; + /* Don't poll the roothubs on bus suspend. */ + xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + del_timer_sync(&hcd->rh_timer); + spin_lock_irq(&xhci->lock); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); @@ -1069,6 +1074,11 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) if (xhci->quirks & XHCI_COMP_MODE_QUIRK) compliance_mode_recovery_timer_init(xhci); + /* Re-enable port polling. */ + xhci_dbg(xhci, "%s: starting port polling.\n", __func__); + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + usb_hcd_poll_rh_status(hcd); + return retval; } #endif /* CONFIG_PM */ diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 7667b12f2ff..268148de971 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -2179,7 +2179,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) if (dev->out_pipe == 0 || !param->length || param->sglen < 4) break; retval = 0; - dev_info(&intf->dev, "TEST 17: unlink from %d queues of " + dev_info(&intf->dev, "TEST 24: unlink from %d queues of " "%d %d-byte writes\n", param->iterations, param->sglen, param->length); for (i = param->iterations; retval == 0 && i > 0; --i) { diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index 0968dd7a859..f522000e8f0 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -105,7 +105,7 @@ static void cppi_reset_tx(struct cppi_tx_stateram __iomem *tx, u32 ptr) musb_writel(&tx->tx_complete, 0, ptr); } -static void __init cppi_pool_init(struct cppi *cppi, struct cppi_channel *c) +static void cppi_pool_init(struct cppi *cppi, struct cppi_channel *c) { int j; @@ -150,7 +150,7 @@ static void cppi_pool_free(struct cppi_channel *c) c->last_processed = NULL; } -static int __init cppi_controller_start(struct dma_controller *c) +static int cppi_controller_start(struct dma_controller *c) { struct cppi *controller; void __iomem *tibase; diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index f1c6c5470b9..fd3486745e6 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2298,10 +2298,7 @@ static int __init musb_init(void) if (usb_disabled()) return 0; - pr_info("%s: version " MUSB_VERSION ", " - "?dma?" - ", " - "otg (peripheral+host)", + pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n", musb_driver_name); return platform_driver_register(&musb_driver); } diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index e6f2ae8368b..f7d764de6fd 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -134,6 +134,11 @@ static const resource_size_t dsps_control_module_phys[] = { DSPS_AM33XX_CONTROL_MODULE_PHYS_1, }; +#define USBPHY_CM_PWRDN (1 << 0) +#define USBPHY_OTG_PWRDN (1 << 1) +#define USBPHY_OTGVDET_EN (1 << 19) +#define USBPHY_OTGSESSEND_EN (1 << 20) + /** * musb_dsps_phy_control - phy on/off * @glue: struct dsps_glue * diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 6223062d5d1..37962c99ff1 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -110,7 +110,7 @@ config AB8500_USB config FSL_USB2_OTG bool "Freescale USB OTG Transceiver Driver" - depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 && USB_SUSPEND + depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND select USB_OTG select USB_OTG_UTILS help diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c index 1dd57504186..eace975991a 100644 --- a/drivers/usb/otg/mv_otg.c +++ b/drivers/usb/otg/mv_otg.c @@ -240,7 +240,7 @@ static void otg_clock_enable(struct mv_otg *mvotg) unsigned int i; for (i = 0; i < mvotg->clknum; i++) - clk_enable(mvotg->clk[i]); + clk_prepare_enable(mvotg->clk[i]); } static void otg_clock_disable(struct mv_otg *mvotg) @@ -248,7 +248,7 @@ static void otg_clock_disable(struct mv_otg *mvotg) unsigned int i; for (i = 0; i < mvotg->clknum; i++) - clk_disable(mvotg->clk[i]); + clk_disable_unprepare(mvotg->clk[i]); } static int mv_otg_enable_internal(struct mv_otg *mvotg) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index dd41f61893e..f2985cd8802 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -545,15 +545,6 @@ static int usbhsg_pipe_disable(struct usbhsg_uep *uep) return 0; } -static void usbhsg_uep_init(struct usbhsg_gpriv *gpriv) -{ - int i; - struct usbhsg_uep *uep; - - usbhsg_for_each_uep_with_dcp(uep, gpriv, i) - uep->pipe = NULL; -} - /* * * usb_ep_ops @@ -610,7 +601,12 @@ static int usbhsg_ep_disable(struct usb_ep *ep) { struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); - return usbhsg_pipe_disable(uep); + usbhsg_pipe_disable(uep); + + uep->pipe->mod_private = NULL; + uep->pipe = NULL; + + return 0; } static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, @@ -761,9 +757,8 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) usbhs_pipe_init(priv, usbhsg_dma_map_ctrl); usbhs_fifo_init(priv); - usbhsg_uep_init(gpriv); - /* dcp init */ + /* dcp init instead of usbhsg_ep_enable() */ dcp->pipe = usbhs_dcp_malloc(priv); dcp->pipe->mod_private = dcp; usbhs_pipe_config_update(dcp->pipe, 0, 0, 64); @@ -825,7 +820,7 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) usbhs_sys_set_test_mode(priv, 0); usbhs_sys_function_ctrl(priv, 0); - usbhsg_pipe_disable(dcp); + usbhsg_ep_disable(&dcp->ep); dev_dbg(dev, "stop gadget\n"); @@ -998,6 +993,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) */ usbhsg_for_each_uep_with_dcp(uep, gpriv, i) { uep->gpriv = gpriv; + uep->pipe = NULL; snprintf(uep->ep_name, EP_NAME_SIZE, "ep%d", i); uep->ep.name = uep->ep_name; diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index 3d3cd6ca268..b86815421c8 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -661,9 +661,10 @@ static void usbhsh_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt) status = -ESHUTDOWN; urb->actual_length = pkt->actual; - usbhsh_ureq_free(hpriv, ureq); usbhsh_endpoint_sequence_save(hpriv, urb, pkt); + usbhsh_ureq_free(hpriv, ureq); + usbhsh_pipe_detach(hpriv, usbhsh_ep_to_uep(urb->ep)); usb_hcd_unlink_urb_from_ep(hcd, urb); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 0a373b3ae96..ba68835d06a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -875,6 +875,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, + /* Crucible Devices */ + { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 049b6e715fa..fa5d5603827 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1259,3 +1259,9 @@ * ATI command output: Cinterion MC55i */ #define FTDI_CINTERION_MC55I_PID 0xA951 + +/* + * Product: Comet Caller ID decoder + * Manufacturer: Crucible Technologies + */ +#define FTDI_CT_COMET_PID 0x8e08 diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 58184f3de68..82afc4d6a32 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -530,6 +530,9 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, wait_queue_t wait; unsigned long flags; + if (!tty) + return; + if (!timeout) timeout = (HZ * EDGE_CLOSING_WAIT)/100; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e6f87b76c71..0d9dac9e7f9 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -288,6 +288,7 @@ static void option_instat_callback(struct urb *urb); #define ALCATEL_VENDOR_ID 0x1bbb #define ALCATEL_PRODUCT_X060S_X200 0x0000 #define ALCATEL_PRODUCT_X220_X500D 0x0017 +#define ALCATEL_PRODUCT_L100V 0x011e #define PIRELLI_VENDOR_ID 0x1266 #define PIRELLI_PRODUCT_C100_1 0x1002 @@ -429,9 +430,12 @@ static void option_instat_callback(struct urb *urb); #define MEDIATEK_VENDOR_ID 0x0e8d #define MEDIATEK_PRODUCT_DC_1COM 0x00a0 #define MEDIATEK_PRODUCT_DC_4COM 0x00a5 +#define MEDIATEK_PRODUCT_DC_4COM2 0x00a7 #define MEDIATEK_PRODUCT_DC_5COM 0x00a4 #define MEDIATEK_PRODUCT_7208_1COM 0x7101 #define MEDIATEK_PRODUCT_7208_2COM 0x7102 +#define MEDIATEK_PRODUCT_7103_2COM 0x7103 +#define MEDIATEK_PRODUCT_7106_2COM 0x7106 #define MEDIATEK_PRODUCT_FP_1COM 0x0003 #define MEDIATEK_PRODUCT_FP_2COM 0x0023 #define MEDIATEK_PRODUCT_FPDC_1COM 0x0043 @@ -441,6 +445,14 @@ static void option_instat_callback(struct urb *urb); #define CELLIENT_VENDOR_ID 0x2692 #define CELLIENT_PRODUCT_MEN200 0x9005 +/* Hyundai Petatel Inc. products */ +#define PETATEL_VENDOR_ID 0x1ff4 +#define PETATEL_PRODUCT_NP10T 0x600e + +/* TP-LINK Incorporated products */ +#define TPLINK_VENDOR_ID 0x2357 +#define TPLINK_PRODUCT_MA180 0x0201 + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -922,8 +934,10 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff), /* ONDA MT8205 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff), /* ZTE MF880 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, @@ -1190,6 +1204,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), @@ -1294,7 +1310,14 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7103_2COM, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7106_2COM, 0x02, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) }, { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, + { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, + { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c index 4362d9e7baa..f72323ef618 100644 --- a/drivers/vfio/pci/vfio_pci_rdwr.c +++ b/drivers/vfio/pci/vfio_pci_rdwr.c @@ -240,17 +240,17 @@ ssize_t vfio_pci_mem_readwrite(struct vfio_pci_device *vdev, char __user *buf, filled = 1; } else { /* Drop writes, fill reads with FF */ + filled = min((size_t)(x_end - pos), count); if (!iswrite) { char val = 0xFF; size_t i; - for (i = 0; i < x_end - pos; i++) { + for (i = 0; i < filled; i++) { if (put_user(val, buf + i)) goto out; } } - filled = x_end - pos; } count -= filled; diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 12526787a7c..0abf2bf2083 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -139,6 +139,7 @@ struct imxfb_info { struct clk *clk_ahb; struct clk *clk_per; enum imxfb_type devtype; + bool enabled; /* * These are the addresses we mapped @@ -536,6 +537,10 @@ static void imxfb_exit_backlight(struct imxfb_info *fbi) static void imxfb_enable_controller(struct imxfb_info *fbi) { + + if (fbi->enabled) + return; + pr_debug("Enabling LCD controller\n"); writel(fbi->screen_dma, fbi->regs + LCDC_SSA); @@ -556,6 +561,7 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) clk_prepare_enable(fbi->clk_ipg); clk_prepare_enable(fbi->clk_ahb); clk_prepare_enable(fbi->clk_per); + fbi->enabled = true; if (fbi->backlight_power) fbi->backlight_power(1); @@ -565,6 +571,9 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) static void imxfb_disable_controller(struct imxfb_info *fbi) { + if (!fbi->enabled) + return; + pr_debug("Disabling LCD controller\n"); if (fbi->backlight_power) @@ -575,6 +584,7 @@ static void imxfb_disable_controller(struct imxfb_info *fbi) clk_disable_unprepare(fbi->clk_per); clk_disable_unprepare(fbi->clk_ipg); clk_disable_unprepare(fbi->clk_ahb); + fbi->enabled = false; writel(0, fbi->regs + LCDC_RMCR); } @@ -729,6 +739,8 @@ static int __init imxfb_init_fbinfo(struct platform_device *pdev) memset(fbi, 0, sizeof(struct imxfb_info)); + fbi->devtype = pdev->id_entry->driver_data; + strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id)); info->fix.type = FB_TYPE_PACKED_PIXELS; @@ -789,7 +801,6 @@ static int __init imxfb_probe(struct platform_device *pdev) return -ENOMEM; fbi = info->par; - fbi->devtype = pdev->id_entry->driver_data; if (!fb_mode) fb_mode = pdata->mode[0].mode.name; diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c index 4d99dd7a683..395cb6a8d8f 100644 --- a/drivers/video/ssd1307fb.c +++ b/drivers/video/ssd1307fb.c @@ -145,8 +145,8 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par) u32 page_length = SSD1307FB_WIDTH * i; u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8; u8 byte = *(vmem + index); - u8 bit = byte & (1 << (7 - (j % 8))); - bit = bit >> (7 - (j % 8)); + u8 bit = byte & (1 << (j % 8)); + bit = bit >> (j % 8); buf |= bit << k; } ssd1307fb_write_data(par->client, buf); diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c index 4dcfced107f..084041d42c9 100644 --- a/drivers/xen/cpu_hotplug.c +++ b/drivers/xen/cpu_hotplug.c @@ -25,10 +25,10 @@ static void disable_hotplug_cpu(int cpu) static int vcpu_online(unsigned int cpu) { int err; - char dir[32], state[32]; + char dir[16], state[16]; sprintf(dir, "cpu/%u", cpu); - err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state); + err = xenbus_scanf(XBT_NIL, dir, "availability", "%15s", state); if (err != 1) { if (!xen_initial_domain()) printk(KERN_ERR "XENBUS: Unable to read cpu state\n"); diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 2e22df2f7a3..3c8803feba2 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -56,10 +56,15 @@ MODULE_PARM_DESC(limit, "Maximum number of grants that may be mapped by " static atomic_t pages_mapped = ATOMIC_INIT(0); static int use_ptemod; +#define populate_freeable_maps use_ptemod struct gntdev_priv { + /* maps with visible offsets in the file descriptor */ struct list_head maps; - /* lock protects maps from concurrent changes */ + /* maps that are not visible; will be freed on munmap. + * Only populated if populate_freeable_maps == 1 */ + struct list_head freeable_maps; + /* lock protects maps and freeable_maps */ spinlock_t lock; struct mm_struct *mm; struct mmu_notifier mn; @@ -193,7 +198,7 @@ static struct grant_map *gntdev_find_map_index(struct gntdev_priv *priv, return NULL; } -static void gntdev_put_map(struct grant_map *map) +static void gntdev_put_map(struct gntdev_priv *priv, struct grant_map *map) { if (!map) return; @@ -208,6 +213,12 @@ static void gntdev_put_map(struct grant_map *map) evtchn_put(map->notify.event); } + if (populate_freeable_maps && priv) { + spin_lock(&priv->lock); + list_del(&map->next); + spin_unlock(&priv->lock); + } + if (map->pages && !use_ptemod) unmap_grant_pages(map, 0, map->count); gntdev_free_map(map); @@ -301,17 +312,10 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages) if (map->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) { int pgno = (map->notify.addr >> PAGE_SHIFT); - if (pgno >= offset && pgno < offset + pages && use_ptemod) { - void __user *tmp = (void __user *) - map->vma->vm_start + map->notify.addr; - err = copy_to_user(tmp, &err, 1); - if (err) - return -EFAULT; - map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE; - } else if (pgno >= offset && pgno < offset + pages) { - uint8_t *tmp = kmap(map->pages[pgno]); + if (pgno >= offset && pgno < offset + pages) { + /* No need for kmap, pages are in lowmem */ + uint8_t *tmp = pfn_to_kaddr(page_to_pfn(map->pages[pgno])); tmp[map->notify.addr & (PAGE_SIZE-1)] = 0; - kunmap(map->pages[pgno]); map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE; } } @@ -376,11 +380,24 @@ static void gntdev_vma_open(struct vm_area_struct *vma) static void gntdev_vma_close(struct vm_area_struct *vma) { struct grant_map *map = vma->vm_private_data; + struct file *file = vma->vm_file; + struct gntdev_priv *priv = file->private_data; pr_debug("gntdev_vma_close %p\n", vma); - map->vma = NULL; + if (use_ptemod) { + /* It is possible that an mmu notifier could be running + * concurrently, so take priv->lock to ensure that the vma won't + * vanishing during the unmap_grant_pages call, since we will + * spin here until that completes. Such a concurrent call will + * not do any unmapping, since that has been done prior to + * closing the vma, but it may still iterate the unmap_ops list. + */ + spin_lock(&priv->lock); + map->vma = NULL; + spin_unlock(&priv->lock); + } vma->vm_private_data = NULL; - gntdev_put_map(map); + gntdev_put_map(priv, map); } static struct vm_operations_struct gntdev_vmops = { @@ -390,33 +407,43 @@ static struct vm_operations_struct gntdev_vmops = { /* ------------------------------------------------------------------ */ +static void unmap_if_in_range(struct grant_map *map, + unsigned long start, unsigned long end) +{ + unsigned long mstart, mend; + int err; + + if (!map->vma) + return; + if (map->vma->vm_start >= end) + return; + if (map->vma->vm_end <= start) + return; + mstart = max(start, map->vma->vm_start); + mend = min(end, map->vma->vm_end); + pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n", + map->index, map->count, + map->vma->vm_start, map->vma->vm_end, + start, end, mstart, mend); + err = unmap_grant_pages(map, + (mstart - map->vma->vm_start) >> PAGE_SHIFT, + (mend - mstart) >> PAGE_SHIFT); + WARN_ON(err); +} + static void mn_invl_range_start(struct mmu_notifier *mn, struct mm_struct *mm, unsigned long start, unsigned long end) { struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); struct grant_map *map; - unsigned long mstart, mend; - int err; spin_lock(&priv->lock); list_for_each_entry(map, &priv->maps, next) { - if (!map->vma) - continue; - if (map->vma->vm_start >= end) - continue; - if (map->vma->vm_end <= start) - continue; - mstart = max(start, map->vma->vm_start); - mend = min(end, map->vma->vm_end); - pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n", - map->index, map->count, - map->vma->vm_start, map->vma->vm_end, - start, end, mstart, mend); - err = unmap_grant_pages(map, - (mstart - map->vma->vm_start) >> PAGE_SHIFT, - (mend - mstart) >> PAGE_SHIFT); - WARN_ON(err); + unmap_if_in_range(map, start, end); + } + list_for_each_entry(map, &priv->freeable_maps, next) { + unmap_if_in_range(map, start, end); } spin_unlock(&priv->lock); } @@ -445,6 +472,15 @@ static void mn_release(struct mmu_notifier *mn, err = unmap_grant_pages(map, /* offset */ 0, map->count); WARN_ON(err); } + list_for_each_entry(map, &priv->freeable_maps, next) { + if (!map->vma) + continue; + pr_debug("map %d+%d (%lx %lx)\n", + map->index, map->count, + map->vma->vm_start, map->vma->vm_end); + err = unmap_grant_pages(map, /* offset */ 0, map->count); + WARN_ON(err); + } spin_unlock(&priv->lock); } @@ -466,6 +502,7 @@ static int gntdev_open(struct inode *inode, struct file *flip) return -ENOMEM; INIT_LIST_HEAD(&priv->maps); + INIT_LIST_HEAD(&priv->freeable_maps); spin_lock_init(&priv->lock); if (use_ptemod) { @@ -500,8 +537,9 @@ static int gntdev_release(struct inode *inode, struct file *flip) while (!list_empty(&priv->maps)) { map = list_entry(priv->maps.next, struct grant_map, next); list_del(&map->next); - gntdev_put_map(map); + gntdev_put_map(NULL /* already removed */, map); } + WARN_ON(!list_empty(&priv->freeable_maps)); if (use_ptemod) mmu_notifier_unregister(&priv->mn, priv->mm); @@ -529,14 +567,14 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv, if (unlikely(atomic_add_return(op.count, &pages_mapped) > limit)) { pr_debug("can't map: over limit\n"); - gntdev_put_map(map); + gntdev_put_map(NULL, map); return err; } if (copy_from_user(map->grants, &u->refs, sizeof(map->grants[0]) * op.count) != 0) { - gntdev_put_map(map); - return err; + gntdev_put_map(NULL, map); + return -EFAULT; } spin_lock(&priv->lock); @@ -565,11 +603,13 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv, map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count); if (map) { list_del(&map->next); + if (populate_freeable_maps) + list_add_tail(&map->next, &priv->freeable_maps); err = 0; } spin_unlock(&priv->lock); if (map) - gntdev_put_map(map); + gntdev_put_map(priv, map); return err; } @@ -579,25 +619,31 @@ static long gntdev_ioctl_get_offset_for_vaddr(struct gntdev_priv *priv, struct ioctl_gntdev_get_offset_for_vaddr op; struct vm_area_struct *vma; struct grant_map *map; + int rv = -EINVAL; if (copy_from_user(&op, u, sizeof(op)) != 0) return -EFAULT; pr_debug("priv %p, offset for vaddr %lx\n", priv, (unsigned long)op.vaddr); + down_read(¤t->mm->mmap_sem); vma = find_vma(current->mm, op.vaddr); if (!vma || vma->vm_ops != &gntdev_vmops) - return -EINVAL; + goto out_unlock; map = vma->vm_private_data; if (!map) - return -EINVAL; + goto out_unlock; op.offset = map->index << PAGE_SHIFT; op.count = map->count; + rv = 0; - if (copy_to_user(u, &op, sizeof(op)) != 0) + out_unlock: + up_read(¤t->mm->mmap_sem); + + if (rv == 0 && copy_to_user(u, &op, sizeof(op)) != 0) return -EFAULT; - return 0; + return rv; } static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u) @@ -778,7 +824,7 @@ out_unlock_put: out_put_map: if (use_ptemod) map->vma = NULL; - gntdev_put_map(map); + gntdev_put_map(priv, map); return err; } diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 7038de53652..157c0ccda3e 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -56,10 +56,6 @@ /* External tools reserve first few grant table entries. */ #define NR_RESERVED_ENTRIES 8 #define GNTTAB_LIST_END 0xffffffff -#define GREFS_PER_GRANT_FRAME \ -(grant_table_version == 1 ? \ -(PAGE_SIZE / sizeof(struct grant_entry_v1)) : \ -(PAGE_SIZE / sizeof(union grant_entry_v2))) static grant_ref_t **gnttab_list; static unsigned int nr_grant_frames; @@ -154,6 +150,7 @@ static struct gnttab_ops *gnttab_interface; static grant_status_t *grstatus; static int grant_table_version; +static int grefs_per_grant_frame; static struct gnttab_free_callback *gnttab_free_callback_list; @@ -767,12 +764,14 @@ static int grow_gnttab_list(unsigned int more_frames) unsigned int new_nr_grant_frames, extra_entries, i; unsigned int nr_glist_frames, new_nr_glist_frames; + BUG_ON(grefs_per_grant_frame == 0); + new_nr_grant_frames = nr_grant_frames + more_frames; - extra_entries = more_frames * GREFS_PER_GRANT_FRAME; + extra_entries = more_frames * grefs_per_grant_frame; - nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; + nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; new_nr_glist_frames = - (new_nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; + (new_nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; for (i = nr_glist_frames; i < new_nr_glist_frames; i++) { gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC); if (!gnttab_list[i]) @@ -780,12 +779,12 @@ static int grow_gnttab_list(unsigned int more_frames) } - for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames; - i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++) + for (i = grefs_per_grant_frame * nr_grant_frames; + i < grefs_per_grant_frame * new_nr_grant_frames - 1; i++) gnttab_entry(i) = i + 1; gnttab_entry(i) = gnttab_free_head; - gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames; + gnttab_free_head = grefs_per_grant_frame * nr_grant_frames; gnttab_free_count += extra_entries; nr_grant_frames = new_nr_grant_frames; @@ -957,7 +956,8 @@ EXPORT_SYMBOL_GPL(gnttab_unmap_refs); static unsigned nr_status_frames(unsigned nr_grant_frames) { - return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP; + BUG_ON(grefs_per_grant_frame == 0); + return (nr_grant_frames * grefs_per_grant_frame + SPP - 1) / SPP; } static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes) @@ -1115,6 +1115,7 @@ static void gnttab_request_version(void) rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1); if (rc == 0 && gsv.version == 2) { grant_table_version = 2; + grefs_per_grant_frame = PAGE_SIZE / sizeof(union grant_entry_v2); gnttab_interface = &gnttab_v2_ops; } else if (grant_table_version == 2) { /* @@ -1127,17 +1128,17 @@ static void gnttab_request_version(void) panic("we need grant tables version 2, but only version 1 is available"); } else { grant_table_version = 1; + grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1); gnttab_interface = &gnttab_v1_ops; } printk(KERN_INFO "Grant tables using version %d layout.\n", grant_table_version); } -int gnttab_resume(void) +static int gnttab_setup(void) { unsigned int max_nr_gframes; - gnttab_request_version(); max_nr_gframes = gnttab_max_grant_frames(); if (max_nr_gframes < nr_grant_frames) return -ENOSYS; @@ -1160,6 +1161,12 @@ int gnttab_resume(void) return 0; } +int gnttab_resume(void) +{ + gnttab_request_version(); + return gnttab_setup(); +} + int gnttab_suspend(void) { gnttab_interface->unmap_frames(); @@ -1171,9 +1178,10 @@ static int gnttab_expand(unsigned int req_entries) int rc; unsigned int cur, extra; + BUG_ON(grefs_per_grant_frame == 0); cur = nr_grant_frames; - extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) / - GREFS_PER_GRANT_FRAME); + extra = ((req_entries + (grefs_per_grant_frame-1)) / + grefs_per_grant_frame); if (cur + extra > gnttab_max_grant_frames()) return -ENOSPC; @@ -1191,21 +1199,23 @@ int gnttab_init(void) unsigned int nr_init_grefs; int ret; + gnttab_request_version(); nr_grant_frames = 1; boot_max_nr_grant_frames = __max_nr_grant_frames(); /* Determine the maximum number of frames required for the * grant reference free list on the current hypervisor. */ + BUG_ON(grefs_per_grant_frame == 0); max_nr_glist_frames = (boot_max_nr_grant_frames * - GREFS_PER_GRANT_FRAME / RPP); + grefs_per_grant_frame / RPP); gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *), GFP_KERNEL); if (gnttab_list == NULL) return -ENOMEM; - nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; + nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; for (i = 0; i < nr_glist_frames; i++) { gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL); if (gnttab_list[i] == NULL) { @@ -1214,12 +1224,12 @@ int gnttab_init(void) } } - if (gnttab_resume() < 0) { + if (gnttab_setup() < 0) { ret = -ENODEV; goto ini_nomem; } - nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME; + nr_init_grefs = nr_grant_frames * grefs_per_grant_frame; for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) gnttab_entry(i) = i + 1; diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 0bbbccbb1f1..ca2b00e9d55 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -199,9 +199,6 @@ static long privcmd_ioctl_mmap(void __user *udata) LIST_HEAD(pagelist); struct mmap_mfn_state state; - if (!xen_initial_domain()) - return -EPERM; - /* We only support privcmd_ioctl_mmap_batch for auto translated. */ if (xen_feature(XENFEAT_auto_translated_physmap)) return -ENOSYS; @@ -261,11 +258,12 @@ struct mmap_batch_state { * -ENOENT if at least 1 -ENOENT has happened. */ int global_error; - /* An array for individual errors */ - int *err; + int version; /* User-space mfn array to store errors in the second pass for V1. */ xen_pfn_t __user *user_mfn; + /* User-space int array to store errors in the second pass for V2. */ + int __user *user_err; }; /* auto translated dom0 note: if domU being created is PV, then mfn is @@ -288,7 +286,19 @@ static int mmap_batch_fn(void *data, void *state) &cur_page); /* Store error code for second pass. */ - *(st->err++) = ret; + if (st->version == 1) { + if (ret < 0) { + /* + * V1 encodes the error codes in the 32bit top nibble of the + * mfn (with its known limitations vis-a-vis 64 bit callers). + */ + *mfnp |= (ret == -ENOENT) ? + PRIVCMD_MMAPBATCH_PAGED_ERROR : + PRIVCMD_MMAPBATCH_MFN_ERROR; + } + } else { /* st->version == 2 */ + *((int *) mfnp) = ret; + } /* And see if it affects the global_error. */ if (ret < 0) { @@ -305,20 +315,25 @@ static int mmap_batch_fn(void *data, void *state) return 0; } -static int mmap_return_errors_v1(void *data, void *state) +static int mmap_return_errors(void *data, void *state) { - xen_pfn_t *mfnp = data; struct mmap_batch_state *st = state; - int err = *(st->err++); - /* - * V1 encodes the error codes in the 32bit top nibble of the - * mfn (with its known limitations vis-a-vis 64 bit callers). - */ - *mfnp |= (err == -ENOENT) ? - PRIVCMD_MMAPBATCH_PAGED_ERROR : - PRIVCMD_MMAPBATCH_MFN_ERROR; - return __put_user(*mfnp, st->user_mfn++); + if (st->version == 1) { + xen_pfn_t mfnp = *((xen_pfn_t *) data); + if (mfnp & PRIVCMD_MMAPBATCH_MFN_ERROR) + return __put_user(mfnp, st->user_mfn++); + else + st->user_mfn++; + } else { /* st->version == 2 */ + int err = *((int *) data); + if (err) + return __put_user(err, st->user_err++); + else + st->user_err++; + } + + return 0; } /* Allocate pfns that are then mapped with gmfns from foreign domid. Update @@ -357,12 +372,8 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) struct vm_area_struct *vma; unsigned long nr_pages; LIST_HEAD(pagelist); - int *err_array = NULL; struct mmap_batch_state state; - if (!xen_initial_domain()) - return -EPERM; - switch (version) { case 1: if (copy_from_user(&m, udata, sizeof(struct privcmd_mmapbatch))) @@ -396,10 +407,12 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) goto out; } - err_array = kcalloc(m.num, sizeof(int), GFP_KERNEL); - if (err_array == NULL) { - ret = -ENOMEM; - goto out; + if (version == 2) { + /* Zero error array now to only copy back actual errors. */ + if (clear_user(m.err, sizeof(int) * m.num)) { + ret = -EFAULT; + goto out; + } } down_write(&mm->mmap_sem); @@ -427,7 +440,7 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) state.va = m.addr; state.index = 0; state.global_error = 0; - state.err = err_array; + state.version = version; /* mmap_batch_fn guarantees ret == 0 */ BUG_ON(traverse_pages(m.num, sizeof(xen_pfn_t), @@ -435,21 +448,14 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) up_write(&mm->mmap_sem); - if (version == 1) { - if (state.global_error) { - /* Write back errors in second pass. */ - state.user_mfn = (xen_pfn_t *)m.arr; - state.err = err_array; - ret = traverse_pages(m.num, sizeof(xen_pfn_t), - &pagelist, mmap_return_errors_v1, &state); - } else - ret = 0; - - } else if (version == 2) { - ret = __copy_to_user(m.err, err_array, m.num * sizeof(int)); - if (ret) - ret = -EFAULT; - } + if (state.global_error) { + /* Write back errors in second pass. */ + state.user_mfn = (xen_pfn_t *)m.arr; + state.user_err = m.err; + ret = traverse_pages(m.num, sizeof(xen_pfn_t), + &pagelist, mmap_return_errors, &state); + } else + ret = 0; /* If we have not had any EFAULT-like global errors then set the global * error to -ENOENT if necessary. */ @@ -457,7 +463,6 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) ret = -ENOENT; out: - kfree(err_array); free_page_list(&pagelist); return ret; diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h index a7def010eba..f72af87640e 100644 --- a/drivers/xen/xen-pciback/pciback.h +++ b/drivers/xen/xen-pciback/pciback.h @@ -124,7 +124,7 @@ static inline int xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, static inline void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev, struct pci_dev *dev) { - if (xen_pcibk_backend && xen_pcibk_backend->free) + if (xen_pcibk_backend && xen_pcibk_backend->release) return xen_pcibk_backend->release(pdev, dev); } diff --git a/fs/Kconfig b/fs/Kconfig index cfe512fd1ca..780725a463b 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -68,16 +68,6 @@ source "fs/quota/Kconfig" source "fs/autofs4/Kconfig" source "fs/fuse/Kconfig" -config CUSE - tristate "Character device in Userspace support" - depends on FUSE_FS - help - This FUSE extension allows character devices to be - implemented in userspace. - - If you want to develop or use userspace character device - based on CUSE, answer Y or M. - config GENERIC_ACL bool select FS_POSIX_ACL diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 521e9d4424f..a8b8adc0507 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3997,7 +3997,7 @@ again: * We make the other tasks wait for the flush only when we can flush * all things. */ - if (ret && flush == BTRFS_RESERVE_FLUSH_ALL) { + if (ret && flush != BTRFS_RESERVE_NO_FLUSH) { flushing = true; space_info->flush = 1; } @@ -5560,7 +5560,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, int empty_cluster = 2 * 1024 * 1024; struct btrfs_space_info *space_info; int loop = 0; - int index = 0; + int index = __get_raid_index(data); int alloc_type = (data & BTRFS_BLOCK_GROUP_DATA) ? RESERVE_ALLOC_NO_ACCOUNT : RESERVE_ALLOC; bool found_uncached_bg = false; @@ -6788,11 +6788,13 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans, &wc->flags[level]); if (ret < 0) { btrfs_tree_unlock_rw(eb, path->locks[level]); + path->locks[level] = 0; return ret; } BUG_ON(wc->refs[level] == 0); if (wc->refs[level] == 1) { btrfs_tree_unlock_rw(eb, path->locks[level]); + path->locks[level] = 0; return 1; } } diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index f169d6b11d7..2e8cae63d24 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c @@ -171,6 +171,10 @@ static int mergable_maps(struct extent_map *prev, struct extent_map *next) if (test_bit(EXTENT_FLAG_COMPRESSED, &prev->flags)) return 0; + if (test_bit(EXTENT_FLAG_LOGGING, &prev->flags) || + test_bit(EXTENT_FLAG_LOGGING, &next->flags)) + return 0; + if (extent_map_end(prev) == next->start && prev->flags == next->flags && prev->bdev == next->bdev && @@ -255,7 +259,8 @@ int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, if (!em) goto out; - list_move(&em->list, &tree->modified_extents); + if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags)) + list_move(&em->list, &tree->modified_extents); em->generation = gen; clear_bit(EXTENT_FLAG_PINNED, &em->flags); em->mod_start = em->start; @@ -280,6 +285,12 @@ out: } +void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em) +{ + clear_bit(EXTENT_FLAG_LOGGING, &em->flags); + try_merge_map(tree, em); +} + /** * add_extent_mapping - add new extent map to the extent tree * @tree: tree to insert new map in diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index 922943ce29e..c6598c89cff 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h @@ -69,6 +69,7 @@ void free_extent_map(struct extent_map *em); int __init extent_map_init(void); void extent_map_exit(void); int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, u64 gen); +void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em); struct extent_map *search_extent_mapping(struct extent_map_tree *tree, u64 start, u64 len); #endif diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index bd38cef4235..94aa53b3872 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -460,8 +460,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, if (!contig) offset = page_offset(bvec->bv_page) + bvec->bv_offset; - if (!contig && (offset >= ordered->file_offset + ordered->len || - offset < ordered->file_offset)) { + if (offset >= ordered->file_offset + ordered->len || + offset < ordered->file_offset) { unsigned long bytes_left; sums->len = this_sum_bytes; this_sum_bytes = 0; diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 77061bf43ed..f76b1fd160d 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -2241,6 +2241,7 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int whence) if (lockend <= lockstart) lockend = lockstart + root->sectorsize; + lockend--; len = lockend - lockstart + 1; len = max_t(u64, len, root->sectorsize); @@ -2307,9 +2308,12 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int whence) } } - *offset = start; - free_extent_map(em); - break; + if (!test_bit(EXTENT_FLAG_PREALLOC, + &em->flags)) { + *offset = start; + free_extent_map(em); + break; + } } } diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 59ea2e4349c..0be7a8742a4 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -1862,11 +1862,13 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; struct btrfs_free_space *info; - int ret = 0; + int ret; + bool re_search = false; spin_lock(&ctl->tree_lock); again: + ret = 0; if (!bytes) goto out_lock; @@ -1879,17 +1881,17 @@ again: info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 1, 0); if (!info) { - /* the tree logging code might be calling us before we - * have fully loaded the free space rbtree for this - * block group. So it is possible the entry won't - * be in the rbtree yet at all. The caching code - * will make sure not to put it in the rbtree if - * the logging code has pinned it. + /* + * If we found a partial bit of our free space in a + * bitmap but then couldn't find the other part this may + * be a problem, so WARN about it. */ + WARN_ON(re_search); goto out_lock; } } + re_search = false; if (!info->bitmap) { unlink_free_space(ctl, info); if (offset == info->offset) { @@ -1935,8 +1937,10 @@ again: } ret = remove_from_bitmap(ctl, info, &offset, &bytes); - if (ret == -EAGAIN) + if (ret == -EAGAIN) { + re_search = true; goto again; + } BUG_ON(ret); /* logic error */ out_lock: spin_unlock(&ctl->tree_lock); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 16d9e8e191e..cc93b23ca35 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -88,7 +88,7 @@ static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = { [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK, }; -static int btrfs_setsize(struct inode *inode, loff_t newsize); +static int btrfs_setsize(struct inode *inode, struct iattr *attr); static int btrfs_truncate(struct inode *inode); static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent); static noinline int cow_file_range(struct inode *inode, @@ -2478,6 +2478,18 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) continue; } nr_truncate++; + + /* 1 for the orphan item deletion. */ + trans = btrfs_start_transaction(root, 1); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + goto out; + } + ret = btrfs_orphan_add(trans, inode); + btrfs_end_transaction(trans, root); + if (ret) + goto out; + ret = btrfs_truncate(inode); } else { nr_unlink++; @@ -3665,6 +3677,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) block_end - cur_offset, 0); if (IS_ERR(em)) { err = PTR_ERR(em); + em = NULL; break; } last_byte = min(extent_map_end(em), block_end); @@ -3748,16 +3761,27 @@ next: return err; } -static int btrfs_setsize(struct inode *inode, loff_t newsize) +static int btrfs_setsize(struct inode *inode, struct iattr *attr) { struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_trans_handle *trans; loff_t oldsize = i_size_read(inode); + loff_t newsize = attr->ia_size; + int mask = attr->ia_valid; int ret; if (newsize == oldsize) return 0; + /* + * The regular truncate() case without ATTR_CTIME and ATTR_MTIME is a + * special case where we need to update the times despite not having + * these flags set. For all other operations the VFS set these flags + * explicitly if it wants a timestamp update. + */ + if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME)))) + inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb); + if (newsize > oldsize) { truncate_pagecache(inode, oldsize, newsize); ret = btrfs_cont_expand(inode, oldsize, newsize); @@ -3783,9 +3807,34 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) set_bit(BTRFS_INODE_ORDERED_DATA_CLOSE, &BTRFS_I(inode)->runtime_flags); + /* + * 1 for the orphan item we're going to add + * 1 for the orphan item deletion. + */ + trans = btrfs_start_transaction(root, 2); + if (IS_ERR(trans)) + return PTR_ERR(trans); + + /* + * We need to do this in case we fail at _any_ point during the + * actual truncate. Once we do the truncate_setsize we could + * invalidate pages which forces any outstanding ordered io to + * be instantly completed which will give us extents that need + * to be truncated. If we fail to get an orphan inode down we + * could have left over extents that were never meant to live, + * so we need to garuntee from this point on that everything + * will be consistent. + */ + ret = btrfs_orphan_add(trans, inode); + btrfs_end_transaction(trans, root); + if (ret) + return ret; + /* we don't support swapfiles, so vmtruncate shouldn't fail */ truncate_setsize(inode, newsize); ret = btrfs_truncate(inode); + if (ret && inode->i_nlink) + btrfs_orphan_del(NULL, inode); } return ret; @@ -3805,7 +3854,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) return err; if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { - err = btrfs_setsize(inode, attr->ia_size); + err = btrfs_setsize(inode, attr); if (err) return err; } @@ -5572,10 +5621,13 @@ struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *pag return em; if (em) { /* - * if our em maps to a hole, there might - * actually be delalloc bytes behind it + * if our em maps to + * - a hole or + * - a pre-alloc extent, + * there might actually be delalloc bytes behind it. */ - if (em->block_start != EXTENT_MAP_HOLE) + if (em->block_start != EXTENT_MAP_HOLE && + !test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) return em; else hole_em = em; @@ -5657,6 +5709,8 @@ struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *pag */ em->block_start = hole_em->block_start; em->block_len = hole_len; + if (test_bit(EXTENT_FLAG_PREALLOC, &hole_em->flags)) + set_bit(EXTENT_FLAG_PREALLOC, &em->flags); } else { em->start = range_start; em->len = found; @@ -6915,11 +6969,9 @@ static int btrfs_truncate(struct inode *inode) /* * 1 for the truncate slack space - * 1 for the orphan item we're going to add - * 1 for the orphan item deletion * 1 for updating the inode. */ - trans = btrfs_start_transaction(root, 4); + trans = btrfs_start_transaction(root, 2); if (IS_ERR(trans)) { err = PTR_ERR(trans); goto out; @@ -6930,12 +6982,6 @@ static int btrfs_truncate(struct inode *inode) min_size); BUG_ON(ret); - ret = btrfs_orphan_add(trans, inode); - if (ret) { - btrfs_end_transaction(trans, root); - goto out; - } - /* * setattr is responsible for setting the ordered_data_close flag, * but that is only tested during the last file release. That @@ -7004,12 +7050,6 @@ static int btrfs_truncate(struct inode *inode) ret = btrfs_orphan_del(trans, inode); if (ret) err = ret; - } else if (ret && inode->i_nlink > 0) { - /* - * Failed to do the truncate, remove us from the in memory - * orphan list. - */ - ret = btrfs_orphan_del(NULL, inode); } if (trans) { @@ -7531,41 +7571,61 @@ void btrfs_wait_and_free_delalloc_work(struct btrfs_delalloc_work *work) */ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput) { - struct list_head *head = &root->fs_info->delalloc_inodes; struct btrfs_inode *binode; struct inode *inode; struct btrfs_delalloc_work *work, *next; struct list_head works; + struct list_head splice; int ret = 0; if (root->fs_info->sb->s_flags & MS_RDONLY) return -EROFS; INIT_LIST_HEAD(&works); - + INIT_LIST_HEAD(&splice); +again: spin_lock(&root->fs_info->delalloc_lock); - while (!list_empty(head)) { - binode = list_entry(head->next, struct btrfs_inode, + list_splice_init(&root->fs_info->delalloc_inodes, &splice); + while (!list_empty(&splice)) { + binode = list_entry(splice.next, struct btrfs_inode, delalloc_inodes); + + list_del_init(&binode->delalloc_inodes); + inode = igrab(&binode->vfs_inode); if (!inode) - list_del_init(&binode->delalloc_inodes); + continue; + + list_add_tail(&binode->delalloc_inodes, + &root->fs_info->delalloc_inodes); spin_unlock(&root->fs_info->delalloc_lock); - if (inode) { - work = btrfs_alloc_delalloc_work(inode, 0, delay_iput); - if (!work) { - ret = -ENOMEM; - goto out; - } - list_add_tail(&work->list, &works); - btrfs_queue_worker(&root->fs_info->flush_workers, - &work->work); + + work = btrfs_alloc_delalloc_work(inode, 0, delay_iput); + if (unlikely(!work)) { + ret = -ENOMEM; + goto out; } + list_add_tail(&work->list, &works); + btrfs_queue_worker(&root->fs_info->flush_workers, + &work->work); + cond_resched(); spin_lock(&root->fs_info->delalloc_lock); } spin_unlock(&root->fs_info->delalloc_lock); + list_for_each_entry_safe(work, next, &works, list) { + list_del_init(&work->list); + btrfs_wait_and_free_delalloc_work(work); + } + + spin_lock(&root->fs_info->delalloc_lock); + if (!list_empty(&root->fs_info->delalloc_inodes)) { + spin_unlock(&root->fs_info->delalloc_lock); + goto again; + } + spin_unlock(&root->fs_info->delalloc_lock); + /* the filemap_flush will queue IO into the worker threads, but * we have to make sure the IO is actually started and that * ordered extents get created before we return @@ -7578,11 +7638,18 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput) atomic_read(&root->fs_info->async_delalloc_pages) == 0)); } atomic_dec(&root->fs_info->async_submit_draining); + return 0; out: list_for_each_entry_safe(work, next, &works, list) { list_del_init(&work->list); btrfs_wait_and_free_delalloc_work(work); } + + if (!list_empty_careful(&splice)) { + spin_lock(&root->fs_info->delalloc_lock); + list_splice_tail(&splice, &root->fs_info->delalloc_inodes); + spin_unlock(&root->fs_info->delalloc_lock); + } return ret; } diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 4b4516770f0..5b22d45d3c6 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1339,7 +1339,8 @@ static noinline int btrfs_ioctl_resize(struct file *file, if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, 1)) { pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); - return -EINPROGRESS; + mnt_drop_write_file(file); + return -EINVAL; } mutex_lock(&root->fs_info->volume_mutex); @@ -1362,6 +1363,7 @@ static noinline int btrfs_ioctl_resize(struct file *file, printk(KERN_INFO "btrfs: resizing devid %llu\n", (unsigned long long)devid); } + device = btrfs_find_device(root->fs_info, devid, NULL, NULL); if (!device) { printk(KERN_INFO "btrfs: resizer unable to find device %llu\n", @@ -1369,9 +1371,10 @@ static noinline int btrfs_ioctl_resize(struct file *file, ret = -EINVAL; goto out_free; } - if (device->fs_devices && device->fs_devices->seeding) { + + if (!device->writeable) { printk(KERN_INFO "btrfs: resizer unable to apply on " - "seeding device %llu\n", + "readonly device %llu\n", (unsigned long long)devid); ret = -EINVAL; goto out_free; @@ -1443,8 +1446,8 @@ out_free: kfree(vol_args); out: mutex_unlock(&root->fs_info->volume_mutex); - mnt_drop_write_file(file); atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); + mnt_drop_write_file(file); return ret; } @@ -2095,13 +2098,13 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, err = inode_permission(inode, MAY_WRITE | MAY_EXEC); if (err) goto out_dput; - - /* check if subvolume may be deleted by a non-root user */ - err = btrfs_may_delete(dir, dentry, 1); - if (err) - goto out_dput; } + /* check if subvolume may be deleted by a user */ + err = btrfs_may_delete(dir, dentry, 1); + if (err) + goto out_dput; + if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) { err = -EINVAL; goto out_dput; @@ -2183,19 +2186,20 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) struct btrfs_ioctl_defrag_range_args *range; int ret; - if (btrfs_root_readonly(root)) - return -EROFS; + ret = mnt_want_write_file(file); + if (ret) + return ret; if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, 1)) { pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); - return -EINPROGRESS; + mnt_drop_write_file(file); + return -EINVAL; } - ret = mnt_want_write_file(file); - if (ret) { - atomic_set(&root->fs_info->mutually_exclusive_operation_running, - 0); - return ret; + + if (btrfs_root_readonly(root)) { + ret = -EROFS; + goto out; } switch (inode->i_mode & S_IFMT) { @@ -2247,8 +2251,8 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) ret = -EINVAL; } out: - mnt_drop_write_file(file); atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); + mnt_drop_write_file(file); return ret; } @@ -2263,7 +2267,7 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg) if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, 1)) { pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); - return -EINPROGRESS; + return -EINVAL; } mutex_lock(&root->fs_info->volume_mutex); @@ -2300,7 +2304,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) 1)) { pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); mnt_drop_write_file(file); - return -EINPROGRESS; + return -EINVAL; } mutex_lock(&root->fs_info->volume_mutex); @@ -2316,8 +2320,8 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) kfree(vol_args); out: mutex_unlock(&root->fs_info->volume_mutex); - mnt_drop_write_file(file); atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); + mnt_drop_write_file(file); return ret; } @@ -3437,8 +3441,8 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_ioctl_balance_args *bargs; struct btrfs_balance_control *bctl; + bool need_unlock; /* for mut. excl. ops lock */ int ret; - int need_to_clear_lock = 0; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -3447,14 +3451,61 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) if (ret) return ret; - mutex_lock(&fs_info->volume_mutex); +again: + if (!atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) { + mutex_lock(&fs_info->volume_mutex); + mutex_lock(&fs_info->balance_mutex); + need_unlock = true; + goto locked; + } + + /* + * mut. excl. ops lock is locked. Three possibilites: + * (1) some other op is running + * (2) balance is running + * (3) balance is paused -- special case (think resume) + */ mutex_lock(&fs_info->balance_mutex); + if (fs_info->balance_ctl) { + /* this is either (2) or (3) */ + if (!atomic_read(&fs_info->balance_running)) { + mutex_unlock(&fs_info->balance_mutex); + if (!mutex_trylock(&fs_info->volume_mutex)) + goto again; + mutex_lock(&fs_info->balance_mutex); + + if (fs_info->balance_ctl && + !atomic_read(&fs_info->balance_running)) { + /* this is (3) */ + need_unlock = false; + goto locked; + } + + mutex_unlock(&fs_info->balance_mutex); + mutex_unlock(&fs_info->volume_mutex); + goto again; + } else { + /* this is (2) */ + mutex_unlock(&fs_info->balance_mutex); + ret = -EINPROGRESS; + goto out; + } + } else { + /* this is (1) */ + mutex_unlock(&fs_info->balance_mutex); + pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); + ret = -EINVAL; + goto out; + } + +locked: + BUG_ON(!atomic_read(&fs_info->mutually_exclusive_operation_running)); if (arg) { bargs = memdup_user(arg, sizeof(*bargs)); if (IS_ERR(bargs)) { ret = PTR_ERR(bargs); - goto out; + goto out_unlock; } if (bargs->flags & BTRFS_BALANCE_RESUME) { @@ -3474,13 +3525,10 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) bargs = NULL; } - if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, - 1)) { - pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); + if (fs_info->balance_ctl) { ret = -EINPROGRESS; goto out_bargs; } - need_to_clear_lock = 1; bctl = kzalloc(sizeof(*bctl), GFP_NOFS); if (!bctl) { @@ -3501,11 +3549,17 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) } do_balance: - ret = btrfs_balance(bctl, bargs); /* - * bctl is freed in __cancel_balance or in free_fs_info if - * restriper was paused all the way until unmount + * Ownership of bctl and mutually_exclusive_operation_running + * goes to to btrfs_balance. bctl is freed in __cancel_balance, + * or, if restriper was paused all the way until unmount, in + * free_fs_info. mutually_exclusive_operation_running is + * cleared in __cancel_balance. */ + need_unlock = false; + + ret = btrfs_balance(bctl, bargs); + if (arg) { if (copy_to_user(arg, bargs, sizeof(*bargs))) ret = -EFAULT; @@ -3513,12 +3567,12 @@ do_balance: out_bargs: kfree(bargs); -out: - if (need_to_clear_lock) - atomic_set(&root->fs_info->mutually_exclusive_operation_running, - 0); +out_unlock: mutex_unlock(&fs_info->balance_mutex); mutex_unlock(&fs_info->volume_mutex); + if (need_unlock) + atomic_set(&fs_info->mutually_exclusive_operation_running, 0); +out: mnt_drop_write_file(file); return ret; } @@ -3698,6 +3752,11 @@ static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg) goto drop_write; } + if (!sa->qgroupid) { + ret = -EINVAL; + goto out; + } + trans = btrfs_join_transaction(root); if (IS_ERR(trans)) { ret = PTR_ERR(trans); diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index fe9d02c45f8..a5c85623432 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -379,6 +379,13 @@ next1: ret = add_relation_rb(fs_info, found_key.objectid, found_key.offset); + if (ret == -ENOENT) { + printk(KERN_WARNING + "btrfs: orphan qgroup relation 0x%llx->0x%llx\n", + (unsigned long long)found_key.objectid, + (unsigned long long)found_key.offset); + ret = 0; /* ignore the error */ + } if (ret) goto out; next2: @@ -956,17 +963,28 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 qgroupid) { struct btrfs_root *quota_root; + struct btrfs_qgroup *qgroup; int ret = 0; quota_root = fs_info->quota_root; if (!quota_root) return -EINVAL; + /* check if there are no relations to this qgroup */ + spin_lock(&fs_info->qgroup_lock); + qgroup = find_qgroup_rb(fs_info, qgroupid); + if (qgroup) { + if (!list_empty(&qgroup->groups) || !list_empty(&qgroup->members)) { + spin_unlock(&fs_info->qgroup_lock); + return -EBUSY; + } + } + spin_unlock(&fs_info->qgroup_lock); + ret = del_qgroup_item(trans, quota_root, qgroupid); spin_lock(&fs_info->qgroup_lock); del_qgroup_rb(quota_root->fs_info, qgroupid); - spin_unlock(&fs_info->qgroup_lock); return ret; diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 54454542ad4..321b7fb4e44 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -1814,8 +1814,10 @@ static int name_cache_insert(struct send_ctx *sctx, (unsigned long)nce->ino); if (!nce_head) { nce_head = kmalloc(sizeof(*nce_head), GFP_NOFS); - if (!nce_head) + if (!nce_head) { + kfree(nce); return -ENOMEM; + } INIT_LIST_HEAD(nce_head); ret = radix_tree_insert(&sctx->name_cache, nce->ino, nce_head); diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 99545df1b86..d8982e9601d 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -267,7 +267,7 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans, function, line, errstr); return; } - trans->transaction->aborted = errno; + ACCESS_ONCE(trans->transaction->aborted) = errno; __btrfs_std_error(root->fs_info, function, line, errno, NULL); } /* diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 87fac9a21ea..f15494699f3 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -1468,7 +1468,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, goto cleanup_transaction; } - if (cur_trans->aborted) { + /* Stop the commit early if ->aborted is set */ + if (unlikely(ACCESS_ONCE(cur_trans->aborted))) { ret = cur_trans->aborted; goto cleanup_transaction; } @@ -1574,6 +1575,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, wait_event(cur_trans->writer_wait, atomic_read(&cur_trans->num_writers) == 1); + /* ->aborted might be set after the previous check, so check it */ + if (unlikely(ACCESS_ONCE(cur_trans->aborted))) { + ret = cur_trans->aborted; + goto cleanup_transaction; + } /* * the reloc mutex makes sure that we stop * the balancing code from coming in and moving @@ -1657,6 +1663,17 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, goto cleanup_transaction; } + /* + * The tasks which save the space cache and inode cache may also + * update ->aborted, check it. + */ + if (unlikely(ACCESS_ONCE(cur_trans->aborted))) { + ret = cur_trans->aborted; + mutex_unlock(&root->fs_info->tree_log_mutex); + mutex_unlock(&root->fs_info->reloc_mutex); + goto cleanup_transaction; + } + btrfs_prepare_extent_commit(trans, root); cur_trans = root->fs_info->running_transaction; diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 83186c7e45d..9027bb1e746 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -3357,6 +3357,11 @@ static int log_one_extent(struct btrfs_trans_handle *trans, if (skip_csum) return 0; + if (em->compress_type) { + csum_offset = 0; + csum_len = block_len; + } + /* block start is already adjusted for the file extent offset. */ ret = btrfs_lookup_csums_range(log->fs_info->csum_root, em->block_start + csum_offset, @@ -3410,13 +3415,13 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, em = list_entry(extents.next, struct extent_map, list); list_del_init(&em->list); - clear_bit(EXTENT_FLAG_LOGGING, &em->flags); /* * If we had an error we just need to delete everybody from our * private list. */ if (ret) { + clear_em_logging(tree, em); free_extent_map(em); continue; } @@ -3424,8 +3429,9 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, write_unlock(&tree->lock); ret = log_one_extent(trans, inode, root, em, path); - free_extent_map(em); write_lock(&tree->lock); + clear_em_logging(tree, em); + free_extent_map(em); } WARN_ON(!list_empty(&extents)); write_unlock(&tree->lock); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 5cce6aa7401..15f6efdf646 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1431,7 +1431,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) } } else { ret = btrfs_get_bdev_and_sb(device_path, - FMODE_READ | FMODE_EXCL, + FMODE_WRITE | FMODE_EXCL, root->fs_info->bdev_holder, 0, &bdev, &bh); if (ret) @@ -2614,7 +2614,14 @@ static int chunk_usage_filter(struct btrfs_fs_info *fs_info, u64 chunk_offset, cache = btrfs_lookup_block_group(fs_info, chunk_offset); chunk_used = btrfs_block_group_used(&cache->item); - user_thresh = div_factor_fine(cache->key.offset, bargs->usage); + if (bargs->usage == 0) + user_thresh = 0; + else if (bargs->usage > 100) + user_thresh = cache->key.offset; + else + user_thresh = div_factor_fine(cache->key.offset, + bargs->usage); + if (chunk_used < user_thresh) ret = 0; @@ -2959,6 +2966,8 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info) unset_balance_control(fs_info); ret = del_balance_item(fs_info->tree_root); BUG_ON(ret); + + atomic_set(&fs_info->mutually_exclusive_operation_running, 0); } void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock, @@ -3138,8 +3147,10 @@ int btrfs_balance(struct btrfs_balance_control *bctl, out: if (bctl->flags & BTRFS_BALANCE_RESUME) __cancel_balance(fs_info); - else + else { kfree(bctl); + atomic_set(&fs_info->mutually_exclusive_operation_running, 0); + } return ret; } @@ -3156,7 +3167,6 @@ static int balance_kthread(void *data) ret = btrfs_balance(fs_info->balance_ctl, NULL); } - atomic_set(&fs_info->mutually_exclusive_operation_running, 0); mutex_unlock(&fs_info->balance_mutex); mutex_unlock(&fs_info->volume_mutex); @@ -3179,7 +3189,6 @@ int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info) return 0; } - WARN_ON(atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)); tsk = kthread_run(balance_kthread, fs_info, "btrfs-balance"); if (IS_ERR(tsk)) return PTR_ERR(tsk); @@ -3233,6 +3242,8 @@ int btrfs_recover_balance(struct btrfs_fs_info *fs_info) btrfs_balance_sys(leaf, item, &disk_bargs); btrfs_disk_balance_args_to_cpu(&bctl->sys, &disk_bargs); + WARN_ON(atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)); + mutex_lock(&fs_info->volume_mutex); mutex_lock(&fs_info->balance_mutex); @@ -3496,7 +3507,7 @@ struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = { { 1, 1, 2, 2, 2, 2 /* raid1 */ }, { 1, 2, 1, 1, 1, 2 /* dup */ }, { 1, 1, 0, 2, 1, 1 /* raid0 */ }, - { 1, 1, 0, 1, 1, 1 /* single */ }, + { 1, 1, 1, 1, 1, 1 /* single */ }, }; static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, diff --git a/fs/buffer.c b/fs/buffer.c index c017a2dfb90..7a75c3e0fd5 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2935,6 +2935,7 @@ static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh) void *kaddr = kmap_atomic(bh->b_page); memset(kaddr + bh_offset(bh) + bytes, 0, bh->b_size - bytes); kunmap_atomic(kaddr); + flush_dcache_page(bh->b_page); } } diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index ce5cbd717bf..210fce2df30 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -226,6 +226,8 @@ compose_mount_options_out: compose_mount_options_err: kfree(mountdata); mountdata = ERR_PTR(rc); + kfree(*devname); + *devname = NULL; goto compose_mount_options_out; } diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 17c3643e595..12b3da39733 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1917,7 +1917,7 @@ srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs) } case AF_INET6: { struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr; - struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs; + struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs; return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr); } default: diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 153bb1e42e6..a5f12b7e228 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -176,7 +176,7 @@ static int debugfs_parse_options(char *data, struct debugfs_mount_opts *opts) opts->uid = uid; break; case Opt_gid: - if (match_octal(&args[0], &option)) + if (match_int(&args[0], &option)) return -EINVAL; gid = make_kgid(current_user_ns(), option); if (!gid_valid(gid)) diff --git a/fs/exec.c b/fs/exec.c index 18c45cac368..20df02c1cc7 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -434,8 +434,9 @@ static int count(struct user_arg_ptr argv, int max) if (IS_ERR(p)) return -EFAULT; - if (i++ >= max) + if (i >= max) return -E2BIG; + ++i; if (fatal_signal_pending(current)) return -ERESTARTNOHAND; diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index e95b94945d5..137af4255da 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c @@ -191,15 +191,14 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int type) retval = f2fs_getxattr(inode, name_index, "", value, retval); } - if (retval < 0) { - if (retval == -ENODATA) - acl = NULL; - else - acl = ERR_PTR(retval); - } else { + if (retval > 0) acl = f2fs_acl_from_disk(value, retval); - } + else if (retval == -ENODATA) + acl = NULL; + else + acl = ERR_PTR(retval); kfree(value); + if (!IS_ERR(acl)) set_cached_acl(inode, type, acl); diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 6ef36c37e2b..ff3c8439af8 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -214,7 +214,6 @@ retry: goto retry; } new->ino = ino; - INIT_LIST_HEAD(&new->list); /* add new_oentry into list which is sorted by inode number */ if (orphan) { @@ -772,7 +771,7 @@ void init_orphan_info(struct f2fs_sb_info *sbi) sbi->n_orphans = 0; } -int create_checkpoint_caches(void) +int __init create_checkpoint_caches(void) { orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry", sizeof(struct orphan_inode_entry), NULL); diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 3aa5ce7cab8..7bd22a20112 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -547,6 +547,15 @@ redirty_out: #define MAX_DESIRED_PAGES_WP 4096 +static int __f2fs_writepage(struct page *page, struct writeback_control *wbc, + void *data) +{ + struct address_space *mapping = data; + int ret = mapping->a_ops->writepage(page, wbc); + mapping_set_error(mapping, ret); + return ret; +} + static int f2fs_write_data_pages(struct address_space *mapping, struct writeback_control *wbc) { @@ -563,7 +572,7 @@ static int f2fs_write_data_pages(struct address_space *mapping, if (!S_ISDIR(inode->i_mode)) mutex_lock(&sbi->writepages); - ret = generic_writepages(mapping, wbc); + ret = write_cache_pages(mapping, wbc, __f2fs_writepage, mapping); if (!S_ISDIR(inode->i_mode)) mutex_unlock(&sbi->writepages); f2fs_submit_bio(sbi, DATA, (wbc->sync_mode == WB_SYNC_ALL)); @@ -689,6 +698,11 @@ static int f2fs_set_data_page_dirty(struct page *page) return 0; } +static sector_t f2fs_bmap(struct address_space *mapping, sector_t block) +{ + return generic_block_bmap(mapping, block, get_data_block_ro); +} + const struct address_space_operations f2fs_dblock_aops = { .readpage = f2fs_read_data_page, .readpages = f2fs_read_data_pages, @@ -700,4 +714,5 @@ const struct address_space_operations f2fs_dblock_aops = { .invalidatepage = f2fs_invalidate_data_page, .releasepage = f2fs_release_data_page, .direct_IO = f2fs_direct_IO, + .bmap = f2fs_bmap, }; diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index 0e0380a588a..c8c37307b32 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -26,6 +26,7 @@ static LIST_HEAD(f2fs_stat_list); static struct dentry *debugfs_root; +static DEFINE_MUTEX(f2fs_stat_mutex); static void update_general_status(struct f2fs_sb_info *sbi) { @@ -180,18 +181,14 @@ static int stat_show(struct seq_file *s, void *v) int i = 0; int j; + mutex_lock(&f2fs_stat_mutex); list_for_each_entry_safe(si, next, &f2fs_stat_list, stat_list) { - mutex_lock(&si->stat_lock); - if (!si->sbi) { - mutex_unlock(&si->stat_lock); - continue; - } update_general_status(si->sbi); seq_printf(s, "\n=====[ partition info. #%d ]=====\n", i++); - seq_printf(s, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ", - si->nat_area_segs, si->sit_area_segs); + seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ", + si->sit_area_segs, si->nat_area_segs); seq_printf(s, "[SSA: %d] [MAIN: %d", si->ssa_area_segs, si->main_area_segs); seq_printf(s, "(OverProv:%d Resv:%d)]\n\n", @@ -286,8 +283,8 @@ static int stat_show(struct seq_file *s, void *v) seq_printf(s, "\nMemory: %u KB = static: %u + cached: %u\n", (si->base_mem + si->cache_mem) >> 10, si->base_mem >> 10, si->cache_mem >> 10); - mutex_unlock(&si->stat_lock); } + mutex_unlock(&f2fs_stat_mutex); return 0; } @@ -303,7 +300,7 @@ static const struct file_operations stat_fops = { .release = single_release, }; -static int init_stats(struct f2fs_sb_info *sbi) +int f2fs_build_stats(struct f2fs_sb_info *sbi) { struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); struct f2fs_stat_info *si; @@ -313,9 +310,6 @@ static int init_stats(struct f2fs_sb_info *sbi) return -ENOMEM; si = sbi->stat_info; - mutex_init(&si->stat_lock); - list_add_tail(&si->stat_list, &f2fs_stat_list); - si->all_area_segs = le32_to_cpu(raw_super->segment_count); si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit); si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat); @@ -325,21 +319,11 @@ static int init_stats(struct f2fs_sb_info *sbi) si->main_area_zones = si->main_area_sections / le32_to_cpu(raw_super->secs_per_zone); si->sbi = sbi; - return 0; -} -int f2fs_build_stats(struct f2fs_sb_info *sbi) -{ - int retval; - - retval = init_stats(sbi); - if (retval) - return retval; - - if (!debugfs_root) - debugfs_root = debugfs_create_dir("f2fs", NULL); + mutex_lock(&f2fs_stat_mutex); + list_add_tail(&si->stat_list, &f2fs_stat_list); + mutex_unlock(&f2fs_stat_mutex); - debugfs_create_file("status", S_IRUGO, debugfs_root, NULL, &stat_fops); return 0; } @@ -347,14 +331,22 @@ void f2fs_destroy_stats(struct f2fs_sb_info *sbi) { struct f2fs_stat_info *si = sbi->stat_info; + mutex_lock(&f2fs_stat_mutex); list_del(&si->stat_list); - mutex_lock(&si->stat_lock); - si->sbi = NULL; - mutex_unlock(&si->stat_lock); + mutex_unlock(&f2fs_stat_mutex); + kfree(sbi->stat_info); } -void destroy_root_stats(void) +void __init f2fs_create_root_stats(void) +{ + debugfs_root = debugfs_create_dir("f2fs", NULL); + if (debugfs_root) + debugfs_create_file("status", S_IRUGO, debugfs_root, + NULL, &stat_fops); +} + +void f2fs_destroy_root_stats(void) { debugfs_remove_recursive(debugfs_root); debugfs_root = NULL; diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 951ed52748f..989980e16d0 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -503,7 +503,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, } if (inode) { - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; + inode->i_ctime = CURRENT_TIME; drop_nlink(inode); if (S_ISDIR(inode->i_mode)) { drop_nlink(inode); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 13c6dfbb718..c8e2d751ef9 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -211,11 +211,11 @@ struct dnode_of_data { static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode, struct page *ipage, struct page *npage, nid_t nid) { + memset(dn, 0, sizeof(*dn)); dn->inode = inode; dn->inode_page = ipage; dn->node_page = npage; dn->nid = nid; - dn->inode_page_locked = 0; } /* @@ -877,6 +877,8 @@ bool f2fs_empty_dir(struct inode *); * super.c */ int f2fs_sync_fs(struct super_block *, int); +extern __printf(3, 4) +void f2fs_msg(struct super_block *, const char *, const char *, ...); /* * hash.c @@ -912,7 +914,7 @@ int restore_node_summary(struct f2fs_sb_info *, unsigned int, void flush_nat_entries(struct f2fs_sb_info *); int build_node_manager(struct f2fs_sb_info *); void destroy_node_manager(struct f2fs_sb_info *); -int create_node_manager_caches(void); +int __init create_node_manager_caches(void); void destroy_node_manager_caches(void); /* @@ -964,7 +966,7 @@ void sync_dirty_dir_inodes(struct f2fs_sb_info *); void block_operations(struct f2fs_sb_info *); void write_checkpoint(struct f2fs_sb_info *, bool, bool); void init_orphan_info(struct f2fs_sb_info *); -int create_checkpoint_caches(void); +int __init create_checkpoint_caches(void); void destroy_checkpoint_caches(void); /* @@ -984,9 +986,9 @@ int do_write_data_page(struct page *); int start_gc_thread(struct f2fs_sb_info *); void stop_gc_thread(struct f2fs_sb_info *); block_t start_bidx_of_node(unsigned int); -int f2fs_gc(struct f2fs_sb_info *, int); +int f2fs_gc(struct f2fs_sb_info *); void build_gc_manager(struct f2fs_sb_info *); -int create_gc_caches(void); +int __init create_gc_caches(void); void destroy_gc_caches(void); /* @@ -1058,7 +1060,8 @@ struct f2fs_stat_info { int f2fs_build_stats(struct f2fs_sb_info *); void f2fs_destroy_stats(struct f2fs_sb_info *); -void destroy_root_stats(void); +void __init f2fs_create_root_stats(void); +void f2fs_destroy_root_stats(void); #else #define stat_inc_call_count(si) #define stat_inc_seg_count(si, type) @@ -1068,7 +1071,8 @@ void destroy_root_stats(void); static inline int f2fs_build_stats(struct f2fs_sb_info *sbi) { return 0; } static inline void f2fs_destroy_stats(struct f2fs_sb_info *sbi) { } -static inline void destroy_root_stats(void) { } +static inline void __init f2fs_create_root_stats(void) { } +static inline void f2fs_destroy_root_stats(void) { } #endif extern const struct file_operations f2fs_dir_operations; diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 7f9ea9271eb..3191b52aafb 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -96,8 +96,9 @@ out: } static const struct vm_operations_struct f2fs_file_vm_ops = { - .fault = filemap_fault, - .page_mkwrite = f2fs_vm_page_mkwrite, + .fault = filemap_fault, + .page_mkwrite = f2fs_vm_page_mkwrite, + .remap_pages = generic_file_remap_pages, }; static int need_to_sync_dir(struct f2fs_sb_info *sbi, struct inode *inode) @@ -137,6 +138,9 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) if (ret) return ret; + /* guarantee free sections for fsync */ + f2fs_balance_fs(sbi); + mutex_lock(&inode->i_mutex); if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) @@ -407,6 +411,8 @@ int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end) struct dnode_of_data dn; struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + f2fs_balance_fs(sbi); + mutex_lock_op(sbi, DATA_TRUNC); set_new_dnode(&dn, inode, NULL, NULL, 0); err = get_dnode_of_data(&dn, index, RDONLY_NODE); @@ -534,7 +540,6 @@ static long f2fs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) { struct inode *inode = file->f_path.dentry->d_inode; - struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); long ret; if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) @@ -545,7 +550,10 @@ static long f2fs_fallocate(struct file *file, int mode, else ret = expand_inode_data(inode, offset, len, mode); - f2fs_balance_fs(sbi); + if (!ret) { + inode->i_mtime = inode->i_ctime = CURRENT_TIME; + mark_inode_dirty(inode); + } return ret; } diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index b0ec721e984..c386910dacc 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -78,7 +78,7 @@ static int gc_thread_func(void *data) sbi->bg_gc++; - if (f2fs_gc(sbi, 1) == GC_NONE) + if (f2fs_gc(sbi) == GC_NONE) wait_ms = GC_THREAD_NOGC_SLEEP_TIME; else if (wait_ms == GC_THREAD_NOGC_SLEEP_TIME) wait_ms = GC_THREAD_MAX_SLEEP_TIME; @@ -424,7 +424,11 @@ next_step: } /* - * Calculate start block index that this node page contains + * Calculate start block index indicating the given node offset. + * Be careful, caller should give this node offset only indicating direct node + * blocks. If any node offsets, which point the other types of node blocks such + * as indirect or double indirect node blocks, are given, it must be a caller's + * bug. */ block_t start_bidx_of_node(unsigned int node_ofs) { @@ -651,62 +655,44 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno, return ret; } -int f2fs_gc(struct f2fs_sb_info *sbi, int nGC) +int f2fs_gc(struct f2fs_sb_info *sbi) { - unsigned int segno; - int old_free_secs, cur_free_secs; - int gc_status, nfree; struct list_head ilist; + unsigned int segno, i; int gc_type = BG_GC; + int gc_status = GC_NONE; INIT_LIST_HEAD(&ilist); gc_more: - nfree = 0; - gc_status = GC_NONE; + if (!(sbi->sb->s_flags & MS_ACTIVE)) + goto stop; if (has_not_enough_free_secs(sbi)) - old_free_secs = reserved_sections(sbi); - else - old_free_secs = free_sections(sbi); - - while (sbi->sb->s_flags & MS_ACTIVE) { - int i; - if (has_not_enough_free_secs(sbi)) - gc_type = FG_GC; + gc_type = FG_GC; - cur_free_secs = free_sections(sbi) + nfree; + if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE)) + goto stop; - /* We got free space successfully. */ - if (nGC < cur_free_secs - old_free_secs) - break; - - if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE)) + for (i = 0; i < sbi->segs_per_sec; i++) { + /* + * do_garbage_collect will give us three gc_status: + * GC_ERROR, GC_DONE, and GC_BLOCKED. + * If GC is finished uncleanly, we have to return + * the victim to dirty segment list. + */ + gc_status = do_garbage_collect(sbi, segno + i, &ilist, gc_type); + if (gc_status != GC_DONE) break; - - for (i = 0; i < sbi->segs_per_sec; i++) { - /* - * do_garbage_collect will give us three gc_status: - * GC_ERROR, GC_DONE, and GC_BLOCKED. - * If GC is finished uncleanly, we have to return - * the victim to dirty segment list. - */ - gc_status = do_garbage_collect(sbi, segno + i, - &ilist, gc_type); - if (gc_status != GC_DONE) - goto stop; - nfree++; - } } -stop: - if (has_not_enough_free_secs(sbi) || gc_status == GC_BLOCKED) { + if (has_not_enough_free_secs(sbi)) { write_checkpoint(sbi, (gc_status == GC_BLOCKED), false); - if (nfree) + if (has_not_enough_free_secs(sbi)) goto gc_more; } +stop: mutex_unlock(&sbi->gc_mutex); put_gc_inode(&ilist); - BUG_ON(!list_empty(&ilist)); return gc_status; } @@ -715,7 +701,7 @@ void build_gc_manager(struct f2fs_sb_info *sbi) DIRTY_I(sbi)->v_ops = &default_v_ops; } -int create_gc_caches(void) +int __init create_gc_caches(void) { winode_slab = f2fs_kmem_cache_create("f2fs_gc_inodes", sizeof(struct inode_entry), NULL); diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index bf20b4d0321..79424177732 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -217,6 +217,9 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) inode->i_ino == F2FS_META_INO(sbi)) return 0; + if (wbc) + f2fs_balance_fs(sbi); + node_page = get_node_page(sbi, inode->i_ino); if (IS_ERR(node_page)) return PTR_ERR(node_page); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 5066bfd256c..9bda63c9c16 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1124,6 +1124,12 @@ static int f2fs_write_node_page(struct page *page, return 0; } +/* + * It is very important to gather dirty pages and write at once, so that we can + * submit a big bio without interfering other data writes. + * Be default, 512 pages (2MB), a segment size, is quite reasonable. + */ +#define COLLECT_DIRTY_NODES 512 static int f2fs_write_node_pages(struct address_space *mapping, struct writeback_control *wbc) { @@ -1131,17 +1137,16 @@ static int f2fs_write_node_pages(struct address_space *mapping, struct block_device *bdev = sbi->sb->s_bdev; long nr_to_write = wbc->nr_to_write; - if (wbc->for_kupdate) - return 0; - - if (get_pages(sbi, F2FS_DIRTY_NODES) == 0) - return 0; - + /* First check balancing cached NAT entries */ if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) { write_checkpoint(sbi, false, false); return 0; } + /* collect a number of dirty node pages and write together */ + if (get_pages(sbi, F2FS_DIRTY_NODES) < COLLECT_DIRTY_NODES) + return 0; + /* if mounting is failed, skip writing node pages */ wbc->nr_to_write = bio_get_nr_vecs(bdev); sync_node_pages(sbi, 0, wbc); @@ -1732,7 +1737,7 @@ void destroy_node_manager(struct f2fs_sb_info *sbi) kfree(nm_i); } -int create_node_manager_caches(void) +int __init create_node_manager_caches(void) { nat_entry_slab = f2fs_kmem_cache_create("nat_entry", sizeof(struct nat_entry), NULL); diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index b571fee677d..f42e4060b39 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -67,7 +67,7 @@ static int recover_dentry(struct page *ipage, struct inode *inode) kunmap(page); f2fs_put_page(page, 0); } else { - f2fs_add_link(&dent, inode); + err = f2fs_add_link(&dent, inode); } iput(dir); out: @@ -151,7 +151,6 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) goto out; } - INIT_LIST_HEAD(&entry->list); list_add_tail(&entry->list, head); entry->blkaddr = blkaddr; } @@ -174,10 +173,9 @@ out: static void destroy_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) { - struct list_head *this; - struct fsync_inode_entry *entry; - list_for_each(this, head) { - entry = list_entry(this, struct fsync_inode_entry, list); + struct fsync_inode_entry *entry, *tmp; + + list_for_each_entry_safe(entry, tmp, head, list) { iput(entry->inode); list_del(&entry->list); kmem_cache_free(fsync_entry_slab, entry); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index de6240922b0..4b009906658 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -31,7 +31,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi) */ if (has_not_enough_free_secs(sbi)) { mutex_lock(&sbi->gc_mutex); - f2fs_gc(sbi, 1); + f2fs_gc(sbi); } } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 08a94c814bd..37fad04c866 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -53,6 +53,18 @@ static match_table_t f2fs_tokens = { {Opt_err, NULL}, }; +void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + printk("%sF2FS-fs (%s): %pV\n", level, sb->s_id, &vaf); + va_end(args); +} + static void init_once(void *foo) { struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo; @@ -125,6 +137,8 @@ int f2fs_sync_fs(struct super_block *sb, int sync) if (sync) write_checkpoint(sbi, false, false); + else + f2fs_balance_fs(sbi); return 0; } @@ -247,7 +261,8 @@ static const struct export_operations f2fs_export_ops = { .get_parent = f2fs_get_parent, }; -static int parse_options(struct f2fs_sb_info *sbi, char *options) +static int parse_options(struct super_block *sb, struct f2fs_sb_info *sbi, + char *options) { substring_t args[MAX_OPT_ARGS]; char *p; @@ -286,7 +301,8 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options) break; #else case Opt_nouser_xattr: - pr_info("nouser_xattr options not supported\n"); + f2fs_msg(sb, KERN_INFO, + "nouser_xattr options not supported"); break; #endif #ifdef CONFIG_F2FS_FS_POSIX_ACL @@ -295,7 +311,7 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options) break; #else case Opt_noacl: - pr_info("noacl options not supported\n"); + f2fs_msg(sb, KERN_INFO, "noacl options not supported"); break; #endif case Opt_active_logs: @@ -309,8 +325,9 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options) set_opt(sbi, DISABLE_EXT_IDENTIFY); break; default: - pr_err("Unrecognized mount option \"%s\" or missing value\n", - p); + f2fs_msg(sb, KERN_ERR, + "Unrecognized mount option \"%s\" or missing value", + p); return -EINVAL; } } @@ -337,23 +354,36 @@ static loff_t max_file_size(unsigned bits) return result; } -static int sanity_check_raw_super(struct f2fs_super_block *raw_super) +static int sanity_check_raw_super(struct super_block *sb, + struct f2fs_super_block *raw_super) { unsigned int blocksize; - if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) + if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) { + f2fs_msg(sb, KERN_INFO, + "Magic Mismatch, valid(0x%x) - read(0x%x)", + F2FS_SUPER_MAGIC, le32_to_cpu(raw_super->magic)); return 1; + } /* Currently, support only 4KB block size */ blocksize = 1 << le32_to_cpu(raw_super->log_blocksize); - if (blocksize != PAGE_CACHE_SIZE) + if (blocksize != PAGE_CACHE_SIZE) { + f2fs_msg(sb, KERN_INFO, + "Invalid blocksize (%u), supports only 4KB\n", + blocksize); return 1; + } if (le32_to_cpu(raw_super->log_sectorsize) != - F2FS_LOG_SECTOR_SIZE) + F2FS_LOG_SECTOR_SIZE) { + f2fs_msg(sb, KERN_INFO, "Invalid log sectorsize"); return 1; + } if (le32_to_cpu(raw_super->log_sectors_per_block) != - F2FS_LOG_SECTORS_PER_BLOCK) + F2FS_LOG_SECTORS_PER_BLOCK) { + f2fs_msg(sb, KERN_INFO, "Invalid log sectors per block"); return 1; + } return 0; } @@ -413,14 +443,17 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) if (!sbi) return -ENOMEM; - /* set a temporary block size */ - if (!sb_set_blocksize(sb, F2FS_BLKSIZE)) + /* set a block size */ + if (!sb_set_blocksize(sb, F2FS_BLKSIZE)) { + f2fs_msg(sb, KERN_ERR, "unable to set blocksize"); goto free_sbi; + } /* read f2fs raw super block */ raw_super_buf = sb_bread(sb, 0); if (!raw_super_buf) { err = -EIO; + f2fs_msg(sb, KERN_ERR, "unable to read superblock"); goto free_sbi; } raw_super = (struct f2fs_super_block *) @@ -438,12 +471,14 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) set_opt(sbi, POSIX_ACL); #endif /* parse mount options */ - if (parse_options(sbi, (char *)data)) + if (parse_options(sb, sbi, (char *)data)) goto free_sb_buf; /* sanity checking of raw super */ - if (sanity_check_raw_super(raw_super)) + if (sanity_check_raw_super(sb, raw_super)) { + f2fs_msg(sb, KERN_ERR, "Can't find a valid F2FS filesystem"); goto free_sb_buf; + } sb->s_maxbytes = max_file_size(le32_to_cpu(raw_super->log_blocksize)); sb->s_max_links = F2FS_LINK_MAX; @@ -477,18 +512,23 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) /* get an inode for meta space */ sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi)); if (IS_ERR(sbi->meta_inode)) { + f2fs_msg(sb, KERN_ERR, "Failed to read F2FS meta data inode"); err = PTR_ERR(sbi->meta_inode); goto free_sb_buf; } err = get_valid_checkpoint(sbi); - if (err) + if (err) { + f2fs_msg(sb, KERN_ERR, "Failed to get valid F2FS checkpoint"); goto free_meta_inode; + } /* sanity checking of checkpoint */ err = -EINVAL; - if (sanity_check_ckpt(raw_super, sbi->ckpt)) + if (sanity_check_ckpt(raw_super, sbi->ckpt)) { + f2fs_msg(sb, KERN_ERR, "Invalid F2FS checkpoint"); goto free_cp; + } sbi->total_valid_node_count = le32_to_cpu(sbi->ckpt->valid_node_count); @@ -502,25 +542,28 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) INIT_LIST_HEAD(&sbi->dir_inode_list); spin_lock_init(&sbi->dir_inode_lock); - /* init super block */ - if (!sb_set_blocksize(sb, sbi->blocksize)) - goto free_cp; - init_orphan_info(sbi); /* setup f2fs internal modules */ err = build_segment_manager(sbi); - if (err) + if (err) { + f2fs_msg(sb, KERN_ERR, + "Failed to initialize F2FS segment manager"); goto free_sm; + } err = build_node_manager(sbi); - if (err) + if (err) { + f2fs_msg(sb, KERN_ERR, + "Failed to initialize F2FS node manager"); goto free_nm; + } build_gc_manager(sbi); /* get an inode for node space */ sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi)); if (IS_ERR(sbi->node_inode)) { + f2fs_msg(sb, KERN_ERR, "Failed to read node inode"); err = PTR_ERR(sbi->node_inode); goto free_nm; } @@ -533,6 +576,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) /* read root inode and dentry */ root = f2fs_iget(sb, F2FS_ROOT_INO(sbi)); if (IS_ERR(root)) { + f2fs_msg(sb, KERN_ERR, "Failed to read root inode"); err = PTR_ERR(root); goto free_node_inode; } @@ -596,7 +640,7 @@ static struct file_system_type f2fs_fs_type = { .fs_flags = FS_REQUIRES_DEV, }; -static int init_inodecache(void) +static int __init init_inodecache(void) { f2fs_inode_cachep = f2fs_kmem_cache_create("f2fs_inode_cache", sizeof(struct f2fs_inode_info), NULL); @@ -631,14 +675,17 @@ static int __init init_f2fs_fs(void) err = create_checkpoint_caches(); if (err) goto fail; - return register_filesystem(&f2fs_fs_type); + err = register_filesystem(&f2fs_fs_type); + if (err) + goto fail; + f2fs_create_root_stats(); fail: return err; } static void __exit exit_f2fs_fs(void) { - destroy_root_stats(); + f2fs_destroy_root_stats(); unregister_filesystem(&f2fs_fs_type); destroy_checkpoint_caches(); destroy_gc_caches(); diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 940136a3d3a..8038c049650 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -318,6 +318,8 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, if (name_len > 255 || value_len > MAX_VALUE_LEN) return -ERANGE; + f2fs_balance_fs(sbi); + mutex_lock_op(sbi, NODE_NEW); if (!fi->i_xattr_nid) { /* Allocate new attribute block */ diff --git a/fs/fuse/Kconfig b/fs/fuse/Kconfig index 0cf160a94ed..1b2f6c2c3aa 100644 --- a/fs/fuse/Kconfig +++ b/fs/fuse/Kconfig @@ -4,12 +4,24 @@ config FUSE_FS With FUSE it is possible to implement a fully functional filesystem in a userspace program. - There's also companion library: libfuse. This library along with - utilities is available from the FUSE homepage: + There's also a companion library: libfuse2. This library is available + from the FUSE homepage: <http://fuse.sourceforge.net/> + although chances are your distribution already has that library + installed if you've installed the "fuse" package itself. See <file:Documentation/filesystems/fuse.txt> for more information. See <file:Documentation/Changes> for needed library/utility version. If you want to develop a userspace FS, or if you want to use a filesystem based on FUSE, answer Y or M. + +config CUSE + tristate "Character device in Userspace support" + depends on FUSE_FS + help + This FUSE extension allows character devices to be + implemented in userspace. + + If you want to develop or use a userspace character device + based on CUSE, answer Y or M. diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index ee8d5504229..e397b675b02 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c @@ -45,7 +45,6 @@ #include <linux/miscdevice.h> #include <linux/mutex.h> #include <linux/slab.h> -#include <linux/spinlock.h> #include <linux/stat.h> #include <linux/module.h> @@ -63,7 +62,7 @@ struct cuse_conn { bool unrestricted_ioctl; }; -static DEFINE_SPINLOCK(cuse_lock); /* protects cuse_conntbl */ +static DEFINE_MUTEX(cuse_lock); /* protects registration */ static struct list_head cuse_conntbl[CUSE_CONNTBL_LEN]; static struct class *cuse_class; @@ -114,14 +113,14 @@ static int cuse_open(struct inode *inode, struct file *file) int rc; /* look up and get the connection */ - spin_lock(&cuse_lock); + mutex_lock(&cuse_lock); list_for_each_entry(pos, cuse_conntbl_head(devt), list) if (pos->dev->devt == devt) { fuse_conn_get(&pos->fc); cc = pos; break; } - spin_unlock(&cuse_lock); + mutex_unlock(&cuse_lock); /* dead? */ if (!cc) @@ -267,7 +266,7 @@ static int cuse_parse_one(char **pp, char *end, char **keyp, char **valp) static int cuse_parse_devinfo(char *p, size_t len, struct cuse_devinfo *devinfo) { char *end = p + len; - char *key, *val; + char *uninitialized_var(key), *uninitialized_var(val); int rc; while (true) { @@ -305,14 +304,14 @@ static void cuse_gendev_release(struct device *dev) */ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) { - struct cuse_conn *cc = fc_to_cc(fc); + struct cuse_conn *cc = fc_to_cc(fc), *pos; struct cuse_init_out *arg = req->out.args[0].value; struct page *page = req->pages[0]; struct cuse_devinfo devinfo = { }; struct device *dev; struct cdev *cdev; dev_t devt; - int rc; + int rc, i; if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) { @@ -356,15 +355,24 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) dev_set_drvdata(dev, cc); dev_set_name(dev, "%s", devinfo.name); + mutex_lock(&cuse_lock); + + /* make sure the device-name is unique */ + for (i = 0; i < CUSE_CONNTBL_LEN; ++i) { + list_for_each_entry(pos, &cuse_conntbl[i], list) + if (!strcmp(dev_name(pos->dev), dev_name(dev))) + goto err_unlock; + } + rc = device_add(dev); if (rc) - goto err_device; + goto err_unlock; /* register cdev */ rc = -ENOMEM; cdev = cdev_alloc(); if (!cdev) - goto err_device; + goto err_unlock; cdev->owner = THIS_MODULE; cdev->ops = &cuse_frontend_fops; @@ -377,9 +385,8 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) cc->cdev = cdev; /* make the device available */ - spin_lock(&cuse_lock); list_add(&cc->list, cuse_conntbl_head(devt)); - spin_unlock(&cuse_lock); + mutex_unlock(&cuse_lock); /* announce device availability */ dev_set_uevent_suppress(dev, 0); @@ -391,7 +398,8 @@ out: err_cdev: cdev_del(cdev); -err_device: +err_unlock: + mutex_unlock(&cuse_lock); put_device(dev); err_region: unregister_chrdev_region(devt, 1); @@ -520,9 +528,9 @@ static int cuse_channel_release(struct inode *inode, struct file *file) int rc; /* remove from the conntbl, no more access from this point on */ - spin_lock(&cuse_lock); + mutex_lock(&cuse_lock); list_del_init(&cc->list); - spin_unlock(&cuse_lock); + mutex_unlock(&cuse_lock); /* remove device */ if (cc->dev) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index c16335315e5..e83351aa5ba 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -692,8 +692,6 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) struct page *oldpage = *pagep; struct page *newpage; struct pipe_buffer *buf = cs->pipebufs; - struct address_space *mapping; - pgoff_t index; unlock_request(cs->fc, cs->req); fuse_copy_finish(cs); @@ -724,9 +722,6 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) if (fuse_check_page(newpage) != 0) goto out_fallback_unlock; - mapping = oldpage->mapping; - index = oldpage->index; - /* * This is a new and locked page, it shouldn't be mapped or * have any special flags on it diff --git a/fs/fuse/file.c b/fs/fuse/file.c index e21d4d8f87e..f3ab824fa30 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -2177,8 +2177,8 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, return ret; } -long fuse_file_fallocate(struct file *file, int mode, loff_t offset, - loff_t length) +static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, + loff_t length) { struct fuse_file *ff = file->private_data; struct fuse_conn *fc = ff->fc; @@ -2213,7 +2213,6 @@ long fuse_file_fallocate(struct file *file, int mode, loff_t offset, return err; } -EXPORT_SYMBOL_GPL(fuse_file_fallocate); static const struct file_operations fuse_file_operations = { .llseek = fuse_file_llseek, diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index a2862339323..81cc7eaff86 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -446,7 +446,8 @@ int __log_start_commit(journal_t *journal, tid_t target) * currently running transaction (if it exists). Otherwise, * the target tid must be an old one. */ - if (journal->j_running_transaction && + if (journal->j_commit_request != target && + journal->j_running_transaction && journal->j_running_transaction->t_tid == target) { /* * We want a new commit: OK, mark the request and wakeup the diff --git a/fs/seq_file.c b/fs/seq_file.c index 9d863fb501f..f2bc3dfd0b8 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -296,7 +296,7 @@ EXPORT_SYMBOL(seq_read); * seq_lseek - ->llseek() method for sequential files. * @file: the file in question * @offset: new position - * @origin: 0 for absolute, 1 for relative position + * @whence: 0 for absolute, 1 for relative position * * Ready-made ->f_op->llseek() */ diff --git a/fs/udf/super.c b/fs/udf/super.c index d44fb568abe..e9be396a558 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -307,7 +307,8 @@ static void udf_sb_free_partitions(struct super_block *sb) { struct udf_sb_info *sbi = UDF_SB(sb); int i; - + if (sbi->s_partmaps == NULL) + return; for (i = 0; i < sbi->s_partitions; i++) udf_free_partition(&sbi->s_partmaps[i]); kfree(sbi->s_partmaps); diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 26673a0b20e..56d1614760c 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -175,7 +175,7 @@ xfs_buf_get_maps( bp->b_map_count = map_count; if (map_count == 1) { - bp->b_maps = &bp->b_map; + bp->b_maps = &bp->__b_map; return 0; } @@ -193,7 +193,7 @@ static void xfs_buf_free_maps( struct xfs_buf *bp) { - if (bp->b_maps != &bp->b_map) { + if (bp->b_maps != &bp->__b_map) { kmem_free(bp->b_maps); bp->b_maps = NULL; } @@ -377,8 +377,8 @@ xfs_buf_allocate_memory( } use_alloc_page: - start = BBTOB(bp->b_map.bm_bn) >> PAGE_SHIFT; - end = (BBTOB(bp->b_map.bm_bn + bp->b_length) + PAGE_SIZE - 1) + start = BBTOB(bp->b_maps[0].bm_bn) >> PAGE_SHIFT; + end = (BBTOB(bp->b_maps[0].bm_bn + bp->b_length) + PAGE_SIZE - 1) >> PAGE_SHIFT; page_count = end - start; error = _xfs_buf_get_pages(bp, page_count, flags); @@ -640,7 +640,7 @@ _xfs_buf_read( xfs_buf_flags_t flags) { ASSERT(!(flags & XBF_WRITE)); - ASSERT(bp->b_map.bm_bn != XFS_BUF_DADDR_NULL); + ASSERT(bp->b_maps[0].bm_bn != XFS_BUF_DADDR_NULL); bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_READ_AHEAD); bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | XBF_READ_AHEAD); @@ -1709,7 +1709,7 @@ xfs_buf_cmp( struct xfs_buf *bp = container_of(b, struct xfs_buf, b_list); xfs_daddr_t diff; - diff = ap->b_map.bm_bn - bp->b_map.bm_bn; + diff = ap->b_maps[0].bm_bn - bp->b_maps[0].bm_bn; if (diff < 0) return -1; if (diff > 0) diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index 23f5642480b..433a12ed7b1 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h @@ -151,7 +151,7 @@ typedef struct xfs_buf { struct page **b_pages; /* array of page pointers */ struct page *b_page_array[XB_PAGES]; /* inline pages */ struct xfs_buf_map *b_maps; /* compound buffer map */ - struct xfs_buf_map b_map; /* inline compound buffer map */ + struct xfs_buf_map __b_map; /* inline compound buffer map */ int b_map_count; int b_io_length; /* IO size in BBs */ atomic_t b_pin_count; /* pin count */ @@ -330,8 +330,8 @@ void xfs_buf_stale(struct xfs_buf *bp); * In future, uncached buffers will pass the block number directly to the io * request function and hence these macros will go away at that point. */ -#define XFS_BUF_ADDR(bp) ((bp)->b_map.bm_bn) -#define XFS_BUF_SET_ADDR(bp, bno) ((bp)->b_map.bm_bn = (xfs_daddr_t)(bno)) +#define XFS_BUF_ADDR(bp) ((bp)->b_maps[0].bm_bn) +#define XFS_BUF_SET_ADDR(bp, bno) ((bp)->b_maps[0].bm_bn = (xfs_daddr_t)(bno)) static inline void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref) { diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index becf4a97efc..77b09750e92 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -71,7 +71,7 @@ xfs_buf_item_log_debug( chunk_num = byte >> XFS_BLF_SHIFT; word_num = chunk_num >> BIT_TO_WORD_SHIFT; bit_num = chunk_num & (NBWORD - 1); - wordp = &(bip->bli_format.blf_data_map[word_num]); + wordp = &(bip->__bli_format.blf_data_map[word_num]); bit_set = *wordp & (1 << bit_num); ASSERT(bit_set); byte++; @@ -237,7 +237,7 @@ xfs_buf_item_size( * cancel flag in it. */ trace_xfs_buf_item_size_stale(bip); - ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); + ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); return bip->bli_format_count; } @@ -278,7 +278,7 @@ xfs_buf_item_format_segment( uint buffer_offset; /* copy the flags across from the base format item */ - blfp->blf_flags = bip->bli_format.blf_flags; + blfp->blf_flags = bip->__bli_format.blf_flags; /* * Base size is the actual size of the ondisk structure - it reflects @@ -287,6 +287,17 @@ xfs_buf_item_format_segment( */ base_size = offsetof(struct xfs_buf_log_format, blf_data_map) + (blfp->blf_map_size * sizeof(blfp->blf_data_map[0])); + + nvecs = 0; + first_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0); + if (!(bip->bli_flags & XFS_BLI_STALE) && first_bit == -1) { + /* + * If the map is not be dirty in the transaction, mark + * the size as zero and do not advance the vector pointer. + */ + goto out; + } + vecp->i_addr = blfp; vecp->i_len = base_size; vecp->i_type = XLOG_REG_TYPE_BFORMAT; @@ -301,15 +312,13 @@ xfs_buf_item_format_segment( */ trace_xfs_buf_item_format_stale(bip); ASSERT(blfp->blf_flags & XFS_BLF_CANCEL); - blfp->blf_size = nvecs; - return vecp; + goto out; } /* * Fill in an iovec for each set of contiguous chunks. */ - first_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0); - ASSERT(first_bit != -1); + last_bit = first_bit; nbits = 1; for (;;) { @@ -371,7 +380,8 @@ xfs_buf_item_format_segment( nbits++; } } - bip->bli_format.blf_size = nvecs; +out: + blfp->blf_size = nvecs; return vecp; } @@ -405,7 +415,7 @@ xfs_buf_item_format( if (bip->bli_flags & XFS_BLI_INODE_BUF) { if (!((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) && xfs_log_item_in_current_chkpt(lip))) - bip->bli_format.blf_flags |= XFS_BLF_INODE_BUF; + bip->__bli_format.blf_flags |= XFS_BLF_INODE_BUF; bip->bli_flags &= ~XFS_BLI_INODE_BUF; } @@ -485,7 +495,7 @@ xfs_buf_item_unpin( ASSERT(bip->bli_flags & XFS_BLI_STALE); ASSERT(xfs_buf_islocked(bp)); ASSERT(XFS_BUF_ISSTALE(bp)); - ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); + ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); trace_xfs_buf_item_unpin_stale(bip); @@ -601,7 +611,7 @@ xfs_buf_item_unlock( { struct xfs_buf_log_item *bip = BUF_ITEM(lip); struct xfs_buf *bp = bip->bli_buf; - int aborted; + int aborted, clean, i; uint hold; /* Clear the buffer's association with this transaction. */ @@ -631,7 +641,7 @@ xfs_buf_item_unlock( */ if (bip->bli_flags & XFS_BLI_STALE) { trace_xfs_buf_item_unlock_stale(bip); - ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); + ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); if (!aborted) { atomic_dec(&bip->bli_refcount); return; @@ -644,8 +654,15 @@ xfs_buf_item_unlock( * If the buf item isn't tracking any data, free it, otherwise drop the * reference we hold to it. */ - if (xfs_bitmap_empty(bip->bli_format.blf_data_map, - bip->bli_format.blf_map_size)) + clean = 1; + for (i = 0; i < bip->bli_format_count; i++) { + if (!xfs_bitmap_empty(bip->bli_formats[i].blf_data_map, + bip->bli_formats[i].blf_map_size)) { + clean = 0; + break; + } + } + if (clean) xfs_buf_item_relse(bp); else atomic_dec(&bip->bli_refcount); @@ -716,7 +733,7 @@ xfs_buf_item_get_format( bip->bli_format_count = count; if (count == 1) { - bip->bli_formats = &bip->bli_format; + bip->bli_formats = &bip->__bli_format; return 0; } @@ -731,7 +748,7 @@ STATIC void xfs_buf_item_free_format( struct xfs_buf_log_item *bip) { - if (bip->bli_formats != &bip->bli_format) { + if (bip->bli_formats != &bip->__bli_format) { kmem_free(bip->bli_formats); bip->bli_formats = NULL; } diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h index 6850f49f4af..16def435944 100644 --- a/fs/xfs/xfs_buf_item.h +++ b/fs/xfs/xfs_buf_item.h @@ -104,7 +104,7 @@ typedef struct xfs_buf_log_item { #endif int bli_format_count; /* count of headers */ struct xfs_buf_log_format *bli_formats; /* array of in-log header ptrs */ - struct xfs_buf_log_format bli_format; /* embedded in-log header */ + struct xfs_buf_log_format __bli_format; /* embedded in-log header */ } xfs_buf_log_item_t; void xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *); diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 7536faaa61e..12afe07a91d 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -355,10 +355,12 @@ xfs_dir2_block_addname( /* * If need to compact the leaf entries, do it now. */ - if (compact) + if (compact) { xfs_dir2_block_compact(tp, bp, hdr, btp, blp, &needlog, &lfloghigh, &lfloglow); - else if (btp->stale) { + /* recalculate blp post-compaction */ + blp = xfs_dir2_block_leaf_p(btp); + } else if (btp->stale) { /* * Set leaf logging boundaries to impossible state. * For the no-stale case they're set explicitly. diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c index 5f53e75409b..8a59f854655 100644 --- a/fs/xfs/xfs_qm_syscalls.c +++ b/fs/xfs/xfs_qm_syscalls.c @@ -784,11 +784,11 @@ xfs_qm_scall_getquota( (XFS_IS_OQUOTA_ENFORCED(mp) && (dst->d_flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)))) && dst->d_id != 0) { - if (((int) dst->d_bcount > (int) dst->d_blk_softlimit) && + if ((dst->d_bcount > dst->d_blk_softlimit) && (dst->d_blk_softlimit > 0)) { ASSERT(dst->d_btimer != 0); } - if (((int) dst->d_icount > (int) dst->d_ino_softlimit) && + if ((dst->d_icount > dst->d_ino_softlimit) && (dst->d_ino_softlimit > 0)) { ASSERT(dst->d_itimer != 0); } diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 4fc17d479d4..3edf5dbee00 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -93,7 +93,7 @@ _xfs_trans_bjoin( xfs_buf_item_init(bp, tp->t_mountp); bip = bp->b_fspriv; ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); - ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL)); + ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); if (reset_recur) bip->bli_recur = 0; @@ -432,7 +432,7 @@ xfs_trans_brelse(xfs_trans_t *tp, bip = bp->b_fspriv; ASSERT(bip->bli_item.li_type == XFS_LI_BUF); ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); - ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL)); + ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); ASSERT(atomic_read(&bip->bli_refcount) > 0); trace_xfs_trans_brelse(bip); @@ -519,7 +519,7 @@ xfs_trans_bhold(xfs_trans_t *tp, ASSERT(bp->b_transp == tp); ASSERT(bip != NULL); ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); - ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL)); + ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); ASSERT(atomic_read(&bip->bli_refcount) > 0); bip->bli_flags |= XFS_BLI_HOLD; @@ -539,7 +539,7 @@ xfs_trans_bhold_release(xfs_trans_t *tp, ASSERT(bp->b_transp == tp); ASSERT(bip != NULL); ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); - ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL)); + ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); ASSERT(atomic_read(&bip->bli_refcount) > 0); ASSERT(bip->bli_flags & XFS_BLI_HOLD); @@ -598,7 +598,7 @@ xfs_trans_log_buf(xfs_trans_t *tp, bip->bli_flags &= ~XFS_BLI_STALE; ASSERT(XFS_BUF_ISSTALE(bp)); XFS_BUF_UNSTALE(bp); - bip->bli_format.blf_flags &= ~XFS_BLF_CANCEL; + bip->__bli_format.blf_flags &= ~XFS_BLF_CANCEL; } tp->t_flags |= XFS_TRANS_DIRTY; @@ -643,6 +643,7 @@ xfs_trans_binval( xfs_buf_t *bp) { xfs_buf_log_item_t *bip = bp->b_fspriv; + int i; ASSERT(bp->b_transp == tp); ASSERT(bip != NULL); @@ -657,8 +658,8 @@ xfs_trans_binval( */ ASSERT(XFS_BUF_ISSTALE(bp)); ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY))); - ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_INODE_BUF)); - ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); + ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_INODE_BUF)); + ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); ASSERT(bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY); ASSERT(tp->t_flags & XFS_TRANS_DIRTY); return; @@ -668,10 +669,12 @@ xfs_trans_binval( bip->bli_flags |= XFS_BLI_STALE; bip->bli_flags &= ~(XFS_BLI_INODE_BUF | XFS_BLI_LOGGED | XFS_BLI_DIRTY); - bip->bli_format.blf_flags &= ~XFS_BLF_INODE_BUF; - bip->bli_format.blf_flags |= XFS_BLF_CANCEL; - memset((char *)(bip->bli_format.blf_data_map), 0, - (bip->bli_format.blf_map_size * sizeof(uint))); + bip->__bli_format.blf_flags &= ~XFS_BLF_INODE_BUF; + bip->__bli_format.blf_flags |= XFS_BLF_CANCEL; + for (i = 0; i < bip->bli_format_count; i++) { + memset(bip->bli_formats[i].blf_data_map, 0, + (bip->bli_formats[i].blf_map_size * sizeof(uint))); + } bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY; tp->t_flags |= XFS_TRANS_DIRTY; } @@ -775,5 +778,5 @@ xfs_trans_dquot_buf( type == XFS_BLF_GDQUOT_BUF); ASSERT(atomic_read(&bip->bli_refcount) > 0); - bip->bli_format.blf_flags |= type; + bip->__bli_format.blf_flags |= type; } diff --git a/include/asm-generic/dma-mapping-broken.h b/include/asm-generic/dma-mapping-broken.h index ccf7b4f34a3..6c32af918c2 100644 --- a/include/asm-generic/dma-mapping-broken.h +++ b/include/asm-generic/dma-mapping-broken.h @@ -16,6 +16,22 @@ extern void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle); +static inline void *dma_alloc_attrs(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag, + struct dma_attrs *attrs) +{ + /* attrs is not supported and ignored */ + return dma_alloc_coherent(dev, size, dma_handle, flag); +} + +static inline void dma_free_attrs(struct device *dev, size_t size, + void *cpu_addr, dma_addr_t dma_handle, + struct dma_attrs *attrs) +{ + /* attrs is not supported and ignored */ + dma_free_coherent(dev, size, cpu_addr, dma_handle); +} + #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 701beab27aa..5cf680a98f9 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -461,10 +461,8 @@ static inline int is_zero_pfn(unsigned long pfn) return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT); } -static inline unsigned long my_zero_pfn(unsigned long addr) -{ - return page_to_pfn(ZERO_PAGE(addr)); -} +#define my_zero_pfn(addr) page_to_pfn(ZERO_PAGE(addr)) + #else static inline int is_zero_pfn(unsigned long pfn) { diff --git a/include/asm-generic/syscalls.h b/include/asm-generic/syscalls.h index 58f466ff00d..1db51b8524e 100644 --- a/include/asm-generic/syscalls.h +++ b/include/asm-generic/syscalls.h @@ -21,10 +21,12 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long fd, off_t pgoff); #endif +#ifndef CONFIG_GENERIC_SIGALTSTACK #ifndef sys_sigaltstack asmlinkage long sys_sigaltstack(const stack_t __user *, stack_t __user *, struct pt_regs *); #endif +#endif #ifndef sys_rt_sigreturn asmlinkage long sys_rt_sigreturn(struct pt_regs *regs); diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 1e744c5a0ff..fc62ac5c6d4 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -158,6 +158,16 @@ #define CLKSRC_OF_TABLES() #endif +#ifdef CONFIG_IRQCHIP +#define IRQCHIP_OF_MATCH_TABLE() \ + . = ALIGN(8); \ + VMLINUX_SYMBOL(__irqchip_begin) = .; \ + *(__irqchip_of_table) \ + *(__irqchip_of_end) +#else +#define IRQCHIP_OF_MATCH_TABLE() +#endif + #define KERNEL_DTB() \ STRUCT_ALIGN(); \ VMLINUX_SYMBOL(__dtb_start) = .; \ @@ -502,7 +512,8 @@ CPU_DISCARD(init.rodata) \ MEM_DISCARD(init.rodata) \ CLKSRC_OF_TABLES() \ - KERNEL_DTB() + KERNEL_DTB() \ + IRQCHIP_OF_MATCH_TABLE() #define INIT_TEXT \ *(.init.text) \ diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 0f4a366f6fa..3527fb3f75b 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -70,7 +70,7 @@ struct drm_mm { unsigned long scan_color; unsigned long scan_size; unsigned long scan_hit_start; - unsigned scan_hit_size; + unsigned long scan_hit_end; unsigned scanned_blocks; unsigned long scan_start; unsigned long scan_end; diff --git a/include/linux/ata.h b/include/linux/ata.h index 408da950217..8f7a3d68371 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -297,10 +297,12 @@ enum { ATA_LOG_SATA_NCQ = 0x10, ATA_LOG_SATA_ID_DEV_DATA = 0x30, ATA_LOG_SATA_SETTINGS = 0x08, - ATA_LOG_DEVSLP_MDAT = 0x30, + ATA_LOG_DEVSLP_OFFSET = 0x30, + ATA_LOG_DEVSLP_SIZE = 0x08, + ATA_LOG_DEVSLP_MDAT = 0x00, ATA_LOG_DEVSLP_MDAT_MASK = 0x1F, - ATA_LOG_DEVSLP_DETO = 0x31, - ATA_LOG_DEVSLP_VALID = 0x37, + ATA_LOG_DEVSLP_DETO = 0x01, + ATA_LOG_DEVSLP_VALID = 0x07, ATA_LOG_DEVSLP_VALID_MASK = 0x80, /* READ/WRITE LONG (obsolete) */ diff --git a/include/linux/audit.h b/include/linux/audit.h index bce729afbcf..5a6d718adf3 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -24,6 +24,7 @@ #define _LINUX_AUDIT_H_ #include <linux/sched.h> +#include <linux/ptrace.h> #include <uapi/linux/audit.h> struct audit_sig_info { @@ -157,7 +158,8 @@ void audit_core_dumps(long signr); static inline void audit_seccomp(unsigned long syscall, long signr, int code) { - if (unlikely(!audit_dummy_context())) + /* Force a record to be reported if a signal was delivered. */ + if (signr || unlikely(!audit_dummy_context())) __audit_seccomp(syscall, signr, code); } diff --git a/include/linux/bcm2835_timer.h b/include/linux/bcm2835_timer.h deleted file mode 100644 index ca17aa81700..00000000000 --- a/include/linux/bcm2835_timer.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2012 Simon Arlott - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __BCM2835_TIMER_H -#define __BCM2835_TIMER_H - -#include <asm/mach/time.h> - -extern void bcm2835_timer_init(void); - -#endif diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 7944f14ea94..27cfda427dd 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -339,6 +339,8 @@ extern void clocksource_of_init(void); static const struct of_device_id __clksrc_of_table_##name \ __used __section(__clksrc_of_table) \ = { .compatible = compat, .data = fn }; +#else +#define CLOCKSOURCE_OF_DECLARE(name, compat, fn) #endif #endif /* _LINUX_CLOCKSOURCE_H */ diff --git a/include/linux/compaction.h b/include/linux/compaction.h index 6ecb6dc2f30..cc7bddeaf55 100644 --- a/include/linux/compaction.h +++ b/include/linux/compaction.h @@ -22,7 +22,7 @@ extern int sysctl_extfrag_handler(struct ctl_table *table, int write, extern int fragmentation_index(struct zone *zone, unsigned int order); extern unsigned long try_to_compact_pages(struct zonelist *zonelist, int order, gfp_t gfp_mask, nodemask_t *mask, - bool sync, bool *contended, struct page **page); + bool sync, bool *contended); extern int compact_pgdat(pg_data_t *pgdat, int order); extern void reset_isolation_suitable(pg_data_t *pgdat); extern unsigned long compaction_suitable(struct zone *zone, int order); @@ -75,7 +75,7 @@ static inline bool compaction_restarting(struct zone *zone, int order) #else static inline unsigned long try_to_compact_pages(struct zonelist *zonelist, int order, gfp_t gfp_mask, nodemask_t *nodemask, - bool sync, bool *contended, struct page **page) + bool sync, bool *contended) { return COMPACT_CONTINUE; } diff --git a/include/linux/cpu_rmap.h b/include/linux/cpu_rmap.h index ac3bbb5b950..1739510d899 100644 --- a/include/linux/cpu_rmap.h +++ b/include/linux/cpu_rmap.h @@ -13,9 +13,11 @@ #include <linux/cpumask.h> #include <linux/gfp.h> #include <linux/slab.h> +#include <linux/kref.h> /** * struct cpu_rmap - CPU affinity reverse-map + * @refcount: kref for object * @size: Number of objects to be reverse-mapped * @used: Number of objects added * @obj: Pointer to array of object pointers @@ -23,6 +25,7 @@ * based on affinity masks */ struct cpu_rmap { + struct kref refcount; u16 size, used; void **obj; struct { @@ -33,15 +36,7 @@ struct cpu_rmap { #define CPU_RMAP_DIST_INF 0xffff extern struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags); - -/** - * free_cpu_rmap - free CPU affinity reverse-map - * @rmap: Reverse-map allocated with alloc_cpu_rmap(), or %NULL - */ -static inline void free_cpu_rmap(struct cpu_rmap *rmap) -{ - kfree(rmap); -} +extern int cpu_rmap_put(struct cpu_rmap *rmap); extern int cpu_rmap_add(struct cpu_rmap *rmap, void *obj); extern int cpu_rmap_update(struct cpu_rmap *rmap, u16 index, diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 3711b34dc4f..24cd1037b6d 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -126,9 +126,9 @@ struct cpuidle_driver { struct module *owner; int refcnt; - unsigned int power_specified:1; /* set to 1 to use the core cpuidle time keeping (for all states). */ unsigned int en_core_tk_irqen:1; + /* states array must be ordered in decreasing power consumption */ struct cpuidle_state states[CPUIDLE_STATE_MAX]; int state_count; int safe_state_index; diff --git a/include/linux/init.h b/include/linux/init.h index a799273714a..10ed4f43645 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -93,14 +93,6 @@ #define __exit __section(.exit.text) __exitused __cold notrace -/* Used for HOTPLUG, but that is always enabled now, so just make them noops */ -#define __devinit -#define __devinitdata -#define __devinitconst -#define __devexit -#define __devexitdata -#define __devexitconst - /* Used for HOTPLUG_CPU */ #define __cpuinit __section(.cpuinit.text) __cold notrace #define __cpuinitdata __section(.cpuinit.data) @@ -337,18 +329,6 @@ void __init parse_early_options(char *cmdline); #define __INITRODATA_OR_MODULE __INITRODATA #endif /*CONFIG_MODULES*/ -/* Functions marked as __devexit may be discarded at kernel link time, depending - on config options. Newer versions of binutils detect references from - retained sections to discarded sections and flag an error. Pointers to - __devexit functions must use __devexit_p(function_name), the wrapper will - insert either the function_name or NULL, depending on the config options. - */ -#if defined(MODULE) || defined(CONFIG_HOTPLUG) -#define __devexit_p(x) x -#else -#define __devexit_p(x) NULL -#endif - #ifdef MODULE #define __exit_p(x) x #else diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 5e4e6170f43..5fa5afeeb75 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -268,11 +268,6 @@ struct irq_affinity_notify { extern int irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify); -static inline void irq_run_affinity_notifiers(void) -{ - flush_scheduled_work(); -} - #else /* CONFIG_SMP */ static inline int irq_set_affinity(unsigned int irq, const struct cpumask *m) diff --git a/include/linux/irqchip.h b/include/linux/irqchip.h new file mode 100644 index 00000000000..e0006f1d35a --- /dev/null +++ b/include/linux/irqchip.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2012 Thomas Petazzoni + * + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef _LINUX_IRQCHIP_H +#define _LINUX_IRQCHIP_H + +void irqchip_init(void); + +#endif diff --git a/arch/arm/include/asm/hardware/gic.h b/include/linux/irqchip/arm-gic.h index 4b1ce6cd477..a67ca55e6f4 100644 --- a/arch/arm/include/asm/hardware/gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -1,5 +1,5 @@ /* - * arch/arm/include/asm/hardware/gic.h + * include/linux/irqchip/arm-gic.h * * Copyright (C) 2002 ARM Limited, All Rights Reserved. * @@ -7,10 +7,8 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#ifndef __ASM_ARM_HARDWARE_GIC_H -#define __ASM_ARM_HARDWARE_GIC_H - -#include <linux/compiler.h> +#ifndef __LINUX_IRQCHIP_ARM_GIC_H +#define __LINUX_IRQCHIP_ARM_GIC_H #define GIC_CPU_CTRL 0x00 #define GIC_CPU_PRIMASK 0x04 @@ -32,19 +30,14 @@ #define GIC_DIST_CONFIG 0xc00 #define GIC_DIST_SOFTINT 0xf00 -#ifndef __ASSEMBLY__ -#include <linux/irqdomain.h> struct device_node; extern struct irq_chip gic_arch_extn; void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *, u32 offset, struct device_node *); -int gic_of_init(struct device_node *node, struct device_node *parent); void gic_secondary_init(unsigned int); -void gic_handle_irq(struct pt_regs *regs); void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); -void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); static inline void gic_init(unsigned int nr, int start, void __iomem *dist , void __iomem *cpu) @@ -53,5 +46,3 @@ static inline void gic_init(unsigned int nr, int start, } #endif - -#endif diff --git a/arch/arm/include/asm/hardware/vic.h b/include/linux/irqchip/arm-vic.h index 2bebad36fc8..e3c82dc9575 100644 --- a/arch/arm/include/asm/hardware/vic.h +++ b/include/linux/irqchip/arm-vic.h @@ -20,29 +20,11 @@ #ifndef __ASM_ARM_HARDWARE_VIC_H #define __ASM_ARM_HARDWARE_VIC_H -#define VIC_IRQ_STATUS 0x00 -#define VIC_FIQ_STATUS 0x04 +#include <linux/types.h> + #define VIC_RAW_STATUS 0x08 -#define VIC_INT_SELECT 0x0c /* 1 = FIQ, 0 = IRQ */ #define VIC_INT_ENABLE 0x10 /* 1 = enable, 0 = disable */ #define VIC_INT_ENABLE_CLEAR 0x14 -#define VIC_INT_SOFT 0x18 -#define VIC_INT_SOFT_CLEAR 0x1c -#define VIC_PROTECT 0x20 -#define VIC_PL190_VECT_ADDR 0x30 /* PL190 only */ -#define VIC_PL190_DEF_VECT_ADDR 0x34 /* PL190 only */ - -#define VIC_VECT_ADDR0 0x100 /* 0 to 15 (0..31 PL192) */ -#define VIC_VECT_CNTL0 0x200 /* 0 to 15 (0..31 PL192) */ -#define VIC_ITCR 0x300 /* VIC test control register */ - -#define VIC_VECT_CNTL_ENABLE (1 << 5) - -#define VIC_PL192_VECT_ADDR 0xF00 - -#ifndef __ASSEMBLY__ -#include <linux/compiler.h> -#include <linux/types.h> struct device_node; struct pt_regs; @@ -50,8 +32,5 @@ struct pt_regs; void __vic_init(void __iomem *base, int irq_start, u32 vic_sources, u32 resume_sources, struct device_node *node); void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); -int vic_of_init(struct device_node *node, struct device_node *parent); -void vic_handle_irq(struct pt_regs *regs); -#endif /* __ASSEMBLY__ */ #endif diff --git a/include/linux/libata.h b/include/linux/libata.h index 83ba0ab2c91..649e5f86b5f 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -652,8 +652,8 @@ struct ata_device { u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */ }; - /* Identify Device Data Log (30h), SATA Settings (page 08h) */ - u8 sata_settings[ATA_SECT_SIZE]; + /* DEVSLP Timing Variables from Identify Device Data Log */ + u8 devslp_timing[ATA_LOG_DEVSLP_SIZE]; /* error history */ int spdn_cnt; diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 00e46376e28..2bca44b0893 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -524,14 +524,17 @@ static inline void print_irqtrace_events(struct task_struct *curr) #ifdef CONFIG_DEBUG_LOCK_ALLOC # ifdef CONFIG_PROVE_LOCKING # define rwsem_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, NULL, i) +# define rwsem_acquire_nest(l, s, t, n, i) lock_acquire(l, s, t, 0, 2, n, i) # define rwsem_acquire_read(l, s, t, i) lock_acquire(l, s, t, 1, 2, NULL, i) # else # define rwsem_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, NULL, i) +# define rwsem_acquire_nest(l, s, t, n, i) lock_acquire(l, s, t, 0, 1, n, i) # define rwsem_acquire_read(l, s, t, i) lock_acquire(l, s, t, 1, 1, NULL, i) # endif # define rwsem_release(l, n, i) lock_release(l, n, i) #else # define rwsem_acquire(l, s, t, i) do { } while (0) +# define rwsem_acquire_nest(l, s, t, n, i) do { } while (0) # define rwsem_acquire_read(l, s, t, i) do { } while (0) # define rwsem_release(l, n, i) do { } while (0) #endif diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h index 6ee4247df11..a65deddede2 100644 --- a/include/linux/mfd/db8500-prcmu.h +++ b/include/linux/mfd/db8500-prcmu.h @@ -16,12 +16,6 @@ /* * Registers */ -#define DB8500_PRCM_GPIOCR 0x138 -#define DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0 BIT(0) -#define DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD BIT(9) -#define DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 BIT(11) -#define DB8500_PRCM_GPIOCR_SPI2_SELECT BIT(23) - #define DB8500_PRCM_LINE_VALUE 0x170 #define DB8500_PRCM_LINE_VALUE_HSI_CAWAKE0 BIT(3) diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h index c202d6c4d87..15528064258 100644 --- a/include/linux/mfd/dbx500-prcmu.h +++ b/include/linux/mfd/dbx500-prcmu.h @@ -218,8 +218,6 @@ enum ddr_pwrst { #if defined(CONFIG_UX500_SOC_DB8500) -#include <mach/id.h> - static inline void __init prcmu_early_init(void) { return db8500_prcmu_early_init(); @@ -626,85 +624,6 @@ static inline void prcmu_clear(unsigned int reg, u32 bits) prcmu_write_masked(reg, bits, 0); } -#if defined(CONFIG_UX500_SOC_DB8500) - -/** - * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1. - */ -static inline void prcmu_enable_spi2(void) -{ - if (cpu_is_u8500()) - prcmu_set(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT); -} - -/** - * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1. - */ -static inline void prcmu_disable_spi2(void) -{ - if (cpu_is_u8500()) - prcmu_clear(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT); -} - -/** - * prcmu_enable_stm_mod_uart - Enables pin muxing for STMMOD - * and UARTMOD on OtherAlternateC3. - */ -static inline void prcmu_enable_stm_mod_uart(void) -{ - if (cpu_is_u8500()) { - prcmu_set(DB8500_PRCM_GPIOCR, - (DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 | - DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0)); - } -} - -/** - * prcmu_disable_stm_mod_uart - Disables pin muxing for STMMOD - * and UARTMOD on OtherAlternateC3. - */ -static inline void prcmu_disable_stm_mod_uart(void) -{ - if (cpu_is_u8500()) { - prcmu_clear(DB8500_PRCM_GPIOCR, - (DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 | - DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0)); - } -} - -/** - * prcmu_enable_stm_ape - Enables pin muxing for STM APE on OtherAlternateC1. - */ -static inline void prcmu_enable_stm_ape(void) -{ - if (cpu_is_u8500()) { - prcmu_set(DB8500_PRCM_GPIOCR, - DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD); - } -} - -/** - * prcmu_disable_stm_ape - Disables pin muxing for STM APE on OtherAlternateC1. - */ -static inline void prcmu_disable_stm_ape(void) -{ - if (cpu_is_u8500()) { - prcmu_clear(DB8500_PRCM_GPIOCR, - DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD); - } -} - -#else - -static inline void prcmu_enable_spi2(void) {} -static inline void prcmu_disable_spi2(void) {} -static inline void prcmu_enable_stm_mod_uart(void) {} -static inline void prcmu_disable_stm_mod_uart(void) {} -static inline void prcmu_enable_stm_ape(void) {} -static inline void prcmu_disable_stm_ape(void) {} - -#endif - /* PRCMU QoS APE OPP class */ #define PRCMU_QOS_APE_OPP 1 #define PRCMU_QOS_DDR_OPP 2 diff --git a/include/linux/mm.h b/include/linux/mm.h index 63204078f72..66e2f7c61e5 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -455,7 +455,6 @@ void put_pages_list(struct list_head *pages); void split_page(struct page *page, unsigned int order); int split_free_page(struct page *page); -int capture_free_page(struct page *page, int alloc_order, int migratetype); /* * Compound pages have a destructor function. Provide a diff --git a/include/linux/module.h b/include/linux/module.h index 7760c6d344a..1375ee3f03a 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -199,11 +199,11 @@ struct module_use { struct module *source, *target; }; -enum module_state -{ - MODULE_STATE_LIVE, - MODULE_STATE_COMING, - MODULE_STATE_GOING, +enum module_state { + MODULE_STATE_LIVE, /* Normal state. */ + MODULE_STATE_COMING, /* Full formed, running module_init. */ + MODULE_STATE_GOING, /* Going away. */ + MODULE_STATE_UNFORMED, /* Still setting it up. */ }; /** diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c599e4782d4..9ef07d0868b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -60,6 +60,9 @@ struct wireless_dev; #define SET_ETHTOOL_OPS(netdev,ops) \ ( (netdev)->ethtool_ops = (ops) ) +extern void netdev_set_default_ethtool_ops(struct net_device *dev, + const struct ethtool_ops *ops); + /* hardware address assignment types */ #define NET_ADDR_PERM 0 /* address is permanent (default) */ #define NET_ADDR_RANDOM 1 /* address is generated randomly */ diff --git a/arch/arm/mach-imx/iram.h b/include/linux/platform_data/imx-iram.h index 022690c3370..022690c3370 100644 --- a/arch/arm/mach-imx/iram.h +++ b/include/linux/platform_data/imx-iram.h diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 1693775ecfe..89573a33ab3 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -45,7 +45,6 @@ extern long arch_ptrace(struct task_struct *child, long request, extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); extern void ptrace_disable(struct task_struct *); -extern int ptrace_check_attach(struct task_struct *task, bool ignore_state); extern int ptrace_request(struct task_struct *child, long request, unsigned long addr, unsigned long data); extern void ptrace_notify(int exit_code); diff --git a/include/linux/rbtree_augmented.h b/include/linux/rbtree_augmented.h index 2ac60c9cf64..fea49b5da12 100644 --- a/include/linux/rbtree_augmented.h +++ b/include/linux/rbtree_augmented.h @@ -123,9 +123,9 @@ __rb_change_child(struct rb_node *old, struct rb_node *new, extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); -static __always_inline void -rb_erase_augmented(struct rb_node *node, struct rb_root *root, - const struct rb_augment_callbacks *augment) +static __always_inline struct rb_node * +__rb_erase_augmented(struct rb_node *node, struct rb_root *root, + const struct rb_augment_callbacks *augment) { struct rb_node *child = node->rb_right, *tmp = node->rb_left; struct rb_node *parent, *rebalance; @@ -217,6 +217,14 @@ rb_erase_augmented(struct rb_node *node, struct rb_root *root, } augment->propagate(tmp, NULL); + return rebalance; +} + +static __always_inline void +rb_erase_augmented(struct rb_node *node, struct rb_root *root, + const struct rb_augment_callbacks *augment) +{ + struct rb_node *rebalance = __rb_erase_augmented(node, root, augment); if (rebalance) __rb_erase_color(rebalance, root, augment->rotate); } diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h index 54bd7cd7ecb..8da67d625e1 100644 --- a/include/linux/rwsem.h +++ b/include/linux/rwsem.h @@ -125,8 +125,17 @@ extern void downgrade_write(struct rw_semaphore *sem); */ extern void down_read_nested(struct rw_semaphore *sem, int subclass); extern void down_write_nested(struct rw_semaphore *sem, int subclass); +extern void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest_lock); + +# define down_write_nest_lock(sem, nest_lock) \ +do { \ + typecheck(struct lockdep_map *, &(nest_lock)->dep_map); \ + _down_write_nest_lock(sem, &(nest_lock)->dep_map); \ +} while (0); + #else # define down_read_nested(sem, subclass) down_read(sem) +# define down_write_nest_lock(sem, nest_lock) down_write(sem) # define down_write_nested(sem, subclass) down_write(sem) #endif diff --git a/include/linux/sched.h b/include/linux/sched.h index 206bb089c06..d2112477ff5 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1810,6 +1810,7 @@ extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, #define PF_MEMALLOC 0x00000800 /* Allocating memory */ #define PF_NPROC_EXCEEDED 0x00001000 /* set_user noticed that RLIMIT_NPROC was exceeded */ #define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */ +#define PF_USED_ASYNC 0x00004000 /* used async_schedule*(), used by module init */ #define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */ #define PF_FROZEN 0x00010000 /* frozen for system suspend */ #define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */ @@ -2713,7 +2714,16 @@ static inline void thread_group_cputime_init(struct signal_struct *sig) extern void recalc_sigpending_and_wake(struct task_struct *t); extern void recalc_sigpending(void); -extern void signal_wake_up(struct task_struct *t, int resume_stopped); +extern void signal_wake_up_state(struct task_struct *t, unsigned int state); + +static inline void signal_wake_up(struct task_struct *t, bool resume) +{ + signal_wake_up_state(t, resume ? TASK_WAKEKILL : 0); +} +static inline void ptrace_signal_wake_up(struct task_struct *t, bool resume) +{ + signal_wake_up_state(t, resume ? __TASK_TRACED : 0); +} /* * Wrappers for p->thread_info->cpu access. No-op on UP. diff --git a/include/sound/cs4271.h b/include/sound/cs4271.h index 6d9e15ed1dc..dd8c48d14ed 100644 --- a/include/sound/cs4271.h +++ b/include/sound/cs4271.h @@ -19,7 +19,7 @@ struct cs4271_platform_data { int gpio_nreset; /* GPIO driving Reset pin, if any */ - int amutec_eq_bmutec:1; /* flag to enable AMUTEC=BMUTEC */ + bool amutec_eq_bmutec; /* flag to enable AMUTEC=BMUTEC */ }; #endif /* __CS4271_H */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 769e27c774a..bc56738cb10 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -58,8 +58,9 @@ .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \ .put = snd_soc_put_volsw_range, \ .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .shift = xshift, .min = xmin,\ - .max = xmax, .platform_max = xmax, .invert = xinvert} } + {.reg = xreg, .rreg = xreg, .shift = xshift, \ + .rshift = xshift, .min = xmin, .max = xmax, \ + .platform_max = xmax, .invert = xinvert} } #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -88,8 +89,9 @@ .info = snd_soc_info_volsw_range, \ .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .shift = xshift, .min = xmin,\ - .max = xmax, .platform_max = xmax, .invert = xinvert} } + {.reg = xreg, .rreg = xreg, .shift = xshift, \ + .rshift = xshift, .min = xmin, .max = xmax, \ + .platform_max = xmax, .invert = xinvert} } #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 7cae2360221..663e34a5383 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -174,6 +174,7 @@ typedef unsigned __bitwise__ sense_reason_t; enum tcm_sense_reason_table { #define R(x) (__force sense_reason_t )(x) + TCM_NO_SENSE = R(0x00), TCM_NON_EXISTENT_LUN = R(0x01), TCM_UNSUPPORTED_SCSI_OPCODE = R(0x02), TCM_INCORRECT_AMOUNT_OF_DATA = R(0x03), diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 76352ac45f2..9f096f1c090 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -26,7 +26,6 @@ #include <linux/types.h> #include <linux/elf-em.h> -#include <linux/ptrace.h> /* The netlink messages for the audit system is divided into blocks: * 1000 - 1099 are for commanding the audit system @@ -106,6 +105,7 @@ #define AUDIT_MMAP 1323 /* Record showing descriptor and flags in mmap */ #define AUDIT_NETFILTER_PKT 1324 /* Packets traversing netfilter chains */ #define AUDIT_NETFILTER_CFG 1325 /* Netfilter chain modifications */ +#define AUDIT_SECCOMP 1326 /* Secure Computing event */ #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 78f99d97475..2c6c85f18ea 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -50,7 +50,8 @@ #define PORT_LPC3220 22 /* NXP LPC32xx SoC "Standard" UART */ #define PORT_8250_CIR 23 /* CIR infrared port, has its own driver */ #define PORT_XR17V35X 24 /* Exar XR17V35x UARTs */ -#define PORT_MAX_8250 24 /* max port ID */ +#define PORT_BRCM_TRUMANAGE 24 +#define PORT_MAX_8250 25 /* max port ID */ /* * ARM specific type numbers. These are not currently guaranteed diff --git a/init/Kconfig b/init/Kconfig index 7d30240e5bf..be8b7f55312 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1182,7 +1182,7 @@ config CC_OPTIMIZE_FOR_SIZE Enabling this option will pass "-Os" instead of "-O2" to gcc resulting in a smaller kernel. - If unsure, say Y. + If unsure, say N. config SYSCTL bool diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c index 5e4ded51788..f9acf71b981 100644 --- a/init/do_mounts_initrd.c +++ b/init/do_mounts_initrd.c @@ -36,6 +36,10 @@ __setup("noinitrd", no_initrd); static int init_linuxrc(struct subprocess_info *info, struct cred *new) { sys_unshare(CLONE_FS | CLONE_FILES); + /* stdin/stdout/stderr for /linuxrc */ + sys_open("/dev/console", O_RDWR, 0); + sys_dup(0); + sys_dup(0); /* move initrd over / and chdir/chroot in initrd root */ sys_chdir("/root"); sys_mount(".", "/", NULL, MS_MOVE, NULL); diff --git a/init/main.c b/init/main.c index 85d69dffe86..92d728a32d5 100644 --- a/init/main.c +++ b/init/main.c @@ -802,7 +802,7 @@ static int run_init_process(const char *init_filename) (const char __user *const __user *)envp_init); } -static void __init kernel_init_freeable(void); +static noinline void __init kernel_init_freeable(void); static int __ref kernel_init(void *unused) { @@ -845,7 +845,7 @@ static int __ref kernel_init(void *unused) "See Linux Documentation/init.txt for guidance."); } -static void __init kernel_init_freeable(void) +static noinline void __init kernel_init_freeable(void) { /* * Wait until kthreadd is all set-up. diff --git a/kernel/async.c b/kernel/async.c index 9d311838485..6f34904a0b5 100644 --- a/kernel/async.c +++ b/kernel/async.c @@ -86,18 +86,27 @@ static atomic_t entry_count; */ static async_cookie_t __lowest_in_progress(struct async_domain *running) { + async_cookie_t first_running = next_cookie; /* infinity value */ + async_cookie_t first_pending = next_cookie; /* ditto */ struct async_entry *entry; + /* + * Both running and pending lists are sorted but not disjoint. + * Take the first cookies from both and return the min. + */ if (!list_empty(&running->domain)) { entry = list_first_entry(&running->domain, typeof(*entry), list); - return entry->cookie; + first_running = entry->cookie; } - list_for_each_entry(entry, &async_pending, list) - if (entry->running == running) - return entry->cookie; + list_for_each_entry(entry, &async_pending, list) { + if (entry->running == running) { + first_pending = entry->cookie; + break; + } + } - return next_cookie; /* "infinity" value */ + return min(first_running, first_pending); } static async_cookie_t lowest_in_progress(struct async_domain *running) @@ -118,13 +127,17 @@ static void async_run_entry_fn(struct work_struct *work) { struct async_entry *entry = container_of(work, struct async_entry, work); + struct async_entry *pos; unsigned long flags; ktime_t uninitialized_var(calltime), delta, rettime; struct async_domain *running = entry->running; - /* 1) move self to the running queue */ + /* 1) move self to the running queue, make sure it stays sorted */ spin_lock_irqsave(&async_lock, flags); - list_move_tail(&entry->list, &running->domain); + list_for_each_entry_reverse(pos, &running->domain, list) + if (entry->cookie < pos->cookie) + break; + list_move_tail(&entry->list, &pos->list); spin_unlock_irqrestore(&async_lock, flags); /* 2) run (and print duration) */ @@ -196,6 +209,9 @@ static async_cookie_t __async_schedule(async_func_ptr *ptr, void *data, struct a atomic_inc(&entry_count); spin_unlock_irqrestore(&async_lock, flags); + /* mark that this task has queued an async job, used by module init */ + current->flags |= PF_USED_ASYNC; + /* schedule for execution */ queue_work(system_unbound_wq, &entry->work); diff --git a/kernel/audit.c b/kernel/audit.c index 40414e9143d..d596e5355f1 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -272,6 +272,8 @@ static int audit_log_config_change(char *function_name, int new, int old, int rc = 0; ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); + if (unlikely(!ab)) + return rc; audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new, old, from_kuid(&init_user_ns, loginuid), sessionid); if (sid) { @@ -619,6 +621,8 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, } *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); + if (unlikely(!*ab)) + return rc; audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u", task_tgid_vnr(current), from_kuid(&init_user_ns, current_uid()), @@ -1097,6 +1101,23 @@ static inline void audit_get_stamp(struct audit_context *ctx, } } +/* + * Wait for auditd to drain the queue a little + */ +static void wait_for_auditd(unsigned long sleep_time) +{ + DECLARE_WAITQUEUE(wait, current); + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&audit_backlog_wait, &wait); + + if (audit_backlog_limit && + skb_queue_len(&audit_skb_queue) > audit_backlog_limit) + schedule_timeout(sleep_time); + + __set_current_state(TASK_RUNNING); + remove_wait_queue(&audit_backlog_wait, &wait); +} + /* Obtain an audit buffer. This routine does locking to obtain the * audit buffer, but then no locking is required for calls to * audit_log_*format. If the tsk is a task that is currently in a @@ -1142,20 +1163,13 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, while (audit_backlog_limit && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) { - if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time - && time_before(jiffies, timeout_start + audit_backlog_wait_time)) { + if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time) { + unsigned long sleep_time; - /* Wait for auditd to drain the queue a little */ - DECLARE_WAITQUEUE(wait, current); - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&audit_backlog_wait, &wait); - - if (audit_backlog_limit && - skb_queue_len(&audit_skb_queue) > audit_backlog_limit) - schedule_timeout(timeout_start + audit_backlog_wait_time - jiffies); - - __set_current_state(TASK_RUNNING); - remove_wait_queue(&audit_backlog_wait, &wait); + sleep_time = timeout_start + audit_backlog_wait_time - + jiffies; + if ((long)sleep_time > 0) + wait_for_auditd(sleep_time); continue; } if (audit_rate_check() && printk_ratelimit()) diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index e81175ef25f..642a89c4f3d 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -449,11 +449,26 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) return 0; } +static void audit_log_remove_rule(struct audit_krule *rule) +{ + struct audit_buffer *ab; + + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); + if (unlikely(!ab)) + return; + audit_log_format(ab, "op="); + audit_log_string(ab, "remove rule"); + audit_log_format(ab, " dir="); + audit_log_untrustedstring(ab, rule->tree->pathname); + audit_log_key(ab, rule->filterkey); + audit_log_format(ab, " list=%d res=1", rule->listnr); + audit_log_end(ab); +} + static void kill_rules(struct audit_tree *tree) { struct audit_krule *rule, *next; struct audit_entry *entry; - struct audit_buffer *ab; list_for_each_entry_safe(rule, next, &tree->rules, rlist) { entry = container_of(rule, struct audit_entry, rule); @@ -461,14 +476,7 @@ static void kill_rules(struct audit_tree *tree) list_del_init(&rule->rlist); if (rule->tree) { /* not a half-baked one */ - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); - audit_log_format(ab, "op="); - audit_log_string(ab, "remove rule"); - audit_log_format(ab, " dir="); - audit_log_untrustedstring(ab, rule->tree->pathname); - audit_log_key(ab, rule->filterkey); - audit_log_format(ab, " list=%d res=1", rule->listnr); - audit_log_end(ab); + audit_log_remove_rule(rule); rule->tree = NULL; list_del_rcu(&entry->list); list_del(&entry->rule.list); diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 4a599f699ad..22831c4d369 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -240,6 +240,8 @@ static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watc if (audit_enabled) { struct audit_buffer *ab; ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); + if (unlikely(!ab)) + return; audit_log_format(ab, "auid=%u ses=%u op=", from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 7f19f23d38a..f9fc54bbe06 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -1144,7 +1144,6 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid, * audit_receive_filter - apply all rules to the specified message type * @type: audit message type * @pid: target pid for netlink audit messages - * @uid: target uid for netlink audit messages * @seq: netlink audit message sequence (serial) number * @data: payload data * @datasz: size of payload data diff --git a/kernel/auditsc.c b/kernel/auditsc.c index e37e6a12c5e..a371f857a0a 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1464,14 +1464,14 @@ static void show_special(struct audit_context *context, int *call_panic) audit_log_end(ab); ab = audit_log_start(context, GFP_KERNEL, AUDIT_IPC_SET_PERM); + if (unlikely(!ab)) + return; audit_log_format(ab, "qbytes=%lx ouid=%u ogid=%u mode=%#ho", context->ipc.qbytes, context->ipc.perm_uid, context->ipc.perm_gid, context->ipc.perm_mode); - if (!ab) - return; } break; } case AUDIT_MQ_OPEN: { @@ -2675,7 +2675,7 @@ void __audit_mmap_fd(int fd, int flags) context->type = AUDIT_MMAP; } -static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) +static void audit_log_task(struct audit_buffer *ab) { kuid_t auid, uid; kgid_t gid; @@ -2693,6 +2693,11 @@ static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) audit_log_task_context(ab); audit_log_format(ab, " pid=%d comm=", current->pid); audit_log_untrustedstring(ab, current->comm); +} + +static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) +{ + audit_log_task(ab); audit_log_format(ab, " reason="); audit_log_string(ab, reason); audit_log_format(ab, " sig=%ld", signr); @@ -2715,6 +2720,8 @@ void audit_core_dumps(long signr) return; ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); + if (unlikely(!ab)) + return; audit_log_abend(ab, "memory violation", signr); audit_log_end(ab); } @@ -2723,8 +2730,11 @@ void __audit_seccomp(unsigned long syscall, long signr, int code) { struct audit_buffer *ab; - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); - audit_log_abend(ab, "seccomp", signr); + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP); + if (unlikely(!ab)) + return; + audit_log_task(ab); + audit_log_format(ab, " sig=%ld", signr); audit_log_format(ab, " syscall=%ld", syscall); audit_log_format(ab, " compat=%d", is_compat_task()); audit_log_format(ab, " ip=0x%lx", KSTK_EIP(current)); diff --git a/kernel/compat.c b/kernel/compat.c index f6150e92dfc..36700e9e2be 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -535,9 +535,11 @@ asmlinkage long compat_sys_getrusage(int who, struct compat_rusage __user *ru) return 0; } -asmlinkage long -compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options, - struct compat_rusage __user *ru) +COMPAT_SYSCALL_DEFINE4(wait4, + compat_pid_t, pid, + compat_uint_t __user *, stat_addr, + int, options, + struct compat_rusage __user *, ru) { if (!ru) { return sys_wait4(pid, stat_addr, options, NULL); @@ -564,9 +566,10 @@ compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options, } } -asmlinkage long compat_sys_waitid(int which, compat_pid_t pid, - struct compat_siginfo __user *uinfo, int options, - struct compat_rusage __user *uru) +COMPAT_SYSCALL_DEFINE5(waitid, + int, which, compat_pid_t, pid, + struct compat_siginfo __user *, uinfo, int, options, + struct compat_rusage __user *, uru) { siginfo_t info; struct rusage ru; @@ -584,7 +587,11 @@ asmlinkage long compat_sys_waitid(int which, compat_pid_t pid, return ret; if (uru) { - ret = put_compat_rusage(&ru, uru); + /* sys_waitid() overwrites everything in ru */ + if (COMPAT_USE_64BIT_TIME) + ret = copy_to_user(uru, &ru, sizeof(ru)); + else + ret = put_compat_rusage(&ru, uru); if (ret) return ret; } @@ -994,7 +1001,7 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, sigset_from_compat(&s, &s32); if (uts) { - if (get_compat_timespec(&t, uts)) + if (compat_get_timespec(&t, uts)) return -EFAULT; } diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 4d5f8d5612f..8875254120b 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -1970,6 +1970,8 @@ static int kdb_lsmod(int argc, const char **argv) kdb_printf("Module Size modstruct Used by\n"); list_for_each_entry(mod, kdb_modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; kdb_printf("%-20s%8u 0x%p ", mod->name, mod->core_size, (void *)mod); diff --git a/kernel/fork.c b/kernel/fork.c index 65ca6d27f24..c535f33bbb9 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1668,8 +1668,10 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, int, tls_val) #endif { - return do_fork(clone_flags, newsp, 0, - parent_tidptr, child_tidptr); + long ret = do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr); + asmlinkage_protect(5, ret, clone_flags, newsp, + parent_tidptr, child_tidptr, tls_val); + return ret; } #endif diff --git a/kernel/module.c b/kernel/module.c index 250092c1d57..eab08274ec9 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -188,6 +188,7 @@ struct load_info { ongoing or failed initialization etc. */ static inline int strong_try_module_get(struct module *mod) { + BUG_ON(mod && mod->state == MODULE_STATE_UNFORMED); if (mod && mod->state == MODULE_STATE_COMING) return -EBUSY; if (try_module_get(mod)) @@ -343,6 +344,9 @@ bool each_symbol_section(bool (*fn)(const struct symsearch *arr, #endif }; + if (mod->state == MODULE_STATE_UNFORMED) + continue; + if (each_symbol_in_section(arr, ARRAY_SIZE(arr), mod, fn, data)) return true; } @@ -450,16 +454,24 @@ const struct kernel_symbol *find_symbol(const char *name, EXPORT_SYMBOL_GPL(find_symbol); /* Search for module by name: must hold module_mutex. */ -struct module *find_module(const char *name) +static struct module *find_module_all(const char *name, + bool even_unformed) { struct module *mod; list_for_each_entry(mod, &modules, list) { + if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) + continue; if (strcmp(mod->name, name) == 0) return mod; } return NULL; } + +struct module *find_module(const char *name) +{ + return find_module_all(name, false); +} EXPORT_SYMBOL_GPL(find_module); #ifdef CONFIG_SMP @@ -525,6 +537,8 @@ bool is_module_percpu_address(unsigned long addr) preempt_disable(); list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; if (!mod->percpu_size) continue; for_each_possible_cpu(cpu) { @@ -1048,6 +1062,8 @@ static ssize_t show_initstate(struct module_attribute *mattr, case MODULE_STATE_GOING: state = "going"; break; + default: + BUG(); } return sprintf(buffer, "%s\n", state); } @@ -1786,6 +1802,8 @@ void set_all_modules_text_rw(void) mutex_lock(&module_mutex); list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; if ((mod->module_core) && (mod->core_text_size)) { set_page_attributes(mod->module_core, mod->module_core + mod->core_text_size, @@ -1807,6 +1825,8 @@ void set_all_modules_text_ro(void) mutex_lock(&module_mutex); list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; if ((mod->module_core) && (mod->core_text_size)) { set_page_attributes(mod->module_core, mod->module_core + mod->core_text_size, @@ -2527,6 +2547,13 @@ static int copy_module_from_fd(int fd, struct load_info *info) err = -EFBIG; goto out; } + + /* Don't hand 0 to vmalloc, it whines. */ + if (stat.size == 0) { + err = -EINVAL; + goto out; + } + info->hdr = vmalloc(stat.size); if (!info->hdr) { err = -ENOMEM; @@ -2990,8 +3017,9 @@ static bool finished_loading(const char *name) bool ret; mutex_lock(&module_mutex); - mod = find_module(name); - ret = !mod || mod->state != MODULE_STATE_COMING; + mod = find_module_all(name, true); + ret = !mod || mod->state == MODULE_STATE_LIVE + || mod->state == MODULE_STATE_GOING; mutex_unlock(&module_mutex); return ret; @@ -3013,6 +3041,12 @@ static int do_init_module(struct module *mod) { int ret = 0; + /* + * We want to find out whether @mod uses async during init. Clear + * PF_USED_ASYNC. async_schedule*() will set it. + */ + current->flags &= ~PF_USED_ASYNC; + blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_COMING, mod); @@ -3058,8 +3092,25 @@ static int do_init_module(struct module *mod) blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_LIVE, mod); - /* We need to finish all async code before the module init sequence is done */ - async_synchronize_full(); + /* + * We need to finish all async code before the module init sequence + * is done. This has potential to deadlock. For example, a newly + * detected block device can trigger request_module() of the + * default iosched from async probing task. Once userland helper + * reaches here, async_synchronize_full() will wait on the async + * task waiting on request_module() and deadlock. + * + * This deadlock is avoided by perfomring async_synchronize_full() + * iff module init queued any async jobs. This isn't a full + * solution as it will deadlock the same if module loading from + * async jobs nests more than once; however, due to the various + * constraints, this hack seems to be the best option for now. + * Please refer to the following thread for details. + * + * http://thread.gmane.org/gmane.linux.kernel/1420814 + */ + if (current->flags & PF_USED_ASYNC) + async_synchronize_full(); mutex_lock(&module_mutex); /* Drop initial reference. */ @@ -3113,6 +3164,32 @@ static int load_module(struct load_info *info, const char __user *uargs, goto free_copy; } + /* + * We try to place it in the list now to make sure it's unique + * before we dedicate too many resources. In particular, + * temporary percpu memory exhaustion. + */ + mod->state = MODULE_STATE_UNFORMED; +again: + mutex_lock(&module_mutex); + if ((old = find_module_all(mod->name, true)) != NULL) { + if (old->state == MODULE_STATE_COMING + || old->state == MODULE_STATE_UNFORMED) { + /* Wait in case it fails to load. */ + mutex_unlock(&module_mutex); + err = wait_event_interruptible(module_wq, + finished_loading(mod->name)); + if (err) + goto free_module; + goto again; + } + err = -EEXIST; + mutex_unlock(&module_mutex); + goto free_module; + } + list_add_rcu(&mod->list, &modules); + mutex_unlock(&module_mutex); + #ifdef CONFIG_MODULE_SIG mod->sig_ok = info->sig_ok; if (!mod->sig_ok) @@ -3122,7 +3199,7 @@ static int load_module(struct load_info *info, const char __user *uargs, /* Now module is in final location, initialize linked lists, etc. */ err = module_unload_init(mod); if (err) - goto free_module; + goto unlink_mod; /* Now we've got everything in the final locations, we can * find optional sections. */ @@ -3157,54 +3234,33 @@ static int load_module(struct load_info *info, const char __user *uargs, goto free_arch_cleanup; } - /* Mark state as coming so strong_try_module_get() ignores us. */ - mod->state = MODULE_STATE_COMING; - - /* Now sew it into the lists so we can get lockdep and oops - * info during argument parsing. No one should access us, since - * strong_try_module_get() will fail. - * lockdep/oops can run asynchronous, so use the RCU list insertion - * function to insert in a way safe to concurrent readers. - * The mutex protects against concurrent writers. - */ -again: - mutex_lock(&module_mutex); - if ((old = find_module(mod->name)) != NULL) { - if (old->state == MODULE_STATE_COMING) { - /* Wait in case it fails to load. */ - mutex_unlock(&module_mutex); - err = wait_event_interruptible(module_wq, - finished_loading(mod->name)); - if (err) - goto free_arch_cleanup; - goto again; - } - err = -EEXIST; - goto unlock; - } - - /* This has to be done once we're sure module name is unique. */ dynamic_debug_setup(info->debug, info->num_debug); - /* Find duplicate symbols */ + mutex_lock(&module_mutex); + /* Find duplicate symbols (must be called under lock). */ err = verify_export_symbols(mod); if (err < 0) - goto ddebug; + goto ddebug_cleanup; + /* This relies on module_mutex for list integrity. */ module_bug_finalize(info->hdr, info->sechdrs, mod); - list_add_rcu(&mod->list, &modules); + + /* Mark state as coming so strong_try_module_get() ignores us, + * but kallsyms etc. can see us. */ + mod->state = MODULE_STATE_COMING; + mutex_unlock(&module_mutex); /* Module is ready to execute: parsing args may do that. */ err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, -32768, 32767, &ddebug_dyndbg_module_param_cb); if (err < 0) - goto unlink; + goto bug_cleanup; /* Link in to syfs. */ err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp); if (err < 0) - goto unlink; + goto bug_cleanup; /* Get rid of temporary copy. */ free_copy(info); @@ -3214,16 +3270,13 @@ again: return do_init_module(mod); - unlink: + bug_cleanup: + /* module_bug_cleanup needs module_mutex protection */ mutex_lock(&module_mutex); - /* Unlink carefully: kallsyms could be walking list. */ - list_del_rcu(&mod->list); module_bug_cleanup(mod); - wake_up_all(&module_wq); - ddebug: - dynamic_debug_remove(info->debug); - unlock: + ddebug_cleanup: mutex_unlock(&module_mutex); + dynamic_debug_remove(info->debug); synchronize_sched(); kfree(mod->args); free_arch_cleanup: @@ -3232,6 +3285,12 @@ again: free_modinfo(mod); free_unload: module_unload_free(mod); + unlink_mod: + mutex_lock(&module_mutex); + /* Unlink carefully: kallsyms could be walking list. */ + list_del_rcu(&mod->list); + wake_up_all(&module_wq); + mutex_unlock(&module_mutex); free_module: module_deallocate(mod, info); free_copy: @@ -3354,6 +3413,8 @@ const char *module_address_lookup(unsigned long addr, preempt_disable(); list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; if (within_module_init(addr, mod) || within_module_core(addr, mod)) { if (modname) @@ -3377,6 +3438,8 @@ int lookup_module_symbol_name(unsigned long addr, char *symname) preempt_disable(); list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; if (within_module_init(addr, mod) || within_module_core(addr, mod)) { const char *sym; @@ -3401,6 +3464,8 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, preempt_disable(); list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; if (within_module_init(addr, mod) || within_module_core(addr, mod)) { const char *sym; @@ -3428,6 +3493,8 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, preempt_disable(); list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; if (symnum < mod->num_symtab) { *value = mod->symtab[symnum].st_value; *type = mod->symtab[symnum].st_info; @@ -3470,9 +3537,12 @@ unsigned long module_kallsyms_lookup_name(const char *name) ret = mod_find_symname(mod, colon+1); *colon = ':'; } else { - list_for_each_entry_rcu(mod, &modules, list) + list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; if ((ret = mod_find_symname(mod, name)) != 0) break; + } } preempt_enable(); return ret; @@ -3487,6 +3557,8 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, int ret; list_for_each_entry(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; for (i = 0; i < mod->num_symtab; i++) { ret = fn(data, mod->strtab + mod->symtab[i].st_name, mod, mod->symtab[i].st_value); @@ -3502,6 +3574,7 @@ static char *module_flags(struct module *mod, char *buf) { int bx = 0; + BUG_ON(mod->state == MODULE_STATE_UNFORMED); if (mod->taints || mod->state == MODULE_STATE_GOING || mod->state == MODULE_STATE_COMING) { @@ -3543,6 +3616,10 @@ static int m_show(struct seq_file *m, void *p) struct module *mod = list_entry(p, struct module, list); char buf[8]; + /* We always ignore unformed modules. */ + if (mod->state == MODULE_STATE_UNFORMED) + return 0; + seq_printf(m, "%s %u", mod->name, mod->init_size + mod->core_size); print_unload_info(m, mod); @@ -3603,6 +3680,8 @@ const struct exception_table_entry *search_module_extables(unsigned long addr) preempt_disable(); list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; if (mod->num_exentries == 0) continue; @@ -3651,10 +3730,13 @@ struct module *__module_address(unsigned long addr) if (addr < module_addr_min || addr > module_addr_max) return NULL; - list_for_each_entry_rcu(mod, &modules, list) + list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; if (within_module_core(addr, mod) || within_module_init(addr, mod)) return mod; + } return NULL; } EXPORT_SYMBOL_GPL(__module_address); @@ -3707,8 +3789,11 @@ void print_modules(void) printk(KERN_DEFAULT "Modules linked in:"); /* Most callers should already have preempt disabled, but make sure */ preempt_disable(); - list_for_each_entry_rcu(mod, &modules, list) + list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; printk(" %s%s", mod->name, module_flags(mod, buf)); + } preempt_enable(); if (last_unloaded_module[0]) printk(" [last unloaded: %s]", last_unloaded_module); diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 1599157336a..6cbeaae4406 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -117,11 +117,45 @@ void __ptrace_unlink(struct task_struct *child) * TASK_KILLABLE sleeps. */ if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child)) - signal_wake_up(child, task_is_traced(child)); + ptrace_signal_wake_up(child, true); spin_unlock(&child->sighand->siglock); } +/* Ensure that nothing can wake it up, even SIGKILL */ +static bool ptrace_freeze_traced(struct task_struct *task) +{ + bool ret = false; + + /* Lockless, nobody but us can set this flag */ + if (task->jobctl & JOBCTL_LISTENING) + return ret; + + spin_lock_irq(&task->sighand->siglock); + if (task_is_traced(task) && !__fatal_signal_pending(task)) { + task->state = __TASK_TRACED; + ret = true; + } + spin_unlock_irq(&task->sighand->siglock); + + return ret; +} + +static void ptrace_unfreeze_traced(struct task_struct *task) +{ + if (task->state != __TASK_TRACED) + return; + + WARN_ON(!task->ptrace || task->parent != current); + + spin_lock_irq(&task->sighand->siglock); + if (__fatal_signal_pending(task)) + wake_up_state(task, __TASK_TRACED); + else + task->state = TASK_TRACED; + spin_unlock_irq(&task->sighand->siglock); +} + /** * ptrace_check_attach - check whether ptracee is ready for ptrace operation * @child: ptracee to check for @@ -139,7 +173,7 @@ void __ptrace_unlink(struct task_struct *child) * RETURNS: * 0 on success, -ESRCH if %child is not ready. */ -int ptrace_check_attach(struct task_struct *child, bool ignore_state) +static int ptrace_check_attach(struct task_struct *child, bool ignore_state) { int ret = -ESRCH; @@ -151,24 +185,29 @@ int ptrace_check_attach(struct task_struct *child, bool ignore_state) * be changed by us so it's not changing right after this. */ read_lock(&tasklist_lock); - if ((child->ptrace & PT_PTRACED) && child->parent == current) { + if (child->ptrace && child->parent == current) { + WARN_ON(child->state == __TASK_TRACED); /* * child->sighand can't be NULL, release_task() * does ptrace_unlink() before __exit_signal(). */ - spin_lock_irq(&child->sighand->siglock); - WARN_ON_ONCE(task_is_stopped(child)); - if (ignore_state || (task_is_traced(child) && - !(child->jobctl & JOBCTL_LISTENING))) + if (ignore_state || ptrace_freeze_traced(child)) ret = 0; - spin_unlock_irq(&child->sighand->siglock); } read_unlock(&tasklist_lock); - if (!ret && !ignore_state) - ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH; + if (!ret && !ignore_state) { + if (!wait_task_inactive(child, __TASK_TRACED)) { + /* + * This can only happen if may_ptrace_stop() fails and + * ptrace_stop() changes ->state back to TASK_RUNNING, + * so we should not worry about leaking __TASK_TRACED. + */ + WARN_ON(child->state == __TASK_TRACED); + ret = -ESRCH; + } + } - /* All systems go.. */ return ret; } @@ -317,7 +356,7 @@ static int ptrace_attach(struct task_struct *task, long request, */ if (task_is_stopped(task) && task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING)) - signal_wake_up(task, 1); + signal_wake_up_state(task, __TASK_STOPPED); spin_unlock(&task->sighand->siglock); @@ -737,7 +776,7 @@ int ptrace_request(struct task_struct *child, long request, * tracee into STOP. */ if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP))) - signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); + ptrace_signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); unlock_task_sighand(child, &flags); ret = 0; @@ -763,7 +802,7 @@ int ptrace_request(struct task_struct *child, long request, * start of this trap and now. Trigger re-trap. */ if (child->jobctl & JOBCTL_TRAP_NOTIFY) - signal_wake_up(child, true); + ptrace_signal_wake_up(child, true); ret = 0; } unlock_task_sighand(child, &flags); @@ -900,6 +939,8 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr, goto out_put_task_struct; ret = arch_ptrace(child, request, addr, data); + if (ret || request != PTRACE_DETACH) + ptrace_unfreeze_traced(child); out_put_task_struct: put_task_struct(child); @@ -1039,8 +1080,11 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, ret = ptrace_check_attach(child, request == PTRACE_KILL || request == PTRACE_INTERRUPT); - if (!ret) + if (!ret) { ret = compat_arch_ptrace(child, request, addr, data); + if (ret || request != PTRACE_DETACH) + ptrace_unfreeze_traced(child); + } out_put_task_struct: put_task_struct(child); diff --git a/kernel/rwsem.c b/kernel/rwsem.c index 6850f53e02d..b3c6c3fcd84 100644 --- a/kernel/rwsem.c +++ b/kernel/rwsem.c @@ -116,6 +116,16 @@ void down_read_nested(struct rw_semaphore *sem, int subclass) EXPORT_SYMBOL(down_read_nested); +void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest) +{ + might_sleep(); + rwsem_acquire_nest(&sem->dep_map, 0, 0, nest, _RET_IP_); + + LOCK_CONTENDED(sem, __down_write_trylock, __down_write); +} + +EXPORT_SYMBOL(_down_write_nest_lock); + void down_write_nested(struct rw_semaphore *sem, int subclass) { might_sleep(); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 257002c13bb..26058d0bebb 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1523,7 +1523,8 @@ out: */ int wake_up_process(struct task_struct *p) { - return try_to_wake_up(p, TASK_ALL, 0); + WARN_ON(task_is_stopped_or_traced(p)); + return try_to_wake_up(p, TASK_NORMAL, 0); } EXPORT_SYMBOL(wake_up_process); diff --git a/kernel/signal.c b/kernel/signal.c index 372771e948c..3d09cf6cde7 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -680,23 +680,17 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) * No need to set need_resched since signal event passing * goes through ->blocked */ -void signal_wake_up(struct task_struct *t, int resume) +void signal_wake_up_state(struct task_struct *t, unsigned int state) { - unsigned int mask; - set_tsk_thread_flag(t, TIF_SIGPENDING); - /* - * For SIGKILL, we want to wake it up in the stopped/traced/killable + * TASK_WAKEKILL also means wake it up in the stopped/traced/killable * case. We don't check t->state here because there is a race with it * executing another processor and just now entering stopped state. * By using wake_up_state, we ensure the process will wake up and * handle its death signal. */ - mask = TASK_INTERRUPTIBLE; - if (resume) - mask |= TASK_WAKEKILL; - if (!wake_up_state(t, mask)) + if (!wake_up_state(t, state | TASK_INTERRUPTIBLE)) kick_process(t); } @@ -844,7 +838,7 @@ static void ptrace_trap_notify(struct task_struct *t) assert_spin_locked(&t->sighand->siglock); task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY); - signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); + ptrace_signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); } /* @@ -1800,6 +1794,10 @@ static inline int may_ptrace_stop(void) * If SIGKILL was already sent before the caller unlocked * ->siglock we must see ->core_state != NULL. Otherwise it * is safe to enter schedule(). + * + * This is almost outdated, a task with the pending SIGKILL can't + * block in TASK_TRACED. But PTRACE_EVENT_EXIT can be reported + * after SIGKILL was already dequeued. */ if (unlikely(current->mm->core_state) && unlikely(current->mm == current->parent->mm)) @@ -1925,6 +1923,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) if (gstop_done) do_notify_parent_cldstop(current, false, why); + /* tasklist protects us from ptrace_freeze_traced() */ __set_current_state(TASK_RUNNING); if (clear_code) current->exit_code = 0; @@ -3116,8 +3115,9 @@ int __save_altstack(stack_t __user *uss, unsigned long sp) #ifdef CONFIG_COMPAT #ifdef CONFIG_GENERIC_SIGALTSTACK -asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr, - compat_stack_t __user *uoss_ptr) +COMPAT_SYSCALL_DEFINE2(sigaltstack, + const compat_stack_t __user *, uss_ptr, + compat_stack_t __user *, uoss_ptr) { stack_t uss, uoss; int ret; diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 30b6de0d977..c6d6400ee13 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -339,6 +339,7 @@ void clockevents_config_and_register(struct clock_event_device *dev, clockevents_config(dev, freq); clockevents_register_device(dev); } +EXPORT_SYMBOL_GPL(clockevents_config_and_register); /** * clockevents_update_freq - Update frequency and reprogram a clock event device. diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 3ffe4c5ad3f..41473b4ad7a 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3998,7 +3998,7 @@ static int ftrace_module_notify(struct notifier_block *self, struct notifier_block ftrace_module_nb = { .notifier_call = ftrace_module_notify, - .priority = 0, + .priority = INT_MAX, /* Run before anything that can use kprobes */ }; extern unsigned long __start_mcount_loc[]; diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index e5125677efa..3c13e46d7d2 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2899,6 +2899,8 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf, if (copy_from_user(&buf, ubuf, cnt)) return -EFAULT; + buf[cnt] = 0; + trace_set_options(buf); *ppos += cnt; @@ -3452,7 +3454,7 @@ static int tracing_wait_pipe(struct file *filp) return -EINTR; /* - * We block until we read something and tracing is enabled. + * We block until we read something and tracing is disabled. * We still block if tracing is disabled, but we have never * read anything. This allows a user to cat this file, and * then enable tracing. But after we have read something, @@ -3460,7 +3462,7 @@ static int tracing_wait_pipe(struct file *filp) * * iter->pos will be 0 if we haven't read anything. */ - if (tracing_is_enabled() && iter->pos) + if (!tracing_is_enabled() && iter->pos) break; } @@ -4815,10 +4817,17 @@ rb_simple_write(struct file *filp, const char __user *ubuf, return ret; if (buffer) { - if (val) + mutex_lock(&trace_types_lock); + if (val) { ring_buffer_record_on(buffer); - else + if (current_trace->start) + current_trace->start(tr); + } else { ring_buffer_record_off(buffer); + if (current_trace->stop) + current_trace->stop(tr); + } + mutex_unlock(&trace_types_lock); } (*ppos)++; diff --git a/lib/bug.c b/lib/bug.c index a28c1415357..d0cdf14c651 100644 --- a/lib/bug.c +++ b/lib/bug.c @@ -55,6 +55,7 @@ static inline unsigned long bug_addr(const struct bug_entry *bug) } #ifdef CONFIG_MODULES +/* Updates are protected by module mutex */ static LIST_HEAD(module_bug_list); static const struct bug_entry *module_find_bug(unsigned long bugaddr) diff --git a/lib/cpu_rmap.c b/lib/cpu_rmap.c index 145dec5267c..5fbed5caba6 100644 --- a/lib/cpu_rmap.c +++ b/lib/cpu_rmap.c @@ -45,6 +45,7 @@ struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags) if (!rmap) return NULL; + kref_init(&rmap->refcount); rmap->obj = (void **)((char *)rmap + obj_offset); /* Initially assign CPUs to objects on a rota, since we have @@ -63,6 +64,35 @@ struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags) } EXPORT_SYMBOL(alloc_cpu_rmap); +/** + * cpu_rmap_release - internal reclaiming helper called from kref_put + * @ref: kref to struct cpu_rmap + */ +static void cpu_rmap_release(struct kref *ref) +{ + struct cpu_rmap *rmap = container_of(ref, struct cpu_rmap, refcount); + kfree(rmap); +} + +/** + * cpu_rmap_get - internal helper to get new ref on a cpu_rmap + * @rmap: reverse-map allocated with alloc_cpu_rmap() + */ +static inline void cpu_rmap_get(struct cpu_rmap *rmap) +{ + kref_get(&rmap->refcount); +} + +/** + * cpu_rmap_put - release ref on a cpu_rmap + * @rmap: reverse-map allocated with alloc_cpu_rmap() + */ +int cpu_rmap_put(struct cpu_rmap *rmap) +{ + return kref_put(&rmap->refcount, cpu_rmap_release); +} +EXPORT_SYMBOL(cpu_rmap_put); + /* Reevaluate nearest object for given CPU, comparing with the given * neighbours at the given distance. */ @@ -197,8 +227,7 @@ struct irq_glue { * free_irq_cpu_rmap - free a CPU affinity reverse-map used for IRQs * @rmap: Reverse-map allocated with alloc_irq_cpu_map(), or %NULL * - * Must be called in process context, before freeing the IRQs, and - * without holding any locks required by global workqueue items. + * Must be called in process context, before freeing the IRQs. */ void free_irq_cpu_rmap(struct cpu_rmap *rmap) { @@ -212,12 +241,18 @@ void free_irq_cpu_rmap(struct cpu_rmap *rmap) glue = rmap->obj[index]; irq_set_affinity_notifier(glue->notify.irq, NULL); } - irq_run_affinity_notifiers(); - kfree(rmap); + cpu_rmap_put(rmap); } EXPORT_SYMBOL(free_irq_cpu_rmap); +/** + * irq_cpu_rmap_notify - callback for IRQ subsystem when IRQ affinity updated + * @notify: struct irq_affinity_notify passed by irq/manage.c + * @mask: cpu mask for new SMP affinity + * + * This is executed in workqueue context. + */ static void irq_cpu_rmap_notify(struct irq_affinity_notify *notify, const cpumask_t *mask) { @@ -230,10 +265,16 @@ irq_cpu_rmap_notify(struct irq_affinity_notify *notify, const cpumask_t *mask) pr_warning("irq_cpu_rmap_notify: update failed: %d\n", rc); } +/** + * irq_cpu_rmap_release - reclaiming callback for IRQ subsystem + * @ref: kref to struct irq_affinity_notify passed by irq/manage.c + */ static void irq_cpu_rmap_release(struct kref *ref) { struct irq_glue *glue = container_of(ref, struct irq_glue, notify.kref); + + cpu_rmap_put(glue->rmap); kfree(glue); } @@ -258,10 +299,13 @@ int irq_cpu_rmap_add(struct cpu_rmap *rmap, int irq) glue->notify.notify = irq_cpu_rmap_notify; glue->notify.release = irq_cpu_rmap_release; glue->rmap = rmap; + cpu_rmap_get(rmap); glue->index = cpu_rmap_add(rmap, glue); rc = irq_set_affinity_notifier(irq, &glue->notify); - if (rc) + if (rc) { + cpu_rmap_put(glue->rmap); kfree(glue); + } return rc; } EXPORT_SYMBOL(irq_cpu_rmap_add); diff --git a/lib/rbtree.c b/lib/rbtree.c index 4f56a11d67f..c0e31fe2fab 100644 --- a/lib/rbtree.c +++ b/lib/rbtree.c @@ -194,8 +194,12 @@ __rb_insert(struct rb_node *node, struct rb_root *root, } } -__always_inline void -__rb_erase_color(struct rb_node *parent, struct rb_root *root, +/* + * Inline version for rb_erase() use - we want to be able to inline + * and eliminate the dummy_rotate callback there + */ +static __always_inline void +____rb_erase_color(struct rb_node *parent, struct rb_root *root, void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) { struct rb_node *node = NULL, *sibling, *tmp1, *tmp2; @@ -355,6 +359,13 @@ __rb_erase_color(struct rb_node *parent, struct rb_root *root, } } } + +/* Non-inline version for rb_erase_augmented() use */ +void __rb_erase_color(struct rb_node *parent, struct rb_root *root, + void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) +{ + ____rb_erase_color(parent, root, augment_rotate); +} EXPORT_SYMBOL(__rb_erase_color); /* @@ -380,7 +391,10 @@ EXPORT_SYMBOL(rb_insert_color); void rb_erase(struct rb_node *node, struct rb_root *root) { - rb_erase_augmented(node, root, &dummy_callbacks); + struct rb_node *rebalance; + rebalance = __rb_erase_augmented(node, root, &dummy_callbacks); + if (rebalance) + ____rb_erase_color(rebalance, root, dummy_rotate); } EXPORT_SYMBOL(rb_erase); diff --git a/mm/bootmem.c b/mm/bootmem.c index 1324cd74fae..b93376c39b6 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -185,10 +185,23 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) while (start < end) { unsigned long *map, idx, vec; + unsigned shift; map = bdata->node_bootmem_map; idx = start - bdata->node_min_pfn; + shift = idx & (BITS_PER_LONG - 1); + /* + * vec holds at most BITS_PER_LONG map bits, + * bit 0 corresponds to start. + */ vec = ~map[idx / BITS_PER_LONG]; + + if (shift) { + vec >>= shift; + if (end - start >= BITS_PER_LONG) + vec |= ~map[idx / BITS_PER_LONG + 1] << + (BITS_PER_LONG - shift); + } /* * If we have a properly aligned and fully unreserved * BITS_PER_LONG block of pages in front of us, free @@ -201,19 +214,18 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) count += BITS_PER_LONG; start += BITS_PER_LONG; } else { - unsigned long off = 0; + unsigned long cur = start; - vec >>= start & (BITS_PER_LONG - 1); - while (vec) { + start = ALIGN(start + 1, BITS_PER_LONG); + while (vec && cur != start) { if (vec & 1) { - page = pfn_to_page(start + off); + page = pfn_to_page(cur); __free_pages_bootmem(page, 0); count++; } vec >>= 1; - off++; + ++cur; } - start = ALIGN(start + 1, BITS_PER_LONG); } } diff --git a/mm/compaction.c b/mm/compaction.c index 6b807e46649..c62bd063d76 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -816,6 +816,7 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, static int compact_finished(struct zone *zone, struct compact_control *cc) { + unsigned int order; unsigned long watermark; if (fatal_signal_pending(current)) @@ -850,22 +851,16 @@ static int compact_finished(struct zone *zone, return COMPACT_CONTINUE; /* Direct compactor: Is a suitable page free? */ - if (cc->page) { - /* Was a suitable page captured? */ - if (*cc->page) + for (order = cc->order; order < MAX_ORDER; order++) { + struct free_area *area = &zone->free_area[order]; + + /* Job done if page is free of the right migratetype */ + if (!list_empty(&area->free_list[cc->migratetype])) + return COMPACT_PARTIAL; + + /* Job done if allocation would set block type */ + if (cc->order >= pageblock_order && area->nr_free) return COMPACT_PARTIAL; - } else { - unsigned int order; - for (order = cc->order; order < MAX_ORDER; order++) { - struct free_area *area = &zone->free_area[cc->order]; - /* Job done if page is free of the right migratetype */ - if (!list_empty(&area->free_list[cc->migratetype])) - return COMPACT_PARTIAL; - - /* Job done if allocation would set block type */ - if (cc->order >= pageblock_order && area->nr_free) - return COMPACT_PARTIAL; - } } return COMPACT_CONTINUE; @@ -921,60 +916,6 @@ unsigned long compaction_suitable(struct zone *zone, int order) return COMPACT_CONTINUE; } -static void compact_capture_page(struct compact_control *cc) -{ - unsigned long flags; - int mtype, mtype_low, mtype_high; - - if (!cc->page || *cc->page) - return; - - /* - * For MIGRATE_MOVABLE allocations we capture a suitable page ASAP - * regardless of the migratetype of the freelist is is captured from. - * This is fine because the order for a high-order MIGRATE_MOVABLE - * allocation is typically at least a pageblock size and overall - * fragmentation is not impaired. Other allocation types must - * capture pages from their own migratelist because otherwise they - * could pollute other pageblocks like MIGRATE_MOVABLE with - * difficult to move pages and making fragmentation worse overall. - */ - if (cc->migratetype == MIGRATE_MOVABLE) { - mtype_low = 0; - mtype_high = MIGRATE_PCPTYPES; - } else { - mtype_low = cc->migratetype; - mtype_high = cc->migratetype + 1; - } - - /* Speculatively examine the free lists without zone lock */ - for (mtype = mtype_low; mtype < mtype_high; mtype++) { - int order; - for (order = cc->order; order < MAX_ORDER; order++) { - struct page *page; - struct free_area *area; - area = &(cc->zone->free_area[order]); - if (list_empty(&area->free_list[mtype])) - continue; - - /* Take the lock and attempt capture of the page */ - if (!compact_trylock_irqsave(&cc->zone->lock, &flags, cc)) - return; - if (!list_empty(&area->free_list[mtype])) { - page = list_entry(area->free_list[mtype].next, - struct page, lru); - if (capture_free_page(page, cc->order, mtype)) { - spin_unlock_irqrestore(&cc->zone->lock, - flags); - *cc->page = page; - return; - } - } - spin_unlock_irqrestore(&cc->zone->lock, flags); - } - } -} - static int compact_zone(struct zone *zone, struct compact_control *cc) { int ret; @@ -1054,9 +995,6 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) goto out; } } - - /* Capture a page now if it is a suitable size */ - compact_capture_page(cc); } out: @@ -1069,8 +1007,7 @@ out: static unsigned long compact_zone_order(struct zone *zone, int order, gfp_t gfp_mask, - bool sync, bool *contended, - struct page **page) + bool sync, bool *contended) { unsigned long ret; struct compact_control cc = { @@ -1080,7 +1017,6 @@ static unsigned long compact_zone_order(struct zone *zone, .migratetype = allocflags_to_migratetype(gfp_mask), .zone = zone, .sync = sync, - .page = page, }; INIT_LIST_HEAD(&cc.freepages); INIT_LIST_HEAD(&cc.migratepages); @@ -1110,7 +1046,7 @@ int sysctl_extfrag_threshold = 500; */ unsigned long try_to_compact_pages(struct zonelist *zonelist, int order, gfp_t gfp_mask, nodemask_t *nodemask, - bool sync, bool *contended, struct page **page) + bool sync, bool *contended) { enum zone_type high_zoneidx = gfp_zone(gfp_mask); int may_enter_fs = gfp_mask & __GFP_FS; @@ -1136,7 +1072,7 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist, int status; status = compact_zone_order(zone, order, gfp_mask, sync, - contended, page); + contended); rc = max(status, rc); /* If a normal allocation would succeed, stop compacting */ @@ -1192,7 +1128,6 @@ int compact_pgdat(pg_data_t *pgdat, int order) struct compact_control cc = { .order = order, .sync = false, - .page = NULL, }; return __compact_pgdat(pgdat, &cc); @@ -1203,14 +1138,13 @@ static int compact_node(int nid) struct compact_control cc = { .order = -1, .sync = true, - .page = NULL, }; return __compact_pgdat(NODE_DATA(nid), &cc); } /* Compact all nodes in the system */ -static int compact_nodes(void) +static void compact_nodes(void) { int nid; @@ -1219,8 +1153,6 @@ static int compact_nodes(void) for_each_online_node(nid) compact_node(nid); - - return COMPACT_COMPLETE; } /* The written value is actually unused, all memory is compacted */ @@ -1231,7 +1163,7 @@ int sysctl_compaction_handler(struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) { if (write) - return compact_nodes(); + compact_nodes(); return 0; } diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 9e894edc781..6001ee6347a 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1819,9 +1819,19 @@ int split_huge_page(struct page *page) BUG_ON(is_huge_zero_pfn(page_to_pfn(page))); BUG_ON(!PageAnon(page)); - anon_vma = page_lock_anon_vma_read(page); + + /* + * The caller does not necessarily hold an mmap_sem that would prevent + * the anon_vma disappearing so we first we take a reference to it + * and then lock the anon_vma for write. This is similar to + * page_lock_anon_vma_read except the write lock is taken to serialise + * against parallel split or collapse operations. + */ + anon_vma = page_get_anon_vma(page); if (!anon_vma) goto out; + anon_vma_lock_write(anon_vma); + ret = 0; if (!PageCompound(page)) goto out_unlock; @@ -1832,7 +1842,8 @@ int split_huge_page(struct page *page) BUG_ON(PageCompound(page)); out_unlock: - page_unlock_anon_vma_read(anon_vma); + anon_vma_unlock(anon_vma); + put_anon_vma(anon_vma); out: return ret; } diff --git a/mm/internal.h b/mm/internal.h index d597f94cc20..9ba21100ebf 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -135,7 +135,6 @@ struct compact_control { int migratetype; /* MOVABLE, RECLAIMABLE etc */ struct zone *zone; bool contended; /* True if a lock was contended */ - struct page **page; /* Page captured of requested size */ }; unsigned long diff --git a/mm/memblock.c b/mm/memblock.c index 625905523c2..88adc8afb61 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -314,7 +314,8 @@ static void __init_memblock memblock_merge_regions(struct memblock_type *type) } this->size += next->size; - memmove(next, next + 1, (type->cnt - (i + 1)) * sizeof(*next)); + /* move forward from next + 1, index of which is i + 2 */ + memmove(next, next + 1, (type->cnt - (i + 2)) * sizeof(*next)); type->cnt--; } } diff --git a/mm/migrate.c b/mm/migrate.c index 3b676b0c5c3..c38778610aa 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -1679,9 +1679,21 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm, page_xchg_last_nid(new_page, page_last_nid(page)); isolated = numamigrate_isolate_page(pgdat, page); - if (!isolated) { + + /* + * Failing to isolate or a GUP pin prevents migration. The expected + * page count is 2. 1 for anonymous pages without a mapping and 1 + * for the callers pin. If the page was isolated, the page will + * need to be put back on the LRU. + */ + if (!isolated || page_count(page) != 2) { count_vm_events(PGMIGRATE_FAIL, HPAGE_PMD_NR); put_page(new_page); + if (isolated) { + putback_lru_page(page); + isolated = 0; + goto out; + } goto out_keep_locked; } diff --git a/mm/mmap.c b/mm/mmap.c index f54b235f29a..35730ee9d51 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2886,7 +2886,7 @@ static void vm_lock_anon_vma(struct mm_struct *mm, struct anon_vma *anon_vma) * The LSB of head.next can't change from under us * because we hold the mm_all_locks_mutex. */ - down_write(&anon_vma->root->rwsem); + down_write_nest_lock(&anon_vma->root->rwsem, &mm->mmap_sem); /* * We can safely modify head.next after taking the * anon_vma->root->rwsem. If some other vma in this mm shares diff --git a/mm/page_alloc.c b/mm/page_alloc.c index bc6cc0e913b..df2022ff0c8 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1384,14 +1384,8 @@ void split_page(struct page *page, unsigned int order) set_page_refcounted(page + i); } -/* - * Similar to the split_page family of functions except that the page - * required at the given order and being isolated now to prevent races - * with parallel allocators - */ -int capture_free_page(struct page *page, int alloc_order, int migratetype) +static int __isolate_free_page(struct page *page, unsigned int order) { - unsigned int order; unsigned long watermark; struct zone *zone; int mt; @@ -1399,7 +1393,6 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype) BUG_ON(!PageBuddy(page)); zone = page_zone(page); - order = page_order(page); mt = get_pageblock_migratetype(page); if (mt != MIGRATE_ISOLATE) { @@ -1408,7 +1401,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype) if (!zone_watermark_ok(zone, 0, watermark, 0, 0)) return 0; - __mod_zone_freepage_state(zone, -(1UL << alloc_order), mt); + __mod_zone_freepage_state(zone, -(1UL << order), mt); } /* Remove page from free list */ @@ -1416,11 +1409,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype) zone->free_area[order].nr_free--; rmv_page_order(page); - if (alloc_order != order) - expand(zone, page, alloc_order, order, - &zone->free_area[order], migratetype); - - /* Set the pageblock if the captured page is at least a pageblock */ + /* Set the pageblock if the isolated page is at least a pageblock */ if (order >= pageblock_order - 1) { struct page *endpage = page + (1 << order) - 1; for (; page < endpage; page += pageblock_nr_pages) { @@ -1431,7 +1420,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype) } } - return 1UL << alloc_order; + return 1UL << order; } /* @@ -1449,10 +1438,9 @@ int split_free_page(struct page *page) unsigned int order; int nr_pages; - BUG_ON(!PageBuddy(page)); order = page_order(page); - nr_pages = capture_free_page(page, order, 0); + nr_pages = __isolate_free_page(page, order); if (!nr_pages) return 0; @@ -2136,8 +2124,6 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, bool *contended_compaction, bool *deferred_compaction, unsigned long *did_some_progress) { - struct page *page = NULL; - if (!order) return NULL; @@ -2149,16 +2135,12 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, current->flags |= PF_MEMALLOC; *did_some_progress = try_to_compact_pages(zonelist, order, gfp_mask, nodemask, sync_migration, - contended_compaction, &page); + contended_compaction); current->flags &= ~PF_MEMALLOC; - /* If compaction captured a page, prep and use it */ - if (page) { - prep_new_page(page, order, gfp_mask); - goto got_page; - } - if (*did_some_progress != COMPACT_SKIPPED) { + struct page *page; + /* Page migration frees to the PCP lists but we want merging */ drain_pages(get_cpu()); put_cpu(); @@ -2168,7 +2150,6 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, alloc_flags & ~ALLOC_NO_WATERMARKS, preferred_zone, migratetype); if (page) { -got_page: preferred_zone->compact_blockskip_flush = false; preferred_zone->compact_considered = 0; preferred_zone->compact_defer_shift = 0; @@ -5604,7 +5585,7 @@ static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn) pfn &= (PAGES_PER_SECTION-1); return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS; #else - pfn = pfn - zone->zone_start_pfn; + pfn = pfn - round_down(zone->zone_start_pfn, pageblock_nr_pages); return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS; #endif /* CONFIG_SPARSEMEM */ } diff --git a/net/core/dev.c b/net/core/dev.c index 515473ee52c..f64e439b4a0 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6121,6 +6121,14 @@ struct netdev_queue *dev_ingress_queue_create(struct net_device *dev) static const struct ethtool_ops default_ethtool_ops; +void netdev_set_default_ethtool_ops(struct net_device *dev, + const struct ethtool_ops *ops) +{ + if (dev->ethtool_ops == &default_ethtool_ops) + dev->ethtool_ops = ops; +} +EXPORT_SYMBOL_GPL(netdev_set_default_ethtool_ops); + /** * alloc_netdev_mqs - allocate network device * @sizeof_priv: size of private data to allocate space for diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 3c9d2088028..d9c4f113d70 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -590,7 +590,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, case IP_TTL: if (optlen < 1) goto e_inval; - if (val != -1 && (val < 0 || val > 255)) + if (val != -1 && (val < 1 || val > 255)) goto e_inval; inet->uc_ttl = val; break; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 1ca253635f7..2aa69c8ae60 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1428,12 +1428,12 @@ static void tcp_service_net_dma(struct sock *sk, bool wait) } #endif -static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) +static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) { struct sk_buff *skb; u32 offset; - skb_queue_walk(&sk->sk_receive_queue, skb) { + while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) { offset = seq - TCP_SKB_CB(skb)->seq; if (tcp_hdr(skb)->syn) offset--; @@ -1441,6 +1441,11 @@ static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) *off = offset; return skb; } + /* This looks weird, but this can happen if TCP collapsing + * splitted a fat GRO packet, while we released socket lock + * in skb_splice_bits() + */ + sk_eat_skb(sk, skb, false); } return NULL; } @@ -1482,7 +1487,7 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, break; } used = recv_actor(desc, skb, offset, len); - if (used < 0) { + if (used <= 0) { if (!copied) copied = used; break; @@ -1520,8 +1525,10 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, tcp_rcv_space_adjust(sk); /* Clean up data we have read: This will do ACK frames. */ - if (copied > 0) + if (copied > 0) { + tcp_recv_skb(sk, seq, &offset); tcp_cleanup_rbuf(sk, copied); + } return copied; } EXPORT_SYMBOL(tcp_read_sock); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a28e4db8a95..18f97ca76b0 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5543,7 +5543,7 @@ slow_path: if (len < (th->doff << 2) || tcp_checksum_complete_user(sk, skb)) goto csum_error; - if (!th->ack) + if (!th->ack && !th->rst) goto discard; /* @@ -5988,7 +5988,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, goto discard; } - if (!th->ack) + if (!th->ack && !th->rst) goto discard; if (!tcp_validate_incoming(sk, skb, th, 0)) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 408cac4ae00..420e5632638 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -154,6 +154,11 @@ static void addrconf_type_change(struct net_device *dev, unsigned long event); static int addrconf_ifdown(struct net_device *dev, int how); +static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, + int plen, + const struct net_device *dev, + u32 flags, u32 noflags); + static void addrconf_dad_start(struct inet6_ifaddr *ifp); static void addrconf_dad_timer(unsigned long data); static void addrconf_dad_completed(struct inet6_ifaddr *ifp); @@ -250,12 +255,6 @@ static inline bool addrconf_qdisc_ok(const struct net_device *dev) return !qdisc_tx_is_noop(dev); } -/* Check if a route is valid prefix route */ -static inline int addrconf_is_prefix_route(const struct rt6_info *rt) -{ - return (rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0; -} - static void addrconf_del_timer(struct inet6_ifaddr *ifp) { if (del_timer(&ifp->timer)) @@ -941,17 +940,15 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) { struct in6_addr prefix; struct rt6_info *rt; - struct net *net = dev_net(ifp->idev->dev); - struct flowi6 fl6 = {}; ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); - fl6.flowi6_oif = ifp->idev->dev->ifindex; - fl6.daddr = prefix; - rt = (struct rt6_info *)ip6_route_lookup(net, &fl6, - RT6_LOOKUP_F_IFACE); - if (rt != net->ipv6.ip6_null_entry && - addrconf_is_prefix_route(rt)) { + rt = addrconf_get_prefix_route(&prefix, + ifp->prefix_len, + ifp->idev->dev, + 0, RTF_GATEWAY | RTF_DEFAULT); + + if (rt) { if (onlink == 0) { ip6_del_rt(rt); rt = NULL; @@ -1877,7 +1874,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, continue; if ((rt->rt6i_flags & flags) != flags) continue; - if ((noflags != 0) && ((rt->rt6i_flags & flags) != 0)) + if ((rt->rt6i_flags & noflags) != 0) continue; dst_hold(&rt->dst); break; diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 3ad1f9db5f8..df082508362 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -1806,7 +1806,7 @@ static void iucv_external_interrupt(struct ext_code ext_code, struct iucv_irq_data *p; struct iucv_irq_list *work; - kstat_cpu(smp_processor_id()).irqs[EXTINT_IUC]++; + inc_irq_stat(IRQEXT_IUC); p = iucv_irq_data[smp_processor_id()]; if (p->ippathid >= iucv_max_pathid) { WARN_ON(p->ippathid >= iucv_max_pathid); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 5c61677487c..47e0aca614b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1009,6 +1009,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) if (old_probe_resp) kfree_rcu(old_probe_resp, rcu_head); + list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) + sta_info_flush(local, vlan); sta_info_flush(local, sdata); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 53f03120db5..80e55527504 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -4,6 +4,7 @@ #include <linux/nl80211.h> #include <linux/export.h> +#include <linux/rtnetlink.h> #include <net/cfg80211.h> #include "ieee80211_i.h" #include "driver-ops.h" @@ -197,6 +198,15 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) ctx = container_of(conf, struct ieee80211_chanctx, conf); + if (sdata->vif.type == NL80211_IFTYPE_AP) { + struct ieee80211_sub_if_data *vlan; + + /* for the VLAN list */ + ASSERT_RTNL(); + list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) + rcu_assign_pointer(vlan->vif.chanctx_conf, NULL); + } + ieee80211_unassign_vif_chanctx(sdata, ctx); if (ctx->refcount == 0) ieee80211_free_chanctx(local, ctx); @@ -316,6 +326,15 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, goto out; } + if (sdata->vif.type == NL80211_IFTYPE_AP) { + struct ieee80211_sub_if_data *vlan; + + /* for the VLAN list */ + ASSERT_RTNL(); + list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) + rcu_assign_pointer(vlan->vif.chanctx_conf, &ctx->conf); + } + ieee80211_recalc_smps_chanctx(local, ctx); out: mutex_unlock(&local->chanctx_mtx); @@ -331,6 +350,25 @@ void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) mutex_unlock(&sdata->local->chanctx_mtx); } +void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_sub_if_data *ap; + struct ieee80211_chanctx_conf *conf; + + if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss)) + return; + + ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); + + mutex_lock(&local->chanctx_mtx); + + conf = rcu_dereference_protected(ap->vif.chanctx_conf, + lockdep_is_held(&local->chanctx_mtx)); + rcu_assign_pointer(sdata->vif.chanctx_conf, conf); + mutex_unlock(&local->chanctx_mtx); +} + void ieee80211_iter_chan_contexts_atomic( struct ieee80211_hw *hw, void (*iter)(struct ieee80211_hw *hw, diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 8881fc77fb1..6b7644e818d 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -703,8 +703,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) sdata_info(sdata, "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); - ieee80211_request_internal_scan(sdata, - ifibss->ssid, ifibss->ssid_len, NULL); + ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, + NULL); } static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) @@ -802,9 +802,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) IEEE80211_SCAN_INTERVAL)) { sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); - ieee80211_request_internal_scan(sdata, - ifibss->ssid, ifibss->ssid_len, - ifibss->fixed_channel ? ifibss->channel : NULL); + ieee80211_request_ibss_scan(sdata, ifibss->ssid, + ifibss->ssid_len, chan); } else { int interval = IEEE80211_SCAN_INTERVAL; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 42d0d026773..8563b9a5cac 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -92,8 +92,6 @@ struct ieee80211_bss { u32 device_ts; - u8 dtim_period; - bool wmm_used; bool uapsd_supported; @@ -140,7 +138,6 @@ enum ieee80211_bss_corrupt_data_flags { /** * enum ieee80211_valid_data_flags - BSS valid data flags - * @IEEE80211_BSS_VALID_DTIM: DTIM data was gathered from non-corrupt IE * @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE * @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE * @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE @@ -151,7 +148,6 @@ enum ieee80211_bss_corrupt_data_flags { * beacon/probe response. */ enum ieee80211_bss_valid_data_flags { - IEEE80211_BSS_VALID_DTIM = BIT(0), IEEE80211_BSS_VALID_WMM = BIT(1), IEEE80211_BSS_VALID_RATES = BIT(2), IEEE80211_BSS_VALID_ERP = BIT(3) @@ -440,6 +436,7 @@ struct ieee80211_if_managed { unsigned long timers_running; /* used for quiesce/restart */ bool powersave; /* powersave requested for this iface */ bool broken_ap; /* AP is broken -- turn off powersave */ + u8 dtim_period; enum ieee80211_smps_mode req_smps, /* requested smps mode */ driver_smps_mode; /* smps mode request */ @@ -773,6 +770,10 @@ struct ieee80211_sub_if_data { u32 mntr_flags; } u; + spinlock_t cleanup_stations_lock; + struct list_head cleanup_stations; + struct work_struct cleanup_stations_wk; + #ifdef CONFIG_MAC80211_DEBUGFS struct { struct dentry *dir; @@ -1329,9 +1330,9 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, /* scan/BSS handling */ void ieee80211_scan_work(struct work_struct *work); -int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, - const u8 *ssid, u8 ssid_len, - struct ieee80211_channel *chan); +int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, + const u8 *ssid, u8 ssid_len, + struct ieee80211_channel *chan); int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, struct cfg80211_scan_request *req); void ieee80211_scan_cancel(struct ieee80211_local *local); @@ -1628,6 +1629,7 @@ ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, const struct cfg80211_chan_def *chandef, enum ieee80211_chanctx_mode mode); void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); +void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata); void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, struct ieee80211_chanctx *chanctx); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 09a80b55cf5..8be854e86cd 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -207,17 +207,8 @@ void ieee80211_recalc_idle(struct ieee80211_local *local) static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) { - int meshhdrlen; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - meshhdrlen = (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ? 5 : 0; - - /* FIX: what would be proper limits for MTU? - * This interface uses 802.3 frames. */ - if (new_mtu < 256 || - new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) { + if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN) return -EINVAL; - } dev->mtu = new_mtu; return 0; @@ -586,11 +577,13 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) switch (sdata->vif.type) { case NL80211_IFTYPE_AP_VLAN: - /* no need to tell driver, but set carrier */ - if (rtnl_dereference(sdata->bss->beacon)) + /* no need to tell driver, but set carrier and chanctx */ + if (rtnl_dereference(sdata->bss->beacon)) { + ieee80211_vif_vlan_copy_chanctx(sdata); netif_carrier_on(dev); - else + } else { netif_carrier_off(dev); + } break; case NL80211_IFTYPE_MONITOR: if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { @@ -839,6 +832,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, switch (sdata->vif.type) { case NL80211_IFTYPE_AP_VLAN: list_del(&sdata->u.vlan.list); + rcu_assign_pointer(sdata->vif.chanctx_conf, NULL); /* no need to tell driver */ break; case NL80211_IFTYPE_MONITOR: @@ -865,20 +859,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, cancel_work_sync(&sdata->work); /* * When we get here, the interface is marked down. - * Call rcu_barrier() to wait both for the RX path + * Call synchronize_rcu() to wait for the RX path * should it be using the interface and enqueuing - * frames at this very time on another CPU, and - * for the sta free call_rcu callbacks. - */ - rcu_barrier(); - - /* - * free_sta_rcu() enqueues a work for the actual - * sta cleanup, so we need to flush it while - * sdata is still valid. + * frames at this very time on another CPU. */ - flush_workqueue(local->workqueue); - + synchronize_rcu(); skb_queue_purge(&sdata->skb_queue); /* @@ -1498,6 +1483,15 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, mutex_unlock(&local->iflist_mtx); } +static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk) +{ + struct ieee80211_sub_if_data *sdata; + + sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk); + + ieee80211_cleanup_sdata_stas(sdata); +} + int ieee80211_if_add(struct ieee80211_local *local, const char *name, struct wireless_dev **new_wdev, enum nl80211_iftype type, struct vif_params *params) @@ -1573,6 +1567,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, INIT_LIST_HEAD(&sdata->key_list); + spin_lock_init(&sdata->cleanup_stations_lock); + INIT_LIST_HEAD(&sdata->cleanup_stations); + INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); + for (i = 0; i < IEEE80211_NUM_BANDS; i++) { struct ieee80211_supported_band *sband; sband = local->hw.wiphy->bands[i]; diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 1bf03f9ff3b..649ad513547 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -163,7 +163,7 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) return -ENOMEM; sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1; for (i = 0; i < RMC_BUCKETS; i++) - INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list); + INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i]); return 0; } @@ -177,7 +177,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) return; for (i = 0; i < RMC_BUCKETS; i++) - list_for_each_entry_safe(p, n, &rmc->bucket[i].list, list) { + list_for_each_entry_safe(p, n, &rmc->bucket[i], list) { list_del(&p->list); kmem_cache_free(rm_cache, p); } @@ -210,7 +210,7 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, /* Don't care about endianness since only match matters */ memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum)); idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask; - list_for_each_entry_safe(p, n, &rmc->bucket[idx].list, list) { + list_for_each_entry_safe(p, n, &rmc->bucket[idx], list) { ++entries; if (time_after(jiffies, p->exp_time) || (entries == RMC_QUEUE_MAX_LEN)) { @@ -229,7 +229,7 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, p->seqnum = seqnum; p->exp_time = jiffies + RMC_TIMEOUT; memcpy(p->sa, sa, ETH_ALEN); - list_add(&p->list, &rmc->bucket[idx].list); + list_add(&p->list, &rmc->bucket[idx]); return 0; } diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 7c9215fb2ac..84c28c6101c 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -184,7 +184,7 @@ struct rmc_entry { }; struct mesh_rmc { - struct rmc_entry bucket[RMC_BUCKETS]; + struct list_head bucket[RMC_BUCKETS]; u32 idx_mask; }; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 7753a9ca98a..a3552929a21 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1074,12 +1074,8 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) if (beaconint_us > latency) { local->ps_sdata = NULL; } else { - struct ieee80211_bss *bss; int maxslp = 1; - u8 dtimper; - - bss = (void *)found->u.mgd.associated->priv; - dtimper = bss->dtim_period; + u8 dtimper = found->u.mgd.dtim_period; /* If the TIM IE is invalid, pretend the value is 1 */ if (!dtimper) @@ -1410,10 +1406,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ieee80211_led_assoc(local, 1); - if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) - bss_conf->dtim_period = bss->dtim_period; - else + if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { + /* + * If the AP is buggy we may get here with no DTIM period + * known, so assume it's 1 which is the only safe assumption + * in that case, although if the TIM IE is broken powersave + * probably just won't work at all. + */ + bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1; + } else { bss_conf->dtim_period = 0; + } bss_conf->assoc = 1; @@ -1562,6 +1565,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, sdata->u.mgd.timers_running = 0; + sdata->vif.bss_conf.dtim_period = 0; + ifmgd->flags = 0; ieee80211_vif_release_channel(sdata); } @@ -2373,11 +2378,18 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *channel; bool need_ps = false; - if (sdata->u.mgd.associated && - ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) { - bss = (void *)sdata->u.mgd.associated->priv; + if ((sdata->u.mgd.associated && + ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) || + (sdata->u.mgd.assoc_data && + ether_addr_equal(mgmt->bssid, + sdata->u.mgd.assoc_data->bss->bssid))) { /* not previously set so we may need to recalc */ - need_ps = !bss->dtim_period; + need_ps = sdata->u.mgd.associated && !sdata->u.mgd.dtim_period; + + if (elems->tim && !elems->parse_error) { + struct ieee80211_tim_ie *tim_ie = elems->tim; + sdata->u.mgd.dtim_period = tim_ie->dtim_period; + } } if (elems->ds_params && elems->ds_params_len == 1) @@ -3896,20 +3908,41 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, /* kick off associate process */ ifmgd->assoc_data = assoc_data; + ifmgd->dtim_period = 0; err = ieee80211_prep_connection(sdata, req->bss, true); if (err) goto err_clear; - if (!bss->dtim_period && - sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { - /* - * Wait up to one beacon interval ... - * should this be more if we miss one? - */ - sdata_info(sdata, "waiting for beacon from %pM\n", - ifmgd->bssid); - assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); + if (sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { + const struct cfg80211_bss_ies *beacon_ies; + + rcu_read_lock(); + beacon_ies = rcu_dereference(req->bss->beacon_ies); + if (!beacon_ies) { + /* + * Wait up to one beacon interval ... + * should this be more if we miss one? + */ + sdata_info(sdata, "waiting for beacon from %pM\n", + ifmgd->bssid); + assoc_data->timeout = + TU_TO_EXP_TIME(req->bss->beacon_interval); + } else { + const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, + beacon_ies->data, + beacon_ies->len); + if (tim_ie && tim_ie[1] >= + sizeof(struct ieee80211_tim_ie)) { + const struct ieee80211_tim_ie *tim; + tim = (void *)(tim_ie + 2); + ifmgd->dtim_period = tim->dtim_period; + } + assoc_data->have_beacon = true; + assoc_data->sent_assoc = false; + assoc_data->timeout = jiffies; + } + rcu_read_unlock(); } else { assoc_data->have_beacon = true; assoc_data->sent_assoc = false; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 8ed83dcc149..d59fc6818b1 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -113,18 +113,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local, bss->valid_data |= IEEE80211_BSS_VALID_ERP; } - if (elems->tim && (!elems->parse_error || - !(bss->valid_data & IEEE80211_BSS_VALID_DTIM))) { - struct ieee80211_tim_ie *tim_ie = elems->tim; - bss->dtim_period = tim_ie->dtim_period; - if (!elems->parse_error) - bss->valid_data |= IEEE80211_BSS_VALID_DTIM; - } - - /* If the beacon had no TIM IE, or it was invalid, use 1 */ - if (beacon && !bss->dtim_period) - bss->dtim_period = 1; - /* replace old supported rates if we get new values */ if (!elems->parse_error || !(bss->valid_data & IEEE80211_BSS_VALID_RATES)) { @@ -832,9 +820,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, return res; } -int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, - const u8 *ssid, u8 ssid_len, - struct ieee80211_channel *chan) +int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, + const u8 *ssid, u8 ssid_len, + struct ieee80211_channel *chan) { struct ieee80211_local *local = sdata->local; int ret = -EBUSY; @@ -848,22 +836,36 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, /* fill internal scan request */ if (!chan) { - int i, nchan = 0; + int i, max_n; + int n_ch = 0; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { if (!local->hw.wiphy->bands[band]) continue; - for (i = 0; - i < local->hw.wiphy->bands[band]->n_channels; - i++) { - local->int_scan_req->channels[nchan] = + + max_n = local->hw.wiphy->bands[band]->n_channels; + for (i = 0; i < max_n; i++) { + struct ieee80211_channel *tmp_ch = &local->hw.wiphy->bands[band]->channels[i]; - nchan++; + + if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_DISABLED)) + continue; + + local->int_scan_req->channels[n_ch] = tmp_ch; + n_ch++; } } - local->int_scan_req->n_channels = nchan; + if (WARN_ON_ONCE(n_ch == 0)) + goto unlock; + + local->int_scan_req->n_channels = n_ch; } else { + if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_DISABLED))) + goto unlock; + local->int_scan_req->channels[0] = chan; local->int_scan_req->n_channels = 1; } diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f3e502502fe..ca9fde19818 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -91,9 +91,8 @@ static int sta_info_hash_del(struct ieee80211_local *local, return -ENOENT; } -static void free_sta_work(struct work_struct *wk) +static void cleanup_single_sta(struct sta_info *sta) { - struct sta_info *sta = container_of(wk, struct sta_info, free_sta_wk); int ac, i; struct tid_ampdu_tx *tid_tx; struct ieee80211_sub_if_data *sdata = sta->sdata; @@ -153,11 +152,35 @@ static void free_sta_work(struct work_struct *wk) sta_info_free(local, sta); } +void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata) +{ + struct sta_info *sta; + + spin_lock_bh(&sdata->cleanup_stations_lock); + while (!list_empty(&sdata->cleanup_stations)) { + sta = list_first_entry(&sdata->cleanup_stations, + struct sta_info, list); + list_del(&sta->list); + spin_unlock_bh(&sdata->cleanup_stations_lock); + + cleanup_single_sta(sta); + + spin_lock_bh(&sdata->cleanup_stations_lock); + } + + spin_unlock_bh(&sdata->cleanup_stations_lock); +} + static void free_sta_rcu(struct rcu_head *h) { struct sta_info *sta = container_of(h, struct sta_info, rcu_head); + struct ieee80211_sub_if_data *sdata = sta->sdata; - ieee80211_queue_work(&sta->local->hw, &sta->free_sta_wk); + spin_lock(&sdata->cleanup_stations_lock); + list_add_tail(&sta->list, &sdata->cleanup_stations); + spin_unlock(&sdata->cleanup_stations_lock); + + ieee80211_queue_work(&sdata->local->hw, &sdata->cleanup_stations_wk); } /* protected by RCU */ @@ -310,7 +333,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, spin_lock_init(&sta->lock); INIT_WORK(&sta->drv_unblock_wk, sta_unblock); - INIT_WORK(&sta->free_sta_wk, free_sta_work); INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); mutex_init(&sta->ampdu_mlme.mtx); @@ -862,7 +884,7 @@ void sta_info_init(struct ieee80211_local *local) void sta_info_stop(struct ieee80211_local *local) { - del_timer(&local->sta_cleanup); + del_timer_sync(&local->sta_cleanup); sta_info_flush(local, NULL); } @@ -891,6 +913,20 @@ int sta_info_flush(struct ieee80211_local *local, } mutex_unlock(&local->sta_mtx); + rcu_barrier(); + + if (sdata) { + ieee80211_cleanup_sdata_stas(sdata); + cancel_work_sync(&sdata->cleanup_stations_wk); + } else { + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { + ieee80211_cleanup_sdata_stas(sdata); + cancel_work_sync(&sdata->cleanup_stations_wk); + } + mutex_unlock(&local->iflist_mtx); + } + return ret; } diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 1489bca9ea9..37c1889afd3 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -299,7 +299,6 @@ struct sta_info { spinlock_t lock; struct work_struct drv_unblock_wk; - struct work_struct free_sta_wk; u16 listen_interval; @@ -563,4 +562,6 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta); void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); +void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata); + #endif /* STA_INFO_H */ diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 1915ffe598e..507b5e84fbd 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -555,7 +555,7 @@ EXPORT_SYMBOL_GPL(rpc_clone_client); * rpc_clone_client_set_auth - Clone an RPC client structure and set its auth * * @clnt: RPC client whose parameters are copied - * @auth: security flavor for new client + * @flavor: security flavor for new client * * Returns a fresh RPC client or an ERR_PTR. */ diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index b4133bd1391..bfa31714581 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -972,8 +972,7 @@ static void rpc_async_release(struct work_struct *work) static void rpc_release_resources_task(struct rpc_task *task) { - if (task->tk_rqstp) - xprt_release(task); + xprt_release(task); if (task->tk_msg.rpc_cred) { put_rpccred(task->tk_msg.rpc_cred); task->tk_msg.rpc_cred = NULL; diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index bd462a532ac..33811db8788 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -1136,10 +1136,18 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) void xprt_release(struct rpc_task *task) { struct rpc_xprt *xprt; - struct rpc_rqst *req; + struct rpc_rqst *req = task->tk_rqstp; - if (!(req = task->tk_rqstp)) + if (req == NULL) { + if (task->tk_client) { + rcu_read_lock(); + xprt = rcu_dereference(task->tk_client->cl_xprt); + if (xprt->snd_task == task) + xprt_release_write(xprt, task); + rcu_read_unlock(); + } return; + } xprt = req->rq_xprt; if (task->tk_ops->rpc_count_stats != NULL) diff --git a/net/wireless/core.c b/net/wireless/core.c index 14d99040035..b677eab55b6 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -866,8 +866,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, /* allow mac80211 to determine the timeout */ wdev->ps_timeout = -1; - if (!dev->ethtool_ops) - dev->ethtool_ops = &cfg80211_ethtool_ops; + netdev_set_default_ethtool_ops(dev, &cfg80211_ethtool_ops); if ((wdev->iftype == NL80211_IFTYPE_STATION || wdev->iftype == NL80211_IFTYPE_P2P_CLIENT || diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 19ecc8de9e6..d794abcc4b3 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -215,7 +215,9 @@ static void devcgroup_css_free(struct cgroup *cgroup) struct dev_cgroup *dev_cgroup; dev_cgroup = cgroup_to_devcgroup(cgroup); + mutex_lock(&devcgroup_mutex); dev_exception_clean(dev_cgroup); + mutex_unlock(&devcgroup_mutex); kfree(dev_cgroup); } diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index dfb26918699..7dd538ef5b8 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -205,9 +205,9 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name, rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM, &xattr_data, sizeof(xattr_data), 0); - } - else if (rc == -ENODATA) + } else if (rc == -ENODATA && inode->i_op->removexattr) { rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM); + } return rc; } diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 6fc0ae90e5b..fff7753e35c 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -18,6 +18,7 @@ #include <linux/delay.h> #include <linux/module.h> #include <linux/io.h> +#include <linux/gpio.h> #include <sound/ac97_codec.h> #include <sound/pxa2xx-lib.h> @@ -148,6 +149,8 @@ static inline void pxa_ac97_warm_pxa27x(void) static inline void pxa_ac97_cold_pxa27x(void) { + unsigned int timeout; + GCR &= GCR_COLD_RST; /* clear everything but nCRST */ GCR &= ~GCR_COLD_RST; /* then assert nCRST */ @@ -157,8 +160,10 @@ static inline void pxa_ac97_cold_pxa27x(void) clk_enable(ac97conf_clk); udelay(5); clk_disable(ac97conf_clk); - GCR = GCR_COLD_RST; - udelay(50); + GCR = GCR_COLD_RST | GCR_WARM_RST; + timeout = 100; /* wait for the codec-ready bit to be set */ + while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) + mdelay(1); } #endif @@ -340,8 +345,21 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev) } if (cpu_is_pxa27x()) { - /* Use GPIO 113 as AC97 Reset on Bulverde */ + /* + * This gpio is needed for a work-around to a bug in the ac97 + * controller during warm reset. The direction and level is set + * here so that it is an output driven high when switching from + * AC97_nRESET alt function to generic gpio. + */ + ret = gpio_request_one(reset_gpio, GPIOF_OUT_INIT_HIGH, + "pxa27x ac97 reset"); + if (ret < 0) { + pr_err("%s: gpio_request_one() failed: %d\n", + __func__, ret); + goto err_conf; + } pxa27x_assert_ac97reset(reset_gpio, 0); + ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); if (IS_ERR(ac97conf_clk)) { ret = PTR_ERR(ac97conf_clk); @@ -384,6 +402,8 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe); void pxa2xx_ac97_hw_remove(struct platform_device *dev) { + if (cpu_is_pxa27x()) + gpio_free(reset_gpio); GCR |= GCR_ACLINK_OFF; free_irq(IRQ_AC97, NULL); if (ac97conf_clk) { diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index b8fb0a5adb9..822df971972 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3654,6 +3654,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) hda_set_power_state(codec, AC_PWRST_D0); restore_shutup_pins(codec); hda_exec_init_verbs(codec); + snd_hda_jack_set_dirty_all(codec); if (codec->patch_ops.resume) codec->patch_ops.resume(codec); else { @@ -3665,10 +3666,8 @@ static void hda_call_codec_resume(struct hda_codec *codec) if (codec->jackpoll_interval) hda_jackpoll_work(&codec->jackpoll_work.work); - else { - snd_hda_jack_set_dirty_all(codec); + else snd_hda_jack_report_sync(codec); - } codec->in_pm = 0; snd_hda_power_down(codec); /* flag down before returning */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index cca87277baf..0b6aebacc56 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -573,9 +573,12 @@ enum { #define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */ /* quirks for Intel PCH */ -#define AZX_DCAPS_INTEL_PCH \ +#define AZX_DCAPS_INTEL_PCH_NOPM \ (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \ - AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME) + AZX_DCAPS_COUNT_LPIB_DELAY) + +#define AZX_DCAPS_INTEL_PCH \ + (AZX_DCAPS_INTEL_PCH_NOPM | AZX_DCAPS_PM_RUNTIME) /* quirks for ATI SB / AMD Hudson */ #define AZX_DCAPS_PRESET_ATI_SB \ @@ -3586,13 +3589,13 @@ static void azx_remove(struct pci_dev *pci) static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* CPT */ { PCI_DEVICE(0x8086, 0x1c20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, /* PBG */ { PCI_DEVICE(0x8086, 0x1d20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, /* Panther Point */ { PCI_DEVICE(0x8086, 0x1e20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, /* Lynx Point */ { PCI_DEVICE(0x8086, 0x8c20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 60890bfecc1..009b77a693c 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -558,24 +558,12 @@ static int conexant_build_controls(struct hda_codec *codec) return 0; } -#ifdef CONFIG_PM -static int conexant_suspend(struct hda_codec *codec) -{ - snd_hda_shutup_pins(codec); - return 0; -} -#endif - static const struct hda_codec_ops conexant_patch_ops = { .build_controls = conexant_build_controls, .build_pcms = conexant_build_pcms, .init = conexant_init, .free = conexant_free, .set_power_state = conexant_set_power, -#ifdef CONFIG_PM - .suspend = conexant_suspend, -#endif - .reboot_notify = snd_hda_shutup_pins, }; #ifdef CONFIG_SND_HDA_INPUT_BEEP @@ -4405,10 +4393,6 @@ static const struct hda_codec_ops cx_auto_patch_ops = { .init = cx_auto_init, .free = conexant_free, .unsol_event = snd_hda_jack_unsol_event, -#ifdef CONFIG_PM - .suspend = conexant_suspend, -#endif - .reboot_notify = snd_hda_shutup_pins, }; /* @@ -4652,6 +4636,12 @@ static const struct hda_codec_preset snd_hda_preset_conexant[] = { .patch = patch_conexant_auto }, { .id = 0x14f15111, .name = "CX20753/4", .patch = patch_conexant_auto }, + { .id = 0x14f15113, .name = "CX20755", + .patch = patch_conexant_auto }, + { .id = 0x14f15114, .name = "CX20756", + .patch = patch_conexant_auto }, + { .id = 0x14f15115, .name = "CX20757", + .patch = patch_conexant_auto }, {} /* terminator */ }; @@ -4675,6 +4665,9 @@ MODULE_ALIAS("snd-hda-codec-id:14f150b9"); MODULE_ALIAS("snd-hda-codec-id:14f1510f"); MODULE_ALIAS("snd-hda-codec-id:14f15110"); MODULE_ALIAS("snd-hda-codec-id:14f15111"); +MODULE_ALIAS("snd-hda-codec-id:14f15113"); +MODULE_ALIAS("snd-hda-codec-id:14f15114"); +MODULE_ALIAS("snd-hda-codec-id:14f15115"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Conexant HD-audio codec"); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index b6c21ea187c..807a2aa1ff3 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1502,7 +1502,7 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); substream = snd_pcm_chmap_substream(info, ctl_idx); if (!substream || !substream->runtime) - return -EBADFD; + return 0; /* just for avoiding error from alsactl restore */ switch (substream->runtime->status->state) { case SNDRV_PCM_STATE_OPEN: case SNDRV_PCM_STATE_SETUP: diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 71ae23dd710..cf388617110 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5817,6 +5817,9 @@ enum { ALC269_TYPE_ALC269VB, ALC269_TYPE_ALC269VC, ALC269_TYPE_ALC269VD, + ALC269_TYPE_ALC280, + ALC269_TYPE_ALC282, + ALC269_TYPE_ALC284, }; /* @@ -5833,10 +5836,13 @@ static int alc269_parse_auto_config(struct hda_codec *codec) switch (spec->codec_variant) { case ALC269_TYPE_ALC269VA: case ALC269_TYPE_ALC269VC: + case ALC269_TYPE_ALC280: + case ALC269_TYPE_ALC284: ssids = alc269va_ssids; break; case ALC269_TYPE_ALC269VB: case ALC269_TYPE_ALC269VD: + case ALC269_TYPE_ALC282: ssids = alc269_ssids; break; default: @@ -6245,6 +6251,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED), SND_PCI_QUIRK(0x103c, 0x1972, "HP Pavilion 17", ALC269_FIXUP_MIC1_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x1977, "HP Pavilion 14", ALC269_FIXUP_MIC1_MUTE_LED), SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_DMIC), SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), @@ -6259,6 +6266,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), + 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_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC), SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), @@ -6400,7 +6408,8 @@ static int patch_alc269(struct hda_codec *codec) alc_auto_parse_customize_define(codec); - if (codec->vendor_id == 0x10ec0269) { + switch (codec->vendor_id) { + case 0x10ec0269: spec->codec_variant = ALC269_TYPE_ALC269VA; switch (alc_get_coef0(codec) & 0x00f0) { case 0x0010: @@ -6425,6 +6434,20 @@ static int patch_alc269(struct hda_codec *codec) goto error; spec->init_hook = alc269_fill_coef; alc269_fill_coef(codec); + break; + + case 0x10ec0280: + case 0x10ec0290: + spec->codec_variant = ALC269_TYPE_ALC280; + break; + case 0x10ec0282: + case 0x10ec0283: + spec->codec_variant = ALC269_TYPE_ALC282; + break; + case 0x10ec0284: + case 0x10ec0292: + spec->codec_variant = ALC269_TYPE_ALC284; + break; } /* automatic parse from the BIOS config */ @@ -7129,6 +7152,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 }, { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 }, + { .id = 0x10ec0284, .name = "ALC284", .patch = patch_alc269 }, { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 }, { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 }, { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 6e02e064d7b..223c3d9cc69 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -441,6 +441,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); */ /* status */ #define HDSPM_AES32_wcLock 0x0200000 +#define HDSPM_AES32_wcSync 0x0100000 #define HDSPM_AES32_wcFreq_bit 22 /* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function HDSPM_bit2freq */ @@ -3467,10 +3468,12 @@ static int hdspm_wc_sync_check(struct hdspm *hdspm) switch (hdspm->io_type) { case AES32: status = hdspm_read(hdspm, HDSPM_statusRegister); - if (status & HDSPM_wcSync) - return 2; - else if (status & HDSPM_wcLock) - return 1; + if (status & HDSPM_AES32_wcLock) { + if (status & HDSPM_AES32_wcSync) + return 2; + else + return 1; + } return 0; break; @@ -4658,6 +4661,7 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, unsigned int status; unsigned int status2; unsigned int timecode; + unsigned int wcLock, wcSync; int pref_syncref; char *autosync_ref; int x; @@ -4751,8 +4755,11 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, snd_iprintf(buffer, "--- Status:\n"); + wcLock = status & HDSPM_AES32_wcLock; + wcSync = wcLock && (status & HDSPM_AES32_wcSync); + snd_iprintf(buffer, "Word: %s Frequency: %d\n", - (status & HDSPM_AES32_wcLock) ? "Sync " : "No Lock", + (wcLock) ? (wcSync ? "Sync " : "Lock ") : "No Lock", HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF)); for (x = 0; x < 8; x++) { diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index adf397b9d0e..1d8bb591759 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -446,15 +446,9 @@ static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_DSP_A: mode = 0; break; - case SND_SOC_DAIFMT_DSP_B: - mode = 1; - break; case SND_SOC_DAIFMT_I2S: mode = 2; break; - case SND_SOC_DAIFMT_LEFT_J: - mode = 3; - break; default: arizona_aif_err(dai, "Unsupported DAI format %d\n", fmt & SND_SOC_DAIFMT_FORMAT_MASK); @@ -714,7 +708,8 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1, ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val); snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, - ARIZONA_AIF1_RATE_MASK, 8); + ARIZONA_AIF1_RATE_MASK, + 8 << ARIZONA_AIF1_RATE_SHIFT); break; default: arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk); diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 41dae1ed3b7..4deebeb0717 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -34,15 +34,15 @@ #define ARIZONA_FLL_SRC_MCLK1 0 #define ARIZONA_FLL_SRC_MCLK2 1 -#define ARIZONA_FLL_SRC_SLIMCLK 2 -#define ARIZONA_FLL_SRC_FLL1 3 -#define ARIZONA_FLL_SRC_FLL2 4 -#define ARIZONA_FLL_SRC_AIF1BCLK 5 -#define ARIZONA_FLL_SRC_AIF2BCLK 6 -#define ARIZONA_FLL_SRC_AIF3BCLK 7 -#define ARIZONA_FLL_SRC_AIF1LRCLK 8 -#define ARIZONA_FLL_SRC_AIF2LRCLK 9 -#define ARIZONA_FLL_SRC_AIF3LRCLK 10 +#define ARIZONA_FLL_SRC_SLIMCLK 3 +#define ARIZONA_FLL_SRC_FLL1 4 +#define ARIZONA_FLL_SRC_FLL2 5 +#define ARIZONA_FLL_SRC_AIF1BCLK 8 +#define ARIZONA_FLL_SRC_AIF2BCLK 9 +#define ARIZONA_FLL_SRC_AIF3BCLK 10 +#define ARIZONA_FLL_SRC_AIF1LRCLK 12 +#define ARIZONA_FLL_SRC_AIF2LRCLK 13 +#define ARIZONA_FLL_SRC_AIF3LRCLK 14 #define ARIZONA_MIXER_VOL_MASK 0x00FE #define ARIZONA_MIXER_VOL_SHIFT 1 diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 4f1127935fd..ac8742a1f25 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -474,16 +474,16 @@ static int cs4271_probe(struct snd_soc_codec *codec) struct cs4271_platform_data *cs4271plat = codec->dev->platform_data; int ret; int gpio_nreset = -EINVAL; - int amutec_eq_bmutec = 0; + bool amutec_eq_bmutec = false; #ifdef CONFIG_OF if (of_match_device(cs4271_dt_ids, codec->dev)) { gpio_nreset = of_get_named_gpio(codec->dev->of_node, "reset-gpio", 0); - if (!of_get_property(codec->dev->of_node, + if (of_get_property(codec->dev->of_node, "cirrus,amutec-eq-bmutec", NULL)) - amutec_eq_bmutec = 1; + amutec_eq_bmutec = true; } #endif diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 99bb1c69499..9811a5478c8 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -737,7 +737,7 @@ static const struct cs42l52_clk_para clk_map_table[] = { static int cs42l52_get_clk(int mclk, int rate) { - int i, ret = 0; + int i, ret = -EINVAL; u_int mclk1, mclk2 = 0; for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) { @@ -749,8 +749,6 @@ static int cs42l52_get_clk(int mclk, int rate) } } } - if (ret > ARRAY_SIZE(clk_map_table)) - return -EINVAL; return ret; } diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index d75257d40a4..e19490cfb3a 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -111,9 +111,9 @@ static struct reg_default lm49453_reg_defs[] = { { 101, 0x00 }, { 102, 0x00 }, { 103, 0x01 }, - { 105, 0x01 }, - { 106, 0x00 }, - { 107, 0x01 }, + { 104, 0x01 }, + { 105, 0x00 }, + { 106, 0x01 }, { 107, 0x00 }, { 108, 0x00 }, { 109, 0x00 }, @@ -163,56 +163,25 @@ static struct reg_default lm49453_reg_defs[] = { { 184, 0x00 }, { 185, 0x00 }, { 186, 0x00 }, - { 189, 0x00 }, + { 187, 0x00 }, { 188, 0x00 }, - { 194, 0x00 }, - { 195, 0x00 }, - { 196, 0x00 }, - { 197, 0x00 }, - { 200, 0x00 }, - { 201, 0x00 }, - { 202, 0x00 }, - { 203, 0x00 }, - { 204, 0x00 }, - { 205, 0x00 }, - { 208, 0x00 }, + { 189, 0x00 }, + { 208, 0x06 }, { 209, 0x00 }, - { 210, 0x00 }, - { 211, 0x00 }, - { 213, 0x00 }, - { 214, 0x00 }, - { 215, 0x00 }, - { 216, 0x00 }, - { 217, 0x00 }, - { 218, 0x00 }, - { 219, 0x00 }, + { 210, 0x08 }, + { 211, 0x54 }, + { 212, 0x14 }, + { 213, 0x0d }, + { 214, 0x0d }, + { 215, 0x14 }, + { 216, 0x60 }, { 221, 0x00 }, { 222, 0x00 }, + { 223, 0x00 }, { 224, 0x00 }, - { 225, 0x00 }, - { 226, 0x00 }, - { 227, 0x00 }, - { 228, 0x00 }, - { 229, 0x00 }, - { 230, 0x13 }, - { 231, 0x00 }, - { 232, 0x80 }, - { 233, 0x0C }, - { 234, 0xDD }, - { 235, 0x00 }, - { 236, 0x04 }, - { 237, 0x00 }, - { 238, 0x00 }, - { 239, 0x00 }, - { 240, 0x00 }, - { 241, 0x00 }, - { 242, 0x00 }, - { 243, 0x00 }, - { 244, 0x00 }, - { 245, 0x00 }, { 248, 0x00 }, { 249, 0x00 }, - { 254, 0x00 }, + { 250, 0x00 }, { 255, 0x00 }, }; @@ -525,36 +494,41 @@ SOC_DAPM_SINGLE("Port2_2 Switch", LM49453_P0_PORT2_TX2_REG, 7, 1, 0), }; /* TLV Declarations */ -static const DECLARE_TLV_DB_SCALE(digital_tlv, -7650, 150, 1); -static const DECLARE_TLV_DB_SCALE(port_tlv, 0, 600, 0); +static const DECLARE_TLV_DB_SCALE(adc_dac_tlv, -7650, 150, 1); +static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 200, 1); +static const DECLARE_TLV_DB_SCALE(port_tlv, -1800, 600, 0); +static const DECLARE_TLV_DB_SCALE(stn_tlv, -7200, 150, 0); static const struct snd_kcontrol_new lm49453_sidetone_mixer_controls[] = { /* Sidetone supports mono only */ SOC_DAPM_SINGLE_TLV("Sidetone ADCL Volume", LM49453_P0_STN_VOL_ADCL_REG, - 0, 0x3F, 0, digital_tlv), + 0, 0x3F, 0, stn_tlv), SOC_DAPM_SINGLE_TLV("Sidetone ADCR Volume", LM49453_P0_STN_VOL_ADCR_REG, - 0, 0x3F, 0, digital_tlv), + 0, 0x3F, 0, stn_tlv), SOC_DAPM_SINGLE_TLV("Sidetone DMIC1L Volume", LM49453_P0_STN_VOL_DMIC1L_REG, - 0, 0x3F, 0, digital_tlv), + 0, 0x3F, 0, stn_tlv), SOC_DAPM_SINGLE_TLV("Sidetone DMIC1R Volume", LM49453_P0_STN_VOL_DMIC1R_REG, - 0, 0x3F, 0, digital_tlv), + 0, 0x3F, 0, stn_tlv), SOC_DAPM_SINGLE_TLV("Sidetone DMIC2L Volume", LM49453_P0_STN_VOL_DMIC2L_REG, - 0, 0x3F, 0, digital_tlv), + 0, 0x3F, 0, stn_tlv), SOC_DAPM_SINGLE_TLV("Sidetone DMIC2R Volume", LM49453_P0_STN_VOL_DMIC2R_REG, - 0, 0x3F, 0, digital_tlv), + 0, 0x3F, 0, stn_tlv), }; static const struct snd_kcontrol_new lm49453_snd_controls[] = { /* mic1 and mic2 supports mono only */ - SOC_SINGLE_TLV("Mic1 Volume", LM49453_P0_ADC_LEVELL_REG, 0, 6, - 0, digital_tlv), - SOC_SINGLE_TLV("Mic2 Volume", LM49453_P0_ADC_LEVELR_REG, 0, 6, - 0, digital_tlv), + SOC_SINGLE_TLV("Mic1 Volume", LM49453_P0_MICL_REG, 0, 15, 0, mic_tlv), + SOC_SINGLE_TLV("Mic2 Volume", LM49453_P0_MICR_REG, 0, 15, 0, mic_tlv), + + SOC_SINGLE_TLV("ADCL Volume", LM49453_P0_ADC_LEVELL_REG, 0, 63, + 0, adc_dac_tlv), + SOC_SINGLE_TLV("ADCR Volume", LM49453_P0_ADC_LEVELR_REG, 0, 63, + 0, adc_dac_tlv), SOC_DOUBLE_R_TLV("DMIC1 Volume", LM49453_P0_DMIC1_LEVELL_REG, - LM49453_P0_DMIC1_LEVELR_REG, 0, 6, 0, digital_tlv), + LM49453_P0_DMIC1_LEVELR_REG, 0, 63, 0, adc_dac_tlv), SOC_DOUBLE_R_TLV("DMIC2 Volume", LM49453_P0_DMIC2_LEVELL_REG, - LM49453_P0_DMIC2_LEVELR_REG, 0, 6, 0, digital_tlv), + LM49453_P0_DMIC2_LEVELR_REG, 0, 63, 0, adc_dac_tlv), SOC_DAPM_ENUM("Mic2Mode", lm49453_mic2mode_enum), SOC_DAPM_ENUM("DMIC12 SRC", lm49453_dmic12_cfg_enum), @@ -569,16 +543,16 @@ static const struct snd_kcontrol_new lm49453_snd_controls[] = { 2, 1, 0), SOC_DOUBLE_R_TLV("DAC HP Volume", LM49453_P0_DAC_HP_LEVELL_REG, - LM49453_P0_DAC_HP_LEVELR_REG, 0, 6, 0, digital_tlv), + LM49453_P0_DAC_HP_LEVELR_REG, 0, 63, 0, adc_dac_tlv), SOC_DOUBLE_R_TLV("DAC LO Volume", LM49453_P0_DAC_LO_LEVELL_REG, - LM49453_P0_DAC_LO_LEVELR_REG, 0, 6, 0, digital_tlv), + LM49453_P0_DAC_LO_LEVELR_REG, 0, 63, 0, adc_dac_tlv), SOC_DOUBLE_R_TLV("DAC LS Volume", LM49453_P0_DAC_LS_LEVELL_REG, - LM49453_P0_DAC_LS_LEVELR_REG, 0, 6, 0, digital_tlv), + LM49453_P0_DAC_LS_LEVELR_REG, 0, 63, 0, adc_dac_tlv), SOC_DOUBLE_R_TLV("DAC HA Volume", LM49453_P0_DAC_HA_LEVELL_REG, - LM49453_P0_DAC_HA_LEVELR_REG, 0, 6, 0, digital_tlv), + LM49453_P0_DAC_HA_LEVELR_REG, 0, 63, 0, adc_dac_tlv), SOC_SINGLE_TLV("EP Volume", LM49453_P0_DAC_LS_LEVELL_REG, - 0, 6, 0, digital_tlv), + 0, 63, 0, adc_dac_tlv), SOC_SINGLE_TLV("PORT1_1_RX_LVL Volume", LM49453_P0_PORT1_RX_LVL1_REG, 0, 3, 0, port_tlv), @@ -1218,7 +1192,7 @@ static int lm49453_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) } snd_soc_update_bits(codec, LM49453_P0_AUDIO_PORT1_BASIC_REG, - LM49453_AUDIO_PORT1_BASIC_FMT_MASK|BIT(1)|BIT(5), + LM49453_AUDIO_PORT1_BASIC_FMT_MASK|BIT(0)|BIT(5), (aif_val | mode | clk_phase)); snd_soc_write(codec, LM49453_P0_AUDIO_PORT1_RX_MSB_REG, clk_shift); diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index cb1675cd8e1..92bbfec9b10 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -401,7 +401,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { 5, 1, 0), SOC_SINGLE_TLV("Mic Volume", SGTL5000_CHIP_MIC_CTRL, - 0, 4, 0, mic_gain_tlv), + 0, 3, 0, mic_gain_tlv), }; /* mute the codec used by alsa core */ @@ -1344,7 +1344,7 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) SGTL5000_HP_ZCD_EN | SGTL5000_ADC_ZCD_EN); - snd_soc_write(codec, SGTL5000_CHIP_MIC_CTRL, 0); + snd_soc_write(codec, SGTL5000_CHIP_MIC_CTRL, 2); /* * disable DAP diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index ab355c4f0b2..40c07be9b58 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -74,9 +74,10 @@ SNDRV_PCM_FMTBIT_S32_LE) #define S2PC_VALUE 0x98 #define CLOCK_OUT 0x60 -#define LEFT_J_DATA_FORMAT 0x10 -#define I2S_DATA_FORMAT 0x12 -#define RIGHT_J_DATA_FORMAT 0x14 +#define DATA_FORMAT_MSK 0x0E +#define LEFT_J_DATA_FORMAT 0x00 +#define I2S_DATA_FORMAT 0x02 +#define RIGHT_J_DATA_FORMAT 0x04 #define CODEC_MUTE_VAL 0x80 #define POWER_CNTLMSAK 0x40 @@ -289,7 +290,7 @@ static int sta529_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) return -EINVAL; } - snd_soc_update_bits(codec, STA529_S2PCFG0, 0x0D, mode); + snd_soc_update_bits(codec, STA529_S2PCFG0, DATA_FORMAT_MSK, mode); return 0; } diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 1cbe88f01d6..12bcae63a7f 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -209,9 +209,9 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) ret = wm2000_read(i2c, WM2000_REG_SPEECH_CLARITY); if (wm2000->speech_clarity) - ret &= ~WM2000_SPEECH_CLARITY; - else ret |= WM2000_SPEECH_CLARITY; + else + ret &= ~WM2000_SPEECH_CLARITY; wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, ret); wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33); diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index afcf31df77e..e6cefe1ac67 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1566,15 +1566,9 @@ static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_DSP_A: fmt_val = 0; break; - case SND_SOC_DAIFMT_DSP_B: - fmt_val = 1; - break; case SND_SOC_DAIFMT_I2S: fmt_val = 2; break; - case SND_SOC_DAIFMT_LEFT_J: - fmt_val = 3; - break; default: dev_err(codec->dev, "Unsupported DAI format %d\n", fmt & SND_SOC_DAIFMT_FORMAT_MASK); @@ -1626,7 +1620,7 @@ static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV, lrclk); snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5, - WM2200_AIF1_FMT_MASK << 1, fmt_val << 1); + WM2200_AIF1_FMT_MASK, fmt_val); return 0; } diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 5a5f3693623..54397a50807 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -1279,15 +1279,9 @@ static int wm5100_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_DSP_A: mask = 0; break; - case SND_SOC_DAIFMT_DSP_B: - mask = 1; - break; case SND_SOC_DAIFMT_I2S: mask = 2; break; - case SND_SOC_DAIFMT_LEFT_J: - mask = 3; - break; default: dev_err(codec->dev, "Unsupported DAI format %d\n", fmt & SND_SOC_DAIFMT_FORMAT_MASK); diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 688ade08058..7a9048dad1c 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -36,6 +36,9 @@ struct wm5102_priv { struct arizona_priv core; struct arizona_fll fll[2]; + + unsigned int spk_ena:2; + unsigned int spk_ena_pending:1; }; static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); @@ -787,6 +790,47 @@ ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), }; +static int wm5102_spk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_codec *codec = w->codec; + struct arizona *arizona = dev_get_drvdata(codec->dev->parent); + struct wm5102_priv *wm5102 = snd_soc_codec_get_drvdata(codec); + + if (arizona->rev < 1) + return 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (!wm5102->spk_ena) { + snd_soc_write(codec, 0x4f5, 0x25a); + wm5102->spk_ena_pending = true; + } + break; + case SND_SOC_DAPM_POST_PMU: + if (wm5102->spk_ena_pending) { + msleep(75); + snd_soc_write(codec, 0x4f5, 0xda); + wm5102->spk_ena_pending = false; + wm5102->spk_ena++; + } + break; + case SND_SOC_DAPM_PRE_PMD: + wm5102->spk_ena--; + if (!wm5102->spk_ena) + snd_soc_write(codec, 0x4f5, 0x25a); + break; + case SND_SOC_DAPM_POST_PMD: + if (!wm5102->spk_ena) + snd_soc_write(codec, 0x4f5, 0x0da); + break; + } + + return 0; +} + + ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE); @@ -1034,10 +1078,10 @@ SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1, - ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1, - ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index ffc89fab96f..7b198c38f3e 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -169,6 +169,7 @@ static int wm_adsp_load(struct wm_adsp *dsp) const struct wm_adsp_region *mem; const char *region_name; char *file, *text; + void *buf; unsigned int reg; int regions = 0; int ret, offset, type, sizes; @@ -322,8 +323,18 @@ static int wm_adsp_load(struct wm_adsp *dsp) } if (reg) { - ret = regmap_raw_write(regmap, reg, region->data, + buf = kmemdup(region->data, le32_to_cpu(region->len), + GFP_KERNEL); + if (!buf) { + adsp_err(dsp, "Out of memory\n"); + return -ENOMEM; + } + + ret = regmap_raw_write(regmap, reg, buf, le32_to_cpu(region->len)); + + kfree(buf); + if (ret != 0) { adsp_err(dsp, "%s.%d: Failed to write %d bytes at %d in %s: %d\n", @@ -359,6 +370,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) const char *region_name; int ret, pos, blocks, type, offset, reg; char *file; + void *buf; file = kzalloc(PAGE_SIZE, GFP_KERNEL); if (file == NULL) @@ -426,6 +438,13 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) } if (reg) { + buf = kmemdup(blk->data, le32_to_cpu(blk->len), + GFP_KERNEL); + if (!buf) { + adsp_err(dsp, "Out of memory\n"); + return -ENOMEM; + } + ret = regmap_raw_write(regmap, reg, blk->data, le32_to_cpu(blk->len)); if (ret != 0) { @@ -433,6 +452,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) "%s.%d: Failed to write to %x in %s\n", file, blocks, reg, region_name); } + + kfree(buf); } pos += le32_to_cpu(blk->len) + sizeof(*blk); diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index 3870e9678b5..15a3817aa5c 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c @@ -21,7 +21,6 @@ #include <sound/jack.h> #include <plat/regs-iis.h> -#include <mach/h1940-latch.h> #include <asm/mach-types.h> #include "s3c24xx-i2s.h" @@ -147,9 +146,9 @@ static int h1940_spk_power(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { if (SND_SOC_DAPM_EVENT_ON(event)) - gpio_set_value(H1940_LATCH_AUDIO_POWER, 1); + gpio_set_value(S3C_GPIO_END + 9, 1); else - gpio_set_value(H1940_LATCH_AUDIO_POWER, 0); + gpio_set_value(S3C_GPIO_END + 9, 0); return 0; } @@ -233,11 +232,11 @@ static int __init h1940_init(void) return -ENODEV; /* configure some gpios */ - ret = gpio_request(H1940_LATCH_AUDIO_POWER, "speaker-power"); + ret = gpio_request(S3C_GPIO_END + 9, "speaker-power"); if (ret) goto err_out; - ret = gpio_direction_output(H1940_LATCH_AUDIO_POWER, 0); + ret = gpio_direction_output(S3C_GPIO_END + 9, 0); if (ret) goto err_gpio; @@ -258,7 +257,7 @@ static int __init h1940_init(void) err_plat: platform_device_put(s3c24xx_snd_device); err_gpio: - gpio_free(H1940_LATCH_AUDIO_POWER); + gpio_free(S3C_GPIO_END + 9); err_out: return ret; @@ -269,7 +268,7 @@ static void __exit h1940_exit(void) platform_device_unregister(s3c24xx_snd_device); snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), hp_jack_gpios); - gpio_free(H1940_LATCH_AUDIO_POWER); + gpio_free(S3C_GPIO_END + 9); } module_init(h1940_init); diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index c7e965f80d2..a301d8cfaa3 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -237,7 +237,7 @@ static int lm4853_set_spk(struct snd_kcontrol *kcontrol, { gta02_speaker_enabled = ucontrol->value.integer.value[0]; - gpio_set_value(GTA02_GPIO_HP_IN, !gta02_speaker_enabled); + gpio_set_value(S3C2410_GPJ(2), !gta02_speaker_enabled); return 0; } @@ -252,7 +252,7 @@ static int lm4853_get_spk(struct snd_kcontrol *kcontrol, static int lm4853_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event)); + gpio_set_value(S3C2410_GPJ(1), SND_SOC_DAPM_EVENT_OFF(event)); return 0; } @@ -396,8 +396,8 @@ static struct snd_soc_codec_conf neo1973_codec_conf[] = { }; static const struct gpio neo1973_gta02_gpios[] = { - { GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" }, - { GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" }, + { S3C2410_GPJ(2), GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" }, + { S3C2410_GPJ(1), GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" }, }; static struct snd_soc_card neo1973 = { diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 91d592ff67b..2370063b582 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1255,6 +1255,8 @@ static int soc_post_component_init(struct snd_soc_card *card, INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients); ret = device_add(rtd->dev); if (ret < 0) { + /* calling put_device() here to free the rtd->dev */ + put_device(rtd->dev); dev_err(card->dev, "ASoC: failed to register runtime device: %d\n", ret); return ret; @@ -1554,7 +1556,7 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num) /* unregister the rtd device */ if (rtd->dev_registered) { device_remove_file(rtd->dev, &dev_attr_codec_reg); - device_del(rtd->dev); + device_unregister(rtd->dev); rtd->dev_registered = 0; } @@ -2917,7 +2919,7 @@ int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, platform_max = mc->platform_max; uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; + uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = platform_max - min; @@ -2941,12 +2943,14 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); unsigned int reg = mc->reg; + unsigned int rreg = mc->rreg; unsigned int shift = mc->shift; int min = mc->min; int max = mc->max; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; unsigned int val, val_mask; + int ret; val = ((ucontrol->value.integer.value[0] + min) & mask); if (invert) @@ -2954,7 +2958,21 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, val_mask = mask << shift; val = val << shift; - return snd_soc_update_bits_locked(codec, reg, val_mask, val); + ret = snd_soc_update_bits_locked(codec, reg, val_mask, val); + if (ret != 0) + return ret; + + if (snd_soc_volsw_is_stereo(mc)) { + val = ((ucontrol->value.integer.value[1] + min) & mask); + if (invert) + val = max - val; + val_mask = mask << shift; + val = val << shift; + + ret = snd_soc_update_bits_locked(codec, rreg, val_mask, val); + } + + return ret; } EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); @@ -2974,6 +2992,7 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); unsigned int reg = mc->reg; + unsigned int rreg = mc->rreg; unsigned int shift = mc->shift; int min = mc->min; int max = mc->max; @@ -2988,6 +3007,16 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] = ucontrol->value.integer.value[0] - min; + if (snd_soc_volsw_is_stereo(mc)) { + ucontrol->value.integer.value[1] = + (snd_soc_read(codec, rreg) >> shift) & mask; + if (invert) + ucontrol->value.integer.value[1] = + max - ucontrol->value.integer.value[1]; + ucontrol->value.integer.value[1] = + ucontrol->value.integer.value[1] - min; + } + return 0; } EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index d7711fce119..cf191e6aebb 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1243,6 +1243,7 @@ static int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) && (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) && (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)) continue; diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c index e71fe55cebe..0e2ed3d05c4 100644 --- a/sound/usb/mixer_maps.c +++ b/sound/usb/mixer_maps.c @@ -179,6 +179,15 @@ static struct usbmix_name_map audigy2nx_map[] = { { 0 } /* terminator */ }; +static struct usbmix_selector_map c400_selectors[] = { + { + .id = 0x80, + .count = 2, + .names = (const char*[]) {"Internal", "SPDIF"} + }, + { 0 } /* terminator */ +}; + static struct usbmix_selector_map audigy2nx_selectors[] = { { .id = 14, /* Capture Source */ @@ -367,6 +376,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { .map = hercules_usb51_map, }, { + .id = USB_ID(0x0763, 0x2030), + .selector_map = c400_selectors, + }, + { .id = USB_ID(0x08bb, 0x2702), .map = linex_map, .ignore_ctl_error = 1, diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 0422b1360af..15520de1df5 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -1206,7 +1206,7 @@ static int snd_c400_create_mixer(struct usb_mixer_interface *mixer) * are valid they presents mono controls as L and R channels of * stereo. So we provide a good mixer here. */ -struct std_mono_table ebox44_table[] = { +static struct std_mono_table ebox44_table[] = { { .unitid = 4, .control = 1, diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index c6593101c04..d82e378d37c 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -511,6 +511,16 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs) struct snd_usb_substream *sync_subs = &subs->stream->substream[subs->direction ^ 1]; + if (subs->sync_endpoint->type != SND_USB_ENDPOINT_TYPE_DATA || + !subs->stream) + return snd_usb_endpoint_set_params(subs->sync_endpoint, + subs->pcm_format, + subs->channels, + subs->period_bytes, + subs->cur_rate, + subs->cur_audiofmt, + NULL); + /* Try to find the best matching audioformat. */ list_for_each_entry(fp, &sync_subs->fmt_list, list) { int score = match_endpoint_audioformats(fp, subs->cur_audiofmt, diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 78e845ec65d..64d25a7a4d5 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2289,7 +2289,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100, 48000, 88200, 96000 }, - .clock = 0x81, + .clock = 0x80, } }, /* Capture */ @@ -2315,7 +2315,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100, 48000, 88200, 96000 }, - .clock = 0x81, + .clock = 0x80, } }, /* MIDI */ diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index acc12f004c2..2c971858d6b 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -387,11 +387,13 @@ static int snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev) * rules */ err = usb_driver_set_configuration(dev, 2); - if (err < 0) { + if (err < 0) snd_printdd("error usb_driver_set_configuration: %d\n", err); - return -ENODEV; - } + /* Always return an error, so that we stop creating a device + that will just be destroyed and recreated with a new + configuration */ + return -ENODEV; } else snd_printk(KERN_INFO "usb-audio: Fast Track Pro config OK\n"); @@ -859,6 +861,17 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) if ((le16_to_cpu(ep->chip->dev->descriptor.idVendor) == 0x23ba) && ep->type == SND_USB_ENDPOINT_TYPE_SYNC) ep->skip_packets = 4; + + /* + * M-Audio Fast Track C400 - when packets are not skipped, real world + * latency varies by approx. +/- 50 frames (at 96KHz) each time the + * stream is (re)started. When skipping packets 16 at endpoint start + * up, the real world latency is stable within +/- 1 frame (also + * across power cycles). + */ + if (ep->chip->usb_id == USB_ID(0x0763, 0x2030) && + ep->type == SND_USB_ENDPOINT_TYPE_DATA) + ep->skip_packets = 16; } void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index 80db3f4bcf7..39d41068484 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST @@ -11,11 +11,21 @@ lib/rbtree.c include/linux/swab.h arch/*/include/asm/unistd*.h arch/*/include/asm/perf_regs.h +arch/*/include/uapi/asm/unistd*.h +arch/*/include/uapi/asm/perf_regs.h arch/*/lib/memcpy*.S arch/*/lib/memset*.S include/linux/poison.h include/linux/magic.h include/linux/hw_breakpoint.h +include/linux/rbtree_augmented.h +include/uapi/linux/perf_event.h +include/uapi/linux/const.h +include/uapi/linux/swab.h +include/uapi/linux/hw_breakpoint.h arch/x86/include/asm/svm.h arch/x86/include/asm/vmx.h arch/x86/include/asm/kvm_host.h +arch/x86/include/uapi/asm/svm.h +arch/x86/include/uapi/asm/vmx.h +arch/x86/include/uapi/asm/kvm.h diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 891bc77bdb2..8ab05e543ef 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -58,7 +58,7 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ -e s/arm.*/arm/ -e s/sa110/arm/ \ -e s/s390x/s390/ -e s/parisc64/parisc/ \ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ - -e s/sh[234].*/sh/ ) + -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ ) NO_PERF_REGS := 1 CC = $(CROSS_COMPILE)gcc |