Merge tag 'mfd-3.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd...
[cascardo/linux.git] / drivers / mfd / mfd-core.c
index adc8ea3..2676492 100644 (file)
@@ -64,7 +64,8 @@ int mfd_cell_disable(struct platform_device *pdev)
 EXPORT_SYMBOL(mfd_cell_disable);
 
 static int mfd_platform_add_cell(struct platform_device *pdev,
-                                const struct mfd_cell *cell)
+                                const struct mfd_cell *cell,
+                                atomic_t *usage_count)
 {
        if (!cell)
                return 0;
@@ -73,11 +74,12 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
        if (!pdev->mfd_cell)
                return -ENOMEM;
 
+       pdev->mfd_cell->usage_count = usage_count;
        return 0;
 }
 
 static int mfd_add_device(struct device *parent, int id,
-                         const struct mfd_cell *cell,
+                         const struct mfd_cell *cell, atomic_t *usage_count,
                          struct resource *mem_base,
                          int irq_base, struct irq_domain *domain)
 {
@@ -123,7 +125,7 @@ static int mfd_add_device(struct device *parent, int id,
                        goto fail_alias;
        }
 
-       ret = mfd_platform_add_cell(pdev, cell);
+       ret = mfd_platform_add_cell(pdev, cell, usage_count);
        if (ret)
                goto fail_alias;
 
@@ -192,12 +194,12 @@ fail_alloc:
 }
 
 int mfd_add_devices(struct device *parent, int id,
-                   struct mfd_cell *cells, int n_devs,
+                   const struct mfd_cell *cells, int n_devs,
                    struct resource *mem_base,
                    int irq_base, struct irq_domain *domain)
 {
        int i;
-       int ret = 0;
+       int ret;
        atomic_t *cnts;
 
        /* initialize reference counting for all cells */
@@ -207,16 +209,19 @@ int mfd_add_devices(struct device *parent, int id,
 
        for (i = 0; i < n_devs; i++) {
                atomic_set(&cnts[i], 0);
-               cells[i].usage_count = &cnts[i];
-               ret = mfd_add_device(parent, id, cells + i, mem_base,
+               ret = mfd_add_device(parent, id, cells + i, cnts + i, mem_base,
                                     irq_base, domain);
                if (ret)
-                       break;
+                       goto fail;
        }
 
-       if (ret)
-               mfd_remove_devices(parent);
+       return 0;
 
+fail:
+       if (i)
+               mfd_remove_devices(parent);
+       else
+               kfree(cnts);
        return ret;
 }
 EXPORT_SYMBOL(mfd_add_devices);
@@ -271,8 +276,8 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)
        for (i = 0; i < n_clones; i++) {
                cell_entry.name = clones[i];
                /* don't give up if a single call fails; just report error */
-               if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0,
-                                  NULL))
+               if (mfd_add_device(pdev->dev.parent, -1, &cell_entry,
+                                  cell_entry.usage_count, NULL, 0, NULL))
                        dev_err(dev, "failed to create platform device '%s'\n",
                                        clones[i]);
        }