1 // SPDX-License-Identifier: GPL-2.0 1 2 /* 3 * Copyright (C) 1992, 1998-2004 Linus Torvald 4 * 5 * This file contains the interrupt probing co 6 */ 7 8 #include <linux/irq.h> 9 #include <linux/module.h> 10 #include <linux/interrupt.h> 11 #include <linux/delay.h> 12 #include <linux/async.h> 13 14 #include "internals.h" 15 16 /* 17 * Autodetection depends on the fact that any 18 * comes in on to an unassigned handler will g 19 * "IRQS_WAITING" cleared and the interrupt di 20 */ 21 static DEFINE_MUTEX(probing_active); 22 23 /** 24 * probe_irq_on - begin an interrupt a 25 * 26 * Commence probing for an interrupt. The 27 * and a mask of potential interrupt line 28 * 29 */ 30 unsigned long probe_irq_on(void) 31 { 32 struct irq_desc *desc; 33 unsigned long mask = 0; 34 int i; 35 36 /* 37 * quiesce the kernel, or at least the 38 */ 39 async_synchronize_full(); 40 mutex_lock(&probing_active); 41 /* 42 * something may have generated an irq 43 * flush such a longstanding irq befor 44 */ 45 for_each_irq_desc_reverse(i, desc) { 46 raw_spin_lock_irq(&desc->lock) 47 if (!desc->action && irq_setti 48 /* 49 * Some chips need to 50 * progress: 51 */ 52 if (desc->irq_data.chi 53 desc->irq_data 54 55 irq_activate_and_start 56 } 57 raw_spin_unlock_irq(&desc->loc 58 } 59 60 /* Wait for longstanding interrupts to 61 msleep(20); 62 63 /* 64 * enable any unassigned irqs 65 * (we must startup again here because 66 * happened in the previous stage, it 67 */ 68 for_each_irq_desc_reverse(i, desc) { 69 raw_spin_lock_irq(&desc->lock) 70 if (!desc->action && irq_setti 71 desc->istate |= IRQS_A 72 if (irq_activate_and_s 73 desc->istate | 74 } 75 raw_spin_unlock_irq(&desc->loc 76 } 77 78 /* 79 * Wait for spurious interrupts to tri 80 */ 81 msleep(100); 82 83 /* 84 * Now filter out any obviously spurio 85 */ 86 for_each_irq_desc(i, desc) { 87 raw_spin_lock_irq(&desc->lock) 88 89 if (desc->istate & IRQS_AUTODE 90 /* It triggered alread 91 if (!(desc->istate & I 92 desc->istate & 93 irq_shutdown_a 94 } else 95 if (i < 32) 96 mask | 97 } 98 raw_spin_unlock_irq(&desc->loc 99 } 100 101 return mask; 102 } 103 EXPORT_SYMBOL(probe_irq_on); 104 105 /** 106 * probe_irq_mask - scan a bitmap of inte 107 * @val: mask of interrupts to consider 108 * 109 * Scan the interrupt lines and return a 110 * autodetect interrupts. The interrupt p 111 * is then returned to its previous value 112 * 113 * Note: we need to scan all the irq's ev 114 * only return autodetect irq numbers - j 115 * them all to a known state. 116 */ 117 unsigned int probe_irq_mask(unsigned long val) 118 { 119 unsigned int mask = 0; 120 struct irq_desc *desc; 121 int i; 122 123 for_each_irq_desc(i, desc) { 124 raw_spin_lock_irq(&desc->lock) 125 if (desc->istate & IRQS_AUTODE 126 if (i < 16 && !(desc-> 127 mask |= 1 << i 128 129 desc->istate &= ~IRQS_ 130 irq_shutdown_and_deact 131 } 132 raw_spin_unlock_irq(&desc->loc 133 } 134 mutex_unlock(&probing_active); 135 136 return mask & val; 137 } 138 EXPORT_SYMBOL(probe_irq_mask); 139 140 /** 141 * probe_irq_off - end an interrupt aut 142 * @val: mask of potential interrupts (un 143 * 144 * Scans the unused interrupt lines and r 145 * appears to have triggered the interrup 146 * found then zero is returned. If more t 147 * found then minus the first candidate i 148 * their is doubt. 149 * 150 * The interrupt probe logic state is ret 151 * value. 152 * 153 * BUGS: When used in a module (which arg 154 * nothing prevents two IRQ probe callers 155 * results of this are non-optimal. 156 */ 157 int probe_irq_off(unsigned long val) 158 { 159 int i, irq_found = 0, nr_of_irqs = 0; 160 struct irq_desc *desc; 161 162 for_each_irq_desc(i, desc) { 163 raw_spin_lock_irq(&desc->lock) 164 165 if (desc->istate & IRQS_AUTODE 166 if (!(desc->istate & I 167 if (!nr_of_irq 168 irq_fo 169 nr_of_irqs++; 170 } 171 desc->istate &= ~IRQS_ 172 irq_shutdown_and_deact 173 } 174 raw_spin_unlock_irq(&desc->loc 175 } 176 mutex_unlock(&probing_active); 177 178 if (nr_of_irqs > 1) 179 irq_found = -irq_found; 180 181 return irq_found; 182 } 183 EXPORT_SYMBOL(probe_irq_off); 184 185
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.