cpuhotplug.c 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /*
  2. * Generic cpu hotunplug interrupt migration code copied from the
  3. * arch/arm implementation
  4. *
  5. * Copyright (C) Russell King
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. */
  11. #include <linux/interrupt.h>
  12. #include <linux/ratelimit.h>
  13. #include <linux/irq.h>
  14. #include "internals.h"
  15. static bool migrate_one_irq(struct irq_desc *desc)
  16. {
  17. struct irq_data *d = irq_desc_get_irq_data(desc);
  18. const struct cpumask *affinity = d->common->affinity;
  19. struct irq_chip *c;
  20. bool ret = false;
  21. /*
  22. * If this is a per-CPU interrupt, or the affinity does not
  23. * include this CPU, then we have nothing to do.
  24. */
  25. if (irqd_is_per_cpu(d) ||
  26. !cpumask_test_cpu(smp_processor_id(), affinity))
  27. return false;
  28. if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
  29. affinity = cpu_online_mask;
  30. ret = true;
  31. }
  32. c = irq_data_get_irq_chip(d);
  33. if (!c->irq_set_affinity) {
  34. pr_debug("IRQ%u: unable to set affinity\n", d->irq);
  35. } else {
  36. int r = irq_do_set_affinity(d, affinity, false);
  37. if (r)
  38. pr_warn_ratelimited("IRQ%u: set affinity failed(%d).\n",
  39. d->irq, r);
  40. }
  41. return ret;
  42. }
  43. /**
  44. * irq_migrate_all_off_this_cpu - Migrate irqs away from offline cpu
  45. *
  46. * The current CPU has been marked offline. Migrate IRQs off this CPU.
  47. * If the affinity settings do not allow other CPUs, force them onto any
  48. * available CPU.
  49. *
  50. * Note: we must iterate over all IRQs, whether they have an attached
  51. * action structure or not, as we need to get chained interrupts too.
  52. */
  53. void irq_migrate_all_off_this_cpu(void)
  54. {
  55. unsigned int irq;
  56. struct irq_desc *desc;
  57. unsigned long flags;
  58. local_irq_save(flags);
  59. for_each_active_irq(irq) {
  60. bool affinity_broken;
  61. desc = irq_to_desc(irq);
  62. raw_spin_lock(&desc->lock);
  63. affinity_broken = migrate_one_irq(desc);
  64. raw_spin_unlock(&desc->lock);
  65. if (affinity_broken)
  66. pr_warn_ratelimited("IRQ%u no longer affine to CPU%u\n",
  67. irq, smp_processor_id());
  68. }
  69. local_irq_restore(flags);
  70. }