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 <arnd@arndb.de>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Tony Prisk <linux@prisktech.co.nz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Stephen Warren 2013-05-07 16:53:52 -06:00 committed by Greg Kroah-Hartman
parent 8ff10bdb14
commit 3b9561e9d9
14 changed files with 41 additions and 52 deletions

View File

@ -173,17 +173,10 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)
ci13xxx_imx_platdata.phy = data->phy; ci13xxx_imx_platdata.phy = data->phy;
if (!pdev->dev.dma_mask) { if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = devm_kzalloc(&pdev->dev, pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
sizeof(*pdev->dev.dma_mask), GFP_KERNEL); if (!pdev->dev.coherent_dma_mask)
if (!pdev->dev.dma_mask) { pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
ret = -ENOMEM;
dev_err(&pdev->dev, "Failed to alloc dma_mask!\n");
goto err;
}
*pdev->dev.dma_mask = DMA_BIT_MASK(32);
dma_set_coherent_mask(&pdev->dev, *pdev->dev.dma_mask);
}
if (usbmisc_ops && usbmisc_ops->init) { if (usbmisc_ops && usbmisc_ops->init) {
ret = usbmisc_ops->init(&pdev->dev); ret = usbmisc_ops->init(&pdev->dev);

View File

@ -95,8 +95,6 @@ static int dwc3_exynos_remove_child(struct device *dev, void *unused)
return 0; return 0;
} }
static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);
static int dwc3_exynos_probe(struct platform_device *pdev) static int dwc3_exynos_probe(struct platform_device *pdev)
{ {
struct dwc3_exynos *exynos; struct dwc3_exynos *exynos;
@ -118,7 +116,9 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
* Once we move to full device tree support this will vanish off. * Once we move to full device tree support this will vanish off.
*/ */
if (!dev->dma_mask) if (!dev->dma_mask)
dev->dma_mask = &dwc3_exynos_dma_mask; dev->dma_mask = &dev->coherent_dma_mask;
if (!dev->coherent_dma_mask)
dev->coherent_dma_mask = DMA_BIT_MASK(32);
platform_set_drvdata(pdev, exynos); platform_set_drvdata(pdev, exynos);

View File

@ -63,8 +63,6 @@ static void atmel_stop_ehci(struct platform_device *pdev)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32);
static int ehci_atmel_drv_probe(struct platform_device *pdev) static int ehci_atmel_drv_probe(struct platform_device *pdev)
{ {
struct usb_hcd *hcd; struct usb_hcd *hcd;
@ -93,7 +91,9 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev)
* Once we have dma capability bindings this can go away. * Once we have dma capability bindings this can go away.
*/ */
if (!pdev->dev.dma_mask) if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &at91_ehci_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);
hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) { if (!hcd) {

View File

@ -90,8 +90,6 @@ static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
.extra_priv_size = sizeof(struct omap_hcd), .extra_priv_size = sizeof(struct omap_hcd),
}; };
static u64 omap_ehci_dma_mask = DMA_BIT_MASK(32);
/** /**
* ehci_hcd_omap_probe - initialize TI-based HCDs * ehci_hcd_omap_probe - initialize TI-based HCDs
* *
@ -146,8 +144,10 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
* Since shared usb code relies on it, set it here for now. * Since shared usb code relies on it, set it here for now.
* Once we have dma capability bindings this can go away. * Once we have dma capability bindings this can go away.
*/ */
if (!pdev->dev.dma_mask) if (!dev->dma_mask)
pdev->dev.dma_mask = &omap_ehci_dma_mask; dev->dma_mask = &dev->coherent_dma_mask;
if (!dev->coherent_dma_mask)
dev->coherent_dma_mask = DMA_BIT_MASK(32);
hcd = usb_create_hcd(&ehci_omap_hc_driver, dev, hcd = usb_create_hcd(&ehci_omap_hc_driver, dev,
dev_name(dev)); dev_name(dev));

