opp: Allow dev_pm_opp_get_opp_table() to return -EPROBE_DEFER
[linux-2.6-microblaze.git] / drivers / opp / core.c
index 0c8c74a..9f16769 100644 (file)
@@ -831,6 +831,37 @@ static int _set_required_opps(struct device *dev,
        return ret;
 }
 
+/**
+ * dev_pm_opp_set_bw() - sets bandwidth levels corresponding to an opp
+ * @dev:       device for which we do this operation
+ * @opp:       opp based on which the bandwidth levels are to be configured
+ *
+ * This configures the bandwidth to the levels specified by the OPP. However
+ * if the OPP specified is NULL the bandwidth levels are cleared out.
+ *
+ * Return: 0 on success or a negative error value.
+ */
+int dev_pm_opp_set_bw(struct device *dev, struct dev_pm_opp *opp)
+{
+       struct opp_table *opp_table;
+       int ret;
+
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table)) {
+               dev_err(dev, "%s: device opp table doesn't exist\n", __func__);
+               return PTR_ERR(opp_table);
+       }
+
+       if (opp)
+               ret = _set_opp_bw(opp_table, opp, dev, false);
+       else
+               ret = _set_opp_bw(opp_table, NULL, dev, true);
+
+       dev_pm_opp_put_opp_table(opp_table);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_set_bw);
+
 /**
  * dev_pm_opp_set_rate() - Configure new OPP based on frequency
  * @dev:        device for which we do this operation
@@ -1032,7 +1063,7 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
         */
        opp_table = kzalloc(sizeof(*opp_table), GFP_KERNEL);
        if (!opp_table)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        mutex_init(&opp_table->lock);
        mutex_init(&opp_table->genpd_virt_dev_lock);
@@ -1043,8 +1074,8 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
 
        opp_dev = _add_opp_dev(dev, opp_table);
        if (!opp_dev) {
-               kfree(opp_table);
-               return NULL;
+               ret = -ENOMEM;
+               goto err;
        }
 
        _of_init_opp_table(opp_table, dev, index);
@@ -1053,16 +1084,21 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
        opp_table->clk = clk_get(dev, NULL);
        if (IS_ERR(opp_table->clk)) {
                ret = PTR_ERR(opp_table->clk);
-               if (ret != -EPROBE_DEFER)
-                       dev_dbg(dev, "%s: Couldn't find clock: %d\n", __func__,
-                               ret);
+               if (ret == -EPROBE_DEFER)
+                       goto err;
+
+               dev_dbg(dev, "%s: Couldn't find clock: %d\n", __func__, ret);
        }
 
        /* Find interconnect path(s) for the device */
        ret = dev_pm_opp_of_find_icc_paths(dev, opp_table);
-       if (ret)
+       if (ret) {
+               if (ret == -EPROBE_DEFER)
+                       goto err;
+
                dev_warn(dev, "%s: Error finding interconnect paths: %d\n",
                         __func__, ret);
+       }
 
        BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head);
        INIT_LIST_HEAD(&opp_table->opp_list);
@@ -1071,6 +1107,10 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
        /* Secure the device table modification */
        list_add(&opp_table->node, &opp_tables);
        return opp_table;
+
+err:
+       kfree(opp_table);
+       return ERR_PTR(ret);
 }
 
 void _get_opp_table_kref(struct opp_table *opp_table)
@@ -1093,7 +1133,7 @@ static struct opp_table *_opp_get_opp_table(struct device *dev, int index)
        if (opp_table) {
                if (!_add_opp_dev_unlocked(dev, opp_table)) {
                        dev_pm_opp_put_opp_table(opp_table);
-                       opp_table = NULL;
+                       opp_table = ERR_PTR(-ENOMEM);
                }
                goto unlock;
        }
@@ -1537,8 +1577,8 @@ struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev,
        struct opp_table *opp_table;
 
        opp_table = dev_pm_opp_get_opp_table(dev);
-       if (!opp_table)
-               return ERR_PTR(-ENOMEM);
+       if (IS_ERR(opp_table))
+               return opp_table;
 
        /* Make sure there are no concurrent readers while updating opp_table */
        WARN_ON(!list_empty(&opp_table->opp_list));
@@ -1596,8 +1636,8 @@ struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, const char *name)
        struct opp_table *opp_table;
 
        opp_table = dev_pm_opp_get_opp_table(dev);
-       if (!opp_table)
-               return ERR_PTR(-ENOMEM);
+       if (IS_ERR(opp_table))
+               return opp_table;
 
        /* Make sure there are no concurrent readers while updating opp_table */
        WARN_ON(!list_empty(&opp_table->opp_list));
@@ -1689,8 +1729,8 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev,
        int ret, i;
 
        opp_table = dev_pm_opp_get_opp_table(dev);
-       if (!opp_table)
-               return ERR_PTR(-ENOMEM);
+       if (IS_ERR(opp_table))
+               return opp_table;
 
        /* This should be called before OPPs are initialized */
        if (WARN_ON(!list_empty(&opp_table->opp_list))) {
@@ -1799,8 +1839,8 @@ struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char *name)
        int ret;
 
        opp_table = dev_pm_opp_get_opp_table(dev);
-       if (!opp_table)
-               return ERR_PTR(-ENOMEM);
+       if (IS_ERR(opp_table))
+               return opp_table;
 
        /* This should be called before OPPs are initialized */
        if (WARN_ON(!list_empty(&opp_table->opp_list))) {
@@ -1867,8 +1907,8 @@ struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev,
                return ERR_PTR(-EINVAL);
 
        opp_table = dev_pm_opp_get_opp_table(dev);
-       if (!opp_table)
-               return ERR_PTR(-ENOMEM);
+       if (!IS_ERR(opp_table))
+               return opp_table;
 
        /* This should be called before OPPs are initialized */
        if (WARN_ON(!list_empty(&opp_table->opp_list))) {
@@ -1948,8 +1988,8 @@ struct opp_table *dev_pm_opp_attach_genpd(struct device *dev,
        const char **name = names;
 
        opp_table = dev_pm_opp_get_opp_table(dev);
-       if (!opp_table)
-               return ERR_PTR(-ENOMEM);
+       if (IS_ERR(opp_table))
+               return opp_table;
 
        /*
         * If the genpd's OPP table isn't already initialized, parsing of the
@@ -2119,8 +2159,8 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
        int ret;
 
        opp_table = dev_pm_opp_get_opp_table(dev);
-       if (!opp_table)
-               return -ENOMEM;
+       if (IS_ERR(opp_table))
+               return PTR_ERR(opp_table);
 
        /* Fix regulator count for dynamic OPPs */
        opp_table->regulator_count = 1;