diff --git a/[refs] b/[refs] index 582ecaa6774b..45a1216153af 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 48944cc84db35e2e023c19a772dd52a7114e12cb +refs/heads/master: 85910c202bb869edd2bb9a6c217a658c83f06f1e diff --git a/trunk/Documentation/devicetree/bindings/arm/atmel-at91.txt b/trunk/Documentation/devicetree/bindings/arm/atmel-at91.txt index d187e9f7cf1c..ecc81e368715 100644 --- a/trunk/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/trunk/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -8,7 +8,7 @@ PIT Timer required properties: shared across all System Controller members. TC/TCLIB Timer required properties: -- compatible: Should be "atmel,-tcb". +- compatible: Should be "atmel,-pit". can be "at91rm9200" or "at91sam9x5" - reg: Should contain registers location and length - interrupts: Should contain all interrupts for the TC block diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index cb7d1a42f2cd..f39a82dc0260 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -637,13 +637,6 @@ W: http://www.arm.linux.org.uk/ S: Maintained F: arch/arm/ -ARM SUB-ARCHITECTURES -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -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 - ARM PRIMECELL AACI PL041 DRIVER M: Russell King S: Maintained @@ -5069,13 +5062,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git S: Odd Fixes F: drivers/net/ F: include/linux/if_* -F: include/linux/netdevice.h -F: include/linux/arcdevice.h -F: include/linux/etherdevice.h -F: include/linux/fcdevice.h -F: include/linux/fddidevice.h -F: include/linux/hippidevice.h -F: include/linux/inetdevice.h +F: include/linux/*device.h NETXEN (1/10) GbE SUPPORT M: Sony Chacko @@ -5647,7 +5634,7 @@ S: Maintained F: drivers/pinctrl/spear/ PKTCDVD DRIVER -M: Jiri Kosina +M: Peter Osterlund S: Maintained F: drivers/block/pktcdvd.c F: include/linux/pktcdvd.h diff --git a/trunk/Makefile b/trunk/Makefile index 42d0e56818ea..14c93b39b929 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 7 SUBLEVEL = 0 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc2 NAME = Terrified Chipmunk # *DOCUMENTATION* diff --git a/trunk/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/trunk/arch/arm/boot/dts/at91sam9g20ek_common.dtsi index e6391a4e6649..b06c0db273b1 100644 --- a/trunk/arch/arm/boot/dts/at91sam9g20ek_common.dtsi +++ b/trunk/arch/arm/boot/dts/at91sam9g20ek_common.dtsi @@ -126,14 +126,14 @@ #size-cells = <0>; btn3 { - label = "Button 3"; + label = "Buttin 3"; gpios = <&pioA 30 1>; linux,code = <0x103>; gpio-key,wakeup; }; btn4 { - label = "Button 4"; + label = "Buttin 4"; gpios = <&pioA 31 1>; linux,code = <0x104>; gpio-key,wakeup; diff --git a/trunk/arch/arm/boot/dts/dbx5x0.dtsi b/trunk/arch/arm/boot/dts/dbx5x0.dtsi index 4b0e0ca08f40..748ba7aa746c 100644 --- a/trunk/arch/arm/boot/dts/dbx5x0.dtsi +++ b/trunk/arch/arm/boot/dts/dbx5x0.dtsi @@ -483,8 +483,6 @@ compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell"; reg = <0x80004000 0x1000>; interrupts = <0 21 0x4>; - arm,primecell-periphid = <0x180024>; - #address-cells = <1>; #size-cells = <0>; v-i2c-supply = <&db8500_vape_reg>; @@ -496,8 +494,6 @@ compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell"; reg = <0x80122000 0x1000>; interrupts = <0 22 0x4>; - arm,primecell-periphid = <0x180024>; - #address-cells = <1>; #size-cells = <0>; v-i2c-supply = <&db8500_vape_reg>; @@ -509,8 +505,6 @@ compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell"; reg = <0x80128000 0x1000>; interrupts = <0 55 0x4>; - arm,primecell-periphid = <0x180024>; - #address-cells = <1>; #size-cells = <0>; v-i2c-supply = <&db8500_vape_reg>; @@ -522,8 +516,6 @@ compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell"; reg = <0x80110000 0x1000>; interrupts = <0 12 0x4>; - arm,primecell-periphid = <0x180024>; - #address-cells = <1>; #size-cells = <0>; v-i2c-supply = <&db8500_vape_reg>; @@ -535,8 +527,6 @@ compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell"; reg = <0x8012a000 0x1000>; interrupts = <0 51 0x4>; - arm,primecell-periphid = <0x180024>; - #address-cells = <1>; #size-cells = <0>; v-i2c-supply = <&db8500_vape_reg>; @@ -583,38 +573,33 @@ interrupts = <0 60 0x4>; status = "disabled"; }; - sdi@80118000 { compatible = "arm,pl18x", "arm,primecell"; reg = <0x80118000 0x1000>; interrupts = <0 50 0x4>; status = "disabled"; }; - sdi@80005000 { compatible = "arm,pl18x", "arm,primecell"; reg = <0x80005000 0x1000>; interrupts = <0 41 0x4>; status = "disabled"; }; - sdi@80119000 { compatible = "arm,pl18x", "arm,primecell"; reg = <0x80119000 0x1000>; interrupts = <0 59 0x4>; status = "disabled"; }; - sdi@80114000 { compatible = "arm,pl18x", "arm,primecell"; reg = <0x80114000 0x1000>; interrupts = <0 99 0x4>; status = "disabled"; }; - sdi@80008000 { compatible = "arm,pl18x", "arm,primecell"; - reg = <0x80008000 0x1000>; + reg = <0x80114000 0x1000>; interrupts = <0 100 0x4>; status = "disabled"; }; diff --git a/trunk/arch/arm/boot/dts/exynos4210-trats.dts b/trunk/arch/arm/boot/dts/exynos4210-trats.dts index a21511c14071..73567b843e72 100644 --- a/trunk/arch/arm/boot/dts/exynos4210-trats.dts +++ b/trunk/arch/arm/boot/dts/exynos4210-trats.dts @@ -20,10 +20,8 @@ compatible = "samsung,trats", "samsung,exynos4210"; memory { - reg = <0x40000000 0x10000000 - 0x50000000 0x10000000 - 0x60000000 0x10000000 - 0x70000000 0x10000000>; + reg = <0x40000000 0x20000000 + 0x60000000 0x20000000>; }; chosen { diff --git a/trunk/arch/arm/boot/dts/imx23.dtsi b/trunk/arch/arm/boot/dts/imx23.dtsi index 6d31aa383460..9ca4ca70c1bc 100644 --- a/trunk/arch/arm/boot/dts/imx23.dtsi +++ b/trunk/arch/arm/boot/dts/imx23.dtsi @@ -69,7 +69,6 @@ interrupts = <13>, <56>; interrupt-names = "gpmi-dma", "bch"; clocks = <&clks 34>; - clock-names = "gpmi_io"; fsl,gpmi-dma-channel = <4>; status = "disabled"; }; diff --git a/trunk/arch/arm/boot/dts/imx28.dtsi b/trunk/arch/arm/boot/dts/imx28.dtsi index 55c57ea6169e..e16d63155480 100644 --- a/trunk/arch/arm/boot/dts/imx28.dtsi +++ b/trunk/arch/arm/boot/dts/imx28.dtsi @@ -85,7 +85,6 @@ interrupts = <88>, <41>; interrupt-names = "gpmi-dma", "bch"; clocks = <&clks 50>; - clock-names = "gpmi_io"; fsl,gpmi-dma-channel = <4>; status = "disabled"; }; diff --git a/trunk/arch/arm/boot/dts/omap3.dtsi b/trunk/arch/arm/boot/dts/omap3.dtsi index 696e929d0304..f38ea8771b44 100644 --- a/trunk/arch/arm/boot/dts/omap3.dtsi +++ b/trunk/arch/arm/boot/dts/omap3.dtsi @@ -257,7 +257,7 @@ interrupt-names = "common", "tx", "rx", "sidetone"; interrupt-parent = <&intc>; ti,buffer-size = <1280>; - ti,hwmods = "mcbsp2", "mcbsp2_sidetone"; + ti,hwmods = "mcbsp2"; }; mcbsp3: mcbsp@49024000 { @@ -272,7 +272,7 @@ interrupt-names = "common", "tx", "rx", "sidetone"; interrupt-parent = <&intc>; ti,buffer-size = <128>; - ti,hwmods = "mcbsp3", "mcbsp3_sidetone"; + ti,hwmods = "mcbsp3"; }; mcbsp4: mcbsp@49026000 { diff --git a/trunk/arch/arm/configs/imx_v6_v7_defconfig b/trunk/arch/arm/configs/imx_v6_v7_defconfig index 394ded624e37..66aa7a6db884 100644 --- a/trunk/arch/arm/configs/imx_v6_v7_defconfig +++ b/trunk/arch/arm/configs/imx_v6_v7_defconfig @@ -139,7 +139,6 @@ CONFIG_I2C_IMX=y CONFIG_SPI=y CONFIG_SPI_IMX=y CONFIG_GPIO_SYSFS=y -CONFIG_GPIO_MC9S08DZ60=y # CONFIG_HWMON is not set CONFIG_WATCHDOG=y CONFIG_IMX2_WDT=y @@ -156,7 +155,6 @@ CONFIG_SOC_CAMERA=y CONFIG_SOC_CAMERA_OV2640=y CONFIG_VIDEO_MX3=y CONFIG_FB=y -CONFIG_LCD_PLATFORM=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_L4F00242T03=y diff --git a/trunk/arch/arm/configs/mvebu_defconfig b/trunk/arch/arm/configs/mvebu_defconfig index 3458752c4bb2..7bcf850eddcd 100644 --- a/trunk/arch/arm/configs/mvebu_defconfig +++ b/trunk/arch/arm/configs/mvebu_defconfig @@ -1,6 +1,6 @@ CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y -CONFIG_IRQ_DOMAIN_DEBUG=y +CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y @@ -9,12 +9,10 @@ CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_ARCH_MVEBU=y -CONFIG_MACH_ARMADA_370=y -CONFIG_MACH_ARMADA_XP=y -# CONFIG_CACHE_L2X0 is not set +CONFIG_MACH_ARMADA_370_XP=y CONFIG_AEABI=y CONFIG_HIGHMEM=y -# CONFIG_COMPACTION is not set +CONFIG_USE_OF=y CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_ARM_APPENDED_DTB=y @@ -25,8 +23,6 @@ CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_OF_PLATFORM=y CONFIG_GPIOLIB=y CONFIG_GPIO_SYSFS=y -# CONFIG_USB_SUPPORT is not set -# CONFIG_IOMMU_SUPPORT is not set CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set diff --git a/trunk/arch/arm/configs/versatile_defconfig b/trunk/arch/arm/configs/versatile_defconfig index 2ba9e63d0f17..cdd4d2bd3962 100644 --- a/trunk/arch/arm/configs/versatile_defconfig +++ b/trunk/arch/arm/configs/versatile_defconfig @@ -1,4 +1,3 @@ -CONFIG_ARCH_VERSATILE=y CONFIG_EXPERIMENTAL=y # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SYSVIPC=y diff --git a/trunk/arch/arm/include/debug/8250_32.S b/trunk/arch/arm/include/debug/8250_32.S deleted file mode 100644 index 8db01eeabbb4..000000000000 --- a/trunk/arch/arm/include/debug/8250_32.S +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2011 Picochip Ltd., Jamie Iles - * - * 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. - * - * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit - * accesses to the 8250. - */ - -#include - - .macro senduart,rd,rx - str \rd, [\rx, #UART_TX << UART_SHIFT] - .endm - - .macro busyuart,rd,rx -1002: ldr \rd, [\rx, #UART_LSR << UART_SHIFT] - and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE - teq \rd, #UART_LSR_TEMT | UART_LSR_THRE - bne 1002b - .endm - - /* The UART's don't have any flow control IO's wired up. */ - .macro waituart,rd,rx - .endm diff --git a/trunk/arch/arm/include/debug/picoxcell.S b/trunk/arch/arm/include/debug/picoxcell.S index bc1f07c49cd4..7419deb1b948 100644 --- a/trunk/arch/arm/include/debug/picoxcell.S +++ b/trunk/arch/arm/include/debug/picoxcell.S @@ -5,7 +5,10 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * + * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit + * accesses to the 8250. */ +#include #define UART_SHIFT 2 #define PICOXCELL_UART1_BASE 0x80230000 @@ -16,4 +19,17 @@ ldr \rp, =PICOXCELL_UART1_BASE .endm -#include "8250_32.S" + .macro senduart,rd,rx + str \rd, [\rx, #UART_TX << UART_SHIFT] + .endm + + .macro busyuart,rd,rx +1002: ldr \rd, [\rx, #UART_LSR << UART_SHIFT] + and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE + teq \rd, #UART_LSR_TEMT | UART_LSR_THRE + bne 1002b + .endm + + /* The UART's don't have any flow control IO's wired up. */ + .macro waituart,rd,rx + .endm diff --git a/trunk/arch/arm/include/debug/socfpga.S b/trunk/arch/arm/include/debug/socfpga.S index 966b2f994946..d6f26d23374f 100644 --- a/trunk/arch/arm/include/debug/socfpga.S +++ b/trunk/arch/arm/include/debug/socfpga.S @@ -7,9 +7,6 @@ * published by the Free Software Foundation. */ -#define UART_SHIFT 2 -#define DEBUG_LL_UART_OFFSET 0x00002000 - .macro addruart, rp, rv, tmp mov \rp, #DEBUG_LL_UART_OFFSET orr \rp, \rp, #0x00c00000 @@ -17,5 +14,3 @@ orr \rp, \rp, #0xff000000 @ physical base .endm -#include "8250_32.S" - diff --git a/trunk/arch/arm/mach-at91/Kconfig b/trunk/arch/arm/mach-at91/Kconfig index 043624219b55..b14207101938 100644 --- a/trunk/arch/arm/mach-at91/Kconfig +++ b/trunk/arch/arm/mach-at91/Kconfig @@ -21,13 +21,19 @@ config SOC_AT91SAM9 bool select CPU_ARM926T select GENERIC_CLOCKEVENTS - select MULTI_IRQ_HANDLER - select SPARSE_IRQ menu "Atmel AT91 System-on-Chip" comment "Atmel AT91 Processor" +config SOC_AT91SAM9 + bool + select AT91_SAM9_SMC + select AT91_SAM9_TIME + select CPU_ARM926T + select MULTI_IRQ_HANDLER + select SPARSE_IRQ + config SOC_AT91RM9200 bool "AT91RM9200" select CPU_ARM920T diff --git a/trunk/arch/arm/mach-at91/at91rm9200.c b/trunk/arch/arm/mach-at91/at91rm9200.c index 5269825194a8..b4f0565aff63 100644 --- a/trunk/arch/arm/mach-at91/at91rm9200.c +++ b/trunk/arch/arm/mach-at91/at91rm9200.c @@ -187,7 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk), - CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200.0", &twi_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200", &twi_clk), /* fake hclk clock */ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk), CLKDEV_CON_ID("pioA", &pioA_clk), diff --git a/trunk/arch/arm/mach-at91/at91rm9200_devices.c b/trunk/arch/arm/mach-at91/at91rm9200_devices.c index 1e122bcd7845..a563189cdfc3 100644 --- a/trunk/arch/arm/mach-at91/at91rm9200_devices.c +++ b/trunk/arch/arm/mach-at91/at91rm9200_devices.c @@ -479,7 +479,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91rm9200_twi_device = { .name = "i2c-gpio", - .id = 0, + .id = -1, .dev.platform_data = &pdata, }; @@ -512,7 +512,7 @@ static struct resource twi_resources[] = { static struct platform_device at91rm9200_twi_device = { .name = "i2c-at91rm9200", - .id = 0, + .id = -1, .resource = twi_resources, .num_resources = ARRAY_SIZE(twi_resources), }; diff --git a/trunk/arch/arm/mach-at91/at91sam9260.c b/trunk/arch/arm/mach-at91/at91sam9260.c index f8202615f4a8..ad29f93f20ca 100644 --- a/trunk/arch/arm/mach-at91/at91sam9260.c +++ b/trunk/arch/arm/mach-at91/at91sam9260.c @@ -211,8 +211,8 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk), CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk), - CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk), - CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20", &twi_clk), /* more usart lookup table for DT entries */ CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck), CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk), diff --git a/trunk/arch/arm/mach-at91/at91sam9260_devices.c b/trunk/arch/arm/mach-at91/at91sam9260_devices.c index aa1e58729885..a76b8684f52d 100644 --- a/trunk/arch/arm/mach-at91/at91sam9260_devices.c +++ b/trunk/arch/arm/mach-at91/at91sam9260_devices.c @@ -389,7 +389,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9260_twi_device = { .name = "i2c-gpio", - .id = 0, + .id = -1, .dev.platform_data = &pdata, }; @@ -421,7 +421,7 @@ static struct resource twi_resources[] = { }; static struct platform_device at91sam9260_twi_device = { - .id = 0, + .id = -1, .resource = twi_resources, .num_resources = ARRAY_SIZE(twi_resources), }; diff --git a/trunk/arch/arm/mach-at91/at91sam9261.c b/trunk/arch/arm/mach-at91/at91sam9261.c index 04295c04b3e0..8d999eb1a137 100644 --- a/trunk/arch/arm/mach-at91/at91sam9261.c +++ b/trunk/arch/arm/mach-at91/at91sam9261.c @@ -178,8 +178,8 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk), CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0), - CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261.0", &twi_clk), - CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261", &twi_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10", &twi_clk), CLKDEV_CON_ID("pioA", &pioA_clk), CLKDEV_CON_ID("pioB", &pioB_clk), CLKDEV_CON_ID("pioC", &pioC_clk), diff --git a/trunk/arch/arm/mach-at91/at91sam9261_devices.c b/trunk/arch/arm/mach-at91/at91sam9261_devices.c index b9487696b7be..9752f17efba9 100644 --- a/trunk/arch/arm/mach-at91/at91sam9261_devices.c +++ b/trunk/arch/arm/mach-at91/at91sam9261_devices.c @@ -285,7 +285,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9261_twi_device = { .name = "i2c-gpio", - .id = 0, + .id = -1, .dev.platform_data = &pdata, }; @@ -317,7 +317,7 @@ static struct resource twi_resources[] = { }; static struct platform_device at91sam9261_twi_device = { - .id = 0, + .id = -1, .resource = twi_resources, .num_resources = ARRAY_SIZE(twi_resources), }; diff --git a/trunk/arch/arm/mach-at91/at91sam9263.c b/trunk/arch/arm/mach-at91/at91sam9263.c index d6f9c23927c4..6a01d0360dfb 100644 --- a/trunk/arch/arm/mach-at91/at91sam9263.c +++ b/trunk/arch/arm/mach-at91/at91sam9263.c @@ -193,7 +193,7 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk), CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk), CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk), - CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk), /* fake hclk clock */ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk), CLKDEV_CON_ID("pioA", &pioA_clk), diff --git a/trunk/arch/arm/mach-at91/at91sam9263_devices.c b/trunk/arch/arm/mach-at91/at91sam9263_devices.c index cb85da2eccea..8dde220b42b6 100644 --- a/trunk/arch/arm/mach-at91/at91sam9263_devices.c +++ b/trunk/arch/arm/mach-at91/at91sam9263_devices.c @@ -567,7 +567,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9263_twi_device = { .name = "i2c-gpio", - .id = 0, + .id = -1, .dev.platform_data = &pdata, }; @@ -600,7 +600,7 @@ static struct resource twi_resources[] = { static struct platform_device at91sam9263_twi_device = { .name = "i2c-at91sam9260", - .id = 0, + .id = -1, .resource = twi_resources, .num_resources = ARRAY_SIZE(twi_resources), }; diff --git a/trunk/arch/arm/mach-at91/at91sam9rl_devices.c b/trunk/arch/arm/mach-at91/at91sam9rl_devices.c index 5047bdc92adf..d6ca0543ce8d 100644 --- a/trunk/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/trunk/arch/arm/mach-at91/at91sam9rl_devices.c @@ -314,7 +314,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9rl_twi_device = { .name = "i2c-gpio", - .id = 0, + .id = -1, .dev.platform_data = &pdata, }; @@ -347,7 +347,7 @@ static struct resource twi_resources[] = { static struct platform_device at91sam9rl_twi_device = { .name = "i2c-at91sam9g20", - .id = 0, + .id = -1, .resource = twi_resources, .num_resources = ARRAY_SIZE(twi_resources), }; diff --git a/trunk/arch/arm/mach-at91/at91x40.c b/trunk/arch/arm/mach-at91/at91x40.c index bb7f54474b92..6bd7300a2bc5 100644 --- a/trunk/arch/arm/mach-at91/at91x40.c +++ b/trunk/arch/arm/mach-at91/at91x40.c @@ -88,6 +88,6 @@ void __init at91x40_init_interrupts(unsigned int priority[NR_AIC_IRQS]) if (!priority) priority = at91x40_default_irq_priority; - at91_aic_init(priority, at91_extern_irq); + at91_aic_init(priority); } diff --git a/trunk/arch/arm/mach-at91/board-neocore926.c b/trunk/arch/arm/mach-at91/board-neocore926.c index 6960778af4c2..9cda3fd346ae 100644 --- a/trunk/arch/arm/mach-at91/board-neocore926.c +++ b/trunk/arch/arm/mach-at91/board-neocore926.c @@ -129,7 +129,7 @@ static struct spi_board_info neocore926_spi_devices[] = { .max_speed_hz = 125000 * 16, .bus_num = 0, .platform_data = &ads_info, - .irq = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1, + .irq = AT91SAM9263_ID_IRQ1, }, #endif }; diff --git a/trunk/arch/arm/mach-at91/board-sam9261ek.c b/trunk/arch/arm/mach-at91/board-sam9261ek.c index a9167dd45f96..27b3af1a3047 100644 --- a/trunk/arch/arm/mach-at91/board-sam9261ek.c +++ b/trunk/arch/arm/mach-at91/board-sam9261ek.c @@ -309,7 +309,7 @@ static struct spi_board_info ek_spi_devices[] = { .max_speed_hz = 125000 * 26, /* (max sample rate @ 3V) * (cmd + data + overhead) */ .bus_num = 0, .platform_data = &ads_info, - .irq = NR_IRQS_LEGACY + AT91SAM9261_ID_IRQ0, + .irq = AT91SAM9261_ID_IRQ0, .controller_data = (void *) AT91_PIN_PA28, /* CS pin */ }, #endif diff --git a/trunk/arch/arm/mach-at91/board-sam9263ek.c b/trunk/arch/arm/mach-at91/board-sam9263ek.c index b87dbe2be0d6..073e17403d98 100644 --- a/trunk/arch/arm/mach-at91/board-sam9263ek.c +++ b/trunk/arch/arm/mach-at91/board-sam9263ek.c @@ -132,7 +132,7 @@ static struct spi_board_info ek_spi_devices[] = { .max_speed_hz = 125000 * 26, /* (max sample rate @ 3V) * (cmd + data + overhead) */ .bus_num = 0, .platform_data = &ads_info, - .irq = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1, + .irq = AT91SAM9263_ID_IRQ1, }, #endif }; diff --git a/trunk/arch/arm/mach-at91/generic.h b/trunk/arch/arm/mach-at91/generic.h index b62f560e6c75..f49650677653 100644 --- a/trunk/arch/arm/mach-at91/generic.h +++ b/trunk/arch/arm/mach-at91/generic.h @@ -26,8 +26,7 @@ extern void __init at91_dt_initialize(void); extern void __init at91_init_irq_default(void); extern void __init at91_init_interrupts(unsigned int priority[]); extern void __init at91x40_init_interrupts(unsigned int priority[]); -extern void __init at91_aic_init(unsigned int priority[], - unsigned int ext_irq_mask); +extern void __init at91_aic_init(unsigned int priority[]); extern int __init at91_aic_of_init(struct device_node *node, struct device_node *parent); extern int __init at91_aic5_of_init(struct device_node *node, diff --git a/trunk/arch/arm/mach-at91/irq.c b/trunk/arch/arm/mach-at91/irq.c index febc2ee901a5..1e02c0e49dcc 100644 --- a/trunk/arch/arm/mach-at91/irq.c +++ b/trunk/arch/arm/mach-at91/irq.c @@ -502,19 +502,14 @@ int __init at91_aic5_of_init(struct device_node *node, /* * Initialize the AIC interrupt controller. */ -void __init at91_aic_init(unsigned int *priority, unsigned int ext_irq_mask) +void __init at91_aic_init(unsigned int *priority) { unsigned int i; int irq_base; - at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs) - * sizeof(*at91_extern_irq), GFP_KERNEL); - - if (at91_aic_pm_init() || at91_extern_irq == NULL) + if (at91_aic_pm_init()) panic("Unable to allocate bit maps\n"); - *at91_extern_irq = ext_irq_mask; - at91_aic_base = ioremap(AT91_AIC, 512); if (!at91_aic_base) panic("Unable to ioremap AIC registers\n"); diff --git a/trunk/arch/arm/mach-at91/setup.c b/trunk/arch/arm/mach-at91/setup.c index 0b32c81730a5..da9881b161e1 100644 --- a/trunk/arch/arm/mach-at91/setup.c +++ b/trunk/arch/arm/mach-at91/setup.c @@ -47,7 +47,7 @@ void __init at91_init_irq_default(void) void __init at91_init_interrupts(unsigned int *priority) { /* Initialize the AIC interrupt controller */ - at91_aic_init(priority, at91_extern_irq); + at91_aic_init(priority); /* Enable GPIO interrupts */ at91_gpio_irq_setup(); @@ -151,7 +151,7 @@ static void __init soc_detect(u32 dbgu_base) } /* at91sam9g10 */ - if ((socid & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) { + if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) { at91_soc_initdata.type = AT91_SOC_SAM9G10; at91_boot_soc = at91sam9261_soc; } diff --git a/trunk/arch/arm/mach-exynos/common.c b/trunk/arch/arm/mach-exynos/common.c index 1947be8e5f5b..715b690e5009 100644 --- a/trunk/arch/arm/mach-exynos/common.c +++ b/trunk/arch/arm/mach-exynos/common.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include "common.h" @@ -347,8 +346,6 @@ static void __init exynos4_map_io(void) s5p_fb_setname(0, "exynos4-fb"); s5p_hdmi_setname("exynos4-hdmi"); - - s3c64xx_spi_setname("exynos4210-spi"); } static void __init exynos5_map_io(void) @@ -369,8 +366,6 @@ static void __init exynos5_map_io(void) s3c_i2c0_setname("s3c2440-i2c"); s3c_i2c1_setname("s3c2440-i2c"); s3c_i2c2_setname("s3c2440-i2c"); - - s3c64xx_spi_setname("exynos4210-spi"); } static void __init exynos4_init_clocks(int xtal) diff --git a/trunk/arch/arm/mach-exynos/mach-exynos4-dt.c b/trunk/arch/arm/mach-exynos/mach-exynos4-dt.c index eadf4b59e7d2..e58d786faf78 100644 --- a/trunk/arch/arm/mach-exynos/mach-exynos4-dt.c +++ b/trunk/arch/arm/mach-exynos/mach-exynos4-dt.c @@ -99,7 +99,6 @@ static char const *exynos4_dt_compat[] __initdata = { DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)") /* Maintainer: Thomas Abraham */ - .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = exynos4_dt_map_io, .handle_irq = gic_handle_irq, diff --git a/trunk/arch/arm/mach-imx/clk-busy.c b/trunk/arch/arm/mach-imx/clk-busy.c index 1ab91b5209e6..1a7a8dd045a1 100644 --- a/trunk/arch/arm/mach-imx/clk-busy.c +++ b/trunk/arch/arm/mach-imx/clk-busy.c @@ -108,7 +108,7 @@ struct clk *imx_clk_busy_divider(const char *name, const char *parent_name, busy->div.hw.init = &init; clk = clk_register(NULL, &busy->div.hw); - if (IS_ERR(clk)) + if (!clk) kfree(busy); return clk; diff --git a/trunk/arch/arm/mach-imx/clk-imx25.c b/trunk/arch/arm/mach-imx/clk-imx25.c index 01e2f843bf2e..d20d4795f4ea 100644 --- a/trunk/arch/arm/mach-imx/clk-imx25.c +++ b/trunk/arch/arm/mach-imx/clk-imx25.c @@ -127,8 +127,8 @@ int __init mx25_clocks_init(void) clk[esdhc2_ipg_per] = imx_clk_gate("esdhc2_ipg_per", "per4", ccm(CCM_CGCR0), 4); clk[gpt_ipg_per] = imx_clk_gate("gpt_ipg_per", "per5", ccm(CCM_CGCR0), 5); clk[i2c_ipg_per] = imx_clk_gate("i2c_ipg_per", "per6", ccm(CCM_CGCR0), 6); - clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per7", ccm(CCM_CGCR0), 7); - clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "per8", ccm(CCM_CGCR0), 8); + clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per8", ccm(CCM_CGCR0), 7); + clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "ipg_per", ccm(CCM_CGCR0), 8); clk[ssi1_ipg_per] = imx_clk_gate("ssi1_ipg_per", "per13", ccm(CCM_CGCR0), 13); clk[ssi2_ipg_per] = imx_clk_gate("ssi2_ipg_per", "per14", ccm(CCM_CGCR0), 14); clk[uart_ipg_per] = imx_clk_gate("uart_ipg_per", "per15", ccm(CCM_CGCR0), 15); diff --git a/trunk/arch/arm/mach-imx/clk-imx27.c b/trunk/arch/arm/mach-imx/clk-imx27.c index 366e5d59d886..3b6b640eed24 100644 --- a/trunk/arch/arm/mach-imx/clk-imx27.c +++ b/trunk/arch/arm/mach-imx/clk-imx27.c @@ -109,7 +109,7 @@ int __init mx27_clocks_init(unsigned long fref) clk[per3_div] = imx_clk_divider("per3_div", "mpll_main2", CCM_PCDR1, 16, 6); clk[per4_div] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6); clk[vpu_sel] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks)); - clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6); + clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 3); clk[usb_div] = imx_clk_divider("usb_div", "spll", CCM_CSCR, 28, 3); clk[cpu_sel] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks)); clk[clko_sel] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks)); @@ -121,7 +121,7 @@ int __init mx27_clocks_init(unsigned long fref) clk[ssi1_sel] = imx_clk_mux("ssi1_sel", CCM_CSCR, 22, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks)); clk[ssi2_sel] = imx_clk_mux("ssi2_sel", CCM_CSCR, 23, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks)); clk[ssi1_div] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6); - clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6); + clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 3); clk[clko_en] = imx_clk_gate("clko_en", "clko_div", CCM_PCCR0, 0); clk[ssi2_ipg_gate] = imx_clk_gate("ssi2_ipg_gate", "ipg", CCM_PCCR0, 0); clk[ssi1_ipg_gate] = imx_clk_gate("ssi1_ipg_gate", "ipg", CCM_PCCR0, 1); diff --git a/trunk/arch/arm/mach-imx/mm-imx3.c b/trunk/arch/arm/mach-imx/mm-imx3.c index b5deb0554552..9d2c843bde02 100644 --- a/trunk/arch/arm/mach-imx/mm-imx3.c +++ b/trunk/arch/arm/mach-imx/mm-imx3.c @@ -108,8 +108,9 @@ void __init imx3_init_l2x0(void) } l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096); - if (!l2x0_base) { - printk(KERN_ERR "remapping L2 cache area failed\n"); + if (IS_ERR(l2x0_base)) { + printk(KERN_ERR "remapping L2 cache area failed with %ld\n", + PTR_ERR(l2x0_base)); return; } diff --git a/trunk/arch/arm/mach-omap2/Kconfig b/trunk/arch/arm/mach-omap2/Kconfig index d669e227e00c..2a1a898c7f90 100644 --- a/trunk/arch/arm/mach-omap2/Kconfig +++ b/trunk/arch/arm/mach-omap2/Kconfig @@ -11,6 +11,7 @@ config ARCH_OMAP2PLUS_TYPICAL select I2C_OMAP select MENELAUS if ARCH_OMAP2 select NEON if ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5 + select PINCTRL select PM_RUNTIME select REGULATOR select SERIAL_OMAP diff --git a/trunk/arch/arm/mach-omap2/board-omap3beagle.c b/trunk/arch/arm/mach-omap2/board-omap3beagle.c index d41ab98890ff..388c431c745a 100644 --- a/trunk/arch/arm/mach-omap2/board-omap3beagle.c +++ b/trunk/arch/arm/mach-omap2/board-omap3beagle.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -445,31 +444,27 @@ static struct omap_board_mux board_mux[] __initdata = { }; #endif -static int __init beagle_opp_init(void) +static void __init beagle_opp_init(void) { int r = 0; - if (!machine_is_omap3_beagle()) - return 0; - - /* Initialize the omap3 opp table if not already created. */ - r = omap3_opp_init(); - if (IS_ERR_VALUE(r) && (r != -EEXIST)) { + /* Initialize the omap3 opp table */ + if (omap3_opp_init()) { pr_err("%s: opp default init failed\n", __func__); - return r; + return; } /* Custom OPP enabled for all xM versions */ if (cpu_is_omap3630()) { struct device *mpu_dev, *iva_dev; - mpu_dev = get_cpu_device(0); + mpu_dev = omap_device_get_by_hwmod_name("mpu"); iva_dev = omap_device_get_by_hwmod_name("iva"); if (IS_ERR(mpu_dev) || IS_ERR(iva_dev)) { pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n", __func__, mpu_dev, iva_dev); - return -ENODEV; + return; } /* Enable MPU 1GHz and lower opps */ r = opp_enable(mpu_dev, 800000000); @@ -489,9 +484,8 @@ static int __init beagle_opp_init(void) opp_disable(iva_dev, 660000000); } } - return 0; + return; } -device_initcall(beagle_opp_init); static void __init omap3_beagle_init(void) { @@ -528,6 +522,8 @@ static void __init omap3_beagle_init(void) /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); + + beagle_opp_init(); } MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board") diff --git a/trunk/arch/arm/mach-omap2/clock33xx_data.c b/trunk/arch/arm/mach-omap2/clock33xx_data.c index 1a45d6bd2539..114ab4b8e0e3 100644 --- a/trunk/arch/arm/mach-omap2/clock33xx_data.c +++ b/trunk/arch/arm/mach-omap2/clock33xx_data.c @@ -1073,8 +1073,6 @@ static struct omap_clk am33xx_clks[] = { CLK(NULL, "gfx_fck_div_ck", &gfx_fck_div_ck, CK_AM33XX), CLK(NULL, "sysclkout_pre_ck", &sysclkout_pre_ck, CK_AM33XX), CLK(NULL, "clkout2_ck", &clkout2_ck, CK_AM33XX), - CLK(NULL, "timer_32k_ck", &clkdiv32k_ick, CK_AM33XX), - CLK(NULL, "timer_sys_ck", &sys_clkin_ck, CK_AM33XX), }; int __init am33xx_clk_init(void) diff --git a/trunk/arch/arm/mach-omap2/mux34xx.c b/trunk/arch/arm/mach-omap2/mux34xx.c index c47140bbbec4..17f80e4ab162 100644 --- a/trunk/arch/arm/mach-omap2/mux34xx.c +++ b/trunk/arch/arm/mach-omap2/mux34xx.c @@ -614,16 +614,16 @@ static struct omap_mux __initdata omap3_muxmodes[] = { "sys_off_mode", NULL, NULL, NULL, "gpio_9", NULL, NULL, "safe_mode"), _OMAP3_MUXENTRY(UART1_CTS, 150, - "uart1_cts", "ssi1_rdy_tx", NULL, NULL, + "uart1_cts", NULL, NULL, NULL, "gpio_150", "hsusb3_tll_clk", NULL, "safe_mode"), _OMAP3_MUXENTRY(UART1_RTS, 149, - "uart1_rts", "ssi1_flag_tx", NULL, NULL, + "uart1_rts", NULL, NULL, NULL, "gpio_149", NULL, NULL, "safe_mode"), _OMAP3_MUXENTRY(UART1_RX, 151, - "uart1_rx", "ss1_wake_tx", "mcbsp1_clkr", "mcspi4_clk", + "uart1_rx", NULL, "mcbsp1_clkr", "mcspi4_clk", "gpio_151", NULL, NULL, "safe_mode"), _OMAP3_MUXENTRY(UART1_TX, 148, - "uart1_tx", "ssi1_dat_tx", NULL, NULL, + "uart1_tx", NULL, NULL, NULL, "gpio_148", NULL, NULL, "safe_mode"), _OMAP3_MUXENTRY(UART2_CTS, 144, "uart2_cts", "mcbsp3_dx", "gpt9_pwm_evt", NULL, diff --git a/trunk/arch/arm/mach-omap2/pm.h b/trunk/arch/arm/mach-omap2/pm.h index 67d66131cfa7..686137d164da 100644 --- a/trunk/arch/arm/mach-omap2/pm.h +++ b/trunk/arch/arm/mach-omap2/pm.h @@ -91,7 +91,6 @@ extern void omap3_save_scratchpad_contents(void); #define PM_RTA_ERRATUM_i608 (1 << 0) #define PM_SDRC_WAKEUP_ERRATUM_i583 (1 << 1) -#define PM_PER_MEMORIES_ERRATUM_i582 (1 << 2) #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) extern u16 pm34xx_errata; diff --git a/trunk/arch/arm/mach-omap2/pm34xx.c b/trunk/arch/arm/mach-omap2/pm34xx.c index 3a904de4313e..ba670db1fd37 100644 --- a/trunk/arch/arm/mach-omap2/pm34xx.c +++ b/trunk/arch/arm/mach-omap2/pm34xx.c @@ -652,17 +652,14 @@ static void __init pm_errata_configure(void) /* Enable the l2 cache toggling in sleep logic */ enable_omap3630_toggle_l2_on_restore(); if (omap_rev() < OMAP3630_REV_ES1_2) - pm34xx_errata |= (PM_SDRC_WAKEUP_ERRATUM_i583 | - PM_PER_MEMORIES_ERRATUM_i582); - } else if (cpu_is_omap34xx()) { - pm34xx_errata |= PM_PER_MEMORIES_ERRATUM_i582; + pm34xx_errata |= PM_SDRC_WAKEUP_ERRATUM_i583; } } int __init omap3_pm_init(void) { struct power_state *pwrst, *tmp; - struct clockdomain *neon_clkdm, *mpu_clkdm, *per_clkdm, *wkup_clkdm; + struct clockdomain *neon_clkdm, *mpu_clkdm; int ret; if (!omap3_has_io_chain_ctrl()) @@ -714,8 +711,6 @@ int __init omap3_pm_init(void) neon_clkdm = clkdm_lookup("neon_clkdm"); mpu_clkdm = clkdm_lookup("mpu_clkdm"); - per_clkdm = clkdm_lookup("per_clkdm"); - wkup_clkdm = clkdm_lookup("wkup_clkdm"); #ifdef CONFIG_SUSPEND omap_pm_suspend = omap3_pm_suspend; @@ -732,27 +727,6 @@ int __init omap3_pm_init(void) if (IS_PM34XX_ERRATUM(PM_RTA_ERRATUM_i608)) omap3630_ctrl_disable_rta(); - /* - * The UART3/4 FIFO and the sidetone memory in McBSP2/3 are - * not correctly reset when the PER powerdomain comes back - * from OFF or OSWR when the CORE powerdomain is kept active. - * See OMAP36xx Erratum i582 "PER Domain reset issue after - * Domain-OFF/OSWR Wakeup". This wakeup dependency is not a - * complete workaround. The kernel must also prevent the PER - * powerdomain from going to OSWR/OFF while the CORE - * powerdomain is not going to OSWR/OFF. And if PER last - * power state was off while CORE last power state was ON, the - * UART3/4 and McBSP2/3 SIDETONE devices need to run a - * self-test using their loopback tests; if that fails, those - * devices are unusable until the PER/CORE can complete a transition - * from ON to OSWR/OFF and then back to ON. - * - * XXX Technically this workaround is only needed if off-mode - * or OSWR is enabled. - */ - if (IS_PM34XX_ERRATUM(PM_PER_MEMORIES_ERRATUM_i582)) - clkdm_add_wkdep(per_clkdm, wkup_clkdm); - clkdm_add_wkdep(neon_clkdm, mpu_clkdm); if (omap_type() != OMAP2_DEVICE_TYPE_GP) { omap3_secure_ram_storage = diff --git a/trunk/arch/arm/mach-omap2/serial.c b/trunk/arch/arm/mach-omap2/serial.c index a507cd6cf4f1..0405c8190803 100644 --- a/trunk/arch/arm/mach-omap2/serial.c +++ b/trunk/arch/arm/mach-omap2/serial.c @@ -329,11 +329,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata, oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt); - if (console_uart_id == bdata->id) { - omap_device_enable(pdev); - pm_runtime_set_active(&pdev->dev); - } - oh->dev_attr = uart; if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) diff --git a/trunk/arch/arm/mach-s3c24xx/s3c2416.c b/trunk/arch/arm/mach-s3c24xx/s3c2416.c index 77ee0b732237..ed5a95ece9eb 100644 --- a/trunk/arch/arm/mach-s3c24xx/s3c2416.c +++ b/trunk/arch/arm/mach-s3c24xx/s3c2416.c @@ -61,7 +61,6 @@ #include #include #include -#include static struct map_desc s3c2416_iodesc[] __initdata = { IODESC_ENT(WATCHDOG), @@ -133,7 +132,6 @@ void __init s3c2416_map_io(void) /* initialize device information early */ s3c2416_default_sdhci0(); s3c2416_default_sdhci1(); - s3c64xx_spi_setname("s3c2443-spi"); iotable_init(s3c2416_iodesc, ARRAY_SIZE(s3c2416_iodesc)); } diff --git a/trunk/arch/arm/mach-s3c24xx/s3c2443.c b/trunk/arch/arm/mach-s3c24xx/s3c2443.c index 165b6a6b3daa..ab648ad8fa50 100644 --- a/trunk/arch/arm/mach-s3c24xx/s3c2443.c +++ b/trunk/arch/arm/mach-s3c24xx/s3c2443.c @@ -43,7 +43,6 @@ #include #include #include -#include static struct map_desc s3c2443_iodesc[] __initdata = { IODESC_ENT(WATCHDOG), @@ -101,9 +100,6 @@ void __init s3c2443_map_io(void) s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull; s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull; - /* initialize device information early */ - s3c64xx_spi_setname("s3c2443-spi"); - iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc)); } diff --git a/trunk/arch/arm/mach-s5p64x0/common.c b/trunk/arch/arm/mach-s5p64x0/common.c index 111e404a81fd..6e6a0a9d6778 100644 --- a/trunk/arch/arm/mach-s5p64x0/common.c +++ b/trunk/arch/arm/mach-s5p64x0/common.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include @@ -180,7 +179,6 @@ void __init s5p6440_map_io(void) /* initialize any device information early */ s3c_adc_setname("s3c64xx-adc"); s3c_fb_setname("s5p64x0-fb"); - s3c64xx_spi_setname("s5p64x0-spi"); s5p64x0_default_sdhci0(); s5p64x0_default_sdhci1(); @@ -195,7 +193,6 @@ void __init s5p6450_map_io(void) /* initialize any device information early */ s3c_adc_setname("s3c64xx-adc"); s3c_fb_setname("s5p64x0-fb"); - s3c64xx_spi_setname("s5p64x0-spi"); s5p64x0_default_sdhci0(); s5p64x0_default_sdhci1(); diff --git a/trunk/arch/arm/mach-s5pc100/common.c b/trunk/arch/arm/mach-s5pc100/common.c index cc6e561c9958..621908658861 100644 --- a/trunk/arch/arm/mach-s5pc100/common.c +++ b/trunk/arch/arm/mach-s5pc100/common.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include @@ -166,8 +165,6 @@ void __init s5pc100_map_io(void) s3c_onenand_setname("s5pc100-onenand"); s3c_fb_setname("s5pc100-fb"); s3c_cfcon_setname("s5pc100-pata"); - - s3c64xx_spi_setname("s5pc100-spi"); } void __init s5pc100_init_clocks(int xtal) diff --git a/trunk/arch/arm/mach-s5pv210/common.c b/trunk/arch/arm/mach-s5pv210/common.c index a0c50efe8145..4c9e9027df9a 100644 --- a/trunk/arch/arm/mach-s5pv210/common.c +++ b/trunk/arch/arm/mach-s5pv210/common.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include "common.h" @@ -197,8 +196,6 @@ void __init s5pv210_map_io(void) /* setup TV devices */ s5p_hdmi_setname("s5pv210-hdmi"); - - s3c64xx_spi_setname("s5pv210-spi"); } void __init s5pv210_init_clocks(int xtal) diff --git a/trunk/arch/arm/mach-shmobile/setup-r8a7779.c b/trunk/arch/arm/mach-shmobile/setup-r8a7779.c index ebbffc25f24f..2917668f0091 100644 --- a/trunk/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/trunk/arch/arm/mach-shmobile/setup-r8a7779.c @@ -247,7 +247,7 @@ void __init r8a7779_add_standard_devices(void) { #ifdef CONFIG_CACHE_L2X0 /* Early BRESP enable, Shared attribute override enable, 64K*16way */ - l2x0_init(IOMEM(0xf0100000), 0x40470000, 0x82000fff); + l2x0_init((void __iomem __force *)(0xf0100000), 0x40470000, 0x82000fff); #endif r8a7779_pm_init(); diff --git a/trunk/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h b/trunk/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/trunk/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h b/trunk/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/trunk/arch/arm/mach-ux500/cpu.c b/trunk/arch/arm/mach-ux500/cpu.c index 1f3fbc2bb776..2236cbd03cd7 100644 --- a/trunk/arch/arm/mach-ux500/cpu.c +++ b/trunk/arch/arm/mach-ux500/cpu.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include diff --git a/trunk/arch/arm/plat-mxc/devices/platform-mxc-mmc.c b/trunk/arch/arm/plat-mxc/devices/platform-mxc-mmc.c index e7b920b58675..540d3a7d92df 100644 --- a/trunk/arch/arm/plat-mxc/devices/platform-mxc-mmc.c +++ b/trunk/arch/arm/plat-mxc/devices/platform-mxc-mmc.c @@ -55,7 +55,7 @@ struct platform_device *__init imx_add_mxc_mmc( struct resource res[] = { { .start = data->iobase, - .end = data->iobase + data->iosize - 1, + .end = data->iobase + SZ_4K - 1, .flags = IORESOURCE_MEM, }, { .start = data->irq, diff --git a/trunk/arch/arm/plat-omap/Kconfig b/trunk/arch/arm/plat-omap/Kconfig index 82fcb206b5b2..7cd56ed5cd94 100644 --- a/trunk/arch/arm/plat-omap/Kconfig +++ b/trunk/arch/arm/plat-omap/Kconfig @@ -26,7 +26,6 @@ config ARCH_OMAP2PLUS select CLKDEV_LOOKUP select GENERIC_IRQ_CHIP select OMAP_DM_TIMER - select PINCTRL select PROC_DEVICETREE if PROC_FS select SPARSE_IRQ select USE_OF diff --git a/trunk/arch/arm/plat-samsung/include/plat/spi-core.h b/trunk/arch/arm/plat-samsung/include/plat/spi-core.h deleted file mode 100644 index 0b9428ab3fc3..000000000000 --- a/trunk/arch/arm/plat-samsung/include/plat/spi-core.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2012 Heiko Stuebner - * - * 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_S3C_SPI_CORE_H -#define __PLAT_S3C_SPI_CORE_H - -/* These functions are only for use with the core support code, such as - * the cpu specific initialisation code - */ - -/* re-define device name depending on support. */ -static inline void s3c64xx_spi_setname(char *name) -{ -#ifdef CONFIG_S3C64XX_DEV_SPI0 - s3c64xx_device_spi0.name = name; -#endif -#ifdef CONFIG_S3C64XX_DEV_SPI1 - s3c64xx_device_spi1.name = name; -#endif -#ifdef CONFIG_S3C64XX_DEV_SPI2 - s3c64xx_device_spi2.name = name; -#endif -} - -#endif /* __PLAT_S3C_SPI_CORE_H */ diff --git a/trunk/arch/arm64/Kconfig b/trunk/arch/arm64/Kconfig index 138fc9cfd783..ef54a59a9e89 100644 --- a/trunk/arch/arm64/Kconfig +++ b/trunk/arch/arm64/Kconfig @@ -6,8 +6,6 @@ config ARM64 select GENERIC_IOMAP select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW - select GENERIC_KERNEL_EXECVE - select GENERIC_KERNEL_THREAD select GENERIC_SMP_IDLE_THREAD select GENERIC_TIME_VSYSCALL select HARDIRQS_SW_RESEND diff --git a/trunk/arch/arm64/include/asm/processor.h b/trunk/arch/arm64/include/asm/processor.h index 42471d07d972..5d810044feda 100644 --- a/trunk/arch/arm64/include/asm/processor.h +++ b/trunk/arch/arm64/include/asm/processor.h @@ -126,6 +126,11 @@ unsigned long get_wchan(struct task_struct *p); extern struct task_struct *cpu_switch_to(struct task_struct *prev, struct task_struct *next); +/* + * Create a new kernel thread + */ +extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); + #define task_pt_regs(p) \ ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) diff --git a/trunk/arch/arm64/include/asm/syscalls.h b/trunk/arch/arm64/include/asm/syscalls.h index 81680a0ae913..09ff33572aab 100644 --- a/trunk/arch/arm64/include/asm/syscalls.h +++ b/trunk/arch/arm64/include/asm/syscalls.h @@ -23,6 +23,9 @@ /* * System call wrappers implemented in kernel/entry.S. */ +asmlinkage long sys_execve_wrapper(const char __user *filename, + const char __user *const __user *argv, + const char __user *const __user *envp); asmlinkage long sys_clone_wrapper(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, diff --git a/trunk/arch/arm64/include/asm/unistd.h b/trunk/arch/arm64/include/asm/unistd.h index b40dc6b69848..63f853f8b718 100644 --- a/trunk/arch/arm64/include/asm/unistd.h +++ b/trunk/arch/arm64/include/asm/unistd.h @@ -26,5 +26,4 @@ #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND #define __ARCH_WANT_COMPAT_SYS_SENDFILE #endif -#define __ARCH_WANT_SYS_EXECVE #include diff --git a/trunk/arch/arm64/include/asm/unistd32.h b/trunk/arch/arm64/include/asm/unistd32.h index 9035e6add3e4..6d909faebf28 100644 --- a/trunk/arch/arm64/include/asm/unistd32.h +++ b/trunk/arch/arm64/include/asm/unistd32.h @@ -32,7 +32,7 @@ __SYSCALL(7, sys_ni_syscall) /* 7 was sys_waitpid */ __SYSCALL(8, sys_creat) __SYSCALL(9, sys_link) __SYSCALL(10, sys_unlink) -__SYSCALL(11, compat_sys_execve) +__SYSCALL(11, compat_sys_execve_wrapper) __SYSCALL(12, sys_chdir) __SYSCALL(13, sys_ni_syscall) /* 13 was sys_time */ __SYSCALL(14, sys_mknod) diff --git a/trunk/arch/arm64/kernel/entry.S b/trunk/arch/arm64/kernel/entry.S index 616531862d52..a6f3f7da6880 100644 --- a/trunk/arch/arm64/kernel/entry.S +++ b/trunk/arch/arm64/kernel/entry.S @@ -594,7 +594,7 @@ work_resched: /* * "slow" syscall return path. */ -ret_to_user: +ENTRY(ret_to_user) disable_irq // disable interrupts ldr x1, [tsk, #TI_FLAGS] and x2, x1, #_TIF_WORK_MASK @@ -611,10 +611,7 @@ ENDPROC(ret_to_user) */ ENTRY(ret_from_fork) bl schedule_tail - cbz x19, 1f // not a kernel thread - mov x0, x20 - blr x19 -1: get_thread_info tsk + get_thread_info tsk b ret_to_user ENDPROC(ret_from_fork) @@ -676,6 +673,11 @@ __sys_trace_return: /* * Special system call wrappers. */ +ENTRY(sys_execve_wrapper) + mov x3, sp + b sys_execve +ENDPROC(sys_execve_wrapper) + ENTRY(sys_clone_wrapper) mov x5, sp b sys_clone diff --git a/trunk/arch/arm64/kernel/process.c b/trunk/arch/arm64/kernel/process.c index bf615e212c6c..f22965ea1cfc 100644 --- a/trunk/arch/arm64/kernel/process.c +++ b/trunk/arch/arm64/kernel/process.c @@ -240,35 +240,27 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *childregs = task_pt_regs(p); unsigned long tls = p->thread.tp_value; - memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); + *childregs = *regs; + childregs->regs[0] = 0; - if (likely(regs)) { - *childregs = *regs; - childregs->regs[0] = 0; - if (is_compat_thread(task_thread_info(p))) { - childregs->compat_sp = stack_start; - } else { - /* - * Read the current TLS pointer from tpidr_el0 as it may be - * out-of-sync with the saved value. - */ - asm("mrs %0, tpidr_el0" : "=r" (tls)); - childregs->sp = stack_start; - } + if (is_compat_thread(task_thread_info(p))) + childregs->compat_sp = stack_start; + else { /* - * If a TLS pointer was passed to clone (4th argument), use it - * for the new thread. + * Read the current TLS pointer from tpidr_el0 as it may be + * out-of-sync with the saved value. */ - if (clone_flags & CLONE_SETTLS) - tls = regs->regs[3]; - } else { - memset(childregs, 0, sizeof(struct pt_regs)); - childregs->pstate = PSR_MODE_EL1h; - p->thread.cpu_context.x19 = stack_start; - p->thread.cpu_context.x20 = stk_sz; + asm("mrs %0, tpidr_el0" : "=r" (tls)); + childregs->sp = stack_start; } - p->thread.cpu_context.pc = (unsigned long)ret_from_fork; + + memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); p->thread.cpu_context.sp = (unsigned long)childregs; + p->thread.cpu_context.pc = (unsigned long)ret_from_fork; + + /* If a TLS pointer was passed to clone, use that for the new thread. */ + if (clone_flags & CLONE_SETTLS) + tls = regs->regs[3]; p->thread.tp_value = tls; ptrace_hw_copy_thread(p); @@ -335,6 +327,43 @@ int dump_fpu (struct pt_regs *regs, struct user_fp *fp) } EXPORT_SYMBOL(dump_fpu); +/* + * Shuffle the argument into the correct register before calling the + * thread function. x1 is the thread argument, x2 is the pointer to + * the thread function, and x3 points to the exit function. + */ +extern void kernel_thread_helper(void); +asm( ".section .text\n" +" .align\n" +" .type kernel_thread_helper, #function\n" +"kernel_thread_helper:\n" +" mov x0, x1\n" +" mov x30, x3\n" +" br x2\n" +" .size kernel_thread_helper, . - kernel_thread_helper\n" +" .previous"); + +#define kernel_thread_exit do_exit + +/* + * Create a kernel thread. + */ +pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) +{ + struct pt_regs regs; + + memset(®s, 0, sizeof(regs)); + + regs.regs[1] = (unsigned long)arg; + regs.regs[2] = (unsigned long)fn; + regs.regs[3] = (unsigned long)kernel_thread_exit; + regs.pc = (unsigned long)kernel_thread_helper; + regs.pstate = PSR_MODE_EL1h; + + return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); +} +EXPORT_SYMBOL(kernel_thread); + unsigned long get_wchan(struct task_struct *p) { struct stackframe frame; diff --git a/trunk/arch/arm64/kernel/sys.c b/trunk/arch/arm64/kernel/sys.c index 9c77c0bacc1d..b120df37de35 100644 --- a/trunk/arch/arm64/kernel/sys.c +++ b/trunk/arch/arm64/kernel/sys.c @@ -41,6 +41,70 @@ asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); } +/* + * sys_execve() executes a new program. + */ +asmlinkage long sys_execve(const char __user *filenamei, + const char __user *const __user *argv, + const char __user *const __user *envp, + struct pt_regs *regs) +{ + long error; + struct filename *filename; + + filename = getname(filenamei); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = do_execve(filename->name, argv, envp, regs); + putname(filename); +out: + return error; +} + +int kernel_execve(const char *filename, + const char *const argv[], + const char *const envp[]) +{ + struct pt_regs regs; + int ret; + + memset(®s, 0, sizeof(struct pt_regs)); + ret = do_execve(filename, + (const char __user *const __user *)argv, + (const char __user *const __user *)envp, ®s); + if (ret < 0) + goto out; + + /* + * Save argc to the register structure for userspace. + */ + regs.regs[0] = ret; + + /* + * We were successful. We won't be returning to our caller, but + * instead to user space by manipulating the kernel stack. + */ + asm( "add x0, %0, %1\n\t" + "mov x1, %2\n\t" + "mov x2, %3\n\t" + "bl memmove\n\t" /* copy regs to top of stack */ + "mov x27, #0\n\t" /* not a syscall */ + "mov x28, %0\n\t" /* thread structure */ + "mov sp, x0\n\t" /* reposition stack pointer */ + "b ret_to_user" + : + : "r" (current_thread_info()), + "Ir" (THREAD_START_SP - sizeof(regs)), + "r" (®s), + "Ir" (sizeof(regs)) + : "x0", "x1", "x2", "x27", "x28", "x30", "memory"); + + out: + return ret; +} +EXPORT_SYMBOL(kernel_execve); + asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, off_t off) @@ -54,6 +118,7 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len, /* * Wrappers to pass the pt_regs argument. */ +#define sys_execve sys_execve_wrapper #define sys_clone sys_clone_wrapper #define sys_rt_sigreturn sys_rt_sigreturn_wrapper #define sys_sigaltstack sys_sigaltstack_wrapper diff --git a/trunk/arch/arm64/kernel/sys32.S b/trunk/arch/arm64/kernel/sys32.S index 92145d402cf1..54c4aec47a08 100644 --- a/trunk/arch/arm64/kernel/sys32.S +++ b/trunk/arch/arm64/kernel/sys32.S @@ -36,6 +36,11 @@ compat_sys_vfork_wrapper: b compat_sys_vfork ENDPROC(compat_sys_vfork_wrapper) +compat_sys_execve_wrapper: + mov x3, sp + b compat_sys_execve +ENDPROC(compat_sys_execve_wrapper) + compat_sys_clone_wrapper: mov x5, sp b compat_sys_clone diff --git a/trunk/arch/arm64/kernel/sys_compat.c b/trunk/arch/arm64/kernel/sys_compat.c index d140b73a8bc4..906e3bd270b0 100644 --- a/trunk/arch/arm64/kernel/sys_compat.c +++ b/trunk/arch/arm64/kernel/sys_compat.c @@ -49,6 +49,24 @@ asmlinkage int compat_sys_vfork(struct pt_regs *regs) regs, 0, NULL, NULL); } +asmlinkage int compat_sys_execve(const char __user *filenamei, + compat_uptr_t argv, compat_uptr_t envp, + struct pt_regs *regs) +{ + int error; + struct filename *filename; + + filename = getname(filenamei); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = compat_do_execve(filename->name, compat_ptr(argv), + compat_ptr(envp), regs); + putname(filename); +out: + return error; +} + asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval) { diff --git a/trunk/arch/c6x/Kconfig b/trunk/arch/c6x/Kconfig index 66eab3703c75..aee1b569ee6e 100644 --- a/trunk/arch/c6x/Kconfig +++ b/trunk/arch/c6x/Kconfig @@ -18,7 +18,6 @@ config C6X select OF_EARLY_FLATTREE select GENERIC_CLOCKEVENTS select GENERIC_KERNEL_THREAD - select GENERIC_KERNEL_EXECVE select MODULES_USE_ELF_RELA config MMU diff --git a/trunk/arch/c6x/include/uapi/asm/unistd.h b/trunk/arch/c6x/include/uapi/asm/unistd.h index 625beafb9cd1..4ff747d12dad 100644 --- a/trunk/arch/c6x/include/uapi/asm/unistd.h +++ b/trunk/arch/c6x/include/uapi/asm/unistd.h @@ -14,6 +14,7 @@ * more details. */ +#define __ARCH_WANT_KERNEL_EXECVE #define __ARCH_WANT_SYS_EXECVE /* Use the standard ABI for syscalls. */ diff --git a/trunk/arch/c6x/kernel/entry.S b/trunk/arch/c6x/kernel/entry.S index 75f6f36472cf..5449c36018fe 100644 --- a/trunk/arch/c6x/kernel/entry.S +++ b/trunk/arch/c6x/kernel/entry.S @@ -413,9 +413,19 @@ ENTRY(ret_from_kernel_thread) 0: B .S2 B10 /* call fn */ LDW .D2T1 *+SP(REGS_A1+8),A4 /* get arg */ - ADDKPC .S2 ret_from_fork_2,B3,3 + MVKL .S2 sys_exit,B11 + MVKH .S2 sys_exit,B11 + ADDKPC .S2 0f,B3,1 +0: + BNOP .S2 B11,5 /* jump to sys_exit */ ENDPROC(ret_from_kernel_thread) +ENTRY(ret_from_kernel_execve) + GET_THREAD_INFO A12 + BNOP .S2 syscall_exit,4 + ADD .D2X A4,-8,SP +ENDPROC(ret_from_kernel_execve) + ;; ;; These are the interrupt handlers, responsible for calling __do_IRQ() ;; int6 is used for syscalls (see _system_call entry) diff --git a/trunk/arch/frv/Kconfig b/trunk/arch/frv/Kconfig index df2eb4bd9fa2..b7412504f08a 100644 --- a/trunk/arch/frv/Kconfig +++ b/trunk/arch/frv/Kconfig @@ -13,7 +13,6 @@ config FRV select GENERIC_CPU_DEVICES select ARCH_WANT_IPC_PARSE_VERSION select GENERIC_KERNEL_THREAD - select GENERIC_KERNEL_EXECVE config ZONE_DMA bool diff --git a/trunk/arch/frv/boot/Makefile b/trunk/arch/frv/boot/Makefile index 636d5bbcd53f..6ae3254da019 100644 --- a/trunk/arch/frv/boot/Makefile +++ b/trunk/arch/frv/boot/Makefile @@ -17,8 +17,6 @@ PARAMS_PHYS = 0x0207c000 INITRD_PHYS = 0x02180000 INITRD_VIRT = 0x02180000 -OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment - # # If you don't define ZRELADDR above, # then it defaults to ZTEXTADDR @@ -34,18 +32,18 @@ Image: $(obj)/Image targets: $(obj)/Image $(obj)/Image: vmlinux FORCE - $(OBJCOPY) $(OBJCOPYFLAGS) -S vmlinux $@ + $(OBJCOPY) -O binary -R .note -R .comment -S vmlinux $@ #$(obj)/Image: $(CONFIGURE) $(SYSTEM) -# $(OBJCOPY) $(OBJCOPYFLAGS) -g -S $(SYSTEM) $@ +# $(OBJCOPY) -O binary -R .note -R .comment -g -S $(SYSTEM) $@ bzImage: zImage zImage: $(CONFIGURE) compressed/$(LINUX) - $(OBJCOPY) $(OBJCOPYFLAGS) -S compressed/$(LINUX) $@ + $(OBJCOPY) -O binary -R .note -R .comment -S compressed/$(LINUX) $@ bootpImage: bootp/bootp - $(OBJCOPY) $(OBJCOPYFLAGS) -S bootp/bootp $@ + $(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@ compressed/$(LINUX): $(LINUX) dep @$(MAKE) -C compressed $(LINUX) diff --git a/trunk/arch/frv/include/asm/unistd.h b/trunk/arch/frv/include/asm/unistd.h index 2358634cacca..266a5b25a0c1 100644 --- a/trunk/arch/frv/include/asm/unistd.h +++ b/trunk/arch/frv/include/asm/unistd.h @@ -30,6 +30,7 @@ #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND #define __ARCH_WANT_SYS_EXECVE +#define __ARCH_WANT_KERNEL_EXECVE /* * "Conditional" syscalls diff --git a/trunk/arch/frv/kernel/entry.S b/trunk/arch/frv/kernel/entry.S index dfcd263c0517..ee0beb354e4d 100644 --- a/trunk/arch/frv/kernel/entry.S +++ b/trunk/arch/frv/kernel/entry.S @@ -869,6 +869,11 @@ ret_from_kernel_thread: call schedule_tail calll.p @(gr21,gr0) or gr20,gr20,gr8 + bra sys_exit + + .globl ret_from_kernel_execve +ret_from_kernel_execve: + ori gr28,0,sp bra __syscall_exit ################################################################################################### @@ -1075,10 +1080,27 @@ __entry_return_from_kernel_interrupt: subicc gr5,#0,gr0,icc0 beq icc0,#0,__entry_return_direct - subcc gr0,gr0,gr0,icc2 /* set Z and clear C */ - call preempt_schedule_irq -#endif +__entry_preempt_need_resched: + ldi @(gr15,#TI_FLAGS),gr4 + andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0 + beq icc0,#1,__entry_return_direct + + setlos #PREEMPT_ACTIVE,gr5 + sti gr5,@(gr15,#TI_FLAGS) + + andi gr23,#~PSR_PIL,gr23 + movgs gr23,psr + + call schedule + sti gr0,@(gr15,#TI_PRE_COUNT) + + movsg psr,gr23 + ori gr23,#PSR_PIL_14,gr23 + movgs gr23,psr + bra __entry_preempt_need_resched +#else bra __entry_return_direct +#endif ############################################################################### diff --git a/trunk/arch/frv/kernel/process.c b/trunk/arch/frv/kernel/process.c index 7e33215f1d8f..e1e3aa196aa4 100644 --- a/trunk/arch/frv/kernel/process.c +++ b/trunk/arch/frv/kernel/process.c @@ -181,9 +181,6 @@ int copy_thread(unsigned long clone_flags, childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE); - /* set up the userspace frame (the only place that the USP is stored) */ - *childregs = *__kernel_frame0_ptr; - p->set_child_tid = p->clear_child_tid = NULL; p->thread.frame = childregs; @@ -194,8 +191,10 @@ int copy_thread(unsigned long clone_flags, p->thread.frame0 = childregs; if (unlikely(!regs)) { + memset(childregs, 0, sizeof(struct pt_regs)); childregs->gr9 = usp; /* function */ childregs->gr8 = arg; + childregs->psr = PSR_S; p->thread.pc = (unsigned long) ret_from_kernel_thread; save_user_regs(p->thread.user); return 0; diff --git a/trunk/arch/frv/mb93090-mb00/pci-dma-nommu.c b/trunk/arch/frv/mb93090-mb00/pci-dma-nommu.c index b99c2a7cc7a4..e47857f889b6 100644 --- a/trunk/arch/frv/mb93090-mb00/pci-dma-nommu.c +++ b/trunk/arch/frv/mb93090-mb00/pci-dma-nommu.c @@ -11,7 +11,6 @@ #include #include -#include #include #include #include diff --git a/trunk/arch/hexagon/Kconfig b/trunk/arch/hexagon/Kconfig index e418803b6c8e..0744f7d7b1fd 100644 --- a/trunk/arch/hexagon/Kconfig +++ b/trunk/arch/hexagon/Kconfig @@ -31,8 +31,6 @@ config HEXAGON select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS_BROADCAST select MODULES_USE_ELF_RELA - select GENERIC_KERNEL_THREAD - select GENERIC_KERNEL_EXECVE ---help--- Qualcomm Hexagon is a processor architecture designed for high performance and low power across a wide variety of applications. diff --git a/trunk/arch/hexagon/include/asm/processor.h b/trunk/arch/hexagon/include/asm/processor.h index 6dd5d3706869..a03323ab9d44 100644 --- a/trunk/arch/hexagon/include/asm/processor.h +++ b/trunk/arch/hexagon/include/asm/processor.h @@ -34,6 +34,7 @@ struct task_struct; /* this is defined in arch/process.c */ +extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); extern unsigned long thread_saved_pc(struct task_struct *tsk); extern void start_thread(struct pt_regs *, unsigned long, unsigned long); diff --git a/trunk/arch/hexagon/include/uapi/asm/ptrace.h b/trunk/arch/hexagon/include/uapi/asm/ptrace.h index 1ffce0c6ee07..8ef784047a74 100644 --- a/trunk/arch/hexagon/include/uapi/asm/ptrace.h +++ b/trunk/arch/hexagon/include/uapi/asm/ptrace.h @@ -32,8 +32,4 @@ extern int regs_query_register_offset(const char *name); extern const char *regs_query_register_name(unsigned int offset); -#define current_pt_regs() \ - ((struct pt_regs *) \ - ((unsigned long)current_thread_info() + THREAD_SIZE) - 1) - #endif diff --git a/trunk/arch/hexagon/include/uapi/asm/unistd.h b/trunk/arch/hexagon/include/uapi/asm/unistd.h index 26b2e0f909c8..81312d6a52e6 100644 --- a/trunk/arch/hexagon/include/uapi/asm/unistd.h +++ b/trunk/arch/hexagon/include/uapi/asm/unistd.h @@ -27,6 +27,5 @@ */ #define sys_mmap2 sys_mmap_pgoff -#define __ARCH_WANT_SYS_EXECVE #include diff --git a/trunk/arch/hexagon/kernel/process.c b/trunk/arch/hexagon/kernel/process.c index cfbc52bd5227..9f6d7411b574 100644 --- a/trunk/arch/hexagon/kernel/process.c +++ b/trunk/arch/hexagon/kernel/process.c @@ -25,6 +25,33 @@ #include #include +/* + * Kernel thread creation. The desired kernel function is "wrapped" + * in the kernel_thread_helper function, which does cleanup + * afterwards. + */ +static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *)) +{ + do_exit(fn(arg)); +} + +int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) +{ + struct pt_regs regs; + + memset(®s, 0, sizeof(regs)); + /* + * Yes, we're exploting illicit knowledge of the ABI here. + */ + regs.r00 = (unsigned long) arg; + regs.r01 = (unsigned long) fn; + pt_set_elr(®s, (unsigned long)kernel_thread_helper); + pt_set_kmode(®s); + + return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); +} +EXPORT_SYMBOL(kernel_thread); + /* * Program thread launch. Often defined as a macro in processor.h, * but we're shooting for a small footprint and it's not an inner-loop @@ -87,7 +114,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk) * Copy architecture-specific thread state */ int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, struct task_struct *p, + unsigned long unused, struct task_struct *p, struct pt_regs *regs) { struct thread_info *ti = task_thread_info(p); @@ -98,50 +125,61 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, childregs = (struct pt_regs *) (((unsigned long) ti + THREAD_SIZE) - sizeof(*childregs)); + memcpy(childregs, regs, sizeof(*childregs)); ti->regs = childregs; /* * Establish kernel stack pointer and initial PC for new thread - * Note that unlike the usual situation, we do not copy the - * parent's callee-saved here; those are in pt_regs and whatever - * we leave here will be overridden on return to userland. */ ss = (struct hexagon_switch_stack *) ((unsigned long) childregs - sizeof(*ss)); ss->lr = (unsigned long)ret_from_fork; p->thread.switch_sp = ss; - if (unlikely(p->flags & PF_KTHREAD)) { - memset(childregs, 0, sizeof(struct pt_regs)); - /* r24 <- fn, r25 <- arg */ - ss->r2524 = usp | ((u64)arg << 32); - pt_set_kmode(childregs); - return 0; - } - memcpy(childregs, regs, sizeof(*childregs)); - ss->r2524 = 0; - pt_set_rte_sp(childregs, usp); - - /* Child sees zero return value */ - childregs->r00 = 0; - - /* - * The clone syscall has the C signature: - * int [r0] clone(int flags [r0], - * void *child_frame [r1], - * void *parent_tid [r2], - * void *child_tid [r3], - * void *thread_control_block [r4]); - * ugp is used to provide TLS support. - */ - if (clone_flags & CLONE_SETTLS) - childregs->ugp = childregs->r04; + /* If User mode thread, set pt_reg stack pointer as per parameter */ + if (user_mode(childregs)) { + pt_set_rte_sp(childregs, usp); + + /* Child sees zero return value */ + childregs->r00 = 0; + + /* + * The clone syscall has the C signature: + * int [r0] clone(int flags [r0], + * void *child_frame [r1], + * void *parent_tid [r2], + * void *child_tid [r3], + * void *thread_control_block [r4]); + * ugp is used to provide TLS support. + */ + if (clone_flags & CLONE_SETTLS) + childregs->ugp = childregs->r04; + + /* + * Parent sees new pid -- not necessary, not even possible at + * this point in the fork process + * Might also want to set things like ti->addr_limit + */ + } else { + /* + * If kernel thread, resume stack is kernel stack base. + * Note that this is pointer arithmetic on pt_regs * + */ + pt_set_rte_sp(childregs, (unsigned long)(childregs + 1)); + /* + * We need the current thread_info fast path pointer + * set up in pt_regs. The register to be used is + * parametric for assembler code, but the mechanism + * doesn't drop neatly into C. Needs to be fixed. + */ + childregs->THREADINFO_REG = (unsigned long) ti; + } /* - * Parent sees new pid -- not necessary, not even possible at - * this point in the fork process - * Might also want to set things like ti->addr_limit + * thread_info pointer is pulled out of task_struct "stack" + * field on switch_to. */ + p->stack = (void *)ti; return 0; } diff --git a/trunk/arch/hexagon/kernel/signal.c b/trunk/arch/hexagon/kernel/signal.c index fe0d1373165d..5047b8b879c0 100644 --- a/trunk/arch/hexagon/kernel/signal.c +++ b/trunk/arch/hexagon/kernel/signal.c @@ -249,14 +249,14 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) */ asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) { - struct pt_regs *regs = current_pt_regs(); + struct pt_regs *regs = current_thread_info()->regs; return do_sigaltstack(uss, uoss, regs->r29); } asmlinkage int sys_rt_sigreturn(void) { - struct pt_regs *regs = current_pt_regs(); + struct pt_regs *regs = current_thread_info()->regs; struct rt_sigframe __user *frame; sigset_t blocked; diff --git a/trunk/arch/hexagon/kernel/syscall.c b/trunk/arch/hexagon/kernel/syscall.c index d2cc3270af3e..319fa6494f58 100644 --- a/trunk/arch/hexagon/kernel/syscall.c +++ b/trunk/arch/hexagon/kernel/syscall.c @@ -35,13 +35,55 @@ * See signal.c for signal-related system call wrappers. */ +asmlinkage int sys_execve(char __user *ufilename, + const char __user *const __user *argv, + const char __user *const __user *envp) +{ + struct pt_regs *pregs = current_thread_info()->regs; + struct filename *filename; + int retval; + + filename = getname(ufilename); + retval = PTR_ERR(filename); + if (IS_ERR(filename)) + return retval; + + retval = do_execve(filename->name, argv, envp, pregs); + putname(filename); + + return retval; +} + asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, unsigned long parent_tidp, unsigned long child_tidp) { - struct pt_regs *pregs = current_pt_regs(); + struct pt_regs *pregs = current_thread_info()->regs; if (!newsp) newsp = pregs->SP; return do_fork(clone_flags, newsp, pregs, 0, (int __user *)parent_tidp, (int __user *)child_tidp); } + +/* + * Do a system call from the kernel, so as to have a proper pt_regs + * and recycle the sys_execvpe infrustructure. + */ +int kernel_execve(const char *filename, + const char *const argv[], const char *const envp[]) +{ + register unsigned long __a0 asm("r0") = (unsigned long) filename; + register unsigned long __a1 asm("r1") = (unsigned long) argv; + register unsigned long __a2 asm("r2") = (unsigned long) envp; + int retval; + + __asm__ volatile( + " R6 = #%4;\n" + " trap0(#1);\n" + " %0 = R0;\n" + : "=r" (retval) + : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve) + ); + + return retval; +} diff --git a/trunk/arch/hexagon/kernel/vm_entry.S b/trunk/arch/hexagon/kernel/vm_entry.S index 425e50c694f7..cd71673ac259 100644 --- a/trunk/arch/hexagon/kernel/vm_entry.S +++ b/trunk/arch/hexagon/kernel/vm_entry.S @@ -266,8 +266,4 @@ _K_enter_machcheck: .globl ret_from_fork ret_from_fork: call schedule_tail - P0 = cmp.eq(R24, #0); - if P0 jump return_from_syscall - R0 = R25; - callr R24 jump return_from_syscall diff --git a/trunk/arch/ia64/Kconfig b/trunk/arch/ia64/Kconfig index 670600468128..3279646120e3 100644 --- a/trunk/arch/ia64/Kconfig +++ b/trunk/arch/ia64/Kconfig @@ -42,8 +42,6 @@ config IA64 select GENERIC_TIME_VSYSCALL_OLD select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_RELA - select GENERIC_KERNEL_THREAD - select GENERIC_KERNEL_EXECVE default y help The Itanium Processor Family is Intel's 64-bit successor to diff --git a/trunk/arch/ia64/include/asm/processor.h b/trunk/arch/ia64/include/asm/processor.h index e0a899a1a8a6..944152a50912 100644 --- a/trunk/arch/ia64/include/asm/processor.h +++ b/trunk/arch/ia64/include/asm/processor.h @@ -340,6 +340,22 @@ struct task_struct; */ #define release_thread(dead_task) +/* + * This is the mechanism for creating a new kernel thread. + * + * NOTE 1: Only a kernel-only process (ie the swapper or direct + * descendants who haven't done an "execve()") should use this: it + * will work within a system call from a "real" process, but the + * process memory space will not be free'd until both the parent and + * the child have exited. + * + * NOTE 2: This MUST NOT be an inlined function. Otherwise, we get + * into trouble in init/main.c when the child thread returns to + * do_basic_setup() and the timing is such that free_initmem() has + * been called already. + */ +extern pid_t kernel_thread (int (*fn)(void *), void *arg, unsigned long flags); + /* Get wait channel for task P. */ extern unsigned long get_wchan (struct task_struct *p); diff --git a/trunk/arch/ia64/include/asm/unistd.h b/trunk/arch/ia64/include/asm/unistd.h index 1574bca86138..8b3ff2f5b861 100644 --- a/trunk/arch/ia64/include/asm/unistd.h +++ b/trunk/arch/ia64/include/asm/unistd.h @@ -29,7 +29,6 @@ #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND -#define __ARCH_WANT_SYS_EXECVE #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER) diff --git a/trunk/arch/ia64/kernel/entry.S b/trunk/arch/ia64/kernel/entry.S index 940a67263629..1ccbe12a4d84 100644 --- a/trunk/arch/ia64/kernel/entry.S +++ b/trunk/arch/ia64/kernel/entry.S @@ -61,13 +61,14 @@ ENTRY(ia64_execve) * Allocate 8 input registers since ptrace() may clobber them */ .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) - alloc loc1=ar.pfs,8,2,3,0 + alloc loc1=ar.pfs,8,2,4,0 mov loc0=rp .body mov out0=in0 // filename ;; // stop bit between alloc and call mov out1=in1 // argv mov out2=in2 // envp + add out3=16,sp // regs br.call.sptk.many rp=sys_execve .ret0: cmp4.ge p6,p7=r8,r0 @@ -75,6 +76,7 @@ ENTRY(ia64_execve) sxt4 r8=r8 // return 64-bit result ;; stf.spill [sp]=f0 +(p6) cmp.ne pKStk,pUStk=r0,r0 // a successful execve() lands us in user-mode... mov rp=loc0 (p6) mov ar.pfs=r0 // clear ar.pfs on success (p7) br.ret.sptk.many rp @@ -482,6 +484,19 @@ GLOBAL_ENTRY(prefetch_stack) br.ret.sptk.many rp END(prefetch_stack) +GLOBAL_ENTRY(kernel_execve) + rum psr.ac + mov r15=__NR_execve // put syscall number in place + break __BREAK_SYSCALL + br.ret.sptk.many rp +END(kernel_execve) + +GLOBAL_ENTRY(clone) + mov r15=__NR_clone // put syscall number in place + break __BREAK_SYSCALL + br.ret.sptk.many rp +END(clone) + /* * Invoke a system call, but do some tracing before and after the call. * We MUST preserve the current register frame throughout this routine @@ -585,27 +600,6 @@ GLOBAL_ENTRY(ia64_strace_leave_kernel) .ret4: br.cond.sptk ia64_leave_kernel END(ia64_strace_leave_kernel) -ENTRY(call_payload) - .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(0) - /* call the kernel_thread payload; fn is in r4, arg - in r5 */ - alloc loc1=ar.pfs,0,3,1,0 - mov loc0=rp - mov loc2=gp - mov out0=r5 // arg - ld8 r14 = [r4], 8 // fn.address - ;; - mov b6 = r14 - ld8 gp = [r4] // fn.gp - ;; - br.call.sptk.many rp=b6 // fn(arg) -.ret12: mov gp=loc2 - mov rp=loc0 - mov ar.pfs=loc1 - /* ... and if it has returned, we are going to userland */ - cmp.ne pKStk,pUStk=r0,r0 - br.ret.sptk.many rp -END(call_payload) - GLOBAL_ENTRY(ia64_ret_from_clone) PT_REGS_UNWIND_INFO(0) { /* @@ -622,7 +616,6 @@ GLOBAL_ENTRY(ia64_ret_from_clone) br.call.sptk.many rp=ia64_invoke_schedule_tail } .ret8: -(pKStk) br.call.sptk.many rp=call_payload adds r2=TI_FLAGS+IA64_TASK_SIZE,r13 ;; ld4 r2=[r2] diff --git a/trunk/arch/ia64/kernel/head.S b/trunk/arch/ia64/kernel/head.S index 4738ff7bd66a..629a250f7c19 100644 --- a/trunk/arch/ia64/kernel/head.S +++ b/trunk/arch/ia64/kernel/head.S @@ -1093,6 +1093,19 @@ GLOBAL_ENTRY(cycle_to_cputime) END(cycle_to_cputime) #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ +GLOBAL_ENTRY(start_kernel_thread) + .prologue + .save rp, r0 // this is the end of the call-chain + .body + alloc r2 = ar.pfs, 0, 0, 2, 0 + mov out0 = r9 + mov out1 = r11;; + br.call.sptk.many rp = kernel_thread_helper;; + mov out0 = r8 + br.call.sptk.many rp = sys_exit;; +1: br.sptk.few 1b // not reached +END(start_kernel_thread) + #ifdef CONFIG_IA64_BRL_EMU /* diff --git a/trunk/arch/ia64/kernel/process.c b/trunk/arch/ia64/kernel/process.c index 25543a295ad9..35e106f2ed13 100644 --- a/trunk/arch/ia64/kernel/process.c +++ b/trunk/arch/ia64/kernel/process.c @@ -401,15 +401,64 @@ copy_thread(unsigned long clone_flags, struct pt_regs *child_ptregs; int retval = 0; +#ifdef CONFIG_SMP + /* + * For SMP idle threads, fork_by_hand() calls do_fork with + * NULL regs. + */ + if (!regs) + return 0; +#endif + + stack = ((struct switch_stack *) regs) - 1; + child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1; child_stack = (struct switch_stack *) child_ptregs - 1; + /* copy parent's switch_stack & pt_regs to child: */ + memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack)); + rbs = (unsigned long) current + IA64_RBS_OFFSET; child_rbs = (unsigned long) p + IA64_RBS_OFFSET; + rbs_size = stack->ar_bspstore - rbs; + + /* copy the parent's register backing store to the child: */ + memcpy((void *) child_rbs, (void *) rbs, rbs_size); + + if (likely(user_mode(child_ptregs))) { + if (clone_flags & CLONE_SETTLS) + child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ + if (user_stack_base) { + child_ptregs->r12 = user_stack_base + user_stack_size - 16; + child_ptregs->ar_bspstore = user_stack_base; + child_ptregs->ar_rnat = 0; + child_ptregs->loadrs = 0; + } + } else { + /* + * Note: we simply preserve the relative position of + * the stack pointer here. There is no need to + * allocate a scratch area here, since that will have + * been taken care of by the caller of sys_clone() + * already. + */ + child_ptregs->r12 = (unsigned long) child_ptregs - 16; /* kernel sp */ + child_ptregs->r13 = (unsigned long) p; /* set `current' pointer */ + } + child_stack->ar_bspstore = child_rbs + rbs_size; + child_stack->b0 = (unsigned long) &ia64_ret_from_clone; /* copy parts of thread_struct: */ p->thread.ksp = (unsigned long) child_stack - 16; + /* stop some PSR bits from being inherited. + * the psr.up/psr.pp bits must be cleared on fork but inherited on execve() + * therefore we must specify them explicitly here and not include them in + * IA64_PSR_BITS_TO_CLEAR. + */ + child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) + & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); + /* * NOTE: The calling convention considers all floating point * registers in the high partition (fph) to be scratch. Since @@ -431,66 +480,8 @@ copy_thread(unsigned long clone_flags, # define THREAD_FLAGS_TO_SET 0 p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) | THREAD_FLAGS_TO_SET); - ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */ - if (unlikely(p->flags & PF_KTHREAD)) { - if (unlikely(!user_stack_base)) { - /* fork_idle() called us */ - return 0; - } - memset(child_stack, 0, sizeof(*child_ptregs) + sizeof(*child_stack)); - child_stack->r4 = user_stack_base; /* payload */ - child_stack->r5 = user_stack_size; /* argument */ - /* - * Preserve PSR bits, except for bits 32-34 and 37-45, - * which we can't read. - */ - child_ptregs->cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN; - /* mark as valid, empty frame */ - child_ptregs->cr_ifs = 1UL << 63; - child_stack->ar_fpsr = child_ptregs->ar_fpsr - = ia64_getreg(_IA64_REG_AR_FPSR); - child_stack->pr = (1 << PRED_KERNEL_STACK); - child_stack->ar_bspstore = child_rbs; - child_stack->b0 = (unsigned long) &ia64_ret_from_clone; - - /* stop some PSR bits from being inherited. - * the psr.up/psr.pp bits must be cleared on fork but inherited on execve() - * therefore we must specify them explicitly here and not include them in - * IA64_PSR_BITS_TO_CLEAR. - */ - child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) - & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); - - return 0; - } - stack = ((struct switch_stack *) regs) - 1; - /* copy parent's switch_stack & pt_regs to child: */ - memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack)); - - /* copy the parent's register backing store to the child: */ - rbs_size = stack->ar_bspstore - rbs; - memcpy((void *) child_rbs, (void *) rbs, rbs_size); - if (clone_flags & CLONE_SETTLS) - child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ - if (user_stack_base) { - child_ptregs->r12 = user_stack_base + user_stack_size - 16; - child_ptregs->ar_bspstore = user_stack_base; - child_ptregs->ar_rnat = 0; - child_ptregs->loadrs = 0; - } - child_stack->ar_bspstore = child_rbs + rbs_size; - child_stack->b0 = (unsigned long) &ia64_ret_from_clone; - - /* stop some PSR bits from being inherited. - * the psr.up/psr.pp bits must be cleared on fork but inherited on execve() - * therefore we must specify them explicitly here and not include them in - * IA64_PSR_BITS_TO_CLEAR. - */ - child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) - & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); - #ifdef CONFIG_PERFMON if (current->thread.pfm_context) pfm_inherit(p, child_ptregs); @@ -617,6 +608,57 @@ dump_fpu (struct pt_regs *pt, elf_fpregset_t dst) return 1; /* f0-f31 are always valid so we always return 1 */ } +long +sys_execve (const char __user *filename, + const char __user *const __user *argv, + const char __user *const __user *envp, + struct pt_regs *regs) +{ + struct filename *fname; + int error; + + fname = getname(filename); + error = PTR_ERR(fname); + if (IS_ERR(fname)) + goto out; + error = do_execve(fname->name, argv, envp, regs); + putname(fname); +out: + return error; +} + +pid_t +kernel_thread (int (*fn)(void *), void *arg, unsigned long flags) +{ + extern void start_kernel_thread (void); + unsigned long *helper_fptr = (unsigned long *) &start_kernel_thread; + struct { + struct switch_stack sw; + struct pt_regs pt; + } regs; + + memset(®s, 0, sizeof(regs)); + regs.pt.cr_iip = helper_fptr[0]; /* set entry point (IP) */ + regs.pt.r1 = helper_fptr[1]; /* set GP */ + regs.pt.r9 = (unsigned long) fn; /* 1st argument */ + regs.pt.r11 = (unsigned long) arg; /* 2nd argument */ + /* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read. */ + regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN; + regs.pt.cr_ifs = 1UL << 63; /* mark as valid, empty frame */ + regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR); + regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET; + regs.sw.pr = (1 << PRED_KERNEL_STACK); + return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s.pt, 0, NULL, NULL); +} +EXPORT_SYMBOL(kernel_thread); + +/* This gets called from kernel_thread() via ia64_invoke_thread_helper(). */ +int +kernel_thread_helper (int (*fn)(void *), void *arg) +{ + return (*fn)(arg); +} + /* * Flush thread state. This is called when a thread does an execve(). */ diff --git a/trunk/arch/m68k/Kconfig b/trunk/arch/m68k/Kconfig index 953a7ba5d050..e7c161433eae 100644 --- a/trunk/arch/m68k/Kconfig +++ b/trunk/arch/m68k/Kconfig @@ -16,7 +16,6 @@ config M68K select ARCH_WANT_IPC_PARSE_VERSION select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE select GENERIC_KERNEL_THREAD - select GENERIC_KERNEL_EXECVE select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_REL select MODULES_USE_ELF_RELA diff --git a/trunk/arch/m68k/include/asm/unistd.h b/trunk/arch/m68k/include/asm/unistd.h index 0aa165405966..5fc7f7bec1c8 100644 --- a/trunk/arch/m68k/include/asm/unistd.h +++ b/trunk/arch/m68k/include/asm/unistd.h @@ -32,6 +32,7 @@ #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND #define __ARCH_WANT_SYS_EXECVE +#define __ARCH_WANT_KERNEL_EXECVE /* * "Conditional" syscalls diff --git a/trunk/arch/m68k/kernel/entry.S b/trunk/arch/m68k/kernel/entry.S index 45b2f293f8cf..946cb0187751 100644 --- a/trunk/arch/m68k/kernel/entry.S +++ b/trunk/arch/m68k/kernel/entry.S @@ -115,9 +115,16 @@ ENTRY(ret_from_kernel_thread) | a3 contains the kernel thread payload, d7 - its argument movel %d1,%sp@- jsr schedule_tail + GET_CURRENT(%d0) movel %d7,(%sp) jsr %a3@ addql #4,%sp + movel %d0,(%sp) + jra sys_exit + +ENTRY(ret_from_kernel_execve) + movel 4(%sp), %sp + GET_CURRENT(%d0) jra ret_from_exception #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) diff --git a/trunk/arch/mips/Kconfig b/trunk/arch/mips/Kconfig index 4183e62f178c..dba9390d37cf 100644 --- a/trunk/arch/mips/Kconfig +++ b/trunk/arch/mips/Kconfig @@ -40,8 +40,6 @@ config MIPS select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_REL select MODULES_USE_ELF_RELA if 64BIT - select GENERIC_KERNEL_THREAD - select GENERIC_KERNEL_EXECVE menu "Machine selection" diff --git a/trunk/arch/mips/include/asm/processor.h b/trunk/arch/mips/include/asm/processor.h index d28c41e0887c..5e33fabe354d 100644 --- a/trunk/arch/mips/include/asm/processor.h +++ b/trunk/arch/mips/include/asm/processor.h @@ -310,6 +310,8 @@ struct task_struct; /* Free all resources held by a thread. */ #define release_thread(thread) do { } while(0) +extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); + extern unsigned long thread_saved_pc(struct task_struct *tsk); /* diff --git a/trunk/arch/mips/include/asm/ptrace.h b/trunk/arch/mips/include/asm/ptrace.h index cec5e125f7e4..4f5da948a777 100644 --- a/trunk/arch/mips/include/asm/ptrace.h +++ b/trunk/arch/mips/include/asm/ptrace.h @@ -61,10 +61,4 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs) die(str, regs); } -#define current_pt_regs() \ -({ \ - unsigned long sp = (unsigned long)__builtin_frame_address(0); \ - (struct pt_regs *)((sp | (THREAD_SIZE - 1)) + 1 - 32) - 1; \ -}) - #endif /* _ASM_PTRACE_H */ diff --git a/trunk/arch/mips/include/asm/unistd.h b/trunk/arch/mips/include/asm/unistd.h index b306e2081cad..9e47cc11aa26 100644 --- a/trunk/arch/mips/include/asm/unistd.h +++ b/trunk/arch/mips/include/asm/unistd.h @@ -20,7 +20,6 @@ #define __ARCH_OMIT_COMPAT_SYS_GETDENTS64 #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_SYS_ALARM -#define __ARCH_WANT_SYS_EXECVE #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_IPC #define __ARCH_WANT_SYS_PAUSE diff --git a/trunk/arch/mips/kernel/entry.S b/trunk/arch/mips/kernel/entry.S index 3320cb4ac1d4..a6c133212003 100644 --- a/trunk/arch/mips/kernel/entry.S +++ b/trunk/arch/mips/kernel/entry.S @@ -65,12 +65,6 @@ need_resched: b need_resched #endif -FEXPORT(ret_from_kernel_thread) - jal schedule_tail # a0 = struct task_struct *prev - move a0, s1 - jal s0 - j syscall_exit - FEXPORT(ret_from_fork) jal schedule_tail # a0 = struct task_struct *prev diff --git a/trunk/arch/mips/kernel/linux32.c b/trunk/arch/mips/kernel/linux32.c index 8796dbc7e358..3a21acedf882 100644 --- a/trunk/arch/mips/kernel/linux32.c +++ b/trunk/arch/mips/kernel/linux32.c @@ -3,6 +3,7 @@ * * Copyright (C) 2000 Silicon Graphics, Inc. * Written by Ulf Carlsson (ulfc@engr.sgi.com) + * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com) */ #include #include @@ -76,6 +77,26 @@ SYSCALL_DEFINE6(32_mmap2, unsigned long, addr, unsigned long, len, return error; } +/* + * sys_execve() executes a new program. + */ +asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs) +{ + int error; + struct filename *filename; + + filename = getname(compat_ptr(regs.regs[4])); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = compat_do_execve(filename->name, compat_ptr(regs.regs[5]), + compat_ptr(regs.regs[6]), ®s); + putname(filename); + +out: + return error; +} + #define RLIM_INFINITY32 0x7fffffff #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) diff --git a/trunk/arch/mips/kernel/mips_ksyms.c b/trunk/arch/mips/kernel/mips_ksyms.c index 2d9304c2b54c..3fc1691110dc 100644 --- a/trunk/arch/mips/kernel/mips_ksyms.c +++ b/trunk/arch/mips/kernel/mips_ksyms.c @@ -32,6 +32,8 @@ EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memmove); +EXPORT_SYMBOL(kernel_thread); + /* * Functions that operate on entire pages. Mostly used by memory management. */ diff --git a/trunk/arch/mips/kernel/process.c b/trunk/arch/mips/kernel/process.c index d13720ac656f..e9a5fd7277f4 100644 --- a/trunk/arch/mips/kernel/process.c +++ b/trunk/arch/mips/kernel/process.c @@ -84,7 +84,6 @@ void __noreturn cpu_idle(void) } asmlinkage void ret_from_fork(void); -asmlinkage void ret_from_kernel_thread(void); void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) { @@ -114,7 +113,7 @@ void flush_thread(void) } int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, struct task_struct *p, struct pt_regs *regs) + unsigned long unused, struct task_struct *p, struct pt_regs *regs) { struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs; @@ -137,30 +136,19 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, childregs = (struct pt_regs *) childksp - 1; /* Put the stack after the struct pt_regs. */ childksp = (unsigned long) childregs; - p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1); - if (unlikely(p->flags & PF_KTHREAD)) { - unsigned long status = p->thread.cp0_status; - memset(childregs, 0, sizeof(struct pt_regs)); - ti->addr_limit = KERNEL_DS; - p->thread.reg16 = usp; /* fn */ - p->thread.reg17 = arg; - p->thread.reg29 = childksp; - p->thread.reg31 = (unsigned long) ret_from_kernel_thread; -#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) - status = (status & ~(ST0_KUP | ST0_IEP | ST0_IEC)) | - ((status & (ST0_KUC | ST0_IEC)) << 2); -#else - status |= ST0_EXL; -#endif - childregs->cp0_status = status; - return 0; - } *childregs = *regs; childregs->regs[7] = 0; /* Clear error flag */ + childregs->regs[2] = 0; /* Child gets zero as return value */ - childregs->regs[29] = usp; - ti->addr_limit = USER_DS; + if (childregs->cp0_status & ST0_CU0) { + childregs->regs[28] = (unsigned long) ti; + childregs->regs[29] = childksp; + ti->addr_limit = KERNEL_DS; + } else { + childregs->regs[29] = usp; + ti->addr_limit = USER_DS; + } p->thread.reg29 = (unsigned long) childregs; p->thread.reg31 = (unsigned long) ret_from_fork; @@ -168,6 +156,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, * New tasks lose permission to use the fpu. This accelerates context * switching for most programs since they don't use the fpu. */ + p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1); childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); #ifdef CONFIG_MIPS_MT_SMTC @@ -232,6 +221,35 @@ int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr) return 1; } +/* + * Create a kernel thread + */ +static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *)) +{ + do_exit(fn(arg)); +} + +long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) +{ + struct pt_regs regs; + + memset(®s, 0, sizeof(regs)); + + regs.regs[4] = (unsigned long) arg; + regs.regs[5] = (unsigned long) fn; + regs.cp0_epc = (unsigned long) kernel_thread_helper; + regs.cp0_status = read_c0_status(); +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) + regs.cp0_status = (regs.cp0_status & ~(ST0_KUP | ST0_IEP | ST0_IEC)) | + ((regs.cp0_status & (ST0_KUC | ST0_IEC)) << 2); +#else + regs.cp0_status |= ST0_EXL; +#endif + + /* Ok, create the new process.. */ + return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); +} + /* * */ diff --git a/trunk/arch/mips/kernel/scall64-n32.S b/trunk/arch/mips/kernel/scall64-n32.S index d27ca340d46d..f6ba8381ee01 100644 --- a/trunk/arch/mips/kernel/scall64-n32.S +++ b/trunk/arch/mips/kernel/scall64-n32.S @@ -167,7 +167,7 @@ EXPORT(sysn32_call_table) PTR sys_getsockopt PTR sys_clone /* 6055 */ PTR sys_fork - PTR compat_sys_execve + PTR sys32_execve PTR sys_exit PTR compat_sys_wait4 PTR sys_kill /* 6060 */ diff --git a/trunk/arch/mips/kernel/scall64-o32.S b/trunk/arch/mips/kernel/scall64-o32.S index 9601be6afa3d..53c2d7245764 100644 --- a/trunk/arch/mips/kernel/scall64-o32.S +++ b/trunk/arch/mips/kernel/scall64-o32.S @@ -203,7 +203,7 @@ sys_call_table: PTR sys_creat PTR sys_link PTR sys_unlink /* 4010 */ - PTR compat_sys_execve + PTR sys32_execve PTR sys_chdir PTR compat_sys_time PTR sys_mknod diff --git a/trunk/arch/mips/kernel/syscall.c b/trunk/arch/mips/kernel/syscall.c index c611e2df7767..2bd561bc05ae 100644 --- a/trunk/arch/mips/kernel/syscall.c +++ b/trunk/arch/mips/kernel/syscall.c @@ -127,6 +127,28 @@ _sys_clone(nabi_no_regargs struct pt_regs regs) parent_tidptr, child_tidptr); } +/* + * sys_execve() executes a new program. + */ +asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs) +{ + int error; + struct filename *filename; + + filename = getname((const char __user *) (long)regs.regs[4]); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = do_execve(filename->name, + (const char __user *const __user *) (long)regs.regs[5], + (const char __user *const __user *) (long)regs.regs[6], + ®s); + putname(filename); + +out: + return error; +} + SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) { struct thread_info *ti = task_thread_info(current); @@ -291,3 +313,34 @@ asmlinkage void bad_stack(void) { do_exit(SIGSEGV); } + +/* + * Do a system call from kernel instead of calling sys_execve so we + * end up with proper pt_regs. + */ +int kernel_execve(const char *filename, + const char *const argv[], + const char *const envp[]) +{ + register unsigned long __a0 asm("$4") = (unsigned long) filename; + register unsigned long __a1 asm("$5") = (unsigned long) argv; + register unsigned long __a2 asm("$6") = (unsigned long) envp; + register unsigned long __a3 asm("$7"); + unsigned long __v0; + + __asm__ volatile (" \n" + " .set noreorder \n" + " li $2, %5 # __NR_execve \n" + " syscall \n" + " move %0, $2 \n" + " .set reorder \n" + : "=&r" (__v0), "=r" (__a3) + : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve) + : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", + "memory"); + + if (__a3 == 0) + return __v0; + + return -__v0; +} diff --git a/trunk/arch/openrisc/Kconfig b/trunk/arch/openrisc/Kconfig index e7f1a2993f78..05f2ba41ff1a 100644 --- a/trunk/arch/openrisc/Kconfig +++ b/trunk/arch/openrisc/Kconfig @@ -22,8 +22,6 @@ config OPENRISC select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNLEN_USER select MODULES_USE_ELF_RELA - select GENERIC_KERNEL_THREAD - select GENERIC_KERNEL_EXECVE config MMU def_bool y diff --git a/trunk/arch/openrisc/include/uapi/asm/unistd.h b/trunk/arch/openrisc/include/uapi/asm/unistd.h index 5db7bc0fa5a7..437bdbb61b14 100644 --- a/trunk/arch/openrisc/include/uapi/asm/unistd.h +++ b/trunk/arch/openrisc/include/uapi/asm/unistd.h @@ -20,8 +20,6 @@ #define sys_mmap2 sys_mmap_pgoff -#define __ARCH_WANT_SYS_EXECVE - #include #define __NR_or1k_atomic __NR_arch_specific_syscall diff --git a/trunk/arch/openrisc/kernel/entry.S b/trunk/arch/openrisc/kernel/entry.S index c60a09df323f..ddfcaa828b0e 100644 --- a/trunk/arch/openrisc/kernel/entry.S +++ b/trunk/arch/openrisc/kernel/entry.S @@ -894,16 +894,6 @@ ENTRY(ret_from_fork) l.jal schedule_tail l.nop - /* Check if we are a kernel thread */ - l.sfeqi r20,0 - l.bf 1f - l.nop - - /* ...we are a kernel thread so invoke the requested callback */ - l.jalr r20 - l.or r3,r22,r0 - -1: /* _syscall_returns expect r11 to contain return value */ l.lwz r11,PT_GPR11(r1) @@ -925,6 +915,26 @@ ENTRY(ret_from_fork) l.j _syscall_return l.nop +/* Since syscalls don't save call-clobbered registers, the args to + * kernel_thread_helper will need to be passed through callee-saved + * registers and copied to the parameter registers when the thread + * begins running. + * + * See arch/openrisc/kernel/process.c: + * The args are passed as follows: + * arg1 (r3) : passed in r20 + * arg2 (r4) : passed in r22 + */ + +ENTRY(_kernel_thread_helper) + l.or r3,r20,r0 + l.or r4,r22,r0 + l.movhi r31,hi(kernel_thread_helper) + l.ori r31,r31,lo(kernel_thread_helper) + l.jr r31 + l.nop + + /* ========================================================[ switch ] === */ /* @@ -1034,13 +1044,8 @@ ENTRY(_switch) /* Unwind stack to pre-switch state */ l.addi r1,r1,(INT_FRAME_SIZE) - /* Return via the link-register back to where we 'came from', where - * that may be either schedule(), ret_from_fork(), or - * ret_from_kernel_thread(). If we are returning to a new thread, - * we are expected to have set up the arg to schedule_tail already, - * hence we do so here unconditionally: - */ - l.lwz r3,TI_STACK(r3) /* Load 'prev' as schedule_tail arg */ + /* Return via the link-register back to where we 'came from', where that can be + * either schedule() or return_from_fork()... */ l.jr r9 l.nop @@ -1083,6 +1088,10 @@ ENTRY(sys_fork) l.j _fork_save_extra_regs_and_call l.addi r3,r1,0 +ENTRY(sys_execve) + l.j _sys_execve + l.addi r6,r1,0 + ENTRY(sys_sigaltstack) l.j _sys_sigaltstack l.addi r5,r1,0 diff --git a/trunk/arch/openrisc/kernel/process.c b/trunk/arch/openrisc/kernel/process.c index e0874b8e09e4..c35f3ab1a8d3 100644 --- a/trunk/arch/openrisc/kernel/process.c +++ b/trunk/arch/openrisc/kernel/process.c @@ -109,82 +109,66 @@ void release_thread(struct task_struct *dead_task) */ extern asmlinkage void ret_from_fork(void); -/* - * copy_thread - * @clone_flags: flags - * @usp: user stack pointer or fn for kernel thread - * @arg: arg to fn for kernel thread; always NULL for userspace thread - * @p: the newly created task - * @regs: CPU context to copy for userspace thread; always NULL for kthread - * - * At the top of a newly initialized kernel stack are two stacked pt_reg - * structures. The first (topmost) is the userspace context of the thread. - * The second is the kernelspace context of the thread. - * - * A kernel thread will not be returning to userspace, so the topmost pt_regs - * struct can be uninitialized; it _does_ need to exist, though, because - * a kernel thread can become a userspace thread by doing a kernel_execve, in - * which case the topmost context will be initialized and used for 'returning' - * to userspace. - * - * The second pt_reg struct needs to be initialized to 'return' to - * ret_from_fork. A kernel thread will need to set r20 to the address of - * a function to call into (with arg in r22); userspace threads need to set - * r20 to NULL in which case ret_from_fork will just continue a return to - * userspace. - * - * A kernel thread 'fn' may return; this is effectively what happens when - * kernel_execve is called. In that case, the userspace pt_regs must have - * been initialized (which kernel_execve takes care of, see start_thread - * below); ret_from_fork will then continue its execution causing the - * 'kernel thread' to return to userspace as a userspace thread. - */ - int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, struct task_struct *p, struct pt_regs *regs) + unsigned long unused, struct task_struct *p, struct pt_regs *regs) { - struct pt_regs *userregs; + struct pt_regs *childregs; struct pt_regs *kregs; unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; + struct thread_info *ti; unsigned long top_of_kernel_stack; top_of_kernel_stack = sp; p->set_child_tid = p->clear_child_tid = NULL; - /* Locate userspace context on stack... */ - sp -= STACK_FRAME_OVERHEAD; /* redzone */ + /* Copy registers */ + /* redzone */ + sp -= STACK_FRAME_OVERHEAD; sp -= sizeof(struct pt_regs); - userregs = (struct pt_regs *) sp; + childregs = (struct pt_regs *)sp; - /* ...and kernel context */ - sp -= STACK_FRAME_OVERHEAD; /* redzone */ - sp -= sizeof(struct pt_regs); - kregs = (struct pt_regs *)sp; + /* Copy parent registers */ + *childregs = *regs; - if (unlikely(p->flags & PF_KTHREAD)) { - memset(kregs, 0, sizeof(struct pt_regs)); - kregs->gpr[20] = usp; /* fn, kernel thread */ - kregs->gpr[22] = arg; + if ((childregs->sr & SPR_SR_SM) == 1) { + /* for kernel thread, set `current_thread_info' + * and stackptr in new task + */ + childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; + childregs->gpr[10] = (unsigned long)task_thread_info(p); } else { - *userregs = *regs; - - userregs->sp = usp; - userregs->gpr[11] = 0; /* Result from fork() */ - - kregs->gpr[20] = 0; /* Userspace thread */ + childregs->sp = usp; } + childregs->gpr[11] = 0; /* Result from fork() */ + /* - * _switch wants the kernel stack page in pt_regs->sp so that it - * can restore it to thread_info->ksp... see _switch for details. + * The way this works is that at some point in the future + * some task will call _switch to switch to the new task. + * That will pop off the stack frame created below and start + * the new task running at ret_from_fork. The new task will + * do some house keeping and then return from the fork or clone + * system call, using the stack frame created above. + */ + /* redzone */ + sp -= STACK_FRAME_OVERHEAD; + sp -= sizeof(struct pt_regs); + kregs = (struct pt_regs *)sp; + + ti = task_thread_info(p); + ti->ksp = sp; + + /* kregs->sp must store the location of the 'pre-switch' kernel stack + * pointer... for a newly forked process, this is simply the top of + * the kernel stack. */ kregs->sp = top_of_kernel_stack; + kregs->gpr[3] = (unsigned long)current; /* arg to schedule_tail */ + kregs->gpr[10] = (unsigned long)task_thread_info(p); kregs->gpr[9] = (unsigned long)ret_from_fork; - task_thread_info(p)->ksp = (unsigned long)kregs; - return 0; } @@ -193,14 +177,16 @@ copy_thread(unsigned long clone_flags, unsigned long usp, */ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) { - unsigned long sr = mfspr(SPR_SR) & ~SPR_SR_SM; + unsigned long sr = regs->sr & ~SPR_SR_SM; set_fs(USER_DS); - memset(regs, 0, sizeof(struct pt_regs)); + memset(regs->gpr, 0, sizeof(regs->gpr)); regs->pc = pc; regs->sr = sr; regs->sp = sp; + +/* printk("start thread, ksp = %lx\n", current_thread_info()->ksp);*/ } /* Fill in the fpu structure for a core dump. */ @@ -251,9 +237,74 @@ void dump_elf_thread(elf_greg_t *dest, struct pt_regs* regs) dest[35] = 0; } +extern void _kernel_thread_helper(void); + +void __noreturn kernel_thread_helper(int (*fn) (void *), void *arg) +{ + do_exit(fn(arg)); +} + +/* + * Create a kernel thread. + */ +int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags) +{ + struct pt_regs regs; + + memset(®s, 0, sizeof(regs)); + + regs.gpr[20] = (unsigned long)fn; + regs.gpr[22] = (unsigned long)arg; + regs.sr = mfspr(SPR_SR); + regs.pc = (unsigned long)_kernel_thread_helper; + + return do_fork(flags | CLONE_VM | CLONE_UNTRACED, + 0, ®s, 0, NULL, NULL); +} + +/* + * sys_execve() executes a new program. + */ +asmlinkage long _sys_execve(const char __user *name, + const char __user * const __user *argv, + const char __user * const __user *envp, + struct pt_regs *regs) +{ + int error; + struct filename *filename; + + filename = getname(name); + error = PTR_ERR(filename); + + if (IS_ERR(filename)) + goto out; + + error = do_execve(filename->name, argv, envp, regs); + putname(filename); + +out: + return error; +} + unsigned long get_wchan(struct task_struct *p) { /* TODO */ return 0; } + +int kernel_execve(const char *filename, char *const argv[], char *const envp[]) +{ + register long __res asm("r11") = __NR_execve; + register long __a asm("r3") = (long)(filename); + register long __b asm("r4") = (long)(argv); + register long __c asm("r5") = (long)(envp); + __asm__ volatile ("l.sys 1" + : "=r" (__res), "=r"(__a), "=r"(__b), "=r"(__c) + : "0"(__res), "1"(__a), "2"(__b), "3"(__c) + : "r6", "r7", "r8", "r12", "r13", "r15", + "r17", "r19", "r21", "r23", "r25", "r27", + "r29", "r31"); + __asm__ volatile ("l.nop"); + return __res; +} diff --git a/trunk/arch/parisc/Kconfig b/trunk/arch/parisc/Kconfig index 0aec70c35614..11def45b98c5 100644 --- a/trunk/arch/parisc/Kconfig +++ b/trunk/arch/parisc/Kconfig @@ -22,8 +22,6 @@ config PARISC select GENERIC_STRNCPY_FROM_USER select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_RELA - select GENERIC_KERNEL_THREAD - select GENERIC_KERNEL_EXECVE help The PA-RISC microprocessor is designed by Hewlett-Packard and used diff --git a/trunk/arch/parisc/include/asm/unistd.h b/trunk/arch/parisc/include/asm/unistd.h index 55512e26b0c2..541639c3f607 100644 --- a/trunk/arch/parisc/include/asm/unistd.h +++ b/trunk/arch/parisc/include/asm/unistd.h @@ -163,7 +163,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND -#define __ARCH_WANT_SYS_EXECVE #endif /* __ASSEMBLY__ */ diff --git a/trunk/arch/parisc/kernel/entry.S b/trunk/arch/parisc/kernel/entry.S index c9a9abd4bc58..18670a078849 100644 --- a/trunk/arch/parisc/kernel/entry.S +++ b/trunk/arch/parisc/kernel/entry.S @@ -707,10 +707,60 @@ ENTRY(end_fault_vector) .import handle_interruption,code .import do_cpu_irq_mask,code + /* + * r26 = function to be called + * r25 = argument to pass in + * r24 = flags for do_fork() + * + * Kernel threads don't ever return, so they don't need + * a true register context. We just save away the arguments + * for copy_thread/ret_ to properly set up the child. + */ + +#define CLONE_VM 0x100 /* Must agree with */ +#define CLONE_UNTRACED 0x00800000 + + .import do_fork +ENTRY(__kernel_thread) + STREG %r2, -RP_OFFSET(%r30) + + copy %r30, %r1 + ldo PT_SZ_ALGN(%r30),%r30 +#ifdef CONFIG_64BIT + /* Yo, function pointers in wide mode are little structs... -PB */ + ldd 24(%r26), %r2 + STREG %r2, PT_GR27(%r1) /* Store childs %dp */ + ldd 16(%r26), %r26 + + STREG %r22, PT_GR22(%r1) /* save r22 (arg5) */ + copy %r0, %r22 /* user_tid */ +#endif + STREG %r26, PT_GR26(%r1) /* Store function & argument for child */ + STREG %r25, PT_GR25(%r1) + ldil L%CLONE_UNTRACED, %r26 + ldo CLONE_VM(%r26), %r26 /* Force CLONE_VM since only init_mm */ + or %r26, %r24, %r26 /* will have kernel mappings. */ + ldi 1, %r25 /* stack_start, signals kernel thread */ + stw %r0, -52(%r30) /* user_tid */ +#ifdef CONFIG_64BIT + ldo -16(%r30),%r29 /* Reference param save area */ +#endif + BL do_fork, %r2 + copy %r1, %r24 /* pt_regs */ + + /* Parent Returns here */ + + LDREG -PT_SZ_ALGN-RP_OFFSET(%r30), %r2 + ldo -PT_SZ_ALGN(%r30), %r30 + bv %r0(%r2) + nop +ENDPROC(__kernel_thread) + /* * Child Returns here * - * copy_thread moved args into task save area. + * copy_thread moved args from temp save area set up above + * into task save area. */ ENTRY(ret_from_kernel_thread) @@ -719,18 +769,52 @@ ENTRY(ret_from_kernel_thread) BL schedule_tail, %r2 nop - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 + LDREG TI_TASK-THREAD_SZ_ALGN(%r30), %r1 LDREG TASK_PT_GR25(%r1), %r26 #ifdef CONFIG_64BIT LDREG TASK_PT_GR27(%r1), %r27 + LDREG TASK_PT_GR22(%r1), %r22 #endif LDREG TASK_PT_GR26(%r1), %r1 ble 0(%sr7, %r1) copy %r31, %r2 - b finish_child_return - nop + +#ifdef CONFIG_64BIT + ldo -16(%r30),%r29 /* Reference param save area */ + loadgp /* Thread could have been in a module */ +#endif +#ifndef CONFIG_64BIT + b sys_exit +#else + load32 sys_exit, %r1 + bv %r0(%r1) +#endif + ldi 0, %r26 ENDPROC(ret_from_kernel_thread) + .import sys_execve, code +ENTRY(__execve) + copy %r2, %r15 + copy %r30, %r16 + ldo PT_SZ_ALGN(%r30), %r30 + STREG %r26, PT_GR26(%r16) + STREG %r25, PT_GR25(%r16) + STREG %r24, PT_GR24(%r16) +#ifdef CONFIG_64BIT + ldo -16(%r30),%r29 /* Reference param save area */ +#endif + BL sys_execve, %r2 + copy %r16, %r26 + + cmpib,=,n 0,%r28,intr_return /* forward */ + + /* yes, this will trap and die. */ + copy %r15, %r2 + copy %r16, %r30 + bv %r0(%r2) + nop +ENDPROC(__execve) + /* * struct task_struct *_switch_to(struct task_struct *prev, @@ -1692,27 +1776,49 @@ ENTRY(sys_fork_wrapper) LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 ldo TASK_REGS(%r1),%r1 reg_save %r1 - mfctl %cr27, %r28 - STREG %r28, PT_CR27(%r1) + mfctl %cr27, %r3 + STREG %r3, PT_CR27(%r1) + + STREG %r2,-RP_OFFSET(%r30) + ldo FRAME_SIZE(%r30),%r30 +#ifdef CONFIG_64BIT + ldo -16(%r30),%r29 /* Reference param save area */ +#endif + + /* These are call-clobbered registers and therefore + also syscall-clobbered (we hope). */ + STREG %r2,PT_GR19(%r1) /* save for child */ + STREG %r30,PT_GR21(%r1) LDREG PT_GR30(%r1),%r25 copy %r1,%r24 - b sys_clone + BL sys_clone,%r2 ldi SIGCHLD,%r26 + + LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 +wrapper_exit: + ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */ + LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 + ldo TASK_REGS(%r1),%r1 /* get pt regs */ + + LDREG PT_CR27(%r1), %r3 + mtctl %r3, %cr27 + reg_restore %r1 + + /* strace expects syscall # to be preserved in r20 */ + ldi __NR_fork,%r20 + bv %r0(%r2) + STREG %r20,PT_GR20(%r1) ENDPROC(sys_fork_wrapper) /* Set the return value for the child */ ENTRY(child_return) BL schedule_tail, %r2 nop -finish_child_return: - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 - ldo TASK_REGS(%r1),%r1 /* get pt regs */ - LDREG PT_CR27(%r1), %r3 - mtctl %r3, %cr27 - reg_restore %r1 - b syscall_exit + LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1 + LDREG TASK_PT_GR19(%r1),%r2 + b wrapper_exit copy %r0,%r28 ENDPROC(child_return) @@ -1721,10 +1827,23 @@ ENTRY(sys_clone_wrapper) LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 ldo TASK_REGS(%r1),%r1 /* get pt regs */ reg_save %r1 - mfctl %cr27, %r28 - STREG %r28, PT_CR27(%r1) - b sys_clone + mfctl %cr27, %r3 + STREG %r3, PT_CR27(%r1) + + STREG %r2,-RP_OFFSET(%r30) + ldo FRAME_SIZE(%r30),%r30 +#ifdef CONFIG_64BIT + ldo -16(%r30),%r29 /* Reference param save area */ +#endif + + /* WARNING - Clobbers r19 and r21, userspace must save these! */ + STREG %r2,PT_GR19(%r1) /* save for child */ + STREG %r30,PT_GR21(%r1) + BL sys_clone,%r2 copy %r1,%r24 + + b wrapper_exit + LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 ENDPROC(sys_clone_wrapper) @@ -1732,14 +1851,72 @@ ENTRY(sys_vfork_wrapper) LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 ldo TASK_REGS(%r1),%r1 /* get pt regs */ reg_save %r1 - mfctl %cr27, %r28 - STREG %r28, PT_CR27(%r1) + mfctl %cr27, %r3 + STREG %r3, PT_CR27(%r1) - b sys_vfork + STREG %r2,-RP_OFFSET(%r30) + ldo FRAME_SIZE(%r30),%r30 +#ifdef CONFIG_64BIT + ldo -16(%r30),%r29 /* Reference param save area */ +#endif + + STREG %r2,PT_GR19(%r1) /* save for child */ + STREG %r30,PT_GR21(%r1) + + BL sys_vfork,%r2 copy %r1,%r26 + + b wrapper_exit + LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 ENDPROC(sys_vfork_wrapper) + .macro execve_wrapper execve + LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 + ldo TASK_REGS(%r1),%r1 /* get pt regs */ + + /* + * Do we need to save/restore r3-r18 here? + * I don't think so. why would new thread need old + * threads registers? + */ + + /* %arg0 - %arg3 are already saved for us. */ + + STREG %r2,-RP_OFFSET(%r30) + ldo FRAME_SIZE(%r30),%r30 +#ifdef CONFIG_64BIT + ldo -16(%r30),%r29 /* Reference param save area */ +#endif + BL \execve,%r2 + copy %r1,%arg0 + + ldo -FRAME_SIZE(%r30),%r30 + LDREG -RP_OFFSET(%r30),%r2 + + /* If exec succeeded we need to load the args */ + + ldo -1024(%r0),%r1 + cmpb,>>= %r28,%r1,error_\execve + copy %r2,%r19 + +error_\execve: + bv %r0(%r19) + nop + .endm + + .import sys_execve +ENTRY(sys_execve_wrapper) + execve_wrapper sys_execve +ENDPROC(sys_execve_wrapper) + +#ifdef CONFIG_64BIT + .import sys32_execve +ENTRY(sys32_execve_wrapper) + execve_wrapper sys32_execve +ENDPROC(sys32_execve_wrapper) +#endif + ENTRY(sys_rt_sigreturn_wrapper) LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 ldo TASK_REGS(%r26),%r26 /* get pt regs */ diff --git a/trunk/arch/parisc/kernel/process.c b/trunk/arch/parisc/kernel/process.c index 38db36f64307..cbc37216bf90 100644 --- a/trunk/arch/parisc/kernel/process.c +++ b/trunk/arch/parisc/kernel/process.c @@ -52,7 +52,6 @@ #include #include -#include #include #include #include @@ -165,6 +164,23 @@ void machine_power_off(void) void (*pm_power_off)(void) = machine_power_off; EXPORT_SYMBOL(pm_power_off); +/* + * Create a kernel thread + */ + +extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); +pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) +{ + + /* + * FIXME: Once we are sure we don't need any debug here, + * kernel_thread can become a #define. + */ + + return __kernel_thread(fn, arg, flags); +} +EXPORT_SYMBOL(kernel_thread); + /* * Free current thread data structures etc.. */ @@ -240,8 +256,8 @@ sys_vfork(struct pt_regs *regs) int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, - struct task_struct *p, struct pt_regs *pregs) + unsigned long unused, /* in ia64 this is "user_stack_size" */ + struct task_struct * p, struct pt_regs * pregs) { struct pt_regs * cregs = &(p->thread.regs); void *stack = task_stack_page(p); @@ -254,32 +270,48 @@ copy_thread(unsigned long clone_flags, unsigned long usp, #ifdef CONFIG_HPUX extern void * const hpux_child_return; #endif - if (unlikely(p->flags & PF_KTHREAD)) { - memset(cregs, 0, sizeof(struct pt_regs)); - if (!usp) /* idle thread */ - return 0; + *cregs = *pregs; + + /* Set the return value for the child. Note that this is not + actually restored by the syscall exit path, but we put it + here for consistency in case of signals. */ + cregs->gr[28] = 0; /* child */ + + /* + * We need to differentiate between a user fork and a + * kernel fork. We can't use user_mode, because the + * the syscall path doesn't save iaoq. Right now + * We rely on the fact that kernel_thread passes + * in zero for usp. + */ + if (usp == 1) { /* kernel thread */ + cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN; /* Must exit via ret_from_kernel_thread in order * to call schedule_tail() */ - cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; cregs->kpc = (unsigned long) &ret_from_kernel_thread; /* * Copy function and argument to be called from * ret_from_kernel_thread. */ #ifdef CONFIG_64BIT - cregs->gr[27] = ((unsigned long *)usp)[3]; - cregs->gr[26] = ((unsigned long *)usp)[2]; -#else - cregs->gr[26] = usp; + cregs->gr[27] = pregs->gr[27]; #endif - cregs->gr[25] = arg; + cregs->gr[26] = pregs->gr[26]; + cregs->gr[25] = pregs->gr[25]; } else { /* user thread */ + /* + * Note that the fork wrappers are responsible + * for setting gr[21]. + */ + + /* Use same stack depth as parent */ + cregs->ksp = (unsigned long)stack + + (pregs->gr[21] & (THREAD_SIZE - 1)); cregs->gr[30] = usp; - cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; if (personality(p->personality) == PER_HPUX) { #ifdef CONFIG_HPUX cregs->kpc = (unsigned long) &hpux_child_return; @@ -291,7 +323,8 @@ copy_thread(unsigned long clone_flags, unsigned long usp, } /* Setup thread TLS area from the 4th parameter in clone */ if (clone_flags & CLONE_SETTLS) - cregs->cr27 = pregs->gr[23]; + cregs->cr27 = pregs->gr[23]; + } return 0; @@ -302,6 +335,39 @@ unsigned long thread_saved_pc(struct task_struct *t) return t->thread.regs.kpc; } +/* + * sys_execve() executes a new program. + */ + +asmlinkage int sys_execve(struct pt_regs *regs) +{ + int error; + struct filename *filename; + + filename = getname((const char __user *) regs->gr[26]); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = do_execve(filename->name, + (const char __user *const __user *) regs->gr[25], + (const char __user *const __user *) regs->gr[24], + regs); + putname(filename); +out: + + return error; +} + +extern int __execve(const char *filename, + const char *const argv[], + const char *const envp[], struct task_struct *task); +int kernel_execve(const char *filename, + const char *const argv[], + const char *const envp[]) +{ + return __execve(filename, argv, envp, current); +} + unsigned long get_wchan(struct task_struct *p) { diff --git a/trunk/arch/parisc/kernel/sys_parisc32.c b/trunk/arch/parisc/kernel/sys_parisc32.c index 9cfdaa19ab63..bf5b93a885d3 100644 --- a/trunk/arch/parisc/kernel/sys_parisc32.c +++ b/trunk/arch/parisc/kernel/sys_parisc32.c @@ -53,6 +53,28 @@ #define DBG(x) #endif +/* + * sys32_execve() executes a new program. + */ + +asmlinkage int sys32_execve(struct pt_regs *regs) +{ + int error; + struct filename *filename; + + DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26])); + filename = getname((const char __user *) regs->gr[26]); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = compat_do_execve(filename->name, compat_ptr(regs->gr[25]), + compat_ptr(regs->gr[24]), regs); + putname(filename); +out: + + return error; +} + asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23, int r22, int r21, int r20) { diff --git a/trunk/arch/parisc/kernel/syscall_table.S b/trunk/arch/parisc/kernel/syscall_table.S index cb2da96d6ab9..3735abd7f8f6 100644 --- a/trunk/arch/parisc/kernel/syscall_table.S +++ b/trunk/arch/parisc/kernel/syscall_table.S @@ -66,7 +66,7 @@ ENTRY_SAME(creat) ENTRY_SAME(link) ENTRY_SAME(unlink) /* 10 */ - ENTRY_COMP(execve) + ENTRY_DIFF(execve_wrapper) ENTRY_SAME(chdir) /* See comments in kernel/time.c!!! Maybe we don't need this? */ ENTRY_COMP(time) diff --git a/trunk/arch/s390/Kconfig b/trunk/arch/s390/Kconfig index af431de6363c..5dba755a43e6 100644 --- a/trunk/arch/s390/Kconfig +++ b/trunk/arch/s390/Kconfig @@ -137,7 +137,6 @@ config S390 select KTIME_SCALAR if 32BIT select HAVE_ARCH_SECCOMP_FILTER select GENERIC_KERNEL_THREAD - select GENERIC_KERNEL_EXECVE select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_RELA diff --git a/trunk/arch/s390/include/asm/unistd.h b/trunk/arch/s390/include/asm/unistd.h index ccbcab7742cd..bbbae41fa9a5 100644 --- a/trunk/arch/s390/include/asm/unistd.h +++ b/trunk/arch/s390/include/asm/unistd.h @@ -54,6 +54,7 @@ # define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND # endif #define __ARCH_WANT_SYS_EXECVE +#define __ARCH_WANT_KERNEL_EXECVE /* * "Conditional" syscalls diff --git a/trunk/arch/s390/kernel/entry.S b/trunk/arch/s390/kernel/entry.S index aa8f2ba6289b..ef46f66bc0d6 100644 --- a/trunk/arch/s390/kernel/entry.S +++ b/trunk/arch/s390/kernel/entry.S @@ -330,18 +330,40 @@ ENTRY(ret_from_fork) la %r11,STACK_FRAME_OVERHEAD(%r15) l %r12,__LC_THREAD_INFO l %r13,__LC_SVC_NEW_PSW+4 + tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? + je 1f l %r1,BASED(.Lschedule_tail) basr %r14,%r1 # call schedule_tail TRACE_IRQS_ON ssm __LC_SVC_NEW_PSW # reenable interrupts - tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? - jne sysc_tracenogo - # it's a kernel thread - lm %r9,%r10,__PT_R9(%r11) # load gprs + j sysc_tracenogo + +1: # it's a kernel thread + st %r15,__PT_R15(%r11) # store stack pointer for new kthread + l %r1,BASED(.Lschedule_tail) + basr %r14,%r1 # call schedule_tail + TRACE_IRQS_ON + ssm __LC_SVC_NEW_PSW # reenable interrupts + lm %r9,%r11,__PT_R9(%r11) # load gprs ENTRY(kernel_thread_starter) la %r2,0(%r10) basr %r14,%r9 - j sysc_tracenogo + la %r2,0 + br %r11 # do_exit + +# +# kernel_execve function needs to deal with pt_regs that is not +# at the usual place +# +ENTRY(ret_from_kernel_execve) + ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts + lr %r15,%r2 + lr %r11,%r2 + ahi %r15,-STACK_FRAME_OVERHEAD + xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) + l %r12,__LC_THREAD_INFO + ssm __LC_SVC_NEW_PSW # reenable interrupts + j sysc_return /* * Program check handler routine diff --git a/trunk/arch/s390/kernel/entry64.S b/trunk/arch/s390/kernel/entry64.S index 499e95e90f38..07d8de353984 100644 --- a/trunk/arch/s390/kernel/entry64.S +++ b/trunk/arch/s390/kernel/entry64.S @@ -352,17 +352,33 @@ sysc_tracenogo: ENTRY(ret_from_fork) la %r11,STACK_FRAME_OVERHEAD(%r15) lg %r12,__LC_THREAD_INFO + tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? + je 1f brasl %r14,schedule_tail TRACE_IRQS_ON ssm __LC_SVC_NEW_PSW # reenable interrupts - tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? - jne sysc_tracenogo - # it's a kernel thread - lmg %r9,%r10,__PT_R9(%r11) # load gprs + j sysc_tracenogo +1: # it's a kernel thread + stg %r15,__PT_R15(%r11) # store stack pointer for new kthread + brasl %r14,schedule_tail + TRACE_IRQS_ON + ssm __LC_SVC_NEW_PSW # reenable interrupts + lmg %r9,%r11,__PT_R9(%r11) # load gprs ENTRY(kernel_thread_starter) la %r2,0(%r10) basr %r14,%r9 - j sysc_tracenogo + la %r2,0 + br %r11 # do_exit + +ENTRY(ret_from_kernel_execve) + ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts + lgr %r15,%r2 + lgr %r11,%r2 + aghi %r15,-STACK_FRAME_OVERHEAD + xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) + lg %r12,__LC_THREAD_INFO + ssm __LC_SVC_NEW_PSW # reenable interrupts + j sysc_return /* * Program check handler routine diff --git a/trunk/arch/sparc/include/asm/compat.h b/trunk/arch/sparc/include/asm/compat.h index cef99fbc0a21..830502fe62b4 100644 --- a/trunk/arch/sparc/include/asm/compat.h +++ b/trunk/arch/sparc/include/asm/compat.h @@ -232,9 +232,10 @@ static inline void __user *arch_compat_alloc_user_space(long len) struct pt_regs *regs = current_thread_info()->kregs; unsigned long usp = regs->u_regs[UREG_I6]; - if (!(test_thread_flag(TIF_32BIT))) + if (test_thread_64bit_stack(usp)) usp += STACK_BIAS; - else + + if (test_thread_flag(TIF_32BIT)) usp &= 0xffffffffUL; usp -= len; diff --git a/trunk/arch/sparc/include/asm/thread_info_64.h b/trunk/arch/sparc/include/asm/thread_info_64.h index ea2ba22d595a..269bd92313df 100644 --- a/trunk/arch/sparc/include/asm/thread_info_64.h +++ b/trunk/arch/sparc/include/asm/thread_info_64.h @@ -258,6 +258,11 @@ static inline bool test_and_clear_restore_sigmask(void) #define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG) +#define thread32_stack_is_64bit(__SP) (((__SP) & 0x1) != 0) +#define test_thread_64bit_stack(__SP) \ + ((test_thread_flag(TIF_32BIT) && !thread32_stack_is_64bit(__SP)) ? \ + false : true) + #endif /* !__ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/trunk/arch/sparc/include/asm/ttable.h b/trunk/arch/sparc/include/asm/ttable.h index 48f2807d3265..71b5a67522ab 100644 --- a/trunk/arch/sparc/include/asm/ttable.h +++ b/trunk/arch/sparc/include/asm/ttable.h @@ -372,7 +372,9 @@ etrap_spill_fixup_64bit: \ /* Normal 32bit spill */ #define SPILL_2_GENERIC(ASI) \ - srl %sp, 0, %sp; \ + and %sp, 1, %g3; \ + brnz,pn %g3, (. - (128 + 4)); \ + srl %sp, 0, %sp; \ stwa %l0, [%sp + %g0] ASI; \ mov 0x04, %g3; \ stwa %l1, [%sp + %g3] ASI; \ @@ -398,14 +400,16 @@ etrap_spill_fixup_64bit: \ stwa %i6, [%g1 + %g0] ASI; \ stwa %i7, [%g1 + %g3] ASI; \ saved; \ - retry; nop; nop; \ + retry; \ b,a,pt %xcc, spill_fixup_dax; \ b,a,pt %xcc, spill_fixup_mna; \ b,a,pt %xcc, spill_fixup; #define SPILL_2_GENERIC_ETRAP \ etrap_user_spill_32bit: \ - srl %sp, 0, %sp; \ + and %sp, 1, %g3; \ + brnz,pn %g3, etrap_user_spill_64bit; \ + srl %sp, 0, %sp; \ stwa %l0, [%sp + 0x00] %asi; \ stwa %l1, [%sp + 0x04] %asi; \ stwa %l2, [%sp + 0x08] %asi; \ @@ -427,7 +431,7 @@ etrap_user_spill_32bit: \ ba,pt %xcc, etrap_save; \ wrpr %g1, %cwp; \ nop; nop; nop; nop; \ - nop; nop; nop; nop; \ + nop; nop; \ ba,a,pt %xcc, etrap_spill_fixup_32bit; \ ba,a,pt %xcc, etrap_spill_fixup_32bit; \ ba,a,pt %xcc, etrap_spill_fixup_32bit; @@ -592,7 +596,9 @@ user_rtt_fill_64bit: \ /* Normal 32bit fill */ #define FILL_2_GENERIC(ASI) \ - srl %sp, 0, %sp; \ + and %sp, 1, %g3; \ + brnz,pn %g3, (. - (128 + 4)); \ + srl %sp, 0, %sp; \ lduwa [%sp + %g0] ASI, %l0; \ mov 0x04, %g2; \ mov 0x08, %g3; \ @@ -616,14 +622,16 @@ user_rtt_fill_64bit: \ lduwa [%g1 + %g3] ASI, %i6; \ lduwa [%g1 + %g5] ASI, %i7; \ restored; \ - retry; nop; nop; nop; nop; \ + retry; nop; nop; \ b,a,pt %xcc, fill_fixup_dax; \ b,a,pt %xcc, fill_fixup_mna; \ b,a,pt %xcc, fill_fixup; #define FILL_2_GENERIC_RTRAP \ user_rtt_fill_32bit: \ - srl %sp, 0, %sp; \ + and %sp, 1, %g3; \ + brnz,pn %g3, user_rtt_fill_64bit; \ + srl %sp, 0, %sp; \ lduwa [%sp + 0x00] %asi, %l0; \ lduwa [%sp + 0x04] %asi, %l1; \ lduwa [%sp + 0x08] %asi, %l2; \ @@ -643,7 +651,7 @@ user_rtt_fill_32bit: \ ba,pt %xcc, user_rtt_pre_restore; \ restored; \ nop; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; \ + nop; nop; nop; \ ba,a,pt %xcc, user_rtt_fill_fixup; \ ba,a,pt %xcc, user_rtt_fill_fixup; \ ba,a,pt %xcc, user_rtt_fill_fixup; diff --git a/trunk/arch/sparc/include/uapi/asm/unistd.h b/trunk/arch/sparc/include/uapi/asm/unistd.h index 8974ef7ae920..bed86a820d09 100644 --- a/trunk/arch/sparc/include/uapi/asm/unistd.h +++ b/trunk/arch/sparc/include/uapi/asm/unistd.h @@ -405,8 +405,12 @@ #define __NR_setns 337 #define __NR_process_vm_readv 338 #define __NR_process_vm_writev 339 +#define __NR_kern_features 340 -#define NR_syscalls 340 +#define NR_syscalls 341 + +/* Bitmask values returned from kern_features system call. */ +#define KERN_FEATURE_MIXED_MODE_STACK 0x00000001 #ifdef __32bit_syscall_numbers__ /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, diff --git a/trunk/arch/sparc/kernel/perf_event.c b/trunk/arch/sparc/kernel/perf_event.c index 885a8af74064..b5c38faa4ead 100644 --- a/trunk/arch/sparc/kernel/perf_event.c +++ b/trunk/arch/sparc/kernel/perf_event.c @@ -1762,15 +1762,25 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, ufp = regs->u_regs[UREG_I6] & 0xffffffffUL; do { - struct sparc_stackf32 *usf, sf; unsigned long pc; - usf = (struct sparc_stackf32 *) ufp; - if (__copy_from_user_inatomic(&sf, usf, sizeof(sf))) - break; + if (thread32_stack_is_64bit(ufp)) { + struct sparc_stackf *usf, sf; - pc = sf.callers_pc; - ufp = (unsigned long)sf.fp; + ufp += STACK_BIAS; + usf = (struct sparc_stackf *) ufp; + if (__copy_from_user_inatomic(&sf, usf, sizeof(sf))) + break; + pc = sf.callers_pc & 0xffffffff; + ufp = ((unsigned long) sf.fp) & 0xffffffff; + } else { + struct sparc_stackf32 *usf, sf; + usf = (struct sparc_stackf32 *) ufp; + if (__copy_from_user_inatomic(&sf, usf, sizeof(sf))) + break; + pc = sf.callers_pc; + ufp = (unsigned long)sf.fp; + } perf_callchain_store(entry, pc); } while (entry->nr < PERF_MAX_STACK_DEPTH); } diff --git a/trunk/arch/sparc/kernel/process_64.c b/trunk/arch/sparc/kernel/process_64.c index db5b46a250d2..dff54f46728d 100644 --- a/trunk/arch/sparc/kernel/process_64.c +++ b/trunk/arch/sparc/kernel/process_64.c @@ -452,13 +452,16 @@ void flush_thread(void) /* It's a bit more tricky when 64-bit tasks are involved... */ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp) { + bool stack_64bit = test_thread_64bit_stack(psp); unsigned long fp, distance, rval; - if (!(test_thread_flag(TIF_32BIT))) { + if (stack_64bit) { csp += STACK_BIAS; psp += STACK_BIAS; __get_user(fp, &(((struct reg_window __user *)psp)->ins[6])); fp += STACK_BIAS; + if (test_thread_flag(TIF_32BIT)) + fp &= 0xffffffff; } else __get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6])); @@ -472,7 +475,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp) rval = (csp - distance); if (copy_in_user((void __user *) rval, (void __user *) psp, distance)) rval = 0; - else if (test_thread_flag(TIF_32BIT)) { + else if (!stack_64bit) { if (put_user(((u32)csp), &(((struct reg_window32 __user *)rval)->ins[6]))) rval = 0; @@ -507,18 +510,18 @@ void synchronize_user_stack(void) flush_user_windows(); if ((window = get_thread_wsaved()) != 0) { - int winsize = sizeof(struct reg_window); - int bias = 0; - - if (test_thread_flag(TIF_32BIT)) - winsize = sizeof(struct reg_window32); - else - bias = STACK_BIAS; - window -= 1; do { - unsigned long sp = (t->rwbuf_stkptrs[window] + bias); struct reg_window *rwin = &t->reg_window[window]; + int winsize = sizeof(struct reg_window); + unsigned long sp; + + sp = t->rwbuf_stkptrs[window]; + + if (test_thread_64bit_stack(sp)) + sp += STACK_BIAS; + else + winsize = sizeof(struct reg_window32); if (!copy_to_user((char __user *)sp, rwin, winsize)) { shift_window_buffer(window, get_thread_wsaved() - 1, t); @@ -544,13 +547,6 @@ void fault_in_user_windows(void) { struct thread_info *t = current_thread_info(); unsigned long window; - int winsize = sizeof(struct reg_window); - int bias = 0; - - if (test_thread_flag(TIF_32BIT)) - winsize = sizeof(struct reg_window32); - else - bias = STACK_BIAS; flush_user_windows(); window = get_thread_wsaved(); @@ -558,8 +554,16 @@ void fault_in_user_windows(void) if (likely(window != 0)) { window -= 1; do { - unsigned long sp = (t->rwbuf_stkptrs[window] + bias); struct reg_window *rwin = &t->reg_window[window]; + int winsize = sizeof(struct reg_window); + unsigned long sp; + + sp = t->rwbuf_stkptrs[window]; + + if (test_thread_64bit_stack(sp)) + sp += STACK_BIAS; + else + winsize = sizeof(struct reg_window32); if (unlikely(sp & 0x7UL)) stack_unaligned(sp); diff --git a/trunk/arch/sparc/kernel/ptrace_64.c b/trunk/arch/sparc/kernel/ptrace_64.c index 484dabac7045..7ff45e4ba681 100644 --- a/trunk/arch/sparc/kernel/ptrace_64.c +++ b/trunk/arch/sparc/kernel/ptrace_64.c @@ -151,7 +151,7 @@ static int regwindow64_get(struct task_struct *target, { unsigned long rw_addr = regs->u_regs[UREG_I6]; - if (test_tsk_thread_flag(current, TIF_32BIT)) { + if (!test_thread_64bit_stack(rw_addr)) { struct reg_window32 win32; int i; @@ -176,7 +176,7 @@ static int regwindow64_set(struct task_struct *target, { unsigned long rw_addr = regs->u_regs[UREG_I6]; - if (test_tsk_thread_flag(current, TIF_32BIT)) { + if (!test_thread_64bit_stack(rw_addr)) { struct reg_window32 win32; int i; diff --git a/trunk/arch/sparc/kernel/sys_sparc_64.c b/trunk/arch/sparc/kernel/sys_sparc_64.c index adfe60ece05f..51b85feb8b97 100644 --- a/trunk/arch/sparc/kernel/sys_sparc_64.c +++ b/trunk/arch/sparc/kernel/sys_sparc_64.c @@ -729,3 +729,8 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act, return ret; } + +asmlinkage long sys_kern_features(void) +{ + return KERN_FEATURE_MIXED_MODE_STACK; +} diff --git a/trunk/arch/sparc/kernel/systbls_64.S b/trunk/arch/sparc/kernel/systbls_64.S index acad343667d0..d8b22b3266d0 100644 --- a/trunk/arch/sparc/kernel/systbls_64.S +++ b/trunk/arch/sparc/kernel/systbls_64.S @@ -86,6 +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 #endif /* CONFIG_COMPAT */ @@ -163,3 +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 diff --git a/trunk/arch/sparc/kernel/unaligned_64.c b/trunk/arch/sparc/kernel/unaligned_64.c index f81d038f7340..8201c25e7669 100644 --- a/trunk/arch/sparc/kernel/unaligned_64.c +++ b/trunk/arch/sparc/kernel/unaligned_64.c @@ -113,21 +113,24 @@ static inline long sign_extend_imm13(long imm) static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs) { - unsigned long value; + unsigned long value, fp; if (reg < 16) return (!reg ? 0 : regs->u_regs[reg]); + + fp = regs->u_regs[UREG_FP]; + if (regs->tstate & TSTATE_PRIV) { struct reg_window *win; - win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window *)(fp + STACK_BIAS); value = win->locals[reg - 16]; - } else if (test_thread_flag(TIF_32BIT)) { + } else if (!test_thread_64bit_stack(fp)) { struct reg_window32 __user *win32; - win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); + win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp)); get_user(value, &win32->locals[reg - 16]); } else { struct reg_window __user *win; - win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window __user *)(fp + STACK_BIAS); get_user(value, &win->locals[reg - 16]); } return value; @@ -135,19 +138,24 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs) static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs) { + unsigned long fp; + if (reg < 16) return ®s->u_regs[reg]; + + fp = regs->u_regs[UREG_FP]; + if (regs->tstate & TSTATE_PRIV) { struct reg_window *win; - win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window *)(fp + STACK_BIAS); return &win->locals[reg - 16]; - } else if (test_thread_flag(TIF_32BIT)) { + } else if (!test_thread_64bit_stack(fp)) { struct reg_window32 *win32; - win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP])); + win32 = (struct reg_window32 *)((unsigned long)((u32)fp)); return (unsigned long *)&win32->locals[reg - 16]; } else { struct reg_window *win; - win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window *)(fp + STACK_BIAS); return &win->locals[reg - 16]; } } @@ -392,13 +400,15 @@ int handle_popc(u32 insn, struct pt_regs *regs) if (rd) regs->u_regs[rd] = ret; } else { - if (test_thread_flag(TIF_32BIT)) { + unsigned long fp = regs->u_regs[UREG_FP]; + + if (!test_thread_64bit_stack(fp)) { struct reg_window32 __user *win32; - win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); + win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp)); put_user(ret, &win32->locals[rd - 16]); } else { struct reg_window __user *win; - win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window __user *)(fp + STACK_BIAS); put_user(ret, &win->locals[rd - 16]); } } @@ -554,7 +564,7 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs) reg[0] = 0; if ((insn & 0x780000) == 0x180000) reg[1] = 0; - } else if (test_thread_flag(TIF_32BIT)) { + } else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) { put_user(0, (int __user *) reg); if ((insn & 0x780000) == 0x180000) put_user(0, ((int __user *) reg) + 1); diff --git a/trunk/arch/sparc/kernel/visemul.c b/trunk/arch/sparc/kernel/visemul.c index 08e074b7eb6a..c096c624ac4d 100644 --- a/trunk/arch/sparc/kernel/visemul.c +++ b/trunk/arch/sparc/kernel/visemul.c @@ -149,21 +149,24 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2, static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs) { - unsigned long value; + unsigned long value, fp; if (reg < 16) return (!reg ? 0 : regs->u_regs[reg]); + + fp = regs->u_regs[UREG_FP]; + if (regs->tstate & TSTATE_PRIV) { struct reg_window *win; - win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window *)(fp + STACK_BIAS); value = win->locals[reg - 16]; - } else if (test_thread_flag(TIF_32BIT)) { + } else if (!test_thread_64bit_stack(fp)) { struct reg_window32 __user *win32; - win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); + win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp)); get_user(value, &win32->locals[reg - 16]); } else { struct reg_window __user *win; - win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window __user *)(fp + STACK_BIAS); get_user(value, &win->locals[reg - 16]); } return value; @@ -172,16 +175,18 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs) static inline unsigned long __user *__fetch_reg_addr_user(unsigned int reg, struct pt_regs *regs) { + unsigned long fp = regs->u_regs[UREG_FP]; + BUG_ON(reg < 16); BUG_ON(regs->tstate & TSTATE_PRIV); - if (test_thread_flag(TIF_32BIT)) { + if (!test_thread_64bit_stack(fp)) { struct reg_window32 __user *win32; - win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); + win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp)); return (unsigned long __user *)&win32->locals[reg - 16]; } else { struct reg_window __user *win; - win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window __user *)(fp + STACK_BIAS); return &win->locals[reg - 16]; } } @@ -204,7 +209,7 @@ static void store_reg(struct pt_regs *regs, unsigned long val, unsigned long rd) } else { unsigned long __user *rd_user = __fetch_reg_addr_user(rd, regs); - if (test_thread_flag(TIF_32BIT)) + if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) __put_user((u32)val, (u32 __user *)rd_user); else __put_user(val, rd_user); diff --git a/trunk/arch/sparc/kernel/winfixup.S b/trunk/arch/sparc/kernel/winfixup.S index a6b0863c27df..1e67ce958369 100644 --- a/trunk/arch/sparc/kernel/winfixup.S +++ b/trunk/arch/sparc/kernel/winfixup.S @@ -43,6 +43,8 @@ spill_fixup_mna: spill_fixup_dax: TRAP_LOAD_THREAD_REG(%g6, %g1) ldx [%g6 + TI_FLAGS], %g1 + andcc %sp, 0x1, %g0 + movne %icc, 0, %g1 andcc %g1, _TIF_32BIT, %g0 ldub [%g6 + TI_WSAVED], %g1 sll %g1, 3, %g3 diff --git a/trunk/arch/sparc/math-emu/math_64.c b/trunk/arch/sparc/math-emu/math_64.c index 1704068da928..034aadbff036 100644 --- a/trunk/arch/sparc/math-emu/math_64.c +++ b/trunk/arch/sparc/math-emu/math_64.c @@ -320,7 +320,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap) XR = 0; else if (freg < 16) XR = regs->u_regs[freg]; - else if (test_thread_flag(TIF_32BIT)) { + else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) { struct reg_window32 __user *win32; flushw_user (); win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); diff --git a/trunk/arch/tile/Kconfig b/trunk/arch/tile/Kconfig index ea7f61e8bc9e..875d008828b8 100644 --- a/trunk/arch/tile/Kconfig +++ b/trunk/arch/tile/Kconfig @@ -21,8 +21,6 @@ config TILE select ARCH_HAVE_NMI_SAFE_CMPXCHG select GENERIC_CLOCKEVENTS select MODULES_USE_ELF_RELA - select GENERIC_KERNEL_THREAD - select GENERIC_KERNEL_EXECVE # FIXME: investigate whether we need/want these options. # select HAVE_IOREMAP_PROT diff --git a/trunk/arch/tile/include/asm/compat.h b/trunk/arch/tile/include/asm/compat.h index ca61fb4296b3..3063e6fc8daa 100644 --- a/trunk/arch/tile/include/asm/compat.h +++ b/trunk/arch/tile/include/asm/compat.h @@ -275,14 +275,18 @@ extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka, struct compat_sigaction; struct compat_siginfo; struct compat_sigaltstack; +long compat_sys_execve(const char __user *path, + compat_uptr_t __user *argv, + compat_uptr_t __user *envp, struct pt_regs *); long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, struct compat_sigaction __user *oact, size_t sigsetsize); long compat_sys_rt_sigqueueinfo(int pid, int sig, struct compat_siginfo __user *uinfo); -long compat_sys_rt_sigreturn(void); +long compat_sys_rt_sigreturn(struct pt_regs *); long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, - struct compat_sigaltstack __user *uoss_ptr); + struct compat_sigaltstack __user *uoss_ptr, + struct pt_regs *); long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high); long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high); long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count, @@ -299,7 +303,12 @@ long compat_sys_fallocate(int fd, int mode, long compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval); -/* Assembly trampoline to avoid clobbering r0. */ +/* These are the intvec_64.S trampolines. */ +long _compat_sys_execve(const char __user *path, + const compat_uptr_t __user *argv, + const compat_uptr_t __user *envp); +long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, + struct compat_sigaltstack __user *uoss_ptr); long _compat_sys_rt_sigreturn(void); #endif /* _ASM_TILE_COMPAT_H */ diff --git a/trunk/arch/tile/include/asm/elf.h b/trunk/arch/tile/include/asm/elf.h index b73e1039c911..f8ccf08f6934 100644 --- a/trunk/arch/tile/include/asm/elf.h +++ b/trunk/arch/tile/include/asm/elf.h @@ -148,7 +148,6 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm, #define compat_start_thread(regs, ip, usp) do { \ regs->pc = ptr_to_compat_reg((void *)(ip)); \ regs->sp = ptr_to_compat_reg((void *)(usp)); \ - single_step_execve(); \ } while (0) /* diff --git a/trunk/arch/tile/include/asm/processor.h b/trunk/arch/tile/include/asm/processor.h index 879073e76586..8c4dd9ff91eb 100644 --- a/trunk/arch/tile/include/asm/processor.h +++ b/trunk/arch/tile/include/asm/processor.h @@ -211,7 +211,6 @@ static inline void start_thread(struct pt_regs *regs, { regs->pc = pc; regs->sp = usp; - single_step_execve(); } /* Free all resources held by a thread. */ @@ -240,9 +239,6 @@ unsigned long get_wchan(struct task_struct *p); #define KSTK_TOP(task) (task_ksp0(task) - STACK_TOP_DELTA) #define task_pt_regs(task) \ ((struct pt_regs *)(task_ksp0(task) - KSTK_PTREGS_GAP) - 1) -#define current_pt_regs() \ - ((struct pt_regs *)((stack_pointer | (THREAD_SIZE - 1)) - \ - (KSTK_PTREGS_GAP - 1)) - 1) #define task_sp(task) (task_pt_regs(task)->sp) #define task_pc(task) (task_pt_regs(task)->pc) /* Aliases for pc and sp (used in fs/proc/array.c) */ diff --git a/trunk/arch/tile/include/asm/switch_to.h b/trunk/arch/tile/include/asm/switch_to.h index b8f888cbe6b0..1d48c5fee8b7 100644 --- a/trunk/arch/tile/include/asm/switch_to.h +++ b/trunk/arch/tile/include/asm/switch_to.h @@ -68,10 +68,7 @@ extern unsigned long get_switch_to_pc(void); /* Support function for forking a new task. */ void ret_from_fork(void); -/* Support function for forking a new kernel thread. */ -void ret_from_kernel_thread(void *fn, void *arg); - -/* Called from ret_from_xxx() when a new process starts up. */ +/* Called from ret_from_fork() when a new process starts up. */ struct task_struct *sim_notify_fork(struct task_struct *prev); #endif /* !__ASSEMBLY__ */ diff --git a/trunk/arch/tile/include/asm/syscalls.h b/trunk/arch/tile/include/asm/syscalls.h index 369696d63e7b..06f0464cfed9 100644 --- a/trunk/arch/tile/include/asm/syscalls.h +++ b/trunk/arch/tile/include/asm/syscalls.h @@ -51,7 +51,8 @@ long sys_cacheflush(unsigned long addr, unsigned long len, #ifndef __tilegx__ /* mm/fault.c */ -long sys_cmpxchg_badaddr(unsigned long address); +long sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *); +long _sys_cmpxchg_badaddr(unsigned long address); #endif #ifdef CONFIG_COMPAT @@ -62,23 +63,14 @@ long sys_truncate64(const char __user *path, loff_t length); long sys_ftruncate64(unsigned int fd, loff_t length); #endif -/* Provide versions of standard syscalls that use current_pt_regs(). */ -long sys_clone(unsigned long clone_flags, unsigned long newsp, - void __user *parent_tid, void __user *child_tid); -long sys_execve(const char __user *filename, - const char __user *const __user *argv, - const char __user *const __user *envp); -long sys_rt_sigreturn(void); -long sys_sigaltstack(const stack_t __user *, stack_t __user *); -#define sys_clone sys_clone -#define sys_execve sys_execve -#define sys_rt_sigreturn sys_rt_sigreturn -#define sys_sigaltstack sys_sigaltstack - /* These are the intvec*.S trampolines. */ +long _sys_sigaltstack(const stack_t __user *, stack_t __user *); long _sys_rt_sigreturn(void); long _sys_clone(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, void __user *child_tid); +long _sys_execve(const char __user *filename, + const char __user *const __user *argv, + const char __user *const __user *envp); #include diff --git a/trunk/arch/tile/include/asm/unistd.h b/trunk/arch/tile/include/asm/unistd.h index dab827dc8acb..6e032a0a268e 100644 --- a/trunk/arch/tile/include/asm/unistd.h +++ b/trunk/arch/tile/include/asm/unistd.h @@ -16,5 +16,4 @@ #define __ARCH_WANT_SYS_LLSEEK #endif #define __ARCH_WANT_SYS_NEWFSTATAT -#define __ARCH_WANT_SYS_EXECVE #include diff --git a/trunk/arch/tile/kernel/compat.c b/trunk/arch/tile/kernel/compat.c index a2e805569d5d..d67459b9ac2a 100644 --- a/trunk/arch/tile/kernel/compat.c +++ b/trunk/arch/tile/kernel/compat.c @@ -102,9 +102,10 @@ long compat_sys_sched_rr_get_interval(compat_pid_t pid, #define compat_sys_fadvise64_64 sys32_fadvise64_64 #define compat_sys_readahead sys32_readahead -/* Call the assembly trampolines where necessary. */ +/* Call the trampolines to manage pt_regs where necessary. */ +#define compat_sys_execve _compat_sys_execve +#define compat_sys_sigaltstack _compat_sys_sigaltstack #define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn -#undef sys_clone #define sys_clone _sys_clone /* diff --git a/trunk/arch/tile/kernel/compat_signal.c b/trunk/arch/tile/kernel/compat_signal.c index 210a9bbae963..08b4fe1717bb 100644 --- a/trunk/arch/tile/kernel/compat_signal.c +++ b/trunk/arch/tile/kernel/compat_signal.c @@ -197,7 +197,8 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from) } long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, - struct compat_sigaltstack __user *uoss_ptr) + struct compat_sigaltstack __user *uoss_ptr, + struct pt_regs *regs) { stack_t uss, uoss; int ret; @@ -218,7 +219,7 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, set_fs(KERNEL_DS); ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL, (stack_t __user __force *)&uoss, - (unsigned long)compat_ptr(current_pt_regs()->sp)); + (unsigned long)compat_ptr(regs->sp)); set_fs(seg); if (ret >= 0 && uoss_ptr) { if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) || @@ -231,9 +232,8 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, } /* The assembly shim for this function arranges to ignore the return value. */ -long compat_sys_rt_sigreturn(void) +long compat_sys_rt_sigreturn(struct pt_regs *regs) { - struct pt_regs *regs = current_pt_regs(); struct compat_rt_sigframe __user *frame = (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); sigset_t set; @@ -248,7 +248,7 @@ long compat_sys_rt_sigreturn(void) if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) goto badframe; - if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL) != 0) + if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) goto badframe; return 0; diff --git a/trunk/arch/tile/kernel/entry.S b/trunk/arch/tile/kernel/entry.S index f116cb0bce20..c31637baff28 100644 --- a/trunk/arch/tile/kernel/entry.S +++ b/trunk/arch/tile/kernel/entry.S @@ -27,6 +27,17 @@ STD_ENTRY(current_text_addr) { move r0, lr; jrp lr } STD_ENDPROC(current_text_addr) +/* + * Implement execve(). The i386 code has a note that forking from kernel + * space results in no copy on write until the execve, so we should be + * careful not to write to the stack here. + */ +STD_ENTRY(kernel_execve) + moveli TREG_SYSCALL_NR_NAME, __NR_execve + swint1 + jrp lr + STD_ENDPROC(kernel_execve) + /* * We don't run this function directly, but instead copy it to a page * we map into every user process. See vdso_setup(). diff --git a/trunk/arch/tile/kernel/intvec_32.S b/trunk/arch/tile/kernel/intvec_32.S index f212bf7cea86..6943515100f8 100644 --- a/trunk/arch/tile/kernel/intvec_32.S +++ b/trunk/arch/tile/kernel/intvec_32.S @@ -1291,21 +1291,6 @@ STD_ENTRY(ret_from_fork) } STD_ENDPROC(ret_from_fork) -STD_ENTRY(ret_from_kernel_thread) - jal sim_notify_fork - jal schedule_tail - FEEDBACK_REENTER(ret_from_fork) - { - move r0, r31 - jalr r30 - } - FEEDBACK_REENTER(ret_from_kernel_thread) - { - movei r30, 0 /* not an NMI */ - j .Lresume_userspace /* jump into middle of interrupt_return */ - } - STD_ENDPROC(ret_from_kernel_thread) - /* * Code for ill interrupt. */ @@ -1452,6 +1437,15 @@ STD_ENTRY_LOCAL(bad_intr) panic "Unhandled interrupt %#x: PC %#lx" STD_ENDPROC(bad_intr) +/* Put address of pt_regs in reg and jump. */ +#define PTREGS_SYSCALL(x, reg) \ + STD_ENTRY(_##x); \ + { \ + PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ + j x \ + }; \ + STD_ENDPROC(_##x) + /* * Special-case sigreturn to not write r0 to the stack on return. * This is technically more efficient, but it also avoids difficulties @@ -1467,9 +1461,12 @@ STD_ENTRY_LOCAL(bad_intr) }; \ STD_ENDPROC(_##x) +PTREGS_SYSCALL(sys_execve, r3) +PTREGS_SYSCALL(sys_sigaltstack, r2) PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) +PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1) -/* Save additional callee-saves to pt_regs and jump to standard function. */ +/* Save additional callee-saves to pt_regs, put address in r4 and jump. */ STD_ENTRY(_sys_clone) push_extra_callee_saves r4 j sys_clone diff --git a/trunk/arch/tile/kernel/intvec_64.S b/trunk/arch/tile/kernel/intvec_64.S index 54bc9a6678e8..7c06d597ffd0 100644 --- a/trunk/arch/tile/kernel/intvec_64.S +++ b/trunk/arch/tile/kernel/intvec_64.S @@ -1150,21 +1150,6 @@ STD_ENTRY(ret_from_fork) } STD_ENDPROC(ret_from_fork) -STD_ENTRY(ret_from_kernel_thread) - jal sim_notify_fork - jal schedule_tail - FEEDBACK_REENTER(ret_from_fork) - { - move r0, r31 - jalr r30 - } - FEEDBACK_REENTER(ret_from_kernel_thread) - { - movei r30, 0 /* not an NMI */ - j .Lresume_userspace /* jump into middle of interrupt_return */ - } - STD_ENDPROC(ret_from_kernel_thread) - /* Various stub interrupt handlers and syscall handlers */ STD_ENTRY_LOCAL(_kernel_double_fault) @@ -1181,6 +1166,15 @@ STD_ENTRY_LOCAL(bad_intr) panic "Unhandled interrupt %#x: PC %#lx" STD_ENDPROC(bad_intr) +/* Put address of pt_regs in reg and jump. */ +#define PTREGS_SYSCALL(x, reg) \ + STD_ENTRY(_##x); \ + { \ + PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ + j x \ + }; \ + STD_ENDPROC(_##x) + /* * Special-case sigreturn to not write r0 to the stack on return. * This is technically more efficient, but it also avoids difficulties @@ -1196,12 +1190,16 @@ STD_ENTRY_LOCAL(bad_intr) }; \ STD_ENDPROC(_##x) +PTREGS_SYSCALL(sys_execve, r3) +PTREGS_SYSCALL(sys_sigaltstack, r2) PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) #ifdef CONFIG_COMPAT +PTREGS_SYSCALL(compat_sys_execve, r3) +PTREGS_SYSCALL(compat_sys_sigaltstack, r2) PTREGS_SYSCALL_SIGRETURN(compat_sys_rt_sigreturn, r0) #endif -/* Save additional callee-saves to pt_regs and jump to standard function. */ +/* Save additional callee-saves to pt_regs, put address in r4 and jump. */ STD_ENTRY(_sys_clone) push_extra_callee_saves r4 j sys_clone diff --git a/trunk/arch/tile/kernel/process.c b/trunk/arch/tile/kernel/process.c index 1c20029d2f5a..307d010696c9 100644 --- a/trunk/arch/tile/kernel/process.c +++ b/trunk/arch/tile/kernel/process.c @@ -157,44 +157,24 @@ void arch_release_thread_info(struct thread_info *info) static void save_arch_state(struct thread_struct *t); int copy_thread(unsigned long clone_flags, unsigned long sp, - unsigned long arg, - struct task_struct *p, struct pt_regs *unused) + unsigned long stack_size, + struct task_struct *p, struct pt_regs *regs) { - struct pt_regs *childregs = task_pt_regs(p); + struct pt_regs *childregs; unsigned long ksp; - unsigned long *callee_regs; /* - * Set up the stack and stack pointer appropriately for the - * new child to find itself woken up in __switch_to(). - * The callee-saved registers must be on the stack to be read; - * the new task will then jump to assembly support to handle - * calling schedule_tail(), etc., and (for userspace tasks) - * returning to the context set up in the pt_regs. + * When creating a new kernel thread we pass sp as zero. + * Assign it to a reasonable value now that we have the stack. */ - ksp = (unsigned long) childregs; - ksp -= C_ABI_SAVE_AREA_SIZE; /* interrupt-entry save area */ - ((long *)ksp)[0] = ((long *)ksp)[1] = 0; - ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long); - callee_regs = (unsigned long *)ksp; - ksp -= C_ABI_SAVE_AREA_SIZE; /* __switch_to() save area */ - ((long *)ksp)[0] = ((long *)ksp)[1] = 0; - p->thread.ksp = ksp; + if (sp == 0 && regs->ex1 == PL_ICS_EX1(KERNEL_PL, 0)) + sp = KSTK_TOP(p); - /* Record the pid of the task that created this one. */ - p->thread.creator_pid = current->pid; - - if (unlikely(p->flags & PF_KTHREAD)) { - /* kernel thread */ - memset(childregs, 0, sizeof(struct pt_regs)); - memset(&callee_regs[2], 0, - (CALLEE_SAVED_REGS_COUNT - 2) * sizeof(unsigned long)); - callee_regs[0] = sp; /* r30 = function */ - callee_regs[1] = arg; /* r31 = arg */ - childregs->ex1 = PL_ICS_EX1(KERNEL_PL, 0); - p->thread.pc = (unsigned long) ret_from_kernel_thread; - return 0; - } + /* + * Do not clone step state from the parent; each thread + * must make its own lazily. + */ + task_thread_info(p)->step_state = NULL; /* * Start new thread in ret_from_fork so it schedules properly @@ -202,33 +182,46 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, */ p->thread.pc = (unsigned long) ret_from_fork; - /* - * Do not clone step state from the parent; each thread - * must make its own lazily. - */ - task_thread_info(p)->step_state = NULL; + /* Save user stack top pointer so we can ID the stack vm area later. */ + p->thread.usp0 = sp; + + /* Record the pid of the process that created this one. */ + p->thread.creator_pid = current->pid; /* * Copy the registers onto the kernel stack so the * return-from-interrupt code will reload it into registers. */ - *childregs = *current_pt_regs(); + childregs = task_pt_regs(p); + *childregs = *regs; childregs->regs[0] = 0; /* return value is zero */ - if (sp) - childregs->sp = sp; /* override with new user stack pointer */ - memcpy(callee_regs, &childregs->regs[CALLEE_SAVED_FIRST_REG], - CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long)); - - /* Save user stack top pointer so we can ID the stack vm area later. */ - p->thread.usp0 = childregs->sp; + childregs->sp = sp; /* override with new user stack pointer */ /* * If CLONE_SETTLS is set, set "tp" in the new task to "r4", * which is passed in as arg #5 to sys_clone(). */ if (clone_flags & CLONE_SETTLS) - childregs->tp = childregs->regs[4]; + childregs->tp = regs->regs[4]; + /* + * Copy the callee-saved registers from the passed pt_regs struct + * into the context-switch callee-saved registers area. + * This way when we start the interrupt-return sequence, the + * callee-save registers will be correctly in registers, which + * is how we assume the compiler leaves them as we start doing + * the normal return-from-interrupt path after calling C code. + * Zero out the C ABI save area to mark the top of the stack. + */ + ksp = (unsigned long) childregs; + ksp -= C_ABI_SAVE_AREA_SIZE; /* interrupt-entry save area */ + ((long *)ksp)[0] = ((long *)ksp)[1] = 0; + ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long); + memcpy((void *)ksp, ®s->regs[CALLEE_SAVED_FIRST_REG], + CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long)); + ksp -= C_ABI_SAVE_AREA_SIZE; /* __switch_to() save area */ + ((long *)ksp)[0] = ((long *)ksp)[1] = 0; + p->thread.ksp = ksp; #if CHIP_HAS_TILE_DMA() /* @@ -585,13 +578,61 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags) } /* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */ -SYSCALL_DEFINE4(clone, unsigned long, clone_flags, unsigned long, newsp, - void __user *, parent_tidptr, void __user *, child_tidptr) +SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, + void __user *, parent_tidptr, void __user *, child_tidptr, + struct pt_regs *, regs) { - return do_fork(clone_flags, newsp, current_pt_regs(), 0, + if (!newsp) + newsp = regs->sp; + return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); } +/* + * sys_execve() executes a new program. + */ +SYSCALL_DEFINE4(execve, const char __user *, path, + const char __user *const __user *, argv, + const char __user *const __user *, envp, + struct pt_regs *, regs) +{ + long error; + struct filename *filename; + + filename = getname(path); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = do_execve(filename->name, argv, envp, regs); + putname(filename); + if (error == 0) + single_step_execve(); +out: + return error; +} + +#ifdef CONFIG_COMPAT +long compat_sys_execve(const char __user *path, + compat_uptr_t __user *argv, + compat_uptr_t __user *envp, + struct pt_regs *regs) +{ + long error; + struct filename *filename; + + filename = getname(path); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = compat_do_execve(filename->name, argv, envp, regs); + putname(filename); + if (error == 0) + single_step_execve(); +out: + return error; +} +#endif + unsigned long get_wchan(struct task_struct *p) { struct KBacktraceIterator kbt; @@ -609,6 +650,37 @@ unsigned long get_wchan(struct task_struct *p) return 0; } +/* + * We pass in lr as zero (cleared in kernel_thread) and the caller + * part of the backtrace ABI on the stack also zeroed (in copy_thread) + * so that backtraces will stop with this function. + * Note that we don't use r0, since copy_thread() clears it. + */ +static void start_kernel_thread(int dummy, int (*fn)(int), int arg) +{ + do_exit(fn(arg)); +} + +/* + * Create a kernel thread + */ +int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + struct pt_regs regs; + + memset(®s, 0, sizeof(regs)); + regs.ex1 = PL_ICS_EX1(KERNEL_PL, 0); /* run at kernel PL, no ICS */ + regs.pc = (long) start_kernel_thread; + regs.flags = PT_FLAGS_CALLER_SAVES; /* need to restore r1 and r2 */ + regs.regs[1] = (long) fn; /* function pointer */ + regs.regs[2] = (long) arg; /* parameter register */ + + /* Ok, create the new process.. */ + return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, + 0, NULL, NULL); +} +EXPORT_SYMBOL(kernel_thread); + /* Flush thread state. */ void flush_thread(void) { diff --git a/trunk/arch/tile/kernel/signal.c b/trunk/arch/tile/kernel/signal.c index 657a7ace4ab4..67efb656d104 100644 --- a/trunk/arch/tile/kernel/signal.c +++ b/trunk/arch/tile/kernel/signal.c @@ -37,10 +37,10 @@ #define DEBUG_SIG 0 -SYSCALL_DEFINE2(sigaltstack, const stack_t __user *, uss, - stack_t __user *, uoss) +SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss, + stack_t __user *, uoss, struct pt_regs *, regs) { - return do_sigaltstack(uss, uoss, current_pt_regs()->sp); + return do_sigaltstack(uss, uoss, regs->sp); } @@ -83,9 +83,8 @@ void signal_fault(const char *type, struct pt_regs *regs, } /* The assembly shim for this function arranges to ignore the return value. */ -SYSCALL_DEFINE0(rt_sigreturn) +SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) { - struct pt_regs *regs = current_pt_regs(); struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(regs->sp); sigset_t set; diff --git a/trunk/arch/tile/kernel/sys.c b/trunk/arch/tile/kernel/sys.c index 02ff5c0ef775..b08095b402d6 100644 --- a/trunk/arch/tile/kernel/sys.c +++ b/trunk/arch/tile/kernel/sys.c @@ -106,11 +106,14 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, #define sys_readahead sys32_readahead #endif -/* Call the assembly trampolines where necessary. */ -#undef sys_rt_sigreturn +/* Call the trampolines to manage pt_regs where necessary. */ +#define sys_execve _sys_execve +#define sys_sigaltstack _sys_sigaltstack #define sys_rt_sigreturn _sys_rt_sigreturn -#undef sys_clone #define sys_clone _sys_clone +#ifndef __tilegx__ +#define sys_cmpxchg_badaddr _sys_cmpxchg_badaddr +#endif /* * Note that we can't include here since the header diff --git a/trunk/arch/tile/mm/fault.c b/trunk/arch/tile/mm/fault.c index 3d2b81c163a6..fe811fa5f1b9 100644 --- a/trunk/arch/tile/mm/fault.c +++ b/trunk/arch/tile/mm/fault.c @@ -70,10 +70,9 @@ static noinline void force_sig_info_fault(const char *type, int si_signo, * Synthesize the fault a PL0 process would get by doing a word-load of * an unaligned address or a high kernel address. */ -SYSCALL_DEFINE1(cmpxchg_badaddr, unsigned long, address) +SYSCALL_DEFINE2(cmpxchg_badaddr, unsigned long, address, + struct pt_regs *, regs) { - struct pt_regs *regs = current_pt_regs(); - if (address >= PAGE_OFFSET) force_sig_info_fault("atomic segfault", SIGSEGV, SEGV_MAPERR, address, INT_DTLB_MISS, current, regs); diff --git a/trunk/arch/x86/kvm/x86.c b/trunk/arch/x86/kvm/x86.c index 224a7e78cb6c..1eefebe5d727 100644 --- a/trunk/arch/x86/kvm/x86.c +++ b/trunk/arch/x86/kvm/x86.c @@ -3779,7 +3779,7 @@ static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, { struct kvm_mmio_fragment *frag = &vcpu->mmio_fragments[0]; - memcpy(vcpu->run->mmio.data, frag->data, min(8u, frag->len)); + memcpy(vcpu->run->mmio.data, frag->data, frag->len); return X86EMUL_CONTINUE; } @@ -3832,11 +3832,18 @@ static int emulator_read_write_onepage(unsigned long addr, void *val, bytes -= handled; val += handled; - WARN_ON(vcpu->mmio_nr_fragments >= KVM_MAX_MMIO_FRAGMENTS); - frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++]; - frag->gpa = gpa; - frag->data = val; - frag->len = bytes; + while (bytes) { + unsigned now = min(bytes, 8U); + + frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++]; + frag->gpa = gpa; + frag->data = val; + frag->len = now; + + gpa += now; + val += now; + bytes -= now; + } return X86EMUL_CONTINUE; } @@ -3883,7 +3890,7 @@ int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr, vcpu->mmio_needed = 1; vcpu->mmio_cur_fragment = 0; - vcpu->run->mmio.len = min(8u, vcpu->mmio_fragments[0].len); + vcpu->run->mmio.len = vcpu->mmio_fragments[0].len; vcpu->run->mmio.is_write = vcpu->mmio_is_write = ops->write; vcpu->run->exit_reason = KVM_EXIT_MMIO; vcpu->run->mmio.phys_addr = gpa; @@ -5515,44 +5522,28 @@ static int complete_emulated_pio(struct kvm_vcpu *vcpu) * * read: * for each fragment - * for each mmio piece in the fragment - * write gpa, len - * exit - * copy data + * write gpa, len + * exit + * copy data * execute insn * * write: * for each fragment - * for each mmio piece in the fragment - * write gpa, len - * copy data - * exit + * write gpa, len + * copy data + * exit */ static int complete_emulated_mmio(struct kvm_vcpu *vcpu) { struct kvm_run *run = vcpu->run; struct kvm_mmio_fragment *frag; - unsigned len; BUG_ON(!vcpu->mmio_needed); /* Complete previous fragment */ - frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment]; - len = min(8u, frag->len); + frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment++]; if (!vcpu->mmio_is_write) - memcpy(frag->data, run->mmio.data, len); - - if (frag->len <= 8) { - /* Switch to the next fragment. */ - frag++; - vcpu->mmio_cur_fragment++; - } else { - /* Go forward to the next mmio piece. */ - frag->data += len; - frag->gpa += len; - frag->len -= len; - } - + memcpy(frag->data, run->mmio.data, frag->len); if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) { vcpu->mmio_needed = 0; if (vcpu->mmio_is_write) @@ -5560,12 +5551,13 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu) vcpu->mmio_read_completed = 1; return complete_emulated_io(vcpu); } - + /* Initiate next fragment */ + ++frag; run->exit_reason = KVM_EXIT_MMIO; run->mmio.phys_addr = frag->gpa; if (vcpu->mmio_is_write) - memcpy(run->mmio.data, frag->data, min(8u, frag->len)); - run->mmio.len = min(8u, frag->len); + memcpy(run->mmio.data, frag->data, frag->len); + run->mmio.len = frag->len; run->mmio.is_write = vcpu->mmio_is_write; vcpu->arch.complete_userspace_io = complete_emulated_mmio; return 0; diff --git a/trunk/arch/xtensa/Kconfig b/trunk/arch/xtensa/Kconfig index 0d1f36a22c98..cdcb48adee4c 100644 --- a/trunk/arch/xtensa/Kconfig +++ b/trunk/arch/xtensa/Kconfig @@ -13,8 +13,6 @@ config XTENSA select GENERIC_CPU_DEVICES select MODULES_USE_ELF_RELA select GENERIC_PCI_IOMAP - select GENERIC_KERNEL_THREAD - select GENERIC_KERNEL_EXECVE select ARCH_WANT_OPTIONAL_GPIOLIB help Xtensa processors are 32-bit RISC machines designed by Tensilica diff --git a/trunk/arch/xtensa/include/asm/io.h b/trunk/arch/xtensa/include/asm/io.h index 700c2e6f2d25..e6be5b9091c2 100644 --- a/trunk/arch/xtensa/include/asm/io.h +++ b/trunk/arch/xtensa/include/asm/io.h @@ -62,10 +62,6 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size) static inline void iounmap(volatile void __iomem *addr) { } - -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt - #endif /* CONFIG_MMU */ /* diff --git a/trunk/arch/xtensa/include/asm/processor.h b/trunk/arch/xtensa/include/asm/processor.h index 2d630e7399ca..5c371d8d4528 100644 --- a/trunk/arch/xtensa/include/asm/processor.h +++ b/trunk/arch/xtensa/include/asm/processor.h @@ -152,7 +152,6 @@ struct thread_struct { /* Clearing a0 terminates the backtrace. */ #define start_thread(regs, new_pc, new_sp) \ - memset(regs, 0, sizeof(*regs)); \ regs->pc = new_pc; \ regs->ps = USER_PS_VALUE; \ regs->areg[1] = new_sp; \ @@ -169,6 +168,9 @@ struct mm_struct; /* Free all resources held by a thread. */ #define release_thread(thread) do { } while(0) +/* Create a kernel thread without removing it from tasklists */ +extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); + /* Copy and release all segment info associated with a VM */ #define copy_segments(p, mm) do { } while(0) #define release_segments(mm) do { } while(0) diff --git a/trunk/arch/xtensa/include/asm/syscall.h b/trunk/arch/xtensa/include/asm/syscall.h index 124aeee0d381..c1dacca312f3 100644 --- a/trunk/arch/xtensa/include/asm/syscall.h +++ b/trunk/arch/xtensa/include/asm/syscall.h @@ -10,7 +10,7 @@ struct pt_regs; struct sigaction; -asmlinkage long sys_execve(char*, char**, char**, struct pt_regs*); +asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*); asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*); asmlinkage long xtensa_ptrace(long, long, long, long); asmlinkage long xtensa_sigreturn(struct pt_regs*); diff --git a/trunk/arch/xtensa/include/asm/unistd.h b/trunk/arch/xtensa/include/asm/unistd.h index f4e6eaa40d1c..9ef1c31d2c83 100644 --- a/trunk/arch/xtensa/include/asm/unistd.h +++ b/trunk/arch/xtensa/include/asm/unistd.h @@ -1,9 +1,16 @@ -#ifndef _XTENSA_UNISTD_H -#define _XTENSA_UNISTD_H +/* + * include/asm-xtensa/unistd.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2001 - 2005 Tensilica Inc. + */ -#define __ARCH_WANT_SYS_EXECVE #include + /* * "Conditional" syscalls * @@ -30,5 +37,3 @@ #define __IGNORE_mmap /* use mmap2 */ #define __IGNORE_vfork /* use clone */ #define __IGNORE_fadvise64 /* use fadvise64_64 */ - -#endif /* _XTENSA_UNISTD_H */ diff --git a/trunk/arch/xtensa/include/uapi/asm/unistd.h b/trunk/arch/xtensa/include/uapi/asm/unistd.h index 9f36d0e3e0ac..479abaea5aae 100644 --- a/trunk/arch/xtensa/include/uapi/asm/unistd.h +++ b/trunk/arch/xtensa/include/uapi/asm/unistd.h @@ -1,4 +1,14 @@ -#if !defined(_UAPI_XTENSA_UNISTD_H) || defined(__SYSCALL) +/* + * include/asm-xtensa/unistd.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2001 - 2012 Tensilica Inc. + */ + +#ifndef _UAPI_XTENSA_UNISTD_H #define _UAPI_XTENSA_UNISTD_H #ifndef __SYSCALL @@ -262,7 +272,7 @@ __SYSCALL(115, sys_sendmmsg, 4) #define __NR_clone 116 __SYSCALL(116, xtensa_clone, 5) #define __NR_execve 117 -__SYSCALL(117, sys_execve, 3) +__SYSCALL(117, xtensa_execve, 3) #define __NR_exit 118 __SYSCALL(118, sys_exit, 1) #define __NR_exit_group 119 @@ -749,6 +759,4 @@ __SYSCALL(331, sys_kcmp, 5) #define SYS_XTENSA_COUNT 5 /* count */ -#undef __SYSCALL - #endif /* _UAPI_XTENSA_UNISTD_H */ diff --git a/trunk/arch/xtensa/kernel/entry.S b/trunk/arch/xtensa/kernel/entry.S index 90bfc1dbc13d..18453067c258 100644 --- a/trunk/arch/xtensa/kernel/entry.S +++ b/trunk/arch/xtensa/kernel/entry.S @@ -1832,6 +1832,50 @@ ENTRY(system_call) retw +/* + * Create a kernel thread + * + * int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) + * a2 a2 a3 a4 + */ + +ENTRY(kernel_thread) + entry a1, 16 + + mov a5, a2 # preserve fn over syscall + mov a7, a3 # preserve args over syscall + + movi a3, _CLONE_VM | _CLONE_UNTRACED + movi a2, __NR_clone + or a6, a4, a3 # arg0: flags + mov a3, a1 # arg1: sp + syscall + + beq a3, a1, 1f # branch if parent + mov a6, a7 # args + callx4 a5 # fn(args) + + movi a2, __NR_exit + syscall # return value of fn(args) still in a6 + +1: retw + +/* + * Do a system call from kernel instead of calling sys_execve, so we end up + * with proper pt_regs. + * + * int kernel_execve(const char *fname, char *const argv[], charg *const envp[]) + * a2 a2 a3 a4 + */ + +ENTRY(kernel_execve) + entry a1, 16 + mov a6, a2 # arg0 is in a6 + movi a2, __NR_execve + syscall + + retw + /* * Task switch. * @@ -1914,16 +1958,3 @@ ENTRY(ret_from_fork) j common_exception_return -/* - * Kernel thread creation helper - * On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg - * left from _switch_to: a6 = prev - */ -ENTRY(ret_from_kernel_thread) - - call4 schedule_tail - mov a6, a3 - callx4 a2 - j common_exception_return - -ENDPROC(ret_from_kernel_thread) diff --git a/trunk/arch/xtensa/kernel/process.c b/trunk/arch/xtensa/kernel/process.c index 09ae7bfab9a7..1908f6642d31 100644 --- a/trunk/arch/xtensa/kernel/process.c +++ b/trunk/arch/xtensa/kernel/process.c @@ -45,7 +45,6 @@ #include extern void ret_from_fork(void); -extern void ret_from_kernel_thread(void); struct task_struct *current_set[NR_CPUS] = {&init_task, }; @@ -159,30 +158,18 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) /* * Copy thread. * - * There are two modes in which this function is called: - * 1) Userspace thread creation, - * regs != NULL, usp_thread_fn is userspace stack pointer. - * It is expected to copy parent regs (in case CLONE_VM is not set - * in the clone_flags) and set up passed usp in the childregs. - * 2) Kernel thread creation, - * regs == NULL, usp_thread_fn is the function to run in the new thread - * and thread_fn_arg is its parameter. - * childregs are not used for the kernel threads. - * * The stack layout for the new thread looks like this: * - * +------------------------+ + * +------------------------+ <- sp in childregs (= tos) * | childregs | * +------------------------+ <- thread.sp = sp in dummy-frame * | dummy-frame | (saved in dummy-frame spill-area) * +------------------------+ * - * We create a dummy frame to return to either ret_from_fork or - * ret_from_kernel_thread: - * a0 points to ret_from_fork/ret_from_kernel_thread (simulating a call4) + * We create a dummy frame to return to ret_from_fork: + * a0 points to ret_from_fork (simulating a call4) * sp points to itself (thread.sp) - * a2, a3 are unused for userspace threads, - * a2 points to thread_fn, a3 holds thread_fn arg for kernel threads. + * a2, a3 are unused. * * Note: This is a pristine frame, so we don't need any spill region on top of * childregs. @@ -198,63 +185,43 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) * involved. Much simpler to just not copy those live frames across. */ -int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, - unsigned long thread_fn_arg, - struct task_struct *p, struct pt_regs *unused) +int copy_thread(unsigned long clone_flags, unsigned long usp, + unsigned long unused, + struct task_struct * p, struct pt_regs * regs) { - struct pt_regs *childregs = task_pt_regs(p); + struct pt_regs *childregs; + unsigned long tos; + int user_mode = user_mode(regs); #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) struct thread_info *ti; #endif + /* Set up new TSS. */ + tos = (unsigned long)task_stack_page(p) + THREAD_SIZE; + if (user_mode) + childregs = (struct pt_regs*)(tos - PT_USER_SIZE); + else + childregs = (struct pt_regs*)tos - 1; + + /* This does not copy all the regs. In a bout of brilliance or madness, + ARs beyond a0-a15 exist past the end of the struct. */ + *childregs = *regs; + /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */ *((int*)childregs - 3) = (unsigned long)childregs; *((int*)childregs - 4) = 0; + childregs->areg[2] = 0; + p->set_child_tid = p->clear_child_tid = NULL; + p->thread.ra = MAKE_RA_FOR_CALL((unsigned long)ret_from_fork, 0x1); p->thread.sp = (unsigned long)childregs; - if (!(p->flags & PF_KTHREAD)) { - struct pt_regs *regs = current_pt_regs(); - unsigned long usp = usp_thread_fn ? - usp_thread_fn : regs->areg[1]; + if (user_mode(regs)) { - p->thread.ra = MAKE_RA_FOR_CALL( - (unsigned long)ret_from_fork, 0x1); - - /* This does not copy all the regs. - * In a bout of brilliance or madness, - * ARs beyond a0-a15 exist past the end of the struct. - */ - *childregs = *regs; childregs->areg[1] = usp; - childregs->areg[2] = 0; - - /* When sharing memory with the parent thread, the child - usually starts on a pristine stack, so we have to reset - windowbase, windowstart and wmask. - (Note that such a new thread is required to always create - an initial call4 frame) - The exception is vfork, where the new thread continues to - run on the parent's stack until it calls execve. This could - be a call8 or call12, which requires a legal stack frame - of the previous caller for the overflow handlers to work. - (Note that it's always legal to overflow live registers). - In this case, ensure to spill at least the stack pointer - of that frame. */ - if (clone_flags & CLONE_VM) { - /* check that caller window is live and same stack */ - int len = childregs->wmask & ~0xf; - if (regs->areg[1] == usp && len != 0) { - int callinc = (regs->areg[0] >> 30) & 3; - int caller_ars = XCHAL_NUM_AREGS - callinc * 4; - put_user(regs->areg[caller_ars+1], - (unsigned __user*)(usp - 12)); - } - childregs->wmask = 1; - childregs->windowstart = 1; - childregs->windowbase = 0; + childregs->wmask = 1; /* can't share live windows */ } else { int len = childregs->wmask & ~0xf; memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4], @@ -263,19 +230,11 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, // FIXME: we need to set THREADPTR in thread_info... if (clone_flags & CLONE_SETTLS) childregs->areg[2] = childregs->areg[6]; + } else { - p->thread.ra = MAKE_RA_FOR_CALL( - (unsigned long)ret_from_kernel_thread, 1); - - /* pass parameters to ret_from_kernel_thread: - * a2 = thread_fn, a3 = thread_fn arg - */ - *((int *)childregs - 1) = thread_fn_arg; - *((int *)childregs - 2) = usp_thread_fn; - - /* Childregs are only used when we're going to userspace - * in which case start_thread will set them up. - */ + /* In kernel space, we start a new thread with a new stack. */ + childregs->wmask = 1; + childregs->areg[1] = tos; } #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) @@ -371,5 +330,32 @@ long xtensa_clone(unsigned long clone_flags, unsigned long newsp, void __user *child_tid, long a5, struct pt_regs *regs) { + if (!newsp) + newsp = regs->areg[1]; return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); } + +/* + * xtensa_execve() executes a new program. + */ + +asmlinkage +long xtensa_execve(const char __user *name, + const char __user *const __user *argv, + const char __user *const __user *envp, + long a3, long a4, long a5, + struct pt_regs *regs) +{ + long error; + struct filename *filename; + + filename = getname(name); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = do_execve(filename->name, argv, envp, regs); + putname(filename); +out: + return error; +} + diff --git a/trunk/arch/xtensa/kernel/syscall.c b/trunk/arch/xtensa/kernel/syscall.c index 5702065f472a..a5c01e74d5d5 100644 --- a/trunk/arch/xtensa/kernel/syscall.c +++ b/trunk/arch/xtensa/kernel/syscall.c @@ -32,8 +32,10 @@ typedef void (*syscall_t)(void); syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= { [0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall, +#undef __SYSCALL #define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol, -#include +#undef __KERNEL_SYSCALLS__ +#include }; asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg) @@ -47,8 +49,7 @@ asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg) return (long)ret; } -asmlinkage long xtensa_fadvise64_64(int fd, int advice, - unsigned long long offset, unsigned long long len) +asmlinkage long xtensa_fadvise64_64(int fd, int advice, unsigned long long offset, unsigned long long len) { return sys_fadvise64_64(fd, offset, len, advice); } diff --git a/trunk/arch/xtensa/kernel/xtensa_ksyms.c b/trunk/arch/xtensa/kernel/xtensa_ksyms.c index afe058b24e6e..a8b9f1fd1e17 100644 --- a/trunk/arch/xtensa/kernel/xtensa_ksyms.c +++ b/trunk/arch/xtensa/kernel/xtensa_ksyms.c @@ -43,6 +43,7 @@ EXPORT_SYMBOL(__strncpy_user); EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(copy_page); +EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(empty_zero_page); /* diff --git a/trunk/block/Kconfig b/trunk/block/Kconfig index a7e40a7c8214..09acf1b39905 100644 --- a/trunk/block/Kconfig +++ b/trunk/block/Kconfig @@ -89,7 +89,7 @@ config BLK_DEV_INTEGRITY config BLK_DEV_THROTTLING bool "Block layer bio throttling support" - depends on BLK_CGROUP=y + depends on BLK_CGROUP=y && EXPERIMENTAL default n ---help--- Block layer bio throttling support. It can be used to limit diff --git a/trunk/block/blk-cgroup.c b/trunk/block/blk-cgroup.c index d0b770391ad4..cafcd7431189 100644 --- a/trunk/block/blk-cgroup.c +++ b/trunk/block/blk-cgroup.c @@ -285,13 +285,6 @@ static void blkg_destroy_all(struct request_queue *q) blkg_destroy(blkg); spin_unlock(&blkcg->lock); } - - /* - * root blkg is destroyed. Just clear the pointer since - * root_rl does not take reference on root blkg. - */ - q->root_blkg = NULL; - q->root_rl.blkg = NULL; } static void blkg_rcu_free(struct rcu_head *rcu_head) @@ -333,9 +326,6 @@ struct request_list *__blk_queue_next_rl(struct request_list *rl, */ if (rl == &q->root_rl) { ent = &q->blkg_list; - /* There are no more block groups, hence no request lists */ - if (list_empty(ent)) - return NULL; } else { blkg = container_of(rl, struct blkcg_gq, rl); ent = &blkg->q_node; diff --git a/trunk/block/blk-core.c b/trunk/block/blk-core.c index 3c95c4d6e31a..a33870b1847b 100644 --- a/trunk/block/blk-core.c +++ b/trunk/block/blk-core.c @@ -2868,8 +2868,7 @@ static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b) struct request *rqa = container_of(a, struct request, queuelist); struct request *rqb = container_of(b, struct request, queuelist); - return !(rqa->q < rqb->q || - (rqa->q == rqb->q && blk_rq_pos(rqa) < blk_rq_pos(rqb))); + return !(rqa->q <= rqb->q); } /* diff --git a/trunk/drivers/acpi/glue.c b/trunk/drivers/acpi/glue.c index 08373086cd7e..d1a2d74033e9 100644 --- a/trunk/drivers/acpi/glue.c +++ b/trunk/drivers/acpi/glue.c @@ -159,7 +159,6 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) { retval = -ENOSPC; mutex_unlock(&acpi_dev->physical_node_lock); - kfree(physical_node); goto err; } diff --git a/trunk/drivers/acpi/processor_driver.c b/trunk/drivers/acpi/processor_driver.c index bd4e5dca3ff7..e78c2a52ea46 100644 --- a/trunk/drivers/acpi/processor_driver.c +++ b/trunk/drivers/acpi/processor_driver.c @@ -409,7 +409,6 @@ static void acpi_processor_notify(struct acpi_device *device, u32 event) acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, 0); - break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); diff --git a/trunk/drivers/base/power/domain.c b/trunk/drivers/base/power/domain.c index 96b71b6536d6..c22b869245d9 100644 --- a/trunk/drivers/base/power/domain.c +++ b/trunk/drivers/base/power/domain.c @@ -1862,7 +1862,7 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state) cpuidle_drv = cpuidle_driver_ref(); if (!cpuidle_drv) { ret = -ENODEV; - goto err_drv; + goto out; } if (cpuidle_drv->state_count <= state) { ret = -EINVAL; @@ -1884,9 +1884,6 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state) err: cpuidle_driver_unref(); - - err_drv: - kfree(cpu_data); goto out; } diff --git a/trunk/drivers/bcma/main.c b/trunk/drivers/bcma/main.c index d865470bc951..432aeeedfd5e 100644 --- a/trunk/drivers/bcma/main.c +++ b/trunk/drivers/bcma/main.c @@ -158,10 +158,9 @@ static int bcma_register_cores(struct bcma_bus *bus) static void bcma_unregister_cores(struct bcma_bus *bus) { - struct bcma_device *core, *tmp; + struct bcma_device *core; - list_for_each_entry_safe(core, tmp, &bus->cores, list) { - list_del(&core->list); + list_for_each_entry(core, &bus->cores, list) { if (core->dev_registered) device_unregister(&core->dev); } diff --git a/trunk/drivers/block/Kconfig b/trunk/drivers/block/Kconfig index 824e09c4d0d7..f529407db93f 100644 --- a/trunk/drivers/block/Kconfig +++ b/trunk/drivers/block/Kconfig @@ -131,7 +131,6 @@ config BLK_CPQ_DA config BLK_CPQ_CISS_DA tristate "Compaq Smart Array 5xxx support" depends on PCI - select CHECK_SIGNATURE help This is the driver for Compaq Smart Array 5xxx controllers. Everyone using these boards should say Y here. @@ -167,8 +166,8 @@ config BLK_DEV_DAC960 module will be called DAC960. config BLK_DEV_UMEM - tristate "Micro Memory MM5415 Battery Backed RAM support" - depends on PCI + tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)" + depends on PCI && EXPERIMENTAL ---help--- Saying Y here will include support for the MM5415 family of battery backed (Non-volatile) RAM cards. @@ -431,8 +430,8 @@ config CDROM_PKTCDVD_BUFFERS a disc is opened for writing. config CDROM_PKTCDVD_WCACHE - bool "Enable write caching" - depends on CDROM_PKTCDVD + bool "Enable write caching (EXPERIMENTAL)" + depends on CDROM_PKTCDVD && EXPERIMENTAL help If enabled, write caching will be set for the CD-R/W device. For now this option is dangerous unless the CD-RW media is known good, as we @@ -509,8 +508,8 @@ config XEN_BLKDEV_BACKEND config VIRTIO_BLK - tristate "Virtio block driver" - depends on VIRTIO + tristate "Virtio block driver (EXPERIMENTAL)" + depends on EXPERIMENTAL && VIRTIO ---help--- This is the virtual block driver for virtio. It can be used with lguest or QEMU based VMMs (like KVM or Xen). Say Y or M. @@ -529,7 +528,7 @@ config BLK_DEV_HD config BLK_DEV_RBD tristate "Rados block device (RBD)" - depends on INET && BLOCK + depends on INET && EXPERIMENTAL && BLOCK select CEPH_LIB select LIBCRC32C select CRYPTO_AES diff --git a/trunk/drivers/block/cciss.c b/trunk/drivers/block/cciss.c index ca83f96756ad..b0f553b26d0f 100644 --- a/trunk/drivers/block/cciss.c +++ b/trunk/drivers/block/cciss.c @@ -5205,6 +5205,7 @@ static void cciss_shutdown(struct pci_dev *pdev) return; } /* write all data in the battery backed cache to disk */ + memset(flush_buf, 0, 4); return_code = sendcmd_withirq(h, CCISS_CACHE_FLUSH, flush_buf, 4, 0, CTLR_LUNID, TYPE_CMD); kfree(flush_buf); diff --git a/trunk/drivers/block/floppy.c b/trunk/drivers/block/floppy.c index 1c49d7173966..17c675c52295 100644 --- a/trunk/drivers/block/floppy.c +++ b/trunk/drivers/block/floppy.c @@ -4109,19 +4109,12 @@ static struct platform_driver floppy_driver = { static struct platform_device floppy_device[N_DRIVE]; -static bool floppy_available(int drive) -{ - if (!(allowed_drive_mask & (1 << drive))) - return false; - if (fdc_state[FDC(drive)].version == FDC_NONE) - return false; - return true; -} - static struct kobject *floppy_find(dev_t dev, int *part, void *data) { int drive = (*part & 3) | ((*part & 0x80) >> 5); - if (drive >= N_DRIVE || !floppy_available(drive)) + if (drive >= N_DRIVE || + !(allowed_drive_mask & (1 << drive)) || + fdc_state[FDC(drive)].version == FDC_NONE) return NULL; if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type)) return NULL; @@ -4131,7 +4124,8 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data) static int __init do_floppy_init(void) { - int i, unit, drive, err; + int i, unit, drive; + int err, dr; set_debugt(); interruptjiffies = resultjiffies = jiffies; @@ -4143,32 +4137,34 @@ static int __init do_floppy_init(void) raw_cmd = NULL; - floppy_wq = alloc_ordered_workqueue("floppy", 0); - if (!floppy_wq) - return -ENOMEM; - - for (drive = 0; drive < N_DRIVE; drive++) { - disks[drive] = alloc_disk(1); - if (!disks[drive]) { + for (dr = 0; dr < N_DRIVE; dr++) { + disks[dr] = alloc_disk(1); + if (!disks[dr]) { err = -ENOMEM; goto out_put_disk; } - disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock); - if (!disks[drive]->queue) { + floppy_wq = alloc_ordered_workqueue("floppy", 0); + if (!floppy_wq) { err = -ENOMEM; goto out_put_disk; } - blk_queue_max_hw_sectors(disks[drive]->queue, 64); - disks[drive]->major = FLOPPY_MAJOR; - disks[drive]->first_minor = TOMINOR(drive); - disks[drive]->fops = &floppy_fops; - sprintf(disks[drive]->disk_name, "fd%d", drive); + disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); + if (!disks[dr]->queue) { + err = -ENOMEM; + goto out_destroy_workq; + } + + blk_queue_max_hw_sectors(disks[dr]->queue, 64); + disks[dr]->major = FLOPPY_MAJOR; + disks[dr]->first_minor = TOMINOR(dr); + disks[dr]->fops = &floppy_fops; + sprintf(disks[dr]->disk_name, "fd%d", dr); - init_timer(&motor_off_timer[drive]); - motor_off_timer[drive].data = drive; - motor_off_timer[drive].function = motor_off_callback; + init_timer(&motor_off_timer[dr]); + motor_off_timer[dr].data = dr; + motor_off_timer[dr].function = motor_off_callback; } err = register_blkdev(FLOPPY_MAJOR, "fd"); @@ -4286,7 +4282,9 @@ static int __init do_floppy_init(void) } for (drive = 0; drive < N_DRIVE; drive++) { - if (!floppy_available(drive)) + if (!(allowed_drive_mask & (1 << drive))) + continue; + if (fdc_state[FDC(drive)].version == FDC_NONE) continue; floppy_device[drive].name = floppy_device_name; @@ -4295,7 +4293,7 @@ static int __init do_floppy_init(void) err = platform_device_register(&floppy_device[drive]); if (err) - goto out_remove_drives; + goto out_release_dma; err = device_create_file(&floppy_device[drive].dev, &dev_attr_cmos); @@ -4313,34 +4311,29 @@ static int __init do_floppy_init(void) out_unreg_platform_dev: platform_device_unregister(&floppy_device[drive]); -out_remove_drives: - while (drive--) { - if (floppy_available(drive)) { - del_gendisk(disks[drive]); - device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); - platform_device_unregister(&floppy_device[drive]); - } - } out_release_dma: if (atomic_read(&usage_count)) floppy_release_irq_and_dma(); out_unreg_region: blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); platform_driver_unregister(&floppy_driver); +out_destroy_workq: + destroy_workqueue(floppy_wq); out_unreg_blkdev: unregister_blkdev(FLOPPY_MAJOR, "fd"); out_put_disk: - for (drive = 0; drive < N_DRIVE; drive++) { - if (!disks[drive]) - break; - if (disks[drive]->queue) { - del_timer_sync(&motor_off_timer[drive]); - blk_cleanup_queue(disks[drive]->queue); - disks[drive]->queue = NULL; + while (dr--) { + del_timer_sync(&motor_off_timer[dr]); + if (disks[dr]->queue) { + blk_cleanup_queue(disks[dr]->queue); + /* + * put_disk() is not paired with add_disk() and + * will put queue reference one extra time. fix it. + */ + disks[dr]->queue = NULL; } - put_disk(disks[drive]); + put_disk(disks[dr]); } - destroy_workqueue(floppy_wq); return err; } @@ -4558,7 +4551,8 @@ static void __exit floppy_module_exit(void) for (drive = 0; drive < N_DRIVE; drive++) { del_timer_sync(&motor_off_timer[drive]); - if (floppy_available(drive)) { + if ((allowed_drive_mask & (1 << drive)) && + fdc_state[FDC(drive)].version != FDC_NONE) { del_gendisk(disks[drive]); device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); platform_device_unregister(&floppy_device[drive]); diff --git a/trunk/drivers/block/loop.c b/trunk/drivers/block/loop.c index 54046e51160a..e9d594fd12cb 100644 --- a/trunk/drivers/block/loop.c +++ b/trunk/drivers/block/loop.c @@ -976,21 +976,8 @@ static int loop_clr_fd(struct loop_device *lo) if (lo->lo_state != Lo_bound) return -ENXIO; - /* - * If we've explicitly asked to tear down the loop device, - * and it has an elevated reference count, set it for auto-teardown when - * the last reference goes away. This stops $!~#$@ udev from - * preventing teardown because it decided that it needs to run blkid on - * the loopback device whenever they appear. xfstests is notorious for - * failing tests because blkid via udev races with a losetup - * /do something like mkfs/losetup -d causing the losetup -d - * command to fail with EBUSY. - */ - if (lo->lo_refcnt > 1) { - lo->lo_flags |= LO_FLAGS_AUTOCLEAR; - mutex_unlock(&lo->lo_ctl_mutex); - return 0; - } + if (lo->lo_refcnt > 1) /* we needed one fd for the ioctl */ + return -EBUSY; if (filp == NULL) return -EINVAL; diff --git a/trunk/drivers/block/mtip32xx/mtip32xx.c b/trunk/drivers/block/mtip32xx/mtip32xx.c index adc6f36564cf..f946d31d6917 100644 --- a/trunk/drivers/block/mtip32xx/mtip32xx.c +++ b/trunk/drivers/block/mtip32xx/mtip32xx.c @@ -2035,9 +2035,8 @@ static unsigned int implicit_sector(unsigned char command, } return rv; } -static void mtip_set_timeout(struct driver_data *dd, - struct host_to_dev_fis *fis, - unsigned int *timeout, u8 erasemode) + +static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout) { switch (fis->command) { case ATA_CMD_DOWNLOAD_MICRO: @@ -2045,10 +2044,7 @@ static void mtip_set_timeout(struct driver_data *dd, break; case ATA_CMD_SEC_ERASE_UNIT: case 0xFC: - if (erasemode) - *timeout = ((*(dd->port->identify + 90) * 2) * 60000); - else - *timeout = ((*(dd->port->identify + 89) * 2) * 60000); + *timeout = 240000; /* 4 minutes */ break; case ATA_CMD_STANDBYNOW1: *timeout = 120000; /* 2 minutes */ @@ -2091,7 +2087,6 @@ static int exec_drive_taskfile(struct driver_data *dd, unsigned int transfer_size; unsigned long task_file_data; int intotal = outtotal + req_task->out_size; - int erasemode = 0; taskout = req_task->out_size; taskin = req_task->in_size; @@ -2217,13 +2212,7 @@ static int exec_drive_taskfile(struct driver_data *dd, fis.lba_hi, fis.device); - /* check for erase mode support during secure erase.*/ - if ((fis.command == ATA_CMD_SEC_ERASE_UNIT) - && (outbuf[0] & MTIP_SEC_ERASE_MODE)) { - erasemode = 1; - } - - mtip_set_timeout(dd, &fis, &timeout, erasemode); + mtip_set_timeout(&fis, &timeout); /* Determine the correct transfer size.*/ if (force_single_sector) diff --git a/trunk/drivers/block/mtip32xx/mtip32xx.h b/trunk/drivers/block/mtip32xx/mtip32xx.h index 5f4a917bd8bb..18627a1d04c5 100644 --- a/trunk/drivers/block/mtip32xx/mtip32xx.h +++ b/trunk/drivers/block/mtip32xx/mtip32xx.h @@ -33,9 +33,6 @@ /* offset of Device Control register in PCIe extended capabilites space */ #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48 -/* check for erase mode support during secure erase */ -#define MTIP_SEC_ERASE_MODE 0x3 - /* # of times to retry timed out/failed IOs */ #define MTIP_MAX_RETRIES 2 diff --git a/trunk/drivers/block/xen-blkback/common.h b/trunk/drivers/block/xen-blkback/common.h index 9a54623e52d7..9ad3b5ec1dc1 100644 --- a/trunk/drivers/block/xen-blkback/common.h +++ b/trunk/drivers/block/xen-blkback/common.h @@ -158,8 +158,8 @@ struct xen_vbd { struct block_device *bdev; /* Cached size parameter. */ sector_t size; - unsigned int flush_support:1; - unsigned int discard_secure:1; + bool flush_support; + bool discard_secure; }; struct backend_info; diff --git a/trunk/drivers/block/xen-blkback/xenbus.c b/trunk/drivers/block/xen-blkback/xenbus.c index f58434c2617c..4f66171c6683 100644 --- a/trunk/drivers/block/xen-blkback/xenbus.c +++ b/trunk/drivers/block/xen-blkback/xenbus.c @@ -105,10 +105,11 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid) { struct xen_blkif *blkif; - blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL); + blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL); if (!blkif) return ERR_PTR(-ENOMEM); + memset(blkif, 0, sizeof(*blkif)); blkif->domid = domid; spin_lock_init(&blkif->blk_ring_lock); atomic_set(&blkif->refcnt, 1); @@ -195,7 +196,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif) } } -static void xen_blkif_free(struct xen_blkif *blkif) +void xen_blkif_free(struct xen_blkif *blkif) { if (!atomic_dec_and_test(&blkif->refcnt)) BUG(); @@ -256,7 +257,7 @@ static struct attribute_group xen_vbdstat_group = { VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor); VBD_SHOW(mode, "%s\n", be->mode); -static int xenvbd_sysfs_addif(struct xenbus_device *dev) +int xenvbd_sysfs_addif(struct xenbus_device *dev) { int error; @@ -280,7 +281,7 @@ fail1: device_remove_file(&dev->dev, &dev_attr_physical_device); return error; } -static void xenvbd_sysfs_delif(struct xenbus_device *dev) +void xenvbd_sysfs_delif(struct xenbus_device *dev) { sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group); device_remove_file(&dev->dev, &dev_attr_mode); diff --git a/trunk/drivers/cpufreq/cpufreq_stats.c b/trunk/drivers/cpufreq/cpufreq_stats.c index 399831690fed..b40ee1403be9 100644 --- a/trunk/drivers/cpufreq/cpufreq_stats.c +++ b/trunk/drivers/cpufreq/cpufreq_stats.c @@ -328,7 +328,6 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb, cpufreq_update_policy(cpu); break; case CPU_DOWN_PREPARE: - case CPU_DOWN_PREPARE_FROZEN: cpufreq_stats_free_sysfs(cpu); break; case CPU_DEAD: diff --git a/trunk/drivers/cpufreq/powernow-k8.c b/trunk/drivers/cpufreq/powernow-k8.c index c16a3a593ba4..129e80bfff22 100644 --- a/trunk/drivers/cpufreq/powernow-k8.c +++ b/trunk/drivers/cpufreq/powernow-k8.c @@ -1052,7 +1052,14 @@ static int powernowk8_target(struct cpufreq_policy *pol, struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq, .relation = relation }; - return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); + /* + * Must run on @pol->cpu. cpufreq core is responsible for ensuring + * that we're bound to the current CPU and pol->cpu stays online. + */ + if (smp_processor_id() == pol->cpu) + return powernowk8_target_fn(&pta); + else + return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); } /* Driver entry point to verify the policy and range of frequencies */ diff --git a/trunk/drivers/dma/imx-dma.c b/trunk/drivers/dma/imx-dma.c index 7d9554cc4976..f11b5b2b1a1c 100644 --- a/trunk/drivers/dma/imx-dma.c +++ b/trunk/drivers/dma/imx-dma.c @@ -474,10 +474,8 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) slot = i; break; } - if (slot < 0) { - spin_unlock_irqrestore(&imxdma->lock, flags); + if (slot < 0) return -EBUSY; - } imxdma->slots_2d[slot].xsr = d->x; imxdma->slots_2d[slot].ysr = d->y; diff --git a/trunk/drivers/dma/sirf-dma.c b/trunk/drivers/dma/sirf-dma.c index d451caace806..64385cde044b 100644 --- a/trunk/drivers/dma/sirf-dma.c +++ b/trunk/drivers/dma/sirf-dma.c @@ -109,7 +109,7 @@ static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan) sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc, node); /* Move the first queued descriptor to active list */ - list_move_tail(&sdesc->node, &schan->active); + list_move_tail(&schan->queued, &schan->active); /* Start the DMA transfer */ writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 + @@ -428,7 +428,7 @@ static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved( unsigned long iflags; int ret; - if ((xt->dir != DMA_MEM_TO_DEV) && (xt->dir != DMA_DEV_TO_MEM)) { + if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) { ret = -EINVAL; goto err_dir; } diff --git a/trunk/drivers/gpio/gpio-74x164.c b/trunk/drivers/gpio/gpio-74x164.c index f05e54258ffb..ed3e55161bdc 100644 --- a/trunk/drivers/gpio/gpio-74x164.c +++ b/trunk/drivers/gpio/gpio-74x164.c @@ -153,7 +153,7 @@ static int __devinit gen_74x164_probe(struct spi_device *spi) } chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers; - chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL); + chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL); if (!chip->buffer) { ret = -ENOMEM; goto exit_destroy; diff --git a/trunk/drivers/gpio/gpio-mvebu.c b/trunk/drivers/gpio/gpio-mvebu.c index cf7afb9eb61a..7a874129e5d8 100644 --- a/trunk/drivers/gpio/gpio-mvebu.c +++ b/trunk/drivers/gpio/gpio-mvebu.c @@ -244,8 +244,6 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin, if (ret) return ret; - mvebu_gpio_set(chip, pin, value); - spin_lock_irqsave(&mvchip->lock, flags); u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)); u &= ~(1 << pin); @@ -646,7 +644,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev) ct->handler = handle_edge_irq; ct->chip.name = mvchip->chip.label; - irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0, + irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); /* Setup irq domain on top of the generic chip. */ diff --git a/trunk/drivers/gpio/gpio-omap.c b/trunk/drivers/gpio/gpio-omap.c index d335af1d4d85..94cbc842fbc3 100644 --- a/trunk/drivers/gpio/gpio-omap.c +++ b/trunk/drivers/gpio/gpio-omap.c @@ -251,40 +251,6 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, } } -/** - * _clear_gpio_debounce - clear debounce settings for a gpio - * @bank: the gpio bank we're acting upon - * @gpio: the gpio number on this @gpio - * - * If a gpio is using debounce, then clear the debounce enable bit and if - * this is the only gpio in this bank using debounce, then clear the debounce - * time too. The debounce clock will also be disabled when calling this function - * if this is the only gpio in the bank using debounce. - */ -static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio) -{ - u32 gpio_bit = GPIO_BIT(bank, gpio); - - if (!bank->dbck_flag) - return; - - if (!(bank->dbck_enable_mask & gpio_bit)) - return; - - bank->dbck_enable_mask &= ~gpio_bit; - bank->context.debounce_en &= ~gpio_bit; - __raw_writel(bank->context.debounce_en, - bank->base + bank->regs->debounce_en); - - if (!bank->dbck_enable_mask) { - bank->context.debounce = 0; - __raw_writel(bank->context.debounce, bank->base + - bank->regs->debounce); - clk_disable(bank->dbck); - bank->dbck_enabled = false; - } -} - static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio, unsigned trigger) { @@ -573,7 +539,6 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio) _set_gpio_irqenable(bank, gpio, 0); _clear_gpio_irqstatus(bank, gpio); _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); - _clear_gpio_debounce(bank, gpio); } /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */ diff --git a/trunk/drivers/gpio/gpio-timberdale.c b/trunk/drivers/gpio/gpio-timberdale.c index 1a3e2b9b4772..031c6adf5b65 100644 --- a/trunk/drivers/gpio/gpio-timberdale.c +++ b/trunk/drivers/gpio/gpio-timberdale.c @@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d) unsigned long flags; spin_lock_irqsave(&tgpio->lock, flags); - tgpio->last_ier &= ~(1UL << offset); + tgpio->last_ier &= ~(1 << offset); iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); spin_unlock_irqrestore(&tgpio->lock, flags); } @@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d) unsigned long flags; spin_lock_irqsave(&tgpio->lock, flags); - tgpio->last_ier |= 1UL << offset; + tgpio->last_ier |= 1 << offset; iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); spin_unlock_irqrestore(&tgpio->lock, flags); } diff --git a/trunk/drivers/gpio/gpiolib.c b/trunk/drivers/gpio/gpiolib.c index 1c8d9e3380e1..5d6c71edc739 100644 --- a/trunk/drivers/gpio/gpiolib.c +++ b/trunk/drivers/gpio/gpiolib.c @@ -623,11 +623,9 @@ static ssize_t export_store(struct class *class, */ status = gpio_request(gpio, "sysfs"); - if (status < 0) { - if (status == -EPROBE_DEFER) - status = -ENODEV; + if (status < 0) goto done; - } + status = gpio_export(gpio, true); if (status < 0) gpio_free(gpio); @@ -1193,10 +1191,8 @@ int gpio_request(unsigned gpio, const char *label) spin_lock_irqsave(&gpio_lock, flags); - if (!gpio_is_valid(gpio)) { - status = -EINVAL; + if (!gpio_is_valid(gpio)) goto done; - } desc = &gpio_desc[gpio]; chip = desc->chip; if (chip == NULL) diff --git a/trunk/drivers/gpu/drm/nouveau/core/core/mm.c b/trunk/drivers/gpu/drm/nouveau/core/core/mm.c index a6d3cd6490f7..4d6206448670 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/core/mm.c +++ b/trunk/drivers/gpu/drm/nouveau/core/core/mm.c @@ -218,16 +218,13 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block) node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) return -ENOMEM; - - if (length) { - node->offset = roundup(offset, mm->block_size); - node->length = rounddown(offset + length, mm->block_size); - node->length -= node->offset; - } + node->offset = roundup(offset, mm->block_size); + node->length = rounddown(offset + length, mm->block_size) - node->offset; list_add_tail(&node->nl_entry, &mm->nodes); list_add_tail(&node->fl_entry, &mm->free); mm->heap_nodes++; + mm->heap_size += length; return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/core/mm.h b/trunk/drivers/gpu/drm/nouveau/core/include/core/mm.h index 975137ba34a6..9ee9bf4028ca 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/core/mm.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/core/mm.h @@ -19,6 +19,7 @@ struct nouveau_mm { u32 block_size; int heap_nodes; + u32 heap_size; }; int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block); diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index 5f570806143a..27fb1af7a779 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -219,11 +219,13 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ((priv->base.ram.size & 0x000000ff) << 32); tags = nv_rd32(priv, 0x100320); - ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); - if (ret) - return ret; + if (tags) { + ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); + if (ret) + return ret; - nv_debug(priv, "%d compression tags\n", tags); + nv_debug(priv, "%d compression tags\n", tags); + } size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail; switch (device->chipset) { diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index dbfc2abf0cfe..3d2c88310f98 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, case DCB_I2C_NVIO_BIT: port->drive = info.drive & 0x0f; if (device->card_type < NV_D0) { - if (port->drive >= ARRAY_SIZE(nv50_i2c_port)) + if (info.drive >= ARRAY_SIZE(nv50_i2c_port)) break; port->drive = nv50_i2c_port[port->drive]; port->sense = port->drive; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_display.c b/trunk/drivers/gpu/drm/nouveau/nouveau_display.c index 86124b131f4f..d2f8ffeed742 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_display.c @@ -290,7 +290,6 @@ nouveau_display_create(struct drm_device *dev) struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_disp *pdisp = nouveau_disp(drm->device); struct nouveau_display *disp; - u32 pclass = dev->pdev->class >> 8; int ret, gen; disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL); @@ -361,27 +360,23 @@ nouveau_display_create(struct drm_device *dev) drm_kms_helper_poll_init(dev); drm_kms_helper_poll_disable(dev); - if (nouveau_modeset == 1 || - (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) { - if (nv_device(drm->device)->card_type < NV_50) - ret = nv04_display_create(dev); - else - if (nv_device(drm->device)->card_type < NV_D0) - ret = nv50_display_create(dev); - else - ret = nvd0_display_create(dev); - if (ret) - goto disp_create_err; - - if (dev->mode_config.num_crtc) { - ret = drm_vblank_init(dev, dev->mode_config.num_crtc); - if (ret) - goto vblank_err; - } + if (nv_device(drm->device)->card_type < NV_50) + ret = nv04_display_create(dev); + else + if (nv_device(drm->device)->card_type < NV_D0) + ret = nv50_display_create(dev); + else + ret = nvd0_display_create(dev); + if (ret) + goto disp_create_err; - nouveau_backlight_init(dev); + if (dev->mode_config.num_crtc) { + ret = drm_vblank_init(dev, dev->mode_config.num_crtc); + if (ret) + goto vblank_err; } + nouveau_backlight_init(dev); return 0; vblank_err: @@ -400,8 +395,7 @@ nouveau_display_destroy(struct drm_device *dev) nouveau_backlight_exit(dev); drm_vblank_cleanup(dev); - if (disp->dtor) - disp->dtor(dev); + disp->dtor(dev); drm_kms_helper_poll_fini(dev); drm_mode_config_cleanup(dev); diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_drm.c b/trunk/drivers/gpu/drm/nouveau/nouveau_drm.c index 0910125cbbc3..ccae8c26ae2b 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -63,9 +63,8 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration"); static int nouveau_noaccel = 0; module_param_named(noaccel, nouveau_noaccel, int, 0400); -MODULE_PARM_DESC(modeset, "enable driver (default: auto, " - "0 = disabled, 1 = enabled, 2 = headless)"); -int nouveau_modeset = -1; +MODULE_PARM_DESC(modeset, "enable driver"); +static int nouveau_modeset = -1; module_param_named(modeset, nouveau_modeset, int, 0400); static struct drm_driver driver; @@ -364,8 +363,7 @@ nouveau_drm_unload(struct drm_device *dev) nouveau_pm_fini(dev); - if (dev->mode_config.num_crtc) - nouveau_display_fini(dev); + nouveau_display_fini(dev); nouveau_display_destroy(dev); nouveau_irq_fini(dev); @@ -405,15 +403,13 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state) pm_state.event == PM_EVENT_PRETHAW) return 0; - if (dev->mode_config.num_crtc) { - NV_INFO(drm, "suspending fbcon...\n"); - nouveau_fbcon_set_suspend(dev, 1); + NV_INFO(drm, "suspending fbcon...\n"); + nouveau_fbcon_set_suspend(dev, 1); - NV_INFO(drm, "suspending display...\n"); - ret = nouveau_display_suspend(dev); - if (ret) - return ret; - } + NV_INFO(drm, "suspending display...\n"); + ret = nouveau_display_suspend(dev); + if (ret) + return ret; NV_INFO(drm, "evicting buffers...\n"); ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM); @@ -449,10 +445,8 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state) nouveau_client_init(&cli->base); } - if (dev->mode_config.num_crtc) { - NV_INFO(drm, "resuming display...\n"); - nouveau_display_resume(dev); - } + NV_INFO(drm, "resuming display...\n"); + nouveau_display_resume(dev); return ret; } @@ -492,10 +486,8 @@ nouveau_drm_resume(struct pci_dev *pdev) nouveau_irq_postinstall(dev); nouveau_pm_resume(dev); - if (dev->mode_config.num_crtc) { - NV_INFO(drm, "resuming display...\n"); - nouveau_display_resume(dev); - } + NV_INFO(drm, "resuming display...\n"); + nouveau_display_resume(dev); return 0; } @@ -670,7 +662,9 @@ nouveau_drm_init(void) #ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force()) nouveau_modeset = 0; + else #endif + nouveau_modeset = 1; } if (!nouveau_modeset) diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_drm.h b/trunk/drivers/gpu/drm/nouveau/nouveau_drm.h index a10169927086..819471217546 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -141,6 +141,4 @@ int nouveau_drm_resume(struct pci_dev *); nv_info((cli), fmt, ##args); \ } while (0) -extern int nouveau_modeset; - #endif diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_irq.c b/trunk/drivers/gpu/drm/nouveau/nouveau_irq.c index 1d8cb506a28a..9ca8afdb5549 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -61,15 +61,13 @@ nouveau_irq_handler(DRM_IRQ_ARGS) nv_subdev(pmc)->intr(nv_subdev(pmc)); - if (dev->mode_config.num_crtc) { - if (device->card_type >= NV_D0) { - if (nv_rd32(device, 0x000100) & 0x04000000) - nvd0_display_intr(dev); - } else - if (device->card_type >= NV_50) { - if (nv_rd32(device, 0x000100) & 0x04000000) - nv50_display_intr(dev); - } + if (device->card_type >= NV_D0) { + if (nv_rd32(device, 0x000100) & 0x04000000) + nvd0_display_intr(dev); + } else + if (device->card_type >= NV_50) { + if (nv_rd32(device, 0x000100) & 0x04000000) + nv50_display_intr(dev); } return IRQ_HANDLED; diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_dac.c b/trunk/drivers/gpu/drm/nouveau/nv04_dac.c index 64f7020fb605..347a3bd78d04 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_dac.c @@ -220,7 +220,7 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode); if (blue == 0x18) { - NV_DEBUG(drm, "Load detected on head A\n"); + NV_INFO(drm, "Load detected on head A\n"); return connector_status_connected; } @@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) if (nv17_dac_sample_load(encoder) & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { - NV_DEBUG(drm, "Load detected on output %c\n", - '@' + ffs(dcb->or)); + NV_INFO(drm, "Load detected on output %c\n", + '@' + ffs(dcb->or)); return connector_status_connected; } else { return connector_status_disconnected; @@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", - drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), - nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); + NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", + drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), + nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) @@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n", - mode, nv_encoder->dcb->index); + NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n", + mode, nv_encoder->dcb->index); nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); } diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c b/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c index 184cdf806761..da55d7642c8c 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", - drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), - nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); + NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", + drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), + nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) @@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", - mode, nv_encoder->dcb->index); + NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", + mode, nv_encoder->dcb->index); if (was_powersaving && is_powersaving_dpms(mode)) return; @@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", - mode, nv_encoder->dcb->index); + NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", + mode, nv_encoder->dcb->index); nv04_dfp_update_backlight(encoder, mode); nv04_dfp_update_fp_control(encoder, mode); diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_tv.c b/trunk/drivers/gpu/drm/nouveau/nv04_tv.c index 62e826a139b3..099fbeda6e2e 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_tv.c @@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) struct nv04_mode_state *state = &nv04_display(dev)->mode_reg; uint8_t crtc1A; - NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n", - mode, nv_encoder->dcb->index); + NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n", + mode, nv_encoder->dcb->index); state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); @@ -167,8 +167,9 @@ static void nv04_tv_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", - drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); + NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", + drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, + '@' + ffs(nv_encoder->dcb->or)); } static void nv04_tv_destroy(struct drm_encoder *encoder) diff --git a/trunk/drivers/hid/hid-apple.c b/trunk/drivers/hid/hid-apple.c index fd7722aecf77..06ebdbb6ea02 100644 --- a/trunk/drivers/hid/hid-apple.c +++ b/trunk/drivers/hid/hid-apple.c @@ -522,12 +522,6 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI), - .driver_data = APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO), - .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS), - .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), diff --git a/trunk/drivers/hid/hid-core.c b/trunk/drivers/hid/hid-core.c index f4109fd657ff..bd3971bf31bf 100644 --- a/trunk/drivers/hid/hid-core.c +++ b/trunk/drivers/hid/hid-core.c @@ -1532,9 +1532,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, @@ -2142,9 +2139,6 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { } diff --git a/trunk/drivers/hid/hid-ids.h b/trunk/drivers/hid/hid-ids.h index 9d7a42857ea1..269b50912a4a 100644 --- a/trunk/drivers/hid/hid-ids.h +++ b/trunk/drivers/hid/hid-ids.h @@ -118,9 +118,6 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254 -#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259 -#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a -#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a #define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b diff --git a/trunk/drivers/hid/hid-microsoft.c b/trunk/drivers/hid/hid-microsoft.c index f676c01bb471..3acdcfcc17df 100644 --- a/trunk/drivers/hid/hid-microsoft.c +++ b/trunk/drivers/hid/hid-microsoft.c @@ -28,30 +28,22 @@ #define MS_RDESC 0x08 #define MS_NOGET 0x10 #define MS_DUPLICATE_USAGES 0x20 -#define MS_RDESC_3K 0x40 +/* + * Microsoft Wireless Desktop Receiver (Model 1028) has + * 'Usage Min/Max' where it ought to have 'Physical Min/Max' + */ static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - /* - * Microsoft Wireless Desktop Receiver (Model 1028) has - * 'Usage Min/Max' where it ought to have 'Physical Min/Max' - */ if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 && rdesc[559] == 0x29) { hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n"); rdesc[557] = 0x35; rdesc[559] = 0x45; } - /* the same as above (s/usage/physical/) */ - if ((quirks & MS_RDESC_3K) && *rsize == 106 && - !memcmp((char []){ 0x19, 0x00, 0x29, 0xff }, - &rdesc[94], 4)) { - rdesc[94] = 0x35; - rdesc[96] = 0x45; - } return rdesc; } @@ -200,7 +192,7 @@ static const struct hid_device_id ms_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB), .driver_data = MS_PRESENTER }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K), - .driver_data = MS_ERGONOMY | MS_RDESC_3K }, + .driver_data = MS_ERGONOMY }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0), .driver_data = MS_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), diff --git a/trunk/drivers/hid/hid-multitouch.c b/trunk/drivers/hid/hid-multitouch.c index 7867d69f0efe..3eb02b94fc87 100644 --- a/trunk/drivers/hid/hid-multitouch.c +++ b/trunk/drivers/hid/hid-multitouch.c @@ -210,7 +210,8 @@ static struct mt_class mt_classes[] = { }, { .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | - MT_QUIRK_SLOT_IS_CONTACTNUMBER + MT_QUIRK_SLOT_IS_CONTACTNUMBER, + .maxcontacts = 10 }, { .name = MT_CLS_FLATFROG, @@ -420,11 +421,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, * contact max are global to the report */ td->last_field_index = field->index; return -1; + } case HID_DG_TOUCH: /* Legacy devices use TIPSWITCH and not TOUCH. * Let's just ignore this field. */ return -1; - } /* let hid-input decide for the others */ return 0; diff --git a/trunk/drivers/i2c/Makefile b/trunk/drivers/i2c/Makefile index 1722f50f2473..beee6b2d361d 100644 --- a/trunk/drivers/i2c/Makefile +++ b/trunk/drivers/i2c/Makefile @@ -8,7 +8,6 @@ obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o obj-$(CONFIG_I2C_MUX) += i2c-mux.o obj-y += algos/ busses/ muxes/ -obj-$(CONFIG_I2C_STUB) += i2c-stub.o ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG CFLAGS_i2c-core.o := -Wno-deprecated-declarations diff --git a/trunk/drivers/i2c/busses/Kconfig b/trunk/drivers/i2c/busses/Kconfig index e9df4612b7eb..65dd599a0262 100644 --- a/trunk/drivers/i2c/busses/Kconfig +++ b/trunk/drivers/i2c/busses/Kconfig @@ -81,6 +81,7 @@ config I2C_I801 tristate "Intel 82801 (ICH/PCH)" depends on PCI select CHECK_SIGNATURE if X86 && DMI + select GPIOLIB if I2C_MUX help If you say yes to this option, support will be included for the Intel 801 family of mainboard I2C interfaces. Specifically, the following diff --git a/trunk/drivers/i2c/busses/Makefile b/trunk/drivers/i2c/busses/Makefile index 395b516ffa08..2d33d62952c1 100644 --- a/trunk/drivers/i2c/busses/Makefile +++ b/trunk/drivers/i2c/busses/Makefile @@ -85,6 +85,7 @@ obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o +obj-$(CONFIG_I2C_STUB) += i2c-stub.o obj-$(CONFIG_SCx200_ACB) += scx200_acb.o obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o diff --git a/trunk/drivers/i2c/busses/i2c-i801.c b/trunk/drivers/i2c/busses/i2c-i801.c index 6abc00d59881..37793156bd93 100644 --- a/trunk/drivers/i2c/busses/i2c-i801.c +++ b/trunk/drivers/i2c/busses/i2c-i801.c @@ -82,8 +82,7 @@ #include #include -#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ - defined CONFIG_DMI +#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE #include #include #include @@ -193,8 +192,7 @@ struct i801_priv { int len; u8 *data; -#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ - defined CONFIG_DMI +#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE const struct i801_mux_config *mux_drvdata; struct platform_device *mux_pdev; #endif @@ -923,8 +921,7 @@ static void __init input_apanel_init(void) {} static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {} #endif /* CONFIG_X86 && CONFIG_DMI */ -#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ - defined CONFIG_DMI +#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE static struct i801_mux_config i801_mux_config_asus_z8_d12 = { .gpio_chip = "gpio_ich", .values = { 0x02, 0x03 }, @@ -1062,7 +1059,7 @@ static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv) id = dmi_first_match(mux_dmi_table); if (id) { - /* Remove branch classes from trunk */ + /* Remove from branch classes from trunk */ mux_config = id->driver_data; for (i = 0; i < mux_config->n_values; i++) class &= ~mux_config->classes[i]; diff --git a/trunk/drivers/i2c/i2c-stub.c b/trunk/drivers/i2c/busses/i2c-stub.c similarity index 75% rename from trunk/drivers/i2c/i2c-stub.c rename to trunk/drivers/i2c/busses/i2c-stub.c index d0a9c590c3cd..b1b3447942c9 100644 --- a/trunk/drivers/i2c/i2c-stub.c +++ b/trunk/drivers/i2c/busses/i2c-stub.c @@ -2,7 +2,7 @@ i2c-stub.c - I2C/SMBus chip emulator Copyright (c) 2004 Mark M. Hoffman - Copyright (C) 2007, 2012 Jean Delvare + Copyright (C) 2007 Jean Delvare 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 @@ -51,8 +51,8 @@ struct stub_chip { static struct stub_chip *stub_chips; /* Return negative errno on error. */ -static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags, - char read_write, u8 command, int size, union i2c_smbus_data *data) +static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, + char read_write, u8 command, int size, union i2c_smbus_data * data) { s32 ret; int i, len; @@ -78,14 +78,14 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags, case I2C_SMBUS_BYTE: if (read_write == I2C_SMBUS_WRITE) { chip->pointer = command; - dev_dbg(&adap->dev, - "smbus byte - addr 0x%02x, wrote 0x%02x.\n", - addr, command); + dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " + "wrote 0x%02x.\n", + addr, command); } else { data->byte = chip->words[chip->pointer++] & 0xff; - dev_dbg(&adap->dev, - "smbus byte - addr 0x%02x, read 0x%02x.\n", - addr, data->byte); + dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " + "read 0x%02x.\n", + addr, data->byte); } ret = 0; @@ -95,14 +95,14 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags, if (read_write == I2C_SMBUS_WRITE) { chip->words[command] &= 0xff00; chip->words[command] |= data->byte; - dev_dbg(&adap->dev, - "smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n", - addr, data->byte, command); + dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " + "wrote 0x%02x at 0x%02x.\n", + addr, data->byte, command); } else { data->byte = chip->words[command] & 0xff; - dev_dbg(&adap->dev, - "smbus byte data - addr 0x%02x, read 0x%02x at 0x%02x.\n", - addr, data->byte, command); + dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " + "read 0x%02x at 0x%02x.\n", + addr, data->byte, command); } chip->pointer = command + 1; @@ -112,14 +112,14 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags, case I2C_SMBUS_WORD_DATA: if (read_write == I2C_SMBUS_WRITE) { chip->words[command] = data->word; - dev_dbg(&adap->dev, - "smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n", - addr, data->word, command); + dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " + "wrote 0x%04x at 0x%02x.\n", + addr, data->word, command); } else { data->word = chip->words[command]; - dev_dbg(&adap->dev, - "smbus word data - addr 0x%02x, read 0x%04x at 0x%02x.\n", - addr, data->word, command); + dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " + "read 0x%04x at 0x%02x.\n", + addr, data->word, command); } ret = 0; @@ -132,17 +132,17 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags, chip->words[command + i] &= 0xff00; chip->words[command + i] |= data->block[1 + i]; } - dev_dbg(&adap->dev, - "i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n", - addr, len, command); + dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " + "wrote %d bytes at 0x%02x.\n", + addr, len, command); } else { for (i = 0; i < len; i++) { data->block[1 + i] = chip->words[command + i] & 0xff; } - dev_dbg(&adap->dev, - "i2c block data - addr 0x%02x, read %d bytes at 0x%02x.\n", - addr, len, command); + dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " + "read %d bytes at 0x%02x.\n", + addr, len, command); } ret = 0; @@ -179,24 +179,25 @@ static int __init i2c_stub_init(void) int i, ret; if (!chip_addr[0]) { - pr_err("i2c-stub: Please specify a chip address\n"); + printk(KERN_ERR "i2c-stub: Please specify a chip address\n"); return -ENODEV; } for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) { if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) { - pr_err("i2c-stub: Invalid chip address 0x%02x\n", - chip_addr[i]); + printk(KERN_ERR "i2c-stub: Invalid chip address " + "0x%02x\n", chip_addr[i]); return -EINVAL; } - pr_info("i2c-stub: Virtual chip at 0x%02x\n", chip_addr[i]); + printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n", + chip_addr[i]); } /* Allocate memory for all chips at once */ stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL); if (!stub_chips) { - pr_err("i2c-stub: Out of memory\n"); + printk(KERN_ERR "i2c-stub: Out of memory\n"); return -ENOMEM; } @@ -218,3 +219,4 @@ MODULE_LICENSE("GPL"); module_init(i2c_stub_init); module_exit(i2c_stub_exit); + diff --git a/trunk/drivers/infiniband/hw/cxgb4/mem.c b/trunk/drivers/infiniband/hw/cxgb4/mem.c index afd81790ab3c..57e07c61ace2 100644 --- a/trunk/drivers/infiniband/hw/cxgb4/mem.c +++ b/trunk/drivers/infiniband/hw/cxgb4/mem.c @@ -468,7 +468,7 @@ struct ib_mr *c4iw_register_phys_mem(struct ib_pd *pd, ret = alloc_pbl(mhp, npages); if (ret) { kfree(page_list); - goto err; + goto err_pbl; } ret = write_pbl(&mhp->rhp->rdev, page_list, mhp->attr.pbl_addr, diff --git a/trunk/drivers/infiniband/hw/mlx4/alias_GUID.c b/trunk/drivers/infiniband/hw/mlx4/alias_GUID.c index 2f215b93db6b..d2fb38d43571 100644 --- a/trunk/drivers/infiniband/hw/mlx4/alias_GUID.c +++ b/trunk/drivers/infiniband/hw/mlx4/alias_GUID.c @@ -107,7 +107,7 @@ static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index { if (index >= NUM_ALIAS_GUID_PER_PORT) { pr_err("%s: ERROR: asked for index:%d\n", __func__, index); - return (__force __be64) -1; + return (__force __be64) ((u64) 0xFFFFFFFFFFFFFFFFUL); } return *(__be64 *)&dev->sriov.demux[port - 1].guid_cache[index]; } diff --git a/trunk/drivers/infiniband/hw/mlx4/mad.c b/trunk/drivers/infiniband/hw/mlx4/mad.c index 0a903c129f0a..21a794152d15 100644 --- a/trunk/drivers/infiniband/hw/mlx4/mad.c +++ b/trunk/drivers/infiniband/hw/mlx4/mad.c @@ -409,45 +409,38 @@ int mlx4_ib_find_real_gid(struct ib_device *ibdev, u8 port, __be64 guid) } -static int find_slave_port_pkey_ix(struct mlx4_ib_dev *dev, int slave, - u8 port, u16 pkey, u16 *ix) +static int get_pkey_phys_indices(struct mlx4_ib_dev *ibdev, u8 port, u8 ph_pkey_ix, + u8 *full_pk_ix, u8 *partial_pk_ix, + int *is_full_member) { - int i, ret; - u8 unassigned_pkey_ix, pkey_ix, partial_ix = 0xFF; - u16 slot_pkey; - - if (slave == mlx4_master_func_num(dev->dev)) - return ib_find_cached_pkey(&dev->ib_dev, port, pkey, ix); - - unassigned_pkey_ix = dev->dev->phys_caps.pkey_phys_table_len[port] - 1; + u16 search_pkey; + int fm; + int err = 0; + u16 pk; - for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) { - if (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == unassigned_pkey_ix) - continue; - - pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][i]; + err = ib_get_cached_pkey(&ibdev->ib_dev, port, ph_pkey_ix, &search_pkey); + if (err) + return err; - ret = ib_get_cached_pkey(&dev->ib_dev, port, pkey_ix, &slot_pkey); - if (ret) - continue; - if ((slot_pkey & 0x7FFF) == (pkey & 0x7FFF)) { - if (slot_pkey & 0x8000) { - *ix = (u16) pkey_ix; - return 0; - } else { - /* take first partial pkey index found */ - if (partial_ix == 0xFF) - partial_ix = pkey_ix; - } - } + fm = (search_pkey & 0x8000) ? 1 : 0; + if (fm) { + *full_pk_ix = ph_pkey_ix; + search_pkey &= 0x7FFF; + } else { + *partial_pk_ix = ph_pkey_ix; + search_pkey |= 0x8000; } - if (partial_ix < 0xFF) { - *ix = (u16) partial_ix; - return 0; - } + if (ib_find_exact_cached_pkey(&ibdev->ib_dev, port, search_pkey, &pk)) + pk = 0xFFFF; - return -EINVAL; + if (fm) + *partial_pk_ix = (pk & 0xFF); + else + *full_pk_ix = (pk & 0xFF); + + *is_full_member = fm; + return err; } int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port, @@ -465,8 +458,10 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port, unsigned tun_tx_ix = 0; int dqpn; int ret = 0; + int i; + int is_full_member = 0; u16 tun_pkey_ix; - u16 cached_pkey; + u8 ph_pkey_ix, full_pk_ix = 0, partial_pk_ix = 0; if (dest_qpt > IB_QPT_GSI) return -EINVAL; @@ -486,17 +481,27 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port, else tun_qp = &tun_ctx->qp[1]; - /* compute P_Key index to put in tunnel header for slave */ + /* compute pkey index for slave */ + /* get physical pkey -- virtualized Dom0 pkey to phys*/ if (dest_qpt) { - u16 pkey_ix; - ret = ib_get_cached_pkey(&dev->ib_dev, port, wc->pkey_index, &cached_pkey); + ph_pkey_ix = + dev->pkeys.virt2phys_pkey[mlx4_master_func_num(dev->dev)][port - 1][wc->pkey_index]; + + /* now, translate this to the slave pkey index */ + ret = get_pkey_phys_indices(dev, port, ph_pkey_ix, &full_pk_ix, + &partial_pk_ix, &is_full_member); if (ret) return -EINVAL; - ret = find_slave_port_pkey_ix(dev, slave, port, cached_pkey, &pkey_ix); - if (ret) + for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) { + if ((dev->pkeys.virt2phys_pkey[slave][port - 1][i] == full_pk_ix) || + (is_full_member && + (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == partial_pk_ix))) + break; + } + if (i == dev->dev->caps.pkey_table_len[port]) return -EINVAL; - tun_pkey_ix = pkey_ix; + tun_pkey_ix = i; } else tun_pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][0]; diff --git a/trunk/drivers/infiniband/hw/mlx4/mcg.c b/trunk/drivers/infiniband/hw/mlx4/mcg.c index 25b2cdff00f8..3c3b54c3fdd9 100644 --- a/trunk/drivers/infiniband/hw/mlx4/mcg.c +++ b/trunk/drivers/infiniband/hw/mlx4/mcg.c @@ -233,8 +233,7 @@ static int send_mad_to_slave(int slave, struct mlx4_ib_demux_ctx *ctx, ib_query_ah(dev->sm_ah[ctx->port - 1], &ah_attr); - if (ib_find_cached_pkey(&dev->ib_dev, ctx->port, IB_DEFAULT_PKEY_FULL, &wc.pkey_index)) - return -EINVAL; + wc.pkey_index = 0; wc.sl = 0; wc.dlid_path_bits = 0; wc.port_num = ctx->port; @@ -1075,6 +1074,10 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy unsigned long end; int count; + if (ctx->flushing) + return; + + ctx->flushing = 1; for (i = 0; i < MAX_VFS; ++i) clean_vf_mcast(ctx, i); @@ -1104,6 +1107,9 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy force_clean_group(group); } mutex_unlock(&ctx->mcg_table_lock); + + if (!destroy_wq) + ctx->flushing = 0; } struct clean_work { @@ -1117,7 +1123,6 @@ static void mcg_clean_task(struct work_struct *work) struct clean_work *cw = container_of(work, struct clean_work, work); _mlx4_ib_mcg_port_cleanup(cw->ctx, cw->destroy_wq); - cw->ctx->flushing = 0; kfree(cw); } @@ -1125,20 +1130,13 @@ void mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy_wq) { struct clean_work *work; - if (ctx->flushing) - return; - - ctx->flushing = 1; - if (destroy_wq) { _mlx4_ib_mcg_port_cleanup(ctx, destroy_wq); - ctx->flushing = 0; return; } work = kmalloc(sizeof *work, GFP_KERNEL); if (!work) { - ctx->flushing = 0; mcg_warn("failed allocating work for cleanup\n"); return; } diff --git a/trunk/drivers/input/mouse/bcm5974.c b/trunk/drivers/input/mouse/bcm5974.c index 2baff1b79a55..3a78f235fa3e 100644 --- a/trunk/drivers/input/mouse/bcm5974.c +++ b/trunk/drivers/input/mouse/bcm5974.c @@ -84,10 +84,6 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262 #define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263 #define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS 0x0264 -/* MacbookPro10,2 (unibody, October 2012) */ -#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259 -#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a -#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b #define BCM5974_DEVICE(prod) { \ .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ @@ -141,10 +137,6 @@ static const struct usb_device_id bcm5974_table[] = { BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS), - /* MacbookPro10,2 */ - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS), /* Terminating entry */ {} }; @@ -387,19 +379,6 @@ static const struct bcm5974_config bcm5974_config_table[] = { { SN_COORD, -150, 6730 }, { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } }, - { - USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI, - USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO, - USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS, - HAS_INTEGRATED_BUTTON, - 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { SN_PRESSURE, 0, 300 }, - { SN_WIDTH, 0, 2048 }, - { SN_COORD, -4750, 5280 }, - { SN_COORD, -150, 6730 }, - { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } - }, {} }; diff --git a/trunk/drivers/isdn/gigaset/bas-gigaset.c b/trunk/drivers/isdn/gigaset/bas-gigaset.c index c44950d3eb7b..527588708948 100644 --- a/trunk/drivers/isdn/gigaset/bas-gigaset.c +++ b/trunk/drivers/isdn/gigaset/bas-gigaset.c @@ -617,13 +617,7 @@ static void int_in_work(struct work_struct *work) if (rc == 0) /* success, resubmit interrupt read URB */ rc = usb_submit_urb(urb, GFP_ATOMIC); - - switch (rc) { - case 0: /* success */ - case -ENODEV: /* device gone */ - case -EINVAL: /* URB already resubmitted, or terminal badness */ - break; - default: /* failure: try to recover by resetting the device */ + if (rc != 0 && rc != -ENODEV) { dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc)); rc = usb_lock_device_for_reset(ucs->udev, ucs->interface); if (rc == 0) { @@ -2448,9 +2442,7 @@ static void gigaset_disconnect(struct usb_interface *interface) } /* gigaset_suspend - * This function is called before the USB connection is suspended - * or before the USB device is reset. - * In the latter case, message == PMSG_ON. + * This function is called before the USB connection is suspended. */ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) { @@ -2506,12 +2498,7 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) del_timer_sync(&ucs->timer_atrdy); del_timer_sync(&ucs->timer_cmd_in); del_timer_sync(&ucs->timer_int_in); - - /* don't try to cancel int_in_wq from within reset as it - * might be the one requesting the reset - */ - if (message.event != PM_EVENT_ON) - cancel_work_sync(&ucs->int_in_wq); + cancel_work_sync(&ucs->int_in_wq); gig_dbg(DEBUG_SUSPEND, "suspend complete"); return 0; diff --git a/trunk/drivers/md/faulty.c b/trunk/drivers/md/faulty.c index 5e7dc772f5de..45135f69509c 100644 --- a/trunk/drivers/md/faulty.c +++ b/trunk/drivers/md/faulty.c @@ -315,11 +315,8 @@ static int run(struct mddev *mddev) } conf->nfaults = 0; - rdev_for_each(rdev, mddev) { + rdev_for_each(rdev, mddev) conf->rdev = rdev; - disk_stack_limits(mddev->gendisk, rdev->bdev, - rdev->data_offset << 9); - } md_set_array_sectors(mddev, faulty_size(mddev, 0, 0)); mddev->private = conf; diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c index 636bae0405e8..8034fbd6190c 100644 --- a/trunk/drivers/md/raid1.c +++ b/trunk/drivers/md/raid1.c @@ -2710,7 +2710,7 @@ static struct r1conf *setup_conf(struct mddev *mddev) || disk_idx < 0) continue; if (test_bit(Replacement, &rdev->flags)) - disk = conf->mirrors + mddev->raid_disks + disk_idx; + disk = conf->mirrors + conf->raid_disks + disk_idx; else disk = conf->mirrors + disk_idx; diff --git a/trunk/drivers/md/raid10.c b/trunk/drivers/md/raid10.c index d1295aff4173..906ccbd0f7dc 100644 --- a/trunk/drivers/md/raid10.c +++ b/trunk/drivers/md/raid10.c @@ -1783,7 +1783,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev) clear_bit(Unmerged, &rdev->flags); } md_integrity_add_rdev(rdev, mddev); - if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev))) + if (blk_queue_discard(bdev_get_queue(rdev->bdev))) queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); print_conf(conf); @@ -3613,14 +3613,11 @@ static int run(struct mddev *mddev) discard_supported = true; } - if (mddev->queue) { - if (discard_supported) - queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, - mddev->queue); - else - queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, - mddev->queue); - } + if (discard_supported) + queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); + else + queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); + /* need to check that every block has at least one working mirror */ if (!enough(conf, -1)) { printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n", diff --git a/trunk/drivers/net/can/flexcan.c b/trunk/drivers/net/can/flexcan.c index a412bf6d73ef..c78ecfca1e45 100644 --- a/trunk/drivers/net/can/flexcan.c +++ b/trunk/drivers/net/can/flexcan.c @@ -144,22 +144,9 @@ #define FLEXCAN_MB_CODE_MASK (0xf0ffffff) -/* - * FLEXCAN hardware feature flags - * - * Below is some version info we got: - * SOC Version IP-Version Glitch- [TR]WRN_INT - * Filter? connected? - * MX25 FlexCAN2 03.00.00.00 no no - * MX28 FlexCAN2 03.00.04.00 yes yes - * MX35 FlexCAN2 03.00.00.00 no no - * MX53 FlexCAN2 03.00.00.00 yes no - * MX6s FlexCAN3 10.00.12.00 yes yes - * - * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. - */ +/* FLEXCAN hardware feature flags */ #define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */ -#define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* [TR]WRN_INT not connected */ +#define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* Broken error state handling */ /* Structure of the message buffer */ struct flexcan_mb { @@ -218,7 +205,7 @@ static struct flexcan_devtype_data fsl_p1010_devtype_data = { }; static struct flexcan_devtype_data fsl_imx28_devtype_data; static struct flexcan_devtype_data fsl_imx6q_devtype_data = { - .features = FLEXCAN_HAS_V10_FEATURES, + .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_BROKEN_ERR_STATE, }; static const struct can_bittiming_const flexcan_bittiming_const = { diff --git a/trunk/drivers/net/can/sja1000/peak_pci.c b/trunk/drivers/net/can/sja1000/peak_pci.c index 6525dbcca4e3..f5b82aeb2540 100644 --- a/trunk/drivers/net/can/sja1000/peak_pci.c +++ b/trunk/drivers/net/can/sja1000/peak_pci.c @@ -30,10 +30,9 @@ #include "sja1000.h" -MODULE_AUTHOR("Stephane Grosjean "); +MODULE_AUTHOR("Wolfgang Grandegger "); MODULE_DESCRIPTION("Socket-CAN driver for PEAK PCAN PCI family cards"); MODULE_SUPPORTED_DEVICE("PEAK PCAN PCI/PCIe/PCIeC miniPCI CAN cards"); -MODULE_SUPPORTED_DEVICE("PEAK PCAN miniPCIe/cPCI PC/104+ PCI/104e CAN Cards"); MODULE_LICENSE("GPL v2"); #define DRV_NAME "peak_pci" @@ -65,11 +64,7 @@ struct peak_pci_chan { #define PEAK_PCI_DEVICE_ID 0x0001 /* for PCI/PCIe slot cards */ #define PEAK_PCIEC_DEVICE_ID 0x0002 /* for ExpressCard slot cards */ #define PEAK_PCIE_DEVICE_ID 0x0003 /* for nextgen PCIe slot cards */ -#define PEAK_CPCI_DEVICE_ID 0x0004 /* for nextgen cPCI slot cards */ -#define PEAK_MPCI_DEVICE_ID 0x0005 /* for nextgen miniPCI slot cards */ -#define PEAK_PC_104P_DEVICE_ID 0x0006 /* PCAN-PC/104+ cards */ -#define PEAK_PCI_104E_DEVICE_ID 0x0007 /* PCAN-PCI/104 Express cards */ -#define PEAK_MPCIE_DEVICE_ID 0x0008 /* The miniPCIe slot cards */ +#define PEAK_MPCI_DEVICE_ID 0x0008 /* The miniPCI slot cards */ #define PEAK_PCI_CHAN_MAX 4 @@ -81,10 +76,6 @@ static DEFINE_PCI_DEVICE_TABLE(peak_pci_tbl) = { {PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, #ifdef CONFIG_CAN_PEAK_PCIEC {PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, #endif diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 378988b5709a..a4da893ac1e1 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -251,8 +251,6 @@ struct adapter_params { unsigned char rev; /* chip revision */ unsigned char offload; - unsigned char bypass; - unsigned int ofldq_wr_cred; }; @@ -644,23 +642,6 @@ extern int dbfifo_int_thresh; #define for_each_port(adapter, iter) \ for (iter = 0; iter < (adapter)->params.nports; ++iter) -static inline int is_bypass(struct adapter *adap) -{ - return adap->params.bypass; -} - -static inline int is_bypass_device(int device) -{ - /* this should be set based upon device capabilities */ - switch (device) { - case 0x440b: - case 0x440c: - return 1; - default: - return 0; - } -} - static inline unsigned int core_ticks_per_usec(const struct adapter *adap) { return adap->params.vpd.cclk / 1000; diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index c1cde11b0c6d..604f4f87f550 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -3513,6 +3513,18 @@ static int adap_init0_no_config(struct adapter *adapter, int reset) if (ret < 0) goto bye; +#ifndef CONFIG_CHELSIO_T4_OFFLOAD + /* + * If we're a pure NIC driver then disable all offloading facilities. + * This will allow the firmware to optimize aspects of the hardware + * configuration which will result in improved performance. + */ + caps_cmd.ofldcaps = 0; + caps_cmd.iscsicaps = 0; + caps_cmd.rdmacaps = 0; + caps_cmd.fcoecaps = 0; +#endif + if (caps_cmd.niccaps & htons(FW_CAPS_CONFIG_NIC_VM)) { if (!vf_acls) caps_cmd.niccaps ^= htons(FW_CAPS_CONFIG_NIC_VM); @@ -3733,7 +3745,6 @@ static int adap_init0(struct adapter *adap) u32 v, port_vec; enum dev_state state; u32 params[7], val[7]; - struct fw_caps_config_cmd caps_cmd; int reset = 1, j; /* @@ -3887,9 +3898,6 @@ static int adap_init0(struct adapter *adap) goto bye; } - if (is_bypass_device(adap->pdev->device)) - adap->params.bypass = 1; - /* * Grab some of our basic fundamental operating parameters. */ @@ -3932,12 +3940,13 @@ static int adap_init0(struct adapter *adap) adap->tids.aftid_end = val[1]; } +#ifdef CONFIG_CHELSIO_T4_OFFLOAD /* * Get device capabilities so we can determine what resources we need * to manage. */ memset(&caps_cmd, 0, sizeof(caps_cmd)); - caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | + caps_cmd.op_to_write = htonl(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | FW_CMD_REQUEST | FW_CMD_READ); caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd)); ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd), @@ -3982,6 +3991,15 @@ static int adap_init0(struct adapter *adap) adap->vres.ddp.size = val[4] - val[3] + 1; adap->params.ofldq_wr_cred = val[5]; + params[0] = FW_PARAM_PFVF(ETHOFLD_START); + params[1] = FW_PARAM_PFVF(ETHOFLD_END); + ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2, + params, val); + if ((val[0] != val[1]) && (ret >= 0)) { + adap->tids.uotid_base = val[0]; + adap->tids.nuotids = val[1] - val[0] + 1; + } + adap->params.offload = 1; } if (caps_cmd.rdmacaps) { @@ -4030,6 +4048,7 @@ static int adap_init0(struct adapter *adap) } #undef FW_PARAM_PFVF #undef FW_PARAM_DEV +#endif /* CONFIG_CHELSIO_T4_OFFLOAD */ /* * These are finalized by FW initialization, load their values now. diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index 39bec73ff87c..1b899fea1a91 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -102,9 +102,6 @@ struct tid_info { unsigned int ftid_base; unsigned int aftid_base; unsigned int aftid_end; - /* Server filter region */ - unsigned int sftid_base; - unsigned int nsftids; spinlock_t atid_lock ____cacheline_aligned_in_smp; union aopen_entry *afree; diff --git a/trunk/drivers/net/ethernet/freescale/gianfar_ptp.c b/trunk/drivers/net/ethernet/freescale/gianfar_ptp.c index 2e5daee0438a..b9db0e040563 100644 --- a/trunk/drivers/net/ethernet/freescale/gianfar_ptp.c +++ b/trunk/drivers/net/ethernet/freescale/gianfar_ptp.c @@ -478,7 +478,7 @@ static int gianfar_ptp_probe(struct platform_device *dev) pr_err("no resource\n"); goto no_resource; } - if (request_resource(&iomem_resource, etsects->rsrc)) { + if (request_resource(&ioport_resource, etsects->rsrc)) { pr_err("resource busy\n"); goto no_resource; } diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c index b35094c590ba..c10e3a6de09f 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -143,6 +143,7 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, mlx4_bf_free(mdev->dev, &ring->bf); mlx4_qp_remove(mdev->dev, &ring->qp); mlx4_qp_free(mdev->dev, &ring->qp); + mlx4_qp_release_range(mdev->dev, ring->qpn, 1); mlx4_en_unmap_buffer(&ring->wqres.buf); mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size); kfree(ring->bounce_buf); @@ -711,7 +712,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) if (bounce) tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size); - if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tx_tag_present(skb)) { + if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tag) { *(__be32 *) (&tx_desc->ctrl.vlan_tag) |= cpu_to_be32(ring->doorbell_qpn); op_own |= htonl((bf_index & 0xffff) << 8); /* Ensure new descirptor hits memory diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/eq.c b/trunk/drivers/net/ethernet/mellanox/mlx4/eq.c index b84a88bc44dc..51c764901ad2 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -329,6 +329,9 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave, ctx = &priv->mfunc.master.slave_state[slave]; spin_lock_irqsave(&ctx->lock, flags); + mlx4_dbg(dev, "%s: slave: %d, current state: %d new event :%d\n", + __func__, slave, cur_state, event); + switch (cur_state) { case SLAVE_PORT_DOWN: if (MLX4_PORT_STATE_DEV_EVENT_PORT_UP == event) @@ -363,6 +366,9 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave, goto out; } ret = mlx4_get_slave_port_state(dev, slave, port); + mlx4_dbg(dev, "%s: slave: %d, current state: %d new event" + " :%d gen_event: %d\n", + __func__, slave, cur_state, event, *gen_event); out: spin_unlock_irqrestore(&ctx->lock, flags); @@ -837,18 +843,6 @@ static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq) return priv->eq_table.uar_map[index] + 0x800 + 8 * (eq->eqn % 4); } -static void mlx4_unmap_uar(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int i; - - for (i = 0; i < mlx4_num_eq_uar(dev); ++i) - if (priv->eq_table.uar_map[i]) { - iounmap(priv->eq_table.uar_map[i]); - priv->eq_table.uar_map[i] = NULL; - } -} - static int mlx4_create_eq(struct mlx4_dev *dev, int nent, u8 intr, struct mlx4_eq *eq) { @@ -1213,7 +1207,6 @@ int mlx4_init_eq_table(struct mlx4_dev *dev) mlx4_free_irqs(dev); err_out_bitmap: - mlx4_unmap_uar(dev); mlx4_bitmap_cleanup(&priv->eq_table.bitmap); err_out_free: @@ -1238,7 +1231,10 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev) if (!mlx4_is_slave(dev)) mlx4_unmap_clr_int(dev); - mlx4_unmap_uar(dev); + for (i = 0; i < mlx4_num_eq_uar(dev); ++i) + if (priv->eq_table.uar_map[i]) + iounmap(priv->eq_table.uar_map[i]); + mlx4_bitmap_cleanup(&priv->eq_table.bitmap); kfree(priv->eq_table.uar_map); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/main.c b/trunk/drivers/net/ethernet/mellanox/mlx4/main.c index 2aa80afd98d2..80df2ab0177c 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1405,10 +1405,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev) unmap_bf_area(dev); err_close: - if (mlx4_is_slave(dev)) - mlx4_slave_exit(dev); - else - mlx4_CLOSE_HCA(dev, 0); + mlx4_close_hca(dev); err_free_icm: if (!mlx4_is_slave(dev)) diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/trunk/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index b05705f50f0f..926c911c0ac4 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -330,6 +330,9 @@ static void update_pkey_index(struct mlx4_dev *dev, int slave, new_index = priv->virt2phys_pkey[slave][port - 1][orig_index]; *(u8 *)(inbox->buf + 35) = new_index; + + mlx4_dbg(dev, "port = %d, orig pkey index = %d, " + "new pkey index = %d\n", port, orig_index, new_index); } static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox, @@ -348,6 +351,9 @@ static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox, if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH) qp_ctx->alt_path.mgid_index = slave & 0x7F; } + + mlx4_dbg(dev, "slave %d, new gid index: 0x%x ", + slave, qp_ctx->pri_path.mgid_index); } static int mpt_mask(struct mlx4_dev *dev) diff --git a/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 4c4fe5b1a29a..b2a94d02a521 100644 --- a/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -338,6 +338,26 @@ static void pch_gbe_wait_clr_bit(void *reg, u32 bit) pr_err("Error: busy bit is not cleared\n"); } +/** + * pch_gbe_wait_clr_bit_irq - Wait to clear a bit for interrupt context + * @reg: Pointer of register + * @busy: Busy bit + */ +static int pch_gbe_wait_clr_bit_irq(void *reg, u32 bit) +{ + u32 tmp; + int ret = -1; + /* wait busy */ + tmp = 20; + while ((ioread32(reg) & bit) && --tmp) + udelay(5); + if (!tmp) + pr_err("Error: busy bit is not cleared\n"); + else + ret = 0; + return ret; +} + /** * pch_gbe_mac_mar_set - Set MAC address register * @hw: Pointer to the HW structure @@ -389,20 +409,15 @@ static void pch_gbe_mac_reset_hw(struct pch_gbe_hw *hw) return; } -static void pch_gbe_disable_mac_rx(struct pch_gbe_hw *hw) +static void pch_gbe_mac_reset_rx(struct pch_gbe_hw *hw) { - u32 rctl; - /* Disables Receive MAC */ - rctl = ioread32(&hw->reg->MAC_RX_EN); - iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN); -} - -static void pch_gbe_enable_mac_rx(struct pch_gbe_hw *hw) -{ - u32 rctl; - /* Enables Receive MAC */ - rctl = ioread32(&hw->reg->MAC_RX_EN); - iowrite32((rctl | PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN); + /* Read the MAC addresses. and store to the private data */ + pch_gbe_mac_read_mac_addr(hw); + iowrite32(PCH_GBE_RX_RST, &hw->reg->RESET); + pch_gbe_wait_clr_bit_irq(&hw->reg->RESET, PCH_GBE_RX_RST); + /* Setup the MAC addresses */ + pch_gbe_mac_mar_set(hw, hw->mac.addr, 0); + return; } /** @@ -898,7 +913,7 @@ static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter) static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter) { struct pch_gbe_hw *hw = &adapter->hw; - u32 rdba, rdlen, rxdma; + u32 rdba, rdlen, rctl, rxdma; pr_debug("dma adr = 0x%08llx size = 0x%08x\n", (unsigned long long)adapter->rx_ring->dma, @@ -906,7 +921,9 @@ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter) pch_gbe_mac_force_mac_fc(hw); - pch_gbe_disable_mac_rx(hw); + /* Disables Receive MAC */ + rctl = ioread32(&hw->reg->MAC_RX_EN); + iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN); /* Disables Receive DMA */ rxdma = ioread32(&hw->reg->DMA_CTRL); @@ -1299,17 +1316,38 @@ void pch_gbe_update_stats(struct pch_gbe_adapter *adapter) spin_unlock_irqrestore(&adapter->stats_lock, flags); } -static void pch_gbe_disable_dma_rx(struct pch_gbe_hw *hw) +static void pch_gbe_stop_receive(struct pch_gbe_adapter *adapter) { + struct pch_gbe_hw *hw = &adapter->hw; u32 rxdma; + u16 value; + int ret; /* Disable Receive DMA */ rxdma = ioread32(&hw->reg->DMA_CTRL); rxdma &= ~PCH_GBE_RX_DMA_EN; iowrite32(rxdma, &hw->reg->DMA_CTRL); + /* Wait Rx DMA BUS is IDLE */ + ret = pch_gbe_wait_clr_bit_irq(&hw->reg->RX_DMA_ST, PCH_GBE_IDLE_CHECK); + if (ret) { + /* Disable Bus master */ + pci_read_config_word(adapter->pdev, PCI_COMMAND, &value); + value &= ~PCI_COMMAND_MASTER; + pci_write_config_word(adapter->pdev, PCI_COMMAND, value); + /* Stop Receive */ + pch_gbe_mac_reset_rx(hw); + /* Enable Bus master */ + value |= PCI_COMMAND_MASTER; + pci_write_config_word(adapter->pdev, PCI_COMMAND, value); + } else { + /* Stop Receive */ + pch_gbe_mac_reset_rx(hw); + } + /* reprogram multicast address register after reset */ + pch_gbe_set_multi(adapter->netdev); } -static void pch_gbe_enable_dma_rx(struct pch_gbe_hw *hw) +static void pch_gbe_start_receive(struct pch_gbe_hw *hw) { u32 rxdma; @@ -1317,6 +1355,9 @@ static void pch_gbe_enable_dma_rx(struct pch_gbe_hw *hw) rxdma = ioread32(&hw->reg->DMA_CTRL); rxdma |= PCH_GBE_RX_DMA_EN; iowrite32(rxdma, &hw->reg->DMA_CTRL); + /* Enables Receive */ + iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN); + return; } /** @@ -1352,7 +1393,7 @@ static irqreturn_t pch_gbe_intr(int irq, void *data) int_en = ioread32(&hw->reg->INT_EN); iowrite32((int_en & ~PCH_GBE_INT_RX_FIFO_ERR), &hw->reg->INT_EN); - pch_gbe_disable_dma_rx(&adapter->hw); + pch_gbe_stop_receive(adapter); int_st |= ioread32(&hw->reg->INT_ST); int_st = int_st & ioread32(&hw->reg->INT_EN); } @@ -1930,12 +1971,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) struct net_device *netdev = adapter->netdev; struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring; struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring; - int err = -EINVAL; + int err; /* Ensure we have a valid MAC */ if (!is_valid_ether_addr(adapter->hw.mac.addr)) { pr_err("Error: Invalid MAC address\n"); - goto out; + return -EINVAL; } /* hardware has been reset, we need to reload some things */ @@ -1948,19 +1989,18 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) err = pch_gbe_request_irq(adapter); if (err) { - pr_err("Error: can't bring device up - irq request failed\n"); - goto out; + pr_err("Error: can't bring device up\n"); + return err; } err = pch_gbe_alloc_rx_buffers_pool(adapter, rx_ring, rx_ring->count); if (err) { - pr_err("Error: can't bring device up - alloc rx buffers pool failed\n"); - goto freeirq; + pr_err("Error: can't bring device up\n"); + return err; } pch_gbe_alloc_tx_buffers(adapter, tx_ring); pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count); adapter->tx_queue_len = netdev->tx_queue_len; - pch_gbe_enable_dma_rx(&adapter->hw); - pch_gbe_enable_mac_rx(&adapter->hw); + pch_gbe_start_receive(&adapter->hw); mod_timer(&adapter->watchdog_timer, jiffies); @@ -1969,11 +2009,6 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) netif_start_queue(adapter->netdev); return 0; - -freeirq: - pch_gbe_free_irq(adapter); -out: - return err; } /** @@ -2370,6 +2405,7 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) int work_done = 0; bool poll_end_flag = false; bool cleaned = false; + u32 int_en; pr_debug("budget : %d\n", budget); @@ -2386,13 +2422,19 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) if (poll_end_flag) { napi_complete(napi); + if (adapter->rx_stop_flag) { + adapter->rx_stop_flag = false; + pch_gbe_start_receive(&adapter->hw); + } pch_gbe_irq_enable(adapter); - } - - if (adapter->rx_stop_flag) { - adapter->rx_stop_flag = false; - pch_gbe_enable_dma_rx(&adapter->hw); - } + } else + if (adapter->rx_stop_flag) { + adapter->rx_stop_flag = false; + pch_gbe_start_receive(&adapter->hw); + int_en = ioread32(&adapter->hw.reg->INT_EN); + iowrite32((int_en | PCH_GBE_INT_RX_FIFO_ERR), + &adapter->hw.reg->INT_EN); + } pr_debug("poll_end_flag : %d work_done : %d budget : %d\n", poll_end_flag, work_done, budget); diff --git a/trunk/drivers/net/ethernet/qlogic/qla3xxx.c b/trunk/drivers/net/ethernet/qlogic/qla3xxx.c index 6407d0d77e81..df09b1cb742f 100644 --- a/trunk/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/trunk/drivers/net/ethernet/qlogic/qla3xxx.c @@ -2525,13 +2525,6 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev) qdev->req_q_size = (u32) (NUM_REQ_Q_ENTRIES * sizeof(struct ob_mac_iocb_req)); - qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb); - - /* The barrier is required to ensure request and response queue - * addr writes to the registers. - */ - wmb(); - qdev->req_q_virt_addr = pci_alloc_consistent(qdev->pdev, (size_t) qdev->req_q_size, @@ -2543,6 +2536,8 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev) return -ENOMEM; } + qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb); + qdev->rsp_q_virt_addr = pci_alloc_consistent(qdev->pdev, (size_t) qdev->rsp_q_size, diff --git a/trunk/drivers/net/ethernet/ti/Kconfig b/trunk/drivers/net/ethernet/ti/Kconfig index 2c41894d5472..b26cbda5efa9 100644 --- a/trunk/drivers/net/ethernet/ti/Kconfig +++ b/trunk/drivers/net/ethernet/ti/Kconfig @@ -5,7 +5,7 @@ config NET_VENDOR_TI bool "Texas Instruments (TI) devices" default y - depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX)) + depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3)) ---help--- If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from diff --git a/trunk/drivers/net/ethernet/tile/tilegx.c b/trunk/drivers/net/ethernet/tile/tilegx.c index 4e9810013850..4e2a1628484d 100644 --- a/trunk/drivers/net/ethernet/tile/tilegx.c +++ b/trunk/drivers/net/ethernet/tile/tilegx.c @@ -1334,11 +1334,11 @@ static int tso_count_edescs(struct sk_buff *skb) { struct skb_shared_info *sh = skb_shinfo(skb); unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - unsigned int data_len = skb->len - sh_len; + unsigned int data_len = skb->data_len + skb->hdr_len - sh_len; unsigned int p_len = sh->gso_size; long f_id = -1; /* id of the current fragment */ - long f_size = skb_headlen(skb) - sh_len; /* current fragment size */ - long f_used = 0; /* bytes used from the current fragment */ + long f_size = skb->hdr_len; /* size of the current fragment */ + long f_used = sh_len; /* bytes used from the current fragment */ long n; /* size of the current piece of payload */ int num_edescs = 0; int segment; @@ -1353,7 +1353,7 @@ static int tso_count_edescs(struct sk_buff *skb) /* Advance as needed. */ while (f_used >= f_size) { f_id++; - f_size = skb_frag_size(&sh->frags[f_id]); + f_size = sh->frags[f_id].size; f_used = 0; } @@ -1384,13 +1384,13 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, struct iphdr *ih; struct tcphdr *th; unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - unsigned int data_len = skb->len - sh_len; + unsigned int data_len = skb->data_len + skb->hdr_len - sh_len; unsigned char *data = skb->data; unsigned int ih_off, th_off, p_len; unsigned int isum_seed, tsum_seed, id, seq; long f_id = -1; /* id of the current fragment */ - long f_size = skb_headlen(skb) - sh_len; /* current fragment size */ - long f_used = 0; /* bytes used from the current fragment */ + long f_size = skb->hdr_len; /* size of the current fragment */ + long f_used = sh_len; /* bytes used from the current fragment */ long n; /* size of the current piece of payload */ int segment; @@ -1405,7 +1405,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, isum_seed = ((0xFFFF - ih->check) + (0xFFFF - ih->tot_len) + (0xFFFF - ih->id)); - tsum_seed = th->check + (0xFFFF ^ htons(skb->len)); + tsum_seed = th->check + (0xFFFF ^ htons(sh_len + data_len)); id = ntohs(ih->id); seq = ntohl(th->seq); @@ -1444,7 +1444,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, /* Advance as needed. */ while (f_used >= f_size) { f_id++; - f_size = skb_frag_size(&sh->frags[f_id]); + f_size = sh->frags[f_id].size; f_used = 0; } @@ -1478,14 +1478,14 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, struct tile_net_priv *priv = netdev_priv(dev); struct skb_shared_info *sh = skb_shinfo(skb); unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - unsigned int data_len = skb->len - sh_len; + unsigned int data_len = skb->data_len + skb->hdr_len - sh_len; unsigned int p_len = sh->gso_size; gxio_mpipe_edesc_t edesc_head = { { 0 } }; gxio_mpipe_edesc_t edesc_body = { { 0 } }; long f_id = -1; /* id of the current fragment */ - long f_size = skb_headlen(skb) - sh_len; /* current fragment size */ - long f_used = 0; /* bytes used from the current fragment */ - void *f_data = skb->data + sh_len; + long f_size = skb->hdr_len; /* size of the current fragment */ + long f_used = sh_len; /* bytes used from the current fragment */ + void *f_data = skb->data; long n; /* size of the current piece of payload */ unsigned long tx_packets = 0, tx_bytes = 0; unsigned int csum_start; @@ -1516,18 +1516,15 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, /* Egress the payload. */ while (p_used < p_len) { - void *va; /* Advance as needed. */ while (f_used >= f_size) { f_id++; - f_size = skb_frag_size(&sh->frags[f_id]); - f_data = tile_net_frag_buf(&sh->frags[f_id]); + f_size = sh->frags[f_id].size; f_used = 0; + f_data = tile_net_frag_buf(&sh->frags[f_id]); } - va = f_data + f_used; - /* Use bytes from the current fragment. */ n = p_len - p_used; if (n > f_size - f_used) @@ -1536,7 +1533,7 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, p_used += n; /* Egress a piece of the payload. */ - edesc_body.va = va_to_tile_io_addr(va); + edesc_body.va = va_to_tile_io_addr(f_data) + f_used; edesc_body.xfer_size = n; edesc_body.bound = !(p_used < p_len); gxio_mpipe_equeue_put_at(equeue, edesc_body, slot); diff --git a/trunk/drivers/net/phy/Kconfig b/trunk/drivers/net/phy/Kconfig index 961f0b293913..983bbf4d5ef6 100644 --- a/trunk/drivers/net/phy/Kconfig +++ b/trunk/drivers/net/phy/Kconfig @@ -15,11 +15,6 @@ if PHYLIB comment "MII PHY device drivers" -config AT803X_PHY - tristate "Drivers for Atheros AT803X PHYs" - ---help--- - Currently supports the AT8030 and AT8035 model - config AMD_PHY tristate "Drivers for the AMD PHYs" ---help--- diff --git a/trunk/drivers/net/phy/Makefile b/trunk/drivers/net/phy/Makefile index 9645e389a58d..426674debae4 100644 --- a/trunk/drivers/net/phy/Makefile +++ b/trunk/drivers/net/phy/Makefile @@ -25,7 +25,6 @@ obj-$(CONFIG_STE10XP) += ste10Xp.o obj-$(CONFIG_MICREL_PHY) += micrel.o obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o -obj-$(CONFIG_AT803X_PHY) += at803x.o obj-$(CONFIG_AMD_PHY) += amd.o obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o diff --git a/trunk/drivers/net/phy/at803x.c b/trunk/drivers/net/phy/at803x.c deleted file mode 100644 index 45cbc10de01c..000000000000 --- a/trunk/drivers/net/phy/at803x.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * drivers/net/phy/at803x.c - * - * Driver for Atheros 803x PHY - * - * Author: Matus Ujhelyi - * - * 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. - */ - -#include -#include -#include -#include -#include - -#define AT803X_INTR_ENABLE 0x12 -#define AT803X_INTR_STATUS 0x13 -#define AT803X_WOL_ENABLE 0x01 -#define AT803X_DEVICE_ADDR 0x03 -#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C -#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B -#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A -#define AT803X_MMD_ACCESS_CONTROL 0x0D -#define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E -#define AT803X_FUNC_DATA 0x4003 - -MODULE_DESCRIPTION("Atheros 803x PHY driver"); -MODULE_AUTHOR("Matus Ujhelyi"); -MODULE_LICENSE("GPL"); - -static void at803x_set_wol_mac_addr(struct phy_device *phydev) -{ - struct net_device *ndev = phydev->attached_dev; - const u8 *mac; - unsigned int i, offsets[] = { - AT803X_LOC_MAC_ADDR_32_47_OFFSET, - AT803X_LOC_MAC_ADDR_16_31_OFFSET, - AT803X_LOC_MAC_ADDR_0_15_OFFSET, - }; - - if (!ndev) - return; - - mac = (const u8 *) ndev->dev_addr; - - if (!is_valid_ether_addr(mac)) - return; - - for (i = 0; i < 3; i++) { - phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, - AT803X_DEVICE_ADDR); - phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, - offsets[i]); - phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, - AT803X_FUNC_DATA); - phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, - mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); - } -} - -static int at803x_config_init(struct phy_device *phydev) -{ - int val; - u32 features; - int status; - - features = SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI | - SUPPORTED_FIBRE | SUPPORTED_BNC; - - val = phy_read(phydev, MII_BMSR); - if (val < 0) - return val; - - if (val & BMSR_ANEGCAPABLE) - features |= SUPPORTED_Autoneg; - if (val & BMSR_100FULL) - features |= SUPPORTED_100baseT_Full; - if (val & BMSR_100HALF) - features |= SUPPORTED_100baseT_Half; - if (val & BMSR_10FULL) - features |= SUPPORTED_10baseT_Full; - if (val & BMSR_10HALF) - features |= SUPPORTED_10baseT_Half; - - if (val & BMSR_ESTATEN) { - val = phy_read(phydev, MII_ESTATUS); - if (val < 0) - return val; - - if (val & ESTATUS_1000_TFULL) - features |= SUPPORTED_1000baseT_Full; - if (val & ESTATUS_1000_THALF) - features |= SUPPORTED_1000baseT_Half; - } - - phydev->supported = features; - phydev->advertising = features; - - /* enable WOL */ - at803x_set_wol_mac_addr(phydev); - status = phy_write(phydev, AT803X_INTR_ENABLE, AT803X_WOL_ENABLE); - status = phy_read(phydev, AT803X_INTR_STATUS); - - return 0; -} - -/* ATHEROS 8035 */ -static struct phy_driver at8035_driver = { - .phy_id = 0x004dd072, - .name = "Atheros 8035 ethernet", - .phy_id_mask = 0xffffffef, - .config_init = at803x_config_init, - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .config_aneg = &genphy_config_aneg, - .read_status = &genphy_read_status, - .driver = { - .owner = THIS_MODULE, - }, -}; - -/* ATHEROS 8030 */ -static struct phy_driver at8030_driver = { - .phy_id = 0x004dd076, - .name = "Atheros 8030 ethernet", - .phy_id_mask = 0xffffffef, - .config_init = at803x_config_init, - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .config_aneg = &genphy_config_aneg, - .read_status = &genphy_read_status, - .driver = { - .owner = THIS_MODULE, - }, -}; - -static int __init atheros_init(void) -{ - int ret; - - ret = phy_driver_register(&at8035_driver); - if (ret) - goto err1; - - ret = phy_driver_register(&at8030_driver); - if (ret) - goto err2; - - return 0; - -err2: - phy_driver_unregister(&at8035_driver); -err1: - return ret; -} - -static void __exit atheros_exit(void) -{ - phy_driver_unregister(&at8035_driver); - phy_driver_unregister(&at8030_driver); -} - -module_init(atheros_init); -module_exit(atheros_exit); - -static struct mdio_device_id __maybe_unused atheros_tbl[] = { - { 0x004dd076, 0xffffffef }, - { 0x004dd072, 0xffffffef }, - { } -}; - -MODULE_DEVICE_TABLE(mdio, atheros_tbl); diff --git a/trunk/drivers/net/usb/cdc_ether.c b/trunk/drivers/net/usb/cdc_ether.c index d0129827602b..a03de7197049 100644 --- a/trunk/drivers/net/usb/cdc_ether.c +++ b/trunk/drivers/net/usb/cdc_ether.c @@ -592,32 +592,6 @@ static const struct usb_device_id products [] = { .driver_info = 0, }, -/* Novatel USB551L and MC551 - handled by qmi_wwan */ -{ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR - | USB_DEVICE_ID_MATCH_PRODUCT - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = NOVATEL_VENDOR_ID, - .idProduct = 0xB001, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, - .bInterfaceProtocol = USB_CDC_PROTO_NONE, - .driver_info = 0, -}, - -/* Novatel E362 - handled by qmi_wwan */ -{ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR - | USB_DEVICE_ID_MATCH_PRODUCT - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = NOVATEL_VENDOR_ID, - .idProduct = 0x9010, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, - .bInterfaceProtocol = USB_CDC_PROTO_NONE, - .driver_info = 0, -}, - /* * WHITELIST!!! * @@ -630,6 +604,21 @@ static const struct usb_device_id products [] = { * because of bugs/quirks in a given product (like Zaurus, above). */ { + /* Novatel USB551L */ + /* This match must come *before* the generic CDC-ETHER match so that + * we get FLAG_WWAN set on the device, since it's descriptors are + * generic CDC-ETHER. + */ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_PRODUCT + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = NOVATEL_VENDOR_ID, + .idProduct = 0xB001, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, + .bInterfaceProtocol = USB_CDC_PROTO_NONE, + .driver_info = (unsigned long)&wwan_info, +}, { /* ZTE (Vodafone) K3805-Z */ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT diff --git a/trunk/drivers/net/usb/ipheth.c b/trunk/drivers/net/usb/ipheth.c index 534d8becbbdc..a28a983d465e 100644 --- a/trunk/drivers/net/usb/ipheth.c +++ b/trunk/drivers/net/usb/ipheth.c @@ -62,7 +62,6 @@ #define USB_PRODUCT_IPAD 0x129a #define USB_PRODUCT_IPHONE_4_VZW 0x129c #define USB_PRODUCT_IPHONE_4S 0x12a0 -#define USB_PRODUCT_IPHONE_5 0x12a8 #define IPHETH_USBINTF_CLASS 255 #define IPHETH_USBINTF_SUBCLASS 253 @@ -114,10 +113,6 @@ static struct usb_device_id ipheth_table[] = { USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO) }, - { USB_DEVICE_AND_INTERFACE_INFO( - USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5, - IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, - IPHETH_USBINTF_PROTO) }, { } }; MODULE_DEVICE_TABLE(usb, ipheth_table); diff --git a/trunk/drivers/net/usb/qmi_wwan.c b/trunk/drivers/net/usb/qmi_wwan.c index 3b566fa0f8e6..6883c371c59f 100644 --- a/trunk/drivers/net/usb/qmi_wwan.c +++ b/trunk/drivers/net/usb/qmi_wwan.c @@ -369,73 +369,18 @@ static const struct usb_device_id products[] = { USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff), .driver_info = (unsigned long)&qmi_wwan_info, }, - { /* Novatel USB551L and MC551 */ - USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0xb001, - USB_CLASS_COMM, - USB_CDC_SUBCLASS_ETHERNET, - USB_CDC_PROTO_NONE), - .driver_info = (unsigned long)&qmi_wwan_info, - }, - { /* Novatel E362 */ - USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0x9010, - USB_CLASS_COMM, - USB_CDC_SUBCLASS_ETHERNET, - USB_CDC_PROTO_NONE), - .driver_info = (unsigned long)&qmi_wwan_info, - }, /* 3. Combined interface devices matching on interface number */ - {QMI_FIXED_INTF(0x19d2, 0x0002, 1)}, - {QMI_FIXED_INTF(0x19d2, 0x0012, 1)}, - {QMI_FIXED_INTF(0x19d2, 0x0017, 3)}, - {QMI_FIXED_INTF(0x19d2, 0x0021, 4)}, - {QMI_FIXED_INTF(0x19d2, 0x0025, 1)}, - {QMI_FIXED_INTF(0x19d2, 0x0031, 4)}, - {QMI_FIXED_INTF(0x19d2, 0x0042, 4)}, - {QMI_FIXED_INTF(0x19d2, 0x0049, 5)}, - {QMI_FIXED_INTF(0x19d2, 0x0052, 4)}, {QMI_FIXED_INTF(0x19d2, 0x0055, 1)}, /* ZTE (Vodafone) K3520-Z */ - {QMI_FIXED_INTF(0x19d2, 0x0058, 4)}, {QMI_FIXED_INTF(0x19d2, 0x0063, 4)}, /* ZTE (Vodafone) K3565-Z */ {QMI_FIXED_INTF(0x19d2, 0x0104, 4)}, /* ZTE (Vodafone) K4505-Z */ - {QMI_FIXED_INTF(0x19d2, 0x0113, 5)}, - {QMI_FIXED_INTF(0x19d2, 0x0118, 5)}, - {QMI_FIXED_INTF(0x19d2, 0x0121, 5)}, - {QMI_FIXED_INTF(0x19d2, 0x0123, 4)}, - {QMI_FIXED_INTF(0x19d2, 0x0124, 5)}, - {QMI_FIXED_INTF(0x19d2, 0x0125, 6)}, - {QMI_FIXED_INTF(0x19d2, 0x0126, 5)}, - {QMI_FIXED_INTF(0x19d2, 0x0130, 1)}, - {QMI_FIXED_INTF(0x19d2, 0x0133, 3)}, - {QMI_FIXED_INTF(0x19d2, 0x0141, 5)}, {QMI_FIXED_INTF(0x19d2, 0x0157, 5)}, /* ZTE MF683 */ - {QMI_FIXED_INTF(0x19d2, 0x0158, 3)}, {QMI_FIXED_INTF(0x19d2, 0x0167, 4)}, /* ZTE MF820D */ - {QMI_FIXED_INTF(0x19d2, 0x0168, 4)}, - {QMI_FIXED_INTF(0x19d2, 0x0176, 3)}, - {QMI_FIXED_INTF(0x19d2, 0x0178, 3)}, - {QMI_FIXED_INTF(0x19d2, 0x0191, 4)}, /* ZTE EuFi890 */ - {QMI_FIXED_INTF(0x19d2, 0x0199, 1)}, /* ZTE MF820S */ - {QMI_FIXED_INTF(0x19d2, 0x0200, 1)}, - {QMI_FIXED_INTF(0x19d2, 0x0257, 3)}, /* ZTE MF821 */ {QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */ {QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */ {QMI_FIXED_INTF(0x19d2, 0x1010, 4)}, /* ZTE (Vodafone) K3571-Z */ - {QMI_FIXED_INTF(0x19d2, 0x1012, 4)}, {QMI_FIXED_INTF(0x19d2, 0x1018, 3)}, /* ZTE (Vodafone) K5006-Z */ - {QMI_FIXED_INTF(0x19d2, 0x1021, 2)}, - {QMI_FIXED_INTF(0x19d2, 0x1245, 4)}, - {QMI_FIXED_INTF(0x19d2, 0x1247, 4)}, - {QMI_FIXED_INTF(0x19d2, 0x1252, 4)}, - {QMI_FIXED_INTF(0x19d2, 0x1254, 4)}, - {QMI_FIXED_INTF(0x19d2, 0x1255, 3)}, - {QMI_FIXED_INTF(0x19d2, 0x1255, 4)}, - {QMI_FIXED_INTF(0x19d2, 0x1256, 4)}, - {QMI_FIXED_INTF(0x19d2, 0x1401, 2)}, {QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */ - {QMI_FIXED_INTF(0x19d2, 0x1424, 2)}, - {QMI_FIXED_INTF(0x19d2, 0x1425, 2)}, - {QMI_FIXED_INTF(0x19d2, 0x1426, 2)}, /* ZTE MF91 */ {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */ {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ diff --git a/trunk/drivers/net/usb/usbnet.c b/trunk/drivers/net/usb/usbnet.c index cb04f900cc46..f9819d10b1f9 100644 --- a/trunk/drivers/net/usb/usbnet.c +++ b/trunk/drivers/net/usb/usbnet.c @@ -1158,7 +1158,6 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, usb_anchor_urb(urb, &dev->deferred); /* no use to process more packets */ netif_stop_queue(net); - usb_put_urb(urb); spin_unlock_irqrestore(&dev->txq.lock, flags); netdev_dbg(dev->net, "Delaying transmission for resumption\n"); goto deferred; @@ -1311,8 +1310,6 @@ void usbnet_disconnect (struct usb_interface *intf) cancel_work_sync(&dev->kevent); - usb_scuttle_anchored_urbs(&dev->deferred); - if (dev->driver_info->unbind) dev->driver_info->unbind (dev, intf); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 6f7cf49eff4d..89bf94d4d8a1 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -534,107 +534,107 @@ static const u32 ar9300_2p2_baseband_core[][2] = { static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, - {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, - {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, - {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, - {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400}, + {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402}, + {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404}, + {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640}, + {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x5a08442e, 0x5a08442e, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x5e0a4431, 0x5e0a4431, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, - {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, - {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, - {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, - {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, - {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, - {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, - {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, - {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, - {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, - {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400}, + {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402}, + {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, - {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, - {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, - {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, + {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, + {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, + {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, + {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000}, + {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501}, + {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501}, + {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, + {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, + {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, + {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, + {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; diff --git a/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c b/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c index f5dda84176c3..924c4616c3d9 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -38,7 +38,6 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ { USB_DEVICE(0x040D, 0x3801) }, /* VIA */ { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */ - { USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */ { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */ { USB_DEVICE(0x0cf3, 0x7015), diff --git a/trunk/drivers/net/wireless/b43/main.c b/trunk/drivers/net/wireless/b43/main.c index c5a99c8c8168..73730e94e0ac 100644 --- a/trunk/drivers/net/wireless/b43/main.c +++ b/trunk/drivers/net/wireless/b43/main.c @@ -5404,8 +5404,6 @@ static void b43_bcma_remove(struct bcma_device *core) cancel_work_sync(&wldev->restart_work); B43_WARN_ON(!wl); - if (!wldev->fw.ucode.data) - return; /* NULL if firmware never loaded */ if (wl->current_dev == wldev && wl->hw_registred) { b43_leds_stop(wldev); ieee80211_unregister_hw(wl->hw); @@ -5480,8 +5478,6 @@ static void b43_ssb_remove(struct ssb_device *sdev) cancel_work_sync(&wldev->restart_work); B43_WARN_ON(!wl); - if (!wldev->fw.ucode.data) - return; /* NULL if firmware never loaded */ if (wl->current_dev == wldev && wl->hw_registred) { b43_leds_stop(wldev); ieee80211_unregister_hw(wl->hw); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 7a6dfdc67b6c..a2b4b1e71017 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -1339,7 +1339,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo, } ret = brcmf_bus_start(dev); - if (ret) { + if (ret == -ENOLINK) { brcmf_dbg(ERROR, "dongle is not responding\n"); brcmf_detach(dev); goto fail; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index a6f1e8166008..c1abaa6db59e 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -3569,7 +3569,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, if (!request || !request->n_ssids || !request->n_match_sets) { WL_ERR("Invalid sched scan req!! n_ssids:%d\n", - request ? request->n_ssids : 0); + request->n_ssids); return -EINVAL; } @@ -3972,7 +3972,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg, u8 *iovar_ie_buf; u8 *curr_ie_buf; u8 *mgmt_ie_buf = NULL; - int mgmt_ie_buf_len; + u32 mgmt_ie_buf_len = 0; u32 *mgmt_ie_len = 0; u32 del_add_ie_buf_len = 0; u32 total_ie_buf_len = 0; @@ -3982,7 +3982,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg, struct parsed_vndr_ie_info *vndrie_info; s32 i; u8 *ptr; - int remained_buf_len; + u32 remained_buf_len; WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag); iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); @@ -4606,13 +4606,12 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); struct wiphy *wiphy = cfg_to_wiphy(cfg); - struct ieee80211_channel *notify_channel = NULL; + struct brcmf_channel_info_le channel_le; + struct ieee80211_channel *notify_channel; struct ieee80211_supported_band *band; - struct brcmf_bss_info_le *bi; u32 freq; s32 err = 0; u32 target_channel; - u8 *buf; WL_TRACE("Enter\n"); @@ -4620,22 +4619,11 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, memcpy(profile->bssid, e->addr, ETH_ALEN); brcmf_update_bss_info(cfg); - buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); - if (buf == NULL) { - err = -ENOMEM; - goto done; - } - - /* data sent to dongle has to be little endian */ - *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX); - err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX); - - if (err) - goto done; + brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le, + sizeof(channel_le)); - bi = (struct brcmf_bss_info_le *)(buf + 4); - target_channel = bi->ctl_ch ? bi->ctl_ch : - CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); + target_channel = le32_to_cpu(channel_le.target_channel); + WL_CONN("Roamed to channel %d\n", target_channel); if (target_channel <= CH_MAX_2G_CHANNEL) band = wiphy->bands[IEEE80211_BAND_2GHZ]; @@ -4645,8 +4633,6 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, freq = ieee80211_channel_to_frequency(target_channel, band->band); notify_channel = ieee80211_get_channel(wiphy, freq); -done: - kfree(buf); cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid, conn_info->req_ie, conn_info->req_ie_len, conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); @@ -5200,6 +5186,41 @@ brcmf_cfg80211_event(struct net_device *ndev, schedule_work(&cfg->event_work); } +static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype) +{ + s32 infra = 0; + s32 err = 0; + + switch (iftype) { + case NL80211_IFTYPE_MONITOR: + case NL80211_IFTYPE_WDS: + WL_ERR("type (%d) : currently we do not support this mode\n", + iftype); + err = -EINVAL; + return err; + case NL80211_IFTYPE_ADHOC: + infra = 0; + break; + case NL80211_IFTYPE_STATION: + infra = 1; + break; + case NL80211_IFTYPE_AP: + infra = 1; + break; + default: + err = -EINVAL; + WL_ERR("invalid type (%d)\n", iftype); + return err; + } + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); + if (err) { + WL_ERR("WLC_SET_INFRA error (%d)\n", err); + return err; + } + + return 0; +} + static s32 brcmf_dongle_eventmsg(struct net_device *ndev) { /* Room for "event_msgs" + '\0' + bitvec */ @@ -5418,8 +5439,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) WL_BEACON_TIMEOUT); if (err) goto default_conf_out; - err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype, - NULL, NULL); + err = brcmf_dongle_mode(ndev, wdev->iftype); if (err && err != -EINPROGRESS) goto default_conf_out; err = brcmf_dongle_probecap(cfg); diff --git a/trunk/drivers/net/wireless/ipw2x00/ipw2200.c b/trunk/drivers/net/wireless/ipw2x00/ipw2200.c index 768bf612533e..935120fc8c93 100644 --- a/trunk/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/trunk/drivers/net/wireless/ipw2x00/ipw2200.c @@ -10472,7 +10472,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv, } else len = src->len; - dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC); + dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC); if (!dst) continue; diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/devices.c b/trunk/drivers/net/wireless/iwlwifi/dvm/devices.c index da5862064195..349c205d5f62 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/devices.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/devices.c @@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, * See iwlagn_mac_channel_switch. */ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - struct iwl6000_channel_switch_cmd *cmd; + struct iwl6000_channel_switch_cmd cmd; u32 switch_time_in_usec, ucode_switch_time; u16 ch; u32 tsf_low; @@ -527,25 +527,18 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, - .len = { sizeof(*cmd), }, + .len = { sizeof(cmd), }, .flags = CMD_SYNC, - .dataflags[0] = IWL_HCMD_DFL_NOCOPY, + .data = { &cmd, }, }; - int err; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) - return -ENOMEM; - - hcmd.data[0] = cmd; - cmd->band = priv->band == IEEE80211_BAND_2GHZ; + cmd.band = priv->band == IEEE80211_BAND_2GHZ; ch = ch_switch->channel->hw_value; IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", ctx->active.channel, ch); - cmd->channel = cpu_to_le16(ch); - cmd->rxon_flags = ctx->staging.flags; - cmd->rxon_filter_flags = ctx->staging.filter_flags; + cmd.channel = cpu_to_le16(ch); + cmd.rxon_flags = ctx->staging.flags; + cmd.rxon_filter_flags = ctx->staging.filter_flags; switch_count = ch_switch->count; tsf_low = ch_switch->timestamp & 0x0ffffffff; /* @@ -561,25 +554,23 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, switch_count = 0; } if (switch_count <= 1) - cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time); + cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); else { switch_time_in_usec = vif->bss_conf.beacon_int * switch_count * TIME_UNIT; ucode_switch_time = iwl_usecs_to_beacons(priv, switch_time_in_usec, beacon_interval); - cmd->switch_time = iwl_add_beacon_time(priv, - priv->ucode_beacon_time, - ucode_switch_time, - beacon_interval); + cmd.switch_time = iwl_add_beacon_time(priv, + priv->ucode_beacon_time, + ucode_switch_time, + beacon_interval); } IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", - cmd->switch_time); - cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; + cmd.switch_time); + cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; - err = iwl_dvm_send_cmd(priv, &hcmd); - kfree(cmd); - return err; + return iwl_dvm_send_cmd(priv, &hcmd); } struct iwl_lib_ops iwl6000_lib = { diff --git a/trunk/drivers/net/wireless/mwifiex/cfg80211.c b/trunk/drivers/net/wireless/mwifiex/cfg80211.c index 780d3e168297..0679458a1bac 100644 --- a/trunk/drivers/net/wireless/mwifiex/cfg80211.c +++ b/trunk/drivers/net/wireless/mwifiex/cfg80211.c @@ -1825,6 +1825,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, return -EBUSY; } + priv->scan_request = request; + priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); if (!priv->user_scan_cfg) { @@ -1832,8 +1834,6 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, return -ENOMEM; } - priv->scan_request = request; - priv->user_scan_cfg->num_ssids = request->n_ssids; priv->user_scan_cfg->ssid_list = request->ssids; @@ -1870,9 +1870,6 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, ret = mwifiex_scan_networks(priv, priv->user_scan_cfg); if (ret) { dev_err(priv->adapter->dev, "scan failed: %d\n", ret); - priv->scan_request = NULL; - kfree(priv->user_scan_cfg); - priv->user_scan_cfg = NULL; return ret; } diff --git a/trunk/drivers/net/wireless/mwifiex/scan.c b/trunk/drivers/net/wireless/mwifiex/scan.c index 9171aaedbccd..00b658d3b6ec 100644 --- a/trunk/drivers/net/wireless/mwifiex/scan.c +++ b/trunk/drivers/net/wireless/mwifiex/scan.c @@ -1843,18 +1843,21 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, struct cfg80211_ssid *req_ssid) { struct mwifiex_adapter *adapter = priv->adapter; - int ret; + int ret = 0; struct mwifiex_user_scan_cfg *scan_cfg; + if (!req_ssid) + return -1; + if (adapter->scan_processing) { - dev_err(adapter->dev, "cmd: Scan already in process...\n"); - return -EBUSY; + dev_dbg(adapter->dev, "cmd: Scan already in process...\n"); + return ret; } if (priv->scan_block) { - dev_err(adapter->dev, + dev_dbg(adapter->dev, "cmd: Scan is blocked during association...\n"); - return -EBUSY; + return ret; } scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500usb.c b/trunk/drivers/net/wireless/rt2x00/rt2500usb.c index 6b2e1e431dd2..a12e84f892be 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1988,7 +1988,6 @@ static struct usb_driver rt2500usb_driver = { .disconnect = rt2x00usb_disconnect, .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, - .reset_resume = rt2x00usb_resume, .disable_hub_initiated_lpm = 1, }; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c index 3b8fb5a603f2..c9e9370eb789 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1282,7 +1282,6 @@ static struct usb_driver rt2800usb_driver = { .disconnect = rt2x00usb_disconnect, .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, - .reset_resume = rt2x00usb_resume, .disable_hub_initiated_lpm = 1, }; diff --git a/trunk/drivers/net/wireless/rt2x00/rt73usb.c b/trunk/drivers/net/wireless/rt2x00/rt73usb.c index 24eec66e9fd2..e5eb43b3eee7 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt73usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt73usb.c @@ -2535,7 +2535,6 @@ static struct usb_driver rt73usb_driver = { .disconnect = rt2x00usb_disconnect, .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, - .reset_resume = rt2x00usb_resume, .disable_hub_initiated_lpm = 1, }; diff --git a/trunk/drivers/net/wireless/rtlwifi/usb.c b/trunk/drivers/net/wireless/rtlwifi/usb.c index e3ea4b346889..030beb45d8b0 100644 --- a/trunk/drivers/net/wireless/rtlwifi/usb.c +++ b/trunk/drivers/net/wireless/rtlwifi/usb.c @@ -673,7 +673,7 @@ static int rtl_usb_start(struct ieee80211_hw *hw) set_hal_start(rtlhal); /* Start bulk IN */ - err = _rtl_usb_receive(hw); + _rtl_usb_receive(hw); } return err; diff --git a/trunk/drivers/scsi/qla2xxx/qla_mid.c b/trunk/drivers/scsi/qla2xxx/qla_mid.c index 20fd974f903a..bd4708a422cd 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_mid.c +++ b/trunk/drivers/scsi/qla2xxx/qla_mid.c @@ -149,7 +149,6 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) int qla24xx_disable_vp(scsi_qla_host_t *vha) { - unsigned long flags; int ret; ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL); @@ -157,9 +156,7 @@ qla24xx_disable_vp(scsi_qla_host_t *vha) atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); /* Remove port id from vp target map */ - spin_lock_irqsave(&vha->hw->vport_slock, flags); qlt_update_vp_map(vha, RESET_AL_PA); - spin_unlock_irqrestore(&vha->hw->vport_slock, flags); qla2x00_mark_vp_devices_dead(vha); atomic_set(&vha->vp_state, VP_FAILED); diff --git a/trunk/drivers/scsi/qla2xxx/qla_target.c b/trunk/drivers/scsi/qla2xxx/qla_target.c index 62aa5584f644..0e09d8f433d1 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_target.c +++ b/trunk/drivers/scsi/qla2xxx/qla_target.c @@ -557,7 +557,6 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha, int pmap_len; fc_port_t *fcport; int global_resets; - unsigned long flags; retry: global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count); @@ -626,10 +625,10 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha, sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain, fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id); - spin_lock_irqsave(&ha->hardware_lock, flags); - ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, - (fcport->flags & FCF_CONF_COMP_SUPPORTED)); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + sess->s_id = fcport->d_id; + sess->loop_id = fcport->loop_id; + sess->conf_compl_supported = !!(fcport->flags & + FCF_CONF_COMP_SUPPORTED); res = true; @@ -741,9 +740,10 @@ static struct qla_tgt_sess *qlt_create_sess( qlt_undelete_sess(sess); kref_get(&sess->se_sess->sess_kref); - ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, - (fcport->flags & FCF_CONF_COMP_SUPPORTED)); - + sess->s_id = fcport->d_id; + sess->loop_id = fcport->loop_id; + sess->conf_compl_supported = !!(fcport->flags & + FCF_CONF_COMP_SUPPORTED); if (sess->local && !local) sess->local = 0; spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -796,7 +796,8 @@ static struct qla_tgt_sess *qlt_create_sess( */ kref_get(&sess->se_sess->sess_kref); - sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED); + sess->conf_compl_supported = !!(fcport->flags & + FCF_CONF_COMP_SUPPORTED); BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name)); memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name)); @@ -868,8 +869,10 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007, "Reappeared sess %p\n", sess); } - ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, - (fcport->flags & FCF_CONF_COMP_SUPPORTED)); + sess->s_id = fcport->d_id; + sess->loop_id = fcport->loop_id; + sess->conf_compl_supported = !!(fcport->flags & + FCF_CONF_COMP_SUPPORTED); } if (sess && sess->local) { diff --git a/trunk/drivers/scsi/qla2xxx/qla_target.h b/trunk/drivers/scsi/qla2xxx/qla_target.h index bad749561ec2..170af1571214 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_target.h +++ b/trunk/drivers/scsi/qla2xxx/qla_target.h @@ -648,7 +648,6 @@ struct qla_tgt_func_tmpl { int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *, void *, uint8_t *, uint16_t); - void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool); struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *, const uint16_t); struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *, diff --git a/trunk/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/trunk/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 3d74f2f39ae1..2358c16c4c8e 100644 --- a/trunk/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/trunk/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -237,7 +237,7 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg) struct tcm_qla2xxx_tpg, se_tpg); struct tcm_qla2xxx_lport *lport = tpg->lport; - return lport->lport_naa_name; + return &lport->lport_name[0]; } static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg) @@ -1457,78 +1457,6 @@ static int tcm_qla2xxx_check_initiator_node_acl( return 0; } -static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id, - uint16_t loop_id, bool conf_compl_supported) -{ - struct qla_tgt *tgt = sess->tgt; - struct qla_hw_data *ha = tgt->ha; - struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr; - struct se_node_acl *se_nacl = sess->se_sess->se_node_acl; - struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, - struct tcm_qla2xxx_nacl, se_node_acl); - u32 key; - - - if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24) - pr_info("Updating session %p from port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n", - sess, - sess->port_name[0], sess->port_name[1], - sess->port_name[2], sess->port_name[3], - sess->port_name[4], sess->port_name[5], - sess->port_name[6], sess->port_name[7], - sess->loop_id, loop_id, - sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa, - s_id.b.domain, s_id.b.area, s_id.b.al_pa); - - if (sess->loop_id != loop_id) { - /* - * Because we can shuffle loop IDs around and we - * update different sessions non-atomically, we might - * have overwritten this session's old loop ID - * already, and we might end up overwriting some other - * session that will be updated later. So we have to - * be extra careful and we can't warn about those things... - */ - if (lport->lport_loopid_map[sess->loop_id].se_nacl == se_nacl) - lport->lport_loopid_map[sess->loop_id].se_nacl = NULL; - - lport->lport_loopid_map[loop_id].se_nacl = se_nacl; - - sess->loop_id = loop_id; - } - - if (sess->s_id.b24 != s_id.b24) { - key = (((u32) sess->s_id.b.domain << 16) | - ((u32) sess->s_id.b.area << 8) | - ((u32) sess->s_id.b.al_pa)); - - if (btree_lookup32(&lport->lport_fcport_map, key)) - WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl, - "Found wrong se_nacl when updating s_id %x:%x:%x\n", - sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa); - else - WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n", - sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa); - - key = (((u32) s_id.b.domain << 16) | - ((u32) s_id.b.area << 8) | - ((u32) s_id.b.al_pa)); - - if (btree_lookup32(&lport->lport_fcport_map, key)) { - WARN(1, "Already have lport_fcport_map entry for s_id %x:%x:%x\n", - s_id.b.domain, s_id.b.area, s_id.b.al_pa); - btree_update32(&lport->lport_fcport_map, key, se_nacl); - } else { - btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC); - } - - sess->s_id = s_id; - nacl->nport_id = key; - } - - sess->conf_compl_supported = conf_compl_supported; -} - /* * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path. */ @@ -1539,7 +1467,6 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = { .free_cmd = tcm_qla2xxx_free_cmd, .free_mcmd = tcm_qla2xxx_free_mcmd, .free_session = tcm_qla2xxx_free_session, - .update_sess = tcm_qla2xxx_update_sess, .check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl, .find_sess_by_s_id = tcm_qla2xxx_find_sess_by_s_id, .find_sess_by_loop_id = tcm_qla2xxx_find_sess_by_loop_id, @@ -1607,7 +1534,6 @@ static struct se_wwn *tcm_qla2xxx_make_lport( lport->lport_wwpn = wwpn; tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN, wwpn); - sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) wwpn); ret = tcm_qla2xxx_init_lport(lport); if (ret != 0) @@ -1675,7 +1601,6 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport( lport->lport_npiv_wwnn = npiv_wwnn; tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0], TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn); - sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn); /* FIXME: tcm_qla2xxx_npiv_make_lport */ ret = -ENOSYS; diff --git a/trunk/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/trunk/drivers/scsi/qla2xxx/tcm_qla2xxx.h index 9ba075fe9781..825498103352 100644 --- a/trunk/drivers/scsi/qla2xxx/tcm_qla2xxx.h +++ b/trunk/drivers/scsi/qla2xxx/tcm_qla2xxx.h @@ -61,8 +61,6 @@ struct tcm_qla2xxx_lport { u64 lport_npiv_wwnn; /* ASCII formatted WWPN for FC Target Lport */ char lport_name[TCM_QLA2XXX_NAMELEN]; - /* ASCII formatted naa WWPN for VPD page 83 etc */ - char lport_naa_name[TCM_QLA2XXX_NAMELEN]; /* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */ char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN]; /* map for fc_port pointers in 24-bit FC Port ID space */ diff --git a/trunk/drivers/spi/spi-mxs.c b/trunk/drivers/spi/spi-mxs.c index 86dd04d6bc87..edf1360ab09e 100644 --- a/trunk/drivers/spi/spi-mxs.c +++ b/trunk/drivers/spi/spi-mxs.c @@ -323,7 +323,6 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, if (!ret) { dev_err(ssp->dev, "DMA transfer timeout\n"); ret = -ETIMEDOUT; - dmaengine_terminate_all(ssp->dmach); goto err_vmalloc; } @@ -481,7 +480,7 @@ static int mxs_spi_transfer_one(struct spi_master *master, first = last = 0; } - m->status = status; + m->status = 0; spi_finalize_current_message(master); return status; diff --git a/trunk/drivers/target/target_core_sbc.c b/trunk/drivers/target/target_core_sbc.c index a6e27d967c7b..868f8aa04f13 100644 --- a/trunk/drivers/target/target_core_sbc.c +++ b/trunk/drivers/target/target_core_sbc.c @@ -135,12 +135,6 @@ static int sbc_emulate_verify(struct se_cmd *cmd) return 0; } -static int sbc_emulate_noop(struct se_cmd *cmd) -{ - target_complete_cmd(cmd, GOOD); - return 0; -} - static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors) { return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors; @@ -537,18 +531,6 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) size = 0; cmd->execute_cmd = sbc_emulate_verify; break; - case REZERO_UNIT: - case SEEK_6: - case SEEK_10: - /* - * There are still clients out there which use these old SCSI-2 - * commands. This mainly happens when running VMs with legacy - * guest systems, connected via SCSI command pass-through to - * iSCSI targets. Make them happy and return status GOOD. - */ - size = 0; - cmd->execute_cmd = sbc_emulate_noop; - break; default: ret = spc_parse_cdb(cmd, &size); if (ret) diff --git a/trunk/drivers/target/target_core_transport.c b/trunk/drivers/target/target_core_transport.c index 9097155e9ebe..c33baff86aa6 100644 --- a/trunk/drivers/target/target_core_transport.c +++ b/trunk/drivers/target/target_core_transport.c @@ -1616,6 +1616,7 @@ 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_generic_free_cmd(se_cmd, 0); } /** diff --git a/trunk/drivers/vhost/net.c b/trunk/drivers/vhost/net.c index 7f93f34b7f91..072cbbadbc36 100644 --- a/trunk/drivers/vhost/net.c +++ b/trunk/drivers/vhost/net.c @@ -379,8 +379,7 @@ static void handle_rx(struct vhost_net *net) .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE }; size_t total_len = 0; - int err, mergeable; - s16 headcount; + int err, headcount, mergeable; size_t vhost_hlen, sock_hlen; size_t vhost_len, sock_len; /* TODO: check that we are running from vhost_worker? */ diff --git a/trunk/fs/bio.c b/trunk/fs/bio.c index b96fc6ce4855..9298c65ad9c7 100644 --- a/trunk/fs/bio.c +++ b/trunk/fs/bio.c @@ -75,7 +75,6 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size) unsigned int sz = sizeof(struct bio) + extra_size; struct kmem_cache *slab = NULL; struct bio_slab *bslab, *new_bio_slabs; - unsigned int new_bio_slab_max; unsigned int i, entry = -1; mutex_lock(&bio_slab_lock); @@ -98,13 +97,12 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size) goto out_unlock; if (bio_slab_nr == bio_slab_max && entry == -1) { - new_bio_slab_max = bio_slab_max << 1; + bio_slab_max <<= 1; new_bio_slabs = krealloc(bio_slabs, - new_bio_slab_max * sizeof(struct bio_slab), + bio_slab_max * sizeof(struct bio_slab), GFP_KERNEL); if (!new_bio_slabs) goto out_unlock; - bio_slab_max = new_bio_slab_max; bio_slabs = new_bio_slabs; } if (entry == -1) diff --git a/trunk/fs/block_dev.c b/trunk/fs/block_dev.c index 1a1e5e3b1eaf..b3c1d3dae77d 100644 --- a/trunk/fs/block_dev.c +++ b/trunk/fs/block_dev.c @@ -1661,39 +1661,6 @@ static int blkdev_mmap(struct file *file, struct vm_area_struct *vma) return ret; } -static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos, - struct pipe_inode_info *pipe, size_t len, - unsigned int flags) -{ - ssize_t ret; - struct block_device *bdev = I_BDEV(file->f_mapping->host); - - percpu_down_read(&bdev->bd_block_size_semaphore); - - ret = generic_file_splice_read(file, ppos, pipe, len, flags); - - percpu_up_read(&bdev->bd_block_size_semaphore); - - return ret; -} - -static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe, - struct file *file, loff_t *ppos, size_t len, - unsigned int flags) -{ - ssize_t ret; - struct block_device *bdev = I_BDEV(file->f_mapping->host); - - percpu_down_read(&bdev->bd_block_size_semaphore); - - ret = generic_file_splice_write(pipe, file, ppos, len, flags); - - percpu_up_read(&bdev->bd_block_size_semaphore); - - return ret; -} - - /* * Try to release a page associated with block device when the system * is under memory pressure. @@ -1732,8 +1699,8 @@ const struct file_operations def_blk_fops = { #ifdef CONFIG_COMPAT .compat_ioctl = compat_blkdev_ioctl, #endif - .splice_read = blkdev_splice_read, - .splice_write = blkdev_splice_write, + .splice_read = generic_file_splice_read, + .splice_write = generic_file_splice_write, }; int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg) diff --git a/trunk/fs/ceph/export.c b/trunk/fs/ceph/export.c index 9349bb37a2fe..02ce90972d81 100644 --- a/trunk/fs/ceph/export.c +++ b/trunk/fs/ceph/export.c @@ -90,8 +90,6 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len, *max_len = handle_length; type = 255; } - if (dentry) - dput(dentry); return type; } diff --git a/trunk/fs/exec.c b/trunk/fs/exec.c index 0039055b1fc6..8b9011b67041 100644 --- a/trunk/fs/exec.c +++ b/trunk/fs/exec.c @@ -1083,8 +1083,7 @@ int flush_old_exec(struct linux_binprm * bprm) bprm->mm = NULL; /* We're using it now */ set_fs(USER_DS); - current->flags &= - ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | PF_NOFREEZE); + current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD); flush_thread(); current->personality &= ~bprm->per_clear; diff --git a/trunk/fs/ext4/ialloc.c b/trunk/fs/ext4/ialloc.c index 3a100e7a62a8..4facdd29a350 100644 --- a/trunk/fs/ext4/ialloc.c +++ b/trunk/fs/ext4/ialloc.c @@ -725,10 +725,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, "inode=%lu", ino + 1); continue; } - BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); - err = ext4_journal_get_write_access(handle, inode_bitmap_bh); - if (err) - goto fail; ext4_lock_group(sb, group); ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data); ext4_unlock_group(sb, group); @@ -742,11 +738,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, goto out; got: - BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); - err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); - if (err) - goto fail; - /* We may have to initialize the block bitmap if it isn't already */ if (ext4_has_group_desc_csum(sb) && gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { @@ -780,6 +771,11 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, goto fail; } + BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); + err = ext4_journal_get_write_access(handle, inode_bitmap_bh); + if (err) + goto fail; + BUFFER_TRACE(group_desc_bh, "get_write_access"); err = ext4_journal_get_write_access(handle, group_desc_bh); if (err) @@ -827,6 +823,11 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, } ext4_unlock_group(sb, group); + BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); + err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); + if (err) + goto fail; + BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata"); err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh); if (err) diff --git a/trunk/fs/file.c b/trunk/fs/file.c index 708d997a7748..d3b5fa80b71b 100644 --- a/trunk/fs/file.c +++ b/trunk/fs/file.c @@ -900,7 +900,7 @@ int replace_fd(unsigned fd, struct file *file, unsigned flags) return __close_fd(files, fd); if (fd >= rlimit(RLIMIT_NOFILE)) - return -EBADF; + return -EMFILE; spin_lock(&files->file_lock); err = expand_files(files, fd); @@ -926,7 +926,7 @@ SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags) return -EINVAL; if (newfd >= rlimit(RLIMIT_NOFILE)) - return -EBADF; + return -EMFILE; spin_lock(&files->file_lock); err = expand_files(files, newfd); diff --git a/trunk/include/linux/compat.h b/trunk/include/linux/compat.h index d2db71077d93..d0ced1011f2f 100644 --- a/trunk/include/linux/compat.h +++ b/trunk/include/linux/compat.h @@ -286,8 +286,10 @@ asmlinkage ssize_t compat_sys_pwritev(unsigned long fd, int compat_do_execve(const char *filename, const compat_uptr_t __user *argv, const compat_uptr_t __user *envp, struct pt_regs *regs); +#ifdef __ARCH_WANT_SYS_EXECVE asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv, const compat_uptr_t __user *envp); +#endif asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, diff --git a/trunk/include/linux/kvm_host.h b/trunk/include/linux/kvm_host.h index ecc554374e44..93bfc9f9815c 100644 --- a/trunk/include/linux/kvm_host.h +++ b/trunk/include/linux/kvm_host.h @@ -42,8 +42,19 @@ */ #define KVM_MEMSLOT_INVALID (1UL << 16) -/* Two fragments for cross MMIO pages. */ -#define KVM_MAX_MMIO_FRAGMENTS 2 +/* + * If we support unaligned MMIO, at most one fragment will be split into two: + */ +#ifdef KVM_UNALIGNED_MMIO +# define KVM_EXTRA_MMIO_FRAGMENTS 1 +#else +# define KVM_EXTRA_MMIO_FRAGMENTS 0 +#endif + +#define KVM_USER_MMIO_SIZE 8 + +#define KVM_MAX_MMIO_FRAGMENTS \ + (KVM_MMIO_SIZE / KVM_USER_MMIO_SIZE + KVM_EXTRA_MMIO_FRAGMENTS) /* * For the normal pfn, the highest 12 bits should be zero, diff --git a/trunk/include/linux/percpu-rwsem.h b/trunk/include/linux/percpu-rwsem.h index 250a4acddb2b..cf80f7e5277f 100644 --- a/trunk/include/linux/percpu-rwsem.h +++ b/trunk/include/linux/percpu-rwsem.h @@ -12,27 +12,34 @@ struct percpu_rw_semaphore { struct mutex mtx; }; -#define light_mb() barrier() -#define heavy_mb() synchronize_sched() - static inline void percpu_down_read(struct percpu_rw_semaphore *p) { - rcu_read_lock_sched(); + rcu_read_lock(); if (unlikely(p->locked)) { - rcu_read_unlock_sched(); + rcu_read_unlock(); mutex_lock(&p->mtx); this_cpu_inc(*p->counters); mutex_unlock(&p->mtx); return; } this_cpu_inc(*p->counters); - rcu_read_unlock_sched(); - light_mb(); /* A, between read of p->locked and read of data, paired with D */ + rcu_read_unlock(); } static inline void percpu_up_read(struct percpu_rw_semaphore *p) { - light_mb(); /* B, between read of the data and write to p->counter, paired with C */ + /* + * On X86, write operation in this_cpu_dec serves as a memory unlock + * barrier (i.e. memory accesses may be moved before the write, but + * no memory accesses are moved past the write). + * On other architectures this may not be the case, so we need smp_mb() + * there. + */ +#if defined(CONFIG_X86) && (!defined(CONFIG_X86_PPRO_FENCE) && !defined(CONFIG_X86_OOSTORE)) + barrier(); +#else + smp_mb(); +#endif this_cpu_dec(*p->counters); } @@ -51,15 +58,14 @@ static inline void percpu_down_write(struct percpu_rw_semaphore *p) { mutex_lock(&p->mtx); p->locked = true; - synchronize_sched(); /* make sure that all readers exit the rcu_read_lock_sched region */ + synchronize_rcu(); while (__percpu_count(p->counters)) msleep(1); - heavy_mb(); /* C, between read of p->counter and write to data, paired with B */ + smp_rmb(); /* paired with smp_mb() in percpu_sem_up_read() */ } static inline void percpu_up_write(struct percpu_rw_semaphore *p) { - heavy_mb(); /* D, between write to data and write to p->locked, paired with A */ p->locked = false; mutex_unlock(&p->mtx); } diff --git a/trunk/include/linux/raid/Kbuild b/trunk/include/linux/raid/Kbuild index e69de29bb2d1..2415a64c5e51 100644 --- a/trunk/include/linux/raid/Kbuild +++ b/trunk/include/linux/raid/Kbuild @@ -0,0 +1,2 @@ +header-y += md_p.h +header-y += md_u.h diff --git a/trunk/include/uapi/linux/raid/md_p.h b/trunk/include/linux/raid/md_p.h similarity index 100% rename from trunk/include/uapi/linux/raid/md_p.h rename to trunk/include/linux/raid/md_p.h diff --git a/trunk/include/linux/raid/md_u.h b/trunk/include/linux/raid/md_u.h index 358c04bfbe2a..fb1abb3367e9 100644 --- a/trunk/include/linux/raid/md_u.h +++ b/trunk/include/linux/raid/md_u.h @@ -11,10 +11,149 @@ (for example /usr/src/linux/COPYING); if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #ifndef _MD_U_H #define _MD_U_H -#include +/* + * Different major versions are not compatible. + * Different minor versions are only downward compatible. + * Different patchlevel versions are downward and upward compatible. + */ +#define MD_MAJOR_VERSION 0 +#define MD_MINOR_VERSION 90 +/* + * MD_PATCHLEVEL_VERSION indicates kernel functionality. + * >=1 means different superblock formats are selectable using SET_ARRAY_INFO + * and major_version/minor_version accordingly + * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT + * in the super status byte + * >=3 means that bitmap superblock version 4 is supported, which uses + * little-ending representation rather than host-endian + */ +#define MD_PATCHLEVEL_VERSION 3 + +/* ioctls */ + +/* status */ +#define RAID_VERSION _IOR (MD_MAJOR, 0x10, mdu_version_t) +#define GET_ARRAY_INFO _IOR (MD_MAJOR, 0x11, mdu_array_info_t) +#define GET_DISK_INFO _IOR (MD_MAJOR, 0x12, mdu_disk_info_t) +#define PRINT_RAID_DEBUG _IO (MD_MAJOR, 0x13) +#define RAID_AUTORUN _IO (MD_MAJOR, 0x14) +#define GET_BITMAP_FILE _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t) + +/* configuration */ +#define CLEAR_ARRAY _IO (MD_MAJOR, 0x20) +#define ADD_NEW_DISK _IOW (MD_MAJOR, 0x21, mdu_disk_info_t) +#define HOT_REMOVE_DISK _IO (MD_MAJOR, 0x22) +#define SET_ARRAY_INFO _IOW (MD_MAJOR, 0x23, mdu_array_info_t) +#define SET_DISK_INFO _IO (MD_MAJOR, 0x24) +#define WRITE_RAID_INFO _IO (MD_MAJOR, 0x25) +#define UNPROTECT_ARRAY _IO (MD_MAJOR, 0x26) +#define PROTECT_ARRAY _IO (MD_MAJOR, 0x27) +#define HOT_ADD_DISK _IO (MD_MAJOR, 0x28) +#define SET_DISK_FAULTY _IO (MD_MAJOR, 0x29) +#define HOT_GENERATE_ERROR _IO (MD_MAJOR, 0x2a) +#define SET_BITMAP_FILE _IOW (MD_MAJOR, 0x2b, int) +/* usage */ +#define RUN_ARRAY _IOW (MD_MAJOR, 0x30, mdu_param_t) +/* 0x31 was START_ARRAY */ +#define STOP_ARRAY _IO (MD_MAJOR, 0x32) +#define STOP_ARRAY_RO _IO (MD_MAJOR, 0x33) +#define RESTART_ARRAY_RW _IO (MD_MAJOR, 0x34) + +/* 63 partitions with the alternate major number (mdp) */ +#define MdpMinorShift 6 +#ifdef __KERNEL__ extern int mdp_major; +#endif + +typedef struct mdu_version_s { + int major; + int minor; + int patchlevel; +} mdu_version_t; + +typedef struct mdu_array_info_s { + /* + * Generic constant information + */ + int major_version; + int minor_version; + int patch_version; + int ctime; + int level; + int size; + int nr_disks; + int raid_disks; + int md_minor; + int not_persistent; + + /* + * Generic state information + */ + int utime; /* 0 Superblock update time */ + int state; /* 1 State bits (clean, ...) */ + int active_disks; /* 2 Number of currently active disks */ + int working_disks; /* 3 Number of working disks */ + int failed_disks; /* 4 Number of failed disks */ + int spare_disks; /* 5 Number of spare disks */ + + /* + * Personality information + */ + int layout; /* 0 the array's physical layout */ + int chunk_size; /* 1 chunk size in bytes */ + +} mdu_array_info_t; + +/* non-obvious values for 'level' */ +#define LEVEL_MULTIPATH (-4) +#define LEVEL_LINEAR (-1) +#define LEVEL_FAULTY (-5) + +/* we need a value for 'no level specified' and 0 + * means 'raid0', so we need something else. This is + * for internal use only + */ +#define LEVEL_NONE (-1000000) + +typedef struct mdu_disk_info_s { + /* + * configuration/status of one particular disk + */ + int number; + int major; + int minor; + int raid_disk; + int state; + +} mdu_disk_info_t; + +typedef struct mdu_start_info_s { + /* + * configuration/status of one particular disk + */ + int major; + int minor; + int raid_disk; + int state; + +} mdu_start_info_t; + +typedef struct mdu_bitmap_file_s +{ + char pathname[4096]; +} mdu_bitmap_file_t; + +typedef struct mdu_param_s +{ + int personality; /* 1,2,3,4 */ + int chunk_size; /* in bytes */ + int max_fault; /* unused for now */ +} mdu_param_t; + #endif + diff --git a/trunk/include/linux/tcp.h b/trunk/include/linux/tcp.h index 60b7aac15e0e..8a7fc4be2d75 100644 --- a/trunk/include/linux/tcp.h +++ b/trunk/include/linux/tcp.h @@ -191,8 +191,7 @@ struct tcp_sock { u8 do_early_retrans:1,/* Enable RFC5827 early-retransmit */ early_retrans_delayed:1, /* Delayed ER timer installed */ syn_data:1, /* SYN includes data */ - syn_fastopen:1, /* SYN includes Fast Open option */ - syn_data_acked:1;/* data in SYN is acked by SYN-ACK */ + syn_fastopen:1; /* SYN includes Fast Open option */ /* RTT measurement */ u32 srtt; /* smoothed round trip time << 3 */ diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index f8cd4cf3fad8..1b4989082244 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -1218,7 +1218,6 @@ struct cfg80211_deauth_request { const u8 *ie; size_t ie_len; u16 reason_code; - bool local_state_change; }; /** diff --git a/trunk/include/sound/core.h b/trunk/include/sound/core.h index 93896ad1fcdd..bc056687f647 100644 --- a/trunk/include/sound/core.h +++ b/trunk/include/sound/core.h @@ -132,7 +132,6 @@ struct snd_card { int shutdown; /* this card is going down */ int free_on_last_close; /* free in context of file_release */ wait_queue_head_t shutdown_sleep; - atomic_t refcount; /* refcount for disconnection */ struct device *dev; /* device assigned to this card */ struct device *card_dev; /* cardX object for sysfs */ @@ -190,7 +189,6 @@ struct snd_minor { const struct file_operations *f_ops; /* file operations */ void *private_data; /* private data for f_ops->open */ struct device *dev; /* device for sysfs */ - struct snd_card *card_ptr; /* assigned card instance */ }; /* return a device pointer linked to each sound device as a parent */ @@ -297,7 +295,6 @@ int snd_card_info_done(void); int snd_component_add(struct snd_card *card, const char *component); int snd_card_file_add(struct snd_card *card, struct file *file); int snd_card_file_remove(struct snd_card *card, struct file *file); -void snd_card_unref(struct snd_card *card); #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr)) diff --git a/trunk/include/uapi/linux/raid/Kbuild b/trunk/include/uapi/linux/raid/Kbuild index e2c3d25405d7..aafaa5aa54d4 100644 --- a/trunk/include/uapi/linux/raid/Kbuild +++ b/trunk/include/uapi/linux/raid/Kbuild @@ -1,3 +1 @@ # UAPI Header export list -header-y += md_p.h -header-y += md_u.h diff --git a/trunk/include/uapi/linux/raid/md_u.h b/trunk/include/uapi/linux/raid/md_u.h deleted file mode 100644 index 4133e744e4e6..000000000000 --- a/trunk/include/uapi/linux/raid/md_u.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - md_u.h : user <=> kernel API between Linux raidtools and RAID drivers - Copyright (C) 1998 Ingo Molnar - - 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, or (at your option) - any later version. - - You should have received a copy of the GNU General Public License - (for example /usr/src/linux/COPYING); if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _UAPI_MD_U_H -#define _UAPI_MD_U_H - -/* - * Different major versions are not compatible. - * Different minor versions are only downward compatible. - * Different patchlevel versions are downward and upward compatible. - */ -#define MD_MAJOR_VERSION 0 -#define MD_MINOR_VERSION 90 -/* - * MD_PATCHLEVEL_VERSION indicates kernel functionality. - * >=1 means different superblock formats are selectable using SET_ARRAY_INFO - * and major_version/minor_version accordingly - * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT - * in the super status byte - * >=3 means that bitmap superblock version 4 is supported, which uses - * little-ending representation rather than host-endian - */ -#define MD_PATCHLEVEL_VERSION 3 - -/* ioctls */ - -/* status */ -#define RAID_VERSION _IOR (MD_MAJOR, 0x10, mdu_version_t) -#define GET_ARRAY_INFO _IOR (MD_MAJOR, 0x11, mdu_array_info_t) -#define GET_DISK_INFO _IOR (MD_MAJOR, 0x12, mdu_disk_info_t) -#define PRINT_RAID_DEBUG _IO (MD_MAJOR, 0x13) -#define RAID_AUTORUN _IO (MD_MAJOR, 0x14) -#define GET_BITMAP_FILE _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t) - -/* configuration */ -#define CLEAR_ARRAY _IO (MD_MAJOR, 0x20) -#define ADD_NEW_DISK _IOW (MD_MAJOR, 0x21, mdu_disk_info_t) -#define HOT_REMOVE_DISK _IO (MD_MAJOR, 0x22) -#define SET_ARRAY_INFO _IOW (MD_MAJOR, 0x23, mdu_array_info_t) -#define SET_DISK_INFO _IO (MD_MAJOR, 0x24) -#define WRITE_RAID_INFO _IO (MD_MAJOR, 0x25) -#define UNPROTECT_ARRAY _IO (MD_MAJOR, 0x26) -#define PROTECT_ARRAY _IO (MD_MAJOR, 0x27) -#define HOT_ADD_DISK _IO (MD_MAJOR, 0x28) -#define SET_DISK_FAULTY _IO (MD_MAJOR, 0x29) -#define HOT_GENERATE_ERROR _IO (MD_MAJOR, 0x2a) -#define SET_BITMAP_FILE _IOW (MD_MAJOR, 0x2b, int) - -/* usage */ -#define RUN_ARRAY _IOW (MD_MAJOR, 0x30, mdu_param_t) -/* 0x31 was START_ARRAY */ -#define STOP_ARRAY _IO (MD_MAJOR, 0x32) -#define STOP_ARRAY_RO _IO (MD_MAJOR, 0x33) -#define RESTART_ARRAY_RW _IO (MD_MAJOR, 0x34) - -/* 63 partitions with the alternate major number (mdp) */ -#define MdpMinorShift 6 - -typedef struct mdu_version_s { - int major; - int minor; - int patchlevel; -} mdu_version_t; - -typedef struct mdu_array_info_s { - /* - * Generic constant information - */ - int major_version; - int minor_version; - int patch_version; - int ctime; - int level; - int size; - int nr_disks; - int raid_disks; - int md_minor; - int not_persistent; - - /* - * Generic state information - */ - int utime; /* 0 Superblock update time */ - int state; /* 1 State bits (clean, ...) */ - int active_disks; /* 2 Number of currently active disks */ - int working_disks; /* 3 Number of working disks */ - int failed_disks; /* 4 Number of failed disks */ - int spare_disks; /* 5 Number of spare disks */ - - /* - * Personality information - */ - int layout; /* 0 the array's physical layout */ - int chunk_size; /* 1 chunk size in bytes */ - -} mdu_array_info_t; - -/* non-obvious values for 'level' */ -#define LEVEL_MULTIPATH (-4) -#define LEVEL_LINEAR (-1) -#define LEVEL_FAULTY (-5) - -/* we need a value for 'no level specified' and 0 - * means 'raid0', so we need something else. This is - * for internal use only - */ -#define LEVEL_NONE (-1000000) - -typedef struct mdu_disk_info_s { - /* - * configuration/status of one particular disk - */ - int number; - int major; - int minor; - int raid_disk; - int state; - -} mdu_disk_info_t; - -typedef struct mdu_start_info_s { - /* - * configuration/status of one particular disk - */ - int major; - int minor; - int raid_disk; - int state; - -} mdu_start_info_t; - -typedef struct mdu_bitmap_file_s -{ - char pathname[4096]; -} mdu_bitmap_file_t; - -typedef struct mdu_param_s -{ - int personality; /* 1,2,3,4 */ - int chunk_size; /* in bytes */ - int max_fault; /* unused for now */ -} mdu_param_t; - -#endif /* _UAPI_MD_U_H */ diff --git a/trunk/include/uapi/linux/tcp.h b/trunk/include/uapi/linux/tcp.h index e962faa5ab0d..c4b89a5cb7df 100644 --- a/trunk/include/uapi/linux/tcp.h +++ b/trunk/include/uapi/linux/tcp.h @@ -130,7 +130,6 @@ enum { #define TCPI_OPT_WSCALE 4 #define TCPI_OPT_ECN 8 /* ECN was negociated at TCP session init */ #define TCPI_OPT_ECN_SEEN 16 /* we received at least one packet with ECT */ -#define TCPI_OPT_SYN_DATA 32 /* SYN-ACK acked data in SYN sent or rcvd */ enum tcp_ca_state { TCP_CA_Open = 0, diff --git a/trunk/init/main.c b/trunk/init/main.c index e33e09df3cbc..9cf77ab138a6 100644 --- a/trunk/init/main.c +++ b/trunk/init/main.c @@ -442,11 +442,9 @@ void __init __weak smp_setup_processor_id(void) { } -# if THREAD_SIZE >= PAGE_SIZE void __init __weak thread_info_cache_init(void) { } -#endif /* * Set up kernel memory allocators diff --git a/trunk/net/8021q/vlan.c b/trunk/net/8021q/vlan.c index ee070722a3a3..9096bcb08132 100644 --- a/trunk/net/8021q/vlan.c +++ b/trunk/net/8021q/vlan.c @@ -463,9 +463,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, case NETDEV_PRE_TYPE_CHANGE: /* Forbid underlaying device to change its type. */ - if (vlan_uses_dev(dev)) - return NOTIFY_BAD; - break; + return NOTIFY_BAD; case NETDEV_NOTIFY_PEERS: case NETDEV_BONDING_FAILOVER: diff --git a/trunk/net/batman-adv/bridge_loop_avoidance.c b/trunk/net/batman-adv/bridge_loop_avoidance.c index fd8d5afec0dd..0a9084ad19a6 100644 --- a/trunk/net/batman-adv/bridge_loop_avoidance.c +++ b/trunk/net/batman-adv/bridge_loop_avoidance.c @@ -1167,8 +1167,6 @@ int batadv_bla_init(struct batadv_priv *bat_priv) uint16_t crc; unsigned long entrytime; - spin_lock_init(&bat_priv->bla.bcast_duplist_lock); - batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n"); /* setting claim destination address */ @@ -1212,8 +1210,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv) /** * batadv_bla_check_bcast_duplist * @bat_priv: the bat priv with all the soft interface information - * @bcast_packet: encapsulated broadcast frame plus batman header - * @bcast_packet_len: length of encapsulated broadcast frame plus batman header + * @bcast_packet: originator mac address + * @hdr_size: maximum length of the frame * * check if it is on our broadcast list. Another gateway might * have sent the same packet because it is connected to the same backbone, @@ -1226,22 +1224,20 @@ int batadv_bla_init(struct batadv_priv *bat_priv) */ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, struct batadv_bcast_packet *bcast_packet, - int bcast_packet_len) + int hdr_size) { - int i, length, curr, ret = 0; + int i, length, curr; uint8_t *content; uint16_t crc; struct batadv_bcast_duplist_entry *entry; - length = bcast_packet_len - sizeof(*bcast_packet); + length = hdr_size - sizeof(*bcast_packet); content = (uint8_t *)bcast_packet; content += sizeof(*bcast_packet); /* calculate the crc ... */ crc = crc16(0, content, length); - spin_lock_bh(&bat_priv->bla.bcast_duplist_lock); - for (i = 0; i < BATADV_DUPLIST_SIZE; i++) { curr = (bat_priv->bla.bcast_duplist_curr + i); curr %= BATADV_DUPLIST_SIZE; @@ -1263,12 +1259,9 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, /* this entry seems to match: same crc, not too old, * and from another gw. therefore return 1 to forbid it. */ - ret = 1; - goto out; + return 1; } - /* not found, add a new entry (overwrite the oldest entry) - * and allow it, its the first occurence. - */ + /* not found, add a new entry (overwrite the oldest entry) */ curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1); curr %= BATADV_DUPLIST_SIZE; entry = &bat_priv->bla.bcast_duplist[curr]; @@ -1277,10 +1270,8 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, memcpy(entry->orig, bcast_packet->orig, ETH_ALEN); bat_priv->bla.bcast_duplist_curr = curr; -out: - spin_unlock_bh(&bat_priv->bla.bcast_duplist_lock); - - return ret; + /* allow it, its the first occurence. */ + return 0; } diff --git a/trunk/net/batman-adv/routing.c b/trunk/net/batman-adv/routing.c index 376b4cc6ca82..939fc01371df 100644 --- a/trunk/net/batman-adv/routing.c +++ b/trunk/net/batman-adv/routing.c @@ -1124,14 +1124,8 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, spin_unlock_bh(&orig_node->bcast_seqno_lock); - /* keep skb linear for crc calculation */ - if (skb_linearize(skb) < 0) - goto out; - - bcast_packet = (struct batadv_bcast_packet *)skb->data; - /* check whether this has been sent by another originator before */ - if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, skb->len)) + if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, hdr_size)) goto out; /* rebroadcast packet */ diff --git a/trunk/net/batman-adv/types.h b/trunk/net/batman-adv/types.h index ac1e07a80454..2ed82caacdca 100644 --- a/trunk/net/batman-adv/types.h +++ b/trunk/net/batman-adv/types.h @@ -205,8 +205,6 @@ struct batadv_priv_bla { struct batadv_hashtable *backbone_hash; struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE]; int bcast_duplist_curr; - /* protects bcast_duplist and bcast_duplist_curr */ - spinlock_t bcast_duplist_lock; struct batadv_bla_claim_dst claim_dest; struct delayed_work work; }; diff --git a/trunk/net/bluetooth/smp.c b/trunk/net/bluetooth/smp.c index 2ac8d50861e0..8c225ef349cd 100644 --- a/trunk/net/bluetooth/smp.c +++ b/trunk/net/bluetooth/smp.c @@ -32,8 +32,6 @@ #define SMP_TIMEOUT msecs_to_jiffies(30000) -#define AUTH_REQ_MASK 0x07 - static inline void swap128(u8 src[16], u8 dst[16]) { int i; @@ -232,7 +230,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, req->max_key_size = SMP_MAX_ENC_KEY_SIZE; req->init_key_dist = 0; req->resp_key_dist = dist_keys; - req->auth_req = (authreq & AUTH_REQ_MASK); + req->auth_req = authreq; return; } @@ -241,7 +239,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; rsp->init_key_dist = 0; rsp->resp_key_dist = req->resp_key_dist & dist_keys; - rsp->auth_req = (authreq & AUTH_REQ_MASK); + rsp->auth_req = authreq; } static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) diff --git a/trunk/net/ceph/messenger.c b/trunk/net/ceph/messenger.c index 3ef1759403b4..159aa8bef9e7 100644 --- a/trunk/net/ceph/messenger.c +++ b/trunk/net/ceph/messenger.c @@ -2300,11 +2300,10 @@ static void con_work(struct work_struct *work) mutex_unlock(&con->mutex); return; } else { + con->ops->put(con); dout("con_work %p FAILED to back off %lu\n", con, con->delay); - set_bit(CON_FLAG_BACKOFF, &con->flags); } - goto done; } if (con->state == CON_STATE_STANDBY) { @@ -2750,8 +2749,7 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip) msg = con->ops->alloc_msg(con, hdr, skip); mutex_lock(&con->mutex); if (con->state != CON_STATE_OPEN) { - if (msg) - ceph_msg_put(msg); + ceph_msg_put(msg); return -EAGAIN; } con->in_msg = msg; diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index 4007c1437fda..6e04b1fa11f2 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -3379,12 +3379,10 @@ EXPORT_SYMBOL(__skb_warn_lro_forwarding); void kfree_skb_partial(struct sk_buff *skb, bool head_stolen) { - if (head_stolen) { - skb_release_head_state(skb); + if (head_stolen) kmem_cache_free(skbuff_head_cache, skb); - } else { + else __kfree_skb(skb); - } } EXPORT_SYMBOL(kfree_skb_partial); diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index a8c651216fa6..432f4bb77238 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -1163,12 +1163,8 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, spin_lock_bh(&fnhe_lock); if (daddr == fnhe->fnhe_daddr) { - struct rtable *orig = rcu_dereference(fnhe->fnhe_rth); - if (orig && rt_is_expired(orig)) { - fnhe->fnhe_gw = 0; - fnhe->fnhe_pmtu = 0; - fnhe->fnhe_expires = 0; - } + struct rtable *orig; + if (fnhe->fnhe_pmtu) { unsigned long expires = fnhe->fnhe_expires; unsigned long diff = expires - jiffies; @@ -1185,6 +1181,7 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, } else if (!rt->rt_gateway) rt->rt_gateway = daddr; + orig = rcu_dereference(fnhe->fnhe_rth); rcu_assign_pointer(fnhe->fnhe_rth, rt); if (orig) rt_free(orig); diff --git a/trunk/net/ipv4/tcp.c b/trunk/net/ipv4/tcp.c index 197c0008503c..f32c02e2a543 100644 --- a/trunk/net/ipv4/tcp.c +++ b/trunk/net/ipv4/tcp.c @@ -549,12 +549,14 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) !tp->urg_data || before(tp->urg_seq, tp->copied_seq) || !before(tp->urg_seq, tp->rcv_nxt)) { + struct sk_buff *skb; answ = tp->rcv_nxt - tp->copied_seq; - /* Subtract 1, if FIN was received */ - if (answ && sock_flag(sk, SOCK_DONE)) - answ--; + /* Subtract 1, if FIN is in queue. */ + skb = skb_peek_tail(&sk->sk_receive_queue); + if (answ && skb) + answ -= tcp_hdr(skb)->fin; } else answ = tp->urg_seq - tp->copied_seq; release_sock(sk); @@ -2764,8 +2766,6 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info) info->tcpi_options |= TCPI_OPT_ECN; if (tp->ecn_flags & TCP_ECN_SEEN) info->tcpi_options |= TCPI_OPT_ECN_SEEN; - if (tp->syn_data_acked) - info->tcpi_options |= TCPI_OPT_SYN_DATA; info->tcpi_rto = jiffies_to_usecs(icsk->icsk_rto); info->tcpi_ato = jiffies_to_usecs(icsk->icsk_ack.ato); diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index 1db663983587..432c36649db3 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -5646,7 +5646,6 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, tcp_rearm_rto(sk); return true; } - tp->syn_data_acked = tp->syn_data; return false; } @@ -5964,7 +5963,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, req = tp->fastopen_rsk; if (req != NULL) { - WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV && + BUG_ON(sk->sk_state != TCP_SYN_RECV && sk->sk_state != TCP_FIN_WAIT1); if (tcp_check_req(sk, skb, req, NULL, true) == NULL) @@ -6053,15 +6052,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, * ACK we have received, this would have acknowledged * our SYNACK so stop the SYNACK timer. */ - if (req != NULL) { - /* Return RST if ack_seq is invalid. - * Note that RFC793 only says to generate a - * DUPACK for it but for TCP Fast Open it seems - * better to treat this case like TCP_SYN_RECV - * above. - */ - if (!acceptable) - return 1; + if (acceptable && req != NULL) { /* We no longer need the request sock. */ reqsk_fastopen_remove(sk, req, false); tcp_rearm_rto(sk); diff --git a/trunk/net/ipv4/tcp_ipv4.c b/trunk/net/ipv4/tcp_ipv4.c index 0c4a64355603..ef998b008a57 100644 --- a/trunk/net/ipv4/tcp_ipv4.c +++ b/trunk/net/ipv4/tcp_ipv4.c @@ -1461,7 +1461,6 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk, skb_set_owner_r(skb, child); __skb_queue_tail(&child->sk_receive_queue, skb); tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; - tp->syn_data_acked = 1; } sk->sk_data_ready(sk, 0); bh_unlock_sock(child); diff --git a/trunk/net/ipv4/tcp_minisocks.c b/trunk/net/ipv4/tcp_minisocks.c index a7302d974f32..27536ba16c9d 100644 --- a/trunk/net/ipv4/tcp_minisocks.c +++ b/trunk/net/ipv4/tcp_minisocks.c @@ -510,7 +510,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, newtp->rx_opt.mss_clamp = req->mss; TCP_ECN_openreq_child(newtp, req); newtp->fastopen_rsk = NULL; - newtp->syn_data_acked = 0; TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_PASSIVEOPENS); } diff --git a/trunk/net/ipv4/tcp_timer.c b/trunk/net/ipv4/tcp_timer.c index d47c1b4421a3..fc04711e80c8 100644 --- a/trunk/net/ipv4/tcp_timer.c +++ b/trunk/net/ipv4/tcp_timer.c @@ -347,8 +347,8 @@ void tcp_retransmit_timer(struct sock *sk) return; } if (tp->fastopen_rsk) { - WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV && - sk->sk_state != TCP_FIN_WAIT1); + BUG_ON(sk->sk_state != TCP_SYN_RECV && + sk->sk_state != TCP_FIN_WAIT1); tcp_fastopen_synack_timer(sk); /* Before we receive ACK to our SYN-ACK don't retransmit * anything else (e.g., data or FIN segments). diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index b1e6cf0b95fd..7c7e963260e1 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -219,7 +219,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { }; static const u32 ip6_template_metrics[RTAX_MAX] = { - [RTAX_HOPLIMIT - 1] = 0, + [RTAX_HOPLIMIT - 1] = 255, }; static const struct rt6_info ip6_null_entry_template = { @@ -1232,7 +1232,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, rt->rt6i_dst.addr = fl6->daddr; rt->rt6i_dst.plen = 128; rt->rt6i_idev = idev; - dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0); + dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); spin_lock_bh(&icmp6_dst_lock); rt->dst.next = icmp6_dst_gc_list; diff --git a/trunk/net/mac80211/iface.c b/trunk/net/mac80211/iface.c index 7de7717ad67d..6f8a73c64fb3 100644 --- a/trunk/net/mac80211/iface.c +++ b/trunk/net/mac80211/iface.c @@ -853,7 +853,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (info->control.vif == &sdata->vif) { __skb_unlink(skb, &local->pending[i]); - ieee80211_free_txskb(&local->hw, skb); + dev_kfree_skb_irq(skb); } } } diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index 1b7eed252fe9..e714ed8bb198 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -3099,32 +3099,22 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, ht_cfreq, ht_oper->primary_chan, cbss->channel->band); ht_oper = NULL; - } else { - channel_type = NL80211_CHAN_HT20; } } - if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { - /* - * cfg80211 already verified that the channel itself can - * be used, but it didn't check that we can do the right - * HT type, so do that here as well. If HT40 isn't allowed - * on this channel, disable 40 MHz operation. - */ + if (ht_oper) { + channel_type = NL80211_CHAN_HT20; - switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) - ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; - else + if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { + switch (ht_oper->ht_param & + IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: channel_type = NL80211_CHAN_HT40PLUS; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) - ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; - else + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: channel_type = NL80211_CHAN_HT40MINUS; - break; + break; + } } } @@ -3559,7 +3549,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; - bool tx = !req->local_state_change; mutex_lock(&ifmgd->mtx); @@ -3576,12 +3565,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, if (ifmgd->associated && ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, - req->reason_code, tx, frame_buf); + req->reason_code, true, frame_buf); } else { drv_mgd_prepare_tx(sdata->local, sdata); ieee80211_send_deauth_disassoc(sdata, req->bssid, IEEE80211_STYPE_DEAUTH, - req->reason_code, tx, + req->reason_code, true, frame_buf); } diff --git a/trunk/net/mac80211/sta_info.c b/trunk/net/mac80211/sta_info.c index 0a4e4c04db89..797dd36a220d 100644 --- a/trunk/net/mac80211/sta_info.c +++ b/trunk/net/mac80211/sta_info.c @@ -650,7 +650,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, */ if (!skb) break; - ieee80211_free_txskb(&local->hw, skb); + dev_kfree_skb(skb); } /* @@ -679,7 +679,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, local->total_ps_buffered--; ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n", sta->sta.addr); - ieee80211_free_txskb(&local->hw, skb); + dev_kfree_skb(skb); } /* diff --git a/trunk/net/mac80211/util.c b/trunk/net/mac80211/util.c index 94e586873979..22ca35054dd0 100644 --- a/trunk/net/mac80211/util.c +++ b/trunk/net/mac80211/util.c @@ -406,7 +406,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, int queue = info->hw_queue; if (WARN_ON(!info->control.vif)) { - ieee80211_free_txskb(&local->hw, skb); + kfree_skb(skb); return; } @@ -431,7 +431,7 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (WARN_ON(!info->control.vif)) { - ieee80211_free_txskb(&local->hw, skb); + kfree_skb(skb); continue; } diff --git a/trunk/net/mac80211/wpa.c b/trunk/net/mac80211/wpa.c index 8bd2f5c6a56e..bdb53aba888e 100644 --- a/trunk/net/mac80211/wpa.c +++ b/trunk/net/mac80211/wpa.c @@ -106,8 +106,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) if (status->flag & RX_FLAG_MMIC_ERROR) goto mic_fail; - if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key && - rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP) + if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key) goto update_iv; return RX_CONTINUE; @@ -546,19 +545,14 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) static void bip_aad(struct sk_buff *skb, u8 *aad) { - __le16 mask_fc; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - /* BIP AAD: FC(masked) || A1 || A2 || A3 */ /* FC type/subtype */ + aad[0] = skb->data[0]; /* Mask FC Retry, PwrMgt, MoreData flags to zero */ - mask_fc = hdr->frame_control; - mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM | - IEEE80211_FCTL_MOREDATA); - put_unaligned(mask_fc, (__le16 *) &aad[0]); + aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6)); /* A1 || A2 || A3 */ - memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN); + memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN); } diff --git a/trunk/net/netfilter/ipvs/ip_vs_ctl.c b/trunk/net/netfilter/ipvs/ip_vs_ctl.c index c4ee43710aab..7e7198b51c06 100644 --- a/trunk/net/netfilter/ipvs/ip_vs_ctl.c +++ b/trunk/net/netfilter/ipvs/ip_vs_ctl.c @@ -2589,8 +2589,6 @@ __ip_vs_get_timeouts(struct net *net, struct ip_vs_timeout_user *u) struct ip_vs_proto_data *pd; #endif - memset(u, 0, sizeof (*u)); - #ifdef CONFIG_IP_VS_PROTO_TCP pd = ip_vs_proto_data_get(net, IPPROTO_TCP); u->tcp_timeout = pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ; @@ -2768,6 +2766,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) { struct ip_vs_timeout_user t; + memset(&t, 0, sizeof(t)); __ip_vs_get_timeouts(net, &t); if (copy_to_user(user, &t, sizeof(t)) != 0) ret = -EFAULT; diff --git a/trunk/net/netfilter/xt_CT.c b/trunk/net/netfilter/xt_CT.c index ae7f5daeee43..16c712563860 100644 --- a/trunk/net/netfilter/xt_CT.c +++ b/trunk/net/netfilter/xt_CT.c @@ -180,9 +180,9 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, typeof(nf_ct_timeout_find_get_hook) timeout_find_get; struct ctnl_timeout *timeout; struct nf_conn_timeout *timeout_ext; + const struct ipt_entry *e = par->entryinfo; struct nf_conntrack_l4proto *l4proto; int ret = 0; - u8 proto; rcu_read_lock(); timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); @@ -192,11 +192,9 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, goto out; } - proto = xt_ct_find_proto(par); - if (!proto) { + if (e->ip.invflags & IPT_INV_PROTO) { ret = -EINVAL; - pr_info("You must specify a L4 protocol, and not use " - "inversions on it.\n"); + pr_info("You cannot use inversion on L4 protocol\n"); goto out; } @@ -216,7 +214,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, /* Make sure the timeout policy matches any existing protocol tracker, * otherwise default to generic. */ - l4proto = __nf_ct_l4proto_find(par->family, proto); + l4proto = __nf_ct_l4proto_find(par->family, e->ip.proto); if (timeout->l4proto->l4proto != l4proto->l4proto) { ret = -EINVAL; pr_info("Timeout policy `%s' can only be used by L4 protocol " diff --git a/trunk/net/netfilter/xt_TEE.c b/trunk/net/netfilter/xt_TEE.c index bd93e51d30ac..ee2e5bc5a8c7 100644 --- a/trunk/net/netfilter/xt_TEE.c +++ b/trunk/net/netfilter/xt_TEE.c @@ -70,7 +70,6 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info) fl4.daddr = info->gw.ip; fl4.flowi4_tos = RT_TOS(iph->tos); fl4.flowi4_scope = RT_SCOPE_UNIVERSE; - fl4.flowi4_flags = FLOWI_FLAG_KNOWN_NH; rt = ip_route_output_key(net, &fl4); if (IS_ERR(rt)) return false; diff --git a/trunk/net/netfilter/xt_nat.c b/trunk/net/netfilter/xt_nat.c index bea7464cc43f..81aafa8e4fef 100644 --- a/trunk/net/netfilter/xt_nat.c +++ b/trunk/net/netfilter/xt_nat.c @@ -111,7 +111,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { .family = NFPROTO_IPV4, .table = "nat", .hooks = (1 << NF_INET_POST_ROUTING) | - (1 << NF_INET_LOCAL_IN), + (1 << NF_INET_LOCAL_OUT), .me = THIS_MODULE, }, { @@ -123,7 +123,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { .family = NFPROTO_IPV4, .table = "nat", .hooks = (1 << NF_INET_PRE_ROUTING) | - (1 << NF_INET_LOCAL_OUT), + (1 << NF_INET_LOCAL_IN), .me = THIS_MODULE, }, { @@ -133,7 +133,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { .targetsize = sizeof(struct nf_nat_range), .table = "nat", .hooks = (1 << NF_INET_POST_ROUTING) | - (1 << NF_INET_LOCAL_IN), + (1 << NF_INET_LOCAL_OUT), .me = THIS_MODULE, }, { @@ -143,7 +143,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { .targetsize = sizeof(struct nf_nat_range), .table = "nat", .hooks = (1 << NF_INET_PRE_ROUTING) | - (1 << NF_INET_LOCAL_OUT), + (1 << NF_INET_LOCAL_IN), .me = THIS_MODULE, }, }; diff --git a/trunk/net/netlink/af_netlink.c b/trunk/net/netlink/af_netlink.c index 4da797fa5ec5..01e944a017a4 100644 --- a/trunk/net/netlink/af_netlink.c +++ b/trunk/net/netlink/af_netlink.c @@ -138,8 +138,6 @@ static int netlink_dump(struct sock *sk); static DEFINE_RWLOCK(nl_table_lock); static atomic_t nl_table_users = ATOMIC_INIT(0); -#define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock)); - static ATOMIC_NOTIFIER_HEAD(netlink_chain); static inline u32 netlink_group_mask(u32 group) @@ -347,11 +345,6 @@ netlink_update_listeners(struct sock *sk) struct hlist_node *node; unsigned long mask; unsigned int i; - struct listeners *listeners; - - listeners = nl_deref_protected(tbl->listeners); - if (!listeners) - return; for (i = 0; i < NLGRPLONGS(tbl->groups); i++) { mask = 0; @@ -359,7 +352,7 @@ netlink_update_listeners(struct sock *sk) if (i < NLGRPLONGS(nlk_sk(sk)->ngroups)) mask |= nlk_sk(sk)->groups[i]; } - listeners->masks[i] = mask; + tbl->listeners->masks[i] = mask; } /* this function is only called with the netlink table "grabbed", which * makes sure updates are visible before bind or setsockopt return. */ @@ -543,11 +536,7 @@ static int netlink_release(struct socket *sock) if (netlink_is_kernel(sk)) { BUG_ON(nl_table[sk->sk_protocol].registered == 0); if (--nl_table[sk->sk_protocol].registered == 0) { - struct listeners *old; - - old = nl_deref_protected(nl_table[sk->sk_protocol].listeners); - RCU_INIT_POINTER(nl_table[sk->sk_protocol].listeners, NULL); - kfree_rcu(old, rcu); + kfree(nl_table[sk->sk_protocol].listeners); nl_table[sk->sk_protocol].module = NULL; nl_table[sk->sk_protocol].bind = NULL; nl_table[sk->sk_protocol].flags = 0; @@ -993,7 +982,7 @@ int netlink_has_listeners(struct sock *sk, unsigned int group) rcu_read_lock(); listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners); - if (listeners && group - 1 < nl_table[sk->sk_protocol].groups) + if (group - 1 < nl_table[sk->sk_protocol].groups) res = test_bit(group - 1, listeners->masks); rcu_read_unlock(); @@ -1636,7 +1625,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups) new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC); if (!new) return -ENOMEM; - old = nl_deref_protected(tbl->listeners); + old = rcu_dereference_protected(tbl->listeners, 1); memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups)); rcu_assign_pointer(tbl->listeners, new); diff --git a/trunk/net/wireless/mlme.c b/trunk/net/wireless/mlme.c index 904a7f368325..8016fee0752b 100644 --- a/trunk/net/wireless/mlme.c +++ b/trunk/net/wireless/mlme.c @@ -457,14 +457,20 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, .reason_code = reason, .ie = ie, .ie_len = ie_len, - .local_state_change = local_state_change, }; ASSERT_WDEV_LOCK(wdev); - if (local_state_change && (!wdev->current_bss || - !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) + if (local_state_change) { + if (wdev->current_bss && + ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { + cfg80211_unhold_bss(wdev->current_bss); + cfg80211_put_bss(&wdev->current_bss->pub); + wdev->current_bss = NULL; + } + return 0; + } return rdev->ops->deauth(&rdev->wiphy, dev, &req); } diff --git a/trunk/sound/core/compress_offload.c b/trunk/sound/core/compress_offload.c index ad11dc994792..c40ae573346d 100644 --- a/trunk/sound/core/compress_offload.c +++ b/trunk/sound/core/compress_offload.c @@ -100,15 +100,12 @@ static int snd_compr_open(struct inode *inode, struct file *f) if (dirn != compr->direction) { pr_err("this device doesn't support this direction\n"); - snd_card_unref(compr->card); return -EINVAL; } data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) { - snd_card_unref(compr->card); + if (!data) return -ENOMEM; - } data->stream.ops = compr->ops; data->stream.direction = dirn; data->stream.private_data = compr->private_data; @@ -116,7 +113,6 @@ static int snd_compr_open(struct inode *inode, struct file *f) runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); if (!runtime) { kfree(data); - snd_card_unref(compr->card); return -ENOMEM; } runtime->state = SNDRV_PCM_STATE_OPEN; @@ -130,8 +126,7 @@ static int snd_compr_open(struct inode *inode, struct file *f) kfree(runtime); kfree(data); } - snd_card_unref(compr->card); - return 0; + return ret; } static int snd_compr_free(struct inode *inode, struct file *f) diff --git a/trunk/sound/core/control.c b/trunk/sound/core/control.c index 8c7c2c9bba61..7e86a5b9f3b5 100644 --- a/trunk/sound/core/control.c +++ b/trunk/sound/core/control.c @@ -86,7 +86,6 @@ static int snd_ctl_open(struct inode *inode, struct file *file) write_lock_irqsave(&card->ctl_files_rwlock, flags); list_add_tail(&ctl->list, &card->ctl_files); write_unlock_irqrestore(&card->ctl_files_rwlock, flags); - snd_card_unref(card); return 0; __error: @@ -94,8 +93,6 @@ static int snd_ctl_open(struct inode *inode, struct file *file) __error2: snd_card_file_remove(card, file); __error1: - if (card) - snd_card_unref(card); return err; } @@ -1437,8 +1434,6 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, spin_unlock_irq(&ctl->read_lock); schedule(); remove_wait_queue(&ctl->change_sleep, &wait); - if (ctl->card->shutdown) - return -ENODEV; if (signal_pending(current)) return -ERESTARTSYS; spin_lock_irq(&ctl->read_lock); diff --git a/trunk/sound/core/hwdep.c b/trunk/sound/core/hwdep.c index 3f7f6628cf7b..75ea16f35b1a 100644 --- a/trunk/sound/core/hwdep.c +++ b/trunk/sound/core/hwdep.c @@ -100,10 +100,8 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) if (hw == NULL) return -ENODEV; - if (!try_module_get(hw->card->module)) { - snd_card_unref(hw->card); + if (!try_module_get(hw->card->module)) return -EFAULT; - } init_waitqueue_entry(&wait, current); add_wait_queue(&hw->open_wait, &wait); @@ -131,10 +129,6 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) mutex_unlock(&hw->open_mutex); schedule(); mutex_lock(&hw->open_mutex); - if (hw->card->shutdown) { - err = -ENODEV; - break; - } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -154,7 +148,6 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) mutex_unlock(&hw->open_mutex); if (err < 0) module_put(hw->card->module); - snd_card_unref(hw->card); return err; } @@ -466,15 +459,12 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device) mutex_unlock(®ister_mutex); return -EINVAL; } - mutex_lock(&hwdep->open_mutex); - wake_up(&hwdep->open_wait); #ifdef CONFIG_SND_OSSEMUL if (hwdep->ossreg) snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); #endif snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); list_del_init(&hwdep->list); - mutex_unlock(&hwdep->open_mutex); mutex_unlock(®ister_mutex); return 0; } diff --git a/trunk/sound/core/init.c b/trunk/sound/core/init.c index 7b012d15c2cf..d8ec849af128 100644 --- a/trunk/sound/core/init.c +++ b/trunk/sound/core/init.c @@ -213,7 +213,6 @@ int snd_card_create(int idx, const char *xid, spin_lock_init(&card->files_lock); INIT_LIST_HEAD(&card->files_list); init_waitqueue_head(&card->shutdown_sleep); - atomic_set(&card->refcount, 0); #ifdef CONFIG_PM mutex_init(&card->power_lock); init_waitqueue_head(&card->power_sleep); @@ -447,36 +446,21 @@ static int snd_card_do_free(struct snd_card *card) return 0; } -/** - * snd_card_unref - release the reference counter - * @card: the card instance - * - * Decrements the reference counter. When it reaches to zero, wake up - * the sleeper and call the destructor if needed. - */ -void snd_card_unref(struct snd_card *card) -{ - if (atomic_dec_and_test(&card->refcount)) { - wake_up(&card->shutdown_sleep); - if (card->free_on_last_close) - snd_card_do_free(card); - } -} -EXPORT_SYMBOL(snd_card_unref); - int snd_card_free_when_closed(struct snd_card *card) { - int ret; - - atomic_inc(&card->refcount); - ret = snd_card_disconnect(card); - if (ret) { - atomic_dec(&card->refcount); + int free_now = 0; + int ret = snd_card_disconnect(card); + if (ret) return ret; - } - card->free_on_last_close = 1; - if (atomic_dec_and_test(&card->refcount)) + spin_lock(&card->files_lock); + if (list_empty(&card->files_list)) + free_now = 1; + else + card->free_on_last_close = 1; + spin_unlock(&card->files_lock); + + if (free_now) snd_card_do_free(card); return 0; } @@ -490,7 +474,7 @@ int snd_card_free(struct snd_card *card) return ret; /* wait, until all devices are ready for the free operation */ - wait_event(card->shutdown_sleep, !atomic_read(&card->refcount)); + wait_event(card->shutdown_sleep, list_empty(&card->files_list)); snd_card_do_free(card); return 0; } @@ -902,7 +886,6 @@ int snd_card_file_add(struct snd_card *card, struct file *file) return -ENODEV; } list_add(&mfile->list, &card->files_list); - atomic_inc(&card->refcount); spin_unlock(&card->files_lock); return 0; } @@ -925,6 +908,7 @@ EXPORT_SYMBOL(snd_card_file_add); int snd_card_file_remove(struct snd_card *card, struct file *file) { struct snd_monitor_file *mfile, *found = NULL; + int last_close = 0; spin_lock(&card->files_lock); list_for_each_entry(mfile, &card->files_list, list) { @@ -939,13 +923,19 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) break; } } + if (list_empty(&card->files_list)) + last_close = 1; spin_unlock(&card->files_lock); + if (last_close) { + wake_up(&card->shutdown_sleep); + if (card->free_on_last_close) + snd_card_do_free(card); + } if (!found) { snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); return -ENOENT; } kfree(found); - snd_card_unref(card); return 0; } diff --git a/trunk/sound/core/oss/mixer_oss.c b/trunk/sound/core/oss/mixer_oss.c index a9a2e63c0222..29f6ded02555 100644 --- a/trunk/sound/core/oss/mixer_oss.c +++ b/trunk/sound/core/oss/mixer_oss.c @@ -52,19 +52,14 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) SNDRV_OSS_DEVICE_TYPE_MIXER); if (card == NULL) return -ENODEV; - if (card->mixer_oss == NULL) { - snd_card_unref(card); + if (card->mixer_oss == NULL) return -ENODEV; - } err = snd_card_file_add(card, file); - if (err < 0) { - snd_card_unref(card); + if (err < 0) return err; - } fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL); if (fmixer == NULL) { snd_card_file_remove(card, file); - snd_card_unref(card); return -ENOMEM; } fmixer->card = card; @@ -73,7 +68,6 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) if (!try_module_get(card->module)) { kfree(fmixer); snd_card_file_remove(card, file); - snd_card_unref(card); return -EFAULT; } return 0; diff --git a/trunk/sound/core/oss/pcm_oss.c b/trunk/sound/core/oss/pcm_oss.c index f337b66a020b..08fde0060fd9 100644 --- a/trunk/sound/core/oss/pcm_oss.c +++ b/trunk/sound/core/oss/pcm_oss.c @@ -2441,10 +2441,6 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) mutex_unlock(&pcm->open_mutex); schedule(); mutex_lock(&pcm->open_mutex); - if (pcm->card->shutdown) { - err = -ENODEV; - break; - } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -2461,8 +2457,6 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) __error2: snd_card_file_remove(pcm->card, file); __error1: - if (pcm) - snd_card_unref(pcm->card); return err; } diff --git a/trunk/sound/core/pcm.c b/trunk/sound/core/pcm.c index 030102caeee9..f2991940b271 100644 --- a/trunk/sound/core/pcm.c +++ b/trunk/sound/core/pcm.c @@ -1086,19 +1086,11 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) if (list_empty(&pcm->list)) goto unlock; - mutex_lock(&pcm->open_mutex); - wake_up(&pcm->open_wait); list_del_init(&pcm->list); for (cidx = 0; cidx < 2; cidx++) - for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { - snd_pcm_stream_lock_irq(substream); - if (substream->runtime) { + for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) + if (substream->runtime) substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; - wake_up(&substream->runtime->sleep); - wake_up(&substream->runtime->tsleep); - } - snd_pcm_stream_unlock_irq(substream); - } list_for_each_entry(notify, &snd_pcm_notify_list, list) { notify->n_disconnect(pcm); } @@ -1118,7 +1110,6 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) pcm->streams[cidx].chmap_kctl = NULL; } } - mutex_unlock(&pcm->open_mutex); unlock: mutex_unlock(®ister_mutex); return 0; diff --git a/trunk/sound/core/pcm_native.c b/trunk/sound/core/pcm_native.c index 6e8872de5ba0..5e12e5bacbba 100644 --- a/trunk/sound/core/pcm_native.c +++ b/trunk/sound/core/pcm_native.c @@ -369,14 +369,6 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime) return usecs; } -static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state) -{ - snd_pcm_stream_lock_irq(substream); - if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED) - substream->runtime->status->state = state; - snd_pcm_stream_unlock_irq(substream); -} - static int snd_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -460,7 +452,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, runtime->boundary *= 2; snd_pcm_timer_resolution_change(substream); - snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP); + runtime->status->state = SNDRV_PCM_STATE_SETUP; if (pm_qos_request_active(&substream->latency_pm_qos_req)) pm_qos_remove_request(&substream->latency_pm_qos_req); @@ -472,7 +464,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, /* hardware might be unusable from this time, so we force application to retry to set the correct hardware parameter settings */ - snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); + runtime->status->state = SNDRV_PCM_STATE_OPEN; if (substream->ops->hw_free != NULL) substream->ops->hw_free(substream); return err; @@ -520,7 +512,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream) return -EBADFD; if (substream->ops->hw_free) result = substream->ops->hw_free(substream); - snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); + runtime->status->state = SNDRV_PCM_STATE_OPEN; pm_qos_remove_request(&substream->latency_pm_qos_req); return result; } @@ -1328,7 +1320,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state) { struct snd_pcm_runtime *runtime = substream->runtime; runtime->control->appl_ptr = runtime->status->hw_ptr; - snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED); + runtime->status->state = SNDRV_PCM_STATE_PREPARED; } static struct action_ops snd_pcm_action_prepare = { @@ -1518,10 +1510,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, down_read(&snd_pcm_link_rwsem); snd_pcm_stream_lock_irq(substream); remove_wait_queue(&to_check->sleep, &wait); - if (card->shutdown) { - result = -ENODEV; - break; - } if (tout == 0) { if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) result = -ESTRPIPE; @@ -1646,7 +1634,6 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) write_unlock_irq(&snd_pcm_link_rwlock); up_write(&snd_pcm_link_rwsem); _nolock: - snd_card_unref(substream1->pcm->card); fput_light(file, fput_needed); if (res < 0) kfree(group); @@ -2121,9 +2108,7 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file) return err; pcm = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_PCM_PLAYBACK); - err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); - snd_card_unref(pcm->card); - return err; + return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); } static int snd_pcm_capture_open(struct inode *inode, struct file *file) @@ -2134,9 +2119,7 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file) return err; pcm = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_PCM_CAPTURE); - err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); - snd_card_unref(pcm->card); - return err; + return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); } static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) @@ -2173,10 +2156,6 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) mutex_unlock(&pcm->open_mutex); schedule(); mutex_lock(&pcm->open_mutex); - if (pcm->card->shutdown) { - err = -ENODEV; - break; - } if (signal_pending(current)) { err = -ERESTARTSYS; break; diff --git a/trunk/sound/core/rawmidi.c b/trunk/sound/core/rawmidi.c index 1bb95aeea084..ebf6e49ad3d4 100644 --- a/trunk/sound/core/rawmidi.c +++ b/trunk/sound/core/rawmidi.c @@ -379,10 +379,8 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) if (rmidi == NULL) return -ENODEV; - if (!try_module_get(rmidi->card->module)) { - snd_card_unref(rmidi->card); + if (!try_module_get(rmidi->card->module)) return -ENXIO; - } mutex_lock(&rmidi->open_mutex); card = rmidi->card; @@ -424,10 +422,6 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) mutex_unlock(&rmidi->open_mutex); schedule(); mutex_lock(&rmidi->open_mutex); - if (rmidi->card->shutdown) { - err = -ENODEV; - break; - } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -446,7 +440,6 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) #endif file->private_data = rawmidi_file; mutex_unlock(&rmidi->open_mutex); - snd_card_unref(rmidi->card); return 0; __error: @@ -454,7 +447,6 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) __error_card: mutex_unlock(&rmidi->open_mutex); module_put(rmidi->card->module); - snd_card_unref(rmidi->card); return err; } @@ -999,8 +991,6 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun spin_unlock_irq(&runtime->lock); schedule(); remove_wait_queue(&runtime->sleep, &wait); - if (rfile->rmidi->card->shutdown) - return -ENODEV; if (signal_pending(current)) return result > 0 ? result : -ERESTARTSYS; if (!runtime->avail) @@ -1244,8 +1234,6 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, spin_unlock_irq(&runtime->lock); timeout = schedule_timeout(30 * HZ); remove_wait_queue(&runtime->sleep, &wait); - if (rfile->rmidi->card->shutdown) - return -ENODEV; if (signal_pending(current)) return result > 0 ? result : -ERESTARTSYS; if (!runtime->avail && !timeout) @@ -1621,20 +1609,9 @@ static int snd_rawmidi_dev_register(struct snd_device *device) static int snd_rawmidi_dev_disconnect(struct snd_device *device) { struct snd_rawmidi *rmidi = device->device_data; - int dir; mutex_lock(®ister_mutex); - mutex_lock(&rmidi->open_mutex); - wake_up(&rmidi->open_wait); list_del_init(&rmidi->list); - for (dir = 0; dir < 2; dir++) { - struct snd_rawmidi_substream *s; - list_for_each_entry(s, &rmidi->streams[dir].substreams, list) { - if (s->runtime) - wake_up(&s->runtime->sleep); - } - } - #ifdef CONFIG_SND_OSSEMUL if (rmidi->ossreg) { if ((int)rmidi->device == midi_map[rmidi->card->number]) { @@ -1649,7 +1626,6 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) } #endif /* CONFIG_SND_OSSEMUL */ snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); - mutex_unlock(&rmidi->open_mutex); mutex_unlock(®ister_mutex); return 0; } diff --git a/trunk/sound/core/sound.c b/trunk/sound/core/sound.c index 89780c323f19..643976000ce8 100644 --- a/trunk/sound/core/sound.c +++ b/trunk/sound/core/sound.c @@ -98,10 +98,6 @@ static void snd_request_other(int minor) * * Checks that a minor device with the specified type is registered, and returns * its user data pointer. - * - * This function increments the reference counter of the card instance - * if an associated instance with the given minor number and type is found. - * The caller must call snd_card_unref() appropriately later. */ void *snd_lookup_minor_data(unsigned int minor, int type) { @@ -112,11 +108,9 @@ void *snd_lookup_minor_data(unsigned int minor, int type) return NULL; mutex_lock(&sound_mutex); mreg = snd_minors[minor]; - if (mreg && mreg->type == type) { + if (mreg && mreg->type == type) private_data = mreg->private_data; - if (mreg->card_ptr) - atomic_inc(&mreg->card_ptr->refcount); - } else + else private_data = NULL; mutex_unlock(&sound_mutex); return private_data; @@ -281,7 +275,6 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev, preg->device = dev; preg->f_ops = f_ops; preg->private_data = private_data; - preg->card_ptr = card; mutex_lock(&sound_mutex); #ifdef CONFIG_SND_DYNAMIC_MINORS minor = snd_find_free_minor(type); diff --git a/trunk/sound/core/sound_oss.c b/trunk/sound/core/sound_oss.c index e1d79ee35906..e9528333e36d 100644 --- a/trunk/sound/core/sound_oss.c +++ b/trunk/sound/core/sound_oss.c @@ -40,9 +40,6 @@ static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS]; static DEFINE_MUTEX(sound_oss_mutex); -/* NOTE: This function increments the refcount of the associated card like - * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately - */ void *snd_lookup_oss_minor_data(unsigned int minor, int type) { struct snd_minor *mreg; @@ -52,11 +49,9 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) return NULL; mutex_lock(&sound_oss_mutex); mreg = snd_oss_minors[minor]; - if (mreg && mreg->type == type) { + if (mreg && mreg->type == type) private_data = mreg->private_data; - if (mreg->card_ptr) - atomic_inc(&mreg->card_ptr->refcount); - } else + else private_data = NULL; mutex_unlock(&sound_oss_mutex); return private_data; @@ -128,7 +123,6 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, preg->device = dev; preg->f_ops = f_ops; preg->private_data = private_data; - preg->card_ptr = card; mutex_lock(&sound_oss_mutex); snd_oss_minors[minor] = preg; minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); diff --git a/trunk/sound/pci/hda/patch_sigmatel.c b/trunk/sound/pci/hda/patch_sigmatel.c index 9ba8af056170..770013ff556f 100644 --- a/trunk/sound/pci/hda/patch_sigmatel.c +++ b/trunk/sound/pci/hda/patch_sigmatel.c @@ -1763,8 +1763,6 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { "HP", STAC_HP_ZEPHYR), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3660, "HP Mini", STAC_92HD83XXX_HP_LED), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x144E, - "HP Pavilion dv5", STAC_92HD83XXX_HP_INV_LED), {} /* terminator */ }; diff --git a/trunk/sound/pci/ice1712/ice1724.c b/trunk/sound/pci/ice1712/ice1724.c index 245d874891ba..3050a5279253 100644 --- a/trunk/sound/pci/ice1712/ice1724.c +++ b/trunk/sound/pci/ice1712/ice1724.c @@ -2859,12 +2859,7 @@ static int snd_vt1724_resume(struct device *dev) ice->set_spdif_clock(ice, 0); } else { /* internal on-card clock */ - int rate; - if (ice->cur_rate) - rate = ice->cur_rate; - else - rate = ice->pro_rate_default; - snd_vt1724_set_pro_rate(ice, rate, 1); + snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); } update_spdif_bits(ice, ice->pm_saved_spdif_ctrl); diff --git a/trunk/sound/soc/omap/omap-dmic.c b/trunk/sound/soc/omap/omap-dmic.c index 5a6aeaf552a8..68f2cd1a9206 100644 --- a/trunk/sound/soc/omap/omap-dmic.c +++ b/trunk/sound/soc/omap/omap-dmic.c @@ -464,9 +464,9 @@ static __devinit int asoc_dmic_probe(struct platform_device *pdev) mutex_init(&dmic->mutex); - dmic->fclk = clk_get(dmic->dev, "fck"); + dmic->fclk = clk_get(dmic->dev, "dmic_fck"); if (IS_ERR(dmic->fclk)) { - dev_err(dmic->dev, "cant get fck\n"); + dev_err(dmic->dev, "cant get dmic_fck\n"); return -ENODEV; } diff --git a/trunk/sound/soc/omap/zoom2.c b/trunk/sound/soc/omap/zoom2.c index 1ff6bb9ade5c..677b567935f8 100644 --- a/trunk/sound/soc/omap/zoom2.c +++ b/trunk/sound/soc/omap/zoom2.c @@ -21,14 +21,15 @@ #include #include -#include #include #include #include #include +#include +#include +#include #include -#include /* Register descriptions for twl4030 codec part */ #include diff --git a/trunk/sound/usb/card.c b/trunk/sound/usb/card.c index 282f0fc9fed1..561bb74fd364 100644 --- a/trunk/sound/usb/card.c +++ b/trunk/sound/usb/card.c @@ -339,7 +339,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, } mutex_init(&chip->mutex); - init_rwsem(&chip->shutdown_rwsem); + mutex_init(&chip->shutdown_mutex); chip->index = idx; chip->dev = dev; chip->card = card; @@ -560,7 +560,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, card = chip->card; mutex_lock(®ister_mutex); - down_write(&chip->shutdown_rwsem); + mutex_lock(&chip->shutdown_mutex); chip->shutdown = 1; chip->num_interfaces--; if (chip->num_interfaces <= 0) { @@ -582,11 +582,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, snd_usb_mixer_disconnect(p); } usb_chip[chip->index] = NULL; - up_write(&chip->shutdown_rwsem); + mutex_unlock(&chip->shutdown_mutex); mutex_unlock(®ister_mutex); snd_card_free_when_closed(card); } else { - up_write(&chip->shutdown_rwsem); + mutex_unlock(&chip->shutdown_mutex); mutex_unlock(®ister_mutex); } } @@ -618,20 +618,16 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) { int err = -ENODEV; - down_read(&chip->shutdown_rwsem); if (!chip->shutdown && !chip->probing) err = usb_autopm_get_interface(chip->pm_intf); - up_read(&chip->shutdown_rwsem); return err; } void snd_usb_autosuspend(struct snd_usb_audio *chip) { - down_read(&chip->shutdown_rwsem); if (!chip->shutdown && !chip->probing) usb_autopm_put_interface(chip->pm_intf); - up_read(&chip->shutdown_rwsem); } static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) diff --git a/trunk/sound/usb/card.h b/trunk/sound/usb/card.h index 814cb357ff88..afa4f9e9b27a 100644 --- a/trunk/sound/usb/card.h +++ b/trunk/sound/usb/card.h @@ -126,7 +126,6 @@ struct snd_usb_substream { struct snd_usb_endpoint *sync_endpoint; unsigned long flags; bool need_setup_ep; /* (re)configure EP at prepare? */ - unsigned int speed; /* USB_SPEED_XXX */ u64 formats; /* format bitmasks (all or'ed) */ unsigned int num_formats; /* number of supported audio formats (list) */ diff --git a/trunk/sound/usb/mixer.c b/trunk/sound/usb/mixer.c index 298070e8f2d4..fe56c9da38e9 100644 --- a/trunk/sound/usb/mixer.c +++ b/trunk/sound/usb/mixer.c @@ -287,32 +287,25 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v unsigned char buf[2]; int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; int timeout = 10; - int idx = 0, err; + int err; err = snd_usb_autoresume(cval->mixer->chip); if (err < 0) return -EIO; - down_read(&chip->shutdown_rwsem); while (timeout-- > 0) { - if (chip->shutdown) - break; - idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, idx, buf, val_len) >= val_len) { + validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), + buf, val_len) >= val_len) { *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); - err = 0; - goto out; + snd_usb_autosuspend(cval->mixer->chip); + return 0; } } - snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", - request, validx, idx, cval->val_type); - err = -EINVAL; - - out: - up_read(&chip->shutdown_rwsem); snd_usb_autosuspend(cval->mixer->chip); - return err; + snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", + request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); + return -EINVAL; } static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) @@ -320,7 +313,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v struct snd_usb_audio *chip = cval->mixer->chip; unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ unsigned char *val; - int idx = 0, ret, size; + int ret, size; __u8 bRequest; if (request == UAC_GET_CUR) { @@ -337,22 +330,16 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v if (ret) goto error; - down_read(&chip->shutdown_rwsem); - if (chip->shutdown) - ret = -ENODEV; - else { - idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); - ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, + ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, idx, buf, size); - } - up_read(&chip->shutdown_rwsem); + validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), + buf, size); snd_usb_autosuspend(chip); if (ret < 0) { error: snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", - request, validx, idx, cval->val_type); + request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); return ret; } @@ -430,7 +417,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, { struct snd_usb_audio *chip = cval->mixer->chip; unsigned char buf[2]; - int idx = 0, val_len, err, timeout = 10; + int val_len, err, timeout = 10; if (cval->mixer->protocol == UAC_VERSION_1) { val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; @@ -453,27 +440,19 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, err = snd_usb_autoresume(chip); if (err < 0) return -EIO; - down_read(&chip->shutdown_rwsem); - while (timeout-- > 0) { - if (chip->shutdown) - break; - idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); + while (timeout-- > 0) if (snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - validx, idx, buf, val_len) >= 0) { - err = 0; - goto out; + validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), + buf, val_len) >= 0) { + snd_usb_autosuspend(chip); + return 0; } - } - snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", - request, validx, idx, cval->val_type, buf[0], buf[1]); - err = -EINVAL; - - out: - up_read(&chip->shutdown_rwsem); snd_usb_autosuspend(chip); - return err; + snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", + request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); + return -EINVAL; } static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) diff --git a/trunk/sound/usb/mixer_quirks.c b/trunk/sound/usb/mixer_quirks.c index ae2b71435220..690000db0ec0 100644 --- a/trunk/sound/usb/mixer_quirks.c +++ b/trunk/sound/usb/mixer_quirks.c @@ -283,11 +283,6 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e if (value > 1) return -EINVAL; changed = value != mixer->audigy2nx_leds[index]; - down_read(&mixer->chip->shutdown_rwsem); - if (mixer->chip->shutdown) { - err = -ENODEV; - goto out; - } if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) err = snd_usb_ctl_msg(mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, @@ -304,8 +299,6 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, value, index + 2, NULL, 0); - out: - up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; mixer->audigy2nx_leds[index] = value; @@ -399,16 +392,11 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, for (i = 0; jacks[i].name; ++i) { snd_iprintf(buffer, "%s: ", jacks[i].name); - down_read(&mixer->chip->shutdown_rwsem); - if (mixer->chip->shutdown) - err = 0; - else - err = snd_usb_ctl_msg(mixer->chip->dev, + err = snd_usb_ctl_msg(mixer->chip->dev, usb_rcvctrlpipe(mixer->chip->dev, 0), UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, jacks[i].unitid << 8, buf, 3); - up_read(&mixer->chip->shutdown_rwsem); if (err == 3 && (buf[0] == 3 || buf[0] == 6)) snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); else @@ -438,15 +426,10 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, else new_status = old_status & ~0x02; changed = new_status != old_status; - down_read(&mixer->chip->shutdown_rwsem); - if (mixer->chip->shutdown) - err = -ENODEV; - else - err = snd_usb_ctl_msg(mixer->chip->dev, + err = snd_usb_ctl_msg(mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0), 0x08, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, 50, 0, &new_status, 1); - up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; mixer->xonar_u1_status = new_status; @@ -485,17 +468,11 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, u8 bRequest = (kcontrol->private_value >> 16) & 0xff; u16 wIndex = kcontrol->private_value & 0xffff; u8 tmp; - int ret; - down_read(&mixer->chip->shutdown_rwsem); - if (mixer->chip->shutdown) - ret = -ENODEV; - else - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, + int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0, cpu_to_le16(wIndex), &tmp, sizeof(tmp), 1000); - up_read(&mixer->chip->shutdown_rwsem); if (ret < 0) { snd_printk(KERN_ERR @@ -516,17 +493,11 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, u8 bRequest = (kcontrol->private_value >> 16) & 0xff; u16 wIndex = kcontrol->private_value & 0xffff; u16 wValue = ucontrol->value.integer.value[0]; - int ret; - down_read(&mixer->chip->shutdown_rwsem); - if (mixer->chip->shutdown) - ret = -ENODEV; - else - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, + int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, cpu_to_le16(wValue), cpu_to_le16(wIndex), NULL, 0, 1000); - up_read(&mixer->chip->shutdown_rwsem); if (ret < 0) { snd_printk(KERN_ERR @@ -685,16 +656,11 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, return -EINVAL; - down_read(&mixer->chip->shutdown_rwsem); - if (mixer->chip->shutdown) - err = -ENODEV; - else - err = snd_usb_ctl_msg(chip->dev, + err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), value, val_len); - up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; @@ -737,16 +703,11 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, if (!pval->is_cached) { /* Read current value */ - down_read(&mixer->chip->shutdown_rwsem); - if (mixer->chip->shutdown) - err = -ENODEV; - else - err = snd_usb_ctl_msg(chip->dev, + err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), value, val_len); - up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; @@ -758,16 +719,11 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, if (cur_val != new_val) { value[0] = new_val; value[1] = 0; - down_read(&mixer->chip->shutdown_rwsem); - if (mixer->chip->shutdown) - err = -ENODEV; - else - err = snd_usb_ctl_msg(chip->dev, + err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), value, val_len); - up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; diff --git a/trunk/sound/usb/pcm.c b/trunk/sound/usb/pcm.c index 37428f74dbb6..55e19e1b80ec 100644 --- a/trunk/sound/usb/pcm.c +++ b/trunk/sound/usb/pcm.c @@ -71,8 +71,6 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream unsigned int hwptr_done; subs = (struct snd_usb_substream *)substream->runtime->private_data; - if (subs->stream->chip->shutdown) - return SNDRV_PCM_POS_XRUN; spin_lock(&subs->lock); hwptr_done = subs->hwptr_done; substream->runtime->delay = snd_usb_pcm_delay(subs, @@ -446,6 +444,7 @@ static int configure_endpoint(struct snd_usb_substream *subs) { int ret; + mutex_lock(&subs->stream->chip->shutdown_mutex); /* format changed */ stop_endpoints(subs, 0, 0, 0); ret = snd_usb_endpoint_set_params(subs->data_endpoint, @@ -456,7 +455,7 @@ static int configure_endpoint(struct snd_usb_substream *subs) subs->cur_audiofmt, subs->sync_endpoint); if (ret < 0) - return ret; + goto unlock; if (subs->sync_endpoint) ret = snd_usb_endpoint_set_params(subs->data_endpoint, @@ -466,6 +465,9 @@ static int configure_endpoint(struct snd_usb_substream *subs) subs->cur_rate, subs->cur_audiofmt, NULL); + +unlock: + mutex_unlock(&subs->stream->chip->shutdown_mutex); return ret; } @@ -503,13 +505,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - down_read(&subs->stream->chip->shutdown_rwsem); - if (subs->stream->chip->shutdown) - ret = -ENODEV; - else - ret = set_format(subs, fmt); - up_read(&subs->stream->chip->shutdown_rwsem); - if (ret < 0) + if ((ret = set_format(subs, fmt)) < 0) return ret; subs->interface = fmt->iface; @@ -531,12 +527,10 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) subs->cur_audiofmt = NULL; subs->cur_rate = 0; subs->period_bytes = 0; - down_read(&subs->stream->chip->shutdown_rwsem); - if (!subs->stream->chip->shutdown) { - stop_endpoints(subs, 0, 1, 1); - deactivate_endpoints(subs); - } - up_read(&subs->stream->chip->shutdown_rwsem); + mutex_lock(&subs->stream->chip->shutdown_mutex); + stop_endpoints(subs, 0, 1, 1); + deactivate_endpoints(subs); + mutex_unlock(&subs->stream->chip->shutdown_mutex); return snd_pcm_lib_free_vmalloc_buffer(substream); } @@ -558,19 +552,12 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) return -ENXIO; } - down_read(&subs->stream->chip->shutdown_rwsem); - if (subs->stream->chip->shutdown) { - ret = -ENODEV; - goto unlock; - } - if (snd_BUG_ON(!subs->data_endpoint)) { - ret = -EIO; - goto unlock; - } + if (snd_BUG_ON(!subs->data_endpoint)) + return -EIO; ret = set_format(subs, subs->cur_audiofmt); if (ret < 0) - goto unlock; + return ret; iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; @@ -580,12 +567,12 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) subs->cur_audiofmt, subs->cur_rate); if (ret < 0) - goto unlock; + return ret; if (subs->need_setup_ep) { ret = configure_endpoint(subs); if (ret < 0) - goto unlock; + return ret; subs->need_setup_ep = false; } @@ -605,11 +592,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) /* for playback, submit the URBs now; otherwise, the first hwptr_done * updates for all URBs would happen at the same time when starting */ if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) - ret = start_endpoints(subs, 1); + return start_endpoints(subs, 1); - unlock: - up_read(&subs->stream->chip->shutdown_rwsem); - return ret; + return 0; } static struct snd_pcm_hardware snd_usb_hardware = @@ -662,7 +647,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs, return 0; } /* check whether the period time is >= the data packet interval */ - if (subs->speed != USB_SPEED_FULL) { + if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) { ptime = 125 * (1 << fp->datainterval); if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); @@ -940,7 +925,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre return err; param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; - if (subs->speed == USB_SPEED_FULL) + if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) /* full speed devices have fixed data packet interval */ ptmin = 1000; if (ptmin == 1000) diff --git a/trunk/sound/usb/proc.c b/trunk/sound/usb/proc.c index d218f763501f..ebc1a5b5b3f1 100644 --- a/trunk/sound/usb/proc.c +++ b/trunk/sound/usb/proc.c @@ -108,7 +108,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s } snd_iprintf(buffer, "\n"); } - if (subs->speed != USB_SPEED_FULL) + if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) snd_iprintf(buffer, " Data packet interval: %d us\n", 125 * (1 << fp->datainterval)); // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); @@ -124,7 +124,7 @@ static void proc_dump_ep_status(struct snd_usb_substream *subs, return; snd_iprintf(buffer, " Packet Size = %d\n", ep->curpacksize); snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n", - subs->speed == USB_SPEED_FULL + snd_usb_get_speed(subs->dev) == USB_SPEED_FULL ? get_full_speed_hz(ep->freqm) : get_high_speed_hz(ep->freqm), ep->freqm >> 16, ep->freqm & 0xffff); diff --git a/trunk/sound/usb/stream.c b/trunk/sound/usb/stream.c index 1de0c8c002a8..083ed81160e5 100644 --- a/trunk/sound/usb/stream.c +++ b/trunk/sound/usb/stream.c @@ -90,7 +90,6 @@ static void snd_usb_init_substream(struct snd_usb_stream *as, subs->direction = stream; subs->dev = as->chip->dev; subs->txfr_quirk = as->chip->txfr_quirk; - subs->speed = snd_usb_get_speed(subs->dev); snd_usb_set_pcm_ops(as->pcm, stream); diff --git a/trunk/sound/usb/usbaudio.h b/trunk/sound/usb/usbaudio.h index ef42797f56fb..b8233ebe250f 100644 --- a/trunk/sound/usb/usbaudio.h +++ b/trunk/sound/usb/usbaudio.h @@ -37,7 +37,7 @@ struct snd_usb_audio { struct usb_interface *pm_intf; u32 usb_id; struct mutex mutex; - struct rw_semaphore shutdown_rwsem; + struct mutex shutdown_mutex; unsigned int shutdown:1; unsigned int probing:1; unsigned int autosuspended:1; diff --git a/trunk/tools/testing/ktest/ktest.pl b/trunk/tools/testing/ktest/ktest.pl index c7ba7614061b..b51d787176d3 100755 --- a/trunk/tools/testing/ktest/ktest.pl +++ b/trunk/tools/testing/ktest/ktest.pl @@ -1740,10 +1740,8 @@ sub install { open(IN, "$output_config") or dodie("Can't read config file"); while () { if (/CONFIG_MODULES(=y)?/) { - if (defined($1)) { - $install_mods = 1; - last; - } + $install_mods = 1 if (defined($1)); + last; } } close(IN);