powerpc/fsl-rio: Fix fsl_rio_setup error paths and use-after-unmap
authorScott Wood <scottwood@freescale.com>
Mon, 28 Apr 2014 23:20:09 +0000 (18:20 -0500)
committerScott Wood <scottwood@freescale.com>
Fri, 9 May 2014 20:49:05 +0000 (15:49 -0500)
Several of the error paths from fsl_rio_setup are missing error
messages.

Worse, fsl_rio_setup initializes several global pointers and does not
NULL them out after freeing/unmapping on error.  This caused
fsl_rio_mcheck_exception() to crash when accessing rio_regs_win which
was non-NULL but had been unmapped.

Signed-off-by: Scott Wood <scottwood@freescale.com>
Cc: Liu Gang <Gang.Liu@freescale.com>
---
Liu Gang, are you sure all of these error conditions are fatal?  Why
does the rio driver fail if rmu is not present (e.g.  on t4240)?

arch/powerpc/sysdev/fsl_rio.c

index cf2b0840a672f893a3b2386154716ef54672dfd7..c04b718307c89837efe57b1df82c97e204e3cde0 100644 (file)
@@ -391,8 +391,10 @@ int fsl_rio_setup(struct platform_device *dev)
        ops->get_inb_message = fsl_get_inb_message;
 
        rmu_node = of_parse_phandle(dev->dev.of_node, "fsl,srio-rmu-handle", 0);
-       if (!rmu_node)
+       if (!rmu_node) {
+               dev_err(&dev->dev, "No valid fsl,srio-rmu-handle property\n");
                goto err_rmu;
+       }
        rc = of_address_to_resource(rmu_node, 0, &rmu_regs);
        if (rc) {
                dev_err(&dev->dev, "Can't get %s property 'reg'\n",
@@ -413,6 +415,7 @@ int fsl_rio_setup(struct platform_device *dev)
        /*set up doobell node*/
        np = of_find_compatible_node(NULL, NULL, "fsl,srio-dbell-unit");
        if (!np) {
+               dev_err(&dev->dev, "No fsl,srio-dbell-unit node\n");
                rc = -ENODEV;
                goto err_dbell;
        }
@@ -441,6 +444,7 @@ int fsl_rio_setup(struct platform_device *dev)
        /*set up port write node*/
        np = of_find_compatible_node(NULL, NULL, "fsl,srio-port-write-unit");
        if (!np) {
+               dev_err(&dev->dev, "No fsl,srio-port-write-unit node\n");
                rc = -ENODEV;
                goto err_pw;
        }
@@ -633,14 +637,18 @@ int fsl_rio_setup(struct platform_device *dev)
        return 0;
 err:
        kfree(pw);
+       pw = NULL;
 err_pw:
        kfree(dbell);
+       dbell = NULL;
 err_dbell:
        iounmap(rmu_regs_win);
+       rmu_regs_win = NULL;
 err_rmu:
        kfree(ops);
 err_ops:
        iounmap(rio_regs_win);
+       rio_regs_win = NULL;
 err_rio_regs:
        return rc;
 }