Skip to content

Commit

Permalink
Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git…
Browse files Browse the repository at this point in the history
…/davej/cpufreq

* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq:
  [CPUFREQ] Powernow-k8: support family 0xf with 2 low p-states
  [CPUFREQ] fix (utter) cpufreq_add_dev mess
  [CPUFREQ] Cleanup locking in conservative governor
  [CPUFREQ] Cleanup locking in ondemand governor
  [CPUFREQ] Mark policy_rwsem as going static in cpufreq.c wont be exported
  [CPUFREQ] Eliminate the recent lockdep warnings in cpufreq
  • Loading branch information
Linus Torvalds committed Jul 8, 2009
2 parents 728b690 + a2e1b4c commit b4b21ca
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 123 deletions.
10 changes: 10 additions & 0 deletions Documentation/feature-removal-schedule.txt
Original file line number Diff line number Diff line change
Expand Up @@ -458,3 +458,13 @@ Why: Remove the old legacy 32bit machine check code. This has been
but the old version has been kept around for easier testing. Note this
doesn't impact the old P5 and WinChip machine check handlers.
Who: Andi Kleen <andi@firstfloor.org>

----------------------------

What: lock_policy_rwsem_* and unlock_policy_rwsem_* will not be
exported interface anymore.
When: 2.6.33
Why: cpu_policy_rwsem has a new cleaner definition making it local to
cpufreq core and contained inside cpufreq.c. Other dependent
drivers should not use it in order to safely avoid lockdep issues.
Who: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
30 changes: 11 additions & 19 deletions arch/x86/kernel/cpu/cpufreq/powernow-k8.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ static int transition_pstate(struct powernow_k8_data *data, u32 pstate)
static int transition_fid_vid(struct powernow_k8_data *data,
u32 reqfid, u32 reqvid)
{
if (core_voltage_pre_transition(data, reqvid))
if (core_voltage_pre_transition(data, reqvid, reqfid))
return 1;

if (core_frequency_transition(data, reqfid))
Expand Down Expand Up @@ -327,17 +327,20 @@ static int transition_fid_vid(struct powernow_k8_data *data,

/* Phase 1 - core voltage transition ... setup voltage */
static int core_voltage_pre_transition(struct powernow_k8_data *data,
u32 reqvid)
u32 reqvid, u32 reqfid)
{
u32 rvosteps = data->rvo;
u32 savefid = data->currfid;
u32 maxvid, lo;
u32 maxvid, lo, rvomult = 1;

dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, "
"reqvid 0x%x, rvo 0x%x\n",
smp_processor_id(),
data->currfid, data->currvid, reqvid, data->rvo);

if ((savefid < LO_FID_TABLE_TOP) && (reqfid < LO_FID_TABLE_TOP))
rvomult = 2;
rvosteps *= rvomult;
rdmsr(MSR_FIDVID_STATUS, lo, maxvid);
maxvid = 0x1f & (maxvid >> 16);
dprintk("ph1 maxvid=0x%x\n", maxvid);
Expand All @@ -351,7 +354,8 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data,
return 1;
}

while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) {
while ((rvosteps > 0) &&
((rvomult * data->rvo + data->currvid) > reqvid)) {
if (data->currvid == maxvid) {
rvosteps = 0;
} else {
Expand Down Expand Up @@ -384,13 +388,6 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
u32 vcoreqfid, vcocurrfid, vcofiddiff;
u32 fid_interval, savevid = data->currvid;

if ((reqfid < HI_FID_TABLE_BOTTOM) &&
(data->currfid < HI_FID_TABLE_BOTTOM)) {
printk(KERN_ERR PFX "ph2: illegal lo-lo transition "
"0x%x 0x%x\n", reqfid, data->currfid);
return 1;
}

if (data->currfid == reqfid) {
printk(KERN_ERR PFX "ph2 null fid transition 0x%x\n",
data->currfid);
Expand All @@ -407,6 +404,9 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid
: vcoreqfid - vcocurrfid;

if ((reqfid <= LO_FID_TABLE_TOP) && (data->currfid <= LO_FID_TABLE_TOP))
vcofiddiff = 0;

while (vcofiddiff > 2) {
(data->currfid & 1) ? (fid_interval = 1) : (fid_interval = 2);

Expand Down Expand Up @@ -1081,14 +1081,6 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
return 0;
}

if ((fid < HI_FID_TABLE_BOTTOM) &&
(data->currfid < HI_FID_TABLE_BOTTOM)) {
printk(KERN_ERR PFX
"ignoring illegal change in lo freq table-%x to 0x%x\n",
data->currfid, fid);
return 1;
}

dprintk("cpu %d, changing to fid 0x%x, vid 0x%x\n",
smp_processor_id(), fid, vid);
freqs.old = find_khz_freq_from_fid(data->currfid);
Expand Down
3 changes: 2 additions & 1 deletion arch/x86/kernel/cpu/cpufreq/powernow-k8.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ struct pst_s {

#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "powernow-k8", msg)

static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid);
static int core_voltage_pre_transition(struct powernow_k8_data *data,
u32 reqvid, u32 regfid);
static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvid);
static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid);

Expand Down
69 changes: 42 additions & 27 deletions drivers/cpufreq/cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,10 @@ static struct kobj_type ktype_cpufreq = {
* cpufreq_add_dev - add a CPU device
*
* Adds the cpufreq interface for a CPU device.
*
* The Oracle says: try running cpufreq registration/unregistration concurrently
* with with cpu hotplugging and all hell will break loose. Tried to clean this
* mess up, but more thorough testing is needed. - Mathieu
*/
static int cpufreq_add_dev(struct sys_device *sys_dev)
{
Expand Down Expand Up @@ -804,23 +808,21 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
goto nomem_out;
}
if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL)) {
kfree(policy);
ret = -ENOMEM;
goto nomem_out;
goto err_free_policy;
}
if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) {
free_cpumask_var(policy->cpus);
kfree(policy);
ret = -ENOMEM;
goto nomem_out;
goto err_free_cpumask;
}

policy->cpu = cpu;
cpumask_copy(policy->cpus, cpumask_of(cpu));

/* Initially set CPU itself as the policy_cpu */
per_cpu(policy_cpu, cpu) = cpu;
lock_policy_rwsem_write(cpu);
ret = (lock_policy_rwsem_write(cpu) < 0);
WARN_ON(ret);

init_completion(&policy->kobj_unregister);
INIT_WORK(&policy->update, handle_update);
Expand All @@ -833,7 +835,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
ret = cpufreq_driver->init(policy);
if (ret) {
dprintk("initialization failed\n");
goto err_out;
goto err_unlock_policy;
}
policy->user_policy.min = policy->min;
policy->user_policy.max = policy->max;
Expand All @@ -858,15 +860,21 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
/* Check for existing affected CPUs.
* They may not be aware of it due to CPU Hotplug.
*/
managed_policy = cpufreq_cpu_get(j); /* FIXME: Where is this released? What about error paths? */
managed_policy = cpufreq_cpu_get(j);
if (unlikely(managed_policy)) {

/* Set proper policy_cpu */
unlock_policy_rwsem_write(cpu);
per_cpu(policy_cpu, cpu) = managed_policy->cpu;

if (lock_policy_rwsem_write(cpu) < 0)
goto err_out_driver_exit;
if (lock_policy_rwsem_write(cpu) < 0) {
/* Should not go through policy unlock path */
if (cpufreq_driver->exit)
cpufreq_driver->exit(policy);
ret = -EBUSY;
cpufreq_cpu_put(managed_policy);
goto err_free_cpumask;
}

spin_lock_irqsave(&cpufreq_driver_lock, flags);
cpumask_copy(managed_policy->cpus, policy->cpus);
Expand All @@ -877,12 +885,14 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
ret = sysfs_create_link(&sys_dev->kobj,
&managed_policy->kobj,
"cpufreq");
if (ret)
goto err_out_driver_exit;

cpufreq_debug_enable_ratelimit();
ret = 0;
goto err_out_driver_exit; /* call driver->exit() */
if (!ret)
cpufreq_cpu_put(managed_policy);
/*
* Success. We only needed to be added to the mask.
* Call driver->exit() because only the cpu parent of
* the kobj needed to call init().
*/
goto out_driver_exit; /* call driver->exit() */
}
}
#endif
Expand All @@ -892,25 +902,25 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj,
"cpufreq");
if (ret)
goto err_out_driver_exit;
goto out_driver_exit;

/* 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_driver_exit;
goto err_out_kobj_put;
drv_attr++;
}
if (cpufreq_driver->get) {
ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
if (ret)
goto err_out_driver_exit;
goto err_out_kobj_put;
}
if (cpufreq_driver->target) {
ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
if (ret)
goto err_out_driver_exit;
goto err_out_kobj_put;
}

spin_lock_irqsave(&cpufreq_driver_lock, flags);
Expand All @@ -928,12 +938,14 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
continue;

dprintk("CPU %u already managed, adding link\n", j);
cpufreq_cpu_get(cpu);
managed_policy = cpufreq_cpu_get(cpu);
cpu_sys_dev = get_cpu_sysdev(j);
ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
"cpufreq");
if (ret)
if (ret) {
cpufreq_cpu_put(managed_policy);
goto err_out_unregister;
}
}

policy->governor = NULL; /* to assure that the starting sequence is
Expand Down Expand Up @@ -965,17 +977,20 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
per_cpu(cpufreq_cpu_data, j) = NULL;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);

err_out_kobj_put:
kobject_put(&policy->kobj);
wait_for_completion(&policy->kobj_unregister);

err_out_driver_exit:
out_driver_exit:
if (cpufreq_driver->exit)
cpufreq_driver->exit(policy);

err_out:
err_unlock_policy:
unlock_policy_rwsem_write(cpu);
err_free_cpumask:
free_cpumask_var(policy->cpus);
err_free_policy:
kfree(policy);

nomem_out:
module_put(cpufreq_driver->owner);
module_out:
Expand Down Expand Up @@ -1070,8 +1085,6 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
#endif

unlock_policy_rwsem_write(cpu);

if (cpufreq_driver->target)
__cpufreq_governor(data, CPUFREQ_GOV_STOP);

Expand All @@ -1088,6 +1101,8 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
if (cpufreq_driver->exit)
cpufreq_driver->exit(data);

unlock_policy_rwsem_write(cpu);

free_cpumask_var(data->related_cpus);
free_cpumask_var(data->cpus);
kfree(data);
Expand Down
Loading

0 comments on commit b4b21ca

Please sign in to comment.