new helper to create platform devices with dma mask
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Thu, 25 Aug 2011 09:16:00 +0000 (11:16 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 26 Aug 2011 18:31:09 +0000 (11:31 -0700)
compared to the most powerful and already existing helper (namely
platform_device_register_resndata) this allows to specify a dma_mask.
To make eventual extensions later more easy, a struct holding the used
information is created instead of passing the information by function
parameters.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/base/platform.c
include/linux/platform_device.h

index cd71575..4573f5e 100644 (file)
@@ -375,52 +375,64 @@ void platform_device_unregister(struct platform_device *pdev)
 EXPORT_SYMBOL_GPL(platform_device_unregister);
 
 /**
- * platform_device_register_resndata - add a platform-level device with
+ * platform_device_register_full - add a platform-level device with
  * resources and platform-specific data
  *
- * @parent: parent device for the device we're adding
- * @name: base name of the device we're adding
- * @id: instance id
- * @res: set of resources that needs to be allocated for the device
- * @num: number of resources
- * @data: platform specific data for this platform device
- * @size: size of platform specific data
+ * @pdevinfo: data used to create device
  *
  * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
  */
-struct platform_device *platform_device_register_resndata(
-               struct device *parent,
-               const char *name, int id,
-               const struct resource *res, unsigned int num,
-               const void *data, size_t size)
+struct platform_device *platform_device_register_full(
+               struct platform_device_info *pdevinfo)
 {
        int ret = -ENOMEM;
        struct platform_device *pdev;
 
-       pdev = platform_device_alloc(name, id);
+       pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id);
        if (!pdev)
-               goto err;
-
-       pdev->dev.parent = parent;
+               goto err_alloc;
+
+       pdev->dev.parent = pdevinfo->parent;
+
+       if (pdevinfo->dma_mask) {
+               /*
+                * This memory isn't freed when the device is put,
+                * I don't have a nice idea for that though.  Conceptually
+                * dma_mask in struct device should not be a pointer.
+                * See http://thread.gmane.org/gmane.linux.kernel.pci/9081
+                */
+               pdev->dev.dma_mask =
+                       kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
+               if (!pdev->dev.dma_mask)
+                       goto err;
+
+               *pdev->dev.dma_mask = pdevinfo->dma_mask;
+               pdev->dev.coherent_dma_mask = pdevinfo->dma_mask;
+       }
 
-       ret = platform_device_add_resources(pdev, res, num);
+       ret = platform_device_add_resources(pdev,
+                       pdevinfo->res, pdevinfo->num_res);
        if (ret)
                goto err;
 
-       ret = platform_device_add_data(pdev, data, size);
+       ret = platform_device_add_data(pdev,
+                       pdevinfo->data, pdevinfo->size_data);
        if (ret)
                goto err;
 
        ret = platform_device_add(pdev);
        if (ret) {
 err:
+               kfree(pdev->dev.dma_mask);
+
+err_alloc:
                platform_device_put(pdev);
                return ERR_PTR(ret);
        }
 
        return pdev;
 }
-EXPORT_SYMBOL_GPL(platform_device_register_resndata);
+EXPORT_SYMBOL_GPL(platform_device_register_full);
 
 static int platform_drv_probe(struct device *_dev)
 {
index 27bb05a..651a066 100644 (file)
@@ -49,10 +49,54 @@ extern struct resource *platform_get_resource_byname(struct platform_device *, u
 extern int platform_get_irq_byname(struct platform_device *, const char *);
 extern int platform_add_devices(struct platform_device **, int);
 
-extern struct platform_device *platform_device_register_resndata(
+struct platform_device_info {
+               struct device *parent;
+
+               const char *name;
+               int id;
+
+               const struct resource *res;
+               unsigned int num_res;
+
+               const void *data;
+               size_t size_data;
+               u64 dma_mask;
+};
+extern struct platform_device *platform_device_register_full(
+               struct platform_device_info *pdevinfo);
+
+/**
+ * platform_device_register_resndata - add a platform-level device with
+ * resources and platform-specific data
+ *
+ * @parent: parent device for the device we're adding
+ * @name: base name of the device we're adding
+ * @id: instance id
+ * @res: set of resources that needs to be allocated for the device
+ * @num: number of resources
+ * @data: platform specific data for this platform device
+ * @size: size of platform specific data
+ *
+ * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
+ */
+static inline struct platform_device *platform_device_register_resndata(
                struct device *parent, const char *name, int id,
                const struct resource *res, unsigned int num,
-               const void *data, size_t size);
+               const void *data, size_t size) {
+
+       struct platform_device_info pdevinfo = {
+               .parent = parent,
+               .name = name,
+               .id = id,
+               .res = res,
+               .num_res = num,
+               .data = data,
+               .size_data = size,
+               .dma_mask = 0,
+       };
+
+       return platform_device_register_full(&pdevinfo);
+}
 
 /**
  * platform_device_register_simple - add a platform-level device and its resources