From a614db9ae9377f102d3fc35ca52efd93454f7a77 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 28 Apr 2014 18:20:09 -0500 Subject: [PATCH] powerpc/fsl-rio: Fix fsl_rio_setup error paths and use-after-unmap 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 Cc: Liu Gang --- 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 | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index cf2b0840a672..c04b718307c8 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -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; } -- 2.39.2