blob: e6f1d61925f02fdc35dfa58099ec21f5e1d0d964 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
/*
* linux/kernel/irq/timings.c
*
* Copyright (C) 2016, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdesc.h>
#include <linux/percpu.h>
#include <linux/static_key.h>
#include "internals.h"
DEFINE_STATIC_KEY_FALSE(irq_timing_enabled);
void irq_timings_enable(void)
{
static_branch_inc(&irq_timing_enabled);
}
void irq_timings_disable(void)
{
static_branch_dec(&irq_timing_enabled);
}
/**
* irqtiming_get_next - return the next irq timing
*
* @irq: a pointer to an integer representing the interrupt number
*
* Must be called under rcu_read_lock().
*
* This function allows to browse safely the interrupt descriptors in order
* to retrieve the interrupts timings. The parameter gives the interrupt
* number to begin with and will return the interrupt timings for the next
* allocated irq. This approach gives us the possibility to go through the
* different interrupts without having to handle the sparse irq.
*
* The function changes @irq to the next allocated irq + 1, it should be
* passed back again and again until NULL is returned. Usually this function
* is called the first time with @irq = 0.
*
* Returns a struct irq_timings, NULL if we reach the end of the interrupts
* list.
*/
struct irq_timings *irq_timings_get_next(int *irq)
{
struct irq_desc *desc;
int next;
again:
/* Do a racy lookup of the next allocated irq */
next = irq_get_next_irq(*irq);
if (next >= nr_irqs)
return NULL;
*irq = next + 1;
/*
* Now lookup the descriptor. It's RCU protected. This
* descriptor might belong to an uninteresting interrupt or
* one that is not measured. Look for the next interrupt in
* that case.
*/
desc = irq_to_desc(next);
if (!desc || !(desc->istate & IRQS_TIMINGS))
goto again;
return this_cpu_ptr(desc->timings);
}
|