dmaengine: shdma: Fix up fallout from runtime PM changes.
Paul Mundt [Tue, 31 May 2011 06:53:03 +0000 (15:53 +0900)]
The runtime PM changes introduce sh_dmae_rst() wrapping via the
runtime_resume helper, depending on dev_get_drvdata() to fetch the
platform data needed for the DMAOR initialization default at a time
where drvdata hasn't yet been established by the probe path, resulting
in general probe misery:

        Unable to handle kernel NULL pointer dereference at virtual address 000000c4
        pc = 8025adee
        *pde = 00000000
        Oops: 0000 [#1]
        Modules linked in:

        Pid : 1, Comm:           swapper
        CPU : 0                  Not tainted  (3.0.0-rc1-00012-g9436b4a-dirty #1456)

        PC is at sh_dmae_rst+0x28/0x86
        PR is at sh_dmae_rst+0x22/0x86
        PC  : 8025adee SP  : 9e803d10 SR  : 400080f1 TEA : 000000c4
        R0  : 000000c4 R1  : 0000fff8 R2  : 00000000 R3  : 00000040
        R4  : 000000f0 R5  : 00000000 R6  : 00000000 R7  : 804f184c
        R8  : 00000000 R9  : 804dd0e8 R10 : 80283204 R11 : ffffffda
        R12 : 000000a0 R13 : 804dd18c R14 : 9e803d10
        MACH: 00000000 MACL: 00008f20 GBR : 00000000 PR  : 8025ade8

        Call trace:
        [<8025ae70>] sh_dmae_runtime_resume+0x24/0x34
        [<80283238>] pm_generic_runtime_resume+0x34/0x3c
        [<80283370>] rpm_callback+0x4a/0x7e
        [<80283efc>] rpm_resume+0x240/0x384
        [<80283f54>] rpm_resume+0x298/0x384
        [<8028428c>] __pm_runtime_resume+0x44/0x7c
        [<8038a358>] __ioremap_caller+0x0/0xec
        [<80284296>] __pm_runtime_resume+0x4e/0x7c
        [<8038a358>] __ioremap_caller+0x0/0xec
        [<80666254>] sh_dmae_probe+0x180/0x6a0
        [<802803ae>] platform_drv_probe+0x26/0x2e

Fix up the ordering accordingly.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>

drivers/dma/shdma.c

index 636e409..727e76f 100644 (file)
@@ -1144,6 +1144,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
        /* platform data */
        shdev->pdata = pdata;
 
+       platform_set_drvdata(pdev, shdev);
+
        pm_runtime_enable(&pdev->dev);
        pm_runtime_get_sync(&pdev->dev);
 
@@ -1256,7 +1258,6 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
 
        pm_runtime_put(&pdev->dev);
 
-       platform_set_drvdata(pdev, shdev);
        dma_async_device_register(&shdev->common);
 
        return err;
@@ -1278,6 +1279,8 @@ rst_err:
 
        if (dmars)
                iounmap(shdev->dmars);
+
+       platform_set_drvdata(pdev, NULL);
 emapdmars:
        iounmap(shdev->chan_reg);
        synchronize_rcu();
@@ -1316,6 +1319,8 @@ static int __exit sh_dmae_remove(struct platform_device *pdev)
                iounmap(shdev->dmars);
        iounmap(shdev->chan_reg);
 
+       platform_set_drvdata(pdev, NULL);
+
        synchronize_rcu();
        kfree(shdev);