View File

@ -137,8 +137,6 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
} }
} }
static u64 ehci_orion_dma_mask = DMA_BIT_MASK(32);
static int ehci_orion_drv_probe(struct platform_device *pdev) static int ehci_orion_drv_probe(struct platform_device *pdev)
{ {
struct orion_ehci_data *pd = pdev->dev.platform_data; struct orion_ehci_data *pd = pdev->dev.platform_data;
@ -183,7 +181,9 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
* now. Once we have dma capability bindings this can go away. * now. Once we have dma capability bindings this can go away.
*/ */
if (!pdev->dev.dma_mask) if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &ehci_orion_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);
if (!request_mem_region(res->start, resource_size(res), if (!request_mem_region(res->start, resource_size(res),
ehci_orion_hc_driver.description)) { ehci_orion_hc_driver.description)) {

View File

@ -71,8 +71,6 @@ static void s5p_setup_vbus_gpio(struct platform_device *pdev)
dev_err(dev, "can't request ehci vbus gpio %d", gpio); dev_err(dev, "can't request ehci vbus gpio %d", gpio);
} }
static u64 ehci_s5p_dma_mask = DMA_BIT_MASK(32);
static int s5p_ehci_probe(struct platform_device *pdev) static int s5p_ehci_probe(struct platform_device *pdev)
{ {
struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
@ -90,7 +88,7 @@ static int s5p_ehci_probe(struct platform_device *pdev)
* Once we move to full device tree support this will vanish off. * Once we move to full device tree support this will vanish off.
*/ */
if (!pdev->dev.dma_mask) if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &ehci_s5p_dma_mask; pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
if (!pdev->dev.coherent_dma_mask) if (!pdev->dev.coherent_dma_mask)
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);

View File

@ -58,8 +58,6 @@ static int ehci_spear_drv_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend, static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend,
ehci_spear_drv_resume); ehci_spear_drv_resume);
static u64 spear_ehci_dma_mask = DMA_BIT_MASK(32);
static int spear_ehci_hcd_drv_probe(struct platform_device *pdev) static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
{ {
struct usb_hcd *hcd ; struct usb_hcd *hcd ;
@ -84,7 +82,9 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
* Once we have dma capability bindings this can go away. * Once we have dma capability bindings this can go away.
*/ */
if (!pdev->dev.dma_mask) if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &spear_ehci_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);
usbh_clk = devm_clk_get(&pdev->dev, NULL); usbh_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(usbh_clk)) { if (IS_ERR(usbh_clk)) {

View File

@ -637,8 +637,6 @@ static void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)
writel(val, base + TEGRA_USB_PORTSC1); writel(val, base + TEGRA_USB_PORTSC1);
} }
static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);
static int tegra_ehci_probe(struct platform_device *pdev) static int tegra_ehci_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
@ -661,7 +659,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)
* Once we have dma capability bindings this can go away. * Once we have dma capability bindings this can go away.
*/ */
if (!pdev->dev.dma_mask) if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &tegra_ehci_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);
setup_vbus_gpio(pdev, pdata); setup_vbus_gpio(pdev, pdata);

View File

@ -504,8 +504,6 @@ static const struct of_device_id at91_ohci_dt_ids[] = {
MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids); MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids);
static u64 at91_ohci_dma_mask = DMA_BIT_MASK(32);
static int ohci_at91_of_init(struct platform_device *pdev) static int ohci_at91_of_init(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
@ -522,7 +520,9 @@ static int ohci_at91_of_init(struct platform_device *pdev)
* Once we have dma capability bindings this can go away. * Once we have dma capability bindings this can go away.
*/ */
if (!pdev->dev.dma_mask) if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &at91_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); pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) if (!pdata)

View File

