⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bbc_envctrl.c

📁 MIZI Research, Inc.发布的嵌入式Linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	tp->sample_tick++;}static enum fan_action prioritize_fan_action(int which_fan){	struct bbc_cpu_temperature *tp;	enum fan_action decision = FAN_STATE_MAX;	/* Basically, prioritize what the temperature sensors	 * recommend we do, and perform that action on all the	 * fans.	 */	for (tp = all_bbc_temps; tp; tp = tp->next) {		if (tp->fan_todo[which_fan] == FAN_FULLBLAST) {			decision = FAN_FULLBLAST;			break;		}		if (tp->fan_todo[which_fan] == FAN_SAME &&		    decision != FAN_FASTER)			decision = FAN_SAME;		else if (tp->fan_todo[which_fan] == FAN_FASTER)			decision = FAN_FASTER;		else if (decision != FAN_FASTER &&			 decision != FAN_SAME &&			 tp->fan_todo[which_fan] == FAN_SLOWER)			decision = FAN_SLOWER;	}	if (decision == FAN_STATE_MAX)		decision = FAN_SAME;	return decision;}static int maybe_new_ambient_fan_speed(struct bbc_fan_control *fp){	enum fan_action decision = prioritize_fan_action(FAN_AMBIENT);	int ret;	if (decision == FAN_SAME)		return 0;	ret = 1;	if (decision == FAN_FULLBLAST) {		if (fp->system_fan_speed >= FAN_SPEED_MAX)			ret = 0;		else			fp->system_fan_speed = FAN_SPEED_MAX;	} else {		if (decision == FAN_FASTER) {			if (fp->system_fan_speed >= FAN_SPEED_MAX)				ret = 0;			else				fp->system_fan_speed += 2;		} else {			int orig_speed = fp->system_fan_speed;			if (orig_speed <= FAN_SPEED_MIN ||			    orig_speed <= (fp->cpu_fan_speed - 3))				ret = 0;			else				fp->system_fan_speed -= 1;		}	}	return ret;}static int maybe_new_cpu_fan_speed(struct bbc_fan_control *fp){	enum fan_action decision = prioritize_fan_action(FAN_CPU);	int ret;	if (decision == FAN_SAME)		return 0;	ret = 1;	if (decision == FAN_FULLBLAST) {		if (fp->cpu_fan_speed >= FAN_SPEED_MAX)			ret = 0;		else			fp->cpu_fan_speed = FAN_SPEED_MAX;	} else {		if (decision == FAN_FASTER) {			if (fp->cpu_fan_speed >= FAN_SPEED_MAX)				ret = 0;			else {				fp->cpu_fan_speed += 2;				if (fp->system_fan_speed <				    (fp->cpu_fan_speed - 3))					fp->system_fan_speed =						fp->cpu_fan_speed - 3;			}		} else {			if (fp->cpu_fan_speed <= FAN_SPEED_MIN)				ret = 0;			else				fp->cpu_fan_speed -= 1;		}	}	return ret;}static void maybe_new_fan_speeds(struct bbc_fan_control *fp){	int new;	new  = maybe_new_ambient_fan_speed(fp);	new |= maybe_new_cpu_fan_speed(fp);	if (new)		set_fan_speeds(fp);}static void fans_full_blast(void){	struct bbc_fan_control *fp;	/* Since we will not be monitoring things anymore, put	 * the fans on full blast.	 */	for (fp = all_bbc_fans; fp; fp = fp->next) {		fp->cpu_fan_speed = FAN_SPEED_MAX;		fp->system_fan_speed = FAN_SPEED_MAX;		fp->psupply_fan_on = 1;		set_fan_speeds(fp);	}}#define POLL_INTERVAL	(5 * HZ)static unsigned long last_warning_jiffies;static struct task_struct *kenvctrld_task;static int kenvctrld(void *__unused){	daemonize();	strcpy(current->comm, "kenvctrld");	kenvctrld_task = current;	printk(KERN_INFO "bbc_envctrl: kenvctrld starting...\n");	last_warning_jiffies = jiffies - WARN_INTERVAL;	for (;;) {		struct bbc_cpu_temperature *tp;		struct bbc_fan_control *fp;		current->state = TASK_INTERRUPTIBLE;		schedule_timeout(POLL_INTERVAL);		current->state = TASK_RUNNING;		if (signal_pending(current))			break;		for (tp = all_bbc_temps; tp; tp = tp->next) {			get_current_temps(tp);			analyze_temps(tp, &last_warning_jiffies);		}		for (fp = all_bbc_fans; fp; fp = fp->next)			maybe_new_fan_speeds(fp);	}	printk(KERN_INFO "bbc_envctrl: kenvctrld exiting...\n");	fans_full_blast();	return 0;}static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx){	struct bbc_cpu_temperature *tp = kmalloc(sizeof(*tp), GFP_KERNEL);	if (!tp)		return;	memset(tp, 0, sizeof(*tp));	tp->client = bbc_i2c_attach(echild);	if (!tp->client) {		kfree(tp);		return;	}	tp->index = temp_idx;	{		struct bbc_cpu_temperature **tpp = &all_bbc_temps;		while (*tpp)			tpp = &((*tpp)->next);		tp->next = NULL;		*tpp = tp;	}	/* Tell it to convert once every 5 seconds, clear all cfg	 * bits.	 */	bbc_i2c_writeb(tp->client, 0x00, MAX1617_WR_CFG_BYTE);	bbc_i2c_writeb(tp->client, 0x02, MAX1617_WR_CVRATE_BYTE);	/* Program the hard temperature limits into the chip. */	bbc_i2c_writeb(tp->client, amb_temp_limits[tp->index].high_pwroff,		       MAX1617_WR_AMB_HIGHLIM);	bbc_i2c_writeb(tp->client, amb_temp_limits[tp->index].low_pwroff,		       MAX1617_WR_AMB_LOWLIM);	bbc_i2c_writeb(tp->client, cpu_temp_limits[tp->index].high_pwroff,		       MAX1617_WR_CPU_HIGHLIM);	bbc_i2c_writeb(tp->client, cpu_temp_limits[tp->index].low_pwroff,		       MAX1617_WR_CPU_LOWLIM);	get_current_temps(tp);	tp->prev_cpu_temp = tp->avg_cpu_temp = tp->curr_cpu_temp;	tp->prev_amb_temp = tp->avg_amb_temp = tp->curr_amb_temp;	tp->fan_todo[FAN_AMBIENT] = FAN_SAME;	tp->fan_todo[FAN_CPU] = FAN_SAME;}static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx){	struct bbc_fan_control *fp = kmalloc(sizeof(*fp), GFP_KERNEL);	if (!fp)		return;	memset(fp, 0, sizeof(*fp));	fp->client = bbc_i2c_attach(echild);	if (!fp->client) {		kfree(fp);		return;	}	fp->index = fan_idx;	{		struct bbc_fan_control **fpp = &all_bbc_fans;		while (*fpp)			fpp = &((*fpp)->next);		fp->next = NULL;		*fpp = fp;	}	/* The i2c device controlling the fans is write-only.	 * So the only way to keep track of the current power	 * level fed to the fans is via software.  Choose half	 * power for cpu/system and 'on' fo the powersupply fan	 * and set it now.	 */	fp->psupply_fan_on = 1;	fp->cpu_fan_speed = (FAN_SPEED_MAX - FAN_SPEED_MIN) / 2;	fp->cpu_fan_speed += FAN_SPEED_MIN;	fp->system_fan_speed = (FAN_SPEED_MAX - FAN_SPEED_MIN) / 2;	fp->system_fan_speed += FAN_SPEED_MIN;	set_fan_speeds(fp);}void bbc_envctrl_init(void){	struct linux_ebus_child *echild;	int temp_index = 0;	int fan_index = 0;	int devidx = 0;	while ((echild = bbc_i2c_getdev(devidx++)) != NULL) {		if (!strcmp(echild->prom_name, "temperature"))			attach_one_temp(echild, temp_index++);		if (!strcmp(echild->prom_name, "fan-control"))			attach_one_fan(echild, fan_index++);	}	if (temp_index != 0 && fan_index != 0)		kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES);}static void destroy_one_temp(struct bbc_cpu_temperature *tp){	bbc_i2c_detach(tp->client);	kfree(tp);}static void destroy_one_fan(struct bbc_fan_control *fp){	bbc_i2c_detach(fp->client);	kfree(fp);}void bbc_envctrl_cleanup(void){	struct bbc_cpu_temperature *tp;	struct bbc_fan_control *fp;	if (kenvctrld_task != NULL) {		force_sig(SIGKILL, kenvctrld_task);		for (;;) {			struct task_struct *p;			int found = 0;			read_lock(&tasklist_lock);			for_each_task(p) {				if (p == kenvctrld_task) {					found = 1;					break;				}			}			read_unlock(&tasklist_lock);			if (!found)				break;			current->state = TASK_INTERRUPTIBLE;			schedule_timeout(HZ);			current->state = TASK_RUNNING;		}		kenvctrld_task = NULL;	}	tp = all_bbc_temps;	while (tp != NULL) {		struct bbc_cpu_temperature *next = tp->next;		destroy_one_temp(tp);		tp = next;	}	all_bbc_temps = NULL;	fp = all_bbc_fans;	while (fp != NULL) {		struct bbc_fan_control *next = fp->next;		destroy_one_fan(fp);		fp = next;	}	all_bbc_fans = NULL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -