smp.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*
  2. * drivers/power/smp.c - Functions for stopping other CPUs.
  3. *
  4. * Copyright 2004 Pavel Machek <pavel@suse.cz>
  5. * Copyright (C) 2002-2003 Nigel Cunningham <ncunningham@clear.net.nz>
  6. *
  7. * This file is released under the GPLv2.
  8. */
  9. #undef DEBUG
  10. #include <linux/smp_lock.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/suspend.h>
  13. #include <linux/module.h>
  14. #include <asm/atomic.h>
  15. #include <asm/tlbflush.h>
  16. static atomic_t cpu_counter, freeze;
  17. static void smp_pause(void * data)
  18. {
  19. struct saved_context ctxt;
  20. __save_processor_state(&ctxt);
  21. printk("Sleeping in:\n");
  22. dump_stack();
  23. atomic_inc(&cpu_counter);
  24. while (atomic_read(&freeze)) {
  25. /* FIXME: restore takes place at random piece inside this.
  26. This should probably be written in assembly, and
  27. preserve general-purpose registers, too
  28. What about stack? We may need to move to new stack here.
  29. This should better be ran with interrupts disabled.
  30. */
  31. cpu_relax();
  32. barrier();
  33. }
  34. atomic_dec(&cpu_counter);
  35. __restore_processor_state(&ctxt);
  36. }
  37. static cpumask_t oldmask;
  38. void disable_nonboot_cpus(void)
  39. {
  40. oldmask = current->cpus_allowed;
  41. set_cpus_allowed(current, cpumask_of_cpu(0));
  42. printk("Freezing CPUs (at %d)", raw_smp_processor_id());
  43. current->state = TASK_INTERRUPTIBLE;
  44. schedule_timeout(HZ);
  45. printk("...");
  46. BUG_ON(raw_smp_processor_id() != 0);
  47. /* FIXME: for this to work, all the CPUs must be running
  48. * "idle" thread (or we deadlock). Is that guaranteed? */
  49. atomic_set(&cpu_counter, 0);
  50. atomic_set(&freeze, 1);
  51. smp_call_function(smp_pause, NULL, 0, 0);
  52. while (atomic_read(&cpu_counter) < (num_online_cpus() - 1)) {
  53. cpu_relax();
  54. barrier();
  55. }
  56. printk("ok\n");
  57. }
  58. void enable_nonboot_cpus(void)
  59. {
  60. printk("Restarting CPUs");
  61. atomic_set(&freeze, 0);
  62. while (atomic_read(&cpu_counter)) {
  63. cpu_relax();
  64. barrier();
  65. }
  66. printk("...");
  67. set_cpus_allowed(current, oldmask);
  68. schedule();
  69. printk("ok\n");
  70. }