@ -98,8 +98,6 @@ static const struct hc_driver exynos_ohci_hc_driver = {
.start_port_reset = ohci_start_port_reset, .start_port_reset = ohci_start_port_reset,
}; };
static u64 ohci_exynos_dma_mask = DMA_BIT_MASK(32);
static int exynos_ohci_probe(struct platform_device *pdev) static int exynos_ohci_probe(struct platform_device *pdev)
{ {
struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
@ -117,7 +115,7 @@ static int exynos_ohci_probe(struct platform_device *pdev)
* Once we move to full device tree support this will vanish off. * Once we move to full device tree support this will vanish off.
*/ */
if (!pdev->dev.dma_mask) if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &ohci_exynos_dma_mask; pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
if (!pdev->dev.coherent_dma_mask) if (!pdev->dev.coherent_dma_mask)
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);

View File

@ -114,8 +114,6 @@ static const struct hc_driver ohci_omap3_hc_driver = {
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static u64 omap_ohci_dma_mask = DMA_BIT_MASK(32);
/* /*
* configure so an HC device and id are always provided * configure so an HC device and id are always provided
* always called with process context; sleeping is OK * always called with process context; sleeping is OK
@ -168,8 +166,10 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)
* Since shared usb code relies on it, set it here for now. * Since shared usb code relies on it, set it here for now.
* Once we have dma capability bindings this can go away. * Once we have dma capability bindings this can go away.
*/ */
if (!pdev->dev.dma_mask) if (!dev->dma_mask)
pdev->dev.dma_mask = &omap_ohci_dma_mask; dev->dma_mask = &dev->coherent_dma_mask;
if (!dev->coherent_dma_mask)
dev->coherent_dma_mask = DMA_BIT_MASK(32);
hcd = usb_create_hcd(&ohci_omap3_hc_driver, dev, hcd = usb_create_hcd(&ohci_omap3_hc_driver, dev,
dev_name(dev)); dev_name(dev));

View File

@ -282,8 +282,6 @@ static const struct of_device_id pxa_ohci_dt_ids[] = {
MODULE_DEVICE_TABLE(of, 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) static int ohci_pxa_of_init(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; 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. * Once we have dma capability bindings this can go away.
*/ */
if (!pdev->dev.dma_mask) 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); pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) if (!pdata)

View File

@ -91,8 +91,6 @@ static const struct hc_driver ohci_spear_hc_driver = {
.start_port_reset = ohci_start_port_reset, .start_port_reset = ohci_start_port_reset,
}; };
static u64 spear_ohci_dma_mask = DMA_BIT_MASK(32);
static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
{ {
const struct hc_driver *driver = &ohci_spear_hc_driver; const struct hc_driver *driver = &ohci_spear_hc_driver;
@ -114,7 +112,9 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
* Once we have dma capability bindings this can go away. * Once we have dma capability bindings this can go away.
*/ */
if (!pdev->dev.dma_mask) if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &spear_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);
usbh_clk = devm_clk_get(&pdev->dev, NULL); usbh_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(usbh_clk)) { if (IS_ERR(usbh_clk)) {

View File

@ -60,8 +60,6 @@ static const struct hc_driver uhci_platform_hc_driver = {
.hub_control = uhci_hub_control, .hub_control = uhci_hub_control,
}; };
static u64 platform_uhci_dma_mask = DMA_BIT_MASK(32);
static int uhci_hcd_platform_probe(struct platform_device *pdev) static int uhci_hcd_platform_probe(struct platform_device *pdev)
{ {
struct usb_hcd *hcd; struct usb_hcd *hcd;
@ -78,7 +76,9 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev)
* Once we have dma capability bindings this can go away. * Once we have dma capability bindings this can go away.
*/ */
if (!pdev->dev.dma_mask) if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &platform_uhci_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);
hcd = usb_create_hcd(&uhci_platform_hc_driver, &pdev->dev, hcd = usb_create_hcd(&uhci_platform_hc_driver, &pdev->dev,
pdev->name); pdev->name);