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