From 7096d0422153ffcc2264eef652fc3a7bca3e6d3c Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Wed, 20 Oct 2010 11:45:13 -0600 Subject: of/device: Rework to use common platform_device_alloc() for allocating devices The current code allocates and manages platform_devices created from the device tree manually. It also uses an unsafe shortcut for allocating the platform_device and the resource table at the same time. (which I added in the last rework; sorry). This patch refactors the code to use platform_device_alloc() for allocating new devices. This reduces the amount of custom code implemented by of_platform, eliminates the unsafe alloc trick, and has the side benefit of letting the platform_bus code manage freeing the device data and resources when the device is freed. Signed-off-by: Grant Likely Cc: Benjamin Herrenschmidt Cc: Greg Kroah-Hartman Cc: "David S. Miller" Cc: Michal Simek --- drivers/of/device.c | 27 +++++++-------------------- drivers/of/platform.c | 24 +++++++++++++----------- 2 files changed, 20 insertions(+), 31 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/device.c b/drivers/of/device.c index 92de0eb..45d8653 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -81,29 +81,10 @@ struct device_attribute of_platform_device_attrs[] = { __ATTR_NULL }; -/** - * of_release_dev - free an of device structure when all users of it are finished. - * @dev: device that's been disconnected - * - * Will be called only by the device core when all users of this of device are - * done. - */ -void of_release_dev(struct device *dev) -{ - struct platform_device *ofdev; - - ofdev = to_platform_device(dev); - of_node_put(ofdev->dev.of_node); - kfree(ofdev); -} -EXPORT_SYMBOL(of_release_dev); - -int of_device_register(struct platform_device *ofdev) +int of_device_add(struct platform_device *ofdev) { BUG_ON(ofdev->dev.of_node == NULL); - device_initialize(&ofdev->dev); - /* name and id have to be set so that the platform bus doesn't get * confused on matching */ ofdev->name = dev_name(&ofdev->dev); @@ -117,6 +98,12 @@ int of_device_register(struct platform_device *ofdev) return device_add(&ofdev->dev); } + +int of_device_register(struct platform_device *pdev) +{ + device_initialize(&pdev->dev); + return of_device_add(pdev); +} EXPORT_SYMBOL(of_device_register); void of_device_unregister(struct platform_device *ofdev) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 30726c8..5b4a07f 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -587,20 +587,23 @@ struct platform_device *of_device_alloc(struct device_node *np, int rc, i, num_reg = 0, num_irq; struct resource *res, temp_res; - /* First count how many resources are needed */ + dev = platform_device_alloc("", -1); + if (!dev) + return NULL; + + /* count the io and irq resources */ while (of_address_to_resource(np, num_reg, &temp_res) == 0) num_reg++; num_irq = of_irq_count(np); - /* Allocate memory for both the struct device and the resource table */ - dev = kzalloc(sizeof(*dev) + (sizeof(*res) * (num_reg + num_irq)), - GFP_KERNEL); - if (!dev) - return NULL; - res = (struct resource *) &dev[1]; - /* Populate the resource table */ if (num_irq || num_reg) { + res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL); + if (!res) { + platform_device_put(dev); + return NULL; + } + dev->num_resources = num_reg + num_irq; dev->resource = res; for (i = 0; i < num_reg; i++, res++) { @@ -615,7 +618,6 @@ struct platform_device *of_device_alloc(struct device_node *np, dev->dev.dma_mask = &dev->archdata.dma_mask; #endif dev->dev.parent = parent; - dev->dev.release = of_release_dev; if (bus_id) dev_set_name(&dev->dev, "%s", bus_id); @@ -653,8 +655,8 @@ struct platform_device *of_platform_device_create(struct device_node *np, * to do such, possibly using a device notifier */ - if (of_device_register(dev) != 0) { - of_device_free(dev); + if (of_device_add(dev) != 0) { + platform_device_put(dev); return NULL; } -- cgit v1.1