Exemplo n.º 1
0
static void set_fail_state(void)
{
	cpu_max_all_fans();

	if (backside_fan)
		wf_control_set_max(backside_fan);
	if (slots_fan)
		wf_control_set_max(slots_fan);
}
static void cpu_fans_tick_split(void)
{
    int err, cpu;
    s32 intake, temp, power, t_max = 0;

    DBG_LOTS("* cpu fans_tick_split()\n");

    for (cpu = 0; cpu < nr_chips; ++cpu) {
        struct wf_cpu_pid_state *sp = &cpu_pid[cpu];

        /* Read current speed */
        wf_control_get(cpu_rear_fans[cpu], &sp->target);

        DBG_LOTS("  CPU%d: cur_target = %d RPM\n", cpu, sp->target);

        err = read_one_cpu_vals(cpu, &temp, &power);
        if (err) {
            failure_state |= FAILURE_SENSOR;
            cpu_max_all_fans();
            return;
        }

        /* Keep track of highest temp */
        t_max = max(t_max, temp);

        /* Handle possible overtemps */
        if (cpu_check_overtemp(t_max))
            return;

        /* Run PID */
        wf_cpu_pid_run(sp, power, temp);

        DBG_LOTS("  CPU%d: target = %d RPM\n", cpu, sp->target);

        /* Apply result directly to exhaust fan */
        err = wf_control_set(cpu_rear_fans[cpu], sp->target);
        if (err) {
            pr_warning("wf_pm72: Fan %s reports error %d\n",
                       cpu_rear_fans[cpu]->name, err);
            failure_state |= FAILURE_FAN;
            break;
        }

        /* Scale result for intake fan */
        intake = (sp->target * CPU_INTAKE_SCALE) >> 16;
        DBG_LOTS("  CPU%d: intake = %d RPM\n", cpu, intake);
        err = wf_control_set(cpu_front_fans[cpu], intake);
        if (err) {
            pr_warning("wf_pm72: Fan %s reports error %d\n",
                       cpu_front_fans[cpu]->name, err);
            failure_state |= FAILURE_FAN;
            break;
        }
    }
}
Exemplo n.º 3
0
static void cpu_fans_tick(void)
{
	int err, cpu, i;
	s32 speed, temp, power, t_max = 0;

	DBG_LOTS("* cpu fans_tick_split()\n");

	for (cpu = 0; cpu < nr_chips; ++cpu) {
		struct wf_cpu_pid_state *sp = &cpu_pid[cpu];

		/* Read current speed */
		wf_control_get(cpu_fans[cpu][0], &sp->target);

		err = read_one_cpu_vals(cpu, &temp, &power);
		if (err) {
			failure_state |= FAILURE_SENSOR;
			cpu_max_all_fans();
			return;
		}

		/* Keep track of highest temp */
		t_max = max(t_max, temp);

		/* Handle possible overtemps */
		if (cpu_check_overtemp(t_max))
			return;

		/* Run PID */
		wf_cpu_pid_run(sp, power, temp);

		DBG_LOTS("  CPU%d: target = %d RPM\n", cpu, sp->target);

		/* Apply DIMMs clamp */
		speed = max(sp->target, dimms_output_clamp);

		/* Apply result to all cpu fans */
		for (i = 0; i < 3; i++) {
			err = wf_control_set(cpu_fans[cpu][i], speed);
			if (err) {
				pr_warning("wf_rm31: Fan %s reports error %d\n",
					   cpu_fans[cpu][i]->name, err);
				failure_state |= FAILURE_FAN;
			}
		}
	}
}
Exemplo n.º 4
0
static int cpu_check_overtemp(s32 temp)
{
	int new_state = 0;
	s32 t_avg, t_old;
	static bool first = true;

	/* First check for immediate overtemps */
	if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) {
		new_state |= FAILURE_LOW_OVERTEMP;
		if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
			printk(KERN_ERR "windfarm: Overtemp due to immediate CPU"
			       " temperature !\n");
	}
	if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) {
		new_state |= FAILURE_HIGH_OVERTEMP;
		if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
			printk(KERN_ERR "windfarm: Critical overtemp due to"
			       " immediate CPU temperature !\n");
	}

	/*
	 * The first time around, initialize the array with the first
	 * temperature reading
	 */
	if (first) {
		int i;

		cpu_thist_total = 0;
		for (i = 0; i < CPU_TEMP_HIST_SIZE; i++) {
			cpu_thist[i] = temp;
			cpu_thist_total += temp;
		}
		first = false;
	}

	/*
	 * We calculate a history of max temperatures and use that for the
	 * overtemp management
	 */
	t_old = cpu_thist[cpu_thist_pt];
	cpu_thist[cpu_thist_pt] = temp;
	cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE;
	cpu_thist_total -= t_old;
	cpu_thist_total += temp;
	t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE;

	DBG_LOTS("  t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n",
		 FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp));

	/* Now check for average overtemps */
	if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) {
		new_state |= FAILURE_LOW_OVERTEMP;
		if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
			printk(KERN_ERR "windfarm: Overtemp due to average CPU"
			       " temperature !\n");
	}
	if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) {
		new_state |= FAILURE_HIGH_OVERTEMP;
		if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
			printk(KERN_ERR "windfarm: Critical overtemp due to"
			       " average CPU temperature !\n");
	}

	/* Now handle overtemp conditions. We don't currently use the windfarm
	 * overtemp handling core as it's not fully suited to the needs of those
	 * new machine. This will be fixed later.
	 */
	if (new_state) {
		/* High overtemp -> immediate shutdown */
		if (new_state & FAILURE_HIGH_OVERTEMP)
			machine_power_off();
		if ((failure_state & new_state) != new_state)
			cpu_max_all_fans();
		failure_state |= new_state;
	} else if ((failure_state & FAILURE_LOW_OVERTEMP) &&
		   (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) {
		printk(KERN_ERR "windfarm: Overtemp condition cleared !\n");
		failure_state &= ~FAILURE_LOW_OVERTEMP;
	}

	return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP);
}
Exemplo n.º 5
0
static void cpu_fans_tick(void)
{
	int err, cpu;
	s32 greatest_delta = 0;
	s32 temp, power, t_max = 0;
	int i, t, target = 0;
	struct wf_sensor *sr;
	struct wf_control *ct;
	struct wf_cpu_pid_state *sp;

	DBG_LOTS(KERN_DEBUG);
	for (cpu = 0; cpu < nr_cores; ++cpu) {
		/* Get CPU core temperature */
		sr = sens_cpu_temp[cpu];
		err = sr->ops->get_value(sr, &temp);
		if (err) {
			DBG("\n");
//			printk(KERN_WARNING "windfarm: CPU %d temperature "
;
			failure_state |= FAILURE_SENSOR;
			cpu_max_all_fans();
			return;
		}

		/* Keep track of highest temp */
		t_max = max(t_max, temp);

		/* Get CPU power */
		sr = sens_cpu_power[cpu];
		err = sr->ops->get_value(sr, &power);
		if (err) {
			DBG("\n");
//			printk(KERN_WARNING "windfarm: CPU %d power "
;
			failure_state |= FAILURE_SENSOR;
			cpu_max_all_fans();
			return;
		}

		/* Run PID */
		sp = &cpu_pid[cpu];
		t = wf_cpu_pid_run(sp, power, temp);

		if (cpu == 0 || sp->last_delta > greatest_delta) {
			greatest_delta = sp->last_delta;
			target = t;
		}
		DBG_LOTS("[%d] P=%d.%.3d T=%d.%.3d ",
		    cpu, FIX32TOPRINT(power), FIX32TOPRINT(temp));
	}
	DBG_LOTS("fans = %d, t_max = %d.%03d\n", target, FIX32TOPRINT(t_max));

	/* Darwin limits decrease to 20 per iteration */
	if (target < (cpu_last_target - 20))
		target = cpu_last_target - 20;
	cpu_last_target = target;
	for (cpu = 0; cpu < nr_cores; ++cpu)
		cpu_pid[cpu].target = target;

	/* Handle possible overtemps */
	if (cpu_check_overtemp(t_max))
		return;

	/* Set fans */
	for (i = 0; i < NR_CPU_FANS; ++i) {
		ct = cpu_fans[i];
		if (ct == NULL)
			continue;
		err = ct->ops->set_value(ct, target * cpu_fan_scale[i] / 100);
		if (err) {
//			printk(KERN_WARNING "windfarm: fan %s reports "
;
			failure_state |= FAILURE_FAN;
			break;
		}
	}
}
static void cpu_fans_tick_combined(void)
{
    s32 temp0, power0, temp1, power1, t_max = 0;
    s32 temp, power, intake, pump;
    struct wf_control *pump0, *pump1;
    struct wf_cpu_pid_state *sp = &cpu_pid[0];
    int err, cpu;

    DBG_LOTS("* cpu fans_tick_combined()\n");

    /* Read current speed from cpu 0 */
    wf_control_get(cpu_rear_fans[0], &sp->target);

    DBG_LOTS("  CPUs: cur_target = %d RPM\n", sp->target);

    /* Read values for both CPUs */
    err = read_one_cpu_vals(0, &temp0, &power0);
    if (err) {
        failure_state |= FAILURE_SENSOR;
        cpu_max_all_fans();
        return;
    }
    err = read_one_cpu_vals(1, &temp1, &power1);
    if (err) {
        failure_state |= FAILURE_SENSOR;
        cpu_max_all_fans();
        return;
    }

    /* Keep track of highest temp */
    t_max = max(t_max, max(temp0, temp1));

    /* Handle possible overtemps */
    if (cpu_check_overtemp(t_max))
        return;

    /* Use the max temp & power of both */
    temp = max(temp0, temp1);
    power = max(power0, power1);

    /* Run PID */
    wf_cpu_pid_run(sp, power, temp);

    /* Scale result for intake fan */
    intake = (sp->target * CPU_INTAKE_SCALE) >> 16;

    /* Same deal with pump speed */
    pump0 = cpu_pumps[0];
    pump1 = cpu_pumps[1];
    if (!pump0) {
        pump0 = pump1;
        pump1 = NULL;
    }
    pump = (sp->target * wf_control_get_max(pump0)) /
           cpu_mpu_data[0]->rmaxn_exhaust_fan;

    DBG_LOTS("  CPUs: target = %d RPM\n", sp->target);
    DBG_LOTS("  CPUs: intake = %d RPM\n", intake);
    DBG_LOTS("  CPUs: pump   = %d RPM\n", pump);

    for (cpu = 0; cpu < nr_chips; cpu++) {
        err = wf_control_set(cpu_rear_fans[cpu], sp->target);
        if (err) {
            pr_warning("wf_pm72: Fan %s reports error %d\n",
                       cpu_rear_fans[cpu]->name, err);
            failure_state |= FAILURE_FAN;
        }
        err = wf_control_set(cpu_front_fans[cpu], intake);
        if (err) {
            pr_warning("wf_pm72: Fan %s reports error %d\n",
                       cpu_front_fans[cpu]->name, err);
            failure_state |= FAILURE_FAN;
        }
        err = 0;
        if (cpu_pumps[cpu])
            err = wf_control_set(cpu_pumps[cpu], pump);
        if (err) {
            pr_warning("wf_pm72: Pump %s reports error %d\n",
                       cpu_pumps[cpu]->name, err);
            failure_state |= FAILURE_FAN;
        }
    }
}