lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Fri,  4 Jan 2013 00:31:10 +0200
From:	Pantelis Antoniou <panto@...oniou-consulting.com>
To:	Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Cc:	linux-kernel@...r.kernel.org, Matt Porter <mporter@...com>,
	Russ Dill <Russ.Dill@...com>,
	Koen Kooi <koen@...inion.thruhere.net>,
	Pantelis Antoniou <panto@...oniou-consulting.com>
Subject: [PATCH] platform: Fix platform device resource linking

Platform device removal uncovered a number of problems with
the way resources are handled in the core platform code.

Resources now form child/parent linkages and this requires
proper linking of the resources. On top of that the OF core
directly creates it's own platform devices. Simplify things
by providing helper functions that manage the linking properly.

Two functions are provided:

platform_device_link_resources(), which links all the
linkable resources (if not already linked).

and platform_device_unlink_resources(), which unlinks all the
resources.

Signed-off-by: Pantelis Antoniou <panto@...oniou-consulting.com>
---
 drivers/base/platform.c         | 124 +++++++++++++++++++++++++++-------------
 include/linux/platform_device.h |   4 ++
 2 files changed, 87 insertions(+), 41 deletions(-)

diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index c0b8df3..dab9552 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -270,6 +270,80 @@ int platform_device_add_data(struct platform_device *pdev, const void *data,
 }
 EXPORT_SYMBOL_GPL(platform_device_add_data);
 
+static struct resource *platform_device_parent_resource(
+		struct platform_device *pdev, struct resource *r)
+{
+	unsigned long type;
+
+	if (r->parent)
+		return r->parent;
+
+	type = resource_type(r);
+	switch (type) {
+		case IORESOURCE_MEM:
+			return &iomem_resource;
+		case IORESOURCE_IO:
+			return &ioport_resource;
+		/* TODO: What about the other resources? */
+		default:
+			break;
+	}
+	pr_debug("%s: no parent for resource %p type 0x%lx\n",
+			dev_name(&pdev->dev), r, resource_type(r));
+	return NULL;
+}
+
+int platform_device_unlink_resources(struct platform_device *pdev)
+{
+	struct resource *r;
+	int i;
+
+	for (i = pdev->num_resources - 1; i >= 0; i--) {
+		r = &pdev->resource[i];
+		if (r->parent == NULL)
+			continue;
+		release_resource(r);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(platform_device_unlink_resources);
+
+int platform_device_link_resources(struct platform_device *pdev)
+{
+	int i;
+	struct resource *p, *r;
+
+	for (i = 0; i < pdev->num_resources; i++) {
+		r = &pdev->resource[i];
+
+		if (r->name == NULL)
+			r->name = dev_name(&pdev->dev);
+
+		/* already linked */
+		if (r->parent != NULL)
+			continue;
+
+		p = platform_device_parent_resource(pdev, r);
+		if (p && insert_resource(p, r)) {
+			pr_err("%s: failed to claim resource %d\n",
+			       dev_name(&pdev->dev), i);
+			goto fail;
+		}
+	}
+
+	return 0;
+
+fail:
+	while (--i >= 0) {
+		r = &pdev->resource[i];
+		if (r->parent == NULL)
+			continue;
+		release_resource(r);
+	}
+	return -EBUSY;
+}
+EXPORT_SYMBOL_GPL(platform_device_link_resources);
+
 /**
  * platform_device_add - add a platform device to device hierarchy
  * @pdev: platform device we're adding
@@ -279,7 +353,7 @@ EXPORT_SYMBOL_GPL(platform_device_add_data);
  */
 int platform_device_add(struct platform_device *pdev)
 {
-	int i, ret;
+	int ret;
 
 	if (!pdev)
 		return -EINVAL;
@@ -311,28 +385,10 @@ int platform_device_add(struct platform_device *pdev)
 		break;
 	}
 
-	for (i = 0; i < pdev->num_resources; i++) {
-		struct resource *p, *r = &pdev->resource[i];
-
-		if (r->name == NULL)
-			r->name = dev_name(&pdev->dev);
-
-		p = r->parent;
-		if (!p) {
-			if (resource_type(r) == IORESOURCE_MEM)
-				p = &iomem_resource;
-			else if (resource_type(r) == IORESOURCE_IO)
-				p = &ioport_resource;
-		}
-
-		if (p && insert_resource(p, r)) {
-			printk(KERN_ERR
-			       "%s: failed to claim resource %d\n",
-			       dev_name(&pdev->dev), i);
-			ret = -EBUSY;
-			goto failed;
-		}
-	}
+	/* make sure the resources are linked properly */
+	ret = platform_device_link_resources(pdev);
+	if (ret != 0)
+		goto failed_res;
 
 	pr_debug("Registering platform device '%s'. Parent at %s\n",
 		 dev_name(&pdev->dev), dev_name(pdev->dev.parent));
@@ -341,20 +397,14 @@ int platform_device_add(struct platform_device *pdev)
 	if (ret == 0)
 		return ret;
 
- failed:
+	platform_device_unlink_resources(pdev);
+
+ failed_res:
 	if (pdev->id_auto) {
 		ida_simple_remove(&platform_devid_ida, pdev->id);
 		pdev->id = PLATFORM_DEVID_AUTO;
 	}
 
-	while (--i >= 0) {
-		struct resource *r = &pdev->resource[i];
-		unsigned long type = resource_type(r);
-
-		if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
-			release_resource(r);
-	}
-
  err_out:
 	return ret;
 }
@@ -370,8 +420,6 @@ EXPORT_SYMBOL_GPL(platform_device_add);
  */
 void platform_device_del(struct platform_device *pdev)
 {
-	int i;
-
 	if (pdev) {
 		device_del(&pdev->dev);
 
@@ -380,13 +428,7 @@ void platform_device_del(struct platform_device *pdev)
 			pdev->id = PLATFORM_DEVID_AUTO;
 		}
 
-		for (i = 0; i < pdev->num_resources; i++) {
-			struct resource *r = &pdev->resource[i];
-			unsigned long type = resource_type(r);
-
-			if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
-				release_resource(r);
-		}
+		platform_device_unlink_resources(pdev);
 	}
 }
 EXPORT_SYMBOL_GPL(platform_device_del);
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index a9ded9a..e48c2d5 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -293,4 +293,8 @@ extern int platform_pm_restore(struct device *dev);
 #define USE_PLATFORM_PM_SLEEP_OPS
 #endif
 
+/* helper functions for resource list managment */
+int platform_device_unlink_resources(struct platform_device *pdev);
+int platform_device_link_resources(struct platform_device *pdev);
+
 #endif /* _PLATFORM_DEVICE_H_ */
-- 
1.7.12

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists