File Index
Files and directories
Sign in
FILE

autoprobe.c

File preview with syntax highlighting.

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