Browse Source

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 <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)?
Scott Wood 11 years ago
parent
commit
a614db9ae9
1 changed files with 9 additions and 1 deletions
  1. 9 1
      arch/powerpc/sysdev/fsl_rio.c

+ 9 - 1
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;
 }