Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/shli/md
[linux-2.6-block.git] / drivers / opp / of.c
index a71ff3acca0f1d398d2f459d78d5233f7c05f87a..5a4b47958073ee4526772f35e8b5614cc3c63418 100644 (file)
@@ -297,15 +297,21 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
  * removed by dev_pm_opp_remove.
  *
  * Return:
- * 0           On success OR
+ * Valid OPP pointer:
+ *             On success
+ * NULL:
  *             Duplicate OPPs (both freq and volt are same) and opp->available
- * -EEXIST     Freq are same and volt are different OR
+ *             OR if the OPP is not supported by hardware.
+ * ERR_PTR(-EEXIST):
+ *             Freq are same and volt are different OR
  *             Duplicate OPPs (both freq and volt are same) and !opp->available
- * -ENOMEM     Memory allocation failure
- * -EINVAL     Failed parsing the OPP node
+ * ERR_PTR(-ENOMEM):
+ *             Memory allocation failure
+ * ERR_PTR(-EINVAL):
+ *             Failed parsing the OPP node
  */
-static int _opp_add_static_v2(struct opp_table *opp_table, struct device *dev,
-                             struct device_node *np)
+static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
+               struct device *dev, struct device_node *np)
 {
        struct dev_pm_opp *new_opp;
        u64 rate = 0;
@@ -315,7 +321,7 @@ static int _opp_add_static_v2(struct opp_table *opp_table, struct device *dev,
 
        new_opp = _opp_allocate(opp_table);
        if (!new_opp)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        ret = of_property_read_u64(np, "opp-hz", &rate);
        if (ret < 0) {
@@ -390,12 +396,12 @@ static int _opp_add_static_v2(struct opp_table *opp_table, struct device *dev,
         * frequency/voltage list.
         */
        blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ADD, new_opp);
-       return 0;
+       return new_opp;
 
 free_opp:
        _opp_free(new_opp);
 
-       return ret;
+       return ERR_PTR(ret);
 }
 
 /* Initializes OPP tables based on new bindings */
@@ -415,14 +421,15 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
 
        /* We have opp-table node now, iterate over it and add OPPs */
        for_each_available_child_of_node(opp_table->np, np) {
-               count++;
-
-               ret = _opp_add_static_v2(opp_table, dev, np);
-               if (ret) {
+               opp = _opp_add_static_v2(opp_table, dev, np);
+               if (IS_ERR(opp)) {
+                       ret = PTR_ERR(opp);
                        dev_err(dev, "%s: Failed to add OPP, %d\n", __func__,
                                ret);
                        of_node_put(np);
                        goto put_list_kref;
+               } else if (opp) {
+                       count++;
                }
        }
 
@@ -614,16 +621,18 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_remove_table);
 int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask)
 {
        struct device *cpu_dev;
-       int cpu, ret = 0;
+       int cpu, ret;
 
-       WARN_ON(cpumask_empty(cpumask));
+       if (WARN_ON(cpumask_empty(cpumask)))
+               return -ENODEV;
 
        for_each_cpu(cpu, cpumask) {
                cpu_dev = get_cpu_device(cpu);
                if (!cpu_dev) {
                        pr_err("%s: failed to get cpu%d device\n", __func__,
                               cpu);
-                       continue;
+                       ret = -ENODEV;
+                       goto remove_table;
                }
 
                ret = dev_pm_opp_of_add_table(cpu_dev);
@@ -635,12 +644,16 @@ int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask)
                        pr_debug("%s: couldn't find opp table for cpu:%d, %d\n",
                                 __func__, cpu, ret);
 
-                       /* Free all other OPPs */
-                       _dev_pm_opp_cpumask_remove_table(cpumask, cpu);
-                       break;
+                       goto remove_table;
                }
        }
 
+       return 0;
+
+remove_table:
+       /* Free all other OPPs */
+       _dev_pm_opp_cpumask_remove_table(cpumask, cpu);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_add_table);