From 3b9561e9d9b88eca9d4ed6aab025dec2eeeed501 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 7 May 2013 16:53:52 -0600 Subject: USB: set device dma_mask without reference to global data Many USB host drivers contain code such as: if (!pdev->dev.dma_mask) pdev->dev.dma_mask = &tegra_ehci_dma_mask; ... where tegra_ehci_dma_mask is a global. I suspect this code originated in commit 4a53f4e "USB: ehci-tegra: add probing through device tree" and was simply copied everywhere else. This works fine when the code is built-in, but can cause a crash when the code is in a module. The first module load sets up the dma_mask pointer, but if the module is removed and re-inserted, the value is now non-NULL, and hence is not updated to point at the new location, and hence points at a stale location within the previous module load address, which in turn causes a crash if the pointer is de-referenced. The simplest way of solving this seems to be to copy the code from ehci-platform.c, which uses the coherent_dma_mask as the target for the dma_mask pointer. Suggested-by: Arnd Bergmann Signed-off-by: Stephen Warren Acked-by: Tony Prisk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-pxa27x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/usb/host/ohci-pxa27x.c') diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index efe71f3ca477..279b2ef17411 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -282,8 +282,6 @@ static const struct of_device_id pxa_ohci_dt_ids[] = { MODULE_DEVICE_TABLE(of, pxa_ohci_dt_ids); -static u64 pxa_ohci_dma_mask = DMA_BIT_MASK(32); - static int ohci_pxa_of_init(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -298,7 +296,9 @@ static int ohci_pxa_of_init(struct platform_device *pdev) * Once we have dma capability bindings this can go away. */ if (!pdev->dev.dma_mask) - pdev->dev.dma_mask = &pxa_ohci_dma_mask; + pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; + if (!pdev->dev.coherent_dma_mask) + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) -- cgit v1.2.3