diff options
author | Arnd Bergmann <arnd@arndb.de> | 2012-04-30 23:49:49 +0200 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2012-04-30 23:53:58 +0200 |
commit | ca731a5da08926f669360342bcad50353fbe141a (patch) | |
tree | 670a546ca3accd4647d46a6b5c90a6b067fb7a0a | |
parent | 989b7135666c464d90e296752802b2f37d168588 (diff) | |
parent | c0af14d3212a54c6a11759cd6b78e755c68714a1 (diff) | |
download | blackbird-op-linux-ca731a5da08926f669360342bcad50353fbe141a.tar.gz blackbird-op-linux-ca731a5da08926f669360342bcad50353fbe141a.zip |
Merge branch 'ux500-gpio-pins-for-arm-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson into next/gpio
Linus Walleij <linus.walleij@linaro.org> writes:
This is a pull request for the GPIO and pin control stuff
accumulated in the ST-Ericsson tree. Here we have:
- Improvements and fixes and a custom pin config API from
Rabin Vincent
- Device Tree bindings from Lee Jones
- Some accumulated patches by yours truly.
- A MSP platform data init patch from Ola Lilja that is merged
here due to dependency on pin config work. It is to be
used with work being worked on in parallel in the ALSA
SoC subsystem.
If you wonder about the custom pin config implementation this
is to be used as a transition base as I am rewriting the
driver to use pinctrl. Expect a final pull request on top
of this one that will move the ux500 over to pinctrl.
* 'ux500-gpio-pins-for-arm-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson:
ARM: ux500: Add support for MSP I2S-devices
drivers/gpio: gpio-nomadik: Add support for irqdomains
drivers/gpio: gpio-nomadik: Apply Device Tree bindings
ARM: ux500: update pin handling
ARM: ux500: implement pin API
ARM: ux500: remove a bunch of internal pull-ups
plat-nomadik: new sleep mode pincfg macros
gpio/nomadik: use ioremap() instead of static mappings
gpio/nomadik: support low EMI mode
gpio/nomadik: fix spurious interrupts with SKE
gpio/nomadik: cache [rf]w?imsc
gpio/nomadik: don't set SLPM to 1 for non-wakeup pins
Also includes an update to v3.4-rc4.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
237 files changed, 2754 insertions, 1485 deletions
diff --git a/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml b/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml index 3fd3ce5df270..5274c24d11e0 100644 --- a/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml +++ b/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml @@ -1,6 +1,6 @@ <refentry id="V4L2-PIX-FMT-NV12M"> <refmeta> - <refentrytitle>V4L2_PIX_FMT_NV12M ('NV12M')</refentrytitle> + <refentrytitle>V4L2_PIX_FMT_NV12M ('NM12')</refentrytitle> &manvol; </refmeta> <refnamediv> diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml b/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml index 9957863daf18..60308f1eefdf 100644 --- a/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml +++ b/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml @@ -1,6 +1,6 @@ <refentry id="V4L2-PIX-FMT-YUV420M"> <refmeta> - <refentrytitle>V4L2_PIX_FMT_YUV420M ('YU12M')</refentrytitle> + <refentrytitle>V4L2_PIX_FMT_YUV420M ('YM12')</refentrytitle> &manvol; </refmeta> <refnamediv> diff --git a/MAINTAINERS b/MAINTAINERS index cf900fcd074b..99e1ba8bd054 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2321,9 +2321,9 @@ S: Supported F: drivers/acpi/dock.c DOCUMENTATION -M: Randy Dunlap <rdunlap@xenotime.net> +M: Rob Landley <rob@landley.net> L: linux-doc@vger.kernel.org -T: quilt http://xenotime.net/kernel-doc-patches/current/ +T: TBD S: Maintained F: Documentation/ @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = Saber-toothed Squirrel # *DOCUMENTATION* diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig index b5ac644e12af..6b31cb60daab 100644 --- a/arch/arm/configs/imx_v4_v5_defconfig +++ b/arch/arm/configs/imx_v4_v5_defconfig @@ -112,6 +112,7 @@ CONFIG_WATCHDOG=y CONFIG_IMX2_WDT=y CONFIG_MFD_MC13XXX=y CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_MC13783=y CONFIG_REGULATOR_MC13892=y CONFIG_FB=y diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 889d73ac1ae1..7e84f453e8a6 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -8,8 +8,6 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_LBDAF is not set # CONFIG_BLK_DEV_BSG is not set CONFIG_ARCH_U8500=y -CONFIG_UX500_SOC_DB5500=y -CONFIG_UX500_SOC_DB8500=y CONFIG_MACH_HREFV60=y CONFIG_MACH_SNOWBALL=y CONFIG_MACH_U5500=y @@ -39,7 +37,6 @@ CONFIG_CAIF=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=65536 -CONFIG_MISC_DEVICES=y CONFIG_AB8500_PWM=y CONFIG_SENSORS_BH1780=y CONFIG_NETDEVICES=y @@ -65,16 +62,18 @@ CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_NOMADIK=y -CONFIG_I2C=y -CONFIG_I2C_NOMADIK=y CONFIG_SPI=y CONFIG_SPI_PL022=y CONFIG_GPIO_STMPE=y CONFIG_GPIO_TC3589X=y +CONFIG_POWER_SUPPLY=y +CONFIG_AB8500_BM=y +CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL=y CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y CONFIG_AB5500_CORE=y CONFIG_AB8500_CORE=y +CONFIG_REGULATOR=y CONFIG_REGULATOR_AB8500=y # CONFIG_HID_SUPPORT is not set CONFIG_USB_GADGET=y diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 99ce5c955e39..05774e5b1cba 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -1173,7 +1173,6 @@ void __init at91_add_device_serial(void) printk(KERN_INFO "AT91: No default serial console defined.\n"); } #else -void __init __deprecated at91_init_serial(struct at91_uart_config *config) {} void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {} void __init at91_set_serial_console(unsigned portnr) {} void __init at91_add_device_serial(void) {} diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c index dd7f782b0b91..104ca40d8d18 100644 --- a/arch/arm/mach-at91/at91rm9200_time.c +++ b/arch/arm/mach-at91/at91rm9200_time.c @@ -23,6 +23,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/clockchips.h> +#include <linux/export.h> #include <asm/mach/time.h> @@ -176,6 +177,7 @@ static struct clock_event_device clkevt = { }; void __iomem *at91_st_base; +EXPORT_SYMBOL_GPL(at91_st_base); void __init at91rm9200_ioremap_st(u32 addr) { diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c index 11cbaa8946fe..b2e4fe21f346 100644 --- a/arch/arm/mach-at91/board-rm9200ek.c +++ b/arch/arm/mach-at91/board-rm9200ek.c @@ -117,7 +117,7 @@ static struct i2c_board_info __initdata ek_i2c_devices[] = { }; #define EK_FLASH_BASE AT91_CHIPSELECT_0 -#define EK_FLASH_SIZE SZ_2M +#define EK_FLASH_SIZE SZ_8M static struct physmap_flash_data ek_flash_data = { .width = 2, diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index c3f994462864..065fed342424 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -85,8 +85,6 @@ static struct resource dm9000_resource[] = { .flags = IORESOURCE_MEM }, [2] = { - .start = AT91_PIN_PC11, - .end = AT91_PIN_PC11, .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE, } @@ -130,6 +128,8 @@ static struct sam9_smc_config __initdata dm9000_smc_config = { static void __init ek_add_device_dm9000(void) { + struct resource *r = &dm9000_resource[2]; + /* Configure chip-select 2 (DM9000) */ sam9_smc_configure(0, 2, &dm9000_smc_config); @@ -139,6 +139,7 @@ static void __init ek_add_device_dm9000(void) /* Configure Interrupt pin as input, no pull-up */ at91_set_gpio_input(AT91_PIN_PC11, 0); + r->start = r->end = gpio_to_irq(AT91_PIN_PC11); platform_device_register(&dm9000_device); } #else diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index a0f4d7424cdc..6b692824c988 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -35,6 +35,7 @@ #include "generic.h" void __iomem *at91_pmc_base; +EXPORT_SYMBOL_GPL(at91_pmc_base); /* * There's a lot more which can be done with clocks, including cpufreq diff --git a/arch/arm/mach-at91/include/mach/at91_pmc.h b/arch/arm/mach-at91/include/mach/at91_pmc.h index 36604782a78f..ea2c57a86ca6 100644 --- a/arch/arm/mach-at91/include/mach/at91_pmc.h +++ b/arch/arm/mach-at91/include/mach/at91_pmc.h @@ -25,7 +25,7 @@ extern void __iomem *at91_pmc_base; #define at91_pmc_write(field, value) \ __raw_writel(value, at91_pmc_base + field) #else -.extern at91_aic_base +.extern at91_pmc_base #endif #define AT91_PMC_SCER 0x00 /* System Clock Enable Register */ diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 97cc04dc8073..f44a2e7272e3 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -54,6 +54,7 @@ void __init at91_init_interrupts(unsigned int *priority) } void __iomem *at91_ramc_base[2]; +EXPORT_SYMBOL_GPL(at91_ramc_base); void __init at91_ioremap_ramc(int id, u32 addr, u32 size) { @@ -292,6 +293,7 @@ void __init at91_ioremap_rstc(u32 base_addr) } void __iomem *at91_matrix_base; +EXPORT_SYMBOL_GPL(at91_matrix_base); void __init at91_ioremap_matrix(u32 base_addr) { diff --git a/arch/arm/mach-bcmring/core.c b/arch/arm/mach-bcmring/core.c index 22e4e0a28ad1..adbfb1994582 100644 --- a/arch/arm/mach-bcmring/core.c +++ b/arch/arm/mach-bcmring/core.c @@ -52,8 +52,8 @@ #include <mach/csp/chipcHw_inline.h> #include <mach/csp/tmrHw_reg.h> -static AMBA_APB_DEVICE(uartA, "uarta", MM_ADDR_IO_UARTA, { IRQ_UARTA }, NULL); -static AMBA_APB_DEVICE(uartB, "uartb", MM_ADDR_IO_UARTB, { IRQ_UARTB }, NULL); +static AMBA_APB_DEVICE(uartA, "uartA", 0, MM_ADDR_IO_UARTA, {IRQ_UARTA}, NULL); +static AMBA_APB_DEVICE(uartB, "uartB", 0, MM_ADDR_IO_UARTB, {IRQ_UARTB}, NULL); static struct clk pll1_clk = { .name = "PLL1", diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c index 861ceb8232d6..ed38d03c61f2 100644 --- a/arch/arm/mach-imx/imx27-dt.c +++ b/arch/arm/mach-imx/imx27-dt.c @@ -35,7 +35,7 @@ static const struct of_dev_auxdata imx27_auxdata_lookup[] __initconst = { static int __init imx27_avic_add_irq_domain(struct device_node *np, struct device_node *interrupt_parent) { - irq_domain_add_simple(np, 0); + irq_domain_add_legacy(np, 64, 0, 0, &irq_domain_simple_ops, NULL); return 0; } @@ -44,7 +44,9 @@ static int __init imx27_gpio_add_irq_domain(struct device_node *np, { static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS; - irq_domain_add_simple(np, gpio_irq_base); + gpio_irq_base -= 32; + irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, + NULL); return 0; } diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c index 05250aed61fb..e10f3914fcfe 100644 --- a/arch/arm/mach-imx/mm-imx5.c +++ b/arch/arm/mach-imx/mm-imx5.c @@ -35,7 +35,7 @@ static void imx5_idle(void) } clk_enable(gpc_dvfs_clk); mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); - if (tzic_enable_wake() != 0) + if (!tzic_enable_wake()) cpu_do_idle(); clk_disable(gpc_dvfs_clk); } diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c index 087dba0df47e..e9cc52d4cb28 100644 --- a/arch/arm/mach-omap1/mux.c +++ b/arch/arm/mach-omap1/mux.c @@ -27,6 +27,7 @@ #include <linux/io.h> #include <linux/spinlock.h> +#include <mach/hardware.h> #include <plat/mux.h> diff --git a/arch/arm/mach-omap1/timer.c b/arch/arm/mach-omap1/timer.c index 6e90665a7c47..fb202af01d0d 100644 --- a/arch/arm/mach-omap1/timer.c +++ b/arch/arm/mach-omap1/timer.c @@ -47,9 +47,9 @@ static int omap1_dm_timer_set_src(struct platform_device *pdev, int n = (pdev->id - 1) << 1; u32 l; - l = __raw_readl(MOD_CONF_CTRL_1) & ~(0x03 << n); + l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n); l |= source << n; - __raw_writel(l, MOD_CONF_CTRL_1); + omap_writel(l, MOD_CONF_CTRL_1); return 0; } diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index a39fc4bbd2b8..130ab00c09a2 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -20,6 +20,7 @@ #include <linux/usb/otg.h> #include <linux/spi/spi.h> #include <linux/i2c/twl.h> +#include <linux/mfd/twl6040.h> #include <linux/gpio_keys.h> #include <linux/regulator/machine.h> #include <linux/regulator/fixed.h> @@ -560,7 +561,7 @@ static struct regulator_init_data sdp4430_vusim = { }, }; -static struct twl4030_codec_data twl6040_codec = { +static struct twl6040_codec_data twl6040_codec = { /* single-step ramp for headset and handsfree */ .hs_left_step = 0x0f, .hs_right_step = 0x0f, @@ -568,7 +569,7 @@ static struct twl4030_codec_data twl6040_codec = { .hf_right_step = 0x1d, }; -static struct twl4030_vibra_data twl6040_vibra = { +static struct twl6040_vibra_data twl6040_vibra = { .vibldrv_res = 8, .vibrdrv_res = 3, .viblmotor_res = 10, @@ -577,16 +578,14 @@ static struct twl4030_vibra_data twl6040_vibra = { .vddvibr_uV = 0, /* fixed volt supply - VBAT */ }; -static struct twl4030_audio_data twl6040_audio = { +static struct twl6040_platform_data twl6040_data = { .codec = &twl6040_codec, .vibra = &twl6040_vibra, .audpwron_gpio = 127, - .naudint_irq = OMAP44XX_IRQ_SYS_2N, .irq_base = TWL6040_CODEC_IRQ_BASE, }; static struct twl4030_platform_data sdp4430_twldata = { - .audio = &twl6040_audio, /* Regulators */ .vusim = &sdp4430_vusim, .vaux1 = &sdp4430_vaux1, @@ -617,7 +616,8 @@ static int __init omap4_i2c_init(void) TWL_COMMON_REGULATOR_VCXIO | TWL_COMMON_REGULATOR_VUSB | TWL_COMMON_REGULATOR_CLK32KG); - omap4_pmic_init("twl6030", &sdp4430_twldata); + omap4_pmic_init("twl6030", &sdp4430_twldata, + &twl6040_data, OMAP44XX_IRQ_SYS_2N); omap_register_i2c_bus(2, 400, NULL, 0); omap_register_i2c_bus(3, 400, sdp4430_i2c_3_boardinfo, ARRAY_SIZE(sdp4430_i2c_3_boardinfo)); diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 74e1687b5170..098d183a0086 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -137,7 +137,7 @@ static struct twl4030_platform_data sdp4430_twldata = { static void __init omap4_i2c_init(void) { - omap4_pmic_init("twl6030", &sdp4430_twldata); + omap4_pmic_init("twl6030", &sdp4430_twldata, NULL, 0); } static void __init omap4_init(void) diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index d8c0e89f0126..1b782ba53433 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -25,6 +25,7 @@ #include <linux/gpio.h> #include <linux/usb/otg.h> #include <linux/i2c/twl.h> +#include <linux/mfd/twl6040.h> #include <linux/regulator/machine.h> #include <linux/regulator/fixed.h> #include <linux/wl12xx.h> @@ -284,7 +285,7 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers) return 0; } -static struct twl4030_codec_data twl6040_codec = { +static struct twl6040_codec_data twl6040_codec = { /* single-step ramp for headset and handsfree */ .hs_left_step = 0x0f, .hs_right_step = 0x0f, @@ -292,17 +293,14 @@ static struct twl4030_codec_data twl6040_codec = { .hf_right_step = 0x1d, }; -static struct twl4030_audio_data twl6040_audio = { +static struct twl6040_platform_data twl6040_data = { .codec = &twl6040_codec, .audpwron_gpio = 127, - .naudint_irq = OMAP44XX_IRQ_SYS_2N, .irq_base = TWL6040_CODEC_IRQ_BASE, }; /* Panda board uses the common PMIC configuration */ -static struct twl4030_platform_data omap4_panda_twldata = { - .audio = &twl6040_audio, -}; +static struct twl4030_platform_data omap4_panda_twldata; /* * Display monitor features are burnt in their EEPROM as EDID data. The EEPROM @@ -326,7 +324,8 @@ static int __init omap4_panda_i2c_init(void) TWL_COMMON_REGULATOR_VCXIO | TWL_COMMON_REGULATOR_VUSB | TWL_COMMON_REGULATOR_CLK32KG); - omap4_pmic_init("twl6030", &omap4_panda_twldata); + omap4_pmic_init("twl6030", &omap4_panda_twldata, + &twl6040_data, OMAP44XX_IRQ_SYS_2N); omap_register_i2c_bus(2, 400, NULL, 0); /* * Bus 3 is attached to the DVI port where devices like the pico DLP diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 2c27fdb61e66..7144ae651d3d 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1422,6 +1422,9 @@ static int _ocp_softreset(struct omap_hwmod *oh) goto dis_opt_clks; _write_sysconfig(v, oh); + if (oh->class->sysc->srst_udelay) + udelay(oh->class->sysc->srst_udelay); + if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS) omap_test_timeout((omap_hwmod_read(oh, oh->class->sysc->syss_offs) @@ -1903,10 +1906,20 @@ void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs) */ int omap_hwmod_softreset(struct omap_hwmod *oh) { - if (!oh) + u32 v; + int ret; + + if (!oh || !(oh->_sysc_cache)) return -EINVAL; - return _ocp_softreset(oh); + v = oh->_sysc_cache; + ret = _set_softreset(oh, &v); + if (ret) + goto error; + _write_sysconfig(v, oh); + +error: + return ret; } /** diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index a5409ce3f323..a6bde34e443a 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -1000,7 +1000,6 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__dss_venc = { .flags = OMAP_FIREWALL_L4, } }, - .flags = OCPIF_SWSUP_IDLE, .user = OCP_USER_MPU | OCP_USER_SDMA, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index c4f56cb60d7d..04a3885f4475 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -1049,7 +1049,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__dss_venc = { .slave = &omap2430_dss_venc_hwmod, .clk = "dss_ick", .addr = omap2_dss_venc_addrs, - .flags = OCPIF_SWSUP_IDLE, .user = OCP_USER_MPU | OCP_USER_SDMA, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 34b9766d1d23..db86ce90c69f 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1676,7 +1676,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_venc = { .flags = OMAP_FIREWALL_L4, } }, - .flags = OCPIF_SWSUP_IDLE, .user = OCP_USER_MPU | OCP_USER_SDMA, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index cc9bd106a854..6abc75753e42 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -2594,6 +2594,15 @@ static struct omap_hwmod omap44xx_ipu_hwmod = { static struct omap_hwmod_class_sysconfig omap44xx_iss_sysc = { .rev_offs = 0x0000, .sysc_offs = 0x0010, + /* + * ISS needs 100 OCP clk cycles delay after a softreset before + * accessing sysconfig again. + * The lowest frequency at the moment for L3 bus is 100 MHz, so + * 1usec delay is needed. Add an x2 margin to be safe (2 usecs). + * + * TODO: Indicate errata when available. + */ + .srst_udelay = 2, .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 0cdd359a128e..9fc2f44188cb 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -108,8 +108,14 @@ static void omap_uart_set_noidle(struct platform_device *pdev) static void omap_uart_set_smartidle(struct platform_device *pdev) { struct omap_device *od = to_omap_device(pdev); + u8 idlemode; - omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_SMART); + if (od->hwmods[0]->class->sysc->idlemodes & SIDLE_SMART_WKUP) + idlemode = HWMOD_IDLEMODE_SMART_WKUP; + else + idlemode = HWMOD_IDLEMODE_SMART; + + omap_hwmod_set_slave_idlemode(od->hwmods[0], idlemode); } #else @@ -120,124 +126,8 @@ static void omap_uart_set_smartidle(struct platform_device *pdev) {} #endif /* CONFIG_PM */ #ifdef CONFIG_OMAP_MUX -static struct omap_device_pad default_uart1_pads[] __initdata = { - { - .name = "uart1_cts.uart1_cts", - .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, - }, - { - .name = "uart1_rts.uart1_rts", - .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, - }, - { - .name = "uart1_tx.uart1_tx", - .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, - }, - { - .name = "uart1_rx.uart1_rx", - .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, - .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, - .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, - }, -}; - -static struct omap_device_pad default_uart2_pads[] __initdata = { - { - .name = "uart2_cts.uart2_cts", - .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, - }, - { - .name = "uart2_rts.uart2_rts", - .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, - }, - { - .name = "uart2_tx.uart2_tx", - .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, - }, - { - .name = "uart2_rx.uart2_rx", - .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, - .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, - .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, - }, -}; - -static struct omap_device_pad default_uart3_pads[] __initdata = { - { - .name = "uart3_cts_rctx.uart3_cts_rctx", - .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, - }, - { - .name = "uart3_rts_sd.uart3_rts_sd", - .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, - }, - { - .name = "uart3_tx_irtx.uart3_tx_irtx", - .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, - }, - { - .name = "uart3_rx_irrx.uart3_rx_irrx", - .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, - .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0, - .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0, - }, -}; - -static struct omap_device_pad default_omap36xx_uart4_pads[] __initdata = { - { - .name = "gpmc_wait2.uart4_tx", - .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, - }, - { - .name = "gpmc_wait3.uart4_rx", - .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, - .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE2, - .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE2, - }, -}; - -static struct omap_device_pad default_omap4_uart4_pads[] __initdata = { - { - .name = "uart4_tx.uart4_tx", - .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, - }, - { - .name = "uart4_rx.uart4_rx", - .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, - .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0, - .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0, - }, -}; - static void omap_serial_fill_default_pads(struct omap_board_data *bdata) { - switch (bdata->id) { - case 0: - bdata->pads = default_uart1_pads; - bdata->pads_cnt = ARRAY_SIZE(default_uart1_pads); - break; - case 1: - bdata->pads = default_uart2_pads; - bdata->pads_cnt = ARRAY_SIZE(default_uart2_pads); - break; - case 2: - bdata->pads = default_uart3_pads; - bdata->pads_cnt = ARRAY_SIZE(default_uart3_pads); - break; - case 3: - if (cpu_is_omap44xx()) { - bdata->pads = default_omap4_uart4_pads; - bdata->pads_cnt = - ARRAY_SIZE(default_omap4_uart4_pads); - } else if (cpu_is_omap3630()) { - bdata->pads = default_omap36xx_uart4_pads; - bdata->pads_cnt = - ARRAY_SIZE(default_omap36xx_uart4_pads); - } - break; - default: - break; - } } #else static void omap_serial_fill_default_pads(struct omap_board_data *bdata) {} diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index 4b57757bf9d1..7a7b89304c48 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c @@ -37,6 +37,16 @@ static struct i2c_board_info __initdata pmic_i2c_board_info = { .flags = I2C_CLIENT_WAKE, }; +static struct i2c_board_info __initdata omap4_i2c1_board_info[] = { + { + .addr = 0x48, + .flags = I2C_CLIENT_WAKE, + }, + { + I2C_BOARD_INFO("twl6040", 0x4b), + }, +}; + void __init omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq, struct twl4030_platform_data *pmic_data) @@ -49,14 +59,31 @@ void __init omap_pmic_init(int bus, u32 clkrate, omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1); } +void __init omap4_pmic_init(const char *pmic_type, + struct twl4030_platform_data *pmic_data, + struct twl6040_platform_data *twl6040_data, int twl6040_irq) +{ + /* PMIC part*/ + strncpy(omap4_i2c1_board_info[0].type, pmic_type, + sizeof(omap4_i2c1_board_info[0].type)); + omap4_i2c1_board_info[0].irq = OMAP44XX_IRQ_SYS_1N; + omap4_i2c1_board_info[0].platform_data = pmic_data; + + /* TWL6040 audio IC part */ + omap4_i2c1_board_info[1].irq = twl6040_irq; + omap4_i2c1_board_info[1].platform_data = twl6040_data; + + omap_register_i2c_bus(1, 400, omap4_i2c1_board_info, 2); + +} + void __init omap_pmic_late_init(void) { /* Init the OMAP TWL parameters (if PMIC has been registerd) */ - if (!pmic_i2c_board_info.irq) - return; - - omap3_twl_init(); - omap4_twl_init(); + if (pmic_i2c_board_info.irq) + omap3_twl_init(); + if (omap4_i2c1_board_info[0].irq) + omap4_twl_init(); } #if defined(CONFIG_ARCH_OMAP3) diff --git a/arch/arm/mach-omap2/twl-common.h b/arch/arm/mach-omap2/twl-common.h index 275dde8cb27a..09627483a57f 100644 --- a/arch/arm/mach-omap2/twl-common.h +++ b/arch/arm/mach-omap2/twl-common.h @@ -29,6 +29,7 @@ struct twl4030_platform_data; +struct twl6040_platform_data; void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq, struct twl4030_platform_data *pmic_data); @@ -46,12 +47,9 @@ static inline void omap3_pmic_init(const char *pmic_type, omap_pmic_init(1, 2600, pmic_type, INT_34XX_SYS_NIRQ, pmic_data); } -static inline void omap4_pmic_init(const char *pmic_type, - struct twl4030_platform_data *pmic_data) -{ - /* Phoenix Audio IC needs I2C1 to start with 400 KHz or less */ - omap_pmic_init(1, 400, pmic_type, OMAP44XX_IRQ_SYS_1N, pmic_data); -} +void omap4_pmic_init(const char *pmic_type, + struct twl4030_platform_data *pmic_data, + struct twl6040_platform_data *audio_data, int twl6040_irq); void omap3_pmic_get_config(struct twl4030_platform_data *pmic_data, u32 pdata_flags, u32 regulators_flags); diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 880d02ec89d4..ef7099eea0f2 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -17,6 +17,7 @@ config UX500_SOC_DB5500 config UX500_SOC_DB8500 bool select MFD_DB8500_PRCMU + select REGULATOR select REGULATOR_DB8500_PRCMU select CPU_FREQ_TABLE if CPU_FREQ diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 465b9ec9510a..015932c6bf08 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -3,7 +3,7 @@ # obj-y := clock.o cpu.o devices.o devices-common.o \ - id.o usb.o timer.o + id.o pins.o usb.o timer.o obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o @@ -11,7 +11,8 @@ obj-$(CONFIG_MACH_MOP500) += board-mop500.o board-mop500-sdi.o \ board-mop500-regulators.o \ board-mop500-uib.o board-mop500-stuib.o \ board-mop500-u8500uib.o \ - board-mop500-pins.o + board-mop500-pins.o \ + board-mop500-msp.o obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c new file mode 100644 index 000000000000..c8f6300cb7d2 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-msp.c @@ -0,0 +1,250 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License (GPL), version 2 + */ + +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <plat/gpio-nomadik.h> + +#include <plat/pincfg.h> +#include <plat/ste_dma40.h> + +#include <mach/devices.h> +#include <ste-dma40-db8500.h> +#include <mach/hardware.h> +#include <mach/irqs.h> +#include <mach/msp.h> + +#include "board-mop500.h" +#include "devices-db8500.h" +#include "pins-db8500.h" + +/* MSP1/3 Tx/Rx usage protection */ +static DEFINE_SPINLOCK(msp_rxtx_lock); + +/* Reference Count */ +static int msp_rxtx_ref; + +static pin_cfg_t mop500_msp1_pins_init[] = { + GPIO33_MSP1_TXD | PIN_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE, + GPIO34_MSP1_TFS | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_DISABLE, + GPIO35_MSP1_TCK | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_DISABLE, + GPIO36_MSP1_RXD | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_DISABLE, +}; + +static pin_cfg_t mop500_msp1_pins_exit[] = { + GPIO33_MSP1_TXD | PIN_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE, + GPIO34_MSP1_TFS | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_ENABLE, + GPIO35_MSP1_TCK | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_ENABLE, + GPIO36_MSP1_RXD | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_ENABLE, +}; + +int msp13_i2s_init(void) +{ + int retval = 0; + unsigned long flags; + + spin_lock_irqsave(&msp_rxtx_lock, flags); + if (msp_rxtx_ref == 0) + retval = nmk_config_pins( + ARRAY_AND_SIZE(mop500_msp1_pins_init)); + if (!retval) + msp_rxtx_ref++; + spin_unlock_irqrestore(&msp_rxtx_lock, flags); + + return retval; +} + +int msp13_i2s_exit(void) +{ + int retval = 0; + unsigned long flags; + + spin_lock_irqsave(&msp_rxtx_lock, flags); + WARN_ON(!msp_rxtx_ref); + msp_rxtx_ref--; + if (msp_rxtx_ref == 0) + retval = nmk_config_pins_sleep( + ARRAY_AND_SIZE(mop500_msp1_pins_exit)); + spin_unlock_irqrestore(&msp_rxtx_lock, flags); + + return retval; +} + +static struct stedma40_chan_cfg msp0_dma_rx = { + .high_priority = true, + .dir = STEDMA40_PERIPH_TO_MEM, + + .src_dev_type = DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct stedma40_chan_cfg msp0_dma_tx = { + .high_priority = true, + .dir = STEDMA40_MEM_TO_PERIPH, + + .src_dev_type = STEDMA40_DEV_DST_MEMORY, + .dst_dev_type = DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct msp_i2s_platform_data msp0_platform_data = { + .id = MSP_I2S_0, + .msp_i2s_dma_rx = &msp0_dma_rx, + .msp_i2s_dma_tx = &msp0_dma_tx, +}; + +static struct stedma40_chan_cfg msp1_dma_rx = { + .high_priority = true, + .dir = STEDMA40_PERIPH_TO_MEM, + + .src_dev_type = DB8500_DMA_DEV30_MSP3_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct stedma40_chan_cfg msp1_dma_tx = { + .high_priority = true, + .dir = STEDMA40_MEM_TO_PERIPH, + + .src_dev_type = STEDMA40_DEV_DST_MEMORY, + .dst_dev_type = DB8500_DMA_DEV30_MSP1_TX, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct msp_i2s_platform_data msp1_platform_data = { + .id = MSP_I2S_1, + .msp_i2s_dma_rx = NULL, + .msp_i2s_dma_tx = &msp1_dma_tx, + .msp_i2s_init = msp13_i2s_init, + .msp_i2s_exit = msp13_i2s_exit, +}; + +static struct stedma40_chan_cfg msp2_dma_rx = { + .high_priority = true, + .dir = STEDMA40_PERIPH_TO_MEM, + + .src_dev_type = DB8500_DMA_DEV14_MSP2_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + + /* MSP2 DMA doesn't work with PSIZE == 4 on DB8500v2 */ + .src_info.psize = STEDMA40_PSIZE_LOG_1, + .dst_info.psize = STEDMA40_PSIZE_LOG_1, + + /* data_width is set during configuration */ +}; + +static struct stedma40_chan_cfg msp2_dma_tx = { + .high_priority = true, + .dir = STEDMA40_MEM_TO_PERIPH, + + .src_dev_type = STEDMA40_DEV_DST_MEMORY, + .dst_dev_type = DB8500_DMA_DEV14_MSP2_TX, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + .use_fixed_channel = true, + .phy_channel = 1, + + /* data_width is set during configuration */ +}; + +static int db8500_add_msp_i2s(struct device *parent, int id, + resource_size_t base, int irq, + struct msp_i2s_platform_data *pdata) +{ + struct platform_device *pdev; + struct resource res[] = { + DEFINE_RES_MEM(base, SZ_4K), + DEFINE_RES_IRQ(irq), + }; + + pr_info("Register platform-device 'ux500-msp-i2s', id %d, irq %d\n", + id, irq); + pdev = platform_device_register_resndata(parent, "ux500-msp-i2s", id, + res, ARRAY_SIZE(res), + pdata, sizeof(*pdata)); + if (!pdev) { + pr_err("Failed to register platform-device 'ux500-msp-i2s.%d'!\n", + id); + return -EIO; + } + + return 0; +} + +/* Platform device for ASoC U8500 machine */ +static struct platform_device snd_soc_u8500 = { + .name = "snd-soc-u8500", + .id = 0, + .dev = { + .platform_data = NULL, + }, +}; + +/* Platform device for Ux500-PCM */ +static struct platform_device ux500_pcm = { + .name = "ux500-pcm", + .id = 0, + .dev = { + .platform_data = NULL, + }, +}; + +static struct msp_i2s_platform_data msp2_platform_data = { + .id = MSP_I2S_2, + .msp_i2s_dma_rx = &msp2_dma_rx, + .msp_i2s_dma_tx = &msp2_dma_tx, +}; + +static struct msp_i2s_platform_data msp3_platform_data = { + .id = MSP_I2S_3, + .msp_i2s_dma_rx = &msp1_dma_rx, + .msp_i2s_dma_tx = NULL, + .msp_i2s_init = msp13_i2s_init, + .msp_i2s_exit = msp13_i2s_exit, +}; + +int mop500_msp_init(struct device *parent) +{ + int ret; + + pr_info("%s: Register platform-device 'snd-soc-u8500'.\n", __func__); + platform_device_register(&snd_soc_u8500); + + pr_info("Initialize MSP I2S-devices.\n"); + ret = db8500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, + &msp0_platform_data); + ret |= db8500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, + &msp1_platform_data); + ret |= db8500_add_msp_i2s(parent, 2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, + &msp2_platform_data); + ret |= db8500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, + &msp3_platform_data); + + pr_info("%s: Register platform-device 'ux500-pcm'\n", __func__); + platform_device_register(&ux500_pcm); + + return ret; +} diff --git a/arch/arm/mach-ux500/board-mop500-msp.h b/arch/arm/mach-ux500/board-mop500-msp.h new file mode 100644 index 000000000000..6fcfb5e2cc94 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-msp.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) ST-Ericsson SA 2012 + * + * Author: Ola Lilja <ola.o.lilja@stericsson.com>, + * for ST-Ericsson. + * + * License terms: + * + * 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. + */ + +void mop500_msp_init(struct device *parent); diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c index f5413dca532c..df5b190d331c 100644 --- a/arch/arm/mach-ux500/board-mop500-pins.c +++ b/arch/arm/mach-ux500/board-mop500-pins.c @@ -7,109 +7,47 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/bug.h> +#include <linux/string.h> #include <asm/mach-types.h> #include <plat/pincfg.h> #include <plat/gpio-nomadik.h> + #include <mach/hardware.h> #include "pins-db8500.h" +#include "pins.h" +#include "board-mop500.h" + +enum custom_pin_cfg_t { + PINS_FOR_DEFAULT, + PINS_FOR_U9500, +}; + +static enum custom_pin_cfg_t pinsfor; static pin_cfg_t mop500_pins_common[] = { - /* I2C */ - GPIO147_I2C0_SCL, - GPIO148_I2C0_SDA, - GPIO16_I2C1_SCL, - GPIO17_I2C1_SDA, - GPIO10_I2C2_SDA, - GPIO11_I2C2_SCL, - GPIO229_I2C3_SDA, - GPIO230_I2C3_SCL, - - /* MSP0 */ + /* uMSP0 */ GPIO12_MSP0_TXD, GPIO13_MSP0_TFS, GPIO14_MSP0_TCK, GPIO15_MSP0_RXD, /* MSP2: HDMI */ - GPIO193_MSP2_TXD, - GPIO194_MSP2_TCK, - GPIO195_MSP2_TFS, + GPIO193_MSP2_TXD | PIN_INPUT_PULLDOWN, + GPIO194_MSP2_TCK | PIN_INPUT_PULLDOWN, + GPIO195_MSP2_TFS | PIN_INPUT_PULLDOWN, GPIO196_MSP2_RXD | PIN_OUTPUT_LOW, + /* LCD TE0 */ + GPIO68_LCD_VSI0 | PIN_INPUT_PULLUP, + /* Touch screen INTERFACE */ GPIO84_GPIO | PIN_INPUT_PULLUP, /* TOUCH_INT1 */ /* STMPE1601/tc35893 keypad IRQ */ GPIO218_GPIO | PIN_INPUT_PULLUP, - /* MMC0 (MicroSD card) */ - GPIO18_MC0_CMDDIR | PIN_OUTPUT_HIGH, - GPIO19_MC0_DAT0DIR | PIN_OUTPUT_HIGH, - GPIO20_MC0_DAT2DIR | PIN_OUTPUT_HIGH, - - GPIO22_MC0_FBCLK | PIN_INPUT_NOPULL, - GPIO23_MC0_CLK | PIN_OUTPUT_LOW, - GPIO24_MC0_CMD | PIN_INPUT_PULLUP, - GPIO25_MC0_DAT0 | PIN_INPUT_PULLUP, - GPIO26_MC0_DAT1 | PIN_INPUT_PULLUP, - GPIO27_MC0_DAT2 | PIN_INPUT_PULLUP, - GPIO28_MC0_DAT3 | PIN_INPUT_PULLUP, - - /* SDI1 (SDIO) */ - GPIO208_MC1_CLK | PIN_OUTPUT_LOW, - GPIO209_MC1_FBCLK | PIN_INPUT_NOPULL, - GPIO210_MC1_CMD | PIN_INPUT_PULLUP, - GPIO211_MC1_DAT0 | PIN_INPUT_PULLUP, - GPIO212_MC1_DAT1 | PIN_INPUT_PULLUP, - GPIO213_MC1_DAT2 | PIN_INPUT_PULLUP, - GPIO214_MC1_DAT3 | PIN_INPUT_PULLUP, - - /* MMC2 (On-board DATA INTERFACE eMMC) */ - GPIO128_MC2_CLK | PIN_OUTPUT_LOW, - GPIO129_MC2_CMD | PIN_INPUT_PULLUP, - GPIO130_MC2_FBCLK | PIN_INPUT_NOPULL, - GPIO131_MC2_DAT0 | PIN_INPUT_PULLUP, - GPIO132_MC2_DAT1 | PIN_INPUT_PULLUP, - GPIO133_MC2_DAT2 | PIN_INPUT_PULLUP, - GPIO134_MC2_DAT3 | PIN_INPUT_PULLUP, - GPIO135_MC2_DAT4 | PIN_INPUT_PULLUP, - GPIO136_MC2_DAT5 | PIN_INPUT_PULLUP, - GPIO137_MC2_DAT6 | PIN_INPUT_PULLUP, - GPIO138_MC2_DAT7 | PIN_INPUT_PULLUP, - - /* MMC4 (On-board STORAGE INTERFACE eMMC) */ - GPIO197_MC4_DAT3 | PIN_INPUT_PULLUP, - GPIO198_MC4_DAT2 | PIN_INPUT_PULLUP, - GPIO199_MC4_DAT1 | PIN_INPUT_PULLUP, - GPIO200_MC4_DAT0 | PIN_INPUT_PULLUP, - GPIO201_MC4_CMD | PIN_INPUT_PULLUP, - GPIO202_MC4_FBCLK | PIN_INPUT_NOPULL, - GPIO203_MC4_CLK | PIN_OUTPUT_LOW, - GPIO204_MC4_DAT7 | PIN_INPUT_PULLUP, - GPIO205_MC4_DAT6 | PIN_INPUT_PULLUP, - GPIO206_MC4_DAT5 | PIN_INPUT_PULLUP, - GPIO207_MC4_DAT4 | PIN_INPUT_PULLUP, - - /* SKE keypad */ - GPIO153_KP_I7, - GPIO154_KP_I6, - GPIO155_KP_I5, - GPIO156_KP_I4, - GPIO157_KP_O7, - GPIO158_KP_O6, - GPIO159_KP_O5, - GPIO160_KP_O4, - GPIO161_KP_I3, - GPIO162_KP_I2, - GPIO163_KP_I1, - GPIO164_KP_I0, - GPIO165_KP_O3, - GPIO166_KP_O2, - GPIO167_KP_O1, - GPIO168_KP_O0, - /* UART */ /* uart-0 pins gpio configuration should be * kept intact to prevent glitch in tx line @@ -128,10 +66,6 @@ static pin_cfg_t mop500_pins_common[] = { GPIO30_U2_TXD | PIN_OUTPUT_HIGH, GPIO31_U2_CTSn | PIN_INPUT_PULLUP, GPIO32_U2_RTSn | PIN_OUTPUT_HIGH, - - /* Display & HDMI HW sync */ - GPIO68_LCD_VSI0 | PIN_INPUT_PULLUP, - GPIO69_LCD_VSI1 | PIN_INPUT_PULLUP, }; static pin_cfg_t mop500_pins_default[] = { @@ -141,10 +75,13 @@ static pin_cfg_t mop500_pins_default[] = { GPIO145_SSP0_RXD | PIN_PULL_DOWN, GPIO146_SSP0_TXD, + /* XENON Flashgun INTERFACE */ + GPIO6_IP_GPIO0 | PIN_INPUT_PULLUP,/* XENON_FLASH_ID */ + GPIO7_IP_GPIO1 | PIN_INPUT_PULLUP,/* XENON_READY */ GPIO217_GPIO | PIN_INPUT_PULLUP, /* TC35892 IRQ */ - /* SDI0 (MicroSD card) */ + /* sdi0 (removable MMC/SD/SDIO cards) not handled by pm_runtime */ GPIO21_MC0_DAT31DIR | PIN_OUTPUT_HIGH, /* UART */ @@ -156,13 +93,11 @@ static pin_cfg_t mop500_pins_default[] = { static pin_cfg_t hrefv60_pins[] = { /* WLAN */ - GPIO4_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */ GPIO85_GPIO | PIN_OUTPUT_LOW,/* WLAN_ENA */ /* XENON Flashgun INTERFACE */ GPIO6_IP_GPIO0 | PIN_INPUT_PULLUP,/* XENON_FLASH_ID */ GPIO7_IP_GPIO1 | PIN_INPUT_PULLUP,/* XENON_READY */ - GPIO170_GPIO | PIN_OUTPUT_LOW, /* XENON_CHARGE */ /* Assistant LED INTERFACE */ GPIO21_GPIO | PIN_OUTPUT_LOW, /* XENON_EN1 */ @@ -173,7 +108,7 @@ static pin_cfg_t hrefv60_pins[] = { GPIO32_GPIO | PIN_INPUT_PULLDOWN, /* Magnetometer DRDY */ /* Display Interface */ - GPIO65_GPIO | PIN_OUTPUT_LOW, /* DISP1 RST */ + GPIO65_GPIO | PIN_OUTPUT_HIGH, /* DISP1 NO RST */ GPIO66_GPIO | PIN_OUTPUT_LOW, /* DISP2 RST */ /* Touch screen INTERFACE */ @@ -215,11 +150,8 @@ static pin_cfg_t hrefv60_pins[] = { /* DiPro Sensor Interface */ GPIO139_GPIO | PIN_INPUT_PULLUP, /* DIPRO_INT */ - /* HAL SWITCH INTERFACE */ - GPIO145_GPIO | PIN_INPUT_PULLDOWN,/* HAL_SW */ - /* Audio Amplifier Interface */ - GPIO149_GPIO | PIN_OUTPUT_LOW, /* VAUDIO_HF_EN */ + GPIO149_GPIO | PIN_OUTPUT_HIGH, /* VAUDIO_HF_EN, enable MAX8968 */ /* GBF INTERFACE */ GPIO171_GPIO | PIN_OUTPUT_LOW, /* GBF_ENA_RESET */ @@ -231,10 +163,29 @@ static pin_cfg_t hrefv60_pins[] = { GPIO82_GPIO | PIN_INPUT_PULLUP, /* ACC_INT1 */ GPIO83_GPIO | PIN_INPUT_PULLUP, /* ACC_INT2 */ - /* Proximity Sensor */ - GPIO217_GPIO | PIN_INPUT_PULLUP, + /* SD card detect */ + GPIO95_GPIO | PIN_INPUT_PULLUP, +}; +static pin_cfg_t u9500_pins[] = { + GPIO4_U1_RXD | PIN_INPUT_PULLUP, + GPIO5_U1_TXD | PIN_OUTPUT_HIGH, + GPIO144_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */ + + /* HSI */ + GPIO219_HSIR_FLA0 | PIN_INPUT_PULLDOWN, + GPIO220_HSIR_DAT0 | PIN_INPUT_PULLDOWN, + GPIO221_HSIR_RDY0 | PIN_OUTPUT_LOW, + GPIO222_HSIT_FLA0 | PIN_OUTPUT_LOW, + GPIO223_HSIT_DAT0 | PIN_OUTPUT_LOW, + GPIO224_HSIT_RDY0 | PIN_INPUT_PULLDOWN, + GPIO225_HSIT_CAWAKE0 | PIN_INPUT_PULLDOWN, /* CA_WAKE0 */ + GPIO226_GPIO | PIN_OUTPUT_HIGH, /* AC_WAKE0 */ +}; +static pin_cfg_t u8500_pins[] = { + GPIO226_GPIO | PIN_OUTPUT_LOW, /* WLAN_PMU_EN */ + GPIO4_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */ }; static pin_cfg_t snowball_pins[] = { @@ -275,13 +226,245 @@ static pin_cfg_t snowball_pins[] = { /* RSTn_LAN */ GPIO141_GPIO | PIN_OUTPUT_HIGH, + + /* Accelerometer/Magnetometer */ + GPIO163_GPIO | PIN_INPUT_PULLUP, /* ACCEL_IRQ1 */ + GPIO164_GPIO | PIN_INPUT_PULLUP, /* ACCEL_IRQ2 */ + GPIO165_GPIO | PIN_INPUT_PULLUP, /* MAG_DRDY */ + + /* WLAN/GBF */ + GPIO161_GPIO | PIN_OUTPUT_LOW, /* WLAN_PMU_EN */ + GPIO171_GPIO | PIN_OUTPUT_HIGH,/* GBF_ENA */ + GPIO215_GPIO | PIN_OUTPUT_LOW,/* WLAN_ENA */ + GPIO216_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */ +}; + +/* + * I2C + */ + +static UX500_PINS(mop500_pins_i2c0, + GPIO147_I2C0_SCL | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO148_I2C0_SDA | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_i2c1, + GPIO16_I2C1_SCL | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO17_I2C1_SDA | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_i2c2, + GPIO10_I2C2_SDA | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO11_I2C2_SCL | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_i2c3, + GPIO229_I2C3_SDA | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO230_I2C3_SCL | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_mcde_tvout, + GPIO78_LCD_D8, + GPIO79_LCD_D9, + GPIO80_LCD_D10, + GPIO81_LCD_D11, + GPIO150_LCDA_CLK, +); + +static UX500_PINS(mop500_pins_mcde_hdmi, + GPIO69_LCD_VSI1 | PIN_INPUT_PULLUP, +); + +static UX500_PINS(mop500_pins_ske, + GPIO153_KP_I7 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO154_KP_I6 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO155_KP_I5 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO156_KP_I4 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO161_KP_I3 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO162_KP_I2 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO163_KP_I1 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO164_KP_I0 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO157_KP_O7 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO158_KP_O6 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO159_KP_O5 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO160_KP_O4 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO165_KP_O3 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO166_KP_O2 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO167_KP_O1 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO168_KP_O0 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, +); + +/* sdi0 (removable MMC/SD/SDIO cards) */ +static UX500_PINS(mop500_pins_sdi0, + GPIO18_MC0_CMDDIR | PIN_OUTPUT_HIGH, + GPIO19_MC0_DAT0DIR | PIN_OUTPUT_HIGH, + GPIO20_MC0_DAT2DIR | PIN_OUTPUT_HIGH, + + GPIO22_MC0_FBCLK | PIN_INPUT_NOPULL, + GPIO23_MC0_CLK | PIN_OUTPUT_LOW, + GPIO24_MC0_CMD | PIN_INPUT_PULLUP, + GPIO25_MC0_DAT0 | PIN_INPUT_PULLUP, + GPIO26_MC0_DAT1 | PIN_INPUT_PULLUP, + GPIO27_MC0_DAT2 | PIN_INPUT_PULLUP, + GPIO28_MC0_DAT3 | PIN_INPUT_PULLUP, +); + +/* sdi1 (WLAN CW1200) */ +static UX500_PINS(mop500_pins_sdi1, + GPIO208_MC1_CLK | PIN_OUTPUT_LOW, + GPIO209_MC1_FBCLK | PIN_INPUT_NOPULL, + GPIO210_MC1_CMD | PIN_INPUT_PULLUP, + GPIO211_MC1_DAT0 | PIN_INPUT_PULLUP, + GPIO212_MC1_DAT1 | PIN_INPUT_PULLUP, + GPIO213_MC1_DAT2 | PIN_INPUT_PULLUP, + GPIO214_MC1_DAT3 | PIN_INPUT_PULLUP, +); + +/* sdi2 (POP eMMC) */ +static UX500_PINS(mop500_pins_sdi2, + GPIO128_MC2_CLK | PIN_OUTPUT_LOW, + GPIO129_MC2_CMD | PIN_INPUT_PULLUP, + GPIO130_MC2_FBCLK | PIN_INPUT_NOPULL, + GPIO131_MC2_DAT0 | PIN_INPUT_PULLUP, + GPIO132_MC2_DAT1 | PIN_INPUT_PULLUP, + GPIO133_MC2_DAT2 | PIN_INPUT_PULLUP, + GPIO134_MC2_DAT3 | PIN_INPUT_PULLUP, + GPIO135_MC2_DAT4 | PIN_INPUT_PULLUP, + GPIO136_MC2_DAT5 | PIN_INPUT_PULLUP, + GPIO137_MC2_DAT6 | PIN_INPUT_PULLUP, + GPIO138_MC2_DAT7 | PIN_INPUT_PULLUP, +); + +/* sdi4 (PCB eMMC) */ +static UX500_PINS(mop500_pins_sdi4, + GPIO197_MC4_DAT3 | PIN_INPUT_PULLUP, + GPIO198_MC4_DAT2 | PIN_INPUT_PULLUP, + GPIO199_MC4_DAT1 | PIN_INPUT_PULLUP, + GPIO200_MC4_DAT0 | PIN_INPUT_PULLUP, + GPIO201_MC4_CMD | PIN_INPUT_PULLUP, + GPIO202_MC4_FBCLK | PIN_INPUT_NOPULL, + GPIO203_MC4_CLK | PIN_OUTPUT_LOW, + GPIO204_MC4_DAT7 | PIN_INPUT_PULLUP, + GPIO205_MC4_DAT6 | PIN_INPUT_PULLUP, + GPIO206_MC4_DAT5 | PIN_INPUT_PULLUP, + GPIO207_MC4_DAT4 | PIN_INPUT_PULLUP, +); + +/* USB */ +static UX500_PINS(mop500_pins_usb, + GPIO256_USB_NXT, + GPIO257_USB_STP | PIN_OUTPUT_HIGH, + GPIO258_USB_XCLK, + GPIO259_USB_DIR, + GPIO260_USB_DAT7, + GPIO261_USB_DAT6, + GPIO262_USB_DAT5, + GPIO263_USB_DAT4, + GPIO264_USB_DAT3, + GPIO265_USB_DAT2, + GPIO266_USB_DAT1, + GPIO267_USB_DAT0, +); + +/* SPI2 */ +static UX500_PINS(mop500_pins_spi2, + GPIO216_GPIO | PIN_OUTPUT_HIGH, + GPIO218_SPI2_RXD | PIN_INPUT_PULLDOWN, + GPIO215_SPI2_TXD | PIN_OUTPUT_LOW, + GPIO217_SPI2_CLK | PIN_OUTPUT_LOW, +); + +static UX500_PINS(mop500_pins_sensors1p_v60, + GPIO217_GPIO| PIN_INPUT_PULLUP | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO145_GPIO | PIN_INPUT_PULLDOWN | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO139_GPIO | PIN_INPUT_PULLUP | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_sensors1p, + PIN_CFG_INPUT(GPIO_PROX_SENSOR, GPIO, NOPULL), + PIN_CFG_INPUT(GPIO_HAL_SENSOR, GPIO, NOPULL), +); + +static struct ux500_pin_lookup mop500_runtime_pins[] = { + PIN_LOOKUP("mcde-tvout", &mop500_pins_mcde_tvout), + PIN_LOOKUP("av8100-hdmi", &mop500_pins_mcde_hdmi), + PIN_LOOKUP("nmk-i2c.0", &mop500_pins_i2c0), + PIN_LOOKUP("nmk-i2c.1", &mop500_pins_i2c1), + PIN_LOOKUP("nmk-i2c.2", &mop500_pins_i2c2), + PIN_LOOKUP("nmk-i2c.3", &mop500_pins_i2c3), + PIN_LOOKUP("sdi0", &mop500_pins_sdi0), + PIN_LOOKUP("sdi1", &mop500_pins_sdi1), + PIN_LOOKUP("sdi2", &mop500_pins_sdi2), + PIN_LOOKUP("sdi4", &mop500_pins_sdi4), + PIN_LOOKUP("musb-ux500.0", &mop500_pins_usb), + PIN_LOOKUP("spi2", &mop500_pins_spi2), }; +static struct ux500_pin_lookup mop500_runtime_pins_v60[] = { + PIN_LOOKUP("ske", &mop500_pins_ske), + PIN_LOOKUP("gpio-keys.0", &mop500_pins_sensors1p_v60), +}; + +static struct ux500_pin_lookup mop500_runtime_pins_pre_v60[] = { + PIN_LOOKUP("ske", &mop500_pins_ske), + PIN_LOOKUP("gpio-keys.0", &mop500_pins_sensors1p), +}; + +/* + * passing "pinsfor=" in kernel cmdline allows for custom + * configuration of GPIOs on u8500 derived boards. + */ +static int __init early_pinsfor(char *p) +{ + pinsfor = PINS_FOR_DEFAULT; + + if (strcmp(p, "u9500-21") == 0) + pinsfor = PINS_FOR_U9500; + + return 0; +} +early_param("pinsfor", early_pinsfor); + +int pins_for_u9500(void) +{ + if (pinsfor == PINS_FOR_U9500) + return 1; + + return 0; +} + void __init mop500_pins_init(void) { nmk_config_pins(mop500_pins_common, ARRAY_SIZE(mop500_pins_common)); + ux500_pins_add(mop500_runtime_pins, ARRAY_SIZE(mop500_runtime_pins)); + + ux500_pins_add(mop500_runtime_pins_pre_v60, + ARRAY_SIZE(mop500_runtime_pins_pre_v60)); + + switch (pinsfor) { + case PINS_FOR_U9500: + nmk_config_pins(u9500_pins, ARRAY_SIZE(u9500_pins)); + break; + + case PINS_FOR_DEFAULT: + nmk_config_pins(u8500_pins, ARRAY_SIZE(u8500_pins)); + default: + break; + } + nmk_config_pins(mop500_pins_default, ARRAY_SIZE(mop500_pins_default)); } @@ -291,8 +474,11 @@ void __init snowball_pins_init(void) nmk_config_pins(mop500_pins_common, ARRAY_SIZE(mop500_pins_common)); - nmk_config_pins(snowball_pins, - ARRAY_SIZE(snowball_pins)); + ux500_pins_add(mop500_runtime_pins, ARRAY_SIZE(mop500_runtime_pins)); + + nmk_config_pins(u8500_pins, ARRAY_SIZE(u8500_pins)); + + nmk_config_pins(snowball_pins, ARRAY_SIZE(snowball_pins)); } void __init hrefv60_pins_init(void) @@ -300,6 +486,22 @@ void __init hrefv60_pins_init(void) nmk_config_pins(mop500_pins_common, ARRAY_SIZE(mop500_pins_common)); + ux500_pins_add(mop500_runtime_pins, ARRAY_SIZE(mop500_runtime_pins)); + + ux500_pins_add(mop500_runtime_pins_v60, + ARRAY_SIZE(mop500_runtime_pins_v60)); + nmk_config_pins(hrefv60_pins, ARRAY_SIZE(hrefv60_pins)); + + switch (pinsfor) { + case PINS_FOR_U9500: + nmk_config_pins(u9500_pins, ARRAY_SIZE(u9500_pins)); + break; + + case PINS_FOR_DEFAULT: + nmk_config_pins(u8500_pins, ARRAY_SIZE(u8500_pins)); + default: + break; + } } diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 77d03c1fbd04..ca0d62599f70 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -53,6 +53,7 @@ #include "devices-db8500.h" #include "board-mop500.h" #include "board-mop500-regulators.h" +#include "board-mop500-msp.h" static struct gpio_led snowball_led_array[] = { { @@ -631,6 +632,7 @@ static void __init mop500_init_machine(void) mop500_i2c_init(parent); mop500_sdi_init(parent); mop500_spi_init(parent); + mop500_msp_init(parent); mop500_uart_init(parent); i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); @@ -662,6 +664,7 @@ static void __init snowball_init_machine(void) mop500_i2c_init(parent); snowball_sdi_init(parent); mop500_spi_init(parent); + mop500_msp_init(parent); mop500_uart_init(parent); i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); @@ -699,6 +702,7 @@ static void __init hrefv60_init_machine(void) mop500_i2c_init(parent); hrefv60_sdi_init(parent); mop500_spi_init(parent); + mop500_msp_init(parent); mop500_uart_init(parent); i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); @@ -746,10 +750,22 @@ MACHINE_END #ifdef CONFIG_MACH_UX500_DT struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = { + /* Requires DMA and call-back bindings. */ OF_DEV_AUXDATA("arm,pl011", 0x80120000, "uart0", &uart0_plat), OF_DEV_AUXDATA("arm,pl011", 0x80121000, "uart1", &uart1_plat), OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", &uart2_plat), + /* Requires DMA bindings. */ OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0", &ssp0_plat), + /* Requires clock name bindings. */ + OF_DEV_AUXDATA("st,nomadik-gpio", 0x8012e000, "gpio.0", NULL), + OF_DEV_AUXDATA("st,nomadik-gpio", 0x8012e080, "gpio.1", NULL), + OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e000, "gpio.2", NULL), + OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e080, "gpio.3", NULL), + OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e100, "gpio.4", NULL), + OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e180, "gpio.5", NULL), + OF_DEV_AUXDATA("st,nomadik-gpio", 0x8011e000, "gpio.6", NULL), + OF_DEV_AUXDATA("st,nomadik-gpio", 0x8011e080, "gpio.7", NULL), + OF_DEV_AUXDATA("st,nomadik-gpio", 0xa03fe000, "gpio.8", NULL), {}, }; diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index fdcfa8721bb4..91dc63fe101b 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -7,6 +7,9 @@ #ifndef __BOARD_MOP500_H #define __BOARD_MOP500_H +/* For NOMADIK_NR_GPIO */ +#include <mach/irqs.h> + /* Snowball specific GPIO assignments, this board has no GPIO expander */ #define SNOWBALL_ACCEL_INT1_GPIO 163 #define SNOWBALL_ACCEL_INT2_GPIO 164 @@ -73,6 +76,7 @@ #define SNOWBALL_PME_ETH_GPIO MOP500_AB8500_PIN_GPIO(24) /* SYSCLKREQ7/GPIO24 */ #define SNOWBALL_EN_3V3_ETH_GPIO MOP500_AB8500_PIN_GPIO(26) /* GPIO26 */ +struct device; struct i2c_board_info; extern void mop500_sdi_init(struct device *parent); diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index ec35f0aa5665..700042cb6681 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -336,6 +336,7 @@ static DEFINE_PRCMU_CLK(uiccclk, 0x4, 1, UICCCLK); /* v1 */ */ /* Peripheral Cluster #1 */ +static DEFINE_PRCC_CLK(1, msp3, 11, 10, &clk_msp1clk); static DEFINE_PRCC_CLK(1, i2c4, 10, 9, &clk_i2cclk); static DEFINE_PRCC_CLK(1, gpio0, 9, -1, NULL); static DEFINE_PRCC_CLK(1, slimbus0, 8, 8, &clk_slimclk); @@ -405,7 +406,7 @@ static struct clk_lookup u8500_clks[] = { CLK(slimbus0, "slimbus0", NULL), CLK(i2c2, "nmk-i2c.2", NULL), CLK(sdi0, "sdi0", NULL), - CLK(msp0, "msp0", NULL), + CLK(msp0, "ux500-msp-i2s.0", NULL), CLK(i2c1, "nmk-i2c.1", NULL), CLK(uart1, "uart1", NULL), CLK(uart0, "uart0", NULL), @@ -455,7 +456,8 @@ static struct clk_lookup u8500_clks[] = { /* Peripheral Cluster #1 */ CLK(i2c4, "nmk-i2c.4", NULL), CLK(spi3, "spi3", NULL), - CLK(msp1, "msp1", NULL), + CLK(msp1, "ux500-msp-i2s.1", NULL), + CLK(msp3, "ux500-msp-i2s.3", NULL), /* Peripheral Cluster #2 */ CLK(gpio1, "gpio.6", NULL), @@ -465,7 +467,7 @@ static struct clk_lookup u8500_clks[] = { CLK(spi0, "spi0", NULL), CLK(sdi3, "sdi3", NULL), CLK(sdi1, "sdi1", NULL), - CLK(msp2, "msp2", NULL), + CLK(msp2, "ux500-msp-i2s.2", NULL), CLK(sdi4, "sdi4", NULL), CLK(pwl, "pwl", NULL), CLK(spi1, "spi1", NULL), diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index d11f3892a27d..f6522f9f129c 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -30,6 +30,18 @@ void __iomem *_PRCMU_BASE; +/* + * FIXME: Should we set up the GPIO domain here? + * + * The problem is that we cannot put the interrupt resources into the platform + * device until the irqdomain has been added. Right now, we set the GIC interrupt + * domain from init_irq(), then load the gpio driver from + * core_initcall(nmk_gpio_init) and add the platform devices from + * arch_initcall(customize_machine). + * + * This feels fragile because it depends on the gpio device getting probed + * _before_ any device uses the gpio interrupts. +*/ static const struct of_device_id ux500_dt_irq_match[] = { { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, {}, diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h index 9fd93e9da529..e22b78626068 100644 --- a/arch/arm/mach-ux500/devices-db8500.h +++ b/arch/arm/mach-ux500/devices-db8500.h @@ -34,7 +34,6 @@ db8500_add_ssp(struct device *parent, const char *name, resource_size_t base, return dbx500_add_amba_device(parent, name, base, irq, pdata, 0); } - #define db8500_add_i2c0(parent, pdata) \ dbx500_add_i2c(parent, 0, U8500_I2C0_BASE, IRQ_DB8500_I2C0, pdata) #define db8500_add_i2c1(parent, pdata) \ @@ -46,15 +45,6 @@ db8500_add_ssp(struct device *parent, const char *name, resource_size_t base, #define db8500_add_i2c4(parent, pdata) \ dbx500_add_i2c(parent, 4, U8500_I2C4_BASE, IRQ_DB8500_I2C4, pdata) -#define db8500_add_msp0_i2s(parent, pdata) \ - dbx500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata) -#define db8500_add_msp1_i2s(parent, pdata) \ - dbx500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata) -#define db8500_add_msp2_i2s(parent, pdata) \ - dbx500_add_msp_i2s(parent, 2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata) -#define db8500_add_msp3_i2s(parent, pdata) \ - dbx500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata) - #define db8500_add_msp0_spi(parent, pdata) \ dbx500_add_msp_spi(parent, "msp0", U8500_MSP0_BASE, \ IRQ_DB8500_MSP0, pdata) diff --git a/arch/arm/mach-ux500/include/mach/msp.h b/arch/arm/mach-ux500/include/mach/msp.h new file mode 100644 index 000000000000..798be19129ef --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/msp.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson + * License terms: GNU General Public License (GPL), version 2. + */ + +#ifndef __MSP_H +#define __MSP_H + +#include <plat/ste_dma40.h> + +enum msp_i2s_id { + MSP_I2S_0 = 0, + MSP_I2S_1, + MSP_I2S_2, + MSP_I2S_3, +}; + +/* Platform data structure for a MSP I2S-device */ +struct msp_i2s_platform_data { + enum msp_i2s_id id; + struct stedma40_chan_cfg *msp_i2s_dma_rx; + struct stedma40_chan_cfg *msp_i2s_dma_tx; + int (*msp_i2s_init) (void); + int (*msp_i2s_exit) (void); +}; + +#endif diff --git a/arch/arm/mach-ux500/pins-db8500.h b/arch/arm/mach-ux500/pins-db8500.h index 8b1d1a7a679e..062c7acf4576 100644 --- a/arch/arm/mach-ux500/pins-db8500.h +++ b/arch/arm/mach-ux500/pins-db8500.h @@ -35,40 +35,40 @@ #define GPIO4_GPIO PIN_CFG(4, GPIO) #define GPIO4_U1_RXD PIN_CFG(4, ALT_A) -#define GPIO4_I2C4_SCL PIN_CFG_INPUT(4, ALT_B, PULLUP) +#define GPIO4_I2C4_SCL PIN_CFG(4, ALT_B) #define GPIO4_IP_TRSTn PIN_CFG(4, ALT_C) #define GPIO5_GPIO PIN_CFG(5, GPIO) #define GPIO5_U1_TXD PIN_CFG(5, ALT_A) -#define GPIO5_I2C4_SDA PIN_CFG_INPUT(5, ALT_B, PULLUP) +#define GPIO5_I2C4_SDA PIN_CFG(5, ALT_B) #define GPIO5_IP_GPIO6 PIN_CFG(5, ALT_C) #define GPIO6_GPIO PIN_CFG(6, GPIO) #define GPIO6_U1_CTSn PIN_CFG(6, ALT_A) -#define GPIO6_I2C1_SCL PIN_CFG_INPUT(6, ALT_B, PULLUP) +#define GPIO6_I2C1_SCL PIN_CFG(6, ALT_B) #define GPIO6_IP_GPIO0 PIN_CFG(6, ALT_C) #define GPIO7_GPIO PIN_CFG(7, GPIO) #define GPIO7_U1_RTSn PIN_CFG(7, ALT_A) -#define GPIO7_I2C1_SDA PIN_CFG_INPUT(7, ALT_B, PULLUP) +#define GPIO7_I2C1_SDA PIN_CFG(7, ALT_B) #define GPIO7_IP_GPIO1 PIN_CFG(7, ALT_C) #define GPIO8_GPIO PIN_CFG(8, GPIO) -#define GPIO8_IPI2C_SDA PIN_CFG_INPUT(8, ALT_A, PULLUP) -#define GPIO8_I2C2_SDA PIN_CFG_INPUT(8, ALT_B, PULLUP) +#define GPIO8_IPI2C_SDA PIN_CFG(8, ALT_A) +#define GPIO8_I2C2_SDA PIN_CFG(8, ALT_B) #define GPIO9_GPIO PIN_CFG(9, GPIO) -#define GPIO9_IPI2C_SCL PIN_CFG_INPUT(9, ALT_A, PULLUP) -#define GPIO9_I2C2_SCL PIN_CFG_INPUT(9, ALT_B, PULLUP) +#define GPIO9_IPI2C_SCL PIN_CFG(9, ALT_A) +#define GPIO9_I2C2_SCL PIN_CFG(9, ALT_B) #define GPIO10_GPIO PIN_CFG(10, GPIO) -#define GPIO10_IPI2C_SDA PIN_CFG_INPUT(10, ALT_A, PULLUP) -#define GPIO10_I2C2_SDA PIN_CFG_INPUT(10, ALT_B, PULLUP) +#define GPIO10_IPI2C_SDA PIN_CFG(10, ALT_A) +#define GPIO10_I2C2_SDA PIN_CFG(10, ALT_B) #define GPIO10_IP_GPIO3 PIN_CFG(10, ALT_C) #define GPIO11_GPIO PIN_CFG(11, GPIO) -#define GPIO11_IPI2C_SCL PIN_CFG_INPUT(11, ALT_A, PULLUP) -#define GPIO11_I2C2_SCL PIN_CFG_INPUT(11, ALT_B, PULLUP) +#define GPIO11_IPI2C_SCL PIN_CFG(11, ALT_A) +#define GPIO11_I2C2_SCL PIN_CFG(11, ALT_B) #define GPIO11_IP_GPIO2 PIN_CFG(11, ALT_C) #define GPIO12_GPIO PIN_CFG(12, GPIO) @@ -87,12 +87,12 @@ #define GPIO16_GPIO PIN_CFG(16, GPIO) #define GPIO16_MSP0_RFS PIN_CFG(16, ALT_A) -#define GPIO16_I2C1_SCL PIN_CFG_INPUT(16, ALT_B, PULLUP) +#define GPIO16_I2C1_SCL PIN_CFG(16, ALT_B) #define GPIO16_SLIM0_DAT PIN_CFG(16, ALT_C) #define GPIO17_GPIO PIN_CFG(17, GPIO) #define GPIO17_MSP0_RCK PIN_CFG(17, ALT_A) -#define GPIO17_I2C1_SDA PIN_CFG_INPUT(17, ALT_B, PULLUP) +#define GPIO17_I2C1_SDA PIN_CFG(17, ALT_B) #define GPIO17_SLIM0_CLK PIN_CFG(17, ALT_C) #define GPIO18_GPIO PIN_CFG(18, GPIO) @@ -434,10 +434,10 @@ #define GPIO146_SSP0_TXD PIN_CFG(146, ALT_A) #define GPIO147_GPIO PIN_CFG(147, GPIO) -#define GPIO147_I2C0_SCL PIN_CFG_INPUT(147, ALT_A, PULLUP) +#define GPIO147_I2C0_SCL PIN_CFG(147, ALT_A) #define GPIO148_GPIO PIN_CFG(148, GPIO) -#define GPIO148_I2C0_SDA PIN_CFG_INPUT(148, ALT_A, PULLUP) +#define GPIO148_I2C0_SDA PIN_CFG(148, ALT_A) #define GPIO149_GPIO PIN_CFG(149, GPIO) #define GPIO149_IP_GPIO0 PIN_CFG(149, ALT_A) @@ -459,82 +459,82 @@ #define GPIO152_KP_O9 PIN_CFG(152, ALT_C) #define GPIO153_GPIO PIN_CFG(153, GPIO) -#define GPIO153_KP_I7 PIN_CFG_INPUT(153, ALT_A, PULLDOWN) +#define GPIO153_KP_I7 PIN_CFG(153, ALT_A) #define GPIO153_LCD_D24 PIN_CFG(153, ALT_B) #define GPIO153_U2_RXD PIN_CFG(153, ALT_C) #define GPIO154_GPIO PIN_CFG(154, GPIO) -#define GPIO154_KP_I6 PIN_CFG_INPUT(154, ALT_A, PULLDOWN) +#define GPIO154_KP_I6 PIN_CFG(154, ALT_A) #define GPIO154_LCD_D25 PIN_CFG(154, ALT_B) #define GPIO154_U2_TXD PIN_CFG(154, ALT_C) #define GPIO155_GPIO PIN_CFG(155, GPIO) -#define GPIO155_KP_I5 PIN_CFG_INPUT(155, ALT_A, PULLDOWN) +#define GPIO155_KP_I5 PIN_CFG(155, ALT_A) #define GPIO155_LCD_D26 PIN_CFG(155, ALT_B) #define GPIO155_STMAPE_CLK PIN_CFG(155, ALT_C) #define GPIO156_GPIO PIN_CFG(156, GPIO) -#define GPIO156_KP_I4 PIN_CFG_INPUT(156, ALT_A, PULLDOWN) +#define GPIO156_KP_I4 PIN_CFG(156, ALT_A) #define GPIO156_LCD_D27 PIN_CFG(156, ALT_B) #define GPIO156_STMAPE_DAT3 PIN_CFG(156, ALT_C) #define GPIO157_GPIO PIN_CFG(157, GPIO) -#define GPIO157_KP_O7 PIN_CFG_INPUT(157, ALT_A, PULLUP) +#define GPIO157_KP_O7 PIN_CFG(157, ALT_A) #define GPIO157_LCD_D28 PIN_CFG(157, ALT_B) #define GPIO157_STMAPE_DAT2 PIN_CFG(157, ALT_C) #define GPIO158_GPIO PIN_CFG(158, GPIO) -#define GPIO158_KP_O6 PIN_CFG_INPUT(158, ALT_A, PULLUP) +#define GPIO158_KP_O6 PIN_CFG(158, ALT_A) #define GPIO158_LCD_D29 PIN_CFG(158, ALT_B) #define GPIO158_STMAPE_DAT1 PIN_CFG(158, ALT_C) #define GPIO159_GPIO PIN_CFG(159, GPIO) -#define GPIO159_KP_O5 PIN_CFG_INPUT(159, ALT_A, PULLUP) +#define GPIO159_KP_O5 PIN_CFG(159, ALT_A) #define GPIO159_LCD_D30 PIN_CFG(159, ALT_B) #define GPIO159_STMAPE_DAT0 PIN_CFG(159, ALT_C) #define GPIO160_GPIO PIN_CFG(160, GPIO) -#define GPIO160_KP_O4 PIN_CFG_INPUT(160, ALT_A, PULLUP) +#define GPIO160_KP_O4 PIN_CFG(160, ALT_A) #define GPIO160_LCD_D31 PIN_CFG(160, ALT_B) #define GPIO160_NONE PIN_CFG(160, ALT_C) #define GPIO161_GPIO PIN_CFG(161, GPIO) -#define GPIO161_KP_I3 PIN_CFG_INPUT(161, ALT_A, PULLDOWN) +#define GPIO161_KP_I3 PIN_CFG(161, ALT_A) #define GPIO161_LCD_D32 PIN_CFG(161, ALT_B) #define GPIO161_UARTMOD_RXD PIN_CFG(161, ALT_C) #define GPIO162_GPIO PIN_CFG(162, GPIO) -#define GPIO162_KP_I2 PIN_CFG_INPUT(162, ALT_A, PULLDOWN) +#define GPIO162_KP_I2 PIN_CFG(162, ALT_A) #define GPIO162_LCD_D33 PIN_CFG(162, ALT_B) #define GPIO162_UARTMOD_TXD PIN_CFG(162, ALT_C) #define GPIO163_GPIO PIN_CFG(163, GPIO) -#define GPIO163_KP_I1 PIN_CFG_INPUT(163, ALT_A, PULLDOWN) +#define GPIO163_KP_I1 PIN_CFG(163, ALT_A) #define GPIO163_LCD_D34 PIN_CFG(163, ALT_B) #define GPIO163_STMMOD_CLK PIN_CFG(163, ALT_C) #define GPIO164_GPIO PIN_CFG(164, GPIO) -#define GPIO164_KP_I0 PIN_CFG_INPUT(164, ALT_A, PULLUP) +#define GPIO164_KP_I0 PIN_CFG(164, ALT_A) #define GPIO164_LCD_D35 PIN_CFG(164, ALT_B) #define GPIO164_STMMOD_DAT3 PIN_CFG(164, ALT_C) #define GPIO165_GPIO PIN_CFG(165, GPIO) -#define GPIO165_KP_O3 PIN_CFG_INPUT(165, ALT_A, PULLUP) +#define GPIO165_KP_O3 PIN_CFG(165, ALT_A) #define GPIO165_LCD_D36 PIN_CFG(165, ALT_B) #define GPIO165_STMMOD_DAT2 PIN_CFG(165, ALT_C) #define GPIO166_GPIO PIN_CFG(166, GPIO) -#define GPIO166_KP_O2 PIN_CFG_INPUT(166, ALT_A, PULLUP) +#define GPIO166_KP_O2 PIN_CFG(166, ALT_A) #define GPIO166_LCD_D37 PIN_CFG(166, ALT_B) #define GPIO166_STMMOD_DAT1 PIN_CFG(166, ALT_C) #define GPIO167_GPIO PIN_CFG(167, GPIO) -#define GPIO167_KP_O1 PIN_CFG_INPUT(167, ALT_A, PULLUP) +#define GPIO167_KP_O1 PIN_CFG(167, ALT_A) #define GPIO167_LCD_D38 PIN_CFG(167, ALT_B) #define GPIO167_STMMOD_DAT0 PIN_CFG(167, ALT_C) #define GPIO168_GPIO PIN_CFG(168, GPIO) -#define GPIO168_KP_O0 PIN_CFG_INPUT(168, ALT_A, PULLUP) +#define GPIO168_KP_O0 PIN_CFG(168, ALT_A) #define GPIO168_LCD_D39 PIN_CFG(168, ALT_B) #define GPIO168_NONE PIN_CFG(168, ALT_C) @@ -637,7 +637,7 @@ #define GPIO216_GPIO PIN_CFG(216, GPIO) #define GPIO216_MC1_DAT2DIR PIN_CFG(216, ALT_A) #define GPIO216_MC3_CMDDIR PIN_CFG(216, ALT_B) -#define GPIO216_I2C3_SDA PIN_CFG_INPUT(216, ALT_C, PULLUP) +#define GPIO216_I2C3_SDA PIN_CFG(216, ALT_C) #define GPIO216_SPI2_FRM PIN_CFG(216, ALT_C) #define GPIO217_GPIO PIN_CFG(217, GPIO) @@ -649,7 +649,7 @@ #define GPIO218_GPIO PIN_CFG(218, GPIO) #define GPIO218_MC1_DAT31DIR PIN_CFG(218, ALT_A) #define GPIO218_MC3_DAT0DIR PIN_CFG(218, ALT_B) -#define GPIO218_I2C3_SCL PIN_CFG_INPUT(218, ALT_C, PULLUP) +#define GPIO218_I2C3_SCL PIN_CFG(218, ALT_C) #define GPIO218_SPI2_RXD PIN_CFG(218, ALT_C) #define GPIO219_GPIO PIN_CFG(219, GPIO) @@ -698,12 +698,12 @@ #define GPIO229_GPIO PIN_CFG(229, GPIO) #define GPIO229_CLKOUT1 PIN_CFG(229, ALT_A) #define GPIO229_PWL PIN_CFG(229, ALT_B) -#define GPIO229_I2C3_SDA PIN_CFG_INPUT(229, ALT_C, PULLUP) +#define GPIO229_I2C3_SDA PIN_CFG(229, ALT_C) #define GPIO230_GPIO PIN_CFG(230, GPIO) #define GPIO230_CLKOUT2 PIN_CFG(230, ALT_A) #define GPIO230_PWL PIN_CFG(230, ALT_B) -#define GPIO230_I2C3_SCL PIN_CFG_INPUT(230, ALT_C, PULLUP) +#define GPIO230_I2C3_SCL PIN_CFG(230, ALT_C) #define GPIO256_GPIO PIN_CFG(256, GPIO) #define GPIO256_USB_NXT PIN_CFG(256, ALT_A) diff --git a/arch/arm/mach-ux500/pins.c b/arch/arm/mach-ux500/pins.c new file mode 100644 index 000000000000..38c1d47b29a1 --- /dev/null +++ b/arch/arm/mach-ux500/pins.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson + * License terms: GNU General Public License (GPL), version 2 + */ + +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/device.h> +#include <linux/mutex.h> +#include <linux/spinlock.h> +#include <linux/err.h> +#include <plat/pincfg.h> + +#include "pins.h" + +static LIST_HEAD(pin_lookups); +static DEFINE_MUTEX(pin_lookups_mutex); +static DEFINE_SPINLOCK(pins_lock); + +void __init ux500_pins_add(struct ux500_pin_lookup *pl, size_t num) +{ + mutex_lock(&pin_lookups_mutex); + + while (num--) { + list_add_tail(&pl->node, &pin_lookups); + pl++; + } + + mutex_unlock(&pin_lookups_mutex); +} + +struct ux500_pins *ux500_pins_get(const char *name) +{ + struct ux500_pins *pins = NULL; + struct ux500_pin_lookup *pl; + + mutex_lock(&pin_lookups_mutex); + + list_for_each_entry(pl, &pin_lookups, node) { + if (!strcmp(pl->name, name)) { + pins = pl->pins; + goto out; + } + } + +out: + mutex_unlock(&pin_lookups_mutex); + return pins; +} + +int ux500_pins_enable(struct ux500_pins *pins) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&pins_lock, flags); + + if (pins->usage++ == 0) + ret = nmk_config_pins(pins->cfg, pins->num); + + spin_unlock_irqrestore(&pins_lock, flags); + return ret; +} + +int ux500_pins_disable(struct ux500_pins *pins) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&pins_lock, flags); + + if (WARN_ON(pins->usage == 0)) + goto out; + + if (--pins->usage == 0) + ret = nmk_config_pins_sleep(pins->cfg, pins->num); + +out: + spin_unlock_irqrestore(&pins_lock, flags); + return ret; +} + +void ux500_pins_put(struct ux500_pins *pins) +{ + WARN_ON(!pins); +} diff --git a/arch/arm/mach-ux500/pins.h b/arch/arm/mach-ux500/pins.h new file mode 100644 index 000000000000..0d36af2e7d92 --- /dev/null +++ b/arch/arm/mach-ux500/pins.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson + * License terms: GNU General Public License (GPL), version 2 + */ + +#ifndef __MACH_UX500_PINS_H +#define __MACH_UX500_PINS_H + +#include <linux/list.h> +#include <plat/pincfg.h> + +#define PIN_LOOKUP(_name, _pins) \ +{ \ + .name = _name, \ + .pins = _pins, \ +} + +#define UX500_PINS(name, pins...) \ +struct ux500_pins name = { \ + .cfg = (pin_cfg_t[]) {pins}, \ + .num = ARRAY_SIZE(((pin_cfg_t[]) {pins})), \ +} + +struct ux500_pins { + int usage; + int num; + pin_cfg_t *cfg; +}; + +struct ux500_pin_lookup { + struct list_head node; + const char *name; + struct ux500_pins *pins; +}; + +void __init ux500_pins_add(struct ux500_pin_lookup *pl, size_t num); +void __init ux500_offchip_gpio_init(struct ux500_pins *pins); +struct ux500_pins *ux500_pins_get(const char *name); +int ux500_pins_enable(struct ux500_pins *pins); +int ux500_pins_disable(struct ux500_pins *pins); +void ux500_pins_put(struct ux500_pins *pins); +int pins_for_u9500(void); + +#endif diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index d2058ef8345f..eff5842f6232 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -99,7 +99,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) */ write_pen_release(cpu_logical_map(cpu)); - gic_raise_softirq(cpumask_of(cpu), 1); + smp_send_reschedule(cpu); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { diff --git a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h index 9605bf227df9..3e8b7f16fb78 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h +++ b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h @@ -29,6 +29,7 @@ #define NMK_GPIO_SLPC 0x1c #define NMK_GPIO_AFSLA 0x20 #define NMK_GPIO_AFSLB 0x24 +#define NMK_GPIO_LOWEMI 0x28 #define NMK_GPIO_RIMSC 0x40 #define NMK_GPIO_FIMSC 0x44 diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h index 22cb97d2d8ad..c015133a7ad3 100644 --- a/arch/arm/plat-nomadik/include/plat/pincfg.h +++ b/arch/arm/plat-nomadik/include/plat/pincfg.h @@ -24,6 +24,7 @@ * bit 16..18 - SLPM pull up/down state * bit 19..20 - SLPM direction * bit 21..22 - SLPM Value (if output) + * bit 23..25 - PDIS value (if input) * * to facilitate the definition, the following macros are provided * @@ -67,6 +68,10 @@ typedef unsigned long pin_cfg_t; /* These two replace the above in DB8500v2+ */ #define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT) #define PIN_SLPM_WAKEUP_DISABLE (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT) +#define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE + +#define PIN_SLPM_GPIO PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */ +#define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */ #define PIN_DIR_SHIFT 14 #define PIN_DIR_MASK (0x1 << PIN_DIR_SHIFT) @@ -105,6 +110,20 @@ typedef unsigned long pin_cfg_t; #define PIN_SLPM_VAL_LOW ((1 + 0) << PIN_SLPM_VAL_SHIFT) #define PIN_SLPM_VAL_HIGH ((1 + 1) << PIN_SLPM_VAL_SHIFT) +#define PIN_SLPM_PDIS_SHIFT 23 +#define PIN_SLPM_PDIS_MASK (0x3 << PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS(x) \ + (((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS_NO_CHANGE (0 << PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS_DISABLED (1 << PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS_ENABLED (2 << PIN_SLPM_PDIS_SHIFT) + +#define PIN_LOWEMI_SHIFT 25 +#define PIN_LOWEMI_MASK (0x1 << PIN_LOWEMI_SHIFT) +#define PIN_LOWEMI(x) (((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT) +#define PIN_LOWEMI_DISABLED (0 << PIN_LOWEMI_SHIFT) +#define PIN_LOWEMI_ENABLED (1 << PIN_LOWEMI_SHIFT) + /* Shortcuts. Use these instead of separate DIR, PULL, and VAL. */ #define PIN_INPUT_PULLDOWN (PIN_DIR_INPUT | PIN_PULL_DOWN) #define PIN_INPUT_PULLUP (PIN_DIR_INPUT | PIN_PULL_UP) diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 8070145ccb98..3f26db4ee8e6 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -305,6 +305,7 @@ struct omap_hwmod_sysc_fields { * @rev_offs: IP block revision register offset (from module base addr) * @sysc_offs: OCP_SYSCONFIG register offset (from module base addr) * @syss_offs: OCP_SYSSTATUS register offset (from module base addr) + * @srst_udelay: Delay needed after doing a softreset in usecs * @idlemodes: One or more of {SIDLE,MSTANDBY}_{OFF,FORCE,SMART} * @sysc_flags: SYS{C,S}_HAS* flags indicating SYSCONFIG bits supported * @clockact: the default value of the module CLOCKACTIVITY bits @@ -330,9 +331,10 @@ struct omap_hwmod_class_sysconfig { u16 sysc_offs; u16 syss_offs; u16 sysc_flags; + struct omap_hwmod_sysc_fields *sysc_fields; + u8 srst_udelay; u8 idlemodes; u8 clockact; - struct omap_hwmod_sysc_fields *sysc_fields; }; /** diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index eec98afa0f83..f9a8c5341ee9 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -348,7 +348,6 @@ u32 omap3_configure_core_dpll(u32 m2, u32 unlock_dll, u32 f, u32 inc, sdrc_actim_ctrl_b_1, sdrc_mr_1); } -#ifdef CONFIG_PM void omap3_sram_restore_context(void) { omap_sram_ceil = omap_sram_base + omap_sram_size; @@ -358,17 +357,18 @@ void omap3_sram_restore_context(void) omap3_sram_configure_core_dpll_sz); omap_push_sram_idle(); } -#endif /* CONFIG_PM */ - -#endif /* CONFIG_ARCH_OMAP3 */ static inline int omap34xx_sram_init(void) { -#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) omap3_sram_restore_context(); -#endif return 0; } +#else +static inline int omap34xx_sram_init(void) +{ + return 0; +} +#endif /* CONFIG_ARCH_OMAP3 */ static inline int am33xx_sram_init(void) { diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h index 0ab82cc2dc8f..d2bf1fd5e44f 100644 --- a/arch/ia64/include/asm/futex.h +++ b/arch/ia64/include/asm/futex.h @@ -106,15 +106,16 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, return -EFAULT; { - register unsigned long r8 __asm ("r8") = 0; + register unsigned long r8 __asm ("r8"); unsigned long prev; __asm__ __volatile__( " mf;; \n" - " mov ar.ccv=%3;; \n" - "[1:] cmpxchg4.acq %0=[%1],%2,ar.ccv \n" + " mov %0=r0 \n" + " mov ar.ccv=%4;; \n" + "[1:] cmpxchg4.acq %1=[%2],%3,ar.ccv \n" " .xdata4 \"__ex_table\", 1b-., 2f-. \n" "[2:]" - : "=r" (prev) + : "=r" (r8), "=r" (prev) : "r" (uaddr), "r" (newval), "rO" ((long) (unsigned) oldval) : "memory"); diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 9d0fd7d5bb82..f00ba025375d 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -604,12 +604,6 @@ pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f) spin_unlock(&(x)->ctx_lock); } -static inline unsigned int -pfm_do_munmap(struct mm_struct *mm, unsigned long addr, size_t len, int acct) -{ - return do_munmap(mm, addr, len); -} - static inline unsigned long pfm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, unsigned long exec) { @@ -1458,8 +1452,9 @@ pfm_unreserve_session(pfm_context_t *ctx, int is_syswide, unsigned int cpu) * a PROTECT_CTX() section. */ static int -pfm_remove_smpl_mapping(struct task_struct *task, void *vaddr, unsigned long size) +pfm_remove_smpl_mapping(void *vaddr, unsigned long size) { + struct task_struct *task = current; int r; /* sanity checks */ @@ -1473,13 +1468,8 @@ pfm_remove_smpl_mapping(struct task_struct *task, void *vaddr, unsigned long siz /* * does the actual unmapping */ - down_write(&task->mm->mmap_sem); + r = vm_munmap((unsigned long)vaddr, size); - DPRINT(("down_write done smpl_vaddr=%p size=%lu\n", vaddr, size)); - - r = pfm_do_munmap(task->mm, (unsigned long)vaddr, size, 0); - - up_write(&task->mm->mmap_sem); if (r !=0) { printk(KERN_ERR "perfmon: [%d] unable to unmap sampling buffer @%p size=%lu\n", task_pid_nr(task), vaddr, size); } @@ -1945,7 +1935,7 @@ pfm_flush(struct file *filp, fl_owner_t id) * because some VM function reenables interrupts. * */ - if (smpl_buf_vaddr) pfm_remove_smpl_mapping(current, smpl_buf_vaddr, smpl_buf_size); + if (smpl_buf_vaddr) pfm_remove_smpl_mapping(smpl_buf_vaddr, smpl_buf_size); return 0; } diff --git a/arch/m68k/configs/m5275evb_defconfig b/arch/m68k/configs/m5275evb_defconfig index 33c32aeca12b..a1230e82bb1e 100644 --- a/arch/m68k/configs/m5275evb_defconfig +++ b/arch/m68k/configs/m5275evb_defconfig @@ -49,7 +49,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_NETDEVICES=y CONFIG_NET_ETHERNET=y CONFIG_FEC=y -CONFIG_FEC2=y # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set CONFIG_PPP=y diff --git a/arch/m68k/platform/527x/config.c b/arch/m68k/platform/527x/config.c index 7ed848c3b848..f91a53294c35 100644 --- a/arch/m68k/platform/527x/config.c +++ b/arch/m68k/platform/527x/config.c @@ -74,9 +74,7 @@ static void __init m527x_fec_init(void) writew(par | 0xf00, MCF_IPSBAR + 0x100082); v = readb(MCF_IPSBAR + 0x100078); writeb(v | 0xc0, MCF_IPSBAR + 0x100078); -#endif -#ifdef CONFIG_FEC2 /* Set multi-function pins to ethernet mode for fec1 */ par = readw(MCF_IPSBAR + 0x100082); writew(par | 0xa0, MCF_IPSBAR + 0x100082); diff --git a/arch/m68k/platform/68EZ328/Makefile b/arch/m68k/platform/68EZ328/Makefile index ee97735a242c..b44d799b1115 100644 --- a/arch/m68k/platform/68EZ328/Makefile +++ b/arch/m68k/platform/68EZ328/Makefile @@ -3,9 +3,3 @@ # obj-y := config.o - -extra-y := bootlogo.rh - -$(obj)/bootlogo.rh: $(src)/bootlogo.h - perl $(src)/../68328/bootlogo.pl < $(src)/bootlogo.h \ - > $(obj)/bootlogo.rh diff --git a/arch/m68k/platform/68VZ328/Makefile b/arch/m68k/platform/68VZ328/Makefile index 447ffa0fd7c7..a49d75e65489 100644 --- a/arch/m68k/platform/68VZ328/Makefile +++ b/arch/m68k/platform/68VZ328/Makefile @@ -3,14 +3,9 @@ # obj-y := config.o -logo-$(UCDIMM) := bootlogo.rh -logo-$(DRAGEN2) := screen.h -extra-y := $(logo-y) - -$(obj)/bootlogo.rh: $(src)/../68EZ328/bootlogo.h - perl $(src)/bootlogo.pl < $(src)/../68328/bootlogo.h > $(obj)/bootlogo.rh +extra-$(DRAGEN2):= screen.h $(obj)/screen.h: $(src)/screen.xbm $(src)/xbm2lcd.pl perl $(src)/xbm2lcd.pl < $(src)/screen.xbm > $(obj)/screen.h -clean-files := $(obj)/screen.h $(obj)/bootlogo.rh +clean-files := $(obj)/screen.h diff --git a/arch/m68k/platform/68EZ328/bootlogo.h b/arch/m68k/platform/68VZ328/bootlogo.h index e842bdae5839..b38e2b255142 100644 --- a/arch/m68k/platform/68EZ328/bootlogo.h +++ b/arch/m68k/platform/68VZ328/bootlogo.h @@ -1,6 +1,6 @@ #define splash_width 640 #define splash_height 480 -static unsigned char splash_bits[] = { +unsigned char __attribute__ ((aligned(16))) bootlogo_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/arch/m68k/platform/coldfire/device.c b/arch/m68k/platform/coldfire/device.c index fa50c48292ff..7af97362b95c 100644 --- a/arch/m68k/platform/coldfire/device.c +++ b/arch/m68k/platform/coldfire/device.c @@ -114,7 +114,7 @@ static struct resource mcf_fec1_resources[] = { static struct platform_device mcf_fec1 = { .name = "fec", - .id = 0, + .id = 1, .num_resources = ARRAY_SIZE(mcf_fec1_resources), .resource = mcf_fec1_resources, }; diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 2b7c0fbe578e..9015060919a0 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -90,7 +90,6 @@ config S390 select HAVE_KERNEL_XZ select HAVE_ARCH_MUTEX_CPU_RELAX select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 - select HAVE_RCU_TABLE_FREE if SMP select ARCH_SAVE_PAGE_KEYS if HIBERNATION select HAVE_MEMBLOCK select HAVE_MEMBLOCK_NODE_MAP diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 6cf8e26b3137..1957a9dd256d 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -1,8 +1,12 @@ CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y +CONFIG_FHANDLE=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y CONFIG_AUDIT=y -CONFIG_RCU_TRACE=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_CGROUPS=y @@ -14,16 +18,22 @@ CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_BLK_CGROUP=y +CONFIG_NAMESPACES=y CONFIG_BLK_DEV_INITRD=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_EXPERT=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_OPROFILE=y CONFIG_KPROBES=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_IBM_PARTITION=y CONFIG_DEFAULT_DEADLINE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -34,18 +44,15 @@ CONFIG_KSM=y CONFIG_BINFMT_MISC=m CONFIG_CMM=m CONFIG_HZ_100=y -CONFIG_KEXEC=y -CONFIG_PM=y +CONFIG_CRASH_DUMP=y CONFIG_HIBERNATION=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_NET_KEY=y -CONFIG_AFIUCV=m CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_INET_LRO is not set CONFIG_IPV6=y -CONFIG_NET_SCTPPROBE=m CONFIG_L2TP=m CONFIG_L2TP_DEBUGFS=m CONFIG_VLAN_8021Q=y @@ -84,15 +91,14 @@ CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SCAN_ASYNC=y CONFIG_ZFCP=y -CONFIG_ZFCP_DIF=y CONFIG_NETDEVICES=y -CONFIG_DUMMY=m CONFIG_BONDING=m +CONFIG_DUMMY=m CONFIG_EQUALIZER=m CONFIG_TUN=m -CONFIG_NET_ETHERNET=y CONFIG_VIRTIO_NET=y CONFIG_RAW_DRIVER=m +CONFIG_VIRTIO_BALLOON=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set @@ -103,27 +109,21 @@ CONFIG_PROC_KCORE=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y # CONFIG_NETWORK_FILESYSTEMS is not set -CONFIG_PARTITION_ADVANCED=y -CONFIG_IBM_PARTITION=y -CONFIG_DLM=m CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_KERNEL=y CONFIG_TIMER_STATS=y CONFIG_PROVE_LOCKING=y CONFIG_PROVE_RCU=y CONFIG_LOCK_STAT=y CONFIG_DEBUG_LOCKDEP=y -CONFIG_DEBUG_SPINLOCK_SLEEP=y CONFIG_DEBUG_LIST=y CONFIG_DEBUG_NOTIFIERS=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_RCU_TRACE=y CONFIG_KPROBES_SANITY_TEST=y CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y CONFIG_CPU_NOTIFIER_ERROR_INJECT=m CONFIG_LATENCYTOP=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_DEBUG_PAGEALLOC=y -# CONFIG_FTRACE is not set +CONFIG_BLK_DEV_IO_TRACE=y # CONFIG_STRICT_DEVMEM is not set CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_CRYPTD=m @@ -173,4 +173,3 @@ CONFIG_CRYPTO_SHA512_S390=m CONFIG_CRYPTO_DES_S390=m CONFIG_CRYPTO_AES_S390=m CONFIG_CRC7=m -CONFIG_VIRTIO_BALLOON=y diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h index 1e5b27edc0c9..2ee66a65f2d4 100644 --- a/arch/s390/include/asm/facility.h +++ b/arch/s390/include/asm/facility.h @@ -38,12 +38,11 @@ static inline void stfle(u64 *stfle_fac_list, int size) unsigned long nr; preempt_disable(); - S390_lowcore.stfl_fac_list = 0; asm volatile( " .insn s,0xb2b10000,0(0)\n" /* stfl */ "0:\n" EX_TABLE(0b, 0b) - : "=m" (S390_lowcore.stfl_fac_list)); + : "+m" (S390_lowcore.stfl_fac_list)); nr = 4; /* bytes stored by stfl */ memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4); if (S390_lowcore.stfl_fac_list & 0x01000000) { diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h index 8eef9b5b3cf4..78e3041919de 100644 --- a/arch/s390/include/asm/pgalloc.h +++ b/arch/s390/include/asm/pgalloc.h @@ -22,10 +22,7 @@ void crst_table_free(struct mm_struct *, unsigned long *); unsigned long *page_table_alloc(struct mm_struct *, unsigned long); void page_table_free(struct mm_struct *, unsigned long *); -#ifdef CONFIG_HAVE_RCU_TABLE_FREE void page_table_free_rcu(struct mmu_gather *, unsigned long *); -void __tlb_remove_table(void *_table); -#endif static inline void clear_table(unsigned long *s, unsigned long val, size_t n) { diff --git a/arch/s390/include/asm/swab.h b/arch/s390/include/asm/swab.h index 6bdee21c077e..a3e4ebb32090 100644 --- a/arch/s390/include/asm/swab.h +++ b/arch/s390/include/asm/swab.h @@ -77,7 +77,7 @@ static inline __u16 __arch_swab16p(const __u16 *x) asm volatile( #ifndef __s390x__ - " icm %0,2,%O+1(%R1)\n" + " icm %0,2,%O1+1(%R1)\n" " ic %0,%1\n" : "=&d" (result) : "Q" (*x) : "cc"); #else /* __s390x__ */ diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h index c687a2c83462..775a5eea8f9e 100644 --- a/arch/s390/include/asm/tlb.h +++ b/arch/s390/include/asm/tlb.h @@ -30,14 +30,10 @@ struct mmu_gather { struct mm_struct *mm; -#ifdef CONFIG_HAVE_RCU_TABLE_FREE struct mmu_table_batch *batch; -#endif unsigned int fullmm; - unsigned int need_flush; }; -#ifdef CONFIG_HAVE_RCU_TABLE_FREE struct mmu_table_batch { struct rcu_head rcu; unsigned int nr; @@ -49,7 +45,6 @@ struct mmu_table_batch { extern void tlb_table_flush(struct mmu_gather *tlb); extern void tlb_remove_table(struct mmu_gather *tlb, void *table); -#endif static inline void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, @@ -57,29 +52,20 @@ static inline void tlb_gather_mmu(struct mmu_gather *tlb, { tlb->mm = mm; tlb->fullmm = full_mm_flush; - tlb->need_flush = 0; -#ifdef CONFIG_HAVE_RCU_TABLE_FREE tlb->batch = NULL; -#endif if (tlb->fullmm) __tlb_flush_mm(mm); } static inline void tlb_flush_mmu(struct mmu_gather *tlb) { - if (!tlb->need_flush) - return; - tlb->need_flush = 0; - __tlb_flush_mm(tlb->mm); -#ifdef CONFIG_HAVE_RCU_TABLE_FREE tlb_table_flush(tlb); -#endif } static inline void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) { - tlb_flush_mmu(tlb); + tlb_table_flush(tlb); } /* @@ -105,10 +91,8 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, unsigned long address) { -#ifdef CONFIG_HAVE_RCU_TABLE_FREE if (!tlb->fullmm) return page_table_free_rcu(tlb, (unsigned long *) pte); -#endif page_table_free(tlb->mm, (unsigned long *) pte); } @@ -125,10 +109,8 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, #ifdef __s390x__ if (tlb->mm->context.asce_limit <= (1UL << 31)) return; -#ifdef CONFIG_HAVE_RCU_TABLE_FREE if (!tlb->fullmm) return tlb_remove_table(tlb, pmd); -#endif crst_table_free(tlb->mm, (unsigned long *) pmd); #endif } @@ -146,10 +128,8 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud, #ifdef __s390x__ if (tlb->mm->context.asce_limit <= (1UL << 42)) return; -#ifdef CONFIG_HAVE_RCU_TABLE_FREE if (!tlb->fullmm) return tlb_remove_table(tlb, pud); -#endif crst_table_free(tlb->mm, (unsigned long *) pud); #endif } diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index c27a0727f930..adccd908ebc7 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -474,9 +474,9 @@ ENTRY(startup_kdump) stck __LC_LAST_UPDATE_CLOCK spt 5f-.LPG0(%r13) mvc __LC_LAST_UPDATE_TIMER(8),5f-.LPG0(%r13) + xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST #ifndef CONFIG_MARCH_G5 # check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10} - xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST .insn s,0xb2b10000,__LC_STFL_FAC_LIST # store facility list tm __LC_STFL_FAC_LIST,0x01 # stfle available ? jz 0f diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 1c2cdd59ccd0..8a22c27219dd 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -118,9 +118,10 @@ asmlinkage void do_softirq(void) "a" (__do_softirq) : "0", "1", "2", "3", "4", "5", "14", "cc", "memory" ); - } else + } else { /* We are already on the async stack. */ __do_softirq(); + } } local_irq_restore(flags); @@ -192,11 +193,12 @@ int unregister_external_interrupt(u16 code, ext_int_handler_t handler) int index = ext_hash(code); spin_lock_irqsave(&ext_int_hash_lock, flags); - list_for_each_entry_rcu(p, &ext_int_hash[index], entry) + list_for_each_entry_rcu(p, &ext_int_hash[index], entry) { if (p->code == code && p->handler == handler) { list_del_rcu(&p->entry); kfree_rcu(p, rcu); } + } spin_unlock_irqrestore(&ext_int_hash_lock, flags); return 0; } @@ -211,9 +213,10 @@ void __irq_entry do_extint(struct pt_regs *regs, struct ext_code ext_code, old_regs = set_irq_regs(regs); irq_enter(); - if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) + if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) { /* Serve timer interrupts first. */ clock_comparator_work(); + } kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; if (ext_code.code != 0x1004) __get_cpu_var(s390_idle).nohz_delay = 1; diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index 46405086479c..cb019f429e88 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c @@ -178,7 +178,7 @@ static void cpumf_pmu_enable(struct pmu *pmu) err = lcctl(cpuhw->state); if (err) { pr_err("Enabling the performance measuring unit " - "failed with rc=%lx\n", err); + "failed with rc=%x\n", err); return; } @@ -203,7 +203,7 @@ static void cpumf_pmu_disable(struct pmu *pmu) err = lcctl(inactive); if (err) { pr_err("Disabling the performance measuring unit " - "failed with rc=%lx\n", err); + "failed with rc=%x\n", err); return; } diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c index 7bb15fcca75e..e1335dc2b1b7 100644 --- a/arch/s390/mm/maccess.c +++ b/arch/s390/mm/maccess.c @@ -61,21 +61,14 @@ long probe_kernel_write(void *dst, const void *src, size_t size) return copied < 0 ? -EFAULT : 0; } -/* - * Copy memory in real mode (kernel to kernel) - */ -int memcpy_real(void *dest, void *src, size_t count) +static int __memcpy_real(void *dest, void *src, size_t count) { register unsigned long _dest asm("2") = (unsigned long) dest; register unsigned long _len1 asm("3") = (unsigned long) count; register unsigned long _src asm("4") = (unsigned long) src; register unsigned long _len2 asm("5") = (unsigned long) count; - unsigned long flags; int rc = -EFAULT; - if (!count) - return 0; - flags = __arch_local_irq_stnsm(0xf8UL); asm volatile ( "0: mvcle %1,%2,0x0\n" "1: jo 0b\n" @@ -86,7 +79,23 @@ int memcpy_real(void *dest, void *src, size_t count) "+d" (_len2), "=m" (*((long *) dest)) : "m" (*((long *) src)) : "cc", "memory"); - arch_local_irq_restore(flags); + return rc; +} + +/* + * Copy memory in real mode (kernel to kernel) + */ +int memcpy_real(void *dest, void *src, size_t count) +{ + unsigned long flags; + int rc; + + if (!count) + return 0; + local_irq_save(flags); + __arch_local_irq_stnsm(0xfbUL); + rc = __memcpy_real(dest, src, count); + local_irq_restore(flags); return rc; } diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 373adf69b01c..6e765bf00670 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -678,8 +678,6 @@ void page_table_free(struct mm_struct *mm, unsigned long *table) } } -#ifdef CONFIG_HAVE_RCU_TABLE_FREE - static void __page_table_free_rcu(void *table, unsigned bit) { struct page *page; @@ -733,7 +731,66 @@ void __tlb_remove_table(void *_table) free_pages((unsigned long) table, ALLOC_ORDER); } -#endif +static void tlb_remove_table_smp_sync(void *arg) +{ + /* Simply deliver the interrupt */ +} + +static void tlb_remove_table_one(void *table) +{ + /* + * This isn't an RCU grace period and hence the page-tables cannot be + * assumed to be actually RCU-freed. + * + * It is however sufficient for software page-table walkers that rely + * on IRQ disabling. See the comment near struct mmu_table_batch. + */ + smp_call_function(tlb_remove_table_smp_sync, NULL, 1); + __tlb_remove_table(table); +} + +static void tlb_remove_table_rcu(struct rcu_head *head) +{ + struct mmu_table_batch *batch; + int i; + + batch = container_of(head, struct mmu_table_batch, rcu); + + for (i = 0; i < batch->nr; i++) + __tlb_remove_table(batch->tables[i]); + + free_page((unsigned long)batch); +} + +void tlb_table_flush(struct mmu_gather *tlb) +{ + struct mmu_table_batch **batch = &tlb->batch; + + if (*batch) { + __tlb_flush_mm(tlb->mm); + call_rcu_sched(&(*batch)->rcu, tlb_remove_table_rcu); + *batch = NULL; + } +} + +void tlb_remove_table(struct mmu_gather *tlb, void *table) +{ + struct mmu_table_batch **batch = &tlb->batch; + + if (*batch == NULL) { + *batch = (struct mmu_table_batch *) + __get_free_page(GFP_NOWAIT | __GFP_NOWARN); + if (*batch == NULL) { + __tlb_flush_mm(tlb->mm); + tlb_remove_table_one(table); + return; + } + (*batch)->nr = 0; + } + (*batch)->tables[(*batch)->nr++] = table; + if ((*batch)->nr == MAX_TABLE_BATCH) + tlb_table_flush(tlb); +} /* * switch on pgstes for its userspace process (for kvm) diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index 1210fde18740..160cac9c4036 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c @@ -23,6 +23,7 @@ #include <linux/pm.h> #include <linux/delay.h> #include <linux/gfp.h> +#include <linux/cpu.h> #include <asm/cacheflush.h> #include <asm/tlbflush.h> @@ -78,6 +79,8 @@ void __cpuinit leon_callin(void) local_flush_tlb_all(); leon_configure_cache_smp(); + notify_cpu_starting(cpuid); + /* Get our local ticker going. */ smp_setup_percpu_timer(); diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 232df9949530..3ee51f189a55 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -566,15 +566,10 @@ out: SYSCALL_DEFINE2(64_munmap, unsigned long, addr, size_t, len) { - long ret; - if (invalid_64bit_range(addr, len)) return -EINVAL; - down_write(¤t->mm->mmap_sem); - ret = do_munmap(current->mm, addr, len); - up_write(¤t->mm->mmap_sem); - return ret; + return vm_munmap(addr, len); } extern unsigned long do_mremap(unsigned long addr, diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c index 9efbc1391b3c..89529c9f0605 100644 --- a/arch/tile/kernel/single_step.c +++ b/arch/tile/kernel/single_step.c @@ -346,12 +346,10 @@ void single_step_once(struct pt_regs *regs) } /* allocate a cache line of writable, executable memory */ - down_write(¤t->mm->mmap_sem); - buffer = (void __user *) do_mmap(NULL, 0, 64, + buffer = (void __user *) vm_mmap(NULL, 0, 64, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0); - up_write(¤t->mm->mmap_sem); if (IS_ERR((void __force *)buffer)) { kfree(state); diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index d511d951a052..4824fb45560f 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c @@ -119,9 +119,7 @@ static void set_brk(unsigned long start, unsigned long end) end = PAGE_ALIGN(end); if (end <= start) return; - down_write(¤t->mm->mmap_sem); - do_brk(start, end - start); - up_write(¤t->mm->mmap_sem); + vm_brk(start, end - start); } #ifdef CORE_DUMP @@ -332,9 +330,7 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) pos = 32; map_size = ex.a_text+ex.a_data; - down_write(¤t->mm->mmap_sem); - error = do_brk(text_addr & PAGE_MASK, map_size); - up_write(¤t->mm->mmap_sem); + error = vm_brk(text_addr & PAGE_MASK, map_size); if (error != (text_addr & PAGE_MASK)) { send_sig(SIGKILL, current, 0); @@ -373,9 +369,7 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) if (!bprm->file->f_op->mmap || (fd_offset & ~PAGE_MASK) != 0) { loff_t pos = fd_offset; - down_write(¤t->mm->mmap_sem); - do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); - up_write(¤t->mm->mmap_sem); + vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); @@ -385,26 +379,22 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) goto beyond_if; } - down_write(¤t->mm->mmap_sem); - error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, + error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE | MAP_32BIT, fd_offset); - up_write(¤t->mm->mmap_sem); if (error != N_TXTADDR(ex)) { send_sig(SIGKILL, current, 0); return error; } - down_write(¤t->mm->mmap_sem); - error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, + error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE | MAP_32BIT, fd_offset + ex.a_text); - up_write(¤t->mm->mmap_sem); if (error != N_DATADDR(ex)) { send_sig(SIGKILL, current, 0); return error; @@ -476,9 +466,7 @@ static int load_aout_library(struct file *file) error_time = jiffies; } #endif - down_write(¤t->mm->mmap_sem); - do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); - up_write(¤t->mm->mmap_sem); + vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); file->f_op->read(file, (char __user *)start_addr, ex.a_text + ex.a_data, &pos); @@ -490,12 +478,10 @@ static int load_aout_library(struct file *file) goto out; } /* Now use mmap to map the library into memory. */ - down_write(¤t->mm->mmap_sem); - error = do_mmap(file, start_addr, ex.a_text + ex.a_data, + error = vm_mmap(file, start_addr, ex.a_text + ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT, N_TXTOFF(ex)); - up_write(¤t->mm->mmap_sem); retval = error; if (error != start_addr) goto out; @@ -503,9 +489,7 @@ static int load_aout_library(struct file *file) len = PAGE_ALIGN(ex.a_text + ex.a_data); bss = ex.a_text + ex.a_data + ex.a_bss; if (bss > len) { - down_write(¤t->mm->mmap_sem); - error = do_brk(start_addr + len, bss - len); - up_write(¤t->mm->mmap_sem); + error = vm_brk(start_addr + len, bss - len); retval = error; if (error != start_addr + len) goto out; diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index 173df38dbda5..2e88438ffd83 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -459,17 +459,17 @@ void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu) pmu->available_event_types = ~entry->ebx & ((1ull << bitmap_len) - 1); if (pmu->version == 1) { - pmu->global_ctrl = (1 << pmu->nr_arch_gp_counters) - 1; - return; + pmu->nr_arch_fixed_counters = 0; + } else { + pmu->nr_arch_fixed_counters = min((int)(entry->edx & 0x1f), + X86_PMC_MAX_FIXED); + pmu->counter_bitmask[KVM_PMC_FIXED] = + ((u64)1 << ((entry->edx >> 5) & 0xff)) - 1; } - pmu->nr_arch_fixed_counters = min((int)(entry->edx & 0x1f), - X86_PMC_MAX_FIXED); - pmu->counter_bitmask[KVM_PMC_FIXED] = - ((u64)1 << ((entry->edx >> 5) & 0xff)) - 1; - pmu->global_ctrl_mask = ~(((1 << pmu->nr_arch_gp_counters) - 1) - | (((1ull << pmu->nr_arch_fixed_counters) - 1) - << X86_PMC_IDX_FIXED)); + pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) - 1) | + (((1ull << pmu->nr_arch_fixed_counters) - 1) << X86_PMC_IDX_FIXED); + pmu->global_ctrl_mask = ~pmu->global_ctrl; } void kvm_pmu_init(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index ad85adfef843..4ff0ab9bc3c8 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2210,9 +2210,12 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) msr = find_msr_entry(vmx, msr_index); if (msr) { msr->data = data; - if (msr - vmx->guest_msrs < vmx->save_nmsrs) + if (msr - vmx->guest_msrs < vmx->save_nmsrs) { + preempt_disable(); kvm_set_shared_msr(msr->index, msr->data, msr->mask); + preempt_enable(); + } break; } ret = kvm_set_msr_common(vcpu, msr_index, data); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 4044ce0bf7c1..91a5e989abcf 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6336,13 +6336,11 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, if (npages && !old.rmap) { unsigned long userspace_addr; - down_write(¤t->mm->mmap_sem); - userspace_addr = do_mmap(NULL, 0, + userspace_addr = vm_mmap(NULL, 0, npages * PAGE_SIZE, PROT_READ | PROT_WRITE, map_flags, 0); - up_write(¤t->mm->mmap_sem); if (IS_ERR((void *)userspace_addr)) return PTR_ERR((void *)userspace_addr); @@ -6366,10 +6364,8 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, if (!user_alloc && !old.user_alloc && old.rmap && !npages) { int ret; - down_write(¤t->mm->mmap_sem); - ret = do_munmap(current->mm, old.userspace_addr, + ret = vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE); - up_write(¤t->mm->mmap_sem); if (ret < 0) printk(KERN_WARNING "kvm_vm_ioctl_set_memory_region: " diff --git a/arch/x86/lib/insn.c b/arch/x86/lib/insn.c index 25feb1ae71c5..b1e6c4b2e8eb 100644 --- a/arch/x86/lib/insn.c +++ b/arch/x86/lib/insn.c @@ -379,8 +379,8 @@ err_out: return; } -/* Decode moffset16/32/64 */ -static void __get_moffset(struct insn *insn) +/* Decode moffset16/32/64. Return 0 if failed */ +static int __get_moffset(struct insn *insn) { switch (insn->addr_bytes) { case 2: @@ -397,15 +397,19 @@ static void __get_moffset(struct insn *insn) insn->moffset2.value = get_next(int, insn); insn->moffset2.nbytes = 4; break; + default: /* opnd_bytes must be modified manually */ + goto err_out; } insn->moffset1.got = insn->moffset2.got = 1; + return 1; + err_out: - return; + return 0; } -/* Decode imm v32(Iz) */ -static void __get_immv32(struct insn *insn) +/* Decode imm v32(Iz). Return 0 if failed */ +static int __get_immv32(struct insn *insn) { switch (insn->opnd_bytes) { case 2: @@ -417,14 +421,18 @@ static void __get_immv32(struct insn *insn) insn->immediate.value = get_next(int, insn); insn->immediate.nbytes = 4; break; + default: /* opnd_bytes must be modified manually */ + goto err_out; } + return 1; + err_out: - return; + return 0; } -/* Decode imm v64(Iv/Ov) */ -static void __get_immv(struct insn *insn) +/* Decode imm v64(Iv/Ov), Return 0 if failed */ +static int __get_immv(struct insn *insn) { switch (insn->opnd_bytes) { case 2: @@ -441,15 +449,18 @@ static void __get_immv(struct insn *insn) insn->immediate2.value = get_next(int, insn); insn->immediate2.nbytes = 4; break; + default: /* opnd_bytes must be modified manually */ + goto err_out; } insn->immediate1.got = insn->immediate2.got = 1; + return 1; err_out: - return; + return 0; } /* Decode ptr16:16/32(Ap) */ -static void __get_immptr(struct insn *insn) +static int __get_immptr(struct insn *insn) { switch (insn->opnd_bytes) { case 2: @@ -462,14 +473,17 @@ static void __get_immptr(struct insn *insn) break; case 8: /* ptr16:64 is not exist (no segment) */ - return; + return 0; + default: /* opnd_bytes must be modified manually */ + goto err_out; } insn->immediate2.value = get_next(unsigned short, insn); insn->immediate2.nbytes = 2; insn->immediate1.got = insn->immediate2.got = 1; + return 1; err_out: - return; + return 0; } /** @@ -489,7 +503,8 @@ void insn_get_immediate(struct insn *insn) insn_get_displacement(insn); if (inat_has_moffset(insn->attr)) { - __get_moffset(insn); + if (!__get_moffset(insn)) + goto err_out; goto done; } @@ -517,16 +532,20 @@ void insn_get_immediate(struct insn *insn) insn->immediate2.nbytes = 4; break; case INAT_IMM_PTR: - __get_immptr(insn); + if (!__get_immptr(insn)) + goto err_out; break; case INAT_IMM_VWORD32: - __get_immv32(insn); + if (!__get_immv32(insn)) + goto err_out; break; case INAT_IMM_VWORD: - __get_immv(insn); + if (!__get_immv(insn)) + goto err_out; break; default: - break; + /* Here, insn must have an immediate, but failed */ + goto err_out; } if (inat_has_second_immediate(insn->attr)) { insn->immediate2.value = get_next(char, insn); diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c index 107f6f7be5e1..dd30f40af9f5 100644 --- a/crypto/sha512_generic.c +++ b/crypto/sha512_generic.c @@ -174,7 +174,7 @@ sha512_update(struct shash_desc *desc, const u8 *data, unsigned int len) index = sctx->count[0] & 0x7f; /* Update number of bytes */ - if (!(sctx->count[0] += len)) + if ((sctx->count[0] += len) < len) sctx->count[1]++; part_len = 128 - index; diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index ab513a972c95..a716fede4f25 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -74,7 +74,8 @@ acpi_status acpi_reset(void) /* Check if the reset register is supported */ - if (!reset_reg->address) { + if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || + !reset_reg->address) { return_ACPI_STATUS(AE_NOT_EXIST); } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index ba14fb93c929..c3881b2eb8b2 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -607,8 +607,7 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, acpi_irq_handler = handler; acpi_irq_context = context; - if (request_threaded_irq(irq, NULL, acpi_irq, IRQF_SHARED, "acpi", - acpi_irq)) { + if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) { printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); acpi_irq_handler = NULL; return AE_NOT_ACQUIRED; diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c index c1d612435939..a6c77e8b37bd 100644 --- a/drivers/acpi/reboot.c +++ b/drivers/acpi/reboot.c @@ -23,7 +23,8 @@ void acpi_reboot(void) /* Is the reset register supported? The spec says we should be * checking the bit width and bit offset, but Windows ignores * these fields */ - /* Ignore also acpi_gbl_FADT.flags.ACPI_FADT_RESET_REGISTER */ + if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER)) + return; reset_value = acpi_gbl_FADT.reset_value; diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 68013f96729f..7857e8fd0a3e 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -329,6 +329,8 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (Lynx Point) */ { 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (DH89xxCC) */ + { 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, { } /* terminate list */ }; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index e0bda9ff89cd..28db50b57b91 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -95,7 +95,7 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev); static void ata_dev_xfermask(struct ata_device *dev); static unsigned long ata_dev_blacklisted(const struct ata_device *dev); -unsigned int ata_print_id = 1; +atomic_t ata_print_id = ATOMIC_INIT(1); struct ata_force_param { const char *name; @@ -6029,7 +6029,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) /* give ports names and add SCSI hosts */ for (i = 0; i < host->n_ports; i++) - host->ports[i]->print_id = ata_print_id++; + host->ports[i]->print_id = atomic_inc_return(&ata_print_id); /* Create associated sysfs transport objects */ diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 1ee00c8b5b04..93dabdcd2cbe 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3843,7 +3843,7 @@ int ata_sas_async_port_init(struct ata_port *ap) int rc = ap->ops->port_start(ap); if (!rc) { - ap->print_id = ata_print_id++; + ap->print_id = atomic_inc_return(&ata_print_id); __ata_port_probe(ap); } @@ -3867,7 +3867,7 @@ int ata_sas_port_init(struct ata_port *ap) int rc = ap->ops->port_start(ap); if (!rc) { - ap->print_id = ata_print_id++; + ap->print_id = atomic_inc_return(&ata_print_id); rc = ata_port_probe(ap); } diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index 74aaee30e264..c34190485377 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -294,6 +294,7 @@ int ata_tport_add(struct device *parent, device_enable_async_suspend(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); + pm_runtime_forbid(dev); transport_add_device(dev); transport_configure_device(dev); diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 2e26fcaf635b..9d0fd0b71852 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -53,7 +53,7 @@ enum { ATA_DNXFER_QUIET = (1 << 31), }; -extern unsigned int ata_print_id; +extern atomic_t ata_print_id; extern int atapi_passthru16; extern int libata_fua; extern int libata_noacpi; diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 38950ea8398a..7336d4a7ab31 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -4025,7 +4025,8 @@ static int mv_platform_probe(struct platform_device *pdev) struct ata_host *host; struct mv_host_priv *hpriv; struct resource *res; - int n_ports, rc; + int n_ports = 0; + int rc; ata_print_version_once(&pdev->dev, DRV_VERSION); diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 0e4ef3de9d5d..0d39f2f4294a 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -375,6 +375,34 @@ static int init_vq(struct virtio_blk *vblk) return err; } +/* + * Legacy naming scheme used for virtio devices. We are stuck with it for + * virtio blk but don't ever use it for any new driver. + */ +static int virtblk_name_format(char *prefix, int index, char *buf, int buflen) +{ + const int base = 'z' - 'a' + 1; + char *begin = buf + strlen(prefix); + char *end = buf + buflen; + char *p; + int unit; + + p = end - 1; + *p = '\0'; + unit = base; + do { + if (p == begin) + return -EINVAL; + *--p = 'a' + (index % unit); + index = (index / unit) - 1; + } while (index >= 0); + + memmove(begin, p, end - p); + memcpy(buf, prefix, strlen(prefix)); + + return 0; +} + static int __devinit virtblk_probe(struct virtio_device *vdev) { struct virtio_blk *vblk; @@ -443,18 +471,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) q->queuedata = vblk; - if (index < 26) { - sprintf(vblk->disk->disk_name, "vd%c", 'a' + index % 26); - } else if (index < (26 + 1) * 26) { - sprintf(vblk->disk->disk_name, "vd%c%c", - 'a' + index / 26 - 1, 'a' + index % 26); - } else { - const unsigned int m1 = (index / 26 - 1) / 26 - 1; - const unsigned int m2 = (index / 26 - 1) % 26; - const unsigned int m3 = index % 26; - sprintf(vblk->disk->disk_name, "vd%c%c%c", - 'a' + m1, 'a' + m2, 'a' + m3); - } + virtblk_name_format("vd", index, vblk->disk->disk_name, DISK_NAME_LEN); vblk->disk->major = major; vblk->disk->first_minor = index_to_minor(index); diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 89860f34a7ec..4f66171c6683 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -416,7 +416,7 @@ static void xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info "discard-secure", "%d", blkif->vbd.discard_secure); if (err) { - dev_warn(dev-dev, "writing discard-secure (%d)", err); + dev_warn(&dev->dev, "writing discard-secure (%d)", err); return; } } diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index 0053d7ebb5ca..8f3f74ce8c7f 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c @@ -18,6 +18,7 @@ #include <linux/interrupt.h> #include <linux/spinlock.h> #include <linux/gfp.h> +#include <linux/module.h> #include <crypto/ctr.h> #include <crypto/des.h> diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index dc641c796526..921039e56f87 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -124,6 +124,9 @@ struct talitos_private { void __iomem *reg; int irq[2]; + /* SEC global registers lock */ + spinlock_t reg_lock ____cacheline_aligned; + /* SEC version geometry (from device tree node) */ unsigned int num_channels; unsigned int chfifo_len; @@ -412,6 +415,7 @@ static void talitos_done_##name(unsigned long data) \ { \ struct device *dev = (struct device *)data; \ struct talitos_private *priv = dev_get_drvdata(dev); \ + unsigned long flags; \ \ if (ch_done_mask & 1) \ flush_channel(dev, 0, 0, 0); \ @@ -427,8 +431,10 @@ static void talitos_done_##name(unsigned long data) \ out: \ /* At this point, all completed channels have been processed */ \ /* Unmask done interrupts for channels completed later on. */ \ + spin_lock_irqsave(&priv->reg_lock, flags); \ setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT); \ + spin_unlock_irqrestore(&priv->reg_lock, flags); \ } DEF_TALITOS_DONE(4ch, TALITOS_ISR_4CHDONE) DEF_TALITOS_DONE(ch0_2, TALITOS_ISR_CH_0_2_DONE) @@ -619,22 +625,28 @@ static irqreturn_t talitos_interrupt_##name(int irq, void *data) \ struct device *dev = data; \ struct talitos_private *priv = dev_get_drvdata(dev); \ u32 isr, isr_lo; \ + unsigned long flags; \ \ + spin_lock_irqsave(&priv->reg_lock, flags); \ isr = in_be32(priv->reg + TALITOS_ISR); \ isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \ /* Acknowledge interrupt */ \ out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \ out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \ \ - if (unlikely((isr & ~TALITOS_ISR_4CHDONE) & ch_err_mask || isr_lo)) \ - talitos_error(dev, isr, isr_lo); \ - else \ + if (unlikely(isr & ch_err_mask || isr_lo)) { \ + spin_unlock_irqrestore(&priv->reg_lock, flags); \ + talitos_error(dev, isr & ch_err_mask, isr_lo); \ + } \ + else { \ if (likely(isr & ch_done_mask)) { \ /* mask further done interrupts. */ \ clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ /* done_task will unmask done interrupts at exit */ \ tasklet_schedule(&priv->done_task[tlet]); \ } \ + spin_unlock_irqrestore(&priv->reg_lock, flags); \ + } \ \ return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \ IRQ_NONE; \ @@ -2719,6 +2731,8 @@ static int talitos_probe(struct platform_device *ofdev) priv->ofdev = ofdev; + spin_lock_init(&priv->reg_lock); + err = talitos_probe_irq(ofdev); if (err) goto err_out; diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index cf9da362d64f..ef378b5b17e4 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -91,11 +91,10 @@ config DW_DMAC config AT_HDMAC tristate "Atmel AHB DMA support" - depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 + depends on ARCH_AT91 select DMA_ENGINE help - Support the Atmel AHB DMA controller. This can be integrated in - chips such as the Atmel AT91SAM9RL. + Support the Atmel AHB DMA controller. config FSL_DMA tristate "Freescale Elo and Elo Plus DMA support" diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/gpio/gpio-nomadik.c index 839624f9fe6a..9b126b6d79cc 100644 --- a/drivers/gpio/gpio-nomadik.c +++ b/drivers/gpio/gpio-nomadik.c @@ -22,14 +22,13 @@ #include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/irqdomain.h> #include <linux/slab.h> #include <asm/mach/irq.h> #include <plat/pincfg.h> #include <plat/gpio-nomadik.h> -#include <mach/hardware.h> -#include <asm/gpio.h> /* * The GPIO module in the Nomadik family of Systems-on-Chip is an @@ -43,6 +42,7 @@ struct nmk_gpio_chip { struct gpio_chip chip; + struct irq_domain *domain; void __iomem *addr; struct clk *clk; unsigned int bank; @@ -58,8 +58,10 @@ struct nmk_gpio_chip { u32 real_wake; u32 rwimsc; u32 fwimsc; - u32 slpm; + u32 rimsc; + u32 fimsc; u32 pull_up; + u32 lowemi; }; static struct nmk_gpio_chip * @@ -124,6 +126,24 @@ static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip, } } +static void __nmk_gpio_set_lowemi(struct nmk_gpio_chip *nmk_chip, + unsigned offset, bool lowemi) +{ + u32 bit = BIT(offset); + bool enabled = nmk_chip->lowemi & bit; + + if (lowemi == enabled) + return; + + if (lowemi) + nmk_chip->lowemi |= bit; + else + nmk_chip->lowemi &= ~bit; + + writel_relaxed(nmk_chip->lowemi, + nmk_chip->addr + NMK_GPIO_LOWEMI); +} + static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip, unsigned offset) { @@ -150,8 +170,8 @@ static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip, unsigned offset, int gpio_mode, bool glitch) { - u32 rwimsc = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); - u32 fwimsc = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); + u32 rwimsc = nmk_chip->rwimsc; + u32 fwimsc = nmk_chip->fwimsc; if (glitch && nmk_chip->set_ioforce) { u32 bit = BIT(offset); @@ -173,6 +193,36 @@ static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip, } } +static void +nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset) +{ + u32 falling = nmk_chip->fimsc & BIT(offset); + u32 rising = nmk_chip->rimsc & BIT(offset); + int gpio = nmk_chip->chip.base + offset; + int irq = NOMADIK_GPIO_TO_IRQ(gpio); + struct irq_data *d = irq_get_irq_data(irq); + + if (!rising && !falling) + return; + + if (!d || !irqd_irq_disabled(d)) + return; + + if (rising) { + nmk_chip->rimsc &= ~BIT(offset); + writel_relaxed(nmk_chip->rimsc, + nmk_chip->addr + NMK_GPIO_RIMSC); + } + + if (falling) { + nmk_chip->fimsc &= ~BIT(offset); + writel_relaxed(nmk_chip->fimsc, + nmk_chip->addr + NMK_GPIO_FIMSC); + } + + dev_dbg(nmk_chip->chip.dev, "%d: clearing interrupt mask\n", gpio); +} + static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, pin_cfg_t cfg, bool sleep, unsigned int *slpmregs) { @@ -238,6 +288,17 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, __nmk_gpio_set_pull(nmk_chip, offset, pull); } + __nmk_gpio_set_lowemi(nmk_chip, offset, PIN_LOWEMI(cfg)); + + /* + * If the pin is switching to altfunc, and there was an interrupt + * installed on it which has been lazy disabled, actually mask the + * interrupt to prevent spurious interrupts that would occur while the + * pin is under control of the peripheral. Only SKE does this. + */ + if (af != NMK_GPIO_ALT_GPIO) + nmk_gpio_disable_lazy_irq(nmk_chip, offset); + /* * If we've backed up the SLPM registers (glitch workaround), modify * the backups since they will be restored. @@ -334,7 +395,7 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep) struct nmk_gpio_chip *nmk_chip; int pin = PIN_NUM(cfgs[i]); - nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(pin)); + nmk_chip = nmk_gpio_chips[pin / NMK_GPIO_PER_CHIP]; if (!nmk_chip) { ret = -EINVAL; break; @@ -342,7 +403,7 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep) clk_enable(nmk_chip->clk); spin_lock(&nmk_chip->lock); - __nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base, + __nmk_config_pin(nmk_chip, pin % NMK_GPIO_PER_CHIP, cfgs[i], sleep, glitch ? slpm : NULL); spin_unlock(&nmk_chip->lock); clk_disable(nmk_chip->clk); @@ -426,7 +487,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) struct nmk_gpio_chip *nmk_chip; unsigned long flags; - nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); + nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP]; if (!nmk_chip) return -EINVAL; @@ -434,7 +495,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); spin_lock(&nmk_chip->lock); - __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, mode); + __nmk_gpio_set_slpm(nmk_chip, gpio % NMK_GPIO_PER_CHIP, mode); spin_unlock(&nmk_chip->lock); spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); @@ -461,13 +522,13 @@ int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull) struct nmk_gpio_chip *nmk_chip; unsigned long flags; - nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); + nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP]; if (!nmk_chip) return -EINVAL; clk_enable(nmk_chip->clk); spin_lock_irqsave(&nmk_chip->lock, flags); - __nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull); + __nmk_gpio_set_pull(nmk_chip, gpio % NMK_GPIO_PER_CHIP, pull); spin_unlock_irqrestore(&nmk_chip->lock, flags); clk_disable(nmk_chip->clk); @@ -489,13 +550,13 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode) struct nmk_gpio_chip *nmk_chip; unsigned long flags; - nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); + nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP]; if (!nmk_chip) return -EINVAL; clk_enable(nmk_chip->clk); spin_lock_irqsave(&nmk_chip->lock, flags); - __nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode); + __nmk_gpio_set_mode(nmk_chip, gpio % NMK_GPIO_PER_CHIP, gpio_mode); spin_unlock_irqrestore(&nmk_chip->lock, flags); clk_disable(nmk_chip->clk); @@ -508,11 +569,11 @@ int nmk_gpio_get_mode(int gpio) struct nmk_gpio_chip *nmk_chip; u32 afunc, bfunc, bit; - nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); + nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP]; if (!nmk_chip) return -EINVAL; - bit = 1 << (gpio - nmk_chip->chip.base); + bit = 1 << (gpio % NMK_GPIO_PER_CHIP); clk_enable(nmk_chip->clk); @@ -529,21 +590,19 @@ EXPORT_SYMBOL(nmk_gpio_get_mode); /* IRQ functions */ static inline int nmk_gpio_get_bitmask(int gpio) { - return 1 << (gpio % 32); + return 1 << (gpio % NMK_GPIO_PER_CHIP); } static void nmk_gpio_irq_ack(struct irq_data *d) { - int gpio; struct nmk_gpio_chip *nmk_chip; - gpio = NOMADIK_IRQ_TO_GPIO(d->irq); nmk_chip = irq_data_get_irq_chip_data(d); if (!nmk_chip) return; clk_enable(nmk_chip->clk); - writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); + writel(nmk_gpio_get_bitmask(d->hwirq), nmk_chip->addr + NMK_GPIO_IC); clk_disable(nmk_chip->clk); } @@ -556,37 +615,52 @@ static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip, int gpio, enum nmk_gpio_irq_type which, bool enable) { - u32 rimsc = which == WAKE ? NMK_GPIO_RWIMSC : NMK_GPIO_RIMSC; - u32 fimsc = which == WAKE ? NMK_GPIO_FWIMSC : NMK_GPIO_FIMSC; u32 bitmask = nmk_gpio_get_bitmask(gpio); - u32 reg; + u32 *rimscval; + u32 *fimscval; + u32 rimscreg; + u32 fimscreg; + + if (which == NORMAL) { + rimscreg = NMK_GPIO_RIMSC; + fimscreg = NMK_GPIO_FIMSC; + rimscval = &nmk_chip->rimsc; + fimscval = &nmk_chip->fimsc; + } else { + rimscreg = NMK_GPIO_RWIMSC; + fimscreg = NMK_GPIO_FWIMSC; + rimscval = &nmk_chip->rwimsc; + fimscval = &nmk_chip->fwimsc; + } /* we must individually set/clear the two edges */ if (nmk_chip->edge_rising & bitmask) { - reg = readl(nmk_chip->addr + rimsc); if (enable) - reg |= bitmask; + *rimscval |= bitmask; else - reg &= ~bitmask; - writel(reg, nmk_chip->addr + rimsc); + *rimscval &= ~bitmask; + writel(*rimscval, nmk_chip->addr + rimscreg); } if (nmk_chip->edge_falling & bitmask) { - reg = readl(nmk_chip->addr + fimsc); if (enable) - reg |= bitmask; + *fimscval |= bitmask; else - reg &= ~bitmask; - writel(reg, nmk_chip->addr + fimsc); + *fimscval &= ~bitmask; + writel(*fimscval, nmk_chip->addr + fimscreg); } } static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip, int gpio, bool on) { - if (nmk_chip->sleepmode) { - __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, - on ? NMK_GPIO_SLPM_WAKEUP_ENABLE - : NMK_GPIO_SLPM_WAKEUP_DISABLE); + /* + * Ensure WAKEUP_ENABLE is on. No need to disable it if wakeup is + * disabled, since setting SLPM to 1 increases power consumption, and + * wakeup is anyhow controlled by the RIMSC and FIMSC registers. + */ + if (nmk_chip->sleepmode && on) { + __nmk_gpio_set_slpm(nmk_chip, gpio % nmk_chip->chip.base, + NMK_GPIO_SLPM_WAKEUP_ENABLE); } __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on); @@ -594,14 +668,12 @@ static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip, static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable) { - int gpio; struct nmk_gpio_chip *nmk_chip; unsigned long flags; u32 bitmask; - gpio = NOMADIK_IRQ_TO_GPIO(d->irq); nmk_chip = irq_data_get_irq_chip_data(d); - bitmask = nmk_gpio_get_bitmask(gpio); + bitmask = nmk_gpio_get_bitmask(d->hwirq); if (!nmk_chip) return -EINVAL; @@ -609,10 +681,10 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable) spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); spin_lock(&nmk_chip->lock); - __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, enable); + __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, enable); if (!(nmk_chip->real_wake & bitmask)) - __nmk_gpio_set_wake(nmk_chip, gpio, enable); + __nmk_gpio_set_wake(nmk_chip, d->hwirq, enable); spin_unlock(&nmk_chip->lock); spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); @@ -636,20 +708,18 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) struct nmk_gpio_chip *nmk_chip; unsigned long flags; u32 bitmask; - int gpio; - gpio = NOMADIK_IRQ_TO_GPIO(d->irq); nmk_chip = irq_data_get_irq_chip_data(d); if (!nmk_chip) return -EINVAL; - bitmask = nmk_gpio_get_bitmask(gpio); + bitmask = nmk_gpio_get_bitmask(d->hwirq); clk_enable(nmk_chip->clk); spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); spin_lock(&nmk_chip->lock); if (irqd_irq_disabled(d)) - __nmk_gpio_set_wake(nmk_chip, gpio, on); + __nmk_gpio_set_wake(nmk_chip, d->hwirq, on); if (on) nmk_chip->real_wake |= bitmask; @@ -667,17 +737,14 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) { bool enabled = !irqd_irq_disabled(d); bool wake = irqd_is_wakeup_set(d); - int gpio; struct nmk_gpio_chip *nmk_chip; unsigned long flags; u32 bitmask; - gpio = NOMADIK_IRQ_TO_GPIO(d->irq); nmk_chip = irq_data_get_irq_chip_data(d); - bitmask = nmk_gpio_get_bitmask(gpio); + bitmask = nmk_gpio_get_bitmask(d->hwirq); if (!nmk_chip) return -EINVAL; - if (type & IRQ_TYPE_LEVEL_HIGH) return -EINVAL; if (type & IRQ_TYPE_LEVEL_LOW) @@ -687,10 +754,10 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) spin_lock_irqsave(&nmk_chip->lock, flags); if (enabled) - __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false); + __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, false); if (enabled || wake) - __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false); + __nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, false); nmk_chip->edge_rising &= ~bitmask; if (type & IRQ_TYPE_EDGE_RISING) @@ -701,10 +768,10 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) nmk_chip->edge_falling |= bitmask; if (enabled) - __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true); + __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, true); if (enabled || wake) - __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true); + __nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, true); spin_unlock_irqrestore(&nmk_chip->lock, flags); clk_disable(nmk_chip->clk); @@ -750,7 +817,7 @@ static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, chained_irq_enter(host_chip, desc); nmk_chip = irq_get_handler_data(irq); - first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); + first_irq = nmk_chip->domain->revmap_data.legacy.first_irq; while (status) { int bit = __ffs(status); @@ -784,18 +851,6 @@ static void nmk_gpio_secondary_irq_handler(unsigned int irq, static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) { - unsigned int first_irq; - int i; - - first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); - for (i = first_irq; i < first_irq + nmk_chip->chip.ngpio; i++) { - irq_set_chip_and_handler(i, &nmk_gpio_irq_chip, - handle_edge_irq); - set_irq_flags(i, IRQF_VALID); - irq_set_chip_data(i, nmk_chip); - irq_set_irq_type(i, IRQ_TYPE_EDGE_FALLING); - } - irq_set_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler); irq_set_handler_data(nmk_chip->parent_irq, nmk_chip); @@ -872,7 +927,7 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset) struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); - return NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base) + offset; + return irq_find_mapping(nmk_chip->domain, offset); } #ifdef CONFIG_DEBUG_FS @@ -1008,21 +1063,11 @@ void nmk_gpio_wakeups_suspend(void) clk_enable(chip->clk); - chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC); - chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC); - writel(chip->rwimsc & chip->real_wake, chip->addr + NMK_GPIO_RWIMSC); writel(chip->fwimsc & chip->real_wake, chip->addr + NMK_GPIO_FWIMSC); - if (chip->sleepmode) { - chip->slpm = readl(chip->addr + NMK_GPIO_SLPC); - - /* 0 -> wakeup enable */ - writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC); - } - clk_disable(chip->clk); } } @@ -1042,9 +1087,6 @@ void nmk_gpio_wakeups_resume(void) writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC); writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC); - if (chip->sleepmode) - writel(chip->slpm, chip->addr + NMK_GPIO_SLPC); - clk_disable(chip->clk); } } @@ -1068,19 +1110,62 @@ void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up) } } +int nmk_gpio_irq_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hwirq) +{ + struct nmk_gpio_chip *nmk_chip = d->host_data; + + if (!nmk_chip) + return -EINVAL; + + irq_set_chip_and_handler(irq, &nmk_gpio_irq_chip, handle_edge_irq); + set_irq_flags(irq, IRQF_VALID); + irq_set_chip_data(irq, nmk_chip); + irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); + + return 0; +} + +const struct irq_domain_ops nmk_gpio_irq_simple_ops = { + .map = nmk_gpio_irq_map, + .xlate = irq_domain_xlate_twocell, +}; + static int __devinit nmk_gpio_probe(struct platform_device *dev) { struct nmk_gpio_platform_data *pdata = dev->dev.platform_data; + struct device_node *np = dev->dev.of_node; struct nmk_gpio_chip *nmk_chip; struct gpio_chip *chip; struct resource *res; struct clk *clk; int secondary_irq; + void __iomem *base; int irq; int ret; - if (!pdata) + if (!pdata && !np) { + dev_err(&dev->dev, "No platform data or device tree found\n"); return -ENODEV; + } + + if (np) { + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + if (of_get_property(np, "supports-sleepmode", NULL)) + pdata->supports_sleepmode = true; + + if (of_property_read_u32(np, "gpio-bank", &dev->id)) { + dev_err(&dev->dev, "gpio-bank property not found\n"); + ret = -EINVAL; + goto out; + } + + pdata->first_gpio = dev->id * NMK_GPIO_PER_CHIP; + pdata->num_gpio = NMK_GPIO_PER_CHIP; + } res = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res) { @@ -1106,10 +1191,16 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) goto out; } + base = ioremap(res->start, resource_size(res)); + if (!base) { + ret = -ENOMEM; + goto out_release; + } + clk = clk_get(&dev->dev, NULL); if (IS_ERR(clk)) { ret = PTR_ERR(clk); - goto out_release; + goto out_unmap; } nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); @@ -1117,13 +1208,14 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) ret = -ENOMEM; goto out_clk; } + /* * The virt address in nmk_chip->addr is in the nomadik register space, * so we can simply convert the resource address, without remapping */ nmk_chip->bank = dev->id; nmk_chip->clk = clk; - nmk_chip->addr = io_p2v(res->start); + nmk_chip->addr = base; nmk_chip->chip = nmk_gpio_template; nmk_chip->parent_irq = irq; nmk_chip->secondary_parent_irq = secondary_irq; @@ -1139,6 +1231,12 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) chip->dev = &dev->dev; chip->owner = THIS_MODULE; + clk_enable(nmk_chip->clk); + nmk_chip->lowemi = readl_relaxed(nmk_chip->addr + NMK_GPIO_LOWEMI); + clk_disable(nmk_chip->clk); + + chip->of_node = np; + ret = gpiochip_add(&nmk_chip->chip); if (ret) goto out_free; @@ -1146,12 +1244,22 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips)); nmk_gpio_chips[nmk_chip->bank] = nmk_chip; + platform_set_drvdata(dev, nmk_chip); + nmk_chip->domain = irq_domain_add_legacy(np, NMK_GPIO_PER_CHIP, + NOMADIK_GPIO_TO_IRQ(pdata->first_gpio), + 0, &nmk_gpio_irq_simple_ops, nmk_chip); + if (!nmk_chip->domain) { + pr_err("%s: Failed to create irqdomain\n", np->full_name); + ret = -ENOSYS; + goto out_free; + } + nmk_gpio_init_irq(nmk_chip); - dev_info(&dev->dev, "at address %p\n", - nmk_chip->addr); + dev_info(&dev->dev, "at address %p\n", nmk_chip->addr); + return 0; out_free: @@ -1159,18 +1267,29 @@ out_free: out_clk: clk_disable(clk); clk_put(clk); +out_unmap: + iounmap(base); out_release: release_mem_region(res->start, resource_size(res)); out: dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret, pdata->first_gpio, pdata->first_gpio+31); + if (np) + kfree(pdata); + return ret; } +static const struct of_device_id nmk_gpio_match[] = { + { .compatible = "st,nomadik-gpio", }, + {} +}; + static struct platform_driver nmk_gpio_driver = { .driver = { .owner = THIS_MODULE, .name = "gpio", + .of_match_table = nmk_gpio_match, }, .probe = nmk_gpio_probe, }; diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 30372f7b2d45..348b367debeb 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -1510,8 +1510,8 @@ int drm_freebufs(struct drm_device *dev, void *data, * \param arg pointer to a drm_buf_map structure. * \return zero on success or a negative number on failure. * - * Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information - * about each buffer into user space. For PCI buffers, it calls do_mmap() with + * Maps the AGP, SG or PCI buffer region with vm_mmap(), and copies information + * about each buffer into user space. For PCI buffers, it calls vm_mmap() with * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls * drm_mmap_dma(). */ @@ -1553,18 +1553,14 @@ int drm_mapbufs(struct drm_device *dev, void *data, retcode = -EINVAL; goto done; } - down_write(¤t->mm->mmap_sem); - virtual = do_mmap(file_priv->filp, 0, map->size, + virtual = vm_mmap(file_priv->filp, 0, map->size, PROT_READ | PROT_WRITE, MAP_SHARED, token); - up_write(¤t->mm->mmap_sem); } else { - down_write(¤t->mm->mmap_sem); - virtual = do_mmap(file_priv->filp, 0, dma->byte_count, + virtual = vm_mmap(file_priv->filp, 0, dma->byte_count, PROT_READ | PROT_WRITE, MAP_SHARED, 0); - up_write(¤t->mm->mmap_sem); } if (virtual > -1024UL) { /* Real error */ diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index d3aaeb6ae236..c79870a75c2f 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -3335,10 +3335,12 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, ret = crtc->funcs->page_flip(crtc, fb, e); if (ret) { - spin_lock_irqsave(&dev->event_lock, flags); - file_priv->event_space += sizeof e->event; - spin_unlock_irqrestore(&dev->event_lock, flags); - kfree(e); + if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { + spin_lock_irqsave(&dev->event_lock, flags); + file_priv->event_space += sizeof e->event; + spin_unlock_irqrestore(&dev->event_lock, flags); + kfree(e); + } } out: diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index cdfbf27b2b3c..123de28f94ef 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -507,12 +507,12 @@ int drm_release(struct inode *inode, struct file *filp) drm_events_release(file_priv); - if (dev->driver->driver_features & DRIVER_GEM) - drm_gem_release(dev, file_priv); - if (dev->driver->driver_features & DRIVER_MODESET) drm_fb_release(file_priv); + if (dev->driver->driver_features & DRIVER_GEM) + drm_gem_release(dev, file_priv); + mutex_lock(&dev->ctxlist_mutex); if (!list_empty(&dev->ctxlist)) { struct drm_ctx_list *pos, *n; diff --git a/drivers/gpu/drm/drm_usb.c b/drivers/gpu/drm/drm_usb.c index c8c83dad2ce1..37c9a523dd1c 100644 --- a/drivers/gpu/drm/drm_usb.c +++ b/drivers/gpu/drm/drm_usb.c @@ -1,6 +1,6 @@ #include "drmP.h" #include <linux/usb.h> -#include <linux/export.h> +#include <linux/module.h> int drm_get_usb_dev(struct usb_interface *interface, const struct usb_device_id *id, @@ -114,3 +114,7 @@ void drm_usb_exit(struct drm_driver *driver, usb_deregister(udriver); } EXPORT_SYMBOL(drm_usb_exit); + +MODULE_AUTHOR("David Airlie"); +MODULE_DESCRIPTION("USB DRM support"); +MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 26d51979116b..392ce71ed6a1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -581,10 +581,8 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, obj->filp->f_op = &exynos_drm_gem_fops; obj->filp->private_data = obj; - down_write(¤t->mm->mmap_sem); - addr = do_mmap(obj->filp, 0, args->size, + addr = vm_mmap(obj->filp, 0, args->size, PROT_READ | PROT_WRITE, MAP_SHARED, 0); - up_write(¤t->mm->mmap_sem); drm_gem_object_unreference_unlocked(obj); diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.h b/drivers/gpu/drm/gma500/mdfld_dsi_output.h index 21071cef92a4..36eb0744841c 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.h +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.h @@ -29,7 +29,6 @@ #define __MDFLD_DSI_OUTPUT_H__ #include <linux/backlight.h> -#include <linux/version.h> #include <drm/drmP.h> #include <drm/drm.h> #include <drm/drm_crtc.h> diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index 2c8a60c3b98e..f920fb5e42b6 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -129,6 +129,7 @@ static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv) if (buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL; + /* This is all entirely broken */ down_write(¤t->mm->mmap_sem); old_fops = file_priv->filp->f_op; file_priv->filp->f_op = &i810_buffer_fops; @@ -157,11 +158,8 @@ static int i810_unmap_buffer(struct drm_buf *buf) if (buf_priv->currently_mapped != I810_BUF_MAPPED) return -EINVAL; - down_write(¤t->mm->mmap_sem); - retcode = do_munmap(current->mm, - (unsigned long)buf_priv->virtual, + retcode = vm_munmap((unsigned long)buf_priv->virtual, (size_t) buf->total); - up_write(¤t->mm->mmap_sem); buf_priv->currently_mapped = I810_BUF_UNMAPPED; buf_priv->virtual = NULL; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0e3c6acde955..0d1e4b7b4b99 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1087,11 +1087,9 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, if (obj == NULL) return -ENOENT; - down_write(¤t->mm->mmap_sem); - addr = do_mmap(obj->filp, 0, args->size, + addr = vm_mmap(obj->filp, 0, args->size, PROT_READ | PROT_WRITE, MAP_SHARED, args->offset); - up_write(¤t->mm->mmap_sem); drm_gem_object_unreference_unlocked(obj); if (IS_ERR((void *)addr)) return addr; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bae38acf44dc..5908cd563400 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3478,8 +3478,11 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, return false; } - /* All interlaced capable intel hw wants timings in frames. */ - drm_mode_set_crtcinfo(adjusted_mode, 0); + /* All interlaced capable intel hw wants timings in frames. Note though + * that intel_lvds_mode_fixup does some funny tricks with the crtc + * timings, so we need to be careful not to clobber these.*/ + if (!(adjusted_mode->private_flags & INTEL_MODE_CRTC_TIMINGS_SET)) + drm_mode_set_crtcinfo(adjusted_mode, 0); return true; } @@ -7465,7 +7468,13 @@ static int intel_gen6_queue_flip(struct drm_device *dev, OUT_RING(fb->pitches[0] | obj->tiling_mode); OUT_RING(obj->gtt_offset); - pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE; + /* Contrary to the suggestions in the documentation, + * "Enable Panel Fitter" does not seem to be required when page + * flipping with a non-native mode, and worse causes a normal + * modeset to fail. + * pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE; + */ + pf = 0; pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; OUT_RING(pf | pipesrc); ADVANCE_LP_RING(); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5a14149b3794..715afa153025 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -105,6 +105,10 @@ #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0) #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT) #define INTEL_MODE_DP_FORCE_6BPC (0x10) +/* This flag must be set by the encoder's mode_fixup if it changes the crtc + * timings in the mode to prevent the crtc fixup from overwriting them. + * Currently only lvds needs that. */ +#define INTEL_MODE_CRTC_TIMINGS_SET (0x20) static inline void intel_mode_set_pixel_multiplier(struct drm_display_mode *mode, diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 19ecd78b8a2c..6e9ee33fd412 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -279,6 +279,8 @@ void intel_fb_restore_mode(struct drm_device *dev) struct drm_mode_config *config = &dev->mode_config; struct drm_plane *plane; + mutex_lock(&dev->mode_config.mutex); + ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper); if (ret) DRM_DEBUG("failed to restore crtc mode\n"); @@ -286,4 +288,6 @@ void intel_fb_restore_mode(struct drm_device *dev) /* Be sure to shut off any planes that may be active */ list_for_each_entry(plane, &config->plane_list, head) plane->funcs->disable_plane(plane); + + mutex_unlock(&dev->mode_config.mutex); } diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 95db2e988227..30e2c82101de 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -187,6 +187,8 @@ centre_horizontally(struct drm_display_mode *mode, mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos; mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width; + + mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET; } static void @@ -208,6 +210,8 @@ centre_vertically(struct drm_display_mode *mode, mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos; mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width; + + mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET; } static inline u32 panel_fitter_scaling(u32 source, u32 target) @@ -283,6 +287,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, for_each_pipe(pipe) I915_WRITE(BCLRPAT(pipe), 0); + drm_mode_set_crtcinfo(adjusted_mode, 0); + switch (intel_lvds->fitting_mode) { case DRM_MODE_SCALE_CENTER: /* diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 230a141dbea3..48177ec4720e 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -47,8 +47,6 @@ intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, adjusted_mode->vtotal = fixed_mode->vtotal; adjusted_mode->clock = fixed_mode->clock; - - drm_mode_set_crtcinfo(adjusted_mode, 0); } /* adjusted_mode has been preset to be the panel's fixed mode */ diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index 34d591b7d4ef..da3e7c3abab7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -235,6 +235,7 @@ nouveau_pm_profile_set(struct drm_device *dev, const char *profile) return -EPERM; strncpy(string, profile, sizeof(string)); + string[sizeof(string) - 1] = 0; if ((ptr = strchr(string, '\n'))) *ptr = '\0'; diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index a7844ab6a50c..274640212475 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c @@ -42,7 +42,7 @@ nv50_sor_dp_lane_map(struct drm_device *dev, struct dcb_entry *dcb, u8 lane) struct drm_nouveau_private *dev_priv = dev->dev_private; static const u8 nvaf[] = { 24, 16, 8, 0 }; /* thanks, apple.. */ static const u8 nv50[] = { 16, 8, 0, 24 }; - if (dev_priv->card_type == 0xaf) + if (dev_priv->chipset == 0xaf) return nvaf[lane]; return nv50[lane]; } diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index de71243b591f..c8187c4b6ae8 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1135,7 +1135,7 @@ static void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc } if (rdev->flags & RADEON_IS_AGP) { size_bf = mc->gtt_start; - size_af = 0xFFFFFFFF - mc->gtt_end + 1; + size_af = 0xFFFFFFFF - mc->gtt_end; if (size_bf > size_af) { if (mc->mc_vram_size > size_bf) { dev_warn(rdev->dev, "limiting VRAM\n"); @@ -1149,7 +1149,7 @@ static void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc mc->real_vram_size = size_af; mc->mc_vram_size = size_af; } - mc->vram_start = mc->gtt_end; + mc->vram_start = mc->gtt_end + 1; } mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n", diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index bd05156edbdb..3c2e7a000a2a 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -970,7 +970,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) encoder = obj_to_encoder(obj); - if (encoder->encoder_type != DRM_MODE_ENCODER_DAC || + if (encoder->encoder_type != DRM_MODE_ENCODER_DAC && encoder->encoder_type != DRM_MODE_ENCODER_TVDAC) continue; @@ -1000,6 +1000,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) * cases the DVI port is actually a virtual KVM port connected to the service * processor. */ +out: if ((!rdev->is_atom_bios) && (ret == connector_status_disconnected) && rdev->mode_info.bios_hardcoded_edid_size) { @@ -1007,7 +1008,6 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) ret = connector_status_connected; } -out: /* updated in get modes as well since we need to know if it's analog or digital */ radeon_connector_update_scratch_regs(connector, ret); return ret; diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 66d5fe1c8174..65060b77c805 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -147,6 +147,12 @@ static bool radeon_msi_ok(struct radeon_device *rdev) (rdev->pdev->subsystem_device == 0x01fd)) return true; + /* RV515 seems to have MSI issues where it loses + * MSI rearms occasionally. This leads to lockups and freezes. + * disable it by default. + */ + if (rdev->family == CHIP_RV515) + return false; if (rdev->flags & RADEON_IS_IGP) { /* APUs work fine with MSIs */ if (rdev->family >= CHIP_PALM) diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index c62ae4be3845..cdab1aeaed6e 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -969,7 +969,7 @@ void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) } if (rdev->flags & RADEON_IS_AGP) { size_bf = mc->gtt_start; - size_af = 0xFFFFFFFF - mc->gtt_end + 1; + size_af = 0xFFFFFFFF - mc->gtt_end; if (size_bf > size_af) { if (mc->mc_vram_size > size_bf) { dev_warn(rdev->dev, "limiting VRAM\n"); @@ -983,7 +983,7 @@ void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) mc->real_vram_size = size_af; mc->mc_vram_size = size_af; } - mc->vram_start = mc->gtt_end; + mc->vram_start = mc->gtt_end + 1; } mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n", diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index ac7a199ffece..27bda986fc2b 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2999,8 +2999,8 @@ int si_rlc_init(struct radeon_device *rdev) } r = radeon_bo_pin(rdev->rlc.save_restore_obj, RADEON_GEM_DOMAIN_VRAM, &rdev->rlc.save_restore_gpu_addr); + radeon_bo_unreserve(rdev->rlc.save_restore_obj); if (r) { - radeon_bo_unreserve(rdev->rlc.save_restore_obj); dev_warn(rdev->dev, "(%d) pin RLC sr bo failed\n", r); si_rlc_fini(rdev); return r; @@ -3023,9 +3023,8 @@ int si_rlc_init(struct radeon_device *rdev) } r = radeon_bo_pin(rdev->rlc.clear_state_obj, RADEON_GEM_DOMAIN_VRAM, &rdev->rlc.clear_state_gpu_addr); + radeon_bo_unreserve(rdev->rlc.clear_state_obj); if (r) { - - radeon_bo_unreserve(rdev->rlc.clear_state_obj); dev_warn(rdev->dev, "(%d) pin RLC c bo failed\n", r); si_rlc_fini(rdev); return r; diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index a3d033252995..ffddcba32af6 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -34,7 +34,7 @@ config HID config HID_BATTERY_STRENGTH bool depends on HID && POWER_SUPPLY && HID = POWER_SUPPLY - default y + default n config HIDRAW bool "/dev/hidraw raw HID device support" diff --git a/drivers/hid/hid-tivo.c b/drivers/hid/hid-tivo.c index de47039c708c..9f85f827607f 100644 --- a/drivers/hid/hid-tivo.c +++ b/drivers/hid/hid-tivo.c @@ -62,7 +62,7 @@ static int tivo_input_mapping(struct hid_device *hdev, struct hid_input *hi, static const struct hid_device_id tivo_devices[] = { /* TiVo Slide Bluetooth remote, pairs with a Broadcom dongle */ - { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) }, { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) }, { } }; diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c index 7765e4f74ec5..1958f03efd7a 100644 --- a/drivers/hwmon/ads1015.c +++ b/drivers/hwmon/ads1015.c @@ -59,14 +59,11 @@ struct ads1015_data { struct ads1015_channel_data channel_data[ADS1015_CHANNELS]; }; -static int ads1015_read_value(struct i2c_client *client, unsigned int channel, - int *value) +static int ads1015_read_adc(struct i2c_client *client, unsigned int channel) { u16 config; - s16 conversion; struct ads1015_data *data = i2c_get_clientdata(client); unsigned int pga = data->channel_data[channel].pga; - int fullscale; unsigned int data_rate = data->channel_data[channel].data_rate; unsigned int conversion_time_ms; int res; @@ -78,7 +75,6 @@ static int ads1015_read_value(struct i2c_client *client, unsigned int channel, if (res < 0) goto err_unlock; config = res; - fullscale = fullscale_table[pga]; conversion_time_ms = DIV_ROUND_UP(1000, data_rate_table[data_rate]); /* setup and start single conversion */ @@ -105,33 +101,36 @@ static int ads1015_read_value(struct i2c_client *client, unsigned int channel, } res = i2c_smbus_read_word_swapped(client, ADS1015_CONVERSION); - if (res < 0) - goto err_unlock; - conversion = res; - - mutex_unlock(&data->update_lock); - - *value = DIV_ROUND_CLOSEST(conversion * fullscale, 0x7ff0); - - return 0; err_unlock: mutex_unlock(&data->update_lock); return res; } +static int ads1015_reg_to_mv(struct i2c_client *client, unsigned int channel, + s16 reg) +{ + struct ads1015_data *data = i2c_get_clientdata(client); + unsigned int pga = data->channel_data[channel].pga; + int fullscale = fullscale_table[pga]; + + return DIV_ROUND_CLOSEST(reg * fullscale, 0x7ff0); +} + /* sysfs callback function */ static ssize_t show_in(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct i2c_client *client = to_i2c_client(dev); - int in; int res; + int index = attr->index; - res = ads1015_read_value(client, attr->index, &in); + res = ads1015_read_adc(client, index); + if (res < 0) + return res; - return (res < 0) ? res : sprintf(buf, "%d\n", in); + return sprintf(buf, "%d\n", ads1015_reg_to_mv(client, index, res)); } static const struct sensor_device_attribute ads1015_in[] = { diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index b7494af1e4a9..37a8fc92b44a 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -122,6 +122,38 @@ static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4) return true; } +/* + * Newer BKDG versions have an updated recommendation on how to properly + * initialize the running average range (was: 0xE, now: 0x9). This avoids + * counter saturations resulting in bogus power readings. + * We correct this value ourselves to cope with older BIOSes. + */ +static void __devinit tweak_runavg_range(struct pci_dev *pdev) +{ + u32 val; + const struct pci_device_id affected_device = { + PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }; + + /* + * let this quirk apply only to the current version of the + * northbridge, since future versions may change the behavior + */ + if (!pci_match_id(&affected_device, pdev)) + return; + + pci_bus_read_config_dword(pdev->bus, + PCI_DEVFN(PCI_SLOT(pdev->devfn), 5), + REG_TDP_RUNNING_AVERAGE, &val); + if ((val & 0xf) != 0xe) + return; + + val &= ~0xf; + val |= 0x9; + pci_bus_write_config_dword(pdev->bus, + PCI_DEVFN(PCI_SLOT(pdev->devfn), 5), + REG_TDP_RUNNING_AVERAGE, val); +} + static void __devinit fam15h_power_init_data(struct pci_dev *f4, struct fam15h_power_data *data) { @@ -155,6 +187,13 @@ static int __devinit fam15h_power_probe(struct pci_dev *pdev, struct device *dev; int err; + /* + * though we ignore every other northbridge, we still have to + * do the tweaking on _each_ node in MCM processors as the counters + * are working hand-in-hand + */ + tweak_runavg_range(pdev); + if (!fam15h_power_is_internal_node0(pdev)) { err = -ENODEV; goto exit; diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 2d787796bf50..7faf4a7fcaa9 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -380,8 +380,7 @@ config INPUT_TWL4030_VIBRA config INPUT_TWL6040_VIBRA tristate "Support for TWL6040 Vibrator" - depends on TWL4030_CORE - select TWL6040_CORE + depends on TWL6040_CORE select INPUT_FF_MEMLESS help This option enables support for TWL6040 Vibrator Driver. diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index 45874fed523a..14e94f56cb7d 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c @@ -28,7 +28,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/workqueue.h> -#include <linux/i2c/twl.h> +#include <linux/input.h> #include <linux/mfd/twl6040.h> #include <linux/slab.h> #include <linux/delay.h> @@ -257,7 +257,7 @@ static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL); static int __devinit twl6040_vibra_probe(struct platform_device *pdev) { - struct twl4030_vibra_data *pdata = pdev->dev.platform_data; + struct twl6040_vibra_data *pdata = pdev->dev.platform_data; struct vibra_info *info; int ret; diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c index 800243b6037e..64ad702a2ecc 100644 --- a/drivers/leds/leds-atmel-pwm.c +++ b/drivers/leds/leds-atmel-pwm.c @@ -35,7 +35,7 @@ static void pwmled_brightness(struct led_classdev *cdev, enum led_brightness b) * NOTE: we reuse the platform_data structure of GPIO leds, * but repurpose its "gpio" number as a PWM channel number. */ -static int __init pwmled_probe(struct platform_device *pdev) +static int __devinit pwmled_probe(struct platform_device *pdev) { const struct gpio_led_platform_data *pdata; struct pwmled *leds; diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index 7f98984e4fad..eab2ea424200 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -54,6 +54,7 @@ struct xc5000_priv { struct list_head hybrid_tuner_instance_list; u32 if_khz; + u32 xtal_khz; u32 freq_hz; u32 bandwidth; u8 video_standard; @@ -214,9 +215,9 @@ static const struct xc5000_fw_cfg xc5000a_1_6_114 = { .size = 12401, }; -static const struct xc5000_fw_cfg xc5000c_41_024_5_31875 = { - .name = "dvb-fe-xc5000c-41.024.5-31875.fw", - .size = 16503, +static const struct xc5000_fw_cfg xc5000c_41_024_5 = { + .name = "dvb-fe-xc5000c-41.024.5.fw", + .size = 16497, }; static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id) @@ -226,7 +227,7 @@ static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id) case XC5000A: return &xc5000a_1_6_114; case XC5000C: - return &xc5000c_41_024_5_31875; + return &xc5000c_41_024_5; } } @@ -572,6 +573,31 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode) return found; } +static int xc_set_xtal(struct dvb_frontend *fe) +{ + struct xc5000_priv *priv = fe->tuner_priv; + int ret = XC_RESULT_SUCCESS; + + switch (priv->chip_id) { + default: + case XC5000A: + /* 32.000 MHz xtal is default */ + break; + case XC5000C: + switch (priv->xtal_khz) { + default: + case 32000: + /* 32.000 MHz xtal is default */ + break; + case 31875: + /* 31.875 MHz xtal configuration */ + ret = xc_write_reg(priv, 0x000f, 0x8081); + break; + } + break; + } + return ret; +} static int xc5000_fwupload(struct dvb_frontend *fe) { @@ -603,6 +629,8 @@ static int xc5000_fwupload(struct dvb_frontend *fe) } else { printk(KERN_INFO "xc5000: firmware uploading...\n"); ret = xc_load_i2c_sequence(fe, fw->data); + if (XC_RESULT_SUCCESS == ret) + ret = xc_set_xtal(fe); printk(KERN_INFO "xc5000: firmware upload complete...\n"); } @@ -1164,6 +1192,9 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, priv->if_khz = cfg->if_khz; } + if (priv->xtal_khz == 0) + priv->xtal_khz = cfg->xtal_khz; + if (priv->radio_input == 0) priv->radio_input = cfg->radio_input; diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/common/tuners/xc5000.h index 3396f8e02b40..39a73bf01406 100644 --- a/drivers/media/common/tuners/xc5000.h +++ b/drivers/media/common/tuners/xc5000.h @@ -34,6 +34,7 @@ struct xc5000_config { u8 i2c_address; u32 if_khz; u8 radio_input; + u32 xtal_khz; int chip_id; }; diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 39696c6a4ed7..0f64d7182657 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1446,6 +1446,28 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) __func__); return -EINVAL; } + /* + * Get a delivery system that is compatible with DVBv3 + * NOTE: in order for this to work with softwares like Kaffeine that + * uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to + * DVB-S, drivers that support both should put the SYS_DVBS entry + * before the SYS_DVBS2, otherwise it won't switch back to DVB-S. + * The real fix is that userspace applications should not use DVBv3 + * and not trust on calling FE_SET_FRONTEND to switch the delivery + * system. + */ + ncaps = 0; + while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { + if (fe->ops.delsys[ncaps] == desired_system) { + delsys = desired_system; + break; + } + ncaps++; + } + if (delsys == SYS_UNDEFINED) { + dprintk("%s() Couldn't find a delivery system that matches %d\n", + __func__, desired_system); + } } else { /* * This is a DVBv5 call. So, it likely knows the supported @@ -1494,9 +1516,10 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) __func__); return -EINVAL; } - c->delivery_system = delsys; } + c->delivery_system = delsys; + /* * The DVBv3 or DVBv5 call is requesting a different system. So, * emulation is needed. diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index 36d11756492f..a414b1f2b6a5 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -1520,8 +1520,10 @@ static int scu_command(struct drxk_state *state, dprintk(1, "\n"); if ((cmd == 0) || ((parameterLen > 0) && (parameter == NULL)) || - ((resultLen > 0) && (result == NULL))) - goto error; + ((resultLen > 0) && (result == NULL))) { + printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } mutex_lock(&state->mutex); diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c index b09c5fae489b..af526586fa26 100644 --- a/drivers/media/rc/winbond-cir.c +++ b/drivers/media/rc/winbond-cir.c @@ -1046,6 +1046,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) goto exit_unregister_led; } + data->dev->driver_type = RC_DRIVER_IR_RAW; data->dev->driver_name = WBCIR_NAME; data->dev->input_name = WBCIR_NAME; data->dev->input_phys = "wbcir/cir0"; diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index f2479c5c0eb2..ce1e7ba940f6 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -492,7 +492,7 @@ config VIDEO_VS6624 config VIDEO_MT9M032 tristate "MT9M032 camera sensor support" - depends on I2C && VIDEO_V4L2 + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API select VIDEO_APTINA_PLL ---help--- This driver supports MT9M032 camera sensors from Aptina, monochrome diff --git a/drivers/media/video/mt9m032.c b/drivers/media/video/mt9m032.c index 7636672c3548..645973c5feb0 100644 --- a/drivers/media/video/mt9m032.c +++ b/drivers/media/video/mt9m032.c @@ -392,10 +392,11 @@ static int mt9m032_set_pad_format(struct v4l2_subdev *subdev, } /* Scaling is not supported, the format is thus fixed. */ - ret = mt9m032_get_pad_format(subdev, fh, fmt); + fmt->format = *__mt9m032_get_pad_format(sensor, fh, fmt->which); + ret = 0; done: - mutex_lock(&sensor->lock); + mutex_unlock(&sensor->lock); return ret; } diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 29f463cc09cb..11e44386fa9b 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -268,10 +268,17 @@ config TWL6030_PWM This is used to control charging LED brightness. config TWL6040_CORE - bool - depends on TWL4030_CORE && GENERIC_HARDIRQS + bool "Support for TWL6040 audio codec" + depends on I2C=y && GENERIC_HARDIRQS select MFD_CORE + select REGMAP_I2C default n + help + Say yes here if you want support for Texas Instruments TWL6040 audio + codec. + This driver provides common support for accessing the device, + additional drivers must be enabled in order to use the + functionality of the device (audio, vibra). config MFD_STMPE bool "Support STMicroelectronics STMPE" diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 1895cf9fab8c..1582c3d95257 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -527,7 +527,9 @@ static void asic3_gpio_set(struct gpio_chip *chip, static int asic3_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { - return (offset < ASIC3_NUM_GPIOS) ? IRQ_BOARD_START + offset : -ENXIO; + struct asic3 *asic = container_of(chip, struct asic3, gpio); + + return (offset < ASIC3_NUM_GPIOS) ? asic->irq_base + offset : -ENXIO; } static __init int asic3_gpio_probe(struct platform_device *pdev, diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 95a2e546a489..c8aae6640e64 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -25,7 +25,6 @@ #include <linux/clk.h> #include <linux/dma-mapping.h> #include <linux/spinlock.h> -#include <linux/gpio.h> #include <plat/usb.h> #include <linux/pm_runtime.h> @@ -502,19 +501,6 @@ static void omap_usbhs_init(struct device *dev) pm_runtime_get_sync(dev); spin_lock_irqsave(&omap->lock, flags); - if (pdata->ehci_data->phy_reset) { - if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) - gpio_request_one(pdata->ehci_data->reset_gpio_port[0], - GPIOF_OUT_INIT_LOW, "USB1 PHY reset"); - - if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) - gpio_request_one(pdata->ehci_data->reset_gpio_port[1], - GPIOF_OUT_INIT_LOW, "USB2 PHY reset"); - - /* Hold the PHY in RESET for enough time till DIR is high */ - udelay(10); - } - omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev); @@ -593,39 +579,10 @@ static void omap_usbhs_init(struct device *dev) usbhs_omap_tll_init(dev, OMAP_TLL_CHANNEL_COUNT); } - if (pdata->ehci_data->phy_reset) { - /* Hold the PHY in RESET for enough time till - * PHY is settled and ready - */ - udelay(10); - - if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) - gpio_set_value - (pdata->ehci_data->reset_gpio_port[0], 1); - - if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) - gpio_set_value - (pdata->ehci_data->reset_gpio_port[1], 1); - } - spin_unlock_irqrestore(&omap->lock, flags); pm_runtime_put_sync(dev); } -static void omap_usbhs_deinit(struct device *dev) -{ - struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); - struct usbhs_omap_platform_data *pdata = &omap->platdata; - - if (pdata->ehci_data->phy_reset) { - if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) - gpio_free(pdata->ehci_data->reset_gpio_port[0]); - - if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) - gpio_free(pdata->ehci_data->reset_gpio_port[1]); - } -} - /** * usbhs_omap_probe - initialize TI-based HCDs @@ -860,7 +817,6 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev) { struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev); - omap_usbhs_deinit(&pdev->dev); iounmap(omap->tll_base); iounmap(omap->uhh_base); clk_put(omap->init_60m_fclk); diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c index 99ef944c621d..44afae0a69ce 100644 --- a/drivers/mfd/rc5t583.c +++ b/drivers/mfd/rc5t583.c @@ -80,44 +80,6 @@ static struct mfd_cell rc5t583_subdevs[] = { {.name = "rc5t583-key", } }; -int rc5t583_write(struct device *dev, uint8_t reg, uint8_t val) -{ - struct rc5t583 *rc5t583 = dev_get_drvdata(dev); - return regmap_write(rc5t583->regmap, reg, val); -} - -int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val) -{ - struct rc5t583 *rc5t583 = dev_get_drvdata(dev); - unsigned int ival; - int ret; - ret = regmap_read(rc5t583->regmap, reg, &ival); - if (!ret) - *val = (uint8_t)ival; - return ret; -} - -int rc5t583_set_bits(struct device *dev, unsigned int reg, - unsigned int bit_mask) -{ - struct rc5t583 *rc5t583 = dev_get_drvdata(dev); - return regmap_update_bits(rc5t583->regmap, reg, bit_mask, bit_mask); -} - -int rc5t583_clear_bits(struct device *dev, unsigned int reg, - unsigned int bit_mask) -{ - struct rc5t583 *rc5t583 = dev_get_drvdata(dev); - return regmap_update_bits(rc5t583->regmap, reg, bit_mask, 0); -} - -int rc5t583_update(struct device *dev, unsigned int reg, - unsigned int val, unsigned int mask) -{ - struct rc5t583 *rc5t583 = dev_get_drvdata(dev); - return regmap_update_bits(rc5t583->regmap, reg, mask, val); -} - static int __rc5t583_set_ext_pwrreq1_control(struct device *dev, int id, int ext_pwr, int slots) { @@ -197,6 +159,7 @@ int rc5t583_ext_power_req_config(struct device *dev, int ds_id, ds_id, ext_pwr_req); return 0; } +EXPORT_SYMBOL(rc5t583_ext_power_req_config); static int rc5t583_clear_ext_power_req(struct rc5t583 *rc5t583, struct rc5t583_platform_data *pdata) diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c index b2d8e512d3cb..2d6bedadca09 100644 --- a/drivers/mfd/twl6040-core.c +++ b/drivers/mfd/twl6040-core.c @@ -30,7 +30,9 @@ #include <linux/platform_device.h> #include <linux/gpio.h> #include <linux/delay.h> -#include <linux/i2c/twl.h> +#include <linux/i2c.h> +#include <linux/regmap.h> +#include <linux/err.h> #include <linux/mfd/core.h> #include <linux/mfd/twl6040.h> @@ -39,7 +41,7 @@ int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg) { int ret; - u8 val = 0; + unsigned int val; mutex_lock(&twl6040->io_mutex); /* Vibra control registers from cache */ @@ -47,7 +49,7 @@ int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg) reg == TWL6040_REG_VIBCTLR)) { val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)]; } else { - ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg); + ret = regmap_read(twl6040->regmap, reg, &val); if (ret < 0) { mutex_unlock(&twl6040->io_mutex); return ret; @@ -64,7 +66,7 @@ int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val) int ret; mutex_lock(&twl6040->io_mutex); - ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg); + ret = regmap_write(twl6040->regmap, reg, val); /* Cache the vibra control registers */ if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR) twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val; @@ -77,16 +79,9 @@ EXPORT_SYMBOL(twl6040_reg_write); int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask) { int ret; - u8 val; mutex_lock(&twl6040->io_mutex); - ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg); - if (ret) - goto out; - - val |= mask; - ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg); -out: + ret = regmap_update_bits(twl6040->regmap, reg, mask, mask); mutex_unlock(&twl6040->io_mutex); return ret; } @@ -95,16 +90,9 @@ EXPORT_SYMBOL(twl6040_set_bits); int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask) { int ret; - u8 val; mutex_lock(&twl6040->io_mutex); - ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg); - if (ret) - goto out; - - val &= ~mask; - ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg); -out: + ret = regmap_update_bits(twl6040->regmap, reg, mask, 0); mutex_unlock(&twl6040->io_mutex); return ret; } @@ -494,32 +482,58 @@ static struct resource twl6040_codec_rsrc[] = { }, }; -static int __devinit twl6040_probe(struct platform_device *pdev) +static bool twl6040_readable_reg(struct device *dev, unsigned int reg) { - struct twl4030_audio_data *pdata = pdev->dev.platform_data; + /* Register 0 is not readable */ + if (!reg) + return false; + return true; +} + +static struct regmap_config twl6040_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = TWL6040_REG_STATUS, /* 0x2e */ + + .readable_reg = twl6040_readable_reg, +}; + +static int __devinit twl6040_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct twl6040_platform_data *pdata = client->dev.platform_data; struct twl6040 *twl6040; struct mfd_cell *cell = NULL; int ret, children = 0; if (!pdata) { - dev_err(&pdev->dev, "Platform data is missing\n"); + dev_err(&client->dev, "Platform data is missing\n"); return -EINVAL; } /* In order to operate correctly we need valid interrupt config */ - if (!pdata->naudint_irq || !pdata->irq_base) { - dev_err(&pdev->dev, "Invalid IRQ configuration\n"); + if (!client->irq || !pdata->irq_base) { + dev_err(&client->dev, "Invalid IRQ configuration\n"); return -EINVAL; } - twl6040 = kzalloc(sizeof(struct twl6040), GFP_KERNEL); - if (!twl6040) - return -ENOMEM; + twl6040 = devm_kzalloc(&client->dev, sizeof(struct twl6040), + GFP_KERNEL); + if (!twl6040) { + ret = -ENOMEM; + goto err; + } + + twl6040->regmap = regmap_init_i2c(client, &twl6040_regmap_config); + if (IS_ERR(twl6040->regmap)) { + ret = PTR_ERR(twl6040->regmap); + goto err; + } - platform_set_drvdata(pdev, twl6040); + i2c_set_clientdata(client, twl6040); - twl6040->dev = &pdev->dev; - twl6040->irq = pdata->naudint_irq; + twl6040->dev = &client->dev; + twl6040->irq = client->irq; twl6040->irq_base = pdata->irq_base; mutex_init(&twl6040->mutex); @@ -588,12 +602,12 @@ static int __devinit twl6040_probe(struct platform_device *pdev) } if (children) { - ret = mfd_add_devices(&pdev->dev, pdev->id, twl6040->cells, + ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children, NULL, 0); if (ret) goto mfd_err; } else { - dev_err(&pdev->dev, "No platform data found for children\n"); + dev_err(&client->dev, "No platform data found for children\n"); ret = -ENODEV; goto mfd_err; } @@ -608,14 +622,15 @@ gpio2_err: if (gpio_is_valid(twl6040->audpwron)) gpio_free(twl6040->audpwron); gpio1_err: - platform_set_drvdata(pdev, NULL); - kfree(twl6040); + i2c_set_clientdata(client, NULL); + regmap_exit(twl6040->regmap); +err: return ret; } -static int __devexit twl6040_remove(struct platform_device *pdev) +static int __devexit twl6040_remove(struct i2c_client *client) { - struct twl6040 *twl6040 = platform_get_drvdata(pdev); + struct twl6040 *twl6040 = i2c_get_clientdata(client); if (twl6040->power_count) twl6040_power(twl6040, 0); @@ -626,23 +641,30 @@ static int __devexit twl6040_remove(struct platform_device *pdev) free_irq(twl6040->irq_base + TWL6040_IRQ_READY, twl6040); twl6040_irq_exit(twl6040); - mfd_remove_devices(&pdev->dev); - platform_set_drvdata(pdev, NULL); - kfree(twl6040); + mfd_remove_devices(&client->dev); + i2c_set_clientdata(client, NULL); + regmap_exit(twl6040->regmap); return 0; } -static struct platform_driver twl6040_driver = { +static const struct i2c_device_id twl6040_i2c_id[] = { + { "twl6040", 0, }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, twl6040_i2c_id); + +static struct i2c_driver twl6040_driver = { + .driver = { + .name = "twl6040", + .owner = THIS_MODULE, + }, .probe = twl6040_probe, .remove = __devexit_p(twl6040_remove), - .driver = { - .owner = THIS_MODULE, - .name = "twl6040", - }, + .id_table = twl6040_i2c_id, }; -module_platform_driver(twl6040_driver); +module_i2c_driver(twl6040_driver); MODULE_DESCRIPTION("TWL6040 MFD"); MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>"); diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index b1809650b7aa..dabec556ebb8 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -873,7 +873,7 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, { struct mmc_blk_data *md = mq->data; struct mmc_card *card = md->queue.card; - unsigned int from, nr, arg; + unsigned int from, nr, arg, trim_arg, erase_arg; int err = 0, type = MMC_BLK_SECDISCARD; if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) { @@ -881,20 +881,26 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, goto out; } + from = blk_rq_pos(req); + nr = blk_rq_sectors(req); + /* The sanitize operation is supported at v4.5 only */ if (mmc_can_sanitize(card)) { - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_SANITIZE_START, 1, 0); - goto out; + erase_arg = MMC_ERASE_ARG; + trim_arg = MMC_TRIM_ARG; + } else { + erase_arg = MMC_SECURE_ERASE_ARG; + trim_arg = MMC_SECURE_TRIM1_ARG; } - from = blk_rq_pos(req); - nr = blk_rq_sectors(req); - - if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr)) - arg = MMC_SECURE_TRIM1_ARG; - else - arg = MMC_SECURE_ERASE_ARG; + if (mmc_erase_group_aligned(card, from, nr)) + arg = erase_arg; + else if (mmc_can_trim(card)) + arg = trim_arg; + else { + err = -EINVAL; + goto out; + } retry: if (card->quirks & MMC_QUIRK_INAND_CMD38) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, @@ -904,25 +910,41 @@ retry: INAND_CMD38_ARG_SECERASE, 0); if (err) - goto out; + goto out_retry; } + err = mmc_erase(card, from, nr, arg); - if (!err && arg == MMC_SECURE_TRIM1_ARG) { + if (err == -EIO) + goto out_retry; + if (err) + goto out; + + if (arg == MMC_SECURE_TRIM1_ARG) { if (card->quirks & MMC_QUIRK_INAND_CMD38) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, INAND_CMD38_ARG_EXT_CSD, INAND_CMD38_ARG_SECTRIM2, 0); if (err) - goto out; + goto out_retry; } + err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG); + if (err == -EIO) + goto out_retry; + if (err) + goto out; } -out: - if (err == -EIO && !mmc_blk_reset(md, card->host, type)) + + if (mmc_can_sanitize(card)) + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_SANITIZE_START, 1, 0); +out_retry: + if (err && !mmc_blk_reset(md, card->host, type)) goto retry; if (!err) mmc_blk_reset_success(md, type); +out: spin_lock_irq(&md->lock); __blk_end_request(req, err, blk_rq_bytes(req)); spin_unlock_irq(&md->lock); @@ -1802,7 +1824,7 @@ static void mmc_blk_remove(struct mmc_card *card) } #ifdef CONFIG_PM -static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state) +static int mmc_blk_suspend(struct mmc_card *card) { struct mmc_blk_data *part_md; struct mmc_blk_data *md = mmc_get_drvdata(card); diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 2517547b4366..996f8e36e23d 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -139,7 +139,7 @@ static void mmc_queue_setup_discard(struct request_queue *q, queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); q->limits.max_discard_sectors = max_discard; - if (card->erased_byte == 0) + if (card->erased_byte == 0 && !mmc_can_discard(card)) q->limits.discard_zeroes_data = 1; q->limits.discard_granularity = card->pref_erase << 9; /* granularity must not be greater than max. discard */ diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 3f606068d552..c60cee92a2b2 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -122,14 +122,14 @@ static int mmc_bus_remove(struct device *dev) return 0; } -static int mmc_bus_suspend(struct device *dev, pm_message_t state) +static int mmc_bus_suspend(struct device *dev) { struct mmc_driver *drv = to_mmc_driver(dev->driver); struct mmc_card *card = mmc_dev_to_card(dev); int ret = 0; if (dev->driver && drv->suspend) - ret = drv->suspend(card, state); + ret = drv->suspend(card); return ret; } @@ -165,20 +165,14 @@ static int mmc_runtime_idle(struct device *dev) return pm_runtime_suspend(dev); } +#endif /* !CONFIG_PM_RUNTIME */ + static const struct dev_pm_ops mmc_bus_pm_ops = { - .runtime_suspend = mmc_runtime_suspend, - .runtime_resume = mmc_runtime_resume, - .runtime_idle = mmc_runtime_idle, + SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume, + mmc_runtime_idle) + SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume) }; -#define MMC_PM_OPS_PTR (&mmc_bus_pm_ops) - -#else /* !CONFIG_PM_RUNTIME */ - -#define MMC_PM_OPS_PTR NULL - -#endif /* !CONFIG_PM_RUNTIME */ - static struct bus_type mmc_bus_type = { .name = "mmc", .dev_attrs = mmc_dev_attrs, @@ -186,9 +180,7 @@ static struct bus_type mmc_bus_type = { .uevent = mmc_bus_uevent, .probe = mmc_bus_probe, .remove = mmc_bus_remove, - .suspend = mmc_bus_suspend, - .resume = mmc_bus_resume, - .pm = MMC_PM_OPS_PTR, + .pm = &mmc_bus_pm_ops, }; int mmc_register_bus(void) diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/cd-gpio.c index 29de31e260dd..2c14be73254c 100644 --- a/drivers/mmc/core/cd-gpio.c +++ b/drivers/mmc/core/cd-gpio.c @@ -12,6 +12,7 @@ #include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/jiffies.h> +#include <linux/mmc/cd-gpio.h> #include <linux/mmc/host.h> #include <linux/module.h> #include <linux/slab.h> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 7474c47b9c08..ba821fe70bca 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1409,7 +1409,10 @@ static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card, { unsigned int erase_timeout; - if (card->ext_csd.erase_group_def & 1) { + if (arg == MMC_DISCARD_ARG || + (arg == MMC_TRIM_ARG && card->ext_csd.rev >= 6)) { + erase_timeout = card->ext_csd.trim_timeout; + } else if (card->ext_csd.erase_group_def & 1) { /* High Capacity Erase Group Size uses HC timeouts */ if (arg == MMC_TRIM_ARG) erase_timeout = card->ext_csd.trim_timeout; @@ -1681,8 +1684,6 @@ int mmc_can_trim(struct mmc_card *card) { if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN) return 1; - if (mmc_can_discard(card)) - return 1; return 0; } EXPORT_SYMBOL(mmc_can_trim); @@ -1701,6 +1702,8 @@ EXPORT_SYMBOL(mmc_can_discard); int mmc_can_sanitize(struct mmc_card *card) { + if (!mmc_can_trim(card) && !mmc_can_erase(card)) + return 0; if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_SANITIZE) return 1; return 0; @@ -2235,6 +2238,7 @@ int mmc_cache_ctrl(struct mmc_host *host, u8 enable) mmc_card_is_removable(host)) return err; + mmc_claim_host(host); if (card && mmc_card_mmc(card) && (card->ext_csd.cache_size > 0)) { enable = !!enable; @@ -2252,6 +2256,7 @@ int mmc_cache_ctrl(struct mmc_host *host, u8 enable) card->ext_csd.cache_ctrl = enable; } } + mmc_release_host(host); return err; } @@ -2269,49 +2274,32 @@ int mmc_suspend_host(struct mmc_host *host) cancel_delayed_work(&host->detect); mmc_flush_scheduled_work(); - if (mmc_try_claim_host(host)) { - err = mmc_cache_ctrl(host, 0); - mmc_release_host(host); - } else { - err = -EBUSY; - } + err = mmc_cache_ctrl(host, 0); if (err) goto out; mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { - /* - * A long response time is not acceptable for device drivers - * when doing suspend. Prevent mmc_claim_host in the suspend - * sequence, to potentially wait "forever" by trying to - * pre-claim the host. - */ - if (mmc_try_claim_host(host)) { - if (host->bus_ops->suspend) { - err = host->bus_ops->suspend(host); - } - mmc_release_host(host); + if (host->bus_ops->suspend) + err = host->bus_ops->suspend(host); - if (err == -ENOSYS || !host->bus_ops->resume) { - /* - * We simply "remove" the card in this case. - * It will be redetected on resume. (Calling - * bus_ops->remove() with a claimed host can - * deadlock.) - */ - if (host->bus_ops->remove) - host->bus_ops->remove(host); - mmc_claim_host(host); - mmc_detach_bus(host); - mmc_power_off(host); - mmc_release_host(host); - host->pm_flags = 0; - err = 0; - } - } else { - err = -EBUSY; + if (err == -ENOSYS || !host->bus_ops->resume) { + /* + * We simply "remove" the card in this case. + * It will be redetected on resume. (Calling + * bus_ops->remove() with a claimed host can + * deadlock.) + */ + if (host->bus_ops->remove) + host->bus_ops->remove(host); + mmc_claim_host(host); + mmc_detach_bus(host); + mmc_power_off(host); + mmc_release_host(host); + host->pm_flags = 0; + err = 0; } } mmc_bus_put(host); diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index bf3c9b456aaf..ab3fc4617107 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -526,8 +526,10 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) return -ENODEV; sg_len = dw_mci_pre_dma_transfer(host, data, 0); - if (sg_len < 0) + if (sg_len < 0) { + host->dma_ops->stop(host); return sg_len; + } host->using_dma = 1; @@ -1879,7 +1881,8 @@ static void dw_mci_init_dma(struct dw_mci *host) if (!host->dma_ops) goto no_dma; - if (host->dma_ops->init) { + if (host->dma_ops->init && host->dma_ops->start && + host->dma_ops->stop && host->dma_ops->cleanup) { if (host->dma_ops->init(host)) { dev_err(&host->dev, "%s: Unable to initialize " "DMA Controller.\n", __func__); diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 5c2b1c10af9c..56d4499d4388 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -249,7 +249,7 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on, * the pbias cell programming support is still missing when * booting with Device tree */ - if (of_have_populated_dt() && !vdd) + if (dev->of_node && !vdd) return 0; if (mmc_slot(host).before_set_reg) @@ -1549,7 +1549,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) * can't be allowed when booting with device * tree. */ - (!of_have_populated_dt())) { + !host->dev->of_node) { /* * The mmc_select_voltage fn of the core does * not seem to set the power_mode to @@ -1741,7 +1741,7 @@ static const struct of_device_id omap_mmc_of_match[] = { .data = &omap4_reg_offset, }, {}, -} +}; MODULE_DEVICE_TABLE(of, omap_mmc_of_match); static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 6193a0d7bde5..8abdaf6697a8 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -467,8 +467,7 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) clk_prepare_enable(clk); pltfm_host->clk = clk; - if (!is_imx25_esdhc(imx_data)) - host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; + host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data)) /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */ diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9aa77f3f04a8..ccefdebeff14 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -147,7 +147,7 @@ static void sdhci_set_card_detection(struct sdhci_host *host, bool enable) u32 present, irqs; if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) || - !mmc_card_is_removable(host->mmc)) + (host->mmc->caps & MMC_CAP_NONREMOVABLE)) return; present = sdhci_readl(host, SDHCI_PRESENT_STATE) & diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d20f1334792b..111569ccab43 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -991,8 +991,8 @@ static void pci_restore_config_dword(struct pci_dev *pdev, int offset, } } -static void pci_restore_config_space(struct pci_dev *pdev, int start, int end, - int retry) +static void pci_restore_config_space_range(struct pci_dev *pdev, + int start, int end, int retry) { int index; @@ -1002,6 +1002,18 @@ static void pci_restore_config_space(struct pci_dev *pdev, int start, int end, retry); } +static void pci_restore_config_space(struct pci_dev *pdev) +{ + if (pdev->hdr_type == PCI_HEADER_TYPE_NORMAL) { + pci_restore_config_space_range(pdev, 10, 15, 0); + /* Restore BARs before the command register. */ + pci_restore_config_space_range(pdev, 4, 9, 10); + pci_restore_config_space_range(pdev, 0, 3, 0); + } else { + pci_restore_config_space_range(pdev, 0, 15, 0); + } +} + /** * pci_restore_state - Restore the saved state of a PCI device * @dev: - PCI device that we're dealing with @@ -1015,13 +1027,7 @@ void pci_restore_state(struct pci_dev *dev) pci_restore_pcie_state(dev); pci_restore_ats_state(dev); - pci_restore_config_space(dev, 10, 15, 0); - /* - * The Base Address register should be programmed before the command - * register(s) - */ - pci_restore_config_space(dev, 4, 9, 10); - pci_restore_config_space(dev, 0, 3, 0); + pci_restore_config_space(dev); pci_restore_pcix_state(dev); pci_restore_msi_state(dev); diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index ec3b8cc188af..df6296c5f47b 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -908,10 +908,6 @@ static int pinctrl_groups_show(struct seq_file *s, void *what) const struct pinctrl_ops *ops = pctldev->desc->pctlops; unsigned selector = 0; - /* No grouping */ - if (!ops) - return 0; - mutex_lock(&pinctrl_mutex); seq_puts(s, "registered pin groups:\n"); @@ -1225,6 +1221,19 @@ static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev) #endif +static int pinctrl_check_ops(struct pinctrl_dev *pctldev) +{ + const struct pinctrl_ops *ops = pctldev->desc->pctlops; + + if (!ops || + !ops->list_groups || + !ops->get_group_name || + !ops->get_group_pins) + return -EINVAL; + + return 0; +} + /** * pinctrl_register() - register a pin controller device * @pctldesc: descriptor for this pin controller @@ -1256,6 +1265,14 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, INIT_LIST_HEAD(&pctldev->gpio_ranges); pctldev->dev = dev; + /* check core ops for sanity */ + ret = pinctrl_check_ops(pctldev); + if (ret) { + pr_err("%s pinctrl ops lacks necessary functions\n", + pctldesc->name); + goto out_err; + } + /* If we're implementing pinmuxing, check the ops for sanity */ if (pctldesc->pmxops) { ret = pinmux_check_ops(pctldev); diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index c21871a4e73d..bc2e8a7c265b 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -2844,6 +2844,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( sector_t recid, trkid; unsigned int offs; unsigned int count, count_to_trk_end; + int ret; basedev = block->base; if (rq_data_dir(req) == READ) { @@ -2884,8 +2885,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( itcw = itcw_init(cqr->data, itcw_size, itcw_op, 0, ctidaw, 0); if (IS_ERR(itcw)) { - dasd_sfree_request(cqr, startdev); - return ERR_PTR(-EINVAL); + ret = -EINVAL; + goto out_error; } cqr->cpaddr = itcw_get_tcw(itcw); if (prepare_itcw(itcw, first_trk, last_trk, @@ -2897,8 +2898,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( /* Clock not in sync and XRC is enabled. * Try again later. */ - dasd_sfree_request(cqr, startdev); - return ERR_PTR(-EAGAIN); + ret = -EAGAIN; + goto out_error; } len_to_track_end = 0; /* @@ -2937,8 +2938,10 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( tidaw_flags = 0; last_tidaw = itcw_add_tidaw(itcw, tidaw_flags, dst, part_len); - if (IS_ERR(last_tidaw)) - return ERR_PTR(-EINVAL); + if (IS_ERR(last_tidaw)) { + ret = -EINVAL; + goto out_error; + } dst += part_len; } } @@ -2947,8 +2950,10 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( dst = page_address(bv->bv_page) + bv->bv_offset; last_tidaw = itcw_add_tidaw(itcw, 0x00, dst, bv->bv_len); - if (IS_ERR(last_tidaw)) - return ERR_PTR(-EINVAL); + if (IS_ERR(last_tidaw)) { + ret = -EINVAL; + goto out_error; + } } } last_tidaw->flags |= TIDAW_FLAGS_LAST; @@ -2968,6 +2973,9 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( cqr->buildclk = get_clock(); cqr->status = DASD_CQR_FILLED; return cqr; +out_error: + dasd_sfree_request(cqr, startdev); + return ERR_PTR(ret); } static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev, diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index 85f4a9a5d12e..73bef0bd394c 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c @@ -903,7 +903,7 @@ static int ur_set_online(struct ccw_device *cdev) goto fail_urdev_put; } - cdev_init(urd->char_device, &ur_fops); + urd->char_device->ops = &ur_fops; urd->char_device->dev = MKDEV(major, minor); urd->char_device->owner = ur_fops.owner; diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 24145c30c9b0..6cc4358f68c1 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -1073,8 +1073,10 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, (new_serial.close_delay != port->close_delay) || (new_serial.xmit_fifo_size != state->xmit_fifo_size) || ((new_serial.flags & ~ASYNC_USR_MASK) != - (port->flags & ~ASYNC_USR_MASK))) + (port->flags & ~ASYNC_USR_MASK))) { + tty_unlock(); return -EPERM; + } port->flags = ((port->flags & ~ASYNC_USR_MASK) | (new_serial.flags & ASYNC_USR_MASK)); state->custom_divisor = new_serial.custom_divisor; diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index e6c3dbd781d6..836fe2731234 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c @@ -154,10 +154,9 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id) port->x_char = 0; return IRQ_HANDLED; } - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - clps711xuart_stop_tx(port); - return IRQ_HANDLED; - } + + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) + goto disable_tx_irq; count = port->fifosize >> 1; do { @@ -171,8 +170,11 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); - if (uart_circ_empty(xmit)) - clps711xuart_stop_tx(port); + if (uart_circ_empty(xmit)) { + disable_tx_irq: + disable_irq_nosync(TX_IRQ(port)); + tx_enabled(port) = 0; + } return IRQ_HANDLED; } diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index bbbec4a74cfb..c2816f494807 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1447,9 +1447,11 @@ static int pch_uart_verify_port(struct uart_port *port, __func__); return -EOPNOTSUPP; #endif - priv->use_dma = 1; priv->use_dma_flag = 1; dev_info(priv->port.dev, "PCH UART : Use DMA Mode\n"); + if (!priv->use_dma) + pch_request_dma(port); + priv->use_dma = 1; } return 0; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a2aa9d652c67..ec6c97dadbe4 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1667,7 +1667,6 @@ void usb_disconnect(struct usb_device **pdev) { struct usb_device *udev = *pdev; int i; - struct usb_hcd *hcd = bus_to_hcd(udev->bus); /* mark the device as inactive, so any further urb submissions for * this device (and any of its children) will fail immediately. @@ -1690,9 +1689,7 @@ void usb_disconnect(struct usb_device **pdev) * so that the hardware is now fully quiesced. */ dev_dbg (&udev->dev, "unregistering device\n"); - mutex_lock(hcd->bandwidth_mutex); usb_disable_device(udev, 0); - mutex_unlock(hcd->bandwidth_mutex); usb_hcd_synchronize_unlinks(udev); usb_remove_ep_devs(&udev->ep0); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index aed3e07942d4..ca717da3be95 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1136,8 +1136,6 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf, * Deallocates hcd/hardware state for the endpoints (nuking all or most * pending urbs) and usbcore state for the interfaces, so that usbcore * must usb_set_configuration() before any interfaces could be used. - * - * Must be called with hcd->bandwidth_mutex held. */ void usb_disable_device(struct usb_device *dev, int skip_ep0) { @@ -1190,7 +1188,9 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) usb_disable_endpoint(dev, i + USB_DIR_IN, false); } /* Remove endpoints from the host controller internal state */ + mutex_lock(hcd->bandwidth_mutex); usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); + mutex_unlock(hcd->bandwidth_mutex); /* Second pass: remove endpoint pointers */ } for (i = skip_ep0; i < 16; ++i) { @@ -1750,7 +1750,6 @@ free_interfaces: /* if it's already configured, clear out old state first. * getting rid of old interfaces means unbinding their drivers. */ - mutex_lock(hcd->bandwidth_mutex); if (dev->state != USB_STATE_ADDRESS) usb_disable_device(dev, 1); /* Skip ep0 */ @@ -1763,6 +1762,7 @@ free_interfaces: * host controller will not allow submissions to dropped endpoints. If * this call fails, the device state is unchanged. */ + mutex_lock(hcd->bandwidth_mutex); ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); if (ret < 0) { mutex_unlock(hcd->bandwidth_mutex); diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 7bd815a507e8..99b58d84553a 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -206,11 +206,11 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc) for (i = 0; i < dwc->num_event_buffers; i++) { evt = dwc->ev_buffs[i]; - if (evt) { + if (evt) dwc3_free_one_event_buffer(dwc, evt); - dwc->ev_buffs[i] = NULL; - } } + + kfree(dwc->ev_buffs); } /** diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 25910e251c04..3584a169886f 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -353,6 +353,9 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, dwc->test_mode_nr = wIndex >> 8; dwc->test_mode = true; + break; + default: + return -EINVAL; } break; @@ -559,15 +562,20 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, length = trb->size & DWC3_TRB_SIZE_MASK; if (dwc->ep0_bounced) { + unsigned transfer_size = ur->length; + unsigned maxp = ep0->endpoint.maxpacket; + + transfer_size += (maxp - (transfer_size % maxp)); transferred = min_t(u32, ur->length, - ep0->endpoint.maxpacket - length); + transfer_size - length); memcpy(ur->buf, dwc->ep0_bounce, transferred); dwc->ep0_bounced = false; } else { transferred = ur->length - length; - ur->actual += transferred; } + ur->actual += transferred; + if ((epnum & 1) && ur->actual < ur->length) { /* for some reason we did not get everything out */ diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 0c935d7c65bd..9d7bcd910074 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1863,8 +1863,8 @@ static int __devinit at91udc_probe(struct platform_device *pdev) mod_timer(&udc->vbus_timer, jiffies + VBUS_POLL_TIMEOUT); } else { - if (request_irq(udc->board.vbus_pin, at91_vbus_irq, - 0, driver_name, udc)) { + if (request_irq(gpio_to_irq(udc->board.vbus_pin), + at91_vbus_irq, 0, driver_name, udc)) { DBG("request vbus irq %d failed\n", udc->board.vbus_pin); retval = -EBUSY; @@ -1886,7 +1886,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev) return 0; fail4: if (gpio_is_valid(udc->board.vbus_pin) && !udc->board.vbus_polled) - free_irq(udc->board.vbus_pin, udc); + free_irq(gpio_to_irq(udc->board.vbus_pin), udc); fail3: if (gpio_is_valid(udc->board.vbus_pin)) gpio_free(udc->board.vbus_pin); @@ -1924,7 +1924,7 @@ static int __exit at91udc_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); remove_debug_file(udc); if (gpio_is_valid(udc->board.vbus_pin)) { - free_irq(udc->board.vbus_pin, udc); + free_irq(gpio_to_irq(udc->board.vbus_pin), udc); gpio_free(udc->board.vbus_pin); } free_irq(udc->udp_irq, udc); diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 1cbba70836bc..f52cb1ae45d9 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -712,7 +712,7 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value) if (code == FUNCTIONFS_INTERFACE_REVMAP) { struct ffs_function *func = ffs->func; ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV; - } else if (gadget->ops->ioctl) { + } else if (gadget && gadget->ops->ioctl) { ret = gadget->ops->ioctl(gadget, code, value); } else { ret = -ENOTTY; @@ -1382,6 +1382,7 @@ static void functionfs_unbind(struct ffs_data *ffs) ffs->ep0req = NULL; ffs->gadget = NULL; ffs_data_put(ffs); + clear_bit(FFS_FL_BOUND, &ffs->flags); } } diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 7b1cf18df5e3..52343654f5df 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -500,6 +500,7 @@ rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) if (buf) { memcpy(req->buf, buf, n); req->complete = rndis_response_complete; + req->context = rndis; rndis_free_response(rndis->config, buf); value = n; } diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 5f94e79cd6b9..55abfb6bd612 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -730,7 +730,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) : (1 << (ep_index(ep))); /* check if the pipe is empty */ - if (!(list_empty(&ep->queue))) { + if (!(list_empty(&ep->queue)) && !(ep_index(ep) == 0)) { /* Add td to the end */ struct fsl_req *lastreq; lastreq = list_entry(ep->queue.prev, struct fsl_req, queue); @@ -918,10 +918,6 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) return -ENOMEM; } - /* Update ep0 state */ - if ((ep_index(ep) == 0)) - udc->ep0_state = DATA_STATE_XMIT; - /* irq handler advances the queue */ if (req != NULL) list_add_tail(&req->queue, &ep->queue); @@ -1279,7 +1275,8 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction) udc->ep0_dir = USB_DIR_OUT; ep = &udc->eps[0]; - udc->ep0_state = WAIT_FOR_OUT_STATUS; + if (udc->ep0_state != DATA_STATE_XMIT) + udc->ep0_state = WAIT_FOR_OUT_STATUS; req->ep = ep; req->req.length = 0; @@ -1384,6 +1381,9 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, list_add_tail(&req->queue, &ep->queue); udc->ep0_state = DATA_STATE_XMIT; + if (ep0_prime_status(udc, EP_DIR_OUT)) + ep0stall(udc); + return; stall: ep0stall(udc); @@ -1492,6 +1492,14 @@ static void setup_received_irq(struct fsl_udc *udc, spin_lock(&udc->lock); udc->ep0_state = (setup->bRequestType & USB_DIR_IN) ? DATA_STATE_XMIT : DATA_STATE_RECV; + /* + * If the data stage is IN, send status prime immediately. + * See 2.0 Spec chapter 8.5.3.3 for detail. + */ + if (udc->ep0_state == DATA_STATE_XMIT) + if (ep0_prime_status(udc, EP_DIR_OUT)) + ep0stall(udc); + } else { /* No data phase, IN status from gadget */ udc->ep0_dir = USB_DIR_IN; @@ -1520,9 +1528,8 @@ static void ep0_req_complete(struct fsl_udc *udc, struct fsl_ep *ep0, switch (udc->ep0_state) { case DATA_STATE_XMIT: - /* receive status phase */ - if (ep0_prime_status(udc, EP_DIR_OUT)) - ep0stall(udc); + /* already primed at setup_received_irq */ + udc->ep0_state = WAIT_FOR_OUT_STATUS; break; case DATA_STATE_RECV: /* send status phase */ diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 331cd6729d3c..a85eaf40b948 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -161,7 +161,7 @@ static struct usb_composite_driver gfs_driver = { static struct ffs_data *gfs_ffs_data; static unsigned long gfs_registered; -static int gfs_init(void) +static int __init gfs_init(void) { ENTER(); @@ -169,7 +169,7 @@ static int gfs_init(void) } module_init(gfs_init); -static void gfs_exit(void) +static void __exit gfs_exit(void) { ENTER(); diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 69295ba9d99a..105b206cd844 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -340,7 +340,7 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg) /* currently we allocate TX FIFOs for all possible endpoints, * and assume that they are all the same size. */ - for (ep = 0; ep <= 15; ep++) { + for (ep = 1; ep <= 15; ep++) { val = addr; val |= size << S3C_DPTXFSIZn_DPTxFSize_SHIFT; addr += size; @@ -741,7 +741,7 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, /* write size / packets */ writel(epsize, hsotg->regs + epsize_reg); - if (using_dma(hsotg)) { + if (using_dma(hsotg) && !continuing) { unsigned int dma_reg; /* write DMA address to control register, buffer already @@ -1696,10 +1696,12 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg, reg |= mpsval; writel(reg, regs + S3C_DIEPCTL(ep)); - reg = readl(regs + S3C_DOEPCTL(ep)); - reg &= ~S3C_DxEPCTL_MPS_MASK; - reg |= mpsval; - writel(reg, regs + S3C_DOEPCTL(ep)); + if (ep) { + reg = readl(regs + S3C_DOEPCTL(ep)); + reg &= ~S3C_DxEPCTL_MPS_MASK; + reg |= mpsval; + writel(reg, regs + S3C_DOEPCTL(ep)); + } return; @@ -1919,7 +1921,8 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, ints & S3C_DIEPMSK_TxFIFOEmpty) { dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n", __func__, idx); - s3c_hsotg_trytx(hsotg, hs_ep); + if (!using_dma(hsotg)) + s3c_hsotg_trytx(hsotg, hs_ep); } } } diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 56da49f31d6c..2fa9865babed 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -264,8 +264,8 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) if (udc_is_newstyle(udc)) { udc->driver->disconnect(udc->gadget); udc->driver->unbind(udc->gadget); - usb_gadget_udc_stop(udc->gadget, udc->driver); usb_gadget_disconnect(udc->gadget); + usb_gadget_udc_stop(udc->gadget, udc->driver); } else { usb_gadget_stop(udc->gadget, udc->driver); } @@ -411,8 +411,12 @@ static ssize_t usb_udc_softconn_store(struct device *dev, struct usb_udc *udc = container_of(dev, struct usb_udc, dev); if (sysfs_streq(buf, "connect")) { + if (udc_is_newstyle(udc)) + usb_gadget_udc_start(udc->gadget, udc->driver); usb_gadget_connect(udc->gadget); } else if (sysfs_streq(buf, "disconnect")) { + if (udc_is_newstyle(udc)) + usb_gadget_udc_stop(udc->gadget, udc->driver); usb_gadget_disconnect(udc->gadget); } else { dev_err(dev, "unsupported command '%s'\n", buf); diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c index d776adb2da67..0cdf89d32a15 100644 --- a/drivers/usb/gadget/uvc_queue.c +++ b/drivers/usb/gadget/uvc_queue.c @@ -543,11 +543,11 @@ done: return ret; } +/* called with queue->irqlock held.. */ static struct uvc_buffer * uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) { struct uvc_buffer *nextbuf; - unsigned long flags; if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) && buf->buf.length != buf->buf.bytesused) { @@ -556,14 +556,12 @@ uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) return buf; } - spin_lock_irqsave(&queue->irqlock, flags); list_del(&buf->queue); if (!list_empty(&queue->irqqueue)) nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, queue); else nextbuf = NULL; - spin_unlock_irqrestore(&queue->irqlock, flags); buf->buf.sequence = queue->sequence++; do_gettimeofday(&buf->buf.timestamp); diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 3e7345172e03..d0a84bd3f3eb 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -218,6 +218,9 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, u32 portsc; struct usb_hcd *hcd = ehci_to_hcd(ehci); void __iomem *non_ehci = hcd->regs; + struct fsl_usb2_platform_data *pdata; + + pdata = hcd->self.controller->platform_data; portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]); portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW); @@ -234,7 +237,9 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, /* fall through */ case FSL_USB2_PHY_UTMI: /* enable UTMI PHY */ - setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN); + if (pdata->have_sysif_regs) + setbits32(non_ehci + FSL_SOC_USB_CTRL, + CTRL_UTMI_PHY_EN); portsc |= PORT_PTS_UTMI; break; case FSL_USB2_PHY_NONE: diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 806cc95317aa..4a3bc5b7a06f 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -858,8 +858,13 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) goto dead; } + /* + * We don't use STS_FLR, but some controllers don't like it to + * remain on, so mask it out along with the other status bits. + */ + masked_status = status & (INTR_MASK | STS_FLR); + /* Shared IRQ? */ - masked_status = status & INTR_MASK; if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) { spin_unlock(&ehci->lock); return IRQ_NONE; @@ -910,7 +915,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) pcd_status = status; /* resume root hub? */ - if (!(cmd & CMD_RUN)) + if (ehci->rh_state == EHCI_RH_SUSPENDED) usb_hcd_resume_root_hub(hcd); /* get per-port change detect bits */ diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index bba9850f32f0..5c78f9e71466 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -42,6 +42,7 @@ #include <plat/usb.h> #include <linux/regulator/consumer.h> #include <linux/pm_runtime.h> +#include <linux/gpio.h> /* EHCI Register Set */ #define EHCI_INSNREG04 (0xA0) @@ -191,6 +192,19 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) } } + if (pdata->phy_reset) { + if (gpio_is_valid(pdata->reset_gpio_port[0])) + gpio_request_one(pdata->reset_gpio_port[0], + GPIOF_OUT_INIT_LOW, "USB1 PHY reset"); + + if (gpio_is_valid(pdata->reset_gpio_port[1])) + gpio_request_one(pdata->reset_gpio_port[1], + GPIOF_OUT_INIT_LOW, "USB2 PHY reset"); + + /* Hold the PHY in RESET for enough time till DIR is high */ + udelay(10); + } + pm_runtime_enable(dev); pm_runtime_get_sync(dev); @@ -237,6 +251,19 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) /* root ports should always stay powered */ ehci_port_power(omap_ehci, 1); + if (pdata->phy_reset) { + /* Hold the PHY in RESET for enough time till + * PHY is settled and ready + */ + udelay(10); + + if (gpio_is_valid(pdata->reset_gpio_port[0])) + gpio_set_value(pdata->reset_gpio_port[0], 1); + + if (gpio_is_valid(pdata->reset_gpio_port[1])) + gpio_set_value(pdata->reset_gpio_port[1], 1); + } + return 0; err_add_hcd: @@ -259,8 +286,9 @@ err_io: */ static int ehci_hcd_omap_remove(struct platform_device *pdev) { - struct device *dev = &pdev->dev; - struct usb_hcd *hcd = dev_get_drvdata(dev); + struct device *dev = &pdev->dev; + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct ehci_hcd_omap_platform_data *pdata = dev->platform_data; usb_remove_hcd(hcd); disable_put_regulator(dev->platform_data); @@ -269,6 +297,13 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev) pm_runtime_put_sync(dev); pm_runtime_disable(dev); + if (pdata->phy_reset) { + if (gpio_is_valid(pdata->reset_gpio_port[0])) + gpio_free(pdata->reset_gpio_port[0]); + + if (gpio_is_valid(pdata->reset_gpio_port[1])) + gpio_free(pdata->reset_gpio_port[1]); + } return 0; } diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 73544bd440bd..86183366647f 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -731,7 +731,6 @@ static int tegra_ehci_probe(struct platform_device *pdev) err = -ENODEV; goto fail; } - set_irq_flags(irq, IRQF_VALID); #ifdef CONFIG_USB_OTG_UTILS if (pdata->operating_mode == TEGRA_USB_OTG) { diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 09f597ad6e00..13ebeca8e73e 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -94,7 +94,7 @@ static void at91_stop_hc(struct platform_device *pdev) /*-------------------------------------------------------------------------*/ -static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); +static void __devexit usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); /* configure so an HC device and id are always provided */ /* always called with process context; sleeping is OK */ @@ -108,7 +108,7 @@ static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); * then invokes the start() method for the HCD associated with it * through the hotplug entry's driver_data. */ -static int usb_hcd_at91_probe(const struct hc_driver *driver, +static int __devinit usb_hcd_at91_probe(const struct hc_driver *driver, struct platform_device *pdev) { int retval; @@ -203,7 +203,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, * context, "rmmod" or something similar. * */ -static void usb_hcd_at91_remove(struct usb_hcd *hcd, +static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd, struct platform_device *pdev) { usb_remove_hcd(hcd); @@ -545,7 +545,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev) /*-------------------------------------------------------------------------*/ -static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) +static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev) { struct at91_usbh_data *pdata; int i; @@ -620,7 +620,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev); } -static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) +static int __devexit ohci_hcd_at91_drv_remove(struct platform_device *pdev) { struct at91_usbh_data *pdata = pdev->dev.platform_data; int i; @@ -696,7 +696,7 @@ MODULE_ALIAS("platform:at91_ohci"); static struct platform_driver ohci_hcd_at91_driver = { .probe = ohci_hcd_at91_drv_probe, - .remove = ohci_hcd_at91_drv_remove, + .remove = __devexit_p(ohci_hcd_at91_drv_remove), .shutdown = usb_hcd_platform_shutdown, .suspend = ohci_hcd_at91_drv_suspend, .resume = ohci_hcd_at91_drv_resume, diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 959145baf3cf..9dcb68f04f03 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -423,7 +423,7 @@ alloc_sglist(int nents, int max, int vary) unsigned i; unsigned size = max; - sg = kmalloc(nents * sizeof *sg, GFP_KERNEL); + sg = kmalloc_array(nents, sizeof *sg, GFP_KERNEL); if (!sg) return NULL; sg_init_table(sg, nents); @@ -904,6 +904,9 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param) struct ctrl_ctx context; int i; + if (param->sglen == 0 || param->iterations > UINT_MAX / param->sglen) + return -EOPNOTSUPP; + spin_lock_init(&context.lock); context.dev = dev; init_completion(&context.complete); @@ -1981,8 +1984,6 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) /* queued control messaging */ case 10: - if (param->sglen == 0) - break; retval = 0; dev_info(&intf->dev, "TEST 10: queue %d control calls, %d times\n", @@ -2276,6 +2277,8 @@ usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id) if (status < 0) { WARNING(dev, "couldn't get endpoints, %d\n", status); + kfree(dev->buf); + kfree(dev); return status; } /* may find bulk or ISO pipes */ diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c index 897edda42270..70201462e19c 100644 --- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -99,9 +99,7 @@ static void yurex_delete(struct kref *kref) usb_put_dev(dev->udev); if (dev->cntl_urb) { usb_kill_urb(dev->cntl_urb); - if (dev->cntl_req) - usb_free_coherent(dev->udev, YUREX_BUF_SIZE, - dev->cntl_req, dev->cntl_urb->setup_dma); + kfree(dev->cntl_req); if (dev->cntl_buffer) usb_free_coherent(dev->udev, YUREX_BUF_SIZE, dev->cntl_buffer, dev->cntl_urb->transfer_dma); @@ -234,9 +232,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ } /* allocate buffer for control req */ - dev->cntl_req = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE, - GFP_KERNEL, - &dev->cntl_urb->setup_dma); + dev->cntl_req = kmalloc(YUREX_BUF_SIZE, GFP_KERNEL); if (!dev->cntl_req) { err("Could not allocate cntl_req"); goto error; @@ -286,7 +282,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ usb_rcvintpipe(dev->udev, dev->int_in_endpointAddr), dev->int_buffer, YUREX_BUF_SIZE, yurex_interrupt, dev, 1); - dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + dev->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; if (usb_submit_urb(dev->urb, GFP_KERNEL)) { retval = -EIO; err("Could not submitting URB"); diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 0f8b82918a40..66aaccf04490 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -137,6 +137,9 @@ static int musb_ulpi_read(struct usb_phy *phy, u32 offset) int i = 0; u8 r; u8 power; + int ret; + + pm_runtime_get_sync(phy->io_dev); /* Make sure the transceiver is not in low power mode */ power = musb_readb(addr, MUSB_POWER); @@ -154,15 +157,22 @@ static int musb_ulpi_read(struct usb_phy *phy, u32 offset) while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL) & MUSB_ULPI_REG_CMPLT)) { i++; - if (i == 10000) - return -ETIMEDOUT; + if (i == 10000) { + ret = -ETIMEDOUT; + goto out; + } } r = musb_readb(addr, MUSB_ULPI_REG_CONTROL); r &= ~MUSB_ULPI_REG_CMPLT; musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r); - return musb_readb(addr, MUSB_ULPI_REG_DATA); + ret = musb_readb(addr, MUSB_ULPI_REG_DATA); + +out: + pm_runtime_put(phy->io_dev); + + return ret; } static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) @@ -171,6 +181,9 @@ static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) int i = 0; u8 r = 0; u8 power; + int ret = 0; + + pm_runtime_get_sync(phy->io_dev); /* Make sure the transceiver is not in low power mode */ power = musb_readb(addr, MUSB_POWER); @@ -184,15 +197,20 @@ static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL) & MUSB_ULPI_REG_CMPLT)) { i++; - if (i == 10000) - return -ETIMEDOUT; + if (i == 10000) { + ret = -ETIMEDOUT; + goto out; + } } r = musb_readb(addr, MUSB_ULPI_REG_CONTROL); r &= ~MUSB_ULPI_REG_CMPLT; musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r); - return 0; +out: + pm_runtime_put(phy->io_dev); + + return ret; } #else #define musb_ulpi_read NULL @@ -1904,14 +1922,17 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) if (!musb->isr) { status = -ENODEV; - goto fail3; + goto fail2; } if (!musb->xceiv->io_ops) { + musb->xceiv->io_dev = musb->controller; musb->xceiv->io_priv = musb->mregs; musb->xceiv->io_ops = &musb_ulpi_access; } + pm_runtime_get_sync(musb->controller); + #ifndef CONFIG_MUSB_PIO_ONLY if (use_dma && dev->dma_mask) { struct dma_controller *c; @@ -2023,6 +2044,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) goto fail5; #endif + pm_runtime_put(musb->controller); + dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n", ({char *s; switch (musb->board_mode) { @@ -2047,6 +2070,9 @@ fail4: musb_gadget_cleanup(musb); fail3: + pm_runtime_put_sync(musb->controller); + +fail2: if (musb->irq_wake) device_init_wakeup(dev, 0); musb_platform_exit(musb); diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 79cb0af779fa..ef8d744800ac 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2098,7 +2098,7 @@ static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh) } /* turn off DMA requests, discard state, stop polling ... */ - if (is_in) { + if (ep->epnum && is_in) { /* giveback saves bulk toggle */ csr = musb_h_flush_rxfifo(ep, 0); diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 2ae0bb309994..c7785e81254c 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -282,7 +282,8 @@ static void musb_otg_notifier_work(struct work_struct *data_notifier_work) static int omap2430_musb_init(struct musb *musb) { - u32 l, status = 0; + u32 l; + int status = 0; struct device *dev = musb->controller; struct musb_hdrc_platform_data *plat = dev->platform_data; struct omap_musb_board_data *data = plat->board_data; @@ -301,7 +302,7 @@ static int omap2430_musb_init(struct musb *musb) status = pm_runtime_get_sync(dev); if (status < 0) { - dev_err(dev, "pm_runtime_get_sync FAILED"); + dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status); goto err1; } @@ -333,6 +334,7 @@ static int omap2430_musb_init(struct musb *musb) setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); + pm_runtime_put_noidle(musb->controller); return 0; err1: @@ -452,14 +454,14 @@ static int __devinit omap2430_probe(struct platform_device *pdev) goto err2; } + pm_runtime_enable(&pdev->dev); + ret = platform_device_add(musb); if (ret) { dev_err(&pdev->dev, "failed to register musb device\n"); goto err2; } - pm_runtime_enable(&pdev->dev); - return 0; err2: @@ -478,7 +480,6 @@ static int __devexit omap2430_remove(struct platform_device *pdev) platform_device_del(glue->musb); platform_device_put(glue->musb); - pm_runtime_put(&pdev->dev); kfree(glue); return 0; @@ -491,11 +492,13 @@ static int omap2430_runtime_suspend(struct device *dev) struct omap2430_glue *glue = dev_get_drvdata(dev); struct musb *musb = glue_to_musb(glue); - musb->context.otg_interfsel = musb_readl(musb->mregs, - OTG_INTERFSEL); + if (musb) { + musb->context.otg_interfsel = musb_readl(musb->mregs, + OTG_INTERFSEL); - omap2430_low_level_exit(musb); - usb_phy_set_suspend(musb->xceiv, 1); + omap2430_low_level_exit(musb); + usb_phy_set_suspend(musb->xceiv, 1); + } return 0; } @@ -505,11 +508,13 @@ static int omap2430_runtime_resume(struct device *dev) struct omap2430_glue *glue = dev_get_drvdata(dev); struct musb *musb = glue_to_musb(glue); - omap2430_low_level_init(musb); - musb_writel(musb->mregs, OTG_INTERFSEL, - musb->context.otg_interfsel); + if (musb) { + omap2430_low_level_init(musb); + musb_writel(musb->mregs, OTG_INTERFSEL, + musb->context.otg_interfsel); - usb_phy_set_suspend(musb->xceiv, 0); + usb_phy_set_suspend(musb->xceiv, 0); + } return 0; } diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 0310e2df59f5..ec30f95ef399 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -287,7 +287,8 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, /* Issue the request, attempting to read 'size' bytes */ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), request, REQTYPE_DEVICE_TO_HOST, 0x0000, - port_priv->bInterfaceNumber, buf, size, 300); + port_priv->bInterfaceNumber, buf, size, + USB_CTRL_GET_TIMEOUT); /* Convert data into an array of integers */ for (i = 0; i < length; i++) @@ -340,12 +341,14 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_DEVICE, 0x0000, - port_priv->bInterfaceNumber, buf, size, 300); + port_priv->bInterfaceNumber, buf, size, + USB_CTRL_SET_TIMEOUT); } else { result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_DEVICE, data[0], - port_priv->bInterfaceNumber, NULL, 0, 300); + port_priv->bInterfaceNumber, NULL, 0, + USB_CTRL_SET_TIMEOUT); } kfree(buf); diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index fdd5aa2c8d82..8c8bf806f6fa 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -221,7 +221,7 @@ static const struct sierra_iface_info typeB_interface_list = { }; /* 'blacklist' of interfaces not served by this driver */ -static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11 }; +static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11, 19, 20 }; static const struct sierra_iface_info direct_ip_interface_blacklist = { .infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces), .ifaceinfo = direct_ip_non_serial_ifaces, @@ -289,7 +289,6 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1199, 0x6856) }, /* Sierra Wireless AirCard 881 U */ { USB_DEVICE(0x1199, 0x6859) }, /* Sierra Wireless AirCard 885 E */ { USB_DEVICE(0x1199, 0x685A) }, /* Sierra Wireless AirCard 885 E */ - { USB_DEVICE(0x1199, 0x68A2) }, /* Sierra Wireless MC7710 */ /* Sierra Wireless C885 */ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)}, /* Sierra Wireless C888, Air Card 501, USB 303, USB 304 */ @@ -299,6 +298,9 @@ static const struct usb_device_id id_table[] = { /* Sierra Wireless HSPA Non-Composite Device */ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)}, { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */ + { USB_DEVICE(0x1199, 0x68A2), /* Sierra Wireless MC77xx in QMI mode */ + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist }, diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c index 66797e9c5010..810c90ae2c55 100644 --- a/drivers/uwb/hwa-rc.c +++ b/drivers/uwb/hwa-rc.c @@ -645,7 +645,8 @@ void hwarc_neep_cb(struct urb *urb) dev_err(dev, "NEEP: URB error %d\n", urb->status); } result = usb_submit_urb(urb, GFP_ATOMIC); - if (result < 0) { + if (result < 0 && result != -ENODEV && result != -EPERM) { + /* ignoring unrecoverable errors */ dev_err(dev, "NEEP: Can't resubmit URB (%d) resetting device\n", result); goto error; diff --git a/drivers/uwb/neh.c b/drivers/uwb/neh.c index a269937be1b8..8cb71bb333c2 100644 --- a/drivers/uwb/neh.c +++ b/drivers/uwb/neh.c @@ -107,6 +107,7 @@ struct uwb_rc_neh { u8 evt_type; __le16 evt; u8 context; + u8 completed; uwb_rc_cmd_cb_f cb; void *arg; @@ -409,6 +410,7 @@ static void uwb_rc_neh_grok_event(struct uwb_rc *rc, struct uwb_rceb *rceb, size struct device *dev = &rc->uwb_dev.dev; struct uwb_rc_neh *neh; struct uwb_rceb *notif; + unsigned long flags; if (rceb->bEventContext == 0) { notif = kmalloc(size, GFP_ATOMIC); @@ -422,7 +424,11 @@ static void uwb_rc_neh_grok_event(struct uwb_rc *rc, struct uwb_rceb *rceb, size } else { neh = uwb_rc_neh_lookup(rc, rceb); if (neh) { - del_timer_sync(&neh->timer); + spin_lock_irqsave(&rc->neh_lock, flags); + /* to guard against a timeout */ + neh->completed = 1; + del_timer(&neh->timer); + spin_unlock_irqrestore(&rc->neh_lock, flags); uwb_rc_neh_cb(neh, rceb, size); } else dev_warn(dev, "event 0x%02x/%04x/%02x (%zu bytes): nobody cared\n", @@ -568,6 +574,10 @@ static void uwb_rc_neh_timer(unsigned long arg) unsigned long flags; spin_lock_irqsave(&rc->neh_lock, flags); + if (neh->completed) { + spin_unlock_irqrestore(&rc->neh_lock, flags); + return; + } if (neh->context) __uwb_rc_neh_rm(rc, neh); else diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c index fc9a1d75281f..3de00d9fae2e 100644 --- a/drivers/vhost/test.c +++ b/drivers/vhost/test.c @@ -155,7 +155,7 @@ static int vhost_test_release(struct inode *inode, struct file *f) vhost_test_stop(n, &private); vhost_test_flush(n); - vhost_dev_cleanup(&n->dev); + vhost_dev_cleanup(&n->dev, false); /* We do an extra flush before freeing memory, * since jobs can re-queue themselves. */ vhost_test_flush(n); diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 05f0a80818a2..c2d05a8279fd 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -28,6 +28,13 @@ #include <linux/slab.h> #include <linux/module.h> +/* + * Balloon device works in 4K page units. So each page is pointed to by + * multiple balloon pages. All memory counters in this driver are in balloon + * page units. + */ +#define VIRTIO_BALLOON_PAGES_PER_PAGE (PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT) + struct virtio_balloon { struct virtio_device *vdev; @@ -42,8 +49,13 @@ struct virtio_balloon /* Waiting for host to ack the pages we released. */ struct completion acked; - /* The pages we've told the Host we're not using. */ + /* Number of balloon pages we've told the Host we're not using. */ unsigned int num_pages; + /* + * The pages we've told the Host we're not using. + * Each page on this list adds VIRTIO_BALLOON_PAGES_PER_PAGE + * to num_pages above. + */ struct list_head pages; /* The array of pfns we tell the Host about. */ @@ -66,7 +78,13 @@ static u32 page_to_balloon_pfn(struct page *page) BUILD_BUG_ON(PAGE_SHIFT < VIRTIO_BALLOON_PFN_SHIFT); /* Convert pfn from Linux page size to balloon page size. */ - return pfn >> (PAGE_SHIFT - VIRTIO_BALLOON_PFN_SHIFT); + return pfn * VIRTIO_BALLOON_PAGES_PER_PAGE; +} + +static struct page *balloon_pfn_to_page(u32 pfn) +{ + BUG_ON(pfn % VIRTIO_BALLOON_PAGES_PER_PAGE); + return pfn_to_page(pfn / VIRTIO_BALLOON_PAGES_PER_PAGE); } static void balloon_ack(struct virtqueue *vq) @@ -96,12 +114,23 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq) wait_for_completion(&vb->acked); } +static void set_page_pfns(u32 pfns[], struct page *page) +{ + unsigned int i; + + /* Set balloon pfns pointing at this page. + * Note that the first pfn points at start of the page. */ + for (i = 0; i < VIRTIO_BALLOON_PAGES_PER_PAGE; i++) + pfns[i] = page_to_balloon_pfn(page) + i; +} + static void fill_balloon(struct virtio_balloon *vb, size_t num) { /* We can only do one array worth at a time. */ num = min(num, ARRAY_SIZE(vb->pfns)); - for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) { + for (vb->num_pfns = 0; vb->num_pfns < num; + vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) { struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); if (!page) { @@ -113,9 +142,9 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num) msleep(200); break; } - vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page); + set_page_pfns(vb->pfns + vb->num_pfns, page); + vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE; totalram_pages--; - vb->num_pages++; list_add(&page->lru, &vb->pages); } @@ -130,8 +159,9 @@ static void release_pages_by_pfn(const u32 pfns[], unsigned int num) { unsigned int i; - for (i = 0; i < num; i++) { - __free_page(pfn_to_page(pfns[i])); + /* Find pfns pointing at start of each page, get pages and free them. */ + for (i = 0; i < num; i += VIRTIO_BALLOON_PAGES_PER_PAGE) { + __free_page(balloon_pfn_to_page(pfns[i])); totalram_pages++; } } @@ -143,11 +173,12 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num) /* We can only do one array worth at a time. */ num = min(num, ARRAY_SIZE(vb->pfns)); - for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) { + for (vb->num_pfns = 0; vb->num_pfns < num; + vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) { page = list_first_entry(&vb->pages, struct page, lru); list_del(&page->lru); - vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page); - vb->num_pages--; + set_page_pfns(vb->pfns + vb->num_pfns, page); + vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE; } /* @@ -234,11 +265,14 @@ static void virtballoon_changed(struct virtio_device *vdev) static inline s64 towards_target(struct virtio_balloon *vb) { - u32 v; + __le32 v; + s64 target; + vb->vdev->config->get(vb->vdev, offsetof(struct virtio_balloon_config, num_pages), &v, sizeof(v)); - return (s64)v - vb->num_pages; + target = le32_to_cpu(v); + return target - vb->num_pages; } static void update_balloon_size(struct virtio_balloon *vb) diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 99d8151c824a..1ffd03bf8e10 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -722,7 +722,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma) vma->vm_flags |= VM_RESERVED|VM_DONTEXPAND; if (use_ptemod) - vma->vm_flags |= VM_DONTCOPY|VM_PFNMAP; + vma->vm_flags |= VM_DONTCOPY; vma->vm_private_data = map; diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index b4d4eac761db..f100ce20b16b 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -1029,6 +1029,7 @@ int gnttab_init(void) int i; unsigned int max_nr_glist_frames, nr_glist_frames; unsigned int nr_init_grefs; + int ret; nr_grant_frames = 1; boot_max_nr_grant_frames = __max_nr_grant_frames(); @@ -1047,12 +1048,16 @@ int gnttab_init(void) nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; for (i = 0; i < nr_glist_frames; i++) { gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL); - if (gnttab_list[i] == NULL) + if (gnttab_list[i] == NULL) { + ret = -ENOMEM; goto ini_nomem; + } } - if (gnttab_resume() < 0) - return -ENODEV; + if (gnttab_resume() < 0) { + ret = -ENODEV; + goto ini_nomem; + } nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME; @@ -1070,7 +1075,7 @@ int gnttab_init(void) for (i--; i >= 0; i--) free_page((unsigned long)gnttab_list[i]); kfree(gnttab_list); - return -ENOMEM; + return ret; } EXPORT_SYMBOL_GPL(gnttab_init); diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 9e14ae6cd49c..412b96cc5305 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -132,6 +132,7 @@ static void do_suspend(void) err = dpm_suspend_end(PMSG_FREEZE); if (err) { printk(KERN_ERR "dpm_suspend_end failed: %d\n", err); + si.cancelled = 0; goto out_resume; } diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index f20c5f178b40..a31b54d48839 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c @@ -135,7 +135,7 @@ static int read_backend_details(struct xenbus_device *xendev) return xenbus_read_otherend_details(xendev, "backend-id", "backend"); } -static int is_device_connecting(struct device *dev, void *data) +static int is_device_connecting(struct device *dev, void *data, bool ignore_nonessential) { struct xenbus_device *xendev = to_xenbus_device(dev); struct device_driver *drv = data; @@ -152,16 +152,41 @@ static int is_device_connecting(struct device *dev, void *data) if (drv && (dev->driver != drv)) return 0; + if (ignore_nonessential) { + /* With older QEMU, for PVonHVM guests the guest config files + * could contain: vfb = [ 'vnc=1, vnclisten=0.0.0.0'] + * which is nonsensical as there is no PV FB (there can be + * a PVKB) running as HVM guest. */ + + if ((strncmp(xendev->nodename, "device/vkbd", 11) == 0)) + return 0; + + if ((strncmp(xendev->nodename, "device/vfb", 10) == 0)) + return 0; + } xendrv = to_xenbus_driver(dev->driver); return (xendev->state < XenbusStateConnected || (xendev->state == XenbusStateConnected && xendrv->is_ready && !xendrv->is_ready(xendev))); } +static int essential_device_connecting(struct device *dev, void *data) +{ + return is_device_connecting(dev, data, true /* ignore PV[KBB+FB] */); +} +static int non_essential_device_connecting(struct device *dev, void *data) +{ + return is_device_connecting(dev, data, false); +} -static int exists_connecting_device(struct device_driver *drv) +static int exists_essential_connecting_device(struct device_driver *drv) { return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, - is_device_connecting); + essential_device_connecting); +} +static int exists_non_essential_connecting_device(struct device_driver *drv) +{ + return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, + non_essential_device_connecting); } static int print_device_status(struct device *dev, void *data) @@ -192,6 +217,23 @@ static int print_device_status(struct device *dev, void *data) /* We only wait for device setup after most initcalls have run. */ static int ready_to_wait_for_devices; +static bool wait_loop(unsigned long start, unsigned int max_delay, + unsigned int *seconds_waited) +{ + if (time_after(jiffies, start + (*seconds_waited+5)*HZ)) { + if (!*seconds_waited) + printk(KERN_WARNING "XENBUS: Waiting for " + "devices to initialise: "); + *seconds_waited += 5; + printk("%us...", max_delay - *seconds_waited); + if (*seconds_waited == max_delay) + return true; + } + + schedule_timeout_interruptible(HZ/10); + + return false; +} /* * On a 5-minute timeout, wait for all devices currently configured. We need * to do this to guarantee that the filesystems and / or network devices @@ -215,19 +257,14 @@ static void wait_for_devices(struct xenbus_driver *xendrv) if (!ready_to_wait_for_devices || !xen_domain()) return; - while (exists_connecting_device(drv)) { - if (time_after(jiffies, start + (seconds_waited+5)*HZ)) { - if (!seconds_waited) - printk(KERN_WARNING "XENBUS: Waiting for " - "devices to initialise: "); - seconds_waited += 5; - printk("%us...", 300 - seconds_waited); - if (seconds_waited == 300) - break; - } - - schedule_timeout_interruptible(HZ/10); - } + while (exists_non_essential_connecting_device(drv)) + if (wait_loop(start, 30, &seconds_waited)) + break; + + /* Skips PVKB and PVFB check.*/ + while (exists_essential_connecting_device(drv)) + if (wait_loop(start, 270, &seconds_waited)) + break; if (seconds_waited) printk("\n"); @@ -93,9 +93,8 @@ static void aio_free_ring(struct kioctx *ctx) put_page(info->ring_pages[i]); if (info->mmap_size) { - down_write(&ctx->mm->mmap_sem); - do_munmap(ctx->mm, info->mmap_base, info->mmap_size); - up_write(&ctx->mm->mmap_sem); + BUG_ON(ctx->mm != current->mm); + vm_munmap(info->mmap_base, info->mmap_size); } if (info->ring_pages && info->ring_pages != info->internal_pages) @@ -389,6 +388,17 @@ void exit_aio(struct mm_struct *mm) "exit_aio:ioctx still alive: %d %d %d\n", atomic_read(&ctx->users), ctx->dead, ctx->reqs_active); + /* + * We don't need to bother with munmap() here - + * exit_mmap(mm) is coming and it'll unmap everything. + * Since aio_free_ring() uses non-zero ->mmap_size + * as indicator that it needs to unmap the area, + * just set it to 0; aio_free_ring() is the only + * place that uses ->mmap_size, so it's safe. + * That way we get all munmap done to current->mm - + * all other callers have ctx->mm == current->mm. + */ + ctx->ring_info.mmap_size = 0; put_ioctx(ctx); } } diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index 2eb12f13593d..d146e181d10d 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -50,9 +50,7 @@ static int set_brk(unsigned long start, unsigned long end) end = PAGE_ALIGN(end); if (end > start) { unsigned long addr; - down_write(¤t->mm->mmap_sem); - addr = do_brk(start, end - start); - up_write(¤t->mm->mmap_sem); + addr = vm_brk(start, end - start); if (BAD_ADDR(addr)) return addr; } @@ -280,9 +278,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) pos = 32; map_size = ex.a_text+ex.a_data; #endif - down_write(¤t->mm->mmap_sem); - error = do_brk(text_addr & PAGE_MASK, map_size); - up_write(¤t->mm->mmap_sem); + error = vm_brk(text_addr & PAGE_MASK, map_size); if (error != (text_addr & PAGE_MASK)) { send_sig(SIGKILL, current, 0); return error; @@ -313,9 +309,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) { loff_t pos = fd_offset; - down_write(¤t->mm->mmap_sem); - do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); - up_write(¤t->mm->mmap_sem); + vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); @@ -325,24 +319,20 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) goto beyond_if; } - down_write(¤t->mm->mmap_sem); - error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, + error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset); - up_write(¤t->mm->mmap_sem); if (error != N_TXTADDR(ex)) { send_sig(SIGKILL, current, 0); return error; } - down_write(¤t->mm->mmap_sem); - error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, + error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset + ex.a_text); - up_write(¤t->mm->mmap_sem); if (error != N_DATADDR(ex)) { send_sig(SIGKILL, current, 0); return error; @@ -412,9 +402,7 @@ static int load_aout_library(struct file *file) "N_TXTOFF is not page aligned. Please convert library: %s\n", file->f_path.dentry->d_name.name); } - down_write(¤t->mm->mmap_sem); - do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); - up_write(¤t->mm->mmap_sem); + vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); file->f_op->read(file, (char __user *)start_addr, ex.a_text + ex.a_data, &pos); @@ -425,12 +413,10 @@ static int load_aout_library(struct file *file) goto out; } /* Now use mmap to map the library into memory. */ - down_write(¤t->mm->mmap_sem); - error = do_mmap(file, start_addr, ex.a_text + ex.a_data, + error = vm_mmap(file, start_addr, ex.a_text + ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, N_TXTOFF(ex)); - up_write(¤t->mm->mmap_sem); retval = error; if (error != start_addr) goto out; @@ -438,9 +424,7 @@ static int load_aout_library(struct file *file) len = PAGE_ALIGN(ex.a_text + ex.a_data); bss = ex.a_text + ex.a_data + ex.a_bss; if (bss > len) { - down_write(¤t->mm->mmap_sem); - error = do_brk(start_addr + len, bss - len); - up_write(¤t->mm->mmap_sem); + error = vm_brk(start_addr + len, bss - len); retval = error; if (error != start_addr + len) goto out; diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 48ffb3dc610a..16f735417072 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -82,9 +82,7 @@ static int set_brk(unsigned long start, unsigned long end) end = ELF_PAGEALIGN(end); if (end > start) { unsigned long addr; - down_write(¤t->mm->mmap_sem); - addr = do_brk(start, end - start); - up_write(¤t->mm->mmap_sem); + addr = vm_brk(start, end - start); if (BAD_ADDR(addr)) return addr; } @@ -514,9 +512,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1); /* Map the last of the bss segment */ - down_write(¤t->mm->mmap_sem); - error = do_brk(elf_bss, last_bss - elf_bss); - up_write(¤t->mm->mmap_sem); + error = vm_brk(elf_bss, last_bss - elf_bss); if (BAD_ADDR(error)) goto out_close; } @@ -962,10 +958,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) and some applications "depend" upon this behavior. Since we do not have the power to recompile these, we emulate the SVr4 behavior. Sigh. */ - down_write(¤t->mm->mmap_sem); - error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, + error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); - up_write(¤t->mm->mmap_sem); } #ifdef ELF_PLAT_INIT @@ -1050,8 +1044,7 @@ static int load_elf_library(struct file *file) eppnt++; /* Now use mmap to map the library into memory. */ - down_write(¤t->mm->mmap_sem); - error = do_mmap(file, + error = vm_mmap(file, ELF_PAGESTART(eppnt->p_vaddr), (eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr)), @@ -1059,7 +1052,6 @@ static int load_elf_library(struct file *file) MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, (eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr))); - up_write(¤t->mm->mmap_sem); if (error != ELF_PAGESTART(eppnt->p_vaddr)) goto out_free_ph; @@ -1072,11 +1064,8 @@ static int load_elf_library(struct file *file) len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr + ELF_MIN_ALIGN - 1); bss = eppnt->p_memsz + eppnt->p_vaddr; - if (bss > len) { - down_write(¤t->mm->mmap_sem); - do_brk(len, bss - len); - up_write(¤t->mm->mmap_sem); - } + if (bss > len) + vm_brk(len, bss - len); error = 0; out_free_ph: diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 9bd5612a8224..d390a0fffc65 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -390,21 +390,17 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, (executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC)) stack_prot |= PROT_EXEC; - down_write(¤t->mm->mmap_sem); - current->mm->start_brk = do_mmap(NULL, 0, stack_size, stack_prot, + current->mm->start_brk = vm_mmap(NULL, 0, stack_size, stack_prot, MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZED | MAP_GROWSDOWN, 0); if (IS_ERR_VALUE(current->mm->start_brk)) { - up_write(¤t->mm->mmap_sem); retval = current->mm->start_brk; current->mm->start_brk = 0; goto error_kill; } - up_write(¤t->mm->mmap_sem); - current->mm->brk = current->mm->start_brk; current->mm->context.end_brk = current->mm->start_brk; current->mm->context.end_brk += @@ -955,10 +951,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux( if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE) mflags |= MAP_EXECUTABLE; - down_write(&mm->mmap_sem); - maddr = do_mmap(NULL, load_addr, top - base, + maddr = vm_mmap(NULL, load_addr, top - base, PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0); - up_write(&mm->mmap_sem); if (IS_ERR_VALUE(maddr)) return (int) maddr; @@ -1096,10 +1090,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, /* create the mapping */ disp = phdr->p_vaddr & ~PAGE_MASK; - down_write(&mm->mmap_sem); - maddr = do_mmap(file, maddr, phdr->p_memsz + disp, prot, flags, + maddr = vm_mmap(file, maddr, phdr->p_memsz + disp, prot, flags, phdr->p_offset - disp); - up_write(&mm->mmap_sem); kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx", loop, phdr->p_memsz + disp, prot, flags, @@ -1143,10 +1135,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, unsigned long xmaddr; flags |= MAP_FIXED | MAP_ANONYMOUS; - down_write(&mm->mmap_sem); - xmaddr = do_mmap(NULL, xaddr, excess - excess1, + xmaddr = vm_mmap(NULL, xaddr, excess - excess1, prot, flags, 0); - up_write(&mm->mmap_sem); kdebug("mmap[%d] <anon>" " ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx", diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 024d20ee3ca3..6b2daf99fab8 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -542,10 +542,8 @@ static int load_flat_file(struct linux_binprm * bprm, */ DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); - down_write(¤t->mm->mmap_sem); - textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, + textpos = vm_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_EXECUTABLE, 0); - up_write(¤t->mm->mmap_sem); if (!textpos || IS_ERR_VALUE(textpos)) { if (!textpos) textpos = (unsigned long) -ENOMEM; @@ -556,10 +554,8 @@ static int load_flat_file(struct linux_binprm * bprm, len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); len = PAGE_ALIGN(len); - down_write(¤t->mm->mmap_sem); - realdatastart = do_mmap(0, 0, len, + realdatastart = vm_mmap(0, 0, len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); - up_write(¤t->mm->mmap_sem); if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) { if (!realdatastart) @@ -603,10 +599,8 @@ static int load_flat_file(struct linux_binprm * bprm, len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); len = PAGE_ALIGN(len); - down_write(¤t->mm->mmap_sem); - textpos = do_mmap(0, 0, len, + textpos = vm_mmap(0, 0, len, PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); - up_write(¤t->mm->mmap_sem); if (!textpos || IS_ERR_VALUE(textpos)) { if (!textpos) diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c index e4fc746629a7..4517aaff61b4 100644 --- a/fs/binfmt_som.c +++ b/fs/binfmt_som.c @@ -147,10 +147,8 @@ static int map_som_binary(struct file *file, code_size = SOM_PAGEALIGN(hpuxhdr->exec_tsize); current->mm->start_code = code_start; current->mm->end_code = code_start + code_size; - down_write(¤t->mm->mmap_sem); - retval = do_mmap(file, code_start, code_size, prot, + retval = vm_mmap(file, code_start, code_size, prot, flags, SOM_PAGESTART(hpuxhdr->exec_tfile)); - up_write(¤t->mm->mmap_sem); if (retval < 0 && retval > -1024) goto out; @@ -158,20 +156,16 @@ static int map_som_binary(struct file *file, data_size = SOM_PAGEALIGN(hpuxhdr->exec_dsize); current->mm->start_data = data_start; current->mm->end_data = bss_start = data_start + data_size; - down_write(¤t->mm->mmap_sem); - retval = do_mmap(file, data_start, data_size, + retval = vm_mmap(file, data_start, data_size, prot | PROT_WRITE, flags, SOM_PAGESTART(hpuxhdr->exec_dfile)); - up_write(¤t->mm->mmap_sem); if (retval < 0 && retval > -1024) goto out; som_brk = bss_start + SOM_PAGEALIGN(hpuxhdr->exec_bsize); current->mm->start_brk = current->mm->brk = som_brk; - down_write(¤t->mm->mmap_sem); - retval = do_mmap(NULL, bss_start, som_brk - bss_start, + retval = vm_mmap(NULL, bss_start, som_brk - bss_start, prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, 0); - up_write(¤t->mm->mmap_sem); if (retval > 0 || retval < -1024) retval = 0; out: diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 5b8ef8eb3521..3f65a812e282 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2166,7 +2166,7 @@ BTRFS_SETGET_STACK_FUNCS(root_last_snapshot, struct btrfs_root_item, static inline bool btrfs_root_readonly(struct btrfs_root *root) { - return root->root_item.flags & BTRFS_ROOT_SUBVOL_RDONLY; + return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_RDONLY)) != 0; } /* struct btrfs_root_backup */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index d81e933a796b..f31dc9ac37b7 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -109,6 +109,8 @@ enum { /* Options which could be blank */ Opt_blank_pass, + Opt_blank_user, + Opt_blank_ip, Opt_err }; @@ -183,11 +185,15 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_wsize, "wsize=%s" }, { Opt_actimeo, "actimeo=%s" }, + { Opt_blank_user, "user=" }, + { Opt_blank_user, "username=" }, { Opt_user, "user=%s" }, { Opt_user, "username=%s" }, { Opt_blank_pass, "pass=" }, { Opt_pass, "pass=%s" }, { Opt_pass, "password=%s" }, + { Opt_blank_ip, "ip=" }, + { Opt_blank_ip, "addr=" }, { Opt_ip, "ip=%s" }, { Opt_ip, "addr=%s" }, { Opt_unc, "unc=%s" }, @@ -1117,7 +1123,7 @@ static int get_option_ul(substring_t args[], unsigned long *option) string = match_strdup(args); if (string == NULL) return -ENOMEM; - rc = kstrtoul(string, 10, option); + rc = kstrtoul(string, 0, option); kfree(string); return rc; @@ -1534,15 +1540,17 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, /* String Arguments */ + case Opt_blank_user: + /* null user, ie. anonymous authentication */ + vol->nullauth = 1; + vol->username = NULL; + break; case Opt_user: string = match_strdup(args); if (string == NULL) goto out_nomem; - if (!*string) { - /* null user, ie. anonymous authentication */ - vol->nullauth = 1; - } else if (strnlen(string, MAX_USERNAME_SIZE) > + if (strnlen(string, MAX_USERNAME_SIZE) > MAX_USERNAME_SIZE) { printk(KERN_WARNING "CIFS: username too long\n"); goto cifs_parse_mount_err; @@ -1611,14 +1619,15 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, } vol->password[j] = '\0'; break; + case Opt_blank_ip: + vol->UNCip = NULL; + break; case Opt_ip: string = match_strdup(args); if (string == NULL) goto out_nomem; - if (!*string) { - vol->UNCip = NULL; - } else if (strnlen(string, INET6_ADDRSTRLEN) > + if (strnlen(string, INET6_ADDRSTRLEN) > INET6_ADDRSTRLEN) { printk(KERN_WARNING "CIFS: ip address " "too long\n"); @@ -1636,12 +1645,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: invalid path to " - "network resource\n"); - goto cifs_parse_mount_err; - } - temp_len = strnlen(string, 300); if (temp_len == 300) { printk(KERN_WARNING "CIFS: UNC name too long\n"); @@ -1670,11 +1673,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: invalid domain" - " name\n"); - goto cifs_parse_mount_err; - } else if (strnlen(string, 256) == 256) { + if (strnlen(string, 256) == 256) { printk(KERN_WARNING "CIFS: domain name too" " long\n"); goto cifs_parse_mount_err; @@ -1693,11 +1692,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: srcaddr value not" - " specified\n"); - goto cifs_parse_mount_err; - } else if (!cifs_convert_address( + if (!cifs_convert_address( (struct sockaddr *)&vol->srcaddr, string, strlen(string))) { printk(KERN_WARNING "CIFS: Could not parse" @@ -1710,11 +1705,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: Invalid path" - " prefix\n"); - goto cifs_parse_mount_err; - } temp_len = strnlen(string, 1024); if (string[0] != '/') temp_len++; /* missing leading slash */ @@ -1742,11 +1732,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: Invalid iocharset" - " specified\n"); - goto cifs_parse_mount_err; - } else if (strnlen(string, 1024) >= 65) { + if (strnlen(string, 1024) >= 65) { printk(KERN_WARNING "CIFS: iocharset name " "too long.\n"); goto cifs_parse_mount_err; @@ -1771,11 +1757,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: No socket option" - " specified\n"); - goto cifs_parse_mount_err; - } if (strnicmp(string, "TCP_NODELAY", 11) == 0) vol->sockopt_tcp_nodelay = 1; break; @@ -1784,12 +1765,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: Invalid (empty)" - " netbiosname\n"); - break; - } - memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN); /* @@ -1817,11 +1792,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: Empty server" - " netbiosname specified\n"); - break; - } /* last byte, type, is 0x20 for servr type */ memset(vol->target_rfc1001_name, 0x20, RFC1001_NAME_LEN_WITH_NULL); @@ -1848,12 +1818,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - cERROR(1, "no protocol version specified" - " after vers= mount option"); - goto cifs_parse_mount_err; - } - if (strnicmp(string, "cifs", 4) == 0 || strnicmp(string, "1", 1) == 0) { /* This is the default */ @@ -1868,12 +1832,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: no security flavor" - " specified\n"); - break; - } - if (cifs_parse_security_flavors(string, vol) != 0) goto cifs_parse_mount_err; break; diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index ab2594a30f86..0e01e90add8b 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1203,9 +1203,6 @@ struct ext4_sb_info { unsigned long s_ext_blocks; unsigned long s_ext_extents; #endif - /* ext4 extent cache stats */ - unsigned long extent_cache_hits; - unsigned long extent_cache_misses; /* for buddy allocator */ struct ext4_group_info ***s_group_info; diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 1421938e6792..abcdeab67f52 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2066,10 +2066,6 @@ static int ext4_ext_check_cache(struct inode *inode, ext4_lblk_t block, ret = 1; } errout: - if (!ret) - sbi->extent_cache_misses++; - else - sbi->extent_cache_hits++; trace_ext4_ext_in_cache(inode, block, ret); spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); return ret; @@ -2882,7 +2878,7 @@ static int ext4_split_extent_at(handle_t *handle, if (err) goto fix_extent_len; /* update the extent length and mark as initialized */ - ex->ee_len = cpu_to_le32(ee_len); + ex->ee_len = cpu_to_le16(ee_len); ext4_ext_try_to_merge(inode, path, ex); err = ext4_ext_dirty(handle, inode, path + depth); goto out; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index ceebaf853beb..6da193564e43 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1305,20 +1305,20 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args) ext4_msg(sb, KERN_ERR, "Cannot change journaled " "quota options when quota turned on"); - return 0; + return -1; } qname = match_strdup(args); if (!qname) { ext4_msg(sb, KERN_ERR, "Not enough memory for storing quotafile name"); - return 0; + return -1; } if (sbi->s_qf_names[qtype] && strcmp(sbi->s_qf_names[qtype], qname)) { ext4_msg(sb, KERN_ERR, "%s quota file already specified", QTYPE2NAME(qtype)); kfree(qname); - return 0; + return -1; } sbi->s_qf_names[qtype] = qname; if (strchr(sbi->s_qf_names[qtype], '/')) { @@ -1326,7 +1326,7 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args) "quotafile must be on filesystem root"); kfree(sbi->s_qf_names[qtype]); sbi->s_qf_names[qtype] = NULL; - return 0; + return -1; } set_opt(sb, QUOTA); return 1; @@ -1341,7 +1341,7 @@ static int clear_qf_name(struct super_block *sb, int qtype) sbi->s_qf_names[qtype]) { ext4_msg(sb, KERN_ERR, "Cannot change journaled quota options" " when quota turned on"); - return 0; + return -1; } /* * The space will be released later when all options are confirmed @@ -1450,6 +1450,16 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, const struct mount_opts *m; int arg = 0; +#ifdef CONFIG_QUOTA + if (token == Opt_usrjquota) + return set_qf_name(sb, USRQUOTA, &args[0]); + else if (token == Opt_grpjquota) + return set_qf_name(sb, GRPQUOTA, &args[0]); + else if (token == Opt_offusrjquota) + return clear_qf_name(sb, USRQUOTA); + else if (token == Opt_offgrpjquota) + return clear_qf_name(sb, GRPQUOTA); +#endif if (args->from && match_int(args, &arg)) return -1; switch (token) { @@ -1549,18 +1559,6 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, sbi->s_mount_opt |= m->mount_opt; } #ifdef CONFIG_QUOTA - } else if (token == Opt_usrjquota) { - if (!set_qf_name(sb, USRQUOTA, &args[0])) - return -1; - } else if (token == Opt_grpjquota) { - if (!set_qf_name(sb, GRPQUOTA, &args[0])) - return -1; - } else if (token == Opt_offusrjquota) { - if (!clear_qf_name(sb, USRQUOTA)) - return -1; - } else if (token == Opt_offgrpjquota) { - if (!clear_qf_name(sb, GRPQUOTA)) - return -1; } else if (m->flags & MOPT_QFMT) { if (sb_any_quota_loaded(sb) && sbi->s_jquota_fmt != m->mount_opt) { @@ -2366,18 +2364,6 @@ static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a, EXT4_SB(sb)->s_sectors_written_start) >> 1))); } -static ssize_t extent_cache_hits_show(struct ext4_attr *a, - struct ext4_sb_info *sbi, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_hits); -} - -static ssize_t extent_cache_misses_show(struct ext4_attr *a, - struct ext4_sb_info *sbi, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_misses); -} - static ssize_t inode_readahead_blks_store(struct ext4_attr *a, struct ext4_sb_info *sbi, const char *buf, size_t count) @@ -2435,8 +2421,6 @@ static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store) EXT4_RO_ATTR(delayed_allocation_blocks); EXT4_RO_ATTR(session_write_kbytes); EXT4_RO_ATTR(lifetime_write_kbytes); -EXT4_RO_ATTR(extent_cache_hits); -EXT4_RO_ATTR(extent_cache_misses); EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show, inode_readahead_blks_store, s_inode_readahead_blks); EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); @@ -2452,8 +2436,6 @@ static struct attribute *ext4_attrs[] = { ATTR_LIST(delayed_allocation_blocks), ATTR_LIST(session_write_kbytes), ATTR_LIST(lifetime_write_kbytes), - ATTR_LIST(extent_cache_hits), - ATTR_LIST(extent_cache_misses), ATTR_LIST(inode_readahead_blks), ATTR_LIST(inode_goal), ATTR_LIST(mb_stats), diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 206632887bb4..df5ac048dc74 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -387,9 +387,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, if (fc->no_create) return -ENOSYS; - if (flags & O_DIRECT) - return -EINVAL; - forget = fuse_alloc_forget(); if (!forget) return -ENOMEM; @@ -644,13 +641,12 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) fuse_put_request(fc, req); if (!err) { struct inode *inode = entry->d_inode; + struct fuse_inode *fi = get_fuse_inode(inode); - /* - * Set nlink to zero so the inode can be cleared, if the inode - * does have more links this will be discovered at the next - * lookup/getattr. - */ - clear_nlink(inode); + spin_lock(&fc->lock); + fi->attr_version = ++fc->attr_version; + drop_nlink(inode); + spin_unlock(&fc->lock); fuse_invalidate_attr(inode); fuse_invalidate_attr(dir); fuse_invalidate_entry_cache(entry); @@ -762,8 +758,17 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, will reflect changes in the backing inode (link count, etc.) */ - if (!err || err == -EINTR) + if (!err) { + struct fuse_inode *fi = get_fuse_inode(inode); + + spin_lock(&fc->lock); + fi->attr_version = ++fc->attr_version; + inc_nlink(inode); + spin_unlock(&fc->lock); + fuse_invalidate_attr(inode); + } else if (err == -EINTR) { fuse_invalidate_attr(inode); + } return err; } diff --git a/fs/fuse/file.c b/fs/fuse/file.c index a841868bf9ce..504e61b7fd75 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -194,10 +194,6 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir) struct fuse_conn *fc = get_fuse_conn(inode); int err; - /* VFS checks this, but only _after_ ->open() */ - if (file->f_flags & O_DIRECT) - return -EINVAL; - err = generic_file_open(inode, file); if (err) return err; @@ -932,17 +928,23 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov, struct file *file = iocb->ki_filp; struct address_space *mapping = file->f_mapping; size_t count = 0; + size_t ocount = 0; ssize_t written = 0; + ssize_t written_buffered = 0; struct inode *inode = mapping->host; ssize_t err; struct iov_iter i; + loff_t endbyte = 0; WARN_ON(iocb->ki_pos != pos); - err = generic_segment_checks(iov, &nr_segs, &count, VERIFY_READ); + ocount = 0; + err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ); if (err) return err; + count = ocount; + mutex_lock(&inode->i_mutex); vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); @@ -962,11 +964,41 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov, file_update_time(file); - iov_iter_init(&i, iov, nr_segs, count, 0); - written = fuse_perform_write(file, mapping, &i, pos); - if (written >= 0) - iocb->ki_pos = pos + written; + if (file->f_flags & O_DIRECT) { + written = generic_file_direct_write(iocb, iov, &nr_segs, + pos, &iocb->ki_pos, + count, ocount); + if (written < 0 || written == count) + goto out; + + pos += written; + count -= written; + iov_iter_init(&i, iov, nr_segs, count, written); + written_buffered = fuse_perform_write(file, mapping, &i, pos); + if (written_buffered < 0) { + err = written_buffered; + goto out; + } + endbyte = pos + written_buffered - 1; + + err = filemap_write_and_wait_range(file->f_mapping, pos, + endbyte); + if (err) + goto out; + + invalidate_mapping_pages(file->f_mapping, + pos >> PAGE_CACHE_SHIFT, + endbyte >> PAGE_CACHE_SHIFT); + + written += written_buffered; + iocb->ki_pos = pos + written_buffered; + } else { + iov_iter_init(&i, iov, nr_segs, count, 0); + written = fuse_perform_write(file, mapping, &i, pos); + if (written >= 0) + iocb->ki_pos = pos + written; + } out: current->backing_dev_info = NULL; mutex_unlock(&inode->i_mutex); @@ -1101,30 +1133,41 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf, return res; } -static ssize_t fuse_direct_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) +static ssize_t __fuse_direct_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) { struct inode *inode = file->f_path.dentry->d_inode; ssize_t res; - if (is_bad_inode(inode)) - return -EIO; - - /* Don't allow parallel writes to the same file */ - mutex_lock(&inode->i_mutex); res = generic_write_checks(file, ppos, &count, 0); if (!res) { res = fuse_direct_io(file, buf, count, ppos, 1); if (res > 0) fuse_write_update_size(inode, *ppos); } - mutex_unlock(&inode->i_mutex); fuse_invalidate_attr(inode); return res; } +static ssize_t fuse_direct_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct inode *inode = file->f_path.dentry->d_inode; + ssize_t res; + + if (is_bad_inode(inode)) + return -EIO; + + /* Don't allow parallel writes to the same file */ + mutex_lock(&inode->i_mutex); + res = __fuse_direct_write(file, buf, count, ppos); + mutex_unlock(&inode->i_mutex); + + return res; +} + static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req) { __free_page(req->pages[0]); @@ -2077,6 +2120,57 @@ int fuse_notify_poll_wakeup(struct fuse_conn *fc, return 0; } +static ssize_t fuse_loop_dio(struct file *filp, const struct iovec *iov, + unsigned long nr_segs, loff_t *ppos, int rw) +{ + const struct iovec *vector = iov; + ssize_t ret = 0; + + while (nr_segs > 0) { + void __user *base; + size_t len; + ssize_t nr; + + base = vector->iov_base; + len = vector->iov_len; + vector++; + nr_segs--; + + if (rw == WRITE) + nr = __fuse_direct_write(filp, base, len, ppos); + else + nr = fuse_direct_read(filp, base, len, ppos); + + if (nr < 0) { + if (!ret) + ret = nr; + break; + } + ret += nr; + if (nr != len) + break; + } + + return ret; +} + + +static ssize_t +fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, + loff_t offset, unsigned long nr_segs) +{ + ssize_t ret = 0; + struct file *file = NULL; + loff_t pos = 0; + + file = iocb->ki_filp; + pos = offset; + + ret = fuse_loop_dio(file, iov, nr_segs, &pos, rw); + + return ret; +} + static const struct file_operations fuse_file_operations = { .llseek = fuse_file_llseek, .read = do_sync_read, @@ -2120,6 +2214,7 @@ static const struct address_space_operations fuse_file_aops = { .readpages = fuse_readpages, .set_page_dirty = __set_page_dirty_nobuffers, .bmap = fuse_bmap, + .direct_IO = fuse_direct_IO, }; void fuse_init_file_inode(struct inode *inode) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 4aec5995867e..26783eb2b1fc 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -947,6 +947,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) sb->s_magic = FUSE_SUPER_MAGIC; sb->s_op = &fuse_super_operations; sb->s_maxbytes = MAX_LFS_FILESIZE; + sb->s_time_gran = 1; sb->s_export_op = &fuse_export_operations; file = fget(d.fd); diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c index 3ddcbb1c0a43..13ad1539fbf2 100644 --- a/fs/lockd/clnt4xdr.c +++ b/fs/lockd/clnt4xdr.c @@ -241,7 +241,7 @@ static int decode_nlm4_stat(struct xdr_stream *xdr, __be32 *stat) p = xdr_inline_decode(xdr, 4); if (unlikely(p == NULL)) goto out_overflow; - if (unlikely(*p > nlm4_failed)) + if (unlikely(ntohl(*p) > ntohl(nlm4_failed))) goto out_bad_xdr; *stat = *p; return 0; diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c index 3d35e3e80c1c..d269ada7670e 100644 --- a/fs/lockd/clntxdr.c +++ b/fs/lockd/clntxdr.c @@ -236,7 +236,7 @@ static int decode_nlm_stat(struct xdr_stream *xdr, p = xdr_inline_decode(xdr, 4); if (unlikely(p == NULL)) goto out_overflow; - if (unlikely(*p > nlm_lck_denied_grace_period)) + if (unlikely(ntohl(*p) > ntohl(nlm_lck_denied_grace_period))) goto out_enum; *stat = *p; return 0; diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 08c6e36ab2eb..43f46cd9edea 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -803,13 +803,13 @@ encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, return p; } -static int +static __be32 compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, const char *name, int namlen) { struct svc_export *exp; struct dentry *dparent, *dchild; - int rv = 0; + __be32 rv = nfserr_noent; dparent = cd->fh.fh_dentry; exp = cd->fh.fh_export; @@ -817,26 +817,20 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, if (isdotent(name, namlen)) { if (namlen == 2) { dchild = dget_parent(dparent); - if (dchild == dparent) { - /* filesystem root - cannot return filehandle for ".." */ - dput(dchild); - return -ENOENT; - } + /* filesystem root - cannot return filehandle for ".." */ + if (dchild == dparent) + goto out; } else dchild = dget(dparent); } else dchild = lookup_one_len(name, dparent, namlen); if (IS_ERR(dchild)) - return -ENOENT; - rv = -ENOENT; + return rv; if (d_mountpoint(dchild)) goto out; - rv = fh_compose(fhp, exp, dchild, &cd->fh); - if (rv) - goto out; if (!dchild->d_inode) goto out; - rv = 0; + rv = fh_compose(fhp, exp, dchild, &cd->fh); out: dput(dchild); return rv; @@ -845,7 +839,7 @@ out: static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen) { struct svc_fh fh; - int err; + __be32 err; fh_init(&fh, NFS3_FHSIZE); err = compose_entry_fh(cd, &fh, name, namlen); diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 2ed14dfd00a2..987e719fbae8 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -235,17 +235,17 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o */ if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0) open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS | - FATTR4_WORD1_TIME_MODIFY); + FATTR4_WORD1_TIME_MODIFY); } else { status = nfsd_lookup(rqstp, current_fh, open->op_fname.data, open->op_fname.len, resfh); fh_unlock(current_fh); - if (status) - goto out; - status = nfsd_check_obj_isreg(resfh); } if (status) goto out; + status = nfsd_check_obj_isreg(resfh); + if (status) + goto out; if (is_create_with_attrs(open) && open->op_acl != NULL) do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval); @@ -841,6 +841,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_setattr *setattr) { __be32 status = nfs_ok; + int err; if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { nfs4_lock_state(); @@ -852,9 +853,9 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, return status; } } - status = fh_want_write(&cstate->current_fh); - if (status) - return status; + err = fh_want_write(&cstate->current_fh); + if (err) + return nfserrno(err); status = nfs_ok; status = check_attr_support(rqstp, cstate, setattr->sa_bmval, diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 1841f8bf845e..7f71c69cdcdf 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4211,16 +4211,14 @@ out: * vfs_test_lock. (Arguably perhaps test_lock should be done with an * inode operation.) */ -static int nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock) +static __be32 nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock) { struct file *file; - int err; - - err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); - if (err) - return err; - err = vfs_test_lock(file, lock); - nfsd_close(file); + __be32 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); + if (!err) { + err = nfserrno(vfs_test_lock(file, lock)); + nfsd_close(file); + } return err; } @@ -4234,7 +4232,6 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct inode *inode; struct file_lock file_lock; struct nfs4_lockowner *lo; - int error; __be32 status; if (locks_in_grace()) @@ -4280,12 +4277,10 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, nfs4_transform_lock_offset(&file_lock); - status = nfs_ok; - error = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock); - if (error) { - status = nfserrno(error); + status = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock); + if (status) goto out; - } + if (file_lock.fl_type != F_UNLCK) { status = nfserr_denied; nfs4_set_lock_denied(&file_lock, &lockt->lt_denied); diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index bcd8904ab1e3..74c00bc92b9a 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1392,7 +1392,7 @@ nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_sta for (i = 0; i < test_stateid->ts_num_ids; i++) { stateid = kmalloc(sizeof(struct nfsd4_test_stateid_id), GFP_KERNEL); if (!stateid) { - status = PTR_ERR(stateid); + status = nfserrno(-ENOMEM); goto out; } @@ -3410,7 +3410,7 @@ nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, int nfserr, *p++ = htonl(test_stateid->ts_num_ids); list_for_each_entry_safe(stateid, next, &test_stateid->ts_stateid_list, ts_id_list) { - *p++ = htonl(stateid->ts_id_status); + *p++ = stateid->ts_id_status; } ADJUST_ARGS(); diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 296d671654d6..568666156ea4 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1458,7 +1458,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, switch (createmode) { case NFS3_CREATE_UNCHECKED: if (! S_ISREG(dchild->d_inode->i_mode)) - err = nfserr_exist; + goto out; else if (truncp) { /* in nfsv4, we need to treat this case a little * differently. we don't want to truncate the diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 3165aebb43c8..31b9463fba1f 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -1134,7 +1134,7 @@ static int ocfs2_adjust_rightmost_branch(handle_t *handle, } el = path_leaf_el(path); - rec = &el->l_recs[le32_to_cpu(el->l_next_free_rec) - 1]; + rec = &el->l_recs[le16_to_cpu(el->l_next_free_rec) - 1]; ocfs2_adjust_rightmost_records(handle, et, path, rec); diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index cf7823382664..9f32d7cbb7a3 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -1036,14 +1036,14 @@ static int ocfs2_get_refcount_cpos_end(struct ocfs2_caching_info *ci, tmp_el = left_path->p_node[subtree_root].el; blkno = left_path->p_node[subtree_root+1].bh->b_blocknr; - for (i = 0; i < le32_to_cpu(tmp_el->l_next_free_rec); i++) { + for (i = 0; i < le16_to_cpu(tmp_el->l_next_free_rec); i++) { if (le64_to_cpu(tmp_el->l_recs[i].e_blkno) == blkno) { *cpos_end = le32_to_cpu(tmp_el->l_recs[i+1].e_cpos); break; } } - BUG_ON(i == le32_to_cpu(tmp_el->l_next_free_rec)); + BUG_ON(i == le16_to_cpu(tmp_el->l_next_free_rec)); out: ocfs2_free_path(left_path); @@ -1468,7 +1468,7 @@ static int ocfs2_divide_leaf_refcount_block(struct buffer_head *ref_leaf_bh, trace_ocfs2_divide_leaf_refcount_block( (unsigned long long)ref_leaf_bh->b_blocknr, - le32_to_cpu(rl->rl_count), le32_to_cpu(rl->rl_used)); + le16_to_cpu(rl->rl_count), le16_to_cpu(rl->rl_used)); /* * XXX: Improvement later. @@ -2411,7 +2411,7 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb, rb = (struct ocfs2_refcount_block *) prev_bh->b_data; - if (le64_to_cpu(rb->rf_records.rl_used) + + if (le16_to_cpu(rb->rf_records.rl_used) + recs_add > le16_to_cpu(rb->rf_records.rl_count)) ref_blocks++; @@ -2476,7 +2476,7 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb, if (prev_bh) { rb = (struct ocfs2_refcount_block *)prev_bh->b_data; - if (le64_to_cpu(rb->rf_records.rl_used) + recs_add > + if (le16_to_cpu(rb->rf_records.rl_used) + recs_add > le16_to_cpu(rb->rf_records.rl_count)) ref_blocks++; @@ -3629,7 +3629,7 @@ int ocfs2_refcounted_xattr_delete_need(struct inode *inode, * one will split a refcount rec, so totally we need * clusters * 2 new refcount rec. */ - if (le64_to_cpu(rb->rf_records.rl_used) + clusters * 2 > + if (le16_to_cpu(rb->rf_records.rl_used) + clusters * 2 > le16_to_cpu(rb->rf_records.rl_count)) ref_blocks++; diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index ba5d97e4a73e..f169da4624fd 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -600,7 +600,7 @@ static void ocfs2_bg_alloc_cleanup(handle_t *handle, ret = ocfs2_free_clusters(handle, cluster_ac->ac_inode, cluster_ac->ac_bh, le64_to_cpu(rec->e_blkno), - le32_to_cpu(rec->e_leaf_clusters)); + le16_to_cpu(rec->e_leaf_clusters)); if (ret) mlog_errno(ret); /* Try all the clusters to free */ @@ -1628,7 +1628,7 @@ static int ocfs2_bg_discontig_fix_by_rec(struct ocfs2_suballoc_result *res, { unsigned int bpc = le16_to_cpu(cl->cl_bpc); unsigned int bitoff = le32_to_cpu(rec->e_cpos) * bpc; - unsigned int bitcount = le32_to_cpu(rec->e_leaf_clusters) * bpc; + unsigned int bitcount = le16_to_cpu(rec->e_leaf_clusters) * bpc; if (res->sr_bit_offset < bitoff) return 0; diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 8ba2c9460b28..8f2ab8fef929 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -593,7 +593,7 @@ struct fuse_dirent { __u64 off; __u32 namelen; __u32 type; - char name[0]; + char name[]; }; #define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name) diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 2463b6100333..1f90de0cfdbe 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -666,23 +666,11 @@ struct twl4030_codec_data { unsigned int check_defaults:1; unsigned int reset_registers:1; unsigned int hs_extmute:1; - u16 hs_left_step; - u16 hs_right_step; - u16 hf_left_step; - u16 hf_right_step; void (*set_hs_extmute)(int mute); }; struct twl4030_vibra_data { unsigned int coexist; - - /* twl6040 */ - unsigned int vibldrv_res; /* left driver resistance */ - unsigned int vibrdrv_res; /* right driver resistance */ - unsigned int viblmotor_res; /* left motor resistance */ - unsigned int vibrmotor_res; /* right motor resistance */ - int vddvibl_uV; /* VDDVIBL volt, set 0 for fixed reg */ - int vddvibr_uV; /* VDDVIBR volt, set 0 for fixed reg */ }; struct twl4030_audio_data { diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 665a260c7e09..72cbf08d45fb 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -596,6 +596,7 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id); #ifdef CONFIG_IOMMU_API int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot); +void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot); int kvm_iommu_map_guest(struct kvm *kvm); int kvm_iommu_unmap_guest(struct kvm *kvm); int kvm_assign_device(struct kvm *kvm, @@ -609,6 +610,11 @@ static inline int kvm_iommu_map_pages(struct kvm *kvm, return 0; } +static inline void kvm_iommu_unmap_pages(struct kvm *kvm, + struct kvm_memory_slot *slot) +{ +} + static inline int kvm_iommu_map_guest(struct kvm *kvm) { return -ENODEV; diff --git a/include/linux/mfd/db5500-prcmu.h b/include/linux/mfd/db5500-prcmu.h index 9890687f582d..5a049dfaf153 100644 --- a/include/linux/mfd/db5500-prcmu.h +++ b/include/linux/mfd/db5500-prcmu.h @@ -8,41 +8,14 @@ #ifndef __MFD_DB5500_PRCMU_H #define __MFD_DB5500_PRCMU_H -#ifdef CONFIG_MFD_DB5500_PRCMU - -void db5500_prcmu_early_init(void); -int db5500_prcmu_set_epod(u16 epod_id, u8 epod_state); -int db5500_prcmu_set_display_clocks(void); -int db5500_prcmu_disable_dsipll(void); -int db5500_prcmu_enable_dsipll(void); -int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); -int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); -void db5500_prcmu_enable_wakeups(u32 wakeups); -int db5500_prcmu_request_clock(u8 clock, bool enable); -void db5500_prcmu_config_abb_event_readout(u32 abb_events); -void db5500_prcmu_get_abb_event_buffer(void __iomem **buf); -int prcmu_resetout(u8 resoutn, u8 state); -int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, - bool keep_ap_pll); -int db5500_prcmu_config_esram0_deep_sleep(u8 state); -void db5500_prcmu_system_reset(u16 reset_code); -u16 db5500_prcmu_get_reset_code(void); -bool db5500_prcmu_is_ac_wake_requested(void); -int db5500_prcmu_set_arm_opp(u8 opp); -int db5500_prcmu_get_arm_opp(void); - -#else /* !CONFIG_UX500_SOC_DB5500 */ - -static inline void db5500_prcmu_early_init(void) {} - -static inline int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) +static inline int prcmu_resetout(u8 resoutn, u8 state) { - return -ENOSYS; + return 0; } -static inline int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) +static inline int db5500_prcmu_set_epod(u16 epod_id, u8 epod_state) { - return -ENOSYS; + return 0; } static inline int db5500_prcmu_request_clock(u8 clock, bool enable) @@ -50,69 +23,82 @@ static inline int db5500_prcmu_request_clock(u8 clock, bool enable) return 0; } -static inline int db5500_prcmu_set_display_clocks(void) +static inline int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, + bool keep_ap_pll) { return 0; } -static inline int db5500_prcmu_disable_dsipll(void) +static inline int db5500_prcmu_config_esram0_deep_sleep(u8 state) { return 0; } -static inline int db5500_prcmu_enable_dsipll(void) +static inline u16 db5500_prcmu_get_reset_code(void) { return 0; } -static inline int db5500_prcmu_config_esram0_deep_sleep(u8 state) +static inline bool db5500_prcmu_is_ac_wake_requested(void) { return 0; } -static inline void db5500_prcmu_enable_wakeups(u32 wakeups) {} - -static inline int prcmu_resetout(u8 resoutn, u8 state) +static inline int db5500_prcmu_set_arm_opp(u8 opp) { return 0; } -static inline int db5500_prcmu_set_epod(u16 epod_id, u8 epod_state) +static inline int db5500_prcmu_get_arm_opp(void) { return 0; } -static inline void db5500_prcmu_get_abb_event_buffer(void __iomem **buf) {} static inline void db5500_prcmu_config_abb_event_readout(u32 abb_events) {} -static inline int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, - bool keep_ap_pll) -{ - return 0; -} +static inline void db5500_prcmu_get_abb_event_buffer(void __iomem **buf) {} static inline void db5500_prcmu_system_reset(u16 reset_code) {} -static inline u16 db5500_prcmu_get_reset_code(void) +static inline void db5500_prcmu_enable_wakeups(u32 wakeups) {} + +#ifdef CONFIG_MFD_DB5500_PRCMU + +void db5500_prcmu_early_init(void); +int db5500_prcmu_set_display_clocks(void); +int db5500_prcmu_disable_dsipll(void); +int db5500_prcmu_enable_dsipll(void); +int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); +int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); + +#else /* !CONFIG_UX500_SOC_DB5500 */ + +static inline void db5500_prcmu_early_init(void) {} + +static inline int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) { - return 0; + return -ENOSYS; } -static inline bool db5500_prcmu_is_ac_wake_requested(void) +static inline int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) { - return 0; + return -ENOSYS; } -static inline int db5500_prcmu_set_arm_opp(u8 opp) +static inline int db5500_prcmu_set_display_clocks(void) { return 0; } -static inline int db5500_prcmu_get_arm_opp(void) +static inline int db5500_prcmu_disable_dsipll(void) { return 0; } +static inline int db5500_prcmu_enable_dsipll(void) +{ + return 0; +} #endif /* CONFIG_MFD_DB5500_PRCMU */ diff --git a/include/linux/mfd/rc5t583.h b/include/linux/mfd/rc5t583.h index a2c61609d21d..0b64b19d81ab 100644 --- a/include/linux/mfd/rc5t583.h +++ b/include/linux/mfd/rc5t583.h @@ -26,6 +26,7 @@ #include <linux/mutex.h> #include <linux/types.h> +#include <linux/regmap.h> #define RC5T583_MAX_REGS 0xF8 @@ -279,14 +280,44 @@ struct rc5t583_platform_data { bool enable_shutdown; }; -int rc5t583_write(struct device *dev, u8 reg, uint8_t val); -int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val); -int rc5t583_set_bits(struct device *dev, unsigned int reg, - unsigned int bit_mask); -int rc5t583_clear_bits(struct device *dev, unsigned int reg, - unsigned int bit_mask); -int rc5t583_update(struct device *dev, unsigned int reg, - unsigned int val, unsigned int mask); +static inline int rc5t583_write(struct device *dev, uint8_t reg, uint8_t val) +{ + struct rc5t583 *rc5t583 = dev_get_drvdata(dev); + return regmap_write(rc5t583->regmap, reg, val); +} + +static inline int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val) +{ + struct rc5t583 *rc5t583 = dev_get_drvdata(dev); + unsigned int ival; + int ret; + ret = regmap_read(rc5t583->regmap, reg, &ival); + if (!ret) + *val = (uint8_t)ival; + return ret; +} + +static inline int rc5t583_set_bits(struct device *dev, unsigned int reg, + unsigned int bit_mask) +{ + struct rc5t583 *rc5t583 = dev_get_drvdata(dev); + return regmap_update_bits(rc5t583->regmap, reg, bit_mask, bit_mask); +} + +static inline int rc5t583_clear_bits(struct device *dev, unsigned int reg, + unsigned int bit_mask) +{ + struct rc5t583 *rc5t583 = dev_get_drvdata(dev); + return regmap_update_bits(rc5t583->regmap, reg, bit_mask, 0); +} + +static inline int rc5t583_update(struct device *dev, unsigned int reg, + unsigned int val, unsigned int mask) +{ + struct rc5t583 *rc5t583 = dev_get_drvdata(dev); + return regmap_update_bits(rc5t583->regmap, reg, mask, val); +} + int rc5t583_ext_power_req_config(struct device *dev, int deepsleep_id, int ext_pwr_req, int deepsleep_slot_nr); int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base); diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h index 9bc9ac651dad..b15b5f03f5c4 100644 --- a/include/linux/mfd/twl6040.h +++ b/include/linux/mfd/twl6040.h @@ -174,8 +174,35 @@ #define TWL6040_SYSCLK_SEL_LPPLL 0 #define TWL6040_SYSCLK_SEL_HPPLL 1 +struct twl6040_codec_data { + u16 hs_left_step; + u16 hs_right_step; + u16 hf_left_step; + u16 hf_right_step; +}; + +struct twl6040_vibra_data { + unsigned int vibldrv_res; /* left driver resistance */ + unsigned int vibrdrv_res; /* right driver resistance */ + unsigned int viblmotor_res; /* left motor resistance */ + unsigned int vibrmotor_res; /* right motor resistance */ + int vddvibl_uV; /* VDDVIBL volt, set 0 for fixed reg */ + int vddvibr_uV; /* VDDVIBR volt, set 0 for fixed reg */ +}; + +struct twl6040_platform_data { + int audpwron_gpio; /* audio power-on gpio */ + unsigned int irq_base; + + struct twl6040_codec_data *codec; + struct twl6040_vibra_data *vibra; +}; + +struct regmap; + struct twl6040 { struct device *dev; + struct regmap *regmap; struct mutex mutex; struct mutex io_mutex; struct mutex irq_mutex; diff --git a/include/linux/mm.h b/include/linux/mm.h index d8738a464b94..74aa71bea1e4 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1393,29 +1393,20 @@ extern int install_special_mapping(struct mm_struct *mm, extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); -extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, - unsigned long len, unsigned long prot, - unsigned long flag, unsigned long pgoff); extern unsigned long mmap_region(struct file *file, unsigned long addr, unsigned long len, unsigned long flags, vm_flags_t vm_flags, unsigned long pgoff); - -static inline unsigned long do_mmap(struct file *file, unsigned long addr, - unsigned long len, unsigned long prot, - unsigned long flag, unsigned long offset) -{ - unsigned long ret = -EINVAL; - if ((offset + PAGE_ALIGN(len)) < offset) - goto out; - if (!(offset & ~PAGE_MASK)) - ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); -out: - return ret; -} - +extern unsigned long do_mmap(struct file *, unsigned long, + unsigned long, unsigned long, + unsigned long, unsigned long); extern int do_munmap(struct mm_struct *, unsigned long, size_t); -extern unsigned long do_brk(unsigned long, unsigned long); +/* These take the mm semaphore themselves */ +extern unsigned long vm_brk(unsigned long, unsigned long); +extern int vm_munmap(unsigned long, size_t); +extern unsigned long vm_mmap(struct file *, unsigned long, + unsigned long, unsigned long, + unsigned long, unsigned long); /* truncate.c */ extern void truncate_inode_pages(struct address_space *, loff_t); diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 01beae78f079..629b823f8836 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -481,7 +481,7 @@ struct mmc_driver { struct device_driver drv; int (*probe)(struct mmc_card *); void (*remove)(struct mmc_card *); - int (*suspend)(struct mmc_card *, pm_message_t); + int (*suspend)(struct mmc_card *); int (*resume)(struct mmc_card *); }; diff --git a/include/linux/nfsd/Kbuild b/include/linux/nfsd/Kbuild index b8d4001212b3..5b7d84ac954a 100644 --- a/include/linux/nfsd/Kbuild +++ b/include/linux/nfsd/Kbuild @@ -1,3 +1,4 @@ +header-y += cld.h header-y += debug.h header-y += export.h header-y += nfsfh.h diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h index fee4349364f7..e4d1de742502 100644 --- a/include/linux/pinctrl/machine.h +++ b/include/linux/pinctrl/machine.h @@ -12,6 +12,8 @@ #ifndef __LINUX_PINCTRL_MACHINE_H #define __LINUX_PINCTRL_MACHINE_H +#include <linux/bug.h> + #include "pinctrl-state.h" enum pinctrl_map_type { @@ -148,7 +150,7 @@ struct pinctrl_map { #define PIN_MAP_CONFIGS_GROUP_HOG_DEFAULT(dev, grp, cfgs) \ PIN_MAP_CONFIGS_GROUP(dev, PINCTRL_STATE_DEFAULT, dev, grp, cfgs) -#ifdef CONFIG_PINMUX +#ifdef CONFIG_PINCTRL extern int pinctrl_register_mappings(struct pinctrl_map const *map, unsigned num_maps); diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index f67810f8f21b..38ab3f46346f 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -94,6 +94,7 @@ struct usb_phy { struct usb_otg *otg; + struct device *io_dev; struct usb_phy_io_ops *io_ops; void __iomem *io_priv; diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c index 2f526627e4f5..0c505361da19 100644 --- a/lib/mpi/mpi-bit.c +++ b/lib/mpi/mpi-bit.c @@ -177,8 +177,8 @@ int mpi_rshift(MPI x, MPI a, unsigned n) */ int mpi_lshift_limbs(MPI a, unsigned int count) { - mpi_ptr_t ap = a->d; - int n = a->nlimbs; + const int n = a->nlimbs; + mpi_ptr_t ap; int i; if (!count || !n) @@ -187,6 +187,7 @@ int mpi_lshift_limbs(MPI a, unsigned int count) if (RESIZE_IF_NEEDED(a, n + count) < 0) return -ENOMEM; + ap = a->d; for (i = n - 1; i >= 0; i--) ap[i + count] = ap[i]; for (i = 0; i < count; i++) diff --git a/mm/memblock.c b/mm/memblock.c index 99f285599501..a44eab3157f8 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -330,6 +330,9 @@ static int __init_memblock memblock_add_region(struct memblock_type *type, phys_addr_t end = base + memblock_cap_size(base, &size); int i, nr_new; + if (!size) + return 0; + /* special case for empty array */ if (type->regions[0].size == 0) { WARN_ON(type->cnt != 1 || type->total_size); @@ -430,6 +433,9 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, *start_rgn = *end_rgn = 0; + if (!size) + return 0; + /* we'll create at most two more regions */ while (type->cnt + 2 > type->max) if (memblock_double_array(type) < 0) @@ -514,7 +520,6 @@ int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size) (unsigned long long)base, (unsigned long long)base + size, (void *)_RET_IP_); - BUG_ON(0 == size); return memblock_add_region(_rgn, base, size, MAX_NUMNODES); } diff --git a/mm/memcontrol.c b/mm/memcontrol.c index a7165a60d0a7..b868def9bcc1 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -3392,6 +3392,7 @@ void mem_cgroup_replace_page_cache(struct page *oldpage, * the newpage may be on LRU(or pagevec for LRU) already. We lock * LRU while we overwrite pc->mem_cgroup. */ + pc = lookup_page_cgroup(newpage); __mem_cgroup_commit_charge(memcg, newpage, 1, pc, type, true); } diff --git a/mm/mmap.c b/mm/mmap.c index a7bf6a31c9f6..848ef52d9603 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -240,6 +240,8 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) return next; } +static unsigned long do_brk(unsigned long addr, unsigned long len); + SYSCALL_DEFINE1(brk, unsigned long, brk) { unsigned long rlim, retval; @@ -951,7 +953,7 @@ static inline unsigned long round_hint_to_min(unsigned long hint) * The caller must hold down_write(¤t->mm->mmap_sem). */ -unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, +static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long pgoff) { @@ -1087,7 +1089,32 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, return mmap_region(file, addr, len, flags, vm_flags, pgoff); } -EXPORT_SYMBOL(do_mmap_pgoff); + +unsigned long do_mmap(struct file *file, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flag, unsigned long offset) +{ + if (unlikely(offset + PAGE_ALIGN(len) < offset)) + return -EINVAL; + if (unlikely(offset & ~PAGE_MASK)) + return -EINVAL; + return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); +} +EXPORT_SYMBOL(do_mmap); + +unsigned long vm_mmap(struct file *file, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flag, unsigned long offset) +{ + unsigned long ret; + struct mm_struct *mm = current->mm; + + down_write(&mm->mmap_sem); + ret = do_mmap(file, addr, len, prot, flag, offset); + up_write(&mm->mmap_sem); + return ret; +} +EXPORT_SYMBOL(vm_mmap); SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, @@ -2105,21 +2132,25 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len) return 0; } - EXPORT_SYMBOL(do_munmap); -SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len) +int vm_munmap(unsigned long start, size_t len) { int ret; struct mm_struct *mm = current->mm; - profile_munmap(addr); - down_write(&mm->mmap_sem); - ret = do_munmap(mm, addr, len); + ret = do_munmap(mm, start, len); up_write(&mm->mmap_sem); return ret; } +EXPORT_SYMBOL(vm_munmap); + +SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len) +{ + profile_munmap(addr); + return vm_munmap(addr, len); +} static inline void verify_mm_writelocked(struct mm_struct *mm) { @@ -2136,7 +2167,7 @@ static inline void verify_mm_writelocked(struct mm_struct *mm) * anonymous maps. eventually we may be able to do some * brk-specific accounting here. */ -unsigned long do_brk(unsigned long addr, unsigned long len) +static unsigned long do_brk(unsigned long addr, unsigned long len) { struct mm_struct * mm = current->mm; struct vm_area_struct * vma, * prev; @@ -2232,7 +2263,17 @@ out: return addr; } -EXPORT_SYMBOL(do_brk); +unsigned long vm_brk(unsigned long addr, unsigned long len) +{ + struct mm_struct *mm = current->mm; + unsigned long ret; + + down_write(&mm->mmap_sem); + ret = do_brk(addr, len); + up_write(&mm->mmap_sem); + return ret; +} +EXPORT_SYMBOL(vm_brk); /* Release all mmaps. */ void exit_mmap(struct mm_struct *mm) diff --git a/mm/nommu.c b/mm/nommu.c index f59e170fceb4..bb8f4f004a82 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -1233,7 +1233,7 @@ enomem: /* * handle mapping creation for uClinux */ -unsigned long do_mmap_pgoff(struct file *file, +static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, @@ -1470,7 +1470,32 @@ error_getting_region: show_free_areas(0); return -ENOMEM; } -EXPORT_SYMBOL(do_mmap_pgoff); + +unsigned long do_mmap(struct file *file, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flag, unsigned long offset) +{ + if (unlikely(offset + PAGE_ALIGN(len) < offset)) + return -EINVAL; + if (unlikely(offset & ~PAGE_MASK)) + return -EINVAL; + return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); +} +EXPORT_SYMBOL(do_mmap); + +unsigned long vm_mmap(struct file *file, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flag, unsigned long offset) +{ + unsigned long ret; + struct mm_struct *mm = current->mm; + + down_write(&mm->mmap_sem); + ret = do_mmap(file, addr, len, prot, flag, offset); + up_write(&mm->mmap_sem); + return ret; +} +EXPORT_SYMBOL(vm_mmap); SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, @@ -1709,16 +1734,22 @@ erase_whole_vma: } EXPORT_SYMBOL(do_munmap); -SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len) +int vm_munmap(unsigned long addr, size_t len) { - int ret; struct mm_struct *mm = current->mm; + int ret; down_write(&mm->mmap_sem); ret = do_munmap(mm, addr, len); up_write(&mm->mmap_sem); return ret; } +EXPORT_SYMBOL(vm_munmap); + +SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len) +{ + return vm_munmap(addr, len); +} /* * release all the mappings made in a process's VM space @@ -1744,7 +1775,7 @@ void exit_mmap(struct mm_struct *mm) kleave(""); } -unsigned long do_brk(unsigned long addr, unsigned long len) +unsigned long vm_brk(unsigned long addr, unsigned long len) { return -ENOMEM; } diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index de639eeeed50..faea0ec612bf 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1869,12 +1869,6 @@ sub process { "No space is necessary after a cast\n" . $hereprev); } - if ($rawline =~ /^\+[ \t]*\/\*[ \t]*$/ && - $prevrawline =~ /^\+[ \t]*$/) { - CHK("BLOCK_COMMENT_STYLE", - "Don't begin block comments with only a /* line, use /* comment...\n" . $hereprev); - } - # check for spaces at the beginning of a line. # Exceptions: # 1) within comments diff --git a/scripts/xz_wrap.sh b/scripts/xz_wrap.sh index 17a5798c29da..7a2d372f4885 100644 --- a/scripts/xz_wrap.sh +++ b/scripts/xz_wrap.sh @@ -12,8 +12,8 @@ BCJ= LZMA2OPTS= -case $ARCH in - x86|x86_64) BCJ=--x86 ;; +case $SRCARCH in + x86) BCJ=--x86 ;; powerpc) BCJ=--powerpc ;; ia64) BCJ=--ia64; LZMA2OPTS=pb=4 ;; arm) BCJ=--arm ;; diff --git a/security/commoncap.c b/security/commoncap.c index 0cf4b53480a7..71a166a05975 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -29,6 +29,7 @@ #include <linux/securebits.h> #include <linux/user_namespace.h> #include <linux/binfmts.h> +#include <linux/personality.h> /* * If a non-root user executes a setuid-root binary in @@ -505,6 +506,11 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) } skip: + /* if we have fs caps, clear dangerous personality flags */ + if (!cap_issubset(new->cap_permitted, old->cap_permitted)) + bprm->per_clear |= PER_CLEAR_ON_SETID; + + /* Don't let someone trace a set[ug]id/setpcap binary with the revised * credentials unless they have the appropriate permit */ diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 10056f2f6df3..45c32f074166 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3640,8 +3640,38 @@ struct security_operations smack_ops = { }; -static __init void init_smack_know_list(void) +static __init void init_smack_known_list(void) { + /* + * Initialize CIPSO locks + */ + spin_lock_init(&smack_known_huh.smk_cipsolock); + spin_lock_init(&smack_known_hat.smk_cipsolock); + spin_lock_init(&smack_known_star.smk_cipsolock); + spin_lock_init(&smack_known_floor.smk_cipsolock); + spin_lock_init(&smack_known_invalid.smk_cipsolock); + spin_lock_init(&smack_known_web.smk_cipsolock); + /* + * Initialize rule list locks + */ + mutex_init(&smack_known_huh.smk_rules_lock); + mutex_init(&smack_known_hat.smk_rules_lock); + mutex_init(&smack_known_floor.smk_rules_lock); + mutex_init(&smack_known_star.smk_rules_lock); + mutex_init(&smack_known_invalid.smk_rules_lock); + mutex_init(&smack_known_web.smk_rules_lock); + /* + * Initialize rule lists + */ + INIT_LIST_HEAD(&smack_known_huh.smk_rules); + INIT_LIST_HEAD(&smack_known_hat.smk_rules); + INIT_LIST_HEAD(&smack_known_star.smk_rules); + INIT_LIST_HEAD(&smack_known_floor.smk_rules); + INIT_LIST_HEAD(&smack_known_invalid.smk_rules); + INIT_LIST_HEAD(&smack_known_web.smk_rules); + /* + * Create the known labels list + */ list_add(&smack_known_huh.list, &smack_known_list); list_add(&smack_known_hat.list, &smack_known_list); list_add(&smack_known_star.list, &smack_known_list); @@ -3676,16 +3706,8 @@ static __init int smack_init(void) cred = (struct cred *) current->cred; cred->security = tsp; - /* initialize the smack_know_list */ - init_smack_know_list(); - /* - * Initialize locks - */ - spin_lock_init(&smack_known_huh.smk_cipsolock); - spin_lock_init(&smack_known_hat.smk_cipsolock); - spin_lock_init(&smack_known_star.smk_cipsolock); - spin_lock_init(&smack_known_floor.smk_cipsolock); - spin_lock_init(&smack_known_invalid.smk_cipsolock); + /* initialize the smack_known_list */ + init_smack_known_list(); /* * Register with LSM diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 5c32f36ff706..038811cb7e62 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -1614,20 +1614,6 @@ static int __init init_smk_fs(void) smk_cipso_doi(); smk_unlbl_ambient(NULL); - mutex_init(&smack_known_floor.smk_rules_lock); - mutex_init(&smack_known_hat.smk_rules_lock); - mutex_init(&smack_known_huh.smk_rules_lock); - mutex_init(&smack_known_invalid.smk_rules_lock); - mutex_init(&smack_known_star.smk_rules_lock); - mutex_init(&smack_known_web.smk_rules_lock); - - INIT_LIST_HEAD(&smack_known_floor.smk_rules); - INIT_LIST_HEAD(&smack_known_hat.smk_rules); - INIT_LIST_HEAD(&smack_known_huh.smk_rules); - INIT_LIST_HEAD(&smack_known_invalid.smk_rules); - INIT_LIST_HEAD(&smack_known_star.smk_rules); - INIT_LIST_HEAD(&smack_known_web.smk_rules); - return err; } diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 14a286a7bf2b..857586135d18 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c @@ -419,6 +419,7 @@ EXPORT_SYMBOL(snd_ctl_make_virtual_master); * snd_ctl_add_vmaster_hook - Add a hook to a vmaster control * @kcontrol: vmaster kctl element * @hook: the hook function + * @private_data: the private_data pointer to be saved * * Adds the given hook to the vmaster control element so that it's called * at each time when the value is changed. diff --git a/sound/last.c b/sound/last.c index bdd0857b8871..7ffc182e0844 100644 --- a/sound/last.c +++ b/sound/last.c @@ -38,4 +38,4 @@ static int __init alsa_sound_last_init(void) return 0; } -__initcall(alsa_sound_last_init); +late_initcall_sync(alsa_sound_last_init); diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index a36488d94aaa..d906c5b74cf0 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3971,9 +3971,14 @@ static void cx_auto_init_output(struct hda_codec *codec) int i; mute_outputs(codec, spec->multiout.num_dacs, spec->multiout.dac_nids); - for (i = 0; i < cfg->hp_outs; i++) + for (i = 0; i < cfg->hp_outs; i++) { + unsigned int val = PIN_OUT; + if (snd_hda_query_pin_caps(codec, cfg->hp_pins[i]) & + AC_PINCAP_HP_DRV) + val |= AC_PINCTL_HP_EN; snd_hda_codec_write(codec, cfg->hp_pins[i], 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); + AC_VERB_SET_PIN_WIDGET_CONTROL, val); + } mute_outputs(codec, cfg->hp_outs, cfg->hp_pins); mute_outputs(codec, cfg->line_outs, cfg->line_out_pins); mute_outputs(codec, cfg->speaker_outs, cfg->speaker_pins); @@ -4391,8 +4396,10 @@ static void apply_pin_fixup(struct hda_codec *codec, enum { CXT_PINCFG_LENOVO_X200, + CXT_PINCFG_LENOVO_TP410, }; +/* ThinkPad X200 & co with cxt5051 */ static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = { { 0x16, 0x042140ff }, /* HP (seq# overridden) */ { 0x17, 0x21a11000 }, /* dock-mic */ @@ -4401,15 +4408,33 @@ static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = { {} }; +/* ThinkPad 410/420/510/520, X201 & co with cxt5066 */ +static const struct cxt_pincfg cxt_pincfg_lenovo_tp410[] = { + { 0x19, 0x042110ff }, /* HP (seq# overridden) */ + { 0x1a, 0x21a190f0 }, /* dock-mic */ + { 0x1c, 0x212140ff }, /* dock-HP */ + {} +}; + static const struct cxt_pincfg *cxt_pincfg_tbl[] = { [CXT_PINCFG_LENOVO_X200] = cxt_pincfg_lenovo_x200, + [CXT_PINCFG_LENOVO_TP410] = cxt_pincfg_lenovo_tp410, }; -static const struct snd_pci_quirk cxt_fixups[] = { +static const struct snd_pci_quirk cxt5051_fixups[] = { SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200), {} }; +static const struct snd_pci_quirk cxt5066_fixups[] = { + SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410), + SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410), + SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410), + SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), + SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), + {} +}; + /* add "fake" mute amp-caps to DACs on cx5051 so that mixer mute switches * can be created (bko#42825) */ @@ -4446,13 +4471,13 @@ static int patch_conexant_auto(struct hda_codec *codec) case 0x14f15051: add_cx5051_fake_mutes(codec); codec->pin_amp_workaround = 1; + apply_pin_fixup(codec, cxt5051_fixups, cxt_pincfg_tbl); break; default: codec->pin_amp_workaround = 1; + apply_pin_fixup(codec, cxt5066_fixups, cxt_pincfg_tbl); } - apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl); - /* Show mute-led control only on HP laptops * This is a sort of white-list: on HP laptops, EAPD corresponds * only to the mute-LED without actualy amp function. Meanwhile, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2508f8109f11..e65e35433055 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1445,6 +1445,13 @@ enum { ALC_FIXUP_ACT_BUILD, }; +static void alc_apply_pincfgs(struct hda_codec *codec, + const struct alc_pincfg *cfg) +{ + for (; cfg->nid; cfg++) + snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val); +} + static void alc_apply_fixup(struct hda_codec *codec, int action) { struct alc_spec *spec = codec->spec; @@ -1478,9 +1485,7 @@ static void alc_apply_fixup(struct hda_codec *codec, int action) snd_printdd(KERN_INFO "hda_codec: %s: " "Apply pincfg for %s\n", codec->chip_name, modelname); - for (; cfg->nid; cfg++) - snd_hda_codec_set_pincfg(codec, cfg->nid, - cfg->val); + alc_apply_pincfgs(codec, cfg); break; case ALC_FIXUP_VERBS: if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs) @@ -4861,6 +4866,7 @@ enum { ALC260_FIXUP_GPIO1_TOGGLE, ALC260_FIXUP_REPLACER, ALC260_FIXUP_HP_B1900, + ALC260_FIXUP_KN1, }; static void alc260_gpio1_automute(struct hda_codec *codec) @@ -4888,6 +4894,36 @@ static void alc260_fixup_gpio1_toggle(struct hda_codec *codec, } } +static void alc260_fixup_kn1(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + static const struct alc_pincfg pincfgs[] = { + { 0x0f, 0x02214000 }, /* HP/speaker */ + { 0x12, 0x90a60160 }, /* int mic */ + { 0x13, 0x02a19000 }, /* ext mic */ + { 0x18, 0x01446000 }, /* SPDIF out */ + /* disable bogus I/O pins */ + { 0x10, 0x411111f0 }, + { 0x11, 0x411111f0 }, + { 0x14, 0x411111f0 }, + { 0x15, 0x411111f0 }, + { 0x16, 0x411111f0 }, + { 0x17, 0x411111f0 }, + { 0x19, 0x411111f0 }, + { } + }; + + switch (action) { + case ALC_FIXUP_ACT_PRE_PROBE: + alc_apply_pincfgs(codec, pincfgs); + break; + case ALC_FIXUP_ACT_PROBE: + spec->init_amp = ALC_INIT_NONE; + break; + } +} + static const struct alc_fixup alc260_fixups[] = { [ALC260_FIXUP_HP_DC5750] = { .type = ALC_FIXUP_PINS, @@ -4938,7 +4974,11 @@ static const struct alc_fixup alc260_fixups[] = { .v.func = alc260_fixup_gpio1_toggle, .chained = true, .chain_id = ALC260_FIXUP_COEF, - } + }, + [ALC260_FIXUP_KN1] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc260_fixup_kn1, + }, }; static const struct snd_pci_quirk alc260_fixup_tbl[] = { @@ -4948,6 +4988,7 @@ static const struct snd_pci_quirk alc260_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750), SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900), SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1), + SND_PCI_QUIRK(0x152d, 0x0729, "Quanta KN1", ALC260_FIXUP_KN1), SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER), SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF), {} diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 33a9946b492c..4742cac26aa9 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -5063,12 +5063,11 @@ static void stac92xx_update_led_status(struct hda_codec *codec, int enabled) if (spec->gpio_led_polarity) muted = !muted; - /*polarity defines *not* muted state level*/ if (!spec->vref_mute_led_nid) { if (muted) - spec->gpio_data &= ~spec->gpio_led; /* orange */ + spec->gpio_data |= spec->gpio_led; else - spec->gpio_data |= spec->gpio_led; /* white */ + spec->gpio_data &= ~spec->gpio_led; stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); } else { diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 6508e8b790bb..59d8efaa17e9 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -57,7 +57,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_TPA6130A2 if I2C select SND_SOC_TLV320DAC33 if I2C select SND_SOC_TWL4030 if TWL4030_CORE - select SND_SOC_TWL6040 if TWL4030_CORE + select SND_SOC_TWL6040 if TWL6040_CORE select SND_SOC_UDA134X select SND_SOC_UDA1380 if I2C select SND_SOC_WL1273 if MFD_WL1273_CORE @@ -276,7 +276,6 @@ config SND_SOC_TWL4030 tristate config SND_SOC_TWL6040 - select TWL6040_CORE tristate config SND_SOC_UDA134X diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 2d8c6b825e57..dc7509b9d53a 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -26,7 +26,6 @@ #include <linux/pm.h> #include <linux/platform_device.h> #include <linux/slab.h> -#include <linux/i2c/twl.h> #include <linux/mfd/twl6040.h> #include <sound/core.h> @@ -1528,7 +1527,7 @@ static int twl6040_resume(struct snd_soc_codec *codec) static int twl6040_probe(struct snd_soc_codec *codec) { struct twl6040_data *priv; - struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev); + struct twl6040_codec_data *pdata = dev_get_platdata(codec->dev); struct platform_device *pdev = container_of(codec->dev, struct platform_device, dev); int ret = 0; diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index e00dd0b1139c..deafbfaacdbf 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -97,7 +97,7 @@ config SND_OMAP_SOC_SDP3430 config SND_OMAP_SOC_OMAP_ABE_TWL6040 tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" - depends on TWL4030_CORE && SND_OMAP_SOC && ARCH_OMAP4 + depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4 select SND_OMAP_SOC_DMIC select SND_OMAP_SOC_MCPDM select SND_SOC_TWL6040 diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore index 416684be0ad3..26b823b61aa1 100644 --- a/tools/perf/.gitignore +++ b/tools/perf/.gitignore @@ -19,3 +19,5 @@ TAGS cscope* config.mak config.mak.autogen +*-bison.* +*-flex.* diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 820371f10d1b..03059e75665a 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -237,21 +237,20 @@ export PERL_PATH FLEX = $(CROSS_COMPILE)flex BISON= $(CROSS_COMPILE)bison -event-parser: - $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c +$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c -$(OUTPUT)util/parse-events-flex.c: event-parser -$(OUTPUT)util/parse-events-bison.c: event-parser +$(OUTPUT)util/parse-events-bison.c: util/parse-events.y + $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c -pmu-parser: - $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c +$(OUTPUT)util/pmu-flex.c: util/pmu.l $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c -$(OUTPUT)util/pmu-flex.c: pmu-parser -$(OUTPUT)util/pmu-bison.c: pmu-parser +$(OUTPUT)util/pmu-bison.c: util/pmu.y + $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -$(OUTPUT)util/parse-events.o: event-parser pmu-parser +$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c +$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c LIB_FILE=$(OUTPUT)libperf.a @@ -527,7 +526,7 @@ else endif ifdef NO_GTK2 - BASIC_CFLAGS += -DNO_GTK2 + BASIC_CFLAGS += -DNO_GTK2_SUPPORT else FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0) ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2)),y) @@ -852,8 +851,6 @@ help: @echo ' html - make html documentation' @echo ' info - make GNU info documentation (access with info <foo>)' @echo ' pdf - make pdf documentation' - @echo ' event-parser - make event parser code' - @echo ' pmu-parser - make pmu format parser code' @echo ' TAGS - use etags to make tag information for source browsing' @echo ' tags - use ctags to make tag information for source browsing' @echo ' cscope - use cscope to make interactive browsing database' diff --git a/tools/perf/perf-archive.sh b/tools/perf/perf-archive.sh index 677e59d62a8d..95b6f8b6177a 100644 --- a/tools/perf/perf-archive.sh +++ b/tools/perf/perf-archive.sh @@ -29,13 +29,14 @@ if [ ! -s $BUILDIDS ] ; then fi MANIFEST=$(mktemp /tmp/perf-archive-manifest.XXXXXX) +PERF_BUILDID_LINKDIR=$(readlink -f $PERF_BUILDID_DIR)/ cut -d ' ' -f 1 $BUILDIDS | \ while read build_id ; do linkname=$PERF_BUILDID_DIR.build-id/${build_id:0:2}/${build_id:2} filename=$(readlink -f $linkname) echo ${linkname#$PERF_BUILDID_DIR} >> $MANIFEST - echo ${filename#$PERF_BUILDID_DIR} >> $MANIFEST + echo ${filename#$PERF_BUILDID_LINKDIR} >> $MANIFEST done tar cfj $PERF_DATA.tar.bz2 -C $PERF_BUILDID_DIR -T $MANIFEST diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 00923cda4d9c..1efd3bee6336 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -876,11 +876,11 @@ static int perf_session_deliver_event(struct perf_session *session, dump_sample(session, event, sample); if (evsel == NULL) { ++session->hists.stats.nr_unknown_id; - return -1; + return 0; } if (machine == NULL) { ++session->hists.stats.nr_unprocessable_samples; - return -1; + return 0; } return tool->sample(tool, event, sample, evsel, machine); case PERF_RECORD_MMAP: diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c index a457d2138f49..e9fff9830bf0 100644 --- a/virt/kvm/iommu.c +++ b/virt/kvm/iommu.c @@ -240,9 +240,13 @@ int kvm_iommu_map_guest(struct kvm *kvm) return -ENODEV; } + mutex_lock(&kvm->slots_lock); + kvm->arch.iommu_domain = iommu_domain_alloc(&pci_bus_type); - if (!kvm->arch.iommu_domain) - return -ENOMEM; + if (!kvm->arch.iommu_domain) { + r = -ENOMEM; + goto out_unlock; + } if (!allow_unsafe_assigned_interrupts && !iommu_domain_has_cap(kvm->arch.iommu_domain, @@ -253,17 +257,16 @@ int kvm_iommu_map_guest(struct kvm *kvm) " module option.\n", __func__); iommu_domain_free(kvm->arch.iommu_domain); kvm->arch.iommu_domain = NULL; - return -EPERM; + r = -EPERM; + goto out_unlock; } r = kvm_iommu_map_memslots(kvm); if (r) - goto out_unmap; - - return 0; + kvm_iommu_unmap_memslots(kvm); -out_unmap: - kvm_iommu_unmap_memslots(kvm); +out_unlock: + mutex_unlock(&kvm->slots_lock); return r; } @@ -310,6 +313,11 @@ static void kvm_iommu_put_pages(struct kvm *kvm, } } +void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot) +{ + kvm_iommu_put_pages(kvm, slot->base_gfn, slot->npages); +} + static int kvm_iommu_unmap_memslots(struct kvm *kvm) { int idx; @@ -320,7 +328,7 @@ static int kvm_iommu_unmap_memslots(struct kvm *kvm) slots = kvm_memslots(kvm); kvm_for_each_memslot(memslot, slots) - kvm_iommu_put_pages(kvm, memslot->base_gfn, memslot->npages); + kvm_iommu_unmap_pages(kvm, memslot); srcu_read_unlock(&kvm->srcu, idx); @@ -335,7 +343,11 @@ int kvm_iommu_unmap_guest(struct kvm *kvm) if (!domain) return 0; + mutex_lock(&kvm->slots_lock); kvm_iommu_unmap_memslots(kvm); + kvm->arch.iommu_domain = NULL; + mutex_unlock(&kvm->slots_lock); + iommu_domain_free(domain); return 0; } diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 42b73930a6de..9739b533ca2e 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -808,12 +808,13 @@ int __kvm_set_memory_region(struct kvm *kvm, if (r) goto out_free; - /* map the pages in iommu page table */ + /* map/unmap the pages in iommu page table */ if (npages) { r = kvm_iommu_map_pages(kvm, &new); if (r) goto out_free; - } + } else + kvm_iommu_unmap_pages(kvm, &old); r = -ENOMEM; slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots), |