Merge tag 'pinctrl-v3.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
[cascardo/linux.git] / drivers / cpufreq / cpufreq.c
index 4473eba..a09a29c 100644 (file)
@@ -535,7 +535,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
 static ssize_t store_##file_name                                       \
 (struct cpufreq_policy *policy, const char *buf, size_t count)         \
 {                                                                      \
-       int ret;                                                        \
+       int ret, temp;                                                  \
        struct cpufreq_policy new_policy;                               \
                                                                        \
        ret = cpufreq_get_policy(&new_policy, policy->cpu);             \
@@ -546,8 +546,10 @@ static ssize_t store_##file_name                                   \
        if (ret != 1)                                                   \
                return -EINVAL;                                         \
                                                                        \
+       temp = new_policy.object;                                       \
        ret = cpufreq_set_policy(policy, &new_policy);          \
-       policy->user_policy.object = policy->object;                    \
+       if (!ret)                                                       \
+               policy->user_policy.object = temp;                      \
                                                                        \
        return ret ? ret : count;                                       \
 }
@@ -898,46 +900,31 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy,
        struct freq_attr **drv_attr;
        int ret = 0;
 
-       /* prepare interface data */
-       ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
-                                  &dev->kobj, "cpufreq");
-       if (ret)
-               return ret;
-
        /* set up files for this cpu device */
        drv_attr = cpufreq_driver->attr;
        while ((drv_attr) && (*drv_attr)) {
                ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
                if (ret)
-                       goto err_out_kobj_put;
+                       return ret;
                drv_attr++;
        }
        if (cpufreq_driver->get) {
                ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
                if (ret)
-                       goto err_out_kobj_put;
+                       return ret;
        }
 
        ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
        if (ret)
-               goto err_out_kobj_put;
+               return ret;
 
        if (cpufreq_driver->bios_limit) {
                ret = sysfs_create_file(&policy->kobj, &bios_limit.attr);
                if (ret)
-                       goto err_out_kobj_put;
+                       return ret;
        }
 
-       ret = cpufreq_add_dev_symlink(policy);
-       if (ret)
-               goto err_out_kobj_put;
-
-       return ret;
-
-err_out_kobj_put:
-       kobject_put(&policy->kobj);
-       wait_for_completion(&policy->kobj_unregister);
-       return ret;
+       return cpufreq_add_dev_symlink(policy);
 }
 
 static void cpufreq_init_policy(struct cpufreq_policy *policy)
@@ -1196,6 +1183,8 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
                goto err_set_policy_cpu;
        }
 
+       down_write(&policy->rwsem);
+
        /* related cpus should atleast have policy->cpus */
        cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus);
 
@@ -1208,9 +1197,17 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
        if (!recover_policy) {
                policy->user_policy.min = policy->min;
                policy->user_policy.max = policy->max;
+
+               /* prepare interface data */
+               ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
+                                          &dev->kobj, "cpufreq");
+               if (ret) {
+                       pr_err("%s: failed to init policy->kobj: %d\n",
+                              __func__, ret);
+                       goto err_init_policy_kobj;
+               }
        }
 
-       down_write(&policy->rwsem);
        write_lock_irqsave(&cpufreq_driver_lock, flags);
        for_each_cpu(j, policy->cpus)
                per_cpu(cpufreq_cpu_data, j) = policy;
@@ -1288,8 +1285,13 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
        up_write(&policy->rwsem);
 
        kobject_uevent(&policy->kobj, KOBJ_ADD);
+
        up_read(&cpufreq_rwsem);
 
+       /* Callback for handling stuff after policy is ready */
+       if (cpufreq_driver->ready)
+               cpufreq_driver->ready(policy);
+
        pr_debug("initialization complete\n");
 
        return 0;
@@ -1301,6 +1303,11 @@ err_get_freq:
                per_cpu(cpufreq_cpu_data, j) = NULL;
        write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
+       if (!recover_policy) {
+               kobject_put(&policy->kobj);
+               wait_for_completion(&policy->kobj_unregister);
+       }
+err_init_policy_kobj:
        up_write(&policy->rwsem);
 
        if (cpufreq_driver->exit)