bbc_envctrl.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:17k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: bbc_envctrl.c,v 1.4 2001/04/06 16:48:08 davem Exp $
  2.  * bbc_envctrl.c: UltraSPARC-III environment control driver.
  3.  *
  4.  * Copyright (C) 2001 David S. Miller (davem@redhat.com)
  5.  */
  6. #include <linux/kernel.h>
  7. #include <linux/sched.h>
  8. #include <linux/slab.h>
  9. #include <asm/oplib.h>
  10. #include <asm/ebus.h>
  11. #define __KERNEL_SYSCALLS__
  12. static int errno;
  13. #include <asm/unistd.h>
  14. #include "bbc_i2c.h"
  15. #include "max1617.h"
  16. #undef ENVCTRL_TRACE
  17. /* WARNING: Making changes to this driver is very dangerous.
  18.  *          If you misprogram the sensor chips they can
  19.  *          cut the power on you instantly.
  20.  */
  21. /* Two temperature sensors exist in the SunBLADE-1000 enclosure.
  22.  * Both are implemented using max1617 i2c devices.  Each max1617
  23.  * monitors 2 temperatures, one for one of the cpu dies and the other
  24.  * for the ambient temperature.
  25.  *
  26.  * The max1617 is capable of being programmed with power-off
  27.  * temperature values, one low limit and one high limit.  These
  28.  * can be controlled independantly for the cpu or ambient temperature.
  29.  * If a limit is violated, the power is simply shut off.  The frequency
  30.  * with which the max1617 does temperature sampling can be controlled
  31.  * as well.
  32.  *
  33.  * Three fans exist inside the machine, all three are controlled with
  34.  * an i2c digital to analog converter.  There is a fan directed at the
  35.  * two processor slots, another for the rest of the enclosure, and the
  36.  * third is for the power supply.  The first two fans may be speed
  37.  * controlled by changing the voltage fed to them.  The third fan may
  38.  * only be completely off or on.  The third fan is meant to only be
  39.  * disabled/enabled when entering/exiting the lowest power-saving
  40.  * mode of the machine.
  41.  *
  42.  * An environmental control kernel thread periodically monitors all
  43.  * temperature sensors.  Based upon the samples it will adjust the
  44.  * fan speeds to try and keep the system within a certain temperature
  45.  * range (the goal being to make the fans as quiet as possible without
  46.  * allowing the system to get too hot).
  47.  *
  48.  * If the temperature begins to rise/fall outside of the acceptable
  49.  * operating range, a periodic warning will be sent to the kernel log.
  50.  * The fans will be put on full blast to attempt to deal with this
  51.  * situation.  After exceeding the acceptable operating range by a
  52.  * certain threshold, the kernel thread will shut down the system.
  53.  * Here, the thread is attempting to shut the machine down cleanly
  54.  * before the hardware based power-off event is triggered.
  55.  */
  56. /* These settings are in celcius.  We use these defaults only
  57.  * if we cannot interrogate the cpu-fru SEEPROM.
  58.  */
  59. struct temp_limits {
  60. s8 high_pwroff, high_shutdown, high_warn;
  61. s8 low_warn, low_shutdown, low_pwroff;
  62. };
  63. static struct temp_limits cpu_temp_limits[2] = {
  64. { 100, 85, 80, 5, -5, -10 },
  65. { 100, 85, 80, 5, -5, -10 },
  66. };
  67. static struct temp_limits amb_temp_limits[2] = {
  68. { 65, 55, 40, 5, -5, -10 },
  69. { 65, 55, 40, 5, -5, -10 },
  70. };
  71. enum fan_action { FAN_SLOWER, FAN_SAME, FAN_FASTER, FAN_FULLBLAST, FAN_STATE_MAX };
  72. struct bbc_cpu_temperature {
  73. struct bbc_cpu_temperature *next;
  74. struct bbc_i2c_client *client;
  75. int index;
  76. /* Current readings, and history. */
  77. s8 curr_cpu_temp;
  78. s8 curr_amb_temp;
  79. s8 prev_cpu_temp;
  80. s8 prev_amb_temp;
  81. s8 avg_cpu_temp;
  82. s8 avg_amb_temp;
  83. int sample_tick;
  84. enum fan_action fan_todo[2];
  85. #define FAN_AMBIENT 0
  86. #define FAN_CPU 1
  87. };
  88. struct bbc_cpu_temperature *all_bbc_temps;
  89. struct bbc_fan_control {
  90. struct bbc_fan_control  *next;
  91. struct bbc_i2c_client  *client;
  92. int  index;
  93. int psupply_fan_on;
  94. int cpu_fan_speed;
  95. int system_fan_speed;
  96. };
  97. struct bbc_fan_control *all_bbc_fans;
  98. #define CPU_FAN_REG 0xf0
  99. #define SYS_FAN_REG 0xf2
  100. #define PSUPPLY_FAN_REG 0xf4
  101. #define FAN_SPEED_MIN 0x0c
  102. #define FAN_SPEED_MAX 0x3f
  103. #define PSUPPLY_FAN_ON 0x1f
  104. #define PSUPPLY_FAN_OFF 0x00
  105. static void set_fan_speeds(struct bbc_fan_control *fp)
  106. {
  107. /* Put temperatures into range so we don't mis-program
  108.  * the hardware.
  109.  */
  110. if (fp->cpu_fan_speed < FAN_SPEED_MIN)
  111. fp->cpu_fan_speed = FAN_SPEED_MIN;
  112. if (fp->cpu_fan_speed > FAN_SPEED_MAX)
  113. fp->cpu_fan_speed = FAN_SPEED_MAX;
  114. if (fp->system_fan_speed < FAN_SPEED_MIN)
  115. fp->system_fan_speed = FAN_SPEED_MIN;
  116. if (fp->system_fan_speed > FAN_SPEED_MAX)
  117. fp->system_fan_speed = FAN_SPEED_MAX;
  118. #ifdef ENVCTRL_TRACE
  119. printk("fan%d: Changed fan speed to cpu(%02x) sys(%02x)n",
  120.        fp->index,
  121.        fp->cpu_fan_speed, fp->system_fan_speed);
  122. #endif
  123. bbc_i2c_writeb(fp->client, fp->cpu_fan_speed, CPU_FAN_REG);
  124. bbc_i2c_writeb(fp->client, fp->system_fan_speed, SYS_FAN_REG);
  125. bbc_i2c_writeb(fp->client,
  126.        (fp->psupply_fan_on ?
  127. PSUPPLY_FAN_ON : PSUPPLY_FAN_OFF),
  128.        PSUPPLY_FAN_REG);
  129. }
  130. static void get_current_temps(struct bbc_cpu_temperature *tp)
  131. {
  132. tp->prev_amb_temp = tp->curr_amb_temp;
  133. bbc_i2c_readb(tp->client,
  134.       (unsigned char *) &tp->curr_amb_temp,
  135.       MAX1617_AMB_TEMP);
  136. tp->prev_cpu_temp = tp->curr_cpu_temp;
  137. bbc_i2c_readb(tp->client,
  138.       (unsigned char *) &tp->curr_cpu_temp,
  139.       MAX1617_CPU_TEMP);
  140. #ifdef ENVCTRL_TRACE
  141. printk("temp%d: cpu(%d C) amb(%d C)n",
  142.        tp->index,
  143.        (int) tp->curr_cpu_temp, (int) tp->curr_amb_temp);
  144. #endif
  145. }
  146. static void do_envctrl_shutdown(struct bbc_cpu_temperature *tp)
  147. {
  148. static int shutting_down = 0;
  149. static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
  150. char *argv[] = { "/sbin/shutdown", "-h", "now", NULL };
  151. char *type = "???";
  152. s8 val = -1;
  153. if (shutting_down != 0)
  154. return;
  155. if (tp->curr_amb_temp >= amb_temp_limits[tp->index].high_shutdown ||
  156.     tp->curr_amb_temp < amb_temp_limits[tp->index].low_shutdown) {
  157. type = "ambient";
  158. val = tp->curr_amb_temp;
  159. } else if (tp->curr_cpu_temp >= cpu_temp_limits[tp->index].high_shutdown ||
  160.    tp->curr_cpu_temp < cpu_temp_limits[tp->index].low_shutdown) {
  161. type = "CPU";
  162. val = tp->curr_cpu_temp;
  163. }
  164. printk(KERN_CRIT "temp%d: Outside of safe %s "
  165.        "operating temperature, %d C.n",
  166.        tp->index, type, val);
  167. printk(KERN_CRIT "kenvctrld: Shutting down the system now.n");
  168. shutting_down = 1;
  169. if (execve("/sbin/shutdown", argv, envp) < 0)
  170. printk(KERN_CRIT "envctrl: shutdown execution failedn");
  171. }
  172. #define WARN_INTERVAL (30 * HZ)
  173. static void analyze_ambient_temp(struct bbc_cpu_temperature *tp, unsigned long *last_warn, int tick)
  174. {
  175. int ret = 0;
  176. if (time_after(jiffies, (*last_warn + WARN_INTERVAL))) {
  177. if (tp->curr_amb_temp >=
  178.     amb_temp_limits[tp->index].high_warn) {
  179. printk(KERN_WARNING "temp%d: "
  180.        "Above safe ambient operating temperature, %d C.n",
  181.        tp->index, (int) tp->curr_amb_temp);
  182. ret = 1;
  183. } else if (tp->curr_amb_temp <
  184.    amb_temp_limits[tp->index].low_warn) {
  185. printk(KERN_WARNING "temp%d: "
  186.        "Below safe ambient operating temperature, %d C.n",
  187.        tp->index, (int) tp->curr_amb_temp);
  188. ret = 1;
  189. }
  190. if (ret)
  191. *last_warn = jiffies;
  192. } else if (tp->curr_amb_temp >= amb_temp_limits[tp->index].high_warn ||
  193.    tp->curr_amb_temp < amb_temp_limits[tp->index].low_warn)
  194. ret = 1;
  195. /* Now check the shutdown limits. */
  196. if (tp->curr_amb_temp >= amb_temp_limits[tp->index].high_shutdown ||
  197.     tp->curr_amb_temp < amb_temp_limits[tp->index].low_shutdown) {
  198. do_envctrl_shutdown(tp);
  199. ret = 1;
  200. }
  201. if (ret) {
  202. tp->fan_todo[FAN_AMBIENT] = FAN_FULLBLAST;
  203. } else if ((tick & (8 - 1)) == 0) {
  204. s8 amb_goal_hi = amb_temp_limits[tp->index].high_warn - 10;
  205. s8 amb_goal_lo;
  206. amb_goal_lo = amb_goal_hi - 3;
  207. /* We do not try to avoid 'too cold' events.  Basically we
  208.  * only try to deal with over-heating and fan noise reduction.
  209.  */
  210. if (tp->avg_amb_temp < amb_goal_hi) {
  211. if (tp->avg_amb_temp >= amb_goal_lo)
  212. tp->fan_todo[FAN_AMBIENT] = FAN_SAME;
  213. else
  214. tp->fan_todo[FAN_AMBIENT] = FAN_SLOWER;
  215. } else {
  216. tp->fan_todo[FAN_AMBIENT] = FAN_FASTER;
  217. }
  218. } else {
  219. tp->fan_todo[FAN_AMBIENT] = FAN_SAME;
  220. }
  221. }
  222. static void analyze_cpu_temp(struct bbc_cpu_temperature *tp, unsigned long *last_warn, int tick)
  223. {
  224. int ret = 0;
  225. if (time_after(jiffies, (*last_warn + WARN_INTERVAL))) {
  226. if (tp->curr_cpu_temp >=
  227.     cpu_temp_limits[tp->index].high_warn) {
  228. printk(KERN_WARNING "temp%d: "
  229.        "Above safe CPU operating temperature, %d C.n",
  230.        tp->index, (int) tp->curr_cpu_temp);
  231. ret = 1;
  232. } else if (tp->curr_cpu_temp <
  233.    cpu_temp_limits[tp->index].low_warn) {
  234. printk(KERN_WARNING "temp%d: "
  235.        "Below safe CPU operating temperature, %d C.n",
  236.        tp->index, (int) tp->curr_cpu_temp);
  237. ret = 1;
  238. }
  239. if (ret)
  240. *last_warn = jiffies;
  241. } else if (tp->curr_cpu_temp >= cpu_temp_limits[tp->index].high_warn ||
  242.    tp->curr_cpu_temp < cpu_temp_limits[tp->index].low_warn)
  243. ret = 1;
  244. /* Now check the shutdown limits. */
  245. if (tp->curr_cpu_temp >= cpu_temp_limits[tp->index].high_shutdown ||
  246.     tp->curr_cpu_temp < cpu_temp_limits[tp->index].low_shutdown) {
  247. do_envctrl_shutdown(tp);
  248. ret = 1;
  249. }
  250. if (ret) {
  251. tp->fan_todo[FAN_CPU] = FAN_FULLBLAST;
  252. } else if ((tick & (8 - 1)) == 0) {
  253. s8 cpu_goal_hi = cpu_temp_limits[tp->index].high_warn - 10;
  254. s8 cpu_goal_lo;
  255. cpu_goal_lo = cpu_goal_hi - 3;
  256. /* We do not try to avoid 'too cold' events.  Basically we
  257.  * only try to deal with over-heating and fan noise reduction.
  258.  */
  259. if (tp->avg_cpu_temp < cpu_goal_hi) {
  260. if (tp->avg_cpu_temp >= cpu_goal_lo)
  261. tp->fan_todo[FAN_CPU] = FAN_SAME;
  262. else
  263. tp->fan_todo[FAN_CPU] = FAN_SLOWER;
  264. } else {
  265. tp->fan_todo[FAN_CPU] = FAN_FASTER;
  266. }
  267. } else {
  268. tp->fan_todo[FAN_CPU] = FAN_SAME;
  269. }
  270. }
  271. static void analyze_temps(struct bbc_cpu_temperature *tp, unsigned long *last_warn)
  272. {
  273. tp->avg_amb_temp = (s8)((int)((int)tp->avg_amb_temp + (int)tp->curr_amb_temp) / 2);
  274. tp->avg_cpu_temp = (s8)((int)((int)tp->avg_cpu_temp + (int)tp->curr_cpu_temp) / 2);
  275. analyze_ambient_temp(tp, last_warn, tp->sample_tick);
  276. analyze_cpu_temp(tp, last_warn, tp->sample_tick);
  277. tp->sample_tick++;
  278. }
  279. static enum fan_action prioritize_fan_action(int which_fan)
  280. {
  281. struct bbc_cpu_temperature *tp;
  282. enum fan_action decision = FAN_STATE_MAX;
  283. /* Basically, prioritize what the temperature sensors
  284.  * recommend we do, and perform that action on all the
  285.  * fans.
  286.  */
  287. for (tp = all_bbc_temps; tp; tp = tp->next) {
  288. if (tp->fan_todo[which_fan] == FAN_FULLBLAST) {
  289. decision = FAN_FULLBLAST;
  290. break;
  291. }
  292. if (tp->fan_todo[which_fan] == FAN_SAME &&
  293.     decision != FAN_FASTER)
  294. decision = FAN_SAME;
  295. else if (tp->fan_todo[which_fan] == FAN_FASTER)
  296. decision = FAN_FASTER;
  297. else if (decision != FAN_FASTER &&
  298.  decision != FAN_SAME &&
  299.  tp->fan_todo[which_fan] == FAN_SLOWER)
  300. decision = FAN_SLOWER;
  301. }
  302. if (decision == FAN_STATE_MAX)
  303. decision = FAN_SAME;
  304. return decision;
  305. }
  306. static int maybe_new_ambient_fan_speed(struct bbc_fan_control *fp)
  307. {
  308. enum fan_action decision = prioritize_fan_action(FAN_AMBIENT);
  309. int ret;
  310. if (decision == FAN_SAME)
  311. return 0;
  312. ret = 1;
  313. if (decision == FAN_FULLBLAST) {
  314. if (fp->system_fan_speed >= FAN_SPEED_MAX)
  315. ret = 0;
  316. else
  317. fp->system_fan_speed = FAN_SPEED_MAX;
  318. } else {
  319. if (decision == FAN_FASTER) {
  320. if (fp->system_fan_speed >= FAN_SPEED_MAX)
  321. ret = 0;
  322. else
  323. fp->system_fan_speed += 2;
  324. } else {
  325. int orig_speed = fp->system_fan_speed;
  326. if (orig_speed <= FAN_SPEED_MIN ||
  327.     orig_speed <= (fp->cpu_fan_speed - 3))
  328. ret = 0;
  329. else
  330. fp->system_fan_speed -= 1;
  331. }
  332. }
  333. return ret;
  334. }
  335. static int maybe_new_cpu_fan_speed(struct bbc_fan_control *fp)
  336. {
  337. enum fan_action decision = prioritize_fan_action(FAN_CPU);
  338. int ret;
  339. if (decision == FAN_SAME)
  340. return 0;
  341. ret = 1;
  342. if (decision == FAN_FULLBLAST) {
  343. if (fp->cpu_fan_speed >= FAN_SPEED_MAX)
  344. ret = 0;
  345. else
  346. fp->cpu_fan_speed = FAN_SPEED_MAX;
  347. } else {
  348. if (decision == FAN_FASTER) {
  349. if (fp->cpu_fan_speed >= FAN_SPEED_MAX)
  350. ret = 0;
  351. else {
  352. fp->cpu_fan_speed += 2;
  353. if (fp->system_fan_speed <
  354.     (fp->cpu_fan_speed - 3))
  355. fp->system_fan_speed =
  356. fp->cpu_fan_speed - 3;
  357. }
  358. } else {
  359. if (fp->cpu_fan_speed <= FAN_SPEED_MIN)
  360. ret = 0;
  361. else
  362. fp->cpu_fan_speed -= 1;
  363. }
  364. }
  365. return ret;
  366. }
  367. static void maybe_new_fan_speeds(struct bbc_fan_control *fp)
  368. {
  369. int new;
  370. new  = maybe_new_ambient_fan_speed(fp);
  371. new |= maybe_new_cpu_fan_speed(fp);
  372. if (new)
  373. set_fan_speeds(fp);
  374. }
  375. static void fans_full_blast(void)
  376. {
  377. struct bbc_fan_control *fp;
  378. /* Since we will not be monitoring things anymore, put
  379.  * the fans on full blast.
  380.  */
  381. for (fp = all_bbc_fans; fp; fp = fp->next) {
  382. fp->cpu_fan_speed = FAN_SPEED_MAX;
  383. fp->system_fan_speed = FAN_SPEED_MAX;
  384. fp->psupply_fan_on = 1;
  385. set_fan_speeds(fp);
  386. }
  387. }
  388. #define POLL_INTERVAL (5 * HZ)
  389. static unsigned long last_warning_jiffies;
  390. static struct task_struct *kenvctrld_task;
  391. static int kenvctrld(void *__unused)
  392. {
  393. daemonize();
  394. strcpy(current->comm, "kenvctrld");
  395. kenvctrld_task = current;
  396. printk(KERN_INFO "bbc_envctrl: kenvctrld starting...n");
  397. last_warning_jiffies = jiffies - WARN_INTERVAL;
  398. for (;;) {
  399. struct bbc_cpu_temperature *tp;
  400. struct bbc_fan_control *fp;
  401. current->state = TASK_INTERRUPTIBLE;
  402. schedule_timeout(POLL_INTERVAL);
  403. current->state = TASK_RUNNING;
  404. if (signal_pending(current))
  405. break;
  406. for (tp = all_bbc_temps; tp; tp = tp->next) {
  407. get_current_temps(tp);
  408. analyze_temps(tp, &last_warning_jiffies);
  409. }
  410. for (fp = all_bbc_fans; fp; fp = fp->next)
  411. maybe_new_fan_speeds(fp);
  412. }
  413. printk(KERN_INFO "bbc_envctrl: kenvctrld exiting...n");
  414. fans_full_blast();
  415. return 0;
  416. }
  417. static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx)
  418. {
  419. struct bbc_cpu_temperature *tp = kmalloc(sizeof(*tp), GFP_KERNEL);
  420. if (!tp)
  421. return;
  422. memset(tp, 0, sizeof(*tp));
  423. tp->client = bbc_i2c_attach(echild);
  424. if (!tp->client) {
  425. kfree(tp);
  426. return;
  427. }
  428. tp->index = temp_idx;
  429. {
  430. struct bbc_cpu_temperature **tpp = &all_bbc_temps;
  431. while (*tpp)
  432. tpp = &((*tpp)->next);
  433. tp->next = NULL;
  434. *tpp = tp;
  435. }
  436. /* Tell it to convert once every 5 seconds, clear all cfg
  437.  * bits.
  438.  */
  439. bbc_i2c_writeb(tp->client, 0x00, MAX1617_WR_CFG_BYTE);
  440. bbc_i2c_writeb(tp->client, 0x02, MAX1617_WR_CVRATE_BYTE);
  441. /* Program the hard temperature limits into the chip. */
  442. bbc_i2c_writeb(tp->client, amb_temp_limits[tp->index].high_pwroff,
  443.        MAX1617_WR_AMB_HIGHLIM);
  444. bbc_i2c_writeb(tp->client, amb_temp_limits[tp->index].low_pwroff,
  445.        MAX1617_WR_AMB_LOWLIM);
  446. bbc_i2c_writeb(tp->client, cpu_temp_limits[tp->index].high_pwroff,
  447.        MAX1617_WR_CPU_HIGHLIM);
  448. bbc_i2c_writeb(tp->client, cpu_temp_limits[tp->index].low_pwroff,
  449.        MAX1617_WR_CPU_LOWLIM);
  450. get_current_temps(tp);
  451. tp->prev_cpu_temp = tp->avg_cpu_temp = tp->curr_cpu_temp;
  452. tp->prev_amb_temp = tp->avg_amb_temp = tp->curr_amb_temp;
  453. tp->fan_todo[FAN_AMBIENT] = FAN_SAME;
  454. tp->fan_todo[FAN_CPU] = FAN_SAME;
  455. }
  456. static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx)
  457. {
  458. struct bbc_fan_control *fp = kmalloc(sizeof(*fp), GFP_KERNEL);
  459. if (!fp)
  460. return;
  461. memset(fp, 0, sizeof(*fp));
  462. fp->client = bbc_i2c_attach(echild);
  463. if (!fp->client) {
  464. kfree(fp);
  465. return;
  466. }
  467. fp->index = fan_idx;
  468. {
  469. struct bbc_fan_control **fpp = &all_bbc_fans;
  470. while (*fpp)
  471. fpp = &((*fpp)->next);
  472. fp->next = NULL;
  473. *fpp = fp;
  474. }
  475. /* The i2c device controlling the fans is write-only.
  476.  * So the only way to keep track of the current power
  477.  * level fed to the fans is via software.  Choose half
  478.  * power for cpu/system and 'on' fo the powersupply fan
  479.  * and set it now.
  480.  */
  481. fp->psupply_fan_on = 1;
  482. fp->cpu_fan_speed = (FAN_SPEED_MAX - FAN_SPEED_MIN) / 2;
  483. fp->cpu_fan_speed += FAN_SPEED_MIN;
  484. fp->system_fan_speed = (FAN_SPEED_MAX - FAN_SPEED_MIN) / 2;
  485. fp->system_fan_speed += FAN_SPEED_MIN;
  486. set_fan_speeds(fp);
  487. }
  488. void bbc_envctrl_init(void)
  489. {
  490. struct linux_ebus_child *echild;
  491. int temp_index = 0;
  492. int fan_index = 0;
  493. int devidx = 0;
  494. while ((echild = bbc_i2c_getdev(devidx++)) != NULL) {
  495. if (!strcmp(echild->prom_name, "temperature"))
  496. attach_one_temp(echild, temp_index++);
  497. if (!strcmp(echild->prom_name, "fan-control"))
  498. attach_one_fan(echild, fan_index++);
  499. }
  500. if (temp_index != 0 && fan_index != 0)
  501. kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES);
  502. }
  503. static void destroy_one_temp(struct bbc_cpu_temperature *tp)
  504. {
  505. bbc_i2c_detach(tp->client);
  506. kfree(tp);
  507. }
  508. static void destroy_one_fan(struct bbc_fan_control *fp)
  509. {
  510. bbc_i2c_detach(fp->client);
  511. kfree(fp);
  512. }
  513. void bbc_envctrl_cleanup(void)
  514. {
  515. struct bbc_cpu_temperature *tp;
  516. struct bbc_fan_control *fp;
  517. if (kenvctrld_task != NULL) {
  518. force_sig(SIGKILL, kenvctrld_task);
  519. for (;;) {
  520. struct task_struct *p;
  521. int found = 0;
  522. read_lock(&tasklist_lock);
  523. for_each_task(p) {
  524. if (p == kenvctrld_task) {
  525. found = 1;
  526. break;
  527. }
  528. }
  529. read_unlock(&tasklist_lock);
  530. if (!found)
  531. break;
  532. current->state = TASK_INTERRUPTIBLE;
  533. schedule_timeout(HZ);
  534. current->state = TASK_RUNNING;
  535. }
  536. kenvctrld_task = NULL;
  537. }
  538. tp = all_bbc_temps;
  539. while (tp != NULL) {
  540. struct bbc_cpu_temperature *next = tp->next;
  541. destroy_one_temp(tp);
  542. tp = next;
  543. }
  544. all_bbc_temps = NULL;
  545. fp = all_bbc_fans;
  546. while (fp != NULL) {
  547. struct bbc_fan_control *next = fp->next;
  548. destroy_one_fan(fp);
  549. fp = next;
  550. }
  551. all_bbc_fans = NULL;
  552. }