diff options
Diffstat (limited to 'drivers/cpufreq/longhaul.c')
| -rw-r--r-- | drivers/cpufreq/longhaul.c | 93 | 
1 files changed, 35 insertions, 58 deletions
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 4ada1cccb05..c913906a719 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -242,7 +242,7 @@ static void do_powersaver(int cx_address, unsigned int mults_index,   * Sets a new clock ratio.   */ -static void longhaul_setstate(struct cpufreq_policy *policy, +static int longhaul_setstate(struct cpufreq_policy *policy,  		unsigned int table_index)  {  	unsigned int mults_index; @@ -258,10 +258,12 @@ static void longhaul_setstate(struct cpufreq_policy *policy,  	/* Safety precautions */  	mult = mults[mults_index & 0x1f];  	if (mult == -1) -		return; +		return -EINVAL; +  	speed = calc_speed(mult);  	if ((speed > highest_speed) || (speed < lowest_speed)) -		return; +		return -EINVAL; +  	/* Voltage transition before frequency transition? */  	if (can_scale_voltage && longhaul_index < table_index)  		dir = 1; @@ -269,8 +271,6 @@ static void longhaul_setstate(struct cpufreq_policy *policy,  	freqs.old = calc_speed(longhaul_get_cpu_mult());  	freqs.new = speed; -	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); -  	pr_debug("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",  			fsb, mult/10, mult%10, print_speed(speed/1000));  retry_loop: @@ -385,12 +385,14 @@ retry_loop:  			goto retry_loop;  		}  	} -	/* Report true CPU frequency */ -	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); -	if (!bm_timeout) +	if (!bm_timeout) {  		printk(KERN_INFO PFX "Warning: Timeout while waiting for "  				"idle PCI bus.\n"); +		return -EBUSY; +	} + +	return 0;  }  /* @@ -475,7 +477,7 @@ static int longhaul_get_ranges(void)  		return -EINVAL;  	} -	longhaul_table = kmalloc((numscales + 1) * sizeof(*longhaul_table), +	longhaul_table = kzalloc((numscales + 1) * sizeof(*longhaul_table),  			GFP_KERNEL);  	if (!longhaul_table)  		return -ENOMEM; @@ -528,6 +530,7 @@ static int longhaul_get_ranges(void)  static void longhaul_setup_voltagescaling(void)  { +	struct cpufreq_frequency_table *freq_pos;  	union msr_longhaul longhaul;  	struct mV_pos minvid, maxvid, vid;  	unsigned int j, speed, pos, kHz_step, numvscales; @@ -606,18 +609,16 @@ static void longhaul_setup_voltagescaling(void)  	/* Calculate kHz for one voltage step */  	kHz_step = (highest_speed - min_vid_speed) / numvscales; -	j = 0; -	while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) { -		speed = longhaul_table[j].frequency; +	cpufreq_for_each_entry(freq_pos, longhaul_table) { +		speed = freq_pos->frequency;  		if (speed > min_vid_speed)  			pos = (speed - min_vid_speed) / kHz_step + minvid.pos;  		else  			pos = minvid.pos; -		longhaul_table[j].driver_data |= mV_vrm_table[pos] << 8; +		freq_pos->driver_data |= mV_vrm_table[pos] << 8;  		vid = vrm_mV_table[mV_vrm_table[pos]];  		printk(KERN_INFO PFX "f: %d kHz, index: %d, vid: %d mV\n", -				speed, j, vid.mV); -		j++; +			speed, (int)(freq_pos - longhaul_table), vid.mV);  	}  	can_scale_voltage = 1; @@ -625,30 +626,16 @@ static void longhaul_setup_voltagescaling(void)  } -static int longhaul_verify(struct cpufreq_policy *policy) -{ -	return cpufreq_frequency_table_verify(policy, longhaul_table); -} - -  static int longhaul_target(struct cpufreq_policy *policy, -			    unsigned int target_freq, unsigned int relation) +			    unsigned int table_index)  { -	unsigned int table_index = 0;  	unsigned int i;  	unsigned int dir = 0;  	u8 vid, current_vid; - -	if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, -				relation, &table_index)) -		return -EINVAL; - -	/* Don't set same frequency again */ -	if (longhaul_index == table_index) -		return 0; +	int retval = 0;  	if (!can_scale_voltage) -		longhaul_setstate(policy, table_index); +		retval = longhaul_setstate(policy, table_index);  	else {  		/* On test system voltage transitions exceeding single  		 * step up or down were turning motherboard off. Both @@ -663,7 +650,7 @@ static int longhaul_target(struct cpufreq_policy *policy,  		while (i != table_index) {  			vid = (longhaul_table[i].driver_data >> 8) & 0x1f;  			if (vid != current_vid) { -				longhaul_setstate(policy, i); +				retval = longhaul_setstate(policy, i);  				current_vid = vid;  				msleep(200);  			} @@ -672,10 +659,11 @@ static int longhaul_target(struct cpufreq_policy *policy,  			else  				i--;  		} -		longhaul_setstate(policy, table_index); +		retval = longhaul_setstate(policy, table_index);  	} +  	longhaul_index = table_index; -	return 0; +	return retval;  } @@ -919,36 +907,17 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy)  		longhaul_setup_voltagescaling();  	policy->cpuinfo.transition_latency = 200000;	/* nsec */ -	policy->cur = calc_speed(longhaul_get_cpu_mult()); - -	ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table); -	if (ret) -		return ret; - -	cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu); - -	return 0; -} -static int longhaul_cpu_exit(struct cpufreq_policy *policy) -{ -	cpufreq_frequency_table_put_attr(policy->cpu); -	return 0; +	return cpufreq_table_validate_and_show(policy, longhaul_table);  } -static struct freq_attr *longhaul_attr[] = { -	&cpufreq_freq_attr_scaling_available_freqs, -	NULL, -}; -  static struct cpufreq_driver longhaul_driver = { -	.verify	= longhaul_verify, -	.target	= longhaul_target, +	.verify	= cpufreq_generic_frequency_table_verify, +	.target_index = longhaul_target,  	.get	= longhaul_get,  	.init	= longhaul_cpu_init, -	.exit	= longhaul_cpu_exit,  	.name	= "longhaul", -	.attr	= longhaul_attr, +	.attr	= cpufreq_generic_attr,  };  static const struct x86_cpu_id longhaul_id[] = { @@ -1002,7 +971,15 @@ static void __exit longhaul_exit(void)  	for (i = 0; i < numscales; i++) {  		if (mults[i] == maxmult) { +			struct cpufreq_freqs freqs; + +			freqs.old = policy->cur; +			freqs.new = longhaul_table[i].frequency; +			freqs.flags = 0; + +			cpufreq_freq_transition_begin(policy, &freqs);  			longhaul_setstate(policy, i); +			cpufreq_freq_transition_end(policy, &freqs, 0);  			break;  		}  	}  | 
