From aec85e8664fa3bc6ea6f26f7bf0b78a218d89bc0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 30 Mar 2012 11:07:58 -0700 Subject: [PATCH] 3.3-stable patches added patches: arm-tegra-fix-device-tree-auxdata-for-usb-ehci.patch serial-sh-sci-fix-a-race-of-dma-submit_tx-on-transfer.patch --- ...fix-device-tree-auxdata-for-usb-ehci.patch | 86 ++++++++++++++++++ ...-a-race-of-dma-submit_tx-on-transfer.patch | 88 +++++++++++++++++++ queue-3.3/series | 2 + 3 files changed, 176 insertions(+) create mode 100644 queue-3.3/arm-tegra-fix-device-tree-auxdata-for-usb-ehci.patch create mode 100644 queue-3.3/serial-sh-sci-fix-a-race-of-dma-submit_tx-on-transfer.patch diff --git a/queue-3.3/arm-tegra-fix-device-tree-auxdata-for-usb-ehci.patch b/queue-3.3/arm-tegra-fix-device-tree-auxdata-for-usb-ehci.patch new file mode 100644 index 00000000000..19781b8fe23 --- /dev/null +++ b/queue-3.3/arm-tegra-fix-device-tree-auxdata-for-usb-ehci.patch @@ -0,0 +1,86 @@ +From 8c3ec84102d171a24f050a086bfc546e9de93f9f Mon Sep 17 00:00:00 2001 +From: Stephen Warren +Date: Mon, 19 Mar 2012 13:57:13 -0600 +Subject: ARM: tegra: Fix device tree AUXDATA for USB/EHCI + +From: Stephen Warren + +commit 8c3ec84102d171a24f050a086bfc546e9de93f9f upstream. + +Commit 4a53f4e "USB: ehci-tegra: add probing through device tree" added +AUXDATA for Tegra's USB/EHCI controller. However, it pointed the platform +data at a location containing the address of the intended platform data, +rather than the platform data itself. This change fixes that. + +Signed-off-by: Stephen Warren +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/mach-tegra/board-dt-tegra20.c | 6 +++--- + arch/arm/mach-tegra/devices.c | 7 +++---- + arch/arm/mach-tegra/devices.h | 5 +++++ + 3 files changed, 11 insertions(+), 7 deletions(-) + +--- a/arch/arm/mach-tegra/board-dt-tegra20.c ++++ b/arch/arm/mach-tegra/board-dt-tegra20.c +@@ -68,11 +68,11 @@ struct of_dev_auxdata tegra20_auxdata_lo + OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S2_BASE, "tegra-i2s.1", NULL), + OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra-das", NULL), + OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB_BASE, "tegra-ehci.0", +- &tegra_ehci1_device.dev.platform_data), ++ &tegra_ehci1_pdata), + OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB2_BASE, "tegra-ehci.1", +- &tegra_ehci2_device.dev.platform_data), ++ &tegra_ehci2_pdata), + OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB3_BASE, "tegra-ehci.2", +- &tegra_ehci3_device.dev.platform_data), ++ &tegra_ehci3_pdata), + {} + }; + +--- a/arch/arm/mach-tegra/devices.c ++++ b/arch/arm/mach-tegra/devices.c +@@ -23,7 +23,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -446,18 +445,18 @@ static struct tegra_ulpi_config tegra_eh + .clk = "cdev2", + }; + +-static struct tegra_ehci_platform_data tegra_ehci1_pdata = { ++struct tegra_ehci_platform_data tegra_ehci1_pdata = { + .operating_mode = TEGRA_USB_OTG, + .power_down_on_bus_suspend = 1, + }; + +-static struct tegra_ehci_platform_data tegra_ehci2_pdata = { ++struct tegra_ehci_platform_data tegra_ehci2_pdata = { + .phy_config = &tegra_ehci2_ulpi_phy_config, + .operating_mode = TEGRA_USB_HOST, + .power_down_on_bus_suspend = 1, + }; + +-static struct tegra_ehci_platform_data tegra_ehci3_pdata = { ++struct tegra_ehci_platform_data tegra_ehci3_pdata = { + .operating_mode = TEGRA_USB_HOST, + .power_down_on_bus_suspend = 1, + }; +--- a/arch/arm/mach-tegra/devices.h ++++ b/arch/arm/mach-tegra/devices.h +@@ -20,6 +20,11 @@ + #define __MACH_TEGRA_DEVICES_H + + #include ++#include ++ ++extern struct tegra_ehci_platform_data tegra_ehci1_pdata; ++extern struct tegra_ehci_platform_data tegra_ehci2_pdata; ++extern struct tegra_ehci_platform_data tegra_ehci3_pdata; + + extern struct platform_device tegra_gpio_device; + extern struct platform_device tegra_pinmux_device; diff --git a/queue-3.3/serial-sh-sci-fix-a-race-of-dma-submit_tx-on-transfer.patch b/queue-3.3/serial-sh-sci-fix-a-race-of-dma-submit_tx-on-transfer.patch new file mode 100644 index 00000000000..2ef7c41564e --- /dev/null +++ b/queue-3.3/serial-sh-sci-fix-a-race-of-dma-submit_tx-on-transfer.patch @@ -0,0 +1,88 @@ +From 49d4bcaddca977fffdea8b0b71f6e5da96dac78e Mon Sep 17 00:00:00 2001 +From: Yoshii Takashi +Date: Wed, 14 Mar 2012 16:14:43 +0900 +Subject: serial: sh-sci: fix a race of DMA submit_tx on transfer + +From: Yoshii Takashi + +commit 49d4bcaddca977fffdea8b0b71f6e5da96dac78e upstream. + +When DMA is enabled, sh-sci transfer begins with + uart_start() + sci_start_tx() + if (cookie_tx < 0) schedule_work() +Then, starts DMA when wq scheduled, -- (A) + process_one_work() + work_fn_rx() + cookie_tx = desc->submit_tx() +And finishes when DMA transfer ends, -- (B) + sci_dma_tx_complete() + async_tx_ack() + cookie_tx = -EINVAL + (possible another schedule_work()) + +This A to B sequence is not reentrant, since controlling variables +(for example, cookie_tx above) are not queues nor lists. So, they +must be invoked as A B A B..., otherwise results in kernel crash. + +To ensure the sequence, sci_start_tx() seems to test if cookie_tx < 0 +(represents "not used") to call schedule_work(). +But cookie_tx will not be set (to a cookie, also means "used") until +in the middle of work queue scheduled function work_fn_tx(). + +This gap between the test and set allows the breakage of the sequence +under the very frequently call of uart_start(). +Another gap between async_tx_ack() and another schedule_work() results +in the same issue, too. + +This patch introduces a new condition "cookie_tx == 0" just to mark +it is "busy" and assign it within spin-locked region to fill the gaps. + +Signed-off-by: Takashi Yoshii +Reviewed-by: Guennadi Liakhovetski +Signed-off-by: Paul Mundt +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/sh-sci.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -1229,17 +1229,20 @@ static void sci_dma_tx_complete(void *ar + port->icount.tx += sg_dma_len(&s->sg_tx); + + async_tx_ack(s->desc_tx); +- s->cookie_tx = -EINVAL; + s->desc_tx = NULL; + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + + if (!uart_circ_empty(xmit)) { ++ s->cookie_tx = 0; + schedule_work(&s->work_tx); +- } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { +- u16 ctrl = sci_in(port, SCSCR); +- sci_out(port, SCSCR, ctrl & ~SCSCR_TIE); ++ } else { ++ s->cookie_tx = -EINVAL; ++ if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { ++ u16 ctrl = sci_in(port, SCSCR); ++ sci_out(port, SCSCR, ctrl & ~SCSCR_TIE); ++ } + } + + spin_unlock_irqrestore(&port->lock, flags); +@@ -1501,8 +1504,10 @@ static void sci_start_tx(struct uart_por + } + + if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && +- s->cookie_tx < 0) ++ s->cookie_tx < 0) { ++ s->cookie_tx = 0; + schedule_work(&s->work_tx); ++ } + #endif + + if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) { diff --git a/queue-3.3/series b/queue-3.3/series index 90f0b958471..43ef0b4b18a 100644 --- a/queue-3.3/series +++ b/queue-3.3/series @@ -171,3 +171,5 @@ x86-tls-off-by-one-limit-check.patch compat-use-sys_sendfile64-implementation-for-sendfile-syscall.patch rtc-provide-flag-for-rtc-devices-that-don-t-support-uie.patch nfsd-don-t-allow-zero-length-strings-in-cache_parse.patch +arm-tegra-fix-device-tree-auxdata-for-usb-ehci.patch +serial-sh-sci-fix-a-race-of-dma-submit_tx-on-transfer.patch -- 2.47.3