~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/kernel/irq/migration.c

Version: ~ [ linux-5.12-rc7 ] ~ [ linux-5.11.13 ] ~ [ linux-5.10.29 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.111 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.186 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.230 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.266 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.266 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 
  3 #include <linux/irq.h>
  4 #include <linux/interrupt.h>
  5 
  6 #include "internals.h"
  7 
  8 /**
  9  * irq_fixup_move_pending - Cleanup irq move pending from a dying CPU
 10  * @desc:               Interrupt descpriptor to clean up
 11  * @force_clear:        If set clear the move pending bit unconditionally.
 12  *                      If not set, clear it only when the dying CPU is the
 13  *                      last one in the pending mask.
 14  *
 15  * Returns true if the pending bit was set and the pending mask contains an
 16  * online CPU other than the dying CPU.
 17  */
 18 bool irq_fixup_move_pending(struct irq_desc *desc, bool force_clear)
 19 {
 20         struct irq_data *data = irq_desc_get_irq_data(desc);
 21 
 22         if (!irqd_is_setaffinity_pending(data))
 23                 return false;
 24 
 25         /*
 26          * The outgoing CPU might be the last online target in a pending
 27          * interrupt move. If that's the case clear the pending move bit.
 28          */
 29         if (cpumask_any_and(desc->pending_mask, cpu_online_mask) >= nr_cpu_ids) {
 30                 irqd_clr_move_pending(data);
 31                 return false;
 32         }
 33         if (force_clear)
 34                 irqd_clr_move_pending(data);
 35         return true;
 36 }
 37 
 38 void irq_move_masked_irq(struct irq_data *idata)
 39 {
 40         struct irq_desc *desc = irq_data_to_desc(idata);
 41         struct irq_data *data = &desc->irq_data;
 42         struct irq_chip *chip = data->chip;
 43 
 44         if (likely(!irqd_is_setaffinity_pending(data)))
 45                 return;
 46 
 47         irqd_clr_move_pending(data);
 48 
 49         /*
 50          * Paranoia: cpu-local interrupts shouldn't be calling in here anyway.
 51          */
 52         if (irqd_is_per_cpu(data)) {
 53                 WARN_ON(1);
 54                 return;
 55         }
 56 
 57         if (unlikely(cpumask_empty(desc->pending_mask)))
 58                 return;
 59 
 60         if (!chip->irq_set_affinity)
 61                 return;
 62 
 63         assert_raw_spin_locked(&desc->lock);
 64 
 65         /*
 66          * If there was a valid mask to work with, please
 67          * do the disable, re-program, enable sequence.
 68          * This is *not* particularly important for level triggered
 69          * but in a edge trigger case, we might be setting rte
 70          * when an active trigger is coming in. This could
 71          * cause some ioapics to mal-function.
 72          * Being paranoid i guess!
 73          *
 74          * For correct operation this depends on the caller
 75          * masking the irqs.
 76          */
 77         if (cpumask_any_and(desc->pending_mask, cpu_online_mask) < nr_cpu_ids) {
 78                 int ret;
 79 
 80                 ret = irq_do_set_affinity(data, desc->pending_mask, false);
 81                 /*
 82                  * If the there is a cleanup pending in the underlying
 83                  * vector management, reschedule the move for the next
 84                  * interrupt. Leave desc->pending_mask intact.
 85                  */
 86                 if (ret == -EBUSY) {
 87                         irqd_set_move_pending(data);
 88                         return;
 89                 }
 90         }
 91         cpumask_clear(desc->pending_mask);
 92 }
 93 
 94 void __irq_move_irq(struct irq_data *idata)
 95 {
 96         bool masked;
 97 
 98         /*
 99          * Get top level irq_data when CONFIG_IRQ_DOMAIN_HIERARCHY is enabled,
100          * and it should be optimized away when CONFIG_IRQ_DOMAIN_HIERARCHY is
101          * disabled. So we avoid an "#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY" here.
102          */
103         idata = irq_desc_get_irq_data(irq_data_to_desc(idata));
104 
105         if (unlikely(irqd_irq_disabled(idata)))
106                 return;
107 
108         /*
109          * Be careful vs. already masked interrupts. If this is a
110          * threaded interrupt with ONESHOT set, we can end up with an
111          * interrupt storm.
112          */
113         masked = irqd_irq_masked(idata);
114         if (!masked)
115                 idata->chip->irq_mask(idata);
116         irq_move_masked_irq(idata);
117         if (!masked)
118                 idata->chip->irq_unmask(idata);
119 }
120 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp