From f14c4f141ad88290bb23d597a0a47833e7891fcd Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 27 Jul 2010 08:14:35 +0000 Subject: ARM: mach-shmobile: Runtime PM V3 This is the SH-Mobile ARM Runtime PM implementation V3. Only clocks are managed at this point. If Runtime PM is disabled then the clocks will be enabled before ->probe() and disabled after ->remove(). Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/Makefile | 2 +- arch/arm/mach-shmobile/clock-sh7372.c | 2 +- arch/arm/mach-shmobile/pm_runtime.c | 169 ++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-shmobile/pm_runtime.c (limited to 'arch') diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 5e16b4c69222..ae416fe7daf2 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -3,7 +3,7 @@ # # Common objects -obj-y := timer.o console.o clock.o +obj-y := timer.o console.o clock.o pm_runtime.o # CPU objects obj-$(CONFIG_ARCH_SH7367) += setup-sh7367.o clock-sh7367.o intc-sh7367.o diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index fb4e9b1d788e..4a1d019f7bad 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c @@ -428,7 +428,7 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */ [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ - [MSTP328] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR3, 28, CLK_ENABLE_ON_INIT), /* FSIA */ + [MSTP328] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR3, 28, 0), /* FSIA */ [MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ [MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */ [MSTP314] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */ diff --git a/arch/arm/mach-shmobile/pm_runtime.c b/arch/arm/mach-shmobile/pm_runtime.c new file mode 100644 index 000000000000..94912d3944d3 --- /dev/null +++ b/arch/arm/mach-shmobile/pm_runtime.c @@ -0,0 +1,169 @@ +/* + * arch/arm/mach-shmobile/pm_runtime.c + * + * Runtime PM support code for SuperH Mobile ARM + * + * Copyright (C) 2009-2010 Magnus Damm + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PM_RUNTIME +#define BIT_ONCE 0 +#define BIT_ACTIVE 1 +#define BIT_CLK_ENABLED 2 + +struct pm_runtime_data { + unsigned long flags; + struct clk *clk; +}; + +static void __devres_release(struct device *dev, void *res) +{ + struct pm_runtime_data *prd = res; + + dev_dbg(dev, "__devres_release()\n"); + + if (test_bit(BIT_CLK_ENABLED, &prd->flags)) + clk_disable(prd->clk); + + if (test_bit(BIT_ACTIVE, &prd->flags)) + clk_put(prd->clk); +} + +static struct pm_runtime_data *__to_prd(struct device *dev) +{ + return devres_find(dev, __devres_release, NULL, NULL); +} + +static void platform_pm_runtime_init(struct device *dev, + struct pm_runtime_data *prd) +{ + if (prd && !test_and_set_bit(BIT_ONCE, &prd->flags)) { + prd->clk = clk_get(dev, NULL); + if (!IS_ERR(prd->clk)) { + set_bit(BIT_ACTIVE, &prd->flags); + dev_info(dev, "clocks managed by runtime pm\n"); + } + } +} + +static void platform_pm_runtime_bug(struct device *dev, + struct pm_runtime_data *prd) +{ + if (prd && !test_and_set_bit(BIT_ONCE, &prd->flags)) + dev_err(dev, "runtime pm suspend before resume\n"); +} + +int platform_pm_runtime_suspend(struct device *dev) +{ + struct pm_runtime_data *prd = __to_prd(dev); + + dev_dbg(dev, "platform_pm_runtime_suspend()\n"); + + platform_pm_runtime_bug(dev, prd); + + if (prd && test_bit(BIT_ACTIVE, &prd->flags)) { + clk_disable(prd->clk); + clear_bit(BIT_CLK_ENABLED, &prd->flags); + } + + return 0; +} + +int platform_pm_runtime_resume(struct device *dev) +{ + struct pm_runtime_data *prd = __to_prd(dev); + + dev_dbg(dev, "platform_pm_runtime_resume()\n"); + + platform_pm_runtime_init(dev, prd); + + if (prd && test_bit(BIT_ACTIVE, &prd->flags)) { + clk_enable(prd->clk); + set_bit(BIT_CLK_ENABLED, &prd->flags); + } + + return 0; +} + +int platform_pm_runtime_idle(struct device *dev) +{ + /* suspend synchronously to disable clocks immediately */ + return pm_runtime_suspend(dev); +} + +static int platform_bus_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct device *dev = data; + struct pm_runtime_data *prd; + + dev_dbg(dev, "platform_bus_notify() %ld !\n", action); + + if (action == BUS_NOTIFY_BIND_DRIVER) { + prd = devres_alloc(__devres_release, sizeof(*prd), GFP_KERNEL); + if (prd) + devres_add(dev, prd); + else + dev_err(dev, "unable to alloc memory for runtime pm\n"); + } + + return 0; +} + +#else /* CONFIG_PM_RUNTIME */ + +static int platform_bus_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct device *dev = data; + struct clk *clk; + + dev_dbg(dev, "platform_bus_notify() %ld !\n", action); + + switch (action) { + case BUS_NOTIFY_BIND_DRIVER: + clk = clk_get(dev, NULL); + if (!IS_ERR(clk)) { + clk_enable(clk); + clk_put(clk); + dev_info(dev, "runtime pm disabled, clock forced on\n"); + } + break; + case BUS_NOTIFY_UNBOUND_DRIVER: + clk = clk_get(dev, NULL); + if (!IS_ERR(clk)) { + clk_disable(clk); + clk_put(clk); + dev_info(dev, "runtime pm disabled, clock forced off\n"); + } + break; + } + + return 0; +} + +#endif /* CONFIG_PM_RUNTIME */ + +static struct notifier_block platform_bus_notifier = { + .notifier_call = platform_bus_notify +}; + +static int __init sh_pm_runtime_init(void) +{ + bus_register_notifier(&platform_bus_type, &platform_bus_notifier); + return 0; +} +core_initcall(sh_pm_runtime_init); -- cgit v1.2.2 From a4909b52682c1e2ac858754c8bc46f2501e67dee Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 26 Jul 2010 16:20:53 +0000 Subject: ARM: mach-shmobile: add clock definitions for CEU and CSI2 Two more clocks to be managed by the runtime PM. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/clock-sh7372.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 4a1d019f7bad..dcaac1b6691d 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c @@ -395,7 +395,7 @@ static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { enum { MSTP001, MSTP131, MSTP130, - MSTP129, MSTP128, + MSTP129, MSTP128, MSTP127, MSTP126, MSTP118, MSTP117, MSTP116, MSTP106, MSTP101, MSTP100, MSTP223, @@ -413,6 +413,8 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP130] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 30, 0), /* VEU2 */ [MSTP129] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 29, 0), /* VEU1 */ [MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* VEU0 */ + [MSTP127] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 27, 0), /* CEU */ + [MSTP126] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 26, 0), /* CSI2 */ [MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX */ [MSTP117] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */ [MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */ @@ -498,6 +500,8 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[MSTP130]), /* VEU2 */ CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[MSTP129]), /* VEU1 */ CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[MSTP128]), /* VEU0 */ + CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU */ + CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2 */ CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */ CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */ -- cgit v1.2.2 From 2863e935a59b36d55522af8620112c64a56b4022 Mon Sep 17 00:00:00 2001 From: Arnd Hannemann Date: Sat, 14 Aug 2010 19:45:21 +0000 Subject: ARM: mach-shmobile: AP4EVB: use gpio-leds for leds. This allows control of the leds on the AP4EVB board by kernel events (triggers) like mmc0/mmc1. In userland, the leds won't be available anymore over /sys/class/gpio but via /sys/class/leds. Signed-off-by: Arnd Hannemann Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-ap4evb.c | 52 +++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 23d472f9525e..98c1cf76c2b4 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -650,7 +651,44 @@ static struct platform_device hdmi_device = { }, }; +static struct gpio_led ap4evb_leds[] = { + { + .name = "led4", + .gpio = GPIO_PORT185, + .default_state = LEDS_GPIO_DEFSTATE_ON, + }, + { + .name = "led2", + .gpio = GPIO_PORT186, + .default_state = LEDS_GPIO_DEFSTATE_ON, + }, + { + .name = "led3", + .gpio = GPIO_PORT187, + .default_state = LEDS_GPIO_DEFSTATE_ON, + }, + { + .name = "led1", + .gpio = GPIO_PORT188, + .default_state = LEDS_GPIO_DEFSTATE_ON, + } +}; + +static struct gpio_led_platform_data ap4evb_leds_pdata = { + .num_leds = ARRAY_SIZE(ap4evb_leds), + .leds = &ap4evb_leds, +}; + +static struct platform_device leds_device = { + .name = "leds-gpio", + .id = 0, + .dev = { + .platform_data = &ap4evb_leds_pdata, + }, +}; + static struct platform_device *ap4evb_devices[] __initdata = { + &leds_device, &nor_flash_device, &smc911x_device, &sdhi0_device, @@ -840,20 +878,6 @@ static void __init ap4evb_init(void) gpio_request(GPIO_FN_CS5A, NULL); gpio_request(GPIO_FN_IRQ6_39, NULL); - /* enable LED 1 - 4 */ - gpio_request(GPIO_PORT185, NULL); - gpio_request(GPIO_PORT186, NULL); - gpio_request(GPIO_PORT187, NULL); - gpio_request(GPIO_PORT188, NULL); - gpio_direction_output(GPIO_PORT185, 1); - gpio_direction_output(GPIO_PORT186, 1); - gpio_direction_output(GPIO_PORT187, 1); - gpio_direction_output(GPIO_PORT188, 1); - gpio_export(GPIO_PORT185, 0); - gpio_export(GPIO_PORT186, 0); - gpio_export(GPIO_PORT187, 0); - gpio_export(GPIO_PORT188, 0); - /* enable Debug switch (S6) */ gpio_request(GPIO_PORT32, NULL); gpio_request(GPIO_PORT33, NULL); -- cgit v1.2.2 From 8050fbf268c3bc09752ceece40aff5d3f4e3e182 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 16 Aug 2010 14:54:35 +0900 Subject: ARM: mach-shmobile: Fix up gpio-leds pdata definition. Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-ap4evb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 98c1cf76c2b4..8afdb1dab029 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -676,7 +676,7 @@ static struct gpio_led ap4evb_leds[] = { static struct gpio_led_platform_data ap4evb_leds_pdata = { .num_leds = ARRAY_SIZE(ap4evb_leds), - .leds = &ap4evb_leds, + .leds = ap4evb_leds, }; static struct platform_device leds_device = { -- cgit v1.2.2 From ec53fe3d655befce6420a1b8485af9b1145a0c90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20B=C3=A9nard?= Date: Fri, 30 Jul 2010 22:58:40 +0200 Subject: eukrea-baseboards: fix the merge in one file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Last change I did made a big mess in function names and CONFIG names, this patch fixes this so that the baseboard support is really built when selected. Signed-off-by: Eric Bénard Signed-off-by: Sascha Hauer --- arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c | 2 +- arch/arm/mach-mx25/mach-cpuimx25.c | 4 ++-- arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c | 2 +- arch/arm/mach-mx3/mach-cpuimx35.c | 4 ++-- arch/arm/plat-mxc/include/mach/eukrea-baseboards.h | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c index 91931dcb0689..4aaadc753d3e 100644 --- a/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c +++ b/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c @@ -215,7 +215,7 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata = { * Add platform devices present on this baseboard and init * them from CPU side as far as required to use them later on */ -void __init eukrea_mbimxsd_baseboard_init(void) +void __init eukrea_mbimxsd25_baseboard_init(void) { if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads, ARRAY_SIZE(eukrea_mbimxsd_pads))) diff --git a/arch/arm/mach-mx25/mach-cpuimx25.c b/arch/arm/mach-mx25/mach-cpuimx25.c index 56b2e26d23b4..b5efee23008f 100644 --- a/arch/arm/mach-mx25/mach-cpuimx25.c +++ b/arch/arm/mach-mx25/mach-cpuimx25.c @@ -147,8 +147,8 @@ static void __init eukrea_cpuimx25_init(void) if (!otg_mode_host) mxc_register_device(&otg_udc_device, &otg_device_pdata); -#ifdef CONFIG_MACH_EUKREA_MBIMXSD_BASEBOARD - eukrea_mbimxsd_baseboard_init(); +#ifdef CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD + eukrea_mbimxsd25_baseboard_init(); #endif } diff --git a/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c index 1dc5004df866..f8f15e3ac7a0 100644 --- a/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c +++ b/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c @@ -216,7 +216,7 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata = { * Add platform devices present on this baseboard and init * them from CPU side as far as required to use them later on */ -void __init eukrea_mbimxsd_baseboard_init(void) +void __init eukrea_mbimxsd35_baseboard_init(void) { if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads, ARRAY_SIZE(eukrea_mbimxsd_pads))) diff --git a/arch/arm/mach-mx3/mach-cpuimx35.c b/arch/arm/mach-mx3/mach-cpuimx35.c index 63f970f340a2..e4268bbb8fbc 100644 --- a/arch/arm/mach-mx3/mach-cpuimx35.c +++ b/arch/arm/mach-mx3/mach-cpuimx35.c @@ -201,8 +201,8 @@ static void __init mxc_board_init(void) if (!otg_mode_host) mxc_register_device(&mxc_otg_udc_device, &otg_device_pdata); -#ifdef CONFIG_MACH_EUKREA_MBIMXSD_BASEBOARD - eukrea_mbimxsd_baseboard_init(); +#ifdef CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD + eukrea_mbimxsd35_baseboard_init(); #endif } diff --git a/arch/arm/plat-mxc/include/mach/eukrea-baseboards.h b/arch/arm/plat-mxc/include/mach/eukrea-baseboards.h index 634e3f4c454d..656acb45d434 100644 --- a/arch/arm/plat-mxc/include/mach/eukrea-baseboards.h +++ b/arch/arm/plat-mxc/include/mach/eukrea-baseboards.h @@ -37,9 +37,9 @@ * mach-mx5/eukrea_mbimx51-baseboard.c for cpuimx51 */ -extern void eukrea_mbimx25_baseboard_init(void); +extern void eukrea_mbimxsd25_baseboard_init(void); extern void eukrea_mbimx27_baseboard_init(void); -extern void eukrea_mbimx35_baseboard_init(void); +extern void eukrea_mbimxsd35_baseboard_init(void); extern void eukrea_mbimx51_baseboard_init(void); #endif -- cgit v1.2.2 From 3d6e614952e3e4cf9e70e58893a740ffec220b24 Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Thu, 12 Aug 2010 15:10:53 +0200 Subject: mx35: Fix boot ROM hang in internal boot mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a watchdog reset occurs after booting in internal boot mode, the i.MX35 won't boot anymore. The boot ROM code seems to assume that some clocks are turned on (they are after a power-on reset). This patch turns on the necessary clocks. Signed-off-by: Hans J. Koch Acked-by: Uwe Kleine-König Reported-by: John Ogness Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/clock-imx35.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index d3af0fdf8475..32adf8d5b1f8 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c @@ -485,10 +485,10 @@ static struct clk_lookup lookups[] = { int __init mx35_clocks_init() { - unsigned int ll = 0; + unsigned int cgr2 = 3 << 26, cgr3 = 0; #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC) - ll = (3 << 16); + cgr2 |= 3 << 16; #endif clkdev_add_table(lookups, ARRAY_SIZE(lookups)); @@ -499,8 +499,20 @@ int __init mx35_clocks_init() __raw_writel((3 << 18), CCM_BASE + CCM_CGR0); __raw_writel((3 << 2) | (3 << 4) | (3 << 6) | (3 << 8) | (3 << 16), CCM_BASE + CCM_CGR1); - __raw_writel((3 << 26) | ll, CCM_BASE + CCM_CGR2); - __raw_writel(0, CCM_BASE + CCM_CGR3); + + /* + * Check if we came up in internal boot mode. If yes, we need some + * extra clocks turned on, otherwise the MX35 boot ROM code will + * hang after a watchdog reset. + */ + if (!(__raw_readl(CCM_BASE + CCM_RCSR) & (3 << 10))) { + /* Additionally turn on UART1, SCC, and IIM clocks */ + cgr2 |= 3 << 16 | 3 << 4; + cgr3 |= 3 << 2; + } + + __raw_writel(cgr2, CCM_BASE + CCM_CGR2); + __raw_writel(cgr3, CCM_BASE + CCM_CGR3); mxc_timer_init(&gpt_clk, MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR), MX35_INT_GPT); -- cgit v1.2.2 From 9a6f17fd1cd84811962735ff47111f84a8f05073 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 22 Apr 2010 12:37:13 +0200 Subject: i.MX35: remove get_3_3_div helper function In the v2 reference manual there are no dividers combined of two dividers. Instead, all dividers are simple 6bit dividers. I assume the combined dividers only exist in preliminary hardware. Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/clock-imx35.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index 32adf8d5b1f8..d3a8d3f32160 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c @@ -176,16 +176,11 @@ static unsigned long get_rate_ipg(struct clk *clk) return get_rate_ahb(NULL) >> 1; } -static unsigned long get_3_3_div(unsigned long in) -{ - return (((in >> 3) & 0x7) + 1) * ((in & 0x7) + 1); -} - static unsigned long get_rate_uart(struct clk *clk) { unsigned long pdr3 = __raw_readl(CCM_BASE + CCM_PDR3); unsigned long pdr4 = __raw_readl(CCM_BASE + CCM_PDR4); - unsigned long div = get_3_3_div(pdr4 >> 10); + unsigned long div = ((pdr4 >> 10) & 0x3f) + 1; if (pdr3 & (1 << 14)) return get_rate_arm() / div; @@ -216,7 +211,7 @@ static unsigned long get_rate_sdhc(struct clk *clk) break; } - return rate / get_3_3_div(div); + return rate / (div + 1); } static unsigned long get_rate_mshc(struct clk *clk) @@ -270,7 +265,7 @@ static unsigned long get_rate_csi(struct clk *clk) else rate = get_rate_ppll(); - return rate / get_3_3_div((pdr2 >> 16) & 0x3f); + return rate / (((pdr2 >> 16) & 0x3f) + 1); } static unsigned long get_rate_otg(struct clk *clk) @@ -283,22 +278,21 @@ static unsigned long get_rate_otg(struct clk *clk) else rate = get_rate_ppll(); - return rate / get_3_3_div((pdr4 >> 22) & 0x3f); + return rate / (((pdr4 >> 22) & 0x3f) + 1); } static unsigned long get_rate_ipg_per(struct clk *clk) { unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0); unsigned long pdr4 = __raw_readl(CCM_BASE + CCM_PDR4); - unsigned long div1, div2; + unsigned long div; if (pdr0 & (1 << 26)) { - div1 = (pdr4 >> 19) & 0x7; - div2 = (pdr4 >> 16) & 0x7; - return get_rate_arm() / ((div1 + 1) * (div2 + 1)); + div = (pdr4 >> 16) & 0x3f; + return get_rate_arm() / (div + 1); } else { - div1 = (pdr0 >> 12) & 0x7; - return get_rate_ahb(NULL) / div1; + div = (pdr0 >> 12) & 0x7; + return get_rate_ahb(NULL) / div; } } -- cgit v1.2.2 From c96c1e394fa72bd995154af7143873945a3fa89d Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 16 Aug 2010 15:54:05 +0200 Subject: clock-imx35: fix divider if ahb is source for ipg_per According to the Datasheet: "i.MX35 (MCIMX35) Multimedia Applications Processor Reference Manual, Rev. 2" "Table 14-6. PDR0 Field Descriptions" the divider is CCM_PER_AHB[3:0] + 1. This patch adds the missing + 1. Signed-off-by: Marc Kleine-Budde Signed-off-by: Michael Grzeschik Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/clock-imx35.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index d3a8d3f32160..e582ceb6e0c1 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c @@ -292,7 +292,7 @@ static unsigned long get_rate_ipg_per(struct clk *clk) return get_rate_arm() / (div + 1); } else { div = (pdr0 >> 12) & 0x7; - return get_rate_ahb(NULL) / div; + return get_rate_ahb(NULL) / (div + 1); } } -- cgit v1.2.2 From c56702de106b4fde301282f7ea60412276481442 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 16 Aug 2010 15:54:06 +0200 Subject: clock-imx35: correct arm and ahb clock calculation According to the Datasheet: "i.MX35 (MCIMX35) Multimedia Applications Processor Reference Manual, Rev. 2" "Figure 14-24. Clock Control And Gating" change the result of get_rate_ahb based on the frequency returned by get_rate_arm to calculate the proper rate. Signed-off-by: Marc Kleine-Budde Signed-off-by: Michael Grzeschik Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/clock-imx35.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index e582ceb6e0c1..1d311b77b40e 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c @@ -155,7 +155,7 @@ static unsigned long get_rate_arm(void) aad = &clk_consumer[(pdr0 >> 16) & 0xf]; if (aad->sel) - fref = fref * 2 / 3; + fref = fref * 3 / 4; return fref / aad->arm; } @@ -164,7 +164,7 @@ static unsigned long get_rate_ahb(struct clk *clk) { unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0); struct arm_ahb_div *aad; - unsigned long fref = get_rate_mpll(); + unsigned long fref = get_rate_arm(); aad = &clk_consumer[(pdr0 >> 16) & 0xf]; -- cgit v1.2.2 From c735c40587cea45f9d2f83339f374595073c1923 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Mon, 16 Aug 2010 15:54:07 +0200 Subject: clock-imx35: Calculate the base clock rate for the IPU unit The mx3fb driver needs the clock the IPU runs in order to calculate the divider for the LCD clock. This patch adds the clock rate calculation routine for the i.MX35 CPU. Signed-off-by: Juergen Beisert Signed-off-by: Michael Grzeschik Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/clock-imx35.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index 1d311b77b40e..7a62e744a8b0 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c @@ -296,6 +296,33 @@ static unsigned long get_rate_ipg_per(struct clk *clk) } } +static unsigned long get_rate_hsp(struct clk *clk) +{ + unsigned long hsp_podf = (__raw_readl(CCM_BASE + CCM_PDR0) >> 20) & 0x03; + unsigned long fref = get_rate_mpll(); + + if (fref > 400 * 1000 * 1000) { + switch (hsp_podf) { + case 0: + return fref >> 2; + case 1: + return fref >> 3; + case 2: + return fref / 3; + } + } else { + switch (hsp_podf) { + case 0: + case 2: + return fref / 3; + case 1: + return fref / 6; + } + } + + return 0; +} + static int clk_cgr_enable(struct clk *clk) { u32 reg; @@ -353,7 +380,7 @@ DEFINE_CLOCK(i2c1_clk, 0, CCM_CGR1, 10, get_rate_ipg_per, NULL); DEFINE_CLOCK(i2c2_clk, 1, CCM_CGR1, 12, get_rate_ipg_per, NULL); DEFINE_CLOCK(i2c3_clk, 2, CCM_CGR1, 14, get_rate_ipg_per, NULL); DEFINE_CLOCK(iomuxc_clk, 0, CCM_CGR1, 16, NULL, NULL); -DEFINE_CLOCK(ipu_clk, 0, CCM_CGR1, 18, get_rate_ahb, NULL); +DEFINE_CLOCK(ipu_clk, 0, CCM_CGR1, 18, get_rate_hsp, NULL); DEFINE_CLOCK(kpp_clk, 0, CCM_CGR1, 20, get_rate_ipg, NULL); DEFINE_CLOCK(mlb_clk, 0, CCM_CGR1, 22, get_rate_ahb, NULL); DEFINE_CLOCK(mshc_clk, 0, CCM_CGR1, 24, get_rate_mshc, NULL); -- cgit v1.2.2 From 23b90cfd7bcf8ae1c0711df1cae7dfec3c01aec8 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 17 Aug 2010 09:15:24 -0700 Subject: x86/PCI: only define pci_domain_nr if PCI and PCI_DOMAINS are set Otherwise we'll duplicate definitions with the pci.h stubs. Reported-by: Randy Dunlap Acked-by: Randy Dunlap Signed-off-by: Jesse Barnes --- arch/x86/include/asm/pci.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 404a880ea325..d395540ff894 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -27,6 +27,9 @@ extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node); extern struct pci_bus *pci_scan_bus_with_sysdata(int busno); +#ifdef CONFIG_PCI + +#ifdef CONFIG_PCI_DOMAINS static inline int pci_domain_nr(struct pci_bus *bus) { struct pci_sysdata *sd = bus->sysdata; @@ -37,13 +40,12 @@ static inline int pci_proc_domain(struct pci_bus *bus) { return pci_domain_nr(bus); } - +#endif /* Can be used to override the logic in pci_scan_bus for skipping already-configured bus numbers - to be used for buggy BIOSes or architectures with incomplete PCI setup by the loader */ -#ifdef CONFIG_PCI extern unsigned int pcibios_assign_all_busses(void); extern int pci_legacy_init(void); # ifdef CONFIG_ACPI -- cgit v1.2.2 From 3572b33efb044f76c224197408a812cda7d54fe4 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 16 Aug 2010 10:40:49 +0000 Subject: ARM: mach-shmobile: Clock framework comment fix Update clock framework header comment for SH-Mobile ARM. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/clock.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/clock.c b/arch/arm/mach-shmobile/clock.c index b7c705a213a2..6b7c7c42bc8f 100644 --- a/arch/arm/mach-shmobile/clock.c +++ b/arch/arm/mach-shmobile/clock.c @@ -1,8 +1,10 @@ /* - * SH-Mobile Timer + * SH-Mobile Clock Framework * * Copyright (C) 2010 Magnus Damm * + * Used together with arch/arm/common/clkdev.c and drivers/sh/clk.c. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. -- cgit v1.2.2 From 4e1774f3a5de0885be2e59a8e8ef0e99c5f79e7a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 17 Aug 2010 22:53:58 +0000 Subject: ARM: mach-shmobile: do not enable the PLLC2 clock on init AP4EVB has to reparent PLLC2 to provide a precise HDMI clock, this is only possible, if PLLC2 hasn't been enabled yet. Since no other driver currently uses PLLC2 we can safely remove the CLK_ENABLE_ON_INIT flag. This fixes the "Cannot set PLLC2 parent: -16, 1 users" error message, when trying to use HDMI on AP4EVB. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/clock-sh7372.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index dcaac1b6691d..759468992ad2 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c @@ -286,7 +286,6 @@ static struct clk_ops pllc2_clk_ops = { struct clk pllc2_clk = { .ops = &pllc2_clk_ops, - .flags = CLK_ENABLE_ON_INIT, .parent = &extal1_div2_clk, .freq_table = pllc2_freq_table, .parent_table = pllc2_parent, -- cgit v1.2.2 From 9f6f11b65ea2da8fab4d6902595d770e89e64d93 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 18 Aug 2010 03:37:19 +0000 Subject: ARM: mach-shmobile: ap4evb: modify FSI2 ID Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-ap4evb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 8afdb1dab029..1b95f122ecf5 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -559,7 +559,7 @@ static struct resource fsi_resources[] = { static struct platform_device fsi_device = { .name = "sh_fsi2", - .id = 0, + .id = -1, .num_resources = ARRAY_SIZE(fsi_resources), .resource = fsi_resources, .dev = { -- cgit v1.2.2 From 410d878bd05315a19894b8b4685107f2cd0712a5 Mon Sep 17 00:00:00 2001 From: Arnd Hannemann Date: Wed, 18 Aug 2010 16:24:13 +0000 Subject: ARM: mach-shmobile: ap4evb: fix write protect for SDHI1 SDHI1 on AP4EVB has no pin to detect write protection of a card. This had the result that a card inserted in this slot was always detected as read only. This patch adds the corresponding flag to disable write protection detection for SDHI1. Signed-off-by: Arnd Hannemann Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-ap4evb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 1b95f122ecf5..95935c83c306 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -308,6 +309,7 @@ static struct sh_mobile_sdhi_info sdhi1_info = { .dma_slave_tx = SHDMA_SLAVE_SDHI1_TX, .dma_slave_rx = SHDMA_SLAVE_SDHI1_RX, .tmio_ocr_mask = MMC_VDD_165_195, + .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE, }; static struct resource sdhi1_resources[] = { -- cgit v1.2.2 From 51e3c1b558b31b11bf5fc66d3c6f5adacf3573f7 Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Fri, 20 Aug 2010 10:36:34 +0300 Subject: x86, hwmon: Fix unsafe smp_processor_id() in thermal_throttle_add_dev Fix BUG: using smp_processor_id() in preemptible thermal_throttle_add_dev. We know the cpu number when calling thermal_throttle_add_dev, so we can remove smp_processor_id call in thermal_throttle_add_dev by supplying the cpu number as argument. This should resolve kernel bugzilla 16615/16629. Signed-off-by: Sergey Senozhatsky LKML-Reference: <20100820073634.GB5209@swordfish.minsk.epam.com> Cc: Fenghua Yu Cc: Joerg Roedel Cc: Maciej Rutecki Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/mcheck/therm_throt.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index c2a8b26d4fea..d9368eeda309 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -202,10 +202,11 @@ static int therm_throt_process(bool new_event, int event, int level) #ifdef CONFIG_SYSFS /* Add/Remove thermal_throttle interface for CPU device: */ -static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev) +static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev, + unsigned int cpu) { int err; - struct cpuinfo_x86 *c = &cpu_data(smp_processor_id()); + struct cpuinfo_x86 *c = &cpu_data(cpu); err = sysfs_create_group(&sys_dev->kobj, &thermal_attr_group); if (err) @@ -251,7 +252,7 @@ thermal_throttle_cpu_callback(struct notifier_block *nfb, case CPU_UP_PREPARE: case CPU_UP_PREPARE_FROZEN: mutex_lock(&therm_cpu_lock); - err = thermal_throttle_add_dev(sys_dev); + err = thermal_throttle_add_dev(sys_dev, cpu); mutex_unlock(&therm_cpu_lock); WARN_ON(err); break; @@ -287,7 +288,7 @@ static __init int thermal_throttle_init_device(void) #endif /* connect live CPUs to sysfs */ for_each_online_cpu(cpu) { - err = thermal_throttle_add_dev(get_cpu_sysdev(cpu)); + err = thermal_throttle_add_dev(get_cpu_sysdev(cpu), cpu); WARN_ON(err); } #ifdef CONFIG_HOTPLUG_CPU -- cgit v1.2.2 From a38b372fc2a3d8fe7ddbeab94d4c8bcb721f2403 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Sat, 21 Aug 2010 16:24:03 +0800 Subject: mxc/tzic: add base address when accessing TZIC registers When we call tzic_enable_wake function, the kernel will crash because of access to an unmapped address. This is because two register access operations forgot to add base address. Signed-off-by: Jason Wang Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/tzic.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c index b3da9aad4295..3703ab28257f 100644 --- a/arch/arm/plat-mxc/tzic.c +++ b/arch/arm/plat-mxc/tzic.c @@ -164,8 +164,9 @@ int tzic_enable_wake(int is_idle) return -EAGAIN; for (i = 0; i < 4; i++) { - v = is_idle ? __raw_readl(TZIC_ENSET0(i)) : wakeup_intr[i]; - __raw_writel(v, TZIC_WAKEUP0(i)); + v = is_idle ? __raw_readl(tzic_base + TZIC_ENSET0(i)) : + wakeup_intr[i]; + __raw_writel(v, tzic_base + TZIC_WAKEUP0(i)); } return 0; -- cgit v1.2.2 From 7f67bff58662604874778e6853e5c394f944e554 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Sat, 21 Aug 2010 16:24:04 +0800 Subject: mx5/clock: fix clear bit fields issue in _clk_ccgr_disable function We can see MXC_CCM_CCGRx_MOD_OFF is defined as 0 while MXC_CCM_CCGRx_CG_MASK is defined as 0x3 in crm_regs.h, here in the _clk_ccgr_disable function, we want to clear the corresponding enable bit fields to disable this clock, so we should choose MASK instead of OFF otherwise clocks can't be disabled. Signed-off-by: Jason Wang Signed-off-by: Sascha Hauer --- arch/arm/mach-mx5/clock-mx51.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c index 6af69def357f..57c10a9926cc 100644 --- a/arch/arm/mach-mx5/clock-mx51.c +++ b/arch/arm/mach-mx5/clock-mx51.c @@ -56,7 +56,7 @@ static void _clk_ccgr_disable(struct clk *clk) { u32 reg; reg = __raw_readl(clk->enable_reg); - reg &= ~(MXC_CCM_CCGRx_MOD_OFF << clk->enable_shift); + reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift); __raw_writel(reg, clk->enable_reg); } -- cgit v1.2.2 From 14f0f512ba6f4eccc9b7cf67be47439ed2917afb Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Sat, 21 Aug 2010 16:24:05 +0800 Subject: ARM: imx: set cache line size to 64 bytes for i.MX5 The core of i.MX5 series is cortex-A8, its cache line size is 64 bytes instead of 32 bytes. Refer to the OMAP3's selection, we choose 64 bytes for i.MX5, this can increase a little bit performance when perform cache operations. Signed-off-by: Jason Wang Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index 0527e65318f4..6785db4179b8 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig @@ -43,6 +43,7 @@ config ARCH_MXC91231 config ARCH_MX5 bool "MX5-based" select CPU_V7 + select ARM_L1_CACHE_SHIFT_6 help This enables support for systems based on the Freescale i.MX51 family -- cgit v1.2.2 From b7d460897739e02f186425b7276e3fdb1595cea7 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 24 Aug 2010 22:44:12 -0700 Subject: x86, mm: Fix CONFIG_VMSPLIT_1G and 2G_OPT trampoline rc2 kernel crashes when booting second cpu on this CONFIG_VMSPLIT_2G_OPT laptop: whereas cloning from kernel to low mappings pgd range does need to limit by both KERNEL_PGD_PTRS and KERNEL_PGD_BOUNDARY, cloning kernel pgd range itself must not be limited by the smaller KERNEL_PGD_BOUNDARY. Signed-off-by: Hugh Dickins LKML-Reference: Signed-off-by: H. Peter Anvin --- arch/x86/kernel/trampoline.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c index a874495b3673..e2a595257390 100644 --- a/arch/x86/kernel/trampoline.c +++ b/arch/x86/kernel/trampoline.c @@ -45,8 +45,7 @@ void __init setup_trampoline_page_table(void) /* Copy kernel address range */ clone_pgd_range(trampoline_pg_dir + KERNEL_PGD_BOUNDARY, swapper_pg_dir + KERNEL_PGD_BOUNDARY, - min_t(unsigned long, KERNEL_PGD_PTRS, - KERNEL_PGD_BOUNDARY)); + KERNEL_PGD_PTRS); /* Initialize low mappings */ clone_pgd_range(trampoline_pg_dir, -- cgit v1.2.2 From 2971944582ff43b7dedbb460777052243ac9915a Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 9 Aug 2010 12:54:43 +0100 Subject: ARM: 6307/1: mmci: allow the card detect GPIO value not to be inverted On some platforms, the GPIO value from the gpio_cd pin doesn't need to be inverted to get it active high. Add a cd_invert platform data parameter and change existing platforms using GPIO for CD (only Realview) to enable it. Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/mach-realview/core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 2fa38df28414..07c08151dfe6 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -259,6 +259,7 @@ struct mmci_platform_data realview_mmc0_plat_data = { .status = realview_mmc_status, .gpio_wp = 17, .gpio_cd = 16, + .cd_invert = true, }; struct mmci_platform_data realview_mmc1_plat_data = { @@ -266,6 +267,7 @@ struct mmci_platform_data realview_mmc1_plat_data = { .status = realview_mmc_status, .gpio_wp = 19, .gpio_cd = 18, + .cd_invert = true, }; /* -- cgit v1.2.2 From 50e77fcd790e02a095f906df0f6fa72afef7e11c Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 18 Aug 2010 11:51:13 +0800 Subject: ARM: pxa: remove __init from cpufreq_driver->init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is causing section mismatches when linking, as cpufreq_driver->init() is not supposed to be in init section. Reported-by: Tomáš 'Sleep_Walker' Čech Signed-off-by: Eric Miao --- arch/arm/mach-pxa/cpufreq-pxa2xx.c | 2 +- arch/arm/mach-pxa/cpufreq-pxa3xx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/cpufreq-pxa2xx.c b/arch/arm/mach-pxa/cpufreq-pxa2xx.c index 268a9bc6be8a..50d5939a78f1 100644 --- a/arch/arm/mach-pxa/cpufreq-pxa2xx.c +++ b/arch/arm/mach-pxa/cpufreq-pxa2xx.c @@ -398,7 +398,7 @@ static int pxa_set_target(struct cpufreq_policy *policy, return 0; } -static __init int pxa_cpufreq_init(struct cpufreq_policy *policy) +static int pxa_cpufreq_init(struct cpufreq_policy *policy) { int i; unsigned int freq; diff --git a/arch/arm/mach-pxa/cpufreq-pxa3xx.c b/arch/arm/mach-pxa/cpufreq-pxa3xx.c index 27fa329d9a8b..0a0d0fe99220 100644 --- a/arch/arm/mach-pxa/cpufreq-pxa3xx.c +++ b/arch/arm/mach-pxa/cpufreq-pxa3xx.c @@ -204,7 +204,7 @@ static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy, return 0; } -static __init int pxa3xx_cpufreq_init(struct cpufreq_policy *policy) +static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy) { int ret = -EINVAL; -- cgit v1.2.2 From be7a6d9dd67251675b83a29f4b15392eae62e70b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 13 Aug 2010 11:39:07 +0800 Subject: ARM: pxa: fix CI_HSYNC and CI_VSYNC MFP defines for pxa300 According to PXA3xx Processor Family Developer Manuall Vol1. section "Pin Descriptions and Control", PXA30x and PXA31x Processor Alternate Function Table shows the Alt FN 0 for GPIO51 is CI_HSYNC and for GPIO52 is CI_VSYNC. This patch fixes the MFP defines and also corrects the order of MFD defines. Signed-off-by: Axel Lin Signed-off-by: Eric Miao --- arch/arm/mach-pxa/include/mach/mfp-pxa300.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h index 7139e0dc26d1..4e1287070d21 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h @@ -71,10 +71,10 @@ #define GPIO46_CI_DD_7 MFP_CFG_DRV(GPIO46, AF0, DS04X) #define GPIO47_CI_DD_8 MFP_CFG_DRV(GPIO47, AF1, DS04X) #define GPIO48_CI_DD_9 MFP_CFG_DRV(GPIO48, AF1, DS04X) -#define GPIO52_CI_HSYNC MFP_CFG_DRV(GPIO52, AF0, DS04X) -#define GPIO51_CI_VSYNC MFP_CFG_DRV(GPIO51, AF0, DS04X) #define GPIO49_CI_MCLK MFP_CFG_DRV(GPIO49, AF0, DS04X) #define GPIO50_CI_PCLK MFP_CFG_DRV(GPIO50, AF0, DS04X) +#define GPIO51_CI_HSYNC MFP_CFG_DRV(GPIO51, AF0, DS04X) +#define GPIO52_CI_VSYNC MFP_CFG_DRV(GPIO52, AF0, DS04X) /* KEYPAD */ #define GPIO3_KP_DKIN_6 MFP_CFG_LPM(GPIO3, AF2, FLOAT) -- cgit v1.2.2 From b3282ab116cd7ebd2829ac8088524b5b279330e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 12 Aug 2010 08:18:28 +0200 Subject: ARM: pxa: Make id const in pwm_probe() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the compiler warning: arch/arm/plat-pxa/pwm.c: In function 'pwm_probe': arch/arm/plat-pxa/pwm.c:179: warning: initialization discards qualifiers from pointer target type Signed-off-by: Uwe Kleine-König Signed-off-by: Eric Miao --- arch/arm/plat-pxa/pwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/plat-pxa/pwm.c b/arch/arm/plat-pxa/pwm.c index 0732c6c8d511..ef32686feef9 100644 --- a/arch/arm/plat-pxa/pwm.c +++ b/arch/arm/plat-pxa/pwm.c @@ -176,7 +176,7 @@ static inline void __add_pwm(struct pwm_device *pwm) static int __devinit pwm_probe(struct platform_device *pdev) { - struct platform_device_id *id = platform_get_device_id(pdev); + const struct platform_device_id *id = platform_get_device_id(pdev); struct pwm_device *pwm, *secondary = NULL; struct resource *r; int ret = 0; -- cgit v1.2.2 From 4562c986f0d694124de20815adf7e1aad8a94668 Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Fri, 27 Aug 2010 11:58:21 +0000 Subject: powerpc/kexec: Adds correct calling convention for kexec purgatory Call kexec purgatory code correctly. We were getting lucky before. If you examine the powerpc 32bit kexec "purgatory" code you will see it expects the following: >From kexec-tools: purgatory/arch/ppc/v2wrap_32.S -> calling convention: -> r3 = physical number of this cpu (all cpus) -> r4 = address of this chunk (master only) As such, we need to set r3 to the current core, r4 happens to be unused by purgatory at the moment but we go ahead and set it here as well Signed-off-by: Matthew McClintock Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/misc_32.S | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 6bbd7a604d24..a7a570dcdd57 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -810,6 +810,9 @@ relocate_new_kernel: isync sync + mfspr r3, SPRN_PIR /* current core we are running on */ + mr r4, r5 /* load physical address of chunk called */ + /* jump to the entry point, usually the setup routine */ mtlr r5 blrl -- cgit v1.2.2 From b0d278b7d3ae9115939ddcea93f516308cc367e2 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 10 Aug 2010 20:38:23 +0000 Subject: powerpc/perf_event: Reduce latency of calling perf_event_do_pending Commit 0fe1ac48 ("powerpc/perf_event: Fix oops due to perf_event_do_pending call") moved the call to perf_event_do_pending in timer_interrupt() down so that it was after the irq_enter() call. Unfortunately this moved it after the code that checks whether it is time for the next decrementer clock event. The result is that the call to perf_event_do_pending() won't happen until the next decrementer clock event is due. This was pointed out by Milton Miller. This fixes it by moving the check for whether it's time for the next decrementer clock event down to the point where we're about to call the event handler, after we've called perf_event_do_pending. This has the side effect that on old pre-Core99 Powermacs where we use the ppc_n_lost_interrupts mechanism to replay interrupts, a replayed interrupt will incur a little more latency since it will now do the code from the irq_enter down to the irq_exit, that it used to skip. However, these machines are now old and rare enough that this doesn't matter. To make it clear that ppc_n_lost_interrupts is only used on Powermacs, and to speed up the code slightly on non-Powermac ppc32 machines, the code that tests ppc_n_lost_interrupts is now conditional on CONFIG_PMAC as well as CONFIG_PPC32. Signed-off-by: Paul Mackerras Cc: stable@kernel.org Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/time.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index ce53dfa7130d..8533b3b83f5d 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -577,20 +577,11 @@ void timer_interrupt(struct pt_regs * regs) * some CPUs will continuue to take decrementer exceptions */ set_dec(DECREMENTER_MAX); -#ifdef CONFIG_PPC32 +#if defined(CONFIG_PPC32) && defined(CONFIG_PMAC) if (atomic_read(&ppc_n_lost_interrupts) != 0) do_IRQ(regs); #endif - now = get_tb_or_rtc(); - if (now < decrementer->next_tb) { - /* not time for this event yet */ - now = decrementer->next_tb - now; - if (now <= DECREMENTER_MAX) - set_dec((int)now); - trace_timer_interrupt_exit(regs); - return; - } old_regs = set_irq_regs(regs); irq_enter(); @@ -606,8 +597,16 @@ void timer_interrupt(struct pt_regs * regs) get_lppaca()->int_dword.fields.decr_int = 0; #endif - if (evt->event_handler) - evt->event_handler(evt); + now = get_tb_or_rtc(); + if (now >= decrementer->next_tb) { + decrementer->next_tb = ~(u64)0; + if (evt->event_handler) + evt->event_handler(evt); + } else { + now = decrementer->next_tb - now; + if (now <= DECREMENTER_MAX) + set_dec((int)now); + } #ifdef CONFIG_PPC_ISERIES if (firmware_has_feature(FW_FEATURE_ISERIES) && hvlpevent_is_pending()) -- cgit v1.2.2 From 54a834043314c257210db2a9d59f8cc605571639 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Wed, 25 Aug 2010 21:04:25 +0000 Subject: powerpc: Don't use kernel stack with translation off In f761622e59433130bc33ad086ce219feee9eb961 we changed early_setup_secondary so it's called using the proper kernel stack rather than the emergency one. Unfortunately, this stack pointer can't be used when translation is off on PHYP as this stack pointer might be outside the RMO. This results in the following on all non zero cpus: cpu 0x1: Vector: 300 (Data Access) at [c00000001639fd10] pc: 000000000001c50c lr: 000000000000821c sp: c00000001639ff90 msr: 8000000000001000 dar: c00000001639ffa0 dsisr: 42000000 current = 0xc000000016393540 paca = 0xc000000006e00200 pid = 0, comm = swapper The original patch was only tested on bare metal system, so it never caught this problem. This changes __secondary_start so that we calculate the new stack pointer but only start using it after we've called early_setup_secondary. With this patch, the above problem goes away. Signed-off-by: Michael Neuling Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/head_64.S | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 4d6681dce816..c571cd3c1453 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -575,13 +575,19 @@ __secondary_start: /* Initialize the kernel stack. Just a repeat for iSeries. */ LOAD_REG_ADDR(r3, current_set) sldi r28,r24,3 /* get current_set[cpu#] */ - ldx r1,r3,r28 - addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD - std r1,PACAKSAVE(r13) + ldx r14,r3,r28 + addi r14,r14,THREAD_SIZE-STACK_FRAME_OVERHEAD + std r14,PACAKSAVE(r13) /* Do early setup for that CPU (stab, slb, hash table pointer) */ bl .early_setup_secondary + /* + * setup the new stack pointer, but *don't* use this until + * translation is on. + */ + mr r1, r14 + /* Clear backchain so we get nice backtraces */ li r7,0 mtlr r7 -- cgit v1.2.2 From 10f0412f57f2a76a90eff4376f59cbb0a39e4e18 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 30 Aug 2010 10:56:18 +0200 Subject: oprofile, x86: fix init_sysfs error handling On failure init_sysfs() might not properly free resources. The error code of the function is not checked. And, when reinitializing the exit function might be called twice. This patch fixes all this. Cc: stable@kernel.org Signed-off-by: Robert Richter --- arch/x86/oprofile/nmi_int.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index f6b48f6c5951..73a41d3c6c09 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -568,8 +568,13 @@ static int __init init_sysfs(void) int error; error = sysdev_class_register(&oprofile_sysclass); - if (!error) - error = sysdev_register(&device_oprofile); + if (error) + return error; + + error = sysdev_register(&device_oprofile); + if (error) + sysdev_class_unregister(&oprofile_sysclass); + return error; } @@ -695,6 +700,8 @@ int __init op_nmi_init(struct oprofile_operations *ops) char *cpu_type = NULL; int ret = 0; + using_nmi = 0; + if (!cpu_has_apic) return -ENODEV; @@ -774,7 +781,10 @@ int __init op_nmi_init(struct oprofile_operations *ops) mux_init(ops); - init_sysfs(); + ret = init_sysfs(); + if (ret) + return ret; + using_nmi = 1; printk(KERN_INFO "oprofile: using NMI interrupt.\n"); return 0; -- cgit v1.2.2 From 6d4f2fb0860c36e7ef16cc41126242a8b6542771 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 31 Aug 2010 04:15:22 +0200 Subject: powerpc/85xx: Fix compilation of mpc85xx_mds.c Commit 99d8238f berobbed the for_each loop of its iterator! Let's be nice and give it back, so it compiles for us. CC: Anton Vorontsov Signed-off-by: Alexander Graf Signed-off-by: Kumar Gala --- arch/powerpc/platforms/85xx/mpc85xx_mds.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index da64be19d099..aa34cac4eb5c 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -357,6 +357,7 @@ static void __init mpc85xx_mds_setup_arch(void) { #ifdef CONFIG_PCI struct pci_controller *hose; + struct device_node *np; #endif dma_addr_t max = 0xffffffff; -- cgit v1.2.2 From dc1c41f450a5f201f1d8c19aef32319f3b84c273 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 31 Aug 2010 11:39:25 -0500 Subject: powerpc/85xx: Fix compile issue with p1022_ds due to lmb rename to memblock arch/powerpc/platforms/85xx/p1022_ds.c:22:23: error: linux/lmb.h: No such file or directory arch/powerpc/platforms/85xx/p1022_ds.c: In function 'p1022_ds_setup_arch': arch/powerpc/platforms/85xx/p1022_ds.c:100: error: implicit declaration of function 'memblock_end_of_DRAM' arch/powerpc/platforms/85xx/p1022_ds.c: At top level: arch/powerpc/platforms/85xx/p1022_ds.c:147: error: 'udbg_progress' undeclared here (not in a function) make[2]: *** [arch/powerpc/platforms/85xx/p1022_ds.o] Error 1 Signed-off-by: Kumar Gala --- arch/powerpc/platforms/85xx/p1022_ds.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index e1467c937450..34e00902ce86 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include @@ -97,7 +97,7 @@ static void __init p1022_ds_setup_arch(void) #endif #ifdef CONFIG_SWIOTLB - if (lmb_end_of_DRAM() > max) { + if (memblock_end_of_DRAM() > max) { ppc_swiotlb_enable = 1; set_pci_dma_ops(&swiotlb_dma_ops); ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; -- cgit v1.2.2 From ff33f1821259d00d3fd85d86f59783e2ca3c9ee1 Mon Sep 17 00:00:00 2001 From: Li Yang Date: Fri, 18 Jun 2010 14:24:20 +0800 Subject: fsl_rio: fix compile errors Fixes the following compile problem on E500 platforms: arch/powerpc/sysdev/fsl_rio.c: In function 'fsl_rio_mcheck_exception': arch/powerpc/sysdev/fsl_rio.c:248: error: 'MCSR_MASK' undeclared (first use in this function) Also fixes the compile problem on non-E500 platforms. Signed-off-by: Li Yang Signed-off-by: Kumar Gala --- arch/powerpc/sysdev/fsl_rio.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 6425abe5b7db..3017532319c8 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -240,12 +240,13 @@ struct rio_priv { static void __iomem *rio_regs_win; +#ifdef CONFIG_E500 static int (*saved_mcheck_exception)(struct pt_regs *regs); static int fsl_rio_mcheck_exception(struct pt_regs *regs) { const struct exception_table_entry *entry = NULL; - unsigned long reason = (mfspr(SPRN_MCSR) & MCSR_MASK); + unsigned long reason = mfspr(SPRN_MCSR); if (reason & MCSR_BUS_RBERR) { reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR)); @@ -269,6 +270,7 @@ static int fsl_rio_mcheck_exception(struct pt_regs *regs) else return cur_cpu_spec->machine_check(regs); } +#endif /** * fsl_rio_doorbell_send - Send a MPC85xx doorbell message @@ -1517,8 +1519,10 @@ int fsl_rio_setup(struct platform_device *dev) fsl_rio_doorbell_init(port); fsl_rio_port_write_init(port); +#ifdef CONFIG_E500 saved_mcheck_exception = ppc_md.machine_check_exception; ppc_md.machine_check_exception = fsl_rio_mcheck_exception; +#endif /* Ensure that RFXE is set */ mtspr(SPRN_HID1, (mfspr(SPRN_HID1) | 0x20000)); -- cgit v1.2.2 From fa9fc821f8892590211a9aa9e855eb83152b9870 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Aug 2010 21:47:18 +0200 Subject: arch/powerpc/platforms/83xx/mpc837x_mds.c: Add missing iounmap The function of_iomap returns the result of calling ioremap, so iounmap should be called on the result in the error handling code, as done in the normal exit of the function. The sematic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r exists@ local idexpression x; expression E,E1; identifier l; statement S; @@ *x = of_iomap(...); ... when != iounmap(x) when != if (...) { ... iounmap(x); ... } when != E = x when any ( if (x == NULL) S | if (...) { ... when != iounmap(x) when != if (...) { ... iounmap(x); ... } ( return <+...x...+>; | * return ...; ) } ) ... when != x = E1 when any iounmap(x); // Signed-off-by: Julia Lawall Signed-off-by: Kumar Gala --- arch/powerpc/platforms/83xx/mpc837x_mds.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c index f9751c8905be..83068322abd1 100644 --- a/arch/powerpc/platforms/83xx/mpc837x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c @@ -48,8 +48,10 @@ static int mpc837xmds_usb_cfg(void) return -1; np = of_find_node_by_name(NULL, "usb"); - if (!np) - return -ENODEV; + if (!np) { + ret = -ENODEV; + goto out; + } phy_type = of_get_property(np, "phy_type", NULL); if (phy_type && !strcmp(phy_type, "ulpi")) { clrbits8(bcsr_regs + 12, BCSR12_USB_SER_PIN); @@ -65,8 +67,9 @@ static int mpc837xmds_usb_cfg(void) } of_node_put(np); +out: iounmap(bcsr_regs); - return 0; + return ret; } /* ************************************************************************ -- cgit v1.2.2 From 5aac4d73dc234fe7be91679b547af2436d7f8d1e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Aug 2010 11:52:44 +0200 Subject: arch/powerpc/sysdev/qe_lib/qe.c: Add of_node_put to avoid memory leak Add a call to of_node_put in the error handling code following a call to of_find_compatible_node. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r exists@ local idexpression x; expression E,E1; statement S; @@ *x = (of_find_node_by_path |of_find_node_by_name |of_find_node_by_phandle |of_get_parent |of_get_next_parent |of_get_next_child |of_find_compatible_node |of_match_node )(...); ... if (x == NULL) S <... when != x = E *if (...) { ... when != of_node_put(x) when != if (...) { ... of_node_put(x); ... } ( return <+...x...+>; | * return ...; ) } ...> of_node_put(x); // Signed-off-by: Julia Lawall Acked-by: Timur Tabi Signed-off-by: Kumar Gala --- arch/powerpc/sysdev/qe_lib/qe.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 3da8014931c9..90020de4dcf2 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c @@ -640,6 +640,7 @@ unsigned int qe_get_num_of_snums(void) if ((num_of_snums < 28) || (num_of_snums > QE_NUM_OF_SNUM)) { /* No QE ever has fewer than 28 SNUMs */ pr_err("QE: number of snum is invalid\n"); + of_node_put(qe); return -EINVAL; } } -- cgit v1.2.2 From a28dec2f26013aad89446b1f708f948617bc28a2 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sun, 8 Aug 2010 18:03:33 +0400 Subject: powerpc/85xx: Add P1021 PCI IDs and quirks This is needed for proper PCI-E support on P1021 SoCs. Signed-off-by: Anton Vorontsov Signed-off-by: Kumar Gala --- arch/powerpc/sysdev/fsl_pci.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 209384b6e039..4ae933225251 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -399,6 +399,8 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013E, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020E, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1021E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1021, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022E, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010E, quirk_fsl_pcie_header); -- cgit v1.2.2 From 6445671b00b3c4bcb26c8e0fc74abe780a67b901 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 31 Aug 2010 22:26:15 -0400 Subject: alpha: remove homegrown L1_CACHE_ALIGN macro Let's use the standard L1_CACHE_ALIGN macro instead. Signed-off-by: FUJITA Tomonori Signed-off-by: Matt Turner --- arch/alpha/include/asm/cache.h | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/alpha/include/asm/cache.h b/arch/alpha/include/asm/cache.h index f199e69a5d0b..ad368a93a46a 100644 --- a/arch/alpha/include/asm/cache.h +++ b/arch/alpha/include/asm/cache.h @@ -17,7 +17,6 @@ # define L1_CACHE_SHIFT 5 #endif -#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)) #define SMP_CACHE_BYTES L1_CACHE_BYTES #endif -- cgit v1.2.2 From 59b25ed91400ace98d6cf0d59b1cb6928ad5cd37 Mon Sep 17 00:00:00 2001 From: "Morten H. Larsen" Date: Tue, 31 Aug 2010 22:29:13 -0400 Subject: Fix call to replaced SuperIO functions This patch fixes the failure to compile Alpha Generic because of previously overlooked calls to ns87312_enable_ide(). The function has been replaced by newer SuperIO code. Tested-by: Michael Cree Signed-off-by: Morten H. Larsen Signed-off-by: Matt Turner --- arch/alpha/kernel/proto.h | 3 --- arch/alpha/kernel/sys_cabriolet.c | 19 ++++++++++++++++--- arch/alpha/kernel/sys_takara.c | 11 +++++++++-- 3 files changed, 25 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h index 3d2627ec9860..d3e52d3fd592 100644 --- a/arch/alpha/kernel/proto.h +++ b/arch/alpha/kernel/proto.h @@ -156,9 +156,6 @@ extern void SMC669_Init(int); /* es1888.c */ extern void es1888_init(void); -/* ns87312.c */ -extern void ns87312_enable_ide(long ide_base); - /* ../lib/fpreg.c */ extern void alpha_write_fp_reg (unsigned long reg, unsigned long val); extern unsigned long alpha_read_fp_reg (unsigned long reg); diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c index affd0f3f25df..14c8898d19ec 100644 --- a/arch/alpha/kernel/sys_cabriolet.c +++ b/arch/alpha/kernel/sys_cabriolet.c @@ -33,7 +33,7 @@ #include "irq_impl.h" #include "pci_impl.h" #include "machvec_impl.h" - +#include "pc873xx.h" /* Note mask bit is true for DISABLED irqs. */ static unsigned long cached_irq_mask = ~0UL; @@ -235,18 +235,31 @@ cabriolet_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return COMMON_TABLE_LOOKUP; } +static inline void __init +cabriolet_enable_ide(void) +{ + if (pc873xx_probe() == -1) { + printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n"); + } else { + printk(KERN_INFO "Found %s Super IO chip at 0x%x\n", + pc873xx_get_model(), pc873xx_get_base()); + + pc873xx_enable_ide(); + } +} + static inline void __init cabriolet_init_pci(void) { common_init_pci(); - ns87312_enable_ide(0x398); + cabriolet_enable_ide(); } static inline void __init cia_cab_init_pci(void) { cia_init_pci(); - ns87312_enable_ide(0x398); + cabriolet_enable_ide(); } /* diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c index 230464885b5c..4da596b6adbb 100644 --- a/arch/alpha/kernel/sys_takara.c +++ b/arch/alpha/kernel/sys_takara.c @@ -29,7 +29,7 @@ #include "irq_impl.h" #include "pci_impl.h" #include "machvec_impl.h" - +#include "pc873xx.h" /* Note mask bit is true for DISABLED irqs. */ static unsigned long cached_irq_mask[2] = { -1, -1 }; @@ -264,7 +264,14 @@ takara_init_pci(void) alpha_mv.pci_map_irq = takara_map_irq_srm; cia_init_pci(); - ns87312_enable_ide(0x26e); + + if (pc873xx_probe() == -1) { + printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n"); + } else { + printk(KERN_INFO "Found %s Super IO chip at 0x%x\n", + pc873xx_get_model(), pc873xx_get_base()); + pc873xx_enable_ide(); + } } -- cgit v1.2.2 From 7b598cdd03e35a4361f4ff7ebc630aa508c35be6 Mon Sep 17 00:00:00 2001 From: Michael Cree Date: Tue, 31 Aug 2010 22:46:04 -0400 Subject: alpha: convert perf_event to use local_t Updates the Alpha perf_event code to match the changes recently made to the core perf_event code in commit e78505958cf123048fb48cb56b79cebb8edd15fb. Signed-off-by: Michael Cree Signed-off-by: Matt Turner --- arch/alpha/kernel/perf_event.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c index 51c39fa41693..85d8e4f58c83 100644 --- a/arch/alpha/kernel/perf_event.c +++ b/arch/alpha/kernel/perf_event.c @@ -241,20 +241,20 @@ static inline unsigned long alpha_read_pmc(int idx) static int alpha_perf_event_set_period(struct perf_event *event, struct hw_perf_event *hwc, int idx) { - long left = atomic64_read(&hwc->period_left); + long left = local64_read(&hwc->period_left); long period = hwc->sample_period; int ret = 0; if (unlikely(left <= -period)) { left = period; - atomic64_set(&hwc->period_left, left); + local64_set(&hwc->period_left, left); hwc->last_period = period; ret = 1; } if (unlikely(left <= 0)) { left += period; - atomic64_set(&hwc->period_left, left); + local64_set(&hwc->period_left, left); hwc->last_period = period; ret = 1; } @@ -269,7 +269,7 @@ static int alpha_perf_event_set_period(struct perf_event *event, if (left > (long)alpha_pmu->pmc_max_period[idx]) left = alpha_pmu->pmc_max_period[idx]; - atomic64_set(&hwc->prev_count, (unsigned long)(-left)); + local64_set(&hwc->prev_count, (unsigned long)(-left)); alpha_write_pmc(idx, (unsigned long)(-left)); @@ -300,10 +300,10 @@ static unsigned long alpha_perf_event_update(struct perf_event *event, long delta; again: - prev_raw_count = atomic64_read(&hwc->prev_count); + prev_raw_count = local64_read(&hwc->prev_count); new_raw_count = alpha_read_pmc(idx); - if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count, + if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, new_raw_count) != prev_raw_count) goto again; @@ -316,8 +316,8 @@ again: delta += alpha_pmu->pmc_max_period[idx] + 1; } - atomic64_add(delta, &event->count); - atomic64_sub(delta, &hwc->period_left); + local64_add(delta, &event->count); + local64_sub(delta, &hwc->period_left); return new_raw_count; } @@ -636,7 +636,7 @@ static int __hw_perf_event_init(struct perf_event *event) if (!hwc->sample_period) { hwc->sample_period = alpha_pmu->pmc_max_period[0]; hwc->last_period = hwc->sample_period; - atomic64_set(&hwc->period_left, hwc->sample_period); + local64_set(&hwc->period_left, hwc->sample_period); } return 0; -- cgit v1.2.2 From 25d3584797a39f57b69cd835722ac7c41113fb9a Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 16 Aug 2010 15:15:14 +0100 Subject: ARM: 6330/1: perf: reword comments relating to perf_event_do_pending This is purely a cosmetic change to the ARM perf backend because the current comments about the relationship between NMIs, interrupt context and perf_event_do_pending are misleading. This patch updates the comments so that they reflect what the code actually does (which is in line with other architectures). Acked-by: Jamie Iles Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/perf_event.h | 2 +- arch/arm/kernel/perf_event.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h index 48837e6d8887..b5799a3b7117 100644 --- a/arch/arm/include/asm/perf_event.h +++ b/arch/arm/include/asm/perf_event.h @@ -17,7 +17,7 @@ * counter interrupts are regular interrupts and not an NMI. This * means that when we receive the interrupt we can call * perf_event_do_pending() that handles all of the work with - * interrupts enabled. + * interrupts disabled. */ static inline void set_perf_event_pending(void) diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 417c392ddf1c..e2139256524e 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -1041,8 +1041,8 @@ armv6pmu_handle_irq(int irq_num, /* * Handle the pending perf events. * - * Note: this call *must* be run with interrupts enabled. For - * platforms that can have the PMU interrupts raised as a PMI, this + * Note: this call *must* be run with interrupts disabled. For + * platforms that can have the PMU interrupts raised as an NMI, this * will not work. */ perf_event_do_pending(); @@ -2017,8 +2017,8 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) /* * Handle the pending perf events. * - * Note: this call *must* be run with interrupts enabled. For - * platforms that can have the PMU interrupts raised as a PMI, this + * Note: this call *must* be run with interrupts disabled. For + * platforms that can have the PMU interrupts raised as an NMI, this * will not work. */ perf_event_do_pending(); -- cgit v1.2.2 From 418cf646c9999f2f7d216b1a693c2c575ab8094c Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Wed, 25 Aug 2010 20:49:01 +0100 Subject: ARM: 6343/1: wire up fanotify and prlimit64 syscalls on ARM The 2.6.36-rc kernel added three new system calls: fanotify_init, fanotify_mark, and prlimit64. This patch wires them up on ARM. The only non-trivial issue here is the u64 argument to sys_fanotify_mark(), but it is the 3rd argument and thus passed in r2/r3 in both kernel and user space, so it causes no problems. Tested with a 2.6.36-rc2 EABI kernel on an ixp4xx machine. Tested-by: Anand Gadiyar Signed-off-by: Mikael Pettersson Signed-off-by: Russell King --- arch/arm/include/asm/unistd.h | 3 +++ arch/arm/kernel/calls.S | 3 +++ 2 files changed, 6 insertions(+) (limited to 'arch') diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index d02cfb683487..c891eb76c0e3 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h @@ -393,6 +393,9 @@ #define __NR_perf_event_open (__NR_SYSCALL_BASE+364) #define __NR_recvmmsg (__NR_SYSCALL_BASE+365) #define __NR_accept4 (__NR_SYSCALL_BASE+366) +#define __NR_fanotify_init (__NR_SYSCALL_BASE+367) +#define __NR_fanotify_mark (__NR_SYSCALL_BASE+368) +#define __NR_prlimit64 (__NR_SYSCALL_BASE+369) /* * The following SWIs are ARM private. diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index afeb71fa72cb..5c26eccef998 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -376,6 +376,9 @@ CALL(sys_perf_event_open) /* 365 */ CALL(sys_recvmmsg) CALL(sys_accept4) + CALL(sys_fanotify_init) + CALL(sys_fanotify_mark) + CALL(sys_prlimit64) #ifndef syscalls_counted .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls #define syscalls_counted -- cgit v1.2.2 From 3e073367a57d41e506f20aebb98e308387ce3090 Mon Sep 17 00:00:00 2001 From: Michael Cree Date: Wed, 1 Sep 2010 11:25:17 -0400 Subject: alpha: Fix printk format errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiling alpha generic build get errors such as: arch/alpha/kernel/err_marvel.c: In function ‘marvel_print_err_cyc’: arch/alpha/kernel/err_marvel.c:119: error: format ‘%ld’ expects type ‘long int’, but argument 6 has type ‘u64’ Replaced a number of %ld format specifiers with %lld since u64 is unsigned long long. Signed-off-by: Michael Cree Signed-off-by: Matt Turner --- arch/alpha/kernel/err_marvel.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/err_marvel.c b/arch/alpha/kernel/err_marvel.c index 52a79dfc13c6..5c905aaaeccd 100644 --- a/arch/alpha/kernel/err_marvel.c +++ b/arch/alpha/kernel/err_marvel.c @@ -109,7 +109,7 @@ marvel_print_err_cyc(u64 err_cyc) #define IO7__ERR_CYC__CYCLE__M (0x7) printk("%s Packet In Error: %s\n" - "%s Error in %s, cycle %ld%s%s\n", + "%s Error in %s, cycle %lld%s%s\n", err_print_prefix, packet_desc[EXTRACT(err_cyc, IO7__ERR_CYC__PACKET)], err_print_prefix, @@ -313,7 +313,7 @@ marvel_print_po7_ugbge_sym(u64 ugbge_sym) } printk("%s Up Hose Garbage Symptom:\n" - "%s Source Port: %ld - Dest PID: %ld - OpCode: %s\n", + "%s Source Port: %lld - Dest PID: %lld - OpCode: %s\n", err_print_prefix, err_print_prefix, EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_SRC_PORT), @@ -552,7 +552,7 @@ marvel_print_pox_spl_cmplt(u64 spl_cmplt) #define IO7__POX_SPLCMPLT__REM_BYTE_COUNT__M (0xfff) printk("%s Split Completion Error:\n" - "%s Source (Bus:Dev:Func): %ld:%ld:%ld\n", + "%s Source (Bus:Dev:Func): %lld:%lld:%lld\n", err_print_prefix, err_print_prefix, EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__SOURCE_BUS), -- cgit v1.2.2 From 269f45c25028c75fe10e6d9be86e7202ab461fbc Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 1 Sep 2010 14:50:50 +0200 Subject: oprofile, x86: fix init_sysfs() function stub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The use of the return value of init_sysfs() with commit 10f0412 oprofile, x86: fix init_sysfs error handling discovered the following build error for !CONFIG_PM: .../linux/arch/x86/oprofile/nmi_int.c: In function ‘op_nmi_init’: .../linux/arch/x86/oprofile/nmi_int.c:784: error: expected expression before ‘do’ make[2]: *** [arch/x86/oprofile/nmi_int.o] Error 1 make[1]: *** [arch/x86/oprofile] Error 2 This patch fixes this. Reported-by: Ingo Molnar Cc: stable@kernel.org Signed-off-by: Robert Richter --- arch/x86/oprofile/nmi_int.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 73a41d3c6c09..cfe4faabb0f6 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -585,8 +585,10 @@ static void exit_sysfs(void) } #else -#define init_sysfs() do { } while (0) -#define exit_sysfs() do { } while (0) + +static inline int init_sysfs(void) { return 0; } +static inline void exit_sysfs(void) { } + #endif /* CONFIG_PM */ static int __init p4_init(char **cpu_type) -- cgit v1.2.2 From a9d8fb4d09ec8823045f44ebcde53a563fce2feb Mon Sep 17 00:00:00 2001 From: Erik Gilling Date: Fri, 27 Aug 2010 12:57:39 -0700 Subject: [ARM] tegra: Add ZRELADDR default for ARCH_TEGRA fixes the warning: .config:369:warning: symbol value '' invalid for ZRELADDR and the prompt for ZRELADDR on make Signed-off-by: Erik Gilling --- arch/arm/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a7ed21f0136a..16bc8eb4901c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1601,6 +1601,7 @@ config ZRELADDR ARCH_ORION5X ||\ ARCH_SPEAR3XX ||\ ARCH_SPEAR6XX ||\ + ARCH_TEGRA ||\ ARCH_U8500 ||\ ARCH_VERSATILE ||\ ARCH_W90X900 -- cgit v1.2.2 From 93f68f1ef787d97ab688f78a01f446e85bb9a496 Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Wed, 18 Aug 2010 09:58:46 +0000 Subject: powerpc/pseries: Correct rtas_data_buf locking in dlpar code The dlpar code can cause a deadlock to occur when making the RTAS configure-connector call. This occurs because we make kmalloc calls, which can block, while parsing the rtas_data_buf and holding the rtas_data_buf_lock. This an cause issues if someone else attempts to grab the rtas_data_bug_lock. This patch alleviates this issue by copying the contents of the rtas_data_buf to a local buffer before parsing. This allows us to only hold the rtas_data_buf_lock around the RTAS configure-connector calls. Signed-off-by: Nathan Fontenot Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/dlpar.c | 42 +++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 227c1c3d585e..72d8054fa739 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -129,20 +129,35 @@ struct device_node *dlpar_configure_connector(u32 drc_index) struct property *property; struct property *last_property = NULL; struct cc_workarea *ccwa; + char *data_buf; int cc_token; - int rc; + int rc = -1; cc_token = rtas_token("ibm,configure-connector"); if (cc_token == RTAS_UNKNOWN_SERVICE) return NULL; - spin_lock(&rtas_data_buf_lock); - ccwa = (struct cc_workarea *)&rtas_data_buf[0]; + data_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL); + if (!data_buf) + return NULL; + + ccwa = (struct cc_workarea *)&data_buf[0]; ccwa->drc_index = drc_index; ccwa->zero = 0; - rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL); - while (rc) { + do { + /* Since we release the rtas_data_buf lock between configure + * connector calls we want to re-populate the rtas_data_buffer + * with the contents of the previous call. + */ + spin_lock(&rtas_data_buf_lock); + + memcpy(rtas_data_buf, data_buf, RTAS_DATA_BUF_SIZE); + rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL); + memcpy(data_buf, rtas_data_buf, RTAS_DATA_BUF_SIZE); + + spin_unlock(&rtas_data_buf_lock); + switch (rc) { case NEXT_SIBLING: dn = dlpar_parse_cc_node(ccwa); @@ -197,18 +212,19 @@ struct device_node *dlpar_configure_connector(u32 drc_index) "returned from configure-connector\n", rc); goto cc_error; } + } while (rc); - rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL); +cc_error: + kfree(data_buf); + + if (rc) { + if (first_dn) + dlpar_free_cc_nodes(first_dn); + + return NULL; } - spin_unlock(&rtas_data_buf_lock); return first_dn; - -cc_error: - if (first_dn) - dlpar_free_cc_nodes(first_dn); - spin_unlock(&rtas_data_buf_lock); - return NULL; } static struct device_node *derive_parent(const char *path) -- cgit v1.2.2 From 09bfafac3e237415cc4b6adde49f9f28b3a42659 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 10 Aug 2010 19:32:37 +0100 Subject: ARM: 6314/1: ftrace: allow build without frame pointers on ARM With a new enough GCC, ARM function tracing can be supported without the need for frame pointers. This is essential for Thumb-2 support, since frame pointers aren't available then. Acked-by: Catalin Marinas Acked-by: Steven Rostedt Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/Kconfig.debug | 5 +++++ arch/arm/kernel/armksyms.c | 2 ++ arch/arm/kernel/entry-common.S | 14 ++++++++++++++ 3 files changed, 21 insertions(+) (limited to 'arch') diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 91344af75f39..4dbce538fec4 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -27,6 +27,11 @@ config ARM_UNWIND the performance is not affected. Currently, this feature only works with EABI compilers. If unsure say Y. +config OLD_MCOUNT + bool + depends on FUNCTION_TRACER && FRAME_POINTER + default y + config DEBUG_USER bool "Verbose user fault messages" help diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 8214bfebfaca..e5e1e5387678 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -165,6 +165,8 @@ EXPORT_SYMBOL(_find_next_bit_be); #endif #ifdef CONFIG_FUNCTION_TRACER +#ifdef CONFIG_OLD_MCOUNT EXPORT_SYMBOL(mcount); +#endif EXPORT_SYMBOL(__gnu_mcount_nc); #endif diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index f05a35a59694..6805a7216bf8 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -128,6 +128,13 @@ ENDPROC(ret_from_fork) * allows it to be clobbered in subroutines and doesn't use it to hold * parameters.) */ + +#ifndef CONFIG_OLD_MCOUNT +#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) +#error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0. +#endif +#endif + #ifdef CONFIG_DYNAMIC_FTRACE ENTRY(mcount) stmdb sp!, {r0-r3, lr} @@ -173,6 +180,12 @@ gnu_trace: ldmia sp!, {r0-r3, ip, lr} mov pc, ip +#ifdef CONFIG_OLD_MCOUNT +/* + * This is under an ifdef in order to force link-time errors for people trying + * to build with !FRAME_POINTER with a GCC which doesn't use the new-style + * mcount. + */ ENTRY(mcount) stmdb sp!, {r0-r3, lr} ldr r0, =ftrace_trace_function @@ -191,6 +204,7 @@ trace: mov pc, r2 ldr lr, [fp, #-4] @ restore lr ldmia sp!, {r0-r3, pc} +#endif #endif /* CONFIG_DYNAMIC_FTRACE */ -- cgit v1.2.2 From 72fa62fa5dff0e2e06491dd99c429adb137f299b Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 10 Aug 2010 19:33:52 +0100 Subject: ARM: 6315/1: ftrace: add ENDPROC annotations When building as Thumb-2, the ".type foo, %function" annotation in ENDPROC seems to be required in order for the assembly routines to be recognized as Thumb-2 code. If the ENDPROC annotations are not present, calls to these routines are generated as BLX instead of BL. Acked-by: Catalin Marinas Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/kernel/entry-common.S | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 6805a7216bf8..c7a8c208a45c 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -146,6 +146,7 @@ mcount_call: bl ftrace_stub ldr lr, [fp, #-4] @ restore lr ldmia sp!, {r0-r3, pc} +ENDPROC(mcount) ENTRY(ftrace_caller) stmdb sp!, {r0-r3, lr} @@ -158,6 +159,7 @@ ftrace_call: bl ftrace_stub ldr lr, [fp, #-4] @ restore lr ldmia sp!, {r0-r3, pc} +ENDPROC(ftrace_caller) #else @@ -179,6 +181,7 @@ gnu_trace: mov pc, r2 ldmia sp!, {r0-r3, ip, lr} mov pc, ip +ENDPROC(__gnu_mcount_nc) #ifdef CONFIG_OLD_MCOUNT /* @@ -204,13 +207,14 @@ trace: mov pc, r2 ldr lr, [fp, #-4] @ restore lr ldmia sp!, {r0-r3, pc} +ENDPROC(mcount) #endif #endif /* CONFIG_DYNAMIC_FTRACE */ - .globl ftrace_stub -ftrace_stub: +ENTRY(ftrace_stub) mov pc, lr +ENDPROC(ftrace_stub) #endif /* CONFIG_FUNCTION_TRACER */ -- cgit v1.2.2 From a3ba87a614992500cf2c47e6f788e74a971ce91f Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 10 Aug 2010 19:37:21 +0100 Subject: ARM: 6316/1: ftrace: add Thumb-2 support Fix the mcount routines to build and run on a kernel built with the Thumb-2 instruction set by correcting the following errors using the fixes suggested by Catalin Marinas: - Problem: The following assembler errors appear at the "adr r0, ftrace_stub" instruction: entry-common.S: Assembler messages: entry-common.S:179: Error: invalid immediate for address calculation (value = 0x00000004) Fix: The errors don't occur with a non-global symbol, so use one. - Problem: The "mov lr, pc" does not set the lsb when storing the pc in lr. The called function returns with "bx lr", and the mode changes to ARM. Fix: Add a label on the return address and use "adr lr, BSYM(label)". We don't modify the old mcount because it won't be built when using Thumb-2. Acked-by: Catalin Marinas Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/kernel/entry-common.S | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index c7a8c208a45c..f5e75de0203e 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -167,7 +167,7 @@ ENTRY(__gnu_mcount_nc) stmdb sp!, {r0-r3, lr} ldr r0, =ftrace_trace_function ldr r2, [r0] - adr r0, ftrace_stub + adr r0, .Lftrace_stub cmp r0, r2 bne gnu_trace ldmia sp!, {r0-r3, ip, lr} @@ -177,8 +177,9 @@ gnu_trace: ldr r1, [sp, #20] @ lr of instrumented routine mov r0, lr sub r0, r0, #MCOUNT_INSN_SIZE - mov lr, pc + adr lr, BSYM(1f) mov pc, r2 +1: ldmia sp!, {r0-r3, ip, lr} mov pc, ip ENDPROC(__gnu_mcount_nc) @@ -213,6 +214,7 @@ ENDPROC(mcount) #endif /* CONFIG_DYNAMIC_FTRACE */ ENTRY(ftrace_stub) +.Lftrace_stub: mov pc, lr ENDPROC(ftrace_stub) -- cgit v1.2.2 From 3b6c223b1b97ad60bbb0f4efda57d649414ac2a2 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 10 Aug 2010 19:43:28 +0100 Subject: ARM: 6318/1: ftrace: fix and update dynamic ftrace This adds mcount recording and updates dynamic ftrace for ARM to work with the new ftrace dyamic tracing implementation. It also adds support for the mcount format used by newer ARM compilers. With dynamic tracing, mcount() is implemented as a nop. Callsites are patched on startup with nops, and dynamically patched to call to the ftrace_caller() routine as needed. Acked-by: Steven Rostedt [recordmcount.pl change] Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/include/asm/ftrace.h | 19 ++++- arch/arm/kernel/entry-common.S | 37 +++++++--- arch/arm/kernel/ftrace.c | 155 ++++++++++++++++++++++++++++------------- 3 files changed, 153 insertions(+), 58 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h index 103f7ee97313..4a56a2ee067c 100644 --- a/arch/arm/include/asm/ftrace.h +++ b/arch/arm/include/asm/ftrace.h @@ -2,12 +2,29 @@ #define _ASM_ARM_FTRACE #ifdef CONFIG_FUNCTION_TRACER -#define MCOUNT_ADDR ((long)(mcount)) +#define MCOUNT_ADDR ((unsigned long)(__gnu_mcount_nc)) #define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */ #ifndef __ASSEMBLY__ extern void mcount(void); extern void __gnu_mcount_nc(void); + +#ifdef CONFIG_DYNAMIC_FTRACE +struct dyn_arch_ftrace { +#ifdef CONFIG_OLD_MCOUNT + bool old_mcount; +#endif +}; + +static inline unsigned long ftrace_call_adjust(unsigned long addr) +{ + return addr; +} + +extern void ftrace_caller_old(void); +extern void ftrace_call_old(void); +#endif + #endif #endif diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index f5e75de0203e..e02790f28879 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -127,6 +127,10 @@ ENDPROC(ret_from_fork) * clobber the ip register. This is OK because the ARM calling convention * allows it to be clobbered in subroutines and doesn't use it to hold * parameters.) + * + * When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0" + * for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see + * arch/arm/kernel/ftrace.c). */ #ifndef CONFIG_OLD_MCOUNT @@ -136,30 +140,45 @@ ENDPROC(ret_from_fork) #endif #ifdef CONFIG_DYNAMIC_FTRACE -ENTRY(mcount) +ENTRY(__gnu_mcount_nc) + mov ip, lr + ldmia sp!, {lr} + mov pc, ip +ENDPROC(__gnu_mcount_nc) + +ENTRY(ftrace_caller) stmdb sp!, {r0-r3, lr} mov r0, lr sub r0, r0, #MCOUNT_INSN_SIZE + ldr r1, [sp, #20] - .globl mcount_call -mcount_call: + .global ftrace_call +ftrace_call: bl ftrace_stub - ldr lr, [fp, #-4] @ restore lr - ldmia sp!, {r0-r3, pc} + ldmia sp!, {r0-r3, ip, lr} + mov pc, ip +ENDPROC(ftrace_caller) + +#ifdef CONFIG_OLD_MCOUNT +ENTRY(mcount) + stmdb sp!, {lr} + ldr lr, [fp, #-4] + ldmia sp!, {pc} ENDPROC(mcount) -ENTRY(ftrace_caller) +ENTRY(ftrace_caller_old) stmdb sp!, {r0-r3, lr} ldr r1, [fp, #-4] mov r0, lr sub r0, r0, #MCOUNT_INSN_SIZE - .globl ftrace_call -ftrace_call: + .globl ftrace_call_old +ftrace_call_old: bl ftrace_stub ldr lr, [fp, #-4] @ restore lr ldmia sp!, {r0-r3, pc} -ENDPROC(ftrace_caller) +ENDPROC(ftrace_caller_old) +#endif #else diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index 0298286ad4ad..f09014cfbf2c 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c @@ -2,102 +2,161 @@ * Dynamic function tracing support. * * Copyright (C) 2008 Abhishek Sagar + * Copyright (C) 2010 Rabin Vincent * * For licencing details, see COPYING. * * Defines low-level handling of mcount calls when the kernel * is compiled with the -pg flag. When using dynamic ftrace, the - * mcount call-sites get patched lazily with NOP till they are - * enabled. All code mutation routines here take effect atomically. + * mcount call-sites get patched with NOP till they are enabled. + * All code mutation routines here are called under stop_machine(). */ #include +#include #include #include -#define PC_OFFSET 8 -#define BL_OPCODE 0xeb000000 -#define BL_OFFSET_MASK 0x00ffffff +#define NOP 0xe8bd4000 /* pop {lr} */ -static unsigned long bl_insn; -static const unsigned long NOP = 0xe1a00000; /* mov r0, r0 */ +#ifdef CONFIG_OLD_MCOUNT +#define OLD_MCOUNT_ADDR ((unsigned long) mcount) +#define OLD_FTRACE_ADDR ((unsigned long) ftrace_caller_old) -unsigned char *ftrace_nop_replace(void) +#define OLD_NOP 0xe1a00000 /* mov r0, r0 */ + +static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec) +{ + return rec->arch.old_mcount ? OLD_NOP : NOP; +} + +static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr) +{ + if (!rec->arch.old_mcount) + return addr; + + if (addr == MCOUNT_ADDR) + addr = OLD_MCOUNT_ADDR; + else if (addr == FTRACE_ADDR) + addr = OLD_FTRACE_ADDR; + + return addr; +} +#else +static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec) +{ + return NOP; +} + +static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr) { - return (char *)&NOP; + return addr; } +#endif /* construct a branch (BL) instruction to addr */ -unsigned char *ftrace_call_replace(unsigned long pc, unsigned long addr) +static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr) { long offset; - offset = (long)addr - (long)(pc + PC_OFFSET); + offset = (long)addr - (long)(pc + 8); if (unlikely(offset < -33554432 || offset > 33554428)) { /* Can't generate branches that far (from ARM ARM). Ftrace * doesn't generate branches outside of kernel text. */ WARN_ON_ONCE(1); - return NULL; + return 0; } - offset = (offset >> 2) & BL_OFFSET_MASK; - bl_insn = BL_OPCODE | offset; - return (unsigned char *)&bl_insn; -} -int ftrace_modify_code(unsigned long pc, unsigned char *old_code, - unsigned char *new_code) -{ - unsigned long err = 0, replaced = 0, old, new; + offset = (offset >> 2) & 0x00ffffff; - old = *(unsigned long *)old_code; - new = *(unsigned long *)new_code; + return 0xeb000000 | offset; +} - __asm__ __volatile__ ( - "1: ldr %1, [%2] \n" - " cmp %1, %4 \n" - "2: streq %3, [%2] \n" - " cmpne %1, %3 \n" - " movne %0, #2 \n" - "3:\n" +static int ftrace_modify_code(unsigned long pc, unsigned long old, + unsigned long new) +{ + unsigned long replaced; - ".pushsection .fixup, \"ax\"\n" - "4: mov %0, #1 \n" - " b 3b \n" - ".popsection\n" + if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE)) + return -EFAULT; - ".pushsection __ex_table, \"a\"\n" - " .long 1b, 4b \n" - " .long 2b, 4b \n" - ".popsection\n" + if (replaced != old) + return -EINVAL; - : "=r"(err), "=r"(replaced) - : "r"(pc), "r"(new), "r"(old), "0"(err), "1"(replaced) - : "memory"); + if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE)) + return -EPERM; - if (!err && (replaced == old)) - flush_icache_range(pc, pc + MCOUNT_INSN_SIZE); + flush_icache_range(pc, pc + MCOUNT_INSN_SIZE); - return err; + return 0; } int ftrace_update_ftrace_func(ftrace_func_t func) { - int ret; unsigned long pc, old; - unsigned char *new; + unsigned long new; + int ret; pc = (unsigned long)&ftrace_call; memcpy(&old, &ftrace_call, MCOUNT_INSN_SIZE); new = ftrace_call_replace(pc, (unsigned long)func); - ret = ftrace_modify_code(pc, (unsigned char *)&old, new); + + ret = ftrace_modify_code(pc, old, new); + +#ifdef CONFIG_OLD_MCOUNT + if (!ret) { + pc = (unsigned long)&ftrace_call_old; + memcpy(&old, &ftrace_call_old, MCOUNT_INSN_SIZE); + new = ftrace_call_replace(pc, (unsigned long)func); + + ret = ftrace_modify_code(pc, old, new); + } +#endif + + return ret; +} + +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) +{ + unsigned long new, old; + unsigned long ip = rec->ip; + + old = ftrace_nop_replace(rec); + new = ftrace_call_replace(ip, adjust_address(rec, addr)); + + return ftrace_modify_code(rec->ip, old, new); +} + +int ftrace_make_nop(struct module *mod, + struct dyn_ftrace *rec, unsigned long addr) +{ + unsigned long ip = rec->ip; + unsigned long old; + unsigned long new; + int ret; + + old = ftrace_call_replace(ip, adjust_address(rec, addr)); + new = ftrace_nop_replace(rec); + ret = ftrace_modify_code(ip, old, new); + +#ifdef CONFIG_OLD_MCOUNT + if (ret == -EINVAL && addr == MCOUNT_ADDR) { + rec->arch.old_mcount = true; + + old = ftrace_call_replace(ip, adjust_address(rec, addr)); + new = ftrace_nop_replace(rec); + ret = ftrace_modify_code(ip, old, new); + } +#endif + return ret; } -/* run from ftrace_init with irqs disabled */ int __init ftrace_dyn_arch_init(void *data) { - ftrace_mcount_set(data); + *(unsigned long *)data = 0; + return 0; } -- cgit v1.2.2 From 72dc43a9eb123d2742bd413c80dbeab0c588f622 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 10 Aug 2010 19:52:35 +0100 Subject: ARM: 6319/1: ftrace: add Thumb-2 support to dynamic ftrace Handle the different nop and call instructions for Thumb-2. Also, we need to adjust the recorded mcount_loc addresses because they have the lsb set. Cc: Catalin Marinas Acked-by: Steven Rostedt [recordmcount.pl change] Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/include/asm/ftrace.h | 3 ++- arch/arm/kernel/ftrace.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h index 4a56a2ee067c..f89515adac60 100644 --- a/arch/arm/include/asm/ftrace.h +++ b/arch/arm/include/asm/ftrace.h @@ -18,7 +18,8 @@ struct dyn_arch_ftrace { static inline unsigned long ftrace_call_adjust(unsigned long addr) { - return addr; + /* With Thumb-2, the recorded addresses have the lsb set */ + return addr & ~1; } extern void ftrace_caller_old(void); diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index f09014cfbf2c..971ac8c36ea7 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c @@ -18,7 +18,11 @@ #include #include +#ifdef CONFIG_THUMB2_KERNEL +#define NOP 0xeb04f85d /* pop.w {lr} */ +#else #define NOP 0xe8bd4000 /* pop {lr} */ +#endif #ifdef CONFIG_OLD_MCOUNT #define OLD_MCOUNT_ADDR ((unsigned long) mcount) @@ -56,6 +60,34 @@ static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr) #endif /* construct a branch (BL) instruction to addr */ +#ifdef CONFIG_THUMB2_KERNEL +static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr) +{ + unsigned long s, j1, j2, i1, i2, imm10, imm11; + unsigned long first, second; + long offset; + + offset = (long)addr - (long)(pc + 4); + if (offset < -16777216 || offset > 16777214) { + WARN_ON_ONCE(1); + return 0; + } + + s = (offset >> 24) & 0x1; + i1 = (offset >> 23) & 0x1; + i2 = (offset >> 22) & 0x1; + imm10 = (offset >> 12) & 0x3ff; + imm11 = (offset >> 1) & 0x7ff; + + j1 = (!i1) ^ s; + j2 = (!i2) ^ s; + + first = 0xf000 | (s << 10) | imm10; + second = 0xd000 | (j1 << 13) | (j2 << 11) | imm11; + + return (second << 16) | first; +} +#else static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr) { long offset; @@ -73,6 +105,7 @@ static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr) return 0xeb000000 | offset; } +#endif static int ftrace_modify_code(unsigned long pc, unsigned long old, unsigned long new) -- cgit v1.2.2 From 80be7a7f642719bf99fc49692fc77d6333f51a73 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 10 Aug 2010 19:58:17 +0100 Subject: ARM: 6320/1: ftrace: enable dynamic ftrace Dynamic ftrace for ARM has been disabled since 07c4cc1cdaa08f ("ftrace: disable dynamic ftrace for all archs that use daemon"). Now that the code has been updated, re-enable it. Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/Kconfig | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 92951103255a..8d09765ce564 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -19,6 +19,8 @@ config ARM select HAVE_KPROBES if (!XIP_KERNEL) select HAVE_KRETPROBES if (HAVE_KPROBES) select HAVE_FUNCTION_TRACER if (!XIP_KERNEL) + select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL) + select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) select HAVE_GENERIC_DMA_COHERENT select HAVE_KERNEL_GZIP select HAVE_KERNEL_LZO -- cgit v1.2.2 From 5793432628ad76f93ae4d31c23fb1c26e3d8b525 Mon Sep 17 00:00:00 2001 From: Phil Carmody Date: Thu, 19 Aug 2010 15:10:24 +0100 Subject: ARM: 6338/1: module - simplify code with temporaries Less to read. Signed-off-by: Phil Carmody Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/kernel/module.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 6b4605893f1e..1dae0468677a 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -71,17 +71,19 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum; for (s = sechdrs; s < sechdrs_end; s++) { - if (strcmp(".ARM.exidx.init.text", secstrings + s->sh_name) == 0) + char const *secname = secstrings + s->sh_name; + + if (strcmp(".ARM.exidx.init.text", secname) == 0) mod->arch.unw_sec_init = s; - else if (strcmp(".ARM.exidx.devinit.text", secstrings + s->sh_name) == 0) + else if (strcmp(".ARM.exidx.devinit.text", secname) == 0) mod->arch.unw_sec_devinit = s; - else if (strcmp(".ARM.exidx", secstrings + s->sh_name) == 0) + else if (strcmp(".ARM.exidx", secname) == 0) mod->arch.unw_sec_core = s; - else if (strcmp(".init.text", secstrings + s->sh_name) == 0) + else if (strcmp(".init.text", secname) == 0) mod->arch.sec_init_text = s; - else if (strcmp(".devinit.text", secstrings + s->sh_name) == 0) + else if (strcmp(".devinit.text", secname) == 0) mod->arch.sec_devinit_text = s; - else if (strcmp(".text", secstrings + s->sh_name) == 0) + else if (strcmp(".text", secname) == 0) mod->arch.sec_core_text = s; } #endif -- cgit v1.2.2 From e5f7772eec3ec342ecfe686ab8330ef538af134b Mon Sep 17 00:00:00 2001 From: Phil Carmody Date: Thu, 19 Aug 2010 15:16:37 +0100 Subject: ARM: 6339/1: module - simplify unwind table handling The various sections are all dealt with similarly, so factor out that common behaviour. (Incorporating Peter Huewe's fix.) Cc: Peter Huewe Signed-off-by: Phil Carmody Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/include/asm/module.h | 29 ++++++++++++++++----------- arch/arm/kernel/module.c | 46 ++++++++++++++++++------------------------- 2 files changed, 36 insertions(+), 39 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h index e4dfa69abb68..6dcff0f7f8d7 100644 --- a/arch/arm/include/asm/module.h +++ b/arch/arm/include/asm/module.h @@ -7,20 +7,25 @@ struct unwind_table; -struct mod_arch_specific -{ #ifdef CONFIG_ARM_UNWIND - Elf_Shdr *unw_sec_init; - Elf_Shdr *unw_sec_devinit; - Elf_Shdr *unw_sec_core; - Elf_Shdr *sec_init_text; - Elf_Shdr *sec_devinit_text; - Elf_Shdr *sec_core_text; - struct unwind_table *unwind_init; - struct unwind_table *unwind_devinit; - struct unwind_table *unwind_core; -#endif +struct arm_unwind_mapping { + Elf_Shdr *unw_sec; + Elf_Shdr *sec_text; + struct unwind_table *unwind; +}; +enum { + ARM_SEC_INIT, + ARM_SEC_DEVINIT, + ARM_SEC_CORE, + ARM_SEC_MAX, +}; +struct mod_arch_specific { + struct arm_unwind_mapping map[ARM_SEC_MAX]; }; +#else +struct mod_arch_specific { +}; +#endif /* * Include the ARM architecture version. diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 1dae0468677a..0aa622e84b24 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -69,22 +69,23 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, { #ifdef CONFIG_ARM_UNWIND Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum; + struct arm_unwind_mapping *maps = mod->arch.map; for (s = sechdrs; s < sechdrs_end; s++) { char const *secname = secstrings + s->sh_name; if (strcmp(".ARM.exidx.init.text", secname) == 0) - mod->arch.unw_sec_init = s; + maps[ARM_SEC_INIT].unw_sec = s; else if (strcmp(".ARM.exidx.devinit.text", secname) == 0) - mod->arch.unw_sec_devinit = s; + maps[ARM_SEC_DEVINIT].unw_sec = s; else if (strcmp(".ARM.exidx", secname) == 0) - mod->arch.unw_sec_core = s; + maps[ARM_SEC_CORE].unw_sec = s; else if (strcmp(".init.text", secname) == 0) - mod->arch.sec_init_text = s; + maps[ARM_SEC_INIT].sec_text = s; else if (strcmp(".devinit.text", secname) == 0) - mod->arch.sec_devinit_text = s; + maps[ARM_SEC_DEVINIT].sec_text = s; else if (strcmp(".text", secname) == 0) - mod->arch.sec_core_text = s; + maps[ARM_SEC_CORE].sec_text = s; } #endif return 0; @@ -294,31 +295,22 @@ apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, #ifdef CONFIG_ARM_UNWIND static void register_unwind_tables(struct module *mod) { - if (mod->arch.unw_sec_init && mod->arch.sec_init_text) - mod->arch.unwind_init = - unwind_table_add(mod->arch.unw_sec_init->sh_addr, - mod->arch.unw_sec_init->sh_size, - mod->arch.sec_init_text->sh_addr, - mod->arch.sec_init_text->sh_size); - if (mod->arch.unw_sec_devinit && mod->arch.sec_devinit_text) - mod->arch.unwind_devinit = - unwind_table_add(mod->arch.unw_sec_devinit->sh_addr, - mod->arch.unw_sec_devinit->sh_size, - mod->arch.sec_devinit_text->sh_addr, - mod->arch.sec_devinit_text->sh_size); - if (mod->arch.unw_sec_core && mod->arch.sec_core_text) - mod->arch.unwind_core = - unwind_table_add(mod->arch.unw_sec_core->sh_addr, - mod->arch.unw_sec_core->sh_size, - mod->arch.sec_core_text->sh_addr, - mod->arch.sec_core_text->sh_size); + int i; + for (i = 0; i < ARM_SEC_MAX; ++i) { + struct arm_unwind_mapping *map = &mod->arch.map[i]; + if (map->unw_sec && map->sec_text) + map->unwind = unwind_table_add(map->unw_sec->sh_addr, + map->unw_sec->sh_size, + map->sec_text->sh_addr, + map->sec_text->sh_size); + } } static void unregister_unwind_tables(struct module *mod) { - unwind_table_del(mod->arch.unwind_init); - unwind_table_del(mod->arch.unwind_devinit); - unwind_table_del(mod->arch.unwind_core); + int i = ARM_SEC_MAX; + while (--i >= 0) + unwind_table_del(mod->arch.map[i].unwind); } #else static inline void register_unwind_tables(struct module *mod) { } -- cgit v1.2.2 From 09e56a2d076c2afb2a1932ae4283e10ef2d26ef3 Mon Sep 17 00:00:00 2001 From: Phil Carmody Date: Thu, 19 Aug 2010 15:19:04 +0100 Subject: ARM: 6340/1: module - additional unwind tables for exit/devexit sections Without these, exit functions cannot be stack-traced, so to speak. This implies that module unloads that perform allocations (don't laugh) will cause noisy warnings on the console when kmemleak is enabled, as it presumes that all code's call chains are traceable. Similarly, BUGs and WARN_ONs will give additional console spam. Signed-off-by: Phil Carmody Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/include/asm/module.h | 2 ++ arch/arm/kernel/module.c | 8 ++++++++ 2 files changed, 10 insertions(+) (limited to 'arch') diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h index 6dcff0f7f8d7..cbb0bc295d2b 100644 --- a/arch/arm/include/asm/module.h +++ b/arch/arm/include/asm/module.h @@ -17,6 +17,8 @@ enum { ARM_SEC_INIT, ARM_SEC_DEVINIT, ARM_SEC_CORE, + ARM_SEC_EXIT, + ARM_SEC_DEVEXIT, ARM_SEC_MAX, }; struct mod_arch_specific { diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 0aa622e84b24..d9bd786ce23d 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -80,12 +80,20 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, maps[ARM_SEC_DEVINIT].unw_sec = s; else if (strcmp(".ARM.exidx", secname) == 0) maps[ARM_SEC_CORE].unw_sec = s; + else if (strcmp(".ARM.exidx.exit.text", secname) == 0) + maps[ARM_SEC_EXIT].unw_sec = s; + else if (strcmp(".ARM.exidx.devexit.text", secname) == 0) + maps[ARM_SEC_DEVEXIT].unw_sec = s; else if (strcmp(".init.text", secname) == 0) maps[ARM_SEC_INIT].sec_text = s; else if (strcmp(".devinit.text", secname) == 0) maps[ARM_SEC_DEVINIT].sec_text = s; else if (strcmp(".text", secname) == 0) maps[ARM_SEC_CORE].sec_text = s; + else if (strcmp(".exit.text", secname) == 0) + maps[ARM_SEC_EXIT].sec_text = s; + else if (strcmp(".devexit.text", secname) == 0) + maps[ARM_SEC_DEVEXIT].sec_text = s; } #endif return 0; -- cgit v1.2.2 From 5333a3de3cdd739ec4f6d501f5f6d09bab7ff919 Mon Sep 17 00:00:00 2001 From: Phil Carmody Date: Thu, 19 Aug 2010 15:20:37 +0100 Subject: ARM: 6341/1: unwind - optimise linked-list searches for modules With several sections per module, and dozens of modules, the searches down the linked list of sections would dominate the lookup time, dwarfing any savings from the binary search within the section. A simple move-to-front optimisation exploits the commonality of the code paths taken, and in simple real-world tests reduces the number of steps in the search to barely more than 1. Signed-off-by: Phil Carmody Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/kernel/unwind.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index dd81a918c106..2a161765f6d5 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -146,6 +146,8 @@ static struct unwind_idx *unwind_find_idx(unsigned long addr) addr < table->end_addr) { idx = search_index(addr, table->start, table->stop - 1); + /* Move-to-front to exploit common traces */ + list_move(&table->list, &unwind_tables); break; } } -- cgit v1.2.2 From 026b5ca3b65f878019a8eb0c7a702cd5c20a4104 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Wed, 1 Sep 2010 14:33:29 +0100 Subject: ARM: 6344/1: Mark CPU_32v6K as depended on CPU_V7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPU_32v6K is selected by CPU_V7 but it only depends on CPU_V6. Signed-off-by: Catalin Marinas Acked-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/mm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 33c3f570aaa0..a0a2928ae4dd 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -398,7 +398,7 @@ config CPU_V6 # ARMv6k config CPU_32v6K bool "Support ARM V6K processor extensions" if !SMP - depends on CPU_V6 + depends on CPU_V6 || CPU_V7 default y if SMP && !(ARCH_MX3 || ARCH_OMAP2) help Say Y here if your ARMv6 processor supports the 'K' extension. -- cgit v1.2.2 From f946738ca882c365a963043de471f45e91ab0a95 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 19 Aug 2010 10:27:49 +0100 Subject: ARM: 6331/1: ux500 cpu/SoC version macros v2 This patch adds support for checking if the digital baseband (DB) System-on-Chip (aka "cpu) ASIC hardware version is 1.0, 1.1 or 2.0. We print the result in the bootlog, the functions are then used for runtime decisions based on hardware version. Signed-off-by: Mattias Wallin Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-ux500/cpu-db8500.c | 82 ++++++++++++++++++++++++++ arch/arm/mach-ux500/include/mach/db8500-regs.h | 2 - arch/arm/mach-ux500/include/mach/hardware.h | 23 +++++++- arch/arm/mach-ux500/include/mach/setup.h | 7 +++ 4 files changed, 110 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index f21c444edd99..4acab7544b3c 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -38,10 +38,12 @@ static struct platform_device *platform_devs[] __initdata = { /* minimum static i/o mapping required to boot U8500 platforms */ static struct map_desc u8500_io_desc[] __initdata = { __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), + __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K), + __MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M), }; static struct map_desc u8500ed_io_desc[] __initdata = { @@ -53,6 +55,69 @@ static struct map_desc u8500v1_io_desc[] __initdata = { __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), }; +/* + * Functions to differentiate between later ASICs + * We look into the end of the ROM to locate the hardcoded ASIC ID. + * This is only needed to differentiate between minor revisions and + * process variants of an ASIC, the major revisions are encoded in + * the cpuid. + */ +#define U8500_ASIC_ID_LOC_ED_V1 (U8500_BOOT_ROM_BASE + 0x1FFF4) +#define U8500_ASIC_ID_LOC_V2 (U8500_BOOT_ROM_BASE + 0x1DBF4) +#define U8500_ASIC_REV_ED 0x01 +#define U8500_ASIC_REV_V10 0xA0 +#define U8500_ASIC_REV_V11 0xA1 +#define U8500_ASIC_REV_V20 0xB0 + +/** + * struct db8500_asic_id - fields of the ASIC ID + * @process: the manufacturing process, 0x40 is 40 nm + * 0x00 is "standard" + * @partnumber: hithereto 0x8500 for DB8500 + * @revision: version code in the series + * This field definion is not formally defined but makes + * sense. + */ +struct db8500_asic_id { + u8 process; + u16 partnumber; + u8 revision; +}; + +/* This isn't going to change at runtime */ +static struct db8500_asic_id db8500_id; + +static void __init get_db8500_asic_id(void) +{ + u32 asicid; + + if (cpu_is_u8500v1() || cpu_is_u8500ed()) + asicid = readl(__io_address(U8500_ASIC_ID_LOC_ED_V1)); + else if (cpu_is_u8500v2()) + asicid = readl(__io_address(U8500_ASIC_ID_LOC_V2)); + else + BUG(); + + db8500_id.process = (asicid >> 24); + db8500_id.partnumber = (asicid >> 16) & 0xFFFFU; + db8500_id.revision = asicid & 0xFFU; +} + +bool cpu_is_u8500v10(void) +{ + return (db8500_id.revision == U8500_ASIC_REV_V10); +} + +bool cpu_is_u8500v11(void) +{ + return (db8500_id.revision == U8500_ASIC_REV_V11); +} + +bool cpu_is_u8500v20(void) +{ + return (db8500_id.revision == U8500_ASIC_REV_V20); +} + void __init u8500_map_io(void) { ux500_map_io(); @@ -63,6 +128,9 @@ void __init u8500_map_io(void) iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc)); else iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc)); + + /* Read out the ASIC ID as early as we can */ + get_db8500_asic_id(); } /* @@ -70,6 +138,20 @@ void __init u8500_map_io(void) */ void __init u8500_init_devices(void) { + /* Display some ASIC boilerplate */ + pr_info("DB8500: process: %02x, revision ID: 0x%02x\n", + db8500_id.process, db8500_id.revision); + if (cpu_is_u8500ed()) + pr_info("DB8500: Early Drop (ED)\n"); + else if (cpu_is_u8500v10()) + pr_info("DB8500: version 1.0\n"); + else if (cpu_is_u8500v11()) + pr_info("DB8500: version 1.1\n"); + else if (cpu_is_u8500v20()) + pr_info("DB8500: version 2.0\n"); + else + pr_warning("ASIC: UNKNOWN SILICON VERSION!\n"); + ux500_init_devices(); if (cpu_is_u8500ed()) diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h index f000218210c9..f07d0986409d 100644 --- a/arch/arm/mach-ux500/include/mach/db8500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h @@ -30,8 +30,6 @@ #define U8500_ICN_BASE 0x81000000 #define U8500_BOOT_ROM_BASE 0x90000000 -/* ASIC ID is at 0xff4 offset within this region */ -#define U8500_ASIC_ID_BASE 0x9001F000 #define U8500_PER6_BASE 0xa03c0000 #define U8500_PER5_BASE 0xa03e0000 diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h index 8656379a8309..32e883a8f2a2 100644 --- a/arch/arm/mach-ux500/include/mach/hardware.h +++ b/arch/arm/mach-ux500/include/mach/hardware.h @@ -104,16 +104,35 @@ static inline bool cpu_is_u8500(void) #endif } +#define CPUID_DB8500ED 0x410fc090 +#define CPUID_DB8500V1 0x411fc091 +#define CPUID_DB8500V2 0x412fc091 + static inline bool cpu_is_u8500ed(void) { - return cpu_is_u8500() && (read_cpuid_id() & 15) == 0; + return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500ED); } static inline bool cpu_is_u8500v1(void) { - return cpu_is_u8500() && (read_cpuid_id() & 15) == 1; + return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V1); +} + +static inline bool cpu_is_u8500v2(void) +{ + return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V2); } +#ifdef CONFIG_UX500_SOC_DB8500 +bool cpu_is_u8500v10(void); +bool cpu_is_u8500v11(void); +bool cpu_is_u8500v20(void); +#else +static inline bool cpu_is_u8500v10(void) { return false; } +static inline bool cpu_is_u8500v11(void) { return false; } +static inline bool cpu_is_u8500v20(void) { return false; } +#endif + static inline bool cpu_is_u5500(void) { #ifdef CONFIG_UX500_SOC_DB5500 diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index e978dbd9e210..54bbe648bf58 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -38,4 +38,11 @@ extern struct sys_timer ux500_timer; .type = MT_DEVICE, \ } +#define __MEM_DEV_DESC(x, sz) { \ + .virtual = IO_ADDRESS(x), \ + .pfn = __phys_to_pfn(x), \ + .length = sz, \ + .type = MT_MEMORY, \ +} + #endif /* __ASM_ARCH_SETUP_H */ -- cgit v1.2.2 From 1c833abc1f8c056f562ccf4d57a69514d338cc35 Mon Sep 17 00:00:00 2001 From: Hanumath Prasad Date: Thu, 19 Aug 2010 12:06:10 +0100 Subject: ARM: 6334/1: ux500: add DB8500 SD/MMC platform devices Acked-by: Linus Walleij Signed-off-by: Hanumath Prasad Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/mach-ux500/devices-db8500.c | 76 ++++++++++++++++++++++++++++++ arch/arm/mach-ux500/include/mach/devices.h | 7 +++ 2 files changed, 83 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index 9280d2561111..f2e01a6dafe7 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -110,6 +110,82 @@ struct platform_device u8500_i2c4_device = { .num_resources = ARRAY_SIZE(u8500_i2c4_resources), }; +/* + * SD/MMC + */ + +struct amba_device u8500_sdi0_device = { + .dev = { + .init_name = "sdi0", + }, + .res = { + .start = U8500_SDI0_BASE, + .end = U8500_SDI0_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_DB8500_SDMMC0, NO_IRQ}, +}; + +struct amba_device u8500_sdi1_device = { + .dev = { + .init_name = "sdi1", + }, + .res = { + .start = U8500_SDI1_BASE, + .end = U8500_SDI1_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_DB8500_SDMMC1, NO_IRQ}, +}; + +struct amba_device u8500_sdi2_device = { + .dev = { + .init_name = "sdi2", + }, + .res = { + .start = U8500_SDI2_BASE, + .end = U8500_SDI2_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_DB8500_SDMMC2, NO_IRQ}, +}; + +struct amba_device u8500_sdi3_device = { + .dev = { + .init_name = "sdi3", + }, + .res = { + .start = U8500_SDI3_BASE, + .end = U8500_SDI3_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_DB8500_SDMMC3, NO_IRQ}, +}; + +struct amba_device u8500_sdi4_device = { + .dev = { + .init_name = "sdi4", + }, + .res = { + .start = U8500_SDI4_BASE, + .end = U8500_SDI4_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_DB8500_SDMMC4, NO_IRQ}, +}; + +struct amba_device u8500_sdi5_device = { + .dev = { + .init_name = "sdi5", + }, + .res = { + .start = U8500_SDI5_BASE, + .end = U8500_SDI5_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_DB8500_SDMMC5, NO_IRQ}, +}; + static struct resource dma40_resources[] = { [0] = { .start = U8500_DMA_BASE, diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h index c2b2f2574947..33a120c2e82e 100644 --- a/arch/arm/mach-ux500/include/mach/devices.h +++ b/arch/arm/mach-ux500/include/mach/devices.h @@ -27,6 +27,13 @@ extern struct platform_device u8500_i2c0_device; extern struct platform_device u8500_i2c4_device; extern struct platform_device u8500_dma40_device; +extern struct amba_device u8500_sdi0_device; +extern struct amba_device u8500_sdi1_device; +extern struct amba_device u8500_sdi2_device; +extern struct amba_device u8500_sdi3_device; +extern struct amba_device u8500_sdi4_device; +extern struct amba_device u8500_sdi5_device; + void dma40_u8500ed_fixup(void); #endif -- cgit v1.2.2 From 008f8a2f7ff4d63559b7ba7a6f7073efef9b1e08 Mon Sep 17 00:00:00 2001 From: Hanumath Prasad Date: Thu, 19 Aug 2010 12:06:32 +0100 Subject: ARM: 6335/1: ux500: mop500: register eMMC devices Acked-by: Linus Walleij Signed-off-by: Hanumath Prasad Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/mach-ux500/Makefile | 2 +- arch/arm/mach-ux500/board-mop500-sdi.c | 91 ++++++++++++++++++++++++++++++++++ arch/arm/mach-ux500/board-mop500.c | 3 ++ arch/arm/mach-ux500/board-mop500.h | 12 +++++ arch/arm/mach-ux500/pins-db8500.h | 66 ++++++++++++------------ 5 files changed, 140 insertions(+), 34 deletions(-) create mode 100644 arch/arm/mach-ux500/board-mop500-sdi.c create mode 100644 arch/arm/mach-ux500/board-mop500.h (limited to 'arch') diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 4556aea9c3c5..33903af98b24 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -5,7 +5,7 @@ obj-y := clock.o cpu.o devices.o obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o -obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o +obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o obj-$(CONFIG_MACH_U5500) += board-u5500.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c new file mode 100644 index 000000000000..bac995665b58 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Hanumath Prasad + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "pins-db8500.h" +#include "board-mop500.h" + +static pin_cfg_t mop500_sdi_pins[] = { + /* SDI4 (on-board eMMC) */ + GPIO197_MC4_DAT3, + GPIO198_MC4_DAT2, + GPIO199_MC4_DAT1, + GPIO200_MC4_DAT0, + GPIO201_MC4_CMD, + GPIO202_MC4_FBCLK, + GPIO203_MC4_CLK, + GPIO204_MC4_DAT7, + GPIO205_MC4_DAT6, + GPIO206_MC4_DAT5, + GPIO207_MC4_DAT4, +}; + +static pin_cfg_t mop500_sdi2_pins[] = { + /* SDI2 (POP eMMC) */ + GPIO128_MC2_CLK, + GPIO129_MC2_CMD, + GPIO130_MC2_FBCLK, + GPIO131_MC2_DAT0, + GPIO132_MC2_DAT1, + GPIO133_MC2_DAT2, + GPIO134_MC2_DAT3, + GPIO135_MC2_DAT4, + GPIO136_MC2_DAT5, + GPIO137_MC2_DAT6, + GPIO138_MC2_DAT7, +}; + +/* + * SDI 2 (POP eMMC, not on DB8500ed) + */ + +static struct mmci_platform_data mop500_sdi2_data = { + .ocr_mask = MMC_VDD_165_195, + .f_max = 100000000, + .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, + .gpio_cd = -1, + .gpio_wp = -1, +}; + +/* + * SDI 4 (on-board eMMC) + */ + +static struct mmci_platform_data mop500_sdi4_data = { + .ocr_mask = MMC_VDD_29_30, + .f_max = 100000000, + .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA | + MMC_CAP_MMC_HIGHSPEED, + .gpio_cd = -1, + .gpio_wp = -1, +}; + +void mop500_sdi_init(void) +{ + nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins)); + + u8500_sdi2_device.dev.platform_data = &mop500_sdi2_data; + u8500_sdi4_device.dev.platform_data = &mop500_sdi4_data; + + if (!cpu_is_u8500ed()) { + nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins)); + amba_device_register(&u8500_sdi2_device, &iomem_resource); + } + + /* On-board eMMC */ + amba_device_register(&u8500_sdi4_device, &iomem_resource); +} diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 0e8fd135a57d..de310326df1c 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -30,6 +30,7 @@ #include #include "pins-db8500.h" +#include "board-mop500.h" static pin_cfg_t mop500_pins[] = { /* SSP0 */ @@ -163,6 +164,8 @@ static void __init u8500_init_machine(void) platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); + mop500_sdi_init(); + spi_register_board_info(u8500_spi_devices, ARRAY_SIZE(u8500_spi_devices)); } diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h new file mode 100644 index 000000000000..2d240322fa6f --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef __BOARD_MOP500_H +#define __BOARD_MOP500_H + +extern void mop500_sdi_init(void); + +#endif diff --git a/arch/arm/mach-ux500/pins-db8500.h b/arch/arm/mach-ux500/pins-db8500.h index 9055d5d3233c..66f8761cc823 100644 --- a/arch/arm/mach-ux500/pins-db8500.h +++ b/arch/arm/mach-ux500/pins-db8500.h @@ -96,57 +96,57 @@ #define GPIO17_SLIM0_CLK PIN_CFG(17, ALT_C) #define GPIO18_GPIO PIN_CFG(18, GPIO) -#define GPIO18_MC0_CMDDIR PIN_CFG(18, ALT_A) +#define GPIO18_MC0_CMDDIR PIN_CFG_PULL(18, ALT_A, UP) #define GPIO18_U2_RXD PIN_CFG(18, ALT_B) #define GPIO18_MS_IEP PIN_CFG(18, ALT_C) #define GPIO19_GPIO PIN_CFG(19, GPIO) -#define GPIO19_MC0_DAT0DIR PIN_CFG(19, ALT_A) +#define GPIO19_MC0_DAT0DIR PIN_CFG_PULL(19, ALT_A, UP) #define GPIO19_U2_TXD PIN_CFG(19, ALT_B) #define GPIO19_MS_DAT0DIR PIN_CFG(19, ALT_C) #define GPIO20_GPIO PIN_CFG(20, GPIO) -#define GPIO20_MC0_DAT2DIR PIN_CFG(20, ALT_A) +#define GPIO20_MC0_DAT2DIR PIN_CFG_PULL(20, ALT_A, UP) #define GPIO20_UARTMOD_TXD PIN_CFG(20, ALT_B) #define GPIO20_IP_TRIGOUT PIN_CFG(20, ALT_C) #define GPIO21_GPIO PIN_CFG(21, GPIO) -#define GPIO21_MC0_DAT31DIR PIN_CFG(21, ALT_A) +#define GPIO21_MC0_DAT31DIR PIN_CFG_PULL(21, ALT_A, UP) #define GPIO21_MSP0_SCK PIN_CFG(21, ALT_B) #define GPIO21_MS_DAT31DIR PIN_CFG(21, ALT_C) #define GPIO22_GPIO PIN_CFG(22, GPIO) -#define GPIO22_MC0_FBCLK PIN_CFG(22, ALT_A) +#define GPIO22_MC0_FBCLK PIN_CFG_PULL(22, ALT_A, UP) #define GPIO22_UARTMOD_RXD PIN_CFG(22, ALT_B) #define GPIO22_MS_FBCLK PIN_CFG(22, ALT_C) #define GPIO23_GPIO PIN_CFG(23, GPIO) -#define GPIO23_MC0_CLK PIN_CFG(23, ALT_A) +#define GPIO23_MC0_CLK PIN_CFG_PULL(23, ALT_A, UP) #define GPIO23_STMMOD_CLK PIN_CFG(23, ALT_B) #define GPIO23_MS_CLK PIN_CFG(23, ALT_C) #define GPIO24_GPIO PIN_CFG(24, GPIO) -#define GPIO24_MC0_CMD PIN_CFG(24, ALT_A) +#define GPIO24_MC0_CMD PIN_CFG_PULL(24, ALT_A, UP) #define GPIO24_UARTMOD_RXD PIN_CFG(24, ALT_B) #define GPIO24_MS_BS PIN_CFG(24, ALT_C) #define GPIO25_GPIO PIN_CFG(25, GPIO) -#define GPIO25_MC0_DAT0 PIN_CFG(25, ALT_A) +#define GPIO25_MC0_DAT0 PIN_CFG_PULL(25, ALT_A, UP) #define GPIO25_STMMOD_DAT0 PIN_CFG(25, ALT_B) #define GPIO25_MS_DAT0 PIN_CFG(25, ALT_C) #define GPIO26_GPIO PIN_CFG(26, GPIO) -#define GPIO26_MC0_DAT1 PIN_CFG(26, ALT_A) +#define GPIO26_MC0_DAT1 PIN_CFG_PULL(26, ALT_A, UP) #define GPIO26_STMMOD_DAT1 PIN_CFG(26, ALT_B) #define GPIO26_MS_DAT1 PIN_CFG(26, ALT_C) #define GPIO27_GPIO PIN_CFG(27, GPIO) -#define GPIO27_MC0_DAT2 PIN_CFG(27, ALT_A) +#define GPIO27_MC0_DAT2 PIN_CFG_PULL(27, ALT_A, UP) #define GPIO27_STMMOD_DAT2 PIN_CFG(27, ALT_B) #define GPIO27_MS_DAT2 PIN_CFG(27, ALT_C) #define GPIO28_GPIO PIN_CFG(28, GPIO) -#define GPIO28_MC0_DAT3 PIN_CFG(28, ALT_A) +#define GPIO28_MC0_DAT3 PIN_CFG_PULL(28, ALT_A, UP) #define GPIO28_STMMOD_DAT3 PIN_CFG(28, ALT_B) #define GPIO28_MS_DAT3 PIN_CFG(28, ALT_C) @@ -357,48 +357,48 @@ #define GPIO97_MC5_DAT7 PIN_CFG(97, ALT_C) #define GPIO128_GPIO PIN_CFG(128, GPIO) -#define GPIO128_MC2_CLK PIN_CFG(128, ALT_A) +#define GPIO128_MC2_CLK PIN_CFG_PULL(128, ALT_A, UP) #define GPIO128_SM_CKO PIN_CFG(128, ALT_B) #define GPIO129_GPIO PIN_CFG(129, GPIO) -#define GPIO129_MC2_CMD PIN_CFG(129, ALT_A) +#define GPIO129_MC2_CMD PIN_CFG_PULL(129, ALT_A, UP) #define GPIO129_SM_WAIT0n PIN_CFG(129, ALT_B) #define GPIO130_GPIO PIN_CFG(130, GPIO) -#define GPIO130_MC2_FBCLK PIN_CFG(130, ALT_A) +#define GPIO130_MC2_FBCLK PIN_CFG_PULL(130, ALT_A, UP) #define GPIO130_SM_FBCLK PIN_CFG(130, ALT_B) #define GPIO130_MC2_RSTN PIN_CFG(130, ALT_C) #define GPIO131_GPIO PIN_CFG(131, GPIO) -#define GPIO131_MC2_DAT0 PIN_CFG(131, ALT_A) +#define GPIO131_MC2_DAT0 PIN_CFG_PULL(131, ALT_A, UP) #define GPIO131_SM_ADQ8 PIN_CFG(131, ALT_B) #define GPIO132_GPIO PIN_CFG(132, GPIO) -#define GPIO132_MC2_DAT1 PIN_CFG(132, ALT_A) +#define GPIO132_MC2_DAT1 PIN_CFG_PULL(132, ALT_A, UP) #define GPIO132_SM_ADQ9 PIN_CFG(132, ALT_B) #define GPIO133_GPIO PIN_CFG(133, GPIO) -#define GPIO133_MC2_DAT2 PIN_CFG(133, ALT_A) +#define GPIO133_MC2_DAT2 PIN_CFG_PULL(133, ALT_A, UP) #define GPIO133_SM_ADQ10 PIN_CFG(133, ALT_B) #define GPIO134_GPIO PIN_CFG(134, GPIO) -#define GPIO134_MC2_DAT3 PIN_CFG(134, ALT_A) +#define GPIO134_MC2_DAT3 PIN_CFG_PULL(134, ALT_A, UP) #define GPIO134_SM_ADQ11 PIN_CFG(134, ALT_B) #define GPIO135_GPIO PIN_CFG(135, GPIO) -#define GPIO135_MC2_DAT4 PIN_CFG(135, ALT_A) +#define GPIO135_MC2_DAT4 PIN_CFG_PULL(135, ALT_A, UP) #define GPIO135_SM_ADQ12 PIN_CFG(135, ALT_B) #define GPIO136_GPIO PIN_CFG(136, GPIO) -#define GPIO136_MC2_DAT5 PIN_CFG(136, ALT_A) +#define GPIO136_MC2_DAT5 PIN_CFG_PULL(136, ALT_A, UP) #define GPIO136_SM_ADQ13 PIN_CFG(136, ALT_B) #define GPIO137_GPIO PIN_CFG(137, GPIO) -#define GPIO137_MC2_DAT6 PIN_CFG(137, ALT_A) +#define GPIO137_MC2_DAT6 PIN_CFG_PULL(137, ALT_A, UP) #define GPIO137_SM_ADQ14 PIN_CFG(137, ALT_B) #define GPIO138_GPIO PIN_CFG(138, GPIO) -#define GPIO138_MC2_DAT7 PIN_CFG(138, ALT_A) +#define GPIO138_MC2_DAT7 PIN_CFG_PULL(138, ALT_A, UP) #define GPIO138_SM_ADQ15 PIN_CFG(138, ALT_B) #define GPIO139_GPIO PIN_CFG(139, GPIO) @@ -569,39 +569,39 @@ #define GPIO196_MSP2_RXD PIN_CFG(196, ALT_A) #define GPIO197_GPIO PIN_CFG(197, GPIO) -#define GPIO197_MC4_DAT3 PIN_CFG(197, ALT_A) +#define GPIO197_MC4_DAT3 PIN_CFG_PULL(197, ALT_A, UP) #define GPIO198_GPIO PIN_CFG(198, GPIO) -#define GPIO198_MC4_DAT2 PIN_CFG(198, ALT_A) +#define GPIO198_MC4_DAT2 PIN_CFG_PULL(198, ALT_A, UP) #define GPIO199_GPIO PIN_CFG(199, GPIO) -#define GPIO199_MC4_DAT1 PIN_CFG(199, ALT_A) +#define GPIO199_MC4_DAT1 PIN_CFG_PULL(199, ALT_A, UP) #define GPIO200_GPIO PIN_CFG(200, GPIO) -#define GPIO200_MC4_DAT0 PIN_CFG(200, ALT_A) +#define GPIO200_MC4_DAT0 PIN_CFG_PULL(200, ALT_A, UP) #define GPIO201_GPIO PIN_CFG(201, GPIO) -#define GPIO201_MC4_CMD PIN_CFG(201, ALT_A) +#define GPIO201_MC4_CMD PIN_CFG_PULL(201, ALT_A, UP) #define GPIO202_GPIO PIN_CFG(202, GPIO) -#define GPIO202_MC4_FBCLK PIN_CFG(202, ALT_A) +#define GPIO202_MC4_FBCLK PIN_CFG_PULL(202, ALT_A, UP) #define GPIO202_PWL PIN_CFG(202, ALT_B) #define GPIO202_MC4_RSTN PIN_CFG(202, ALT_C) #define GPIO203_GPIO PIN_CFG(203, GPIO) -#define GPIO203_MC4_CLK PIN_CFG(203, ALT_A) +#define GPIO203_MC4_CLK PIN_CFG_PULL(203, ALT_A, UP) #define GPIO204_GPIO PIN_CFG(204, GPIO) -#define GPIO204_MC4_DAT7 PIN_CFG(204, ALT_A) +#define GPIO204_MC4_DAT7 PIN_CFG_PULL(204, ALT_A, UP) #define GPIO205_GPIO PIN_CFG(205, GPIO) -#define GPIO205_MC4_DAT6 PIN_CFG(205, ALT_A) +#define GPIO205_MC4_DAT6 PIN_CFG_PULL(205, ALT_A, UP) #define GPIO206_GPIO PIN_CFG(206, GPIO) -#define GPIO206_MC4_DAT5 PIN_CFG(206, ALT_A) +#define GPIO206_MC4_DAT5 PIN_CFG_PULL(206, ALT_A, UP) #define GPIO207_GPIO PIN_CFG(207, GPIO) -#define GPIO207_MC4_DAT4 PIN_CFG(207, ALT_A) +#define GPIO207_MC4_DAT4 PIN_CFG_PULL(207, ALT_A, UP) #define GPIO208_GPIO PIN_CFG(208, GPIO) #define GPIO208_MC1_CLK PIN_CFG(208, ALT_A) -- cgit v1.2.2 From e3726fcf263adf764a4f1b9428082837662a41c4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 19 Aug 2010 12:36:01 +0100 Subject: ARM: 6336/1: U8500 PRCMU driver Add an initial driver for communicating with the Power, Reset and Clock Management Unit (PRCMU) firmware in U8500. This initial version supports AB8500 communication only. Signed-off-by: Mattias Nilsson Signed-off-by: Mattias Wallin Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-ux500/Makefile | 2 +- arch/arm/mach-ux500/include/mach/irqs.h | 1 + arch/arm/mach-ux500/include/mach/prcmu-regs.h | 91 ++++++++++ arch/arm/mach-ux500/include/mach/prcmu.h | 15 ++ arch/arm/mach-ux500/prcmu.c | 231 ++++++++++++++++++++++++++ 5 files changed, 339 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-ux500/include/mach/prcmu-regs.h create mode 100644 arch/arm/mach-ux500/include/mach/prcmu.h create mode 100644 arch/arm/mach-ux500/prcmu.c (limited to 'arch') diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 33903af98b24..009731864399 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -4,7 +4,7 @@ obj-y := clock.o cpu.o devices.o obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o -obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o +obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o obj-$(CONFIG_MACH_U5500) += board-u5500.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h index 10385bdc2b77..0e7a2cec1994 100644 --- a/arch/arm/mach-ux500/include/mach/irqs.h +++ b/arch/arm/mach-ux500/include/mach/irqs.h @@ -41,6 +41,7 @@ #define IRQ_HSIR_CH2_OVRRUN (IRQ_SHPI_START + 34) #define IRQ_HSIR_CH3_OVRRUN (IRQ_SHPI_START + 35) #define IRQ_AB4500 (IRQ_SHPI_START + 40) +#define IRQ_PRCMU (IRQ_SHPI_START + 47) #define IRQ_DISP (IRQ_SHPI_START + 48) #define IRQ_SiPI3 (IRQ_SHPI_START + 49) #define IRQ_I2C4 (IRQ_SHPI_START + 51) diff --git a/arch/arm/mach-ux500/include/mach/prcmu-regs.h b/arch/arm/mach-ux500/include/mach/prcmu-regs.h new file mode 100644 index 000000000000..8885f39a6421 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/prcmu-regs.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2009 ST-Ericsson SA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + */ +#ifndef __MACH_PRCMU_REGS_H +#define __MACH_PRCMU_REGS_H + +#include + +#define _PRCMU_BASE IO_ADDRESS(U8500_PRCMU_BASE) + +#define PRCM_ARM_PLLDIVPS (_PRCMU_BASE + 0x118) +#define PRCM_ARM_CHGCLKREQ (_PRCMU_BASE + 0x114) +#define PRCM_PLLARM_ENABLE (_PRCMU_BASE + 0x98) +#define PRCM_ARMCLKFIX_MGT (_PRCMU_BASE + 0x0) +#define PRCM_A9_RESETN_CLR (_PRCMU_BASE + 0x1f4) +#define PRCM_A9_RESETN_SET (_PRCMU_BASE + 0x1f0) +#define PRCM_ARM_LS_CLAMP (_PRCMU_BASE + 0x30c) +#define PRCM_SRAM_A9 (_PRCMU_BASE + 0x308) + +/* ARM WFI Standby signal register */ +#define PRCM_ARM_WFI_STANDBY (_PRCMU_BASE + 0x130) +#define PRCMU_IOCR (_PRCMU_BASE + 0x310) + +/* CPU mailbox registers */ +#define PRCM_MBOX_CPU_VAL (_PRCMU_BASE + 0x0fc) +#define PRCM_MBOX_CPU_SET (_PRCMU_BASE + 0x100) +#define PRCM_MBOX_CPU_CLR (_PRCMU_BASE + 0x104) + +/* Dual A9 core interrupt management unit registers */ +#define PRCM_A9_MASK_REQ (_PRCMU_BASE + 0x328) +#define PRCM_A9_MASK_ACK (_PRCMU_BASE + 0x32c) +#define PRCM_ARMITMSK31TO0 (_PRCMU_BASE + 0x11c) +#define PRCM_ARMITMSK63TO32 (_PRCMU_BASE + 0x120) +#define PRCM_ARMITMSK95TO64 (_PRCMU_BASE + 0x124) +#define PRCM_ARMITMSK127TO96 (_PRCMU_BASE + 0x128) +#define PRCM_POWER_STATE_VAL (_PRCMU_BASE + 0x25C) +#define PRCM_ARMITVAL31TO0 (_PRCMU_BASE + 0x260) +#define PRCM_ARMITVAL63TO32 (_PRCMU_BASE + 0x264) +#define PRCM_ARMITVAL95TO64 (_PRCMU_BASE + 0x268) +#define PRCM_ARMITVAL127TO96 (_PRCMU_BASE + 0x26C) + +#define PRCM_HOSTACCESS_REQ (_PRCMU_BASE + 0x334) +#define ARM_WAKEUP_MODEM 0x1 + +#define PRCM_ARM_IT1_CLEAR (_PRCMU_BASE + 0x48C) +#define PRCM_ARM_IT1_VAL (_PRCMU_BASE + 0x494) +#define PRCM_HOLD_EVT (_PRCMU_BASE + 0x174) + +#define PRCM_ITSTATUS0 (_PRCMU_BASE + 0x148) +#define PRCM_ITSTATUS1 (_PRCMU_BASE + 0x150) +#define PRCM_ITSTATUS2 (_PRCMU_BASE + 0x158) +#define PRCM_ITSTATUS3 (_PRCMU_BASE + 0x160) +#define PRCM_ITSTATUS4 (_PRCMU_BASE + 0x168) +#define PRCM_ITSTATUS5 (_PRCMU_BASE + 0x484) +#define PRCM_ITCLEAR5 (_PRCMU_BASE + 0x488) +#define PRCM_ARMIT_MASKXP70_IT (_PRCMU_BASE + 0x1018) + +/* System reset register */ +#define PRCM_APE_SOFTRST (_PRCMU_BASE + 0x228) + +/* Level shifter and clamp control registers */ +#define PRCM_MMIP_LS_CLAMP_SET (_PRCMU_BASE + 0x420) +#define PRCM_MMIP_LS_CLAMP_CLR (_PRCMU_BASE + 0x424) + +/* PRCMU clock/PLL/reset registers */ +#define PRCM_PLLDSI_FREQ (_PRCMU_BASE + 0x500) +#define PRCM_PLLDSI_ENABLE (_PRCMU_BASE + 0x504) +#define PRCM_LCDCLK_MGT (_PRCMU_BASE + 0x044) +#define PRCM_MCDECLK_MGT (_PRCMU_BASE + 0x064) +#define PRCM_HDMICLK_MGT (_PRCMU_BASE + 0x058) +#define PRCM_TVCLK_MGT (_PRCMU_BASE + 0x07c) +#define PRCM_DSI_PLLOUT_SEL (_PRCMU_BASE + 0x530) +#define PRCM_DSITVCLK_DIV (_PRCMU_BASE + 0x52C) +#define PRCM_APE_RESETN_SET (_PRCMU_BASE + 0x1E4) +#define PRCM_APE_RESETN_CLR (_PRCMU_BASE + 0x1E8) + +/* ePOD and memory power signal control registers */ +#define PRCM_EPOD_C_SET (_PRCMU_BASE + 0x410) +#define PRCM_SRAM_LS_SLEEP (_PRCMU_BASE + 0x304) + +/* Debug power control unit registers */ +#define PRCM_POWER_STATE_SET (_PRCMU_BASE + 0x254) + +/* Miscellaneous unit registers */ +#define PRCM_DSI_SW_RESET (_PRCMU_BASE + 0x324) + +#endif /* __MACH_PRCMU__REGS_H */ diff --git a/arch/arm/mach-ux500/include/mach/prcmu.h b/arch/arm/mach-ux500/include/mach/prcmu.h new file mode 100644 index 000000000000..549843ff6dbe --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/prcmu.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) STMicroelectronics 2009 + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * + * PRCMU f/w APIs + */ +#ifndef __MACH_PRCMU_H +#define __MACH_PRCMU_H + +int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); +int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); + +#endif /* __MACH_PRCMU_H */ diff --git a/arch/arm/mach-ux500/prcmu.c b/arch/arm/mach-ux500/prcmu.c new file mode 100644 index 000000000000..293274d1342a --- /dev/null +++ b/arch/arm/mach-ux500/prcmu.c @@ -0,0 +1,231 @@ +/* + * Copyright (C) ST Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * Author: Mattias Nilsson + * + * U8500 PRCMU driver. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define PRCMU_TCDM_BASE __io_address(U8500_PRCMU_TCDM_BASE) + +#define REQ_MB5 (PRCMU_TCDM_BASE + 0xE44) +#define ACK_MB5 (PRCMU_TCDM_BASE + 0xDF4) + +#define REQ_MB5_I2C_SLAVE_OP (REQ_MB5) +#define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1) +#define REQ_MB5_I2C_REG (REQ_MB5 + 2) +#define REQ_MB5_I2C_VAL (REQ_MB5 + 3) + +#define ACK_MB5_I2C_STATUS (ACK_MB5 + 1) +#define ACK_MB5_I2C_VAL (ACK_MB5 + 3) + +#define I2C_WRITE(slave) ((slave) << 1) +#define I2C_READ(slave) (((slave) << 1) | BIT(0)) +#define I2C_STOP_EN BIT(3) + +enum ack_mb5_status { + I2C_WR_OK = 0x01, + I2C_RD_OK = 0x02, +}; + +#define MBOX_BIT BIT +#define NUM_MBOX 8 + +static struct { + struct mutex lock; + struct completion work; + bool failed; + struct { + u8 status; + u8 value; + } ack; +} mb5_transfer; + +/** + * prcmu_abb_read() - Read register value(s) from the ABB. + * @slave: The I2C slave address. + * @reg: The (start) register address. + * @value: The read out value(s). + * @size: The number of registers to read. + * + * Reads register value(s) from the ABB. + * @size has to be 1 for the current firmware version. + */ +int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) +{ + int r; + + if (size != 1) + return -EINVAL; + + r = mutex_lock_interruptible(&mb5_transfer.lock); + if (r) + return r; + + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) + cpu_relax(); + + writeb(I2C_READ(slave), REQ_MB5_I2C_SLAVE_OP); + writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS); + writeb(reg, REQ_MB5_I2C_REG); + + writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET); + if (!wait_for_completion_timeout(&mb5_transfer.work, + msecs_to_jiffies(500))) { + pr_err("prcmu: prcmu_abb_read timed out.\n"); + r = -EIO; + goto unlock_and_return; + } + r = ((mb5_transfer.ack.status == I2C_RD_OK) ? 0 : -EIO); + if (!r) + *value = mb5_transfer.ack.value; + +unlock_and_return: + mutex_unlock(&mb5_transfer.lock); + return r; +} +EXPORT_SYMBOL(prcmu_abb_read); + +/** + * prcmu_abb_write() - Write register value(s) to the ABB. + * @slave: The I2C slave address. + * @reg: The (start) register address. + * @value: The value(s) to write. + * @size: The number of registers to write. + * + * Reads register value(s) from the ABB. + * @size has to be 1 for the current firmware version. + */ +int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) +{ + int r; + + if (size != 1) + return -EINVAL; + + r = mutex_lock_interruptible(&mb5_transfer.lock); + if (r) + return r; + + + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) + cpu_relax(); + + writeb(I2C_WRITE(slave), REQ_MB5_I2C_SLAVE_OP); + writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS); + writeb(reg, REQ_MB5_I2C_REG); + writeb(*value, REQ_MB5_I2C_VAL); + + writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET); + if (!wait_for_completion_timeout(&mb5_transfer.work, + msecs_to_jiffies(500))) { + pr_err("prcmu: prcmu_abb_write timed out.\n"); + r = -EIO; + goto unlock_and_return; + } + r = ((mb5_transfer.ack.status == I2C_WR_OK) ? 0 : -EIO); + +unlock_and_return: + mutex_unlock(&mb5_transfer.lock); + return r; +} +EXPORT_SYMBOL(prcmu_abb_write); + +static void read_mailbox_0(void) +{ + writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR); +} + +static void read_mailbox_1(void) +{ + writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR); +} + +static void read_mailbox_2(void) +{ + writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR); +} + +static void read_mailbox_3(void) +{ + writel(MBOX_BIT(3), PRCM_ARM_IT1_CLEAR); +} + +static void read_mailbox_4(void) +{ + writel(MBOX_BIT(4), PRCM_ARM_IT1_CLEAR); +} + +static void read_mailbox_5(void) +{ + mb5_transfer.ack.status = readb(ACK_MB5_I2C_STATUS); + mb5_transfer.ack.value = readb(ACK_MB5_I2C_VAL); + complete(&mb5_transfer.work); + writel(MBOX_BIT(5), PRCM_ARM_IT1_CLEAR); +} + +static void read_mailbox_6(void) +{ + writel(MBOX_BIT(6), PRCM_ARM_IT1_CLEAR); +} + +static void read_mailbox_7(void) +{ + writel(MBOX_BIT(7), PRCM_ARM_IT1_CLEAR); +} + +static void (* const read_mailbox[NUM_MBOX])(void) = { + read_mailbox_0, + read_mailbox_1, + read_mailbox_2, + read_mailbox_3, + read_mailbox_4, + read_mailbox_5, + read_mailbox_6, + read_mailbox_7 +}; + +static irqreturn_t prcmu_irq_handler(int irq, void *data) +{ + u32 bits; + u8 n; + + bits = (readl(PRCM_ARM_IT1_VAL) & (MBOX_BIT(NUM_MBOX) - 1)); + if (unlikely(!bits)) + return IRQ_NONE; + + for (n = 0; bits; n++) { + if (bits & MBOX_BIT(n)) { + bits -= MBOX_BIT(n); + read_mailbox[n](); + } + } + return IRQ_HANDLED; +} + +static int __init prcmu_init(void) +{ + mutex_init(&mb5_transfer.lock); + init_completion(&mb5_transfer.work); + + /* Clean up the mailbox interrupts after pre-kernel code. */ + writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR); + + return request_irq(IRQ_PRCMU, prcmu_irq_handler, 0, "prcmu", NULL); +} + +arch_initcall(prcmu_init); -- cgit v1.2.2 From 7e3f7e59ccc6ed8b243de9941ffd09d2ad7a5b9c Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 2 Sep 2010 11:28:05 +0100 Subject: ARM: 6353/1: nomadik-gpio: add SLPM register handing for DB8500v2 The SLPM register enables/disables wakeup detection on DB8500v2. Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/plat-nomadik/gpio.c | 30 ++++++++++++++++++++++++++--- arch/arm/plat-nomadik/include/plat/gpio.h | 2 ++ arch/arm/plat-nomadik/include/plat/pincfg.h | 5 ++++- 3 files changed, 33 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 977c8f9a07a2..014da39b6a88 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -118,8 +118,8 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, [3] /* illegal */ = "??" }; static const char *slpmnames[] = { - [NMK_GPIO_SLPM_INPUT] = "input", - [NMK_GPIO_SLPM_NOCHANGE] = "no-change", + [NMK_GPIO_SLPM_INPUT] = "input/wakeup", + [NMK_GPIO_SLPM_NOCHANGE] = "no-change/no-wakeup", }; int pin = PIN_NUM(cfg); @@ -200,6 +200,10 @@ EXPORT_SYMBOL(nmk_config_pins); * changed to an input (with pullup/down enabled) in sleep and deep sleep. If * @mode is NMK_GPIO_SLPM_NOCHANGE, the pin remains in the state it was * configured even when in sleep and deep sleep. + * + * On DB8500v2 onwards, this setting loses the previous meaning and instead + * indicates if wakeup detection is enabled on the pin. Note that + * enable_irq_wake() will automatically enable wakeup detection. */ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) { @@ -367,7 +371,27 @@ static void nmk_gpio_irq_unmask(unsigned int irq) static int nmk_gpio_irq_set_wake(unsigned int irq, unsigned int on) { - return nmk_gpio_irq_modify(irq, WAKE, on); + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + int gpio; + + gpio = NOMADIK_IRQ_TO_GPIO(irq); + nmk_chip = get_irq_chip_data(irq); + if (!nmk_chip) + return -EINVAL; + + spin_lock_irqsave(&nmk_chip->lock, flags); +#ifdef CONFIG_ARCH_U8500 + if (cpu_is_u8500v2()) { + __nmk_gpio_set_slpm(nmk_chip, gpio, + on ? NMK_GPIO_SLPM_WAKEUP_ENABLE + : NMK_GPIO_SLPM_WAKEUP_DISABLE); + } +#endif + __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on); + spin_unlock_irqrestore(&nmk_chip->lock, flags); + + return 0; } static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index aba355101f49..67b113d639d8 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h @@ -65,7 +65,9 @@ enum nmk_gpio_pull { /* Sleep mode */ enum nmk_gpio_slpm { NMK_GPIO_SLPM_INPUT, + NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT, NMK_GPIO_SLPM_NOCHANGE, + NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE, }; extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode); diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h index 7eed11c1038d..432a201b3b41 100644 --- a/arch/arm/plat-nomadik/include/plat/pincfg.h +++ b/arch/arm/plat-nomadik/include/plat/pincfg.h @@ -24,7 +24,7 @@ * * PIN_CFG_DEFAULT - default config (0): * pull up/down = disabled - * sleep mode = input + * sleep mode = input/wakeup * * PIN_CFG - default config with alternate function * PIN_CFG_PULL - default config with alternate function and pull up/down @@ -55,6 +55,9 @@ typedef unsigned long pin_cfg_t; #define PIN_SLPM(x) (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT) #define PIN_SLPM_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT) #define PIN_SLPM_NOCHANGE (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT) +/* 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_CFG_DEFAULT (PIN_PULL_NONE | PIN_SLPM_INPUT) -- cgit v1.2.2 From 6720db7cc592b2148e0d88a7d76dc0532f3d266c Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 2 Sep 2010 11:28:48 +0100 Subject: ARM: 6354/1: nomadik-gpio: allow control of sleep mode direction and pull up DB8500v2 allows control of direction and pull up/down configuration in sleep mode, instead of switching the pin to input with pull up/down enabled. Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/plat-nomadik/gpio.c | 42 +++++++++++++++++++++-------- arch/arm/plat-nomadik/include/plat/pincfg.h | 31 ++++++++++++++++++++- 2 files changed, 61 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 014da39b6a88..7afc7e8850b6 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -102,6 +102,22 @@ static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip, writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); } +static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip, + unsigned offset, int val) +{ + if (val) + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATS); + else + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATC); +} + +static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip, + unsigned offset, int val) +{ + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS); + __nmk_gpio_set_output(nmk_chip, offset, val); +} + static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, pin_cfg_t cfg) { @@ -126,12 +142,21 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, int pull = PIN_PULL(cfg); int af = PIN_ALT(cfg); int slpm = PIN_SLPM(cfg); + int output = PIN_DIR(cfg); + int val = PIN_VAL(cfg); - dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s\n", - pin, afnames[af], pullnames[pull], slpmnames[slpm]); + dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s (%s%s)\n", + pin, afnames[af], pullnames[pull], slpmnames[slpm], + output ? "output " : "input", + output ? (val ? "high" : "low") : ""); + + if (output) + __nmk_gpio_make_output(nmk_chip, offset, val); + else { + __nmk_gpio_make_input(nmk_chip, offset); + __nmk_gpio_set_pull(nmk_chip, offset, pull); + } - __nmk_gpio_make_input(nmk_chip, offset); - __nmk_gpio_set_pull(nmk_chip, offset, pull); __nmk_gpio_set_slpm(nmk_chip, offset, slpm); __nmk_gpio_set_mode(nmk_chip, offset, af); } @@ -519,12 +544,8 @@ static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, { struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); - u32 bit = 1 << offset; - if (val) - writel(bit, nmk_chip->addr + NMK_GPIO_DATS); - else - writel(bit, nmk_chip->addr + NMK_GPIO_DATC); + __nmk_gpio_set_output(nmk_chip, offset, val); } static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, @@ -533,8 +554,7 @@ static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); - writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS); - nmk_gpio_set_output(chip, offset, val); + __nmk_gpio_make_output(nmk_chip, offset, val); return 0; } diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h index 432a201b3b41..8c5ae3f2acf8 100644 --- a/arch/arm/plat-nomadik/include/plat/pincfg.h +++ b/arch/arm/plat-nomadik/include/plat/pincfg.h @@ -19,12 +19,16 @@ * bit 9..10 - Alternate Function Selection * bit 11..12 - Pull up/down state * bit 13 - Sleep mode behaviour + * bit 14 - (sleep mode) Direction + * bit 15 - (sleep mode) Value (if output) * * to facilitate the definition, the following macros are provided * * PIN_CFG_DEFAULT - default config (0): * pull up/down = disabled * sleep mode = input/wakeup + * (sleep mode) direction = input + * (sleep mode) value = low * * PIN_CFG - default config with alternate function * PIN_CFG_PULL - default config with alternate function and pull up/down @@ -53,12 +57,37 @@ typedef unsigned long pin_cfg_t; #define PIN_SLPM_SHIFT 13 #define PIN_SLPM_MASK (0x1 << PIN_SLPM_SHIFT) #define PIN_SLPM(x) (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT) -#define PIN_SLPM_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT) +#define PIN_SLPM_MAKE_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT) #define PIN_SLPM_NOCHANGE (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT) /* 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_DIR_SHIFT 14 +#define PIN_DIR_MASK (0x1 << PIN_DIR_SHIFT) +#define PIN_DIR(x) (((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT) +#define PIN_DIR_INPUT (0 << PIN_DIR_SHIFT) +#define PIN_DIR_OUTPUT (1 << PIN_DIR_SHIFT) + +#define PIN_VAL_SHIFT 15 +#define PIN_VAL_MASK (0x1 << PIN_VAL_SHIFT) +#define PIN_VAL(x) (((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT) +#define PIN_VAL_LOW (0 << PIN_VAL_SHIFT) +#define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT) + +/* Shortcuts. Use these instead of separate DIR and VAL. */ +#define PIN_INPUT PIN_DIR_INPUT +#define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW) +#define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH) + +/* + * These are the same as the ones above, but should make more sense to the + * reader when seen along with a setting a pin to AF mode. + */ +#define PIN_SLPM_INPUT PIN_INPUT +#define PIN_SLPM_OUTPUT_LOW PIN_OUTPUT_LOW +#define PIN_SLPM_OUTPUT_HIGH PIN_OUTPUT_HIGH + #define PIN_CFG_DEFAULT (PIN_PULL_NONE | PIN_SLPM_INPUT) #define PIN_CFG(num, alt) \ -- cgit v1.2.2 From 495c7b8e64811e8117eca472c6f90dccda039dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 2 Sep 2010 09:14:19 +0100 Subject: ARM: 6348/1: s3c64xx: don't put smartq7_leds in .init.data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a section mismatch found by modpost: WARNING: arch/arm/mach-s3c64xx/built-in.o(.data+0x2c1c): Section mismatch in reference from the variable smartq7_led_data to the (unknown reference) .init.data:(unknown) The variable smartq7_led_data references the (unknown reference) __initdata (unknown) If the reference is valid then annotate the variable with __init* or __refdata (see linux/init.h) or name the variable: *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console, Signed-off-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/mach-s3c64xx/mach-smartq7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-s3c64xx/mach-smartq7.c b/arch/arm/mach-s3c64xx/mach-smartq7.c index e50a7d781732..78a58c351f0a 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq7.c +++ b/arch/arm/mach-s3c64xx/mach-smartq7.c @@ -32,7 +32,7 @@ #include "mach-smartq.h" -static struct gpio_led smartq7_leds[] __initdata = { +static struct gpio_led smartq7_leds[] = { { .name = "smartq7:red", .active_low = 1, -- cgit v1.2.2 From d684f640639d7be8efb7b324294830d9bcbf15f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 2 Sep 2010 09:14:22 +0100 Subject: ARM: 6350/1: s3c64xx: don't put smartq5_leds in .init.data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a section mismatch found by modpost: WARNING: arch/arm/mach-s3c64xx/built-in.o(.data+0x2814): Section mismatch in reference from the variable smartq5_led_data to the (unknown reference) .init.data:(unknown) The variable smartq5_led_data references the (unknown reference) __initdata (unknown) If the reference is valid then annotate the variable with __init* or __refdata (see linux/init.h) or name the variable: *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console, Signed-off-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/mach-s3c64xx/mach-smartq5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c index a4d59b076e3d..235e43928cb8 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq5.c +++ b/arch/arm/mach-s3c64xx/mach-smartq5.c @@ -32,7 +32,7 @@ #include "mach-smartq.h" -static struct gpio_led smartq5_leds[] __initdata = { +static struct gpio_led smartq5_leds[] = { { .name = "smartq5:green", .active_low = 1, -- cgit v1.2.2 From 9e978f096241e303c10cf6e6dc80dce41ef41b92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 2 Sep 2010 09:14:20 +0100 Subject: ARM: 6351/1: s3c64xx: don't put smartq_bl_init in .init.text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a section mismatch found by modpost: WARNING: arch/arm/mach-s3c64xx/built-in.o(.data+0x2498): Section mismatch in reference from the variable smartq_backlight_data to the function .init.text:smartq_bl_init() The variable smartq_backlight_data references the function __init smartq_bl_init() If the reference is valid then annotate the variable with __init* or __refdata (see linux/init.h) or name the variable: *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console, Signed-off-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/mach-s3c64xx/mach-smartq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c index 3a9639bc3d9b..cb1ebeb08763 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq.c +++ b/arch/arm/mach-s3c64xx/mach-smartq.c @@ -136,7 +136,7 @@ static struct platform_device smartq_usb_otg_vbus_dev = { .dev.platform_data = &smartq_usb_otg_vbus_pdata, }; -static int __init smartq_bl_init(struct device *dev) +static int smartq_bl_init(struct device *dev) { s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_SFN(2)); -- cgit v1.2.2 From 65b4711ff513767341aa1915c822de6ec0de65cb Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 2 Sep 2010 09:32:08 +0100 Subject: ARM: 6352/1: perf: fix event validation The validate_event function in the ARM perf events backend has the following problems: 1.) Events that are disabled count towards the cost. 2.) Events associated with other PMUs [for example, software events or breakpoints] do not count towards the cost, but do fail validation, causing the group to fail. This patch changes validate_event so that it ignores events in the PERF_EVENT_STATE_OFF state or that are scheduled for other PMUs. Reported-by: Pawel Moll Acked-by: Jamie Iles Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/perf_event.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index e2139256524e..ecbb0288e5dd 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -319,8 +319,8 @@ validate_event(struct cpu_hw_events *cpuc, { struct hw_perf_event fake_event = event->hw; - if (event->pmu && event->pmu != &pmu) - return 0; + if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF) + return 1; return armpmu->get_event_idx(cpuc, &fake_event) >= 0; } -- cgit v1.2.2 From fd0d67d62def64ed5aa57f99d247e2b3d5eff8c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 2 Sep 2010 16:13:35 +0100 Subject: ARM: 6347/2: nomadik: move nmk_gpio_probe to .devinit.text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a section mismatch reported by modpost: WARNING: arch/arm/plat-nomadik/built-in.o(.data+0x100): Section mismatch in reference from the variable nmk_gpio_driver to the function .init.text:nmk_gpio_probe() The variable nmk_gpio_driver references the function __init nmk_gpio_probe() If the reference is valid then annotate the variable with __init* or __refdata (see linux/init.h) or name the variable: *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console, According to Rabin VINCENT the alternative to use platform_driver_probe won't work because the "platform devices are not yet registered when nmk_gpio_init() is called." Acked-by: Rabin Vincent Signed-off-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/plat-nomadik/gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 7afc7e8850b6..85e6fd212a41 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -578,7 +578,7 @@ static struct gpio_chip nmk_gpio_template = { .can_sleep = 0, }; -static int __init nmk_gpio_probe(struct platform_device *dev) +static int __devinit nmk_gpio_probe(struct platform_device *dev) { struct nmk_gpio_platform_data *pdata = dev->dev.platform_data; struct nmk_gpio_chip *nmk_chip; -- cgit v1.2.2 From 2e556b5b320838fde98480a1f6cf220a5af200fc Mon Sep 17 00:00:00 2001 From: Don Zickus Date: Thu, 2 Sep 2010 15:07:47 -0400 Subject: perf, x86: Fix accidentally ack'ing a second event on intel perf counter During testing of a patch to stop having the perf subsytem swallow nmis, it was uncovered that Nehalem boxes were randomly getting unknown nmis when using the perf tool. Moving the ack'ing of the PMI closer to when we get the status allows the hardware to properly re-set the PMU bit signaling another PMI was triggered during the processing of the first PMI. This allows the new logic for dealing with the shortcomings of multiple PMIs to handle the extra NMI by 'eat'ing it later. Now one can wonder why are we getting a second PMI when we disable all the PMUs in the begining of the NMI handler to prevent such a case, for that I do not know. But I know the fix below helps deal with this quirk. Tested on multiple Nehalems where the problem was occuring. With the patch, the code now loops a second time to handle the second PMI (whereas before it was not). Signed-off-by: Don Zickus Cc: peterz@infradead.org Cc: robert.richter@amd.com Cc: gorcunov@gmail.com Cc: fweisbec@gmail.com Cc: ying.huang@intel.com Cc: ming.m.lin@intel.com Cc: eranian@google.com LKML-Reference: <1283454469-1909-2-git-send-email-dzickus@redhat.com> Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_intel.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index d8d86d014008..1297bf15cb88 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -712,7 +712,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) struct perf_sample_data data; struct cpu_hw_events *cpuc; int bit, loops; - u64 ack, status; + u64 status; perf_sample_data_init(&data, 0); @@ -728,6 +728,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) loops = 0; again: + intel_pmu_ack_status(status); if (++loops > 100) { WARN_ONCE(1, "perfevents: irq loop stuck!\n"); perf_event_print_debug(); @@ -736,7 +737,6 @@ again: } inc_irq_stat(apic_perf_irqs); - ack = status; intel_pmu_lbr_read(); @@ -761,8 +761,6 @@ again: x86_pmu_stop(event); } - intel_pmu_ack_status(ack); - /* * Repeat if there is more work to be done: */ -- cgit v1.2.2 From de725dec9de7a7541996176d59cf8542365b8b0e Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 2 Sep 2010 15:07:49 -0400 Subject: perf, x86: Fix handle_irq return values Now that we rely on the number of handled overflows, ensure all handle_irq implementations actually return the right number. Signed-off-by: Peter Zijlstra Signed-off-by: Don Zickus Cc: peterz@infradead.org Cc: robert.richter@amd.com Cc: gorcunov@gmail.com Cc: fweisbec@gmail.com Cc: ying.huang@intel.com Cc: ming.m.lin@intel.com Cc: eranian@google.com LKML-Reference: <1283454469-1909-4-git-send-email-dzickus@redhat.com> Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_intel.c | 9 +++++++-- arch/x86/kernel/cpu/perf_event_p4.c | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 1297bf15cb88..ee05c90012d2 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -713,6 +713,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) struct cpu_hw_events *cpuc; int bit, loops; u64 status; + int handled = 0; perf_sample_data_init(&data, 0); @@ -743,12 +744,16 @@ again: /* * PEBS overflow sets bit 62 in the global status register */ - if (__test_and_clear_bit(62, (unsigned long *)&status)) + if (__test_and_clear_bit(62, (unsigned long *)&status)) { + handled++; x86_pmu.drain_pebs(regs); + } for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { struct perf_event *event = cpuc->events[bit]; + handled++; + if (!test_bit(bit, cpuc->active_mask)) continue; @@ -770,7 +775,7 @@ again: done: intel_pmu_enable_all(0); - return 1; + return handled; } static struct event_constraint * diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index 7e578e9cc58b..b560db3305be 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -692,7 +692,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs) inc_irq_stat(apic_perf_irqs); } - return handled > 0; + return handled; } /* -- cgit v1.2.2 From 4177c42a6301a34c20038ec2771a33dcc30bb338 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 2 Sep 2010 15:07:48 -0400 Subject: perf, x86: Try to handle unknown nmis with an enabled PMU When the PMU is enabled it is valid to have unhandled nmis, two events could trigger 'simultaneously' raising two back-to-back NMIs. If the first NMI handles both, the latter will be empty and daze the CPU. The solution to avoid an 'unknown nmi' massage in this case was simply to stop the nmi handler chain when the PMU is enabled by stating the nmi was handled. This has the drawback that a) we can not detect unknown nmis anymore, and b) subsequent nmi handlers are not called. This patch addresses this. Now, we check this unknown NMI if it could be a PMU back-to-back NMI. Otherwise we pass it and let the kernel handle the unknown nmi. This is a debug log: cpu #6, nmi #32333, skip_nmi #32330, handled = 1, time = 1934364430 cpu #6, nmi #32334, skip_nmi #32330, handled = 1, time = 1934704616 cpu #6, nmi #32335, skip_nmi #32336, handled = 2, time = 1936032320 cpu #6, nmi #32336, skip_nmi #32336, handled = 0, time = 1936034139 cpu #6, nmi #32337, skip_nmi #32336, handled = 1, time = 1936120100 cpu #6, nmi #32338, skip_nmi #32336, handled = 1, time = 1936404607 cpu #6, nmi #32339, skip_nmi #32336, handled = 1, time = 1937983416 cpu #6, nmi #32340, skip_nmi #32341, handled = 2, time = 1938201032 cpu #6, nmi #32341, skip_nmi #32341, handled = 0, time = 1938202830 cpu #6, nmi #32342, skip_nmi #32341, handled = 1, time = 1938443743 cpu #6, nmi #32343, skip_nmi #32341, handled = 1, time = 1939956552 cpu #6, nmi #32344, skip_nmi #32341, handled = 1, time = 1940073224 cpu #6, nmi #32345, skip_nmi #32341, handled = 1, time = 1940485677 cpu #6, nmi #32346, skip_nmi #32347, handled = 2, time = 1941947772 cpu #6, nmi #32347, skip_nmi #32347, handled = 1, time = 1941949818 cpu #6, nmi #32348, skip_nmi #32347, handled = 0, time = 1941951591 Uhhuh. NMI received for unknown reason 00 on CPU 6. Do you have a strange power saving mode enabled? Dazed and confused, but trying to continue Deltas: nmi #32334 340186 nmi #32335 1327704 nmi #32336 1819 <<<< back-to-back nmi [1] nmi #32337 85961 nmi #32338 284507 nmi #32339 1578809 nmi #32340 217616 nmi #32341 1798 <<<< back-to-back nmi [2] nmi #32342 240913 nmi #32343 1512809 nmi #32344 116672 nmi #32345 412453 nmi #32346 1462095 <<<< 1st nmi (standard) handling 2 counters nmi #32347 2046 <<<< 2nd nmi (back-to-back) handling one counter nmi #32348 1773 <<<< 3rd nmi (back-to-back) handling no counter! [3] For back-to-back nmi detection there are the following rules: The PMU nmi handler was handling more than one counter and no counter was handled in the subsequent nmi (see [1] and [2] above). There is another case if there are two subsequent back-to-back nmis [3]. The 2nd is detected as back-to-back because the first handled more than one counter. If the second handles one counter and the 3rd handles nothing, we drop the 3rd nmi because it could be a back-to-back nmi. Signed-off-by: Robert Richter Signed-off-by: Peter Zijlstra [ renamed nmi variable to pmu_nmi to avoid clash with .nmi in entry.S ] Signed-off-by: Don Zickus Cc: peterz@infradead.org Cc: gorcunov@gmail.com Cc: fweisbec@gmail.com Cc: ying.huang@intel.com Cc: ming.m.lin@intel.com Cc: eranian@google.com LKML-Reference: <1283454469-1909-3-git-send-email-dzickus@redhat.com> Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 59 +++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index f2da20fda02d..3efdf2870a35 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1154,7 +1154,7 @@ static int x86_pmu_handle_irq(struct pt_regs *regs) /* * event overflow */ - handled = 1; + handled++; data.period = event->hw.last_period; if (!x86_perf_event_set_period(event)) @@ -1200,12 +1200,20 @@ void perf_events_lapic_init(void) apic_write(APIC_LVTPC, APIC_DM_NMI); } +struct pmu_nmi_state { + unsigned int marked; + int handled; +}; + +static DEFINE_PER_CPU(struct pmu_nmi_state, pmu_nmi); + static int __kprobes perf_event_nmi_handler(struct notifier_block *self, unsigned long cmd, void *__args) { struct die_args *args = __args; - struct pt_regs *regs; + unsigned int this_nmi; + int handled; if (!atomic_read(&active_events)) return NOTIFY_DONE; @@ -1214,22 +1222,47 @@ perf_event_nmi_handler(struct notifier_block *self, case DIE_NMI: case DIE_NMI_IPI: break; - + case DIE_NMIUNKNOWN: + this_nmi = percpu_read(irq_stat.__nmi_count); + if (this_nmi != __get_cpu_var(pmu_nmi).marked) + /* let the kernel handle the unknown nmi */ + return NOTIFY_DONE; + /* + * This one is a PMU back-to-back nmi. Two events + * trigger 'simultaneously' raising two back-to-back + * NMIs. If the first NMI handles both, the latter + * will be empty and daze the CPU. So, we drop it to + * avoid false-positive 'unknown nmi' messages. + */ + return NOTIFY_STOP; default: return NOTIFY_DONE; } - regs = args->regs; - apic_write(APIC_LVTPC, APIC_DM_NMI); - /* - * Can't rely on the handled return value to say it was our NMI, two - * events could trigger 'simultaneously' raising two back-to-back NMIs. - * - * If the first NMI handles both, the latter will be empty and daze - * the CPU. - */ - x86_pmu.handle_irq(regs); + + handled = x86_pmu.handle_irq(args->regs); + if (!handled) + return NOTIFY_DONE; + + this_nmi = percpu_read(irq_stat.__nmi_count); + if ((handled > 1) || + /* the next nmi could be a back-to-back nmi */ + ((__get_cpu_var(pmu_nmi).marked == this_nmi) && + (__get_cpu_var(pmu_nmi).handled > 1))) { + /* + * We could have two subsequent back-to-back nmis: The + * first handles more than one counter, the 2nd + * handles only one counter and the 3rd handles no + * counter. + * + * This is the 2nd nmi because the previous was + * handling more than one counter. We will mark the + * next (3rd) and then drop it if unhandled. + */ + __get_cpu_var(pmu_nmi).marked = this_nmi + 1; + __get_cpu_var(pmu_nmi).handled = handled; + } return NOTIFY_STOP; } -- cgit v1.2.2 From cc1a8e523333bc3d990102140f4d12908fa83caf Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sat, 4 Sep 2010 22:56:43 +0200 Subject: x86: Fix the address space annotations of iomap_atomic_prot_pfn() This patch fixes the sparse warnings when the return pointer of iomap_atomic_prot_pfn() is used as an argument of iowrite32() and friends. Signed-off-by: Francisco Jerez LKML-Reference: <1283633804-11749-1-git-send-email-currojerez@riseup.net> Cc: Andrew Morton Signed-off-by: Ingo Molnar --- arch/x86/include/asm/iomap.h | 4 ++-- arch/x86/mm/iomap_32.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/iomap.h b/arch/x86/include/asm/iomap.h index f35eb45d6576..c4191b3b7056 100644 --- a/arch/x86/include/asm/iomap.h +++ b/arch/x86/include/asm/iomap.h @@ -26,11 +26,11 @@ #include #include -void * +void __iomem * iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot); void -iounmap_atomic(void *kvaddr, enum km_type type); +iounmap_atomic(void __iomem *kvaddr, enum km_type type); int iomap_create_wc(resource_size_t base, unsigned long size, pgprot_t *prot); diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c index 84e236ce76ba..72fc70cf6184 100644 --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c @@ -74,7 +74,7 @@ void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) /* * Map 'pfn' using fixed map 'type' and protections 'prot' */ -void * +void __iomem * iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) { /* @@ -86,12 +86,12 @@ iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC)) prot = PAGE_KERNEL_UC_MINUS; - return kmap_atomic_prot_pfn(pfn, type, prot); + return (void __force __iomem *) kmap_atomic_prot_pfn(pfn, type, prot); } EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn); void -iounmap_atomic(void *kvaddr, enum km_type type) +iounmap_atomic(void __iomem *kvaddr, enum km_type type) { unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); -- cgit v1.2.2 From 1389298f7d14f179c2fa4b4b343079bd56082c70 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Fri, 27 Aug 2010 11:20:07 +0200 Subject: x86, mcheck: Avoid duplicate sysfs links/files for thresholding banks kobject_add_internal failed for threshold_bank2 with -EEXIST, don't try to register things with the same name in the same directory: Pid: 1, comm: swapper Tainted: G W 2.6.31 #1 Call Trace: [] ? kobject_add_internal+0x156/0x180 [] ? kobject_add+0x66/0x6b [] ? kobject_init+0x42/0x82 [] ? kobject_create_and_add+0x34/0x63 [] ? threshold_create_bank+0x14f/0x259 [] ? mce_create_device+0x8d/0x1b8 [] ? threshold_init_device+0x3f/0x80 [] ? threshold_init_device+0x0/0x80 [] ? do_one_initcall+0x4f/0x143 [] ? kernel_init+0x14c/0x1a2 [] ? child_rip+0xa/0x20 [] ? kernel_init+0x0/0x1a2 [] ? child_rip+0x0/0x20 kobject_create_and_add: kobject_add error: -17 (Probably the for_each_cpu loop should be entirely removed.) Signed-off-by: Andreas Herrmann LKML-Reference: <20100827092006.GB5348@loge.amd.com> Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 224392d8fe8c..5e975298fa81 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -530,7 +530,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) err = -ENOMEM; goto out; } - if (!alloc_cpumask_var(&b->cpus, GFP_KERNEL)) { + if (!zalloc_cpumask_var(&b->cpus, GFP_KERNEL)) { kfree(b); err = -ENOMEM; goto out; @@ -543,7 +543,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) #ifndef CONFIG_SMP cpumask_setall(b->cpus); #else - cpumask_copy(b->cpus, c->llc_shared_map); + cpumask_set_cpu(cpu, b->cpus); #endif per_cpu(threshold_banks, cpu)[bank] = b; -- cgit v1.2.2 From 8d2602e0778299e2d6084f03086b716d6e7a1e1e Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Fri, 20 Aug 2010 16:44:33 +0200 Subject: AT91: change dma resource index Reported-by: Dan Liang Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/at91sam9g45_devices.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 809114d5a5a6..501ac6fae2e7 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -46,7 +46,7 @@ static struct resource hdmac_resources[] = { .end = AT91_BASE_SYS + AT91_DMA + SZ_512 - 1, .flags = IORESOURCE_MEM, }, - [2] = { + [1] = { .start = AT91SAM9G45_ID_DMA, .end = AT91SAM9G45_ID_DMA, .flags = IORESOURCE_IRQ, -- cgit v1.2.2 From 3ab61eb9fd751336d1b3ad50ec7704bd3b62213f Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 31 Aug 2010 16:52:11 +0100 Subject: h8300: IRQ flags should be stored in an unsigned long Fix h8300's asm/atomic.h to store the IRQ flags in an unsigned long to deal with warnings of the following type: arch/h8300/include/asm/atomic.h: In function 'atomic_add_return': arch/h8300/include/asm/atomic.h:22: warning: comparison of distinct pointer types lacks a cast arch/h8300/include/asm/atomic.h:24: warning: comparison of distinct pointer types lacks a cast Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/h8300/include/asm/atomic.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/h8300/include/asm/atomic.h b/arch/h8300/include/asm/atomic.h index e936804b7508..984221abb66d 100644 --- a/arch/h8300/include/asm/atomic.h +++ b/arch/h8300/include/asm/atomic.h @@ -18,7 +18,8 @@ static __inline__ int atomic_add_return(int i, atomic_t *v) { - int ret,flags; + unsigned long flags; + int ret; local_irq_save(flags); ret = v->counter += i; local_irq_restore(flags); @@ -30,7 +31,8 @@ static __inline__ int atomic_add_return(int i, atomic_t *v) static __inline__ int atomic_sub_return(int i, atomic_t *v) { - int ret,flags; + unsigned long flags; + int ret; local_irq_save(flags); ret = v->counter -= i; local_irq_restore(flags); @@ -42,7 +44,8 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v) static __inline__ int atomic_inc_return(atomic_t *v) { - int ret,flags; + unsigned long flags; + int ret; local_irq_save(flags); v->counter++; ret = v->counter; @@ -64,7 +67,8 @@ static __inline__ int atomic_inc_return(atomic_t *v) static __inline__ int atomic_dec_return(atomic_t *v) { - int ret,flags; + unsigned long flags; + int ret; local_irq_save(flags); --v->counter; ret = v->counter; @@ -76,7 +80,8 @@ static __inline__ int atomic_dec_return(atomic_t *v) static __inline__ int atomic_dec_and_test(atomic_t *v) { - int ret,flags; + unsigned long flags; + int ret; local_irq_save(flags); --v->counter; ret = v->counter; -- cgit v1.2.2 From b857189d94e0d8a05943349618c4f84dbc57144c Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 31 Aug 2010 16:52:16 +0100 Subject: h8300: Fix die() Fix h8300's die() to take care of a number of problems: CC arch/h8300/kernel/traps.o In file included from arch/h8300/include/asm/bitops.h:10, from include/linux/bitops.h:22, from include/linux/kernel.h:17, from include/linux/sched.h:54, from arch/h8300/kernel/traps.c:18: arch/h8300/include/asm/system.h:136: warning: 'struct pt_regs' declared inside parameter list arch/h8300/include/asm/system.h:136: warning: its scope is only this definition or declaration, which is probably not what you want arch/h8300/kernel/traps.c:100: error: conflicting types for 'die' arch/h8300/include/asm/system.h:136: error: previous declaration of 'die' was here make[2]: *** [arch/h8300/kernel/traps.o] Error 1 Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/h8300/include/asm/system.h | 4 +++- arch/h8300/kernel/traps.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/h8300/include/asm/system.h b/arch/h8300/include/asm/system.h index d98d97685f06..16bf1560ff68 100644 --- a/arch/h8300/include/asm/system.h +++ b/arch/h8300/include/asm/system.h @@ -3,6 +3,8 @@ #include +struct pt_regs; + /* * switch_to(n) should switch tasks to task ptr, first checking that * ptr isn't the current task, in which case it does nothing. This @@ -155,6 +157,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz #define arch_align_stack(x) (x) -void die(char *str, struct pt_regs *fp, unsigned long err); +extern void die(const char *str, struct pt_regs *fp, unsigned long err); #endif /* _H8300_SYSTEM_H */ diff --git a/arch/h8300/kernel/traps.c b/arch/h8300/kernel/traps.c index 3c0b66bc669e..dfa05bd908b6 100644 --- a/arch/h8300/kernel/traps.c +++ b/arch/h8300/kernel/traps.c @@ -96,7 +96,7 @@ static void dump(struct pt_regs *fp) printk("\n\n"); } -void die(char *str, struct pt_regs *fp, unsigned long err) +void die(const char *str, struct pt_regs *fp, unsigned long err) { static int diecount; -- cgit v1.2.2 From 1e72910e248fb94839cd63c0c62107b1f15716f9 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 31 Aug 2010 16:52:21 +0100 Subject: h8300: Fix missing consts in kernel_execve() Fix missing consts in h8300's kernel_execve(): arch/h8300/kernel/sys_h8300.c: In function 'kernel_execve': arch/h8300/kernel/sys_h8300.c:59: warning: initialization from incompatible pointer type arch/h8300/kernel/sys_h8300.c:60: warning: initialization from incompatible pointer type Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/h8300/kernel/sys_h8300.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c index dc1ac0243b78..aaf5e5a48f93 100644 --- a/arch/h8300/kernel/sys_h8300.c +++ b/arch/h8300/kernel/sys_h8300.c @@ -56,8 +56,8 @@ int kernel_execve(const char *filename, const char *const envp[]) { register long res __asm__("er0"); - register char *const *_c __asm__("er3") = envp; - register char *const *_b __asm__("er2") = argv; + register const char *const *_c __asm__("er3") = envp; + register const char *const *_b __asm__("er2") = argv; register const char * _a __asm__("er1") = filename; __asm__ __volatile__ ("mov.l %1,er0\n\t" "trapa #0\n\t" -- cgit v1.2.2 From e6ba59bcae6968ee18ef5a237a8020a0ea331ae1 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Fri, 3 Sep 2010 11:15:19 +1000 Subject: m68knommu: fix missing linker segments Recent changes to linker segments that hold per-cpu data broke linking for m68knommu targets: LD vmlinux /usr/local/bin/m68k-uclinux-ld.real: error: no memory region specified for loadable section `.data..shared_aligned' Add missing segments into the m68knommu linker script. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- arch/m68knommu/kernel/vmlinux.lds.S | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S index a91b2713451d..ef332136f96d 100644 --- a/arch/m68knommu/kernel/vmlinux.lds.S +++ b/arch/m68knommu/kernel/vmlinux.lds.S @@ -150,6 +150,8 @@ SECTIONS { _sdata = . ; DATA_DATA CACHELINE_ALIGNED_DATA(32) + PAGE_ALIGNED_DATA(PAGE_SIZE) + *(.data..shared_aligned) INIT_TASK_DATA(THREAD_SIZE) _edata = . ; } > DATA -- cgit v1.2.2 From 3a4b5dca53aecb16db9e007d782b2d1e757e941a Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 3 Sep 2010 10:39:59 +0100 Subject: ARM: 6355/1: hw-breakpoint: add mechanism for hooking into prefetch aborts On ARM processors with hardware breakpoint and watchpoint support, triggering these events results in a debug exception. These manifest as prefetch and data aborts respectively. arch/arm/mm/fault.c already provides hook_fault_code for hooking into data aborts dependent on the DFSR. This patch adds a new function, hook_ifault_code for hooking into prefetch aborts in the same manner. Cc: Frederic Weisbecker Cc: S. Karthikeyan Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/system.h | 4 ++++ arch/arm/mm/fault.c | 13 +++++++++++++ 2 files changed, 17 insertions(+) (limited to 'arch') diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 8ba1ccf82a02..b516cdea5ae2 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -85,6 +85,10 @@ void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *), int sig, int code, const char *name); +void hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, + struct pt_regs *), + int sig, int code, const char *name); + #define xchg(ptr,x) \ ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 23b0b03af5ea..1e21e125fe3a 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -581,6 +581,19 @@ static struct fsr_info ifsr_info[] = { { do_bad, SIGBUS, 0, "unknown 31" }, }; +void __init +hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *), + int sig, int code, const char *name) +{ + if (nr < 0 || nr >= ARRAY_SIZE(ifsr_info)) + BUG(); + + ifsr_info[nr].fn = fn; + ifsr_info[nr].sig = sig; + ifsr_info[nr].code = code; + ifsr_info[nr].name = name; +} + asmlinkage void __exception do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) { -- cgit v1.2.2 From f81ef4a920c8e1af75adf9f15042c2daa49d3cb3 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 3 Sep 2010 10:41:08 +0100 Subject: ARM: 6356/1: hw-breakpoint: add ARM backend for the hw-breakpoint framework The hw-breakpoint framework in the kernel requires architecture-specific support in order to install, remove, validate and manage hardware breakpoints. This patch adds initial support for this framework to the ARM architecture, but restricts the number of watchpoints to a single resource to get around the fact that the Data Fault Address Register is unknown when a watchpoint debug exception is taken. On cores with v7 debug, the Kernel can handle breakpoint and watchpoint exceptions occuring from userspace. Older cores require clients to handle the exception themselves by registering an appropriate overflow handler or, in the case of ptrace, handling the raised SIGTRAP. The memory-mapped extended debug interface is unsupported due to its unreliability in real implementations. Cc: Frederic Weisbecker Cc: S. Karthikeyan Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/hw_breakpoint.h | 123 +++++ arch/arm/kernel/hw_breakpoint.c | 849 +++++++++++++++++++++++++++++++++++ 2 files changed, 972 insertions(+) create mode 100644 arch/arm/include/asm/hw_breakpoint.h create mode 100644 arch/arm/kernel/hw_breakpoint.c (limited to 'arch') diff --git a/arch/arm/include/asm/hw_breakpoint.h b/arch/arm/include/asm/hw_breakpoint.h new file mode 100644 index 000000000000..33048c700caa --- /dev/null +++ b/arch/arm/include/asm/hw_breakpoint.h @@ -0,0 +1,123 @@ +#ifndef _ARM_HW_BREAKPOINT_H +#define _ARM_HW_BREAKPOINT_H + +#ifdef __KERNEL__ +struct arch_hw_breakpoint_ctrl { + u32 __reserved : 9, + mismatch : 1, + : 9, + len : 8, + type : 2, + privilege : 2, + enabled : 1; +}; + +struct arch_hw_breakpoint { + u32 address; + u32 trigger; + struct perf_event *suspended_wp; + struct arch_hw_breakpoint_ctrl ctrl; +}; + +static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl) +{ + return (ctrl.mismatch << 22) | (ctrl.len << 5) | (ctrl.type << 3) | + (ctrl.privilege << 1) | ctrl.enabled; +} + +static inline void decode_ctrl_reg(u32 reg, + struct arch_hw_breakpoint_ctrl *ctrl) +{ + ctrl->enabled = reg & 0x1; + reg >>= 1; + ctrl->privilege = reg & 0x3; + reg >>= 2; + ctrl->type = reg & 0x3; + reg >>= 2; + ctrl->len = reg & 0xff; + reg >>= 17; + ctrl->mismatch = reg & 0x1; +} + +/* Debug architecture numbers. */ +#define ARM_DEBUG_ARCH_RESERVED 0 /* In case of ptrace ABI updates. */ +#define ARM_DEBUG_ARCH_V6 1 +#define ARM_DEBUG_ARCH_V6_1 2 +#define ARM_DEBUG_ARCH_V7_ECP14 3 +#define ARM_DEBUG_ARCH_V7_MM 4 + +/* Breakpoint */ +#define ARM_BREAKPOINT_EXECUTE 0 + +/* Watchpoints */ +#define ARM_BREAKPOINT_LOAD 1 +#define ARM_BREAKPOINT_STORE 2 + +/* Privilege Levels */ +#define ARM_BREAKPOINT_PRIV 1 +#define ARM_BREAKPOINT_USER 2 + +/* Lengths */ +#define ARM_BREAKPOINT_LEN_1 0x1 +#define ARM_BREAKPOINT_LEN_2 0x3 +#define ARM_BREAKPOINT_LEN_4 0xf +#define ARM_BREAKPOINT_LEN_8 0xff + +/* Limits */ +#define ARM_MAX_BRP 16 +#define ARM_MAX_WRP 16 +#define ARM_MAX_HBP_SLOTS (ARM_MAX_BRP + ARM_MAX_WRP) + +/* DSCR method of entry bits. */ +#define ARM_DSCR_MOE(x) ((x >> 2) & 0xf) +#define ARM_ENTRY_BREAKPOINT 0x1 +#define ARM_ENTRY_ASYNC_WATCHPOINT 0x2 +#define ARM_ENTRY_SYNC_WATCHPOINT 0xa + +/* DSCR monitor/halting bits. */ +#define ARM_DSCR_HDBGEN (1 << 14) +#define ARM_DSCR_MDBGEN (1 << 15) + +/* opcode2 numbers for the co-processor instructions. */ +#define ARM_OP2_BVR 4 +#define ARM_OP2_BCR 5 +#define ARM_OP2_WVR 6 +#define ARM_OP2_WCR 7 + +/* Base register numbers for the debug registers. */ +#define ARM_BASE_BVR 64 +#define ARM_BASE_BCR 80 +#define ARM_BASE_WVR 96 +#define ARM_BASE_WCR 112 + +/* Accessor macros for the debug registers. */ +#define ARM_DBG_READ(M, OP2, VAL) do {\ + asm volatile("mrc p14, 0, %0, c0," #M ", " #OP2 : "=r" (VAL));\ +} while (0) + +#define ARM_DBG_WRITE(M, OP2, VAL) do {\ + asm volatile("mcr p14, 0, %0, c0," #M ", " #OP2 : : "r" (VAL));\ +} while (0) + +struct notifier_block; +struct perf_event; +struct pmu; +struct task_struct; + +extern struct pmu perf_ops_bp; +extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, + int *gen_len, int *gen_type); +extern int arch_check_bp_in_kernelspace(struct perf_event *bp); +extern int arch_validate_hwbkpt_settings(struct perf_event *bp); +extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused, + unsigned long val, void *data); +extern u8 arch_get_debug_arch(void); +extern u8 arch_get_max_wp_len(void); + +int arch_install_hw_breakpoint(struct perf_event *bp); +void arch_uninstall_hw_breakpoint(struct perf_event *bp); +void hw_breakpoint_pmu_read(struct perf_event *bp); +int hw_breakpoint_slots(int type); + +#endif /* __KERNEL__ */ +#endif /* _ARM_HW_BREAKPOINT_H */ diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c new file mode 100644 index 000000000000..54593b0c241b --- /dev/null +++ b/arch/arm/kernel/hw_breakpoint.c @@ -0,0 +1,849 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009, 2010 ARM Limited + * + * Author: Will Deacon + */ + +/* + * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility, + * using the CPU's debug registers. + */ +#define pr_fmt(fmt) "hw-breakpoint: " fmt + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Breakpoint currently in use for each BRP. */ +static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]); + +/* Watchpoint currently in use for each WRP. */ +static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]); + +/* Number of BRP/WRP registers on this CPU. */ +static int core_num_brps; +static int core_num_wrps; + +/* Debug architecture version. */ +static u8 debug_arch; + +/* Maximum supported watchpoint length. */ +static u8 max_watchpoint_len; + +/* Determine number of BRP registers available. */ +static int get_num_brps(void) +{ + u32 didr; + ARM_DBG_READ(c0, 0, didr); + return ((didr >> 24) & 0xf) + 1; +} + +/* Determine number of WRP registers available. */ +static int get_num_wrps(void) +{ + /* + * FIXME: When a watchpoint fires, the only way to work out which + * watchpoint it was is by disassembling the faulting instruction + * and working out the address of the memory access. + * + * Furthermore, we can only do this if the watchpoint was precise + * since imprecise watchpoints prevent us from calculating register + * based addresses. + * + * For the time being, we only report 1 watchpoint register so we + * always know which watchpoint fired. In the future we can either + * add a disassembler and address generation emulator, or we can + * insert a check to see if the DFAR is set on watchpoint exception + * entry [the ARM ARM states that the DFAR is UNKNOWN, but + * experience shows that it is set on some implementations]. + */ + +#if 0 + u32 didr, wrps; + ARM_DBG_READ(c0, 0, didr); + return ((didr >> 28) & 0xf) + 1; +#endif + + return 1; +} + +int hw_breakpoint_slots(int type) +{ + /* + * We can be called early, so don't rely on + * our static variables being initialised. + */ + switch (type) { + case TYPE_INST: + return get_num_brps(); + case TYPE_DATA: + return get_num_wrps(); + default: + pr_warning("unknown slot type: %d\n", type); + return 0; + } +} + +/* Determine debug architecture. */ +static u8 get_debug_arch(void) +{ + u32 didr; + + /* Do we implement the extended CPUID interface? */ + if (((read_cpuid_id() >> 16) & 0xf) != 0xf) { + pr_warning("CPUID feature registers not supported. " + "Assuming v6 debug is present.\n"); + return ARM_DEBUG_ARCH_V6; + } + + ARM_DBG_READ(c0, 0, didr); + return (didr >> 16) & 0xf; +} + +/* Does this core support mismatch breakpoints? */ +static int core_has_mismatch_bps(void) +{ + return debug_arch >= ARM_DEBUG_ARCH_V7_ECP14 && core_num_brps > 1; +} + +u8 arch_get_debug_arch(void) +{ + return debug_arch; +} + +#define READ_WB_REG_CASE(OP2, M, VAL) \ + case ((OP2 << 4) + M): \ + ARM_DBG_READ(c ## M, OP2, VAL); \ + break + +#define WRITE_WB_REG_CASE(OP2, M, VAL) \ + case ((OP2 << 4) + M): \ + ARM_DBG_WRITE(c ## M, OP2, VAL);\ + break + +#define GEN_READ_WB_REG_CASES(OP2, VAL) \ + READ_WB_REG_CASE(OP2, 0, VAL); \ + READ_WB_REG_CASE(OP2, 1, VAL); \ + READ_WB_REG_CASE(OP2, 2, VAL); \ + READ_WB_REG_CASE(OP2, 3, VAL); \ + READ_WB_REG_CASE(OP2, 4, VAL); \ + READ_WB_REG_CASE(OP2, 5, VAL); \ + READ_WB_REG_CASE(OP2, 6, VAL); \ + READ_WB_REG_CASE(OP2, 7, VAL); \ + READ_WB_REG_CASE(OP2, 8, VAL); \ + READ_WB_REG_CASE(OP2, 9, VAL); \ + READ_WB_REG_CASE(OP2, 10, VAL); \ + READ_WB_REG_CASE(OP2, 11, VAL); \ + READ_WB_REG_CASE(OP2, 12, VAL); \ + READ_WB_REG_CASE(OP2, 13, VAL); \ + READ_WB_REG_CASE(OP2, 14, VAL); \ + READ_WB_REG_CASE(OP2, 15, VAL) + +#define GEN_WRITE_WB_REG_CASES(OP2, VAL) \ + WRITE_WB_REG_CASE(OP2, 0, VAL); \ + WRITE_WB_REG_CASE(OP2, 1, VAL); \ + WRITE_WB_REG_CASE(OP2, 2, VAL); \ + WRITE_WB_REG_CASE(OP2, 3, VAL); \ + WRITE_WB_REG_CASE(OP2, 4, VAL); \ + WRITE_WB_REG_CASE(OP2, 5, VAL); \ + WRITE_WB_REG_CASE(OP2, 6, VAL); \ + WRITE_WB_REG_CASE(OP2, 7, VAL); \ + WRITE_WB_REG_CASE(OP2, 8, VAL); \ + WRITE_WB_REG_CASE(OP2, 9, VAL); \ + WRITE_WB_REG_CASE(OP2, 10, VAL); \ + WRITE_WB_REG_CASE(OP2, 11, VAL); \ + WRITE_WB_REG_CASE(OP2, 12, VAL); \ + WRITE_WB_REG_CASE(OP2, 13, VAL); \ + WRITE_WB_REG_CASE(OP2, 14, VAL); \ + WRITE_WB_REG_CASE(OP2, 15, VAL) + +static u32 read_wb_reg(int n) +{ + u32 val = 0; + + switch (n) { + GEN_READ_WB_REG_CASES(ARM_OP2_BVR, val); + GEN_READ_WB_REG_CASES(ARM_OP2_BCR, val); + GEN_READ_WB_REG_CASES(ARM_OP2_WVR, val); + GEN_READ_WB_REG_CASES(ARM_OP2_WCR, val); + default: + pr_warning("attempt to read from unknown breakpoint " + "register %d\n", n); + } + + return val; +} + +static void write_wb_reg(int n, u32 val) +{ + switch (n) { + GEN_WRITE_WB_REG_CASES(ARM_OP2_BVR, val); + GEN_WRITE_WB_REG_CASES(ARM_OP2_BCR, val); + GEN_WRITE_WB_REG_CASES(ARM_OP2_WVR, val); + GEN_WRITE_WB_REG_CASES(ARM_OP2_WCR, val); + default: + pr_warning("attempt to write to unknown breakpoint " + "register %d\n", n); + } + isb(); +} + +/* + * In order to access the breakpoint/watchpoint control registers, + * we must be running in debug monitor mode. Unfortunately, we can + * be put into halting debug mode at any time by an external debugger + * but there is nothing we can do to prevent that. + */ +static int enable_monitor_mode(void) +{ + u32 dscr; + int ret = 0; + + ARM_DBG_READ(c1, 0, dscr); + + /* Ensure that halting mode is disabled. */ + if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, "halting debug mode enabled." + "Unable to access hardware resources.")) { + ret = -EPERM; + goto out; + } + + /* Write to the corresponding DSCR. */ + switch (debug_arch) { + case ARM_DEBUG_ARCH_V6: + case ARM_DEBUG_ARCH_V6_1: + ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN)); + break; + case ARM_DEBUG_ARCH_V7_ECP14: + ARM_DBG_WRITE(c2, 2, (dscr | ARM_DSCR_MDBGEN)); + break; + default: + ret = -ENODEV; + goto out; + } + + /* Check that the write made it through. */ + ARM_DBG_READ(c1, 0, dscr); + if (WARN_ONCE(!(dscr & ARM_DSCR_MDBGEN), + "failed to enable monitor mode.")) { + ret = -EPERM; + } + +out: + return ret; +} + +/* + * Check if 8-bit byte-address select is available. + * This clobbers WRP 0. + */ +static u8 get_max_wp_len(void) +{ + u32 ctrl_reg; + struct arch_hw_breakpoint_ctrl ctrl; + u8 size = 4; + + if (debug_arch < ARM_DEBUG_ARCH_V7_ECP14) + goto out; + + if (enable_monitor_mode()) + goto out; + + memset(&ctrl, 0, sizeof(ctrl)); + ctrl.len = ARM_BREAKPOINT_LEN_8; + ctrl_reg = encode_ctrl_reg(ctrl); + + write_wb_reg(ARM_BASE_WVR, 0); + write_wb_reg(ARM_BASE_WCR, ctrl_reg); + if ((read_wb_reg(ARM_BASE_WCR) & ctrl_reg) == ctrl_reg) + size = 8; + +out: + return size; +} + +u8 arch_get_max_wp_len(void) +{ + return max_watchpoint_len; +} + +/* + * Handler for reactivating a suspended watchpoint when the single + * step `mismatch' breakpoint is triggered. + */ +static void wp_single_step_handler(struct perf_event *bp, int unused, + struct perf_sample_data *data, + struct pt_regs *regs) +{ + perf_event_enable(counter_arch_bp(bp)->suspended_wp); + unregister_hw_breakpoint(bp); +} + +static int bp_is_single_step(struct perf_event *bp) +{ + return bp->overflow_handler == wp_single_step_handler; +} + +/* + * Install a perf counter breakpoint. + */ +int arch_install_hw_breakpoint(struct perf_event *bp) +{ + struct arch_hw_breakpoint *info = counter_arch_bp(bp); + struct perf_event **slot, **slots; + int i, max_slots, ctrl_base, val_base, ret = 0; + + /* Ensure that we are in monitor mode and halting mode is disabled. */ + ret = enable_monitor_mode(); + if (ret) + goto out; + + if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { + /* Breakpoint */ + ctrl_base = ARM_BASE_BCR; + val_base = ARM_BASE_BVR; + slots = __get_cpu_var(bp_on_reg); + max_slots = core_num_brps - 1; + + if (bp_is_single_step(bp)) { + info->ctrl.mismatch = 1; + i = max_slots; + slots[i] = bp; + goto setup; + } + } else { + /* Watchpoint */ + ctrl_base = ARM_BASE_WCR; + val_base = ARM_BASE_WVR; + slots = __get_cpu_var(wp_on_reg); + max_slots = core_num_wrps; + } + + for (i = 0; i < max_slots; ++i) { + slot = &slots[i]; + + if (!*slot) { + *slot = bp; + break; + } + } + + if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) { + ret = -EBUSY; + goto out; + } + +setup: + /* Setup the address register. */ + write_wb_reg(val_base + i, info->address); + + /* Setup the control register. */ + write_wb_reg(ctrl_base + i, encode_ctrl_reg(info->ctrl) | 0x1); + +out: + return ret; +} + +void arch_uninstall_hw_breakpoint(struct perf_event *bp) +{ + struct arch_hw_breakpoint *info = counter_arch_bp(bp); + struct perf_event **slot, **slots; + int i, max_slots, base; + + if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { + /* Breakpoint */ + base = ARM_BASE_BCR; + slots = __get_cpu_var(bp_on_reg); + max_slots = core_num_brps - 1; + + if (bp_is_single_step(bp)) { + i = max_slots; + slots[i] = NULL; + goto reset; + } + } else { + /* Watchpoint */ + base = ARM_BASE_WCR; + slots = __get_cpu_var(wp_on_reg); + max_slots = core_num_wrps; + } + + /* Remove the breakpoint. */ + for (i = 0; i < max_slots; ++i) { + slot = &slots[i]; + + if (*slot == bp) { + *slot = NULL; + break; + } + } + + if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) + return; + +reset: + /* Reset the control register. */ + write_wb_reg(base + i, 0); +} + +static int get_hbp_len(u8 hbp_len) +{ + unsigned int len_in_bytes = 0; + + switch (hbp_len) { + case ARM_BREAKPOINT_LEN_1: + len_in_bytes = 1; + break; + case ARM_BREAKPOINT_LEN_2: + len_in_bytes = 2; + break; + case ARM_BREAKPOINT_LEN_4: + len_in_bytes = 4; + break; + case ARM_BREAKPOINT_LEN_8: + len_in_bytes = 8; + break; + } + + return len_in_bytes; +} + +/* + * Check whether bp virtual address is in kernel space. + */ +int arch_check_bp_in_kernelspace(struct perf_event *bp) +{ + unsigned int len; + unsigned long va; + struct arch_hw_breakpoint *info = counter_arch_bp(bp); + + va = info->address; + len = get_hbp_len(info->ctrl.len); + + return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE); +} + +/* + * Extract generic type and length encodings from an arch_hw_breakpoint_ctrl. + * Hopefully this will disappear when ptrace can bypass the conversion + * to generic breakpoint descriptions. + */ +int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, + int *gen_len, int *gen_type) +{ + /* Type */ + switch (ctrl.type) { + case ARM_BREAKPOINT_EXECUTE: + *gen_type = HW_BREAKPOINT_X; + break; + case ARM_BREAKPOINT_LOAD: + *gen_type = HW_BREAKPOINT_R; + break; + case ARM_BREAKPOINT_STORE: + *gen_type = HW_BREAKPOINT_W; + break; + case ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE: + *gen_type = HW_BREAKPOINT_RW; + break; + default: + return -EINVAL; + } + + /* Len */ + switch (ctrl.len) { + case ARM_BREAKPOINT_LEN_1: + *gen_len = HW_BREAKPOINT_LEN_1; + break; + case ARM_BREAKPOINT_LEN_2: + *gen_len = HW_BREAKPOINT_LEN_2; + break; + case ARM_BREAKPOINT_LEN_4: + *gen_len = HW_BREAKPOINT_LEN_4; + break; + case ARM_BREAKPOINT_LEN_8: + *gen_len = HW_BREAKPOINT_LEN_8; + break; + default: + return -EINVAL; + } + + return 0; +} + +/* + * Construct an arch_hw_breakpoint from a perf_event. + */ +static int arch_build_bp_info(struct perf_event *bp) +{ + struct arch_hw_breakpoint *info = counter_arch_bp(bp); + + /* Type */ + switch (bp->attr.bp_type) { + case HW_BREAKPOINT_X: + info->ctrl.type = ARM_BREAKPOINT_EXECUTE; + break; + case HW_BREAKPOINT_R: + info->ctrl.type = ARM_BREAKPOINT_LOAD; + break; + case HW_BREAKPOINT_W: + info->ctrl.type = ARM_BREAKPOINT_STORE; + break; + case HW_BREAKPOINT_RW: + info->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE; + break; + default: + return -EINVAL; + } + + /* Len */ + switch (bp->attr.bp_len) { + case HW_BREAKPOINT_LEN_1: + info->ctrl.len = ARM_BREAKPOINT_LEN_1; + break; + case HW_BREAKPOINT_LEN_2: + info->ctrl.len = ARM_BREAKPOINT_LEN_2; + break; + case HW_BREAKPOINT_LEN_4: + info->ctrl.len = ARM_BREAKPOINT_LEN_4; + break; + case HW_BREAKPOINT_LEN_8: + info->ctrl.len = ARM_BREAKPOINT_LEN_8; + if ((info->ctrl.type != ARM_BREAKPOINT_EXECUTE) + && max_watchpoint_len >= 8) + break; + default: + return -EINVAL; + } + + /* Address */ + info->address = bp->attr.bp_addr; + + /* Privilege */ + info->ctrl.privilege = ARM_BREAKPOINT_USER; + if (arch_check_bp_in_kernelspace(bp) && !bp_is_single_step(bp)) + info->ctrl.privilege |= ARM_BREAKPOINT_PRIV; + + /* Enabled? */ + info->ctrl.enabled = !bp->attr.disabled; + + /* Mismatch */ + info->ctrl.mismatch = 0; + + return 0; +} + +/* + * Validate the arch-specific HW Breakpoint register settings. + */ +int arch_validate_hwbkpt_settings(struct perf_event *bp) +{ + struct arch_hw_breakpoint *info = counter_arch_bp(bp); + int ret = 0; + u32 bytelen, max_len, offset, alignment_mask = 0x3; + + /* Build the arch_hw_breakpoint. */ + ret = arch_build_bp_info(bp); + if (ret) + goto out; + + /* Check address alignment. */ + if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) + alignment_mask = 0x7; + if (info->address & alignment_mask) { + /* + * Try to fix the alignment. This may result in a length + * that is too large, so we must check for that. + */ + bytelen = get_hbp_len(info->ctrl.len); + max_len = info->ctrl.type == ARM_BREAKPOINT_EXECUTE ? 4 : + max_watchpoint_len; + + if (max_len >= 8) + offset = info->address & 0x7; + else + offset = info->address & 0x3; + + if (bytelen > (1 << ((max_len - (offset + 1)) >> 1))) { + ret = -EFBIG; + goto out; + } + + info->ctrl.len <<= offset; + info->address &= ~offset; + + pr_debug("breakpoint alignment fixup: length = 0x%x, " + "address = 0x%x\n", info->ctrl.len, info->address); + } + + /* + * Currently we rely on an overflow handler to take + * care of single-stepping the breakpoint when it fires. + * In the case of userspace breakpoints on a core with V7 debug, + * we can use the mismatch feature as a poor-man's hardware single-step. + */ + if (WARN_ONCE(!bp->overflow_handler && + (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_bps()), + "overflow handler required but none found")) { + ret = -EINVAL; + goto out; + } +out: + return ret; +} + +static void update_mismatch_flag(int idx, int flag) +{ + struct perf_event *bp = __get_cpu_var(bp_on_reg[idx]); + struct arch_hw_breakpoint *info; + + if (bp == NULL) + return; + + info = counter_arch_bp(bp); + + /* Update the mismatch field to enter/exit `single-step' mode */ + if (!bp->overflow_handler && info->ctrl.mismatch != flag) { + info->ctrl.mismatch = flag; + write_wb_reg(ARM_BASE_BCR + idx, encode_ctrl_reg(info->ctrl) | 0x1); + } +} + +static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs) +{ + int i; + struct perf_event *bp, **slots = __get_cpu_var(wp_on_reg); + struct arch_hw_breakpoint *info; + struct perf_event_attr attr; + + /* Without a disassembler, we can only handle 1 watchpoint. */ + BUG_ON(core_num_wrps > 1); + + hw_breakpoint_init(&attr); + attr.bp_addr = regs->ARM_pc & ~0x3; + attr.bp_len = HW_BREAKPOINT_LEN_4; + attr.bp_type = HW_BREAKPOINT_X; + + for (i = 0; i < core_num_wrps; ++i) { + rcu_read_lock(); + + if (slots[i] == NULL) { + rcu_read_unlock(); + continue; + } + + /* + * The DFAR is an unknown value. Since we only allow a + * single watchpoint, we can set the trigger to the lowest + * possible faulting address. + */ + info = counter_arch_bp(slots[i]); + info->trigger = slots[i]->attr.bp_addr; + pr_debug("watchpoint fired: address = 0x%x\n", info->trigger); + perf_bp_event(slots[i], regs); + + /* + * If no overflow handler is present, insert a temporary + * mismatch breakpoint so we can single-step over the + * watchpoint trigger. + */ + if (!slots[i]->overflow_handler) { + bp = register_user_hw_breakpoint(&attr, + wp_single_step_handler, + current); + counter_arch_bp(bp)->suspended_wp = slots[i]; + perf_event_disable(slots[i]); + } + + rcu_read_unlock(); + } +} + +static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs) +{ + int i; + int mismatch; + u32 ctrl_reg, val, addr; + struct perf_event *bp, **slots = __get_cpu_var(bp_on_reg); + struct arch_hw_breakpoint *info; + struct arch_hw_breakpoint_ctrl ctrl; + + /* The exception entry code places the amended lr in the PC. */ + addr = regs->ARM_pc; + + for (i = 0; i < core_num_brps; ++i) { + rcu_read_lock(); + + bp = slots[i]; + + if (bp == NULL) { + rcu_read_unlock(); + continue; + } + + mismatch = 0; + + /* Check if the breakpoint value matches. */ + val = read_wb_reg(ARM_BASE_BVR + i); + if (val != (addr & ~0x3)) + goto unlock; + + /* Possible match, check the byte address select to confirm. */ + ctrl_reg = read_wb_reg(ARM_BASE_BCR + i); + decode_ctrl_reg(ctrl_reg, &ctrl); + if ((1 << (addr & 0x3)) & ctrl.len) { + mismatch = 1; + info = counter_arch_bp(bp); + info->trigger = addr; + } + +unlock: + if ((mismatch && !info->ctrl.mismatch) || bp_is_single_step(bp)) { + pr_debug("breakpoint fired: address = 0x%x\n", addr); + perf_bp_event(bp, regs); + } + + update_mismatch_flag(i, mismatch); + rcu_read_unlock(); + } +} + +/* + * Called from either the Data Abort Handler [watchpoint] or the + * Prefetch Abort Handler [breakpoint]. + */ +static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr, + struct pt_regs *regs) +{ + int ret = 1; /* Unhandled fault. */ + u32 dscr; + + /* We only handle watchpoints and hardware breakpoints. */ + ARM_DBG_READ(c1, 0, dscr); + + /* Perform perf callbacks. */ + switch (ARM_DSCR_MOE(dscr)) { + case ARM_ENTRY_BREAKPOINT: + breakpoint_handler(addr, regs); + break; + case ARM_ENTRY_ASYNC_WATCHPOINT: + WARN_ON("Asynchronous watchpoint exception taken. " + "Debugging results may be unreliable"); + case ARM_ENTRY_SYNC_WATCHPOINT: + watchpoint_handler(addr, regs); + break; + default: + goto out; + } + + ret = 0; +out: + return ret; +} + +/* + * One-time initialisation. + */ +static void __init reset_ctrl_regs(void *unused) +{ + int i; + + if (enable_monitor_mode()) + return; + + for (i = 0; i < core_num_brps; ++i) { + write_wb_reg(ARM_BASE_BCR + i, 0UL); + write_wb_reg(ARM_BASE_BVR + i, 0UL); + } + + for (i = 0; i < core_num_wrps; ++i) { + write_wb_reg(ARM_BASE_WCR + i, 0UL); + write_wb_reg(ARM_BASE_WVR + i, 0UL); + } +} + +static int __init arch_hw_breakpoint_init(void) +{ + int ret = 0; + u32 dscr; + + debug_arch = get_debug_arch(); + + if (debug_arch > ARM_DEBUG_ARCH_V7_ECP14) { + pr_info("debug architecture 0x%x unsupported.\n", debug_arch); + ret = -ENODEV; + goto out; + } + + /* Determine how many BRPs/WRPs are available. */ + core_num_brps = get_num_brps(); + core_num_wrps = get_num_wrps(); + + pr_info("found %d breakpoint and %d watchpoint registers.\n", + core_num_brps, core_num_wrps); + + if (core_has_mismatch_bps()) + pr_info("1 breakpoint reserved for watchpoint single-step.\n"); + + ARM_DBG_READ(c1, 0, dscr); + if (dscr & ARM_DSCR_HDBGEN) { + pr_warning("halting debug mode enabled. Assuming maximum " + "watchpoint size of 4 bytes."); + } else { + /* Work out the maximum supported watchpoint length. */ + max_watchpoint_len = get_max_wp_len(); + pr_info("maximum watchpoint size is %u bytes.\n", + max_watchpoint_len); + + /* + * Reset the breakpoint resources. We assume that a halting + * debugger will leave the world in a nice state for us. + */ + smp_call_function(reset_ctrl_regs, NULL, 1); + reset_ctrl_regs(NULL); + } + + /* Register debug fault handler. */ + hook_fault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT, + "watchpoint debug exception"); + hook_ifault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT, + "breakpoint debug exception"); + +out: + return ret; +} +arch_initcall(arch_hw_breakpoint_init); + +void hw_breakpoint_pmu_read(struct perf_event *bp) +{ +} + +/* + * Dummy function to register with die_notifier. + */ +int hw_breakpoint_exceptions_notify(struct notifier_block *unused, + unsigned long val, void *data) +{ + return NOTIFY_DONE; +} -- cgit v1.2.2 From 864232fa1a2f8dfe003438ef0851a56722740f3e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 3 Sep 2010 10:42:55 +0100 Subject: ARM: 6357/1: hw-breakpoint: add new ptrace requests for hw-breakpoint interaction For debuggers to take advantage of the hw-breakpoint framework in the kernel, it is necessary to expose the API calls via a ptrace interface. This patch exposes the hardware breakpoints framework as a collection of virtual registers, accesible using PTRACE_SETHBPREGS and PTRACE_GETHBPREGS requests. The breakpoints are stored in the debug_info struct of the running thread. Cc: Frederic Weisbecker Cc: S. Karthikeyan Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/hw_breakpoint.h | 12 +- arch/arm/include/asm/processor.h | 4 + arch/arm/include/asm/ptrace.h | 2 + arch/arm/kernel/process.c | 5 + arch/arm/kernel/ptrace.c | 239 +++++++++++++++++++++++++++++++++++ 5 files changed, 261 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/include/asm/hw_breakpoint.h b/arch/arm/include/asm/hw_breakpoint.h index 33048c700caa..4d8ae9d67abe 100644 --- a/arch/arm/include/asm/hw_breakpoint.h +++ b/arch/arm/include/asm/hw_breakpoint.h @@ -2,6 +2,11 @@ #define _ARM_HW_BREAKPOINT_H #ifdef __KERNEL__ + +struct task_struct; + +#ifdef CONFIG_HAVE_HW_BREAKPOINT + struct arch_hw_breakpoint_ctrl { u32 __reserved : 9, mismatch : 1, @@ -102,7 +107,6 @@ static inline void decode_ctrl_reg(u32 reg, struct notifier_block; struct perf_event; struct pmu; -struct task_struct; extern struct pmu perf_ops_bp; extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, @@ -111,13 +115,19 @@ extern int arch_check_bp_in_kernelspace(struct perf_event *bp); extern int arch_validate_hwbkpt_settings(struct perf_event *bp); extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused, unsigned long val, void *data); + extern u8 arch_get_debug_arch(void); extern u8 arch_get_max_wp_len(void); +extern void clear_ptrace_hw_breakpoint(struct task_struct *tsk); int arch_install_hw_breakpoint(struct perf_event *bp); void arch_uninstall_hw_breakpoint(struct perf_event *bp); void hw_breakpoint_pmu_read(struct perf_event *bp); int hw_breakpoint_slots(int type); +#else +static inline void clear_ptrace_hw_breakpoint(struct task_struct *tsk) {} + +#endif /* CONFIG_HAVE_HW_BREAKPOINT */ #endif /* __KERNEL__ */ #endif /* _ARM_HW_BREAKPOINT_H */ diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h index 7bed3daf83b8..67357baaeeeb 100644 --- a/arch/arm/include/asm/processor.h +++ b/arch/arm/include/asm/processor.h @@ -19,6 +19,7 @@ #ifdef __KERNEL__ +#include #include #include @@ -41,6 +42,9 @@ struct debug_entry { struct debug_info { int nsaved; struct debug_entry bp[2]; +#ifdef CONFIG_HAVE_HW_BREAKPOINT + struct perf_event *hbp[ARM_MAX_HBP_SLOTS]; +#endif }; struct thread_struct { diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 7ce15eb15f72..783d50f32618 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -29,6 +29,8 @@ #define PTRACE_SETCRUNCHREGS 26 #define PTRACE_GETVFPREGS 27 #define PTRACE_SETVFPREGS 28 +#define PTRACE_GETHBPREGS 29 +#define PTRACE_SETHBPREGS 30 /* * PSR bits diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 401e38be1f78..974af1c3eb1d 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -317,6 +318,8 @@ void flush_thread(void) struct thread_info *thread = current_thread_info(); struct task_struct *tsk = current; + flush_ptrace_hw_breakpoint(tsk); + memset(thread->used_cp, 0, sizeof(thread->used_cp)); memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); memset(&thread->fpstate, 0, sizeof(union fp_state)); @@ -345,6 +348,8 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start, thread->cpu_context.sp = (unsigned long)childregs; thread->cpu_context.pc = (unsigned long)ret_from_fork; + clear_ptrace_hw_breakpoint(p); + if (clone_flags & CLONE_SETTLS) thread->tp_value = regs->ARM_r3; diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index f99d489822d5..e0cb6370ed14 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include @@ -847,6 +849,232 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data) } #endif +#ifdef CONFIG_HAVE_HW_BREAKPOINT +/* + * Convert a virtual register number into an index for a thread_info + * breakpoint array. Breakpoints are identified using positive numbers + * whilst watchpoints are negative. The registers are laid out as pairs + * of (address, control), each pair mapping to a unique hw_breakpoint struct. + * Register 0 is reserved for describing resource information. + */ +static int ptrace_hbp_num_to_idx(long num) +{ + if (num < 0) + num = (ARM_MAX_BRP << 1) - num; + return (num - 1) >> 1; +} + +/* + * Returns the virtual register number for the address of the + * breakpoint at index idx. + */ +static long ptrace_hbp_idx_to_num(int idx) +{ + long mid = ARM_MAX_BRP << 1; + long num = (idx << 1) + 1; + return num > mid ? mid - num : num; +} + +/* + * Handle hitting a HW-breakpoint. + */ +static void ptrace_hbptriggered(struct perf_event *bp, int unused, + struct perf_sample_data *data, + struct pt_regs *regs) +{ + struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp); + long num; + int i; + siginfo_t info; + + for (i = 0; i < ARM_MAX_HBP_SLOTS; ++i) + if (current->thread.debug.hbp[i] == bp) + break; + + num = (i == ARM_MAX_HBP_SLOTS) ? 0 : ptrace_hbp_idx_to_num(i); + + info.si_signo = SIGTRAP; + info.si_errno = (int)num; + info.si_code = TRAP_HWBKPT; + info.si_addr = (void __user *)(bkpt->trigger); + + force_sig_info(SIGTRAP, &info, current); +} + +/* + * Set ptrace breakpoint pointers to zero for this task. + * This is required in order to prevent child processes from unregistering + * breakpoints held by their parent. + */ +void clear_ptrace_hw_breakpoint(struct task_struct *tsk) +{ + memset(tsk->thread.debug.hbp, 0, sizeof(tsk->thread.debug.hbp)); +} + +/* + * Unregister breakpoints from this task and reset the pointers in + * the thread_struct. + */ +void flush_ptrace_hw_breakpoint(struct task_struct *tsk) +{ + int i; + struct thread_struct *t = &tsk->thread; + + for (i = 0; i < ARM_MAX_HBP_SLOTS; i++) { + if (t->debug.hbp[i]) { + unregister_hw_breakpoint(t->debug.hbp[i]); + t->debug.hbp[i] = NULL; + } + } +} + +static u32 ptrace_get_hbp_resource_info(void) +{ + u8 num_brps, num_wrps, debug_arch, wp_len; + u32 reg = 0; + + num_brps = hw_breakpoint_slots(TYPE_INST); + num_wrps = hw_breakpoint_slots(TYPE_DATA); + debug_arch = arch_get_debug_arch(); + wp_len = arch_get_max_wp_len(); + + reg |= debug_arch; + reg <<= 8; + reg |= wp_len; + reg <<= 8; + reg |= num_wrps; + reg <<= 8; + reg |= num_brps; + + return reg; +} + +static struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type) +{ + struct perf_event_attr attr; + + ptrace_breakpoint_init(&attr); + + /* Initialise fields to sane defaults. */ + attr.bp_addr = 0; + attr.bp_len = HW_BREAKPOINT_LEN_4; + attr.bp_type = type; + attr.disabled = 1; + + return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, tsk); +} + +static int ptrace_gethbpregs(struct task_struct *tsk, long num, + unsigned long __user *data) +{ + u32 reg; + int idx, ret = 0; + struct perf_event *bp; + struct arch_hw_breakpoint_ctrl arch_ctrl; + + if (num == 0) { + reg = ptrace_get_hbp_resource_info(); + } else { + idx = ptrace_hbp_num_to_idx(num); + if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) { + ret = -EINVAL; + goto out; + } + + bp = tsk->thread.debug.hbp[idx]; + if (!bp) { + reg = 0; + goto put; + } + + arch_ctrl = counter_arch_bp(bp)->ctrl; + + /* + * Fix up the len because we may have adjusted it + * to compensate for an unaligned address. + */ + while (!(arch_ctrl.len & 0x1)) + arch_ctrl.len >>= 1; + + if (idx & 0x1) + reg = encode_ctrl_reg(arch_ctrl); + else + reg = bp->attr.bp_addr; + } + +put: + if (put_user(reg, data)) + ret = -EFAULT; + +out: + return ret; +} + +static int ptrace_sethbpregs(struct task_struct *tsk, long num, + unsigned long __user *data) +{ + int idx, gen_len, gen_type, implied_type, ret = 0; + u32 user_val; + struct perf_event *bp; + struct arch_hw_breakpoint_ctrl ctrl; + struct perf_event_attr attr; + + if (num == 0) + goto out; + else if (num < 0) + implied_type = HW_BREAKPOINT_RW; + else + implied_type = HW_BREAKPOINT_X; + + idx = ptrace_hbp_num_to_idx(num); + if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) { + ret = -EINVAL; + goto out; + } + + if (get_user(user_val, data)) { + ret = -EFAULT; + goto out; + } + + bp = tsk->thread.debug.hbp[idx]; + if (!bp) { + bp = ptrace_hbp_create(tsk, implied_type); + if (IS_ERR(bp)) { + ret = PTR_ERR(bp); + goto out; + } + tsk->thread.debug.hbp[idx] = bp; + } + + attr = bp->attr; + + if (num & 0x1) { + /* Address */ + attr.bp_addr = user_val; + } else { + /* Control */ + decode_ctrl_reg(user_val, &ctrl); + ret = arch_bp_generic_fields(ctrl, &gen_len, &gen_type); + if (ret) + goto out; + + if ((gen_type & implied_type) != gen_type) { + ret = -EINVAL; + goto out; + } + + attr.bp_len = gen_len; + attr.bp_type = gen_type; + attr.disabled = !ctrl.enabled; + } + + ret = modify_user_hw_breakpoint(bp, &attr); +out: + return ret; +} +#endif + long arch_ptrace(struct task_struct *child, long request, long addr, long data) { int ret; @@ -916,6 +1144,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; #endif +#ifdef CONFIG_HAVE_HW_BREAKPOINT + case PTRACE_GETHBPREGS: + ret = ptrace_gethbpregs(child, addr, + (unsigned long __user *)data); + break; + case PTRACE_SETHBPREGS: + ret = ptrace_sethbpregs(child, addr, + (unsigned long __user *)data); + break; +#endif + default: ret = ptrace_request(child, request, addr, data); break; -- cgit v1.2.2 From 19852e59002fbba1c2c6ba0f154095a37ad2ac03 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 3 Sep 2010 10:44:33 +0100 Subject: ARM: 6358/1: hw-breakpoint: add HAVE_HW_BREAKPOINT to Kconfig If we're targetting a v6 or v7 core and have at least software perf events available, then automatically add support for hardware breakpoints. Cc: Frederic Weisbecker Cc: S. Karthikeyan Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/kernel/Makefile | 1 + 2 files changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 16bc8eb4901c..0fdd099d4a67 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -26,6 +26,7 @@ config ARM select HAVE_PERF_EVENTS select PERF_USE_VMALLOC select HAVE_REGS_AND_STACK_ACCESS_API + select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7)) help The ARM series is a line of low-power-consumption RISC chip designs licensed by ARM Ltd and targeted at embedded applications and diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 980b78e31328..5b9b268f4fbb 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_ARM_UNWIND) += unwind.o obj-$(CONFIG_HAVE_TCM) += tcm.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o +obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312 -- cgit v1.2.2 From 0485e18bc4112a3b548baa314c24bfbece4d156b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 5 Sep 2010 12:19:50 +0100 Subject: Revert "[ARM] pxa: remove now unnecessary dma_needs_bounce()" This reverts commit 4fa5518, which causes a compilation regression for IXP4xx platforms. Reported-by: Richard Cochran Acked-by: Eric Miao Signed-off-by: Russell King --- arch/arm/common/it8152.c | 8 ++++++++ arch/arm/include/asm/dma-mapping.h | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c index 6c0913562455..7974baacafce 100644 --- a/arch/arm/common/it8152.c +++ b/arch/arm/common/it8152.c @@ -263,6 +263,14 @@ static int it8152_pci_platform_notify_remove(struct device *dev) return 0; } +int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size) +{ + dev_dbg(dev, "%s: dma_addr %08x, size %08x\n", + __func__, dma_addr, size); + return (dev->bus == &pci_bus_type) && + ((dma_addr + size - PHYS_OFFSET) >= SZ_64M); +} + int __init it8152_pci_setup(int nr, struct pci_sys_data *sys) { it8152_io.start = IT8152_IO_BASE + 0x12000; diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index c226fe10553e..c568da7dcae4 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -288,15 +288,7 @@ extern void dmabounce_unregister_dev(struct device *); * DMA access and 1 if the buffer needs to be bounced. * */ -#ifdef CONFIG_SA1111 extern int dma_needs_bounce(struct device*, dma_addr_t, size_t); -#else -static inline int dma_needs_bounce(struct device *dev, dma_addr_t addr, - size_t size) -{ - return 0; -} -#endif /* * The DMA API, implemented by dmabounce.c. See below for descriptions. -- cgit v1.2.2 From a387f0f5409276c5cf75eecb61ef6e6896f851b4 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 3 Sep 2010 17:14:54 +0100 Subject: ARM: 6359/1: ep93xx: move clock initialization earlier Commit 7cfe24947 ("ARM: AMBA: Add pclk support to AMBA bus infrastructure") changed AMBA bus to handle the PCLK automatically. However, in EP93xx clock initialization is arch_initcall which is done later than AMBA device identification. This causes amba_get_enable_pclk() to fail resulting device where UARTs are not functional. So change ep93xx_clock_init() to be postcore_initcall. Signed-off-by: Mika Westerberg Acked-by: H Hartley Sweeten Signed-off-by: Russell King --- arch/arm/mach-ep93xx/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index 8bf3cec98cfa..4566bd1c8660 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -560,4 +560,4 @@ static int __init ep93xx_clock_init(void) clkdev_add_table(clocks, ARRAY_SIZE(clocks)); return 0; } -arch_initcall(ep93xx_clock_init); +postcore_initcall(ep93xx_clock_init); -- cgit v1.2.2 From 2be23c475af8ae4e25f8bab08d815b17593bd547 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 8 Sep 2010 16:27:56 +0100 Subject: ARM: Ensure PTE modifications via dma_alloc_coherent are visible Dave Hylands reports: | We've observed a problem with dma_alloc_writecombine when the system | is under heavy load (heavy bus traffic). We've managed to reduce the | problem to the following snippet, which is run from a kthread in a | continuous loop: | | void *virtAddr; | dma_addr_t physAddr; | unsigned int numBytes = 256; | | for (;;) { | virtAddr = dma_alloc_writecombine(NULL, | numBytes, &physAddr, GFP_KERNEL); | if (virtAddr == NULL) { | printk(KERN_ERR "Running out of memory\n"); | break; | } | | /* access DMA memory allocated */ | tmp = virtAddr; | *tmp = 0x77; | | /* free DMA memory */ | dma_free_writecombine(NULL, | numBytes, virtAddr, physAddr); | | ...sleep here... | } | | By itself, the code will run forever with no issues. However, as we | increase our bus traffic (typically using DMA) then the *tmp = 0x77 | line will eventually cause a page fault. If we add a small delay (a | few microseconds) before the *tmp = 0x77, then we don't see a page | fault, even under heavy load. A dsb() is required after modifying the PTE entries to ensure that they will always be visible. Add this dsb(). Reported-by: Dave Hylands Tested-by: Dave Hylands Signed-off-by: Russell King --- arch/arm/mm/dma-mapping.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index c704eed63c5d..4bc43e535d3b 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -229,6 +229,8 @@ __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot) } } while (size -= PAGE_SIZE); + dsb(); + return (void *)c->vm_start; } return NULL; -- cgit v1.2.2 From 16518d5ada690643453eb0aef3cc7841d3623c2d Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 26 Aug 2010 14:31:30 +0300 Subject: KVM: x86 emulator: fix regression with cmpxchg8b on i386 hosts operand::val and operand::orig_val are 32-bit on i386, whereas cmpxchg8b operands are 64-bit. Fix by adding val64 and orig_val64 union members to struct operand, and using them where needed. Signed-off-by: Avi Kivity Signed-off-by: Marcelo Tosatti --- arch/x86/include/asm/kvm_emulate.h | 7 ++++++- arch/x86/kvm/emulate.c | 9 ++++----- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index 51cfd730ac5d..1f99ecfc48e1 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h @@ -152,9 +152,14 @@ struct x86_emulate_ops { struct operand { enum { OP_REG, OP_MEM, OP_IMM, OP_NONE } type; unsigned int bytes; - unsigned long orig_val, *ptr; + union { + unsigned long orig_val; + u64 orig_val64; + }; + unsigned long *ptr; union { unsigned long val; + u64 val64; char valptr[sizeof(unsigned long) + 2]; }; }; diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index b38bd8b92aa6..66ca98aafdd6 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -1870,17 +1870,16 @@ static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) { struct decode_cache *c = &ctxt->decode; - u64 old = c->dst.orig_val; + u64 old = c->dst.orig_val64; if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) || ((u32) (old >> 32) != (u32) c->regs[VCPU_REGS_RDX])) { - c->regs[VCPU_REGS_RAX] = (u32) (old >> 0); c->regs[VCPU_REGS_RDX] = (u32) (old >> 32); ctxt->eflags &= ~EFLG_ZF; } else { - c->dst.val = ((u64)c->regs[VCPU_REGS_RCX] << 32) | - (u32) c->regs[VCPU_REGS_RBX]; + c->dst.val64 = ((u64)c->regs[VCPU_REGS_RCX] << 32) | + (u32) c->regs[VCPU_REGS_RBX]; ctxt->eflags |= EFLG_ZF; } @@ -2616,7 +2615,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) c->src.valptr, c->src.bytes); if (rc != X86EMUL_CONTINUE) goto done; - c->src.orig_val = c->src.val; + c->src.orig_val64 = c->src.val64; } if (c->src2.type == OP_MEM) { -- cgit v1.2.2 From ae0635b3580844e320a253a16985f4ce8b5bd0b6 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 27 Jul 2010 14:51:44 +0300 Subject: KVM: fix i8259 oops when no vcpus are online If there are no vcpus, found will be NULL. Check before doing anything with it. Signed-off-by: Avi Kivity --- arch/x86/kvm/i8259.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index 8d10c063d7f2..4b7b73ce2098 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c @@ -64,6 +64,9 @@ static void pic_unlock(struct kvm_pic *s) if (!found) found = s->kvm->bsp_vcpu; + if (!found) + return; + kvm_vcpu_kick(found); } } -- cgit v1.2.2 From eebb5f31b8d9a2620dcf32297096f8ce1240b179 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Mon, 30 Aug 2010 12:49:13 +0300 Subject: KVM: i8259: fix migration Top of kvm_kpic_state structure should have the same memory layout as kvm_pic_state since it is copied by memcpy. Signed-off-by: Gleb Natapov Signed-off-by: Avi Kivity --- arch/x86/kvm/irq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h index ffed06871c5c..63c314502993 100644 --- a/arch/x86/kvm/irq.h +++ b/arch/x86/kvm/irq.h @@ -43,7 +43,6 @@ struct kvm_kpic_state { u8 irr; /* interrupt request register */ u8 imr; /* interrupt mask register */ u8 isr; /* interrupt service register */ - u8 isr_ack; /* interrupt ack detection */ u8 priority_add; /* highest irq priority */ u8 irq_base; u8 read_reg_select; @@ -56,6 +55,7 @@ struct kvm_kpic_state { u8 init4; /* true if 4 byte init */ u8 elcr; /* PIIX edge/trigger selection */ u8 elcr_mask; + u8 isr_ack; /* interrupt ack detection */ struct kvm_pic *pics_state; }; -- cgit v1.2.2 From b19f8200392db88d529576a4f8178d08b70047be Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 8 Sep 2010 20:57:59 -0700 Subject: sparc: Kill all BKL usage. They were all bogus artifacts and completely unnecessary. Signed-off-by: David S. Miller --- arch/sparc/kernel/sys_sparc_32.c | 2 -- arch/sparc/kernel/unaligned_32.c | 3 +-- arch/sparc/kernel/windows.c | 2 -- 3 files changed, 1 insertion(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c index ee995b7dae7e..de45de4851e9 100644 --- a/arch/sparc/kernel/sys_sparc_32.c +++ b/arch/sparc/kernel/sys_sparc_32.c @@ -166,7 +166,6 @@ sparc_breakpoint (struct pt_regs *regs) { siginfo_t info; - lock_kernel(); #ifdef DEBUG_SPARC_BREAKPOINT printk ("TRAP: Entering kernel PC=%x, nPC=%x\n", regs->pc, regs->npc); #endif @@ -180,7 +179,6 @@ sparc_breakpoint (struct pt_regs *regs) #ifdef DEBUG_SPARC_BREAKPOINT printk ("TRAP: Returning to space: PC=%x nPC=%x\n", regs->pc, regs->npc); #endif - unlock_kernel(); } asmlinkage int diff --git a/arch/sparc/kernel/unaligned_32.c b/arch/sparc/kernel/unaligned_32.c index f8514e291e15..12b9f352595f 100644 --- a/arch/sparc/kernel/unaligned_32.c +++ b/arch/sparc/kernel/unaligned_32.c @@ -323,7 +323,6 @@ asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn) { enum direction dir; - lock_kernel(); if(!(current->thread.flags & SPARC_FLAG_UNALIGNED) || (((insn >> 30) & 3) != 3)) goto kill_user; @@ -377,5 +376,5 @@ asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn) kill_user: user_mna_trap_fault(regs, insn); out: - unlock_kernel(); + ; } diff --git a/arch/sparc/kernel/windows.c b/arch/sparc/kernel/windows.c index f24d298bda29..b351770cbdd6 100644 --- a/arch/sparc/kernel/windows.c +++ b/arch/sparc/kernel/windows.c @@ -112,7 +112,6 @@ void try_to_clear_window_buffer(struct pt_regs *regs, int who) struct thread_info *tp = current_thread_info(); int window; - lock_kernel(); flush_user_windows(); for(window = 0; window < tp->w_saved; window++) { unsigned long sp = tp->rwbuf_stkptrs[window]; @@ -123,5 +122,4 @@ void try_to_clear_window_buffer(struct pt_regs *regs, int who) do_exit(SIGILL); } tp->w_saved = 0; - unlock_kernel(); } -- cgit v1.2.2 From 5afddee415c829704d3a91031ae634008bc332e9 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Thu, 9 Sep 2010 19:58:23 +0200 Subject: AT91: clock: peripheral clocks can have other parent than mck While registering clock allow to set parent clock other than mck. It is useful for clocks than can be seen as child clock of a peripheral. Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Andrew Victor --- arch/arm/mach-at91/clock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 7f7da439341f..7525cee3983f 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -501,7 +501,8 @@ postcore_initcall(at91_clk_debugfs_init); int __init clk_register(struct clk *clk) { if (clk_is_peripheral(clk)) { - clk->parent = &mck; + if (!clk->parent) + clk->parent = &mck; clk->mode = pmc_periph_mode; list_add_tail(&clk->node, &clocks); } -- cgit v1.2.2 From ab64511cbbd03196d84bcc32c6e7b9d46543df7b Mon Sep 17 00:00:00 2001 From: Fabian Godehardt Date: Fri, 3 Sep 2010 13:31:33 +0100 Subject: AT91: SAM9G45 - add a separate clock entry for every single TC block Without this patch you will not be able to register the first block because of the second association call on at91_add_device_tc(). Signed-off-by: Fabian Godehardt [nicolas.ferre@atmel.com: change tcb1_clk to fake child clock of tcb0_clk] Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Andrew Victor Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/at91sam9g45.c | 15 ++++++++++++--- arch/arm/mach-at91/at91sam9g45_devices.c | 4 ++-- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 753c0d31a3d3..c67b47f1c0fd 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -121,8 +121,8 @@ static struct clk ssc1_clk = { .pmc_mask = 1 << AT91SAM9G45_ID_SSC1, .type = CLK_TYPE_PERIPHERAL, }; -static struct clk tcb_clk = { - .name = "tcb_clk", +static struct clk tcb0_clk = { + .name = "tcb0_clk", .pmc_mask = 1 << AT91SAM9G45_ID_TCB, .type = CLK_TYPE_PERIPHERAL, }; @@ -192,6 +192,14 @@ static struct clk ohci_clk = { .parent = &uhphs_clk, }; +/* One additional fake clock for second TC block */ +static struct clk tcb1_clk = { + .name = "tcb1_clk", + .pmc_mask = 0, + .type = CLK_TYPE_PERIPHERAL, + .parent = &tcb0_clk, +}; + static struct clk *periph_clocks[] __initdata = { &pioA_clk, &pioB_clk, @@ -208,7 +216,7 @@ static struct clk *periph_clocks[] __initdata = { &spi1_clk, &ssc0_clk, &ssc1_clk, - &tcb_clk, + &tcb0_clk, &pwm_clk, &tsc_clk, &dma_clk, @@ -221,6 +229,7 @@ static struct clk *periph_clocks[] __initdata = { &mmc1_clk, // irq0 &ohci_clk, + &tcb1_clk, }; /* diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 501ac6fae2e7..5e71ccd5e7d3 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -835,9 +835,9 @@ static struct platform_device at91sam9g45_tcb1_device = { static void __init at91_add_device_tc(void) { /* this chip has one clock and irq for all six TC channels */ - at91_clock_associate("tcb_clk", &at91sam9g45_tcb0_device.dev, "t0_clk"); + at91_clock_associate("tcb0_clk", &at91sam9g45_tcb0_device.dev, "t0_clk"); platform_device_register(&at91sam9g45_tcb0_device); - at91_clock_associate("tcb_clk", &at91sam9g45_tcb1_device.dev, "t0_clk"); + at91_clock_associate("tcb1_clk", &at91sam9g45_tcb1_device.dev, "t0_clk"); platform_device_register(&at91sam9g45_tcb1_device); } #else -- cgit v1.2.2 From 9e84ed63dc71e13b62cea5ec6b0049260cca0b7a Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 9 Sep 2010 22:39:41 +0100 Subject: ARM: Partially revert "Auto calculate ZRELADDR and provide option for exceptions" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Partially revert e69edc7, which introduced automatic zreladdr support. The change in the way the manual definition is defined seems to be error and conflict prone. Go back to the original way we were handling this for the time being, while keeping the automatic zreladdr facility. Acked-by: Uwe Kleine-König --- arch/arm/Kconfig | 91 --------------------------------------- arch/arm/boot/Makefile | 8 ++-- arch/arm/boot/compressed/Makefile | 4 ++ arch/arm/boot/compressed/head.S | 2 +- 4 files changed, 10 insertions(+), 95 deletions(-) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 16bc8eb4901c..553b7cf17bfb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1576,97 +1576,6 @@ config AUTO_ZRELADDR 0xf8000000. This assumes the zImage being placed in the first 128MB from start of memory. -config ZRELADDR - hex "Physical address of the decompressed kernel image" - depends on !AUTO_ZRELADDR - default 0x00008000 if ARCH_BCMRING ||\ - ARCH_CNS3XXX ||\ - ARCH_DOVE ||\ - ARCH_EBSA110 ||\ - ARCH_FOOTBRIDGE ||\ - ARCH_INTEGRATOR ||\ - ARCH_IOP13XX ||\ - ARCH_IOP33X ||\ - ARCH_IXP2000 ||\ - ARCH_IXP23XX ||\ - ARCH_IXP4XX ||\ - ARCH_KIRKWOOD ||\ - ARCH_KS8695 ||\ - ARCH_LOKI ||\ - ARCH_MMP ||\ - ARCH_MV78XX0 ||\ - ARCH_NOMADIK ||\ - ARCH_NUC93X ||\ - ARCH_NS9XXX ||\ - ARCH_ORION5X ||\ - ARCH_SPEAR3XX ||\ - ARCH_SPEAR6XX ||\ - ARCH_TEGRA ||\ - ARCH_U8500 ||\ - ARCH_VERSATILE ||\ - ARCH_W90X900 - default 0x08008000 if ARCH_MX1 ||\ - ARCH_SHARK - default 0x10008000 if ARCH_MSM ||\ - ARCH_OMAP1 ||\ - ARCH_RPC - default 0x20008000 if ARCH_S5P6440 ||\ - ARCH_S5P6442 ||\ - ARCH_S5PC100 ||\ - ARCH_S5PV210 - default 0x30008000 if ARCH_S3C2410 ||\ - ARCH_S3C2400 ||\ - ARCH_S3C2412 ||\ - ARCH_S3C2416 ||\ - ARCH_S3C2440 ||\ - ARCH_S3C2443 - default 0x40008000 if ARCH_STMP378X ||\ - ARCH_STMP37XX ||\ - ARCH_SH7372 ||\ - ARCH_SH7377 ||\ - ARCH_S5PV310 - default 0x50008000 if ARCH_S3C64XX ||\ - ARCH_SH7367 - default 0x60008000 if ARCH_VEXPRESS - default 0x80008000 if ARCH_MX25 ||\ - ARCH_MX3 ||\ - ARCH_NETX ||\ - ARCH_OMAP2PLUS ||\ - ARCH_PNX4008 - default 0x90008000 if ARCH_MX5 ||\ - ARCH_MX91231 - default 0xa0008000 if ARCH_IOP32X ||\ - ARCH_PXA ||\ - MACH_MX27 - default 0xc0008000 if ARCH_LH7A40X ||\ - MACH_MX21 - default 0xf0008000 if ARCH_AAEC2000 ||\ - ARCH_L7200 - default 0xc0028000 if ARCH_CLPS711X - default 0x70008000 if ARCH_AT91 && (ARCH_AT91CAP9 || ARCH_AT91SAM9G45) - default 0x20008000 if ARCH_AT91 && !(ARCH_AT91CAP9 || ARCH_AT91SAM9G45) - default 0xc0008000 if ARCH_DAVINCI && ARCH_DAVINCI_DA8XX - default 0x80008000 if ARCH_DAVINCI && !ARCH_DAVINCI_DA8XX - default 0x00008000 if ARCH_EP93XX && EP93XX_SDCE3_SYNC_PHYS_OFFSET - default 0xc0008000 if ARCH_EP93XX && EP93XX_SDCE0_PHYS_OFFSET - default 0xd0008000 if ARCH_EP93XX && EP93XX_SDCE1_PHYS_OFFSET - default 0xe0008000 if ARCH_EP93XX && EP93XX_SDCE2_PHYS_OFFSET - default 0xf0008000 if ARCH_EP93XX && EP93XX_SDCE3_ASYNC_PHYS_OFFSET - default 0x00008000 if ARCH_GEMINI && GEMINI_MEM_SWAP - default 0x10008000 if ARCH_GEMINI && !GEMINI_MEM_SWAP - default 0x70008000 if ARCH_REALVIEW && REALVIEW_HIGH_PHYS_OFFSET - default 0x00008000 if ARCH_REALVIEW && !REALVIEW_HIGH_PHYS_OFFSET - default 0xc0208000 if ARCH_SA1100 && SA1111 - default 0xc0008000 if ARCH_SA1100 && !SA1111 - default 0x30108000 if ARCH_S3C2410 && PM_H1940 - default 0x28E08000 if ARCH_U300 && MACH_U300_SINGLE_RAM - default 0x48008000 if ARCH_U300 && !MACH_U300_SINGLE_RAM - help - ZRELADDR is the physical address where the decompressed kernel - image will be placed. ZRELADDR has to be specified when the - assumption of AUTO_ZRELADDR is not valid, or when ZBOOT_ROM is - selected. - endmenu menu "CPU Power Management" diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index f705213caa88..4a590f4113e2 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -14,16 +14,18 @@ MKIMAGE := $(srctree)/scripts/mkuboot.sh ifneq ($(MACHINE),) --include $(srctree)/$(MACHINE)/Makefile.boot +include $(srctree)/$(MACHINE)/Makefile.boot endif # Note: the following conditions must always be true: +# ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET) # PARAMS_PHYS must be within 4MB of ZRELADDR # INITRD_PHYS must be in RAM +ZRELADDR := $(zreladdr-y) PARAMS_PHYS := $(params_phys-y) INITRD_PHYS := $(initrd_phys-y) -export INITRD_PHYS PARAMS_PHYS +export ZRELADDR INITRD_PHYS PARAMS_PHYS targets := Image zImage xipImage bootpImage uImage @@ -65,7 +67,7 @@ quiet_cmd_uimage = UIMAGE $@ ifeq ($(CONFIG_ZBOOT_ROM),y) $(obj)/uImage: LOADADDR=$(CONFIG_ZBOOT_ROM_TEXT) else -$(obj)/uImage: LOADADDR=$(CONFIG_ZRELADDR) +$(obj)/uImage: LOADADDR=$(ZRELADDR) endif ifeq ($(CONFIG_THUMB2_KERNEL),y) diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 68775e33476c..b23f6bc46cfa 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -79,6 +79,10 @@ endif EXTRA_CFLAGS := -fpic -fno-builtin EXTRA_AFLAGS := -Wa,-march=all +# Supply ZRELADDR to the decompressor via a linker symbol. +ifneq ($(CONFIG_AUTO_ZRELADDR),y) +LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR) +endif ifeq ($(CONFIG_CPU_ENDIAN_BE8),y) LDFLAGS_vmlinux += --be8 endif diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 6af9907c3b5c..6825c34646d4 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -177,7 +177,7 @@ not_angel: and r4, pc, #0xf8000000 add r4, r4, #TEXT_OFFSET #else - ldr r4, =CONFIG_ZRELADDR + ldr r4, =zreladdr #endif subs r0, r0, r1 @ calculate the delta offset -- cgit v1.2.2 From a14d0404088a7b0d51bb5219baf33d77e5592007 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 9 Sep 2010 22:43:02 +0100 Subject: ARM: Update mach-types Signed-off-by: Russell King --- arch/arm/tools/mach-types | 98 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 48cbdcb6bbd4..55590a4d87c9 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Mon Jul 12 21:10:14 2010 +# Last update: Thu Sep 9 22:43:01 2010 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -2622,7 +2622,7 @@ kraken MACH_KRAKEN KRAKEN 2634 gw2388 MACH_GW2388 GW2388 2635 jadecpu MACH_JADECPU JADECPU 2636 carlisle MACH_CARLISLE CARLISLE 2637 -lux_sf9 MACH_LUX_SFT9 LUX_SFT9 2638 +lux_sf9 MACH_LUX_SF9 LUX_SF9 2638 nemid_tb MACH_NEMID_TB NEMID_TB 2639 terrier MACH_TERRIER TERRIER 2640 turbot MACH_TURBOT TURBOT 2641 @@ -2950,3 +2950,97 @@ davinci_dm365_dvr MACH_DAVINCI_DM365_DVR DAVINCI_DM365_DVR 2963 netviz MACH_NETVIZ NETVIZ 2964 flexibity MACH_FLEXIBITY FLEXIBITY 2965 wlan_computer MACH_WLAN_COMPUTER WLAN_COMPUTER 2966 +lpc24xx MACH_LPC24XX LPC24XX 2967 +spica MACH_SPICA SPICA 2968 +gpsdisplay MACH_GPSDISPLAY GPSDISPLAY 2969 +bipnet MACH_BIPNET BIPNET 2970 +overo_ctu_inertial MACH_OVERO_CTU_INERTIAL OVERO_CTU_INERTIAL 2971 +davinci_dm355_mmm MACH_DAVINCI_DM355_MMM DAVINCI_DM355_MMM 2972 +pc9260_v2 MACH_PC9260_V2 PC9260_V2 2973 +ptx7545 MACH_PTX7545 PTX7545 2974 +tm_efdc MACH_TM_EFDC TM_EFDC 2975 +omap3_waldo1 MACH_OMAP3_WALDO1 OMAP3_WALDO1 2977 +flyer MACH_FLYER FLYER 2978 +tornado3240 MACH_TORNADO3240 TORNADO3240 2979 +soli_01 MACH_SOLI_01 SOLI_01 2980 +omapl138_europalc MACH_OMAPL138_EUROPALC OMAPL138_EUROPALC 2981 +helios_v1 MACH_HELIOS_V1 HELIOS_V1 2982 +netspace_lite_v2 MACH_NETSPACE_LITE_V2 NETSPACE_LITE_V2 2983 +ssc MACH_SSC SSC 2984 +premierwave_en MACH_PREMIERWAVE_EN PREMIERWAVE_EN 2985 +wasabi MACH_WASABI WASABI 2986 +vivow MACH_VIVOW VIVOW 2987 +mx50_rdp MACH_MX50_RDP MX50_RDP 2988 +universal MACH_UNIVERSAL UNIVERSAL 2989 +real6410 MACH_REAL6410 REAL6410 2990 +spx_sakura MACH_SPX_SAKURA SPX_SAKURA 2991 +ij3k_2440 MACH_IJ3K_2440 IJ3K_2440 2992 +omap3_bc10 MACH_OMAP3_BC10 OMAP3_BC10 2993 +thebe MACH_THEBE THEBE 2994 +rv082 MACH_RV082 RV082 2995 +armlguest MACH_ARMLGUEST ARMLGUEST 2996 +tjinc1000 MACH_TJINC1000 TJINC1000 2997 +dockstar MACH_DOCKSTAR DOCKSTAR 2998 +ax8008 MACH_AX8008 AX8008 2999 +gnet_sgce MACH_GNET_SGCE GNET_SGCE 3000 +pxwnas_500_1000 MACH_PXWNAS_500_1000 PXWNAS_500_1000 3001 +ea20 MACH_EA20 EA20 3002 +awm2 MACH_AWM2 AWM2 3003 +ti8148evm MACH_TI8148EVM TI8148EVM 3004 +tegra_seaboard MACH_TEGRA_SEABOARD TEGRA_SEABOARD 3005 +linkstation_chlv2 MACH_LINKSTATION_CHLV2 LINKSTATION_CHLV2 3006 +tera_pro2_rack MACH_TERA_PRO2_RACK TERA_PRO2_RACK 3007 +rubys MACH_RUBYS RUBYS 3008 +aquarius MACH_AQUARIUS AQUARIUS 3009 +mx53_ard MACH_MX53_ARD MX53_ARD 3010 +mx53_smd MACH_MX53_SMD MX53_SMD 3011 +lswxl MACH_LSWXL LSWXL 3012 +dove_avng_v3 MACH_DOVE_AVNG_V3 DOVE_AVNG_V3 3013 +sdi_ess_9263 MACH_SDI_ESS_9263 SDI_ESS_9263 3014 +jocpu550 MACH_JOCPU550 JOCPU550 3015 +msm8x60_rumi3 MACH_MSM8X60_RUMI3 MSM8X60_RUMI3 3016 +msm8x60_ffa MACH_MSM8X60_FFA MSM8X60_FFA 3017 +yanomami MACH_YANOMAMI YANOMAMI 3018 +gta04 MACH_GTA04 GTA04 3019 +cm_a510 MACH_CM_A510 CM_A510 3020 +omap3_rfs200 MACH_OMAP3_RFS200 OMAP3_RFS200 3021 +kx33xx MACH_KX33XX KX33XX 3022 +ptx7510 MACH_PTX7510 PTX7510 3023 +top9000 MACH_TOP9000 TOP9000 3024 +teenote MACH_TEENOTE TEENOTE 3025 +ts3 MACH_TS3 TS3 3026 +a0 MACH_A0 A0 3027 +fsm9xxx_surf MACH_FSM9XXX_SURF FSM9XXX_SURF 3028 +fsm9xxx_ffa MACH_FSM9XXX_FFA FSM9XXX_FFA 3029 +frrhwcdma60w MACH_FRRHWCDMA60W FRRHWCDMA60W 3030 +remus MACH_REMUS REMUS 3031 +at91cap7xdk MACH_AT91CAP7XDK AT91CAP7XDK 3032 +at91cap7stk MACH_AT91CAP7STK AT91CAP7STK 3033 +kt_sbc_sam9_1 MACH_KT_SBC_SAM9_1 KT_SBC_SAM9_1 3034 +oratisrouter MACH_ORATISROUTER ORATISROUTER 3035 +armada_xp_db MACH_ARMADA_XP_DB ARMADA_XP_DB 3036 +spdm MACH_SPDM SPDM 3037 +gtib MACH_GTIB GTIB 3038 +dgm3240 MACH_DGM3240 DGM3240 3039 +atlas_i_lpe MACH_ATLAS_I_LPE ATLAS_I_LPE 3040 +htcmega MACH_HTCMEGA HTCMEGA 3041 +tricorder MACH_TRICORDER TRICORDER 3042 +tx28 MACH_TX28 TX28 3043 +bstbrd MACH_BSTBRD BSTBRD 3044 +pwb3090 MACH_PWB3090 PWB3090 3045 +idea6410 MACH_IDEA6410 IDEA6410 3046 +qbc9263 MACH_QBC9263 QBC9263 3047 +borabora MACH_BORABORA BORABORA 3048 +valdez MACH_VALDEZ VALDEZ 3049 +ls9g20 MACH_LS9G20 LS9G20 3050 +mios_v1 MACH_MIOS_V1 MIOS_V1 3051 +s5pc110_crespo MACH_S5PC110_CRESPO S5PC110_CRESPO 3052 +controltek9g20 MACH_CONTROLTEK9G20 CONTROLTEK9G20 3053 +tin307 MACH_TIN307 TIN307 3054 +tin510 MACH_TIN510 TIN510 3055 +bluecheese MACH_BLUECHEESE BLUECHEESE 3057 +tem3x30 MACH_TEM3X30 TEM3X30 3058 +harvest_desoto MACH_HARVEST_DESOTO HARVEST_DESOTO 3059 +msm8x60_qrdc MACH_MSM8X60_QRDC MSM8X60_QRDC 3060 +spear900 MACH_SPEAR900 SPEAR900 3061 +pcontrol_g20 MACH_PCONTROL_G20 PCONTROL_G20 3062 -- cgit v1.2.2 From f574c843191728d9407b766a027f779dcd27b272 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Thu, 9 Sep 2010 15:16:56 -0700 Subject: [IA64] fix siglock When ia64 converted to using ticket locks, an inline implementation of trylock/unlock in fsys.S was missed. This was not noticed because in most circumstances it simply resulted in using the slow path because the siglock was apparently not available (under old spinlock rules). Problems occur when the ticket spinlock has value 0x0 (when first initialised, or when it wraps around). At this point the fsys.S code acquires the lock (changing the 0x0 to 0x1. If another process attempts to get the lock at this point, it will change the value from 0x1 to 0x2 (using new ticket lock rules). Then the fsys.S code will free the lock using old spinlock rules by writing 0x0 to it. From here a variety of bad things can happen. Signed-off-by: Tony Luck --- arch/ia64/kernel/fsys.S | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index 3567d54f8cee..471a1e783aca 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S @@ -424,14 +424,26 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP #ifdef CONFIG_SMP - mov r17=1 - ;; - cmpxchg4.acq r18=[r31],r17,ar.ccv // try to acquire the lock + // __ticket_spin_trylock(r31) + ld4 r17=[r31] mov r8=EINVAL // default to EINVAL ;; + extr r9=r17,17,15 + ;; + xor r18=r17,r9 + adds r19=1,r17 + ;; + extr.u r18=r18,0,15 + ;; + cmp.eq p0,p7=0,r18 +(p7) br.cond.spnt.many .lock_contention + mov.m ar.ccv=r17 + ;; + cmpxchg4.acq r9=[r31],r19,ar.ccv + ;; + cmp4.eq p0,p7=r9,r17 +(p7) br.cond.spnt.many .lock_contention ld8 r3=[r2] // re-read current->blocked now that we hold the lock - cmp4.ne p6,p0=r18,r0 -(p6) br.cond.spnt.many .lock_contention ;; #else ld8 r3=[r2] // re-read current->blocked now that we hold the lock @@ -490,7 +502,17 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set (p6) br.cond.spnt.few 1b // yes -> retry #ifdef CONFIG_SMP - st4.rel [r31]=r0 // release the lock + // __ticket_spin_unlock(r31) + adds r31=2,r31 + ;; + ld2.bias r2=[r31] + mov r3=65534 + ;; + adds r2=2,r2 + ;; + and r3=r3,r2 + ;; + st2.rel [r31]=r3 #endif SSM_PSR_I(p0, p9, r31) ;; @@ -512,7 +534,17 @@ EX(.fail_efault, (p15) st8 [r34]=r3) .sig_pending: #ifdef CONFIG_SMP - st4.rel [r31]=r0 // release the lock + // __ticket_spin_unlock(r31) + adds r31=2,r31 + ;; + ld2.bias r2=[r31] + mov r3=65534 + ;; + adds r2=2,r2 + ;; + and r3=r3,r2 + ;; + st2.rel [r31]=r3 #endif SSM_PSR_I(p0, p9, r17) ;; -- cgit v1.2.2 From 94131e174fedd9f3f9bb148cee4be12f2d46d68e Mon Sep 17 00:00:00 2001 From: "Ira W. Snyder" Date: Thu, 9 Sep 2010 16:37:58 -0700 Subject: arch/powerpc/include/asm/fsldma.h needs slab.h The slab.h header is required to use the kmalloc() family of functions. Due to recent kernel changes, this header must be directly included by code that calls into the memory allocator. Without this patch, any code which includes this header fails to build. Signed-off-by: Ira W. Snyder Cc: Dan Williams Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/include/asm/fsldma.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/powerpc/include/asm/fsldma.h b/arch/powerpc/include/asm/fsldma.h index a67aeed17d40..debc5ed96d6e 100644 --- a/arch/powerpc/include/asm/fsldma.h +++ b/arch/powerpc/include/asm/fsldma.h @@ -11,6 +11,7 @@ #ifndef __ARCH_POWERPC_ASM_FSLDMA_H__ #define __ARCH_POWERPC_ASM_FSLDMA_H__ +#include #include /* -- cgit v1.2.2 From 1879c45cce6411fe97b0b65ccad38f5206700dda Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Fri, 10 Sep 2010 11:38:43 +0200 Subject: AT91: dm9000 initialization update Add information in dm9000 mac/phy chip initialization: - irq resource details - platform data details Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/board-sam9261ek.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index c4c8865d52d7..b4307aba523d 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -93,11 +93,12 @@ static struct resource dm9000_resource[] = { .start = AT91_PIN_PC11, .end = AT91_PIN_PC11, .flags = IORESOURCE_IRQ + | IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE, } }; static struct dm9000_plat_data dm9000_platdata = { - .flags = DM9000_PLATF_16BITONLY, + .flags = DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM, }; static struct platform_device dm9000_device = { -- cgit v1.2.2 From 64d72bbeeb68b536a27319471f212d413f58bf6f Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Fri, 10 Sep 2010 11:26:42 +0200 Subject: AT91: at91sam9261ek board: remove warnings related to use of SPI or SD/MMC The sd/mmc data structure is not used if SPI is selected. The configuration of PIO on the board prevent from using both interfaces at the same time (board dependent). Remove the warnings at compilation time adding a preprocessor condition. Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/board-sam9261ek.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index b4307aba523d..19d4d2cbc9c4 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -168,17 +168,6 @@ static struct at91_udc_data __initdata ek_udc_data = { }; -/* - * MCI (SD/MMC) - */ -static struct at91_mmc_data __initdata ek_mmc_data = { - .wire4 = 1, -// .det_pin = ... not connected -// .wp_pin = ... not connected -// .vcc_pin = ... not connected -}; - - /* * NAND flash */ @@ -247,6 +236,10 @@ static void __init ek_add_device_nand(void) at91_add_device_nand(&ek_nand_data); } +/* + * SPI related devices + */ +#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) /* * ADS7846 Touchscreen @@ -357,6 +350,21 @@ static struct spi_board_info ek_spi_devices[] = { #endif }; +#else /* CONFIG_SPI_ATMEL_* */ + +/* + * MCI (SD/MMC) + * spi0 and mmc/sd share the same PIO pins: cannot be used at the same time + */ +static struct at91_mmc_data __initdata ek_mmc_data = { + .wire4 = 1, +// .det_pin = ... not connected +// .wp_pin = ... not connected +// .vcc_pin = ... not connected +}; + +#endif /* CONFIG_SPI_ATMEL_* */ + /* * LCD Controller -- cgit v1.2.2 From 4deb22a6001eb0d4058295c3645c36190a0ec603 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Fri, 10 Sep 2010 14:36:06 +0200 Subject: AT91: at91sam9261ek: remove C99 comments but keep information Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/board-sam9261ek.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index 19d4d2cbc9c4..65eb0943194f 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -351,16 +351,14 @@ static struct spi_board_info ek_spi_devices[] = { }; #else /* CONFIG_SPI_ATMEL_* */ +/* spi0 and mmc/sd share the same PIO pins: cannot be used at the same time */ /* * MCI (SD/MMC) - * spi0 and mmc/sd share the same PIO pins: cannot be used at the same time + * det_pin, wp_pin and vcc_pin are not connected */ static struct at91_mmc_data __initdata ek_mmc_data = { .wire4 = 1, -// .det_pin = ... not connected -// .wp_pin = ... not connected -// .vcc_pin = ... not connected }; #endif /* CONFIG_SPI_ATMEL_* */ -- cgit v1.2.2 From 36ac4b987bea9a95217e1af552252f275ca7fc44 Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Fri, 10 Sep 2010 10:08:08 -0500 Subject: x86, UV: Fix initialization of max_pnode Fix calculation of "max_pnode" for systems where the the highest blade has neither cpus or memory. (And, yes, although rare this does occur). Signed-off-by: Jack Steiner LKML-Reference: <20100910150808.GA19802@sgi.com> Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic/x2apic_uv_x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 7b598b84c902..f744f54cb248 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -698,9 +698,11 @@ void __init uv_system_init(void) for (j = 0; j < 64; j++) { if (!test_bit(j, &present)) continue; - uv_blade_info[blade].pnode = (i * 64 + j); + pnode = (i * 64 + j); + uv_blade_info[blade].pnode = pnode; uv_blade_info[blade].nr_possible_cpus = 0; uv_blade_info[blade].nr_online_cpus = 0; + max_pnode = max(pnode, max_pnode); blade++; } } @@ -738,7 +740,6 @@ void __init uv_system_init(void) uv_cpu_hub_info(cpu)->scir.offset = uv_scir_offset(apicid); uv_node_to_blade[nid] = blade; uv_cpu_to_blade[cpu] = blade; - max_pnode = max(pnode, max_pnode); } /* Add blade/pnode info for nodes without cpus */ @@ -750,7 +751,6 @@ void __init uv_system_init(void) pnode = (paddr >> m_val) & pnode_mask; blade = boot_pnode_to_blade(pnode); uv_node_to_blade[nid] = blade; - max_pnode = max(pnode, max_pnode); } map_gru_high(max_pnode); -- cgit v1.2.2 From 5ee5e97ee9bca919af11c562beeaf61741ad33f1 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 10 Sep 2010 22:32:53 +0200 Subject: x86, tsc: Fix a preemption leak in restore_sched_clock_state() A real life genuine preemption leak.. Reported-and-tested-by: Jeff Chua Signed-off-by: Peter Zijlstra Acked-by: Suresh Siddha Signed-off-by: Linus Torvalds --- arch/x86/kernel/tsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index d632934cb638..26a863a9c2a8 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -655,7 +655,7 @@ void restore_sched_clock_state(void) local_irq_save(flags); - get_cpu_var(cyc2ns_offset) = 0; + __get_cpu_var(cyc2ns_offset) = 0; offset = cyc2ns_suspend - sched_clock(); for_each_possible_cpu(cpu) -- cgit v1.2.2 From b343ae51c116dffaef07a8596661774c12212b66 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 12 Sep 2010 17:20:24 -0700 Subject: sparc64: Support RAW perf events. Encoding is "(encoding << 16) | pic_mask" Signed-off-by: David S. Miller --- arch/sparc/kernel/perf_event.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index 357ced3c33ff..6318e622cfb0 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -1038,6 +1038,7 @@ static int __hw_perf_event_init(struct perf_event *event) if (atomic_read(&nmi_active) < 0) return -ENODEV; + pmap = NULL; if (attr->type == PERF_TYPE_HARDWARE) { if (attr->config >= sparc_pmu->max_events) return -EINVAL; @@ -1046,9 +1047,18 @@ static int __hw_perf_event_init(struct perf_event *event) pmap = sparc_map_cache_event(attr->config); if (IS_ERR(pmap)) return PTR_ERR(pmap); - } else + } else if (attr->type != PERF_TYPE_RAW) return -EOPNOTSUPP; + if (pmap) { + hwc->event_base = perf_event_encode(pmap); + } else { + /* User gives us "(encoding << 16) | pic_mask" for + * PERF_TYPE_RAW events. + */ + hwc->event_base = attr->config; + } + /* We save the enable bits in the config_base. */ hwc->config_base = sparc_pmu->irq_bit; if (!attr->exclude_user) @@ -1058,8 +1068,6 @@ static int __hw_perf_event_init(struct perf_event *event) if (!attr->exclude_hv) hwc->config_base |= sparc_pmu->hv_bit; - hwc->event_base = perf_event_encode(pmap); - n = 0; if (event->group_leader != event) { n = collect_events(event->group_leader, -- cgit v1.2.2 From edc805b7c5e45c3d7202cea5239985d204178e24 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 16 Aug 2010 14:05:20 +0200 Subject: m68k,m68knommu: Wire up fanotify_init, fanotify_mark, and prlimit64 Signed-off-by: Geert Uytterhoeven Acked-by: Greg Ungerer --- arch/m68k/include/asm/unistd.h | 5 ++++- arch/m68k/kernel/entry.S | 3 +++ arch/m68knommu/kernel/syscalltable.S | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index 60b15d0aa072..b43b36beafe3 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h @@ -340,10 +340,13 @@ #define __NR_set_thread_area 334 #define __NR_atomic_cmpxchg_32 335 #define __NR_atomic_barrier 336 +#define __NR_fanotify_init 337 +#define __NR_fanotify_mark 338 +#define __NR_prlimit64 339 #ifdef __KERNEL__ -#define NR_syscalls 337 +#define NR_syscalls 340 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 2391bdff0996..6360c437dcf5 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -765,4 +765,7 @@ sys_call_table: .long sys_set_thread_area .long sys_atomic_cmpxchg_32 /* 335 */ .long sys_atomic_barrier + .long sys_fanotify_init + .long sys_fanotify_mark + .long sys_prlimit64 diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S index b30b3eb197a5..79b1ed198c07 100644 --- a/arch/m68knommu/kernel/syscalltable.S +++ b/arch/m68knommu/kernel/syscalltable.S @@ -355,6 +355,9 @@ ENTRY(sys_call_table) .long sys_set_thread_area .long sys_atomic_cmpxchg_32 /* 335 */ .long sys_atomic_barrier + .long sys_fanotify_init + .long sys_fanotify_mark + .long sys_prlimit64 .rept NR_syscalls-(.-sys_call_table)/4 .long sys_ni_syscall -- cgit v1.2.2 From 05ed160e89baf7f5fb3432d527fec467d2493626 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 13 Sep 2010 19:25:41 +0900 Subject: kprobes: Fix Kconfig dependency Fix Kconfig dependency among Kprobes, optprobe and kallsyms. Kprobes uses kallsyms_lookup for finding target function and checking instruction boundary, thus CONFIG_KPROBES should select CONFIG_KALLSYMS. Optprobe is an optional feature which is supported on x86 arch, and it also uses kallsyms_lookup for checking instructions in the target function. Since KALLSYMS_ALL just adds symbols of kernel variables, it doesn't need to select KALLSYMS_ALL. Signed-off-by: Masami Hiramatsu Acked-by: Randy Dunlap , Cc: Ananth N Mavinakayanahalli Cc: Felipe Contreras Cc: Randy Dunlap Cc: Ananth N Mavinakayanahalli Cc: Anil S Keshavamurthy Cc: David S. Miller Cc: akpm LKML-Reference: <20100913102541.20260.85700.stgit@ltc236.sdl.hitachi.co.jp> Signed-off-by: Ingo Molnar --- arch/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/Kconfig b/arch/Kconfig index 4877a8c8ee16..fe48fc7a3eba 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -32,8 +32,9 @@ config HAVE_OPROFILE config KPROBES bool "Kprobes" - depends on KALLSYMS && MODULES + depends on MODULES depends on HAVE_KPROBES + select KALLSYMS help Kprobes allows you to trap at almost any kernel address and execute a callback function. register_kprobe() establishes @@ -45,7 +46,6 @@ config OPTPROBES def_bool y depends on KPROBES && HAVE_OPTPROBES depends on !PREEMPT - select KALLSYMS_ALL config HAVE_EFFICIENT_UNALIGNED_ACCESS bool -- cgit v1.2.2 From 2fd818642a3c3a257f3b1262145a52bc1bfebd26 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Mon, 30 Aug 2010 09:45:40 +0900 Subject: x86, cpufeature: Suppress compiler warning with gcc 3.x Gcc 3.x generates a warning arch/x86/include/asm/cpufeature.h: In function `__static_cpu_has': arch/x86/include/asm/cpufeature.h:326: warning: asm operand 1 probably doesn't match constraints on each file. But static_cpu_has() for gcc 3.x does not need __static_cpu_has(). Signed-off-by: Tetsuo Handa LKML-Reference: <201008300127.o7U1RC6Z044051@www262.sakura.ne.jp> Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/cpufeature.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 781a50b29a49..c6fbb7b430d1 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -296,6 +296,7 @@ extern const char * const x86_power_flags[32]; #endif /* CONFIG_X86_64 */ +#if __GNUC__ >= 4 /* * Static testing of CPU features. Used the same as boot_cpu_has(). * These are only valid after alternatives have run, but will statically @@ -304,7 +305,7 @@ extern const char * const x86_power_flags[32]; */ static __always_inline __pure bool __static_cpu_has(u16 bit) { -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) +#if __GNUC__ > 4 || __GNUC_MINOR__ >= 5 asm goto("1: jmp %l[t_no]\n" "2:\n" ".section .altinstructions,\"a\"\n" @@ -345,7 +346,6 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) #endif } -#if __GNUC__ >= 4 #define static_cpu_has(bit) \ ( \ __builtin_constant_p(boot_cpu_has(bit)) ? \ -- cgit v1.2.2 From 08c2b394b98786ebb067e2a54d08f1f6f0d247da Mon Sep 17 00:00:00 2001 From: "basile@opensource.dyc.edu" Date: Mon, 13 Sep 2010 06:13:19 -0400 Subject: x86, build: Disable -fPIE when compiling with CONFIG_CC_STACKPROTECTOR=y The arch/x86/Makefile uses scripts/gcc-x86_$(BITS)-has-stack-protector.sh to check if cc1 supports -fstack-protector. When -fPIE is passed to cc1, these scripts fail causing stack protection to be disabled even when it is available. This fix is similar to commit c47efe5548abbf53c2f66e06dcb46183b11d6b22 Reported-by: Kai Dietrich Signed-off-by: Magnus Granberg LKML-Reference: <20100913101319.748A1148E216@opensource.dyc.edu> Signed-off-by: Anthony G. Basile Cc: Andrew Morton Signed-off-by: H. Peter Anvin --- arch/x86/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 8aa1b59b9074..e8c8881351b3 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -74,7 +74,7 @@ endif ifdef CONFIG_CC_STACKPROTECTOR cc_has_sp := $(srctree)/scripts/gcc-x86_$(BITS)-has-stack-protector.sh - ifeq ($(shell $(CONFIG_SHELL) $(cc_has_sp) $(CC) $(biarch)),y) + ifeq ($(shell $(CONFIG_SHELL) $(cc_has_sp) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y) stackp-y := -fstack-protector KBUILD_CFLAGS += $(stackp-y) else -- cgit v1.2.2 From 0fe7f885043ea0e3e026cc98cfd7f8715018c023 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 9 Sep 2010 21:29:52 +0900 Subject: ARM: S5P: Fix DMA coherent mask for FIMC FIMC driver uses DMA_coherent allocator, which requires proper dma mask to be set. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park [kgene.kim@samsung.com: minor title fix] Signed-off-by: Kukjin Kim --- arch/arm/plat-s5p/dev-fimc0.c | 7 +++++++ arch/arm/plat-s5p/dev-fimc1.c | 7 +++++++ arch/arm/plat-s5p/dev-fimc2.c | 7 +++++++ 3 files changed, 21 insertions(+) (limited to 'arch') diff --git a/arch/arm/plat-s5p/dev-fimc0.c b/arch/arm/plat-s5p/dev-fimc0.c index d3f1a9b5d2b5..f9203fa8fe23 100644 --- a/arch/arm/plat-s5p/dev-fimc0.c +++ b/arch/arm/plat-s5p/dev-fimc0.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -28,9 +29,15 @@ static struct resource s5p_fimc0_resource[] = { }, }; +static u64 s5p_fimc0_dma_mask = DMA_BIT_MASK(32); + struct platform_device s5p_device_fimc0 = { .name = "s5p-fimc", .id = 0, .num_resources = ARRAY_SIZE(s5p_fimc0_resource), .resource = s5p_fimc0_resource, + .dev = { + .dma_mask = &s5p_fimc0_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, }; diff --git a/arch/arm/plat-s5p/dev-fimc1.c b/arch/arm/plat-s5p/dev-fimc1.c index 41bd6986d0ad..7ed91a34dd4a 100644 --- a/arch/arm/plat-s5p/dev-fimc1.c +++ b/arch/arm/plat-s5p/dev-fimc1.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -28,9 +29,15 @@ static struct resource s5p_fimc1_resource[] = { }, }; +static u64 s5p_fimc1_dma_mask = DMA_BIT_MASK(32); + struct platform_device s5p_device_fimc1 = { .name = "s5p-fimc", .id = 1, .num_resources = ARRAY_SIZE(s5p_fimc1_resource), .resource = s5p_fimc1_resource, + .dev = { + .dma_mask = &s5p_fimc1_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, }; diff --git a/arch/arm/plat-s5p/dev-fimc2.c b/arch/arm/plat-s5p/dev-fimc2.c index dfddeda6d4a3..5543d637396c 100644 --- a/arch/arm/plat-s5p/dev-fimc2.c +++ b/arch/arm/plat-s5p/dev-fimc2.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -28,9 +29,15 @@ static struct resource s5p_fimc2_resource[] = { }, }; +static u64 s5p_fimc2_dma_mask = DMA_BIT_MASK(32); + struct platform_device s5p_device_fimc2 = { .name = "s5p-fimc", .id = 2, .num_resources = ARRAY_SIZE(s5p_fimc2_resource), .resource = s5p_fimc2_resource, + .dev = { + .dma_mask = &s5p_fimc2_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, }; -- cgit v1.2.2 From 80e2f36aab7e69a193926814b73b3609c2f69f20 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 9 Sep 2010 21:31:46 +0900 Subject: ARM: S5P: Decrease IO Registers memory region size on FIMC IO registers region size of all FIMC versions is less than 1kB so there is no need to reserve 1M. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Marek Szyprowski [kgene.kim@samsung.com: minor title fix] Signed-off-by: Kukjin Kim --- arch/arm/plat-s5p/dev-fimc0.c | 2 +- arch/arm/plat-s5p/dev-fimc1.c | 2 +- arch/arm/plat-s5p/dev-fimc2.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-s5p/dev-fimc0.c b/arch/arm/plat-s5p/dev-fimc0.c index f9203fa8fe23..608770fc1531 100644 --- a/arch/arm/plat-s5p/dev-fimc0.c +++ b/arch/arm/plat-s5p/dev-fimc0.c @@ -19,7 +19,7 @@ static struct resource s5p_fimc0_resource[] = { [0] = { .start = S5P_PA_FIMC0, - .end = S5P_PA_FIMC0 + SZ_1M - 1, + .end = S5P_PA_FIMC0 + SZ_4K - 1, .flags = IORESOURCE_MEM, }, [1] = { diff --git a/arch/arm/plat-s5p/dev-fimc1.c b/arch/arm/plat-s5p/dev-fimc1.c index 7ed91a34dd4a..76e3a97a87d3 100644 --- a/arch/arm/plat-s5p/dev-fimc1.c +++ b/arch/arm/plat-s5p/dev-fimc1.c @@ -19,7 +19,7 @@ static struct resource s5p_fimc1_resource[] = { [0] = { .start = S5P_PA_FIMC1, - .end = S5P_PA_FIMC1 + SZ_1M - 1, + .end = S5P_PA_FIMC1 + SZ_4K - 1, .flags = IORESOURCE_MEM, }, [1] = { diff --git a/arch/arm/plat-s5p/dev-fimc2.c b/arch/arm/plat-s5p/dev-fimc2.c index 5543d637396c..24d29816fa2c 100644 --- a/arch/arm/plat-s5p/dev-fimc2.c +++ b/arch/arm/plat-s5p/dev-fimc2.c @@ -19,7 +19,7 @@ static struct resource s5p_fimc2_resource[] = { [0] = { .start = S5P_PA_FIMC2, - .end = S5P_PA_FIMC2 + SZ_1M - 1, + .end = S5P_PA_FIMC2 + SZ_4K - 1, .flags = IORESOURCE_MEM, }, [1] = { -- cgit v1.2.2 From f1c894de475c2455e6cedcc91d0ee4eb04388f3b Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Sat, 21 Aug 2010 09:18:19 +0900 Subject: ARM: S5PV210: Update I2C-1 Clock Register Property. CLK_GATE_IP3[8] is RESERVED. The port "I2C_HDMI_DDC" of CLK_GATE_IP3[10] is used as another I2C port. Therefore, defined the unused I2C-1 as another I2C there was left undefined but used. Signed-off-by: MyungJoo Ham Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/mach-s5pv210/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index af91fefef2c6..825b8681fbb3 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -357,7 +357,7 @@ static struct clk init_clocks_disable[] = { .id = 1, .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, - .ctrlbit = (1<<8), + .ctrlbit = (1 << 10), }, { .name = "i2c", .id = 2, -- cgit v1.2.2 From a203a13a8843c3ec2d4dbc6285d000079a12afa5 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 21 Aug 2010 11:48:45 +0900 Subject: ARM: S5PV210: Reduce the iodesc length of systimer It's enough to use 4KiB. Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/mach-s5pv210/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c index b9f4d677cf55..77f456c91ad3 100644 --- a/arch/arm/mach-s5pv210/cpu.c +++ b/arch/arm/mach-s5pv210/cpu.c @@ -47,7 +47,7 @@ static struct map_desc s5pv210_iodesc[] __initdata = { { .virtual = (unsigned long)S5P_VA_SYSTIMER, .pfn = __phys_to_pfn(S5PV210_PA_SYSTIMER), - .length = SZ_1M, + .length = SZ_4K, .type = MT_DEVICE, }, { .virtual = (unsigned long)VA_VIC2, -- cgit v1.2.2 From da01c2f733f5eaa1b0670e7b584f431934c60306 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 10 Sep 2010 19:43:12 +0900 Subject: ARM: S5PV210: Add FIMC clocks These clocks enables FIMC driver to operate on machines, which bootloader power gated FIMC devices to save power on boot. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park [kgene.kim@samsung.com: minor title fix] Signed-off-by: Kukjin Kim --- arch/arm/mach-s5pv210/clock.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 825b8681fbb3..cfecd70657cb 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -280,6 +280,24 @@ static struct clk init_clocks_disable[] = { .parent = &clk_hclk_dsys.clk, .enable = s5pv210_clk_ip0_ctrl, .ctrlbit = (1<<29), + }, { + .name = "fimc", + .id = 0, + .parent = &clk_hclk_dsys.clk, + .enable = s5pv210_clk_ip0_ctrl, + .ctrlbit = (1 << 24), + }, { + .name = "fimc", + .id = 1, + .parent = &clk_hclk_dsys.clk, + .enable = s5pv210_clk_ip0_ctrl, + .ctrlbit = (1 << 25), + }, { + .name = "fimc", + .id = 2, + .parent = &clk_hclk_dsys.clk, + .enable = s5pv210_clk_ip0_ctrl, + .ctrlbit = (1 << 26), }, { .name = "otg", .id = -1, -- cgit v1.2.2 From 0770e5280efd6f0001972a2b5127dffad0e22591 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Mon, 30 Aug 2010 10:45:54 +0900 Subject: ARM: SAMSUNG: Fix on drive strength value This patch fixes on defined drive strength value for GPIO. According to data sheet, if we want drive strength 1x, the value should be 00(b), if 2x should be 10(b), if 3x should be 01(b), and if 4x should be 11(b). Also fixes comment(from S5C to S5P). Reported-by: Janghyuck Kim Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/include/plat/gpio-cfg.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h index db4112c6f2be..1c6b92947c5d 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h @@ -143,12 +143,12 @@ extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin); /* Define values for the drvstr available for each gpio pin. * * These values control the value of the output signal driver strength, - * configurable on most pins on the S5C series. + * configurable on most pins on the S5P series. */ -#define S5P_GPIO_DRVSTR_LV1 ((__force s5p_gpio_drvstr_t)0x00) -#define S5P_GPIO_DRVSTR_LV2 ((__force s5p_gpio_drvstr_t)0x01) -#define S5P_GPIO_DRVSTR_LV3 ((__force s5p_gpio_drvstr_t)0x10) -#define S5P_GPIO_DRVSTR_LV4 ((__force s5p_gpio_drvstr_t)0x11) +#define S5P_GPIO_DRVSTR_LV1 ((__force s5p_gpio_drvstr_t)0x0) +#define S5P_GPIO_DRVSTR_LV2 ((__force s5p_gpio_drvstr_t)0x2) +#define S5P_GPIO_DRVSTR_LV3 ((__force s5p_gpio_drvstr_t)0x1) +#define S5P_GPIO_DRVSTR_LV4 ((__force s5p_gpio_drvstr_t)0x3) /** * s5c_gpio_get_drvstr() - get the driver streght value of a gpio pin -- cgit v1.2.2 From cbd2780fcefc370732c1f1526fb784573308177d Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Mon, 30 Aug 2010 12:07:58 +0900 Subject: ARM: SAMSUNG: Fix on s5p_gpio_[get,set]_drvstr This patch fixes bug on gpio drive strength helper function. The offset should be like follwoing. - off = chip->chip.base - pin; + off = pin - chip->chip.base; In the s5p_gpio_get_drvstr(), the second line is unnecessary, because overwrite drvstr. drvstr = __raw_readl(reg); - drvstr = 0xffff & (0x3 << shift); And need 2bit masking before return the drvstr value. drvstr = drvstr >> shift; + drvstr &= 0x3; In the s5p_gpio_set_drvstr(), need relevant bit clear. tmp = __raw_readl(reg); + tmp &= ~(0x3 << shift); tmp |= drvstr << shift; Reported-by: Jaecheol Lee Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/gpio-config.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c index 57b68a50f45e..e3d41eaed1ff 100644 --- a/arch/arm/plat-samsung/gpio-config.c +++ b/arch/arm/plat-samsung/gpio-config.c @@ -273,13 +273,13 @@ s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin) if (!chip) return -EINVAL; - off = chip->chip.base - pin; + off = pin - chip->chip.base; shift = off * 2; reg = chip->base + 0x0C; drvstr = __raw_readl(reg); - drvstr = 0xffff & (0x3 << shift); drvstr = drvstr >> shift; + drvstr &= 0x3; return (__force s5p_gpio_drvstr_t)drvstr; } @@ -296,11 +296,12 @@ int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr) if (!chip) return -EINVAL; - off = chip->chip.base - pin; + off = pin - chip->chip.base; shift = off * 2; reg = chip->base + 0x0C; tmp = __raw_readl(reg); + tmp &= ~(0x3 << shift); tmp |= drvstr << shift; __raw_writel(tmp, reg); -- cgit v1.2.2 From 23a07eb0e8ea7d5b6ac41f2cc647e7ae53859292 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 9 Sep 2010 11:12:37 +0900 Subject: ARM: S3C64XX: Fix dev-spi build The irqs.h usage here got missed in the Samsung platform reorganisation. Signed-off-by: Mark Brown Acked-by: Jassi Brar Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/dev-spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-s3c64xx/dev-spi.c b/arch/arm/mach-s3c64xx/dev-spi.c index a492b982aa06..bfa3ef770bd8 100644 --- a/arch/arm/mach-s3c64xx/dev-spi.c +++ b/arch/arm/mach-s3c64xx/dev-spi.c @@ -18,10 +18,10 @@ #include #include #include +#include #include #include -#include static char *spi_src_clks[] = { [S3C64XX_SPI_SRCCLK_PCLK] = "pclk", -- cgit v1.2.2 From 54ff7e595d763d894104d421b103a89f7becf47c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 14 Sep 2010 22:10:21 +0200 Subject: x86: hpet: Work around hardware stupidity This more or less reverts commits 08be979 (x86: Force HPET readback_cmp for all ATI chipsets) and 30a564be (x86, hpet: Restrict read back to affected ATI chipsets) to the status of commit 8da854c (x86, hpet: Erratum workaround for read after write of HPET comparator). The delta to commit 8da854c is mostly comments and the change from WARN_ONCE to printk_once as we know the call path of this function already. This needs really in depth explanation: First of all the HPET design is a complete failure. Having a counter compare register which generates an interrupt on matching values forces the software to do at least one superfluous readback of the counter register. While it is nice in theory to program "absolute" time events it is practically useless because the timer runs at some absurd frequency which can never be matched to real world units. So we are forced to calculate a relative delta and this forces a readout of the actual counter value, adding the delta and programming the compare register. When the delta is small enough we run into the danger that we program a compare value which is already in the past. Due to the compare for equal nature of HPET we need to read back the counter value after writing the compare rehgister (btw. this is necessary for absolute timeouts as well) to make sure that we did not miss the timer event. We try to work around that by setting the minimum delta to a value which is larger than the theoretical time which elapses between the counter readout and the compare register write, but that's only true in theory. A NMI or SMI which hits between the readout and the write can easily push us beyond that limit. This would result in waiting for the next HPET timer interrupt until the 32bit wraparound of the counter happens which takes about 306 seconds. So we designed the next event function to look like: match = read_cnt() + delta; write_compare_ref(match); return read_cnt() < match ? 0 : -ETIME; At some point we got into trouble with certain ATI chipsets. Even the above "safe" procedure failed. The reason was that the write to the compare register was delayed probably for performance reasons. The theory was that they wanted to avoid the synchronization of the write with the HPET clock, which is understandable. So the write does not hit the compare register directly instead it goes to some intermediate register which is copied to the real compare register in sync with the HPET clock. That opens another window for hitting the dreaded "wait for a wraparound" problem. To work around that "optimization" we added a read back of the compare register which either enforced the update of the just written value or just delayed the readout of the counter enough to avoid the issue. We unfortunately never got any affirmative info from ATI/AMD about this. One thing is sure, that we nuked the performance "optimization" that way completely and I'm pretty sure that the result is worse than before some HW folks came up with those. Just for paranoia reasons I added a check whether the read back compare register value was the same as the value we wrote right before. That paranoia check triggered a couple of years after it was added on an Intel ICH9 chipset. Venki added a workaround (commit 8da854c) which was reading the compare register twice when the first check failed. We considered this to be a penalty in general and restricted the readback (thus the wasted CPU cycles) to the known to be affected ATI chipsets. This turned out to be a utterly wrong decision. 2.6.35 testers experienced massive problems and finally one of them bisected it down to commit 30a564be which spured some further investigation. Finally we got confirmation that the write to the compare register can be delayed by up to two HPET clock cycles which explains the problems nicely. All we can do about this is to go back to Venki's initial workaround in a slightly modified version. Just for the record I need to say, that all of this could have been avoided if hardware designers and of course the HPET committee would have thought about the consequences for a split second. It's out of my comprehension why designing a working timer is so hard. There are two ways to achieve it: 1) Use a counter wrap around aware compare_reg <= counter_reg implementation instead of the easy compare_reg == counter_reg Downsides: - It needs more silicon. - It needs a readout of the counter to apply a relative timeout. This is necessary as the counter does not run in any useful (and adjustable) frequency and there is no guarantee that the counter which is used for timer events is the same which is used for reading the actual time (and therefor for calculating the delta) Upsides: - None 2) Use a simple down counter for relative timer events Downsides: - Absolute timeouts are not possible, which is not a problem at all in the context of an OS and the expected max. latencies/jitter (also see Downsides of #1) Upsides: - It needs less or equal silicon. - It works ALWAYS - It is way faster than a compare register based solution (One write versus one write plus at least one and up to four reads) I would not be so grumpy about all of this, if I would not have been ignored for many years when pointing out these flaws to various hardware folks. I really hate timers (at least those which seem to be designed by janitors). Though finally we got a reasonable explanation plus a solution and I want to thank all the folks involved in chasing it down and providing valuable input to this. Bisected-by: Nix Reported-by: Artur Skawina Reported-by: Damien Wyart Reported-by: John Drescher Cc: Venkatesh Pallipadi Cc: Ingo Molnar Cc: H. Peter Anvin Cc: Arjan van de Ven Cc: Andreas Herrmann Cc: Borislav Petkov Cc: stable@kernel.org Acked-by: Suresh Siddha Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/hpet.h | 1 - arch/x86/kernel/early-quirks.c | 18 ------------------ arch/x86/kernel/hpet.c | 31 +++++++++++++++++-------------- 3 files changed, 17 insertions(+), 33 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h index 004e6e25e913..1d5c08a1bdfd 100644 --- a/arch/x86/include/asm/hpet.h +++ b/arch/x86/include/asm/hpet.h @@ -68,7 +68,6 @@ extern unsigned long force_hpet_address; extern u8 hpet_blockid; extern int hpet_force_user; extern u8 hpet_msi_disable; -extern u8 hpet_readback_cmp; extern int is_hpet_enabled(void); extern int hpet_enable(void); extern void hpet_disable(void); diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index e5cc7e82e60d..ebdb85cf2686 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -18,7 +18,6 @@ #include #include #include -#include static void __init fix_hypertransport_config(int num, int slot, int func) { @@ -192,21 +191,6 @@ static void __init ati_bugs_contd(int num, int slot, int func) } #endif -/* - * Force the read back of the CMP register in hpet_next_event() - * to work around the problem that the CMP register write seems to be - * delayed. See hpet_next_event() for details. - * - * We do this on all SMBUS incarnations for now until we have more - * information about the affected chipsets. - */ -static void __init ati_hpet_bugs(int num, int slot, int func) -{ -#ifdef CONFIG_HPET_TIMER - hpet_readback_cmp = 1; -#endif -} - #define QFLAG_APPLY_ONCE 0x1 #define QFLAG_APPLIED 0x2 #define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED) @@ -236,8 +220,6 @@ static struct chipset early_qrk[] __initdata = { PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs }, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs_contd }, - { PCI_VENDOR_ID_ATI, PCI_ANY_ID, - PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_hpet_bugs }, {} }; diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 351f9c0fea1f..410fdb3f1939 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -35,7 +35,6 @@ unsigned long hpet_address; u8 hpet_blockid; /* OS timer block num */ u8 hpet_msi_disable; -u8 hpet_readback_cmp; #ifdef CONFIG_PCI_MSI static unsigned long hpet_num_timers; @@ -395,23 +394,27 @@ static int hpet_next_event(unsigned long delta, * at that point and we would wait for the next hpet interrupt * forever. We found out that reading the CMP register back * forces the transfer so we can rely on the comparison with - * the counter register below. + * the counter register below. If the read back from the + * compare register does not match the value we programmed + * then we might have a real hardware problem. We can not do + * much about it here, but at least alert the user/admin with + * a prominent warning. * - * That works fine on those ATI chipsets, but on newer Intel - * chipsets (ICH9...) this triggers due to an erratum: Reading - * the comparator immediately following a write is returning - * the old value. + * An erratum on some chipsets (ICH9,..), results in + * comparator read immediately following a write returning old + * value. Workaround for this is to read this value second + * time, when first read returns old value. * - * We restrict the read back to the affected ATI chipsets (set - * by quirks) and also run it with hpet=verbose for debugging - * purposes. + * In fact the write to the comparator register is delayed up + * to two HPET cycles so the workaround we tried to restrict + * the readback to those known to be borked ATI chipsets + * failed miserably. So we give up on optimizations forever + * and penalize all HPET incarnations unconditionally. */ - if (hpet_readback_cmp || hpet_verbose) { - u32 cmp = hpet_readl(HPET_Tn_CMP(timer)); - - if (cmp != cnt) + if (unlikely((u32)hpet_readl(HPET_Tn_CMP(timer)) != cnt)) { + if (hpet_readl(HPET_Tn_CMP(timer)) != cnt) printk_once(KERN_WARNING - "hpet: compare register read back failed.\n"); + "hpet: compare register read back failed.\n"); } return (s32)(hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0; -- cgit v1.2.2 From c41d68a513c71e35a14f66d71782d27a79a81ea6 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 7 Sep 2010 16:16:18 -0700 Subject: compat: Make compat_alloc_user_space() incorporate the access_ok() compat_alloc_user_space() expects the caller to independently call access_ok() to verify the returned area. A missing call could introduce problems on some architectures. This patch incorporates the access_ok() check into compat_alloc_user_space() and also adds a sanity check on the length. The existing compat_alloc_user_space() implementations are renamed arch_compat_alloc_user_space() and are used as part of the implementation of the new global function. This patch assumes NULL will cause __get_user()/__put_user() to either fail or access userspace on all architectures. This should be followed by checking the return value of compat_access_user_space() for NULL in the callers, at which time the access_ok() in the callers can also be removed. Reported-by: Ben Hawkes Signed-off-by: H. Peter Anvin Acked-by: Benjamin Herrenschmidt Acked-by: Chris Metcalf Acked-by: David S. Miller Acked-by: Ingo Molnar Acked-by: Thomas Gleixner Acked-by: Tony Luck Cc: Andrew Morton Cc: Arnd Bergmann Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Heiko Carstens Cc: Helge Deller Cc: James Bottomley Cc: Kyle McMartin Cc: Martin Schwidefsky Cc: Paul Mackerras Cc: Ralf Baechle Cc: --- arch/ia64/include/asm/compat.h | 2 +- arch/mips/include/asm/compat.h | 2 +- arch/parisc/include/asm/compat.h | 2 +- arch/powerpc/include/asm/compat.h | 2 +- arch/s390/include/asm/compat.h | 2 +- arch/sparc/include/asm/compat.h | 2 +- arch/tile/include/asm/compat.h | 2 +- arch/x86/include/asm/compat.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h index f90edc85b509..9301a2821615 100644 --- a/arch/ia64/include/asm/compat.h +++ b/arch/ia64/include/asm/compat.h @@ -199,7 +199,7 @@ ptr_to_compat(void __user *uptr) } static __inline__ void __user * -compat_alloc_user_space (long len) +arch_compat_alloc_user_space (long len) { struct pt_regs *regs = task_pt_regs(current); return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len); diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h index 613f6912dfc1..dbc51065df5b 100644 --- a/arch/mips/include/asm/compat.h +++ b/arch/mips/include/asm/compat.h @@ -145,7 +145,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = (struct pt_regs *) ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1; diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h index 02b77baa5da6..efa0b60c63fe 100644 --- a/arch/parisc/include/asm/compat.h +++ b/arch/parisc/include/asm/compat.h @@ -147,7 +147,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static __inline__ void __user *compat_alloc_user_space(long len) +static __inline__ void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = ¤t->thread.regs; return (void __user *)regs->gr[30]; diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index 396d21a80058..a11d4eac4f97 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h @@ -134,7 +134,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = current->thread.regs; unsigned long usp = regs->gpr[1]; diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index 104f2007f097..a875c2f542e1 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h @@ -181,7 +181,7 @@ static inline int is_compat_task(void) #endif -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { unsigned long stack; diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index 5016f76ea98a..6f57325bb883 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h @@ -167,7 +167,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = current_thread_info()->kregs; unsigned long usp = regs->u_regs[UREG_I6]; diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h index 5a34da6cdd79..345d81ce44bb 100644 --- a/arch/tile/include/asm/compat.h +++ b/arch/tile/include/asm/compat.h @@ -195,7 +195,7 @@ static inline unsigned long ptr_to_compat_reg(void __user *uptr) return (long)(int)(long __force)uptr; } -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = task_pt_regs(current); return (void __user *)regs->sp - len; diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h index 306160e58b48..1d9cd27c2920 100644 --- a/arch/x86/include/asm/compat.h +++ b/arch/x86/include/asm/compat.h @@ -205,7 +205,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = task_pt_regs(current); return (void __user *)regs->sp - len; -- cgit v1.2.2 From 36d001c70d8a0144ac1d038f6876c484849a74de Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 14 Sep 2010 12:42:41 -0700 Subject: x86-64, compat: Test %rax for the syscall number, not %eax On 64 bits, we always, by necessity, jump through the system call table via %rax. For 32-bit system calls, in theory the system call number is stored in %eax, and the code was testing %eax for a valid system call number. At one point we loaded the stored value back from the stack to enforce zero-extension, but that was removed in checkin d4d67150165df8bf1cc05e532f6efca96f907cab. An actual 32-bit process will not be able to introduce a non-zero-extended number, but it can happen via ptrace. Instead of re-introducing the zero-extension, test what we are actually going to use, i.e. %rax. This only adds a handful of REX prefixes to the code. Reported-by: Ben Hawkes Signed-off-by: H. Peter Anvin Cc: Cc: Roland McGrath Cc: Andrew Morton --- arch/x86/ia32/ia32entry.S | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index b86feabed69b..84e3a4ef9719 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -153,7 +153,7 @@ ENTRY(ia32_sysenter_target) testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) CFI_REMEMBER_STATE jnz sysenter_tracesys - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja ia32_badsys sysenter_do_call: IA32_ARG_FIXUP @@ -195,7 +195,7 @@ sysexit_from_sys_call: movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */ call audit_syscall_entry movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */ - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja ia32_badsys movl %ebx,%edi /* reload 1st syscall arg */ movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */ @@ -248,7 +248,7 @@ sysenter_tracesys: call syscall_trace_enter LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ jmp sysenter_do_call CFI_ENDPROC @@ -314,7 +314,7 @@ ENTRY(ia32_cstar_target) testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) CFI_REMEMBER_STATE jnz cstar_tracesys - cmpl $IA32_NR_syscalls-1,%eax + cmpq $IA32_NR_syscalls-1,%rax ja ia32_badsys cstar_do_call: IA32_ARG_FIXUP 1 @@ -367,7 +367,7 @@ cstar_tracesys: LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */ RESTORE_REST xchgl %ebp,%r9d - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */ jmp cstar_do_call END(ia32_cstar_target) @@ -425,7 +425,7 @@ ENTRY(ia32_syscall) orl $TS_COMPAT,TI_status(%r10) testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) jnz ia32_tracesys - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja ia32_badsys ia32_do_call: IA32_ARG_FIXUP @@ -444,7 +444,7 @@ ia32_tracesys: call syscall_trace_enter LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ jmp ia32_do_call END(ia32_syscall) -- cgit v1.2.2 From eefdca043e8391dcd719711716492063030b55ac Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 14 Sep 2010 12:22:58 -0700 Subject: x86-64, compat: Retruncate rax after ia32 syscall entry tracing In commit d4d6715, we reopened an old hole for a 64-bit ptracer touching a 32-bit tracee in system call entry. A %rax value set via ptrace at the entry tracing stop gets used whole as a 32-bit syscall number, while we only check the low 32 bits for validity. Fix it by truncating %rax back to 32 bits after syscall_trace_enter, in addition to testing the full 64 bits as has already been added. Reported-by: Ben Hawkes Signed-off-by: Roland McGrath Signed-off-by: H. Peter Anvin --- arch/x86/ia32/ia32entry.S | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 84e3a4ef9719..518bb99c3394 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -50,7 +50,12 @@ /* * Reload arg registers from stack in case ptrace changed them. * We don't reload %eax because syscall_trace_enter() returned - * the value it wants us to use in the table lookup. + * the %rax value we should see. Instead, we just truncate that + * value to 32 bits again as we did on entry from user mode. + * If it's a new value set by user_regset during entry tracing, + * this matches the normal truncation of the user-mode value. + * If it's -1 to make us punt the syscall, then (u32)-1 is still + * an appropriately invalid value. */ .macro LOAD_ARGS32 offset, _r9=0 .if \_r9 @@ -60,6 +65,7 @@ movl \offset+48(%rsp),%edx movl \offset+56(%rsp),%esi movl \offset+64(%rsp),%edi + movl %eax,%eax /* zero extension */ .endm .macro CFI_STARTPROC32 simple -- cgit v1.2.2 From a4128b03ff1ff5bc6ea922518a3f36a09b914379 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 14 Sep 2010 17:59:15 +0100 Subject: MN10300: Fix up the IRQ names for the on-chip serial ports Fix up the IRQ names for the MN10300 on-chip serial ports in the driver as request_interrupt() no longer allows names containing slashes, giving a warning like the following if one is encountered: ------------[ cut here ]------------ WARNING: at fs/proc/generic.c:323 __xlate_proc_name+0x62/0x7c() name 'ttySM0/Rx' Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/mn10300/kernel/mn10300-serial.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c index 9d49073e827a..db509dd80565 100644 --- a/arch/mn10300/kernel/mn10300-serial.c +++ b/arch/mn10300/kernel/mn10300-serial.c @@ -156,17 +156,17 @@ struct mn10300_serial_port mn10300_serial_port_sif0 = { ._intr = &SC0ICR, ._rxb = &SC0RXB, ._txb = &SC0TXB, - .rx_name = "ttySM0/Rx", - .tx_name = "ttySM0/Tx", + .rx_name = "ttySM0:Rx", + .tx_name = "ttySM0:Tx", #ifdef CONFIG_MN10300_TTYSM0_TIMER8 - .tm_name = "ttySM0/Timer8", + .tm_name = "ttySM0:Timer8", ._tmxmd = &TM8MD, ._tmxbr = &TM8BR, ._tmicr = &TM8ICR, .tm_irq = TM8IRQ, .div_timer = MNSCx_DIV_TIMER_16BIT, #else /* CONFIG_MN10300_TTYSM0_TIMER2 */ - .tm_name = "ttySM0/Timer2", + .tm_name = "ttySM0:Timer2", ._tmxmd = &TM2MD, ._tmxbr = (volatile u16 *) &TM2BR, ._tmicr = &TM2ICR, @@ -209,17 +209,17 @@ struct mn10300_serial_port mn10300_serial_port_sif1 = { ._intr = &SC1ICR, ._rxb = &SC1RXB, ._txb = &SC1TXB, - .rx_name = "ttySM1/Rx", - .tx_name = "ttySM1/Tx", + .rx_name = "ttySM1:Rx", + .tx_name = "ttySM1:Tx", #ifdef CONFIG_MN10300_TTYSM1_TIMER9 - .tm_name = "ttySM1/Timer9", + .tm_name = "ttySM1:Timer9", ._tmxmd = &TM9MD, ._tmxbr = &TM9BR, ._tmicr = &TM9ICR, .tm_irq = TM9IRQ, .div_timer = MNSCx_DIV_TIMER_16BIT, #else /* CONFIG_MN10300_TTYSM1_TIMER3 */ - .tm_name = "ttySM1/Timer3", + .tm_name = "ttySM1:Timer3", ._tmxmd = &TM3MD, ._tmxbr = (volatile u16 *) &TM3BR, ._tmicr = &TM3ICR, @@ -260,9 +260,9 @@ struct mn10300_serial_port mn10300_serial_port_sif2 = { .uart.lock = __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock), .name = "ttySM2", - .rx_name = "ttySM2/Rx", - .tx_name = "ttySM2/Tx", - .tm_name = "ttySM2/Timer10", + .rx_name = "ttySM2:Rx", + .tx_name = "ttySM2:Tx", + .tm_name = "ttySM2:Timer10", ._iobase = &SC2CTR, ._control = &SC2CTR, ._status = &SC2STR, -- cgit v1.2.2 From e6e6c46d759cd013cb57eba112a4129a3a353c4b Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Wed, 15 Sep 2010 11:16:05 -0400 Subject: arch/tile: finish const-ifying sys_execve() The sys_execve() implementation was properly const-ified but not the declaration, the syscall wrappers, or the compat version. This change completes the constification process. Signed-off-by: Chris Metcalf --- arch/tile/include/asm/compat.h | 5 +++-- arch/tile/include/asm/syscalls.h | 21 +++++++++++++-------- arch/tile/kernel/process.c | 5 +++-- 3 files changed, 19 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h index 5a34da6cdd79..070ad0a5ef1c 100644 --- a/arch/tile/include/asm/compat.h +++ b/arch/tile/include/asm/compat.h @@ -214,8 +214,9 @@ extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka, struct compat_sigaction; struct compat_siginfo; struct compat_sigaltstack; -long compat_sys_execve(char __user *path, compat_uptr_t __user *argv, - compat_uptr_t __user *envp); +long compat_sys_execve(const char __user *path, + const compat_uptr_t __user *argv, + const compat_uptr_t __user *envp); long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, struct compat_sigaction __user *oact, size_t sigsetsize); diff --git a/arch/tile/include/asm/syscalls.h b/arch/tile/include/asm/syscalls.h index af165a74537f..ce99ffefeacf 100644 --- a/arch/tile/include/asm/syscalls.h +++ b/arch/tile/include/asm/syscalls.h @@ -62,10 +62,12 @@ long sys_fork(void); long _sys_fork(struct pt_regs *regs); long sys_vfork(void); long _sys_vfork(struct pt_regs *regs); -long sys_execve(char __user *filename, char __user * __user *argv, - char __user * __user *envp); -long _sys_execve(char __user *filename, char __user * __user *argv, - char __user * __user *envp, struct pt_regs *regs); +long sys_execve(const char __user *filename, + const char __user *const __user *argv, + const char __user *const __user *envp); +long _sys_execve(const char __user *filename, + const char __user *const __user *argv, + const char __user *const __user *envp, struct pt_regs *regs); /* kernel/signal.c */ long sys_sigaltstack(const stack_t __user *, stack_t __user *); @@ -86,10 +88,13 @@ int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *); #endif #ifdef CONFIG_COMPAT -long compat_sys_execve(char __user *path, compat_uptr_t __user *argv, - compat_uptr_t __user *envp); -long _compat_sys_execve(char __user *path, compat_uptr_t __user *argv, - compat_uptr_t __user *envp, struct pt_regs *regs); +long compat_sys_execve(const char __user *path, + const compat_uptr_t __user *argv, + const compat_uptr_t __user *envp); +long _compat_sys_execve(const char __user *path, + const compat_uptr_t __user *argv, + const compat_uptr_t __user *envp, + struct pt_regs *regs); long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, struct compat_sigaltstack __user *uoss_ptr); long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 985cc28c74c5..88be49e3aa25 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c @@ -561,8 +561,9 @@ out: } #ifdef CONFIG_COMPAT -long _compat_sys_execve(char __user *path, compat_uptr_t __user *argv, - compat_uptr_t __user *envp, struct pt_regs *regs) +long _compat_sys_execve(const char __user *path, + const compat_uptr_t __user *argv, + const compat_uptr_t __user *envp, struct pt_regs *regs) { long error; char *filename; -- cgit v1.2.2 From 74fca9da097b74117ae2cef9e5f0d9b0e28ccbb7 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Wed, 15 Sep 2010 11:16:08 -0400 Subject: arch/tile: Change struct sigcontext to be more useful Rather than just using pt_regs, it now contains the actual saved state explicitly, similar to pt_regs. By doing it this way, we provide a cleaner API for userspace (or equivalently, we avoid the need for libc to provide its own definition of sigcontext). While we're at it, move PT_FLAGS_xxx to where they are not visible from userspace. And always pass siginfo and mcontext to signal handlers, even if they claim they don't need it, since sometimes they actually try to use it anyway in practice. Signed-off-by: Chris Metcalf --- arch/tile/include/asm/ptrace.h | 15 ++++++--------- arch/tile/include/asm/sigcontext.h | 18 +++++++++++++----- arch/tile/include/asm/signal.h | 1 + arch/tile/kernel/signal.c | 27 +++++++++++++++------------ arch/tile/kernel/stack.c | 2 +- 5 files changed, 36 insertions(+), 27 deletions(-) (limited to 'arch') diff --git a/arch/tile/include/asm/ptrace.h b/arch/tile/include/asm/ptrace.h index acdae814e016..4a02bb073979 100644 --- a/arch/tile/include/asm/ptrace.h +++ b/arch/tile/include/asm/ptrace.h @@ -51,10 +51,7 @@ typedef uint_reg_t pt_reg_t; /* * This struct defines the way the registers are stored on the stack during a - * system call/exception. It should be a multiple of 8 bytes to preserve - * normal stack alignment rules. - * - * Must track and + * system call or exception. "struct sigcontext" has the same shape. */ struct pt_regs { /* Saved main processor registers; 56..63 are special. */ @@ -80,11 +77,6 @@ struct pt_regs { #endif /* __ASSEMBLY__ */ -/* Flag bits in pt_regs.flags */ -#define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */ -#define PT_FLAGS_CALLER_SAVES 2 /* caller-save registers are valid */ -#define PT_FLAGS_RESTORE_REGS 4 /* restore callee-save regs on return */ - #define PTRACE_GETREGS 12 #define PTRACE_SETREGS 13 #define PTRACE_GETFPREGS 14 @@ -101,6 +93,11 @@ struct pt_regs { #ifdef __KERNEL__ +/* Flag bits in pt_regs.flags */ +#define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */ +#define PT_FLAGS_CALLER_SAVES 2 /* caller-save registers are valid */ +#define PT_FLAGS_RESTORE_REGS 4 /* restore callee-save regs on return */ + #ifndef __ASSEMBLY__ #define instruction_pointer(regs) ((regs)->pc) diff --git a/arch/tile/include/asm/sigcontext.h b/arch/tile/include/asm/sigcontext.h index 7cd7672e3ad4..5e2d03336f53 100644 --- a/arch/tile/include/asm/sigcontext.h +++ b/arch/tile/include/asm/sigcontext.h @@ -15,13 +15,21 @@ #ifndef _ASM_TILE_SIGCONTEXT_H #define _ASM_TILE_SIGCONTEXT_H -/* NOTE: we can't include due to #include dependencies. */ -#include - -/* Must track */ +#include +/* + * struct sigcontext has the same shape as struct pt_regs, + * but is simplified since we know the fault is from userspace. + */ struct sigcontext { - struct pt_regs regs; + uint_reg_t gregs[53]; /* General-purpose registers. */ + uint_reg_t tp; /* Aliases gregs[TREG_TP]. */ + uint_reg_t sp; /* Aliases gregs[TREG_SP]. */ + uint_reg_t lr; /* Aliases gregs[TREG_LR]. */ + uint_reg_t pc; /* Program counter. */ + uint_reg_t ics; /* In Interrupt Critical Section? */ + uint_reg_t faultnum; /* Fault number. */ + uint_reg_t pad[5]; }; #endif /* _ASM_TILE_SIGCONTEXT_H */ diff --git a/arch/tile/include/asm/signal.h b/arch/tile/include/asm/signal.h index eb0253f32202..c1ee1d61d44c 100644 --- a/arch/tile/include/asm/signal.h +++ b/arch/tile/include/asm/signal.h @@ -24,6 +24,7 @@ #include #if defined(__KERNEL__) && !defined(__ASSEMBLY__) +struct pt_regs; int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); void do_signal(struct pt_regs *regs); diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c index 45b66a3c991f..ce183aa1492c 100644 --- a/arch/tile/kernel/signal.c +++ b/arch/tile/kernel/signal.c @@ -61,13 +61,19 @@ int restore_sigcontext(struct pt_regs *regs, /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; + /* + * Enforce that sigcontext is like pt_regs, and doesn't mess + * up our stack alignment rules. + */ + BUILD_BUG_ON(sizeof(struct sigcontext) != sizeof(struct pt_regs)); + BUILD_BUG_ON(sizeof(struct sigcontext) % 8 != 0); + for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) - err |= __get_user(((long *)regs)[i], - &((long __user *)(&sc->regs))[i]); + err |= __get_user(regs->regs[i], &sc->gregs[i]); regs->faultnum = INT_SWINT_1_SIGRETURN; - err |= __get_user(*pr0, &sc->regs.regs[0]); + err |= __get_user(*pr0, &sc->gregs[0]); return err; } @@ -112,8 +118,7 @@ int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) int i, err = 0; for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) - err |= __put_user(((long *)regs)[i], - &((long __user *)(&sc->regs))[i]); + err |= __put_user(regs->regs[i], &sc->gregs[i]); return err; } @@ -203,19 +208,17 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, * Set up registers for signal handler. * Registers that we don't modify keep the value they had from * user-space at the time we took the signal. + * We always pass siginfo and mcontext, regardless of SA_SIGINFO, + * since some things rely on this (e.g. glibc's debug/segfault.c). */ regs->pc = (unsigned long) ka->sa.sa_handler; regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ regs->sp = (unsigned long) frame; regs->lr = restorer; regs->regs[0] = (unsigned long) usig; - - if (ka->sa.sa_flags & SA_SIGINFO) { - /* Need extra arguments, so mark to restore caller-saves. */ - regs->regs[1] = (unsigned long) &frame->info; - regs->regs[2] = (unsigned long) &frame->uc; - regs->flags |= PT_FLAGS_CALLER_SAVES; - } + regs->regs[1] = (unsigned long) &frame->info; + regs->regs[2] = (unsigned long) &frame->uc; + regs->flags |= PT_FLAGS_CALLER_SAVES; /* * Notify any tracer that was single-stepping it. diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c index 38a68b0b4581..ea2e0ce28380 100644 --- a/arch/tile/kernel/stack.c +++ b/arch/tile/kernel/stack.c @@ -175,7 +175,7 @@ static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt) pr_err(" \n", frame->info.si_signo); } - return &frame->uc.uc_mcontext.regs; + return (struct pt_regs *)&frame->uc.uc_mcontext; } return NULL; } -- cgit v1.2.2 From a802fc685426303ab627b7ad3fd5c97b5dea7e00 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Wed, 15 Sep 2010 11:16:10 -0400 Subject: arch/tile: Save and restore extra user state for tilegx During context switch, save and restore a couple of additional bits of tilegx user state that can be persistently modified by userspace. Signed-off-by: Chris Metcalf --- arch/tile/include/arch/chip_tile64.h | 3 +++ arch/tile/include/arch/chip_tilepro.h | 3 +++ arch/tile/include/asm/processor.h | 12 ++++++++++++ arch/tile/kernel/process.c | 23 ++++++++++++++++------- 4 files changed, 34 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/tile/include/arch/chip_tile64.h b/arch/tile/include/arch/chip_tile64.h index 1246573be59e..261aaba092d4 100644 --- a/arch/tile/include/arch/chip_tile64.h +++ b/arch/tile/include/arch/chip_tile64.h @@ -150,6 +150,9 @@ /** Is the PROC_STATUS SPR supported? */ #define CHIP_HAS_PROC_STATUS_SPR() 0 +/** Is the DSTREAM_PF SPR supported? */ +#define CHIP_HAS_DSTREAM_PF() 0 + /** Log of the number of mshims we have. */ #define CHIP_LOG_NUM_MSHIMS() 2 diff --git a/arch/tile/include/arch/chip_tilepro.h b/arch/tile/include/arch/chip_tilepro.h index e864c47fc89c..70017699a74c 100644 --- a/arch/tile/include/arch/chip_tilepro.h +++ b/arch/tile/include/arch/chip_tilepro.h @@ -150,6 +150,9 @@ /** Is the PROC_STATUS SPR supported? */ #define CHIP_HAS_PROC_STATUS_SPR() 1 +/** Is the DSTREAM_PF SPR supported? */ +#define CHIP_HAS_DSTREAM_PF() 0 + /** Log of the number of mshims we have. */ #define CHIP_LOG_NUM_MSHIMS() 2 diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h index d942d09b252e..ccd5f8425688 100644 --- a/arch/tile/include/asm/processor.h +++ b/arch/tile/include/asm/processor.h @@ -103,6 +103,18 @@ struct thread_struct { /* Any other miscellaneous processor state bits */ unsigned long proc_status; #endif +#if !CHIP_HAS_FIXED_INTVEC_BASE() + /* Interrupt base for PL0 interrupts */ + unsigned long interrupt_vector_base; +#endif +#if CHIP_HAS_TILE_RTF_HWM() + /* Tile cache retry fifo high-water mark */ + unsigned long tile_rtf_hwm; +#endif +#if CHIP_HAS_DSTREAM_PF() + /* Data stream prefetch control */ + unsigned long dstream_pf; +#endif #ifdef CONFIG_HARDWALL /* Is this task tied to an activated hardwall? */ struct hardwall_info *hardwall; diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 88be49e3aa25..c37b6e3873c1 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c @@ -408,6 +408,15 @@ static void save_arch_state(struct thread_struct *t) #if CHIP_HAS_PROC_STATUS_SPR() t->proc_status = __insn_mfspr(SPR_PROC_STATUS); #endif +#if !CHIP_HAS_FIXED_INTVEC_BASE() + t->interrupt_vector_base = __insn_mfspr(SPR_INTERRUPT_VECTOR_BASE_0); +#endif +#if CHIP_HAS_TILE_RTF_HWM() + t->tile_rtf_hwm = __insn_mfspr(SPR_TILE_RTF_HWM); +#endif +#if CHIP_HAS_DSTREAM_PF() + t->dstream_pf = __insn_mfspr(SPR_DSTREAM_PF); +#endif } static void restore_arch_state(const struct thread_struct *t) @@ -428,14 +437,14 @@ static void restore_arch_state(const struct thread_struct *t) #if CHIP_HAS_PROC_STATUS_SPR() __insn_mtspr(SPR_PROC_STATUS, t->proc_status); #endif +#if !CHIP_HAS_FIXED_INTVEC_BASE() + __insn_mtspr(SPR_INTERRUPT_VECTOR_BASE_0, t->interrupt_vector_base); +#endif #if CHIP_HAS_TILE_RTF_HWM() - /* - * Clear this whenever we switch back to a process in case - * the previous process was monkeying with it. Even if enabled - * in CBOX_MSR1 via TILE_RTF_HWM_MIN, it's still just a - * performance hint, so isn't worth a full save/restore. - */ - __insn_mtspr(SPR_TILE_RTF_HWM, 0); + __insn_mtspr(SPR_TILE_RTF_HWM, t->tile_rtf_hwm); +#endif +#if CHIP_HAS_DSTREAM_PF() + __insn_mtspr(SPR_DSTREAM_PF, t->dstream_pf); #endif } -- cgit v1.2.2 From 0fab59e5ddb4e0557825e9ab8e41b66b5f336941 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Wed, 15 Sep 2010 11:17:04 -0400 Subject: arch/tile: fix memcpy_fromio()/memcpy_toio() signatures This tripped up a driver (not yet committed to git). Fix it now. Signed-off-by: Chris Metcalf --- arch/tile/include/asm/io.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/tile/include/asm/io.h b/arch/tile/include/asm/io.h index 8c95bef3fa45..ee43328713ab 100644 --- a/arch/tile/include/asm/io.h +++ b/arch/tile/include/asm/io.h @@ -164,22 +164,22 @@ static inline void _tile_writeq(u64 val, unsigned long addr) #define iowrite32 writel #define iowrite64 writeq -static inline void *memcpy_fromio(void *dst, void *src, int len) +static inline void memcpy_fromio(void *dst, const volatile void __iomem *src, + size_t len) { int x; BUG_ON((unsigned long)src & 0x3); for (x = 0; x < len; x += 4) *(u32 *)(dst + x) = readl(src + x); - return dst; } -static inline void *memcpy_toio(void *dst, void *src, int len) +static inline void memcpy_toio(volatile void __iomem *dst, const void *src, + size_t len) { int x; BUG_ON((unsigned long)dst & 0x3); for (x = 0; x < len; x += 4) writel(*(u32 *)(src + x), dst + x); - return dst; } /* -- cgit v1.2.2 From 7040dea4d2a0609241c7a98a944b7c432c69db2e Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Wed, 15 Sep 2010 11:17:05 -0400 Subject: arch/tile: fix formatting bug in register dumps This cut-and-paste bug was caused by rewriting the register dump code to use only a single printk per line of output. Signed-off-by: Chris Metcalf --- arch/tile/kernel/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index c37b6e3873c1..84c29111756c 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c @@ -667,7 +667,7 @@ void show_regs(struct pt_regs *regs) regs->regs[51], regs->regs[52], regs->tp); pr_err(" sp : "REGFMT" lr : "REGFMT"\n", regs->sp, regs->lr); #else - for (i = 0; i < 52; i += 3) + for (i = 0; i < 52; i += 4) pr_err(" r%-2d: "REGFMT" r%-2d: "REGFMT " r%-2d: "REGFMT" r%-2d: "REGFMT"\n", i, regs->regs[i], i+1, regs->regs[i+1], -- cgit v1.2.2 From 2d2b6901649a62977452be85df53eda2412def24 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Wed, 15 Sep 2010 15:35:48 -0700 Subject: [IA64] Optimize ticket spinlocks in fsys_rt_sigprocmask Tony's fix (f574c843191728d9407b766a027f779dcd27b272) has a small bug, it incorrectly uses "r3" as a scratch register in the first of the two unlock paths ... it is also inefficient. Optimize the fast path again. Signed-off-by: Petr Tesarik Signed-off-by: Tony Luck --- arch/ia64/kernel/fsys.S | 42 +++++++++++------------------------------- 1 file changed, 11 insertions(+), 31 deletions(-) (limited to 'arch') diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index 471a1e783aca..331d42bda77a 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S @@ -420,34 +420,31 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set ;; RSM_PSR_I(p0, r18, r19) // mask interrupt delivery - mov ar.ccv=0 andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP + mov r8=EINVAL // default to EINVAL #ifdef CONFIG_SMP // __ticket_spin_trylock(r31) ld4 r17=[r31] - mov r8=EINVAL // default to EINVAL - ;; - extr r9=r17,17,15 ;; - xor r18=r17,r9 + mov.m ar.ccv=r17 + extr.u r9=r17,17,15 adds r19=1,r17 + extr.u r18=r17,0,15 ;; - extr.u r18=r18,0,15 + cmp.eq p6,p7=r9,r18 ;; - cmp.eq p0,p7=0,r18 +(p6) cmpxchg4.acq r9=[r31],r19,ar.ccv +(p6) dep.z r20=r19,1,15 // next serving ticket for unlock (p7) br.cond.spnt.many .lock_contention - mov.m ar.ccv=r17 - ;; - cmpxchg4.acq r9=[r31],r19,ar.ccv ;; cmp4.eq p0,p7=r9,r17 + adds r31=2,r31 (p7) br.cond.spnt.many .lock_contention ld8 r3=[r2] // re-read current->blocked now that we hold the lock ;; #else ld8 r3=[r2] // re-read current->blocked now that we hold the lock - mov r8=EINVAL // default to EINVAL #endif add r18=IA64_TASK_PENDING_OFFSET+IA64_SIGPENDING_SIGNAL_OFFSET,r16 add r19=IA64_TASK_SIGNAL_OFFSET,r16 @@ -503,16 +500,8 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set #ifdef CONFIG_SMP // __ticket_spin_unlock(r31) - adds r31=2,r31 - ;; - ld2.bias r2=[r31] - mov r3=65534 - ;; - adds r2=2,r2 - ;; - and r3=r3,r2 - ;; - st2.rel [r31]=r3 + st2.rel [r31]=r20 + mov r20=0 // i must not leak kernel bits... #endif SSM_PSR_I(p0, p9, r31) ;; @@ -535,16 +524,7 @@ EX(.fail_efault, (p15) st8 [r34]=r3) .sig_pending: #ifdef CONFIG_SMP // __ticket_spin_unlock(r31) - adds r31=2,r31 - ;; - ld2.bias r2=[r31] - mov r3=65534 - ;; - adds r2=2,r2 - ;; - and r3=r3,r2 - ;; - st2.rel [r31]=r3 + st2.rel [r31]=r20 // release the lock #endif SSM_PSR_I(p0, p9, r17) ;; -- cgit v1.2.2 From c33f543d320843e1732534c3931da4bbd18e6c14 Mon Sep 17 00:00:00 2001 From: Patrick Simmons Date: Wed, 8 Sep 2010 10:34:28 -0400 Subject: oprofile: Add Support for Intel CPU Family 6 / Model 22 (Intel Celeron 540) This patch adds CPU type detection for the Intel Celeron 540, which is part of the Core 2 family according to Wikipedia; the family and ID pair is absent from the Volume 3B table referenced in the source code comments. I have tested this patch on an Intel Celeron 540 machine reporting itself as Family 6 Model 22, and OProfile runs on the machine without issue. Spec: http://download.intel.com/design/mobile/SPECUPDT/317667.pdf Signed-off-by: Patrick Simmons Acked-by: Andi Kleen Acked-by: Arnd Bergmann Cc: stable@kernel.org Signed-off-by: Robert Richter --- arch/x86/oprofile/nmi_int.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index cfe4faabb0f6..009b819f48d0 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -671,7 +671,9 @@ static int __init ppro_init(char **cpu_type) case 14: *cpu_type = "i386/core"; break; - case 15: case 23: + case 0x0f: + case 0x16: + case 0x17: *cpu_type = "i386/core_2"; break; case 0x1a: -- cgit v1.2.2 From 89e45aac42d40426c97e6901811309bf49c4993f Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Fri, 17 Sep 2010 03:24:13 +0200 Subject: x86: Fix instruction breakpoint encoding Lengths and types of breakpoints are encoded in a half byte into CPU registers. However when we extract these values and store them, we add a high half byte part to them: 0x40 to the length and 0x80 to the type. When that gets reloaded to the CPU registers, the high part is masked. While making the instruction breakpoints available for perf, I zapped that high part on instruction breakpoint encoding and that broke the arch -> generic translation used by ptrace instruction breakpoints. Writing dr7 to set an inst breakpoint was then failing. There is no apparent reason for these high parts so we could get rid of them altogether. That's an invasive change though so let's do that later and for now fix the problem by restoring that inst breakpoint high part encoding in this sole patch. Reported-by: Kelvie Wong Signed-off-by: Frederic Weisbecker Cc: Prasad Cc: Mahesh Salgaonkar Cc: Will Deacon --- arch/x86/include/asm/hw_breakpoint.h | 2 +- arch/x86/kernel/hw_breakpoint.c | 40 +++++++++++++++++------------------- 2 files changed, 20 insertions(+), 22 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/hw_breakpoint.h b/arch/x86/include/asm/hw_breakpoint.h index 528a11e8d3e3..824ca07860d0 100644 --- a/arch/x86/include/asm/hw_breakpoint.h +++ b/arch/x86/include/asm/hw_breakpoint.h @@ -20,7 +20,7 @@ struct arch_hw_breakpoint { #include /* Available HW breakpoint length encodings */ -#define X86_BREAKPOINT_LEN_X 0x00 +#define X86_BREAKPOINT_LEN_X 0x40 #define X86_BREAKPOINT_LEN_1 0x40 #define X86_BREAKPOINT_LEN_2 0x44 #define X86_BREAKPOINT_LEN_4 0x4c diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c index a474ec37c32f..ff15c9dcc25d 100644 --- a/arch/x86/kernel/hw_breakpoint.c +++ b/arch/x86/kernel/hw_breakpoint.c @@ -206,11 +206,27 @@ int arch_check_bp_in_kernelspace(struct perf_event *bp) int arch_bp_generic_fields(int x86_len, int x86_type, int *gen_len, int *gen_type) { - /* Len */ - switch (x86_len) { - case X86_BREAKPOINT_LEN_X: + /* Type */ + switch (x86_type) { + case X86_BREAKPOINT_EXECUTE: + if (x86_len != X86_BREAKPOINT_LEN_X) + return -EINVAL; + + *gen_type = HW_BREAKPOINT_X; *gen_len = sizeof(long); + return 0; + case X86_BREAKPOINT_WRITE: + *gen_type = HW_BREAKPOINT_W; break; + case X86_BREAKPOINT_RW: + *gen_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R; + break; + default: + return -EINVAL; + } + + /* Len */ + switch (x86_len) { case X86_BREAKPOINT_LEN_1: *gen_len = HW_BREAKPOINT_LEN_1; break; @@ -229,21 +245,6 @@ int arch_bp_generic_fields(int x86_len, int x86_type, return -EINVAL; } - /* Type */ - switch (x86_type) { - case X86_BREAKPOINT_EXECUTE: - *gen_type = HW_BREAKPOINT_X; - break; - case X86_BREAKPOINT_WRITE: - *gen_type = HW_BREAKPOINT_W; - break; - case X86_BREAKPOINT_RW: - *gen_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R; - break; - default: - return -EINVAL; - } - return 0; } @@ -316,9 +317,6 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) ret = -EINVAL; switch (info->len) { - case X86_BREAKPOINT_LEN_X: - align = sizeof(long) -1; - break; case X86_BREAKPOINT_LEN_1: align = 0; break; -- cgit v1.2.2 From 99f76891a33d130776da3b01935d978b1e75fe68 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 13 Sep 2010 13:38:55 +0100 Subject: ARM: 6375/1: plat-nomadik: MTU timer trivial bug fix timer0 to 3 are all on mtu block 0, so don't calculate the clock event rate based upon mtu block 1's clock speed. Acked-by: Alessandro Rubini Signed-off-by: Jonas Aaberg Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/plat-nomadik/timer.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index ea3ca86c5283..d673888af18e 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c @@ -131,17 +131,12 @@ void __init nmdk_timer_init(void) { unsigned long rate; struct clk *clk0; - struct clk *clk1; u32 cr; clk0 = clk_get_sys("mtu0", NULL); BUG_ON(IS_ERR(clk0)); - clk1 = clk_get_sys("mtu1", NULL); - BUG_ON(IS_ERR(clk1)); - clk_enable(clk0); - clk_enable(clk1); /* * Tick rate is 2.4MHz for Nomadik and 110MHz for ux500: @@ -170,15 +165,8 @@ void __init nmdk_timer_init(void) pr_err("timer: failed to initialize clock source %s\n", nmdk_clksrc.name); - /* Timer 1 is used for events, fix according to rate */ - cr = MTU_CRn_32BITS; - rate = clk_get_rate(clk1); - if (rate > 16 << 20) { - rate /= 16; - cr |= MTU_CRn_PRESCALE_16; - } else { - cr |= MTU_CRn_PRESCALE_1; - } + /* Timer 1 is used for events */ + clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE); writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */ -- cgit v1.2.2 From a0719f52d90aed5b82ecf2f3ed14bc4ced3d1a8a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 13 Sep 2010 13:40:04 +0100 Subject: ARM: 6376/1: plat-nomadik: MTU: Change prescaler limit and comment updates The prescaler 16 is now used only when the timer runs at 32 MHz or more. Some comment updates as well. Acked-by: Alessandro Rubini Signed-off-by: Jonas Aaberg Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/plat-nomadik/timer.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index d673888af18e..aedf9c1d645e 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c @@ -1,5 +1,5 @@ /* - * linux/arch/arm/mach-nomadik/timer.c + * linux/arch/arm/plat-nomadik/timer.c * * Copyright (C) 2008 STMicroelectronics * Copyright (C) 2010 Alessandro Rubini @@ -75,7 +75,7 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode, cr = readl(mtu_base + MTU_CR(1)); writel(0, mtu_base + MTU_LR(1)); writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(1)); - writel(0x2, mtu_base + MTU_IMSC); + writel(1 << 1, mtu_base + MTU_IMSC); break; case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_UNUSED: @@ -131,7 +131,7 @@ void __init nmdk_timer_init(void) { unsigned long rate; struct clk *clk0; - u32 cr; + u32 cr = MTU_CRn_32BITS; clk0 = clk_get_sys("mtu0", NULL); BUG_ON(IS_ERR(clk0)); @@ -139,12 +139,15 @@ void __init nmdk_timer_init(void) clk_enable(clk0); /* - * Tick rate is 2.4MHz for Nomadik and 110MHz for ux500: - * use a divide-by-16 counter if it's more than 16MHz + * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz + * for ux500. + * Use a divide-by-16 counter if the tick rate is more than 32MHz. + * At 32 MHz, the timer (with 32 bit counter) can be programmed + * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer + * with 16 gives too low timer resolution. */ - cr = MTU_CRn_32BITS;; rate = clk_get_rate(clk0); - if (rate > 16 << 20) { + if (rate > 32000000) { rate /= 16; cr |= MTU_CRn_PRESCALE_16; } else { -- cgit v1.2.2 From 63f469324f999a28e67b90eb27a5fe0e379b7064 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 13 Sep 2010 13:44:47 +0100 Subject: ARM: 6377/1: supply _cansleep gpio function to U300 We have to use _cansleep gpio accessors in the MMCI driver so as to avoid slowpath warnings, now U300 has MMCI but doesn't have these functions in place to siply wrap the existing non-sleeping functions into sleepable variants. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-u300/include/mach/gpio.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-u300/include/mach/gpio.h b/arch/arm/mach-u300/include/mach/gpio.h index 7b1fc984abb6..d5a71abcbaea 100644 --- a/arch/arm/mach-u300/include/mach/gpio.h +++ b/arch/arm/mach-u300/include/mach/gpio.h @@ -273,6 +273,9 @@ extern void gpio_pullup(unsigned gpio, int value); extern int gpio_get_value(unsigned gpio); extern void gpio_set_value(unsigned gpio, int value); +#define gpio_get_value_cansleep gpio_get_value +#define gpio_set_value_cansleep gpio_set_value + /* wrappers to sleep-enable the previous two functions */ static inline unsigned gpio_to_irq(unsigned gpio) { -- cgit v1.2.2 From 6491848d1ab246f6d243ddef25085fc1d836ff2c Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 14 Sep 2010 09:50:03 +0100 Subject: ARM: 6387/1: errata: check primary part ID in proc-v7.S Kconfig doesn't have any knowledge of specific v7 cores, so it is possible to select errata workarounds that may cause inadvertent behaviour when executed on a core other than those targetted by the fix. This patch improves the variant and revision checking in proc-v7.S so that the primary part number is also considered when applying errata workarounds. Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/proc-v7.S | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 6a8506d99ee9..1f16f9e3f441 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -204,8 +204,13 @@ __v7_setup: bne 2f and r5, r0, #0x00f00000 @ variant and r6, r0, #0x0000000f @ revision - orr r0, r6, r5, lsr #20-4 @ combine variant and revision + orr r6, r6, r5, lsr #20-4 @ combine variant and revision + ubfx r0, r0, #4, #12 @ primary part number + /* Cortex-A8 Errata */ + ldr r10, =0x00000c08 @ Cortex-A8 primary part number + teq r0, r10 + bne 2f #ifdef CONFIG_ARM_ERRATA_430973 teq r5, #0x00100000 @ only present in r1p* mrceq p15, 0, r10, c1, c0, 1 @ read aux control register @@ -213,14 +218,14 @@ __v7_setup: mcreq p15, 0, r10, c1, c0, 1 @ write aux control register #endif #ifdef CONFIG_ARM_ERRATA_458693 - teq r0, #0x20 @ only present in r2p0 + teq r6, #0x20 @ only present in r2p0 mrceq p15, 0, r10, c1, c0, 1 @ read aux control register orreq r10, r10, #(1 << 5) @ set L1NEON to 1 orreq r10, r10, #(1 << 9) @ set PLDNOP to 1 mcreq p15, 0, r10, c1, c0, 1 @ write aux control register #endif #ifdef CONFIG_ARM_ERRATA_460075 - teq r0, #0x20 @ only present in r2p0 + teq r6, #0x20 @ only present in r2p0 mrceq p15, 1, r10, c9, c0, 2 @ read L2 cache aux ctrl register tsteq r10, #1 << 22 orreq r10, r10, #(1 << 22) @ set the Write Allocate disable bit -- cgit v1.2.2 From 9f05027c7cb3cfe56a31892bd83391138d41a667 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 14 Sep 2010 09:51:43 +0100 Subject: ARM: 6388/1: errata: DMB operation may be faulty On versions of the Cortex-A9 up to and including r2p2, under rare circumstances, a DMB instruction between 2 write operations may not ensure the correct visibility ordering of the 2 writes. This workaround sets a bit in the diagnostic register of the Cortex-A9, causing the DMB instruction to behave like a DSB, which functions correctly on the affected cores. Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/Kconfig | 12 ++++++++++++ arch/arm/mm/proc-v7.S | 16 ++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 553b7cf17bfb..ab14c0a5d21e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1051,6 +1051,18 @@ config ARM_ERRATA_460075 ACTLR register. Note that setting specific bits in the ACTLR register may not be available in non-secure mode. +config ARM_ERRATA_742230 + bool "ARM errata: DMB operation may be faulty" + depends on CPU_V7 && SMP + help + This option enables the workaround for the 742230 Cortex-A9 + (r1p0..r2p2) erratum. Under rare circumstances, a DMB instruction + between two write operations may not ensure the correct visibility + ordering of the two writes. This workaround sets a specific bit in + the diagnostic register of the Cortex-A9 which causes the DMB + instruction to behave as a DSB, ensuring the correct behaviour of + the two writes. + config PL310_ERRATA_588369 bool "Clean & Invalidate maintenance operations do not invalidate clean lines" depends on CACHE_L2X0 && ARCH_OMAP4 diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 1f16f9e3f441..945f36341fa6 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -201,7 +201,7 @@ __v7_setup: mrc p15, 0, r0, c0, c0, 0 @ read main ID register and r10, r0, #0xff000000 @ ARM? teq r10, #0x41000000 - bne 2f + bne 3f and r5, r0, #0x00f00000 @ variant and r6, r0, #0x0000000f @ revision orr r6, r6, r5, lsr #20-4 @ combine variant and revision @@ -231,8 +231,20 @@ __v7_setup: orreq r10, r10, #(1 << 22) @ set the Write Allocate disable bit mcreq p15, 1, r10, c9, c0, 2 @ write the L2 cache aux ctrl register #endif + b 3f + + /* Cortex-A9 Errata */ +2: ldr r10, =0x00000c09 @ Cortex-A9 primary part number + teq r0, r10 + bne 3f +#ifdef CONFIG_ARM_ERRATA_742230 + cmp r6, #0x22 @ only present up to r2p2 + mrcle p15, 0, r10, c15, c0, 1 @ read diagnostic register + orrle r10, r10, #1 << 4 @ set bit #4 + mcrle p15, 0, r10, c15, c0, 1 @ write diagnostic register +#endif -2: mov r10, #0 +3: mov r10, #0 #ifdef HARVARD_CACHE mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate #endif -- cgit v1.2.2 From a672e99b129e286df2e2697a1b603d82321117f3 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 14 Sep 2010 09:53:02 +0100 Subject: ARM: 6389/1: errata: incorrect hazard handling in the SCU may lead to data corruption On the r2p0, r2p1 and r2p2 versions of the Cortex-A9, data corruption can occur if a shared cache line is replaced on one CPU as another CPU is accessing it. This workaround sets two bits in the diagnostic register of the Cortex-A9, reducing the linefill issuing capabilities of the processor and avoiding the erroneous behaviour. Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/Kconfig | 14 ++++++++++++++ arch/arm/mm/proc-v7.S | 9 +++++++++ 2 files changed, 23 insertions(+) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ab14c0a5d21e..0f89335b84c2 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1063,6 +1063,20 @@ config ARM_ERRATA_742230 instruction to behave as a DSB, ensuring the correct behaviour of the two writes. +config ARM_ERRATA_742231 + bool "ARM errata: Incorrect hazard handling in the SCU may lead to data corruption" + depends on CPU_V7 && SMP + help + This option enables the workaround for the 742231 Cortex-A9 + (r2p0..r2p2) erratum. Under certain conditions, specific to the + Cortex-A9 MPCore micro-architecture, two CPUs working in SMP mode, + accessing some data located in the same cache line, may get corrupted + data due to bad handling of the address hazard when the line gets + replaced from one of the CPUs at the same time as another CPU is + accessing it. This workaround sets specific bits in the diagnostic + register of the Cortex-A9 which reduces the linefill issuing + capabilities of the processor. + config PL310_ERRATA_588369 bool "Clean & Invalidate maintenance operations do not invalidate clean lines" depends on CACHE_L2X0 && ARCH_OMAP4 diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 945f36341fa6..080129263eef 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -243,6 +243,15 @@ __v7_setup: orrle r10, r10, #1 << 4 @ set bit #4 mcrle p15, 0, r10, c15, c0, 1 @ write diagnostic register #endif +#ifdef CONFIG_ARM_ERRATA_742231 + teq r6, #0x20 @ present in r2p0 + teqne r6, #0x21 @ present in r2p1 + teqne r6, #0x22 @ present in r2p2 + mrceq p15, 0, r10, c15, c0, 1 @ read diagnostic register + orreq r10, r10, #1 << 12 @ set bit #12 + orreq r10, r10, #1 << 22 @ set bit #22 + mcreq p15, 0, r10, c15, c0, 1 @ write diagnostic register +#endif 3: mov r10, #0 #ifdef HARVARD_CACHE -- cgit v1.2.2 From 1a8e41cd672f894bbd74874eac601e6cedf838fb Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Thu, 16 Sep 2010 17:57:17 +0100 Subject: ARM: 6395/1: VExpress: Set bit 22 in the PL310 (cache controller) AuxCtlr register Clearing bit 22 in the PL310 Auxiliary Control register (shared attribute override enable) has the side effect of transforming Normal Shared Non-cacheable reads into Cacheable no-allocate reads. Coherent DMA buffers in Linux always have a Cacheable alias via the kernel linear mapping and the processor can speculatively load cache lines into the PL310 controller. With bit 22 cleared, Non-cacheable reads would unexpectedly hit such cache lines leading to buffer corruption. Cc: Nicolas Pitre Cc: Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mach-vexpress/ct-ca9x4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 577df6cccb08..1c9c13e9d074 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -227,7 +227,7 @@ static void ct_ca9x4_init(void) int i; #ifdef CONFIG_CACHE_L2X0 - l2x0_init(MMIO_P2V(CT_CA9X4_L2CC), 0x00000000, 0xfe0fffff); + l2x0_init(MMIO_P2V(CT_CA9X4_L2CC), 0x00400000, 0xfe0fffff); #endif clkdev_add_table(lookups, ARRAY_SIZE(lookups)); -- cgit v1.2.2 From b2b163bb82b12bae2504a5b31399c37d099ad3cc Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 17 Sep 2010 14:56:16 +0100 Subject: ARM: prevent multiple syscall restarts Al Viro reports that calling "sys_sigsuspend(-ERESTARTNOHAND, 0, 0)" with two signals coming and being handled in kernel space results in the syscall restart being done twice. Avoid this by clearing the 'why' flag when we call the signal handling code to prevent further syscall restarts after the first. Acked-by: Al Viro Signed-off-by: Russell King --- arch/arm/kernel/entry-common.S | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index f05a35a59694..4a560d30793d 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -48,6 +48,8 @@ work_pending: beq no_work_pending mov r0, sp @ 'regs' mov r2, why @ 'syscall' + tst r1, #_TIF_SIGPENDING @ delivering a signal? + movne why, #0 @ prevent further restarts bl do_notify_resume b ret_slow_syscall @ Check work again -- cgit v1.2.2 From 14eff1812679c76564b775aa95cdd378965f6cfb Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Fri, 17 Sep 2010 16:42:10 +0100 Subject: ARM: 6398/1: add proc info for ARM11MPCore/Cortex-A9 from ARM Setting of these bits can cause issues on other SMP SoC's not produced by ARM. Acked-by: Catalin Marinas Signed-off-by: Daniel Walker Signed-off-by: Russell King --- arch/arm/mm/proc-v7.S | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 080129263eef..7563ff0141bd 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -186,13 +186,14 @@ cpu_v7_name: * It is assumed that: * - cache type register is implemented */ -__v7_setup: +__v7_ca9mp_setup: #ifdef CONFIG_SMP mrc p15, 0, r0, c1, c0, 1 tst r0, #(1 << 6) @ SMP/nAMP mode enabled? orreq r0, r0, #(1 << 6) | (1 << 0) @ Enable SMP/nAMP mode and mcreq p15, 0, r0, c1, c0, 1 @ TLB ops broadcasting #endif +__v7_setup: adr r12, __v7_setup_stack @ the local stack stmia r12, {r0-r5, r7, r9, r11, lr} bl v7_flush_dcache_all @@ -349,6 +350,29 @@ cpu_elf_name: .section ".proc.info.init", #alloc, #execinstr + .type __v7_ca9mp_proc_info, #object +__v7_ca9mp_proc_info: + .long 0x410fc090 @ Required ID value + .long 0xff0ffff0 @ Mask for ID + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ | \ + PMD_FLAGS + .long PMD_TYPE_SECT | \ + PMD_SECT_XN | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ + b __v7_ca9mp_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP + .long cpu_v7_name + .long v7_processor_functions + .long v7wbi_tlb_fns + .long v6_user_fns + .long v7_cache_fns + .size __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info + /* * Match any ARMv7 processor core. */ -- cgit v1.2.2 From 653d48b22166db2d8b1515ebe6f9f0f7c95dfc86 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Sep 2010 14:34:39 +0100 Subject: arm: fix really nasty sigreturn bug If a signal hits us outside of a syscall and another gets delivered when we are in sigreturn (e.g. because it had been in sa_mask for the first one and got sent to us while we'd been in the first handler), we have a chance of returning from the second handler to location one insn prior to where we ought to return. If r0 happens to contain -513 (-ERESTARTNOINTR), sigreturn will get confused into doing restart syscall song and dance. Incredible joy to debug, since it manifests as random, infrequent and very hard to reproduce double execution of instructions in userland code... The fix is simple - mark it "don't bother with restarts" in wrapper, i.e. set r8 to 0 in sys_sigreturn and sys_rt_sigreturn wrappers, suppressing the syscall restart handling on return from these guys. They can't legitimately return a restart-worthy error anyway. Testcase: #include #include #include #include #include void f(int n) { __asm__ __volatile__( "ldr r0, [%0]\n" "b 1f\n" "b 2f\n" "1:b .\n" "2:\n" : : "r"(&n)); } void handler1(int sig) { } void handler2(int sig) { raise(1); } void handler3(int sig) { exit(0); } main() { struct sigaction s = {.sa_handler = handler2}; struct itimerval t1 = { .it_value = {1} }; struct itimerval t2 = { .it_value = {2} }; signal(1, handler1); sigemptyset(&s.sa_mask); sigaddset(&s.sa_mask, 1); sigaction(SIGALRM, &s, NULL); signal(SIGVTALRM, handler3); setitimer(ITIMER_REAL, &t1, NULL); setitimer(ITIMER_VIRTUAL, &t2, NULL); f(-513); /* -ERESTARTNOINTR */ write(1, "buggered\n", 9); return 1; } Signed-off-by: Al Viro Acked-by: Russell King Cc: stable@kernel.org Signed-off-by: Linus Torvalds --- arch/arm/kernel/entry-common.S | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index f05a35a59694..1b560825e1cf 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -418,11 +418,13 @@ ENDPROC(sys_clone_wrapper) sys_sigreturn_wrapper: add r0, sp, #S_OFF + mov why, #0 @ prevent syscall restart handling b sys_sigreturn ENDPROC(sys_sigreturn_wrapper) sys_rt_sigreturn_wrapper: add r0, sp, #S_OFF + mov why, #0 @ prevent syscall restart handling b sys_rt_sigreturn ENDPROC(sys_rt_sigreturn_wrapper) -- cgit v1.2.2 From 5343795fda222183c1f77d0f5870f2027713bb0d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 18 Sep 2010 09:54:38 +0900 Subject: ARM: S3C64XX: Prototype SPI devices Avoids build warnings due to the undeclared non-statics. Signed-off-by: Mark Brown Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/dev-spi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-s3c64xx/dev-spi.c b/arch/arm/mach-s3c64xx/dev-spi.c index bfa3ef770bd8..405e62128917 100644 --- a/arch/arm/mach-s3c64xx/dev-spi.c +++ b/arch/arm/mach-s3c64xx/dev-spi.c @@ -22,6 +22,7 @@ #include #include +#include static char *spi_src_clks[] = { [S3C64XX_SPI_SRCCLK_PCLK] = "pclk", -- cgit v1.2.2 From 591cd25ee35986184870c447ff5c12e78bc80699 Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Thu, 9 Sep 2010 21:40:22 +0900 Subject: ARM: S3C64XX: Fix coding style errors on mach-real6410 Fix errors reported by checkpatch.pl script Signed-off-by: Darius Augulis [kgene.kim@samsung.com: minor title fix] Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/mach-real6410.c | 104 +++++++++++++++++----------------- 1 file changed, 52 insertions(+), 52 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c index 5c07d013b23d..9f79e6bacb59 100644 --- a/arch/arm/mach-s3c64xx/mach-real6410.c +++ b/arch/arm/mach-s3c64xx/mach-real6410.c @@ -30,73 +30,73 @@ #include #include -#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK -#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB -#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE +#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK) +#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB) +#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE) static struct s3c2410_uartcfg real6410_uartcfgs[] __initdata = { [0] = { - .hwport = 0, - .flags = 0, - .ucon = UCON, - .ulcon = ULCON, - .ufcon = UFCON, + .hwport = 0, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, }, [1] = { - .hwport = 1, - .flags = 0, - .ucon = UCON, - .ulcon = ULCON, - .ufcon = UFCON, + .hwport = 1, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, }, [2] = { - .hwport = 2, - .flags = 0, - .ucon = UCON, - .ulcon = ULCON, - .ufcon = UFCON, + .hwport = 2, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, }, [3] = { - .hwport = 3, - .flags = 0, - .ucon = UCON, - .ulcon = ULCON, - .ufcon = UFCON, + .hwport = 3, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, }, }; /* DM9000AEP 10/100 ethernet controller */ static struct resource real6410_dm9k_resource[] = { - [0] = { - .start = S3C64XX_PA_XM0CSN1, - .end = S3C64XX_PA_XM0CSN1 + 1, - .flags = IORESOURCE_MEM - }, - [1] = { - .start = S3C64XX_PA_XM0CSN1 + 4, - .end = S3C64XX_PA_XM0CSN1 + 5, - .flags = IORESOURCE_MEM - }, - [2] = { - .start = S3C_EINT(7), - .end = S3C_EINT(7), - .flags = IORESOURCE_IRQ, - } + [0] = { + .start = S3C64XX_PA_XM0CSN1, + .end = S3C64XX_PA_XM0CSN1 + 1, + .flags = IORESOURCE_MEM + }, + [1] = { + .start = S3C64XX_PA_XM0CSN1 + 4, + .end = S3C64XX_PA_XM0CSN1 + 5, + .flags = IORESOURCE_MEM + }, + [2] = { + .start = S3C_EINT(7), + .end = S3C_EINT(7), + .flags = IORESOURCE_IRQ, + } }; static struct dm9000_plat_data real6410_dm9k_pdata = { - .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM), + .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM), }; static struct platform_device real6410_device_eth = { - .name = "dm9000", - .id = -1, - .num_resources = ARRAY_SIZE(real6410_dm9k_resource), - .resource = real6410_dm9k_resource, - .dev = { - .platform_data = &real6410_dm9k_pdata, - }, + .name = "dm9000", + .id = -1, + .num_resources = ARRAY_SIZE(real6410_dm9k_resource), + .resource = real6410_dm9k_resource, + .dev = { + .platform_data = &real6410_dm9k_pdata, + }, }; static struct platform_device *real6410_devices[] __initdata = { @@ -129,12 +129,12 @@ static void __init real6410_machine_init(void) /* set timing for nCS1 suitable for ethernet chip */ __raw_writel((0 << S3C64XX_SROM_BCX__PMC__SHIFT) | - (6 << S3C64XX_SROM_BCX__TACP__SHIFT) | - (4 << S3C64XX_SROM_BCX__TCAH__SHIFT) | - (1 << S3C64XX_SROM_BCX__TCOH__SHIFT) | - (13 << S3C64XX_SROM_BCX__TACC__SHIFT) | - (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) | - (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1); + (6 << S3C64XX_SROM_BCX__TACP__SHIFT) | + (4 << S3C64XX_SROM_BCX__TCAH__SHIFT) | + (1 << S3C64XX_SROM_BCX__TCOH__SHIFT) | + (13 << S3C64XX_SROM_BCX__TACC__SHIFT) | + (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) | + (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1); platform_add_devices(real6410_devices, ARRAY_SIZE(real6410_devices)); } -- cgit v1.2.2 From 4d89ecaae9c145e60b920acb1120f1de3d6eac6e Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Thu, 9 Sep 2010 21:41:31 +0900 Subject: ARM: S3C64XX: Add IORESOURCE_IRQ_HIGHLEVEL flag to dm9000 on mach-real6410 Add IORESOURCE_IRQ_HIGHLEVEL irq flag to dm9000 driver platform data in board mach-real6410. Signed-off-by: Darius Augulis [kgene.kim@samsung.com: minor title fix] Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/mach-real6410.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c index 9f79e6bacb59..e130379ba0e8 100644 --- a/arch/arm/mach-s3c64xx/mach-real6410.c +++ b/arch/arm/mach-s3c64xx/mach-real6410.c @@ -81,7 +81,7 @@ static struct resource real6410_dm9k_resource[] = { [2] = { .start = S3C_EINT(7), .end = S3C_EINT(7), - .flags = IORESOURCE_IRQ, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL } }; -- cgit v1.2.2 From 31019075f41c785eff7f38c62e4c700af019fdb7 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 14 Sep 2010 04:23:47 -0400 Subject: alpha: Use static const char * const where possible Acked-by: Richard Henderson Signed-off-by: Joe Perches Signed-off-by: Matt Turner --- arch/alpha/kernel/err_ev6.c | 12 +++++++----- arch/alpha/kernel/err_marvel.c | 33 +++++++++++++++++---------------- arch/alpha/kernel/err_titan.c | 35 ++++++++++++++++++++--------------- arch/alpha/kernel/osf_sys.c | 4 ++-- 4 files changed, 46 insertions(+), 38 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/err_ev6.c b/arch/alpha/kernel/err_ev6.c index 8ca6345bf131..253cf1a87481 100644 --- a/arch/alpha/kernel/err_ev6.c +++ b/arch/alpha/kernel/err_ev6.c @@ -90,11 +90,13 @@ static int ev6_parse_cbox(u64 c_addr, u64 c1_syn, u64 c2_syn, u64 c_stat, u64 c_sts, int print) { - char *sourcename[] = { "UNKNOWN", "UNKNOWN", "UNKNOWN", - "MEMORY", "BCACHE", "DCACHE", - "BCACHE PROBE", "BCACHE PROBE" }; - char *streamname[] = { "D", "I" }; - char *bitsname[] = { "SINGLE", "DOUBLE" }; + static const char * const sourcename[] = { + "UNKNOWN", "UNKNOWN", "UNKNOWN", + "MEMORY", "BCACHE", "DCACHE", + "BCACHE PROBE", "BCACHE PROBE" + }; + static const char * const streamname[] = { "D", "I" }; + static const char * const bitsname[] = { "SINGLE", "DOUBLE" }; int status = MCHK_DISPOSITION_REPORT; int source = -1, stream = -1, bits = -1; diff --git a/arch/alpha/kernel/err_marvel.c b/arch/alpha/kernel/err_marvel.c index 5c905aaaeccd..648ae88aeb8a 100644 --- a/arch/alpha/kernel/err_marvel.c +++ b/arch/alpha/kernel/err_marvel.c @@ -589,22 +589,23 @@ marvel_print_pox_spl_cmplt(u64 spl_cmplt) static void marvel_print_pox_trans_sum(u64 trans_sum) { - char *pcix_cmd[] = { "Interrupt Acknowledge", - "Special Cycle", - "I/O Read", - "I/O Write", - "Reserved", - "Reserved / Device ID Message", - "Memory Read", - "Memory Write", - "Reserved / Alias to Memory Read Block", - "Reserved / Alias to Memory Write Block", - "Configuration Read", - "Configuration Write", - "Memory Read Multiple / Split Completion", - "Dual Address Cycle", - "Memory Read Line / Memory Read Block", - "Memory Write and Invalidate / Memory Write Block" + static const char * const pcix_cmd[] = { + "Interrupt Acknowledge", + "Special Cycle", + "I/O Read", + "I/O Write", + "Reserved", + "Reserved / Device ID Message", + "Memory Read", + "Memory Write", + "Reserved / Alias to Memory Read Block", + "Reserved / Alias to Memory Write Block", + "Configuration Read", + "Configuration Write", + "Memory Read Multiple / Split Completion", + "Dual Address Cycle", + "Memory Read Line / Memory Read Block", + "Memory Write and Invalidate / Memory Write Block" }; #define IO7__POX_TRANSUM__PCI_ADDR__S (0) diff --git a/arch/alpha/kernel/err_titan.c b/arch/alpha/kernel/err_titan.c index f7ed97ce0dfd..c3b3781a03de 100644 --- a/arch/alpha/kernel/err_titan.c +++ b/arch/alpha/kernel/err_titan.c @@ -75,8 +75,12 @@ titan_parse_p_serror(int which, u64 serror, int print) int status = MCHK_DISPOSITION_REPORT; #ifdef CONFIG_VERBOSE_MCHECK - char *serror_src[] = {"GPCI", "APCI", "AGP HP", "AGP LP"}; - char *serror_cmd[] = {"DMA Read", "DMA RMW", "SGTE Read", "Reserved"}; + static const char * const serror_src[] = { + "GPCI", "APCI", "AGP HP", "AGP LP" + }; + static const char * const serror_cmd[] = { + "DMA Read", "DMA RMW", "SGTE Read", "Reserved" + }; #endif /* CONFIG_VERBOSE_MCHECK */ #define TITAN__PCHIP_SERROR__LOST_UECC (1UL << 0) @@ -140,14 +144,15 @@ titan_parse_p_perror(int which, int port, u64 perror, int print) int status = MCHK_DISPOSITION_REPORT; #ifdef CONFIG_VERBOSE_MCHECK - char *perror_cmd[] = { "Interrupt Acknowledge", "Special Cycle", - "I/O Read", "I/O Write", - "Reserved", "Reserved", - "Memory Read", "Memory Write", - "Reserved", "Reserved", - "Configuration Read", "Configuration Write", - "Memory Read Multiple", "Dual Address Cycle", - "Memory Read Line","Memory Write and Invalidate" + static const char * const perror_cmd[] = { + "Interrupt Acknowledge", "Special Cycle", + "I/O Read", "I/O Write", + "Reserved", "Reserved", + "Memory Read", "Memory Write", + "Reserved", "Reserved", + "Configuration Read", "Configuration Write", + "Memory Read Multiple", "Dual Address Cycle", + "Memory Read Line", "Memory Write and Invalidate" }; #endif /* CONFIG_VERBOSE_MCHECK */ @@ -273,11 +278,11 @@ titan_parse_p_agperror(int which, u64 agperror, int print) int cmd, len; unsigned long addr; - char *agperror_cmd[] = { "Read (low-priority)", "Read (high-priority)", - "Write (low-priority)", - "Write (high-priority)", - "Reserved", "Reserved", - "Flush", "Fence" + static const char * const agperror_cmd[] = { + "Read (low-priority)", "Read (high-priority)", + "Write (low-priority)", "Write (high-priority)", + "Reserved", "Reserved", + "Flush", "Fence" }; #endif /* CONFIG_VERBOSE_MCHECK */ diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 5d1e6d6ce684..16bc1f5df3e2 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -594,7 +594,7 @@ SYSCALL_DEFINE2(osf_sigstack, struct sigstack __user *, uss, SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count) { - char *sysinfo_table[] = { + const char *sysinfo_table[] = { utsname()->sysname, utsname()->nodename, utsname()->release, @@ -606,7 +606,7 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count) "dummy", /* secure RPC domain */ }; unsigned long offset; - char *res; + const char *res; long len, err = -EINVAL; offset = command-1; -- cgit v1.2.2 From af96f8a340525f24abecc25848a07fff7636a53e Mon Sep 17 00:00:00 2001 From: matt mooney Date: Tue, 14 Sep 2010 05:27:39 -0400 Subject: alpha: remove unnecessary cast from void* in assignment. Acked-by: Jan-Benedict Glaw Signed-off-by: matt mooney Signed-off-by: Matt Turner --- arch/alpha/kernel/pci-sysfs.c | 2 +- arch/alpha/kernel/srm_env.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/pci-sysfs.c b/arch/alpha/kernel/pci-sysfs.c index 738fc824e2ea..b899e95f79fd 100644 --- a/arch/alpha/kernel/pci-sysfs.c +++ b/arch/alpha/kernel/pci-sysfs.c @@ -66,7 +66,7 @@ static int pci_mmap_resource(struct kobject *kobj, { struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); - struct resource *res = (struct resource *)attr->private; + struct resource *res = attr->private; enum pci_mmap_state mmap_type; struct pci_bus_region bar; int i; diff --git a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c index 4afc1a1e2e5a..f0df3fbd8402 100644 --- a/arch/alpha/kernel/srm_env.c +++ b/arch/alpha/kernel/srm_env.c @@ -87,7 +87,7 @@ static int srm_env_proc_show(struct seq_file *m, void *v) srm_env_t *entry; char *page; - entry = (srm_env_t *)m->private; + entry = m->private; page = (char *)__get_free_page(GFP_USER); if (!page) return -ENOMEM; -- cgit v1.2.2 From b97f897d60c34adb9a5a37a14033e6a867e86f48 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 Sep 2010 09:00:22 -0400 Subject: alpha: fix build breakage in asm/cacheflush.h Alpha SMP flush_icache_user_range() is implemented as an inline function inside include/asm/cacheflush.h. It dereferences @current but doesn't include linux/sched.h and thus causes build failure if linux/sched.h wasn't included previously. Fix it by including the needed header file explicitly. Signed-off-by: Tejun Heo Reported-by: Stephen Rothwell Signed-off-by: Matt Turner --- arch/alpha/include/asm/cacheflush.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/alpha/include/asm/cacheflush.h b/arch/alpha/include/asm/cacheflush.h index 01d71e1c8a9e..012f1243b1c1 100644 --- a/arch/alpha/include/asm/cacheflush.h +++ b/arch/alpha/include/asm/cacheflush.h @@ -43,6 +43,8 @@ extern void smp_imb(void); /* ??? Ought to use this in arch/alpha/kernel/signal.c too. */ #ifndef CONFIG_SMP +#include + extern void __load_new_mm_context(struct mm_struct *); static inline void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, -- cgit v1.2.2 From 12e750d956eec8b1778679aff705f617095c46c8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 14 Sep 2010 19:34:56 -0400 Subject: alpha: kill big kernel lock All uses of the BKL on alpha are totally bogus, nothing is really protected by this. Remove the remaining users so we don't have to mark alpha as 'depends on BKL'. Signed-off-by: Arnd Bergmann Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: linux-alpha@vger.kernel.org Signed-off-by: Matt Turner --- arch/alpha/kernel/osf_sys.c | 5 ----- arch/alpha/kernel/traps.c | 3 --- 2 files changed, 8 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 16bc1f5df3e2..547e8b84b2f7 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -69,7 +68,6 @@ SYSCALL_DEFINE4(osf_set_program_attributes, unsigned long, text_start, { struct mm_struct *mm; - lock_kernel(); mm = current->mm; mm->end_code = bss_start + bss_len; mm->start_brk = bss_start + bss_len; @@ -78,7 +76,6 @@ SYSCALL_DEFINE4(osf_set_program_attributes, unsigned long, text_start, printk("set_program_attributes(%lx %lx %lx %lx)\n", text_start, text_len, bss_start, bss_len); #endif - unlock_kernel(); return 0; } @@ -517,7 +514,6 @@ SYSCALL_DEFINE2(osf_proplist_syscall, enum pl_code, code, long error; int __user *min_buf_size_ptr; - lock_kernel(); switch (code) { case PL_SET: if (get_user(error, &args->set.nbytes)) @@ -547,7 +543,6 @@ SYSCALL_DEFINE2(osf_proplist_syscall, enum pl_code, code, error = -EOPNOTSUPP; break; }; - unlock_kernel(); return error; } diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index b14f015008ad..0414e021a91c 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -623,7 +622,6 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg, return; } - lock_kernel(); printk("Bad unaligned kernel access at %016lx: %p %lx %lu\n", pc, va, opcode, reg); do_exit(SIGSEGV); @@ -646,7 +644,6 @@ got_exception: * Yikes! No one to forward the exception to. * Since the registers are in a weird format, dump them ourselves. */ - lock_kernel(); printk("%s(%d): unhandled unaligned exception\n", current->comm, task_pid_nr(current)); -- cgit v1.2.2 From 531f0474bf889d489b28ea4b15e87b7cbb77f580 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Thu, 16 Sep 2010 14:12:55 -0400 Subject: alpha: wire up fanotify and prlimit64 syscalls The 2.6.36-rc kernel added three new system calls: fanotify_init, fanotify_mark, and prlimit64. This patch wires them up on Alpha. Built and booted on an XP900. Untested beyond that. Signed-off-by: Mikael Pettersson Signed-off-by: Matt Turner --- arch/alpha/include/asm/unistd.h | 5 ++++- arch/alpha/kernel/systbls.S | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h index 804e5311c841..9a9672f0a346 100644 --- a/arch/alpha/include/asm/unistd.h +++ b/arch/alpha/include/asm/unistd.h @@ -449,10 +449,13 @@ #define __NR_pwritev 491 #define __NR_rt_tgsigqueueinfo 492 #define __NR_perf_event_open 493 +#define __NR_fanotify_init 494 +#define __NR_fanotify_mark 495 +#define __NR_prlimit64 496 #ifdef __KERNEL__ -#define NR_SYSCALLS 494 +#define NR_SYSCALLS 497 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S index 09acb786e72b..ce594ef533cc 100644 --- a/arch/alpha/kernel/systbls.S +++ b/arch/alpha/kernel/systbls.S @@ -512,6 +512,9 @@ sys_call_table: .quad sys_pwritev .quad sys_rt_tgsigqueueinfo .quad sys_perf_event_open + .quad sys_fanotify_init + .quad sys_fanotify_mark /* 495 */ + .quad sys_prlimit64 .size sys_call_table, . - sys_call_table .type sys_call_table, @object -- cgit v1.2.2 From bdc8b8914b17cf97b53e5f7af8168d68cfb089d6 Mon Sep 17 00:00:00 2001 From: Michael Cree Date: Sun, 19 Sep 2010 02:05:40 -0400 Subject: alpha: Shift perf event pending work earlier in timer interrupt Pending work from the performance event subsystem is executed in the timer interrupt. This patch shifts the call to perf_event_do_pending() before the call to update_process_times() as the latter may call back into the perf event subsystem and it is prudent to have the pending work executed first. Signed-off-by: Michael Cree Signed-off-by: Matt Turner --- arch/alpha/kernel/time.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index eacceb26d9c8..396af1799ea4 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c @@ -191,16 +191,16 @@ irqreturn_t timer_interrupt(int irq, void *dev) write_sequnlock(&xtime_lock); -#ifndef CONFIG_SMP - while (nticks--) - update_process_times(user_mode(get_irq_regs())); -#endif - if (test_perf_event_pending()) { clear_perf_event_pending(); perf_event_do_pending(); } +#ifndef CONFIG_SMP + while (nticks--) + update_process_times(user_mode(get_irq_regs())); +#endif + return IRQ_HANDLED; } -- cgit v1.2.2 From 2deba1bd7126aadb5750beb927c878a6490065e6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Sep 2010 08:38:47 -0400 Subject: alpha: belated ERESTART_RESTARTBLOCK race fix same thing as had been done on other targets back in 2003 - move setting ->restart_block.fn into {rt_,}sigreturn(). Tested-by: Michael Cree Signed-off-by: Al Viro Signed-off-by: Matt Turner --- arch/alpha/kernel/signal.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 0932dbb1ef8e..e5b1b3c79ff3 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -239,6 +239,8 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long usp; long i, err = __get_user(regs->pc, &sc->sc_pc); + current_thread_info()->restart_block.fn = do_no_restart_syscall; + sw->r26 = (unsigned long) ret_from_sys_call; err |= __get_user(regs->r0, sc->sc_regs+0); @@ -591,7 +593,6 @@ syscall_restart(unsigned long r0, unsigned long r19, regs->pc -= 4; break; case ERESTART_RESTARTBLOCK: - current_thread_info()->restart_block.fn = do_no_restart_syscall; regs->r0 = EINTR; break; } -- cgit v1.2.2 From 392fb6e35400edbee183baba24b34a0fa2053813 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Sep 2010 08:40:07 -0400 Subject: alpha: unb0rk sigsuspend() and rt_sigsuspend() Old code used to set regs->r0 and regs->r19 to force the right return value. Leaving that after switch to ERESTARTNOHAND was a Bad Idea(tm), since now that screws the restart - if we hit the case when get_signal_to_deliver() returns 0, we will step back to syscall insn, with v0 set to EINTR and a3 to 1. The latter won't matter, since EINTR is 4, aka __NR_write. Testcase: #include #define _GNU_SOURCE #include #include main() { sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGCONT); sigprocmask(SIG_SETMASK, &mask, NULL); kill(0, SIGCONT); syscall(__NR_sigsuspend, 1, "b0rken\n", 7); } results on alpha in immediate message to stdout... Fix is obvious; moreover, since we don't need regs anymore, we can switch to normal prototypes for these guys and lose the wrappers. Even better, rt_sigsuspend() is identical to generic version in kernel/signal.c now. Tested-by: Michael Cree Signed-off-by: Al Viro Signed-off-by: Matt Turner --- arch/alpha/include/asm/unistd.h | 1 + arch/alpha/kernel/entry.S | 32 -------------------------------- arch/alpha/kernel/signal.c | 38 +------------------------------------- 3 files changed, 2 insertions(+), 69 deletions(-) (limited to 'arch') diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h index 9a9672f0a346..058937bf5a77 100644 --- a/arch/alpha/include/asm/unistd.h +++ b/arch/alpha/include/asm/unistd.h @@ -466,6 +466,7 @@ #define __ARCH_WANT_SYS_OLD_GETRLIMIT #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_SIGPENDING +#define __ARCH_WANT_SYS_RT_SIGSUSPEND /* "Conditional" syscalls. What we want is diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index b45d913a51c3..bceb325fd4c5 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -778,38 +778,6 @@ sys_rt_sigreturn: br ret_from_sys_call .end sys_rt_sigreturn - .align 4 - .globl sys_sigsuspend - .ent sys_sigsuspend -sys_sigsuspend: - .prologue 0 - mov $sp, $17 - br $1, do_switch_stack - mov $sp, $18 - subq $sp, 16, $sp - stq $26, 0($sp) - jsr $26, do_sigsuspend - ldq $26, 0($sp) - lda $sp, SWITCH_STACK_SIZE+16($sp) - ret -.end sys_sigsuspend - - .align 4 - .globl sys_rt_sigsuspend - .ent sys_rt_sigsuspend -sys_rt_sigsuspend: - .prologue 0 - mov $sp, $18 - br $1, do_switch_stack - mov $sp, $19 - subq $sp, 16, $sp - stq $26, 0($sp) - jsr $26, do_rt_sigsuspend - ldq $26, 0($sp) - lda $sp, SWITCH_STACK_SIZE+16($sp) - ret -.end sys_rt_sigsuspend - .align 4 .globl sys_sethae .ent sys_sethae diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index e5b1b3c79ff3..0f6b51ae865a 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -144,8 +144,7 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act, /* * Atomically swap in the new signal mask, and wait for a signal. */ -asmlinkage int -do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw) +SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask) { mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); @@ -154,41 +153,6 @@ do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - /* Indicate EINTR on return from any possible signal handler, - which will not come back through here, but via sigreturn. */ - regs->r0 = EINTR; - regs->r19 = 1; - - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_thread_flag(TIF_RESTORE_SIGMASK); - return -ERESTARTNOHAND; -} - -asmlinkage int -do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, - struct pt_regs *regs, struct switch_stack *sw) -{ - sigset_t set; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - if (copy_from_user(&set, uset, sizeof(set))) - return -EFAULT; - - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - /* Indicate EINTR on return from any possible signal handler, - which will not come back through here, but via sigreturn. */ - regs->r0 = EINTR; - regs->r19 = 1; - current->state = TASK_INTERRUPTIBLE; schedule(); set_thread_flag(TIF_RESTORE_SIGMASK); -- cgit v1.2.2 From 53293638618f1a8b0b182dfedaab08b28930f992 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Sep 2010 08:41:16 -0400 Subject: alpha: fix a 14 years old bug in sigreturn tracing The way sigreturn() is implemented on alpha breaks PTRACE_SYSCALL, all way back to 1.3.95 when alpha has grown PTRACE_SYSCALL support. What happens is direct return to ret_from_syscall, in order to bypass mangling of a3 (error indicator) and prevent other mutilations of registers (e.g. by syscall restart). That's fine, but... the entire TIF_SYSCALL_TRACE codepath is kept separate on alpha and post-syscall stopping/notifying the tracer is after the syscall. And the normal path we are forcibly switching to doesn't have it. So we end up with *one* stop in traced sigreturn() vs. two in other syscalls. And yes, strace is visibly broken by that; try to strace the following #include #include void f(int sig) {} main() { signal(SIGHUP, f); raise(SIGHUP); write(1, "eeeek\n", 6); } and watch the show. The close(1) = 405 in the end of strace output is coming from return value of write() (6 == __NR_close on alpha) and syscall number of exit_group() (__NR_exit_group == 405 there). The fix is fairly simple - the only thing we end up missing is the call of syscall_trace() and we can tell whether we'd been called from the SYSCALL_TRACE path by checking ra value. Since we are setting the switch_stack up (that's what sys_sigreturn() does), we have the right environment for calling syscall_trace() - just before we call undo_switch_stack() and return. Since undo_switch_stack() will overwrite s0 anyway, we can use it to store the result of "has it been called from SYSCALL_TRACE path?" check. The same thing applies in rt_sigreturn(). Tested-by: Michael Cree Signed-off-by: Al Viro Signed-off-by: Matt Turner --- arch/alpha/kernel/entry.S | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index bceb325fd4c5..a3e9cd85cfee 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -430,6 +430,7 @@ strace: beq $1, 1f ldq $27, 0($2) 1: jsr $26, ($27), sys_gettimeofday +ret_from_straced: ldgp $gp, 0($26) /* check return.. */ @@ -757,11 +758,15 @@ sys_vfork: .ent sys_sigreturn sys_sigreturn: .prologue 0 + lda $9, ret_from_straced + cmpult $26, $9, $9 mov $sp, $17 lda $18, -SWITCH_STACK_SIZE($sp) lda $sp, -SWITCH_STACK_SIZE($sp) jsr $26, do_sigreturn - br $1, undo_switch_stack + bne $9, 1f + jsr $26, syscall_trace +1: br $1, undo_switch_stack br ret_from_sys_call .end sys_sigreturn @@ -770,11 +775,15 @@ sys_sigreturn: .ent sys_rt_sigreturn sys_rt_sigreturn: .prologue 0 + lda $9, ret_from_straced + cmpult $26, $9, $9 mov $sp, $17 lda $18, -SWITCH_STACK_SIZE($sp) lda $sp, -SWITCH_STACK_SIZE($sp) jsr $26, do_rt_sigreturn - br $1, undo_switch_stack + bne $9, 1f + jsr $26, syscall_trace +1: br $1, undo_switch_stack br ret_from_sys_call .end sys_rt_sigreturn -- cgit v1.2.2 From 494486a1d2697f2153199b6501ab5b4d6e15a2bb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Sep 2010 08:42:27 -0400 Subject: alpha: deal with multiple simultaneously pending signals Unlike the other targets, alpha sets _one_ sigframe and buggers off until the next syscall/interrupt, even if more signals are pending. It leads to quite a few unpleasant inconsistencies, starting with SIGSEGV potentially arriving not where it should and including e.g. mess with sigsuspend(); consider two pending signals blocked until sigsuspend() unblocks them. We pick the first one; then, if we are hit by interrupt while in the handler, we process the second one as well. If we are not, and if no syscalls had been made, we get out of the first handler and leave the second signal pending; normally sigreturn() would've picked it anyway, but here it starts with restoring the original mask and voila - the second signal is blocked again. On everything else we get both delivered consistently. It's actually easy to fix; the only thing to watch out for is prevention of double syscall restart. Fortunately, the idea I've nicked from arm fix by rmk works just fine... Testcase demonstrating the behaviour in question; on alpha we get one or both flags set (usually one), on everything else both are always set. #include #include int had1, had2; void f1(int sig) { had1 = 1; } void f2(int sig) { had2 = 1; } main() { sigset_t set1, set2; sigemptyset(&set1); sigemptyset(&set2); sigaddset(&set2, 1); sigaddset(&set2, 2); signal(1, f1); signal(2, f2); sigprocmask(SIG_SETMASK, &set2, NULL); raise(1); raise(2); sigsuspend(&set1); printf("had1:%d had2:%d\n", had1, had2); } Tested-by: Michael Cree Signed-off-by: Al Viro Signed-off-by: Matt Turner --- arch/alpha/kernel/entry.S | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index a3e9cd85cfee..ab1ee0ab082b 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -317,14 +317,14 @@ ret_from_sys_call: ldq $0, SP_OFF($sp) and $0, 8, $0 beq $0, restore_all -ret_from_reschedule: +ret_to_user: /* Make sure need_resched and sigpending don't change between sampling and the rti. */ lda $16, 7 call_pal PAL_swpipl ldl $5, TI_FLAGS($8) and $5, _TIF_WORK_MASK, $2 - bne $5, work_pending + bne $2, work_pending restore_all: RESTORE_ALL call_pal PAL_rti @@ -363,7 +363,7 @@ $ret_success: * $8: current. * $19: The old syscall number, or zero if this is not a return * from a syscall that errored and is possibly restartable. - * $20: Error indication. + * $20: The old a3 value */ .align 4 @@ -392,12 +392,18 @@ $work_resched: $work_notifysig: mov $sp, $16 - br $1, do_switch_stack + bsr $1, do_switch_stack mov $sp, $17 mov $5, $18 + mov $19, $9 /* save old syscall number */ + mov $20, $10 /* save old a3 */ + and $5, _TIF_SIGPENDING, $2 + cmovne $2, 0, $9 /* we don't want double syscall restarts */ jsr $26, do_notify_resume + mov $9, $19 + mov $10, $20 bsr $1, undo_switch_stack - br restore_all + br ret_to_user .end work_pending /* -- cgit v1.2.2 From 29aeb3cfeb88ecdb2febb5da247d0cf6a82f8831 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 6 Sep 2010 22:15:08 +0100 Subject: ARM: 6337/2: AB8500 I2C platform configuration and irq This patch adds the platform part of the AB8500 PRCMU I2C access driver. The old irq name AB4500 is changed to AB8500. Signed-off-by: Mattias Wallin Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-ux500/board-mop500.c | 31 +++++++++++++++++++++++++++---- arch/arm/mach-ux500/include/mach/irqs.h | 2 +- 2 files changed, 28 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index de310326df1c..642b8e60d119 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "pins-db8500.h" #include "board-mop500.h" @@ -76,9 +77,27 @@ static struct ab8500_platform_data ab8500_platdata = { .irq_base = MOP500_AB8500_IRQ_BASE, }; -static struct spi_board_info u8500_spi_devices[] = { +static struct resource ab8500_resources[] = { + [0] = { + .start = IRQ_AB8500, + .end = IRQ_AB8500, + .flags = IORESOURCE_IRQ + } +}; + +struct platform_device ab8500_device = { + .name = "ab8500-i2c", + .id = 0, + .dev = { + .platform_data = &ab8500_platdata, + }, + .num_resources = 1, + .resource = ab8500_resources, +}; + +static struct spi_board_info ab8500_spi_devices[] = { { - .modalias = "ab8500", + .modalias = "ab8500-spi", .controller_data = &ab4500_chip_info, .platform_data = &ab8500_platdata, .max_speed_hz = 12000000, @@ -166,8 +185,12 @@ static void __init u8500_init_machine(void) mop500_sdi_init(); - spi_register_board_info(u8500_spi_devices, - ARRAY_SIZE(u8500_spi_devices)); + /* If HW is early drop (ED) or V1.0 then use SPI to access AB8500 */ + if (cpu_is_u8500ed() || cpu_is_u8500v10()) + spi_register_board_info(ab8500_spi_devices, + ARRAY_SIZE(ab8500_spi_devices)); + else /* If HW is v.1.1 or later use I2C to access AB8500 */ + platform_device_register(&ab8500_device); } MACHINE_START(U8500, "ST-Ericsson MOP500 platform") diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h index 0e7a2cec1994..0d552d9c9c00 100644 --- a/arch/arm/mach-ux500/include/mach/irqs.h +++ b/arch/arm/mach-ux500/include/mach/irqs.h @@ -40,7 +40,7 @@ #define IRQ_HSIR_CH1_OVRRUN (IRQ_SHPI_START + 33) #define IRQ_HSIR_CH2_OVRRUN (IRQ_SHPI_START + 34) #define IRQ_HSIR_CH3_OVRRUN (IRQ_SHPI_START + 35) -#define IRQ_AB4500 (IRQ_SHPI_START + 40) +#define IRQ_AB8500 (IRQ_SHPI_START + 40) #define IRQ_PRCMU (IRQ_SHPI_START + 47) #define IRQ_DISP (IRQ_SHPI_START + 48) #define IRQ_SiPI3 (IRQ_SHPI_START + 49) -- cgit v1.2.2 From eaa7f2d50de08efcebb3909ad81fbd76220c9b95 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 13 Sep 2010 12:37:52 +0100 Subject: ARM: 6371/1: ux500: add DB5500 pins Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/mach-ux500/pins-db5500.h | 620 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 620 insertions(+) create mode 100644 arch/arm/mach-ux500/pins-db5500.h (limited to 'arch') diff --git a/arch/arm/mach-ux500/pins-db5500.h b/arch/arm/mach-ux500/pins-db5500.h new file mode 100644 index 000000000000..bf50c21fe69d --- /dev/null +++ b/arch/arm/mach-ux500/pins-db5500.h @@ -0,0 +1,620 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License, version 2 + * Author: Rabin Vincent + */ + +#ifndef __MACH_DB5500_PINS_H +#define __MACH_DB5500_PINS_H + +#define GPIO0_GPIO PIN_CFG(0, GPIO) +#define GPIO0_SM_CS3n PIN_CFG(0, ALT_A) + +#define GPIO1_GPIO PIN_CFG(1, GPIO) +#define GPIO1_SM_A3 PIN_CFG(1, ALT_A) + +#define GPIO2_GPIO PIN_CFG(2, GPIO) +#define GPIO2_SM_A4 PIN_CFG(2, ALT_A) +#define GPIO2_SM_AVD PIN_CFG(2, ALT_B) + +#define GPIO3_GPIO PIN_CFG(3, GPIO) +#define GPIO3_I2C1_SCL PIN_CFG(3, ALT_A) + +#define GPIO4_GPIO PIN_CFG(4, GPIO) +#define GPIO4_I2C1_SDA PIN_CFG(4, ALT_A) + +#define GPIO5_GPIO PIN_CFG(5, GPIO) +#define GPIO5_MC0_DAT0 PIN_CFG(5, ALT_A) +#define GPIO5_SM_ADQ8 PIN_CFG(5, ALT_B) + +#define GPIO6_GPIO PIN_CFG(6, GPIO) +#define GPIO6_MC0_DAT1 PIN_CFG(6, ALT_A) +#define GPIO6_SM_ADQ0 PIN_CFG(6, ALT_B) + +#define GPIO7_GPIO PIN_CFG(7, GPIO) +#define GPIO7_MC0_DAT2 PIN_CFG(7, ALT_A) +#define GPIO7_SM_ADQ9 PIN_CFG(7, ALT_B) + +#define GPIO8_GPIO PIN_CFG(8, GPIO) +#define GPIO8_MC0_DAT3 PIN_CFG(8, ALT_A) +#define GPIO8_SM_ADQ1 PIN_CFG(8, ALT_B) + +#define GPIO9_GPIO PIN_CFG(9, GPIO) +#define GPIO9_MC0_DAT4 PIN_CFG(9, ALT_A) +#define GPIO9_SM_ADQ10 PIN_CFG(9, ALT_B) + +#define GPIO10_GPIO PIN_CFG(10, GPIO) +#define GPIO10_MC0_DAT5 PIN_CFG(10, ALT_A) +#define GPIO10_SM_ADQ2 PIN_CFG(10, ALT_B) + +#define GPIO11_GPIO PIN_CFG(11, GPIO) +#define GPIO11_MC0_DAT6 PIN_CFG(11, ALT_A) +#define GPIO11_SM_ADQ11 PIN_CFG(11, ALT_B) + +#define GPIO12_GPIO PIN_CFG(12, GPIO) +#define GPIO12_MC0_DAT7 PIN_CFG(12, ALT_A) +#define GPIO12_SM_ADQ3 PIN_CFG(12, ALT_B) + +#define GPIO13_GPIO PIN_CFG(13, GPIO) +#define GPIO13_MC0_CMD PIN_CFG(13, ALT_A) +#define GPIO13_SM_BUSY0n PIN_CFG(13, ALT_B) +#define GPIO13_SM_WAIT0n PIN_CFG(13, ALT_C) + +#define GPIO14_GPIO PIN_CFG(14, GPIO) +#define GPIO14_MC0_CLK PIN_CFG(14, ALT_A) +#define GPIO14_SM_CS1n PIN_CFG(14, ALT_B) +#define GPIO14_SM_CKO PIN_CFG(14, ALT_C) + +#define GPIO15_GPIO PIN_CFG(15, GPIO) +#define GPIO15_SM_A5 PIN_CFG(15, ALT_A) +#define GPIO15_SM_CLE PIN_CFG(15, ALT_B) + +#define GPIO16_GPIO PIN_CFG(16, GPIO) +#define GPIO16_MC2_CMD PIN_CFG(16, ALT_A) +#define GPIO16_SM_OEn PIN_CFG(16, ALT_B) + +#define GPIO17_GPIO PIN_CFG(17, GPIO) +#define GPIO17_MC2_CLK PIN_CFG(17, ALT_A) +#define GPIO17_SM_WEn PIN_CFG(17, ALT_B) + +#define GPIO18_GPIO PIN_CFG(18, GPIO) +#define GPIO18_SM_A6 PIN_CFG(18, ALT_A) +#define GPIO18_SM_ALE PIN_CFG(18, ALT_B) +#define GPIO18_SM_AVDn PIN_CFG(18, ALT_C) + +#define GPIO19_GPIO PIN_CFG(19, GPIO) +#define GPIO19_MC2_DAT1 PIN_CFG(19, ALT_A) +#define GPIO19_SM_ADQ4 PIN_CFG(19, ALT_B) + +#define GPIO20_GPIO PIN_CFG(20, GPIO) +#define GPIO20_MC2_DAT3 PIN_CFG(20, ALT_A) +#define GPIO20_SM_ADQ5 PIN_CFG(20, ALT_B) + +#define GPIO21_GPIO PIN_CFG(21, GPIO) +#define GPIO21_MC2_DAT5 PIN_CFG(21, ALT_A) +#define GPIO21_SM_ADQ6 PIN_CFG(21, ALT_B) + +#define GPIO22_GPIO PIN_CFG(22, GPIO) +#define GPIO22_MC2_DAT7 PIN_CFG(22, ALT_A) +#define GPIO22_SM_ADQ7 PIN_CFG(22, ALT_B) + +#define GPIO23_GPIO PIN_CFG(23, GPIO) +#define GPIO23_MC2_DAT0 PIN_CFG(23, ALT_A) +#define GPIO23_SM_ADQ12 PIN_CFG(23, ALT_B) +#define GPIO23_MC0_DAT1 PIN_CFG(23, ALT_C) + +#define GPIO24_GPIO PIN_CFG(24, GPIO) +#define GPIO24_MC2_DAT2 PIN_CFG(24, ALT_A) +#define GPIO24_SM_ADQ13 PIN_CFG(24, ALT_B) +#define GPIO24_MC0_DAT3 PIN_CFG(24, ALT_C) + +#define GPIO25_GPIO PIN_CFG(25, GPIO) +#define GPIO25_MC2_DAT4 PIN_CFG(25, ALT_A) +#define GPIO25_SM_ADQ14 PIN_CFG(25, ALT_B) +#define GPIO25_MC0_CMD PIN_CFG(25, ALT_C) + +#define GPIO26_GPIO PIN_CFG(26, GPIO) +#define GPIO26_MC2_DAT6 PIN_CFG(26, ALT_A) +#define GPIO26_SM_ADQ15 PIN_CFG(26, ALT_B) + +#define GPIO27_GPIO PIN_CFG(27, GPIO) +#define GPIO27_SM_CS0n PIN_CFG(27, ALT_A) +#define GPIO27_SM_PS0n PIN_CFG(27, ALT_B) + +#define GPIO28_GPIO PIN_CFG(28, GPIO) +#define GPIO28_U0_TXD PIN_CFG(28, ALT_A) +#define GPIO28_SM_A0 PIN_CFG(28, ALT_B) + +#define GPIO29_GPIO PIN_CFG(29, GPIO) +#define GPIO29_U0_RXD PIN_CFG(29, ALT_A) +#define GPIO29_SM_A1 PIN_CFG(29, ALT_B) +#define GPIO29_PWM_0 PIN_CFG(29, ALT_C) + +#define GPIO30_GPIO PIN_CFG(30, GPIO) +#define GPIO30_MC0_DAT5 PIN_CFG(30, ALT_A) +#define GPIO30_SM_A2 PIN_CFG(30, ALT_B) +#define GPIO30_PWM_1 PIN_CFG(30, ALT_C) + +#define GPIO31_GPIO PIN_CFG(31, GPIO) +#define GPIO31_MC0_DAT7 PIN_CFG(31, ALT_A) +#define GPIO31_SM_CS2n PIN_CFG(31, ALT_B) +#define GPIO31_PWM_2 PIN_CFG(31, ALT_C) + +#define GPIO32_GPIO PIN_CFG(32, GPIO) +#define GPIO32_MSP0_TCK PIN_CFG(32, ALT_A) +#define GPIO32_ACCI2S0_SCK PIN_CFG(32, ALT_B) + +#define GPIO33_GPIO PIN_CFG(33, GPIO) +#define GPIO33_MSP0_TFS PIN_CFG(33, ALT_A) +#define GPIO33_ACCI2S0_WS PIN_CFG(33, ALT_B) + +#define GPIO34_GPIO PIN_CFG(34, GPIO) +#define GPIO34_MSP0_TXD PIN_CFG(34, ALT_A) +#define GPIO34_ACCI2S0_DLD PIN_CFG(34, ALT_B) + +#define GPIO35_GPIO PIN_CFG(35, GPIO) +#define GPIO35_MSP0_RXD PIN_CFG(35, ALT_A) +#define GPIO35_ACCI2S0_ULD PIN_CFG(35, ALT_B) + +#define GPIO64_GPIO PIN_CFG(64, GPIO) +#define GPIO64_USB_DAT0 PIN_CFG(64, ALT_A) +#define GPIO64_U0_TXD PIN_CFG(64, ALT_B) + +#define GPIO65_GPIO PIN_CFG(65, GPIO) +#define GPIO65_USB_DAT1 PIN_CFG(65, ALT_A) +#define GPIO65_U0_RXD PIN_CFG(65, ALT_B) + +#define GPIO66_GPIO PIN_CFG(66, GPIO) +#define GPIO66_USB_DAT2 PIN_CFG(66, ALT_A) + +#define GPIO67_GPIO PIN_CFG(67, GPIO) +#define GPIO67_USB_DAT3 PIN_CFG(67, ALT_A) + +#define GPIO68_GPIO PIN_CFG(68, GPIO) +#define GPIO68_USB_DAT4 PIN_CFG(68, ALT_A) + +#define GPIO69_GPIO PIN_CFG(69, GPIO) +#define GPIO69_USB_DAT5 PIN_CFG(69, ALT_A) + +#define GPIO70_GPIO PIN_CFG(70, GPIO) +#define GPIO70_USB_DAT6 PIN_CFG(70, ALT_A) + +#define GPIO71_GPIO PIN_CFG(71, GPIO) +#define GPIO71_USB_DAT7 PIN_CFG(71, ALT_A) + +#define GPIO72_GPIO PIN_CFG(72, GPIO) +#define GPIO72_USB_STP PIN_CFG(72, ALT_A) + +#define GPIO73_GPIO PIN_CFG(73, GPIO) +#define GPIO73_USB_DIR PIN_CFG(73, ALT_A) + +#define GPIO74_GPIO PIN_CFG(74, GPIO) +#define GPIO74_USB_NXT PIN_CFG(74, ALT_A) + +#define GPIO75_GPIO PIN_CFG(75, GPIO) +#define GPIO75_USB_XCLK PIN_CFG(75, ALT_A) + +#define GPIO76_GPIO PIN_CFG(76, GPIO) + +#define GPIO77_GPIO PIN_CFG(77, GPIO) +#define GPIO77_ACCTX_ON PIN_CFG(77, ALT_A) + +#define GPIO78_GPIO PIN_CFG(78, GPIO) +#define GPIO78_IRQn PIN_CFG(78, ALT_A) + +#define GPIO79_GPIO PIN_CFG(79, GPIO) +#define GPIO79_ACCSIM_Clk PIN_CFG(79, ALT_A) + +#define GPIO80_GPIO PIN_CFG(80, GPIO) +#define GPIO80_ACCSIM_Da PIN_CFG(80, ALT_A) + +#define GPIO81_GPIO PIN_CFG(81, GPIO) +#define GPIO81_ACCSIM_Reset PIN_CFG(81, ALT_A) + +#define GPIO82_GPIO PIN_CFG(82, GPIO) +#define GPIO82_ACCSIM_DDir PIN_CFG(82, ALT_A) + +#define GPIO96_GPIO PIN_CFG(96, GPIO) +#define GPIO96_MSP1_TCK PIN_CFG(96, ALT_A) +#define GPIO96_PRCMU_DEBUG3 PIN_CFG(96, ALT_B) +#define GPIO96_PRCMU_DEBUG7 PIN_CFG(96, ALT_C) + +#define GPIO97_GPIO PIN_CFG(97, GPIO) +#define GPIO97_MSP1_TFS PIN_CFG(97, ALT_A) +#define GPIO97_PRCMU_DEBUG2 PIN_CFG(97, ALT_B) +#define GPIO97_PRCMU_DEBUG6 PIN_CFG(97, ALT_C) + +#define GPIO98_GPIO PIN_CFG(98, GPIO) +#define GPIO98_MSP1_TXD PIN_CFG(98, ALT_A) +#define GPIO98_PRCMU_DEBUG1 PIN_CFG(98, ALT_B) +#define GPIO98_PRCMU_DEBUG5 PIN_CFG(98, ALT_C) + +#define GPIO99_GPIO PIN_CFG(99, GPIO) +#define GPIO99_MSP1_RXD PIN_CFG(99, ALT_A) +#define GPIO99_PRCMU_DEBUG0 PIN_CFG(99, ALT_B) +#define GPIO99_PRCMU_DEBUG4 PIN_CFG(99, ALT_C) + +#define GPIO100_GPIO PIN_CFG(100, GPIO) +#define GPIO100_I2C0_SCL PIN_CFG(100, ALT_A) + +#define GPIO101_GPIO PIN_CFG(101, GPIO) +#define GPIO101_I2C0_SDA PIN_CFG(101, ALT_A) + +#define GPIO128_GPIO PIN_CFG(128, GPIO) +#define GPIO128_KP_I0 PIN_CFG(128, ALT_A) +#define GPIO128_BUSMON_D0 PIN_CFG(128, ALT_B) + +#define GPIO129_GPIO PIN_CFG(129, GPIO) +#define GPIO129_KP_O0 PIN_CFG(129, ALT_A) +#define GPIO129_BUSMON_D1 PIN_CFG(129, ALT_B) + +#define GPIO130_GPIO PIN_CFG(130, GPIO) +#define GPIO130_KP_I1 PIN_CFG(130, ALT_A) +#define GPIO130_BUSMON_D2 PIN_CFG(130, ALT_B) + +#define GPIO131_GPIO PIN_CFG(131, GPIO) +#define GPIO131_KP_O1 PIN_CFG(131, ALT_A) +#define GPIO131_BUSMON_D3 PIN_CFG(131, ALT_B) + +#define GPIO132_GPIO PIN_CFG(132, GPIO) +#define GPIO132_KP_I2 PIN_CFG(132, ALT_A) +#define GPIO132_ETM_D15 PIN_CFG(132, ALT_B) +#define GPIO132_STMAPE_CLK PIN_CFG(132, ALT_C) + +#define GPIO133_GPIO PIN_CFG(133, GPIO) +#define GPIO133_KP_O2 PIN_CFG(133, ALT_A) +#define GPIO133_ETM_D14 PIN_CFG(133, ALT_B) +#define GPIO133_U0_RXD PIN_CFG(133, ALT_C) + +#define GPIO134_GPIO PIN_CFG(134, GPIO) +#define GPIO134_KP_I3 PIN_CFG(134, ALT_A) +#define GPIO134_ETM_D13 PIN_CFG(134, ALT_B) +#define GPIO134_STMAPE_DAT0 PIN_CFG(134, ALT_C) + +#define GPIO135_GPIO PIN_CFG(135, GPIO) +#define GPIO135_KP_O3 PIN_CFG(135, ALT_A) +#define GPIO135_ETM_D12 PIN_CFG(135, ALT_B) +#define GPIO135_STMAPE_DAT1 PIN_CFG(135, ALT_C) + +#define GPIO136_GPIO PIN_CFG(136, GPIO) +#define GPIO136_KP_I4 PIN_CFG(136, ALT_A) +#define GPIO136_ETM_D11 PIN_CFG(136, ALT_B) +#define GPIO136_STMAPE_DAT2 PIN_CFG(136, ALT_C) + +#define GPIO137_GPIO PIN_CFG(137, GPIO) +#define GPIO137_KP_O4 PIN_CFG(137, ALT_A) +#define GPIO137_ETM_D10 PIN_CFG(137, ALT_B) +#define GPIO137_STMAPE_DAT3 PIN_CFG(137, ALT_C) + +#define GPIO138_GPIO PIN_CFG(138, GPIO) +#define GPIO138_KP_I5 PIN_CFG(138, ALT_A) +#define GPIO138_ETM_D9 PIN_CFG(138, ALT_B) +#define GPIO138_U0_TXD PIN_CFG(138, ALT_C) + +#define GPIO139_GPIO PIN_CFG(139, GPIO) +#define GPIO139_KP_O5 PIN_CFG(139, ALT_A) +#define GPIO139_ETM_D8 PIN_CFG(139, ALT_B) +#define GPIO139_BUSMON_D11 PIN_CFG(139, ALT_C) + +#define GPIO140_GPIO PIN_CFG(140, GPIO) +#define GPIO140_KP_I6 PIN_CFG(140, ALT_A) +#define GPIO140_ETM_D7 PIN_CFG(140, ALT_B) +#define GPIO140_STMAPE_CLK PIN_CFG(140, ALT_C) + +#define GPIO141_GPIO PIN_CFG(141, GPIO) +#define GPIO141_KP_O6 PIN_CFG(141, ALT_A) +#define GPIO141_ETM_D6 PIN_CFG(141, ALT_B) +#define GPIO141_U0_RXD PIN_CFG(141, ALT_C) + +#define GPIO142_GPIO PIN_CFG(142, GPIO) +#define GPIO142_KP_I7 PIN_CFG(142, ALT_A) +#define GPIO142_ETM_D5 PIN_CFG(142, ALT_B) +#define GPIO142_STMAPE_DAT0 PIN_CFG(142, ALT_C) + +#define GPIO143_GPIO PIN_CFG(143, GPIO) +#define GPIO143_KP_O7 PIN_CFG(143, ALT_A) +#define GPIO143_ETM_D4 PIN_CFG(143, ALT_B) +#define GPIO143_STMAPE_DAT1 PIN_CFG(143, ALT_C) + +#define GPIO144_GPIO PIN_CFG(144, GPIO) +#define GPIO144_I2C3_SCL PIN_CFG(144, ALT_A) +#define GPIO144_ETM_D3 PIN_CFG(144, ALT_B) +#define GPIO144_STMAPE_DAT2 PIN_CFG(144, ALT_C) + +#define GPIO145_GPIO PIN_CFG(145, GPIO) +#define GPIO145_I2C3_SDA PIN_CFG(145, ALT_A) +#define GPIO145_ETM_D2 PIN_CFG(145, ALT_B) +#define GPIO145_STMAPE_DAT3 PIN_CFG(145, ALT_C) + +#define GPIO146_GPIO PIN_CFG(146, GPIO) +#define GPIO146_PWM_0 PIN_CFG(146, ALT_A) +#define GPIO146_ETM_D1 PIN_CFG(146, ALT_B) + +#define GPIO147_GPIO PIN_CFG(147, GPIO) +#define GPIO147_PWM_1 PIN_CFG(147, ALT_A) +#define GPIO147_ETM_D0 PIN_CFG(147, ALT_B) + +#define GPIO148_GPIO PIN_CFG(148, GPIO) +#define GPIO148_PWM_2 PIN_CFG(148, ALT_A) +#define GPIO148_ETM_CLK PIN_CFG(148, ALT_B) + +#define GPIO160_GPIO PIN_CFG(160, GPIO) +#define GPIO160_CLKOUT_REQn PIN_CFG(160, ALT_A) + +#define GPIO161_GPIO PIN_CFG(161, GPIO) +#define GPIO161_CLKOUT_0 PIN_CFG(161, ALT_A) + +#define GPIO162_GPIO PIN_CFG(162, GPIO) +#define GPIO162_CLKOUT_1 PIN_CFG(162, ALT_A) + +#define GPIO163_GPIO PIN_CFG(163, GPIO) + +#define GPIO164_GPIO PIN_CFG(164, GPIO) +#define GPIO164_GPS_START PIN_CFG(164, ALT_A) + +#define GPIO165_GPIO PIN_CFG(165, GPIO) +#define GPIO165_SPI1_CS2n PIN_CFG(165, ALT_A) +#define GPIO165_U3_RXD PIN_CFG(165, ALT_B) +#define GPIO165_BUSMON_D20 PIN_CFG(165, ALT_C) + +#define GPIO166_GPIO PIN_CFG(166, GPIO) +#define GPIO166_SPI1_CS1n PIN_CFG(166, ALT_A) +#define GPIO166_U3_TXD PIN_CFG(166, ALT_B) +#define GPIO166_BUSMON_D21 PIN_CFG(166, ALT_C) + +#define GPIO167_GPIO PIN_CFG(167, GPIO) +#define GPIO167_SPI1_CS0n PIN_CFG(167, ALT_A) +#define GPIO167_U3_RTSn PIN_CFG(167, ALT_B) +#define GPIO167_BUSMON_D22 PIN_CFG(167, ALT_C) + +#define GPIO168_GPIO PIN_CFG(168, GPIO) +#define GPIO168_SPI1_RXD PIN_CFG(168, ALT_A) +#define GPIO168_U3_CTSn PIN_CFG(168, ALT_B) +#define GPIO168_BUSMON_D23 PIN_CFG(168, ALT_C) + +#define GPIO169_GPIO PIN_CFG(169, GPIO) +#define GPIO169_SPI1_TXD PIN_CFG(169, ALT_A) +#define GPIO169_DDR_RC PIN_CFG(169, ALT_B) +#define GPIO169_BUSMON_D24 PIN_CFG(169, ALT_C) + +#define GPIO170_GPIO PIN_CFG(170, GPIO) +#define GPIO170_SPI1_CLK PIN_CFG(170, ALT_A) + +#define GPIO171_GPIO PIN_CFG(171, GPIO) +#define GPIO171_MC3_DAT0 PIN_CFG(171, ALT_A) +#define GPIO171_SPI3_RXD PIN_CFG(171, ALT_B) +#define GPIO171_BUSMON_D25 PIN_CFG(171, ALT_C) + +#define GPIO172_GPIO PIN_CFG(172, GPIO) +#define GPIO172_MC3_DAT1 PIN_CFG(172, ALT_A) +#define GPIO172_SPI3_CS1n PIN_CFG(172, ALT_B) +#define GPIO172_BUSMON_D26 PIN_CFG(172, ALT_C) + +#define GPIO173_GPIO PIN_CFG(173, GPIO) +#define GPIO173_MC3_DAT2 PIN_CFG(173, ALT_A) +#define GPIO173_SPI3_CS2n PIN_CFG(173, ALT_B) +#define GPIO173_BUSMON_D27 PIN_CFG(173, ALT_C) + +#define GPIO174_GPIO PIN_CFG(174, GPIO) +#define GPIO174_MC3_DAT3 PIN_CFG(174, ALT_A) +#define GPIO174_SPI3_CS0n PIN_CFG(174, ALT_B) +#define GPIO174_BUSMON_D28 PIN_CFG(174, ALT_C) + +#define GPIO175_GPIO PIN_CFG(175, GPIO) +#define GPIO175_MC3_CMD PIN_CFG(175, ALT_A) +#define GPIO175_SPI3_TXD PIN_CFG(175, ALT_B) +#define GPIO175_BUSMON_D29 PIN_CFG(175, ALT_C) + +#define GPIO176_GPIO PIN_CFG(176, GPIO) +#define GPIO176_MC3_CLK PIN_CFG(176, ALT_A) +#define GPIO176_SPI3_CLK PIN_CFG(176, ALT_B) + +#define GPIO177_GPIO PIN_CFG(177, GPIO) +#define GPIO177_U2_RXD PIN_CFG(177, ALT_A) +#define GPIO177_I2C3_SCL PIN_CFG(177, ALT_B) +#define GPIO177_BUSMON_D30 PIN_CFG(177, ALT_C) + +#define GPIO178_GPIO PIN_CFG(178, GPIO) +#define GPIO178_U2_TXD PIN_CFG(178, ALT_A) +#define GPIO178_I2C3_SDA PIN_CFG(178, ALT_B) +#define GPIO178_BUSMON_D31 PIN_CFG(178, ALT_C) + +#define GPIO179_GPIO PIN_CFG(179, GPIO) +#define GPIO179_U2_CTSn PIN_CFG(179, ALT_A) +#define GPIO179_U3_RXD PIN_CFG(179, ALT_B) +#define GPIO179_BUSMON_D32 PIN_CFG(179, ALT_C) + +#define GPIO180_GPIO PIN_CFG(180, GPIO) +#define GPIO180_U2_RTSn PIN_CFG(180, ALT_A) +#define GPIO180_U3_TXD PIN_CFG(180, ALT_B) +#define GPIO180_BUSMON_D33 PIN_CFG(180, ALT_C) + +#define GPIO185_GPIO PIN_CFG(185, GPIO) +#define GPIO185_SPI3_CS2n PIN_CFG(185, ALT_A) +#define GPIO185_MC4_DAT0 PIN_CFG(185, ALT_B) + +#define GPIO186_GPIO PIN_CFG(186, GPIO) +#define GPIO186_SPI3_CS1n PIN_CFG(186, ALT_A) +#define GPIO186_MC4_DAT1 PIN_CFG(186, ALT_B) + +#define GPIO187_GPIO PIN_CFG(187, GPIO) +#define GPIO187_SPI3_CS0n PIN_CFG(187, ALT_A) +#define GPIO187_MC4_DAT2 PIN_CFG(187, ALT_B) + +#define GPIO188_GPIO PIN_CFG(188, GPIO) +#define GPIO188_SPI3_RXD PIN_CFG(188, ALT_A) +#define GPIO188_MC4_DAT3 PIN_CFG(188, ALT_B) + +#define GPIO189_GPIO PIN_CFG(189, GPIO) +#define GPIO189_SPI3_TXD PIN_CFG(189, ALT_A) +#define GPIO189_MC4_CMD PIN_CFG(189, ALT_B) + +#define GPIO190_GPIO PIN_CFG(190, GPIO) +#define GPIO190_SPI3_CLK PIN_CFG(190, ALT_A) +#define GPIO190_MC4_CLK PIN_CFG(190, ALT_B) + +#define GPIO191_GPIO PIN_CFG(191, GPIO) +#define GPIO191_MC1_DAT0 PIN_CFG(191, ALT_A) +#define GPIO191_MC4_DAT4 PIN_CFG(191, ALT_B) +#define GPIO191_STMAPE_DAT0 PIN_CFG(191, ALT_C) + +#define GPIO192_GPIO PIN_CFG(192, GPIO) +#define GPIO192_MC1_DAT1 PIN_CFG(192, ALT_A) +#define GPIO192_MC4_DAT5 PIN_CFG(192, ALT_B) +#define GPIO192_STMAPE_DAT1 PIN_CFG(192, ALT_C) + +#define GPIO193_GPIO PIN_CFG(193, GPIO) +#define GPIO193_MC1_DAT2 PIN_CFG(193, ALT_A) +#define GPIO193_MC4_DAT6 PIN_CFG(193, ALT_B) +#define GPIO193_STMAPE_DAT2 PIN_CFG(193, ALT_C) + +#define GPIO194_GPIO PIN_CFG(194, GPIO) +#define GPIO194_MC1_DAT3 PIN_CFG(194, ALT_A) +#define GPIO194_MC4_DAT7 PIN_CFG(194, ALT_B) +#define GPIO194_STMAPE_DAT3 PIN_CFG(194, ALT_C) + +#define GPIO195_GPIO PIN_CFG(195, GPIO) +#define GPIO195_MC1_CLK PIN_CFG(195, ALT_A) +#define GPIO195_STMAPE_CLK PIN_CFG(195, ALT_B) +#define GPIO195_BUSMON_CLK PIN_CFG(195, ALT_C) + +#define GPIO196_GPIO PIN_CFG(196, GPIO) +#define GPIO196_MC1_CMD PIN_CFG(196, ALT_A) +#define GPIO196_U0_RXD PIN_CFG(196, ALT_B) +#define GPIO196_BUSMON_D38 PIN_CFG(196, ALT_C) + +#define GPIO197_GPIO PIN_CFG(197, GPIO) +#define GPIO197_MC1_CMDDIR PIN_CFG(197, ALT_A) +#define GPIO197_BUSMON_D39 PIN_CFG(197, ALT_B) + +#define GPIO198_GPIO PIN_CFG(198, GPIO) +#define GPIO198_MC1_FBCLK PIN_CFG(198, ALT_A) + +#define GPIO199_GPIO PIN_CFG(199, GPIO) +#define GPIO199_MC1_DAT0DIR PIN_CFG(199, ALT_A) +#define GPIO199_BUSMON_D40 PIN_CFG(199, ALT_B) + +#define GPIO200_GPIO PIN_CFG(200, GPIO) +#define GPIO200_U1_TXD PIN_CFG(200, ALT_A) +#define GPIO200_ACCU0_RTSn PIN_CFG(200, ALT_B) + +#define GPIO201_GPIO PIN_CFG(201, GPIO) +#define GPIO201_U1_RXD PIN_CFG(201, ALT_A) +#define GPIO201_ACCU0_CTSn PIN_CFG(201, ALT_B) + +#define GPIO202_GPIO PIN_CFG(202, GPIO) +#define GPIO202_U1_CTSn PIN_CFG(202, ALT_A) +#define GPIO202_ACCU0_RXD PIN_CFG(202, ALT_B) + +#define GPIO203_GPIO PIN_CFG(203, GPIO) +#define GPIO203_U1_RTSn PIN_CFG(203, ALT_A) +#define GPIO203_ACCU0_TXD PIN_CFG(203, ALT_B) + +#define GPIO204_GPIO PIN_CFG(204, GPIO) +#define GPIO204_SPI0_CS2n PIN_CFG(204, ALT_A) +#define GPIO204_ACCGPIO_000 PIN_CFG(204, ALT_B) +#define GPIO204_LCD_VSI1 PIN_CFG(204, ALT_C) + +#define GPIO205_GPIO PIN_CFG(205, GPIO) +#define GPIO205_SPI0_CS1n PIN_CFG(205, ALT_A) +#define GPIO205_ACCGPIO_001 PIN_CFG(205, ALT_B) +#define GPIO205_LCD_D3 PIN_CFG(205, ALT_C) + +#define GPIO206_GPIO PIN_CFG(206, GPIO) +#define GPIO206_SPI0_CS0n PIN_CFG(206, ALT_A) +#define GPIO206_ACCGPIO_002 PIN_CFG(206, ALT_B) +#define GPIO206_LCD_D2 PIN_CFG(206, ALT_C) + +#define GPIO207_GPIO PIN_CFG(207, GPIO) +#define GPIO207_SPI0_RXD PIN_CFG(207, ALT_A) +#define GPIO207_ACCGPIO_003 PIN_CFG(207, ALT_B) +#define GPIO207_LCD_D1 PIN_CFG(207, ALT_C) + +#define GPIO208_GPIO PIN_CFG(208, GPIO) +#define GPIO208_SPI0_TXD PIN_CFG(208, ALT_A) +#define GPIO208_ACCGPIO_004 PIN_CFG(208, ALT_B) +#define GPIO208_LCD_D0 PIN_CFG(208, ALT_C) + +#define GPIO209_GPIO PIN_CFG(209, GPIO) +#define GPIO209_SPI0_CLK PIN_CFG(209, ALT_A) +#define GPIO209_ACCGPIO_005 PIN_CFG(209, ALT_B) +#define GPIO209_LCD_CLK PIN_CFG(209, ALT_C) + +#define GPIO210_GPIO PIN_CFG(210, GPIO) +#define GPIO210_LCD_VSO PIN_CFG(210, ALT_A) +#define GPIO210_PRCMU_PWRCTRL1 PIN_CFG(210, ALT_B) + +#define GPIO211_GPIO PIN_CFG(211, GPIO) +#define GPIO211_LCD_VSI0 PIN_CFG(211, ALT_A) +#define GPIO211_PRCMU_PWRCTRL2 PIN_CFG(211, ALT_B) + +#define GPIO212_GPIO PIN_CFG(212, GPIO) +#define GPIO212_SPI2_CS2n PIN_CFG(212, ALT_A) +#define GPIO212_LCD_HSO PIN_CFG(212, ALT_B) + +#define GPIO213_GPIO PIN_CFG(213, GPIO) +#define GPIO213_SPI2_CS1n PIN_CFG(213, ALT_A) +#define GPIO213_LCD_DE PIN_CFG(213, ALT_B) +#define GPIO213_BUSMON_D16 PIN_CFG(213, ALT_C) + +#define GPIO214_GPIO PIN_CFG(214, GPIO) +#define GPIO214_SPI2_CS0n PIN_CFG(214, ALT_A) +#define GPIO214_LCD_D7 PIN_CFG(214, ALT_B) +#define GPIO214_BUSMON_D17 PIN_CFG(214, ALT_C) + +#define GPIO215_GPIO PIN_CFG(215, GPIO) +#define GPIO215_SPI2_RXD PIN_CFG(215, ALT_A) +#define GPIO215_LCD_D6 PIN_CFG(215, ALT_B) +#define GPIO215_BUSMON_D18 PIN_CFG(215, ALT_C) + +#define GPIO216_GPIO PIN_CFG(216, GPIO) +#define GPIO216_SPI2_CLK PIN_CFG(216, ALT_A) +#define GPIO216_LCD_D5 PIN_CFG(216, ALT_B) + +#define GPIO217_GPIO PIN_CFG(217, GPIO) +#define GPIO217_SPI2_TXD PIN_CFG(217, ALT_A) +#define GPIO217_LCD_D4 PIN_CFG(217, ALT_B) +#define GPIO217_BUSMON_D19 PIN_CFG(217, ALT_C) + +#define GPIO218_GPIO PIN_CFG(218, GPIO) +#define GPIO218_I2C2_SCL PIN_CFG(218, ALT_A) +#define GPIO218_LCD_VSO PIN_CFG(218, ALT_B) + +#define GPIO219_GPIO PIN_CFG(219, GPIO) +#define GPIO219_I2C2_SDA PIN_CFG(219, ALT_A) +#define GPIO219_LCD_D3 PIN_CFG(219, ALT_B) + +#define GPIO220_GPIO PIN_CFG(220, GPIO) +#define GPIO220_MSP2_TCK PIN_CFG(220, ALT_A) +#define GPIO220_LCD_D2 PIN_CFG(220, ALT_B) + +#define GPIO221_GPIO PIN_CFG(221, GPIO) +#define GPIO221_MSP2_TFS PIN_CFG(221, ALT_A) +#define GPIO221_LCD_D1 PIN_CFG(221, ALT_B) + +#define GPIO222_GPIO PIN_CFG(222, GPIO) +#define GPIO222_MSP2_TXD PIN_CFG(222, ALT_A) +#define GPIO222_LCD_D0 PIN_CFG(222, ALT_B) + +#define GPIO223_GPIO PIN_CFG(223, GPIO) +#define GPIO223_MSP2_RXD PIN_CFG(223, ALT_A) +#define GPIO223_LCD_CLK PIN_CFG(223, ALT_B) + +#define GPIO224_GPIO PIN_CFG(224, GPIO) +#define GPIO224_PRCMU_PWRCTRL0 PIN_CFG(224, ALT_A) +#define GPIO224_LCD_VSI1 PIN_CFG(224, ALT_B) + +#define GPIO225_GPIO PIN_CFG(225, GPIO) +#define GPIO225_PRCMU_PWRCTRL1 PIN_CFG(225, ALT_A) +#define GPIO225_IRDA_RXD PIN_CFG(225, ALT_B) + +#define GPIO226_GPIO PIN_CFG(226, GPIO) +#define GPIO226_PRCMU_PWRCTRL2 PIN_CFG(226, ALT_A) +#define GPIO226_IRRC_DAT PIN_CFG(226, ALT_B) + +#define GPIO227_GPIO PIN_CFG(227, GPIO) +#define GPIO227_IRRC_DAT PIN_CFG(227, ALT_A) +#define GPIO227_IRDA_TXD PIN_CFG(227, ALT_B) + +#endif -- cgit v1.2.2 From f066439cfc37d498a06de76fcab8c21d4094ca64 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 13 Sep 2010 12:39:38 +0100 Subject: ARM: 6372/1: ux500: add DB5500 DMA event lines Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/mach-ux500/ste-dma40-db5500.h | 135 +++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 arch/arm/mach-ux500/ste-dma40-db5500.h (limited to 'arch') diff --git a/arch/arm/mach-ux500/ste-dma40-db5500.h b/arch/arm/mach-ux500/ste-dma40-db5500.h new file mode 100644 index 000000000000..cb2110c32858 --- /dev/null +++ b/arch/arm/mach-ux500/ste-dma40-db5500.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + * + * DB5500-SoC-specific configuration for DMA40 + */ + +#ifndef STE_DMA40_DB5500_H +#define STE_DMA40_DB5500_H + +#define DB5500_DMA_NR_DEV 64 + +enum dma_src_dev_type { + DB5500_DMA_DEV0_SPI0_RX = 0, + DB5500_DMA_DEV1_SPI1_RX = 1, + DB5500_DMA_DEV2_SPI2_RX = 2, + DB5500_DMA_DEV3_SPI3_RX = 3, + DB5500_DMA_DEV4_USB_OTG_IEP_1_9 = 4, + DB5500_DMA_DEV5_USB_OTG_IEP_2_10 = 5, + DB5500_DMA_DEV6_USB_OTG_IEP_3_11 = 6, + DB5500_DMA_DEV7_IRDA_RFS = 7, + DB5500_DMA_DEV8_IRDA_FIFO_RX = 8, + DB5500_DMA_DEV9_MSP0_RX = 9, + DB5500_DMA_DEV10_MSP1_RX = 10, + DB5500_DMA_DEV11_MSP2_RX = 11, + DB5500_DMA_DEV12_UART0_RX = 12, + DB5500_DMA_DEV13_UART1_RX = 13, + DB5500_DMA_DEV14_UART2_RX = 14, + DB5500_DMA_DEV15_UART3_RX = 15, + DB5500_DMA_DEV16_USB_OTG_IEP_8 = 16, + DB5500_DMA_DEV17_USB_OTG_IEP_1_9 = 17, + DB5500_DMA_DEV18_USB_OTG_IEP_2_10 = 18, + DB5500_DMA_DEV19_USB_OTG_IEP_3_11 = 19, + DB5500_DMA_DEV20_USB_OTG_IEP_4_12 = 20, + DB5500_DMA_DEV21_USB_OTG_IEP_5_13 = 21, + DB5500_DMA_DEV22_USB_OTG_IEP_6_14 = 22, + DB5500_DMA_DEV23_USB_OTG_IEP_7_15 = 23, + DB5500_DMA_DEV24_SDMMC0_RX = 24, + DB5500_DMA_DEV25_SDMMC1_RX = 25, + DB5500_DMA_DEV26_SDMMC2_RX = 26, + DB5500_DMA_DEV27_SDMMC3_RX = 27, + DB5500_DMA_DEV28_SDMMC4_RX = 28, + /* 29 - 32 not used */ + DB5500_DMA_DEV33_SDMMC0_RX = 33, + DB5500_DMA_DEV34_SDMMC1_RX = 34, + DB5500_DMA_DEV35_SDMMC2_RX = 35, + DB5500_DMA_DEV36_SDMMC3_RX = 36, + DB5500_DMA_DEV37_SDMMC4_RX = 37, + DB5500_DMA_DEV38_USB_OTG_IEP_8 = 38, + DB5500_DMA_DEV39_USB_OTG_IEP_1_9 = 39, + DB5500_DMA_DEV40_USB_OTG_IEP_2_10 = 40, + DB5500_DMA_DEV41_USB_OTG_IEP_3_11 = 41, + DB5500_DMA_DEV42_USB_OTG_IEP_4_12 = 42, + DB5500_DMA_DEV43_USB_OTG_IEP_5_13 = 43, + DB5500_DMA_DEV44_USB_OTG_IEP_6_14 = 44, + DB5500_DMA_DEV45_USB_OTG_IEP_7_15 = 45, + /* 46 not used */ + DB5500_DMA_DEV47_MCDE_RX = 47, + DB5500_DMA_DEV48_CRYPTO1_RX = 48, + /* 49, 50 not used */ + DB5500_DMA_DEV49_I2C1_RX = 51, + DB5500_DMA_DEV50_I2C3_RX = 52, + DB5500_DMA_DEV51_I2C2_RX = 53, + /* 54 - 60 not used */ + DB5500_DMA_DEV61_CRYPTO0_RX = 61, + /* 62, 63 not used */ +}; + +enum dma_dest_dev_type { + DB5500_DMA_DEV0_SPI0_TX = 0, + DB5500_DMA_DEV1_SPI1_TX = 1, + DB5500_DMA_DEV2_SPI2_TX = 2, + DB5500_DMA_DEV3_SPI3_TX = 3, + DB5500_DMA_DEV4_USB_OTG_OEP_1_9 = 4, + DB5500_DMA_DEV5_USB_OTG_OEP_2_10 = 5, + DB5500_DMA_DEV6_USB_OTG_OEP_3_11 = 6, + DB5500_DMA_DEV7_IRRC_TX = 7, + DB5500_DMA_DEV8_IRDA_FIFO_TX = 8, + DB5500_DMA_DEV9_MSP0_TX = 9, + DB5500_DMA_DEV10_MSP1_TX = 10, + DB5500_DMA_DEV11_MSP2_TX = 11, + DB5500_DMA_DEV12_UART0_TX = 12, + DB5500_DMA_DEV13_UART1_TX = 13, + DB5500_DMA_DEV14_UART2_TX = 14, + DB5500_DMA_DEV15_UART3_TX = 15, + DB5500_DMA_DEV16_USB_OTG_OEP_8 = 16, + DB5500_DMA_DEV17_USB_OTG_OEP_1_9 = 17, + DB5500_DMA_DEV18_USB_OTG_OEP_2_10 = 18, + DB5500_DMA_DEV19_USB_OTG_OEP_3_11 = 19, + DB5500_DMA_DEV20_USB_OTG_OEP_4_12 = 20, + DB5500_DMA_DEV21_USB_OTG_OEP_5_13 = 21, + DB5500_DMA_DEV22_USB_OTG_OEP_6_14 = 22, + DB5500_DMA_DEV23_USB_OTG_OEP_7_15 = 23, + DB5500_DMA_DEV24_SDMMC0_TX = 24, + DB5500_DMA_DEV25_SDMMC1_TX = 25, + DB5500_DMA_DEV26_SDMMC2_TX = 26, + DB5500_DMA_DEV27_SDMMC3_TX = 27, + DB5500_DMA_DEV28_SDMMC4_TX = 28, + /* 29 - 31 not used */ + DB5500_DMA_DEV32_FSMC_TX = 32, + DB5500_DMA_DEV33_SDMMC0_TX = 33, + DB5500_DMA_DEV34_SDMMC1_TX = 34, + DB5500_DMA_DEV35_SDMMC2_TX = 35, + DB5500_DMA_DEV36_SDMMC3_TX = 36, + DB5500_DMA_DEV37_SDMMC4_TX = 37, + DB5500_DMA_DEV38_USB_OTG_OEP_8 = 38, + DB5500_DMA_DEV39_USB_OTG_OEP_1_9 = 39, + DB5500_DMA_DEV40_USB_OTG_OEP_2_10 = 40, + DB5500_DMA_DEV41_USB_OTG_OEP_3_11 = 41, + DB5500_DMA_DEV42_USB_OTG_OEP_4_12 = 42, + DB5500_DMA_DEV43_USB_OTG_OEP_5_13 = 43, + DB5500_DMA_DEV44_USB_OTG_OEP_6_14 = 44, + DB5500_DMA_DEV45_USB_OTG_OEP_7_15 = 45, + /* 46 not used */ + DB5500_DMA_DEV47_STM_TX = 47, + DB5500_DMA_DEV48_CRYPTO1_TX = 48, + DB5500_DMA_DEV49_CRYPTO1_TX_HASH1_TX = 49, + DB5500_DMA_DEV50_HASH1_TX = 50, + DB5500_DMA_DEV51_I2C1_TX = 51, + DB5500_DMA_DEV52_I2C3_TX = 52, + DB5500_DMA_DEV53_I2C2_TX = 53, + /* 54, 55 not used */ + DB5500_DMA_MEMCPY_TX_1 = 56, + DB5500_DMA_MEMCPY_TX_2 = 57, + DB5500_DMA_MEMCPY_TX_3 = 58, + DB5500_DMA_MEMCPY_TX_4 = 59, + DB5500_DMA_MEMCPY_TX_5 = 60, + DB5500_DMA_DEV61_CRYPTO0_TX = 61, + DB5500_DMA_DEV62_CRYPTO0_TX_HASH0_TX = 62, + DB5500_DMA_DEV63_HASH0_TX = 63, +}; + +#endif -- cgit v1.2.2 From 9d704c04ff8ae61b60935d67ce334b18fc70f1b2 Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Wed, 15 Sep 2010 10:45:51 +0100 Subject: ARM: 6391/1: ux500: add CPU hotplug support Acked-by: Linus Walleij Signed-off-by: Sundar Iyer Signed-off-by: Russell King --- arch/arm/mach-ux500/Makefile | 1 + arch/arm/mach-ux500/hotplug.c | 75 +++++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-ux500/platsmp.c | 2 ++ 3 files changed, 78 insertions(+) create mode 100644 arch/arm/mach-ux500/hotplug.c (limited to 'arch') diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 009731864399..bb3e74e6ab36 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -8,4 +8,5 @@ obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o obj-$(CONFIG_MACH_U5500) += board-u5500.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o +obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c new file mode 100644 index 000000000000..b782a03024be --- /dev/null +++ b/arch/arm/mach-ux500/hotplug.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) STMicroelectronics 2009 + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * Based on ARM realview platform + * + * Author: Sundar Iyer + * + */ +#include +#include +#include +#include + +#include + +extern volatile int pen_release; + +static DECLARE_COMPLETION(cpu_killed); + +static inline void platform_do_lowpower(unsigned int cpu) +{ + flush_cache_all(); + + /* we put the platform to just WFI */ + for (;;) { + __asm__ __volatile__("dsb\n\t" "wfi\n\t" + : : : "memory"); + if (pen_release == cpu) { + /* + * OK, proper wakeup, we're done + */ + break; + } + } +} + +int platform_cpu_kill(unsigned int cpu) +{ + return wait_for_completion_timeout(&cpu_killed, 5000); +} + +/* + * platform-specific code to shutdown a CPU + * + * Called with IRQs disabled + */ +void platform_cpu_die(unsigned int cpu) +{ +#ifdef DEBUG + unsigned int this_cpu = hard_smp_processor_id(); + + if (cpu != this_cpu) { + printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", + this_cpu, cpu); + BUG(); + } +#endif + + printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); + complete(&cpu_killed); + + /* directly enter low power state, skipping secure registers */ + platform_do_lowpower(cpu); +} + +int platform_cpu_disable(unsigned int cpu) +{ + /* + * we don't allow CPU 0 to be shutdown (it is still too special + * e.g. clock tick interrupts) + */ + return cpu == 0 ? -EPERM : 0; +} diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index 438ef16aec90..9e4c678de785 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -78,6 +78,8 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); outer_clean_range(__pa(&pen_release), __pa(&pen_release) + 1); + smp_cross_call(cpumask_of(cpu)); + timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { if (pen_release == -1) -- cgit v1.2.2 From 4f724beace1be4ba3dbd1a75cff3940354e3ff4f Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Wed, 15 Sep 2010 10:50:59 +0100 Subject: ARM: 6392/1: ux500: add ab8500-regulators machine specific data From: Sundar R Iyer Reviewed-by: Mark Brown Acked-by: Linus Walleij Acked-by: Bengt JONSSON Signed-off-by: Sundar R Iyer Signed-off-by: Russell King --- arch/arm/mach-ux500/Makefile | 1 + arch/arm/mach-ux500/board-mop500-regulators.c | 101 ++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 arch/arm/mach-ux500/board-mop500-regulators.c (limited to 'arch') diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index bb3e74e6ab36..46dbaf640422 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_MACH_U5500) += board-u5500.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o +obj-$(CONFIG_REGULATOR_AB8500) += board-mop500-regulators.o diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c new file mode 100644 index 000000000000..1187f1fc2e53 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-regulators.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * + * Author: Sundar Iyer + * + * MOP500 board specific initialization for regulators + */ +#include +#include + +/* supplies to the display/camera */ +static struct regulator_init_data ab8500_vaux1_regulator = { + .constraints = { + .name = "V-DISPLAY", + .min_uV = 2500000, + .max_uV = 2900000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE| + REGULATOR_CHANGE_STATUS, + }, +}; + +/* supplies to the on-board eMMC */ +static struct regulator_init_data ab8500_vaux2_regulator = { + .constraints = { + .name = "V-eMMC1", + .min_uV = 1100000, + .max_uV = 3300000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE| + REGULATOR_CHANGE_STATUS, + }, +}; + +/* supply for VAUX3, supplies to SDcard slots */ +static struct regulator_init_data ab8500_vaux3_regulator = { + .constraints = { + .name = "V-MMC-SD", + .min_uV = 1100000, + .max_uV = 3300000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE| + REGULATOR_CHANGE_STATUS, + }, +}; + +/* supply for tvout, gpadc, TVOUT LDO */ +static struct regulator_init_data ab8500_vtvout_init = { + .constraints = { + .name = "V-TVOUT", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, +}; + +/* supply for ab8500-vaudio, VAUDIO LDO */ +static struct regulator_init_data ab8500_vaudio_init = { + .constraints = { + .name = "V-AUD", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, +}; + +/* supply for v-anamic1 VAMic1-LDO */ +static struct regulator_init_data ab8500_vamic1_init = { + .constraints = { + .name = "V-AMIC1", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, +}; + +/* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */ +static struct regulator_init_data ab8500_vamic2_init = { + .constraints = { + .name = "V-AMIC2", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, +}; + +/* supply for v-dmic, VDMIC LDO */ +static struct regulator_init_data ab8500_vdmic_init = { + .constraints = { + .name = "V-DMIC", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, +}; + +/* supply for v-intcore12, VINTCORE12 LDO */ +static struct regulator_init_data ab8500_vintcore_init = { + .constraints = { + .name = "V-INTCORE", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, +}; + +/* supply for U8500 CSI/DSI, VANA LDO */ +static struct regulator_init_data ab8500_vana_init = { + .constraints = { + .name = "V-CSI/DSI", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, +}; + -- cgit v1.2.2 From 79e27dc0677b969e2d53b76fa0fa58467cce946a Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Sat, 18 Sep 2010 19:55:10 +0100 Subject: ARM: 6400/1: at91: fix arch_gettimeoffset fallout 5cfc8ee0bb51 (ARM: convert arm to arch_gettimeoffset()) marked all of at91 AND at91x40 as needing ARCH_USES_GETTIMEOFFSET, and hence no high res timer support / accurate clock_gettime() - But only at91x40 needs it. Cc: stable@kernel.org Signed-off-by: Peter Korsgaard Acked-by: John Stultz Acked-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Russell King --- arch/arm/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0f89335b84c2..88c97bc7a6f5 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -271,7 +271,6 @@ config ARCH_AT91 bool "Atmel AT91" select ARCH_REQUIRE_GPIOLIB select HAVE_CLK - select ARCH_USES_GETTIMEOFFSET help This enables support for systems based on the Atmel AT91RM9200, AT91SAM9 and AT91CAP9 processors. -- cgit v1.2.2 From 0fc73099dd25df2c5181b7bad57d1faa5cd12d3c Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 13 Sep 2010 15:57:05 +0100 Subject: ARM: 6378/1: Allow lazy cache flushing via PG_arch_1 for highmem pages Commit d73cd42 forced non-lazy cache flushing of highmem pages in flush_dcache_page(). This isn't needed since __flush_dcache_page() (called lazily from update_mmu_cache) can handle highmem pages (fixed by commit 7e5a69e). Signed-off-by: Catalin Marinas Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mm/flush.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index c6844cb9b508..87dd5ffdfa2d 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -247,7 +247,7 @@ void flush_dcache_page(struct page *page) mapping = page_mapping(page); #ifndef CONFIG_SMP - if (!PageHighMem(page) && mapping && !mapping_mapped(mapping)) + if (mapping && !mapping_mapped(mapping)) set_bit(PG_dcache_dirty, &page->flags); else #endif -- cgit v1.2.2 From c01778001a4f5ad9c62d882776235f3f31922fdd Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 13 Sep 2010 15:57:36 +0100 Subject: ARM: 6379/1: Assume new page cache pages have dirty D-cache There are places in Linux where writes to newly allocated page cache pages happen without a subsequent call to flush_dcache_page() (several PIO drivers including USB HCD). This patch changes the meaning of PG_arch_1 to be PG_dcache_clean and always flush the D-cache for a newly mapped page in update_mmu_cache(). The patch also sets the PG_arch_1 bit in the DMA cache maintenance function to avoid additional cache flushing in update_mmu_cache(). Tested-by: Rabin Vincent Cc: Nicolas Pitre Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/include/asm/cacheflush.h | 6 +++--- arch/arm/include/asm/tlbflush.h | 2 +- arch/arm/mm/copypage-v4mc.c | 2 +- arch/arm/mm/copypage-v6.c | 2 +- arch/arm/mm/copypage-xscale.c | 2 +- arch/arm/mm/dma-mapping.c | 6 ++++++ arch/arm/mm/fault-armv.c | 4 ++-- arch/arm/mm/flush.c | 3 ++- 8 files changed, 17 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 4656a24058d2..d3730f0f4b50 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -137,10 +137,10 @@ #endif /* - * This flag is used to indicate that the page pointed to by a pte - * is dirty and requires cleaning before returning it to the user. + * This flag is used to indicate that the page pointed to by a pte is clean + * and does not require cleaning before returning it to the user. */ -#define PG_dcache_dirty PG_arch_1 +#define PG_dcache_clean PG_arch_1 /* * MM Cache Management diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h index 33b546ae72d4..9ad329ad7458 100644 --- a/arch/arm/include/asm/tlbflush.h +++ b/arch/arm/include/asm/tlbflush.h @@ -560,7 +560,7 @@ extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); #endif /* - * if PG_dcache_dirty is set for the page, we need to ensure that any + * If PG_dcache_clean is not set for the page, we need to ensure that any * cache entries for the kernels virtual memory range are written * back to the page. */ diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c index 598c51ad5071..b8061519ce77 100644 --- a/arch/arm/mm/copypage-v4mc.c +++ b/arch/arm/mm/copypage-v4mc.c @@ -73,7 +73,7 @@ void v4_mc_copy_user_highpage(struct page *to, struct page *from, { void *kto = kmap_atomic(to, KM_USER1); - if (test_and_clear_bit(PG_dcache_dirty, &from->flags)) + if (!test_and_set_bit(PG_dcache_clean, &from->flags)) __flush_dcache_page(page_mapping(from), from); spin_lock(&minicache_lock); diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c index f55fa1044f72..bdba6c65c901 100644 --- a/arch/arm/mm/copypage-v6.c +++ b/arch/arm/mm/copypage-v6.c @@ -79,7 +79,7 @@ static void v6_copy_user_highpage_aliasing(struct page *to, unsigned int offset = CACHE_COLOUR(vaddr); unsigned long kfrom, kto; - if (test_and_clear_bit(PG_dcache_dirty, &from->flags)) + if (!test_and_set_bit(PG_dcache_clean, &from->flags)) __flush_dcache_page(page_mapping(from), from); /* FIXME: not highmem safe */ diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c index 9920c0ae2096..649bbcd325bf 100644 --- a/arch/arm/mm/copypage-xscale.c +++ b/arch/arm/mm/copypage-xscale.c @@ -95,7 +95,7 @@ void xscale_mc_copy_user_highpage(struct page *to, struct page *from, { void *kto = kmap_atomic(to, KM_USER1); - if (test_and_clear_bit(PG_dcache_dirty, &from->flags)) + if (!test_and_set_bit(PG_dcache_clean, &from->flags)) __flush_dcache_page(page_mapping(from), from); spin_lock(&minicache_lock); diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 4bc43e535d3b..e4dd0646e859 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -523,6 +523,12 @@ void ___dma_page_dev_to_cpu(struct page *page, unsigned long off, outer_inv_range(paddr, paddr + size); dma_cache_maint_page(page, off, size, dir, dmac_unmap_area); + + /* + * Mark the D-cache clean for this page to avoid extra flushing. + */ + if (dir != DMA_TO_DEVICE && off == 0 && size >= PAGE_SIZE) + set_bit(PG_dcache_clean, &page->flags); } EXPORT_SYMBOL(___dma_page_dev_to_cpu); diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 9b906dec1ca1..58846cbd0e0b 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -141,7 +141,7 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma, * a page table, or changing an existing PTE. Basically, there are two * things that we need to take care of: * - * 1. If PG_dcache_dirty is set for the page, we need to ensure + * 1. If PG_dcache_clean is not set for the page, we need to ensure * that any cache entries for the kernels virtual memory * range are written back to the page. * 2. If we have multiple shared mappings of the same space in @@ -169,7 +169,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, mapping = page_mapping(page); #ifndef CONFIG_SMP - if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) + if (!test_and_set_bit(PG_dcache_clean, &page->flags)) __flush_dcache_page(mapping, page); #endif if (mapping) { diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 87dd5ffdfa2d..b4efce9b7985 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -248,7 +248,7 @@ void flush_dcache_page(struct page *page) #ifndef CONFIG_SMP if (mapping && !mapping_mapped(mapping)) - set_bit(PG_dcache_dirty, &page->flags); + clear_bit(PG_dcache_clean, &page->flags); else #endif { @@ -257,6 +257,7 @@ void flush_dcache_page(struct page *page) __flush_dcache_aliases(mapping, page); else if (mapping) __flush_icache_all(); + set_bit(PG_dcache_clean, &page->flags); } } EXPORT_SYMBOL(flush_dcache_page); -- cgit v1.2.2 From 6012191aa9c6ffff3a23b81162298318b56d7cb3 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 13 Sep 2010 15:58:06 +0100 Subject: ARM: 6380/1: Introduce __sync_icache_dcache() for VIPT caches On SMP systems, there is a small chance of a PTE becoming visible to a different CPU before the current cache maintenance operations in update_mmu_cache(). To avoid this, cache maintenance must be handled in set_pte_at() (similar to IA-64 and PowerPC). This patch provides a unified VIPT cache handling mechanism and implements the __sync_icache_dcache() function for ARMv6 onwards architectures. It is called from set_pte_at() and replaces the update_mmu_cache(). The latter is still used on VIVT hardware where a vm_area_struct is required. Tested-by: Rabin Vincent Cc: Nicolas Pitre Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/include/asm/pgtable.h | 26 +++++++++++++++++++++++--- arch/arm/include/asm/tlbflush.h | 10 +++++++++- arch/arm/mm/fault-armv.c | 4 ++-- arch/arm/mm/flush.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index ab68cf1ef80f..42e694f1d58e 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -278,9 +278,24 @@ extern struct page *empty_zero_page; #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) -#define set_pte_at(mm,addr,ptep,pteval) do { \ - set_pte_ext(ptep, pteval, (addr) >= TASK_SIZE ? 0 : PTE_EXT_NG); \ - } while (0) +#if __LINUX_ARM_ARCH__ < 6 +static inline void __sync_icache_dcache(pte_t pteval) +{ +} +#else +extern void __sync_icache_dcache(pte_t pteval); +#endif + +static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pteval) +{ + if (addr >= TASK_SIZE) + set_pte_ext(ptep, pteval, 0); + else { + __sync_icache_dcache(pteval); + set_pte_ext(ptep, pteval, PTE_EXT_NG); + } +} /* * The following only work if pte_present() is true. @@ -290,8 +305,13 @@ extern struct page *empty_zero_page; #define pte_write(pte) (pte_val(pte) & L_PTE_WRITE) #define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) #define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) +#define pte_exec(pte) (pte_val(pte) & L_PTE_EXEC) #define pte_special(pte) (0) +#define pte_present_user(pte) \ + ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \ + (L_PTE_PRESENT | L_PTE_USER)) + #define PTE_BIT_FUNC(fn,op) \ static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h index 9ad329ad7458..989c9e57d92b 100644 --- a/arch/arm/include/asm/tlbflush.h +++ b/arch/arm/include/asm/tlbflush.h @@ -562,10 +562,18 @@ extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); /* * If PG_dcache_clean is not set for the page, we need to ensure that any * cache entries for the kernels virtual memory range are written - * back to the page. + * back to the page. On ARMv6 and later, the cache coherency is handled via + * the set_pte_at() function. */ +#if __LINUX_ARM_ARCH__ < 6 extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep); +#else +static inline void update_mmu_cache(struct vm_area_struct *vma, + unsigned long addr, pte_t *ptep) +{ +} +#endif #endif diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 58846cbd0e0b..8440d952ba6d 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -28,6 +28,7 @@ static unsigned long shared_pte_mask = L_PTE_MT_BUFFERABLE; +#if __LINUX_ARM_ARCH__ < 6 /* * We take the easy way out of this problem - we make the * PTE uncacheable. However, we leave the write buffer on. @@ -168,10 +169,8 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, return; mapping = page_mapping(page); -#ifndef CONFIG_SMP if (!test_and_set_bit(PG_dcache_clean, &page->flags)) __flush_dcache_page(mapping, page); -#endif if (mapping) { if (cache_is_vivt()) make_coherent(mapping, vma, addr, ptep, pfn); @@ -179,6 +178,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, __flush_icache_all(); } } +#endif /* __LINUX_ARM_ARCH__ < 6 */ /* * Check whether the write buffer has physical address aliasing diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index b4efce9b7985..dd5b0120b92e 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -215,6 +215,36 @@ static void __flush_dcache_aliases(struct address_space *mapping, struct page *p flush_dcache_mmap_unlock(mapping); } +#if __LINUX_ARM_ARCH__ >= 6 +void __sync_icache_dcache(pte_t pteval) +{ + unsigned long pfn; + struct page *page; + struct address_space *mapping; + + if (!pte_present_user(pteval)) + return; + if (cache_is_vipt_nonaliasing() && !pte_exec(pteval)) + /* only flush non-aliasing VIPT caches for exec mappings */ + return; + pfn = pte_pfn(pteval); + if (!pfn_valid(pfn)) + return; + + page = pfn_to_page(pfn); + if (cache_is_vipt_aliasing()) + mapping = page_mapping(page); + else + mapping = NULL; + + if (!test_and_set_bit(PG_dcache_clean, &page->flags)) + __flush_dcache_page(mapping, page); + /* pte_exec() already checked above for non-aliasing VIPT cache */ + if (cache_is_vipt_nonaliasing() || pte_exec(pteval)) + __flush_icache_all(); +} +#endif + /* * Ensure cache coherency between kernel mapping and userspace mapping * of this page. -- cgit v1.2.2 From 85848dd7ab75fce1134856228582a8df522c91d9 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 13 Sep 2010 15:58:37 +0100 Subject: ARM: 6381/1: Use lazy cache flushing on ARMv7 SMP systems ARMv7 processors like Cortex-A9 broadcast the cache maintenance operations in hardware. This patch allows the flush_dcache_page/update_mmu_cache pair to work in lazy flushing mode similar to the UP case. Note that cache flushing on SMP systems now takes place via the set_pte_at() call (__sync_icache_dcache) and there is no race with other CPUs executing code from the new PTE before the cache flushing took place. Tested-by: Rabin Vincent Cc: Nicolas Pitre Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/include/asm/smp_plat.h | 4 ++++ arch/arm/mm/flush.c | 13 ++++--------- 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h index e6215305544a..963a338d567b 100644 --- a/arch/arm/include/asm/smp_plat.h +++ b/arch/arm/include/asm/smp_plat.h @@ -13,9 +13,13 @@ static inline int tlb_ops_need_broadcast(void) return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2; } +#if !defined(CONFIG_SMP) || __LINUX_ARM_ARCH__ >= 7 +#define cache_ops_need_broadcast() 0 +#else static inline int cache_ops_need_broadcast(void) { return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1; } +#endif #endif diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index dd5b0120b92e..2332b774c6b9 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "mm.h" @@ -93,12 +94,10 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig #define flush_pfn_alias(pfn,vaddr) do { } while (0) #endif -#ifdef CONFIG_SMP static void flush_ptrace_access_other(void *args) { __flush_icache_all(); } -#endif static void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, @@ -122,11 +121,9 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, if (vma->vm_flags & VM_EXEC) { unsigned long addr = (unsigned long)kaddr; __cpuc_coherent_kern_range(addr, addr + len); -#ifdef CONFIG_SMP if (cache_ops_need_broadcast()) smp_call_function(flush_ptrace_access_other, NULL, 1); -#endif } } @@ -276,12 +273,10 @@ void flush_dcache_page(struct page *page) mapping = page_mapping(page); -#ifndef CONFIG_SMP - if (mapping && !mapping_mapped(mapping)) + if (!cache_ops_need_broadcast() && + mapping && !mapping_mapped(mapping)) clear_bit(PG_dcache_clean, &page->flags); - else -#endif - { + else { __flush_dcache_page(mapping, page); if (mapping && cache_is_vivt()) __flush_dcache_aliases(mapping, page); -- cgit v1.2.2 From f8b63c184ad13cc8adc3dadb557d4fbc29f76e4d Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 13 Sep 2010 15:59:07 +0100 Subject: ARM: 6382/1: Remove superfluous flush_kernel_dcache_page() Since page cache pages are now considered 'dirty' by default, the cache flushing is handled via __flush_dcache_page() when a page gets mapped to user space. Highmem pages on VIVT systems are flushed during kunmap() and flush_kernel_dcache_page() was already a no-op in this case. ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE is still defined since ARM needs specific implementations for flush_kernel_vmap_range() and invalidate_kernel_vmap_range(). Cc: Nicolas Pitre Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/include/asm/cacheflush.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index d3730f0f4b50..042e13994d38 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -405,9 +405,6 @@ static inline void flush_anon_page(struct vm_area_struct *vma, #define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE static inline void flush_kernel_dcache_page(struct page *page) { - /* highmem pages are always flushed upon kunmap already */ - if ((cache_is_vivt() || cache_is_vipt_aliasing()) && !PageHighMem(page)) - __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE); } #define flush_dcache_mmap_lock(mapping) \ -- cgit v1.2.2 From d907387c42e9e39261629890e45a08ef4c3ed3fe Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 13 Sep 2010 16:01:24 +0100 Subject: ARM: 6383/1: Implement phys_mem_access_prot() to avoid attributes aliasing ARMv7 onwards requires that there are no aliases to the same physical location using different memory types (i.e. Normal vs Strongly Ordered). Access to SO mappings when the unaligned accesses are handled in hardware is also Unpredictable (pgprot_noncached() mappings in user space). The /dev/mem driver requires uncached mappings with O_SYNC. The patch implements the phys_mem_access_prot() function which generates Strongly Ordered memory attributes if !pfn_valid() (independent of O_SYNC) and Normal Noncacheable (writecombine) if O_SYNC. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/include/asm/pgtable.h | 4 ++++ arch/arm/mm/mmu.c | 14 ++++++++++++++ 2 files changed, 18 insertions(+) (limited to 'arch') diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index ab68cf1ef80f..e90b167ea848 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -317,6 +317,10 @@ static inline pte_t pte_mkspecial(pte_t pte) { return pte; } #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE #define pgprot_dmacoherent(prot) \ __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_BUFFERABLE) +#define __HAVE_PHYS_MEM_ACCESS_PROT +struct file; +extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t vma_prot); #else #define pgprot_dmacoherent(prot) \ __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_UNCACHED) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 6e1c4f6a2b3f..a486bd0d97dc 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -498,6 +499,19 @@ static void __init build_mem_type_table(void) } } +#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE +pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t vma_prot) +{ + if (!pfn_valid(pfn)) + return pgprot_noncached(vma_prot); + else if (file->f_flags & O_SYNC) + return pgprot_writecombine(vma_prot); + return vma_prot; +} +EXPORT_SYMBOL(phys_mem_access_prot); +#endif + #define vectors_base() (vectors_high() ? 0xffff0000 : 0) static void __init *early_alloc(unsigned long sz) -- cgit v1.2.2 From d93c333dc867d04111c9dcebdbcaa9ae8b2d5c2d Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 19 Sep 2010 16:16:58 +0100 Subject: ARM: Fix build error when using KCONFIG_CONFIG Jonathan Cameron reports that when using the environment variable KCONFIG_CONFIG, he encounters this error: make[2]: *** No rule to make target `.config', needed by `arch/arm/boot/compressed/vmlinux.lds' Reported-by: Jonathan Cameron Signed-off-by: Russell King --- arch/arm/boot/compressed/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index b23f6bc46cfa..65a7c1c588a9 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -116,5 +116,5 @@ CFLAGS_font.o := -Dstatic= $(obj)/font.c: $(FONTC) $(call cmd,shipped) -$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config +$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile $(KCONFIG_CONFIG) @sed "$(SEDFLAGS)" < $< > $@ -- cgit v1.2.2 From e4ff1c39ee1122198e8355069da59297038e55bb Mon Sep 17 00:00:00 2001 From: Arnaud Patard Date: Sun, 22 Aug 2010 22:49:46 +0200 Subject: ARM: kirkwood: Unbreak PCIe I/O port The support for the 2 pcie port of the 6282 has broken i/o port by switching *_IO_PHYS_BASE and *_IO_BUS_BASE. In fact, the patches reintroduced the same bug solved by commit 35f029e2514be209eb0e88c7d927f3bcc42a5cc2. So, I'm adding back *_IO_BUS_BASE in resource declaration and fix definition of KIRKWOOD_PCIE1_IO_BUS_BASE. With this change, the xgi card on my t5325 is working again. Signed-off-by: Arnaud Patard Acked-by: Saeed Bishara Signed-off-by: Nicolas Pitre Cc: stable@kernel.org --- arch/arm/mach-kirkwood/include/mach/kirkwood.h | 2 +- arch/arm/mach-kirkwood/pcie.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h index 93fc2ec95e76..6e924b398919 100644 --- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h +++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h @@ -38,7 +38,7 @@ #define KIRKWOOD_PCIE1_IO_PHYS_BASE 0xf3000000 #define KIRKWOOD_PCIE1_IO_VIRT_BASE 0xfef00000 -#define KIRKWOOD_PCIE1_IO_BUS_BASE 0x00000000 +#define KIRKWOOD_PCIE1_IO_BUS_BASE 0x00100000 #define KIRKWOOD_PCIE1_IO_SIZE SZ_1M #define KIRKWOOD_PCIE_IO_PHYS_BASE 0xf2000000 diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c index 55e7f00836b7..513ad3102d7c 100644 --- a/arch/arm/mach-kirkwood/pcie.c +++ b/arch/arm/mach-kirkwood/pcie.c @@ -117,7 +117,7 @@ static void __init pcie0_ioresources_init(struct pcie_port *pp) * IORESOURCE_IO */ pp->res[0].name = "PCIe 0 I/O Space"; - pp->res[0].start = KIRKWOOD_PCIE_IO_PHYS_BASE; + pp->res[0].start = KIRKWOOD_PCIE_IO_BUS_BASE; pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE_IO_SIZE - 1; pp->res[0].flags = IORESOURCE_IO; @@ -139,7 +139,7 @@ static void __init pcie1_ioresources_init(struct pcie_port *pp) * IORESOURCE_IO */ pp->res[0].name = "PCIe 1 I/O Space"; - pp->res[0].start = KIRKWOOD_PCIE1_IO_PHYS_BASE; + pp->res[0].start = KIRKWOOD_PCIE1_IO_BUS_BASE; pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE1_IO_SIZE - 1; pp->res[0].flags = IORESOURCE_IO; -- cgit v1.2.2 From c4a90588fa07ea47df7a67fd6cb03d6bc0f99634 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 14 Sep 2010 16:14:15 +0800 Subject: ARM: dove: fix __io() definition to use bus based offset Signed-off-by: Eric Miao Acked-by: Saeed Bishara Signed-off-by: Nicolas Pitre --- arch/arm/mach-dove/include/mach/io.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-dove/include/mach/io.h b/arch/arm/mach-dove/include/mach/io.h index 3b3e4721ce2e..eb4936ff90ad 100644 --- a/arch/arm/mach-dove/include/mach/io.h +++ b/arch/arm/mach-dove/include/mach/io.h @@ -13,8 +13,8 @@ #define IO_SPACE_LIMIT 0xffffffff -#define __io(a) ((void __iomem *)(((a) - DOVE_PCIE0_IO_PHYS_BASE) +\ - DOVE_PCIE0_IO_VIRT_BASE)) -#define __mem_pci(a) (a) +#define __io(a) ((void __iomem *)(((a) - DOVE_PCIE0_IO_BUS_BASE) + \ + DOVE_PCIE0_IO_VIRT_BASE)) +#define __mem_pci(a) (a) #endif -- cgit v1.2.2 From 20cd514d0f3d288d968217028ca67b70e707d896 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Sep 2010 15:13:04 +0100 Subject: frv: restart_block.fn needs to be reset on sigreturn Reset restart_block.fn on executing a sigreturn such that any currently pending system call restarts will be forced to return -EINTR. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/frv/kernel/signal.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index 0974c0ecc594..7fc29615ef01 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c @@ -121,6 +121,9 @@ static int restore_sigcontext(struct sigcontext __user *sc, int *_gr8) struct user_context *user = current->thread.user; unsigned long tbr, psr; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + tbr = user->i.tbr; psr = user->i.psr; if (copy_from_user(user, &sc->sc_context, sizeof(sc->sc_context))) -- cgit v1.2.2 From 5f4ad04a1e805d14de080ff9d5384b4d20518a9a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Sep 2010 15:13:09 +0100 Subject: frv: fix address verification holes in setup_frame/setup_rt_frame a) sa_handler might be maliciously set to point to kernel memory; blindly dereferencing it in FDPIC case is a Bad Idea(tm). b) I'm not sure you need that set_fs(USER_DS) there at all, but if you do, you'd better do it *before* checking the frame you've decided to use with access_ok(), lest sigaltstack() becomes a convenient roothole. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/frv/kernel/signal.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index 7fc29615ef01..5fb2d0661c78 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c @@ -253,6 +253,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) struct sigframe __user *frame; int rsig; + set_fs(USER_DS); + frame = get_sigframe(ka, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) @@ -296,22 +298,23 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) (unsigned long) (frame->retcode + 2)); } - /* set up registers for signal handler */ - __frame->sp = (unsigned long) frame; - __frame->lr = (unsigned long) &frame->retcode; - __frame->gr8 = sig; - + /* Set up registers for the signal handler */ if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; - __get_user(__frame->pc, &funcptr->text); - __get_user(__frame->gr15, &funcptr->GOT); + struct fdpic_func_descriptor desc; + if (copy_from_user(&desc, funcptr, sizeof(desc))) + goto give_sigsegv; + __frame->pc = desc.text; + __frame->gr15 = desc.GOT; } else { __frame->pc = (unsigned long) ka->sa.sa_handler; __frame->gr15 = 0; } - set_fs(USER_DS); + __frame->sp = (unsigned long) frame; + __frame->lr = (unsigned long) &frame->retcode; + __frame->gr8 = sig; /* the tracer may want to single-step inside the handler */ if (test_thread_flag(TIF_SINGLESTEP)) @@ -341,6 +344,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, struct rt_sigframe __user *frame; int rsig; + set_fs(USER_DS); + frame = get_sigframe(ka, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) @@ -395,22 +400,23 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } /* Set up registers for signal handler */ - __frame->sp = (unsigned long) frame; - __frame->lr = (unsigned long) &frame->retcode; - __frame->gr8 = sig; - __frame->gr9 = (unsigned long) &frame->info; - if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; - __get_user(__frame->pc, &funcptr->text); - __get_user(__frame->gr15, &funcptr->GOT); + struct fdpic_func_descriptor desc; + if (copy_from_user(&desc, funcptr, sizeof(desc))) + goto give_sigsegv; + __frame->pc = desc.text; + __frame->gr15 = desc.GOT; } else { __frame->pc = (unsigned long) ka->sa.sa_handler; __frame->gr15 = 0; } - set_fs(USER_DS); + __frame->sp = (unsigned long) frame; + __frame->lr = (unsigned long) &frame->retcode; + __frame->gr8 = sig; + __frame->gr9 = (unsigned long) &frame->info; /* the tracer may want to single-step inside the handler */ if (test_thread_flag(TIF_SINGLESTEP)) -- cgit v1.2.2 From ad0acab4557a91a60251b3ffe3478fad572d6f61 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Sep 2010 15:13:14 +0100 Subject: frv: avoid infinite loop of SIGSEGV delivery Use force_sigsegv() rather than force_sig(SIGSEGV, ...) as the former resets the SEGV handler pointer which will kill the process, rather than leaving it open to an infinite loop if the SEGV handler itself caused a SEGV signal. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/frv/kernel/signal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index 5fb2d0661c78..48203c68e39f 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c @@ -329,7 +329,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) return 0; give_sigsegv: - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return -EFAULT; } /* end setup_frame() */ @@ -431,7 +431,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return 0; give_sigsegv: - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return -EFAULT; } /* end setup_rt_frame() */ -- cgit v1.2.2 From 44c7afffa429a7cdcd1755019ab76566ff41e66d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Sep 2010 15:13:19 +0100 Subject: frv: handling of restart into restart_syscall is fscked do_signal() should place the syscall number in gr7, not gr8 when handling ERESTART_WOULDBLOCK. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/frv/kernel/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index 48203c68e39f..bd13b57a5c9b 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c @@ -547,7 +547,7 @@ no_signal: break; case -ERESTART_RESTARTBLOCK: - __frame->gr8 = __NR_restart_syscall; + __frame->gr7 = __NR_restart_syscall; __frame->pc -= 4; break; } -- cgit v1.2.2 From ed1cde68365c1251b920900c51e73675ff38dc66 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Sep 2010 15:13:25 +0100 Subject: frv: double syscall restarts, syscall restart in sigreturn() We need to make sure that only the first do_signal() to be handled on the way out syscall will bother with syscall restarts; additionally, the check on the "signal has user handler" path had been wrong - compare with restart prevention in sigreturn()... Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/frv/kernel/signal.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index bd13b57a5c9b..bab01298b58e 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c @@ -446,7 +446,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info, int ret; /* Are we from a system call? */ - if (in_syscall(__frame)) { + if (__frame->syscallno != -1) { /* If so, check system call restarting.. */ switch (__frame->gr8) { case -ERESTART_RESTARTBLOCK: @@ -465,6 +465,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info, __frame->gr8 = __frame->orig_gr8; __frame->pc -= 4; } + __frame->syscallno = -1; } /* Set up the stack frame */ @@ -551,6 +552,7 @@ no_signal: __frame->pc -= 4; break; } + __frame->syscallno = -1; } /* if there's no signal to deliver, we just put the saved sigmask -- cgit v1.2.2 From 9b6efcd2e2275e13403700913b7a1da92cf11ad2 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 21 Sep 2010 10:54:01 -0600 Subject: lguest: update comments to reflect LHCALL_LOAD_GDT_ENTRY. We used to have a hypercall which reloaded the entire GDT, then we switched to one which loaded a single entry (to match the IDT code). Some comments were not updated, so fix them. Signed-off-by: Rusty Russell Reported by: Eviatar Khen --- arch/x86/lguest/boot.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 9257510b4836..9d5f55848455 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -324,9 +324,8 @@ static void lguest_load_gdt(const struct desc_ptr *desc) } /* - * For a single GDT entry which changes, we do the lazy thing: alter our GDT, - * then tell the Host to reload the entire thing. This operation is so rare - * that this naive implementation is reasonable. + * For a single GDT entry which changes, we simply change our copy and + * then tell the host about it. */ static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum, const void *desc, int type) @@ -338,9 +337,13 @@ static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum, } /* - * OK, I lied. There are three "thread local storage" GDT entries which change + * There are three "thread local storage" GDT entries which change * on every context switch (these three entries are how glibc implements - * __thread variables). So we have a hypercall specifically for this case. + * __thread variables). As an optimization, we have a hypercall + * specifically for this case. + * + * Wouldn't it be nicer to have a general LOAD_GDT_ENTRIES hypercall + * which took a range of entries? */ static void lguest_load_tls(struct thread_struct *t, unsigned int cpu) { -- cgit v1.2.2 From 05c5e7698bdc54b3079a3517d86077f49ebcc788 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 20 Sep 2010 23:24:52 -0700 Subject: sparc64: Fix race in signal instruction flushing. If another cpu does a very wide munmap() on the signal frame area, it can tear down the page table hierarchy from underneath us. Borrow an idea from the 64-bit fault path's get_user_insn(), and disable cross call interrupts during the page table traversal to lock them in place while we operate. Reported-by: Al Viro Signed-off-by: David S. Miller --- arch/sparc/kernel/signal32.c | 102 +++++++++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 42 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index ea22cd373c64..76b67c4c6aa4 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -453,6 +453,64 @@ static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) return err; } +/* The I-cache flush instruction only works in the primary ASI, which + * right now is the nucleus, aka. kernel space. + * + * Therefore we have to kick the instructions out using the kernel + * side linear mapping of the physical address backing the user + * instructions. + */ +static void flush_signal_insns(unsigned long address) +{ + unsigned long pstate, paddr; + pte_t *ptep, pte; + pgd_t *pgdp; + pud_t *pudp; + pmd_t *pmdp; + + /* Commit all stores of the instructions we are about to flush. */ + wmb(); + + /* Disable cross-call reception. In this way even a very wide + * munmap() on another cpu can't tear down the page table + * hierarchy from underneath us, since that can't complete + * until the IPI tlb flush returns. + */ + + __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); + __asm__ __volatile__("wrpr %0, %1, %%pstate" + : : "r" (pstate), "i" (PSTATE_IE)); + + pgdp = pgd_offset(current->mm, address); + if (pgd_none(*pgdp)) + goto out_irqs_on; + pudp = pud_offset(pgdp, address); + if (pud_none(*pudp)) + goto out_irqs_on; + pmdp = pmd_offset(pudp, address); + if (pmd_none(*pmdp)) + goto out_irqs_on; + + ptep = pte_offset_map(pmdp, address); + pte = *ptep; + if (!pte_present(pte)) + goto out_unmap; + + paddr = (unsigned long) page_address(pte_page(pte)); + + __asm__ __volatile__("flush %0 + %1" + : /* no outputs */ + : "r" (paddr), + "r" (address & (PAGE_SIZE - 1)) + : "memory"); + +out_unmap: + pte_unmap(ptep); +out_irqs_on: + __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); + +} + static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, int signo, sigset_t *oldset) { @@ -547,13 +605,7 @@ static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, if (ka->ka_restorer) { regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; } else { - /* Flush instruction space. */ unsigned long address = ((unsigned long)&(sf->insns[0])); - pgd_t *pgdp = pgd_offset(current->mm, address); - pud_t *pudp = pud_offset(pgdp, address); - pmd_t *pmdp = pmd_offset(pudp, address); - pte_t *ptep; - pte_t pte; regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); @@ -562,22 +614,7 @@ static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, if (err) goto sigsegv; - preempt_disable(); - ptep = pte_offset_map(pmdp, address); - pte = *ptep; - if (pte_present(pte)) { - unsigned long page = (unsigned long) - page_address(pte_page(pte)); - - wmb(); - __asm__ __volatile__("flush %0 + %1" - : /* no outputs */ - : "r" (page), - "r" (address & (PAGE_SIZE - 1)) - : "memory"); - } - pte_unmap(ptep); - preempt_enable(); + flush_signal_insns(address); } return; @@ -687,12 +724,7 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, if (ka->ka_restorer) regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; else { - /* Flush instruction space. */ unsigned long address = ((unsigned long)&(sf->insns[0])); - pgd_t *pgdp = pgd_offset(current->mm, address); - pud_t *pudp = pud_offset(pgdp, address); - pmd_t *pmdp = pmd_offset(pudp, address); - pte_t *ptep; regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); @@ -704,21 +736,7 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, if (err) goto sigsegv; - preempt_disable(); - ptep = pte_offset_map(pmdp, address); - if (pte_present(*ptep)) { - unsigned long page = (unsigned long) - page_address(pte_page(*ptep)); - - wmb(); - __asm__ __volatile__("flush %0 + %1" - : /* no outputs */ - : "r" (page), - "r" (address & (PAGE_SIZE - 1)) - : "memory"); - } - pte_unmap(ptep); - preempt_enable(); + flush_signal_insns(address); } return; -- cgit v1.2.2 From 83d9f65bdae6f6b34d75282c6618d3f50846849a Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 29 Aug 2010 18:12:24 -0700 Subject: x86, setup: Fix earlyprintk=serial,ttyS0,115200 Torsten reported that there is garbage output, after commit 8fee13a48e4879fba57725f6d9513df4bfa8e9f3 (x86, setup: enable early console output from the decompressor) It turns out we missed the offset for that case. Reported-by: Torsten Kaiser Signed-off-by: Yinghai Lu LKML-Reference: <4C7B0578.8090807@kernel.org> Signed-off-by: H. Peter Anvin --- arch/x86/boot/early_serial_console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/boot/early_serial_console.c b/arch/x86/boot/early_serial_console.c index 030f4b93e255..407a8e26f0a7 100644 --- a/arch/x86/boot/early_serial_console.c +++ b/arch/x86/boot/early_serial_console.c @@ -58,7 +58,7 @@ static void parse_earlyprintk(void) if (arg[pos] == ',') pos++; - if (!strncmp(arg, "ttyS", 4)) { + if (!strncmp(arg + pos, "ttyS", 4)) { static const int bases[] = { 0x3f8, 0x2f8 }; int idx = 0; -- cgit v1.2.2 From 74b3c444a963ba55aef89b33a1bcaada9a4c206f Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 29 Aug 2010 18:13:10 -0700 Subject: x86, setup: Fix earlyprintk=serial,0x3f8,115200 earlyprintk can take and I/O port, so we need to handle this case in the setup code too, otherwise 0x3f8 will be treated as a baud rate. Signed-off-by: Yinghai Lu LKML-Reference: <4C7B05A6.4010801@kernel.org> Signed-off-by: H. Peter Anvin --- arch/x86/boot/early_serial_console.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/boot/early_serial_console.c b/arch/x86/boot/early_serial_console.c index 407a8e26f0a7..5df2869c874b 100644 --- a/arch/x86/boot/early_serial_console.c +++ b/arch/x86/boot/early_serial_console.c @@ -58,7 +58,19 @@ static void parse_earlyprintk(void) if (arg[pos] == ',') pos++; - if (!strncmp(arg + pos, "ttyS", 4)) { + /* + * make sure we have + * "serial,0x3f8,115200" + * "serial,ttyS0,115200" + * "ttyS0,115200" + */ + if (pos == 7 && !strncmp(arg + pos, "0x", 2)) { + port = simple_strtoull(arg + pos, &e, 16); + if (port == 0 || arg + pos == e) + port = DEFAULT_SERIAL_PORT; + else + pos = e - arg; + } else if (!strncmp(arg + pos, "ttyS", 4)) { static const int bases[] = { 0x3f8, 0x2f8 }; int idx = 0; -- cgit v1.2.2 From 392c21802ee3aa85cee0e703105f797a8a7b9416 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 21 Sep 2010 21:41:12 -0700 Subject: sparc: Don't mask signal when we can't setup signal frame. Don't invoke the signal handler tracehook in that situation either. Reported-by: Al Viro Signed-off-by: David S. Miller --- arch/sparc/kernel/signal32.c | 55 ++++++++++++++++++++++++++----------------- arch/sparc/kernel/signal_32.c | 53 +++++++++++++++++++++++++---------------- arch/sparc/kernel/signal_64.c | 43 ++++++++++++++++++++------------- 3 files changed, 93 insertions(+), 58 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index 76b67c4c6aa4..643a354795cc 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -511,8 +511,8 @@ out_irqs_on: } -static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset) +static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, + int signo, sigset_t *oldset) { struct signal_frame32 __user *sf; int sigframe_size; @@ -620,13 +620,16 @@ static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, sigill: do_exit(SIGILL); + return -EINVAL; + sigsegv: force_sigsegv(signo, current); + return -EFAULT; } -static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, - unsigned long signr, sigset_t *oldset, - siginfo_t *info) +static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, + unsigned long signr, sigset_t *oldset, + siginfo_t *info) { struct rt_signal_frame32 __user *sf; int sigframe_size; @@ -738,22 +741,30 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, flush_signal_insns(address); } - return; + return 0; sigill: do_exit(SIGILL); + return -EINVAL; + sigsegv: force_sigsegv(signr, current); + return -EFAULT; } -static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, - siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs) +static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka, + siginfo_t *info, + sigset_t *oldset, struct pt_regs *regs) { + int err; + if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame32(ka, regs, signr, oldset, info); + err = setup_rt_frame32(ka, regs, signr, oldset, info); else - setup_frame32(ka, regs, signr, oldset); + err = setup_frame32(ka, regs, signr, oldset); + + if (err) + return err; spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -761,6 +772,10 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, sigaddset(¤t->blocked,signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + + tracehook_signal_handler(signr, info, ka, regs, 0); + + return 0; } static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs, @@ -807,16 +822,14 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, if (signr > 0) { if (restart_syscall) syscall_restart32(orig_i0, regs, &ka.sa); - handle_signal32(signr, &ka, &info, oldset, regs); - - /* A signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TS_RESTORE_SIGMASK flag. - */ - current_thread_info()->status &= ~TS_RESTORE_SIGMASK; - - tracehook_signal_handler(signr, &info, &ka, regs, 0); + if (handle_signal32(signr, &ka, &info, oldset, regs) == 0) { + /* A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TS_RESTORE_SIGMASK flag. + */ + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + } return; } if (restart_syscall && diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 9882df92ba0a..99c85e99bbcf 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -315,8 +315,8 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) return err; } -static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset) +static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs, + int signo, sigset_t *oldset) { struct signal_frame __user *sf; int sigframe_size, err; @@ -384,16 +384,19 @@ static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs, /* Flush instruction space. */ flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); } - return; + return 0; sigill_and_return: do_exit(SIGILL); + return -EINVAL; + sigsegv: force_sigsegv(signo, current); + return -EFAULT; } -static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset, siginfo_t *info) +static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, + int signo, sigset_t *oldset, siginfo_t *info) { struct rt_signal_frame __user *sf; int sigframe_size; @@ -466,22 +469,30 @@ static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, /* Flush instruction space. */ flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); } - return; + return 0; sigill: do_exit(SIGILL); + return -EINVAL; + sigsegv: force_sigsegv(signo, current); + return -EFAULT; } -static inline void +static inline int handle_signal(unsigned long signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { + int err; + if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(ka, regs, signr, oldset, info); + err = setup_rt_frame(ka, regs, signr, oldset, info); else - setup_frame(ka, regs, signr, oldset); + err = setup_frame(ka, regs, signr, oldset); + + if (err) + return err; spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -489,6 +500,10 @@ handle_signal(unsigned long signr, struct k_sigaction *ka, sigaddset(¤t->blocked, signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + + tracehook_signal_handler(signr, info, ka, regs, 0); + + return 0; } static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, @@ -546,17 +561,15 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) if (signr > 0) { if (restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); - handle_signal(signr, &ka, &info, oldset, regs); - - /* a signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag. - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - - tracehook_signal_handler(signr, &info, &ka, regs, 0); + if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } return; } if (restart_syscall && diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 9fa48c30037e..3f19e673e2cd 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -409,7 +409,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs * return (void __user *) sp; } -static inline void +static inline int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, int signo, sigset_t *oldset, siginfo_t *info) { @@ -483,26 +483,37 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, } /* 4. return to kernel instructions */ regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; - return; + return 0; sigill: do_exit(SIGILL); + return -EINVAL; + sigsegv: force_sigsegv(signo, current); + return -EFAULT; } -static inline void handle_signal(unsigned long signr, struct k_sigaction *ka, - siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs) +static inline int handle_signal(unsigned long signr, struct k_sigaction *ka, + siginfo_t *info, + sigset_t *oldset, struct pt_regs *regs) { - setup_rt_frame(ka, regs, signr, oldset, - (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); + int err; + + err = setup_rt_frame(ka, regs, signr, oldset, + (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); + if (err) + return err; spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NOMASK)) sigaddset(¤t->blocked,signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + + tracehook_signal_handler(signr, info, ka, regs, 0); + + return 0; } static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, @@ -571,16 +582,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) if (signr > 0) { if (restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); - handle_signal(signr, &ka, &info, oldset, regs); - - /* A signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TS_RESTORE_SIGMASK flag. - */ - current_thread_info()->status &= ~TS_RESTORE_SIGMASK; - - tracehook_signal_handler(signr, &info, &ka, regs, 0); + if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { + /* A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TS_RESTORE_SIGMASK flag. + */ + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + } return; } if (restart_syscall && -- cgit v1.2.2 From c27852597829128a9c9d96d79ec454a83c6b0da5 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 21 Sep 2010 22:30:13 -0700 Subject: sparc: Prevent no-handler signal syscall restart recursion. Explicitly clear the "in-syscall" bit when we have no signal handler and back up the program counters to back up the system call. Reported-by: Al Viro Signed-off-by: David S. Miller --- arch/sparc/kernel/signal32.c | 4 +++- arch/sparc/kernel/signal_32.c | 2 ++ arch/sparc/kernel/signal_64.c | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index 643a354795cc..75fad425e249 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -616,7 +616,7 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, flush_signal_insns(address); } - return; + return 0; sigill: do_exit(SIGILL); @@ -840,12 +840,14 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, regs->u_regs[UREG_I0] = orig_i0; regs->tpc -= 4; regs->tnpc -= 4; + pt_regs_clear_syscall(regs); } if (restart_syscall && regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->tpc -= 4; regs->tnpc -= 4; + pt_regs_clear_syscall(regs); } /* If there's no signal to deliver, we just put the saved sigmask diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 99c85e99bbcf..5e5c5fd03783 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -580,12 +580,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) regs->u_regs[UREG_I0] = orig_i0; regs->pc -= 4; regs->npc -= 4; + pt_regs_clear_syscall(regs); } if (restart_syscall && regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->pc -= 4; regs->npc -= 4; + pt_regs_clear_syscall(regs); } /* if there's no signal to deliver, we just put the saved sigmask diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 3f19e673e2cd..006fe4515886 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -600,12 +600,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) regs->u_regs[UREG_I0] = orig_i0; regs->tpc -= 4; regs->tnpc -= 4; + pt_regs_clear_syscall(regs); } if (restart_syscall && regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->tpc -= 4; regs->tnpc -= 4; + pt_regs_clear_syscall(regs); } /* If there's no signal to deliver, we just put the saved sigmask -- cgit v1.2.2 From 9a81c16b527528ad307843be5571111aa8d35a80 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Sep 2010 21:48:57 +0100 Subject: powerpc: fix double syscall restarts Make sigreturn zero regs->trap, make do_signal() do the same on all paths. As it is, signal interrupting e.g. read() from fd 512 (== ERESTARTSYS) with another signal getting unblocked when the first handler finishes will lead to restart one insn earlier than it ought to. Same for multiple signals with in-kernel handlers interrupting that sucker at the same time. Same for multiple signals of any kind interrupting that sucker on 64bit... Signed-off-by: Al Viro Acked-by: Paul Mackerras Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/signal.c | 2 ++ arch/powerpc/kernel/signal_32.c | 3 +-- arch/powerpc/kernel/signal_64.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index 7109f5b1baa8..2300426e531a 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c @@ -138,6 +138,7 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs) ti->local_flags &= ~_TLF_RESTORE_SIGMASK; sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } + regs->trap = 0; return 0; /* no signals delivered */ } @@ -164,6 +165,7 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs) ret = handle_rt_signal64(signr, &ka, &info, oldset, regs); } + regs->trap = 0; if (ret) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 266610119f66..b96a3a010c26 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -511,6 +511,7 @@ static long restore_user_regs(struct pt_regs *regs, if (!sig) save_r2 = (unsigned int)regs->gpr[2]; err = restore_general_regs(regs, sr); + regs->trap = 0; err |= __get_user(msr, &sr->mc_gregs[PT_MSR]); if (!sig) regs->gpr[2] = (unsigned long) save_r2; @@ -884,7 +885,6 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, regs->nip = (unsigned long) ka->sa.sa_handler; /* enter the signal handler in big-endian mode */ regs->msr &= ~MSR_LE; - regs->trap = 0; return 1; badframe: @@ -1228,7 +1228,6 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, regs->nip = (unsigned long) ka->sa.sa_handler; /* enter the signal handler in big-endian mode */ regs->msr &= ~MSR_LE; - regs->trap = 0; return 1; diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 2fe6fc64b614..27c4a4584f80 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -178,7 +178,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, err |= __get_user(regs->xer, &sc->gp_regs[PT_XER]); err |= __get_user(regs->ccr, &sc->gp_regs[PT_CCR]); /* skip SOFTE */ - err |= __get_user(regs->trap, &sc->gp_regs[PT_TRAP]); + regs->trap = 0; err |= __get_user(regs->dar, &sc->gp_regs[PT_DAR]); err |= __get_user(regs->dsisr, &sc->gp_regs[PT_DSISR]); err |= __get_user(regs->result, &sc->gp_regs[PT_RESULT]); -- cgit v1.2.2 From 710224fa2750cf449c02dd115548acebfdd2c86a Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 22 Sep 2010 13:04:55 -0700 Subject: arm: fix "arm: fix pci_set_consistent_dma_mask for dmabounce devices" This fixes the regression caused by the commit 6fee48cd330c68 ("dma-mapping: arm: use generic pci_set_dma_mask and pci_set_consistent_dma_mask"). ARM needs to clip the dma coherent mask for dmabounce devices. This restores the old trick. Note that strictly speaking, the DMA API doesn't allow architectures to do such but I'm not sure it's worth adding the new API to set the dma mask that allows architectures to clip it. Reported-by: Krzysztof Halasa Signed-off-by: FUJITA Tomonori Acked-by: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/common/it8152.c | 8 ++++++++ arch/arm/mach-ixp4xx/common-pci.c | 8 ++++++++ arch/arm/mach-ixp4xx/include/mach/hardware.h | 2 ++ arch/arm/mach-pxa/include/mach/hardware.h | 2 +- arch/arm/mach-pxa/include/mach/io.h | 2 ++ 5 files changed, 21 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c index 7974baacafce..1bec96e85196 100644 --- a/arch/arm/common/it8152.c +++ b/arch/arm/common/it8152.c @@ -271,6 +271,14 @@ int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size) ((dma_addr + size - PHYS_OFFSET) >= SZ_64M); } +int dma_set_coherent_mask(struct device *dev, u64 mask) +{ + if (mask >= PHYS_OFFSET + SZ_64M - 1) + return 0; + + return -EIO; +} + int __init it8152_pci_setup(int nr, struct pci_sys_data *sys) { it8152_io.start = IT8152_IO_BASE + 0x12000; diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c index 61cd4d64b985..24498a932ba6 100644 --- a/arch/arm/mach-ixp4xx/common-pci.c +++ b/arch/arm/mach-ixp4xx/common-pci.c @@ -503,6 +503,14 @@ struct pci_bus * __devinit ixp4xx_scan_bus(int nr, struct pci_sys_data *sys) return pci_scan_bus(sys->busnr, &ixp4xx_ops, sys); } +int dma_set_coherent_mask(struct device *dev, u64 mask) +{ + if (mask >= SZ_64M - 1) + return 0; + + return -EIO; +} + EXPORT_SYMBOL(ixp4xx_pci_read); EXPORT_SYMBOL(ixp4xx_pci_write); diff --git a/arch/arm/mach-ixp4xx/include/mach/hardware.h b/arch/arm/mach-ixp4xx/include/mach/hardware.h index f91ca6d4fbe8..8138371c406e 100644 --- a/arch/arm/mach-ixp4xx/include/mach/hardware.h +++ b/arch/arm/mach-ixp4xx/include/mach/hardware.h @@ -26,6 +26,8 @@ #define PCIBIOS_MAX_MEM 0x4BFFFFFF #endif +#define ARCH_HAS_DMA_SET_COHERENT_MASK + #define pcibios_assign_all_busses() 1 /* Register locations and bits */ diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h index 7f64d24cd564..428cc7bda9a4 100644 --- a/arch/arm/mach-pxa/include/mach/hardware.h +++ b/arch/arm/mach-pxa/include/mach/hardware.h @@ -309,7 +309,7 @@ extern unsigned long get_clock_tick_rate(void); #define PCIBIOS_MIN_IO 0 #define PCIBIOS_MIN_MEM 0 #define pcibios_assign_all_busses() 1 +#define ARCH_HAS_DMA_SET_COHERENT_MASK #endif - #endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/mach-pxa/include/mach/io.h b/arch/arm/mach-pxa/include/mach/io.h index 262691fb97d8..fdca3be47d9b 100644 --- a/arch/arm/mach-pxa/include/mach/io.h +++ b/arch/arm/mach-pxa/include/mach/io.h @@ -6,6 +6,8 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H +#include + #define IO_SPACE_LIMIT 0xffffffff /* -- cgit v1.2.2 From cb1dcc0ff4b57873210100fc9d70defa81af43d4 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 22 Sep 2010 13:05:07 -0700 Subject: uml: fix compile warning This fixes: incompatible pointer type: => 89 arch/um/kernel/exec.c: warning: passing argument 2 of 'execve1' from incompatible pointer type: => 69, 85 arch/um/kernel/exec.c: warning: passing argument 3 of 'execve1' from incompatible pointer type: => 69, 85 which was introduced by d7627467b7a8d ("Make do_execve() take a const filename pointer") Signed-off-by: Richard Weinberger Cc: David Howells Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/exec.c | 6 +++--- arch/um/kernel/internal.h | 2 +- arch/um/kernel/syscall.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index cd145eda3579..49b5e1eb3262 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c @@ -62,7 +62,7 @@ static long execve1(const char *file, return error; } -long um_execve(const char *file, char __user *__user *argv, char __user *__user *env) +long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env) { long err; @@ -72,8 +72,8 @@ long um_execve(const char *file, char __user *__user *argv, char __user *__user return err; } -long sys_execve(const char __user *file, char __user *__user *argv, - char __user *__user *env) +long sys_execve(const char __user *file, const char __user *const __user *argv, + const char __user *const __user *env) { long error; char *filename; diff --git a/arch/um/kernel/internal.h b/arch/um/kernel/internal.h index 1303a105fe91..5bf97db24a04 100644 --- a/arch/um/kernel/internal.h +++ b/arch/um/kernel/internal.h @@ -1 +1 @@ -extern long um_execve(const char *file, char __user *__user *argv, char __user *__user *env); +extern long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env); diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index 5ddb246626db..f958cb876ee3 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -60,8 +60,8 @@ int kernel_execve(const char *filename, fs = get_fs(); set_fs(KERNEL_DS); - ret = um_execve(filename, (char __user *__user *)argv, - (char __user *__user *) envp); + ret = um_execve(filename, (const char __user *const __user *)argv, + (const char __user *const __user *) envp); set_fs(fs); return ret; -- cgit v1.2.2 From 9ecd4e1689208afe9b059a5ce1333acb2f42c4d2 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 22 Sep 2010 17:07:27 -0700 Subject: tracing/x86: Don't use mcount in pvclock.c When using a paravirt clock, pvclock.c can be used by sched_clock(), which in turn is used by the tracing mechanism for timestamps, which leads to infinite recursion. Disable mcount/tracing for pvclock.o. Cc: stable@kernel.org Signed-off-by: Jeremy Fitzhardinge LKML-Reference: <4C9A9A3F.4040201@goop.org> Signed-off-by: Steven Rostedt --- arch/x86/kernel/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 0925676266bd..882bbff9d50b 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -11,6 +11,7 @@ ifdef CONFIG_FUNCTION_TRACER CFLAGS_REMOVE_tsc.o = -pg CFLAGS_REMOVE_rtc.o = -pg CFLAGS_REMOVE_paravirt-spinlocks.o = -pg +CFLAGS_REMOVE_pvclock.o = -pg CFLAGS_REMOVE_ftrace.o = -pg CFLAGS_REMOVE_early_printk.o = -pg endif -- cgit v1.2.2 From 258af47479980d8238a04568b94a4e55aa1cb537 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 22 Sep 2010 22:22:25 -0400 Subject: tracing/x86: Don't use mcount in kvmclock.c The guest can use the paravirt clock in kvmclock.c which is used by sched_clock(), which in turn is used by the tracing mechanism for timestamps, which leads to infinite recursion. Disable mcount/tracing for kvmclock.o. Cc: stable@kernel.org Cc: Jeremy Fitzhardinge Cc: Avi Kivity Signed-off-by: Steven Rostedt --- arch/x86/kernel/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 882bbff9d50b..fedf32a8c3ec 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -12,6 +12,7 @@ CFLAGS_REMOVE_tsc.o = -pg CFLAGS_REMOVE_rtc.o = -pg CFLAGS_REMOVE_paravirt-spinlocks.o = -pg CFLAGS_REMOVE_pvclock.o = -pg +CFLAGS_REMOVE_kvmclock.o = -pg CFLAGS_REMOVE_ftrace.o = -pg CFLAGS_REMOVE_early_printk.o = -pg endif -- cgit v1.2.2 From 1d5b4c0fa9ff79a4f01e5efc1caefd16b190a3dc Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Wed, 22 Sep 2010 21:29:59 +0100 Subject: ARM: 6406/1: at91sam9g45: fix i2c bus speed Use a correct udelay value to get bus speed around 100KHz. The udelay value was most likely copied from the older devices, but the 9g45 is signicantly faster (400MHz, DDR, ..), so a udelay of 2 gives a bus speed of around 190KHz, which is too fast for some devices. A udelay value of 5 gives a bus speed of around 90KHz here. Signed-off-by: Peter Korsgaard Signed-off-by: Nicolas Ferre Signed-off-by: Russell King --- arch/arm/mach-at91/at91sam9g45_devices.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 5e71ccd5e7d3..1276babf84d5 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -426,7 +426,7 @@ static struct i2c_gpio_platform_data pdata_i2c0 = { .sda_is_open_drain = 1, .scl_pin = AT91_PIN_PA21, .scl_is_open_drain = 1, - .udelay = 2, /* ~100 kHz */ + .udelay = 5, /* ~100 kHz */ }; static struct platform_device at91sam9g45_twi0_device = { @@ -440,7 +440,7 @@ static struct i2c_gpio_platform_data pdata_i2c1 = { .sda_is_open_drain = 1, .scl_pin = AT91_PIN_PB11, .scl_is_open_drain = 1, - .udelay = 2, /* ~100 kHz */ + .udelay = 5, /* ~100 kHz */ }; static struct platform_device at91sam9g45_twi1_device = { -- cgit v1.2.2 From 2f27bf834e1d0a06e83d7458b535891c552271aa Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 20 Sep 2010 04:10:43 +0100 Subject: ARM: 6401/1: plug a race in the alignment trap handler When the policy for user space is to ignore misaligned accesses from user space, the processor then performs a documented rotation on the accessed data. This is the result of the access being trapped, and the kernel disabling the alignment trap before returning to user space again. In kernel space we always want misaligned accesses to be fixed up. This is enforced by always re-enabling the alignment trap on every entry into kernel space from user space. No such re-enabling is performed when an exception occurs while already in kernel space as the alignment trap is always supposed to be enabled in that case. There is however a small race window when a misaligned access in user space is trapped and the alignment trap disabled, but the CPU didn't return to user space just yet. Any exception would be entered from kernel space at that point and the kernel would then execute with the alignment trap disabled. Thanks to Maxime Bizon for providing a test module that made this issue reproducible. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mm/alignment.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index d073b64ae87e..724ba3bce72c 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -885,8 +885,23 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) if (ai_usermode & UM_SIGNAL) force_sig(SIGBUS, current); - else - set_cr(cr_no_alignment); + else { + /* + * We're about to disable the alignment trap and return to + * user space. But if an interrupt occurs before actually + * reaching user space, then the IRQ vector entry code will + * notice that we were still in kernel space and therefore + * the alignment trap won't be re-enabled in that case as it + * is presumed to be always on from kernel space. + * Let's prevent that race by disabling interrupts here (they + * are disabled on the way back to user space anyway in + * entry-common.S) and disable the alignment trap only if + * there is no work pending for this thread. + */ + raw_local_irq_disable(); + if (!(current_thread_info()->flags & _TIF_WORK_MASK)) + set_cr(cr_no_alignment); + } return 0; } -- cgit v1.2.2 From e9bf51971157e367aabfc111a8219db010f69cd4 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 20 Sep 2010 14:33:07 +0200 Subject: x86/amd-iommu: Set iommu configuration flags in enable-loop This patch moves the setting of the configuration and feature flags out out the acpi table parsing path and moves it into the iommu-enable path. This is needed to reliably fix resume-from-s3. Cc: stable@kernel.org Signed-off-by: Joerg Roedel --- arch/x86/include/asm/amd_iommu_types.h | 3 +++ arch/x86/kernel/amd_iommu_init.c | 49 +++++++++++++++++++--------------- 2 files changed, 30 insertions(+), 22 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h index 7014e88bc779..ef2d5cd7d7e7 100644 --- a/arch/x86/include/asm/amd_iommu_types.h +++ b/arch/x86/include/asm/amd_iommu_types.h @@ -368,6 +368,9 @@ struct amd_iommu { /* capabilities of that IOMMU read from ACPI */ u32 cap; + /* flags read from acpi table */ + u8 acpi_flags; + /* * Capability pointer. There could be more than one IOMMU per PCI * device function if there are more than one AMD IOMMU capability diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 3cc63e2b8dd4..85e9817ead43 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -649,29 +649,9 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, struct ivhd_entry *e; /* - * First set the recommended feature enable bits from ACPI - * into the IOMMU control registers + * First save the recommended feature enable bits from ACPI */ - h->flags & IVHD_FLAG_HT_TUN_EN_MASK ? - iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) : - iommu_feature_disable(iommu, CONTROL_HT_TUN_EN); - - h->flags & IVHD_FLAG_PASSPW_EN_MASK ? - iommu_feature_enable(iommu, CONTROL_PASSPW_EN) : - iommu_feature_disable(iommu, CONTROL_PASSPW_EN); - - h->flags & IVHD_FLAG_RESPASSPW_EN_MASK ? - iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) : - iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN); - - h->flags & IVHD_FLAG_ISOC_EN_MASK ? - iommu_feature_enable(iommu, CONTROL_ISOC_EN) : - iommu_feature_disable(iommu, CONTROL_ISOC_EN); - - /* - * make IOMMU memory accesses cache coherent - */ - iommu_feature_enable(iommu, CONTROL_COHERENT_EN); + iommu->acpi_flags = h->flags; /* * Done. Now parse the device entries @@ -1116,6 +1096,30 @@ static void init_device_table(void) } } +static void iommu_init_flags(struct amd_iommu *iommu) +{ + iommu->acpi_flags & IVHD_FLAG_HT_TUN_EN_MASK ? + iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) : + iommu_feature_disable(iommu, CONTROL_HT_TUN_EN); + + iommu->acpi_flags & IVHD_FLAG_PASSPW_EN_MASK ? + iommu_feature_enable(iommu, CONTROL_PASSPW_EN) : + iommu_feature_disable(iommu, CONTROL_PASSPW_EN); + + iommu->acpi_flags & IVHD_FLAG_RESPASSPW_EN_MASK ? + iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) : + iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN); + + iommu->acpi_flags & IVHD_FLAG_ISOC_EN_MASK ? + iommu_feature_enable(iommu, CONTROL_ISOC_EN) : + iommu_feature_disable(iommu, CONTROL_ISOC_EN); + + /* + * make IOMMU memory accesses cache coherent + */ + iommu_feature_enable(iommu, CONTROL_COHERENT_EN); +} + /* * This function finally enables all IOMMUs found in the system after * they have been initialized @@ -1126,6 +1130,7 @@ static void enable_iommus(void) for_each_iommu(iommu) { iommu_disable(iommu); + iommu_init_flags(iommu); iommu_set_device_table(iommu); iommu_enable_command_buffer(iommu); iommu_enable_event_buffer(iommu); -- cgit v1.2.2 From 4c894f47bb49284008073d351c0ddaac8860864e Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 23 Sep 2010 15:15:19 +0200 Subject: x86/amd-iommu: Work around S3 BIOS bug This patch adds a workaround for an IOMMU BIOS problem to the AMD IOMMU driver. The result of the bug is that the IOMMU does not execute commands anymore when the system comes out of the S3 state resulting in system failure. The bug in the BIOS is that is does not restore certain hardware specific registers correctly. This workaround reads out the contents of these registers at boot time and restores them on resume from S3. The workaround is limited to the specific IOMMU chipset where this problem occurs. Cc: stable@kernel.org Signed-off-by: Joerg Roedel --- arch/x86/include/asm/amd_iommu_proto.h | 6 ++++++ arch/x86/include/asm/amd_iommu_types.h | 9 +++++++++ arch/x86/kernel/amd_iommu_init.c | 18 ++++++++++++++++++ 3 files changed, 33 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/amd_iommu_proto.h b/arch/x86/include/asm/amd_iommu_proto.h index d2544f1d705d..cb030374b90a 100644 --- a/arch/x86/include/asm/amd_iommu_proto.h +++ b/arch/x86/include/asm/amd_iommu_proto.h @@ -38,4 +38,10 @@ static inline void amd_iommu_stats_init(void) { } #endif /* !CONFIG_AMD_IOMMU_STATS */ +static inline bool is_rd890_iommu(struct pci_dev *pdev) +{ + return (pdev->vendor == PCI_VENDOR_ID_ATI) && + (pdev->device == PCI_DEVICE_ID_RD890_IOMMU); +} + #endif /* _ASM_X86_AMD_IOMMU_PROTO_H */ diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h index ef2d5cd7d7e7..08616180deaf 100644 --- a/arch/x86/include/asm/amd_iommu_types.h +++ b/arch/x86/include/asm/amd_iommu_types.h @@ -414,6 +414,15 @@ struct amd_iommu { /* default dma_ops domain for that IOMMU */ struct dma_ops_domain *default_dom; + + /* + * This array is required to work around a potential BIOS bug. + * The BIOS may miss to restore parts of the PCI configuration + * space when the system resumes from S3. The result is that the + * IOMMU does not execute commands anymore which leads to system + * failure. + */ + u32 cache_cfg[4]; }; /* diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 85e9817ead43..5a170cbbbed8 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -632,6 +632,13 @@ static void __init init_iommu_from_pci(struct amd_iommu *iommu) iommu->last_device = calc_devid(MMIO_GET_BUS(range), MMIO_GET_LD(range)); iommu->evt_msi_num = MMIO_MSI_NUM(misc); + + if (is_rd890_iommu(iommu->dev)) { + pci_read_config_dword(iommu->dev, 0xf0, &iommu->cache_cfg[0]); + pci_read_config_dword(iommu->dev, 0xf4, &iommu->cache_cfg[1]); + pci_read_config_dword(iommu->dev, 0xf8, &iommu->cache_cfg[2]); + pci_read_config_dword(iommu->dev, 0xfc, &iommu->cache_cfg[3]); + } } /* @@ -1120,6 +1127,16 @@ static void iommu_init_flags(struct amd_iommu *iommu) iommu_feature_enable(iommu, CONTROL_COHERENT_EN); } +static void iommu_apply_quirks(struct amd_iommu *iommu) +{ + if (is_rd890_iommu(iommu->dev)) { + pci_write_config_dword(iommu->dev, 0xf0, iommu->cache_cfg[0]); + pci_write_config_dword(iommu->dev, 0xf4, iommu->cache_cfg[1]); + pci_write_config_dword(iommu->dev, 0xf8, iommu->cache_cfg[2]); + pci_write_config_dword(iommu->dev, 0xfc, iommu->cache_cfg[3]); + } +} + /* * This function finally enables all IOMMUs found in the system after * they have been initialized @@ -1130,6 +1147,7 @@ static void enable_iommus(void) for_each_iommu(iommu) { iommu_disable(iommu); + iommu_apply_quirks(iommu); iommu_init_flags(iommu); iommu_set_device_table(iommu); iommu_enable_command_buffer(iommu); -- cgit v1.2.2 From 04e0463e088b41060c08c255eb0d3278a504f094 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 23 Sep 2010 16:12:48 +0200 Subject: x86/amd-iommu: Fix rounding-bug in __unmap_single In the __unmap_single function the dma_addr is rounded down to a page boundary before the dma pages are unmapped. The address is later also used to flush the TLB entries for that mapping. But without the offset into the dma page the amount of pages to flush might be miscalculated in the TLB flushing path. This patch fixes this bug by using the original address to flush the TLB. Cc: stable@kernel.org Signed-off-by: Joerg Roedel --- arch/x86/kernel/amd_iommu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index fa044e1e30a2..679b6450382b 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -1953,6 +1953,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, size_t size, int dir) { + dma_addr_t flush_addr; dma_addr_t i, start; unsigned int pages; @@ -1960,6 +1961,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, (dma_addr + size > dma_dom->aperture_size)) return; + flush_addr = dma_addr; pages = iommu_num_pages(dma_addr, size, PAGE_SIZE); dma_addr &= PAGE_MASK; start = dma_addr; @@ -1974,7 +1976,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, dma_ops_free_addresses(dma_dom, dma_addr, pages); if (amd_iommu_unmap_flush || dma_dom->need_flush) { - iommu_flush_pages(&dma_dom->domain, dma_addr, size); + iommu_flush_pages(&dma_dom->domain, flush_addr, size); dma_dom->need_flush = false; } } -- cgit v1.2.2 From fd429a0842c61b60e02a7e63430a609957821c67 Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Thu, 23 Sep 2010 16:40:22 +0100 Subject: MN10300: Fix endianess of ext2 bitops The MN10300 arch ext2 bitops assume a big-endian kernel, but the MN10300 arch only runs in little-endian mode. Reported-by: Akira Takeuchi Signed-off-by: Mark Salter Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/mn10300/include/asm/bitops.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mn10300/include/asm/bitops.h b/arch/mn10300/include/asm/bitops.h index f49ac49e09ad..3f50e9661076 100644 --- a/arch/mn10300/include/asm/bitops.h +++ b/arch/mn10300/include/asm/bitops.h @@ -229,9 +229,9 @@ int ffs(int x) #include #define ext2_set_bit_atomic(lock, nr, addr) \ - test_and_set_bit((nr) ^ 0x18, (addr)) + test_and_set_bit((nr), (addr)) #define ext2_clear_bit_atomic(lock, nr, addr) \ - test_and_clear_bit((nr) ^ 0x18, (addr)) + test_and_clear_bit((nr), (addr)) #include #include -- cgit v1.2.2 From a6ef9c8f1635ccd175be9eb5d36c376ffb8fbc51 Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Thu, 23 Sep 2010 18:04:28 +0100 Subject: MN10300: Fix SIGRTMAX SIGRTMAX should be _NSIG not _NSIG-1. Signed-off-by: Mark Salter Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/mn10300/include/asm/signal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mn10300/include/asm/signal.h b/arch/mn10300/include/asm/signal.h index 7e891fce2370..1865d72a86ff 100644 --- a/arch/mn10300/include/asm/signal.h +++ b/arch/mn10300/include/asm/signal.h @@ -78,7 +78,7 @@ typedef unsigned long sigset_t; /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: -- cgit v1.2.2 From ed3473b18f85b591c1e8afec831e9e06120142b7 Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Thu, 23 Sep 2010 18:04:33 +0100 Subject: MN10300: Arch doesn't support HAVE_ARCH_TRACEHOOK Remove specification of HAVE_ARCH_TRACEHOOK for MN10300 as the arch does not support it at this time. Signed-off-by: Mark Salter Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/mn10300/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 444b9f918fdf..7c2a2f7f8dc1 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig @@ -8,7 +8,6 @@ mainmenu "Linux Kernel Configuration" config MN10300 def_bool y select HAVE_OPROFILE - select HAVE_ARCH_TRACEHOOK config AM33 def_bool y -- cgit v1.2.2 From 63e6be6d98e1a2bcdca86872b67052e51ab6afa1 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 15 Sep 2010 18:20:34 +0200 Subject: perf, x86: Catch spurious interrupts after disabling counters Some cpus still deliver spurious interrupts after disabling a counter. This caused 'undelivered NMI' messages. This patch fixes this. Introduced by: 4177c42: perf, x86: Try to handle unknown nmis with an enabled PMU Reported-by: Ingo Molnar Signed-off-by: Robert Richter Cc: Don Zickus Cc: gorcunov@gmail.com Cc: fweisbec@gmail.com Cc: ying.huang@intel.com Cc: ming.m.lin@intel.com Cc: yinghai@kernel.org Cc: andi@firstfloor.org Cc: eranian@google.com Cc: Peter Zijlstra LKML-Reference: <20100915162034.GO13563@erda.amd.com> Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 3efdf2870a35..03a5b0385ad6 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -102,6 +102,7 @@ struct cpu_hw_events { */ struct perf_event *events[X86_PMC_IDX_MAX]; /* in counter order */ unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; + unsigned long running[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; int enabled; int n_events; @@ -1010,6 +1011,7 @@ static int x86_pmu_start(struct perf_event *event) x86_perf_event_set_period(event); cpuc->events[idx] = event; __set_bit(idx, cpuc->active_mask); + __set_bit(idx, cpuc->running); x86_pmu.enable(event); perf_event_update_userpage(event); @@ -1141,8 +1143,16 @@ static int x86_pmu_handle_irq(struct pt_regs *regs) cpuc = &__get_cpu_var(cpu_hw_events); for (idx = 0; idx < x86_pmu.num_counters; idx++) { - if (!test_bit(idx, cpuc->active_mask)) + if (!test_bit(idx, cpuc->active_mask)) { + /* + * Though we deactivated the counter some cpus + * might still deliver spurious interrupts still + * in flight. Catch them: + */ + if (__test_and_clear_bit(idx, cpuc->running)) + handled++; continue; + } event = cpuc->events[idx]; hwc = &event->hw; -- cgit v1.2.2 From a46590533ad7b0f3f640732081d7e1658145c0ba Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 23 Sep 2010 22:21:34 -0700 Subject: x86/hwmon: fix initialization of coretemp Using cpuid_eax() to determine feature availability on other than the current CPU is invalid. And feature availability should also be checked in the hotplug code path. Signed-off-by: Jan Beulich Cc: Rudolf Marek Cc: Fenghua Yu Signed-off-by: Guenter Roeck --- arch/x86/include/asm/cpufeature.h | 1 + arch/x86/kernel/cpu/scattered.c | 1 + 2 files changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index c6fbb7b430d1..3f76523589af 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -168,6 +168,7 @@ #define X86_FEATURE_XSAVEOPT (7*32+ 4) /* Optimized Xsave */ #define X86_FEATURE_PLN (7*32+ 5) /* Intel Power Limit Notification */ #define X86_FEATURE_PTS (7*32+ 6) /* Intel Package Thermal Status */ +#define X86_FEATURE_DTS (7*32+ 7) /* Digital Thermal Sensor */ /* Virtualization flags: Linux defined, word 8 */ #define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */ diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index 34b4dad6f0b8..d49079515122 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -31,6 +31,7 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) const struct cpuid_bit *cb; static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { + { X86_FEATURE_DTS, CR_EAX, 0, 0x00000006, 0 }, { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006, 0 }, { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006, 0 }, { X86_FEATURE_PLN, CR_EAX, 4, 0x00000006, 0 }, -- cgit v1.2.2 From a7f8388e2c167c73b6abb3b749157aafd08f90ee Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 24 Sep 2010 06:20:35 +0100 Subject: m32r: fix rt_sigsuspend() do_signal() should know about saved_mask for it to work... Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/m32r/include/asm/signal.h | 1 - arch/m32r/include/asm/unistd.h | 1 + arch/m32r/kernel/entry.S | 3 +-- arch/m32r/kernel/signal.c | 48 +++++++++++------------------------------- 4 files changed, 14 insertions(+), 39 deletions(-) (limited to 'arch') diff --git a/arch/m32r/include/asm/signal.h b/arch/m32r/include/asm/signal.h index 9c1acb2b1a92..b2eeb0de1c8d 100644 --- a/arch/m32r/include/asm/signal.h +++ b/arch/m32r/include/asm/signal.h @@ -157,7 +157,6 @@ typedef struct sigaltstack { #undef __HAVE_ARCH_SIG_BITOPS struct pt_regs; -extern int do_signal(struct pt_regs *regs, sigset_t *oldset); #define ptrace_signal_deliver(regs, cookie) do { } while (0) diff --git a/arch/m32r/include/asm/unistd.h b/arch/m32r/include/asm/unistd.h index 76125777483c..c70545689da8 100644 --- a/arch/m32r/include/asm/unistd.h +++ b/arch/m32r/include/asm/unistd.h @@ -351,6 +351,7 @@ #define __ARCH_WANT_SYS_OLD_GETRLIMIT /*will be unused*/ #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_RT_SIGACTION +#define __ARCH_WANT_SYS_RT_SIGSUSPEND #define __IGNORE_lchown #define __IGNORE_setuid diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index 403869833b98..90149daa560f 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S @@ -235,8 +235,7 @@ work_resched: work_notifysig: ; deal with pending signals and ; notify-resume requests mv r0, sp ; arg1 : struct pt_regs *regs - ldi r1, #0 ; arg2 : sigset_t *oldset - mv r2, r9 ; arg3 : __u32 thread_info_flags + ldi r1, r9 ; arg2 : __u32 thread_info_flags bl do_notify_resume bra restore_all diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c index 144b0f124fc7..acd69f7f3357 100644 --- a/arch/m32r/kernel/signal.c +++ b/arch/m32r/kernel/signal.c @@ -28,37 +28,6 @@ #define DEBUG_SIG 0 -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -int do_signal(struct pt_regs *, sigset_t *); - -asmlinkage int -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, - unsigned long r2, unsigned long r3, unsigned long r4, - unsigned long r5, unsigned long r6, struct pt_regs *regs) -{ - sigset_t newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP)); - - spin_lock_irq(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_thread_flag(TIF_RESTORE_SIGMASK); - return -ERESTARTNOHAND; -} - asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r2, unsigned long r3, unsigned long r4, @@ -332,12 +301,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -int do_signal(struct pt_regs *regs, sigset_t *oldset) +static int do_signal(struct pt_regs *regs) { siginfo_t info; int signr; struct k_sigaction ka; unsigned short inst; + sigset_t *oldset; /* * We want the common case to go fast, which @@ -351,7 +321,9 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) if (try_to_freeze()) goto no_signal; - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); @@ -364,6 +336,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) /* Whee! Actually deliver the signal. */ handle_signal(signr, &ka, &info, oldset, regs); + clear_thread_flag(TIF_RESTORE_SIGMASK); return 1; } @@ -391,6 +364,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) regs->bpc -= 4; } } + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } return 0; } @@ -398,8 +375,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) * notification of userspace execution resumption * - triggered by current->work.notify_resume */ -void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, - __u32 thread_info_flags) +void do_notify_resume(struct pt_regs *regs, __u32 thread_info_flags) { /* Pending single-step? */ if (thread_info_flags & _TIF_SINGLESTEP) @@ -407,7 +383,7 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, /* deal with pending signal delivery */ if (thread_info_flags & _TIF_SIGPENDING) - do_signal(regs,oldset); + do_signal(regs); if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); -- cgit v1.2.2 From a748102430f4dbbfca3ff81ac12db6e4f1243677 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 24 Sep 2010 06:22:30 +0100 Subject: make m32r handle multiple pending signals Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/m32r/kernel/entry.S | 4 ++-- arch/m32r/kernel/signal.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index 90149daa560f..225412bc227e 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S @@ -235,9 +235,9 @@ work_resched: work_notifysig: ; deal with pending signals and ; notify-resume requests mv r0, sp ; arg1 : struct pt_regs *regs - ldi r1, r9 ; arg2 : __u32 thread_info_flags + mv r1, r9 ; arg2 : __u32 thread_info_flags bl do_notify_resume - bra restore_all + bra resume_userspace ; perform syscall exit tracing ALIGN diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c index acd69f7f3357..db152263484f 100644 --- a/arch/m32r/kernel/signal.c +++ b/arch/m32r/kernel/signal.c @@ -282,6 +282,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, regs->bpc -= 2; else regs->bpc -= 4; + regs->syscall_nr = -1; } } @@ -353,8 +354,8 @@ static int do_signal(struct pt_regs *regs) regs->bpc -= 2; else regs->bpc -= 4; - } - if (regs->r0 == -ERESTART_RESTARTBLOCK){ + regs->syscall_nr = -1; + } else if (regs->r0 == -ERESTART_RESTARTBLOCK){ regs->r0 = regs->orig_r0; regs->r7 = __NR_restart_syscall; inst = *(unsigned short *)(regs->bpc - 2); @@ -362,6 +363,7 @@ static int do_signal(struct pt_regs *regs) regs->bpc -= 2; else regs->bpc -= 4; + regs->syscall_nr = -1; } } if (test_thread_flag(TIF_RESTORE_SIGMASK)) { -- cgit v1.2.2 From a05c4e1d669d09faa90ce7b22646ad1a4b0de3ff Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 24 Sep 2010 06:23:57 +0100 Subject: m32r: don't block signals if sigframe setup has failed Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/m32r/kernel/signal.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c index db152263484f..a56fcbd8abe6 100644 --- a/arch/m32r/kernel/signal.c +++ b/arch/m32r/kernel/signal.c @@ -187,7 +187,7 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) return (void __user *)((sp - frame_size) & -8ul); } -static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, +static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; @@ -244,17 +244,18 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, current->comm, current->pid, frame, regs->pc); #endif - return; + return 0; give_sigsegv: force_sigsegv(sig, current); + return -EFAULT; } /* * OK, we're invoking a handler */ -static void +static int handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { @@ -287,7 +288,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, } /* Set up the stack frame */ - setup_rt_frame(sig, ka, info, oldset, regs); + if (setup_rt_frame(sig, ka, info, oldset, regs)) + return -EFAULT; spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -295,6 +297,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigaddset(¤t->blocked,sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + return 0; } /* @@ -302,7 +305,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -static int do_signal(struct pt_regs *regs) +static void do_signal(struct pt_regs *regs) { siginfo_t info; int signr; @@ -317,7 +320,7 @@ static int do_signal(struct pt_regs *regs) * if so. */ if (!user_mode(regs)) - return 1; + return; if (try_to_freeze()) goto no_signal; @@ -336,9 +339,10 @@ static int do_signal(struct pt_regs *regs) */ /* Whee! Actually deliver the signal. */ - handle_signal(signr, &ka, &info, oldset, regs); - clear_thread_flag(TIF_RESTORE_SIGMASK); - return 1; + if (handle_signal(signr, &ka, &info, oldset, regs) == 0) + clear_thread_flag(TIF_RESTORE_SIGMASK); + + return; } no_signal: @@ -370,7 +374,6 @@ static int do_signal(struct pt_regs *regs) clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } - return 0; } /* -- cgit v1.2.2 From bb9c861ee1b94c97cd98c783a2b4c1cf53ff1712 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 24 Sep 2010 06:24:53 +0100 Subject: m32r: hole in shifting pc back It's a userland pointer; worse, an untrustable one since ptrace has just provided a chance to modify it. X-Roothole-Covering-Cabal: TINRCC Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/m32r/kernel/signal.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) (limited to 'arch') diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c index a56fcbd8abe6..7bbe38645ed5 100644 --- a/arch/m32r/kernel/signal.c +++ b/arch/m32r/kernel/signal.c @@ -251,6 +251,19 @@ give_sigsegv: return -EFAULT; } +static int prev_insn(struct pt_regs *regs) +{ + u16 inst; + if (get_user(&inst, (u16 __user *)(regs->bpc - 2))) + return -EFAULT; + if ((inst & 0xfff0) == 0x10f0) /* trap ? */ + regs->bpc -= 2; + else + regs->bpc -= 4; + regs->syscall_nr = -1; + return 0; +} + /* * OK, we're invoking a handler */ @@ -259,8 +272,6 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { - unsigned short inst; - /* Are we from a system call? */ if (regs->syscall_nr >= 0) { /* If so, check system call restarting.. */ @@ -278,12 +289,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, /* fallthrough */ case -ERESTARTNOINTR: regs->r0 = regs->orig_r0; - inst = *(unsigned short *)(regs->bpc - 2); - if ((inst & 0xfff0) == 0x10f0) /* trap ? */ - regs->bpc -= 2; - else - regs->bpc -= 4; - regs->syscall_nr = -1; + if (prev_insn(regs) < 0) + return -EFAULT; } } @@ -310,7 +317,6 @@ static void do_signal(struct pt_regs *regs) siginfo_t info; int signr; struct k_sigaction ka; - unsigned short inst; sigset_t *oldset; /* @@ -353,21 +359,11 @@ static void do_signal(struct pt_regs *regs) regs->r0 == -ERESTARTSYS || regs->r0 == -ERESTARTNOINTR) { regs->r0 = regs->orig_r0; - inst = *(unsigned short *)(regs->bpc - 2); - if ((inst & 0xfff0) == 0x10f0) /* trap ? */ - regs->bpc -= 2; - else - regs->bpc -= 4; - regs->syscall_nr = -1; + prev_insn(regs); } else if (regs->r0 == -ERESTART_RESTARTBLOCK){ regs->r0 = regs->orig_r0; regs->r7 = __NR_restart_syscall; - inst = *(unsigned short *)(regs->bpc - 2); - if ((inst & 0xfff0) == 0x10f0) /* trap ? */ - regs->bpc -= 2; - else - regs->bpc -= 4; - regs->syscall_nr = -1; + prev_insn(regs); } } if (test_thread_flag(TIF_RESTORE_SIGMASK)) { -- cgit v1.2.2 From acdc0d5ef9dd74534fe8df77a2056fa1d911abe5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 24 Sep 2010 06:25:34 +0100 Subject: m32r: fix breakage from "m32r: use generic ptrace_resume code" Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/m32r/kernel/ptrace.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c index e555091eb97c..0021ade4cba8 100644 --- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c @@ -592,16 +592,17 @@ void user_enable_single_step(struct task_struct *child) if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0) != sizeof(insn)) - break; + return -EIO; compute_next_pc(insn, pc, &next_pc, child); if (next_pc & 0x80000000) - break; + return -EIO; if (embed_debug_trap(child, next_pc)) - break; + return -EIO; invalidate_cache(); + return 0; } void user_disable_single_step(struct task_struct *child) -- cgit v1.2.2 From ea44e06e79a393fb577272399ef7521a143b6b59 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Fri, 24 Sep 2010 17:19:20 -0400 Subject: arch/tile: remove dead code from intvec_32.S This "bpt_code" instruction was killed off in our development line a while ago (the actual definition of bpt_code that is used is in kernel/traps.c) but I didn't push it for 2.6.36 because it seemed harmless and I didn't want to try to push more than absolutely necessary. However, we recently fixed a bug in our gcc that had been causing "-gdwarf2" not to be passed to the assembler, and passing this flag causes an erroneous assembler failure in the presence of code in a data section, sometimes. While we'd like to track down the bug in the assembler, we'd also like to make sure 2.6.36 builds with the current toolchain, so I'm removing this dead code as well. Signed-off-by: Chris Metcalf --- arch/tile/kernel/intvec_32.S | 7 ------- 1 file changed, 7 deletions(-) (limited to 'arch') diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index 84f296ca9e63..8f58bdff20d7 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S @@ -1506,13 +1506,6 @@ handle_ill: } STD_ENDPROC(handle_ill) - .pushsection .rodata, "a" - .align 8 -bpt_code: - bpt - ENDPROC(bpt_code) - .popsection - /* Various stub interrupt handlers and syscall handlers */ STD_ENTRY_LOCAL(_kernel_double_fault) -- cgit v1.2.2 From 979a281c34906fd905d6153ad999487b0c56f396 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 9 Aug 2010 03:55:09 +0200 Subject: ARM: pxa: Fix Vpac270 gpio_power for MMC GPIO 0 is valid, yet this platform doesn't have any power GPIO for MMC. Signed-off-by: Marek Vasut --- arch/arm/mach-pxa/vpac270.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index c9b747cedea8..37d6173bbb66 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -240,6 +240,7 @@ static void __init vpac270_onenand_init(void) {} #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE) static struct pxamci_platform_data vpac270_mci_platform_data = { .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, + .gpio_power = -1, .gpio_card_detect = GPIO53_VPAC270_SD_DETECT_N, .gpio_card_ro = GPIO52_VPAC270_SD_READONLY, .detect_delay_ms = 200, -- cgit v1.2.2 From cf625368d3ad664c7c9ae89974599bbfe9947511 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 14 Aug 2010 06:08:30 +0200 Subject: ARM: pxa: Use PIO for PI2C communication on Palm27x Original idea by: Mike Rapoport Signed-off-by: Marek Vasut --- arch/arm/mach-pxa/palm27x.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/palm27x.c b/arch/arm/mach-pxa/palm27x.c index 77ad6d34ab5b..405b92a29793 100644 --- a/arch/arm/mach-pxa/palm27x.c +++ b/arch/arm/mach-pxa/palm27x.c @@ -469,9 +469,13 @@ static struct i2c_board_info __initdata palm27x_pi2c_board_info[] = { }, }; +static struct i2c_pxa_platform_data palm27x_i2c_power_info = { + .use_pio = 1, +}; + void __init palm27x_pmic_init(void) { i2c_register_board_info(1, ARRAY_AND_SIZE(palm27x_pi2c_board_info)); - pxa27x_set_i2c_power_info(NULL); + pxa27x_set_i2c_power_info(&palm27x_i2c_power_info); } #endif -- cgit v1.2.2 From 32c4dad8f872fadb0ae3caa15d26e73934982217 Mon Sep 17 00:00:00 2001 From: "Mark F. Brown" Date: Thu, 26 Aug 2010 05:07:29 -0400 Subject: ARM: pxa168: fix corrected reset vector Reset vector for pxa168 is 0xffff_0000 not 0x0. This fix allows reboot to work Signed-off-by: Mark F. Brown Signed-off-by: Eric Miao --- arch/arm/mach-mmp/include/mach/system.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-mmp/include/mach/system.h b/arch/arm/mach-mmp/include/mach/system.h index 4f5b0e0ce6cf..1a8a25edb1b4 100644 --- a/arch/arm/mach-mmp/include/mach/system.h +++ b/arch/arm/mach-mmp/include/mach/system.h @@ -9,6 +9,8 @@ #ifndef __ASM_MACH_SYSTEM_H #define __ASM_MACH_SYSTEM_H +#include + static inline void arch_idle(void) { cpu_do_idle(); @@ -16,6 +18,9 @@ static inline void arch_idle(void) static inline void arch_reset(char mode, const char *cmd) { - cpu_reset(0); + if (cpu_is_pxa168()) + cpu_reset(0xffff0000); + else + cpu_reset(0); } #endif /* __ASM_MACH_SYSTEM_H */ -- cgit v1.2.2 From cfc6a554d7a364997a43964b4b1290487f890447 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 7 Sep 2010 15:10:14 +0800 Subject: ARM: pxa: fix cpu_is_pxa*() not expanding to zero when not configured When CONFIG_PXA3xx is not selected, cpu_is_pxa3xx() doesn't expand to zero, which in some places doesn't result in correct optimization. Signed-off-by: Eric Miao Reported-and-tested-by: Marek Vasut --- arch/arm/mach-pxa/include/mach/hardware.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h index 7f64d24cd564..b03650059d15 100644 --- a/arch/arm/mach-pxa/include/mach/hardware.h +++ b/arch/arm/mach-pxa/include/mach/hardware.h @@ -264,23 +264,35 @@ * <= 0x2 for pxa21x/pxa25x/pxa26x/pxa27x * == 0x3 for pxa300/pxa310/pxa320 */ +#if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x) #define __cpu_is_pxa2xx(id) \ ({ \ unsigned int _id = (id) >> 13 & 0x7; \ _id <= 0x2; \ }) +#else +#define __cpu_is_pxa2xx(id) (0) +#endif +#ifdef CONFIG_PXA3xx #define __cpu_is_pxa3xx(id) \ ({ \ unsigned int _id = (id) >> 13 & 0x7; \ _id == 0x3; \ }) +#else +#define __cpu_is_pxa3xx(id) (0) +#endif +#if defined(CONFIG_CPU_PXA930) || defined(CONFIG_CPU_PXA935) #define __cpu_is_pxa93x(id) \ ({ \ unsigned int _id = (id) >> 4 & 0xfff; \ _id == 0x683 || _id == 0x693; \ }) +#else +#define __cpu_is_pxa93x(id) (0) +#endif #define cpu_is_pxa2xx() \ ({ \ -- cgit v1.2.2 From d42028060dfe1b9b65a387a849e82fd5c86359fb Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 11 Sep 2010 22:10:49 -0700 Subject: ARM: pxa: remove pr_ uses of KERN_ Signed-off-by: Joe Perches Signed-off-by: Eric Miao --- arch/arm/mach-pxa/cpufreq-pxa2xx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/cpufreq-pxa2xx.c b/arch/arm/mach-pxa/cpufreq-pxa2xx.c index 50d5939a78f1..58093d9e07be 100644 --- a/arch/arm/mach-pxa/cpufreq-pxa2xx.c +++ b/arch/arm/mach-pxa/cpufreq-pxa2xx.c @@ -312,8 +312,7 @@ static int pxa_set_target(struct cpufreq_policy *policy, freqs.cpu = policy->cpu; if (freq_debug) - pr_debug(KERN_INFO "Changing CPU frequency to %d Mhz, " - "(SDRAM %d Mhz)\n", + pr_debug("Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n", freqs.new / 1000, (pxa_freq_settings[idx].div2) ? (new_freq_mem / 2000) : (new_freq_mem / 1000)); -- cgit v1.2.2 From f1a2481c0ad3aebd94d11b317c488deaadc25002 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Fri, 24 Sep 2010 07:18:22 +0100 Subject: ARM: 6407/1: mmu: Setup MT_MEMORY and MT_MEMORY_NONCACHED L1 entries This patch populates the L1 entries for MT_MEMORY and MT_MEMORY_NONCACHED types so that at boot-up, we can map memories outside system memory at page level granularity Previously the mapping was limiting to section level, which creates unnecessary additional mapping for which physical memory may not present. On the newer ARM with speculation, this is dangerous and can result in untraceable aborts. Signed-off-by: Santosh Shilimkar Signed-off-by: Russell King --- arch/arm/mm/mmu.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index a486bd0d97dc..6a3a2d0cd6db 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -247,6 +247,9 @@ static struct mem_type mem_types[] = { .domain = DOMAIN_USER, }, [MT_MEMORY] = { + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + L_PTE_USER | L_PTE_EXEC, + .prot_l1 = PMD_TYPE_TABLE, .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, .domain = DOMAIN_KERNEL, }, @@ -255,6 +258,9 @@ static struct mem_type mem_types[] = { .domain = DOMAIN_KERNEL, }, [MT_MEMORY_NONCACHED] = { + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + L_PTE_USER | L_PTE_EXEC | L_PTE_MT_BUFFERABLE, + .prot_l1 = PMD_TYPE_TABLE, .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, .domain = DOMAIN_KERNEL, }, @@ -412,9 +418,12 @@ static void __init build_mem_type_table(void) * Enable CPU-specific coherency if supported. * (Only available on XSC3 at the moment.) */ - if (arch_is_coherent() && cpu_is_xsc3()) + if (arch_is_coherent() && cpu_is_xsc3()) { mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; - + mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED; + mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED; + } /* * ARMv6 and above have extended page tables. */ @@ -439,7 +448,9 @@ static void __init build_mem_type_table(void) mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED; mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED; mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED; #endif } @@ -476,6 +487,8 @@ static void __init build_mem_type_table(void) mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; + mem_types[MT_MEMORY].prot_pte |= kern_pgprot; + mem_types[MT_MEMORY_NONCACHED].prot_sect |= ecc_mask; mem_types[MT_ROM].prot_sect |= cp->pmd; switch (cp->pmd) { -- cgit v1.2.2 From e546f21b4b7af012d9f18edad6237339adfeb681 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Fri, 24 Sep 2010 07:19:49 +0100 Subject: ARM: 6408/1: omap: Map only available sram memory Currently we map 1 MB section while setting up SRAM on OMAPs Regardless of the actual memory. The physical OCM RAM available on OMAP SOCs is in order of KBs. This patch maps only available sram and cleans up some un-necessary cpu_is_xxx checks. Mapping un-available or non-accessible(secure) memory on the newer ARM processor is dangerous. Because ARM CPUs can now speculatively prefetch, we should avoid mapping any no-existing or secure memory. Signed-off-by: Santosh Shilimkar Acked-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/plat-omap/sram.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 226b2e858d6c..10b3b4c63372 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -220,20 +220,7 @@ void __init omap_map_sram(void) if (omap_sram_size == 0) return; - if (cpu_is_omap24xx()) { - omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA; - - base = OMAP2_SRAM_PA; - base = ROUND_DOWN(base, PAGE_SIZE); - omap_sram_io_desc[0].pfn = __phys_to_pfn(base); - } - if (cpu_is_omap34xx()) { - omap_sram_io_desc[0].virtual = OMAP3_SRAM_VA; - base = OMAP3_SRAM_PA; - base = ROUND_DOWN(base, PAGE_SIZE); - omap_sram_io_desc[0].pfn = __phys_to_pfn(base); - /* * SRAM must be marked as non-cached on OMAP3 since the * CORE DPLL M2 divider change code (in SRAM) runs with the @@ -244,13 +231,11 @@ void __init omap_map_sram(void) omap_sram_io_desc[0].type = MT_MEMORY_NONCACHED; } - if (cpu_is_omap44xx()) { - omap_sram_io_desc[0].virtual = OMAP4_SRAM_VA; - base = OMAP4_SRAM_PA; - base = ROUND_DOWN(base, PAGE_SIZE); - omap_sram_io_desc[0].pfn = __phys_to_pfn(base); - } - omap_sram_io_desc[0].length = 1024 * 1024; /* Use section desc */ + omap_sram_io_desc[0].virtual = omap_sram_base; + base = omap_sram_start; + base = ROUND_DOWN(base, PAGE_SIZE); + omap_sram_io_desc[0].pfn = __phys_to_pfn(base); + omap_sram_io_desc[0].length = ROUND_DOWN(omap_sram_size, PAGE_SIZE); iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n", -- cgit v1.2.2 From 2de5c00ac06c8983ab33ad51a8341584f1cf42c3 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Fri, 24 Sep 2010 07:21:05 +0100 Subject: ARM: 6409/1: davinci: map sram using MT_MEMORY_NONCACHED instead of MT_DEVICE On Davinci SRAM is mapped as MT_DEVICE becasue of the section mapping pre-requisite instead of intended MT_MEMORY_NONCACHED Since the section mapping limitation gets fixed with first patch in this series, the MT_MEMORY_NONCACHED can be used now. Signed-off-by: Santosh Shilimkar Acked-by: Kevin Hilman Signed-off-by: Russell King --- arch/arm/mach-davinci/dm355.c | 3 +-- arch/arm/mach-davinci/dm365.c | 3 +-- arch/arm/mach-davinci/dm644x.c | 3 +-- arch/arm/mach-davinci/dm646x.c | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 3d996b659ff4..9be261beae7d 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -769,8 +769,7 @@ static struct map_desc dm355_io_desc[] = { .virtual = SRAM_VIRT, .pfn = __phys_to_pfn(0x00010000), .length = SZ_32K, - /* MT_MEMORY_NONCACHED requires supersection alignment */ - .type = MT_DEVICE, + .type = MT_MEMORY_NONCACHED, }, }; diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 6b6f4c643709..7781e35daec3 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -969,8 +969,7 @@ static struct map_desc dm365_io_desc[] = { .virtual = SRAM_VIRT, .pfn = __phys_to_pfn(0x00010000), .length = SZ_32K, - /* MT_MEMORY_NONCACHED requires supersection alignment */ - .type = MT_DEVICE, + .type = MT_MEMORY_NONCACHED, }, }; diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 40fec315c99a..5e5b0a7831fb 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -653,8 +653,7 @@ static struct map_desc dm644x_io_desc[] = { .virtual = SRAM_VIRT, .pfn = __phys_to_pfn(0x00008000), .length = SZ_16K, - /* MT_MEMORY_NONCACHED requires supersection alignment */ - .type = MT_DEVICE, + .type = MT_MEMORY_NONCACHED, }, }; diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index e4a3df1872ac..26e8a9c7f50b 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -737,8 +737,7 @@ static struct map_desc dm646x_io_desc[] = { .virtual = SRAM_VIRT, .pfn = __phys_to_pfn(0x00010000), .length = SZ_32K, - /* MT_MEMORY_NONCACHED requires supersection alignment */ - .type = MT_DEVICE, + .type = MT_MEMORY_NONCACHED, }, }; -- cgit v1.2.2 From 77edffb652b33a565e099ff0a1687762f03eb46a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 25 Sep 2010 21:07:14 +0100 Subject: alpha: fix hae_cache race in RESTORE_ALL We want interrupts disabled on all paths leading to RESTORE_ALL; otherwise, we are risking an IRQ coming between the updates of alpha_mv->hae_cache and *alpha_mv->hae_register and set_hae() within the IRQ getting badly confused. RESTORE_ALL used to play with disabling IRQ itself, but that got removed back in 2002, without making sure we had them disabled on all paths. It's cheaper to make sure we have them disabled than to revert to original variant... Remove the detritus left from that commit back in 2002; we used to need a reload of $0 and $1 since swpipl would change those, but doing that had become pointless when we stopped doing swpipl in there... Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/alpha/kernel/entry.S | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index ab1ee0ab082b..d1273c1a1364 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -73,8 +73,6 @@ ldq $20, HAE_REG($19); \ stq $21, HAE_CACHE($19); \ stq $21, 0($20); \ - ldq $0, 0($sp); \ - ldq $1, 8($sp); \ 99:; \ ldq $19, 72($sp); \ ldq $20, 80($sp); \ @@ -316,7 +314,7 @@ ret_from_sys_call: cmovne $26, 0, $19 /* $19 = 0 => non-restartable */ ldq $0, SP_OFF($sp) and $0, 8, $0 - beq $0, restore_all + beq $0, ret_to_kernel ret_to_user: /* Make sure need_resched and sigpending don't change between sampling and the rti. */ @@ -329,6 +327,11 @@ restore_all: RESTORE_ALL call_pal PAL_rti +ret_to_kernel: + lda $16, 7 + call_pal PAL_swpipl + br restore_all + .align 3 $syscall_error: /* @@ -657,7 +660,7 @@ kernel_thread: /* We don't actually care for a3 success widgetry in the kernel. Not for positive errno values. */ stq $0, 0($sp) /* $0 */ - br restore_all + br ret_to_kernel .end kernel_thread /* -- cgit v1.2.2 From 32163f4b2cef28a5aab8b226ffecfc6379a53786 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 25 Sep 2010 21:07:51 +0100 Subject: alpha: fix usp value in multithreaded coredumps rdusp() gives us the right value only for the current thread... Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/alpha/kernel/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 842dba308eab..3ec35066f1dc 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -356,7 +356,7 @@ dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti) dest[27] = pt->r27; dest[28] = pt->r28; dest[29] = pt->gp; - dest[30] = rdusp(); + dest[30] = ti == current_thread_info() ? rdusp() : ti->pcb.usp; dest[31] = pt->pc; /* Once upon a time this was the PS value. Which is stupid -- cgit v1.2.2 From c9e2fbd909c20b165b2b9ffb59f8b674cf0a55b0 Mon Sep 17 00:00:00 2001 From: Alexander Chumachenko Date: Thu, 1 Apr 2010 15:34:52 +0300 Subject: x86: Avoid 'constant_test_bit()' misoptimization due to cast to non-volatile While debugging bit_spin_lock() hang, it was tracked down to gcc-4.4 misoptimization of non-inlined constant_test_bit() due to non-volatile addr when 'const volatile unsigned long *addr' cast to 'unsigned long *' with subsequent unconditional jump to pause (and not to the test) leading to hang. Compiling with gcc-4.3 or disabling CONFIG_OPTIMIZE_INLINING yields inlined constant_test_bit() and correct jump, thus working around the kernel bug. Other arches than asm-x86 may implement this slightly differently; 2.6.29 mitigates the misoptimization by changing the function prototype (commit c4295fbb6048d85f0b41c5ced5cbf63f6811c46c) but probably fixing the issue itself is better. Signed-off-by: Alexander Chumachenko Signed-off-by: Michael Shigorin Acked-by: Linus Torvalds Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/bitops.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h index 545776efeb16..bafd80defa43 100644 --- a/arch/x86/include/asm/bitops.h +++ b/arch/x86/include/asm/bitops.h @@ -309,7 +309,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr) static __always_inline int constant_test_bit(unsigned int nr, const volatile unsigned long *addr) { return ((1UL << (nr % BITS_PER_LONG)) & - (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0; + (addr[nr / BITS_PER_LONG])) != 0; } static inline int variable_test_bit(int nr, volatile const unsigned long *addr) -- cgit v1.2.2 From 2de59fea8b3095d1df4c729fda041625930aab4f Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 27 Sep 2010 14:55:15 +0100 Subject: ARM: 6411/1: vexpress: set RAM latencies to 1 cycle for PL310 on ct-ca9x4 tile The PL310 on the ct-ca9x4 tile for the Versatile Express does not need to add additional latency when accessing its cache RAMs. Unfortunately, the boot monitor sets this up for an 8-cycle delay on reads and writes, resulting in greatly reduced memory performance when the L2 cache is enabled. This patch sets the L2 RAM latencies to the correct value of 1 cycle on the ct-ca9x4 tile before enabling the L2 cache. Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mach-vexpress/ct-ca9x4.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 1c9c13e9d074..efb127022d42 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -227,7 +227,13 @@ static void ct_ca9x4_init(void) int i; #ifdef CONFIG_CACHE_L2X0 - l2x0_init(MMIO_P2V(CT_CA9X4_L2CC), 0x00400000, 0xfe0fffff); + void __iomem *l2x0_base = MMIO_P2V(CT_CA9X4_L2CC); + + /* set RAM latencies to 1 cycle for this core tile. */ + writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL); + writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL); + + l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff); #endif clkdev_add_table(lookups, ARRAY_SIZE(lookups)); -- cgit v1.2.2 From c52c2ddc1dfa6fe85ffd5e4c57cf91f6982639fe Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 26 Sep 2010 19:28:12 +0100 Subject: alpha: switch osf_sigprocmask() to use of sigprocmask() get rid of a useless wrapper, while we are at it Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/alpha/kernel/entry.S | 9 --------- arch/alpha/kernel/signal.c | 48 +++++++++++---------------------------------- arch/alpha/kernel/systbls.S | 2 +- 3 files changed, 12 insertions(+), 47 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index d1273c1a1364..6d159cee5f2f 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -914,15 +914,6 @@ sys_execve: jmp $31, do_sys_execve .end sys_execve - .align 4 - .globl osf_sigprocmask - .ent osf_sigprocmask -osf_sigprocmask: - .prologue 0 - mov $sp, $18 - jmp $31, sys_osf_sigprocmask -.end osf_sigprocmask - .align 4 .globl alpha_ni_syscall .ent alpha_ni_syscall diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 0f6b51ae865a..06609aa363b6 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -41,46 +41,20 @@ static void do_signal(struct pt_regs *, struct switch_stack *, /* * The OSF/1 sigprocmask calling sequence is different from the * C sigprocmask() sequence.. - * - * how: - * 1 - SIG_BLOCK - * 2 - SIG_UNBLOCK - * 3 - SIG_SETMASK - * - * We change the range to -1 .. 1 in order to let gcc easily - * use the conditional move instructions. - * - * Note that we don't need to acquire the kernel lock for SMP - * operation, as all of this is local to this thread. */ -SYSCALL_DEFINE3(osf_sigprocmask, int, how, unsigned long, newmask, - struct pt_regs *, regs) +SYSCALL_DEFINE2(osf_sigprocmask, int, how, unsigned long, newmask) { - unsigned long oldmask = -EINVAL; - - if ((unsigned long)how-1 <= 2) { - long sign = how-2; /* -1 .. 1 */ - unsigned long block, unblock; - - newmask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - oldmask = current->blocked.sig[0]; - - unblock = oldmask & ~newmask; - block = oldmask | newmask; - if (!sign) - block = unblock; - if (sign <= 0) - newmask = block; - if (_NSIG_WORDS > 1 && sign > 0) - sigemptyset(¤t->blocked); - current->blocked.sig[0] = newmask; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->r0 = 0; /* special no error return */ + sigset_t oldmask; + sigset_t mask; + unsigned long res; + + siginitset(&mask, newmask & ~_BLOCKABLE); + res = siprocmask(how, &mask, &oldmask); + if (!res) { + force_successful_syscall_return(); + res = oldmask->sig[0]; } - return oldmask; + return res; } SYSCALL_DEFINE3(osf_sigaction, int, sig, diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S index ce594ef533cc..a6a1de9db16f 100644 --- a/arch/alpha/kernel/systbls.S +++ b/arch/alpha/kernel/systbls.S @@ -58,7 +58,7 @@ sys_call_table: .quad sys_open /* 45 */ .quad alpha_ni_syscall .quad sys_getxgid - .quad osf_sigprocmask + .quad sys_osf_sigprocmask .quad alpha_ni_syscall .quad alpha_ni_syscall /* 50 */ .quad sys_acct -- cgit v1.2.2 From 18e6bfa96d4d810ad9a69e17f08e0d0089379f22 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 26 Sep 2010 19:28:22 +0100 Subject: alpha: __get_user/__put_user results need to be checked... Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/alpha/kernel/signal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 06609aa363b6..779780a332d3 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -68,9 +68,9 @@ SYSCALL_DEFINE3(osf_sigaction, int, sig, old_sigset_t mask; if (!access_ok(VERIFY_READ, act, sizeof(*act)) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_flags, &act->sa_flags)) + __get_user(new_ka.sa.sa_flags, &act->sa_flags) || + __get_user(mask, &act->sa_mask)) return -EFAULT; - __get_user(mask, &act->sa_mask); siginitset(&new_ka.sa.sa_mask, mask); new_ka.ka_restorer = NULL; } @@ -80,9 +80,9 @@ SYSCALL_DEFINE3(osf_sigaction, int, sig, if (!ret && oact) { if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_flags, &oact->sa_flags)) + __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) return -EFAULT; - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } return ret; -- cgit v1.2.2 From e46924d246e028c94689087db0699438343a344e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 26 Sep 2010 19:28:32 +0100 Subject: mn10300: avoid SIGSEGV delivery loop force_sigsegv() is there for purpose... Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/mn10300/kernel/signal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c index 717db14c2cc3..57178a8d5af0 100644 --- a/arch/mn10300/kernel/signal.c +++ b/arch/mn10300/kernel/signal.c @@ -345,7 +345,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, return 0; give_sigsegv: - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return -EFAULT; } @@ -428,7 +428,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return 0; give_sigsegv: - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return -EFAULT; } -- cgit v1.2.2 From 00cbf6080c7d60b999864afcd9010e0bbc7c5db6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 26 Sep 2010 19:28:42 +0100 Subject: mn10300: prevent double syscall restarts set ->orig_d0 to -1, same as what sigreturn does Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/mn10300/kernel/signal.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c index 57178a8d5af0..4ef99256fa49 100644 --- a/arch/mn10300/kernel/signal.c +++ b/arch/mn10300/kernel/signal.c @@ -432,6 +432,12 @@ give_sigsegv: return -EFAULT; } +static inline void stepback(struct pt_regs *regs) +{ + regs->pc -= 2; + regs->orig_d0 = -1; +} + /* * handle the actual delivery of a signal to userspace */ @@ -459,7 +465,7 @@ static int handle_signal(int sig, /* fallthrough */ case -ERESTARTNOINTR: regs->d0 = regs->orig_d0; - regs->pc -= 2; + stepback(regs); } } @@ -527,12 +533,12 @@ static void do_signal(struct pt_regs *regs) case -ERESTARTSYS: case -ERESTARTNOINTR: regs->d0 = regs->orig_d0; - regs->pc -= 2; + stepback(regs); break; case -ERESTART_RESTARTBLOCK: regs->d0 = __NR_restart_syscall; - regs->pc -= 2; + stepback(regs); break; } } -- cgit v1.2.2 From c05628b49b19187841d635dddd3e47caab33242b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 26 Sep 2010 19:28:52 +0100 Subject: mn10300: ->restart_block.fn needs to be reset on sigreturn Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/mn10300/kernel/signal.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c index 4ef99256fa49..5a2c0040b166 100644 --- a/arch/mn10300/kernel/signal.c +++ b/arch/mn10300/kernel/signal.c @@ -102,6 +102,9 @@ static int restore_sigcontext(struct pt_regs *regs, { unsigned int err = 0; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + if (is_using_fpu(current)) fpu_kill_state(current); -- cgit v1.2.2 From 8e87354d01b3046aa5e1080419178191f3dce8f0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 26 Sep 2010 19:29:02 +0100 Subject: mn10300: get rid of set_fs(USER_DS) in sigframe setup It really has no business being there; short of a serious kernel bug we should already have USER_DS at that point. It shouldn't have been done on x86 either... Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/mn10300/kernel/signal.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch') diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c index 5a2c0040b166..ae36480b450f 100644 --- a/arch/mn10300/kernel/signal.c +++ b/arch/mn10300/kernel/signal.c @@ -333,8 +333,6 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, regs->d0 = sig; regs->d1 = (unsigned long) &frame->sc; - set_fs(USER_DS); - /* the tracer may want to single-step inside the handler */ if (test_thread_flag(TIF_SINGLESTEP)) ptrace_notify(SIGTRAP); @@ -416,8 +414,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->d0 = sig; regs->d1 = (long) &frame->info; - set_fs(USER_DS); - /* the tracer may want to single-step inside the handler */ if (test_thread_flag(TIF_SINGLESTEP)) ptrace_notify(SIGTRAP); -- cgit v1.2.2 From 60bdb72e3c2e808228612f672bd8d18e82872de3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 26 Sep 2010 19:29:12 +0100 Subject: mn10300: check __get_user/__put_user results... Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/mn10300/kernel/signal.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c index ae36480b450f..d4de05ab7864 100644 --- a/arch/mn10300/kernel/signal.c +++ b/arch/mn10300/kernel/signal.c @@ -65,10 +65,10 @@ asmlinkage long sys_sigaction(int sig, old_sigset_t mask; if (verify_area(VERIFY_READ, act, sizeof(*act)) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags) || + __get_user(mask, &act->sa_mask)) return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); siginitset(&new_ka.sa.sa_mask, mask); } @@ -77,10 +77,10 @@ asmlinkage long sys_sigaction(int sig, if (!ret && oact) { if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } return ret; -- cgit v1.2.2 From 95929eff2cb01e9858779283795f4e3943ee020d Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 27 Sep 2010 13:12:33 +0100 Subject: MN10300: Default config choice GDBSTUB_TTYSM0 should be GDBSTUB_ON_TTYSM0 The configuration choice for the port on which the GDB stub listens has a default of GDBSTUB_TTYSM0, but this should be GDBSTUB_ON_TTYSM0 to match the option. Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/mn10300/Kconfig.debug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mn10300/Kconfig.debug b/arch/mn10300/Kconfig.debug index ff80e86b9bd2..ce83c74b3fd7 100644 --- a/arch/mn10300/Kconfig.debug +++ b/arch/mn10300/Kconfig.debug @@ -101,7 +101,7 @@ config GDBSTUB_DEBUG_BREAKPOINT choice prompt "GDB stub port" - default GDBSTUB_TTYSM0 + default GDBSTUB_ON_TTYSM0 depends on GDBSTUB help Select the serial port used for GDB-stub. -- cgit v1.2.2 From 0f44fbd297e1cda5d9ecc9f5321a86fe647c7d4a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 28 Sep 2010 13:26:57 -0700 Subject: alpha: fix compile problem in arch/alpha/kernel/signal.c Tssk. Apparently Al hadn't checked commit c52c2ddc1dfa ("alpha: switch osf_sigprocmask() to use of sigprocmask()") at all. It doesn't compile. Fixed as per suggestions from Michael Cree. Reported-by: Michael Cree Cc: Al Viro Signed-off-by: Linus Torvalds --- arch/alpha/kernel/signal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 779780a332d3..d290845aef59 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -49,10 +49,10 @@ SYSCALL_DEFINE2(osf_sigprocmask, int, how, unsigned long, newmask) unsigned long res; siginitset(&mask, newmask & ~_BLOCKABLE); - res = siprocmask(how, &mask, &oldmask); + res = sigprocmask(how, &mask, &oldmask); if (!res) { force_successful_syscall_return(); - res = oldmask->sig[0]; + res = oldmask.sig[0]; } return res; } -- cgit v1.2.2 From 62bdb288bf464862a2801b2e53aadc6c4d100fab Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 29 Sep 2010 01:57:02 +0100 Subject: MN10300: Handle missing sys_cacheflush() when caching disabled When caching is disabled on the MN10300 arch, the sys_cacheflush() function is removed by conditional stuff in the makefiles, but is still referred to by the syscall table. Provide a null version that just returns 0 when caching is disabled (or -EINVAL if the arguments are silly). Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/mn10300/mm/Makefile | 14 ++++++-------- arch/mn10300/mm/cache-disabled.c | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 arch/mn10300/mm/cache-disabled.c (limited to 'arch') diff --git a/arch/mn10300/mm/Makefile b/arch/mn10300/mm/Makefile index 28b9d983db0c..1557277fbc5c 100644 --- a/arch/mn10300/mm/Makefile +++ b/arch/mn10300/mm/Makefile @@ -2,13 +2,11 @@ # Makefile for the MN10300-specific memory management code # +cacheflush-y := cache.o cache-mn10300.o +cacheflush-$(CONFIG_MN10300_CACHE_WBACK) += cache-flush-mn10300.o + +cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o + obj-y := \ init.o fault.o pgtable.o extable.o tlb-mn10300.o mmu-context.o \ - misalignment.o dma-alloc.o - -ifneq ($(CONFIG_MN10300_CACHE_DISABLED),y) -obj-y += cache.o cache-mn10300.o -ifeq ($(CONFIG_MN10300_CACHE_WBACK),y) -obj-y += cache-flush-mn10300.o -endif -endif + misalignment.o dma-alloc.o $(cacheflush-y) diff --git a/arch/mn10300/mm/cache-disabled.c b/arch/mn10300/mm/cache-disabled.c new file mode 100644 index 000000000000..f669ea42aba6 --- /dev/null +++ b/arch/mn10300/mm/cache-disabled.c @@ -0,0 +1,21 @@ +/* Handle the cache being disabled + * + * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +#include + +/* + * allow userspace to flush the instruction cache + */ +asmlinkage long sys_cacheflush(unsigned long start, unsigned long end) +{ + if (end < start) + return -EINVAL; + return 0; +} -- cgit v1.2.2 From 4d4a4b037c5d3620b8c55504a8c9e0cbf949f7fa Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 27 Sep 2010 22:09:52 +0100 Subject: ARM: 6413/1: ux500: resources for DB5500 mbox driver and modem irq handler Platform resources found in the DB5500 for mailboxes and the modem IRQ controller. Signed-off-by: Stefan Nilsson XK Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-ux500/cpu-db5500.c | 88 ++++++++++++++++++++++++++ arch/arm/mach-ux500/include/mach/db5500-regs.h | 14 ++++ arch/arm/mach-ux500/include/mach/irqs-db5500.h | 1 + arch/arm/mach-ux500/include/mach/irqs.h | 15 ++++- 4 files changed, 117 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index e9278f6d67aa..2f87075e9d6f 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c @@ -14,6 +14,7 @@ #include #include #include +#include static struct map_desc u5500_io_desc[] __initdata = { __IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K), @@ -24,6 +25,90 @@ static struct map_desc u5500_io_desc[] __initdata = { __IO_DEV_DESC(U5500_PRCMU_BASE, SZ_4K), }; +static struct resource mbox0_resources[] = { + { + .name = "mbox_peer", + .start = U5500_MBOX0_PEER_START, + .end = U5500_MBOX0_PEER_END, + .flags = IORESOURCE_MEM, + }, + { + .name = "mbox_local", + .start = U5500_MBOX0_LOCAL_START, + .end = U5500_MBOX0_LOCAL_END, + .flags = IORESOURCE_MEM, + }, + { + .name = "mbox_irq", + .start = MBOX_PAIR0_VIRT_IRQ, + .end = MBOX_PAIR0_VIRT_IRQ, + .flags = IORESOURCE_IRQ, + } +}; + +static struct resource mbox1_resources[] = { + { + .name = "mbox_peer", + .start = U5500_MBOX1_PEER_START, + .end = U5500_MBOX1_PEER_END, + .flags = IORESOURCE_MEM, + }, + { + .name = "mbox_local", + .start = U5500_MBOX1_LOCAL_START, + .end = U5500_MBOX1_LOCAL_END, + .flags = IORESOURCE_MEM, + }, + { + .name = "mbox_irq", + .start = MBOX_PAIR1_VIRT_IRQ, + .end = MBOX_PAIR1_VIRT_IRQ, + .flags = IORESOURCE_IRQ, + } +}; + +static struct resource mbox2_resources[] = { + { + .name = "mbox_peer", + .start = U5500_MBOX2_PEER_START, + .end = U5500_MBOX2_PEER_END, + .flags = IORESOURCE_MEM, + }, + { + .name = "mbox_local", + .start = U5500_MBOX2_LOCAL_START, + .end = U5500_MBOX2_LOCAL_END, + .flags = IORESOURCE_MEM, + }, + { + .name = "mbox_irq", + .start = MBOX_PAIR2_VIRT_IRQ, + .end = MBOX_PAIR2_VIRT_IRQ, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device mbox0_device = { + .id = 0, + .name = "mbox", + .resource = mbox0_resources, + .num_resources = ARRAY_SIZE(mbox0_resources), +}; + +static struct platform_device mbox1_device = { + .id = 1, + .name = "mbox", + .resource = mbox1_resources, + .num_resources = ARRAY_SIZE(mbox1_resources), +}; + +static struct platform_device mbox2_device = { + .id = 2, + .name = "mbox", + .resource = mbox2_resources, + .num_resources = ARRAY_SIZE(mbox2_resources), +}; + static struct platform_device *u5500_platform_devs[] __initdata = { &u5500_gpio_devs[0], &u5500_gpio_devs[1], @@ -33,6 +118,9 @@ static struct platform_device *u5500_platform_devs[] __initdata = { &u5500_gpio_devs[5], &u5500_gpio_devs[6], &u5500_gpio_devs[7], + &mbox0_device, + &mbox1_device, + &mbox2_device, }; void __init u5500_map_io(void) diff --git a/arch/arm/mach-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h index 545c80fc8024..3eafc0e24ba5 100644 --- a/arch/arm/mach-ux500/include/mach/db5500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db5500-regs.h @@ -100,4 +100,18 @@ #define U5500_GPIOBANK6_BASE (U5500_GPIO4_BASE + 0x80) #define U5500_GPIOBANK7_BASE (U5500_GPIO4_BASE + 0x100) +#define U5500_MBOX_BASE (U5500_MODEM_BASE + 0xFFD1000) +#define U5500_MBOX0_PEER_START (U5500_MBOX_BASE + 0x40) +#define U5500_MBOX0_PEER_END (U5500_MBOX_BASE + 0x5F) +#define U5500_MBOX0_LOCAL_START (U5500_MBOX_BASE + 0x60) +#define U5500_MBOX0_LOCAL_END (U5500_MBOX_BASE + 0x7F) +#define U5500_MBOX1_PEER_START (U5500_MBOX_BASE + 0x80) +#define U5500_MBOX1_PEER_END (U5500_MBOX_BASE + 0x9F) +#define U5500_MBOX1_LOCAL_START (U5500_MBOX_BASE + 0xA0) +#define U5500_MBOX1_LOCAL_END (U5500_MBOX_BASE + 0xBF) +#define U5500_MBOX2_PEER_START (U5500_MBOX_BASE + 0x00) +#define U5500_MBOX2_PEER_END (U5500_MBOX_BASE + 0x1F) +#define U5500_MBOX2_LOCAL_START (U5500_MBOX_BASE + 0x20) +#define U5500_MBOX2_LOCAL_END (U5500_MBOX_BASE + 0x3F) + #endif diff --git a/arch/arm/mach-ux500/include/mach/irqs-db5500.h b/arch/arm/mach-ux500/include/mach/irqs-db5500.h index 6fbfe5e2065a..bfa123dbec3b 100644 --- a/arch/arm/mach-ux500/include/mach/irqs-db5500.h +++ b/arch/arm/mach-ux500/include/mach/irqs-db5500.h @@ -61,6 +61,7 @@ #define IRQ_DB5500_SDMMC0 (IRQ_SHPI_START + 60) #define IRQ_DB5500_HSEM (IRQ_SHPI_START + 61) #define IRQ_DB5500_SBAG (IRQ_SHPI_START + 63) +#define IRQ_DB5500_MODEM (IRQ_SHPI_START + 65) #define IRQ_DB5500_SPI1 (IRQ_SHPI_START + 96) #define IRQ_DB5500_MSP2 (IRQ_SHPI_START + 98) #define IRQ_DB5500_SRPTIMER (IRQ_SHPI_START + 101) diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h index 0d552d9c9c00..693aa57de88d 100644 --- a/arch/arm/mach-ux500/include/mach/irqs.h +++ b/arch/arm/mach-ux500/include/mach/irqs.h @@ -84,6 +84,19 @@ #include #endif -#define NR_IRQS IRQ_BOARD_END +/* + * After the board specific IRQ:s we reserve a range of IRQ:s in which virtual + * IRQ:s representing modem IRQ:s can be allocated + */ +#define IRQ_MODEM_EVENTS_BASE (IRQ_BOARD_END + 1) +#define IRQ_MODEM_EVENTS_NBR 72 +#define IRQ_MODEM_EVENTS_END (IRQ_MODEM_EVENTS_BASE + IRQ_MODEM_EVENTS_NBR) + +/* List of virtual IRQ:s that are allocated from the range above */ +#define MBOX_PAIR0_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 43) +#define MBOX_PAIR1_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 45) +#define MBOX_PAIR2_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 41) + +#define NR_IRQS IRQ_MODEM_EVENTS_END #endif /* ASM_ARCH_IRQS_H */ -- cgit v1.2.2 From b84ccd776fedee8b28f736662cd045bf893ed633 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 27 Sep 2010 22:10:55 +0100 Subject: ARM: 6414/1: ux500: DB5500 generic modem IRQ handler This is a (threaded) IRQ handler for the modems that appear from the modem part of the DB5500 ASIC. Signed-off-by: Stefan Nilsson XK Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-ux500/modem_irq.c | 139 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 arch/arm/mach-ux500/modem_irq.c (limited to 'arch') diff --git a/arch/arm/mach-ux500/modem_irq.c b/arch/arm/mach-ux500/modem_irq.c new file mode 100644 index 000000000000..3187f8871169 --- /dev/null +++ b/arch/arm/mach-ux500/modem_irq.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Stefan Nilsson for ST-Ericsson. + * Author: Martin Persson for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +#include +#include +#include +#include +#include +#include + +#define MODEM_INTCON_BASE_ADDR 0xBFFD3000 +#define MODEM_INTCON_SIZE 0xFFF + +#define DEST_IRQ41_OFFSET 0x2A4 +#define DEST_IRQ43_OFFSET 0x2AC +#define DEST_IRQ45_OFFSET 0x2B4 + +#define PRIO_IRQ41_OFFSET 0x6A4 +#define PRIO_IRQ43_OFFSET 0x6AC +#define PRIO_IRQ45_OFFSET 0x6B4 + +#define ALLOW_IRQ_OFFSET 0x104 + +#define MODEM_INTCON_CPU_NBR 0x1 +#define MODEM_INTCON_PRIO_HIGH 0x0 + +#define MODEM_INTCON_ALLOW_IRQ41 0x0200 +#define MODEM_INTCON_ALLOW_IRQ43 0x0800 +#define MODEM_INTCON_ALLOW_IRQ45 0x2000 + +#define MODEM_IRQ_REG_OFFSET 0x4 + +struct modem_irq { + void __iomem *modem_intcon_base; +}; + + +static void setup_modem_intcon(void __iomem *modem_intcon_base) +{ + /* IC_DESTINATION_BASE_ARRAY - Which CPU to receive the IRQ */ + writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ41_OFFSET); + writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ43_OFFSET); + writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ45_OFFSET); + + /* IC_PRIORITY_BASE_ARRAY - IRQ priority in modem IRQ controller */ + writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ41_OFFSET); + writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ43_OFFSET); + writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ45_OFFSET); + + /* IC_ALLOW_ARRAY - IRQ enable */ + writel(MODEM_INTCON_ALLOW_IRQ41 | + MODEM_INTCON_ALLOW_IRQ43 | + MODEM_INTCON_ALLOW_IRQ45, + modem_intcon_base + ALLOW_IRQ_OFFSET); +} + +static irqreturn_t modem_cpu_irq_handler(int irq, void *data) +{ + int real_irq; + int virt_irq; + struct modem_irq *mi = (struct modem_irq *)data; + + /* Read modem side IRQ number from modem IRQ controller */ + real_irq = readl(mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET) & 0xFF; + virt_irq = IRQ_MODEM_EVENTS_BASE + real_irq; + + pr_debug("modem_irq: Worker read addr 0x%X and got value 0x%X " + "which will be 0x%X (%d) which translates to " + "virtual IRQ 0x%X (%d)!\n", + (u32)mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET, + real_irq, + real_irq & 0xFF, + real_irq & 0xFF, + virt_irq, + virt_irq); + + if (virt_irq != 0) + generic_handle_irq(virt_irq); + + pr_debug("modem_irq: Done handling virtual IRQ %d!\n", virt_irq); + + return IRQ_HANDLED; +} + +static void create_virtual_irq(int irq, struct irq_chip *modem_irq_chip) +{ + set_irq_chip(irq, modem_irq_chip); + set_irq_handler(irq, handle_simple_irq); + set_irq_flags(irq, IRQF_VALID); + + pr_debug("modem_irq: Created virtual IRQ %d\n", irq); +} + +static int modem_irq_init(void) +{ + int err; + static struct irq_chip modem_irq_chip; + struct modem_irq *mi; + + pr_info("modem_irq: Set up IRQ handler for incoming modem IRQ %d\n", + IRQ_DB5500_MODEM); + + mi = kmalloc(sizeof(struct modem_irq), GFP_KERNEL); + if (!mi) { + pr_err("modem_irq: Could not allocate device\n"); + return -ENOMEM; + } + + mi->modem_intcon_base = + ioremap(MODEM_INTCON_BASE_ADDR, MODEM_INTCON_SIZE); + pr_debug("modem_irq: ioremapped modem_intcon_base from " + "phy 0x%x to virt 0x%x\n", MODEM_INTCON_BASE_ADDR, + (u32)mi->modem_intcon_base); + + setup_modem_intcon(mi->modem_intcon_base); + + modem_irq_chip = dummy_irq_chip; + modem_irq_chip.name = "modem_irq"; + + /* Create the virtual IRQ:s needed */ + create_virtual_irq(MBOX_PAIR0_VIRT_IRQ, &modem_irq_chip); + create_virtual_irq(MBOX_PAIR1_VIRT_IRQ, &modem_irq_chip); + create_virtual_irq(MBOX_PAIR2_VIRT_IRQ, &modem_irq_chip); + + err = request_threaded_irq(IRQ_DB5500_MODEM, NULL, + modem_cpu_irq_handler, IRQF_ONESHOT, + "modem_irq", mi); + if (err) + pr_err("modem_irq: Could not register IRQ %d\n", + IRQ_DB5500_MODEM); + + return 0; +} + +arch_initcall(modem_irq_init); -- cgit v1.2.2 From 38cdfe06630a109a7a38b70c3cd208defd9f5711 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 27 Sep 2010 22:11:57 +0100 Subject: ARM: 6415/1: ux500: DB5500 mailbox driver This is a driver for the mailboxes used to communicate with the DB5500 modem portions. Signed-off-by: Stefan Nilsson XK Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-ux500/include/mach/mbox.h | 88 +++++ arch/arm/mach-ux500/mbox.c | 567 ++++++++++++++++++++++++++++++++ 2 files changed, 655 insertions(+) create mode 100644 arch/arm/mach-ux500/include/mach/mbox.h create mode 100644 arch/arm/mach-ux500/mbox.c (limited to 'arch') diff --git a/arch/arm/mach-ux500/include/mach/mbox.h b/arch/arm/mach-ux500/include/mach/mbox.h new file mode 100644 index 000000000000..7f9da4d2fbda --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/mbox.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Stefan Nilsson for ST-Ericsson. + * Author: Martin Persson for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +#ifndef __INC_STE_MBOX_H +#define __INC_STE_MBOX_H + +#define MBOX_BUF_SIZE 16 +#define MBOX_NAME_SIZE 8 + +/** + * mbox_recv_cb_t - Definition of the mailbox callback. + * @mbox_msg: The mailbox message. + * @priv: The clients private data as specified in the call to mbox_setup. + * + * This function will be called upon reception of new mailbox messages. + */ +typedef void mbox_recv_cb_t (u32 mbox_msg, void *priv); + +/** + * struct mbox - Mailbox instance struct + * @list: Linked list head. + * @pdev: Pointer to device struct. + * @cb: Callback function. Will be called + * when new data is received. + * @client_data: Clients private data. Will be sent back + * in the callback function. + * @virtbase_peer: Virtual address for outgoing mailbox. + * @virtbase_local: Virtual address for incoming mailbox. + * @buffer: Then internal queue for outgoing messages. + * @name: Name of this mailbox. + * @buffer_available: Completion variable to achieve "blocking send". + * This variable will be signaled when there is + * internal buffer space available. + * @client_blocked: To keep track if any client is currently + * blocked. + * @lock: Spinlock to protect this mailbox instance. + * @write_index: Index in internal buffer to write to. + * @read_index: Index in internal buffer to read from. + * @allocated: Indicates whether this particular mailbox + * id has been allocated by someone. + */ +struct mbox { + struct list_head list; + struct platform_device *pdev; + mbox_recv_cb_t *cb; + void *client_data; + void __iomem *virtbase_peer; + void __iomem *virtbase_local; + u32 buffer[MBOX_BUF_SIZE]; + char name[MBOX_NAME_SIZE]; + struct completion buffer_available; + u8 client_blocked; + spinlock_t lock; + u8 write_index; + u8 read_index; + bool allocated; +}; + +/** + * mbox_setup - Set up a mailbox and return its instance. + * @mbox_id: The ID number of the mailbox. 0 or 1 for modem CPU, + * 2 for modem DSP. + * @mbox_cb: Pointer to the callback function to be called when a new message + * is received. + * @priv: Client user data which will be returned in the callback. + * + * Returns a mailbox instance to be specified in subsequent calls to mbox_send. + */ +struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv); + +/** + * mbox_send - Send a mailbox message. + * @mbox: Mailbox instance (returned by mbox_setup) + * @mbox_msg: The mailbox message to send. + * @block: Specifies whether this call will block until send is possible, + * or return an error if the mailbox buffer is full. + * + * Returns 0 on success or a negative error code on error. -ENOMEM indicates + * that the internal buffer is full and you have to try again later (or + * specify "block" in order to block until send is possible). + */ +int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block); + +#endif /*INC_STE_MBOX_H*/ diff --git a/arch/arm/mach-ux500/mbox.c b/arch/arm/mach-ux500/mbox.c new file mode 100644 index 000000000000..63435389c544 --- /dev/null +++ b/arch/arm/mach-ux500/mbox.c @@ -0,0 +1,567 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Stefan Nilsson for ST-Ericsson. + * Author: Martin Persson for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +/* + * Mailbox nomenclature: + * + * APE MODEM + * mbox pairX + * .......................... + * . . + * . peer . + * . send ---- . + * . --> | | . + * . | | . + * . ---- . + * . . + * . local . + * . rec ---- . + * . | | <-- . + * . | | . + * . ---- . + * ......................... + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MBOX_NAME "mbox" + +#define MBOX_FIFO_DATA 0x000 +#define MBOX_FIFO_ADD 0x004 +#define MBOX_FIFO_REMOVE 0x008 +#define MBOX_FIFO_THRES_FREE 0x00C +#define MBOX_FIFO_THRES_OCCUP 0x010 +#define MBOX_FIFO_STATUS 0x014 + +#define MBOX_DISABLE_IRQ 0x4 +#define MBOX_ENABLE_IRQ 0x0 +#define MBOX_LATCH 1 + +/* Global list of all mailboxes */ +static struct list_head mboxs = LIST_HEAD_INIT(mboxs); + +static struct mbox *get_mbox_with_id(u8 id) +{ + u8 i; + struct list_head *pos = &mboxs; + for (i = 0; i <= id; i++) + pos = pos->next; + + return (struct mbox *) list_entry(pos, struct mbox, list); +} + +int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block) +{ + int res = 0; + + spin_lock(&mbox->lock); + + dev_dbg(&(mbox->pdev->dev), + "About to buffer 0x%X to mailbox 0x%X." + " ri = %d, wi = %d\n", + mbox_msg, (u32)mbox, mbox->read_index, + mbox->write_index); + + /* Check if write buffer is full */ + while (((mbox->write_index + 1) % MBOX_BUF_SIZE) == mbox->read_index) { + if (!block) { + dev_dbg(&(mbox->pdev->dev), + "Buffer full in non-blocking call! " + "Returning -ENOMEM!\n"); + res = -ENOMEM; + goto exit; + } + spin_unlock(&mbox->lock); + dev_dbg(&(mbox->pdev->dev), + "Buffer full in blocking call! Sleeping...\n"); + mbox->client_blocked = 1; + wait_for_completion(&mbox->buffer_available); + dev_dbg(&(mbox->pdev->dev), + "Blocking send was woken up! Trying again...\n"); + spin_lock(&mbox->lock); + } + + mbox->buffer[mbox->write_index] = mbox_msg; + mbox->write_index = (mbox->write_index + 1) % MBOX_BUF_SIZE; + + /* + * Indicate that we want an IRQ as soon as there is a slot + * in the FIFO + */ + writel(MBOX_ENABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE); + +exit: + spin_unlock(&mbox->lock); + return res; +} +EXPORT_SYMBOL(mbox_send); + +#if defined(CONFIG_DEBUG_FS) +/* + * Expected input: + * Example: "echo 0xdeadbeef 4 > mbox-node" sends 0xdeadbeef 4 times + */ +static ssize_t mbox_write_fifo(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + unsigned long mbox_mess; + unsigned long nbr_sends; + unsigned long i; + char int_buf[16]; + char *token; + char *val; + + struct mbox *mbox = (struct mbox *) dev->platform_data; + + strncpy((char *) &int_buf, buf, sizeof(int_buf)); + token = (char *) &int_buf; + + /* Parse message */ + val = strsep(&token, " "); + if ((val == NULL) || (strict_strtoul(val, 16, &mbox_mess) != 0)) + mbox_mess = 0xDEADBEEF; + + val = strsep(&token, " "); + if ((val == NULL) || (strict_strtoul(val, 10, &nbr_sends) != 0)) + nbr_sends = 1; + + dev_dbg(dev, "Will write 0x%lX %ld times using data struct at 0x%X\n", + mbox_mess, nbr_sends, (u32) mbox); + + for (i = 0; i < nbr_sends; i++) + mbox_send(mbox, mbox_mess, true); + + return count; +} + +static ssize_t mbox_read_fifo(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int mbox_value; + struct mbox *mbox = (struct mbox *) dev->platform_data; + + if ((readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7) <= 0) + return sprintf(buf, "Mailbox is empty\n"); + + mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA); + writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE)); + + return sprintf(buf, "0x%X\n", mbox_value); +} + +static DEVICE_ATTR(fifo, S_IWUGO | S_IRUGO, mbox_read_fifo, mbox_write_fifo); + +static int mbox_show(struct seq_file *s, void *data) +{ + struct list_head *pos; + u8 mbox_index = 0; + + list_for_each(pos, &mboxs) { + struct mbox *m = + (struct mbox *) list_entry(pos, struct mbox, list); + if (m == NULL) { + seq_printf(s, + "Unable to retrieve mailbox %d\n", + mbox_index); + continue; + } + + spin_lock(&m->lock); + if ((m->virtbase_peer == NULL) || (m->virtbase_local == NULL)) { + seq_printf(s, "MAILBOX %d not setup or corrupt\n", + mbox_index); + spin_unlock(&m->lock); + continue; + } + + seq_printf(s, + "===========================\n" + " MAILBOX %d\n" + " PEER MAILBOX DUMP\n" + "---------------------------\n" + "FIFO: 0x%X (%d)\n" + "Free Threshold: 0x%.2X (%d)\n" + "Occupied Threshold: 0x%.2X (%d)\n" + "Status: 0x%.2X (%d)\n" + " Free spaces (ot): %d (%d)\n" + " Occup spaces (ot): %d (%d)\n" + "===========================\n" + " LOCAL MAILBOX DUMP\n" + "---------------------------\n" + "FIFO: 0x%.X (%d)\n" + "Free Threshold: 0x%.2X (%d)\n" + "Occupied Threshold: 0x%.2X (%d)\n" + "Status: 0x%.2X (%d)\n" + " Free spaces (ot): %d (%d)\n" + " Occup spaces (ot): %d (%d)\n" + "===========================\n" + "write_index: %d\n" + "read_index : %d\n" + "===========================\n" + "\n", + mbox_index, + readl(m->virtbase_peer + MBOX_FIFO_DATA), + readl(m->virtbase_peer + MBOX_FIFO_DATA), + readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE), + readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE), + readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP), + readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP), + readl(m->virtbase_peer + MBOX_FIFO_STATUS), + readl(m->virtbase_peer + MBOX_FIFO_STATUS), + (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 4) & 0x7, + (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 7) & 0x1, + (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 0) & 0x7, + (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 3) & 0x1, + readl(m->virtbase_local + MBOX_FIFO_DATA), + readl(m->virtbase_local + MBOX_FIFO_DATA), + readl(m->virtbase_local + MBOX_FIFO_THRES_FREE), + readl(m->virtbase_local + MBOX_FIFO_THRES_FREE), + readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP), + readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP), + readl(m->virtbase_local + MBOX_FIFO_STATUS), + readl(m->virtbase_local + MBOX_FIFO_STATUS), + (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 4) & 0x7, + (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 7) & 0x1, + (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 0) & 0x7, + (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 3) & 0x1, + m->write_index, m->read_index); + mbox_index++; + spin_unlock(&m->lock); + } + + return 0; +} + +static int mbox_open(struct inode *inode, struct file *file) +{ + return single_open(file, mbox_show, NULL); +} + +static const struct file_operations mbox_operations = { + .owner = THIS_MODULE, + .open = mbox_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + +static irqreturn_t mbox_irq(int irq, void *arg) +{ + u32 mbox_value; + int nbr_occup; + int nbr_free; + struct mbox *mbox = (struct mbox *) arg; + + spin_lock(&mbox->lock); + + dev_dbg(&(mbox->pdev->dev), + "mbox IRQ [%d] received. ri = %d, wi = %d\n", + irq, mbox->read_index, mbox->write_index); + + /* + * Check if we have any outgoing messages, and if there is space for + * them in the FIFO. + */ + if (mbox->read_index != mbox->write_index) { + /* + * Check by reading FREE for LOCAL since that indicates + * OCCUP for PEER + */ + nbr_free = (readl(mbox->virtbase_local + MBOX_FIFO_STATUS) + >> 4) & 0x7; + dev_dbg(&(mbox->pdev->dev), + "Status indicates %d empty spaces in the FIFO!\n", + nbr_free); + + while ((nbr_free > 0) && + (mbox->read_index != mbox->write_index)) { + /* Write the message and latch it into the FIFO */ + writel(mbox->buffer[mbox->read_index], + (mbox->virtbase_peer + MBOX_FIFO_DATA)); + writel(MBOX_LATCH, + (mbox->virtbase_peer + MBOX_FIFO_ADD)); + dev_dbg(&(mbox->pdev->dev), + "Wrote message 0x%X to addr 0x%X\n", + mbox->buffer[mbox->read_index], + (u32) (mbox->virtbase_peer + MBOX_FIFO_DATA)); + + nbr_free--; + mbox->read_index = + (mbox->read_index + 1) % MBOX_BUF_SIZE; + } + + /* + * Check if we still want IRQ:s when there is free + * space to send + */ + if (mbox->read_index != mbox->write_index) { + dev_dbg(&(mbox->pdev->dev), + "Still have messages to send, but FIFO full. " + "Request IRQ again!\n"); + writel(MBOX_ENABLE_IRQ, + mbox->virtbase_peer + MBOX_FIFO_THRES_FREE); + } else { + dev_dbg(&(mbox->pdev->dev), + "No more messages to send. " + "Do not request IRQ again!\n"); + writel(MBOX_DISABLE_IRQ, + mbox->virtbase_peer + MBOX_FIFO_THRES_FREE); + } + + /* + * Check if we can signal any blocked clients that it is OK to + * start buffering again + */ + if (mbox->client_blocked && + (((mbox->write_index + 1) % MBOX_BUF_SIZE) + != mbox->read_index)) { + dev_dbg(&(mbox->pdev->dev), + "Waking up blocked client\n"); + complete(&mbox->buffer_available); + mbox->client_blocked = 0; + } + } + + /* Check if we have any incoming messages */ + nbr_occup = readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7; + if (nbr_occup == 0) + goto exit; + + if (mbox->cb == NULL) { + dev_dbg(&(mbox->pdev->dev), "No receive callback registered, " + "leaving %d incoming messages in fifo!\n", nbr_occup); + goto exit; + } + + /* Read and acknowledge the message */ + mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA); + writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE)); + + /* Notify consumer of new mailbox message */ + dev_dbg(&(mbox->pdev->dev), "Calling callback for message 0x%X!\n", + mbox_value); + mbox->cb(mbox_value, mbox->client_data); + +exit: + dev_dbg(&(mbox->pdev->dev), "Exit mbox IRQ. ri = %d, wi = %d\n", + mbox->read_index, mbox->write_index); + spin_unlock(&mbox->lock); + + return IRQ_HANDLED; +} + +/* Setup is executed once for each mbox pair */ +struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv) +{ + struct resource *resource; + int irq; + int res; + struct mbox *mbox; + + mbox = get_mbox_with_id(mbox_id); + if (mbox == NULL) { + dev_err(&(mbox->pdev->dev), "Incorrect mailbox id: %d!\n", + mbox_id); + goto exit; + } + + /* + * Check if mailbox has been allocated to someone else, + * otherwise allocate it + */ + if (mbox->allocated) { + dev_err(&(mbox->pdev->dev), "Mailbox number %d is busy!\n", + mbox_id); + mbox = NULL; + goto exit; + } + mbox->allocated = true; + + dev_dbg(&(mbox->pdev->dev), "Initiating mailbox number %d: 0x%X...\n", + mbox_id, (u32)mbox); + + mbox->client_data = priv; + mbox->cb = mbox_cb; + + /* Get addr for peer mailbox and ioremap it */ + resource = platform_get_resource_byname(mbox->pdev, + IORESOURCE_MEM, + "mbox_peer"); + if (resource == NULL) { + dev_err(&(mbox->pdev->dev), + "Unable to retrieve mbox peer resource\n"); + mbox = NULL; + goto exit; + } + dev_dbg(&(mbox->pdev->dev), + "Resource name: %s start: 0x%X, end: 0x%X\n", + resource->name, resource->start, resource->end); + mbox->virtbase_peer = + ioremap(resource->start, resource->end - resource->start); + if (!mbox->virtbase_peer) { + dev_err(&(mbox->pdev->dev), "Unable to ioremap peer mbox\n"); + mbox = NULL; + goto exit; + } + dev_dbg(&(mbox->pdev->dev), + "ioremapped peer physical: (0x%X-0x%X) to virtual: 0x%X\n", + resource->start, resource->end, (u32) mbox->virtbase_peer); + + /* Get addr for local mailbox and ioremap it */ + resource = platform_get_resource_byname(mbox->pdev, + IORESOURCE_MEM, + "mbox_local"); + if (resource == NULL) { + dev_err(&(mbox->pdev->dev), + "Unable to retrieve mbox local resource\n"); + mbox = NULL; + goto exit; + } + dev_dbg(&(mbox->pdev->dev), + "Resource name: %s start: 0x%X, end: 0x%X\n", + resource->name, resource->start, resource->end); + mbox->virtbase_local = + ioremap(resource->start, resource->end - resource->start); + if (!mbox->virtbase_local) { + dev_err(&(mbox->pdev->dev), "Unable to ioremap local mbox\n"); + mbox = NULL; + goto exit; + } + dev_dbg(&(mbox->pdev->dev), + "ioremapped local physical: (0x%X-0x%X) to virtual: 0x%X\n", + resource->start, resource->end, (u32) mbox->virtbase_peer); + + init_completion(&mbox->buffer_available); + mbox->client_blocked = 0; + + /* Get IRQ for mailbox and allocate it */ + irq = platform_get_irq_byname(mbox->pdev, "mbox_irq"); + if (irq < 0) { + dev_err(&(mbox->pdev->dev), + "Unable to retrieve mbox irq resource\n"); + mbox = NULL; + goto exit; + } + + dev_dbg(&(mbox->pdev->dev), "Allocating irq %d...\n", irq); + res = request_irq(irq, mbox_irq, 0, mbox->name, (void *) mbox); + if (res < 0) { + dev_err(&(mbox->pdev->dev), + "Unable to allocate mbox irq %d\n", irq); + mbox = NULL; + goto exit; + } + + /* Set up mailbox to not launch IRQ on free space in mailbox */ + writel(MBOX_DISABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE); + + /* + * Set up mailbox to launch IRQ on new message if we have + * a callback set. If not, do not raise IRQ, but keep message + * in FIFO for manual retrieval + */ + if (mbox_cb != NULL) + writel(MBOX_ENABLE_IRQ, + mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP); + else + writel(MBOX_DISABLE_IRQ, + mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP); + +#if defined(CONFIG_DEBUG_FS) + res = device_create_file(&(mbox->pdev->dev), &dev_attr_fifo); + if (res != 0) + dev_warn(&(mbox->pdev->dev), + "Unable to create mbox sysfs entry"); + + (void) debugfs_create_file("mbox", S_IFREG | S_IRUGO, NULL, + NULL, &mbox_operations); +#endif + + dev_info(&(mbox->pdev->dev), + "Mailbox driver with index %d initated!\n", mbox_id); + +exit: + return mbox; +} +EXPORT_SYMBOL(mbox_setup); + + +int __init mbox_probe(struct platform_device *pdev) +{ + struct mbox local_mbox; + struct mbox *mbox; + int res = 0; + dev_dbg(&(pdev->dev), "Probing mailbox (pdev = 0x%X)...\n", (u32) pdev); + + memset(&local_mbox, 0x0, sizeof(struct mbox)); + + /* Associate our mbox data with the platform device */ + res = platform_device_add_data(pdev, + (void *) &local_mbox, + sizeof(struct mbox)); + if (res != 0) { + dev_err(&(pdev->dev), + "Unable to allocate driver platform data!\n"); + goto exit; + } + + mbox = (struct mbox *) pdev->dev.platform_data; + mbox->pdev = pdev; + mbox->write_index = 0; + mbox->read_index = 0; + + INIT_LIST_HEAD(&(mbox->list)); + list_add_tail(&(mbox->list), &mboxs); + + sprintf(mbox->name, "%s", MBOX_NAME); + spin_lock_init(&mbox->lock); + + dev_info(&(pdev->dev), "Mailbox driver loaded\n"); + +exit: + return res; +} + +static struct platform_driver mbox_driver = { + .driver = { + .name = MBOX_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init mbox_init(void) +{ + return platform_driver_probe(&mbox_driver, mbox_probe); +} + +module_init(mbox_init); + +void __exit mbox_exit(void) +{ + platform_driver_unregister(&mbox_driver); +} + +module_exit(mbox_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MBOX driver"); -- cgit v1.2.2 From e81fcc97350755e021c85b816877ae292b8f28d0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 28 Sep 2010 15:45:41 +0100 Subject: ARM: 6417/1: ux500: build configuration for DB5500 mbox and modem irq handler This rounds of the DB5500 mailbox patches by adding the Kconfig options to enable the modem IRQs and mailboxes. Signed-off-by: Stefan Nilsson XK Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-ux500/Kconfig | 14 ++++++++++++++ arch/arm/mach-ux500/Makefile | 2 ++ 2 files changed, 16 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 6625e5bbf4d6..23fe018cd10b 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -39,4 +39,18 @@ config UX500_DEBUG_UART Choose the UART on which kernel low-level debug messages should be output. +config U5500_MODEM_IRQ + bool "Modem IRQ support" + depends on MACH_U5500 + default y + help + Add support for handling IRQ:s from modem side + +config U5500_MBOX + bool "Mailbox support" + depends on MACH_U5500 && U5500_MODEM_IRQ + default y + help + Add support for U5500 mailbox communication with modem side + endif diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 46dbaf640422..9e27a84433cb 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -11,3 +11,5 @@ obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_REGULATOR_AB8500) += board-mop500-regulators.o +obj-$(CONFIG_U5500_MODEM_IRQ) += modem_irq.o +obj-$(CONFIG_U5500_MBOX) += mbox.o -- cgit v1.2.2 From 1d7e3565946bf23fef5b3219be7df63b314478a2 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 29 Sep 2010 16:01:08 +0100 Subject: ARM: 6418/1: ux500: rename DB8500 DMA event line macros Change the DMA event line macros to have the name of the SoC. Also, have the event line number encoded in the macro since on DB5500 several event lines are present at multiple alternate numbers. Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/mach-ux500/devices-db8500.c | 18 +-- arch/arm/mach-ux500/ste-dma40-db8500.h | 258 ++++++++++++++++----------------- 2 files changed, 133 insertions(+), 143 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index f2e01a6dafe7..40032fecbc16 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -246,23 +246,23 @@ struct stedma40_chan_cfg dma40_memcpy_conf_log = { * Mapping between destination event lines and physical device address. * The event line is tied to a device and therefor the address is constant. */ -static const dma_addr_t dma40_tx_map[STEDMA40_NR_DEV]; +static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV]; /* Mapping between source event lines and physical device address */ -static const dma_addr_t dma40_rx_map[STEDMA40_NR_DEV]; +static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV]; /* Reserved event lines for memcpy only */ static int dma40_memcpy_event[] = { - STEDMA40_MEMCPY_TX_0, - STEDMA40_MEMCPY_TX_1, - STEDMA40_MEMCPY_TX_2, - STEDMA40_MEMCPY_TX_3, - STEDMA40_MEMCPY_TX_4, - STEDMA40_MEMCPY_TX_5, + DB8500_DMA_MEMCPY_TX_0, + DB8500_DMA_MEMCPY_TX_1, + DB8500_DMA_MEMCPY_TX_2, + DB8500_DMA_MEMCPY_TX_3, + DB8500_DMA_MEMCPY_TX_4, + DB8500_DMA_MEMCPY_TX_5, }; static struct stedma40_platform_data dma40_plat_data = { - .dev_len = STEDMA40_NR_DEV, + .dev_len = DB8500_DMA_NR_DEV, .dev_rx = dma40_rx_map, .dev_tx = dma40_tx_map, .memcpy = dma40_memcpy_event, diff --git a/arch/arm/mach-ux500/ste-dma40-db8500.h b/arch/arm/mach-ux500/ste-dma40-db8500.h index 9d9d3797b3b0..a616419bea76 100644 --- a/arch/arm/mach-ux500/ste-dma40-db8500.h +++ b/arch/arm/mach-ux500/ste-dma40-db8500.h @@ -10,145 +10,135 @@ #ifndef STE_DMA40_DB8500_H #define STE_DMA40_DB8500_H -#define STEDMA40_NR_DEV 64 +#define DB8500_DMA_NR_DEV 64 enum dma_src_dev_type { - STEDMA40_DEV_SPI0_RX = 0, - STEDMA40_DEV_SD_MMC0_RX = 1, - STEDMA40_DEV_SD_MMC1_RX = 2, - STEDMA40_DEV_SD_MMC2_RX = 3, - STEDMA40_DEV_I2C1_RX = 4, - STEDMA40_DEV_I2C3_RX = 5, - STEDMA40_DEV_I2C2_RX = 6, - STEDMA40_DEV_I2C4_RX = 7, /* Only on V1 */ - STEDMA40_DEV_SSP0_RX = 8, - STEDMA40_DEV_SSP1_RX = 9, - STEDMA40_DEV_MCDE_RX = 10, - STEDMA40_DEV_UART2_RX = 11, - STEDMA40_DEV_UART1_RX = 12, - STEDMA40_DEV_UART0_RX = 13, - STEDMA40_DEV_MSP2_RX = 14, - STEDMA40_DEV_I2C0_RX = 15, - STEDMA40_DEV_USB_OTG_IEP_8 = 16, - STEDMA40_DEV_USB_OTG_IEP_1_9 = 17, - STEDMA40_DEV_USB_OTG_IEP_2_10 = 18, - STEDMA40_DEV_USB_OTG_IEP_3_11 = 19, - STEDMA40_DEV_SLIM0_CH0_RX_HSI_RX_CH0 = 20, - STEDMA40_DEV_SLIM0_CH1_RX_HSI_RX_CH1 = 21, - STEDMA40_DEV_SLIM0_CH2_RX_HSI_RX_CH2 = 22, - STEDMA40_DEV_SLIM0_CH3_RX_HSI_RX_CH3 = 23, - STEDMA40_DEV_SRC_SXA0_RX_TX = 24, - STEDMA40_DEV_SRC_SXA1_RX_TX = 25, - STEDMA40_DEV_SRC_SXA2_RX_TX = 26, - STEDMA40_DEV_SRC_SXA3_RX_TX = 27, - STEDMA40_DEV_SD_MM2_RX = 28, - STEDMA40_DEV_SD_MM0_RX = 29, - STEDMA40_DEV_MSP1_RX = 30, - /* - * This channel is either SlimBus or MSP, - * never both at the same time. - */ - STEDMA40_SLIM0_CH0_RX = 31, - STEDMA40_DEV_MSP0_RX = 31, - STEDMA40_DEV_SD_MM1_RX = 32, - STEDMA40_DEV_SPI2_RX = 33, - STEDMA40_DEV_I2C3_RX2 = 34, - STEDMA40_DEV_SPI1_RX = 35, - STEDMA40_DEV_USB_OTG_IEP_4_12 = 36, - STEDMA40_DEV_USB_OTG_IEP_5_13 = 37, - STEDMA40_DEV_USB_OTG_IEP_6_14 = 38, - STEDMA40_DEV_USB_OTG_IEP_7_15 = 39, - STEDMA40_DEV_SPI3_RX = 40, - STEDMA40_DEV_SD_MM3_RX = 41, - STEDMA40_DEV_SD_MM4_RX = 42, - STEDMA40_DEV_SD_MM5_RX = 43, - STEDMA40_DEV_SRC_SXA4_RX_TX = 44, - STEDMA40_DEV_SRC_SXA5_RX_TX = 45, - STEDMA40_DEV_SRC_SXA6_RX_TX = 46, - STEDMA40_DEV_SRC_SXA7_RX_TX = 47, - STEDMA40_DEV_CAC1_RX = 48, - /* RX channels 49 and 50 are unused */ - STEDMA40_DEV_MSHC_RX = 51, - STEDMA40_DEV_SLIM1_CH0_RX_HSI_RX_CH4 = 52, - STEDMA40_DEV_SLIM1_CH1_RX_HSI_RX_CH5 = 53, - STEDMA40_DEV_SLIM1_CH2_RX_HSI_RX_CH6 = 54, - STEDMA40_DEV_SLIM1_CH3_RX_HSI_RX_CH7 = 55, - /* RX channels 56 thru 60 are unused */ - STEDMA40_DEV_CAC0_RX = 61, - /* RX channels 62 and 63 are unused */ + DB8500_DMA_DEV0_SPI0_RX = 0, + DB8500_DMA_DEV1_SD_MMC0_RX = 1, + DB8500_DMA_DEV2_SD_MMC1_RX = 2, + DB8500_DMA_DEV3_SD_MMC2_RX = 3, + DB8500_DMA_DEV4_I2C1_RX = 4, + DB8500_DMA_DEV5_I2C3_RX = 5, + DB8500_DMA_DEV6_I2C2_RX = 6, + DB8500_DMA_DEV7_I2C4_RX = 7, /* Only on V1 and later */ + DB8500_DMA_DEV8_SSP0_RX = 8, + DB8500_DMA_DEV9_SSP1_RX = 9, + DB8500_DMA_DEV10_MCDE_RX = 10, + DB8500_DMA_DEV11_UART2_RX = 11, + DB8500_DMA_DEV12_UART1_RX = 12, + DB8500_DMA_DEV13_UART0_RX = 13, + DB8500_DMA_DEV14_MSP2_RX = 14, + DB8500_DMA_DEV15_I2C0_RX = 15, + DB8500_DMA_DEV16_USB_OTG_IEP_7_15 = 16, + DB8500_DMA_DEV17_USB_OTG_IEP_6_14 = 17, + DB8500_DMA_DEV18_USB_OTG_IEP_5_13 = 18, + DB8500_DMA_DEV19_USB_OTG_IEP_4_12 = 19, + DB8500_DMA_DEV20_SLIM0_CH0_RX_HSI_RX_CH0 = 20, + DB8500_DMA_DEV21_SLIM0_CH1_RX_HSI_RX_CH1 = 21, + DB8500_DMA_DEV22_SLIM0_CH2_RX_HSI_RX_CH2 = 22, + DB8500_DMA_DEV23_SLIM0_CH3_RX_HSI_RX_CH3 = 23, + DB8500_DMA_DEV24_SRC_SXA0_RX_TX = 24, + DB8500_DMA_DEV25_SRC_SXA1_RX_TX = 25, + DB8500_DMA_DEV26_SRC_SXA2_RX_TX = 26, + DB8500_DMA_DEV27_SRC_SXA3_RX_TX = 27, + DB8500_DMA_DEV28_SD_MM2_RX = 28, + DB8500_DMA_DEV29_SD_MM0_RX = 29, + DB8500_DMA_DEV30_MSP1_RX = 30, + /* On DB8500v2, MSP3 RX replaces MSP1 RX */ + DB8500_DMA_DEV30_MSP3_RX = 30, + DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX = 31, + DB8500_DMA_DEV32_SD_MM1_RX = 32, + DB8500_DMA_DEV33_SPI2_RX = 33, + DB8500_DMA_DEV34_I2C3_RX2 = 34, + DB8500_DMA_DEV35_SPI1_RX = 35, + DB8500_DMA_DEV36_USB_OTG_IEP_3_11 = 36, + DB8500_DMA_DEV37_USB_OTG_IEP_2_10 = 37, + DB8500_DMA_DEV38_USB_OTG_IEP_1_9 = 38, + DB8500_DMA_DEV39_USB_OTG_IEP_8 = 39, + DB8500_DMA_DEV40_SPI3_RX = 40, + DB8500_DMA_DEV41_SD_MM3_RX = 41, + DB8500_DMA_DEV42_SD_MM4_RX = 42, + DB8500_DMA_DEV43_SD_MM5_RX = 43, + DB8500_DMA_DEV44_SRC_SXA4_RX_TX = 44, + DB8500_DMA_DEV45_SRC_SXA5_RX_TX = 45, + DB8500_DMA_DEV46_SLIM0_CH8_RX_SRC_SXA6_RX_TX = 46, + DB8500_DMA_DEV47_SLIM0_CH9_RX_SRC_SXA7_RX_TX = 47, + DB8500_DMA_DEV48_CAC1_RX = 48, + /* 49, 50 and 51 are not used */ + DB8500_DMA_DEV52_SLIM0_CH4_RX_HSI_RX_CH4 = 52, + DB8500_DMA_DEV53_SLIM0_CH5_RX_HSI_RX_CH5 = 53, + DB8500_DMA_DEV54_SLIM0_CH6_RX_HSI_RX_CH6 = 54, + DB8500_DMA_DEV55_SLIM0_CH7_RX_HSI_RX_CH7 = 55, + /* 56, 57, 58, 59 and 60 are not used */ + DB8500_DMA_DEV61_CAC0_RX = 61, + /* 62 and 63 are not used */ }; enum dma_dest_dev_type { - STEDMA40_DEV_SPI0_TX = 0, - STEDMA40_DEV_SD_MMC0_TX = 1, - STEDMA40_DEV_SD_MMC1_TX = 2, - STEDMA40_DEV_SD_MMC2_TX = 3, - STEDMA40_DEV_I2C1_TX = 4, - STEDMA40_DEV_I2C3_TX = 5, - STEDMA40_DEV_I2C2_TX = 6, - STEDMA50_DEV_I2C4_TX = 7, /* Only on V1 */ - STEDMA40_DEV_SSP0_TX = 8, - STEDMA40_DEV_SSP1_TX = 9, - /* TX channel 10 is unused */ - STEDMA40_DEV_UART2_TX = 11, - STEDMA40_DEV_UART1_TX = 12, - STEDMA40_DEV_UART0_TX= 13, - STEDMA40_DEV_MSP2_TX = 14, - STEDMA40_DEV_I2C0_TX = 15, - STEDMA40_DEV_USB_OTG_OEP_8 = 16, - STEDMA40_DEV_USB_OTG_OEP_1_9 = 17, - STEDMA40_DEV_USB_OTG_OEP_2_10= 18, - STEDMA40_DEV_USB_OTG_OEP_3_11 = 19, - STEDMA40_DEV_SLIM0_CH0_TX_HSI_TX_CH0 = 20, - STEDMA40_DEV_SLIM0_CH1_TX_HSI_TX_CH1 = 21, - STEDMA40_DEV_SLIM0_CH2_TX_HSI_TX_CH2 = 22, - STEDMA40_DEV_SLIM0_CH3_TX_HSI_TX_CH3 = 23, - STEDMA40_DEV_DST_SXA0_RX_TX = 24, - STEDMA40_DEV_DST_SXA1_RX_TX = 25, - STEDMA40_DEV_DST_SXA2_RX_TX = 26, - STEDMA40_DEV_DST_SXA3_RX_TX = 27, - STEDMA40_DEV_SD_MM2_TX = 28, - STEDMA40_DEV_SD_MM0_TX = 29, - STEDMA40_DEV_MSP1_TX = 30, - /* - * This channel is either SlimBus or MSP, - * never both at the same time. - */ - STEDMA40_SLIM0_CH0_TX = 31, - STEDMA40_DEV_MSP0_TX = 31, - STEDMA40_DEV_SD_MM1_TX = 32, - STEDMA40_DEV_SPI2_TX = 33, - /* Secondary I2C3 channel */ - STEDMA40_DEV_I2C3_TX2 = 34, - STEDMA40_DEV_SPI1_TX = 35, - STEDMA40_DEV_USB_OTG_OEP_4_12 = 36, - STEDMA40_DEV_USB_OTG_OEP_5_13 = 37, - STEDMA40_DEV_USB_OTG_OEP_6_14 = 38, - STEDMA40_DEV_USB_OTG_OEP_7_15 = 39, - STEDMA40_DEV_SPI3_TX = 40, - STEDMA40_DEV_SD_MM3_TX = 41, - STEDMA40_DEV_SD_MM4_TX = 42, - STEDMA40_DEV_SD_MM5_TX = 43, - STEDMA40_DEV_DST_SXA4_RX_TX = 44, - STEDMA40_DEV_DST_SXA5_RX_TX = 45, - STEDMA40_DEV_DST_SXA6_RX_TX = 46, - STEDMA40_DEV_DST_SXA7_RX_TX = 47, - STEDMA40_DEV_CAC1_TX = 48, - STEDMA40_DEV_CAC1_TX_HAC1_TX = 49, - STEDMA40_DEV_HAC1_TX = 50, - STEDMA40_MEMCPY_TX_0 = 51, - STEDMA40_DEV_SLIM1_CH0_TX_HSI_TX_CH4 = 52, - STEDMA40_DEV_SLIM1_CH1_TX_HSI_TX_CH5 = 53, - STEDMA40_DEV_SLIM1_CH2_TX_HSI_TX_CH6 = 54, - STEDMA40_DEV_SLIM1_CH3_TX_HSI_TX_CH7 = 55, - STEDMA40_MEMCPY_TX_1 = 56, - STEDMA40_MEMCPY_TX_2 = 57, - STEDMA40_MEMCPY_TX_3 = 58, - STEDMA40_MEMCPY_TX_4 = 59, - STEDMA40_MEMCPY_TX_5 = 60, - STEDMA40_DEV_CAC0_TX = 61, - STEDMA40_DEV_CAC0_TX_HAC0_TX = 62, - STEDMA40_DEV_HAC0_TX = 63, + DB8500_DMA_DEV0_SPI0_TX = 0, + DB8500_DMA_DEV1_SD_MMC0_TX = 1, + DB8500_DMA_DEV2_SD_MMC1_TX = 2, + DB8500_DMA_DEV3_SD_MMC2_TX = 3, + DB8500_DMA_DEV4_I2C1_TX = 4, + DB8500_DMA_DEV5_I2C3_TX = 5, + DB8500_DMA_DEV6_I2C2_TX = 6, + DB8500_DMA_DEV7_I2C4_TX = 7, /* Only on V1 and later */ + DB8500_DMA_DEV8_SSP0_TX = 8, + DB8500_DMA_DEV9_SSP1_TX = 9, + /* 10 is not used*/ + DB8500_DMA_DEV11_UART2_TX = 11, + DB8500_DMA_DEV12_UART1_TX = 12, + DB8500_DMA_DEV13_UART0_TX = 13, + DB8500_DMA_DEV14_MSP2_TX = 14, + DB8500_DMA_DEV15_I2C0_TX = 15, + DB8500_DMA_DEV16_USB_OTG_OEP_7_15 = 16, + DB8500_DMA_DEV17_USB_OTG_OEP_6_14 = 17, + DB8500_DMA_DEV18_USB_OTG_OEP_5_13 = 18, + DB8500_DMA_DEV19_USB_OTG_OEP_4_12 = 19, + DB8500_DMA_DEV20_SLIM0_CH0_TX_HSI_TX_CH0 = 20, + DB8500_DMA_DEV21_SLIM0_CH1_TX_HSI_TX_CH1 = 21, + DB8500_DMA_DEV22_SLIM0_CH2_TX_HSI_TX_CH2 = 22, + DB8500_DMA_DEV23_SLIM0_CH3_TX_HSI_TX_CH3 = 23, + DB8500_DMA_DEV24_DST_SXA0_RX_TX = 24, + DB8500_DMA_DEV25_DST_SXA1_RX_TX = 25, + DB8500_DMA_DEV26_DST_SXA2_RX_TX = 26, + DB8500_DMA_DEV27_DST_SXA3_RX_TX = 27, + DB8500_DMA_DEV28_SD_MM2_TX = 28, + DB8500_DMA_DEV29_SD_MM0_TX = 29, + DB8500_DMA_DEV30_MSP1_TX = 30, + DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX = 31, + DB8500_DMA_DEV32_SD_MM1_TX = 32, + DB8500_DMA_DEV33_SPI2_TX = 33, + DB8500_DMA_DEV34_I2C3_TX2 = 34, + DB8500_DMA_DEV35_SPI1_TX = 35, + DB8500_DMA_DEV36_USB_OTG_OEP_3_11 = 36, + DB8500_DMA_DEV37_USB_OTG_OEP_2_10 = 37, + DB8500_DMA_DEV38_USB_OTG_OEP_1_9 = 38, + DB8500_DMA_DEV39_USB_OTG_OEP_8 = 39, + DB8500_DMA_DEV40_SPI3_TX = 40, + DB8500_DMA_DEV41_SD_MM3_TX = 41, + DB8500_DMA_DEV42_SD_MM4_TX = 42, + DB8500_DMA_DEV43_SD_MM5_TX = 43, + DB8500_DMA_DEV44_DST_SXA4_RX_TX = 44, + DB8500_DMA_DEV45_DST_SXA5_RX_TX = 45, + DB8500_DMA_DEV46_SLIM0_CH8_TX_DST_SXA6_RX_TX = 46, + DB8500_DMA_DEV47_SLIM0_CH9_TX_DST_SXA7_RX_TX = 47, + DB8500_DMA_DEV48_CAC1_TX = 48, + DB8500_DMA_DEV49_CAC1_TX_HAC1_TX = 49, + DB8500_DMA_DEV50_HAC1_TX = 50, + DB8500_DMA_MEMCPY_TX_0 = 51, + DB8500_DMA_DEV52_SLIM1_CH4_TX_HSI_TX_CH4 = 52, + DB8500_DMA_DEV53_SLIM1_CH5_TX_HSI_TX_CH5 = 53, + DB8500_DMA_DEV54_SLIM1_CH6_TX_HSI_TX_CH6 = 54, + DB8500_DMA_DEV55_SLIM1_CH7_TX_HSI_TX_CH7 = 55, + DB8500_DMA_MEMCPY_TX_1 = 56, + DB8500_DMA_MEMCPY_TX_2 = 57, + DB8500_DMA_MEMCPY_TX_3 = 58, + DB8500_DMA_MEMCPY_TX_4 = 59, + DB8500_DMA_MEMCPY_TX_5 = 60, + DB8500_DMA_DEV61_CAC0_TX = 61, + DB8500_DMA_DEV62_CAC0_TX_HAC0_TX = 62, + DB8500_DMA_DEV63_HAC0_TX = 63, }; #endif -- cgit v1.2.2 From 8234eaef8002cb8ba30920949b338d692508137a Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Wed, 4 Aug 2010 11:22:43 +0100 Subject: ARM: 6291/1: coresight: move struct tracectx inside etm driver This is done so as to be able to make use of the coresight components' registers in assembler code (like omap sleep code). Also, there shouldn't be any users of this structure outside the etm driver. Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Alexander Shishkin Signed-off-by: Russell King --- arch/arm/include/asm/hardware/coresight.h | 12 ------------ arch/arm/kernel/etm.c | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h index 212e47828c79..d84605175fc4 100644 --- a/arch/arm/include/asm/hardware/coresight.h +++ b/arch/arm/include/asm/hardware/coresight.h @@ -21,18 +21,6 @@ #define TRACER_RUNNING BIT(TRACER_RUNNING_BIT) #define TRACER_CYCLE_ACC BIT(TRACER_CYCLE_ACC_BIT) -struct tracectx { - unsigned int etb_bufsz; - void __iomem *etb_regs; - void __iomem *etm_regs; - unsigned long flags; - int ncmppairs; - int etm_portsz; - struct device *dev; - struct clk *emu_clk; - struct mutex mutex; -}; - #define TRACER_TIMEOUT 10000 #define etm_writel(t, v, x) \ diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c index 33c7077174db..a48d51257988 100644 --- a/arch/arm/kernel/etm.c +++ b/arch/arm/kernel/etm.c @@ -30,6 +30,21 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Alexander Shishkin"); +/* + * ETM tracer state + */ +struct tracectx { + unsigned int etb_bufsz; + void __iomem *etb_regs; + void __iomem *etm_regs; + unsigned long flags; + int ncmppairs; + int etm_portsz; + struct device *dev; + struct clk *emu_clk; + struct mutex mutex; +}; + static struct tracectx tracer; static inline bool trace_isrunning(struct tracectx *t) -- cgit v1.2.2 From 9f5336915bc47947230290a1a384de95803f815a Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Wed, 4 Aug 2010 11:26:27 +0100 Subject: ARM: 6293/1: coresight: cosmetic fixes Use BIT() macro whenever it is sensible to do so. Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Alexander Shishkin Signed-off-by: Russell King --- arch/arm/include/asm/hardware/coresight.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h index d84605175fc4..7ecd793b8f5a 100644 --- a/arch/arm/include/asm/hardware/coresight.h +++ b/arch/arm/include/asm/hardware/coresight.h @@ -100,10 +100,10 @@ /* ETM status register, "ETM Architecture", 3.3.2 */ #define ETMR_STATUS (0x10) -#define ETMST_OVERFLOW (1 << 0) -#define ETMST_PROGBIT (1 << 1) -#define ETMST_STARTSTOP (1 << 2) -#define ETMST_TRIGGER (1 << 3) +#define ETMST_OVERFLOW BIT(0) +#define ETMST_PROGBIT BIT(1) +#define ETMST_STARTSTOP BIT(2) +#define ETMST_TRIGGER BIT(3) #define etm_progbit(t) (etm_readl((t), ETMR_STATUS) & ETMST_PROGBIT) #define etm_started(t) (etm_readl((t), ETMR_STATUS) & ETMST_STARTSTOP) @@ -111,7 +111,7 @@ #define ETMR_TRACEENCTRL2 0x1c #define ETMR_TRACEENCTRL 0x24 -#define ETMTE_INCLEXCL (1 << 24) +#define ETMTE_INCLEXCL BIT(24) #define ETMR_TRACEENEVT 0x20 #define ETMCTRL_OPTS (ETMCTRL_DO_CPRT | \ ETMCTRL_DATA_DO_ADDR | \ @@ -134,12 +134,12 @@ #define ETBR_CTRL 0x20 #define ETBR_FORMATTERCTRL 0x304 #define ETBFF_ENFTC 1 -#define ETBFF_ENFCONT (1 << 1) -#define ETBFF_FONFLIN (1 << 4) -#define ETBFF_MANUAL_FLUSH (1 << 6) -#define ETBFF_TRIGIN (1 << 8) -#define ETBFF_TRIGEVT (1 << 9) -#define ETBFF_TRIGFL (1 << 10) +#define ETBFF_ENFCONT BIT(1) +#define ETBFF_FONFLIN BIT(4) +#define ETBFF_MANUAL_FLUSH BIT(6) +#define ETBFF_TRIGIN BIT(8) +#define ETBFF_TRIGEVT BIT(9) +#define ETBFF_TRIGFL BIT(10) #define etb_writel(t, v, x) \ (__raw_writel((v), (t)->etb_regs + (x))) -- cgit v1.2.2 From 055d1965161bde96207371e7d31eb776c0f7790d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 2 Sep 2010 09:14:21 +0100 Subject: ARM: 6349/1: sa1111: move __sa1111_probe() to .devinit.text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit __sa1111_probe is only called by sa1111_probe that lives in .devinit.text. So it's save to move the former to .devinit.text, too. Acked-by: Kristoffer Ericson Signed-off-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/common/sa1111.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 517d50ddbeb3..c0258a8c103b 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -678,7 +678,7 @@ out: * %-EBUSY physical address already marked in-use. * %0 successful. */ -static int +static int __devinit __sa1111_probe(struct device *me, struct resource *mem, int irq) { struct sa1111 *sachip; -- cgit v1.2.2 From 971acb9b420ea1662dd3c48184c4315f87643be5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 4 Sep 2010 08:16:30 +0100 Subject: ARM: Simplify SMP/SCU/TWD dependencies All platforms which currently support SMP also support the ARM SCU and ARM TWD blocks, so it's pointless to make these config symbols conditional on the platform symbols which SMP is already conditional on. Signed-off-by: Russell King --- arch/arm/Kconfig | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 88c97bc7a6f5..6a939e64cbd7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1167,13 +1167,13 @@ source "kernel/time/Kconfig" config SMP bool "Symmetric Multi-Processing (EXPERIMENTAL)" - depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\ - MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\ - ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4) + depends on EXPERIMENTAL depends on GENERIC_CLOCKEVENTS + depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \ + MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\ + ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 select USE_GENERIC_SMP_HELPERS - select HAVE_ARM_SCU if ARCH_REALVIEW || ARCH_OMAP4 || ARCH_S5PV310 ||\ - ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 + select HAVE_ARM_SCU help This enables support for systems with more than one CPU. If you have a system with only one CPU, like most personal computers, say N. If @@ -1241,12 +1241,9 @@ config HOTPLUG_CPU config LOCAL_TIMERS bool "Use local timer interrupts" - depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \ - REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \ - ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4) + depends on SMP default y - select HAVE_ARM_TWD if ARCH_REALVIEW || ARCH_OMAP4 || ARCH_S5PV310 || \ - ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS + select HAVE_ARM_TWD help Enable support for local timers on SMP platforms, rather then the legacy IPI broadcast method. Local timers allows the system -- cgit v1.2.2 From 067173526c3bbc2eaeefcf6b7b2a9d998b9e8042 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 4 Sep 2010 16:14:20 +0100 Subject: ARM: Provide common header for hard_smp_processor_id() Provide a common header to read the SMP CPU number from the MPIDR. Signed-off-by: Russell King --- arch/arm/include/asm/smp_mpidr.h | 12 ++++++++++++ arch/arm/mach-realview/include/mach/smp.h | 10 +--------- arch/arm/mach-s5pv310/include/mach/smp.h | 9 +-------- arch/arm/mach-tegra/include/mach/smp.h | 10 +--------- arch/arm/mach-ux500/include/mach/smp.h | 9 +-------- arch/arm/mach-vexpress/include/mach/smp.h | 9 +-------- arch/arm/plat-omap/include/plat/smp.h | 12 +----------- 7 files changed, 18 insertions(+), 53 deletions(-) create mode 100644 arch/arm/include/asm/smp_mpidr.h (limited to 'arch') diff --git a/arch/arm/include/asm/smp_mpidr.h b/arch/arm/include/asm/smp_mpidr.h new file mode 100644 index 000000000000..7da7105e83e5 --- /dev/null +++ b/arch/arm/include/asm/smp_mpidr.h @@ -0,0 +1,12 @@ +#ifndef ASMARM_SMP_MIDR_H +#define ASMARM_SMP_MIDR_H + +#define hard_smp_processor_id() \ + ({ \ + unsigned int cpunum; \ + __asm__("mrc p15, 0, %0, c0, c0, 5\n" \ + : "=r" (cpunum)); \ + cpunum &= 0x0F; \ + }) + +#endif diff --git a/arch/arm/mach-realview/include/mach/smp.h b/arch/arm/mach-realview/include/mach/smp.h index dd53892d44a7..d3cd265cb058 100644 --- a/arch/arm/mach-realview/include/mach/smp.h +++ b/arch/arm/mach-realview/include/mach/smp.h @@ -1,16 +1,8 @@ #ifndef ASMARM_ARCH_SMP_H #define ASMARM_ARCH_SMP_H - #include - -#define hard_smp_processor_id() \ - ({ \ - unsigned int cpunum; \ - __asm__("mrc p15, 0, %0, c0, c0, 5" \ - : "=r" (cpunum)); \ - cpunum &= 0x0F; \ - }) +#include /* * We use IRQ1 as the IPI diff --git a/arch/arm/mach-s5pv310/include/mach/smp.h b/arch/arm/mach-s5pv310/include/mach/smp.h index 990f3ba88a1f..b7ec252384f4 100644 --- a/arch/arm/mach-s5pv310/include/mach/smp.h +++ b/arch/arm/mach-s5pv310/include/mach/smp.h @@ -7,17 +7,10 @@ #define ASM_ARCH_SMP_H __FILE__ #include +#include extern void __iomem *gic_cpu_base_addr; -#define hard_smp_processor_id() \ - ({ \ - unsigned int cpunum; \ - __asm__("mrc p15, 0, %0, c0, c0, 5" \ - : "=r" (cpunum)); \ - cpunum &= 0x03; \ - }) - /* * We use IRQ1 as the IPI */ diff --git a/arch/arm/mach-tegra/include/mach/smp.h b/arch/arm/mach-tegra/include/mach/smp.h index 8b42dab79a70..e4a34a35a544 100644 --- a/arch/arm/mach-tegra/include/mach/smp.h +++ b/arch/arm/mach-tegra/include/mach/smp.h @@ -1,16 +1,8 @@ #ifndef ASMARM_ARCH_SMP_H #define ASMARM_ARCH_SMP_H - #include - -#define hard_smp_processor_id() \ - ({ \ - unsigned int cpunum; \ - __asm__("mrc p15, 0, %0, c0, c0, 5" \ - : "=r" (cpunum)); \ - cpunum &= 0x0F; \ - }) +#include /* * We use IRQ1 as the IPI diff --git a/arch/arm/mach-ux500/include/mach/smp.h b/arch/arm/mach-ux500/include/mach/smp.h index b59f7bc9725d..197e8417375e 100644 --- a/arch/arm/mach-ux500/include/mach/smp.h +++ b/arch/arm/mach-ux500/include/mach/smp.h @@ -10,18 +10,11 @@ #define ASMARM_ARCH_SMP_H #include +#include /* This is required to wakeup the secondary core */ extern void u8500_secondary_startup(void); -#define hard_smp_processor_id() \ - ({ \ - unsigned int cpunum; \ - __asm__("mrc p15, 0, %0, c0, c0, 5" \ - : "=r" (cpunum)); \ - cpunum &= 0x0F; \ - }) - /* * We use IRQ1 as the IPI */ diff --git a/arch/arm/mach-vexpress/include/mach/smp.h b/arch/arm/mach-vexpress/include/mach/smp.h index 72a9621ed087..5a6da4fd247e 100644 --- a/arch/arm/mach-vexpress/include/mach/smp.h +++ b/arch/arm/mach-vexpress/include/mach/smp.h @@ -2,14 +2,7 @@ #define __MACH_SMP_H #include - -#define hard_smp_processor_id() \ - ({ \ - unsigned int cpunum; \ - __asm__("mrc p15, 0, %0, c0, c0, 5" \ - : "=r" (cpunum)); \ - cpunum &= 0x0F; \ - }) +#include /* * We use IRQ1 as the IPI diff --git a/arch/arm/plat-omap/include/plat/smp.h b/arch/arm/plat-omap/include/plat/smp.h index 5177a9c5a25a..ecd6a488c497 100644 --- a/arch/arm/plat-omap/include/plat/smp.h +++ b/arch/arm/plat-omap/include/plat/smp.h @@ -18,6 +18,7 @@ #define OMAP_ARCH_SMP_H #include +#include /* Needed for secondary core boot */ extern void omap_secondary_startup(void); @@ -33,15 +34,4 @@ static inline void smp_cross_call(const struct cpumask *mask) gic_raise_softirq(mask, 1); } -/* - * Read MPIDR: Multiprocessor affinity register - */ -#define hard_smp_processor_id() \ - ({ \ - unsigned int cpunum; \ - __asm__("mrc p15, 0, %0, c0, c0, 5" \ - : "=r" (cpunum)); \ - cpunum &= 0x0F; \ - }) - #endif -- cgit v1.2.2 From f00ec48fadf5e37e7889f14cff900aa70d18b644 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 4 Sep 2010 10:47:48 +0100 Subject: ARM: Allow SMP kernels to boot on UP systems UP systems do not implement all the instructions that SMP systems have, so in order to boot a SMP kernel on a UP system, we need to rewrite parts of the kernel. Do this using an 'alternatives' scheme, where the kernel code and data is modified prior to initialization to replace the SMP instructions, thereby rendering the problematical code ineffectual. We use the linker to generate a list of 32-bit word locations and their replacement values, and run through these replacements when we detect a UP system. Signed-off-by: Russell King --- arch/arm/Kconfig | 13 +++++++++++ arch/arm/include/asm/assembler.h | 27 ++++++++++++++++++++-- arch/arm/include/asm/smp_mpidr.h | 7 +++++- arch/arm/include/asm/smp_plat.h | 15 ++++++++++++ arch/arm/include/asm/tlbflush.h | 24 +++++++++++++------ arch/arm/kernel/entry-armv.S | 11 ++++----- arch/arm/kernel/head.S | 50 ++++++++++++++++++++++++++++++++++++++++ arch/arm/kernel/setup.c | 4 +++- arch/arm/kernel/vmlinux.lds.S | 11 +++++++++ arch/arm/mm/cache-v7.S | 14 ++++------- arch/arm/mm/mmu.c | 46 +++++++++++++++++------------------- arch/arm/mm/proc-v6.S | 43 ++++++++++++++++++++++------------ arch/arm/mm/proc-v7.S | 41 +++++++++++++++++++++----------- arch/arm/mm/tlb-v7.S | 33 ++++++++++---------------- 14 files changed, 237 insertions(+), 102 deletions(-) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 6a939e64cbd7..f6cdc21b562c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1191,6 +1191,19 @@ config SMP If you don't know what to do here, say N. +config SMP_ON_UP + bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)" + depends on EXPERIMENTAL + depends on SMP && !XIP && !THUMB2_KERNEL + default y + help + SMP kernels contain instructions which fail on non-SMP processors. + Enabling this option allows the kernel to modify itself to make + these instructions safe. Disabling it allows about 1K of space + savings. + + If you don't know what to do here, say Y. + config HAVE_ARM_SCU bool depends on SMP diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 6e8f05c8a1c8..062b58c029ab 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -154,16 +154,39 @@ .long 9999b,9001f; \ .popsection +#ifdef CONFIG_SMP +#define ALT_SMP(instr...) \ +9998: instr +#define ALT_UP(instr...) \ + .pushsection ".alt.smp.init", "a" ;\ + .long 9998b ;\ + instr ;\ + .popsection +#define ALT_UP_B(label) \ + .equ up_b_offset, label - 9998b ;\ + .pushsection ".alt.smp.init", "a" ;\ + .long 9998b ;\ + b . + up_b_offset ;\ + .popsection +#else +#define ALT_SMP(instr...) +#define ALT_UP(instr...) instr +#define ALT_UP_B(label) b label +#endif + /* * SMP data memory barrier */ .macro smp_dmb #ifdef CONFIG_SMP #if __LINUX_ARM_ARCH__ >= 7 - dmb + ALT_SMP(dmb) #elif __LINUX_ARM_ARCH__ == 6 - mcr p15, 0, r0, c7, c10, 5 @ dmb + ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb +#else +#error Incompatible SMP platform #endif + ALT_UP(nop) #endif .endm diff --git a/arch/arm/include/asm/smp_mpidr.h b/arch/arm/include/asm/smp_mpidr.h index 7da7105e83e5..6a9307d64900 100644 --- a/arch/arm/include/asm/smp_mpidr.h +++ b/arch/arm/include/asm/smp_mpidr.h @@ -4,7 +4,12 @@ #define hard_smp_processor_id() \ ({ \ unsigned int cpunum; \ - __asm__("mrc p15, 0, %0, c0, c0, 5\n" \ + __asm__("\n" \ + "1: mrc p15, 0, %0, c0, c0, 5\n" \ + " .pushsection \".alt.smp.init\", \"a\"\n"\ + " .long 1b\n" \ + " mov %0, #0\n" \ + " .popsection" \ : "=r" (cpunum)); \ cpunum &= 0x0F; \ }) diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h index e6215305544a..7de5aa56c18b 100644 --- a/arch/arm/include/asm/smp_plat.h +++ b/arch/arm/include/asm/smp_plat.h @@ -18,4 +18,19 @@ static inline int cache_ops_need_broadcast(void) return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1; } +/* + * Return true if we are running on a SMP platform + */ +static inline bool is_smp(void) +{ +#ifndef CONFIG_SMP + return false; +#elif defined(CONFIG_SMP_ON_UP) + extern unsigned int smp_on_up; + return !!smp_on_up; +#else + return true; +#endif +} + #endif diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h index 33b546ae72d4..cf2f018492e0 100644 --- a/arch/arm/include/asm/tlbflush.h +++ b/arch/arm/include/asm/tlbflush.h @@ -70,6 +70,10 @@ #undef _TLB #undef MULTI_TLB +#ifdef CONFIG_SMP_ON_UP +#define MULTI_TLB 1 +#endif + #define v3_tlb_flags (TLB_V3_FULL | TLB_V3_PAGE) #ifdef CONFIG_CPU_TLB_V3 @@ -185,17 +189,23 @@ # define v6wbi_always_flags (-1UL) #endif -#ifdef CONFIG_SMP -#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \ +#define v7wbi_tlb_flags_smp (TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \ TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID) -#else -#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \ +#define v7wbi_tlb_flags_up (TLB_WB | TLB_DCLEAN | TLB_BTB | \ TLB_V6_U_FULL | TLB_V6_U_PAGE | TLB_V6_U_ASID) -#endif #ifdef CONFIG_CPU_TLB_V7 -# define v7wbi_possible_flags v7wbi_tlb_flags -# define v7wbi_always_flags v7wbi_tlb_flags + +# ifdef CONFIG_SMP_ON_UP +# define v7wbi_possible_flags (v7wbi_tlb_flags_smp | v7wbi_tlb_flags_up) +# define v7wbi_always_flags (v7wbi_tlb_flags_smp & v7wbi_tlb_flags_up) +# elif defined(CONFIG_SMP) +# define v7wbi_possible_flags v7wbi_tlb_flags_smp +# define v7wbi_always_flags v7wbi_tlb_flags_smp +# else +# define v7wbi_possible_flags v7wbi_tlb_flags_up +# define v7wbi_always_flags v7wbi_tlb_flags_up +# endif # ifdef _TLB # define MULTI_TLB 1 # else diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index bb8e93a76407..c09e3573c5de 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -46,7 +46,8 @@ * this macro assumes that irqstat (r6) and base (r5) are * preserved from get_irqnr_and_base above */ - test_for_ipi r0, r6, r5, lr + ALT_SMP(test_for_ipi r0, r6, r5, lr) + ALT_UP_B(9997f) movne r0, sp adrne lr, BSYM(1b) bne do_IPI @@ -57,6 +58,7 @@ adrne lr, BSYM(1b) bne do_local_timer #endif +9997: #endif .endm @@ -965,11 +967,8 @@ kuser_cmpxchg_fixup: beq 1b rsbs r0, r3, #0 /* beware -- each __kuser slot must be 8 instructions max */ -#ifdef CONFIG_SMP - b __kuser_memory_barrier -#else - usr_ret lr -#endif + ALT_SMP(b __kuser_memory_barrier) + ALT_UP(usr_ret lr) #endif diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index eb62bf947212..b44d21e1e344 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -86,6 +86,9 @@ ENTRY(stext) movs r8, r5 @ invalid machine (r5=0)? beq __error_a @ yes, error 'a' bl __vet_atags +#ifdef CONFIG_SMP_ON_UP + bl __fixup_smp +#endif bl __create_page_tables /* @@ -333,4 +336,51 @@ __create_page_tables: ENDPROC(__create_page_tables) .ltorg +#ifdef CONFIG_SMP_ON_UP +__fixup_smp: + mov r7, #0x00070000 + orr r6, r7, #0xff000000 @ mask 0xff070000 + orr r7, r7, #0x41000000 @ val 0x41070000 + and r0, r9, r6 + teq r0, r7 @ ARM CPU and ARMv6/v7? + bne __fixup_smp_on_up @ no, assume UP + + orr r6, r6, #0x0000ff00 + orr r6, r6, #0x000000f0 @ mask 0xff07fff0 + orr r7, r7, #0x0000b000 + orr r7, r7, #0x00000020 @ val 0x4107b020 + and r0, r9, r6 + teq r0, r7 @ ARM 11MPCore? + moveq pc, lr @ yes, assume SMP + + mrc p15, 0, r0, c0, c0, 5 @ read MPIDR + tst r0, #1 << 31 + movne pc, lr @ bit 31 => SMP + +__fixup_smp_on_up: + adr r0, 1f + ldmia r0, {r3, r6, r7} + sub r3, r0, r3 + add r6, r6, r3 + add r7, r7, r3 +2: cmp r6, r7 + ldmia r6!, {r0, r4} + strlo r4, [r0, r3] + blo 2b + mov pc, lr +ENDPROC(__fixup_smp) + +1: .word . + .word __smpalt_begin + .word __smpalt_end + + .pushsection .data + .globl smp_on_up +smp_on_up: + ALT_SMP(.long 1) + ALT_UP(.long 0) + .popsection + +#endif + #include "head-common.S" diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index d5231ae7355a..5a82c39ca85e 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -825,7 +826,8 @@ void __init setup_arch(char **cmdline_p) request_standard_resources(&meminfo, mdesc); #ifdef CONFIG_SMP - smp_init_cpus(); + if (is_smp()) + smp_init_cpus(); #endif reserve_crashkernel(); diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index b16c07914b55..fd5750b8ac84 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -40,6 +40,11 @@ SECTIONS __tagtable_begin = .; *(.taglist.init) __tagtable_end = .; +#ifdef CONFIG_SMP_ON_UP + __smpalt_begin = .; + *(.alt.smp.init) + __smpalt_end = .; +#endif INIT_SETUP(16) @@ -237,6 +242,12 @@ SECTIONS /* Default discards */ DISCARDS + +#ifndef CONFIG_SMP_ON_UP + /DISCARD/ : { + *(.alt.smp.init) + } +#endif } /* diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index 37c8157e116e..e8ea1a071f43 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -91,11 +91,8 @@ ENTRY(v7_flush_kern_cache_all) THUMB( stmfd sp!, {r4-r7, r9-r11, lr} ) bl v7_flush_dcache_all mov r0, #0 -#ifdef CONFIG_SMP - mcr p15, 0, r0, c7, c1, 0 @ invalidate I-cache inner shareable -#else - mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate -#endif + ALT_SMP(mcr p15, 0, r0, c7, c1, 0) @ invalidate I-cache inner shareable + ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} ) THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} ) mov pc, lr @@ -171,11 +168,8 @@ ENTRY(v7_coherent_user_range) cmp r0, r1 blo 1b mov r0, #0 -#ifdef CONFIG_SMP - mcr p15, 0, r0, c7, c1, 6 @ invalidate BTB Inner Shareable -#else - mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB -#endif + ALT_SMP(mcr p15, 0, r0, c7, c1, 6) @ invalidate BTB Inner Shareable + ALT_UP(mcr p15, 0, r0, c7, c5, 6) @ invalidate BTB dsb isb mov pc, lr diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 6a3a2d0cd6db..e2335811c02e 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -310,9 +310,8 @@ static void __init build_mem_type_table(void) cachepolicy = CPOLICY_WRITEBACK; ecc_mask = 0; } -#ifdef CONFIG_SMP - cachepolicy = CPOLICY_WRITEALLOC; -#endif + if (is_smp()) + cachepolicy = CPOLICY_WRITEALLOC; /* * Strip out features not present on earlier architectures. @@ -406,13 +405,11 @@ static void __init build_mem_type_table(void) cp = &cache_policies[cachepolicy]; vecs_pgprot = kern_pgprot = user_pgprot = cp->pte; -#ifndef CONFIG_SMP /* * Only use write-through for non-SMP systems */ - if (cpu_arch >= CPU_ARCH_ARMv5 && cachepolicy > CPOLICY_WRITETHROUGH) + if (!is_smp() && cpu_arch >= CPU_ARCH_ARMv5 && cachepolicy > CPOLICY_WRITETHROUGH) vecs_pgprot = cache_policies[CPOLICY_WRITETHROUGH].pte; -#endif /* * Enable CPU-specific coherency if supported. @@ -436,22 +433,23 @@ static void __init build_mem_type_table(void) mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; -#ifdef CONFIG_SMP - /* - * Mark memory with the "shared" attribute for SMP systems - */ - user_pgprot |= L_PTE_SHARED; - kern_pgprot |= L_PTE_SHARED; - vecs_pgprot |= L_PTE_SHARED; - mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S; - mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED; - mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; - mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED; - mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; - mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED; - mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S; - mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED; -#endif + if (is_smp()) { + /* + * Mark memory with the "shared" attribute + * for SMP systems + */ + user_pgprot |= L_PTE_SHARED; + kern_pgprot |= L_PTE_SHARED; + vecs_pgprot |= L_PTE_SHARED; + mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S; + mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED; + mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; + mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED; + mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED; + mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED; + } } /* @@ -829,8 +827,7 @@ static void __init sanity_check_meminfo(void) * rather difficult. */ reason = "with VIPT aliasing cache"; -#ifdef CONFIG_SMP - } else if (tlb_ops_need_broadcast()) { + } else if (is_smp() && tlb_ops_need_broadcast()) { /* * kmap_high needs to occasionally flush TLB entries, * however, if the TLB entries need to be broadcast @@ -840,7 +837,6 @@ static void __init sanity_check_meminfo(void) * (must not be called with irqs off) */ reason = "without hardware TLB ops broadcasting"; -#endif } if (reason) { printk(KERN_CRIT "HIGHMEM is not supported %s, ignoring high memory\n", diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 22aac8515196..b95662dedb64 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -30,13 +30,10 @@ #define TTB_RGN_WT (2 << 3) #define TTB_RGN_WB (3 << 3) -#ifndef CONFIG_SMP -#define TTB_FLAGS TTB_RGN_WBWA -#define PMD_FLAGS PMD_SECT_WB -#else -#define TTB_FLAGS TTB_RGN_WBWA|TTB_S -#define PMD_FLAGS PMD_SECT_WBWA|PMD_SECT_S -#endif +#define TTB_FLAGS_UP TTB_RGN_WBWA +#define PMD_FLAGS_UP PMD_SECT_WB +#define TTB_FLAGS_SMP TTB_RGN_WBWA|TTB_S +#define PMD_FLAGS_SMP PMD_SECT_WBWA|PMD_SECT_S ENTRY(cpu_v6_proc_init) mov pc, lr @@ -97,7 +94,8 @@ ENTRY(cpu_v6_switch_mm) #ifdef CONFIG_MMU mov r2, #0 ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id - orr r0, r0, #TTB_FLAGS + ALT_SMP(orr r0, r0, #TTB_FLAGS_SMP) + ALT_UP(orr r0, r0, #TTB_FLAGS_UP) mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB mcr p15, 0, r2, c7, c10, 4 @ drain write buffer mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 @@ -156,9 +154,11 @@ cpu_pj4_name: */ __v6_setup: #ifdef CONFIG_SMP - mrc p15, 0, r0, c1, c0, 1 @ Enable SMP/nAMP mode + ALT_SMP(mrc p15, 0, r0, c1, c0, 1) @ Enable SMP/nAMP mode + ALT_UP(nop) orr r0, r0, #0x20 - mcr p15, 0, r0, c1, c0, 1 + ALT_SMP(mcr p15, 0, r0, c1, c0, 1) + ALT_UP(nop) #endif mov r0, #0 @@ -169,7 +169,8 @@ __v6_setup: #ifdef CONFIG_MMU mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs mcr p15, 0, r0, c2, c0, 2 @ TTB control register - orr r4, r4, #TTB_FLAGS + ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP) + ALT_UP(orr r4, r4, #TTB_FLAGS_UP) mcr p15, 0, r4, c2, c0, 1 @ load TTB1 #endif /* CONFIG_MMU */ adr r5, v6_crval @@ -225,10 +226,16 @@ cpu_elf_name: __v6_proc_info: .long 0x0007b000 .long 0x0007f000 - .long PMD_TYPE_SECT | \ + ALT_SMP(.long \ + PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ | \ + PMD_FLAGS_SMP) + ALT_UP(.long \ + PMD_TYPE_SECT | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ | \ - PMD_FLAGS + PMD_FLAGS_UP) .long PMD_TYPE_SECT | \ PMD_SECT_XN | \ PMD_SECT_AP_WRITE | \ @@ -249,10 +256,16 @@ __v6_proc_info: __pj4_v6_proc_info: .long 0x560f5810 .long 0xff0ffff0 - .long PMD_TYPE_SECT | \ + ALT_SMP(.long \ + PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ | \ + PMD_FLAGS_SMP) + ALT_UP(.long \ + PMD_TYPE_SECT | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ | \ - PMD_FLAGS + PMD_FLAGS_UP) .long PMD_TYPE_SECT | \ PMD_SECT_XN | \ PMD_SECT_AP_WRITE | \ diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 7563ff0141bd..df422fee1cb6 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -30,15 +30,13 @@ #define TTB_IRGN_WT ((1 << 0) | (0 << 6)) #define TTB_IRGN_WB ((1 << 0) | (1 << 6)) -#ifndef CONFIG_SMP /* PTWs cacheable, inner WB not shareable, outer WB not shareable */ -#define TTB_FLAGS TTB_IRGN_WB|TTB_RGN_OC_WB -#define PMD_FLAGS PMD_SECT_WB -#else +#define TTB_FLAGS_UP TTB_IRGN_WB|TTB_RGN_OC_WB +#define PMD_FLAGS_UP PMD_SECT_WB + /* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */ -#define TTB_FLAGS TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA -#define PMD_FLAGS PMD_SECT_WBWA|PMD_SECT_S -#endif +#define TTB_FLAGS_SMP TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA +#define PMD_FLAGS_SMP PMD_SECT_WBWA|PMD_SECT_S ENTRY(cpu_v7_proc_init) mov pc, lr @@ -105,7 +103,8 @@ ENTRY(cpu_v7_switch_mm) #ifdef CONFIG_MMU mov r2, #0 ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id - orr r0, r0, #TTB_FLAGS + ALT_SMP(orr r0, r0, #TTB_FLAGS_SMP) + ALT_UP(orr r0, r0, #TTB_FLAGS_UP) #ifdef CONFIG_ARM_ERRATA_430973 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB #endif @@ -188,7 +187,8 @@ cpu_v7_name: */ __v7_ca9mp_setup: #ifdef CONFIG_SMP - mrc p15, 0, r0, c1, c0, 1 + ALT_SMP(mrc p15, 0, r0, c1, c0, 1) + ALT_UP(mov r0, #(1 << 6)) @ fake it for UP tst r0, #(1 << 6) @ SMP/nAMP mode enabled? orreq r0, r0, #(1 << 6) | (1 << 0) @ Enable SMP/nAMP mode and mcreq p15, 0, r0, c1, c0, 1 @ TLB ops broadcasting @@ -262,7 +262,8 @@ __v7_setup: #ifdef CONFIG_MMU mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs mcr p15, 0, r10, c2, c0, 2 @ TTB control register - orr r4, r4, #TTB_FLAGS + ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP) + ALT_UP(orr r4, r4, #TTB_FLAGS_UP) mcr p15, 0, r4, c2, c0, 1 @ load TTB1 mov r10, #0x1f @ domains 0, 1 = manager mcr p15, 0, r10, c3, c0, 0 @ load domain access register @@ -354,10 +355,16 @@ cpu_elf_name: __v7_ca9mp_proc_info: .long 0x410fc090 @ Required ID value .long 0xff0ffff0 @ Mask for ID - .long PMD_TYPE_SECT | \ + ALT_SMP(.long \ + PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ | \ + PMD_FLAGS_SMP) + ALT_UP(.long \ + PMD_TYPE_SECT | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ | \ - PMD_FLAGS + PMD_FLAGS_UP) .long PMD_TYPE_SECT | \ PMD_SECT_XN | \ PMD_SECT_AP_WRITE | \ @@ -380,10 +387,16 @@ __v7_ca9mp_proc_info: __v7_proc_info: .long 0x000f0000 @ Required ID value .long 0x000f0000 @ Mask for ID - .long PMD_TYPE_SECT | \ + ALT_SMP(.long \ + PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ | \ + PMD_FLAGS_SMP) + ALT_UP(.long \ + PMD_TYPE_SECT | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ | \ - PMD_FLAGS + PMD_FLAGS_UP) .long PMD_TYPE_SECT | \ PMD_SECT_XN | \ PMD_SECT_AP_WRITE | \ diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S index f3f288a9546d..53cd5b454673 100644 --- a/arch/arm/mm/tlb-v7.S +++ b/arch/arm/mm/tlb-v7.S @@ -13,6 +13,7 @@ */ #include #include +#include #include #include #include @@ -41,20 +42,15 @@ ENTRY(v7wbi_flush_user_tlb_range) orr r0, r3, r0, lsl #PAGE_SHIFT @ Create initial MVA mov r1, r1, lsl #PAGE_SHIFT 1: -#ifdef CONFIG_SMP - mcr p15, 0, r0, c8, c3, 1 @ TLB invalidate U MVA (shareable) -#else - mcr p15, 0, r0, c8, c7, 1 @ TLB invalidate U MVA -#endif + ALT_SMP(mcr p15, 0, r0, c8, c3, 1) @ TLB invalidate U MVA (shareable) + ALT_UP(mcr p15, 0, r0, c8, c7, 1) @ TLB invalidate U MVA + add r0, r0, #PAGE_SZ cmp r0, r1 blo 1b mov ip, #0 -#ifdef CONFIG_SMP - mcr p15, 0, ip, c7, c1, 6 @ flush BTAC/BTB Inner Shareable -#else - mcr p15, 0, ip, c7, c5, 6 @ flush BTAC/BTB -#endif + ALT_SMP(mcr p15, 0, ip, c7, c1, 6) @ flush BTAC/BTB Inner Shareable + ALT_UP(mcr p15, 0, ip, c7, c5, 6) @ flush BTAC/BTB dsb mov pc, lr ENDPROC(v7wbi_flush_user_tlb_range) @@ -74,20 +70,14 @@ ENTRY(v7wbi_flush_kern_tlb_range) mov r0, r0, lsl #PAGE_SHIFT mov r1, r1, lsl #PAGE_SHIFT 1: -#ifdef CONFIG_SMP - mcr p15, 0, r0, c8, c3, 1 @ TLB invalidate U MVA (shareable) -#else - mcr p15, 0, r0, c8, c7, 1 @ TLB invalidate U MVA -#endif + ALT_SMP(mcr p15, 0, r0, c8, c3, 1) @ TLB invalidate U MVA (shareable) + ALT_UP(mcr p15, 0, r0, c8, c7, 1) @ TLB invalidate U MVA add r0, r0, #PAGE_SZ cmp r0, r1 blo 1b mov r2, #0 -#ifdef CONFIG_SMP - mcr p15, 0, r2, c7, c1, 6 @ flush BTAC/BTB Inner Shareable -#else - mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB -#endif + ALT_SMP(mcr p15, 0, r2, c7, c1, 6) @ flush BTAC/BTB Inner Shareable + ALT_UP(mcr p15, 0, r2, c7, c5, 6) @ flush BTAC/BTB dsb isb mov pc, lr @@ -99,5 +89,6 @@ ENDPROC(v7wbi_flush_kern_tlb_range) ENTRY(v7wbi_tlb_fns) .long v7wbi_flush_user_tlb_range .long v7wbi_flush_kern_tlb_range - .long v7wbi_tlb_flags + ALT_SMP(.long v7wbi_tlb_flags_smp) + ALT_UP(.long v7wbi_tlb_flags_up) .size v7wbi_tlb_fns, . - v7wbi_tlb_fns -- cgit v1.2.2 From f9e417e901e891d139f4d5fd750959e4a862d9f7 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 21 Sep 2010 00:43:19 +0100 Subject: ARM: 6402/1: Don't send IPI in smp_send_stop if there's only one CPU No need to send IPI if there's one CPU, especially when booting systems with CONFIG_SMP_ON_UP that may not even support IPI. Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/kernel/smp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 40dc74f2b27f..32e16da5cbce 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -567,7 +567,8 @@ void smp_send_stop(void) { cpumask_t mask = cpu_online_map; cpu_clear(smp_processor_id(), mask); - send_ipi_message(&mask, IPI_CPU_STOP); + if (!cpus_empty(mask)) + send_ipi_message(&mask, IPI_CPU_STOP); } /* -- cgit v1.2.2 From 81d11955bf0b5ae25e3adbec930cd84840385dae Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 21 Sep 2010 17:16:40 +0100 Subject: ARM: 6405/1: Handle __flush_icache_all for CONFIG_SMP_ON_UP Do this by adding flush_icache_all to cache_fns for ARMv6 and 7. As flush_icache_all may neeed to be called from flush_kern_cache_all, add it as the first entry in the cache_fns. Note that now we can remove the ARM_ERRATA_411920 dependency to !SMP so it can be selected on UP ARMv6 processors, such as omap2. Signed-off-by: Tony Lindgren Signed-off-by: Anand Gadiyar Signed-off-by: Russell King --- arch/arm/Kconfig | 2 +- arch/arm/include/asm/cacheflush.h | 56 ++++++++++++++++++++++++++++----------- arch/arm/mm/cache-v6.S | 30 +++++++++++++-------- arch/arm/mm/cache-v7.S | 16 +++++++++++ 4 files changed, 77 insertions(+), 27 deletions(-) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f6cdc21b562c..7562f884f2c5 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1002,7 +1002,7 @@ endif config ARM_ERRATA_411920 bool "ARM errata: Invalidation of the Instruction Cache operation can fail" - depends on CPU_V6 && !SMP + depends on CPU_V6 help Invalidation of the Instruction Cache operation can fail. This erratum is present in 1136 (before r1p4), 1156 and 1176. diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 4656a24058d2..a3db768ee5cc 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -156,6 +156,12 @@ * Please note that the implementation of these, and the required * effects are cache-type (VIVT/VIPT/PIPT) specific. * + * flush_icache_all() + * + * Unconditionally clean and invalidate the entire icache. + * Currently only needed for cache-v6.S and cache-v7.S, see + * __flush_icache_all for the generic implementation. + * * flush_kern_all() * * Unconditionally clean and invalidate the entire cache. @@ -206,6 +212,7 @@ */ struct cpu_cache_fns { + void (*flush_icache_all)(void); void (*flush_kern_all)(void); void (*flush_user_all)(void); void (*flush_user_range)(unsigned long, unsigned long, unsigned int); @@ -227,6 +234,7 @@ struct cpu_cache_fns { extern struct cpu_cache_fns cpu_cache; +#define __cpuc_flush_icache_all cpu_cache.flush_icache_all #define __cpuc_flush_kern_all cpu_cache.flush_kern_all #define __cpuc_flush_user_all cpu_cache.flush_user_all #define __cpuc_flush_user_range cpu_cache.flush_user_range @@ -246,6 +254,7 @@ extern struct cpu_cache_fns cpu_cache; #else +#define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all) #define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all) #define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all) #define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range) @@ -253,6 +262,7 @@ extern struct cpu_cache_fns cpu_cache; #define __cpuc_coherent_user_range __glue(_CACHE,_coherent_user_range) #define __cpuc_flush_dcache_area __glue(_CACHE,_flush_kern_dcache_area) +extern void __cpuc_flush_icache_all(void); extern void __cpuc_flush_kern_all(void); extern void __cpuc_flush_user_all(void); extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int); @@ -291,6 +301,37 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *, /* * Convert calls to our calling convention. */ + +/* Invalidate I-cache */ +#define __flush_icache_all_generic() \ + asm("mcr p15, 0, %0, c7, c5, 0" \ + : : "r" (0)); + +/* Invalidate I-cache inner shareable */ +#define __flush_icache_all_v7_smp() \ + asm("mcr p15, 0, %0, c7, c1, 0" \ + : : "r" (0)); + +/* + * Optimized __flush_icache_all for the common cases. Note that UP ARMv7 + * will fall through to use __flush_icache_all_generic. + */ +#if (defined(CONFIG_CPU_V7) && defined(CONFIG_CPU_V6)) || \ + defined(CONFIG_SMP_ON_UP) +#define __flush_icache_preferred __cpuc_flush_icache_all +#elif __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP) +#define __flush_icache_preferred __flush_icache_all_v7_smp +#elif __LINUX_ARM_ARCH__ == 6 && defined(CONFIG_ARM_ERRATA_411920) +#define __flush_icache_preferred __cpuc_flush_icache_all +#else +#define __flush_icache_preferred __flush_icache_all_generic +#endif + +static inline void __flush_icache_all(void) +{ + __flush_icache_preferred(); +} + #define flush_cache_all() __cpuc_flush_kern_all() static inline void vivt_flush_cache_mm(struct mm_struct *mm) @@ -366,21 +407,6 @@ extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 extern void flush_dcache_page(struct page *); -static inline void __flush_icache_all(void) -{ -#ifdef CONFIG_ARM_ERRATA_411920 - extern void v6_icache_inval_all(void); - v6_icache_inval_all(); -#elif defined(CONFIG_SMP) && __LINUX_ARM_ARCH__ >= 7 - asm("mcr p15, 0, %0, c7, c1, 0 @ invalidate I-cache inner shareable\n" - : - : "r" (0)); -#else - asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n" - : - : "r" (0)); -#endif -} static inline void flush_kernel_vmap_range(void *addr, int size) { if ((cache_is_vivt() || cache_is_vipt_aliasing())) diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 86aa689ef1aa..99fa688dfadd 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S @@ -21,18 +21,22 @@ #define D_CACHE_LINE_SIZE 32 #define BTB_FLUSH_SIZE 8 -#ifdef CONFIG_ARM_ERRATA_411920 /* - * Invalidate the entire I cache (this code is a workaround for the ARM1136 - * erratum 411920 - Invalidate Instruction Cache operation can fail. This - * erratum is present in 1136, 1156 and 1176. It does not affect the MPCore. + * v6_flush_icache_all() + * + * Flush the whole I-cache. * - * Registers: - * r0 - set to 0 - * r1 - corrupted + * ARM1136 erratum 411920 - Invalidate Instruction Cache operation can fail. + * This erratum is present in 1136, 1156 and 1176. It does not affect the + * MPCore. + * + * Registers: + * r0 - set to 0 + * r1 - corrupted */ -ENTRY(v6_icache_inval_all) +ENTRY(v6_flush_icache_all) mov r0, #0 +#ifdef CONFIG_ARM_ERRATA_411920 mrs r1, cpsr cpsid ifa @ disable interrupts mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache @@ -43,8 +47,11 @@ ENTRY(v6_icache_inval_all) .rept 11 @ ARM Ltd recommends at least nop @ 11 NOPs .endr - mov pc, lr +#else + mcr p15, 0, r0, c7, c5, 0 @ invalidate I-cache #endif + mov pc, lr +ENDPROC(v6_flush_icache_all) /* * v6_flush_cache_all() @@ -60,7 +67,7 @@ ENTRY(v6_flush_kern_cache_all) #ifndef CONFIG_ARM_ERRATA_411920 mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate #else - b v6_icache_inval_all + b v6_flush_icache_all #endif #else mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate @@ -138,7 +145,7 @@ ENTRY(v6_coherent_user_range) #ifndef CONFIG_ARM_ERRATA_411920 mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate #else - b v6_icache_inval_all + b v6_flush_icache_all #endif #else mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB @@ -312,6 +319,7 @@ ENDPROC(v6_dma_unmap_area) .type v6_cache_fns, #object ENTRY(v6_cache_fns) + .long v6_flush_icache_all .long v6_flush_kern_cache_all .long v6_flush_user_cache_all .long v6_flush_user_cache_range diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index e8ea1a071f43..a3ebf7a4f49b 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -17,6 +17,21 @@ #include "proc-macros.S" +/* + * v7_flush_icache_all() + * + * Flush the whole I-cache. + * + * Registers: + * r0 - set to 0 + */ +ENTRY(v7_flush_icache_all) + mov r0, #0 + ALT_SMP(mcr p15, 0, r0, c7, c1, 0) @ invalidate I-cache inner shareable + ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate + mov pc, lr +ENDPROC(v7_flush_icache_all) + /* * v7_flush_dcache_all() * @@ -303,6 +318,7 @@ ENDPROC(v7_dma_unmap_area) .type v7_cache_fns, #object ENTRY(v7_cache_fns) + .long v7_flush_icache_all .long v7_flush_kern_cache_all .long v7_flush_user_cache_all .long v7_flush_user_cache_range -- cgit v1.2.2 From 100642c7b6971fb4ab69a662f4f60970e3a16dfd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 6 Sep 2010 09:16:44 +0100 Subject: ARM: 6366/1: Update U300 defconfig This mainly removes a lot of unused subsystems (as for the mainline drivers) in the U300 defconfig, switch of MMC debugging by default and enables debugfs on the builds. Once we merge the drivers we'll configure it on again. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/configs/u300_defconfig | 37 ++----------------------------------- 1 file changed, 2 insertions(+), 35 deletions(-) (limited to 'arch') diff --git a/arch/arm/configs/u300_defconfig b/arch/arm/configs/u300_defconfig index 46e5e0747269..c1c252cdca60 100644 --- a/arch/arm/configs/u300_defconfig +++ b/arch/arm/configs/u300_defconfig @@ -28,26 +28,9 @@ CONFIG_CPU_IDLE=y CONFIG_FPE_NWFPE=y CONFIG_PM=y # CONFIG_SUSPEND is not set -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_INET_DIAG is not set -# CONFIG_IPV6 is not set -# CONFIG_WIRELESS is not set CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_PREVENT_FIRMWARE_BUILD is not set -CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_ECC_SMC=y +# CONFIG_MISC_DEVICES is not set # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set @@ -58,7 +41,6 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_LEGACY_PTY_COUNT=16 # CONFIG_HW_RANDOM is not set CONFIG_I2C=y -CONFIG_POWER_SUPPLY=y # CONFIG_HWMON is not set CONFIG_WATCHDOG=y CONFIG_REGULATOR=y @@ -66,24 +48,10 @@ CONFIG_FB=y CONFIG_BACKLIGHT_LCD_SUPPORT=y # CONFIG_LCD_CLASS_DEVICE is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y -# CONFIG_VGA_CONSOLE is not set -CONFIG_SOUND=y -CONFIG_SND=y -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_VERBOSE_PROCFS is not set -# CONFIG_SND_DRIVERS is not set -# CONFIG_SND_ARM is not set -# CONFIG_SND_SPI is not set -CONFIG_SND_SOC=y # CONFIG_HID_SUPPORT is not set # CONFIG_USB_SUPPORT is not set CONFIG_MMC=y -CONFIG_MMC_DEBUG=y CONFIG_MMC_ARMMMCI=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_BACKLIGHT=y CONFIG_RTC_CLASS=y # CONFIG_RTC_HCTOSYS is not set CONFIG_RTC_DRV_COH901331=y @@ -93,12 +61,11 @@ CONFIG_COH901318=y CONFIG_FUSE_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y -# CONFIG_NETWORK_FILESYSTEMS is not set CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_FS=y CONFIG_DEBUG_KERNEL=y -# CONFIG_DETECT_SOFTLOCKUP is not set # CONFIG_SCHED_DEBUG is not set CONFIG_TIMER_STATS=y # CONFIG_DEBUG_PREEMPT is not set -- cgit v1.2.2 From 8925ec4c530094b878e7e28a1fd78e7122afd973 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 13 Sep 2010 16:18:30 +0100 Subject: ARM: 6385/1: setup: detect aliasing I-cache when D-cache is non-aliasing Currently, the Kernel assumes that if a CPU has a non-aliasing D-cache then the I-cache is also non-aliasing. This may not be true on ARM cores from v6 onwards, which may have aliasing I-caches but non-aliasing D-caches. This patch adds a cpu_has_aliasing_icache function, which is called from cacheid_init and adds CACHEID_VIPT_I_ALIASING to the cacheid when appropriate. A utility macro, icache_is_vipt_aliasing(), is also provided. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/cachetype.h | 8 ++++++-- arch/arm/kernel/setup.c | 39 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/cachetype.h b/arch/arm/include/asm/cachetype.h index d3a4c2cb9f2f..c023db09fcc1 100644 --- a/arch/arm/include/asm/cachetype.h +++ b/arch/arm/include/asm/cachetype.h @@ -6,6 +6,7 @@ #define CACHEID_VIPT_ALIASING (1 << 2) #define CACHEID_VIPT (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING) #define CACHEID_ASID_TAGGED (1 << 3) +#define CACHEID_VIPT_I_ALIASING (1 << 4) extern unsigned int cacheid; @@ -14,15 +15,18 @@ extern unsigned int cacheid; #define cache_is_vipt_nonaliasing() cacheid_is(CACHEID_VIPT_NONALIASING) #define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING) #define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED) +#define icache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_I_ALIASING) /* * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture * Mask out support which will never be present on newer CPUs. * - v6+ is never VIVT - * - v7+ VIPT never aliases + * - v7+ VIPT never aliases on D-side */ #if __LINUX_ARM_ARCH__ >= 7 -#define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING | CACHEID_ASID_TAGGED) +#define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING |\ + CACHEID_ASID_TAGGED |\ + CACHEID_VIPT_I_ALIASING) #elif __LINUX_ARM_ARCH__ >= 6 #define __CACHEID_ARCH_MIN (~CACHEID_VIVT) #else diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index d5231ae7355a..9fc483393bae 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -238,6 +238,34 @@ int cpu_architecture(void) return cpu_arch; } +static int cpu_has_aliasing_icache(unsigned int arch) +{ + int aliasing_icache; + unsigned int id_reg, num_sets, line_size; + + /* arch specifies the register format */ + switch (arch) { + case CPU_ARCH_ARMv7: + asm("mcr p15, 2, %1, c0, c0, 0 @ set CSSELR\n" + "isb\n" + "mrc p15, 1, %0, c0, c0, 0 @ read CCSIDR" + : "=r" (id_reg) + : "r" (1)); + line_size = 4 << ((id_reg & 0x7) + 2); + num_sets = ((id_reg >> 13) & 0x7fff) + 1; + aliasing_icache = (line_size * num_sets) > PAGE_SIZE; + break; + case CPU_ARCH_ARMv6: + aliasing_icache = read_cpuid_cachetype() & (1 << 11); + break; + default: + /* I-cache aliases will be handled by D-cache aliasing code */ + aliasing_icache = 0; + } + + return aliasing_icache; +} + static void __init cacheid_init(void) { unsigned int cachetype = read_cpuid_cachetype(); @@ -249,10 +277,15 @@ static void __init cacheid_init(void) cacheid = CACHEID_VIPT_NONALIASING; if ((cachetype & (3 << 14)) == 1 << 14) cacheid |= CACHEID_ASID_TAGGED; - } else if (cachetype & (1 << 23)) + else if (cpu_has_aliasing_icache(CPU_ARCH_ARMv7)) + cacheid |= CACHEID_VIPT_I_ALIASING; + } else if (cachetype & (1 << 23)) { cacheid = CACHEID_VIPT_ALIASING; - else + } else { cacheid = CACHEID_VIPT_NONALIASING; + if (cpu_has_aliasing_icache(CPU_ARCH_ARMv6)) + cacheid |= CACHEID_VIPT_I_ALIASING; + } } else { cacheid = CACHEID_VIVT; } @@ -263,7 +296,7 @@ static void __init cacheid_init(void) cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown", cache_is_vivt() ? "VIVT" : icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" : - cache_is_vipt_aliasing() ? "VIPT aliasing" : + icache_is_vipt_aliasing() ? "VIPT aliasing" : cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown"); } -- cgit v1.2.2 From c4e259c859538e94007d1f04a488540375189551 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 13 Sep 2010 16:19:41 +0100 Subject: ARM: 6386/1: flush_ptrace_access: invalidate correct I-cache alias copy_to_user_page can be used by access_process_vm to write to an executable page of a process using a mapping acquired by kmap. For systems with I-cache aliasing, flushing the I-cache using the Kernel mapping may leave stale data in the I-cache if the user mapping is of a different colour. This patch introduces a flush_icache_alias function to flush.c, which calls flush_icache_range with a mapping of the specified colour. flush_ptrace_access is then modified to call this new function instead of coherent_kern_range in the case of an aliasing I-cache and a non-aliasing D-cache. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/flush.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 2332b774c6b9..391ffae75098 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -40,6 +40,18 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr) : "cc"); } +static void flush_icache_alias(unsigned long pfn, unsigned long vaddr, unsigned long len) +{ + unsigned long colour = CACHE_COLOUR(vaddr); + unsigned long offset = vaddr & (PAGE_SIZE - 1); + unsigned long to; + + set_pte_ext(TOP_PTE(ALIAS_FLUSH_START) + colour, pfn_pte(pfn, PAGE_KERNEL), 0); + to = ALIAS_FLUSH_START + (colour << PAGE_SHIFT) + offset; + flush_tlb_kernel_page(to); + flush_icache_range(to, to + len); +} + void flush_cache_mm(struct mm_struct *mm) { if (cache_is_vivt()) { @@ -90,8 +102,10 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig if (vma->vm_flags & VM_EXEC && icache_is_vivt_asid_tagged()) __flush_icache_all(); } + #else -#define flush_pfn_alias(pfn,vaddr) do { } while (0) +#define flush_pfn_alias(pfn,vaddr) do { } while (0) +#define flush_icache_alias(pfn,vaddr,len) do { } while (0) #endif static void flush_ptrace_access_other(void *args) @@ -117,10 +131,13 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, return; } - /* VIPT non-aliasing cache */ + /* VIPT non-aliasing D-cache */ if (vma->vm_flags & VM_EXEC) { unsigned long addr = (unsigned long)kaddr; - __cpuc_coherent_kern_range(addr, addr + len); + if (icache_is_vipt_aliasing()) + flush_icache_alias(page_to_pfn(page), uaddr, len); + else + __cpuc_coherent_kern_range(addr, addr + len); if (cache_ops_need_broadcast()) smp_call_function(flush_ptrace_access_other, NULL, 1); -- cgit v1.2.2 From 5fb31a96e1e0078f1e82736ccd72a61ecabe6a4f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 6 Oct 2010 11:07:28 +0100 Subject: ARM: 6431/1: fix isb regression on CPU < v7 The kernel does not compile for my ARM926EJ-S system U300 due to the isb instruction inserted in generic assember statement from commit 8925ec4c530094b878e7e28a1fd78e7122afd973, "ARM: 6385/1: setup: detect aliasing I-cache when D-cache is non-aliasing" hey the isb is only available when assembling for v7 so let's use the generic isb() macro from setup.h instead. Acked-by: Will Deacon Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/kernel/setup.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 9fc483393bae..e0430d036cea 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -246,11 +246,12 @@ static int cpu_has_aliasing_icache(unsigned int arch) /* arch specifies the register format */ switch (arch) { case CPU_ARCH_ARMv7: - asm("mcr p15, 2, %1, c0, c0, 0 @ set CSSELR\n" - "isb\n" - "mrc p15, 1, %0, c0, c0, 0 @ read CCSIDR" - : "=r" (id_reg) + asm("mcr p15, 2, %0, c0, c0, 0 @ set CSSELR" + : /* No output operands */ : "r" (1)); + isb(); + asm("mrc p15, 1, %0, c0, c0, 0 @ read CCSIDR" + : "=r" (id_reg)); line_size = 4 << ((id_reg & 0x7) + 2); num_sets = ((id_reg >> 13) & 0x7fff) + 1; aliasing_icache = (line_size * num_sets) > PAGE_SIZE; -- cgit v1.2.2 From 7511db9d25080d53e5427bf4b8849278c07019bc Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 5 Oct 2010 16:40:13 +0100 Subject: ARM: 6429/1: Check for is_smp for tlb_ops and cache_ops broadcast Broadcast should not be needed when running SMP kernel on UP systems. Also, this fixes an undefined instruction for SMP_ON_UP on earlier ARM cores without the extended CPUID_EXT_MMFR3 register. Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/include/asm/smp_plat.h | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h index 7de5aa56c18b..7f4e6633f753 100644 --- a/arch/arm/include/asm/smp_plat.h +++ b/arch/arm/include/asm/smp_plat.h @@ -7,17 +7,6 @@ #include -/* all SMP configurations have the extended CPUID registers */ -static inline int tlb_ops_need_broadcast(void) -{ - return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2; -} - -static inline int cache_ops_need_broadcast(void) -{ - return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1; -} - /* * Return true if we are running on a SMP platform */ @@ -33,4 +22,21 @@ static inline bool is_smp(void) #endif } +/* all SMP configurations have the extended CPUID registers */ +static inline int tlb_ops_need_broadcast(void) +{ + if (!is_smp()) + return 0; + + return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2; +} + +static inline int cache_ops_need_broadcast(void) +{ + if (!is_smp()) + return 0; + + return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1; +} + #endif -- cgit v1.2.2 From c7b0aff44a0740eedd31b759fd08d9e25672fa76 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 1 Oct 2010 22:13:47 +0100 Subject: ARM: 6428/1: add cpu_idle_wait() to support CPUidle on SMP systems. In order for CPUidle to work on SMP systems, an implementation of cpu_idle_wait() is needed. This patch duplicates the x86 implementation of cpu_idle_wait() for ARM. Tested-by: Colin Cross Signed-off-by: Kevin Hilman Signed-off-by: Russell King --- arch/arm/Kconfig | 3 +++ arch/arm/include/asm/system.h | 2 ++ arch/arm/kernel/process.c | 19 +++++++++++++++++++ 3 files changed, 24 insertions(+) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 7562f884f2c5..94360e7a7abc 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -145,6 +145,9 @@ config ARCH_HAS_CPUFREQ and that the relevant menu configurations are displayed for it. +config ARCH_HAS_CPU_IDLE_WAIT + def_bool y + config GENERIC_HWEIGHT bool default y diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 8ba1ccf82a02..48e360c74327 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -325,6 +325,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size extern void disable_hlt(void); extern void enable_hlt(void); +void cpu_idle_wait(void); + #include #if __LINUX_ARM_ARCH__ < 6 diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 401e38be1f78..23def52d2d24 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -135,6 +135,25 @@ EXPORT_SYMBOL(pm_power_off); void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart; EXPORT_SYMBOL_GPL(arm_pm_restart); +static void do_nothing(void *unused) +{ +} + +/* + * cpu_idle_wait - Used to ensure that all the CPUs discard old value of + * pm_idle and update to new pm_idle value. Required while changing pm_idle + * handler on SMP systems. + * + * Caller must have changed pm_idle to the new value before the call. Old + * pm_idle value will not be used by any CPU after the return of this function. + */ +void cpu_idle_wait(void) +{ + smp_mb(); + /* kick all the CPUs so that they exit out of pm_idle */ + smp_call_function(do_nothing, NULL, 1); +} +EXPORT_SYMBOL_GPL(cpu_idle_wait); /* * This is our default idle handler. We need to disable -- cgit v1.2.2 From 842eab40b6920819fff5caeefdb709f07d3f8e23 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 1 Oct 2010 14:12:22 +0100 Subject: ARM: vmlinux.lds: Refer to start of .data using _sdata rather than _data Use _sdata as the start of the data section, rather than _data. Signed-off-by: Russell King --- arch/arm/kernel/head-common.S | 2 +- arch/arm/kernel/setup.c | 2 +- arch/arm/mm/init.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index b9505aa267c0..58a3e632b6d5 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -20,7 +20,7 @@ __switch_data: .long __mmap_switched .long __data_loc @ r4 - .long _data @ r5 + .long _sdata @ r5 .long __bss_start @ r6 .long _end @ r7 .long processor_id @ r4 diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 5a82c39ca85e..f38917174b71 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -491,7 +491,7 @@ request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc) kernel_code.start = virt_to_phys(_text); kernel_code.end = virt_to_phys(_etext - 1); - kernel_data.start = virt_to_phys(_data); + kernel_data.start = virt_to_phys(_sdata); kernel_data.end = virt_to_phys(_end - 1); for (i = 0; i < mi->nr_banks; i++) { diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 7185b00650fe..36c4553ffcce 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -277,7 +277,7 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) /* Register the kernel text, kernel data and initrd with memblock. */ #ifdef CONFIG_XIP_KERNEL - memblock_reserve(__pa(_data), _end - _data); + memblock_reserve(__pa(_sdata), _end - _sdata); #else memblock_reserve(__pa(_stext), _end - _stext); #endif @@ -545,7 +545,7 @@ void __init mem_init(void) MLK_ROUNDUP(__init_begin, __init_end), MLK_ROUNDUP(_text, _etext), - MLK_ROUNDUP(_data, _edata)); + MLK_ROUNDUP(_sdata, _edata)); #undef MLK #undef MLM -- cgit v1.2.2 From 74b0ec0708e7c8c530079b737f32c55597d062cc Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 1 Oct 2010 14:26:56 +0100 Subject: ARM: vmlinux.lds: Move unwind tables into _stext.._etext Signed-off-by: Russell King --- arch/arm/kernel/vmlinux.lds.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index fd5750b8ac84..065d35de0e01 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -109,8 +109,6 @@ SECTIONS RO_DATA(PAGE_SIZE) - _etext = .; /* End of text and rodata section */ - #ifdef CONFIG_ARM_UNWIND /* * Stack unwinding tables @@ -128,6 +126,8 @@ SECTIONS } #endif + _etext = .; /* End of text and rodata section */ + #ifdef CONFIG_XIP_KERNEL __data_loc = ALIGN(4); /* location in binary */ . = PAGE_OFFSET + TEXT_OFFSET; -- cgit v1.2.2 From 6a7d520fc141ad8f72efab3a5a2a73b3655fee24 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 6 Sep 2010 09:16:04 +0100 Subject: ARM: 6365/1: Update RealView defconfig This patches the condensed RealView defconfig activating some stuff that has been missing from this config for some time and some stuff that was merged in the 2.6.36 merge window: - The new character LCD driver is enabled - The Versatile I2C is enabled - The PL022 SPI driver is enabled - gpiolib is enabled (and makes MMC detection work properly) - The new LEDs code is enabled with a heartbeat trigger - The RTC class is enabled, and the PL031 RTC (onchip) and the offchip DS1307 on I2C is enabled Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/configs/realview_defconfig | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/configs/realview_defconfig b/arch/arm/configs/realview_defconfig index fb75192ee7e5..fcaa60328051 100644 --- a/arch/arm/configs/realview_defconfig +++ b/arch/arm/configs/realview_defconfig @@ -38,6 +38,7 @@ CONFIG_MTD_CFI=y CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_CFI_AMDSTD=y CONFIG_MTD_ARM_INTEGRATOR=y +CONFIG_ARM_CHARLCD=y CONFIG_NETDEVICES=y CONFIG_SMSC_PHY=y CONFIG_NET_ETHERNET=y @@ -51,10 +52,13 @@ CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_LEGACY_PTY_COUNT=16 # CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_I2C_VERSATILE=y +CONFIG_SPI=y +CONFIG_GPIOLIB=y # CONFIG_HWMON is not set CONFIG_FB=y CONFIG_FB_ARMCLCD=y -# CONFIG_VGA_CONSOLE is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set @@ -69,7 +73,13 @@ CONFIG_SND_ARMAACI=y # CONFIG_USB_SUPPORT is not set CONFIG_MMC=y CONFIG_MMC_ARMMMCI=y -CONFIG_INOTIFY=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_PL031=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_CRAMFS=y @@ -79,6 +89,7 @@ CONFIG_ROOT_NFS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_FS=y CONFIG_DEBUG_KERNEL=y # CONFIG_SCHED_DEBUG is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set -- cgit v1.2.2 From 2da6d64a638eb982bebf34e2999f0b67cfb90f33 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 11 Sep 2010 12:47:25 +0100 Subject: ARM: 6369/1: Update RealView SMP defconfig This patches the condensed RealView SMP defconfig activating the same 2.6.36 features mentioned in the vanilla RealView defconfig patch submitted earlier. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/configs/realview-smp_defconfig | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/configs/realview-smp_defconfig b/arch/arm/configs/realview-smp_defconfig index 9312ef9f9bf4..5ca7a61f7c01 100644 --- a/arch/arm/configs/realview-smp_defconfig +++ b/arch/arm/configs/realview-smp_defconfig @@ -39,6 +39,7 @@ CONFIG_MTD_CFI=y CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_CFI_AMDSTD=y CONFIG_MTD_ARM_INTEGRATOR=y +CONFIG_ARM_CHARLCD=y CONFIG_NETDEVICES=y CONFIG_SMSC_PHY=y CONFIG_NET_ETHERNET=y @@ -52,10 +53,13 @@ CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_LEGACY_PTY_COUNT=16 # CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_I2C_VERSATILE=y +CONFIG_SPI=y +CONFIG_GPIOLIB=y # CONFIG_HWMON is not set CONFIG_FB=y CONFIG_FB_ARMCLCD=y -# CONFIG_VGA_CONSOLE is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set @@ -70,7 +74,13 @@ CONFIG_SND_ARMAACI=y # CONFIG_USB_SUPPORT is not set CONFIG_MMC=y CONFIG_MMC_ARMMMCI=y -CONFIG_INOTIFY=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_PL031=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_CRAMFS=y @@ -80,6 +90,7 @@ CONFIG_ROOT_NFS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_FS=y CONFIG_DEBUG_KERNEL=y # CONFIG_SCHED_DEBUG is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set -- cgit v1.2.2 From 8b1f5d91e23300ea2f65007047d26799157dc4b8 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 7 Sep 2010 04:02:16 +0100 Subject: ARM: 6367/1: PL330: Accept different revision The driver can handle different revisions of the core which vary only minorly. Signed-off-by: Jassi Brar Signed-off-by: Russell King --- arch/arm/common/pl330.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c index 5ebbab6242a7..8f0f86db3602 100644 --- a/arch/arm/common/pl330.c +++ b/arch/arm/common/pl330.c @@ -146,8 +146,7 @@ #define DESIGNER 0x41 #define REVISION 0x0 #define INTEG_CFG 0x0 -#define PERIPH_ID_VAL ((PART << 0) | (DESIGNER << 12) \ - | (REVISION << 20) | (INTEG_CFG << 24)) +#define PERIPH_ID_VAL ((PART << 0) | (DESIGNER << 12)) #define PCELL_ID_VAL 0xb105f00d @@ -1859,10 +1858,10 @@ int pl330_add(struct pl330_info *pi) regs = pi->base; /* Check if we can handle this DMAC */ - if (get_id(pi, PERIPH_ID) != PERIPH_ID_VAL + if ((get_id(pi, PERIPH_ID) & 0xfffff) != PERIPH_ID_VAL || get_id(pi, PCELL_ID) != PCELL_ID_VAL) { dev_err(pi->dev, "PERIPH_ID 0x%x, PCELL_ID 0x%x !\n", - readl(regs + PERIPH_ID), readl(regs + PCELL_ID)); + get_id(pi, PERIPH_ID), get_id(pi, PCELL_ID)); return -EINVAL; } -- cgit v1.2.2 From f3af03de0b1c42225d492d874d9afeed0c02568c Mon Sep 17 00:00:00 2001 From: Srinidhi Kasagar Date: Thu, 14 Oct 2010 08:12:40 +0100 Subject: ARM: 6441/1: ux500: The platform is not just based on early drop silicon version. Update Kconfig text accordingly. Signed-off-by: srinidhi kasagar Acked-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-ux500/Kconfig | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 23fe018cd10b..2dd44a0b4615 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -21,9 +21,7 @@ config MACH_U8500_MOP bool "U8500 Development platform" select UX500_SOC_DB8500 help - Include support for mop500 development platform - based on U8500 architecture. The platform is based - on early drop silicon version of 8500. + Include support for the mop500 development platform. config MACH_U5500 bool "U5500 Development platform" -- cgit v1.2.2